Commit d8e0d9a7 authored by Russ Cox's avatar Russ Cox

add "hg gofmt" to run all modified files through gofmt.

add check before Upload, for now disabled by default,
that files do not change when run through gofmt.
enable by adding

	[codereview]
	force_gofmt = True

to .hgrc or .hg/hgrc.

add doc strings for a few more commands.
rename codereview-login to code-login
to make module doc visible.

R=r
CC=gri
http://go/go-review/1018056
parent ed494c63
...@@ -144,7 +144,7 @@ class CL(object): ...@@ -144,7 +144,7 @@ class CL(object):
dir = CodeReviewDir(ui, repo) dir = CodeReviewDir(ui, repo)
os.unlink(dir + "/cl." + self.name) os.unlink(dir + "/cl." + self.name)
def Subject(self): def Subject(self):
s = line1(self.desc) s = line1(self.desc)
if len(s) > 60: if len(s) > 60:
s = s[0:55] + "..." s = s[0:55] + "..."
...@@ -152,7 +152,9 @@ class CL(object): ...@@ -152,7 +152,9 @@ class CL(object):
s = "code review %s: %s" % (self.name, s) s = "code review %s: %s" % (self.name, s)
return s return s
def Upload(self, ui, repo, send_mail=False): def Upload(self, ui, repo, send_mail=False, gofmt=True):
if ui.configbool("codereview", "force_gofmt", False) and gofmt:
CheckGofmt(ui, repo, self.files)
os.chdir(repo.root) os.chdir(repo.root)
form_fields = [ form_fields = [
("content_upload", "1"), ("content_upload", "1"),
...@@ -434,6 +436,15 @@ def ChangedFiles(ui, repo, pats, opts): ...@@ -434,6 +436,15 @@ def ChangedFiles(ui, repo, pats, opts):
l.sort() l.sort()
return l return l
# Return list of changed files in repository that match pats and still exist.
def ChangedExistingFiles(ui, repo, pats, opts):
matcher = cmdutil.match(repo, pats, opts)
node1, node2 = cmdutil.revpair(repo, None)
modified, added, _ = repo.status(node1, node2, matcher)[:3]
l = modified + added
l.sort()
return l
# Return list of files claimed by existing CLs # Return list of files claimed by existing CLs
def TakenFiles(ui, repo): def TakenFiles(ui, repo):
return Taken(ui, repo).keys() return Taken(ui, repo).keys()
...@@ -540,9 +551,36 @@ def ReplacementForCmdutilMatch(repo, pats=[], opts={}, globbed=False, default='r ...@@ -540,9 +551,36 @@ def ReplacementForCmdutilMatch(repo, pats=[], opts={}, globbed=False, default='r
if err != '': if err != '':
raise util.Abort("loading CL " + clname + ": " + err) raise util.Abort("loading CL " + clname + ": " + err)
files = Add(files, cl.files) files = Add(files, cl.files)
pats = Sub(pats, taken) + ['path:'+f for f in files] pats = Sub(pats, taken) + ['path:'+f for f in files]
return original_match(repo, pats=pats, opts=opts, globbed=globbed, default=default) return original_match(repo, pats=pats, opts=opts, globbed=globbed, default=default)
def RelativePath(path, cwd):
n = len(cwd)
if path.startswith(cwd) and path[n] == '/':
return path[n+1:]
return path
# Check that gofmt run on the list of files does not change them
def CheckGofmt(ui, repo, files):
f = [f for f in files if f.endswith('.go')]
if not f:
return
cwd = os.getcwd()
files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
try:
stdin, stdout, stderr = os.popen3(["gofmt", "-l"] + files)
stdin.close()
except:
raise util.Abort("gofmt: " + ExceptionDetail())
data = stdout.read()
errors = stderr.read()
if len(errors) > 0:
ui.warn("gofmt errors:\n" + errors.rstrip() + "\n")
return
if len(data) > 0:
raise util.Abort("gofmt needs to format these files (run hg gofmt):\n" + data)
return
####################################################################### #######################################################################
# Mercurial commands # Mercurial commands
...@@ -592,7 +630,7 @@ def change(ui, repo, *pats, **opts): ...@@ -592,7 +630,7 @@ def change(ui, repo, *pats, **opts):
files = ChangedFiles(ui, repo, pats, opts) files = ChangedFiles(ui, repo, pats, opts)
taken = TakenFiles(ui, repo) taken = TakenFiles(ui, repo)
files = Sub(files, taken) files = Sub(files, taken)
if opts["delete"]: if opts["delete"]:
if name == "new": if name == "new":
return "cannot use -d with file patterns" return "cannot use -d with file patterns"
...@@ -643,7 +681,7 @@ def change(ui, repo, *pats, **opts): ...@@ -643,7 +681,7 @@ def change(ui, repo, *pats, **opts):
ui.write("CL created: " + cl.url + "\n") ui.write("CL created: " + cl.url + "\n")
return return
def codereview_login(ui, repo, **opts): def code_login(ui, repo, **opts):
"""log in to code review server """log in to code review server
Logs in to the code review server, saving a cookie in Logs in to the code review server, saving a cookie in
...@@ -653,16 +691,16 @@ def codereview_login(ui, repo, **opts): ...@@ -653,16 +691,16 @@ def codereview_login(ui, repo, **opts):
def file(ui, repo, clname, pat, *pats, **opts): def file(ui, repo, clname, pat, *pats, **opts):
"""assign files to or remove files from a change list """assign files to or remove files from a change list
Assign files to or (with -d) remove files from a change list. Assign files to or (with -d) remove files from a change list.
The -d option only removes files from the change list. The -d option only removes files from the change list.
It does not edit them or remove them from the repository. It does not edit them or remove them from the repository.
""" """
pats = tuple([pat] + list(pats)) pats = tuple([pat] + list(pats))
if not GoodCLName(clname): if not GoodCLName(clname):
return "invalid CL name " + clname return "invalid CL name " + clname
dirty = {} dirty = {}
cl, err = LoadCL(ui, repo, clname, web=False) cl, err = LoadCL(ui, repo, clname, web=False)
if err != '': if err != '':
...@@ -709,8 +747,34 @@ def file(ui, repo, clname, pat, *pats, **opts): ...@@ -709,8 +747,34 @@ def file(ui, repo, clname, pat, *pats, **opts):
for d, _ in dirty.items(): for d, _ in dirty.items():
d.Flush(ui, repo) d.Flush(ui, repo)
return return
def gofmt(ui, repo, *pats, **opts):
"""apply gofmt to modified files
Applies gofmt to the modified files in the repository that match
the given patterns.
"""
files = ChangedExistingFiles(ui, repo, pats, opts)
files = [f for f in files if f.endswith(".go")]
if not files:
return "no modified go files"
cwd = os.getcwd()
files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
try:
if os.spawnvp(os.P_WAIT, "gofmt", ["gofmt", "-l", "-w"] + files) != 0:
raise util.Abort("gofmt did not exit cleanly")
except error.Abort, e:
raise
except:
raise util.Abort("gofmt: " + ExceptionDetail())
return
def mail(ui, repo, *pats, **opts): def mail(ui, repo, *pats, **opts):
"""mail a change for review
Uploads a patch to the code review server and then sends mail
to the reviewer and CC list asking for a review.
"""
cl, err = CommandLineCL(ui, repo, pats, opts) cl, err = CommandLineCL(ui, repo, pats, opts)
if err != "": if err != "":
return err return err
...@@ -723,9 +787,14 @@ def mail(ui, repo, *pats, **opts): ...@@ -723,9 +787,14 @@ def mail(ui, repo, *pats, **opts):
PostMessage(cl.name, pmsg, send_mail="checked", subject=cl.Subject()) PostMessage(cl.name, pmsg, send_mail="checked", subject=cl.Subject())
def nocommit(ui, repo, *pats, **opts): def nocommit(ui, repo, *pats, **opts):
"""(disabled when using this extension)"""
return "The codereview extension is enabled; do not use commit." return "The codereview extension is enabled; do not use commit."
def pending(ui, repo, *pats, **opts): def pending(ui, repo, *pats, **opts):
"""show pending changes
Lists pending changes followed by a list of unassigned but modified files.
"""
m = LoadAllCL(ui, repo, web=True) m = LoadAllCL(ui, repo, web=True)
names = m.keys() names = m.keys()
names.sort() names.sort()
...@@ -902,6 +971,10 @@ def uisetup(ui): ...@@ -902,6 +971,10 @@ def uisetup(ui):
commands.table["^commit|ci"] = (nocommit, [], "") commands.table["^commit|ci"] = (nocommit, [], "")
def upload(ui, repo, name, **opts): def upload(ui, repo, name, **opts):
"""upload diffs to the code review server
Uploads the current modifications for a given change to the server.
"""
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 != "":
...@@ -931,8 +1004,11 @@ cmdtable = { ...@@ -931,8 +1004,11 @@ cmdtable = {
], ],
"[-i] [-o] change# or FILE ..." "[-i] [-o] change# or FILE ..."
), ),
"codereview-login": ( # Would prefer to call this codereview-login, but then
codereview_login, # hg help codereview prints the help for this command
# instead of the help for the extension.
"code-login": (
code_login,
[], [],
"", "",
), ),
...@@ -948,6 +1024,11 @@ cmdtable = { ...@@ -948,6 +1024,11 @@ cmdtable = {
], ],
"[-d] change# FILE ..." "[-d] change# FILE ..."
), ),
"^gofmt": (
gofmt,
[],
"FILE ..."
),
"^pending|p": ( "^pending|p": (
pending, pending,
[], [],
...@@ -1198,7 +1279,7 @@ def RietveldSetup(ui, repo): ...@@ -1198,7 +1279,7 @@ def RietveldSetup(ui, repo):
# if not ui.has_section("codereview"): # if not ui.has_section("codereview"):
# cmdtable = {} # cmdtable = {}
# return # return
if not ui.verbose: if not ui.verbose:
verbosity = 0 verbosity = 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment