From 429788db0f065a3e66f9733aa339eb43b30c1154 Mon Sep 17 00:00:00 2001 From: Simon Aquino Date: Mon, 30 Jun 2014 18:29:23 +0100 Subject: [PATCH 1/7] List snapshots by time Users now have the choice of listing the snapshot by time as well as name (default behaviour). An additional flag has been added '--sort=' which controls the sort method applied to the list produced by aptly snapshot list. The possible values are: --sort=name (default): sorts the snapshot list by name (lexicographic order) --sort=time: sorts the snapshot list in chronological order (oldest to newest) --- cmd/snapshot_list.go | 68 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/cmd/snapshot_list.go b/cmd/snapshot_list.go index 6a350d62..6b979bba 100644 --- a/cmd/snapshot_list.go +++ b/cmd/snapshot_list.go @@ -7,6 +7,49 @@ import ( "sort" ) +// Snapshot sorting methods +const ( + SortName = iota + SortTime +) + +type snapshotListToSort struct { + list []*deb.Snapshot + sortMethod int +} + +func ParseSortMethod(sortMethod_string string) int { + + switch sortMethod_string { + case "time", "Time": + return SortTime + case "name", "Name": + return SortName + } + + fmt.Errorf("Sorting method \"%s\" unknown. Defaulting to '-sort=name'", sortMethod_string) + return SortName +} + +func (s snapshotListToSort) Swap(i, j int) { + s.list[i], s.list[j] = s.list[j], s.list[i] +} + +func (s snapshotListToSort) Less(i, j int) bool { + switch s.sortMethod { + case SortName: + sL := []string{s.list[i].Name, s.list[j].Name} + return sort.StringsAreSorted(sL) + case SortTime: + return s.list[i].CreatedAt.Before(s.list[j].CreatedAt) + } + return true +} + +func (s snapshotListToSort) Len() int { + return len(s.list) +} + func aptlySnapshotList(cmd *commander.Command, args []string) error { var err error if len(args) != 0 { @@ -15,32 +58,32 @@ func aptlySnapshotList(cmd *commander.Command, args []string) error { } raw := cmd.Flag.Lookup("raw").Value.Get().(bool) + sortMethod_string := cmd.Flag.Lookup("sort").Value.Get().(string) - snapshots := make([]string, context.CollectionFactory().SnapshotCollection().Len()) + snapshotsToSort := &snapshotListToSort{} + snapshotsToSort.list = make([]*deb.Snapshot, context.CollectionFactory().SnapshotCollection().Len()) + snapshotsToSort.sortMethod = ParseSortMethod(sortMethod_string) i := 0 context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error { - if raw { - snapshots[i] = snapshot.Name - } else { - snapshots[i] = snapshot.String() - } + snapshotsToSort.list[i] = snapshot i++ + return nil }) - sort.Strings(snapshots) + sort.Sort(snapshotsToSort) if raw { - for _, snapshot := range snapshots { - fmt.Printf("%s\n", snapshot) + for _, snapshot := range snapshotsToSort.list { + fmt.Printf("%s\n", snapshot.Name) } } else { - if len(snapshots) > 0 { + if len(snapshotsToSort.list) > 0 { fmt.Printf("List of snapshots:\n") - for _, snapshot := range snapshots { - fmt.Printf(" * %s\n", snapshot) + for _, snapshot := range snapshotsToSort.list { + fmt.Printf(" * %s\n", snapshot.String()) } fmt.Printf("\nTo get more information about snapshot, run `aptly snapshot show `.\n") @@ -67,6 +110,7 @@ Example: } cmd.Flag.Bool("raw", false, "display list in machine-readable format") + cmd.Flag.String("sort", "name", "display list in 'name' or creation 'time' order") return cmd } From b4ea963744e732896f055aa3e213d556a352bd71 Mon Sep 17 00:00:00 2001 From: Simon Aquino Date: Mon, 30 Jun 2014 19:13:35 +0100 Subject: [PATCH 2/7] List snapshots by time: added integration tests Added a couple of integration tests for the new list snapshot by creation time feature. --- system/t05_snapshot/ListSnapshot5Test_gold | 5 ++++ system/t05_snapshot/ListSnapshot6Test_gold | 8 ++++++ system/t05_snapshot/list.py | 33 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 system/t05_snapshot/ListSnapshot5Test_gold create mode 100644 system/t05_snapshot/ListSnapshot6Test_gold diff --git a/system/t05_snapshot/ListSnapshot5Test_gold b/system/t05_snapshot/ListSnapshot5Test_gold new file mode 100644 index 00000000..2768314a --- /dev/null +++ b/system/t05_snapshot/ListSnapshot5Test_gold @@ -0,0 +1,5 @@ +snap2 +snap1 +snap3 +snap4 +snap5 diff --git a/system/t05_snapshot/ListSnapshot6Test_gold b/system/t05_snapshot/ListSnapshot6Test_gold new file mode 100644 index 00000000..76336822 --- /dev/null +++ b/system/t05_snapshot/ListSnapshot6Test_gold @@ -0,0 +1,8 @@ +List of snapshots: + * [snap2]: Snapshot from mirror [wheezy-contrib]: http://mirror.yandex.ru/debian/ wheezy + * [snap1]: Snapshot from mirror [wheezy-main]: http://mirror.yandex.ru/debian/ wheezy + * [snap3]: Merged from sources: 'snap1', 'snap2' + * [snap4]: Pulled into 'snap1' with 'snap2' as source, pull request was: 'mame unrar' + * [snap5]: Snapshot from local repo [local-repo] + +To get more information about snapshot, run `aptly snapshot show `. diff --git a/system/t05_snapshot/list.py b/system/t05_snapshot/list.py index 8d135d15..ee7b313d 100644 --- a/system/t05_snapshot/list.py +++ b/system/t05_snapshot/list.py @@ -47,3 +47,36 @@ class ListSnapshot4Test(BaseTest): list snapshots: raw empty list """ runCmd = "aptly snapshot -raw list" + + +class ListSnapshot5Test(BaseTest): + """ + list snapshots: raw regular list sorted by time + """ + fixtureDB = True + fixtureCmds = [ + "aptly snapshot create snap2 from mirror wheezy-main", + "aptly snapshot create snap1 from mirror wheezy-contrib", + "aptly snapshot merge snap3 snap1 snap2", + "aptly snapshot pull snap1 snap2 snap4 mame unrar", + "aptly repo create local-repo", + "aptly repo add local-repo ${files}", + "aptly snapshot create snap5 from repo local-repo", + ] + runCmd = "aptly -raw -sort=time snapshot list" + +class ListSnapshot6Test(BaseTest): + """ + list snapshots: regular list sorted by time + """ + fixtureDB = True + fixtureCmds = [ + "aptly snapshot create snap2 from mirror wheezy-contrib", + "aptly snapshot create snap1 from mirror wheezy-main", + "aptly snapshot merge snap3 snap1 snap2", + "aptly snapshot pull snap1 snap2 snap4 mame unrar", + "aptly repo create local-repo", + "aptly repo add local-repo ${files}", + "aptly snapshot create snap5 from repo local-repo", + ] + runCmd = "aptly -sort=time snapshot list" From d9b35cea0151f4b1d77d2b8edeacf60637baf207 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Jul 2014 23:13:49 +0400 Subject: [PATCH 3/7] Allow running system tests by mask. E.g. system/run.py 'ListSnapshot*'. --- system/run.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/system/run.py b/system/run.py index 21f673c2..2bb6fb7e 100755 --- a/system/run.py +++ b/system/run.py @@ -4,6 +4,7 @@ import glob import importlib import os import inspect +import fnmatch import sys from lib import BaseTest @@ -15,11 +16,11 @@ except ImportError: return s -def run(include_long_tests=False, tests=None): +def run(include_long_tests=False, tests=None, filters=None): """ Run system test. """ - if tests is None: + if not tests: tests = glob.glob("t*_*") fails = [] numTests = numFailed = numSkipped = 0 @@ -34,6 +35,17 @@ def run(include_long_tests=False, tests=None): if not (inspect.isclass(o) and issubclass(o, BaseTest) and o is not BaseTest): continue + if filters: + matches = False + + for filt in filters: + if fnmatch.fnmatch(o.__name__, filt): + matches = True + break + + if not matches: + continue + t = o() if t.longTest and not include_long_tests or not t.fixture_available(): numSkipped += 1 @@ -70,10 +82,18 @@ if __name__ == "__main__": os.chdir(os.path.realpath(os.path.dirname(sys.argv[0]))) include_long_tests = False tests = None - if len(sys.argv) > 1: - if sys.argv[1] == "--long": - include_long_tests = True - tests = sys.argv[2:] + args = sys.argv[1:] + if len(args) > 0 and args[0] == "--long": + include_long_tests = True + args = args[1:] + + tests = [] + filters = [] + + for arg in args: + if arg.startswith('t'): + tests.append(arg) else: - tests = sys.argv[1:] - run(include_long_tests, tests) + filters.append(arg) + + run(include_long_tests, tests, filters) From de1fa851279ac3fc62e77494adecfce52ca24a96 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Jul 2014 23:14:32 +0400 Subject: [PATCH 4/7] Update man page. #73 --- man/aptly.1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/man/aptly.1 b/man/aptly.1 index d8807186..6c336482 100644 --- a/man/aptly.1 +++ b/man/aptly.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "APTLY" "1" "June 2014" "" "" +.TH "APTLY" "1" "July 2014" "" "" . .SH "NAME" \fBaptly\fR \- Debian repository management tool @@ -531,6 +531,10 @@ Options: \-\fBraw\fR=false display list in machine\-readable format . +.TP +\-\fBsort\fR=name +display list in \(cqname\(cq or creation \(cqtime\(cq order +. .SH "SHOWS DETAILS ABOUT SNAPSHOT" \fBaptly\fR \fBsnapshot\fR \fBshow\fR \fIname\fR . From d3707b4cfe6eef445af92852671bfea4fb9a844e Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Jul 2014 23:29:21 +0400 Subject: [PATCH 5/7] Add system test on wrong --sort parameter. #73 --- system/t05_snapshot/ListSnapshot7Test_gold | 1 + system/t05_snapshot/list.py | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 system/t05_snapshot/ListSnapshot7Test_gold diff --git a/system/t05_snapshot/ListSnapshot7Test_gold b/system/t05_snapshot/ListSnapshot7Test_gold new file mode 100644 index 00000000..a9dfcb04 --- /dev/null +++ b/system/t05_snapshot/ListSnapshot7Test_gold @@ -0,0 +1 @@ +ERROR: sorting method "planet" unknown diff --git a/system/t05_snapshot/list.py b/system/t05_snapshot/list.py index ee7b313d..1a50eab6 100644 --- a/system/t05_snapshot/list.py +++ b/system/t05_snapshot/list.py @@ -65,6 +65,7 @@ class ListSnapshot5Test(BaseTest): ] runCmd = "aptly -raw -sort=time snapshot list" + class ListSnapshot6Test(BaseTest): """ list snapshots: regular list sorted by time @@ -80,3 +81,12 @@ class ListSnapshot6Test(BaseTest): "aptly snapshot create snap5 from repo local-repo", ] runCmd = "aptly -sort=time snapshot list" + + +class ListSnapshot7Test(BaseTest): + """ + list snapshots: wrong parameter sort + """ + runCmd = "aptly -sort=planet snapshot list" + expectedCode = 1 + From 1a92d8bfe97b170b1e287baf9c0cb1cb44b0b8cc Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Jul 2014 23:29:36 +0400 Subject: [PATCH 6/7] Add --capture to auto-create 'gold' results when fail. --- system/lib.py | 17 ++++++++++++++--- system/run.py | 15 +++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/system/lib.py b/system/lib.py index e199d945..6a447a1b 100644 --- a/system/lib.py +++ b/system/lib.py @@ -84,6 +84,8 @@ class BaseTest(object): outputMatchPrepare = None + captureResults = False + def test(self): self.prepare() self.run() @@ -181,12 +183,21 @@ class BaseTest(object): def expand_environ(self, gold): return string.Template(gold).substitute(os.environ) + def get_gold_filename(self, gold_name="gold"): + return os.path.join(os.path.dirname(inspect.getsourcefile(self.__class__)), self.__class__.__name__ + "_" + gold_name) + def get_gold(self, gold_name="gold"): - gold = os.path.join(os.path.dirname(inspect.getsourcefile(self.__class__)), self.__class__.__name__ + "_" + gold_name) - return self.gold_processor(open(gold, "r").read()) + return self.gold_processor(open(self.get_gold_filename(gold_name), "r").read()) def check_output(self): - self.verify_match(self.get_gold(), self.output, match_prepare=self.outputMatchPrepare) + try: + self.verify_match(self.get_gold(), self.output, match_prepare=self.outputMatchPrepare) + except: + if self.captureResults: + with open(self.get_gold_filename(), "w") as f: + f.write(self.output) + else: + raise def check_cmd_output(self, command, gold_name, match_prepare=None, expected_code=0): self.verify_match(self.get_gold(gold_name), self.run_cmd(command, expected_code=expected_code), match_prepare) diff --git a/system/run.py b/system/run.py index 2bb6fb7e..e11feea2 100755 --- a/system/run.py +++ b/system/run.py @@ -16,7 +16,7 @@ except ImportError: return s -def run(include_long_tests=False, tests=None, filters=None): +def run(include_long_tests=False, capture_results=False, tests=None, filters=None): """ Run system test. """ @@ -56,6 +56,7 @@ def run(include_long_tests=False, tests=None, filters=None): sys.stdout.write("%s:%s... " % (test, o.__name__)) try: + t.captureResults = capture_results t.test() except BaseException, e: numFailed += 1 @@ -81,10 +82,16 @@ def run(include_long_tests=False, tests=None, filters=None): if __name__ == "__main__": os.chdir(os.path.realpath(os.path.dirname(sys.argv[0]))) include_long_tests = False + capture_results = False tests = None args = sys.argv[1:] - if len(args) > 0 and args[0] == "--long": - include_long_tests = True + + while len(args) > 0 and args[0].startswith("--"): + if args[0] == "--long": + include_long_tests = True + elif args[0] == "--capture": + capture_results = True + args = args[1:] tests = [] @@ -96,4 +103,4 @@ if __name__ == "__main__": else: filters.append(arg) - run(include_long_tests, tests, filters) + run(include_long_tests, capture_results, tests, filters) From 79016f7f98af835fe2bcef4334c171c327998b09 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Jul 2014 23:36:59 +0400 Subject: [PATCH 7/7] Slight refactoring, make wrong param real error. #73 --- cmd/snapshot_list.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/snapshot_list.go b/cmd/snapshot_list.go index 6b979bba..57f995e0 100644 --- a/cmd/snapshot_list.go +++ b/cmd/snapshot_list.go @@ -18,17 +18,15 @@ type snapshotListToSort struct { sortMethod int } -func ParseSortMethod(sortMethod_string string) int { - +func ParseSortMethod(sortMethod_string string) (int, error) { switch sortMethod_string { case "time", "Time": - return SortTime + return SortTime, nil case "name", "Name": - return SortName + return SortName, nil } - fmt.Errorf("Sorting method \"%s\" unknown. Defaulting to '-sort=name'", sortMethod_string) - return SortName + return -1, fmt.Errorf("sorting method \"%s\" unknown", sortMethod_string) } func (s snapshotListToSort) Swap(i, j int) { @@ -38,12 +36,11 @@ func (s snapshotListToSort) Swap(i, j int) { func (s snapshotListToSort) Less(i, j int) bool { switch s.sortMethod { case SortName: - sL := []string{s.list[i].Name, s.list[j].Name} - return sort.StringsAreSorted(sL) + return s.list[i].Name < s.list[j].Name case SortTime: return s.list[i].CreatedAt.Before(s.list[j].CreatedAt) } - return true + panic("unknown sort method") } func (s snapshotListToSort) Len() int { @@ -62,7 +59,10 @@ func aptlySnapshotList(cmd *commander.Command, args []string) error { snapshotsToSort := &snapshotListToSort{} snapshotsToSort.list = make([]*deb.Snapshot, context.CollectionFactory().SnapshotCollection().Len()) - snapshotsToSort.sortMethod = ParseSortMethod(sortMethod_string) + snapshotsToSort.sortMethod, err = ParseSortMethod(sortMethod_string) + if err != nil { + return err + } i := 0 context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error {