mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
codereview: add release branch support
Note that if you are working on the upcoming release branch you have to point your extension path to a copy of lib/codereview/codereview.py that won't change as the repository flips between release-branch and default branch. This warning should only apply to this one branch and only to rsc, but you never know. R=adg CC=golang-dev https://golang.org/cl/4446076
This commit is contained in:
parent
86e6a44112
commit
35a37f1735
1 changed files with 127 additions and 13 deletions
|
|
@ -112,6 +112,7 @@ defaultcc = None
|
||||||
contributors = {}
|
contributors = {}
|
||||||
missing_codereview = None
|
missing_codereview = None
|
||||||
real_rollback = None
|
real_rollback = None
|
||||||
|
releaseBranch = None
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# RE: UNICODE STRING HANDLING
|
# RE: UNICODE STRING HANDLING
|
||||||
|
|
@ -1049,7 +1050,7 @@ def change(ui, repo, *pats, **opts):
|
||||||
|
|
||||||
if missing_codereview:
|
if missing_codereview:
|
||||||
return missing_codereview
|
return missing_codereview
|
||||||
|
|
||||||
dirty = {}
|
dirty = {}
|
||||||
if len(pats) > 0 and GoodCLName(pats[0]):
|
if len(pats) > 0 and GoodCLName(pats[0]):
|
||||||
name = pats[0]
|
name = pats[0]
|
||||||
|
|
@ -1062,6 +1063,8 @@ def change(ui, repo, *pats, **opts):
|
||||||
if not cl.local and (opts["stdin"] or not opts["stdout"]):
|
if not cl.local and (opts["stdin"] or not opts["stdout"]):
|
||||||
return "cannot change non-local CL " + name
|
return "cannot change non-local CL " + name
|
||||||
else:
|
else:
|
||||||
|
if repo[None].branch() != "default":
|
||||||
|
return "cannot run hg change outside default branch"
|
||||||
name = "new"
|
name = "new"
|
||||||
cl = CL("new")
|
cl = CL("new")
|
||||||
dirty[cl] = True
|
dirty[cl] = True
|
||||||
|
|
@ -1154,7 +1157,9 @@ def clpatch(ui, repo, clname, **opts):
|
||||||
Submitting an imported patch will keep the original author's
|
Submitting an imported patch will keep the original author's
|
||||||
name as the Author: line but add your own name to a Committer: line.
|
name as the Author: line but add your own name to a Committer: line.
|
||||||
"""
|
"""
|
||||||
return clpatch_or_undo(ui, repo, clname, opts)
|
if repo[None].branch() != "default":
|
||||||
|
return "cannot run hg clpatch outside default branch"
|
||||||
|
return clpatch_or_undo(ui, repo, clname, opts, mode="clpatch")
|
||||||
|
|
||||||
def undo(ui, repo, clname, **opts):
|
def undo(ui, repo, clname, **opts):
|
||||||
"""undo the effect of a CL
|
"""undo the effect of a CL
|
||||||
|
|
@ -1163,7 +1168,66 @@ def undo(ui, repo, clname, **opts):
|
||||||
After creating the CL, opens the CL text for editing so that
|
After creating the CL, opens the CL text for editing so that
|
||||||
you can add the reason for the undo to the description.
|
you can add the reason for the undo to the description.
|
||||||
"""
|
"""
|
||||||
return clpatch_or_undo(ui, repo, clname, opts, undo=True)
|
if repo[None].branch() != "default":
|
||||||
|
return "cannot run hg undo outside default branch"
|
||||||
|
return clpatch_or_undo(ui, repo, clname, opts, mode="undo")
|
||||||
|
|
||||||
|
def release_apply(ui, repo, clname, **opts):
|
||||||
|
"""apply a CL to the release branch
|
||||||
|
|
||||||
|
Creates a new CL copying a previously committed change
|
||||||
|
from the main branch to the release branch.
|
||||||
|
The current client must either be clean or already be in
|
||||||
|
the release branch.
|
||||||
|
|
||||||
|
The release branch must be created by starting with a
|
||||||
|
clean client, disabling the code review plugin, and running:
|
||||||
|
|
||||||
|
hg update weekly.YYYY-MM-DD
|
||||||
|
hg branch release-branch.rNN
|
||||||
|
hg commit -m 'create release-branch.rNN'
|
||||||
|
hg push --new-branch
|
||||||
|
|
||||||
|
Then re-enable the code review plugin.
|
||||||
|
|
||||||
|
People can test the release branch by running
|
||||||
|
|
||||||
|
hg update release-branch.rNN
|
||||||
|
|
||||||
|
in a clean client. To return to the normal tree,
|
||||||
|
|
||||||
|
hg update default
|
||||||
|
|
||||||
|
Move changes since the weekly into the release branch
|
||||||
|
using hg release-apply followed by the usual code review
|
||||||
|
process and hg submit.
|
||||||
|
|
||||||
|
When it comes time to tag the release, record the
|
||||||
|
final long-form tag of the release-branch.rNN
|
||||||
|
in the *default* branch's .hgtags file. That is, run
|
||||||
|
|
||||||
|
hg update default
|
||||||
|
|
||||||
|
and then edit .hgtags as you would for a weekly.
|
||||||
|
|
||||||
|
"""
|
||||||
|
c = repo[None]
|
||||||
|
if not releaseBranch:
|
||||||
|
return "no active release branches"
|
||||||
|
if c.branch() != releaseBranch:
|
||||||
|
if c.modified() or c.added() or c.removed():
|
||||||
|
raise util.Abort("uncommitted local changes - cannot switch branches")
|
||||||
|
err = hg.clean(repo, releaseBranch)
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
try:
|
||||||
|
err = clpatch_or_undo(ui, repo, clname, opts, mode="backport")
|
||||||
|
if err:
|
||||||
|
raise util.Abort(err)
|
||||||
|
except Exception, e:
|
||||||
|
hg.clean(repo, "default")
|
||||||
|
raise e
|
||||||
|
return None
|
||||||
|
|
||||||
def rev2clname(rev):
|
def rev2clname(rev):
|
||||||
# Extract CL name from revision description.
|
# Extract CL name from revision description.
|
||||||
|
|
@ -1185,15 +1249,24 @@ undoFooter = """
|
||||||
»»»
|
»»»
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
backportHeader = """[%s] %s
|
||||||
|
|
||||||
|
««« CL %s / %s
|
||||||
|
"""
|
||||||
|
|
||||||
|
backportFooter = """
|
||||||
|
»»»
|
||||||
|
"""
|
||||||
|
|
||||||
# Implementation of clpatch/undo.
|
# Implementation of clpatch/undo.
|
||||||
def clpatch_or_undo(ui, repo, clname, opts, undo=False):
|
def clpatch_or_undo(ui, repo, clname, opts, mode):
|
||||||
if missing_codereview:
|
if missing_codereview:
|
||||||
return missing_codereview
|
return missing_codereview
|
||||||
|
|
||||||
if undo:
|
if mode == "undo" or mode == "backport":
|
||||||
if hgversion < '1.4':
|
if hgversion < '1.4':
|
||||||
# Don't have cmdutil.match (see implementation of sync command).
|
# Don't have cmdutil.match (see implementation of sync command).
|
||||||
return "hg is too old to run hg undo - update to 1.4 or newer"
|
return "hg is too old to run hg %s - update to 1.4 or newer" % mode
|
||||||
|
|
||||||
# Find revision in Mercurial repository.
|
# Find revision in Mercurial repository.
|
||||||
# Assume CL number is 7+ decimal digits.
|
# Assume CL number is 7+ decimal digits.
|
||||||
|
|
@ -1227,8 +1300,19 @@ def clpatch_or_undo(ui, repo, clname, opts, undo=False):
|
||||||
# Create fresh CL and start with patch that would reverse the change.
|
# Create fresh CL and start with patch that would reverse the change.
|
||||||
vers = short(rev.node())
|
vers = short(rev.node())
|
||||||
cl = CL("new")
|
cl = CL("new")
|
||||||
cl.desc = (undoHeader % (clname, vers)) + rev.description() + undoFooter
|
desc = rev.description()
|
||||||
patch = RunShell(["hg", "diff", "--git", "-r", vers + ":" + short(rev.parents()[0].node())])
|
if mode == "undo":
|
||||||
|
cl.desc = (undoHeader % (clname, vers)) + desc + undoFooter
|
||||||
|
else:
|
||||||
|
cl.desc = (backportHeader % (releaseBranch, line1(desc), clname, vers)) + desc + undoFooter
|
||||||
|
v1 = vers
|
||||||
|
v0 = short(rev.parents()[0].node())
|
||||||
|
if mode == "undo":
|
||||||
|
arg = v1 + ":" + v0
|
||||||
|
else:
|
||||||
|
vers = v0
|
||||||
|
arg = v0 + ":" + v1
|
||||||
|
patch = RunShell(["hg", "diff", "--git", "-r", arg])
|
||||||
|
|
||||||
else: # clpatch
|
else: # clpatch
|
||||||
cl, vers, patch, err = DownloadCL(ui, repo, clname)
|
cl, vers, patch, err = DownloadCL(ui, repo, clname)
|
||||||
|
|
@ -1249,10 +1333,10 @@ def clpatch_or_undo(ui, repo, clname, opts, undo=False):
|
||||||
if id != vers:
|
if id != vers:
|
||||||
patch, err = portPatch(repo, patch, vers, id)
|
patch, err = portPatch(repo, patch, vers, id)
|
||||||
if err != "":
|
if err != "":
|
||||||
return "codereview issue %s is out of date: %s" % (clname, err)
|
return "codereview issue %s is out of date: %s (%s->%s)" % (clname, err, vers, id)
|
||||||
|
|
||||||
argv = ["hgpatch"]
|
argv = ["hgpatch"]
|
||||||
if opts["no_incoming"]:
|
if opts["no_incoming"] or mode == "backport":
|
||||||
argv += ["--checksync=false"]
|
argv += ["--checksync=false"]
|
||||||
try:
|
try:
|
||||||
cmd = subprocess.Popen(argv, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, close_fds=sys.platform != "win32")
|
cmd = subprocess.Popen(argv, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, close_fds=sys.platform != "win32")
|
||||||
|
|
@ -1271,7 +1355,7 @@ def clpatch_or_undo(ui, repo, clname, opts, undo=False):
|
||||||
if extra:
|
if extra:
|
||||||
ui.warn("warning: these files were listed in the patch but not changed:\n\t" + "\n\t".join(extra) + "\n")
|
ui.warn("warning: these files were listed in the patch but not changed:\n\t" + "\n\t".join(extra) + "\n")
|
||||||
cl.Flush(ui, repo)
|
cl.Flush(ui, repo)
|
||||||
if undo:
|
if mode == "undo":
|
||||||
err = EditCL(ui, repo, cl)
|
err = EditCL(ui, repo, cl)
|
||||||
if err != "":
|
if err != "":
|
||||||
return "CL created, but error editing: " + err
|
return "CL created, but error editing: " + err
|
||||||
|
|
@ -1506,7 +1590,7 @@ def reposetup(ui, repo):
|
||||||
|
|
||||||
def CheckContributor(ui, repo, user=None):
|
def CheckContributor(ui, repo, user=None):
|
||||||
set_status("checking CONTRIBUTORS file")
|
set_status("checking CONTRIBUTORS file")
|
||||||
_, userline = FindContributor(ui, repo, user, warn=False)
|
user, userline = FindContributor(ui, repo, user, warn=False)
|
||||||
if not userline:
|
if not userline:
|
||||||
raise util.Abort("cannot find %s in CONTRIBUTORS" % (user,))
|
raise util.Abort("cannot find %s in CONTRIBUTORS" % (user,))
|
||||||
return userline
|
return userline
|
||||||
|
|
@ -1524,7 +1608,7 @@ def FindContributor(ui, repo, user=None, warn=True):
|
||||||
if user not in contributors:
|
if user not in contributors:
|
||||||
if warn:
|
if warn:
|
||||||
ui.warn("warning: cannot find %s in CONTRIBUTORS\n" % (user,))
|
ui.warn("warning: cannot find %s in CONTRIBUTORS\n" % (user,))
|
||||||
return None, None
|
return user, None
|
||||||
|
|
||||||
user, email = contributors[user]
|
user, email = contributors[user]
|
||||||
return email, "%s <%s>" % (user, email)
|
return email, "%s <%s>" % (user, email)
|
||||||
|
|
@ -1650,6 +1734,14 @@ def submit(ui, repo, *pats, **opts):
|
||||||
if not cl.copied_from:
|
if not cl.copied_from:
|
||||||
EditDesc(cl.name, closed=True, private=cl.private)
|
EditDesc(cl.name, closed=True, private=cl.private)
|
||||||
cl.Delete(ui, repo)
|
cl.Delete(ui, repo)
|
||||||
|
|
||||||
|
c = repo[None]
|
||||||
|
if c.branch() == releaseBranch and not c.modified() and not c.added() and not c.removed():
|
||||||
|
ui.write("switching from %s to default branch.\n" % releaseBranch)
|
||||||
|
err = hg.clean(repo, "default")
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
return None
|
||||||
|
|
||||||
def sync(ui, repo, **opts):
|
def sync(ui, repo, **opts):
|
||||||
"""synchronize with remote repository
|
"""synchronize with remote repository
|
||||||
|
|
@ -1822,6 +1914,15 @@ cmdtable = {
|
||||||
] + commands.walkopts,
|
] + commands.walkopts,
|
||||||
"[-r reviewer] [--cc cc] [change# | file ...]"
|
"[-r reviewer] [--cc cc] [change# | file ...]"
|
||||||
),
|
),
|
||||||
|
"^release-apply": (
|
||||||
|
release_apply,
|
||||||
|
[
|
||||||
|
('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
|
||||||
|
('', 'no_incoming', None, 'disable check for incoming changes'),
|
||||||
|
],
|
||||||
|
"change#"
|
||||||
|
),
|
||||||
|
# TODO: release-start, release-tag, weekly-tag
|
||||||
"^submit": (
|
"^submit": (
|
||||||
submit,
|
submit,
|
||||||
review_opts + [
|
review_opts + [
|
||||||
|
|
@ -2263,6 +2364,19 @@ def RietveldSetup(ui, repo):
|
||||||
upload_options.email = "test@example.com"
|
upload_options.email = "test@example.com"
|
||||||
|
|
||||||
rpc = None
|
rpc = None
|
||||||
|
|
||||||
|
global releaseBranch
|
||||||
|
tags = repo.branchtags().keys()
|
||||||
|
if 'release-branch.r100' in tags:
|
||||||
|
# NOTE(rsc): This tags.sort is going to get the wrong
|
||||||
|
# answer when comparing release-branch.r99 with
|
||||||
|
# release-branch.r100. If we do ten releases a year
|
||||||
|
# that gives us 4 years before we have to worry about this.
|
||||||
|
raise util.Abort('tags.sort needs to be fixed for release-branch.r100')
|
||||||
|
tags.sort()
|
||||||
|
for t in tags:
|
||||||
|
if t.startswith('release-branch.'):
|
||||||
|
releaseBranch = t
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# http://codereview.appspot.com/static/upload.py, heavily edited.
|
# http://codereview.appspot.com/static/upload.py, heavily edited.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue