From 343e927ae36a113ec8da912c82e570263be18da4 Mon Sep 17 00:00:00 2001 From: George Dunlap Date: Thu, 8 Jun 2017 17:37:45 +0100 Subject: [PATCH] Use new branching scheme New branching scheme: - $v-stable based on the recorded stable branch at the time the xsa was created - $v-baseline; the above, but with 'prerequisites' (outstanding XSAs not published yet) - $v: Branch with actual patches, only present when patches exist (or are being created) To do this: - Separate Recipe.Apply() into ApplyBaseline (which only does -stable and -baseline) and ApplyPatches (which makes the main branch) - Get rid of IsApplied(), which doesn't do what it says on the tin - Implement HasPatchBranch, which detect whether the "patch" branch(es) exist for a given recipe Then: - During Init, call only ApplyBaseline for all branches; only call ApplyPatches for master. - When calling sync-patches with 'all', have VersionsFromArgs filter out patches based on HasPatchBranch. (sync-branches and test will still test all supported branches for 'all'.) - Add a test for the failure path of sync-branches with a non-existent branch While we're here: - Use fmt.Print instead of fmt.Printf when there are no format tokens - Add missing '\n' to many status output messages Signed-off-by: George Dunlap --- main.go | 10 ++++- meta.go | 10 +++++ recipe.go | 119 ++++++++++++++++++++++++++++++++------------------ systemtest.go | 20 ++++++--- test.go | 13 +++--- xsa.go | 30 ++++++++++--- 6 files changed, 138 insertions(+), 64 deletions(-) diff --git a/main.go b/main.go index 99a540b..bb116b7 100644 --- a/main.go +++ b/main.go @@ -31,9 +31,15 @@ func ForEachXenRepo(f func(*XenRepo, Tree) error) error { return ForEachCodeTree(f2) } -func VersionsFromArgs(xsa *XSAMeta, args []string) (vers []XenVersion) { +func VersionsFromArgs(xsa *XSAMeta, args []string, hasPatches bool) (vers []XenVersion) { if len(args) == 0 || (len(args) == 1 && args[0] == "all") { - vers = append(vers, xsa.SupportedVersions...) + for _, v := range xsa.SupportedVersions { + // Check to see if the branch exists + if hasPatches && !xsa.RepoHasPatches(v) { + continue + } + vers = append(vers, v) + } } else { // FIXME: Verify xenversion format for _, v := range args { diff --git a/meta.go b/meta.go index 66b98b0..9588b32 100644 --- a/meta.go +++ b/meta.go @@ -237,6 +237,16 @@ func (m *XSAMeta) NewRecipe(v XenVersion) *Recipe { return &r } +func (m *XSAMeta) RepoHasPatches(v XenVersion) bool { + r := m.GetRecipe(v) + + if r == nil { + return false + } + + return r.HasPatchBranch("xsa") == nil +} + func getXSAPath(xsanum int) string { return fmt.Sprintf("%s/xsa%d.meta", G.config.Tool.GetPath(TreeXSA), xsanum) } diff --git a/recipe.go b/recipe.go index 56fc3e6..61341ed 100644 --- a/recipe.go +++ b/recipe.go @@ -82,7 +82,7 @@ func (r *Recipe) HasPatches() (has bool) { } func (r *Recipe) MakePatches(prefix string, sync bool) (count int, err error) { - branch, baseline := r.branchName(prefix) + _, baseline, branch := r.branchName(prefix) // rm -rf /tmp/xsa if err = os.RemoveAll(FPPath); err != nil { @@ -264,6 +264,11 @@ func (r *Recipe) MakePatches(prefix string, sync bool) (count int, err error) { type ErrorMissingBranch string +func IsMissingBranch(err error) (is bool) { + _, is = err.(ErrorMissingBranch) + return +} + func (s ErrorMissingBranch) Error() string { return fmt.Sprintf("Missing branch: %s", s) } @@ -273,12 +278,12 @@ func (s ErrorMissingBranch) Error() string { // branch (which is aliased as a string which tells you the name of // the missing branch); otherwise it returns whatever error it // encountered when processing. -func (r *Recipe) IsApplied(prefix string) (err error) { - branch, baseline := r.branchName(prefix) +func (r *Recipe) HasPatchBranch(prefix string) (err error) { + _, _, branch := r.branchName(prefix) check := func(tree Tree) (err error) { - tr, prs := r.Recipes[tree] - if !prs || !tr.HasPatches() { + _, prs := r.Recipes[tree] + if !prs { return } @@ -287,11 +292,6 @@ func (r *Recipe) IsApplied(prefix string) (err error) { if !xr.VerifyRef(branch) { return ErrorMissingBranch(branch) } - if !xr.VerifyRef(baseline) { - return ErrorMissingBranch(baseline) - } - - // FIXME: Actually check to see if something is applied return } @@ -303,18 +303,19 @@ func (r *Recipe) IsApplied(prefix string) (err error) { return } -func BranchName(prefix string, xsa int, v XenVersion) (branch, baseline string) { +func BranchName(prefix string, xsa int, v XenVersion) (stable, baseline, branch string) { // Construct branchname branch = prefix + "/" + strconv.Itoa(xsa) + "/" + v.String() + stable = branch + "-stable" baseline = branch + "-baseline" return } -func (r *Recipe) branchName(prefix string) (branch, baseline string) { - branch, baseline = BranchName(prefix, r.xsa, r.XenVersion) +func (r *Recipe) branchName(prefix string) (stable, baseline, branch string) { + stable, baseline, branch = BranchName(prefix, r.xsa, r.XenVersion) - fmt.Printf("Branchnames: %s %s\n", branch, baseline) + fmt.Printf("Branchnames: %s %s %s\n", stable, baseline, branch) return } @@ -322,47 +323,50 @@ func (r *Recipe) branchName(prefix string) (branch, baseline string) { // Naming convention: // // XSA patches: -// xsa/NNN/VV.v-baseline -// xsa/NNN/VV.v +// xsa/NNN/VV-stable +// xsa/NNN/VV-baseline +// xsa/NNN/VV // // Testing: // test/NN/MM.m -// Create branches and apply whatever patches exist. -func (r *Recipe) apply(xr *XenRepo, tr *TreeRecipe, prefix string) (err error) { - branch, baseline := r.branchName(prefix) +// Create a "patch series" branch and apply it +func (r *Recipe) ApplyPatches(prefix string) (err error) { + apply := func(tree Tree) (err error) { + tr, prs := r.Recipes[tree] - // FIXME change this to tr.StableRef - // Make "baseline" branch, based on XenVersion, with Prereq patches - err = xr.MakeBranch(baseline, tr.StableRef) - if err != nil { - return fmt.Errorf("Making baseline %s for xenversion %v: %v\n", - baseline, r.XenVersion) - } + if !prs { + err = fmt.Errorf("Internal data error: no recipe for tree %s\n", tree) + return + } - for _, xsanum := range tr.Prereqs { - err = fmt.Errorf("%d: Don't know how to apply XSA prerequisites yet!", xsanum) - return - } + xr := G.repos.XenRepos[tree] - // Make xsa branch based on "baseline" branch - err = xr.MakeBranch(branch, baseline) - if err != nil { - return fmt.Errorf("Making tempbranch %s for xenversion %v: %v\n", - branch, r.XenVersion) - } + _, baseline, branch := r.branchName(prefix) - for _, glob := range tr.Patches { - // git am - _, err = xr.AmClean(G.config.Tool.GetPath(TreeXSA) + "/" + glob) + // Make xsa branch based on "baseline" branch + err = xr.MakeBranch(branch, baseline) if err != nil { - return fmt.Errorf("Appling am %s: %v\n", glob, err) + return fmt.Errorf("Making tempbranch %s for xenversion %v: %v\n", + branch, r.XenVersion) } + + for _, glob := range tr.Patches { + // git am + _, err = xr.AmClean(G.config.Tool.GetPath(TreeXSA) + "/" + glob) + if err != nil { + return fmt.Errorf("Appling am %s: %v\n", glob, err) + } + } + return } + + err = r.ForEachTree(apply) + return } -func (r *Recipe) Apply(prefix string) (err error) { +func (r *Recipe) ApplyBaselines(prefix string) (err error) { apply := func(tree Tree) (err error) { tr, prs := r.Recipes[tree] @@ -373,11 +377,40 @@ func (r *Recipe) Apply(prefix string) (err error) { xr := G.repos.XenRepos[tree] - err = r.apply(xr, tr, prefix) + stable, baseline, _ := r.branchName(prefix) + + // Create xsa/NNN/VV-stable based on tr.StableRef + if err = xr.MakeBranch(stable, tr.StableRef); err != nil { + return fmt.Errorf("Making stable baseline %s for xenversion %v: %v\n", + stable, r.XenVersion, err) + } + + // Create xsa/NNN/VV-baseline based on -stable + if err = xr.MakeBranch(baseline, stable); err != nil { + return fmt.Errorf("Making patch baseline %s for xenversion %v: %v\n", + baseline, r.XenVersion, err) + } + + // FIXME Apply previous patches + for _, xsanum := range tr.Prereqs { + err = fmt.Errorf("%d: Don't know how to apply XSA prerequisites yet!", xsanum) + return + } + return } err = r.ForEachTree(apply) + + return +} + +func (r *Recipe) ApplyAll(prefix string) (err error) { + if err = r.ApplyBaselines(prefix); err != nil { + return + } + + err = r.ApplyPatches(prefix) return } @@ -394,7 +427,7 @@ func (r *Recipe) GetTreeRecipe(tree Tree) (tr *TreeRecipe, err error) { } func (r *Recipe) Build(prefix string) (err error) { - branch, _ := r.branchName(prefix) + _, _, branch := r.branchName(prefix) xenrepo := G.repos.XenRepos[TreeXen] diff --git a/systemtest.go b/systemtest.go index d86841a..ef6c265 100644 --- a/systemtest.go +++ b/systemtest.go @@ -242,7 +242,7 @@ func GlobalInit(st *SystemTest) (pass bool) { } func Story206Init(st *SystemTest) (pass bool) { - fmt.Printf(" xsatool 206 init xen") + fmt.Print(" xsatool 206 init xen\n") if MainHarness("206", "init", "xen") != 0 { st.Errorf("xsatool 206 init failed\n") return false @@ -383,7 +383,7 @@ func Story206Implement(st *SystemTest) (pass bool) { } func Story206SyncOne(st *SystemTest) (pass bool) { - fmt.Printf(" xsatool 206 sync-patches") + fmt.Print(" xsatool 206 sync-patches\n") if MainHarness("206", "sync-patches") != 0 { st.Errorf("xsatool 206 sync-patches failed\n") return false @@ -415,11 +415,21 @@ func Story206SyncOne(st *SystemTest) (pass bool) { } } - return pass + if !pass { + return + } + + fmt.Print(" xsatool 206 sync-patches 4.8 [should fail]\n") + if MainHarness("206", "sync-patches", "4.8") == 0 { + st.Errorf("xsatool 206 sync-patches 4.8 succeeded without any patches!\n") + return false + } + + return } func Story206TestMaster(st *SystemTest) bool { - fmt.Printf(" xsatool 206 test (initial)") + fmt.Print(" xsatool 206 test (initial)\n") if MainHarness("206", "test") != 0 { st.Errorf("xsatool 206 test (initial - master) failed\n") return false @@ -428,7 +438,7 @@ func Story206TestMaster(st *SystemTest) bool { } func Story206(st *SystemTest) bool { - fmt.Printf("Starting XSA-206 'story'") + fmt.Print("Starting XSA-206 'story'\n") // xsatool 206 init xen if !Story206Init(st) { return false diff --git a/test.go b/test.go index 99bf0e8..5ba91e1 100644 --- a/test.go +++ b/test.go @@ -6,7 +6,7 @@ import ( func test(xsa *XSAMeta, args []string, apply bool, build bool) (ret int) { - vers := VersionsFromArgs(xsa, args) + vers := VersionsFromArgs(xsa, args, false) for _, v := range vers { prefix := "test" @@ -22,22 +22,19 @@ func test(xsa *XSAMeta, args []string, apply bool, build bool) (ret int) { } if apply { - err := r.Apply(prefix) - if err != nil { + if err := r.ApplyAll(prefix); err != nil { fmt.Printf("Applying recipe: %v\n", err) fmt.Printf("FAILED: %v\n", r.XenVersion) return 1 } } else { - err := r.IsApplied(prefix) - if err != nil { - emb, missing := err.(ErrorMissingBranch) - if !missing { + if err := r.HasPatchBranch(prefix); err != nil { + if !IsMissingBranch(err) { fmt.Printf("Error checking to see if recipe has been applied: %v\n", err) return 1 } fmt.Printf("Error: recipe for xsa %d version %v not applied (missing branch %s)\n", - xsa.XSA, v, string(emb)) + xsa.XSA, v, string(err.(ErrorMissingBranch))) return 1 } } diff --git a/xsa.go b/xsa.go index 7b04631..9069f93 100644 --- a/xsa.go +++ b/xsa.go @@ -5,7 +5,7 @@ import ( ) func sync(xsa *XSAMeta, args []string, sync bool) (ret int) { - vers := VersionsFromArgs(xsa, args) + vers := VersionsFromArgs(xsa, args, true) if !sync && len(vers) > 1 { fmt.Printf("Error: Doesn't make sense to make more than one version\n") @@ -20,6 +20,17 @@ func sync(xsa *XSAMeta, args []string, sync bool) (ret int) { return 1 } + // Check to see if there's a branch. If not, throw an error. + if err := r.HasPatchBranch("xsa"); err != nil { + if IsMissingBranch(err) { + fmt.Printf("Error: No patch branch for version %v (missing branch %s)\n", + v, string(err.(ErrorMissingBranch))) + return 1 + } + fmt.Printf("Error checking for patch branch: %v\n", err) + return 1 + } + count, err := r.MakePatches("xsa", sync) if err != nil { fmt.Printf("Making patches: %v\n", err) @@ -47,7 +58,7 @@ func MainMakePatches(xsa *XSAMeta, args []string) (ret int) { } func MainSyncBranch(xsa *XSAMeta, args []string) (ret int) { - vers := VersionsFromArgs(xsa, args) + vers := VersionsFromArgs(xsa, args, false) for _, v := range vers { prefix := "xsa" @@ -57,7 +68,7 @@ func MainSyncBranch(xsa *XSAMeta, args []string) (ret int) { return 1 } - err := r.Apply(prefix) + err := r.ApplyAll(prefix) if err != nil { fmt.Printf("Applying recipe: %v\n", err) fmt.Printf("FAILED: %v\n", r.XenVersion) @@ -133,14 +144,21 @@ func MainInit(xsa *XSAMeta, args []string) (ret int) { } - if err := r.Apply("xsa"); err != nil { - fmt.Printf("Applying initial recipe for version %v\n", v) + if err := r.ApplyBaselines("xsa"); err != nil { + fmt.Printf("Making recipe baseline for version %v\n", v) return 1 } + + if v == XenVersionMaster { + if err := r.ApplyPatches("xsa"); err != nil { + fmt.Printf("Applying recipe patches for version %v\n", v) + return 1 + } + } } // Check out "xsa/NNN/master" on all relevant trees - branch, _ := BranchName("xsa", xsa.XSA, XenVersion("master")) + _, _, branch := BranchName("xsa", xsa.XSA, XenVersion("master")) for _, t := range xsa.Trees { _, err := G.repos.XenRepos[t].Checkout(branch) if err != nil { -- 2.39.5