--- a/hgext/convert/hg.py
+++ b/hgext/convert/hg.py
@@ -26,8 +26,8 @@ class convert_mercurial(converter_sink):
def putfile(self, f, e, data):
self.repo.wwrite(f, data, e)
- if self.repo.dirstate.state(f) == '?':
- self.repo.dirstate.update([f], "a")
+ if f not in self.repo.dirstate:
+ self.repo.dirstate.add(f)
def copyfile(self, source, dest):
self.repo.copy(source, dest)
--- a/hgext/fetch.py
+++ b/hgext/fetch.py
@@ -23,29 +23,29 @@ def fetch(ui, repo, source='default', **
if modheads == 0:
return 0
if modheads == 1:
- return hg.clean(repo, repo.changelog.tip(), wlock=wlock)
+ return hg.clean(repo, repo.changelog.tip())
newheads = repo.heads(parent)
newchildren = [n for n in repo.heads(parent) if n != parent]
newparent = parent
if newchildren:
newparent = newchildren[0]
- hg.clean(repo, newparent, wlock=wlock)
+ hg.clean(repo, newparent)
newheads = [n for n in repo.heads() if n != newparent]
err = False
if newheads:
ui.status(_('merging with new head %d:%s\n') %
(repo.changelog.rev(newheads[0]), short(newheads[0])))
- err = hg.merge(repo, newheads[0], remind=False, wlock=wlock)
+ err = hg.merge(repo, newheads[0], remind=False)
if not err and len(newheads) > 1:
ui.status(_('not merging with %d other new heads '
'(use "hg heads" and "hg merge" to merge them)') %
(len(newheads) - 1))
if not err:
- mod, add, rem = repo.status(wlock=wlock)[:3]
+ mod, add, rem = repo.status()[:3]
message = (cmdutil.logmessage(opts) or
(_('Automated merge with %s') % other.url()))
n = repo.commit(mod + add + rem, message,
- opts['user'], opts['date'], lock=lock, wlock=wlock,
+ opts['user'], opts['date'],
force_editor=opts.get('force_editor'))
ui.status(_('new changeset %d:%s merges remote changes '
'with local\n') % (repo.changelog.rev(n),
@@ -60,7 +60,7 @@ def fetch(ui, repo, source='default', **
raise util.Abort(_("fetch -r doesn't work for remote repositories yet"))
elif opts['rev']:
revs = [other.lookup(rev) for rev in opts['rev']]
- modheads = repo.pull(other, heads=revs, lock=lock)
+ modheads = repo.pull(other, heads=revs)
return postincoming(other, modheads)
parent, p2 = repo.dirstate.parents()
@@ -69,10 +69,11 @@ def fetch(ui, repo, source='default', **
'(use "hg update" to check out tip)'))
if p2 != nullid:
raise util.Abort(_('outstanding uncommitted merge'))
- wlock = repo.wlock()
- lock = repo.lock()
+ wlock = lock = None
try:
- mod, add, rem = repo.status(wlock=wlock)[:3]
+ wlock = repo.wlock()
+ lock = repo.lock()
+ mod, add, rem = repo.status()[:3]
if mod or add or rem:
raise util.Abort(_('outstanding uncommitted changes'))
if len(repo.heads()) > 1:
@@ -80,8 +81,7 @@ def fetch(ui, repo, source='default', **
'(use "hg heads" and "hg merge" to merge)'))
return pull()
finally:
- lock.release()
- wlock.release()
+ del lock, wlock
cmdtable = {
'fetch':
--- a/hgext/gpg.py
+++ b/hgext/gpg.py
@@ -240,7 +240,7 @@ def sign(ui, repo, *revs, **opts):
repo.wfile(".hgsigs", "ab").write(sigmessage)
- if repo.dirstate.state(".hgsigs") == '?':
+ if '.hgsigs' not in repo.dirstate:
repo.add([".hgsigs"])
if opts["no_commit"]:
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -323,10 +323,10 @@ class queue:
patch.diff(repo, node1, node2, fns, match=matchfn,
fp=fp, changes=changes, opts=self.diffopts())
- def mergeone(self, repo, mergeq, head, patch, rev, wlock):
+ def mergeone(self, repo, mergeq, head, patch, rev):
# first try just applying the patch
(err, n) = self.apply(repo, [ patch ], update_status=False,
- strict=True, merge=rev, wlock=wlock)
+ strict=True, merge=rev)
if err == 0:
return (err, n)
@@ -337,15 +337,14 @@ class queue:
self.ui.warn("patch didn't work out, merging %s\n" % patch)
# apply failed, strip away that rev and merge.
- hg.clean(repo, head, wlock=wlock)
- self.strip(repo, n, update=False, backup='strip', wlock=wlock)
+ hg.clean(repo, head)
+ self.strip(repo, n, update=False, backup='strip')
ctx = repo.changectx(rev)
- ret = hg.merge(repo, rev, wlock=wlock)
+ ret = hg.merge(repo, rev)
if ret:
raise util.Abort(_("update returned %d") % ret)
- n = repo.commit(None, ctx.description(), ctx.user(),
- force=1, wlock=wlock)
+ n = repo.commit(None, ctx.description(), ctx.user(), force=1)
if n == None:
raise util.Abort(_("repo commit failed"))
try:
@@ -381,7 +380,7 @@ class queue:
return pp[1]
return pp[0]
- def mergepatch(self, repo, mergeq, series, wlock):
+ def mergepatch(self, repo, mergeq, series):
if len(self.applied) == 0:
# each of the patches merged in will have two parents. This
# can confuse the qrefresh, qdiff, and strip code because it
@@ -390,8 +389,7 @@ class queue:
# the first patch in the queue is never a merge patch
#
pname = ".hg.patches.merge.marker"
- n = repo.commit(None, '[mq]: merge marker', user=None, force=1,
- wlock=wlock)
+ n = repo.commit(None, '[mq]: merge marker', user=None, force=1)
self.removeundo(repo)
self.applied.append(statusentry(revlog.hex(n), pname))
self.applied_dirty = 1
@@ -412,7 +410,7 @@ class queue:
self.ui.warn("patch %s is not applied\n" % patch)
return (1, None)
rev = revlog.bin(info[1])
- (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock)
+ (err, head) = self.mergeone(repo, mergeq, head, patch, rev)
if head:
self.applied.append(statusentry(revlog.hex(head), patch))
self.applied_dirty = 1
@@ -437,30 +435,30 @@ class queue:
return (True, files, fuzz)
def apply(self, repo, series, list=False, update_status=True,
- strict=False, patchdir=None, merge=None, wlock=None,
- all_files={}):
- if not wlock:
- wlock = repo.wlock()
- lock = repo.lock()
- tr = repo.transaction()
+ strict=False, patchdir=None, merge=None, all_files={}):
+ wlock = lock = tr = None
try:
- ret = self._apply(tr, repo, series, list, update_status,
- strict, patchdir, merge, wlock,
- lock=lock, all_files=all_files)
- tr.close()
- self.save_dirty()
- return ret
- except:
+ wlock = repo.wlock()
+ lock = repo.lock()
+ tr = repo.transaction()
try:
- tr.abort()
- finally:
- repo.invalidate()
- repo.dirstate.invalidate()
- raise
+ ret = self._apply(tr, repo, series, list, update_status,
+ strict, patchdir, merge, all_files=all_files)
+ tr.close()
+ self.save_dirty()
+ return ret
+ except:
+ try:
+ tr.abort()
+ finally:
+ repo.invalidate()
+ repo.dirstate.invalidate()
+ raise
+ finally:
+ del lock, wlock, tr
def _apply(self, tr, repo, series, list=False, update_status=True,
- strict=False, patchdir=None, merge=None, wlock=None,
- lock=None, all_files={}):
+ strict=False, patchdir=None, merge=None, all_files={}):
# TODO unify with commands.py
if not patchdir:
patchdir = self.path
@@ -497,17 +495,18 @@ class queue:
removed = []
merged = []
for f in files:
- if os.path.exists(repo.dirstate.wjoin(f)):
+ if os.path.exists(repo.wjoin(f)):
merged.append(f)
else:
removed.append(f)
- repo.dirstate.update(repo.dirstate.filterfiles(removed), 'r')
- repo.dirstate.update(repo.dirstate.filterfiles(merged), 'm')
+ for f in removed:
+ repo.dirstate.remove(f)
+ for f in merged:
+ repo.dirstate.merge(f)
p1, p2 = repo.dirstate.parents()
repo.dirstate.setparents(p1, merge)
- files = patch.updatedir(self.ui, repo, files, wlock=wlock)
- n = repo.commit(files, message, user, date, force=1, lock=lock,
- wlock=wlock)
+ files = patch.updatedir(self.ui, repo, files)
+ n = repo.commit(files, message, user, date, force=1)
if n == None:
raise util.Abort(_("repo commit failed"))
@@ -614,44 +613,49 @@ class queue:
commitfiles = m + a + r
self.check_toppatch(repo)
wlock = repo.wlock()
- insert = self.full_series_end()
- if msg:
- n = repo.commit(commitfiles, msg, force=True, wlock=wlock)
- else:
- n = repo.commit(commitfiles,
- "[mq]: %s" % patch, force=True, wlock=wlock)
- if n == None:
- raise util.Abort(_("repo commit failed"))
- self.full_series[insert:insert] = [patch]
- self.applied.append(statusentry(revlog.hex(n), patch))
- self.parse_series()
- self.series_dirty = 1
- self.applied_dirty = 1
- p = self.opener(patch, "w")
- if msg:
- msg = msg + "\n"
- p.write(msg)
- p.close()
- wlock = None
- r = self.qrepo()
- if r: r.add([patch])
- if commitfiles:
- self.refresh(repo, short=True)
- self.removeundo(repo)
+ try:
+ insert = self.full_series_end()
+ if msg:
+ n = repo.commit(commitfiles, msg, force=True)
+ else:
+ n = repo.commit(commitfiles, "[mq]: %s" % patch, force=True)
+ if n == None:
+ raise util.Abort(_("repo commit failed"))
+ self.full_series[insert:insert] = [patch]
+ self.applied.append(statusentry(revlog.hex(n), patch))
+ self.parse_series()
+ self.series_dirty = 1
+ self.applied_dirty = 1
+ p = self.opener(patch, "w")
+ if msg:
+ msg = msg + "\n"
+ p.write(msg)
+ p.close()
+ wlock = None
+ r = self.qrepo()
+ if r: r.add([patch])
+ if commitfiles:
+ self.refresh(repo, short=True)
+ self.removeundo(repo)
+ finally:
+ del wlock
- def strip(self, repo, rev, update=True, backup="all", wlock=None):
- if not wlock:
+ def strip(self, repo, rev, update=True, backup="all"):
+ wlock = lock = None
+ try:
wlock = repo.wlock()
- lock = repo.lock()
+ lock = repo.lock()
- if update:
- self.check_localchanges(repo, refresh=False)
- urev = self.qparents(repo, rev)
- hg.clean(repo, urev, wlock=wlock)
- repo.dirstate.write()
+ if update:
+ self.check_localchanges(repo, refresh=False)
+ urev = self.qparents(repo, rev)
+ hg.clean(repo, urev)
+ repo.dirstate.write()
- self.removeundo(repo)
- repair.strip(self.ui, repo, rev, backup)
+ self.removeundo(repo)
+ repair.strip(self.ui, repo, rev, backup)
+ finally:
+ del lock, wlock
def isapplied(self, patch):
"""returns (index, rev, patch)"""
@@ -735,157 +739,161 @@ class queue:
raise util.Abort(_("patch %s not in series") % patch)
def push(self, repo, patch=None, force=False, list=False,
- mergeq=None, wlock=None):
- if not wlock:
- wlock = repo.wlock()
- patch = self.lookup(patch)
- # Suppose our series file is: A B C and the current 'top' patch is B.
- # qpush C should be performed (moving forward)
- # qpush B is a NOP (no change)
- # qpush A is an error (can't go backwards with qpush)
- if patch:
- info = self.isapplied(patch)
- if info:
- if info[0] < len(self.applied) - 1:
- raise util.Abort(_("cannot push to a previous patch: %s") %
- patch)
- if info[0] < len(self.series) - 1:
- self.ui.warn(_('qpush: %s is already at the top\n') % patch)
- else:
- self.ui.warn(_('all patches are currently applied\n'))
- return
+ mergeq=None):
+ wlock = repo.wlock()
+ try:
+ patch = self.lookup(patch)
+ # Suppose our series file is: A B C and the current 'top'
+ # patch is B. qpush C should be performed (moving forward)
+ # qpush B is a NOP (no change) qpush A is an error (can't
+ # go backwards with qpush)
+ if patch:
+ info = self.isapplied(patch)
+ if info:
+ if info[0] < len(self.applied) - 1:
+ raise util.Abort(
+ _("cannot push to a previous patch: %s") % patch)
+ if info[0] < len(self.series) - 1:
+ self.ui.warn(
+ _('qpush: %s is already at the top\n') % patch)
+ else:
+ self.ui.warn(_('all patches are currently applied\n'))
+ return
- # Following the above example, starting at 'top' of B:
- # qpush should be performed (pushes C), but a subsequent qpush without
- # an argument is an error (nothing to apply). This allows a loop
- # of "...while hg qpush..." to work as it detects an error when done
- if self.series_end() == len(self.series):
- self.ui.warn(_('patch series already fully applied\n'))
- return 1
- if not force:
- self.check_localchanges(repo)
+ # Following the above example, starting at 'top' of B:
+ # qpush should be performed (pushes C), but a subsequent
+ # qpush without an argument is an error (nothing to
+ # apply). This allows a loop of "...while hg qpush..." to
+ # work as it detects an error when done
+ if self.series_end() == len(self.series):
+ self.ui.warn(_('patch series already fully applied\n'))
+ return 1
+ if not force:
+ self.check_localchanges(repo)
- self.applied_dirty = 1;
- start = self.series_end()
- if start > 0:
- self.check_toppatch(repo)
- if not patch:
- patch = self.series[start]
- end = start + 1
- else:
- end = self.series.index(patch, start) + 1
- s = self.series[start:end]
- all_files = {}
- try:
- if mergeq:
- ret = self.mergepatch(repo, mergeq, s, wlock)
+ self.applied_dirty = 1;
+ start = self.series_end()
+ if start > 0:
+ self.check_toppatch(repo)
+ if not patch:
+ patch = self.series[start]
+ end = start + 1
else:
- ret = self.apply(repo, s, list, wlock=wlock,
- all_files=all_files)
- except:
- self.ui.warn(_('cleaning up working directory...'))
- node = repo.dirstate.parents()[0]
- hg.revert(repo, node, None, wlock)
- unknown = repo.status(wlock=wlock)[4]
- # only remove unknown files that we know we touched or
- # created while patching
- for f in unknown:
- if f in all_files:
- util.unlink(repo.wjoin(f))
- self.ui.warn(_('done\n'))
- raise
- top = self.applied[-1].name
- if ret[0]:
- self.ui.write("Errors during apply, please fix and refresh %s\n" %
- top)
- else:
- self.ui.write("Now at: %s\n" % top)
- return ret[0]
+ end = self.series.index(patch, start) + 1
+ s = self.series[start:end]
+ all_files = {}
+ try:
+ if mergeq:
+ ret = self.mergepatch(repo, mergeq, s)
+ else:
+ ret = self.apply(repo, s, list, all_files=all_files)
+ except:
+ self.ui.warn(_('cleaning up working directory...'))
+ node = repo.dirstate.parents()[0]
+ hg.revert(repo, node, None)
+ unknown = repo.status()[4]
+ # only remove unknown files that we know we touched or
+ # created while patching
+ for f in unknown:
+ if f in all_files:
+ util.unlink(repo.wjoin(f))
+ self.ui.warn(_('done\n'))
+ raise
+ top = self.applied[-1].name
+ if ret[0]:
+ self.ui.write(
+ "Errors during apply, please fix and refresh %s\n" % top)
+ else:
+ self.ui.write("Now at: %s\n" % top)
+ return ret[0]
+ finally:
+ del wlock
- def pop(self, repo, patch=None, force=False, update=True, all=False,
- wlock=None):
+ def pop(self, repo, patch=None, force=False, update=True, all=False):
def getfile(f, rev):
t = repo.file(f).read(rev)
repo.wfile(f, "w").write(t)
- if not wlock:
- wlock = repo.wlock()
- if patch:
- # index, rev, patch
- info = self.isapplied(patch)
- if not info:
- patch = self.lookup(patch)
- info = self.isapplied(patch)
- if not info:
- raise util.Abort(_("patch %s is not applied") % patch)
+ wlock = repo.wlock()
+ try:
+ if patch:
+ # index, rev, patch
+ info = self.isapplied(patch)
+ if not info:
+ patch = self.lookup(patch)
+ info = self.isapplied(patch)
+ if not info:
+ raise util.Abort(_("patch %s is not applied") % patch)
- if len(self.applied) == 0:
- # Allow qpop -a to work repeatedly,
- # but not qpop without an argument
- self.ui.warn(_("no patches applied\n"))
- return not all
+ if len(self.applied) == 0:
+ # Allow qpop -a to work repeatedly,
+ # but not qpop without an argument
+ self.ui.warn(_("no patches applied\n"))
+ return not all
- if not update:
- parents = repo.dirstate.parents()
- rr = [ revlog.bin(x.rev) for x in self.applied ]
- for p in parents:
- if p in rr:
- self.ui.warn("qpop: forcing dirstate update\n")
- update = True
+ if not update:
+ parents = repo.dirstate.parents()
+ rr = [ revlog.bin(x.rev) for x in self.applied ]
+ for p in parents:
+ if p in rr:
+ self.ui.warn("qpop: forcing dirstate update\n")
+ update = True
- if not force and update:
- self.check_localchanges(repo)
+ if not force and update:
+ self.check_localchanges(repo)
- self.applied_dirty = 1;
- end = len(self.applied)
- if not patch:
- if all:
- popi = 0
+ self.applied_dirty = 1;
+ end = len(self.applied)
+ if not patch:
+ if all:
+ popi = 0
+ else:
+ popi = len(self.applied) - 1
else:
- popi = len(self.applied) - 1
- else:
- popi = info[0] + 1
- if popi >= end:
- self.ui.warn("qpop: %s is already at the top\n" % patch)
- return
- info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name]
+ popi = info[0] + 1
+ if popi >= end:
+ self.ui.warn("qpop: %s is already at the top\n" % patch)
+ return
+ info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name]
- start = info[0]
- rev = revlog.bin(info[1])
+ start = info[0]
+ rev = revlog.bin(info[1])
- # we know there are no local changes, so we can make a simplified
- # form of hg.update.
- if update:
- top = self.check_toppatch(repo)
- qp = self.qparents(repo, rev)
- changes = repo.changelog.read(qp)
- mmap = repo.manifest.read(changes[0])
- m, a, r, d, u = repo.status(qp, top)[:5]
- if d:
- raise util.Abort("deletions found between repo revs")
- for f in m:
- getfile(f, mmap[f])
- for f in r:
- getfile(f, mmap[f])
- util.set_exec(repo.wjoin(f), mmap.execf(f))
- repo.dirstate.update(m + r, 'n')
- for f in a:
- try:
- os.unlink(repo.wjoin(f))
- except OSError, e:
- if e.errno != errno.ENOENT:
- raise
- try: os.removedirs(os.path.dirname(repo.wjoin(f)))
- except: pass
- if a:
- repo.dirstate.forget(a)
- repo.dirstate.setparents(qp, revlog.nullid)
- self.strip(repo, rev, update=False, backup='strip', wlock=wlock)
- del self.applied[start:end]
- if len(self.applied):
- self.ui.write("Now at: %s\n" % self.applied[-1].name)
- else:
- self.ui.write("Patch queue now empty\n")
+ # we know there are no local changes, so we can make a simplified
+ # form of hg.update.
+ if update:
+ top = self.check_toppatch(repo)
+ qp = self.qparents(repo, rev)
+ changes = repo.changelog.read(qp)
+ mmap = repo.manifest.read(changes[0])
+ m, a, r, d, u = repo.status(qp, top)[:5]
+ if d:
+ raise util.Abort("deletions found between repo revs")
+ for f in m:
+ getfile(f, mmap[f])
+ for f in r:
+ getfile(f, mmap[f])
+ util.set_exec(repo.wjoin(f), mmap.execf(f))
+ for f in m + r:
+ repo.dirstate.normal(f)
+ for f in a:
+ try:
+ os.unlink(repo.wjoin(f))
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ try: os.removedirs(os.path.dirname(repo.wjoin(f)))
+ except: pass
+ repo.dirstate.forget(f)
+ repo.dirstate.setparents(qp, revlog.nullid)
+ self.strip(repo, rev, update=False, backup='strip')
+ del self.applied[start:end]
+ if len(self.applied):
+ self.ui.write("Now at: %s\n" % self.applied[-1].name)
+ else:
+ self.ui.write("Patch queue now empty\n")
+ finally:
+ del wlock
def diff(self, repo, pats, opts):
top = self.check_toppatch(repo)
@@ -902,175 +910,184 @@ class queue:
self.ui.write("No patches applied\n")
return 1
wlock = repo.wlock()
- self.check_toppatch(repo)
- (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
- top = revlog.bin(top)
- cparents = repo.changelog.parents(top)
- patchparent = self.qparents(repo, top)
- message, comments, user, date, patchfound = self.readheaders(patchfn)
-
- patchf = self.opener(patchfn, 'r+')
-
- # if the patch was a git patch, refresh it as a git patch
- for line in patchf:
- if line.startswith('diff --git'):
- self.diffopts().git = True
- break
- patchf.seek(0)
- patchf.truncate()
+ try:
+ self.check_toppatch(repo)
+ (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
+ top = revlog.bin(top)
+ cparents = repo.changelog.parents(top)
+ patchparent = self.qparents(repo, top)
+ message, comments, user, date, patchfound = self.readheaders(patchfn)
- msg = opts.get('msg', '').rstrip()
- if msg:
- if comments:
- # Remove existing message.
- ci = 0
- subj = None
- for mi in xrange(len(message)):
- if comments[ci].lower().startswith('subject: '):
- subj = comments[ci][9:]
- while message[mi] != comments[ci] and message[mi] != subj:
- ci += 1
- del comments[ci]
- comments.append(msg)
- if comments:
- comments = "\n".join(comments) + '\n\n'
- patchf.write(comments)
+ patchf = self.opener(patchfn, 'r+')
+
+ # if the patch was a git patch, refresh it as a git patch
+ for line in patchf:
+ if line.startswith('diff --git'):
+ self.diffopts().git = True
+ break
+ patchf.seek(0)
+ patchf.truncate()
- if opts.get('git'):
- self.diffopts().git = True
- fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
- tip = repo.changelog.tip()
- if top == tip:
- # if the top of our patch queue is also the tip, there is an
- # optimization here. We update the dirstate in place and strip
- # off the tip commit. Then just commit the current directory
- # tree. We can also send repo.commit the list of files
- # changed to speed up the diff
- #
- # in short mode, we only diff the files included in the
- # patch already
- #
- # this should really read:
- # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5]
- # but we do it backwards to take advantage of manifest/chlog
- # caching against the next repo.status call
- #
- mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5]
- changes = repo.changelog.read(tip)
- man = repo.manifest.read(changes[0])
- aaa = aa[:]
- if opts.get('short'):
- filelist = mm + aa + dd
- match = dict.fromkeys(filelist).__contains__
- else:
- filelist = None
- match = util.always
- m, a, r, d, u = repo.status(files=filelist, match=match)[:5]
+ msg = opts.get('msg', '').rstrip()
+ if msg:
+ if comments:
+ # Remove existing message.
+ ci = 0
+ subj = None
+ for mi in xrange(len(message)):
+ if comments[ci].lower().startswith('subject: '):
+ subj = comments[ci][9:]
+ while message[mi] != comments[ci] and message[mi] != subj:
+ ci += 1
+ del comments[ci]
+ comments.append(msg)
+ if comments:
+ comments = "\n".join(comments) + '\n\n'
+ patchf.write(comments)
- # we might end up with files that were added between tip and
- # the dirstate parent, but then changed in the local dirstate.
- # in this case, we want them to only show up in the added section
- for x in m:
- if x not in aa:
- mm.append(x)
- # we might end up with files added by the local dirstate that
- # were deleted by the patch. In this case, they should only
- # show up in the changed section.
- for x in a:
- if x in dd:
- del dd[dd.index(x)]
- mm.append(x)
+ if opts.get('git'):
+ self.diffopts().git = True
+ fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
+ tip = repo.changelog.tip()
+ if top == tip:
+ # if the top of our patch queue is also the tip, there is an
+ # optimization here. We update the dirstate in place and strip
+ # off the tip commit. Then just commit the current directory
+ # tree. We can also send repo.commit the list of files
+ # changed to speed up the diff
+ #
+ # in short mode, we only diff the files included in the
+ # patch already
+ #
+ # this should really read:
+ # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5]
+ # but we do it backwards to take advantage of manifest/chlog
+ # caching against the next repo.status call
+ #
+ mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5]
+ changes = repo.changelog.read(tip)
+ man = repo.manifest.read(changes[0])
+ aaa = aa[:]
+ if opts.get('short'):
+ filelist = mm + aa + dd
+ match = dict.fromkeys(filelist).__contains__
else:
- aa.append(x)
- # make sure any files deleted in the local dirstate
- # are not in the add or change column of the patch
- forget = []
- for x in d + r:
- if x in aa:
- del aa[aa.index(x)]
- forget.append(x)
- continue
- elif x in mm:
- del mm[mm.index(x)]
- dd.append(x)
+ filelist = None
+ match = util.always
+ m, a, r, d, u = repo.status(files=filelist, match=match)[:5]
- m = util.unique(mm)
- r = util.unique(dd)
- a = util.unique(aa)
- c = [filter(matchfn, l) for l in (m, a, r, [], u)]
- filelist = util.unique(c[0] + c[1] + c[2])
- patch.diff(repo, patchparent, files=filelist, match=matchfn,
- fp=patchf, changes=c, opts=self.diffopts())
- patchf.close()
+ # we might end up with files that were added between
+ # tip and the dirstate parent, but then changed in the
+ # local dirstate. in this case, we want them to only
+ # show up in the added section
+ for x in m:
+ if x not in aa:
+ mm.append(x)
+ # we might end up with files added by the local dirstate that
+ # were deleted by the patch. In this case, they should only
+ # show up in the changed section.
+ for x in a:
+ if x in dd:
+ del dd[dd.index(x)]
+ mm.append(x)
+ else:
+ aa.append(x)
+ # make sure any files deleted in the local dirstate
+ # are not in the add or change column of the patch
+ forget = []
+ for x in d + r:
+ if x in aa:
+ del aa[aa.index(x)]
+ forget.append(x)
+ continue
+ elif x in mm:
+ del mm[mm.index(x)]
+ dd.append(x)
+
+ m = util.unique(mm)
+ r = util.unique(dd)
+ a = util.unique(aa)
+ c = [filter(matchfn, l) for l in (m, a, r, [], u)]
+ filelist = util.unique(c[0] + c[1] + c[2])
+ patch.diff(repo, patchparent, files=filelist, match=matchfn,
+ fp=patchf, changes=c, opts=self.diffopts())
+ patchf.close()
- repo.dirstate.setparents(*cparents)
- copies = {}
- for dst in a:
- src = repo.dirstate.copied(dst)
- if src is None:
- continue
- copies.setdefault(src, []).append(dst)
- repo.dirstate.update(a, 'a')
- # remember the copies between patchparent and tip
- # this may be slow, so don't do it if we're not tracking copies
- if self.diffopts().git:
- for dst in aaa:
- f = repo.file(dst)
- src = f.renamed(man[dst])
- if src:
- copies[src[0]] = copies.get(dst, [])
- if dst in a:
- copies[src[0]].append(dst)
- # we can't copy a file created by the patch itself
- if dst in copies:
- del copies[dst]
- for src, dsts in copies.iteritems():
- for dst in dsts:
- repo.dirstate.copy(src, dst)
- repo.dirstate.update(r, 'r')
- # if the patch excludes a modified file, mark that file with mtime=0
- # so status can see it.
- mm = []
- for i in xrange(len(m)-1, -1, -1):
- if not matchfn(m[i]):
- mm.append(m[i])
- del m[i]
- repo.dirstate.update(m, 'n')
- repo.dirstate.update(mm, 'n', st_mtime=-1, st_size=-1)
- repo.dirstate.forget(forget)
+ repo.dirstate.setparents(*cparents)
+ copies = {}
+ for dst in a:
+ src = repo.dirstate.copied(dst)
+ if src is None:
+ continue
+ copies.setdefault(src, []).append(dst)
+ repo.dirstate.add(dst)
+ # remember the copies between patchparent and tip
+ # this may be slow, so don't do it if we're not tracking copies
+ if self.diffopts().git:
+ for dst in aaa:
+ f = repo.file(dst)
+ src = f.renamed(man[dst])
+ if src:
+ copies[src[0]] = copies.get(dst, [])
+ if dst in a:
+ copies[src[0]].append(dst)
+ # we can't copy a file created by the patch itself
+ if dst in copies:
+ del copies[dst]
+ for src, dsts in copies.iteritems():
+ for dst in dsts:
+ repo.dirstate.copy(src, dst)
+ for f in r:
+ repo.dirstate.remove(f)
+ # if the patch excludes a modified file, mark that
+ # file with mtime=0 so status can see it.
+ mm = []
+ for i in xrange(len(m)-1, -1, -1):
+ if not matchfn(m[i]):
+ mm.append(m[i])
+ del m[i]
+ for f in m:
+ repo.dirstate.normal(f)
+ for f in mm:
+ repo.dirstate.normaldirty(f)
+ for f in forget:
+ repo.dirstate.forget(f)
- if not msg:
- if not message:
- message = "[mq]: %s\n" % patchfn
+ if not msg:
+ if not message:
+ message = "[mq]: %s\n" % patchfn
+ else:
+ message = "\n".join(message)
else:
- message = "\n".join(message)
- else:
- message = msg
+ message = msg
- self.strip(repo, top, update=False, backup='strip', wlock=wlock)
- n = repo.commit(filelist, message, changes[1], match=matchfn,
- force=1, wlock=wlock)
- self.applied[-1] = statusentry(revlog.hex(n), patchfn)
- self.applied_dirty = 1
- self.removeundo(repo)
- else:
- self.printdiff(repo, patchparent, fp=patchf)
- patchf.close()
- added = repo.status()[1]
- for a in added:
- f = repo.wjoin(a)
- try:
- os.unlink(f)
- except OSError, e:
- if e.errno != errno.ENOENT:
- raise
- try: os.removedirs(os.path.dirname(f))
- except: pass
- # forget the file copies in the dirstate
- # push should readd the files later on
- repo.dirstate.forget(added)
- self.pop(repo, force=True, wlock=wlock)
- self.push(repo, force=True, wlock=wlock)
+ self.strip(repo, top, update=False,
+ backup='strip')
+ n = repo.commit(filelist, message, changes[1], match=matchfn,
+ force=1)
+ self.applied[-1] = statusentry(revlog.hex(n), patchfn)
+ self.applied_dirty = 1
+ self.removeundo(repo)
+ else:
+ self.printdiff(repo, patchparent, fp=patchf)
+ patchf.close()
+ added = repo.status()[1]
+ for a in added:
+ f = repo.wjoin(a)
+ try:
+ os.unlink(f)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ try: os.removedirs(os.path.dirname(f))
+ except: pass
+ # forget the file copies in the dirstate
+ # push should readd the files later on
+ repo.dirstate.forget(a)
+ self.pop(repo, force=True)
+ self.push(repo, force=True)
+ finally:
+ del wlock
def init(self, repo, create=False):
if not create and os.path.isdir(self.path):
@@ -1866,10 +1883,13 @@ def rename(ui, repo, patch, name=None, *
r = q.qrepo()
if r:
wlock = r.wlock()
- if r.dirstate.state(name) == 'r':
- r.undelete([name], wlock)
- r.copy(patch, name, wlock)
- r.remove([patch], False, wlock)
+ try:
+ if r.dirstate[name] == 'r':
+ r.undelete([name])
+ r.copy(patch, name)
+ r.remove([patch], False)
+ finally:
+ del wlock
q.save_dirty()
--- a/hgext/transplant.py
+++ b/hgext/transplant.py
@@ -96,9 +96,10 @@ class transplanter:
diffopts = patch.diffopts(self.ui, opts)
diffopts.git = True
- wlock = repo.wlock()
- lock = repo.lock()
+ lock = wlock = None
try:
+ wlock = repo.wlock()
+ lock = repo.lock()
for rev in revs:
node = revmap[rev]
revstr = '%s:%s' % (rev, revlog.short(node))
@@ -118,9 +119,8 @@ class transplanter:
continue
if pulls:
if source != repo:
- repo.pull(source, heads=pulls, lock=lock)
- merge.update(repo, pulls[-1], False, False, None,
- wlock=wlock)
+ repo.pull(source, heads=pulls)
+ merge.update(repo, pulls[-1], False, False, None)
p1, p2 = repo.dirstate.parents()
pulls = []
@@ -131,7 +131,7 @@ class transplanter:
# fail.
domerge = True
if not hasnode(repo, node):
- repo.pull(source, heads=[node], lock=lock)
+ repo.pull(source, heads=[node])
if parents[1] != revlog.nullid:
self.ui.note(_('skipping merge changeset %s:%s\n')
@@ -146,11 +146,11 @@ class transplanter:
del revmap[rev]
if patchfile or domerge:
try:
- n = self.applyone(repo, node, source.changelog.read(node),
+ n = self.applyone(repo, node,
+ source.changelog.read(node),
patchfile, merge=domerge,
log=opts.get('log'),
- filter=opts.get('filter'),
- lock=lock, wlock=wlock)
+ filter=opts.get('filter'))
if n and domerge:
self.ui.status(_('%s merged at %s\n') % (revstr,
revlog.short(n)))
@@ -161,11 +161,12 @@ class transplanter:
if patchfile:
os.unlink(patchfile)
if pulls:
- repo.pull(source, heads=pulls, lock=lock)
- merge.update(repo, pulls[-1], False, False, None, wlock=wlock)
+ repo.pull(source, heads=pulls)
+ merge.update(repo, pulls[-1], False, False, None)
finally:
self.saveseries(revmap, merges)
self.transplants.write()
+ del lock, wlock
def filter(self, filter, changelog, patchfile):
'''arbitrarily rewrite changeset before applying it'''
@@ -193,7 +194,7 @@ class transplanter:
return (user, date, msg)
def applyone(self, repo, node, cl, patchfile, merge=False, log=False,
- filter=None, lock=None, wlock=None):
+ filter=None):
'''apply the patch in patchfile to the repository as a transplant'''
(manifest, user, (time, timezone), files, message) = cl[:5]
date = "%d %d" % (time, timezone)
@@ -219,7 +220,7 @@ class transplanter:
self.ui.warn(_('%s: empty changeset') % revlog.hex(node))
return None
finally:
- files = patch.updatedir(self.ui, repo, files, wlock=wlock)
+ files = patch.updatedir(self.ui, repo, files)
except Exception, inst:
if filter:
os.unlink(patchfile)
@@ -237,8 +238,7 @@ class transplanter:
p1, p2 = repo.dirstate.parents()
repo.dirstate.setparents(p1, node)
- n = repo.commit(files, message, user, date, lock=lock, wlock=wlock,
- extra=extra)
+ n = repo.commit(files, message, user, date, extra=extra)
if not merge:
self.transplants.set(n, node)
@@ -272,20 +272,24 @@ class transplanter:
extra = {'transplant_source': node}
wlock = repo.wlock()
- p1, p2 = repo.dirstate.parents()
- if p1 != parents[0]:
- raise util.Abort(_('working dir not at transplant parent %s') %
- revlog.hex(parents[0]))
- if merge:
- repo.dirstate.setparents(p1, parents[1])
- n = repo.commit(None, message, user, date, wlock=wlock, extra=extra)
- if not n:
- raise util.Abort(_('commit failed'))
- if not merge:
- self.transplants.set(n, node)
- self.unlog()
+ try:
+ p1, p2 = repo.dirstate.parents()
+ if p1 != parents[0]:
+ raise util.Abort(
+ _('working dir not at transplant parent %s') %
+ revlog.hex(parents[0]))
+ if merge:
+ repo.dirstate.setparents(p1, parents[1])
+ n = repo.commit(None, message, user, date, extra=extra)
+ if not n:
+ raise util.Abort(_('commit failed'))
+ if not merge:
+ self.transplants.set(n, node)
+ self.unlog()
- return n, node
+ return n, node
+ finally:
+ del wlock
def readseries(self):
nodes = []
--- a/mercurial/bundlerepo.py
+++ b/mercurial/bundlerepo.py
@@ -61,7 +61,7 @@ class bundlerevlog(revlog.revlog):
if self.version == revlog.REVLOGV0:
e = (start, size, None, link, p1, p2, node)
else:
- e = (self.offset_type(start, 0), size, -1, None, link,
+ e = (revlog.offset_type(start, 0), size, -1, None, link,
self.rev(p1), self.rev(p2), node)
self.basemap[n] = prev
self.index.append(e)
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -628,8 +628,7 @@ def findrenames(repo, added=None, remove
if bestname:
yield bestname, a, bestscore
-def addremove(repo, pats=[], opts={}, wlock=None, dry_run=None,
- similarity=None):
+def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
if dry_run is None:
dry_run = opts.get('dry_run')
if similarity is None:
@@ -638,19 +637,19 @@ def addremove(repo, pats=[], opts={}, wl
mapping = {}
for src, abs, rel, exact in walk(repo, pats, opts):
target = repo.wjoin(abs)
- if src == 'f' and repo.dirstate.state(abs) == '?':
+ if src == 'f' and abs not in repo.dirstate:
add.append(abs)
mapping[abs] = rel, exact
if repo.ui.verbose or not exact:
repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
- if repo.dirstate.state(abs) != 'r' and not util.lexists(target):
+ if repo.dirstate[abs] != 'r' and not util.lexists(target):
remove.append(abs)
mapping[abs] = rel, exact
if repo.ui.verbose or not exact:
repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
if not dry_run:
- repo.add(add, wlock=wlock)
- repo.remove(remove, wlock=wlock)
+ repo.add(add)
+ repo.remove(remove)
if similarity > 0:
for old, new, score in findrenames(repo, add, remove, similarity):
oldrel, oldexact = mapping[old]
@@ -660,7 +659,7 @@ def addremove(repo, pats=[], opts={}, wl
'(%d%% similar)\n') %
(oldrel, newrel, score * 100))
if not dry_run:
- repo.copy(old, new, wlock=wlock)
+ repo.copy(old, new)
def service(opts, parentfn=None, initfn=None, runfn=None):
'''Run a command as a service.'''
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -33,7 +33,7 @@ def add(ui, repo, *pats, **opts):
if ui.verbose:
ui.status(_('adding %s\n') % rel)
names.append(abs)
- elif repo.dirstate.state(abs) == '?':
+ elif abs not in repo.dirstate:
ui.status(_('adding %s\n') % rel)
names.append(abs)
if not opts.get('dry_run'):
@@ -456,7 +456,7 @@ def commit(ui, repo, *pats, **opts):
elif not (stat.S_ISREG(mode) or stat.S_ISLNK(mode)):
raise util.Abort(_("can't commit %s: "
"unsupported file type!") % rf)
- elif repo.dirstate.state(f) == '?':
+ elif f not in repo.dirstate:
raise util.Abort(_("file %s not tracked!") % rf)
else:
files = []
@@ -466,7 +466,7 @@ def commit(ui, repo, *pats, **opts):
except ValueError, inst:
raise util.Abort(str(inst))
-def docopy(ui, repo, pats, opts, wlock):
+def docopy(ui, repo, pats, opts):
# called with the repo lock held
#
# hgsep => pathname that uses "/" to separate directories
@@ -482,7 +482,7 @@ def docopy(ui, repo, pats, opts, wlock):
def okaytocopy(abs, rel, exact):
reasons = {'?': _('is not managed'),
'r': _('has been marked for remove')}
- state = repo.dirstate.state(abs)
+ state = repo.dirstate[abs]
reason = reasons.get(state)
if reason:
if exact:
@@ -510,7 +510,7 @@ def docopy(ui, repo, pats, opts, wlock):
repo.pathto(prevsrc, cwd)))
return
if (not opts['after'] and os.path.exists(target) or
- opts['after'] and repo.dirstate.state(abstarget) not in '?ar'):
+ opts['after'] and repo.dirstate[abstarget] in 'mn'):
if not opts['force']:
ui.warn(_('%s: not overwriting - file exists\n') %
reltarget)
@@ -525,16 +525,16 @@ def docopy(ui, repo, pats, opts, wlock):
if not os.path.isdir(targetdir) and not opts.get('dry_run'):
os.makedirs(targetdir)
try:
- restore = repo.dirstate.state(abstarget) == 'r'
+ restore = repo.dirstate[abstarget] == 'r'
if restore and not opts.get('dry_run'):
- repo.undelete([abstarget], wlock)
+ repo.undelete([abstarget])
try:
if not opts.get('dry_run'):
util.copyfile(src, target)
restore = False
finally:
if restore:
- repo.remove([abstarget], wlock=wlock)
+ repo.remove([abstarget])
except IOError, inst:
if inst.errno == errno.ENOENT:
ui.warn(_('%s: deleted in working copy\n') % relsrc)
@@ -547,15 +547,15 @@ def docopy(ui, repo, pats, opts, wlock):
ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
targets[abstarget] = abssrc
if abstarget != origsrc:
- if repo.dirstate.state(origsrc) == 'a':
+ if repo.dirstate[origsrc] == 'a':
if not ui.quiet:
ui.warn(_("%s has not been committed yet, so no copy "
"data will be stored for %s.\n")
% (repo.pathto(origsrc, cwd), reltarget))
if abstarget not in repo.dirstate and not opts.get('dry_run'):
- repo.add([abstarget], wlock)
+ repo.add([abstarget])
elif not opts.get('dry_run'):
- repo.copy(origsrc, abstarget, wlock)
+ repo.copy(origsrc, abstarget)
copied.append((abssrc, relsrc, exact))
# pat: ossep
@@ -675,8 +675,11 @@ def copy(ui, repo, *pats, **opts):
This command takes effect in the next commit. To undo a copy
before that, see hg revert.
"""
- wlock = repo.wlock(0)
- errs, copied = docopy(ui, repo, pats, opts, wlock)
+ wlock = repo.wlock(False)
+ try:
+ errs, copied = docopy(ui, repo, pats, opts)
+ finally:
+ del wlock
return errs
def debugancestor(ui, index, rev1, rev2):
@@ -713,17 +716,19 @@ def debugrebuildstate(ui, repo, rev=""):
ctx = repo.changectx(rev)
files = ctx.manifest()
wlock = repo.wlock()
- repo.dirstate.rebuild(rev, files)
+ try:
+ repo.dirstate.rebuild(rev, files)
+ finally:
+ del wlock
def debugcheckstate(ui, repo):
"""validate the correctness of the current dirstate"""
parent1, parent2 = repo.dirstate.parents()
- dc = repo.dirstate
m1 = repo.changectx(parent1).manifest()
m2 = repo.changectx(parent2).manifest()
errors = 0
- for f in dc:
- state = repo.dirstate.state(f)
+ for f in repo.dirstate:
+ state = repo.dirstate[f]
if state in "nr" and f not in m1:
ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
errors += 1
@@ -735,7 +740,7 @@ def debugcheckstate(ui, repo):
(f, state))
errors += 1
for f in m1:
- state = repo.dirstate.state(f)
+ state = repo.dirstate[f]
if state not in "nrm":
ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
errors += 1
@@ -783,12 +788,14 @@ def debugsetparents(ui, repo, rev1, rev2
try:
repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
finally:
- wlock.release()
+ del wlock
def debugstate(ui, repo):
"""show the contents of the current dirstate"""
- dc = repo.dirstate
- for file_ in dc:
+ dc = repo.dirstate._map
+ k = dc.keys()
+ k.sort()
+ for file_ in k:
if dc[file_][3] == -1:
# Pad or slice to locale representation
locale_len = len(time.strftime("%x %X", time.localtime(0)))
@@ -1581,70 +1588,75 @@ def import_(ui, repo, patch1, *patches,
d = opts["base"]
strip = opts["strip"]
-
- wlock = repo.wlock()
- lock = repo.lock()
-
- for p in patches:
- pf = os.path.join(d, p)
-
- if pf == '-':
- ui.status(_("applying patch from stdin\n"))
- tmpname, message, user, date, branch, nodeid, p1, p2 = patch.extract(ui, sys.stdin)
- else:
- ui.status(_("applying %s\n") % p)
- tmpname, message, user, date, branch, nodeid, p1, p2 = patch.extract(ui, file(pf, 'rb'))
-
- if tmpname is None:
- raise util.Abort(_('no diffs found'))
-
- try:
- cmdline_message = cmdutil.logmessage(opts)
- if cmdline_message:
- # pickup the cmdline msg
- message = cmdline_message
- elif message:
- # pickup the patch msg
- message = message.strip()
+ wlock = lock = None
+ try:
+ wlock = repo.wlock()
+ lock = repo.lock()
+ for p in patches:
+ pf = os.path.join(d, p)
+
+ if pf == '-':
+ ui.status(_("applying patch from stdin\n"))
+ data = patch.extract(ui, sys.stdin)
else:
- # launch the editor
- message = None
- ui.debug(_('message:\n%s\n') % message)
-
- wp = repo.workingctx().parents()
- if opts.get('exact'):
- if not nodeid or not p1:
- raise util.Abort(_('not a mercurial patch'))
- p1 = repo.lookup(p1)
- p2 = repo.lookup(p2 or hex(nullid))
-
- if p1 != wp[0].node():
- hg.clean(repo, p1, wlock=wlock)
- repo.dirstate.setparents(p1, p2)
- elif p2:
- try:
+ ui.status(_("applying %s\n") % p)
+ data = patch.extract(ui, file(pf, 'rb'))
+
+ tmpname, message, user, date, branch, nodeid, p1, p2 = data
+
+ if tmpname is None:
+ raise util.Abort(_('no diffs found'))
+
+ try:
+ cmdline_message = cmdutil.logmessage(opts)
+ if cmdline_message:
+ # pickup the cmdline msg
+ message = cmdline_message
+ elif message:
+ # pickup the patch msg
+ message = message.strip()
+ else:
+ # launch the editor
+ message = None
+ ui.debug(_('message:\n%s\n') % message)
+
+ wp = repo.workingctx().parents()
+ if opts.get('exact'):
+ if not nodeid or not p1:
+ raise util.Abort(_('not a mercurial patch'))
p1 = repo.lookup(p1)
- p2 = repo.lookup(p2)
- if p1 == wp[0].node():
- repo.dirstate.setparents(p1, p2)
- except hg.RepoError:
- pass
- if opts.get('exact') or opts.get('import_branch'):
- repo.dirstate.setbranch(branch or 'default')
-
- files = {}
- try:
- fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
- files=files)
+ p2 = repo.lookup(p2 or hex(nullid))
+
+ if p1 != wp[0].node():
+ hg.clean(repo, p1)
+ repo.dirstate.setparents(p1, p2)
+ elif p2:
+ try:
+ p1 = repo.lookup(p1)
+ p2 = repo.lookup(p2)
+ if p1 == wp[0].node():
+ repo.dirstate.setparents(p1, p2)
+ except hg.RepoError:
+ pass
+ if opts.get('exact') or opts.get('import_branch'):
+ repo.dirstate.setbranch(branch or 'default')
+
+ files = {}
+ try:
+ fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
+ files=files)
+ finally:
+ files = patch.updatedir(ui, repo, files)
+ n = repo.commit(files, message, user, date)
+ if opts.get('exact'):
+ if hex(n) != nodeid:
+ repo.rollback()
+ raise util.Abort(_('patch is damaged' +
+ ' or loses information'))
finally:
- files = patch.updatedir(ui, repo, files, wlock=wlock)
- n = repo.commit(files, message, user, date, wlock=wlock, lock=lock)
- if opts.get('exact'):
- if hex(n) != nodeid:
- repo.rollback(wlock=wlock, lock=lock)
- raise util.Abort(_('patch is damaged or loses information'))
- finally:
- os.unlink(tmpname)
+ os.unlink(tmpname)
+ finally:
+ del wlock, lock
def incoming(ui, repo, source="default", **opts):
"""show new changesets found in source
@@ -1759,7 +1771,7 @@ def locate(ui, repo, *pats, **opts):
default='relglob'):
if src == 'b':
continue
- if not node and repo.dirstate.state(abs) == '?':
+ if not node and abs not in repo.dirstate:
continue
if opts['fullpath']:
ui.write(os.path.join(repo.root, abs), end)
@@ -2213,7 +2225,7 @@ def remove(ui, repo, *pats, **opts):
forget.append(abs)
continue
reason = _('has been marked for add (use -f to force removal)')
- elif repo.dirstate.state(abs) == '?':
+ elif abs not in repo.dirstate:
reason = _('is not managed')
elif opts['after'] and not exact and abs not in deleted:
continue
@@ -2243,16 +2255,19 @@ def rename(ui, repo, *pats, **opts):
This command takes effect in the next commit. To undo a rename
before that, see hg revert.
"""
- wlock = repo.wlock(0)
- errs, copied = docopy(ui, repo, pats, opts, wlock)
- names = []
- for abs, rel, exact in copied:
- if ui.verbose or not exact:
- ui.status(_('removing %s\n') % rel)
- names.append(abs)
- if not opts.get('dry_run'):
- repo.remove(names, True, wlock=wlock)
- return errs
+ wlock = repo.wlock(False)
+ try:
+ errs, copied = docopy(ui, repo, pats, opts)
+ names = []
+ for abs, rel, exact in copied:
+ if ui.verbose or not exact:
+ ui.status(_('removing %s\n') % rel)
+ names.append(abs)
+ if not opts.get('dry_run'):
+ repo.remove(names, True)
+ return errs
+ finally:
+ del wlock
def revert(ui, repo, *pats, **opts):
"""revert files or dirs to their states as of some revision
@@ -2306,8 +2321,6 @@ def revert(ui, repo, *pats, **opts):
else:
pmf = None
- wlock = repo.wlock()
-
# need all matching names in dirstate and manifest of target rev,
# so have to walk both. do not print errors if files exist in one
# but not other.
@@ -2315,109 +2328,116 @@ def revert(ui, repo, *pats, **opts):
names = {}
target_only = {}
- # walk dirstate.
-
- for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
- badmatch=mf.has_key):
- names[abs] = (rel, exact)
- if src == 'b':
- target_only[abs] = True
-
- # walk target manifest.
-
- def badmatch(path):
- if path in names:
- return True
- path_ = path + '/'
- for f in names:
- if f.startswith(path_):
+ wlock = repo.wlock()
+ try:
+ # walk dirstate.
+ for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
+ badmatch=mf.has_key):
+ names[abs] = (rel, exact)
+ if src == 'b':
+ target_only[abs] = True
+
+ # walk target manifest.
+
+ def badmatch(path):
+ if path in names:
return True
- return False
-
- for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
- badmatch=badmatch):
- if abs in names or src == 'b':
- continue
- names[abs] = (rel, exact)
- target_only[abs] = True
-
- changes = repo.status(match=names.has_key, wlock=wlock)[:5]
- modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
-
- revert = ([], _('reverting %s\n'))
- add = ([], _('adding %s\n'))
- remove = ([], _('removing %s\n'))
- forget = ([], _('forgetting %s\n'))
- undelete = ([], _('undeleting %s\n'))
- update = {}
-
- disptable = (
- # dispatch table:
- # file state
- # action if in target manifest
- # action if not in target manifest
- # make backup if in target manifest
- # make backup if not in target manifest
- (modified, revert, remove, True, True),
- (added, revert, forget, True, False),
- (removed, undelete, None, False, False),
- (deleted, revert, remove, False, False),
- (unknown, add, None, True, False),
- (target_only, add, None, False, False),
- )
-
- entries = names.items()
- entries.sort()
-
- for abs, (rel, exact) in entries:
- mfentry = mf.get(abs)
- target = repo.wjoin(abs)
- def handle(xlist, dobackup):
- xlist[0].append(abs)
- update[abs] = 1
- if dobackup and not opts['no_backup'] and util.lexists(target):
- bakname = "%s.orig" % rel
- ui.note(_('saving current version of %s as %s\n') %
- (rel, bakname))
- if not opts.get('dry_run'):
- util.copyfile(target, bakname)
- if ui.verbose or not exact:
- ui.status(xlist[1] % rel)
- for table, hitlist, misslist, backuphit, backupmiss in disptable:
- if abs not in table: continue
- # file has changed in dirstate
- if mfentry:
- handle(hitlist, backuphit)
- elif misslist is not None:
- handle(misslist, backupmiss)
+ path_ = path + '/'
+ for f in names:
+ if f.startswith(path_):
+ return True
+ return False
+
+ for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
+ badmatch=badmatch):
+ if abs in names or src == 'b':
+ continue
+ names[abs] = (rel, exact)
+ target_only[abs] = True
+
+ changes = repo.status(match=names.has_key)[:5]
+ modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
+
+ revert = ([], _('reverting %s\n'))
+ add = ([], _('adding %s\n'))
+ remove = ([], _('removing %s\n'))
+ forget = ([], _('forgetting %s\n'))
+ undelete = ([], _('undeleting %s\n'))
+ update = {}
+
+ disptable = (
+ # dispatch table:
+ # file state
+ # action if in target manifest
+ # action if not in target manifest
+ # make backup if in target manifest
+ # make backup if not in target manifest
+ (modified, revert, remove, True, True),
+ (added, revert, forget, True, False),
+ (removed, undelete, None, False, False),
+ (deleted, revert, remove, False, False),
+ (unknown, add, None, True, False),
+ (target_only, add, None, False, False),
+ )
+
+ entries = names.items()
+ entries.sort()
+
+ for abs, (rel, exact) in entries:
+ mfentry = mf.get(abs)
+ target = repo.wjoin(abs)
+ def handle(xlist, dobackup):
+ xlist[0].append(abs)
+ update[abs] = 1
+ if dobackup and not opts['no_backup'] and util.lexists(target):
+ bakname = "%s.orig" % rel
+ ui.note(_('saving current version of %s as %s\n') %
+ (rel, bakname))
+ if not opts.get('dry_run'):
+ util.copyfile(target, bakname)
+ if ui.verbose or not exact:
+ ui.status(xlist[1] % rel)
+ for table, hitlist, misslist, backuphit, backupmiss in disptable:
+ if abs not in table: continue
+ # file has changed in dirstate
+ if mfentry:
+ handle(hitlist, backuphit)
+ elif misslist is not None:
+ handle(misslist, backupmiss)
+ else:
+ if exact: ui.warn(_('file not managed: %s\n') % rel)
+ break
else:
- if exact: ui.warn(_('file not managed: %s\n') % rel)
- break
- else:
- # file has not changed in dirstate
- if node == parent:
- if exact: ui.warn(_('no changes needed to %s\n') % rel)
- continue
- if pmf is None:
- # only need parent manifest in this unlikely case,
- # so do not read by default
- pmf = repo.changectx(parent).manifest()
- if abs in pmf:
- if mfentry:
- # if version of file is same in parent and target
- # manifests, do nothing
- if pmf[abs] != mfentry:
- handle(revert, False)
- else:
- handle(remove, False)
-
- if not opts.get('dry_run'):
- repo.dirstate.forget(forget[0])
- r = hg.revert(repo, node, update.has_key, wlock)
- repo.dirstate.update(add[0], 'a')
- repo.dirstate.update(undelete[0], 'n')
- repo.dirstate.update(remove[0], 'r')
- return r
+ # file has not changed in dirstate
+ if node == parent:
+ if exact: ui.warn(_('no changes needed to %s\n') % rel)
+ continue
+ if pmf is None:
+ # only need parent manifest in this unlikely case,
+ # so do not read by default
+ pmf = repo.changectx(parent).manifest()
+ if abs in pmf:
+ if mfentry:
+ # if version of file is same in parent and target
+ # manifests, do nothing
+ if pmf[abs] != mfentry:
+ handle(revert, False)
+ else:
+ handle(remove, False)
+
+ if not opts.get('dry_run'):
+ for f in forget[0]:
+ repo.dirstate.forget(f)
+ r = hg.revert(repo, node, update.has_key)
+ for f in add[0]:
+ repo.dirstate.add(f)
+ for f in undelete[0]:
+ repo.dirstate.normal(f)
+ for f in remove[0]:
+ repo.dirstate.remove(f)
+ return r
+ finally:
+ del wlock
def rollback(ui, repo):
"""roll back the last transaction in this repository
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -60,6 +60,18 @@ class changectx(object):
else:
raise AttributeError, name
+ def __contains__(self, key):
+ return key in self._manifest
+
+ def __getitem__(self, key):
+ return self.filectx(key)
+
+ def __iter__(self):
+ a = self._manifest.keys()
+ a.sort()
+ for f in a:
+ return f
+
def changeset(self): return self._changeset
def manifest(self): return self._manifest
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -20,8 +20,8 @@ class dirstate(object):
def __init__(self, opener, ui, root):
self._opener = opener
self._root = root
- self._dirty = 0
- self._dirtypl = 0
+ self._dirty = False
+ self._dirtypl = False
self._ui = ui
def __getattr__(self, name):
@@ -53,7 +53,7 @@ class dirstate(object):
self._incpath(f)
return self._dirs
elif name == '_ignore':
- files = [self.wjoin('.hgignore')]
+ files = [self._join('.hgignore')]
for name, path in self._ui.configitems("ui"):
if name == 'ignore' or name.startswith('ignore.'):
files.append(os.path.expanduser(path))
@@ -65,7 +65,7 @@ class dirstate(object):
else:
raise AttributeError, name
- def wjoin(self, f):
+ def _join(self, f):
return os.path.join(self._root, f)
def getcwd(self):
@@ -89,11 +89,14 @@ class dirstate(object):
return path.replace(os.sep, '/')
return path
- def __del__(self):
- self.write()
-
def __getitem__(self, key):
- return self._map[key]
+ ''' current states:
+ n normal
+ m needs merging
+ r marked for removal
+ a marked for addition
+ ? not tracked'''
+ return self._map.get(key, ("?",))[0]
def __contains__(self, key):
return key in self._map
@@ -110,21 +113,14 @@ class dirstate(object):
def branch(self):
return self._branch
- def markdirty(self):
- self._dirty = 1
-
def setparents(self, p1, p2=nullid):
- self.markdirty()
- self._dirtypl = 1
+ self._dirty = self._dirtypl = True
self._pl = p1, p2
def setbranch(self, branch):
self._branch = branch
self._opener("branch", "w").write(branch + '\n')
- def state(self, key):
- return self._map.get(key, ("?",))[0]
-
def _read(self):
self._map = {}
self._copymap = {}
@@ -166,10 +162,10 @@ class dirstate(object):
for a in "_map _copymap _branch _pl _dirs _ignore".split():
if a in self.__dict__:
delattr(self, a)
- self._dirty = 0
+ self._dirty = False
def copy(self, source, dest):
- self.markdirty()
+ self._dirty = True
self._copymap[dest] = source
def copied(self, file):
@@ -204,41 +200,54 @@ class dirstate(object):
raise util.Abort(_('file named %r already in dirstate') % d)
self._incpath(f)
- def update(self, files, state, **kw):
- ''' current states:
- n normal
- m needs merging
- r marked for removal
- a marked for addition'''
+ def normal(self, f):
+ 'mark a file normal'
+ self._dirty = True
+ s = os.lstat(self._join(f))
+ self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime)
+ if self._copymap.has_key(f):
+ del self._copymap[f]
- if not files: return
- self.markdirty()
- for f in files:
- if self._copymap.has_key(f):
- del self._copymap[f]
+ def normaldirty(self, f):
+ 'mark a file normal, but possibly dirty'
+ self._dirty = True
+ s = os.lstat(self._join(f))
+ self._map[f] = ('n', s.st_mode, -1, -1)
+ if f in self._copymap:
+ del self._copymap[f]
+
+ def add(self, f):
+ 'mark a file added'
+ self._dirty = True
+ self._incpathcheck(f)
+ self._map[f] = ('a', 0, -1, -1)
+ if f in self._copymap:
+ del self._copymap[f]
- if state == "r":
- self._map[f] = ('r', 0, 0, 0)
- self._decpath(f)
- continue
- else:
- if state == "a":
- self._incpathcheck(f)
- s = os.lstat(self.wjoin(f))
- st_size = kw.get('st_size', s.st_size)
- st_mtime = kw.get('st_mtime', s.st_mtime)
- self._map[f] = (state, s.st_mode, st_size, st_mtime)
+ def remove(self, f):
+ 'mark a file removed'
+ self._dirty = True
+ self._map[f] = ('r', 0, 0, 0)
+ self._decpath(f)
+ if f in self._copymap:
+ del self._copymap[f]
- def forget(self, files):
- if not files: return
- self.markdirty()
- for f in files:
- try:
- del self._map[f]
- self._decpath(f)
- except KeyError:
- self._ui.warn(_("not in dirstate: %s!\n") % f)
- pass
+ def merge(self, f):
+ 'mark a file merged'
+ self._dirty = True
+ s = os.lstat(self._join(f))
+ self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime)
+ if f in self._copymap:
+ del self._copymap[f]
+
+ def forget(self, f):
+ 'forget a file'
+ self._dirty = True
+ try:
+ del self._map[f]
+ self._decpath(f)
+ except KeyError:
+ self._ui.warn(_("not in dirstate: %s!\n") % f)
def rebuild(self, parent, files):
self.invalidate()
@@ -248,7 +257,7 @@ class dirstate(object):
else:
self._map[f] = ('n', 0666, -1, 0)
self._pl = (parent, nullid)
- self.markdirty()
+ self._dirty = True
def write(self):
if not self._dirty:
@@ -265,10 +274,9 @@ class dirstate(object):
st = self._opener("dirstate", "w", atomictemp=True)
st.write(cs.getvalue())
st.rename()
- self._dirty = 0
- self._dirtypl = 0
+ self._dirty = self._dirtypl = False
- def filterfiles(self, files):
+ def _filter(self, files):
ret = {}
unknown = []
@@ -339,7 +347,7 @@ class dirstate(object):
dc = self._map.copy()
else:
files = util.unique(files)
- dc = self.filterfiles(files)
+ dc = self._filter(files)
def imatch(file_):
if file_ not in dc and self._ignore(file_):
@@ -405,7 +413,7 @@ class dirstate(object):
files.sort()
for ff in files:
nf = util.normpath(ff)
- f = self.wjoin(ff)
+ f = self._join(ff)
try:
st = os.lstat(f)
except OSError, inst:
@@ -442,14 +450,13 @@ class dirstate(object):
if not seen(k) and imatch(k):
yield 'm', k, None
- def status(self, files=None, match=util.always, list_ignored=False,
- list_clean=False):
+ def status(self, files, match, list_ignored, list_clean):
lookup, modified, added, unknown, ignored = [], [], [], [], []
removed, deleted, clean = [], [], []
for src, fn, st in self.statwalk(files, match, ignored=list_ignored):
try:
- type_, mode, size, time = self[fn]
+ type_, mode, size, time = self._map[fn]
except KeyError:
if list_ignored and self._ignore(fn):
ignored.append(fn)
@@ -460,7 +467,7 @@ class dirstate(object):
nonexistent = True
if not st:
try:
- st = os.lstat(self.wjoin(fn))
+ st = os.lstat(self._join(fn))
except OSError, inst:
if inst.errno != errno.ENOENT:
raise
@@ -476,7 +483,7 @@ class dirstate(object):
# check the common case first
if type_ == 'n':
if not st:
- st = os.lstat(self.wjoin(fn))
+ st = os.lstat(self._join(fn))
if (size >= 0 and (size != st.st_size
or (mode ^ st.st_mode) & 0100)
or fn in self._copymap):
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -130,103 +130,99 @@ def clone(ui, source, dest=None, pull=Fa
if self.dir_:
self.rmtree(self.dir_, True)
- dir_cleanup = None
- if islocal(dest):
- dir_cleanup = DirCleanup(dest)
+ src_lock = dest_lock = dir_cleanup = None
+ try:
+ if islocal(dest):
+ dir_cleanup = DirCleanup(dest)
- abspath = origsource
- copy = False
- if src_repo.local() and islocal(dest):
- abspath = os.path.abspath(origsource)
- copy = not pull and not rev
+ abspath = origsource
+ copy = False
+ if src_repo.local() and islocal(dest):
+ abspath = os.path.abspath(origsource)
+ copy = not pull and not rev
- src_lock, dest_lock = None, None
- if copy:
- try:
- # we use a lock here because if we race with commit, we
- # can end up with extra data in the cloned revlogs that's
- # not pointed to by changesets, thus causing verify to
- # fail
- src_lock = src_repo.lock()
- except lock.LockException:
- copy = False
+ if copy:
+ try:
+ # we use a lock here because if we race with commit, we
+ # can end up with extra data in the cloned revlogs that's
+ # not pointed to by changesets, thus causing verify to
+ # fail
+ src_lock = src_repo.lock()
+ except lock.LockException:
+ copy = False
- if copy:
- def force_copy(src, dst):
- try:
- util.copyfiles(src, dst)
- except OSError, inst:
- if inst.errno != errno.ENOENT:
- raise
+ if copy:
+ def force_copy(src, dst):
+ try:
+ util.copyfiles(src, dst)
+ except OSError, inst:
+ if inst.errno != errno.ENOENT:
+ raise
- src_store = os.path.realpath(src_repo.spath)
- if not os.path.exists(dest):
- os.mkdir(dest)
- dest_path = os.path.realpath(os.path.join(dest, ".hg"))
- os.mkdir(dest_path)
- if src_repo.spath != src_repo.path:
- dest_store = os.path.join(dest_path, "store")
- os.mkdir(dest_store)
- else:
- dest_store = dest_path
- # copy the requires file
- force_copy(src_repo.join("requires"),
- os.path.join(dest_path, "requires"))
- # we lock here to avoid premature writing to the target
- dest_lock = lock.lock(os.path.join(dest_store, "lock"))
+ src_store = os.path.realpath(src_repo.spath)
+ if not os.path.exists(dest):
+ os.mkdir(dest)
+ dest_path = os.path.realpath(os.path.join(dest, ".hg"))
+ os.mkdir(dest_path)
+ if src_repo.spath != src_repo.path:
+ dest_store = os.path.join(dest_path, "store")
+ os.mkdir(dest_store)
+ else:
+ dest_store = dest_path
+ # copy the requires file
+ force_copy(src_repo.join("requires"),
+ os.path.join(dest_path, "requires"))
+ # we lock here to avoid premature writing to the target
+ dest_lock = lock.lock(os.path.join(dest_store, "lock"))
- files = ("data",
- "00manifest.d", "00manifest.i",
- "00changelog.d", "00changelog.i")
- for f in files:
- src = os.path.join(src_store, f)
- dst = os.path.join(dest_store, f)
- force_copy(src, dst)
+ files = ("data",
+ "00manifest.d", "00manifest.i",
+ "00changelog.d", "00changelog.i")
+ for f in files:
+ src = os.path.join(src_store, f)
+ dst = os.path.join(dest_store, f)
+ force_copy(src, dst)
+
+ # we need to re-init the repo after manually copying the data
+ # into it
+ dest_repo = repository(ui, dest)
+
+ else:
+ dest_repo = repository(ui, dest, create=True)
- # we need to re-init the repo after manually copying the data
- # into it
- dest_repo = repository(ui, dest)
-
- else:
- dest_repo = repository(ui, dest, create=True)
+ revs = None
+ if rev:
+ if 'lookup' not in src_repo.capabilities:
+ raise util.Abort(_("src repository does not support revision "
+ "lookup and so doesn't support clone by "
+ "revision"))
+ revs = [src_repo.lookup(r) for r in rev]
- revs = None
- if rev:
- if 'lookup' not in src_repo.capabilities:
- raise util.Abort(_("src repository does not support revision "
- "lookup and so doesn't support clone by "
- "revision"))
- revs = [src_repo.lookup(r) for r in rev]
+ if dest_repo.local():
+ dest_repo.clone(src_repo, heads=revs, stream=stream)
+ elif src_repo.local():
+ src_repo.push(dest_repo, revs=revs)
+ else:
+ raise util.Abort(_("clone from remote to remote not supported"))
if dest_repo.local():
- dest_repo.clone(src_repo, heads=revs, stream=stream)
- elif src_repo.local():
- src_repo.push(dest_repo, revs=revs)
- else:
- raise util.Abort(_("clone from remote to remote not supported"))
-
- if src_lock:
- src_lock.release()
+ fp = dest_repo.opener("hgrc", "w", text=True)
+ fp.write("[paths]\n")
+ fp.write("default = %s\n" % abspath)
+ fp.close()
- if dest_repo.local():
- fp = dest_repo.opener("hgrc", "w", text=True)
- fp.write("[paths]\n")
- fp.write("default = %s\n" % abspath)
- fp.close()
-
- if dest_lock:
- dest_lock.release()
+ if update:
+ try:
+ checkout = dest_repo.lookup("default")
+ except:
+ checkout = dest_repo.changelog.tip()
+ _update(dest_repo, checkout)
+ if dir_cleanup:
+ dir_cleanup.close()
- if update:
- try:
- checkout = dest_repo.lookup("default")
- except:
- checkout = dest_repo.changelog.tip()
- _update(dest_repo, checkout)
- if dir_cleanup:
- dir_cleanup.close()
-
- return src_repo, dest_repo
+ return src_repo, dest_repo
+ finally:
+ del src_lock, dest_lock, dir_cleanup
def _showstats(repo, stats):
stats = ((stats[0], _("updated")),
@@ -241,7 +237,7 @@ def _update(repo, node): return update(r
def update(repo, node):
"""update the working directory to node, merging linear changes"""
pl = repo.parents()
- stats = _merge.update(repo, node, False, False, None, None)
+ stats = _merge.update(repo, node, False, False, None)
_showstats(repo, stats)
if stats[3]:
repo.ui.status(_("There are unresolved merges with"
@@ -255,15 +251,15 @@ def update(repo, node):
% (pl[0].rev(), repo.changectx(node).rev()))
return stats[3]
-def clean(repo, node, wlock=None, show_stats=True):
+def clean(repo, node, show_stats=True):
"""forcibly switch the working directory to node, clobbering changes"""
- stats = _merge.update(repo, node, False, True, None, wlock)
+ stats = _merge.update(repo, node, False, True, None)
if show_stats: _showstats(repo, stats)
return stats[3]
-def merge(repo, node, force=None, remind=True, wlock=None):
+def merge(repo, node, force=None, remind=True):
"""branch merge with node, resolving changes"""
- stats = _merge.update(repo, node, True, force, False, wlock)
+ stats = _merge.update(repo, node, True, force, False)
_showstats(repo, stats)
if stats[3]:
pl = repo.parents()
@@ -276,9 +272,9 @@ def merge(repo, node, force=None, remind
repo.ui.status(_("(branch merge, don't forget to commit)\n"))
return stats[3]
-def revert(repo, node, choose, wlock):
+def revert(repo, node, choose):
"""revert changes to revision in node without updating dirstate"""
- return _merge.update(repo, node, False, True, choose, wlock)[3]
+ return _merge.update(repo, node, False, True, choose)[3]
def verify(repo):
"""verify the consistency of a repository"""
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -1168,7 +1168,7 @@ class hgweb(object):
req.write('%d\n' % ret)
req.write(val)
finally:
- lock.release()
+ del lock
except (OSError, IOError), inst:
req.write('0\n')
filename = getattr(inst, 'filename', '')
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -8,7 +8,7 @@
from node import *
from i18n import _
import repo, changegroup
-import changelog, dirstate, filelog, manifest, context
+import changelog, dirstate, filelog, manifest, context, weakref
import re, lock, transaction, tempfile, stat, mdiff, errno, ui
import os, revlog, time, util, extensions, hook
@@ -16,8 +16,6 @@ class localrepository(repo.repository):
capabilities = ('lookup', 'changegroupsubset')
supported = ('revlogv1', 'store')
- def __del__(self):
- self.transhandle = None
def __init__(self, parentui, path=None, create=0):
repo.repository.__init__(self)
self.path = path
@@ -84,7 +82,7 @@ class localrepository(repo.repository):
self.branchcache = None
self.nodetagscache = None
self.filterpats = {}
- self.transhandle = None
+ self._transref = self._lockref = self._wlockref = None
def __getattr__(self, name):
if name == 'changelog':
@@ -125,7 +123,7 @@ class localrepository(repo.repository):
fp.write('%s %s\n' % (hex(node), munge and munge(name) or name))
fp.close()
self.hook('tag', node=hex(node), tag=name, local=local)
-
+
prevtags = ''
if local:
try:
@@ -156,7 +154,7 @@ class localrepository(repo.repository):
# committed tags are stored in UTF-8
writetag(fp, name, util.fromlocal, prevtags)
- if use_dirstate and self.dirstate.state('.hgtags') == '?':
+ if use_dirstate and '.hgtags' not in self.dirstate:
self.add(['.hgtags'])
tagnode = self.commit(['.hgtags'], message, user, date, p1=parent,
@@ -396,6 +394,11 @@ class localrepository(repo.repository):
n = self.changelog._partialmatch(key)
if n:
return n
+ try:
+ if len(key) == 20:
+ key = hex(key)
+ except:
+ pass
raise repo.RepoError(_("unknown revision '%s'") % key)
def dev(self):
@@ -495,9 +498,8 @@ class localrepository(repo.repository):
return self._filter("decode", filename, data)
def transaction(self):
- tr = self.transhandle
- if tr != None and tr.running():
- return tr.nest()
+ if self._transref and self._transref():
+ return self._transref().nest()
# save dirstate for rollback
try:
@@ -511,33 +513,38 @@ class localrepository(repo.repository):
tr = transaction.transaction(self.ui.warn, self.sopener,
self.sjoin("journal"),
aftertrans(renames))
- self.transhandle = tr
+ self._transref = weakref.ref(tr)
return tr
def recover(self):
l = self.lock()
- if os.path.exists(self.sjoin("journal")):
- self.ui.status(_("rolling back interrupted transaction\n"))
- transaction.rollback(self.sopener, self.sjoin("journal"))
- self.invalidate()
- return True
- else:
- self.ui.warn(_("no interrupted transaction available\n"))
- return False
+ try:
+ if os.path.exists(self.sjoin("journal")):
+ self.ui.status(_("rolling back interrupted transaction\n"))
+ transaction.rollback(self.sopener, self.sjoin("journal"))
+ self.invalidate()
+ return True
+ else:
+ self.ui.warn(_("no interrupted transaction available\n"))
+ return False
+ finally:
+ del l
- def rollback(self, wlock=None, lock=None):
- if not wlock:
+ def rollback(self):
+ wlock = lock = None
+ try:
wlock = self.wlock()
- if not lock:
lock = self.lock()
- if os.path.exists(self.sjoin("undo")):
- self.ui.status(_("rolling back last transaction\n"))
- transaction.rollback(self.sopener, self.sjoin("undo"))
- util.rename(self.join("undo.dirstate"), self.join("dirstate"))
- self.invalidate()
- self.dirstate.invalidate()
- else:
- self.ui.warn(_("no rollback information available\n"))
+ if os.path.exists(self.sjoin("undo")):
+ self.ui.status(_("rolling back last transaction\n"))
+ transaction.rollback(self.sopener, self.sjoin("undo"))
+ util.rename(self.join("undo.dirstate"), self.join("dirstate"))
+ self.invalidate()
+ self.dirstate.invalidate()
+ else:
+ self.ui.warn(_("no rollback information available\n"))
+ finally:
+ del wlock, lock
def invalidate(self):
for a in "changelog manifest".split():
@@ -546,8 +553,7 @@ class localrepository(repo.repository):
self.tagscache = None
self.nodetagscache = None
- def do_lock(self, lockname, wait, releasefn=None, acquirefn=None,
- desc=None):
+ def _lock(self, lockname, wait, releasefn, acquirefn, desc):
try:
l = lock.lock(lockname, 0, releasefn, desc=desc)
except lock.LockHeld, inst:
@@ -562,15 +568,24 @@ class localrepository(repo.repository):
acquirefn()
return l
- def lock(self, wait=1):
- return self.do_lock(self.sjoin("lock"), wait,
- acquirefn=self.invalidate,
- desc=_('repository %s') % self.origroot)
+ def lock(self, wait=True):
+ if self._lockref and self._lockref():
+ return self._lockref()
+
+ l = self._lock(self.sjoin("lock"), wait, None, self.invalidate,
+ _('repository %s') % self.origroot)
+ self._lockref = weakref.ref(l)
+ return l
- def wlock(self, wait=1):
- return self.do_lock(self.join("wlock"), wait, self.dirstate.write,
- self.dirstate.invalidate,
- desc=_('working directory of %s') % self.origroot)
+ def wlock(self, wait=True):
+ if self._wlockref and self._wlockref():
+ return self._wlockref()
+
+ l = self._lock(self.join("wlock"), wait, self.dirstate.write,
+ self.dirstate.invalidate, _('working directory of %s') %
+ self.origroot)
+ self._wlockref = weakref.ref(l)
+ return l
def filecommit(self, fn, manifest1, manifest2, linkrev, transaction, changelist):
"""
@@ -632,171 +647,176 @@ class localrepository(repo.repository):
changelist.append(fn)
return fl.add(t, meta, transaction, linkrev, fp1, fp2)
- def rawcommit(self, files, text, user, date, p1=None, p2=None, wlock=None, extra={}):
+ def rawcommit(self, files, text, user, date, p1=None, p2=None, extra={}):
if p1 is None:
p1, p2 = self.dirstate.parents()
return self.commit(files=files, text=text, user=user, date=date,
- p1=p1, p2=p2, wlock=wlock, extra=extra)
+ p1=p1, p2=p2, extra=extra)
def commit(self, files=None, text="", user=None, date=None,
- match=util.always, force=False, lock=None, wlock=None,
- force_editor=False, p1=None, p2=None, extra={}):
-
- commit = []
- remove = []
- changed = []
- use_dirstate = (p1 is None) # not rawcommit
- extra = extra.copy()
+ match=util.always, force=False, force_editor=False,
+ p1=None, p2=None, extra={}):
+ wlock = lock = tr = None
+ try:
+ commit = []
+ remove = []
+ changed = []
+ use_dirstate = (p1 is None) # not rawcommit
+ extra = extra.copy()
- if use_dirstate:
- if files:
- for f in files:
- s = self.dirstate.state(f)
- if s in 'nmai':
- commit.append(f)
- elif s == 'r':
- remove.append(f)
- else:
- self.ui.warn(_("%s not tracked!\n") % f)
+ if use_dirstate:
+ if files:
+ for f in files:
+ s = self.dirstate[f]
+ if s in 'nma':
+ commit.append(f)
+ elif s == 'r':
+ remove.append(f)
+ else:
+ self.ui.warn(_("%s not tracked!\n") % f)
+ else:
+ changes = self.status(match=match)[:5]
+ modified, added, removed, deleted, unknown = changes
+ commit = modified + added
+ remove = removed
else:
- changes = self.status(match=match)[:5]
- modified, added, removed, deleted, unknown = changes
- commit = modified + added
- remove = removed
- else:
- commit = files
+ commit = files
- if use_dirstate:
- p1, p2 = self.dirstate.parents()
- update_dirstate = True
- else:
- p1, p2 = p1, p2 or nullid
- update_dirstate = (self.dirstate.parents()[0] == p1)
+ if use_dirstate:
+ p1, p2 = self.dirstate.parents()
+ update_dirstate = True
+ else:
+ p1, p2 = p1, p2 or nullid
+ update_dirstate = (self.dirstate.parents()[0] == p1)
- c1 = self.changelog.read(p1)
- c2 = self.changelog.read(p2)
- m1 = self.manifest.read(c1[0]).copy()
- m2 = self.manifest.read(c2[0])
+ c1 = self.changelog.read(p1)
+ c2 = self.changelog.read(p2)
+ m1 = self.manifest.read(c1[0]).copy()
+ m2 = self.manifest.read(c2[0])
- if use_dirstate:
- branchname = self.workingctx().branch()
- try:
- branchname = branchname.decode('UTF-8').encode('UTF-8')
- except UnicodeDecodeError:
- raise util.Abort(_('branch name not in UTF-8!'))
- else:
- branchname = ""
+ if use_dirstate:
+ branchname = self.workingctx().branch()
+ try:
+ branchname = branchname.decode('UTF-8').encode('UTF-8')
+ except UnicodeDecodeError:
+ raise util.Abort(_('branch name not in UTF-8!'))
+ else:
+ branchname = ""
- if use_dirstate:
- oldname = c1[5].get("branch") # stored in UTF-8
- if (not commit and not remove and not force and p2 == nullid
- and branchname == oldname):
- self.ui.status(_("nothing changed\n"))
- return None
+ if use_dirstate:
+ oldname = c1[5].get("branch") # stored in UTF-8
+ if (not commit and not remove and not force and p2 == nullid
+ and branchname == oldname):
+ self.ui.status(_("nothing changed\n"))
+ return None
- xp1 = hex(p1)
- if p2 == nullid: xp2 = ''
- else: xp2 = hex(p2)
-
- self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
+ xp1 = hex(p1)
+ if p2 == nullid: xp2 = ''
+ else: xp2 = hex(p2)
- if not wlock:
+ self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
+
wlock = self.wlock()
- if not lock:
lock = self.lock()
- tr = self.transaction()
+ tr = self.transaction()
- # check in files
- new = {}
- linkrev = self.changelog.count()
- commit.sort()
- is_exec = util.execfunc(self.root, m1.execf)
- is_link = util.linkfunc(self.root, m1.linkf)
- for f in commit:
- self.ui.note(f + "\n")
- try:
- new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed)
- new_exec = is_exec(f)
- new_link = is_link(f)
- if not changed or changed[-1] != f:
- # mention the file in the changelog if some flag changed,
- # even if there was no content change.
- old_exec = m1.execf(f)
- old_link = m1.linkf(f)
- if old_exec != new_exec or old_link != new_link:
- changed.append(f)
- m1.set(f, new_exec, new_link)
- except (OSError, IOError):
- if use_dirstate:
- self.ui.warn(_("trouble committing %s!\n") % f)
- raise
- else:
- remove.append(f)
+ # check in files
+ new = {}
+ linkrev = self.changelog.count()
+ commit.sort()
+ is_exec = util.execfunc(self.root, m1.execf)
+ is_link = util.linkfunc(self.root, m1.linkf)
+ for f in commit:
+ self.ui.note(f + "\n")
+ try:
+ new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed)
+ new_exec = is_exec(f)
+ new_link = is_link(f)
+ if not changed or changed[-1] != f:
+ # mention the file in the changelog if some
+ # flag changed, even if there was no content
+ # change.
+ old_exec = m1.execf(f)
+ old_link = m1.linkf(f)
+ if old_exec != new_exec or old_link != new_link:
+ changed.append(f)
+ m1.set(f, new_exec, new_link)
+ except (OSError, IOError):
+ if use_dirstate:
+ self.ui.warn(_("trouble committing %s!\n") % f)
+ raise
+ else:
+ remove.append(f)
- # update manifest
- m1.update(new)
- remove.sort()
- removed = []
+ # update manifest
+ m1.update(new)
+ remove.sort()
+ removed = []
- for f in remove:
- if f in m1:
- del m1[f]
- removed.append(f)
- elif f in m2:
- removed.append(f)
- mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0], (new, removed))
+ for f in remove:
+ if f in m1:
+ del m1[f]
+ removed.append(f)
+ elif f in m2:
+ removed.append(f)
+ mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0],
+ (new, removed))
- # add changeset
- new = new.keys()
- new.sort()
+ # add changeset
+ new = new.keys()
+ new.sort()
- user = user or self.ui.username()
- if not text or force_editor:
- edittext = []
- if text:
- edittext.append(text)
- edittext.append("")
- edittext.append("HG: user: %s" % user)
- if p2 != nullid:
- edittext.append("HG: branch merge")
- if branchname:
- edittext.append("HG: branch %s" % util.tolocal(branchname))
- edittext.extend(["HG: changed %s" % f for f in changed])
- edittext.extend(["HG: removed %s" % f for f in removed])
- if not changed and not remove:
- edittext.append("HG: no files changed")
- edittext.append("")
- # run editor in the repository root
- olddir = os.getcwd()
- os.chdir(self.root)
- text = self.ui.edit("\n".join(edittext), user)
- os.chdir(olddir)
+ user = user or self.ui.username()
+ if not text or force_editor:
+ edittext = []
+ if text:
+ edittext.append(text)
+ edittext.append("")
+ edittext.append("HG: user: %s" % user)
+ if p2 != nullid:
+ edittext.append("HG: branch merge")
+ if branchname:
+ edittext.append("HG: branch %s" % util.tolocal(branchname))
+ edittext.extend(["HG: changed %s" % f for f in changed])
+ edittext.extend(["HG: removed %s" % f for f in removed])
+ if not changed and not remove:
+ edittext.append("HG: no files changed")
+ edittext.append("")
+ # run editor in the repository root
+ olddir = os.getcwd()
+ os.chdir(self.root)
+ text = self.ui.edit("\n".join(edittext), user)
+ os.chdir(olddir)
- lines = [line.rstrip() for line in text.rstrip().splitlines()]
- while lines and not lines[0]:
- del lines[0]
- if not lines:
- return None
- text = '\n'.join(lines)
- if branchname:
- extra["branch"] = branchname
- n = self.changelog.add(mn, changed + removed, text, tr, p1, p2,
- user, date, extra)
- self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
- parent2=xp2)
- tr.close()
+ lines = [line.rstrip() for line in text.rstrip().splitlines()]
+ while lines and not lines[0]:
+ del lines[0]
+ if not lines:
+ return None
+ text = '\n'.join(lines)
+ if branchname:
+ extra["branch"] = branchname
+ n = self.changelog.add(mn, changed + removed, text, tr, p1, p2,
+ user, date, extra)
+ self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
+ parent2=xp2)
+ tr.close()
- if self.branchcache and "branch" in extra:
- self.branchcache[util.tolocal(extra["branch"])] = n
+ if self.branchcache and "branch" in extra:
+ self.branchcache[util.tolocal(extra["branch"])] = n
- if use_dirstate or update_dirstate:
- self.dirstate.setparents(n)
- if use_dirstate:
- self.dirstate.update(new, "n")
- self.dirstate.forget(removed)
+ if use_dirstate or update_dirstate:
+ self.dirstate.setparents(n)
+ if use_dirstate:
+ for f in new:
+ self.dirstate.normal(f)
+ for f in removed:
+ self.dirstate.forget(f)
- self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
- return n
+ self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
+ return n
+ finally:
+ del lock, wlock, tr
def walk(self, node=None, files=[], match=util.always, badmatch=None):
'''
@@ -841,7 +861,7 @@ class localrepository(repo.repository):
yield src, fn
def status(self, node1=None, node2=None, files=[], match=util.always,
- wlock=None, list_ignored=False, list_clean=False):
+ list_ignored=False, list_clean=False):
"""return status of files between two nodes or node and working directory
If node1 is None, use the first dirstate parent instead.
@@ -873,8 +893,6 @@ class localrepository(repo.repository):
# all the revisions in parent->child order.
mf1 = mfmatches(node1)
- mywlock = False
-
# are we comparing the working directory?
if not node2:
(lookup, modified, added, removed, deleted, unknown,
@@ -884,24 +902,30 @@ class localrepository(repo.repository):
# are we comparing working dir against its parent?
if compareworking:
if lookup:
+ fixup = []
# do a full compare of any files that might have changed
- mnode = self.changelog.read(self.dirstate.parents()[0])[0]
- getnode = lambda fn: (self.manifest.find(mnode, fn)[0] or
- nullid)
+ ctx = self.changectx()
for f in lookup:
- if fcmp(f, getnode):
+ if f not in ctx or ctx[f].cmp(self.wread(f)):
modified.append(f)
else:
+ fixup.append(f)
if list_clean:
clean.append(f)
- if not wlock and not mywlock:
- mywlock = True
- try:
- wlock = self.wlock(wait=0)
- except lock.LockException:
- pass
+
+ # update dirstate for files that are actually clean
+ if fixup:
+ wlock = None
+ try:
+ try:
+ wlock = self.wlock(False)
+ except lock.LockException:
+ pass
if wlock:
- self.dirstate.update([f], "n")
+ for f in fixup:
+ self.dirstate.normal(f)
+ finally:
+ del wlock
else:
# we are comparing working dir against non-parent
# generate a pseudo-manifest for the working dir
@@ -916,8 +940,6 @@ class localrepository(repo.repository):
if f in mf2:
del mf2[f]
- if mywlock and wlock:
- wlock.release()
else:
# we are comparing two revisions
mf2 = mfmatches(node2)
@@ -950,85 +972,98 @@ class localrepository(repo.repository):
l.sort()
return (modified, added, removed, deleted, unknown, ignored, clean)
- def add(self, list, wlock=None):
- if not wlock:
- wlock = self.wlock()
- for f in list:
- p = self.wjoin(f)
- try:
- st = os.lstat(p)
- except:
- self.ui.warn(_("%s does not exist!\n") % f)
- continue
- if st.st_size > 10000000:
- self.ui.warn(_("%s: files over 10MB may cause memory and"
- " performance problems\n"
- "(use 'hg revert %s' to unadd the file)\n")
- % (f, f))
- if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
- self.ui.warn(_("%s not added: only files and symlinks "
- "supported currently\n") % f)
- elif self.dirstate.state(f) in 'an':
- self.ui.warn(_("%s already tracked!\n") % f)
- else:
- self.dirstate.update([f], "a")
-
- def forget(self, list, wlock=None):
- if not wlock:
- wlock = self.wlock()
- for f in list:
- if self.dirstate.state(f) not in 'ai':
- self.ui.warn(_("%s not added!\n") % f)
- else:
- self.dirstate.forget([f])
-
- def remove(self, list, unlink=False, wlock=None):
- if unlink:
+ def add(self, list):
+ wlock = self.wlock()
+ try:
for f in list:
+ p = self.wjoin(f)
try:
- util.unlink(self.wjoin(f))
- except OSError, inst:
- if inst.errno != errno.ENOENT:
- raise
- if not wlock:
- wlock = self.wlock()
- for f in list:
- if unlink and os.path.exists(self.wjoin(f)):
- self.ui.warn(_("%s still exists!\n") % f)
- elif self.dirstate.state(f) == 'a':
- self.dirstate.forget([f])
- elif f not in self.dirstate:
- self.ui.warn(_("%s not tracked!\n") % f)
- else:
- self.dirstate.update([f], "r")
+ st = os.lstat(p)
+ except:
+ self.ui.warn(_("%s does not exist!\n") % f)
+ continue
+ if st.st_size > 10000000:
+ self.ui.warn(_("%s: files over 10MB may cause memory and"
+ " performance problems\n"
+ "(use 'hg revert %s' to unadd the file)\n")
+ % (f, f))
+ if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
+ self.ui.warn(_("%s not added: only files and symlinks "
+ "supported currently\n") % f)
+ elif self.dirstate[f] in 'an':
+ self.ui.warn(_("%s already tracked!\n") % f)
+ else:
+ self.dirstate.add(f)
+ finally:
+ del wlock
- def undelete(self, list, wlock=None):
- p = self.dirstate.parents()[0]
- mn = self.changelog.read(p)[0]
- m = self.manifest.read(mn)
- if not wlock:
+ def forget(self, list):
+ wlock = self.wlock()
+ try:
+ for f in list:
+ if self.dirstate[f] != 'a':
+ self.ui.warn(_("%s not added!\n") % f)
+ else:
+ self.dirstate.forget(f)
+ finally:
+ del wlock
+
+ def remove(self, list, unlink=False):
+ wlock = None
+ try:
+ if unlink:
+ for f in list:
+ try:
+ util.unlink(self.wjoin(f))
+ except OSError, inst:
+ if inst.errno != errno.ENOENT:
+ raise
wlock = self.wlock()
- for f in list:
- if self.dirstate.state(f) not in "r":
- self.ui.warn("%s not removed!\n" % f)
- else:
- t = self.file(f).read(m[f])
- self.wwrite(f, t, m.flags(f))
- self.dirstate.update([f], "n")
+ for f in list:
+ if unlink and os.path.exists(self.wjoin(f)):
+ self.ui.warn(_("%s still exists!\n") % f)
+ elif self.dirstate[f] == 'a':
+ self.dirstate.forget(f)
+ elif f not in self.dirstate:
+ self.ui.warn(_("%s not tracked!\n") % f)
+ else:
+ self.dirstate.remove(f)
+ finally:
+ del wlock
- def copy(self, source, dest, wlock=None):
- p = self.wjoin(dest)
- if not (os.path.exists(p) or os.path.islink(p)):
- self.ui.warn(_("%s does not exist!\n") % dest)
- elif not (os.path.isfile(p) or os.path.islink(p)):
- self.ui.warn(_("copy failed: %s is not a file or a "
- "symbolic link\n") % dest)
- else:
- if not wlock:
+ def undelete(self, list):
+ wlock = None
+ try:
+ p = self.dirstate.parents()[0]
+ mn = self.changelog.read(p)[0]
+ m = self.manifest.read(mn)
+ wlock = self.wlock()
+ for f in list:
+ if self.dirstate[f] != 'r':
+ self.ui.warn("%s not removed!\n" % f)
+ else:
+ t = self.file(f).read(m[f])
+ self.wwrite(f, t, m.flags(f))
+ self.dirstate.normal(f)
+ finally:
+ del wlock
+
+ def copy(self, source, dest):
+ wlock = None
+ try:
+ p = self.wjoin(dest)
+ if not (os.path.exists(p) or os.path.islink(p)):
+ self.ui.warn(_("%s does not exist!\n") % dest)
+ elif not (os.path.isfile(p) or os.path.islink(p)):
+ self.ui.warn(_("copy failed: %s is not a file or a "
+ "symbolic link\n") % dest)
+ else:
wlock = self.wlock()
- if self.dirstate.state(dest) == '?':
- self.dirstate.update([dest], "a")
- self.dirstate.copy(source, dest)
+ if dest not in self.dirstate:
+ self.dirstate.add(dest)
+ self.dirstate.copy(source, dest)
+ finally:
+ del wlock
def heads(self, start=None):
heads = self.changelog.heads(start)
@@ -1305,12 +1340,8 @@ class localrepository(repo.repository):
else:
return subset
- def pull(self, remote, heads=None, force=False, lock=None):
- mylock = False
- if not lock:
- lock = self.lock()
- mylock = True
-
+ def pull(self, remote, heads=None, force=False):
+ lock = self.lock()
try:
fetch = self.findincoming(remote, force=force)
if fetch == [nullid]:
@@ -1328,8 +1359,7 @@ class localrepository(repo.repository):
cg = remote.changegroupsubset(fetch, heads, 'pull')
return self.addchangegroup(cg, 'pull', remote.url())
finally:
- if mylock:
- lock.release()
+ del lock
def push(self, remote, force=False, revs=None):
# there are two ways to push to remote repo:
@@ -1402,12 +1432,14 @@ class localrepository(repo.repository):
def push_addchangegroup(self, remote, force, revs):
lock = remote.lock()
-
- ret = self.prepush(remote, force, revs)
- if ret[0] is not None:
- cg, remote_heads = ret
- return remote.addchangegroup(cg, 'push', self.url())
- return ret[1]
+ try:
+ ret = self.prepush(remote, force, revs)
+ if ret[0] is not None:
+ cg, remote_heads = ret
+ return remote.addchangegroup(cg, 'push', self.url())
+ return ret[1]
+ finally:
+ del lock
def push_unbundle(self, remote, force, revs):
# local repo finds heads on server, finds out what revs it
@@ -1791,65 +1823,67 @@ class localrepository(repo.repository):
changesets = files = revisions = 0
- tr = self.transaction()
-
# write changelog data to temp files so concurrent readers will not see
# inconsistent view
cl = self.changelog
cl.delayupdate()
oldheads = len(cl.heads())
- # pull off the changeset group
- self.ui.status(_("adding changesets\n"))
- cor = cl.count() - 1
- chunkiter = changegroup.chunkiter(source)
- if cl.addgroup(chunkiter, csmap, tr, 1) is None:
- raise util.Abort(_("received changelog group is empty"))
- cnr = cl.count() - 1
- changesets = cnr - cor
+ tr = self.transaction()
+ try:
+ # pull off the changeset group
+ self.ui.status(_("adding changesets\n"))
+ cor = cl.count() - 1
+ chunkiter = changegroup.chunkiter(source)
+ if cl.addgroup(chunkiter, csmap, tr, 1) is None:
+ raise util.Abort(_("received changelog group is empty"))
+ cnr = cl.count() - 1
+ changesets = cnr - cor
- # pull off the manifest group
- self.ui.status(_("adding manifests\n"))
- chunkiter = changegroup.chunkiter(source)
- # no need to check for empty manifest group here:
- # if the result of the merge of 1 and 2 is the same in 3 and 4,
- # no new manifest will be created and the manifest group will
- # be empty during the pull
- self.manifest.addgroup(chunkiter, revmap, tr)
+ # pull off the manifest group
+ self.ui.status(_("adding manifests\n"))
+ chunkiter = changegroup.chunkiter(source)
+ # no need to check for empty manifest group here:
+ # if the result of the merge of 1 and 2 is the same in 3 and 4,
+ # no new manifest will be created and the manifest group will
+ # be empty during the pull
+ self.manifest.addgroup(chunkiter, revmap, tr)
- # process the files
- self.ui.status(_("adding file changes\n"))
- while 1:
- f = changegroup.getchunk(source)
- if not f:
- break
- self.ui.debug(_("adding %s revisions\n") % f)
- fl = self.file(f)
- o = fl.count()
- chunkiter = changegroup.chunkiter(source)
- if fl.addgroup(chunkiter, revmap, tr) is None:
- raise util.Abort(_("received file revlog group is empty"))
- revisions += fl.count() - o
- files += 1
+ # process the files
+ self.ui.status(_("adding file changes\n"))
+ while 1:
+ f = changegroup.getchunk(source)
+ if not f:
+ break
+ self.ui.debug(_("adding %s revisions\n") % f)
+ fl = self.file(f)
+ o = fl.count()
+ chunkiter = changegroup.chunkiter(source)
+ if fl.addgroup(chunkiter, revmap, tr) is None:
+ raise util.Abort(_("received file revlog group is empty"))
+ revisions += fl.count() - o
+ files += 1
+
+ # make changelog see real files again
+ cl.finalize(tr)
- # make changelog see real files again
- cl.finalize(tr)
+ newheads = len(self.changelog.heads())
+ heads = ""
+ if oldheads and newheads != oldheads:
+ heads = _(" (%+d heads)") % (newheads - oldheads)
- newheads = len(self.changelog.heads())
- heads = ""
- if oldheads and newheads != oldheads:
- heads = _(" (%+d heads)") % (newheads - oldheads)
+ self.ui.status(_("added %d changesets"
+ " with %d changes to %d files%s\n")
+ % (changesets, revisions, files, heads))
- self.ui.status(_("added %d changesets"
- " with %d changes to %d files%s\n")
- % (changesets, revisions, files, heads))
+ if changesets > 0:
+ self.hook('pretxnchangegroup', throw=True,
+ node=hex(self.changelog.node(cor+1)), source=srctype,
+ url=url)
- if changesets > 0:
- self.hook('pretxnchangegroup', throw=True,
- node=hex(self.changelog.node(cor+1)), source=srctype,
- url=url)
-
- tr.close()
+ tr.close()
+ finally:
+ del tr
if changesets > 0:
self.hook("changegroup", node=hex(self.changelog.node(cor+1)),
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -447,25 +447,25 @@ def recordupdates(repo, action, branchme
f, m = a[:2]
if m == "r": # remove
if branchmerge:
- repo.dirstate.update([f], 'r')
+ repo.dirstate.remove(f)
else:
- repo.dirstate.forget([f])
+ repo.dirstate.forget(f)
elif m == "f": # forget
- repo.dirstate.forget([f])
+ repo.dirstate.forget(f)
elif m == "g": # get
if branchmerge:
- repo.dirstate.update([f], 'n', st_mtime=-1)
+ repo.dirstate.normaldirty(f)
else:
- repo.dirstate.update([f], 'n')
+ repo.dirstate.normal(f)
elif m == "m": # merge
f2, fd, flag, move = a[2:]
if branchmerge:
# We've done a branch merge, mark this file as merged
# so that we properly record the merger later
- repo.dirstate.update([fd], 'm')
+ repo.dirstate.merge(fd)
if f != f2: # copy/rename
if move:
- repo.dirstate.update([f], 'r')
+ repo.dirstate.remove(f)
if f != fd:
repo.dirstate.copy(f, fd)
else:
@@ -476,95 +476,94 @@ def recordupdates(repo, action, branchme
# of that file some time in the past. Thus our
# merge will appear as a normal local file
# modification.
- repo.dirstate.update([fd], 'n', st_size=-1, st_mtime=-1)
+ repo.dirstate.normaldirty(fd)
if move:
- repo.dirstate.forget([f])
+ repo.dirstate.forget(f)
elif m == "d": # directory rename
f2, fd, flag = a[2:]
if not f2 and f not in repo.dirstate:
# untracked file moved
continue
if branchmerge:
- repo.dirstate.update([fd], 'a')
+ repo.dirstate.add(fd)
if f:
- repo.dirstate.update([f], 'r')
+ repo.dirstate.remove(f)
repo.dirstate.copy(f, fd)
if f2:
repo.dirstate.copy(f2, fd)
else:
- repo.dirstate.update([fd], 'n')
+ repo.dirstate.normal(fd)
if f:
- repo.dirstate.forget([f])
+ repo.dirstate.forget(f)
-def update(repo, node, branchmerge, force, partial, wlock):
+def update(repo, node, branchmerge, force, partial):
"""
Perform a merge between the working directory and the given node
branchmerge = whether to merge between branches
force = whether to force branch merging or file overwriting
partial = a function to filter file lists (dirstate not updated)
- wlock = working dir lock, if already held
"""
- if not wlock:
- wlock = repo.wlock()
-
- wc = repo.workingctx()
- if node is None:
- # tip of current branch
- try:
- node = repo.branchtags()[wc.branch()]
- except KeyError:
- raise util.Abort(_("branch %s not found") % wc.branch())
- overwrite = force and not branchmerge
- forcemerge = force and branchmerge
- pl = wc.parents()
- p1, p2 = pl[0], repo.changectx(node)
- pa = p1.ancestor(p2)
- fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
- fastforward = False
+ wlock = repo.wlock()
+ try:
+ wc = repo.workingctx()
+ if node is None:
+ # tip of current branch
+ try:
+ node = repo.branchtags()[wc.branch()]
+ except KeyError:
+ raise util.Abort(_("branch %s not found") % wc.branch())
+ overwrite = force and not branchmerge
+ forcemerge = force and branchmerge
+ pl = wc.parents()
+ p1, p2 = pl[0], repo.changectx(node)
+ pa = p1.ancestor(p2)
+ fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
+ fastforward = False
- ### check phase
- if not overwrite and len(pl) > 1:
- raise util.Abort(_("outstanding uncommitted merges"))
- if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
- if branchmerge:
- if p1.branch() != p2.branch() and pa != p2:
- fastforward = True
- else:
- raise util.Abort(_("there is nothing to merge, just use "
- "'hg update' or look at 'hg heads'"))
- elif not (overwrite or branchmerge):
- raise util.Abort(_("update spans branches, use 'hg merge' "
- "or 'hg update -C' to lose changes"))
- if branchmerge and not forcemerge:
- if wc.files():
- raise util.Abort(_("outstanding uncommitted changes"))
+ ### check phase
+ if not overwrite and len(pl) > 1:
+ raise util.Abort(_("outstanding uncommitted merges"))
+ if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
+ if branchmerge:
+ if p1.branch() != p2.branch() and pa != p2:
+ fastforward = True
+ else:
+ raise util.Abort(_("there is nothing to merge, just use "
+ "'hg update' or look at 'hg heads'"))
+ elif not (overwrite or branchmerge):
+ raise util.Abort(_("update spans branches, use 'hg merge' "
+ "or 'hg update -C' to lose changes"))
+ if branchmerge and not forcemerge:
+ if wc.files():
+ raise util.Abort(_("outstanding uncommitted changes"))
- ### calculate phase
- action = []
- if not force:
- checkunknown(wc, p2)
- if not util.checkfolding(repo.path):
- checkcollision(p2)
- if not branchmerge:
- action += forgetremoved(wc, p2)
- action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
+ ### calculate phase
+ action = []
+ if not force:
+ checkunknown(wc, p2)
+ if not util.checkfolding(repo.path):
+ checkcollision(p2)
+ if not branchmerge:
+ action += forgetremoved(wc, p2)
+ action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
- ### apply phase
- if not branchmerge: # just jump to the new rev
- fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
- if not partial:
- repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
+ ### apply phase
+ if not branchmerge: # just jump to the new rev
+ fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
+ if not partial:
+ repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
- stats = applyupdates(repo, action, wc, p2)
+ stats = applyupdates(repo, action, wc, p2)
- if not partial:
- recordupdates(repo, action, branchmerge)
- repo.dirstate.setparents(fp1, fp2)
- if not branchmerge and not fastforward:
- repo.dirstate.setbranch(p2.branch())
- repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
+ if not partial:
+ recordupdates(repo, action, branchmerge)
+ repo.dirstate.setparents(fp1, fp2)
+ if not branchmerge and not fastforward:
+ repo.dirstate.setbranch(p2.branch())
+ repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
- return stats
-
+ return stats
+ finally:
+ del wlock
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -1013,7 +1013,7 @@ def diffopts(ui, opts={}, untrusted=Fals
ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'))
-def updatedir(ui, repo, patches, wlock=None):
+def updatedir(ui, repo, patches):
'''Update dirstate after patch application according to metadata'''
if not patches:
return
@@ -1035,11 +1035,11 @@ def updatedir(ui, repo, patches, wlock=N
for src, dst, after in copies:
if not after:
copyfile(src, dst, repo.root)
- repo.copy(src, dst, wlock=wlock)
+ repo.copy(src, dst)
removes = removes.keys()
if removes:
removes.sort()
- repo.remove(removes, True, wlock=wlock)
+ repo.remove(removes, True)
for f in patches:
ctype, gp = patches[f]
if gp and gp.mode:
@@ -1050,7 +1050,7 @@ def updatedir(ui, repo, patches, wlock=N
repo.wwrite(gp.path, '', x and 'x' or '')
else:
util.set_exec(dst, x)
- cmdutil.addremove(repo, cfiles, wlock=wlock)
+ cmdutil.addremove(repo, cfiles)
files = patches.keys()
files.extend([r for r in removes if r not in files])
files.sort()
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -281,6 +281,17 @@ class lazymap(object):
class RevlogError(Exception): pass
class LookupError(RevlogError): pass
+def getoffset(q):
+ if q & 0xFFFF:
+ raise RevlogError(_('incompatible revision flag %x') % q)
+ return int(q >> 16)
+
+def gettype(q):
+ return int(q & 0xFFFF)
+
+def offset_type(offset, type):
+ return long(long(offset) << 16 | type)
+
class revlog(object):
"""
the underlying revision storage object
@@ -325,14 +336,16 @@ class revlog(object):
self.defversion = opener.defversion
if self.defversion & REVLOGNG:
self.defversion |= REVLOGNGINLINEDATA
- self.load()
+ self._load()
- def load(self):
+ def _load(self):
v = self.defversion
try:
f = self.opener(self.indexfile)
i = f.read(4)
f.seek(0)
+ if len(i) > 0:
+ v = struct.unpack(versionformat, i)[0]
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
@@ -351,8 +364,6 @@ class revlog(object):
and st.st_size == oldst.st_size):
return
self.indexstat = st
- if len(i) > 0:
- v = struct.unpack(versionformat, i)[0]
flags = v & ~0xFFFF
fmt = v & 0xFFFF
if fmt == REVLOGV0:
@@ -375,29 +386,28 @@ class revlog(object):
shaoffset = ngshaoffset
if i:
- if (lazyparser.safe_to_use and not self.inlinedata() and
+ if (lazyparser.safe_to_use and not self._inline() and
st and st.st_size > 10000):
# big index, let's parse it on demand
parser = lazyparser(f, st.st_size, self.indexformat, shaoffset)
self.index = lazyindex(parser)
self.nodemap = lazymap(parser)
else:
- self.parseindex(f, st)
+ self._parseindex(f, st)
if self.version != REVLOGV0:
e = list(self.index[0])
- type = self.ngtype(e[0])
- e[0] = self.offset_type(0, type)
+ type = gettype(e[0])
+ e[0] = offset_type(0, type)
self.index[0] = e
else:
self.nodemap = {nullid: nullrev}
self.index = []
-
- def parseindex(self, fp, st):
+ def _parseindex(self, fp, st):
s = struct.calcsize(self.indexformat)
self.index = []
self.nodemap = {nullid: nullrev}
- inline = self.inlinedata()
+ inline = self._inline()
n = 0
leftover = None
while True:
@@ -408,7 +418,7 @@ class revlog(object):
data = fp.read()
if not data:
break
- if n == 0 and self.inlinedata():
+ if n == 0 and self._inline():
# cache the first chunk
self.chunkcache = (0, data)
if leftover:
@@ -438,37 +448,26 @@ class revlog(object):
break
- def ngoffset(self, q):
- if q & 0xFFFF:
- raise RevlogError(_('%s: incompatible revision flag %x') %
- (self.indexfile, q))
- return long(q >> 16)
-
- def ngtype(self, q):
- return int(q & 0xFFFF)
-
- def offset_type(self, offset, type):
- return long(long(offset) << 16 | type)
-
- def loadindex(self, start, end):
+ def _loadindex(self, start, end):
"""load a block of indexes all at once from the lazy parser"""
if isinstance(self.index, lazyindex):
self.index.p.loadindex(start, end)
- def loadindexmap(self):
+ def _loadindexmap(self):
"""loads both the map and the index from the lazy parser"""
if isinstance(self.index, lazyindex):
p = self.index.p
p.loadindex()
self.nodemap = p.map
- def loadmap(self):
+ def _loadmap(self):
"""loads the map from the lazy parser"""
if isinstance(self.nodemap, lazymap):
self.nodemap.p.loadmap()
self.nodemap = self.nodemap.p.map
- def inlinedata(self): return self.version & REVLOGNGINLINEDATA
+ def _inline(self): return self.version & REVLOGNGINLINEDATA
+
def tip(self): return self.node(len(self.index) - 1)
def count(self): return len(self.index)
def node(self, rev):
@@ -498,7 +497,7 @@ class revlog(object):
if rev == nullrev:
return 0
if self.version != REVLOGV0:
- return self.ngoffset(self.index[rev][0])
+ return getoffset(self.index[rev][0])
return self.index[rev][0]
def end(self, rev): return self.start(rev) + self.length(rev)
@@ -832,14 +831,6 @@ class revlog(object):
p1, p2 = self.parents(node)
return hash(text, p1, p2) != node
- def makenode(self, node, text):
- """calculate a file nodeid for text, descended or possibly
- unchanged from node"""
-
- if self.cmp(node, text):
- return hash(text, node, nullid)
- return node
-
def diff(self, a, b):
"""return a delta between two revisions"""
return mdiff.textdiff(a, b)
@@ -850,7 +841,7 @@ class revlog(object):
def chunk(self, rev, df=None, cachelen=4096):
start, length = self.start(rev), self.length(rev)
- inline = self.inlinedata()
+ inline = self._inline()
if inline:
start += (rev + 1) * struct.calcsize(self.indexformat)
end = start + length
@@ -908,7 +899,7 @@ class revlog(object):
rev = self.rev(node)
base = self.base(rev)
- if self.inlinedata():
+ if self._inline():
# we probably have the whole chunk cached
df = None
else:
@@ -918,9 +909,9 @@ class revlog(object):
if self.cache and self.cache[1] >= base and self.cache[1] < rev:
base = self.cache[1]
text = self.cache[2]
- self.loadindex(base, rev + 1)
+ self._loadindex(base, rev + 1)
else:
- self.loadindex(base, rev + 1)
+ self._loadindex(base, rev + 1)
text = self.chunk(base, df=df)
bins = []
@@ -938,7 +929,7 @@ class revlog(object):
return text
def checkinlinesize(self, tr, fp=None):
- if not self.inlinedata():
+ if not self._inline():
return
if not fp:
fp = self.opener(self.indexfile, 'r')
@@ -995,7 +986,7 @@ class revlog(object):
p1, p2 - the parent nodeids of the revision
d - an optional precomputed delta
"""
- if not self.inlinedata():
+ if not self._inline():
dfh = self.opener(self.datafile, "a")
else:
dfh = None
@@ -1042,14 +1033,14 @@ class revlog(object):
if self.version == REVLOGV0:
e = (offset, l, base, link, p1, p2, node)
else:
- e = (self.offset_type(offset, 0), l, len(text),
+ e = (offset_type(offset, 0), l, len(text),
base, link, self.rev(p1), self.rev(p2), node)
self.index.append(e)
self.nodemap[node] = n
entry = struct.pack(self.indexformat, *e)
- if not self.inlinedata():
+ if not self._inline():
transaction.add(self.datafile, offset)
transaction.add(self.indexfile, n * len(entry))
if data[0]:
@@ -1067,7 +1058,7 @@ class revlog(object):
ifh.write(entry)
- if self.inlinedata():
+ if self._inline():
ifh.write(data[0])
ifh.write(data[1])
self.checkinlinesize(transaction, ifh)
@@ -1144,7 +1135,7 @@ class revlog(object):
ifh = self.opener(self.indexfile, "a+")
ifh.seek(0, 2)
transaction.add(self.indexfile, ifh.tell(), self.count())
- if self.inlinedata():
+ if self._inline():
dfh = None
else:
transaction.add(self.datafile, end)
@@ -1193,7 +1184,7 @@ class revlog(object):
text = self.patches(text, [delta])
chk = self._addrevision(text, transaction, link, p1, p2, None,
ifh, dfh)
- if not dfh and not self.inlinedata():
+ if not dfh and not self._inline():
# addrevision switched from inline to conventional
# reopen the index
dfh = self.opener(self.datafile, "a")
@@ -1205,15 +1196,15 @@ class revlog(object):
if self.version == REVLOGV0:
e = (end, len(cdelta), base, link, p1, p2, node)
else:
- e = (self.offset_type(end, 0), len(cdelta), textlen, base,
+ e = (offset_type(end, 0), len(cdelta), textlen, base,
link, self.rev(p1), self.rev(p2), node)
self.index.append(e)
self.nodemap[node] = r
- if self.inlinedata():
+ if self._inline():
ifh.write(struct.pack(self.indexformat, *e))
ifh.write(cdelta)
self.checkinlinesize(transaction, ifh)
- if not self.inlinedata():
+ if not self._inline():
dfh = self.opener(self.datafile, "a")
ifh = self.opener(self.indexfile, "a")
else:
@@ -1232,7 +1223,7 @@ class revlog(object):
return
if isinstance(self.index, lazyindex):
- self.loadindexmap()
+ self._loadindexmap()
# When stripping away a revision, we need to make sure it
# does not actually belong to an older changeset.
@@ -1245,7 +1236,7 @@ class revlog(object):
# first truncate the files on disk
end = self.start(rev)
- if not self.inlinedata():
+ if not self._inline():
df = self.opener(self.datafile, "a")
df.truncate(end)
end = rev * struct.calcsize(self.indexformat)
@@ -1285,7 +1276,7 @@ class revlog(object):
s = struct.calcsize(self.indexformat)
i = actual / s
di = actual - (i * s)
- if self.inlinedata():
+ if self._inline():
databytes = 0
for r in xrange(self.count()):
databytes += self.length(r)
--- a/mercurial/streamclone.py
+++ b/mercurial/streamclone.py
@@ -66,22 +66,25 @@ def stream_out(repo, fileobj, untrusted=
# get consistent snapshot of repo. lock during scan so lock not
# needed while we stream, and commits can happen.
+ lock = None
try:
- repolock = repo.lock()
- except (lock.LockHeld, lock.LockUnavailable), inst:
- repo.ui.warn('locking the repository failed: %s\n' % (inst,))
- fileobj.write('2\n')
- return
+ try:
+ repolock = repo.lock()
+ except (lock.LockHeld, lock.LockUnavailable), inst:
+ repo.ui.warn('locking the repository failed: %s\n' % (inst,))
+ fileobj.write('2\n')
+ return
- fileobj.write('0\n')
- repo.ui.debug('scanning\n')
- entries = []
- total_bytes = 0
- for name, size in walkrepo(repo.spath):
- name = repo.decodefn(util.pconvert(name))
- entries.append((name, size))
- total_bytes += size
- repolock.release()
+ fileobj.write('0\n')
+ repo.ui.debug('scanning\n')
+ entries = []
+ total_bytes = 0
+ for name, size in walkrepo(repo.spath):
+ name = repo.decodefn(util.pconvert(name))
+ entries.append((name, size))
+ total_bytes += size
+ finally:
+ del repolock
repo.ui.debug('%d files, %d bytes to transfer\n' %
(len(entries), total_bytes))
--- a/mercurial/verify.py
+++ b/mercurial/verify.py
@@ -10,6 +10,13 @@ from i18n import _
import revlog, mdiff
def verify(repo):
+ lock = repo.lock()
+ try:
+ return _verify(repo)
+ finally:
+ del lock
+
+def _verify(repo):
filelinkrevs = {}
filenodes = {}
changesets = revisions = files = 0
@@ -17,8 +24,6 @@ def verify(repo):
warnings = [0]
neededmanifests = {}
- lock = repo.lock()
-
def err(msg):
repo.ui.warn(msg + "\n")
errors[0] += 1
--- a/tests/test-abort-checkin.out
+++ b/tests/test-abort-checkin.out
@@ -1,8 +1,8 @@
error: pretxncommit.nocommits hook failed: no commits allowed
-abort: no commits allowed
transaction abort!
rollback completed
+abort: no commits allowed
error: pretxncommit.nocommits hook failed: no commits allowed
-abort: no commits allowed
transaction abort!
rollback completed
+abort: no commits allowed
--- a/tests/test-acl.out
+++ b/tests/test-acl.out
@@ -129,9 +129,9 @@ acl: acl.allow enabled, 0 entries for us
acl: acl.deny not enabled
acl: user fred not allowed on foo/file.txt
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
-abort: acl: access denied for changeset ef1ea85a6374
transaction abort!
rollback completed
+abort: acl: access denied for changeset ef1ea85a6374
no rollback information available
0:6675d58eff77
@@ -170,9 +170,9 @@ acl: allowing changeset ef1ea85a6374
acl: allowing changeset f9cafe1212c8
acl: user fred not allowed on quux/file.py
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
-abort: acl: access denied for changeset 911600dab2ae
transaction abort!
rollback completed
+abort: acl: access denied for changeset 911600dab2ae
no rollback information available
0:6675d58eff77
@@ -210,9 +210,9 @@ acl: acl.allow enabled, 0 entries for us
acl: acl.deny enabled, 0 entries for user barney
acl: user barney not allowed on foo/file.txt
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
-abort: acl: access denied for changeset ef1ea85a6374
transaction abort!
rollback completed
+abort: acl: access denied for changeset ef1ea85a6374
no rollback information available
0:6675d58eff77
@@ -253,9 +253,9 @@ acl: allowing changeset ef1ea85a6374
acl: allowing changeset f9cafe1212c8
acl: user fred not allowed on quux/file.py
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
-abort: acl: access denied for changeset 911600dab2ae
transaction abort!
rollback completed
+abort: acl: access denied for changeset 911600dab2ae
no rollback information available
0:6675d58eff77
@@ -296,9 +296,9 @@ acl: acl.deny enabled, 2 entries for use
acl: allowing changeset ef1ea85a6374
acl: user fred denied on foo/Bar/file.txt
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
-abort: acl: access denied for changeset f9cafe1212c8
transaction abort!
rollback completed
+abort: acl: access denied for changeset f9cafe1212c8
no rollback information available
0:6675d58eff77
@@ -338,9 +338,9 @@ acl: acl.allow enabled, 0 entries for us
acl: acl.deny enabled, 0 entries for user barney
acl: user barney not allowed on foo/file.txt
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
-abort: acl: access denied for changeset ef1ea85a6374
transaction abort!
rollback completed
+abort: acl: access denied for changeset ef1ea85a6374
no rollback information available
0:6675d58eff77
@@ -427,9 +427,9 @@ acl: allowing changeset ef1ea85a6374
acl: allowing changeset f9cafe1212c8
acl: user wilma not allowed on quux/file.py
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
-abort: acl: access denied for changeset 911600dab2ae
transaction abort!
rollback completed
+abort: acl: access denied for changeset 911600dab2ae
no rollback information available
0:6675d58eff77
@@ -471,9 +471,9 @@ adding quux/file.py revisions
added 3 changesets with 3 changes to 3 files
calling hook pretxnchangegroup.acl: hgext.acl.hook
error: pretxnchangegroup.acl hook failed: unable to open ../acl.config: No such file or directory
-abort: unable to open ../acl.config: No such file or directory
transaction abort!
rollback completed
+abort: unable to open ../acl.config: No such file or directory
no rollback information available
0:6675d58eff77
@@ -524,9 +524,9 @@ acl: allowing changeset ef1ea85a6374
acl: allowing changeset f9cafe1212c8
acl: user betty not allowed on quux/file.py
error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
-abort: acl: access denied for changeset 911600dab2ae
transaction abort!
rollback completed
+abort: acl: access denied for changeset 911600dab2ae
no rollback information available
0:6675d58eff77
--- a/tests/test-clone-pull-corruption.out
+++ b/tests/test-clone-pull-corruption.out
@@ -1,8 +1,8 @@
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
pulling from ../source
-abort: pretxncommit hook exited with status 1
transaction abort!
rollback completed
+abort: pretxncommit hook exited with status 1
searching for changes
adding changesets
adding manifests
--- a/tests/test-committer.out
+++ b/tests/test-committer.out
@@ -22,7 +22,7 @@ user: foo@bar.com
date: Mon Jan 12 13:46:40 1970 +0000
summary: commit-1
-abort: Please specify a username.
transaction abort!
rollback completed
+abort: Please specify a username.
No username found, using user@host instead
--- a/tests/test-hook.out
+++ b/tests/test-hook.out
@@ -60,9 +60,9 @@ precommit hook: HG_PARENT1=8ea2ef7ad3e8c
pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
5:fad284daf8c0
pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
-abort: pretxncommit.forbid1 hook exited with status 1
transaction abort!
rollback completed
+abort: pretxncommit.forbid1 hook exited with status 1
4:8ea2ef7ad3e8
precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
@@ -86,9 +86,9 @@ adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
-abort: pretxnchangegroup.forbid1 hook exited with status 1
transaction abort!
rollback completed
+abort: pretxnchangegroup.forbid1 hook exited with status 1
3:4c52fb2e4022
preoutgoing hook: HG_SOURCE=pull
outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull