--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -516,28 +516,34 @@ class localrepository(repo.repository):
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:
- 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"))
+ try:
+ if not wlock:
+ 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"))
+ finally:
+ del wlock, lock
def invalidate(self):
for a in "changelog manifest".split():
@@ -639,164 +645,169 @@ class localrepository(repo.repository):
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()
+ 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[f]
- if s in 'nma':
- 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)
+ xp1 = hex(p1)
+ if p2 == nullid: xp2 = ''
+ else: xp2 = hex(p2)
- self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
+ self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
- if not wlock:
- wlock = self.wlock()
- if not lock:
- lock = self.lock()
- tr = self.transaction()
+ if not wlock:
+ wlock = self.wlock()
+ if not lock:
+ lock = self.lock()
+ 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:
- for f in new:
- self.dirstate.normal(f)
- for f in removed:
- self.dirstate.forget(f)
+ 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):
'''
@@ -895,18 +906,18 @@ class localrepository(repo.repository):
# update dirstate for files that are actually clean
if fixup:
- cleanup = False
- if not wlock:
- try:
- wlock = self.wlock(False)
- cleanup = True
- except lock.LockException:
- pass
- if wlock:
- for f in fixup:
- self.dirstate.normal(f)
- if cleanup:
- wlock.release()
+ fixlock = wlock
+ try:
+ if not fixlock:
+ try:
+ fixlock = self.wlock(False)
+ except lock.LockException:
+ pass
+ if fixlock:
+ for f in fixup:
+ self.dirstate.normal(f)
+ finally:
+ del fixlock
else:
# we are comparing working dir against non-parent
# generate a pseudo-manifest for the working dir
@@ -954,84 +965,99 @@ class localrepository(repo.repository):
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[f] in 'an':
- self.ui.warn(_("%s already tracked!\n") % f)
- else:
- self.dirstate.add(f)
+ try:
+ 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[f] in 'an':
+ self.ui.warn(_("%s already tracked!\n") % f)
+ else:
+ self.dirstate.add(f)
+ finally:
+ del wlock
def forget(self, list, wlock=None):
- if not wlock:
- wlock = self.wlock()
- for f in list:
- if self.dirstate[f] != 'a':
- self.ui.warn(_("%s not added!\n") % f)
- else:
- self.dirstate.forget(f)
+ try:
+ if not wlock:
+ wlock = self.wlock()
+ 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):
- if unlink:
+ try:
+ if unlink:
+ for f in list:
+ 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:
- 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[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)
+ 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 undelete(self, list, wlock=None):
- p = self.dirstate.parents()[0]
- mn = self.changelog.read(p)[0]
- m = self.manifest.read(mn)
- if not wlock:
- 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)
+ try:
+ p = self.dirstate.parents()[0]
+ mn = self.changelog.read(p)[0]
+ m = self.manifest.read(mn)
+ if not wlock:
+ 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):
- 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:
- wlock = self.wlock()
- if dest not in self.dirstate:
- self.dirstate.add(dest)
- self.dirstate.copy(source, dest)
+ 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:
+ if not wlock:
+ wlock = self.wlock()
+ 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)
@@ -1309,12 +1335,9 @@ class localrepository(repo.repository):
return subset
def pull(self, remote, heads=None, force=False, lock=None):
- mylock = False
- if not lock:
- lock = self.lock()
- mylock = True
-
try:
+ if not lock:
+ lock = self.lock()
fetch = self.findincoming(remote, force=force)
if fetch == [nullid]:
self.ui.status(_("requesting all changes\n"))
@@ -1331,8 +1354,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:
@@ -1405,12 +1427,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
@@ -1794,65 +1818,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)),