summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2011-09-26 18:32:16 -0400
committerRuss Cox <rsc@golang.org>2011-09-26 18:32:16 -0400
commit4da3259d4feeb7045ca9cc9988bc2af10c2ae9b6 (patch)
treed6b8034212e8a788e0892c4e76185a5b3f3e9408 /lib
parent894e44b63f9e7d1859dc47ef8640f1a781c7344c (diff)
downloadgo-4da3259d4feeb7045ca9cc9988bc2af10c2ae9b6.tar.gz
codereview: extra repo sanity check
Also work around Mercurial issue 3023. If anyone has local changes in their repo (due to patch queues or whatever) stop them from leaking into the main repository. R=golang-dev, r CC=golang-dev http://codereview.appspot.com/5144043
Diffstat (limited to 'lib')
-rw-r--r--lib/codereview/codereview.py54
1 files changed, 38 insertions, 16 deletions
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
index 761476371..22b08ad0d 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -38,7 +38,7 @@ For example, if change 123456 contains the files x.go and y.go,
"hg diff @123456" is equivalent to"hg diff x.go y.go".
'''
-from mercurial import cmdutil, commands, hg, util, error, match
+from mercurial import cmdutil, commands, hg, util, error, match, discovery
from mercurial.node import nullrev, hex, nullid, short
import os, re, time
import stat
@@ -71,9 +71,12 @@ except:
try:
from mercurial.discovery import findcommonincoming
+ from mercurial.discovery import findoutgoing
except:
def findcommonincoming(repo, remote):
return repo.findcommonincoming(remote)
+ def findoutgoing(repo, remote):
+ return repo.findoutgoing(remote)
# in Mercurial 1.9 the cmdutil.match and cmdutil.revpair moved to scmutil
if hgversion >= '1.9':
@@ -1738,6 +1741,11 @@ def submit(ui, repo, *pats, **opts):
return "dry run; not submitted"
set_status("pushing " + cl.name + " to remote server")
+
+ other = getremote(ui, repo, opts)
+ if findoutgoing(repo, other):
+ raise util.Abort("local repository corrupt or out-of-phase with remote: found outgoing changes")
+
m = match.exact(repo.root, repo.getcwd(), cl.files)
node = repo.commit(ustr(opts['message']), ustr(userline), opts.get('date'), m)
if not node:
@@ -1758,7 +1766,6 @@ def submit(ui, repo, *pats, **opts):
# push changes to remote.
# if it works, we're committed.
# if not, roll back
- other = getremote(ui, repo, opts)
r = repo.push(other, False, None)
if r == 0:
raise util.Abort("local repository out of date; must sync before submit")
@@ -3130,6 +3137,7 @@ class MercurialVCS(VersionControlSystem):
super(MercurialVCS, self).__init__(options)
self.ui = ui
self.repo = repo
+ self.status = None
# Absolute path to repository (we can be in a subdir)
self.repo_dir = os.path.normpath(repo.root)
# Compute the subdir
@@ -3188,6 +3196,33 @@ class MercurialVCS(VersionControlSystem):
unknown_files.append(fn)
return unknown_files
+ def get_hg_status(self, rev, path):
+ # We'd like to use 'hg status -C path', but that is buggy
+ # (see http://mercurial.selenic.com/bts/issue3023).
+ # Instead, run 'hg status -C' without a path
+ # and skim the output for the path we want.
+ if self.status is None:
+ if use_hg_shell:
+ out = RunShell(["hg", "status", "-C", "--rev", rev])
+ else:
+ fui = FakeMercurialUI()
+ ret = commands.status(fui, self.repo, *[], **{'rev': [rev], 'copies': True})
+ if ret:
+ raise util.Abort(ret)
+ out = fui.output
+ self.status = out.splitlines()
+ for i in range(len(self.status)):
+ # line is
+ # A path
+ # M path
+ # etc
+ line = self.status[i]
+ if line[2:] == path:
+ if i+1 < len(self.status) and self.status[i+1][:2] == ' ':
+ return self.status[i:i+2]
+ return self.status[i:i+1]
+ raise util.Abort("no status for " + path)
+
def GetBaseFile(self, filename):
set_status("inspecting " + filename)
# "hg status" and "hg cat" both take a path relative to the current subdir
@@ -3197,20 +3232,7 @@ class MercurialVCS(VersionControlSystem):
new_content = None
is_binary = False
oldrelpath = relpath = self._GetRelPath(filename)
- # "hg status -C" returns two lines for moved/copied files, one otherwise
- if use_hg_shell:
- out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
- else:
- fui = FakeMercurialUI()
- ret = commands.status(fui, self.repo, *[relpath], **{'rev': [self.base_rev], 'copies': True})
- if ret:
- raise util.Abort(ret)
- out = fui.output
- out = out.splitlines()
- # HACK: strip error message about missing file/directory if it isn't in
- # the working copy
- if out[0].startswith('%s: ' % relpath):
- out = out[1:]
+ out = self.get_hg_status(self.base_rev, relpath)
status, what = out[0].split(' ', 1)
if len(out) > 1 and status == "A" and what == relpath:
oldrelpath = out[1].strip()