]> xenbits.xensource.com Git - people/gdunlap/xsatool/commitdiff
Allow builds to happen in temporary worktrees
authorGeorge Dunlap <george.dunlap@citrix.com>
Thu, 8 Nov 2018 16:28:15 +0000 (16:28 +0000)
committerGeorge Dunlap <george.dunlap@citrix.com>
Thu, 8 Nov 2018 16:28:15 +0000 (16:28 +0000)
Allow builds to happen in separate worktrees, so that further work can
carry on while the build is happening.

Add TreeWork ("worktree") to be able to have a configurable path to
place the worktrees.

Add a new Worktree type.  Add Repo.WorktreeAdd(), which will:
 - Create a new worktree of the name `name` in the given path
 - Create a new branch for that worktree based on the name

Add Worktree.Delete() which will remove the worktree, and delete its
branch from the main repo.

In Recipe.Build(), if the worktree path is set in the config, make a
new worktree to do the build; otherwise, fall back to creating a
temporary branch.  As with the temporary branch, clean up the worktree
only if the build succeeded.

Signed-off-by: George Dunlap <george.dunlap@citrix.com>
git.go
meta.go
recipe.go
repo.go

diff --git a/git.go b/git.go
index 3cacf1b732d7b01e3d8c84da127bf5a747052e8a..8a35c9d8f215ef37be13ef30a1c952b0ad499007 100644 (file)
--- a/git.go
+++ b/git.go
@@ -334,3 +334,37 @@ func (r Repo) ConfigEnableRerere() (err error) {
        _, err = r.gitCmd("config", "rerere.enabled", "true")
        return
 }
+
+type Worktree struct {
+       Repo
+       BaseRepo Repo
+       WorktreeBranch string
+}
+
+func (r Repo) WorktreeAdd(basepath string, name string, ref string) (wt *Worktree, err error) {
+       path := basepath + "/" + name
+       branchname := "worktree/" + name
+       
+       _, err = r.gitCmd("worktree", "add", "-b", branchname, path, ref)
+       if err != nil {
+               return
+       }
+       wt = &Worktree{
+               BaseRepo: r,
+               WorktreeBranch: branchname,
+       }
+       wt.Repo, err = GitOpen(path)
+       
+       return
+}
+
+func (wt Worktree) Delete() (err error) {
+       _, err = wt.gitCmd("worktree", "remove", "--force", ".")
+       if err != nil {
+               return
+       }
+
+       _, err = wt.BaseRepo.DeleteBranch(wt.WorktreeBranch)
+       
+       return
+}
diff --git a/meta.go b/meta.go
index e94e735526dfe78a7159f9b804081a2311867846..5ac63fe99f48fc3d9009074e959a62bcebb2457c 100644 (file)
--- a/meta.go
+++ b/meta.go
@@ -16,6 +16,8 @@ const (
        TreeQemuU = "qemuu"
        TreeQemuT = "qemut"
        TreeXSA   = "xsa"
+       // FIXME: This isn't really a tree...
+       TreeWork  = "worktree"
 )
 
 var TreeListAll = []Tree{TreeXen, TreeQemuU, TreeQemuT, TreeXSA}
@@ -24,7 +26,7 @@ var TreeListCode = []Tree{TreeXen, TreeQemuU, TreeQemuT}
 
 func TreeFromString(s string) (Tree, error) {
        switch s {
-       case TreeXen, TreeQemuU, TreeQemuT, TreeXSA:
+       case TreeXen, TreeQemuU, TreeQemuT, TreeXSA, TreeWork:
                return Tree(s), nil
        default:
                return "", fmt.Errorf("Unknown tree: %s\n", s)
@@ -33,7 +35,7 @@ func TreeFromString(s string) (Tree, error) {
 
 func (t Tree) String() string {
        switch t {
-       case TreeXen, TreeQemuU, TreeQemuT, TreeXSA:
+       case TreeXen, TreeQemuU, TreeQemuT, TreeXSA, TreeWork:
                return string(t)
        default:
                return "[INVALID]"
index 332832667fdecb55f46692d8d5e228cfc2641399..e017332dfa69a4a461c3e6c7ad975c2012dbce18 100644 (file)
--- a/recipe.go
+++ b/recipe.go
@@ -549,10 +549,7 @@ func (r *Recipe) Backport(prefix string, to XenVersion) (err error) {
 func (r *Recipe) Build(prefix string) (err error) {
        _, _, branch := r.branchName(prefix)
 
-       xenrepo := G.repos.GetRepoNC(TreeXen)
-
-       /* Always check out a temporary branch for xen */
-       tmpBranch := "xsa/tmp"
+       repo := G.repos.GetRepoNC(TreeXen).Repo
 
        // If the recipe has Xen patches, use the recipe branch name;
        // otherwise, use the stable branch for that Xen version
@@ -561,10 +558,27 @@ func (r *Recipe) Build(prefix string) (err error) {
                wtbranch = XenStableBranch(r.XenVersion)
        }
 
-       err = xenrepo.MakeBranch(tmpBranch, wtbranch)
-       if err != nil {
-               return fmt.Errorf("Making tempbranch %s from %v for xenversion %v: %v\n",
-                       tmpBranch, branch, r.XenVersion, err)
+       var wt *Worktree
+       
+       /* Always check out a temporary branch for xen */
+       tmpBranch := "xsa/tmp"
+
+       wtPath := G.config.Tool.GetPath(TreeWork)
+       if wtPath != "" {
+               // build-NNN-VV
+               name := fmt.Sprintf("build-%d-%v", r.xsa, r.XenVersion)
+               
+               wt, err = repo.WorktreeAdd(wtPath, name, wtbranch)
+               if err != nil {
+                       return
+               }
+               repo = wt.Repo
+       } else {
+               err = repo.MakeBranch(tmpBranch, wtbranch)
+               if err != nil {
+                       return fmt.Errorf("Making tempbranch %s from %v for xenversion %v: %v\n",
+                               tmpBranch, branch, r.XenVersion, err)
+               }
        }
 
        // Make .config file with path to repos
@@ -590,7 +604,7 @@ func (r *Recipe) Build(prefix string) (err error) {
 
        fmt.Printf("Writing build config file:\n%s\n", config)
 
-       if err = config.Write(xenrepo.GetPath()); err != nil {
+       if err = config.Write(repo.GetPath()); err != nil {
                return fmt.Errorf("Writing config: %v\n", err)
        }
 
@@ -602,7 +616,7 @@ func (r *Recipe) Build(prefix string) (err error) {
        defer os.Chdir(cwd)
 
        // Configure
-       os.Chdir(xenrepo.GetPath())
+       os.Chdir(repo.GetPath())
 
        logfile, err := os.Create("build.log")
        if err != nil {
@@ -627,13 +641,20 @@ func (r *Recipe) Build(prefix string) (err error) {
                return fmt.Errorf("Building: %v\n", err)
        }
 
-       _, err = xenrepo.Checkout("master")
-       if err != nil {
-               return
-       }
-       _, err = xenrepo.DeleteBranch(tmpBranch)
-       if err != nil {
-               return
+       if wt != nil {
+               err = wt.Delete()
+               if err != nil {
+                       return
+               }
+       } else {
+               _, err = repo.Checkout("master")
+               if err != nil {
+                       return
+               }
+               _, err = repo.DeleteBranch(tmpBranch)
+               if err != nil {
+                       return
+               }
        }
 
        return
diff --git a/repo.go b/repo.go
index da2e571323367ba164381e38a27dcb06bb24d4a3..2a8b717f8c9f62c519fc7ada4f36e59eb9d25d83 100644 (file)
--- a/repo.go
+++ b/repo.go
@@ -25,6 +25,7 @@ func MainRepoInit(unused *XSAMeta, args []string) (ret int) {
        proxyURL := flags.String("gitproxy", EmptyString,
                "Git proxy prefix, used for building")
 
+       
        if err := flags.Parse(args); err != nil {
                if err != flag.ErrHelp {
                        fmt.Printf("Error parsing args: %v\n", err)
@@ -58,6 +59,8 @@ func MainRepoInit(unused *XSAMeta, args []string) (ret int) {
                return
        }
 
+       // Only set default paths for actual git trees here; worktree
+       // must currently be set manually.
        ForEachTree(setDefaultPath)
 
        checkDir := func(target string) (clone bool, err error) {