You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2017/03/07 23:49:47 UTC

[2/3] incubator-mynewt-newt git commit: Updates to sync/upgrade/install inner working

Updates to sync/upgrade/install inner working

- sync now creates a new branch when checking out a tag commit
- sync flow now:
  1) stash changes
  2) fetch branchs/tags from origin
  3) merges in changes on master and develop
  4) checks out old branch or new branch (creating if necessary)
  5) stash pops if the previous stash was succesful
- upgrade/install now try first to cleanup and existing repo and if it
  fails do the old style remove+clone.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/0418ceab
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/0418ceab
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/0418ceab

Branch: refs/heads/develop
Commit: 0418ceab007a703ca86652adb7455958d5eac24b
Parents: 0196ba5
Author: Fabio Utzig <ut...@utzig.org>
Authored: Tue Mar 7 11:33:01 2017 -0300
Committer: Fabio Utzig <ut...@utzig.org>
Committed: Tue Mar 7 11:33:01 2017 -0300

----------------------------------------------------------------------
 newt/downloader/downloader.go | 116 +++++++++++++++++++++++++++++++------
 newt/repo/repo.go             |  78 ++++++++++++-------------
 2 files changed, 138 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0418ceab/newt/downloader/downloader.go
----------------------------------------------------------------------
diff --git a/newt/downloader/downloader.go b/newt/downloader/downloader.go
index e57ecfa..c8e13c6 100644
--- a/newt/downloader/downloader.go
+++ b/newt/downloader/downloader.go
@@ -41,7 +41,7 @@ type Downloader interface {
 	SetBranch(branch string)
 	DownloadRepo(branch string) (string, error)
 	CurrentBranch(path string) (string, error)
-	UpdateRepo(path string) error
+	UpdateRepo(path string, branchName string) error
 	CleanupRepo(path string, branchName string) error
 	LocalDiff(path string) ([]byte, error)
 }
@@ -100,22 +100,86 @@ func executeGitCommand(dir string, cmd []string) ([]byte, error) {
 	return output, nil
 }
 
+func isTag(repoDir string, branchName string) bool {
+	cmd := []string{"tag", "--list"}
+	output, _ := executeGitCommand(repoDir, cmd)
+	return strings.Contains(string(output), branchName)
+}
+
+func branchExists(repoDir string, branchName string) bool {
+	cmd := []string{"show-ref", "--verify", "--quiet", "refs/heads/" + branchName}
+	_, err := executeGitCommand(repoDir, cmd)
+	return err == nil
+}
+
+// checkout does checkout a branch, or create a new branch from a tag name
+// if the commit supplied is a tag. sha1 based commits have no special
+// handling and result in dettached from HEAD state.
 func checkout(repoDir string, commit string) error {
-	cmd := []string{
-		"checkout",
-		commit,
+	var cmd []string
+	if isTag(repoDir, commit) && !branchExists(repoDir, commit) {
+		util.StatusMessage(util.VERBOSITY_VERBOSE, "Will create new branch %s"+
+			" from tag %s\n", commit, "tags/"+commit)
+		cmd = []string{
+			"checkout",
+			"tags/" + commit,
+			"-b",
+			commit,
+		}
+	} else {
+		util.StatusMessage(util.VERBOSITY_VERBOSE, "Will checkout branch %s\n",
+			commit)
+		cmd = []string{
+			"checkout",
+			commit,
+		}
 	}
 	_, err := executeGitCommand(repoDir, cmd)
 	return err
 }
 
-func pull(repoDir string) error {
-	_, err := executeGitCommand(repoDir, []string{"pull"})
+// mergeBranches applies upstream changes to the local copy and must be
+// preceeded by a "fetch" to achieve any meaningful result.
+func mergeBranches(repoDir string) {
+	branches := []string{"master", "develop"}
+	for _, branch := range branches {
+		err := checkout(repoDir, branch)
+		if err != nil {
+			continue
+		}
+		_, err = executeGitCommand(repoDir, []string{"merge", "origin/" + branch})
+		if err != nil {
+			util.StatusMessage(util.VERBOSITY_VERBOSE, "Merging changes from origin/%s: %s\n",
+				branch, err)
+		} else {
+			util.StatusMessage(util.VERBOSITY_VERBOSE, "Merging changes from origin/%s\n",
+				branch)
+		}
+		// XXX: ignore error, probably resulting from a branch not available at
+		//      origin anymore.
+	}
+}
+
+func fetch(repoDir string) error {
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "Fetching new remote branches/tags\n")
+	_, err := executeGitCommand(repoDir, []string{"fetch", "--tags"})
 	return err
 }
 
-func stash(repoDir string) error {
-	_, err := executeGitCommand(repoDir, []string{"stash"})
+// stash saves current changes locally and returns if a new stash was
+// created (if there where no changes, there's no need to stash)
+func stash(repoDir string) (bool, error) {
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "Stashing local changes\n")
+	output, err := executeGitCommand(repoDir, []string{"stash"})
+	if err != nil {
+		return false, err
+	}
+	return strings.Contains(string(output), "Saved"), nil
+}
+
+func stashPop(repoDir string) error {
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "Un-stashing local changes\n")
+	_, err := executeGitCommand(repoDir, []string{"stash", "pop"})
 	return err
 }
 
@@ -198,27 +262,45 @@ func (gd *GithubDownloader) CurrentBranch(path string) (string, error) {
 	return strings.Trim(string(branch), "\r\n"), err
 }
 
-func (gd *GithubDownloader) UpdateRepo(path string) error {
-	return pull(path)
-}
-
-func (gd *GithubDownloader) CleanupRepo(path string, branchName string) error {
-	err := stash(path)
+func (gd *GithubDownloader) UpdateRepo(path string, branchName string) error {
+	err := fetch(path)
 	if err != nil {
 		return err
 	}
 
-	err = clean(path)
+	stashed, err := stash(path)
 	if err != nil {
 		return err
 	}
 
+	mergeBranches(path)
+
 	err = checkout(path, branchName)
 	if err != nil {
 		return err
 	}
 
-	return pull(path)
+	if stashed {
+		return stashPop(path)
+	}
+
+	return nil
+}
+
+func (gd *GithubDownloader) CleanupRepo(path string, branchName string) error {
+	_, err := stash(path)
+	if err != nil {
+		return err
+	}
+
+	err = clean(path)
+	if err != nil {
+		return err
+	}
+
+	// TODO: needs handling of non-tracked files
+
+	return gd.UpdateRepo(path, branchName)
 }
 
 func (gd *GithubDownloader) LocalDiff(path string) ([]byte, error) {
@@ -303,7 +385,7 @@ func (ld *LocalDownloader) CurrentBranch(path string) (string, error) {
 }
 
 // NOTE: intentionally always error...
-func (ld *LocalDownloader) UpdateRepo(path string) error {
+func (ld *LocalDownloader) UpdateRepo(path string, branchName string) error {
 	return util.NewNewtError(fmt.Sprintf("Can't pull from a local repo\n"))
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0418ceab/newt/repo/repo.go
----------------------------------------------------------------------
diff --git a/newt/repo/repo.go b/newt/repo/repo.go
index a4a916f..139c499 100644
--- a/newt/repo/repo.go
+++ b/newt/repo/repo.go
@@ -378,11 +378,11 @@ func (r *Repo) checkExists() bool {
 	return util.NodeExist(r.Path())
 }
 
-func (r *Repo) updateRepo() error {
+func (r *Repo) updateRepo(branchName string) error {
 	dl := r.downloader
-	err := dl.UpdateRepo(r.Path())
+	err := dl.UpdateRepo(r.Path(), branchName)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("\tError updating\n"))
+		return util.NewNewtError(fmt.Sprintf("Error updating\n"))
 	}
 	return nil
 }
@@ -391,7 +391,7 @@ func (r *Repo) cleanupRepo(branchName string) error {
 	dl := r.downloader
 	err := dl.CleanupRepo(r.Path(), branchName)
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("\tError cleaning and updating\n"))
+		return util.NewNewtError(fmt.Sprintf("Error cleaning and updating\n"))
 	}
 	return nil
 }
@@ -431,33 +431,15 @@ func (r *Repo) currentBranch() (string, error) {
 		return "", util.NewNewtError(fmt.Sprintf("Error finding current branch for \"%s\" : %s",
 			r.Name(), err.Error()))
 	}
-	return branch, nil
-}
-
-func (r *Repo) checkForceInstall(force bool) (error, bool) {
-	// Copy the git repo into /repos/, error'ing out if the repo already exists
-	if util.NodeExist(r.Path()) {
-		if force {
-			if err := os.RemoveAll(r.Path()); err != nil {
-				return util.NewNewtError(err.Error()), true
-			}
-		}
-		return nil, true
-	}
-	return nil, false
+	return filepath.Base(branch), nil
 }
 
 func (r *Repo) Install(force bool) (*Version, error) {
-	if err, exists := r.checkForceInstall(force); err != nil || exists {
-		if err == nil {
-			if !force {
-				return nil, util.NewNewtError(fmt.Sprintf(
-					"Repository %s already exists, provide the -f option "+
-						"to overwrite", r.Name()))
-			}
-		} else {
-			return nil, err
-		}
+	exists := util.NodeExist(r.Path())
+	if exists && !force {
+		return nil, util.NewNewtError(fmt.Sprintf(
+			"Repository %s already exists, provide the -f option "+
+				"to overwrite", r.Name()))
 	}
 
 	branchName, vers, found := r.rdesc.Match(r)
@@ -466,6 +448,20 @@ func (r *Repo) Install(force bool) (*Version, error) {
 			r.rdesc.String()))
 	}
 
+	// if the repo is already cloned, try to cleanup and checkout the requested branch
+	if exists {
+		err := r.cleanupRepo(branchName)
+		if err == nil {
+			return vers, nil
+		}
+
+		// cleanup failed, so remove current copy and let download clone again...
+		if err := os.RemoveAll(r.Path()); err != nil {
+			return nil, util.NewNewtError(err.Error())
+		}
+	}
+
+	// repo was not already cloned or cleanup failed...
 	if err := r.downloadRepo(branchName); err != nil {
 		return nil, err
 	}
@@ -496,10 +492,13 @@ func (r *Repo) Sync(vers *Version, force bool) (bool, bool, error) {
 		// the user must know what he's doing...
 		// but, if -f is passed let's just save the work and re-clone
 		currBranch, err = r.currentBranch()
+
+		// currBranch == HEAD means we're dettached from HEAD, so
+		// ignore and move to "new" tag
 		if err != nil {
 			return exists, false, err
-		} else if currBranch != branchName {
-			msg := "Unexpected local branch for %s: \"%s\" != \"%s\""
+		} else if currBranch != "HEAD" && currBranch != branchName {
+			msg := "Unexpected local branch for %s: \"%s\" != \"%s\"\n"
 			if force {
 				util.StatusMessage(util.VERBOSITY_VERBOSE,
 					msg, r.rdesc.name, currBranch, branchName)
@@ -511,14 +510,14 @@ func (r *Repo) Sync(vers *Version, force bool) (bool, bool, error) {
 		}
 
 		// Don't try updating if on an invalid branch...
-		if currBranch == branchName {
-			util.StatusMessage(util.VERBOSITY_VERBOSE, "\tTrying to update repository... ")
-			err = r.updateRepo()
+		if currBranch == "HEAD" || currBranch == branchName {
+			util.StatusMessage(util.VERBOSITY_VERBOSE, "Updating repository...\n")
+			err = r.updateRepo(branchName)
 			if err == nil {
-				util.StatusMessage(util.VERBOSITY_VERBOSE, " success!\n")
+				util.StatusMessage(util.VERBOSITY_VERBOSE, "Update successful!\n")
 				return exists, true, err
 			} else {
-				util.StatusMessage(util.VERBOSITY_VERBOSE, " failed!\n")
+				util.StatusMessage(util.VERBOSITY_VERBOSE, "Update failed!\n")
 				if !force {
 					return exists, false, err
 				}
@@ -566,6 +565,7 @@ func (r *Repo) UpdateDesc() ([]*Repo, bool, error) {
 
 	_, repos, err := r.ReadDesc()
 	if err != nil {
+		fmt.Printf("ReadDesc: %v\n", err)
 		return nil, false, err
 	}
 
@@ -578,8 +578,8 @@ func (r *Repo) UpdateDesc() ([]*Repo, bool, error) {
 func (r *Repo) DownloadDesc() error {
 	dl := r.downloader
 
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "\tDownloading "+
-		"repository description... ")
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "Downloading "+
+		"repository description\n")
 
 	// Configuration path
 	cpath := r.repoFilePath()
@@ -592,7 +592,7 @@ func (r *Repo) DownloadDesc() error {
 	dl.SetBranch("master")
 	if err := dl.FetchFile("repository.yml",
 		cpath+"/"+"repository.yml"); err != nil {
-		util.StatusMessage(util.VERBOSITY_VERBOSE, " failed\n")
+		util.StatusMessage(util.VERBOSITY_VERBOSE, "Download failed\n")
 		return err
 	}
 
@@ -604,7 +604,7 @@ func (r *Repo) DownloadDesc() error {
 		}
 	}
 
-	util.StatusMessage(util.VERBOSITY_VERBOSE, " success!\n")
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "Download successful!\n")
 
 	return nil
 }