aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git-codereview/api.go8
-rw-r--r--git-codereview/branch.go17
-rw-r--r--git-codereview/change.go11
-rw-r--r--git-codereview/config.go25
-rw-r--r--git-codereview/doc.go11
-rw-r--r--git-codereview/gofmt.go4
-rw-r--r--git-codereview/hook.go6
-rw-r--r--git-codereview/mail.go4
-rw-r--r--git-codereview/pending.go6
-rw-r--r--git-codereview/submit.go2
-rw-r--r--git-codereview/sync.go40
11 files changed, 85 insertions, 49 deletions
diff --git a/git-codereview/api.go b/git-codereview/api.go
index da3fa76..9fc1b67 100644
--- a/git-codereview/api.go
+++ b/git-codereview/api.go
@@ -57,8 +57,10 @@ func loadGerritOrigin() {
// Gerrit must be set, either explicitly via the code review config or
// implicitly as Git's origin remote.
- origin := config()["gerrit"]
- originUrl := trim(cmdOutput("git", "config", "remote.origin.url"))
+ cfg := config()
+ cfgRemote := cfg["remote"]
+ origin := cfg["gerrit"]
+ originUrl := trim(cmdOutput("git", "config", "remote."+cfgRemote+".url"))
err := loadGerritOriginInternal(origin, originUrl)
if err != nil {
@@ -73,7 +75,7 @@ func loadGerritOrigin() {
func loadGerritOriginInternal(origin, remoteOrigin string) error {
originUrl, err := url.Parse(remoteOrigin)
if err != nil {
- return fmt.Errorf("failed to parse git's remote.origin.url %q as a URL: %v", remoteOrigin, err)
+ return fmt.Errorf("failed to parse git's remote.%s.url %q as a URL: %v", cachedConfig["remote"], remoteOrigin, err)
} else {
originUrl.User = nil
remoteOrigin = originUrl.String()
diff --git a/git-codereview/branch.go b/git-codereview/branch.go
index b22ac39..329109f 100644
--- a/git-codereview/branch.go
+++ b/git-codereview/branch.go
@@ -81,6 +81,9 @@ func (b *Branch) Config() map[string]string {
verbosef("failed to load config for branch %v: %v", b.Name, err)
cfg = make(map[string]string)
}
+ if cfg["remote"] == "" {
+ cfg["remote"] = "origin"
+ }
b.config = cfg
return b.config
}
@@ -121,10 +124,12 @@ func (b *Branch) OriginBranch() string {
return b.originBranch
}
- cfg := b.Config()["branch"]
+ cfg := b.Config()
+ cfgRemote := cfg["remote"]
+ branch := cfg["branch"]
upstream := ""
- if cfg != "" {
- upstream = "origin/" + cfg
+ if branch != "" {
+ upstream = cfgRemote + "/" + branch
}
// Consult and possibly update git,
@@ -139,13 +144,13 @@ func (b *Branch) OriginBranch() string {
// Assume branch was created before we set upstream correctly.
// See if origin/main exists; if so, use it.
// Otherwise, fall back to origin/master.
- argv := []string{"git", "rev-parse", "--abbrev-ref", "origin/main"}
+ argv := []string{"git", "rev-parse", "--abbrev-ref", cfgRemote + "/main"}
cmd := exec.Command(argv[0], argv[1:]...)
setEnglishLocale(cmd)
if err := cmd.Run(); err == nil {
- upstream = "origin/main"
+ upstream = cfgRemote + "/main"
} else {
- upstream = "origin/master"
+ upstream = cfgRemote + "/master"
}
}
if gitUpstream != upstream && b.Current {
diff --git a/git-codereview/change.go b/git-codereview/change.go
index 06b658f..ea0cf3e 100644
--- a/git-codereview/change.go
+++ b/git-codereview/change.go
@@ -156,9 +156,12 @@ func checkoutOrCreate(target string) {
}
}
+ cfg := config()
+ cfgRemote := cfg["remote"]
+
// If origin branch exists, create local branch tracking it.
for _, name := range OriginBranches() {
- if name == "origin/"+target {
+ if name == cfgRemote+"/"+target {
run("git", "checkout", "-q", "-t", "-b", target, name)
printf("created branch %v tracking %s.", target, name)
return
@@ -226,7 +229,11 @@ func checkoutCL(what, cl, ps string) {
} else {
ref = fmt.Sprintf("pull/%s/head", cl)
}
- err := runErr("git", "fetch", "-q", "origin", ref)
+
+ cfg := config()
+ cfgRemote := cfg["remote"]
+
+ err := runErr("git", "fetch", "-q", cfgRemote, ref)
if err != nil {
dief("cannot change to %v %s: %v", what, cl, err)
}
diff --git a/git-codereview/config.go b/git-codereview/config.go
index cc9286c..8c86abf 100644
--- a/git-codereview/config.go
+++ b/git-codereview/config.go
@@ -17,26 +17,29 @@ var (
cachedConfig map[string]string
)
-// Config returns the code review config.
+// config returns the code review config.
// Configs consist of lines of the form "key: value".
// Lines beginning with # are comments.
// If there is no config, it returns an empty map.
// If the config is malformed, it dies.
func config() map[string]string {
- if cachedConfig != nil {
- return cachedConfig
- }
configPath = filepath.Join(repoRoot(), "codereview.cfg")
b, err := os.ReadFile(configPath)
raw := string(b)
if err != nil {
verbosef("%sfailed to load config from %q: %v", raw, configPath, err)
cachedConfig = make(map[string]string)
- return cachedConfig
+ } else {
+ cachedConfig, err = parseConfig(raw)
+ if err != nil {
+ dief("%v", err)
+ }
}
- cachedConfig, err = parseConfig(raw)
- if err != nil {
- dief("%v", err)
+ if cachedConfig["remote"] == "" {
+ cachedConfig["remote"] = "origin"
+ }
+ if cachedConfig["branch"] == "" {
+ cachedConfig["branch"] = "main"
}
return cachedConfig
}
@@ -46,8 +49,10 @@ func config() map[string]string {
// the gerrit https URL or the git origin must be to
// "https://<project>.googlesource.com/<repo>".
func haveGerrit() bool {
- gerrit := config()["gerrit"]
- origin := trim(cmdOutput("git", "config", "remote.origin.url"))
+ cfg := config()
+ cfgRemote := cfg["remote"]
+ gerrit := cfg["gerrit"]
+ origin := trim(cmdOutput("git", "config", "remote."+cfgRemote+".url"))
return haveGerritInternal(gerrit, origin)
}
diff --git a/git-codereview/doc.go b/git-codereview/doc.go
index 012e5ef..ca1b4b2 100644
--- a/git-codereview/doc.go
+++ b/git-codereview/doc.go
@@ -8,8 +8,9 @@ server.
The git-codereview tool manages “change branches” in the local git repository.
Each such branch tracks a single commit, or “pending change”,
-that is reviewed using a Gerrit server; the Gerrit remote must be
-named “origin” in the local git repo.
+that is reviewed using a Gerrit server.
+The Gerrit remote must be named “origin” in the local git repo, unless
+set in configuration under "remote" key.
Modifications to the pending change are applied by amending the commit.
This process implements the “single-commit feature branch” model.
@@ -425,6 +426,12 @@ would typically be “main”, in which case it would have this codereview.cfg:
branch: dev.feature
parent-branch: main
+The "remote" key specifies the name of git remote.
+If this setting is missing its default to "origin".
+This setting can be useful if you works on fork of the repository.
+Your fork can be still the named "origin" and the "upstream" (or other
+remote name) can be configured using this key.
+
In a more complex configuration, one feature branch might depend upon
another, like “dev.feature2” containing follow-on work for “dev.feature”,
neither of which has merged yet. In this case, the dev.feature2 branch
diff --git a/git-codereview/gofmt.go b/git-codereview/gofmt.go
index 1df3e43..de99487 100644
--- a/git-codereview/gofmt.go
+++ b/git-codereview/gofmt.go
@@ -125,7 +125,9 @@ func runGofmt(flags int) (files []string, stderrText string) {
// then check all the pending commits.
branchpt := "HEAD"
if b.OriginBranch() != "" {
- isBranchTagMove := strings.Contains(cmdOutput("git", "branch", "-r", "--contains", b.FullName()), "origin/")
+ cfg := config()
+ cfgRemote := cfg["remote"]
+ isBranchTagMove := strings.Contains(cmdOutput("git", "branch", "-r", "--contains", b.FullName()), cfgRemote+"/")
if !isBranchTagMove {
branchpt = b.Branchpoint()
}
diff --git a/git-codereview/hook.go b/git-codereview/hook.go
index be2b699..0634687 100644
--- a/git-codereview/hook.go
+++ b/git-codereview/hook.go
@@ -227,7 +227,8 @@ func fixCommitMessage(msg []byte) []byte {
data[eol+1] = '\n'
}
- issueRepo := config()["issuerepo"]
+ cfg := config()
+ issueRepo := cfg["issuerepo"]
// Update issue references to point to issue repo, if set.
if issueRepo != "" {
data = issueRefRE.ReplaceAll(data, []byte("${space}"+issueRepo+"${ref}"))
@@ -259,7 +260,8 @@ func fixCommitMessage(msg []byte) []byte {
// dev or release branch and not a special Git fixup! or
// squash! commit message.
b := CurrentBranch()
- branch := strings.TrimPrefix(b.OriginBranch(), "origin/")
+ cfgRemote := cfg["remote"]
+ branch := strings.TrimPrefix(b.OriginBranch(), cfgRemote+"/")
if strings.HasPrefix(branch, "dev.") || strings.HasPrefix(branch, "release-branch.") {
prefix := "[" + branch + "] "
if !bytes.HasPrefix(data, []byte(prefix)) && !isFixup(data) {
diff --git a/git-codereview/mail.go b/git-codereview/mail.go
index c0592bf..98de7fa 100644
--- a/git-codereview/mail.go
+++ b/git-codereview/mail.go
@@ -175,7 +175,7 @@ func cmdMail(args []string) {
if *noverify {
args = append(args, "--no-verify")
}
- args = append(args, "origin", refSpec)
+ args = append(args, config()["remote"], refSpec)
run("git", args...)
// Create local tag for mailed change.
@@ -199,7 +199,7 @@ func (b *Branch) PushSpec(c *Commit) string {
if c != nil && (len(b.Pending()) == 0 || b.Pending()[0].Hash != c.Hash) {
local = c.ShortHash
}
- return local + ":refs/for/" + strings.TrimPrefix(b.OriginBranch(), "origin/")
+ return local + ":refs/for/" + strings.TrimPrefix(b.OriginBranch(), config()["remote"]+"/")
}
// mailAddressRE matches the mail addresses we admit. It's restrictive but admits
diff --git a/git-codereview/pending.go b/git-codereview/pending.go
index 8a74e09..d03b003 100644
--- a/git-codereview/pending.go
+++ b/git-codereview/pending.go
@@ -240,6 +240,8 @@ func printPendingStandard(branches []*pendingBranch) {
}
}
+ cfgRemote := config()["remote"]
+
for _, b := range branches {
if !b.current && b.commitsAhead == 0 {
// Hide branches with no work on them.
@@ -268,8 +270,8 @@ func printPendingStandard(branches []*pendingBranch) {
}
if br := b.OriginBranch(); br == "" {
tags = append(tags, "remote branch unknown")
- } else if br != "origin/master" && br != "origin/main" {
- tags = append(tags, "tracking "+strings.TrimPrefix(b.OriginBranch(), "origin/"))
+ } else if br != cfgRemote+"/master" && br != cfgRemote+"/main" {
+ tags = append(tags, "tracking "+strings.TrimPrefix(b.OriginBranch(), cfgRemote+"/"))
}
if len(tags) > 0 {
fmt.Fprintf(&buf, " (%s)", strings.Join(tags, ", "))
diff --git a/git-codereview/submit.go b/git-codereview/submit.go
index 4bbbf32..5577dac 100644
--- a/git-codereview/submit.go
+++ b/git-codereview/submit.go
@@ -96,7 +96,7 @@ func submit(b *Branch, c *Commit) *GerritChange {
// Upload most recent revision if not already on server.
if c.Hash != g.CurrentRevision {
- run("git", "push", "-q", "origin", b.PushSpec(c))
+ run("git", "push", "-q", config()["remote"], b.PushSpec(c))
// Refetch change information.
g, err = b.GerritChange(c, "LABELS", "CURRENT_REVISION")
diff --git a/git-codereview/sync.go b/git-codereview/sync.go
index 71fc312..6ff36a3 100644
--- a/git-codereview/sync.go
+++ b/git-codereview/sync.go
@@ -60,10 +60,11 @@ func cmdSync(args []string) {
// hint: use --reapply-cherry-picks to include skipped commits
// hint: Disable this message with "git config advice.skippedCherryPicks false"
//
+ cfgRemote := config()["remote"]
if *verbose > 1 {
- run("git", "-c", "advice.skippedCherryPicks=false", "pull", "-q", "-r", "-v", "origin", strings.TrimPrefix(b.OriginBranch(), "origin/"))
+ run("git", "-c", "advice.skippedCherryPicks=false", "pull", "-q", "-r", "-v", cfgRemote, strings.TrimPrefix(b.OriginBranch(), cfgRemote+"/"))
} else {
- run("git", "-c", "advice.skippedCherryPicks=false", "pull", "-q", "-r", "origin", strings.TrimPrefix(b.OriginBranch(), "origin/"))
+ run("git", "-c", "advice.skippedCherryPicks=false", "pull", "-q", "-r", cfgRemote, strings.TrimPrefix(b.OriginBranch(), cfgRemote+"/"))
}
b = CurrentBranch() // discard any cached information
@@ -188,30 +189,32 @@ func cmdSyncBranch(args []string) {
// Note that this does a remote fetch of b.OriginBranch() (aka branch).
cmdSync(nil)
+ cfgRemote := config()["remote"]
+
// Pull down parent commits too.
quiet := "-q"
if *verbose > 0 {
quiet = "-v"
}
- run("git", "fetch", quiet, "origin", "refs/heads/"+parent+":refs/remotes/origin/"+parent)
+ run("git", "fetch", quiet, cfgRemote, "refs/heads/"+parent+":refs/remotes/"+cfgRemote+"/"+parent)
// Write the status file to make sure we can, before starting a merge.
status := &syncBranchStatus{
Local: b.Name,
Parent: parent,
- ParentHash: gitHash("origin/" + parent),
+ ParentHash: gitHash(cfgRemote + "/" + parent),
Branch: branch,
- BranchHash: gitHash("origin/" + branch),
+ BranchHash: gitHash(cfgRemote + "/" + branch),
}
writeSyncBranchStatus(status)
- parentHash, err := cmdOutputErr("git", "rev-parse", "origin/"+parent)
+ parentHash, err := cmdOutputErr("git", "rev-parse", cfgRemote+"/"+parent)
if err != nil {
- dief("cannot sync-branch: cannot resolve origin/%s: %v\n%s", parent, err, parentHash)
+ dief("cannot sync-branch: cannot resolve %s/%s: %v\n%s", cfgRemote, parent, err, parentHash)
}
- branchHash, err := cmdOutputErr("git", "rev-parse", "origin/"+branch)
+ branchHash, err := cmdOutputErr("git", "rev-parse", cfgRemote+"/"+branch)
if err != nil {
- dief("cannot sync-branch: cannot resolve origin/%s: %v\n%s", branch, err, branchHash)
+ dief("cannot sync-branch: cannot resolve %s/%s: %v\n%s", cfgRemote, branch, err, branchHash)
}
parentHash = trim(parentHash)
branchHash = trim(branchHash)
@@ -221,7 +224,7 @@ func cmdSyncBranch(args []string) {
// to be done, it should be done first on the dev branch,
// not the parent branch.
if mergeBackToParent {
- other := cmdOutput("git", "log", "--format=format:+ %cd %h %s", "--date=short", "origin/"+branch+"..origin/"+parent)
+ other := cmdOutput("git", "log", "--format=format:+ %cd %h %s", "--date=short", cfgRemote+"/"+branch+".."+cfgRemote+"/"+parent)
if other != "" {
dief("cannot sync-branch --merge-back-to-parent: parent has new commits.\n"+
"\trun 'git codereview sync-branch' to bring them into this branch first:\n%s",
@@ -237,10 +240,10 @@ func cmdSyncBranch(args []string) {
// of the merge, the same as it would when we are doing it by hand
// with a plain "git merge". This may help the display of the
// merge graph in some tools more closely reflect what we did.
- run("git", "reset", "--hard", "origin/"+parent)
- _, err = cmdOutputErr("git", "merge", "--no-ff", "origin/"+branch)
+ run("git", "reset", "--hard", cfgRemote+"/"+parent)
+ _, err = cmdOutputErr("git", "merge", "--no-ff", cfgRemote+"/"+branch)
} else {
- _, err = cmdOutputErr("git", "merge", "--no-ff", "origin/"+parent)
+ _, err = cmdOutputErr("git", "merge", "--no-ff", cfgRemote+"/"+parent)
}
// Resolve codereview.cfg the right way - never take it from the merge.
@@ -322,10 +325,11 @@ const (
)
func syncBranchContinue(flag string, b *Branch, status *syncBranchStatus) {
- if h := gitHash("origin/" + status.Parent); h != status.ParentHash {
+ cfgRemote := config()["remote"]
+ if h := gitHash(cfgRemote + "/" + status.Parent); h != status.ParentHash {
dief("cannot sync-branch%s: parent hash changed: %.7s -> %.7s", flag, status.ParentHash, h)
}
- if h := gitHash("origin/" + status.Branch); h != status.BranchHash {
+ if h := gitHash(cfgRemote + "/" + status.Branch); h != status.BranchHash {
dief("cannot sync-branch%s: branch hash changed: %.7s -> %.7s", flag, status.BranchHash, h)
}
if b.Name != status.Local {
@@ -364,11 +368,11 @@ func syncBranchContinue(flag string, b *Branch, status *syncBranchStatus) {
}
mergeHead = trim(mergeHead)
if mergeHead != srcHash {
- dief("cannot sync-branch%s: MERGE_HEAD is %.7s, but origin/%s is %.7s", flag, mergeHead, src, srcHash)
+ dief("cannot sync-branch%s: MERGE_HEAD is %.7s, but %s/%s is %.7s", flag, mergeHead, cfgRemote, src, srcHash)
}
head := gitHash("HEAD")
if head != dstHash {
- dief("cannot sync-branch%s: HEAD is %.7s, but origin/%s is %.7s", flag, head, dst, dstHash)
+ dief("cannot sync-branch%s: HEAD is %.7s, but %s/%s is %.7s", flag, head, cfgRemote, dst, dstHash)
}
if HasUnstagedChanges() {
@@ -387,7 +391,7 @@ func syncBranchContinue(flag string, b *Branch, status *syncBranchStatus) {
// Merge must never sync codereview.cfg,
// because it contains the src and dst config.
// Force the on-dst copy back while amending the commit.
- cmdOutputDir(repoRoot(), "git", "checkout", "origin/"+dst, "--", "codereview.cfg")
+ cmdOutputDir(repoRoot(), "git", "checkout", cfgRemote+"/"+dst, "--", "codereview.cfg")
conflictMsg := ""
if len(status.Conflicts) > 0 {