This repository has been archived by the owner on May 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 54
/
bundle_remove.go
120 lines (101 loc) · 3.17 KB
/
bundle_remove.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package main
import (
"fmt"
"io"
"os"
"path/filepath"
"github.com/cnabio/duffle/pkg/duffle/home"
"github.com/cnabio/duffle/pkg/repo"
"github.com/Masterminds/semver"
"github.com/spf13/cobra"
)
const bundleRemoveDesc = `Remove a bundle from the local storage.
This removes a bundle from the local storage so that it will no longer be locally
available. Bundles can be rebuilt with 'duffle build'.
Ex. $ duffle bundle remove foo # removes all versions of foo from local store
If a SemVer range is provided with '--version'/'-r' then only releases that match
that range will be removed.
`
type bundleRemoveCmd struct {
bundleRef string
home home.Home
out io.Writer
versions string
}
func newBundleRemoveCmd(w io.Writer) *cobra.Command {
remove := &bundleRemoveCmd{out: w}
cmd := &cobra.Command{
Use: "remove [BUNDLE]",
Aliases: []string{"rm"},
Short: "remove a bundle from the local storage",
Long: bundleRemoveDesc,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
remove.bundleRef = args[0]
remove.home = home.Home(homePath())
return remove.run()
},
}
cmd.Flags().StringVarP(&remove.versions, "version", "r", "", "A version or SemVer2 version range")
return cmd
}
func (rm *bundleRemoveCmd) run() error {
index, err := repo.LoadIndex(rm.home.Repositories())
if err != nil {
return err
}
vers, ok := index.GetVersions(rm.bundleRef)
if !ok {
fmt.Fprintf(rm.out, "Bundle %q not found. Nothing deleted.", rm.bundleRef)
return nil
}
// If versions is set, we short circuit and only delete specific versions.
if rm.versions != "" {
fmt.Fprintln(rm.out, "Only deleting versions")
matcher, err := semver.NewConstraint(rm.versions)
if err != nil {
return err
}
deletions := []repo.BundleVersion{}
for _, ver := range vers {
if ok, _ := matcher.Validate(ver.Version); ok {
fmt.Fprintf(rm.out, "Version %s matches constraint %q\n", ver, rm.versions)
deletions = append(deletions, ver)
index.DeleteVersion(rm.bundleRef, ver.Version.String())
// If there are no more versions, remove the entire entry.
if vers, ok := index.GetVersions(rm.bundleRef); ok && len(vers) == 0 {
index.Delete(rm.bundleRef)
}
}
}
if len(deletions) == 0 {
return nil
}
if err := index.WriteFile(rm.home.Repositories(), 0644); err != nil {
return err
}
deleteBundleVersions(deletions, index, rm.home, rm.out)
return nil
}
// If no version was specified, delete entire record
if !index.Delete(rm.bundleRef) {
fmt.Fprintf(rm.out, "Bundle %q not found. Nothing deleted.", rm.bundleRef)
return nil
}
if err := index.WriteFile(rm.home.Repositories(), 0644); err != nil {
return err
}
deleteBundleVersions(vers, index, rm.home, rm.out)
return nil
}
// deleteBundleVersions removes the given SHAs from bundle storage
//
// It warns, but does not fail, if a given SHA is not found.
func deleteBundleVersions(vers []repo.BundleVersion, index repo.Index, h home.Home, w io.Writer) {
for _, ver := range vers {
fpath := filepath.Join(h.Bundles(), ver.Digest)
if err := os.Remove(fpath); err != nil {
fmt.Fprintf(w, "WARNING: could not delete stake record %q", fpath)
}
}
}