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/08 00:06:08 UTC
[4/5] incubator-mynewt-newt git commit: MYNEWT-495: updates to sync
command
MYNEWT-495: updates to sync command
- When repo is already cloned, try to update from remote
- If -f is passed, create a modifications diff, and try harder
to update current local (stash, clean, checkout, pull)
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/a7c02356
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/a7c02356
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/a7c02356
Branch: refs/heads/1_0_0_dev
Commit: a7c0235607ab10427aab02f7631e1a451cf889cc
Parents: 934b3cc
Author: Fabio Utzig <ut...@utzig.org>
Authored: Fri Mar 3 09:49:52 2017 -0300
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Mar 7 16:00:35 2017 -0800
----------------------------------------------------------------------
newt/cli/project_cmds.go | 23 ++-
newt/downloader/downloader.go | 110 ++++++++++---
newt/repo/repo.go | 157 +++++++++++++++++--
newt/vendor/mynewt.apache.org/newt/util/util.go | 1 -
4 files changed, 247 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/a7c02356/newt/cli/project_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/project_cmds.go b/newt/cli/project_cmds.go
index a8d93b2..89a6eae 100644
--- a/newt/cli/project_cmds.go
+++ b/newt/cli/project_cmds.go
@@ -20,6 +20,7 @@
package cli
import (
+ "fmt"
"os"
"sort"
"strings"
@@ -156,26 +157,32 @@ func syncRunCmd(cmd *cobra.Command, args []string) {
NewtUsage(nil, err)
}
+ var failedRepos []string
for _, repo := range repos {
var exists bool
+ var updated bool
if repo.IsLocal() {
continue
}
vers := ps.GetInstalledVersion(repo.Name())
if vers == nil {
util.StatusMessage(util.VERBOSITY_DEFAULT,
- "No installed version of %s found, skipping\n",
+ "No installed version of %s found, skipping\n\n",
repo.Name())
}
- if err, exists = repo.Sync(vers, newtutil.NewtForce); err != nil {
- NewtUsage(nil, err)
+ exists, updated, err = repo.Sync(vers, newtutil.NewtForce)
+ if exists && !updated {
+ failedRepos = append(failedRepos, repo.Name())
}
-
- if exists && !newtutil.NewtForce {
- util.StatusMessage(util.VERBOSITY_DEFAULT,
- "Skipping resync of %s because directory exists. To "+
- "force resync, add the -f (force) option.\n", repo.Name())
+ }
+ if len(failedRepos) > 0 {
+ var forceMsg string
+ if !newtutil.NewtForce {
+ forceMsg = " To force resync, add the -f (force) option."
}
+ err = util.NewNewtError(fmt.Sprintf("Failed for repos: %v."+
+ forceMsg, failedRepos))
+ NewtUsage(nil, err)
}
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/a7c02356/newt/downloader/downloader.go
----------------------------------------------------------------------
diff --git a/newt/downloader/downloader.go b/newt/downloader/downloader.go
index 0ab201e..e57ecfa 100644
--- a/newt/downloader/downloader.go
+++ b/newt/downloader/downloader.go
@@ -27,6 +27,7 @@ import (
"os"
"os/exec"
"path/filepath"
+ "strings"
log "github.com/Sirupsen/logrus"
@@ -39,6 +40,10 @@ type Downloader interface {
Branch() string
SetBranch(branch string)
DownloadRepo(branch string) (string, error)
+ CurrentBranch(path string) (string, error)
+ UpdateRepo(path string) error
+ CleanupRepo(path string, branchName string) error
+ LocalDiff(path string) ([]byte, error)
}
type GenericDownloader struct {
@@ -66,42 +71,57 @@ type LocalDownloader struct {
Path string
}
-func checkout(repoDir string, commit string) error {
- // Retrieve the current directory so that we can get back to where we
- // started after the download completes.
- pwd, err := os.Getwd()
+func executeGitCommand(dir string, cmd []string) ([]byte, error) {
+ wd, err := os.Getwd()
if err != nil {
- return util.NewNewtError(err.Error())
+ return nil, util.NewNewtError(err.Error())
}
gitPath, err := exec.LookPath("git")
if err != nil {
- return util.NewNewtError(fmt.Sprintf("Can't find git binary: %s\n",
+ return nil, util.NewNewtError(fmt.Sprintf("Can't find git binary: %s\n",
err.Error()))
}
gitPath = filepath.ToSlash(gitPath)
- if err := os.Chdir(repoDir); err != nil {
- return util.NewNewtError(err.Error())
+ if err := os.Chdir(dir); err != nil {
+ return nil, util.NewNewtError(err.Error())
}
- // Checkout the specified commit.
+ defer os.Chdir(wd)
+
+ gitCmd := []string{gitPath}
+ gitCmd = append(gitCmd, cmd...)
+ output, err := util.ShellCommand(gitCmd, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return output, nil
+}
+
+func checkout(repoDir string, commit string) error {
cmd := []string{
- gitPath,
"checkout",
commit,
}
+ _, err := executeGitCommand(repoDir, cmd)
+ return err
+}
- if o, err := util.ShellCommand(cmd, nil); err != nil {
- return util.NewNewtError(string(o))
- }
+func pull(repoDir string) error {
+ _, err := executeGitCommand(repoDir, []string{"pull"})
+ return err
+}
- // Go back to original directory.
- if err := os.Chdir(pwd); err != nil {
- return util.NewNewtError(err.Error())
- }
+func stash(repoDir string) error {
+ _, err := executeGitCommand(repoDir, []string{"stash"})
+ return err
+}
- return nil
+func clean(repoDir string) error {
+ _, err := executeGitCommand(repoDir, []string{"clean", "-f"})
+ return err
}
func (gd *GenericDownloader) Branch() string {
@@ -172,6 +192,39 @@ func (gd *GithubDownloader) FetchFile(name string, dest string) error {
return nil
}
+func (gd *GithubDownloader) CurrentBranch(path string) (string, error) {
+ cmd := []string{"rev-parse", "--abbrev-ref", "HEAD"}
+ branch, err := executeGitCommand(path, cmd)
+ 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)
+ if err != nil {
+ return err
+ }
+
+ err = clean(path)
+ if err != nil {
+ return err
+ }
+
+ err = checkout(path, branchName)
+ if err != nil {
+ return err
+ }
+
+ return pull(path)
+}
+
+func (gd *GithubDownloader) LocalDiff(path string) ([]byte, error) {
+ return executeGitCommand(path, []string{"diff"})
+}
+
func (gd *GithubDownloader) DownloadRepo(commit string) (string, error) {
// Get a temporary directory, and copy the repository into that directory.
tmpdir, err := ioutil.TempDir("", "newt-repo")
@@ -243,6 +296,27 @@ func (ld *LocalDownloader) FetchFile(name string, dest string) error {
return nil
}
+func (ld *LocalDownloader) CurrentBranch(path string) (string, error) {
+ cmd := []string{"rev-parse", "--abbrev-ref", "HEAD"}
+ branch, err := executeGitCommand(path, cmd)
+ return strings.Trim(string(branch), "\r\n"), err
+}
+
+// NOTE: intentionally always error...
+func (ld *LocalDownloader) UpdateRepo(path string) error {
+ return util.NewNewtError(fmt.Sprintf("Can't pull from a local repo\n"))
+}
+
+func (ld *LocalDownloader) CleanupRepo(path string, branchName string) error {
+ os.RemoveAll(path)
+ _, err := ld.DownloadRepo(branchName)
+ return err
+}
+
+func (ld *LocalDownloader) LocalDiff(path string) ([]byte, error) {
+ return executeGitCommand(path, []string{"diff"})
+}
+
func (ld *LocalDownloader) DownloadRepo(commit string) (string, error) {
// Get a temporary directory, and copy the repository into that directory.
tmpdir, err := ioutil.TempDir("", "newt-repo")
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/a7c02356/newt/repo/repo.go
----------------------------------------------------------------------
diff --git a/newt/repo/repo.go b/newt/repo/repo.go
index a2b98c9..316b274 100644
--- a/newt/repo/repo.go
+++ b/newt/repo/repo.go
@@ -25,6 +25,7 @@ import (
"os"
"path/filepath"
"strings"
+ "time"
log "github.com/Sirupsen/logrus"
"github.com/spf13/cast"
@@ -345,6 +346,11 @@ func (r *Repo) repoFilePath() string {
".configs/" + r.name + "/"
}
+func (r *Repo) patchesFilePath() string {
+ return interfaces.GetProject().Path() + "/" + REPOS_DIR +
+ "/.patches/"
+}
+
func (r *Repo) downloadRepo(branchName string) error {
dl := r.downloader
@@ -366,6 +372,66 @@ func (r *Repo) downloadRepo(branchName string) error {
return nil
}
+func (r *Repo) checkExists() bool {
+ return util.NodeExist(r.Path())
+}
+
+func (r *Repo) updateRepo() error {
+ dl := r.downloader
+ err := dl.UpdateRepo(r.Path())
+ if err != nil {
+ return util.NewNewtError(fmt.Sprintf("\tError updating\n"))
+ }
+ return nil
+}
+
+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 nil
+}
+
+func (r *Repo) saveLocalDiff() (string, error) {
+ dl := r.downloader
+ diff, err := dl.LocalDiff(r.Path())
+ if err != nil {
+ return "", util.NewNewtError(fmt.Sprintf(
+ "Error creating diff for \"%s\" : %s", r.Name(), err.Error()))
+ }
+
+ // NOTE: date was not a typo: https://golang.org/pkg/time/#Time.Format
+ timenow := time.Now().Format("20060102_150405")
+ filename := r.patchesFilePath() + r.Name() + "_" + timenow + ".diff"
+
+ f, err := os.Create(filename)
+ if err != nil {
+ return "", util.NewNewtError(fmt.Sprintf(
+ "Error creating repo diff file \"%s\"", filename))
+ }
+ defer f.Close()
+
+ _, err = f.Write(diff)
+ if err != nil {
+ return "", util.NewNewtError(fmt.Sprintf(
+ "Error writing repo diff file \"%s\"", filename))
+ }
+
+ return filename, nil
+}
+
+func (r *Repo) currentBranch() (string, error) {
+ dl := r.downloader
+ branch, err := dl.CurrentBranch(r.Path())
+ if err != nil {
+ 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()) {
@@ -405,33 +471,82 @@ func (r *Repo) Install(force bool) (*Version, error) {
return vers, nil
}
-func (r *Repo) Sync(vers *Version, force bool) (error, bool) {
+func (r *Repo) Sync(vers *Version, force bool) (bool, bool, error) {
var exists bool
var err error
+ var currBranch string
- if err, exists = r.checkForceInstall(force); err != nil {
- return err, exists
- }
- if exists && !force {
- return nil, exists
- }
+ exists = r.checkExists()
// Update the repo description
if _, updated, err := r.UpdateDesc(); updated != true || err != nil {
- return util.NewNewtError("Cannot update repository description."), exists
+ return exists, false, util.NewNewtError("Cannot update repository description.")
}
- branchName, vers, found := r.rdesc.MatchVersion(vers)
+ branchName, _, found := r.rdesc.MatchVersion(vers)
if found == false {
- return util.NewNewtError(fmt.Sprintf("Branch description for %s not found",
- r.Name())), exists
+ return exists, false, util.NewNewtError(fmt.Sprintf(
+ "Branch description for %s not found", r.Name()))
}
- if err := r.downloadRepo(branchName); err != nil {
- return err, exists
+ if exists {
+ // Here assuming that if the branch was changed by the user,
+ // 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()
+ if err != nil {
+ return exists, false, err
+ } else if currBranch != branchName {
+ msg := "Unexpected local branch for %s: \"%s\" != \"%s\""
+ if force {
+ util.StatusMessage(util.VERBOSITY_VERBOSE,
+ msg, r.rdesc.name, currBranch, branchName)
+ } else {
+ err = util.NewNewtError(
+ fmt.Sprintf(msg, r.rdesc.name, currBranch, branchName))
+ return exists, false, err
+ }
+ }
+
+ // 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 err == nil {
+ util.StatusMessage(util.VERBOSITY_VERBOSE, " success!\n")
+ return exists, true, err
+ } else {
+ util.StatusMessage(util.VERBOSITY_VERBOSE, " failed!\n")
+ if !force {
+ return exists, false, err
+ }
+ }
+ }
+
+ filename, err := r.saveLocalDiff()
+ if err != nil {
+ return exists, false, err
+ }
+ wd, _ := os.Getwd()
+ filename, _ = filepath.Rel(wd, filename)
+
+ util.StatusMessage(util.VERBOSITY_DEFAULT, "Saved local diff: "+
+ "\"%s\"\n", filename)
+
+ err = r.cleanupRepo(branchName)
+ if err != nil {
+ return exists, false, err
+ }
+
+ } else {
+ // fresh or updating was unsuccessfull and force was given...
+ err = r.downloadRepo(branchName)
+ if err != nil {
+ return exists, false, err
+ }
}
- return nil, exists
+ return exists, true, nil
}
func (r *Repo) UpdateDesc() ([]*Repo, bool, error) {
@@ -441,7 +556,7 @@ func (r *Repo) UpdateDesc() ([]*Repo, bool, error) {
return nil, false, nil
}
- util.StatusMessage(util.VERBOSITY_DEFAULT, "%s\n", r.Name())
+ util.StatusMessage(util.VERBOSITY_VERBOSE, "[%s]:\n", r.Name())
if err = r.DownloadDesc(); err != nil {
return nil, false, err
@@ -461,8 +576,8 @@ func (r *Repo) UpdateDesc() ([]*Repo, bool, error) {
func (r *Repo) DownloadDesc() error {
dl := r.downloader
- util.StatusMessage(util.VERBOSITY_VERBOSE, "Downloading "+
- "repository description for %s...\n", r.Name())
+ util.StatusMessage(util.VERBOSITY_VERBOSE, "\tDownloading "+
+ "repository description... ")
// Configuration path
cpath := r.repoFilePath()
@@ -479,6 +594,14 @@ func (r *Repo) DownloadDesc() error {
return err
}
+ // also create a directory to save diffs for sync
+ cpath = r.patchesFilePath()
+ if util.NodeNotExist(cpath) {
+ if err := os.MkdirAll(cpath, REPO_DEFAULT_PERMS); err != nil {
+ return util.NewNewtError(err.Error())
+ }
+ }
+
util.StatusMessage(util.VERBOSITY_VERBOSE, " success!\n")
return nil
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/a7c02356/newt/vendor/mynewt.apache.org/newt/util/util.go
----------------------------------------------------------------------
diff --git a/newt/vendor/mynewt.apache.org/newt/util/util.go b/newt/vendor/mynewt.apache.org/newt/util/util.go
index fa3e60f..083ee9c 100644
--- a/newt/vendor/mynewt.apache.org/newt/util/util.go
+++ b/newt/vendor/mynewt.apache.org/newt/util/util.go
@@ -300,7 +300,6 @@ func ShellCommandLimitDbgOutput(
}
o, err := cmd.CombinedOutput()
-
if maxDbgOutputChrs < 0 || len(o) <= maxDbgOutputChrs {
dbgStr := string(o)
log.Debugf("o=%s", dbgStr)