-
Notifications
You must be signed in to change notification settings - Fork 511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
update to allow removing pending changes #856
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,12 +5,12 @@ import ( | |
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
"sort" | ||
"time" | ||
|
||
"github.com/Sirupsen/logrus" | ||
"github.com/docker/distribution/uuid" | ||
"path/filepath" | ||
) | ||
|
||
// FileChangelist stores all the changes as files | ||
|
@@ -46,13 +46,14 @@ func getFileNames(dirName string) ([]os.FileInfo, error) { | |
} | ||
fileInfos = append(fileInfos, f) | ||
} | ||
sort.Sort(fileChanges(fileInfos)) | ||
return fileInfos, nil | ||
} | ||
|
||
// Read a JSON formatted file from disk; convert to TUFChange struct | ||
func unmarshalFile(dirname string, f os.FileInfo) (*TUFChange, error) { | ||
c := &TUFChange{} | ||
raw, err := ioutil.ReadFile(path.Join(dirname, f.Name())) | ||
raw, err := ioutil.ReadFile(filepath.Join(dirname, f.Name())) | ||
if err != nil { | ||
return c, err | ||
} | ||
|
@@ -70,7 +71,6 @@ func (cl FileChangelist) List() []Change { | |
if err != nil { | ||
return changes | ||
} | ||
sort.Sort(fileChanges(fileInfos)) | ||
for _, f := range fileInfos { | ||
c, err := unmarshalFile(cl.dir, f) | ||
if err != nil { | ||
|
@@ -89,10 +89,32 @@ func (cl FileChangelist) Add(c Change) error { | |
return err | ||
} | ||
filename := fmt.Sprintf("%020d_%s.change", time.Now().UnixNano(), uuid.Generate()) | ||
return ioutil.WriteFile(path.Join(cl.dir, filename), cJSON, 0644) | ||
return ioutil.WriteFile(filepath.Join(cl.dir, filename), cJSON, 0644) | ||
} | ||
|
||
// Remove deletes the changes found at the given indices | ||
func (cl FileChangelist) Remove(idxs []int) error { | ||
fileInfos, err := getFileNames(cl.dir) | ||
if err != nil { | ||
return err | ||
} | ||
remove := make(map[int]struct{}) | ||
for _, i := range idxs { | ||
remove[i] = struct{}{} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we emit a warning or info message (but not fail) if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we explicitly print the change #s, I've been thinking of this as one of those "silent success" cases. We do exactly what has been asked and technically silently succeed to "remove" the invalid indices. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine with this silent success behavior for consistency across notary - we can always add in logging later if this is a pain-point for users There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense. |
||
} | ||
for i, c := range fileInfos { | ||
if _, ok := remove[i]; ok { | ||
file := filepath.Join(cl.dir, c.Name()) | ||
if err := os.Remove(file); err != nil { | ||
logrus.Errorf("could not remove change %d: %s", i, err.Error()) | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// Clear clears the change list | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
// N.B. archiving not currently implemented | ||
func (cl FileChangelist) Clear(archive string) error { | ||
dir, err := os.Open(cl.dir) | ||
if err != nil { | ||
|
@@ -104,7 +126,7 @@ func (cl FileChangelist) Clear(archive string) error { | |
return err | ||
} | ||
for _, f := range files { | ||
os.Remove(path.Join(cl.dir, f.Name())) | ||
os.Remove(filepath.Join(cl.dir, f.Name())) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thank you for fixing these to |
||
} | ||
return nil | ||
} | ||
|
@@ -121,7 +143,6 @@ func (cl FileChangelist) NewIterator() (ChangeIterator, error) { | |
if err != nil { | ||
return &FileChangeListIterator{}, err | ||
} | ||
sort.Sort(fileChanges(fileInfos)) | ||
return &FileChangeListIterator{dirname: cl.dir, collection: fileInfos}, nil | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,14 +97,22 @@ type tufCommander struct { | |
input string | ||
output string | ||
quiet bool | ||
|
||
deleteIdx []int | ||
reset bool | ||
archiveChangelist string | ||
} | ||
|
||
func (t *tufCommander) AddToCommand(cmd *cobra.Command) { | ||
cmdTUFInit := cmdTUFInitTemplate.ToCommand(t.tufInit) | ||
cmdTUFInit.Flags().StringVar(&t.rootKey, "rootkey", "", "Root key to initialize the repository with") | ||
cmd.AddCommand(cmdTUFInit) | ||
|
||
cmd.AddCommand(cmdTUFStatusTemplate.ToCommand(t.tufStatus)) | ||
cmdStatus := cmdTUFStatusTemplate.ToCommand(t.tufStatus) | ||
cmdStatus.Flags().IntSliceVarP(&t.deleteIdx, "unstage", "u", nil, "Numbers of changes to delete, as shown in status list") | ||
cmdStatus.Flags().BoolVar(&t.reset, "reset", false, "Reset the changelist for the GUN by deleting all pending changes") | ||
cmd.AddCommand(cmdStatus) | ||
|
||
cmd.AddCommand(cmdTUFPublishTemplate.ToCommand(t.tufPublish)) | ||
cmd.AddCommand(cmdTUFLookupTemplate.ToCommand(t.tufLookup)) | ||
|
||
|
@@ -440,17 +448,36 @@ func (t *tufCommander) tufStatus(cmd *cobra.Command, args []string) error { | |
return err | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Thanks for fixing this formatting! It looks much nicer! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Big fan of tabwriter now that I've discovered it :-) |
||
|
||
if t.reset { | ||
return cl.Clear(t.archiveChangelist) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we have an interactive remove here? It would match behavior with removing keys and delegation roles There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be nice to have a |
||
} | ||
|
||
if len(t.deleteIdx) > 0 { | ||
return cl.Remove(t.deleteIdx) | ||
} | ||
|
||
if len(cl.List()) == 0 { | ||
cmd.Printf("No unpublished changes for %s\n", gun) | ||
return nil | ||
} | ||
|
||
cmd.Printf("Unpublished changes for %s:\n\n", gun) | ||
cmd.Printf("%-10s%-10s%-12s%s\n", "action", "scope", "type", "path") | ||
cmd.Println("----------------------------------------------------") | ||
for _, ch := range cl.List() { | ||
cmd.Printf("%-10s%-10s%-12s%s\n", ch.Action(), ch.Scope(), ch.Type(), ch.Path()) | ||
} | ||
tw := initTabWriter( | ||
[]string{"#", "ACTION", "SCOPE", "TYPE", "PATH"}, | ||
cmd.Out(), | ||
) | ||
for i, ch := range cl.List() { | ||
fmt.Fprintf( | ||
tw, | ||
fiveItemRow, | ||
fmt.Sprintf("%d", i), | ||
ch.Action(), | ||
ch.Scope(), | ||
ch.Type(), | ||
ch.Path(), | ||
) | ||
} | ||
tw.Flush() | ||
return nil | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a test for this method? I think the
cmd
functions only use file changelists which is why it isn't coveredThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!