Add jiri edit command
This command has been ported from scripts/update-manifest.go in fuchsia
Change-Id: I906224a58e1a7cf43a85ddcacc82d7df6ebdecb4
diff --git a/cmd/jiri/cmd.go b/cmd/jiri/cmd.go
index 0ca9601..7222385 100644
--- a/cmd/jiri/cmd.go
+++ b/cmd/jiri/cmd.go
@@ -56,6 +56,7 @@
Children: []*cmdline.Command{
cmdBranch,
cmdDiff,
+ cmdEdit,
cmdGrep,
cmdImport,
cmdInit,
diff --git a/cmd/jiri/edit.go b/cmd/jiri/edit.go
new file mode 100644
index 0000000..13b9228
--- /dev/null
+++ b/cmd/jiri/edit.go
@@ -0,0 +1,97 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "fuchsia.googlesource.com/jiri"
+ "fuchsia.googlesource.com/jiri/cmdline"
+ "fuchsia.googlesource.com/jiri/gitutil"
+ "fuchsia.googlesource.com/jiri/project"
+)
+
+type stringsValue []string
+
+func (i *stringsValue) String() string {
+ return strings.Join(*i, ",")
+}
+
+func (i *stringsValue) Set(value string) error {
+ *i = strings.Split(value, ",")
+ return nil
+}
+
+var editFlags struct {
+ projects stringsValue
+}
+
+var cmdEdit = &cmdline.Command{
+ Runner: jiri.RunnerFunc(runEdit),
+ Name: "edit",
+ Short: "Edit manifest file",
+ Long: `Edit manifest file by rolling the revision of provided projects`,
+ ArgsName: "<manifest>",
+ ArgsLong: "<manifest> is path of the manifest",
+}
+
+func init() {
+ flags := &cmdEdit.Flags
+ flags.Var(&editFlags.projects, "projects", "List of projects to update")
+}
+
+func runEdit(jirix *jiri.X, args []string) error {
+ if len(args) != 1 {
+ return jirix.UsageErrorf("Wrong number of args")
+ }
+ manifestPath, err := filepath.Abs(args[0])
+ if err != nil {
+ return err
+ }
+ projects := make(map[string]struct{})
+ for _, p := range editFlags.projects {
+ projects[p] = struct{}{}
+ }
+
+ return updateManifest(jirix, manifestPath, projects)
+}
+
+func updateManifest(jirix *jiri.X, manifestPath string, projects map[string]struct{}) error {
+ m, err := project.ManifestFromFile(jirix, manifestPath)
+ if err != nil {
+ return err
+ }
+ content, err := ioutil.ReadFile(manifestPath)
+ if err != nil {
+ return err
+ }
+ manifestContent := string(content)
+ scm := gitutil.New(jirix, gitutil.RootDirOpt(filepath.Dir(manifestPath)))
+ for _, p := range m.Projects {
+
+ if _, ok := projects[p.Name]; !ok {
+ continue
+ }
+
+ if p.Revision != "" {
+ branch := "master"
+ if p.RemoteBranch != "" {
+ branch = p.RemoteBranch
+ }
+ out, err := scm.LsRemote(p.Remote, fmt.Sprintf("refs/heads/%s", branch))
+ if err != nil {
+ return err
+ }
+ latestRevision := strings.Fields(string(out))[0]
+ manifestContent = strings.Replace(manifestContent, p.Revision, latestRevision, 1)
+ }
+ }
+
+ return ioutil.WriteFile(manifestPath, []byte(manifestContent), os.ModePerm)
+}
diff --git a/gitutil/git.go b/gitutil/git.go
index ad51338..a3759bd 100644
--- a/gitutil/git.go
+++ b/gitutil/git.go
@@ -326,6 +326,19 @@
return g.run("branch", "-u", upstream, branch)
}
+func (g *Git) LsRemote(args ...string) (string, error) {
+ a := []string{"ls-remote"}
+ a = append(a, args...)
+ out, err := g.runOutput(a...)
+ if err != nil {
+ return "", err
+ }
+ if got, want := len(out), 1; got != want {
+ return "", fmt.Errorf("git ls-remote %s: unexpected length of %s: got %s, want %s", strings.Join(args, " "), out, got, want)
+ }
+ return out[0], nil
+}
+
// CreateBranchWithUpstream creates a new branch and sets the upstream
// repository to the given upstream.
func (g *Git) CreateBranchWithUpstream(branch, upstream string) error {