mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-24 11:41:58 +00:00
codereview: sync from Go.
LGTM=rsc R=rsc https://codereview.appspot.com/67820044
This commit is contained in:
parent
66ad987412
commit
db800afb4e
1 changed files with 185 additions and 112 deletions
|
@ -61,6 +61,14 @@ import time
|
||||||
from mercurial import commands as hg_commands
|
from mercurial import commands as hg_commands
|
||||||
from mercurial import util as hg_util
|
from mercurial import util as hg_util
|
||||||
|
|
||||||
|
# bind Plan 9 preferred dotfile location
|
||||||
|
if os.sys.platform == 'plan9':
|
||||||
|
try:
|
||||||
|
import plan9
|
||||||
|
n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE|plan9.MCREATE)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
defaultcc = None
|
defaultcc = None
|
||||||
codereview_disabled = None
|
codereview_disabled = None
|
||||||
real_rollback = None
|
real_rollback = None
|
||||||
|
@ -155,7 +163,8 @@ default_to_utf8()
|
||||||
global_status = None
|
global_status = None
|
||||||
|
|
||||||
def set_status(s):
|
def set_status(s):
|
||||||
# print >>sys.stderr, "\t", time.asctime(), s
|
if verbosity > 0:
|
||||||
|
print >>sys.stderr, time.asctime(), s
|
||||||
global global_status
|
global global_status
|
||||||
global_status = s
|
global_status = s
|
||||||
|
|
||||||
|
@ -268,7 +277,7 @@ class CL(object):
|
||||||
s += "\tAuthor: " + cl.copied_from + "\n"
|
s += "\tAuthor: " + cl.copied_from + "\n"
|
||||||
if not quick:
|
if not quick:
|
||||||
s += "\tReviewer: " + JoinComma(cl.reviewer) + "\n"
|
s += "\tReviewer: " + JoinComma(cl.reviewer) + "\n"
|
||||||
for (who, line) in cl.lgtm:
|
for (who, line, _) in cl.lgtm:
|
||||||
s += "\t\t" + who + ": " + line + "\n"
|
s += "\t\t" + who + ": " + line + "\n"
|
||||||
s += "\tCC: " + JoinComma(cl.cc) + "\n"
|
s += "\tCC: " + JoinComma(cl.cc) + "\n"
|
||||||
s += "\tFiles:\n"
|
s += "\tFiles:\n"
|
||||||
|
@ -358,6 +367,8 @@ class CL(object):
|
||||||
msg = lines[0]
|
msg = lines[0]
|
||||||
patchset = lines[1].strip()
|
patchset = lines[1].strip()
|
||||||
patches = [x.split(" ", 1) for x in lines[2:]]
|
patches = [x.split(" ", 1) for x in lines[2:]]
|
||||||
|
else:
|
||||||
|
print >>sys.stderr, "Server says there is nothing to upload (probably wrong):\n" + msg
|
||||||
if response_body.startswith("Issue updated.") and quiet:
|
if response_body.startswith("Issue updated.") and quiet:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -484,9 +495,15 @@ def CutDomain(s):
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def JoinComma(l):
|
def JoinComma(l):
|
||||||
|
seen = {}
|
||||||
|
uniq = []
|
||||||
for s in l:
|
for s in l:
|
||||||
typecheck(s, str)
|
typecheck(s, str)
|
||||||
return ", ".join(l)
|
if s not in seen:
|
||||||
|
seen[s] = True
|
||||||
|
uniq.append(s)
|
||||||
|
|
||||||
|
return ", ".join(uniq)
|
||||||
|
|
||||||
def ExceptionDetail():
|
def ExceptionDetail():
|
||||||
s = str(sys.exc_info()[0])
|
s = str(sys.exc_info()[0])
|
||||||
|
@ -544,10 +561,10 @@ def LoadCL(ui, repo, name, web=True):
|
||||||
cl.private = d.get('private', False) != False
|
cl.private = d.get('private', False) != False
|
||||||
cl.lgtm = []
|
cl.lgtm = []
|
||||||
for m in d.get('messages', []):
|
for m in d.get('messages', []):
|
||||||
if m.get('approval', False) == True:
|
if m.get('approval', False) == True or m.get('disapproval', False) == True:
|
||||||
who = re.sub('@.*', '', m.get('sender', ''))
|
who = re.sub('@.*', '', m.get('sender', ''))
|
||||||
text = re.sub("\n(.|\n)*", '', m.get('text', ''))
|
text = re.sub("\n(.|\n)*", '', m.get('text', ''))
|
||||||
cl.lgtm.append((who, text))
|
cl.lgtm.append((who, text, m.get('approval', False)))
|
||||||
|
|
||||||
set_status("loaded CL " + name)
|
set_status("loaded CL " + name)
|
||||||
return cl, ''
|
return cl, ''
|
||||||
|
@ -711,7 +728,10 @@ Examples:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def promptyesno(ui, msg):
|
def promptyesno(ui, msg):
|
||||||
return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0
|
if hgversion >= "2.7":
|
||||||
|
return ui.promptchoice(msg + " $$ &yes $$ &no", 0) == 0
|
||||||
|
else:
|
||||||
|
return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0
|
||||||
|
|
||||||
def promptremove(ui, repo, f):
|
def promptremove(ui, repo, f):
|
||||||
if promptyesno(ui, "hg remove %s (y/n)?" % (f,)):
|
if promptyesno(ui, "hg remove %s (y/n)?" % (f,)):
|
||||||
|
@ -807,7 +827,7 @@ def EditCL(ui, repo, cl):
|
||||||
# For use by submit, etc. (NOT by change)
|
# For use by submit, etc. (NOT by change)
|
||||||
# Get change list number or list of files from command line.
|
# Get change list number or list of files from command line.
|
||||||
# If files are given, make a new change list.
|
# If files are given, make a new change list.
|
||||||
def CommandLineCL(ui, repo, pats, opts, defaultcc=None):
|
def CommandLineCL(ui, repo, pats, opts, op="verb", defaultcc=None):
|
||||||
if len(pats) > 0 and GoodCLName(pats[0]):
|
if len(pats) > 0 and GoodCLName(pats[0]):
|
||||||
if len(pats) != 1:
|
if len(pats) != 1:
|
||||||
return None, "cannot specify change number and file names"
|
return None, "cannot specify change number and file names"
|
||||||
|
@ -821,7 +841,7 @@ def CommandLineCL(ui, repo, pats, opts, defaultcc=None):
|
||||||
cl.local = True
|
cl.local = True
|
||||||
cl.files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
|
cl.files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
|
||||||
if not cl.files:
|
if not cl.files:
|
||||||
return None, "no files changed"
|
return None, "no files changed (use hg %s <number> to use existing CL)" % op
|
||||||
if opts.get('reviewer'):
|
if opts.get('reviewer'):
|
||||||
cl.reviewer = Add(cl.reviewer, SplitCommaSpace(opts.get('reviewer')))
|
cl.reviewer = Add(cl.reviewer, SplitCommaSpace(opts.get('reviewer')))
|
||||||
if opts.get('cc'):
|
if opts.get('cc'):
|
||||||
|
@ -972,7 +992,7 @@ def ReadContributors(ui, repo):
|
||||||
f = open(repo.root + '/CONTRIBUTORS', 'r')
|
f = open(repo.root + '/CONTRIBUTORS', 'r')
|
||||||
except:
|
except:
|
||||||
ui.write("warning: cannot open %s: %s\n" % (opening, ExceptionDetail()))
|
ui.write("warning: cannot open %s: %s\n" % (opening, ExceptionDetail()))
|
||||||
return
|
return {}
|
||||||
|
|
||||||
contributors = {}
|
contributors = {}
|
||||||
for line in f:
|
for line in f:
|
||||||
|
@ -1027,23 +1047,19 @@ def FindContributor(ui, repo, user=None, warn=True):
|
||||||
|
|
||||||
hgversion = hg_util.version()
|
hgversion = hg_util.version()
|
||||||
|
|
||||||
# We require Mercurial 1.9 and suggest Mercurial 2.0.
|
# We require Mercurial 1.9 and suggest Mercurial 2.1.
|
||||||
# The details of the scmutil package changed then,
|
# The details of the scmutil package changed then,
|
||||||
# so allowing earlier versions would require extra band-aids below.
|
# so allowing earlier versions would require extra band-aids below.
|
||||||
# Ubuntu 11.10 ships with Mercurial 1.9.1 as the default version.
|
# Ubuntu 11.10 ships with Mercurial 1.9.1 as the default version.
|
||||||
hg_required = "1.9"
|
hg_required = "1.9"
|
||||||
hg_suggested = "2.0"
|
hg_suggested = "2.1"
|
||||||
|
|
||||||
old_message = """
|
old_message = """
|
||||||
|
|
||||||
The code review extension requires Mercurial """+hg_required+""" or newer.
|
The code review extension requires Mercurial """+hg_required+""" or newer.
|
||||||
You are using Mercurial """+hgversion+""".
|
You are using Mercurial """+hgversion+""".
|
||||||
|
|
||||||
To install a new Mercurial, use
|
To install a new Mercurial, visit http://mercurial.selenic.com/downloads/.
|
||||||
|
|
||||||
sudo easy_install mercurial=="""+hg_suggested+"""
|
|
||||||
|
|
||||||
or visit http://mercurial.selenic.com/downloads/.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
linux_message = """
|
linux_message = """
|
||||||
|
@ -1171,6 +1187,25 @@ def hg_pull(ui, repo, **opts):
|
||||||
ui.write(line + '\n')
|
ui.write(line + '\n')
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
def hg_update(ui, repo, **opts):
|
||||||
|
w = uiwrap(ui)
|
||||||
|
ui.quiet = False
|
||||||
|
ui.verbose = True # for file list
|
||||||
|
err = hg_commands.update(ui, repo, **opts)
|
||||||
|
for line in w.output().split('\n'):
|
||||||
|
if isNoise(line):
|
||||||
|
continue
|
||||||
|
if line.startswith('moving '):
|
||||||
|
line = 'mv ' + line[len('moving '):]
|
||||||
|
if line.startswith('getting ') and line.find(' to ') >= 0:
|
||||||
|
line = 'mv ' + line[len('getting '):]
|
||||||
|
if line.startswith('getting '):
|
||||||
|
line = '+ ' + line[len('getting '):]
|
||||||
|
if line.startswith('removing '):
|
||||||
|
line = '- ' + line[len('removing '):]
|
||||||
|
ui.write(line + '\n')
|
||||||
|
return err
|
||||||
|
|
||||||
def hg_push(ui, repo, **opts):
|
def hg_push(ui, repo, **opts):
|
||||||
w = uiwrap(ui)
|
w = uiwrap(ui)
|
||||||
ui.quiet = False
|
ui.quiet = False
|
||||||
|
@ -1190,6 +1225,10 @@ def hg_commit(ui, repo, *pats, **opts):
|
||||||
commit_okay = False
|
commit_okay = False
|
||||||
|
|
||||||
def precommithook(ui, repo, **opts):
|
def precommithook(ui, repo, **opts):
|
||||||
|
if hgversion >= "2.1":
|
||||||
|
from mercurial import phases
|
||||||
|
if repo.ui.config('phases', 'new-commit') >= phases.secret:
|
||||||
|
return False
|
||||||
if commit_okay:
|
if commit_okay:
|
||||||
return False # False means okay.
|
return False # False means okay.
|
||||||
ui.write("\ncodereview extension enabled; use mail, upload, or submit instead of commit\n\n")
|
ui.write("\ncodereview extension enabled; use mail, upload, or submit instead of commit\n\n")
|
||||||
|
@ -1247,24 +1286,8 @@ def MatchAt(ctx, pats=None, opts=None, globbed=False, default='relpath'):
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Commands added by code review extension.
|
# Commands added by code review extension.
|
||||||
|
|
||||||
# As of Mercurial 2.1 the commands are all required to return integer
|
|
||||||
# exit codes, whereas earlier versions allowed returning arbitrary strings
|
|
||||||
# to be printed as errors. We wrap the old functions to make sure we
|
|
||||||
# always return integer exit codes now. Otherwise Mercurial dies
|
|
||||||
# with a TypeError traceback (unsupported operand type(s) for &: 'str' and 'int').
|
|
||||||
# Introduce a Python decorator to convert old functions to the new
|
|
||||||
# stricter convention.
|
|
||||||
|
|
||||||
def hgcommand(f):
|
def hgcommand(f):
|
||||||
def wrapped(ui, repo, *pats, **opts):
|
return f
|
||||||
err = f(ui, repo, *pats, **opts)
|
|
||||||
if type(err) is int:
|
|
||||||
return err
|
|
||||||
if not err:
|
|
||||||
return 0
|
|
||||||
raise hg_util.Abort(err)
|
|
||||||
wrapped.__doc__ = f.__doc__
|
|
||||||
return wrapped
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# hg change
|
# hg change
|
||||||
|
@ -1293,42 +1316,42 @@ def change(ui, repo, *pats, **opts):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
dirty = {}
|
dirty = {}
|
||||||
if len(pats) > 0 and GoodCLName(pats[0]):
|
if len(pats) > 0 and GoodCLName(pats[0]):
|
||||||
name = pats[0]
|
name = pats[0]
|
||||||
if len(pats) != 1:
|
if len(pats) != 1:
|
||||||
return "cannot specify CL name and file patterns"
|
raise hg_util.Abort("cannot specify CL name and file patterns")
|
||||||
pats = pats[1:]
|
pats = pats[1:]
|
||||||
cl, err = LoadCL(ui, repo, name, web=True)
|
cl, err = LoadCL(ui, repo, name, web=True)
|
||||||
if err != '':
|
if err != '':
|
||||||
return err
|
raise hg_util.Abort(err)
|
||||||
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
|
raise hg_util.Abort("cannot change non-local CL " + name)
|
||||||
else:
|
else:
|
||||||
name = "new"
|
name = "new"
|
||||||
cl = CL("new")
|
cl = CL("new")
|
||||||
if repo[None].branch() != "default":
|
if repo[None].branch() != "default":
|
||||||
return "cannot create CL outside default branch; switch with 'hg update default'"
|
raise hg_util.Abort("cannot create CL outside default branch; switch with 'hg update default'")
|
||||||
dirty[cl] = True
|
dirty[cl] = True
|
||||||
files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
|
files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
|
||||||
|
|
||||||
if opts["delete"] or opts["deletelocal"]:
|
if opts["delete"] or opts["deletelocal"]:
|
||||||
if opts["delete"] and opts["deletelocal"]:
|
if opts["delete"] and opts["deletelocal"]:
|
||||||
return "cannot use -d and -D together"
|
raise hg_util.Abort("cannot use -d and -D together")
|
||||||
flag = "-d"
|
flag = "-d"
|
||||||
if opts["deletelocal"]:
|
if opts["deletelocal"]:
|
||||||
flag = "-D"
|
flag = "-D"
|
||||||
if name == "new":
|
if name == "new":
|
||||||
return "cannot use "+flag+" with file patterns"
|
raise hg_util.Abort("cannot use "+flag+" with file patterns")
|
||||||
if opts["stdin"] or opts["stdout"]:
|
if opts["stdin"] or opts["stdout"]:
|
||||||
return "cannot use "+flag+" with -i or -o"
|
raise hg_util.Abort("cannot use "+flag+" with -i or -o")
|
||||||
if not cl.local:
|
if not cl.local:
|
||||||
return "cannot change non-local CL " + name
|
raise hg_util.Abort("cannot change non-local CL " + name)
|
||||||
if opts["delete"]:
|
if opts["delete"]:
|
||||||
if cl.copied_from:
|
if cl.copied_from:
|
||||||
return "original author must delete CL; hg change -D will remove locally"
|
raise hg_util.Abort("original author must delete CL; hg change -D will remove locally")
|
||||||
PostMessage(ui, cl.name, "*** Abandoned ***", send_mail=cl.mailed)
|
PostMessage(ui, cl.name, "*** Abandoned ***", send_mail=cl.mailed)
|
||||||
EditDesc(cl.name, closed=True, private=cl.private)
|
EditDesc(cl.name, closed=True, private=cl.private)
|
||||||
cl.Delete(ui, repo)
|
cl.Delete(ui, repo)
|
||||||
|
@ -1338,7 +1361,7 @@ def change(ui, repo, *pats, **opts):
|
||||||
s = sys.stdin.read()
|
s = sys.stdin.read()
|
||||||
clx, line, err = ParseCL(s, name)
|
clx, line, err = ParseCL(s, name)
|
||||||
if err != '':
|
if err != '':
|
||||||
return "error parsing change list: line %d: %s" % (line, err)
|
raise hg_util.Abort("error parsing change list: line %d: %s" % (line, err))
|
||||||
if clx.desc is not None:
|
if clx.desc is not None:
|
||||||
cl.desc = clx.desc;
|
cl.desc = clx.desc;
|
||||||
dirty[cl] = True
|
dirty[cl] = True
|
||||||
|
@ -1360,7 +1383,7 @@ def change(ui, repo, *pats, **opts):
|
||||||
cl.files = files
|
cl.files = files
|
||||||
err = EditCL(ui, repo, cl)
|
err = EditCL(ui, repo, cl)
|
||||||
if err != "":
|
if err != "":
|
||||||
return err
|
raise hg_util.Abort(err)
|
||||||
dirty[cl] = True
|
dirty[cl] = True
|
||||||
|
|
||||||
for d, _ in dirty.items():
|
for d, _ in dirty.items():
|
||||||
|
@ -1391,7 +1414,7 @@ def code_login(ui, repo, **opts):
|
||||||
a file in your home directory.
|
a file in your home directory.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
MySend(None)
|
MySend(None)
|
||||||
|
|
||||||
|
@ -1411,8 +1434,10 @@ def clpatch(ui, repo, clname, **opts):
|
||||||
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.
|
||||||
"""
|
"""
|
||||||
if repo[None].branch() != "default":
|
if repo[None].branch() != "default":
|
||||||
return "cannot run hg clpatch outside default branch"
|
raise hg_util.Abort("cannot run hg clpatch outside default branch")
|
||||||
return clpatch_or_undo(ui, repo, clname, opts, mode="clpatch")
|
err = clpatch_or_undo(ui, repo, clname, opts, mode="clpatch")
|
||||||
|
if err:
|
||||||
|
raise hg_util.Abort(err)
|
||||||
|
|
||||||
@hgcommand
|
@hgcommand
|
||||||
def undo(ui, repo, clname, **opts):
|
def undo(ui, repo, clname, **opts):
|
||||||
|
@ -1423,8 +1448,10 @@ def undo(ui, repo, clname, **opts):
|
||||||
you can add the reason for the undo to the description.
|
you can add the reason for the undo to the description.
|
||||||
"""
|
"""
|
||||||
if repo[None].branch() != "default":
|
if repo[None].branch() != "default":
|
||||||
return "cannot run hg undo outside default branch"
|
raise hg_util.Abort("cannot run hg undo outside default branch")
|
||||||
return clpatch_or_undo(ui, repo, clname, opts, mode="undo")
|
err = clpatch_or_undo(ui, repo, clname, opts, mode="undo")
|
||||||
|
if err:
|
||||||
|
raise hg_util.Abort(err)
|
||||||
|
|
||||||
@hgcommand
|
@hgcommand
|
||||||
def release_apply(ui, repo, clname, **opts):
|
def release_apply(ui, repo, clname, **opts):
|
||||||
|
@ -1468,13 +1495,13 @@ def release_apply(ui, repo, clname, **opts):
|
||||||
"""
|
"""
|
||||||
c = repo[None]
|
c = repo[None]
|
||||||
if not releaseBranch:
|
if not releaseBranch:
|
||||||
return "no active release branches"
|
raise hg_util.Abort("no active release branches")
|
||||||
if c.branch() != releaseBranch:
|
if c.branch() != releaseBranch:
|
||||||
if c.modified() or c.added() or c.removed():
|
if c.modified() or c.added() or c.removed():
|
||||||
raise hg_util.Abort("uncommitted local changes - cannot switch branches")
|
raise hg_util.Abort("uncommitted local changes - cannot switch branches")
|
||||||
err = hg_clean(repo, releaseBranch)
|
err = hg_clean(repo, releaseBranch)
|
||||||
if err:
|
if err:
|
||||||
return err
|
raise hg_util.Abort(err)
|
||||||
try:
|
try:
|
||||||
err = clpatch_or_undo(ui, repo, clname, opts, mode="backport")
|
err = clpatch_or_undo(ui, repo, clname, opts, mode="backport")
|
||||||
if err:
|
if err:
|
||||||
|
@ -1482,13 +1509,12 @@ def release_apply(ui, repo, clname, **opts):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
hg_clean(repo, "default")
|
hg_clean(repo, "default")
|
||||||
raise e
|
raise e
|
||||||
return None
|
|
||||||
|
|
||||||
def rev2clname(rev):
|
def rev2clname(rev):
|
||||||
# Extract CL name from revision description.
|
# Extract CL name from revision description.
|
||||||
# The last line in the description that is a codereview URL is the real one.
|
# The last line in the description that is a codereview URL is the real one.
|
||||||
# Earlier lines might be part of the user-written description.
|
# Earlier lines might be part of the user-written description.
|
||||||
all = re.findall('(?m)^http://codereview.appspot.com/([0-9]+)$', rev.description())
|
all = re.findall('(?m)^https?://codereview.appspot.com/([0-9]+)$', rev.description())
|
||||||
if len(all) > 0:
|
if len(all) > 0:
|
||||||
return all[-1]
|
return all[-1]
|
||||||
return ""
|
return ""
|
||||||
|
@ -1586,24 +1612,24 @@ def clpatch_or_undo(ui, repo, clname, opts, mode):
|
||||||
return "local repository is out of date; sync to get %s" % (vers)
|
return "local repository is out of date; sync to get %s" % (vers)
|
||||||
patch1, err = portPatch(repo, patch, vers, id)
|
patch1, err = portPatch(repo, patch, vers, id)
|
||||||
if err != "":
|
if err != "":
|
||||||
if not opts["ignore_hgpatch_failure"]:
|
if not opts["ignore_hgapplydiff_failure"]:
|
||||||
return "codereview issue %s is out of date: %s (%s->%s)" % (clname, err, vers, id)
|
return "codereview issue %s is out of date: %s (%s->%s)" % (clname, err, vers, id)
|
||||||
else:
|
else:
|
||||||
patch = patch1
|
patch = patch1
|
||||||
argv = ["hgpatch"]
|
argv = ["hgapplydiff"]
|
||||||
if opts["no_incoming"] or mode == "backport":
|
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")
|
||||||
except:
|
except:
|
||||||
return "hgpatch: " + ExceptionDetail() + "\nInstall hgpatch with:\n$ go get code.google.com/p/go.codereview/cmd/hgpatch\n"
|
return "hgapplydiff: " + ExceptionDetail() + "\nInstall hgapplydiff with:\n$ go get code.google.com/p/go.codereview/cmd/hgapplydiff\n"
|
||||||
|
|
||||||
out, err = cmd.communicate(patch)
|
out, err = cmd.communicate(patch)
|
||||||
if cmd.returncode != 0 and not opts["ignore_hgpatch_failure"]:
|
if cmd.returncode != 0 and not opts["ignore_hgapplydiff_failure"]:
|
||||||
return "hgpatch failed"
|
return "hgapplydiff failed"
|
||||||
cl.local = True
|
cl.local = True
|
||||||
cl.files = out.strip().split()
|
cl.files = out.strip().split()
|
||||||
if not cl.files and not opts["ignore_hgpatch_failure"]:
|
if not cl.files and not opts["ignore_hgapplydiff_failure"]:
|
||||||
return "codereview issue %s has no changed files" % clname
|
return "codereview issue %s has no changed files" % clname
|
||||||
files = ChangedFiles(ui, repo, [])
|
files = ChangedFiles(ui, repo, [])
|
||||||
extra = Sub(cl.files, files)
|
extra = Sub(cl.files, files)
|
||||||
|
@ -1618,6 +1644,17 @@ def clpatch_or_undo(ui, repo, clname, opts, mode):
|
||||||
else:
|
else:
|
||||||
ui.write(cl.PendingText() + "\n")
|
ui.write(cl.PendingText() + "\n")
|
||||||
|
|
||||||
|
# warn if clpatch will modify file already in another CL (it's unsafe to submit them)
|
||||||
|
if mode == "clpatch":
|
||||||
|
msgs = []
|
||||||
|
cls = LoadAllCL(ui, repo, web=False)
|
||||||
|
for k, v in cls.iteritems():
|
||||||
|
isec = Intersect(v.files, cl.files)
|
||||||
|
if isec and k != clname:
|
||||||
|
msgs.append("CL " + k + ", because it also modifies " + ", ".join(isec) + ".")
|
||||||
|
if msgs:
|
||||||
|
ui.warn("warning: please double check before submitting this CL and:\n\t" + "\n\t".join(msgs) + "\n")
|
||||||
|
|
||||||
# portPatch rewrites patch from being a patch against
|
# portPatch rewrites patch from being a patch against
|
||||||
# oldver to being a patch against newver.
|
# oldver to being a patch against newver.
|
||||||
def portPatch(repo, patch, oldver, newver):
|
def portPatch(repo, patch, oldver, newver):
|
||||||
|
@ -1687,7 +1724,7 @@ def download(ui, repo, clname, **opts):
|
||||||
followed by its diff, downloaded from the code review server.
|
followed by its diff, downloaded from the code review server.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
cl, vers, patch, err = DownloadCL(ui, repo, clname)
|
cl, vers, patch, err = DownloadCL(ui, repo, clname)
|
||||||
if err != "":
|
if err != "":
|
||||||
|
@ -1709,7 +1746,7 @@ def file(ui, repo, clname, pat, *pats, **opts):
|
||||||
It does not edit them or remove them from the repository.
|
It does not edit them or remove them from the repository.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
pats = tuple([pat] + list(pats))
|
pats = tuple([pat] + list(pats))
|
||||||
if not GoodCLName(clname):
|
if not GoodCLName(clname):
|
||||||
|
@ -1773,19 +1810,20 @@ def gofmt(ui, repo, *pats, **opts):
|
||||||
the given patterns.
|
the given patterns.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
files = ChangedExistingFiles(ui, repo, pats, opts)
|
files = ChangedExistingFiles(ui, repo, pats, opts)
|
||||||
files = gofmt_required(files)
|
files = gofmt_required(files)
|
||||||
if not files:
|
if not files:
|
||||||
return "no modified go files"
|
ui.status("no modified go files\n")
|
||||||
|
return
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
|
files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
|
||||||
try:
|
try:
|
||||||
cmd = ["gofmt", "-l"]
|
cmd = ["gofmt", "-l"]
|
||||||
if not opts["list"]:
|
if not opts["list"]:
|
||||||
cmd += ["-w"]
|
cmd += ["-w"]
|
||||||
if os.spawnvp(os.P_WAIT, "gofmt", cmd + files) != 0:
|
if subprocess.call(cmd + files) != 0:
|
||||||
raise hg_util.Abort("gofmt did not exit cleanly")
|
raise hg_util.Abort("gofmt did not exit cleanly")
|
||||||
except hg_error.Abort, e:
|
except hg_error.Abort, e:
|
||||||
raise
|
raise
|
||||||
|
@ -1807,11 +1845,11 @@ def mail(ui, repo, *pats, **opts):
|
||||||
to the reviewer and CC list asking for a review.
|
to the reviewer and CC list asking for a review.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
cl, err = CommandLineCL(ui, repo, pats, opts, defaultcc=defaultcc)
|
cl, err = CommandLineCL(ui, repo, pats, opts, op="mail", defaultcc=defaultcc)
|
||||||
if err != "":
|
if err != "":
|
||||||
return err
|
raise hg_util.Abort(err)
|
||||||
cl.Upload(ui, repo, gofmt_just_warn=True)
|
cl.Upload(ui, repo, gofmt_just_warn=True)
|
||||||
if not cl.reviewer:
|
if not cl.reviewer:
|
||||||
# If no reviewer is listed, assign the review to defaultcc.
|
# If no reviewer is listed, assign the review to defaultcc.
|
||||||
|
@ -1819,15 +1857,15 @@ def mail(ui, repo, *pats, **opts):
|
||||||
# codereview.appspot.com/user/defaultcc
|
# codereview.appspot.com/user/defaultcc
|
||||||
# page, so that it doesn't get dropped on the floor.
|
# page, so that it doesn't get dropped on the floor.
|
||||||
if not defaultcc:
|
if not defaultcc:
|
||||||
return "no reviewers listed in CL"
|
raise hg_util.Abort("no reviewers listed in CL")
|
||||||
cl.cc = Sub(cl.cc, defaultcc)
|
cl.cc = Sub(cl.cc, defaultcc)
|
||||||
cl.reviewer = defaultcc
|
cl.reviewer = defaultcc
|
||||||
cl.Flush(ui, repo)
|
cl.Flush(ui, repo)
|
||||||
|
|
||||||
if cl.files == []:
|
if cl.files == []:
|
||||||
return "no changed files, not sending mail"
|
raise hg_util.Abort("no changed files, not sending mail")
|
||||||
|
|
||||||
cl.Mail(ui, repo)
|
cl.Mail(ui, repo)
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# hg p / hg pq / hg ps / hg pending
|
# hg p / hg pq / hg ps / hg pending
|
||||||
|
@ -1853,7 +1891,7 @@ def pending(ui, repo, *pats, **opts):
|
||||||
Lists pending changes followed by a list of unassigned but modified files.
|
Lists pending changes followed by a list of unassigned but modified files.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
quick = opts.get('quick', False)
|
quick = opts.get('quick', False)
|
||||||
short = opts.get('short', False)
|
short = opts.get('short', False)
|
||||||
|
@ -1868,7 +1906,7 @@ def pending(ui, repo, *pats, **opts):
|
||||||
ui.write(cl.PendingText(quick=quick) + "\n")
|
ui.write(cl.PendingText(quick=quick) + "\n")
|
||||||
|
|
||||||
if short:
|
if short:
|
||||||
return
|
return 0
|
||||||
files = DefaultFiles(ui, repo, [])
|
files = DefaultFiles(ui, repo, [])
|
||||||
if len(files) > 0:
|
if len(files) > 0:
|
||||||
s = "Changed files not in any CL:\n"
|
s = "Changed files not in any CL:\n"
|
||||||
|
@ -1890,7 +1928,7 @@ def submit(ui, repo, *pats, **opts):
|
||||||
Bails out if the local repository is not in sync with the remote one.
|
Bails out if the local repository is not in sync with the remote one.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
# We already called this on startup but sometimes Mercurial forgets.
|
# We already called this on startup but sometimes Mercurial forgets.
|
||||||
set_mercurial_encoding_to_utf8()
|
set_mercurial_encoding_to_utf8()
|
||||||
|
@ -1898,9 +1936,9 @@ def submit(ui, repo, *pats, **opts):
|
||||||
if not opts["no_incoming"] and hg_incoming(ui, repo):
|
if not opts["no_incoming"] and hg_incoming(ui, repo):
|
||||||
need_sync()
|
need_sync()
|
||||||
|
|
||||||
cl, err = CommandLineCL(ui, repo, pats, opts, defaultcc=defaultcc)
|
cl, err = CommandLineCL(ui, repo, pats, opts, op="submit", defaultcc=defaultcc)
|
||||||
if err != "":
|
if err != "":
|
||||||
return err
|
raise hg_util.Abort(err)
|
||||||
|
|
||||||
user = None
|
user = None
|
||||||
if cl.copied_from:
|
if cl.copied_from:
|
||||||
|
@ -1909,20 +1947,29 @@ def submit(ui, repo, *pats, **opts):
|
||||||
typecheck(userline, str)
|
typecheck(userline, str)
|
||||||
|
|
||||||
about = ""
|
about = ""
|
||||||
if cl.reviewer:
|
|
||||||
about += "R=" + JoinComma([CutDomain(s) for s in cl.reviewer]) + "\n"
|
if not cl.lgtm and not opts.get('tbr') and not isAddca(cl):
|
||||||
|
raise hg_util.Abort("this CL has not been LGTM'ed")
|
||||||
|
if cl.lgtm:
|
||||||
|
about += "LGTM=" + JoinComma([CutDomain(who) for (who, line, approval) in cl.lgtm if approval]) + "\n"
|
||||||
|
reviewer = cl.reviewer
|
||||||
if opts.get('tbr'):
|
if opts.get('tbr'):
|
||||||
tbr = SplitCommaSpace(opts.get('tbr'))
|
tbr = SplitCommaSpace(opts.get('tbr'))
|
||||||
|
for name in tbr:
|
||||||
|
if name.startswith('golang-'):
|
||||||
|
raise hg_util.Abort("--tbr requires a person, not a mailing list")
|
||||||
cl.reviewer = Add(cl.reviewer, tbr)
|
cl.reviewer = Add(cl.reviewer, tbr)
|
||||||
about += "TBR=" + JoinComma([CutDomain(s) for s in tbr]) + "\n"
|
about += "TBR=" + JoinComma([CutDomain(s) for s in tbr]) + "\n"
|
||||||
|
if reviewer:
|
||||||
|
about += "R=" + JoinComma([CutDomain(s) for s in reviewer]) + "\n"
|
||||||
if cl.cc:
|
if cl.cc:
|
||||||
about += "CC=" + JoinComma([CutDomain(s) for s in cl.cc]) + "\n"
|
about += "CC=" + JoinComma([CutDomain(s) for s in cl.cc]) + "\n"
|
||||||
|
|
||||||
if not cl.reviewer:
|
if not cl.reviewer:
|
||||||
return "no reviewers listed in CL"
|
raise hg_util.Abort("no reviewers listed in CL")
|
||||||
|
|
||||||
if not cl.local:
|
if not cl.local:
|
||||||
return "cannot submit non-local CL"
|
raise hg_util.Abort("cannot submit non-local CL")
|
||||||
|
|
||||||
# upload, to sync current patch and also get change number if CL is new.
|
# upload, to sync current patch and also get change number if CL is new.
|
||||||
if not cl.copied_from:
|
if not cl.copied_from:
|
||||||
|
@ -1957,7 +2004,7 @@ def submit(ui, repo, *pats, **opts):
|
||||||
ret = hg_commit(ui, repo, *['path:'+f for f in cl.files], message=message, user=userline)
|
ret = hg_commit(ui, repo, *['path:'+f for f in cl.files], message=message, user=userline)
|
||||||
commit_okay = False
|
commit_okay = False
|
||||||
if ret:
|
if ret:
|
||||||
return "nothing changed"
|
raise hg_util.Abort("nothing changed")
|
||||||
node = repo["-1"].node()
|
node = repo["-1"].node()
|
||||||
# push to remote; if it fails for any reason, roll back
|
# push to remote; if it fails for any reason, roll back
|
||||||
try:
|
try:
|
||||||
|
@ -1968,12 +2015,16 @@ def submit(ui, repo, *pats, **opts):
|
||||||
|
|
||||||
# Push changes to remote. If it works, we're committed. If not, roll back.
|
# Push changes to remote. If it works, we're committed. If not, roll back.
|
||||||
try:
|
try:
|
||||||
hg_push(ui, repo)
|
if hg_push(ui, repo):
|
||||||
|
raise hg_util.Abort("push error")
|
||||||
except hg_error.Abort, e:
|
except hg_error.Abort, e:
|
||||||
if e.message.find("push creates new heads") >= 0:
|
if e.message.find("push creates new heads") >= 0:
|
||||||
# Remote repository had changes we missed.
|
# Remote repository had changes we missed.
|
||||||
need_sync()
|
need_sync()
|
||||||
raise
|
raise
|
||||||
|
except urllib2.HTTPError, e:
|
||||||
|
print >>sys.stderr, "pushing to remote server failed; do you have commit permissions?"
|
||||||
|
raise
|
||||||
except:
|
except:
|
||||||
real_rollback()
|
real_rollback()
|
||||||
raise
|
raise
|
||||||
|
@ -1985,11 +2036,11 @@ def submit(ui, repo, *pats, **opts):
|
||||||
"(^https?://([^@/]+@)?code\.google\.com/p/([^/.]+)(\.[^./]+)?/?)", url)
|
"(^https?://([^@/]+@)?code\.google\.com/p/([^/.]+)(\.[^./]+)?/?)", url)
|
||||||
if m:
|
if m:
|
||||||
if m.group(1): # prj.googlecode.com/hg/ case
|
if m.group(1): # prj.googlecode.com/hg/ case
|
||||||
changeURL = "http://code.google.com/p/%s/source/detail?r=%s" % (m.group(3), changeURL)
|
changeURL = "https://code.google.com/p/%s/source/detail?r=%s" % (m.group(3), changeURL)
|
||||||
elif m.group(4) and m.group(7): # code.google.com/p/prj.subrepo/ case
|
elif m.group(4) and m.group(7): # code.google.com/p/prj.subrepo/ case
|
||||||
changeURL = "http://code.google.com/p/%s/source/detail?r=%s&repo=%s" % (m.group(6), changeURL, m.group(7)[1:])
|
changeURL = "https://code.google.com/p/%s/source/detail?r=%s&repo=%s" % (m.group(6), changeURL, m.group(7)[1:])
|
||||||
elif m.group(4): # code.google.com/p/prj/ case
|
elif m.group(4): # code.google.com/p/prj/ case
|
||||||
changeURL = "http://code.google.com/p/%s/source/detail?r=%s" % (m.group(6), changeURL)
|
changeURL = "https://code.google.com/p/%s/source/detail?r=%s" % (m.group(6), changeURL)
|
||||||
else:
|
else:
|
||||||
print >>sys.stderr, "URL: ", url
|
print >>sys.stderr, "URL: ", url
|
||||||
else:
|
else:
|
||||||
|
@ -2010,7 +2061,12 @@ def submit(ui, repo, *pats, **opts):
|
||||||
err = hg_clean(repo, "default")
|
err = hg_clean(repo, "default")
|
||||||
if err:
|
if err:
|
||||||
return err
|
return err
|
||||||
return None
|
return 0
|
||||||
|
|
||||||
|
def isAddca(cl):
|
||||||
|
rev = cl.reviewer
|
||||||
|
isGobot = 'gobot' in rev or 'gobot@swtch.com' in rev or 'gobot@golang.org' in rev
|
||||||
|
return cl.desc.startswith('A+C:') and 'Generated by addca.' in cl.desc and isGobot
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# hg sync
|
# hg sync
|
||||||
|
@ -2023,10 +2079,22 @@ def sync(ui, repo, **opts):
|
||||||
into the local repository.
|
into the local repository.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
if not opts["local"]:
|
if not opts["local"]:
|
||||||
err = hg_pull(ui, repo, update=True)
|
# If there are incoming CLs, pull -u will do the update.
|
||||||
|
# If there are no incoming CLs, do hg update to make sure
|
||||||
|
# that an update always happens regardless. This is less
|
||||||
|
# surprising than update depending on incoming CLs.
|
||||||
|
# It is important not to do both hg pull -u and hg update
|
||||||
|
# in the same command, because the hg update will end
|
||||||
|
# up marking resolve conflicts from the hg pull -u as resolved,
|
||||||
|
# causing files with <<< >>> markers to not show up in
|
||||||
|
# hg resolve -l. Yay Mercurial.
|
||||||
|
if hg_incoming(ui, repo):
|
||||||
|
err = hg_pull(ui, repo, update=True)
|
||||||
|
else:
|
||||||
|
err = hg_update(ui, repo)
|
||||||
if err:
|
if err:
|
||||||
return err
|
return err
|
||||||
sync_changes(ui, repo)
|
sync_changes(ui, repo)
|
||||||
|
@ -2037,7 +2105,7 @@ def sync_changes(ui, repo):
|
||||||
# Double-check them by looking at the Rietveld log.
|
# Double-check them by looking at the Rietveld log.
|
||||||
for rev in hg_log(ui, repo, limit=100, template="{node}\n").split():
|
for rev in hg_log(ui, repo, limit=100, template="{node}\n").split():
|
||||||
desc = repo[rev].description().strip()
|
desc = repo[rev].description().strip()
|
||||||
for clname in re.findall('(?m)^http://(?:[^\n]+)/([0-9]+)$', desc):
|
for clname in re.findall('(?m)^https?://(?:[^\n]+)/([0-9]+)$', desc):
|
||||||
if IsLocalCL(ui, repo, clname) and IsRietveldSubmitted(ui, clname, repo[rev].hex()):
|
if IsLocalCL(ui, repo, clname) and IsRietveldSubmitted(ui, clname, repo[rev].hex()):
|
||||||
ui.warn("CL %s submitted as %s; closing\n" % (clname, repo[rev]))
|
ui.warn("CL %s submitted as %s; closing\n" % (clname, repo[rev]))
|
||||||
cl, err = LoadCL(ui, repo, clname, web=False)
|
cl, err = LoadCL(ui, repo, clname, web=False)
|
||||||
|
@ -2064,7 +2132,7 @@ def sync_changes(ui, repo):
|
||||||
ui.warn("CL %s has no files; delete (abandon) with hg change -d %s\n" % (cl.name, cl.name))
|
ui.warn("CL %s has no files; delete (abandon) with hg change -d %s\n" % (cl.name, cl.name))
|
||||||
else:
|
else:
|
||||||
ui.warn("CL %s has no files; delete locally with hg change -D %s\n" % (cl.name, cl.name))
|
ui.warn("CL %s has no files; delete locally with hg change -D %s\n" % (cl.name, cl.name))
|
||||||
return
|
return 0
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# hg upload
|
# hg upload
|
||||||
|
@ -2076,17 +2144,17 @@ def upload(ui, repo, name, **opts):
|
||||||
Uploads the current modifications for a given change to the server.
|
Uploads the current modifications for a given change to the server.
|
||||||
"""
|
"""
|
||||||
if codereview_disabled:
|
if codereview_disabled:
|
||||||
return codereview_disabled
|
raise hg_util.Abort(codereview_disabled)
|
||||||
|
|
||||||
repo.ui.quiet = True
|
repo.ui.quiet = True
|
||||||
cl, err = LoadCL(ui, repo, name, web=True)
|
cl, err = LoadCL(ui, repo, name, web=True)
|
||||||
if err != "":
|
if err != "":
|
||||||
return err
|
raise hg_util.Abort(err)
|
||||||
if not cl.local:
|
if not cl.local:
|
||||||
return "cannot upload non-local change"
|
raise hg_util.Abort("cannot upload non-local change")
|
||||||
cl.Upload(ui, repo)
|
cl.Upload(ui, repo)
|
||||||
print "%s%s\n" % (server_url_base, cl.name)
|
print "%s%s\n" % (server_url_base, cl.name)
|
||||||
return
|
return 0
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Table of commands, supplied to Mercurial for installation.
|
# Table of commands, supplied to Mercurial for installation.
|
||||||
|
@ -2115,7 +2183,7 @@ cmdtable = {
|
||||||
"^clpatch": (
|
"^clpatch": (
|
||||||
clpatch,
|
clpatch,
|
||||||
[
|
[
|
||||||
('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
|
('', 'ignore_hgapplydiff_failure', None, 'create CL metadata even if hgapplydiff fails'),
|
||||||
('', 'no_incoming', None, 'disable check for incoming changes'),
|
('', 'no_incoming', None, 'disable check for incoming changes'),
|
||||||
],
|
],
|
||||||
"change#"
|
"change#"
|
||||||
|
@ -2174,7 +2242,7 @@ cmdtable = {
|
||||||
"^release-apply": (
|
"^release-apply": (
|
||||||
release_apply,
|
release_apply,
|
||||||
[
|
[
|
||||||
('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
|
('', 'ignore_hgapplydiff_failure', None, 'create CL metadata even if hgapplydiff fails'),
|
||||||
('', 'no_incoming', None, 'disable check for incoming changes'),
|
('', 'no_incoming', None, 'disable check for incoming changes'),
|
||||||
],
|
],
|
||||||
"change#"
|
"change#"
|
||||||
|
@ -2197,7 +2265,7 @@ cmdtable = {
|
||||||
"^undo": (
|
"^undo": (
|
||||||
undo,
|
undo,
|
||||||
[
|
[
|
||||||
('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
|
('', 'ignore_hgapplydiff_failure', None, 'create CL metadata even if hgapplydiff fails'),
|
||||||
('', 'no_incoming', None, 'disable check for incoming changes'),
|
('', 'no_incoming', None, 'disable check for incoming changes'),
|
||||||
],
|
],
|
||||||
"change#"
|
"change#"
|
||||||
|
@ -2229,6 +2297,7 @@ def reposetup(ui, repo):
|
||||||
if codereview_init:
|
if codereview_init:
|
||||||
return
|
return
|
||||||
codereview_init = True
|
codereview_init = True
|
||||||
|
start_status_thread()
|
||||||
|
|
||||||
# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.
|
# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.
|
||||||
root = ''
|
root = ''
|
||||||
|
@ -2366,7 +2435,7 @@ def IsRietveldSubmitted(ui, clname, hex):
|
||||||
return False
|
return False
|
||||||
for msg in dict.get("messages", []):
|
for msg in dict.get("messages", []):
|
||||||
text = msg.get("text", "")
|
text = msg.get("text", "")
|
||||||
m = re.match('\*\*\* Submitted as [^*]*?([0-9a-f]+) \*\*\*', text)
|
m = re.match('\*\*\* Submitted as [^*]*?r=([0-9a-f]+)[^ ]* \*\*\*', text)
|
||||||
if m is not None and len(m.group(1)) >= 8 and hex.startswith(m.group(1)):
|
if m is not None and len(m.group(1)) >= 8 and hex.startswith(m.group(1)):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -2460,6 +2529,8 @@ def MySend1(request_path, payload=None,
|
||||||
self._Authenticate()
|
self._Authenticate()
|
||||||
if request_path is None:
|
if request_path is None:
|
||||||
return
|
return
|
||||||
|
if timeout is None:
|
||||||
|
timeout = 30 # seconds
|
||||||
|
|
||||||
old_timeout = socket.getdefaulttimeout()
|
old_timeout = socket.getdefaulttimeout()
|
||||||
socket.setdefaulttimeout(timeout)
|
socket.setdefaulttimeout(timeout)
|
||||||
|
@ -2468,7 +2539,7 @@ def MySend1(request_path, payload=None,
|
||||||
while True:
|
while True:
|
||||||
tries += 1
|
tries += 1
|
||||||
args = dict(kwargs)
|
args = dict(kwargs)
|
||||||
url = "http://%s%s" % (self.host, request_path)
|
url = "https://%s%s" % (self.host, request_path)
|
||||||
if args:
|
if args:
|
||||||
url += "?" + urllib.urlencode(args)
|
url += "?" + urllib.urlencode(args)
|
||||||
req = self._CreateRequest(url=url, data=payload)
|
req = self._CreateRequest(url=url, data=payload)
|
||||||
|
@ -2580,7 +2651,7 @@ def RietveldSetup(ui, repo):
|
||||||
if x is not None:
|
if x is not None:
|
||||||
email = x
|
email = x
|
||||||
|
|
||||||
server_url_base = "http://" + server + "/"
|
server_url_base = "https://" + server + "/"
|
||||||
|
|
||||||
testing = ui.config("codereview", "testing")
|
testing = ui.config("codereview", "testing")
|
||||||
force_google_account = ui.configbool("codereview", "force_google_account", False)
|
force_google_account = ui.configbool("codereview", "force_google_account", False)
|
||||||
|
@ -2609,7 +2680,7 @@ def RietveldSetup(ui, repo):
|
||||||
rpc = None
|
rpc = None
|
||||||
|
|
||||||
global releaseBranch
|
global releaseBranch
|
||||||
tags = repo.branchtags().keys()
|
tags = repo.branchmap().keys()
|
||||||
if 'release-branch.go10' in tags:
|
if 'release-branch.go10' in tags:
|
||||||
# NOTE(rsc): This tags.sort is going to get the wrong
|
# NOTE(rsc): This tags.sort is going to get the wrong
|
||||||
# answer when comparing release-branch.go9 with
|
# answer when comparing release-branch.go9 with
|
||||||
|
@ -2755,7 +2826,9 @@ class ClientLoginError(urllib2.HTTPError):
|
||||||
def __init__(self, url, code, msg, headers, args):
|
def __init__(self, url, code, msg, headers, args):
|
||||||
urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
|
urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
|
||||||
self.args = args
|
self.args = args
|
||||||
self.reason = args["Error"]
|
# .reason is now a read-only property based on .msg
|
||||||
|
# this means we ignore 'msg', but that seems to work fine.
|
||||||
|
self.msg = args["Error"]
|
||||||
|
|
||||||
|
|
||||||
class AbstractRpcServer(object):
|
class AbstractRpcServer(object):
|
||||||
|
@ -2858,7 +2931,7 @@ class AbstractRpcServer(object):
|
||||||
# This is a dummy value to allow us to identify when we're successful.
|
# This is a dummy value to allow us to identify when we're successful.
|
||||||
continue_location = "http://localhost/"
|
continue_location = "http://localhost/"
|
||||||
args = {"continue": continue_location, "auth": auth_token}
|
args = {"continue": continue_location, "auth": auth_token}
|
||||||
req = self._CreateRequest("http://%s/_ah/login?%s" % (self.host, urllib.urlencode(args)))
|
req = self._CreateRequest("https://%s/_ah/login?%s" % (self.host, urllib.urlencode(args)))
|
||||||
try:
|
try:
|
||||||
response = self.opener.open(req)
|
response = self.opener.open(req)
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
|
@ -2888,31 +2961,31 @@ class AbstractRpcServer(object):
|
||||||
try:
|
try:
|
||||||
auth_token = self._GetAuthToken(credentials[0], credentials[1])
|
auth_token = self._GetAuthToken(credentials[0], credentials[1])
|
||||||
except ClientLoginError, e:
|
except ClientLoginError, e:
|
||||||
if e.reason == "BadAuthentication":
|
if e.msg == "BadAuthentication":
|
||||||
print >>sys.stderr, "Invalid username or password."
|
print >>sys.stderr, "Invalid username or password."
|
||||||
continue
|
continue
|
||||||
if e.reason == "CaptchaRequired":
|
if e.msg == "CaptchaRequired":
|
||||||
print >>sys.stderr, (
|
print >>sys.stderr, (
|
||||||
"Please go to\n"
|
"Please go to\n"
|
||||||
"https://www.google.com/accounts/DisplayUnlockCaptcha\n"
|
"https://www.google.com/accounts/DisplayUnlockCaptcha\n"
|
||||||
"and verify you are a human. Then try again.")
|
"and verify you are a human. Then try again.")
|
||||||
break
|
break
|
||||||
if e.reason == "NotVerified":
|
if e.msg == "NotVerified":
|
||||||
print >>sys.stderr, "Account not verified."
|
print >>sys.stderr, "Account not verified."
|
||||||
break
|
break
|
||||||
if e.reason == "TermsNotAgreed":
|
if e.msg == "TermsNotAgreed":
|
||||||
print >>sys.stderr, "User has not agreed to TOS."
|
print >>sys.stderr, "User has not agreed to TOS."
|
||||||
break
|
break
|
||||||
if e.reason == "AccountDeleted":
|
if e.msg == "AccountDeleted":
|
||||||
print >>sys.stderr, "The user account has been deleted."
|
print >>sys.stderr, "The user account has been deleted."
|
||||||
break
|
break
|
||||||
if e.reason == "AccountDisabled":
|
if e.msg == "AccountDisabled":
|
||||||
print >>sys.stderr, "The user account has been disabled."
|
print >>sys.stderr, "The user account has been disabled."
|
||||||
break
|
break
|
||||||
if e.reason == "ServiceDisabled":
|
if e.msg == "ServiceDisabled":
|
||||||
print >>sys.stderr, "The user's access to the service has been disabled."
|
print >>sys.stderr, "The user's access to the service has been disabled."
|
||||||
break
|
break
|
||||||
if e.reason == "ServiceUnavailable":
|
if e.msg == "ServiceUnavailable":
|
||||||
print >>sys.stderr, "The service is not available; try again later."
|
print >>sys.stderr, "The service is not available; try again later."
|
||||||
break
|
break
|
||||||
raise
|
raise
|
||||||
|
@ -2948,7 +3021,7 @@ class AbstractRpcServer(object):
|
||||||
while True:
|
while True:
|
||||||
tries += 1
|
tries += 1
|
||||||
args = dict(kwargs)
|
args = dict(kwargs)
|
||||||
url = "http://%s%s" % (self.host, request_path)
|
url = "https://%s%s" % (self.host, request_path)
|
||||||
if args:
|
if args:
|
||||||
url += "?" + urllib.urlencode(args)
|
url += "?" + urllib.urlencode(args)
|
||||||
req = self._CreateRequest(url=url, data=payload)
|
req = self._CreateRequest(url=url, data=payload)
|
||||||
|
|
Loading…
Reference in a new issue