# HG changeset patch # User Brendan Cully # Date 1161722541 25200 # Node ID bd8339976504f6b593a6c4486970a437bc435328 # Parent e0db0b7934f2d21b396b236ada6ebd9de70d560d# Parent ceaa3fefc10c5d4a6684d4720b6c9e776b817f1f Merge with mpm diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -151,7 +151,10 @@ class filectx(object): if '_fileid' in self.__dict__: self._filenode = self._filelog.lookup(self._fileid) else: - self._filenode = self._changectx.filenode(self._path) + try: + self._filenode = self._changectx.filenode(self._path) + except: + self._filenode = self._filerev = None except revlog.RevlogError, inst: raise repo.LookupError(str(inst)) return self._filenode @@ -162,7 +165,7 @@ class filectx(object): raise AttributeError, name def __nonzero__(self): - return self._filerev != nullid + return self._filenode != None def __str__(self): return "%s@%s" % (self.path(), short(self.node())) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -47,6 +47,7 @@ class localrepository(repo.repository): self.origroot = path self.ui = ui.ui(parentui=parentui) self.opener = util.opener(self.path) + self.sopener = util.opener(self.path) self.wopener = util.opener(self.root) try: @@ -66,8 +67,8 @@ class localrepository(repo.repository): flags = revlog.REVLOG_DEFAULT_FLAGS v = self.revlogversion | flags - self.manifest = manifest.manifest(self.opener, v) - self.changelog = changelog.changelog(self.opener, v) + self.manifest = manifest.manifest(self.sopener, v) + self.changelog = changelog.changelog(self.sopener, v) # the changelog might not have the inline index flag # on. If the format of the changelog is the same as found in @@ -245,17 +246,16 @@ class localrepository(repo.repository): # taking precedence heads = self.heads() heads.reverse() - fl = self.file(".hgtags") + seen = {} for node in heads: - change = self.changelog.read(node) - rev = self.changelog.rev(node) - fn, ff = self.manifest.find(change[0], '.hgtags') - if fn is None: continue + f = self.filectx('.hgtags', node) + if not f or f.filerev() in seen: continue + seen[f.filerev()] = 1 count = 0 - for l in fl.read(fn).splitlines(): + for l in f.data().splitlines(): count += 1 - parsetag(l, _(".hgtags (rev %d:%s), line %d") % - (rev, short(node), count)) + parsetag(l, _("%s, line %d") % (str(f), count)) + try: f = self.opener("localtags") count = 0 @@ -344,14 +344,17 @@ class localrepository(repo.repository): key = self.dirstate.parents()[0] if key == nullid: raise repo.RepoError(_("no revision checked out")) + n = self.changelog._match(key) + if n: + return n if key in self.tags(): return self.tags()[key] if key in self.branchtags(): return self.branchtags()[key] - try: - return self.changelog.lookup(key) - except: - raise repo.RepoError(_("unknown revision '%s'") % key) + n = self.changelog._partialmatch(key) + if n: + return n + raise repo.RepoError(_("unknown revision '%s'") % key) def dev(self): return os.lstat(self.path).st_dev @@ -362,13 +365,16 @@ class localrepository(repo.repository): def join(self, f): return os.path.join(self.path, f) + def sjoin(self, f): + return os.path.join(self.path, f) + def wjoin(self, f): return os.path.join(self.root, f) def file(self, f): if f[0] == '/': f = f[1:] - return filelog.filelog(self.opener, f, self.revlogversion) + return filelog.filelog(self.sopener, f, self.revlogversion) def changectx(self, changeid=None): return context.changectx(self, changeid) @@ -448,17 +454,17 @@ class localrepository(repo.repository): ds = "" self.opener("journal.dirstate", "w").write(ds) - tr = transaction.transaction(self.ui.warn, self.opener, - self.join("journal"), + tr = transaction.transaction(self.ui.warn, self.sopener, + self.sjoin("journal"), aftertrans(self.path)) self.transhandle = tr return tr def recover(self): l = self.lock() - if os.path.exists(self.join("journal")): + if os.path.exists(self.sjoin("journal")): self.ui.status(_("rolling back interrupted transaction\n")) - transaction.rollback(self.opener, self.join("journal")) + transaction.rollback(self.sopener, self.sjoin("journal")) self.reload() return True else: @@ -469,9 +475,9 @@ class localrepository(repo.repository): if not wlock: wlock = self.wlock() l = self.lock() - if os.path.exists(self.join("undo")): + if os.path.exists(self.sjoin("undo")): self.ui.status(_("rolling back last transaction\n")) - transaction.rollback(self.opener, self.join("undo")) + transaction.rollback(self.sopener, self.sjoin("undo")) util.rename(self.join("undo.dirstate"), self.join("dirstate")) self.reload() self.wreload() @@ -490,26 +496,25 @@ class localrepository(repo.repository): def do_lock(self, lockname, wait, releasefn=None, acquirefn=None, desc=None): try: - l = lock.lock(self.join(lockname), 0, releasefn, desc=desc) + l = lock.lock(lockname, 0, releasefn, desc=desc) except lock.LockHeld, inst: if not wait: raise self.ui.warn(_("waiting for lock on %s held by %s\n") % (desc, inst.args[0])) # default to 600 seconds timeout - l = lock.lock(self.join(lockname), - int(self.ui.config("ui", "timeout") or 600), + l = lock.lock(lockname, int(self.ui.config("ui", "timeout", "600")), releasefn, desc=desc) if acquirefn: acquirefn() return l def lock(self, wait=1): - return self.do_lock("lock", wait, acquirefn=self.reload, + return self.do_lock(self.sjoin("lock"), wait, acquirefn=self.reload, desc=_('repository %s') % self.origroot) def wlock(self, wait=1): - return self.do_lock("wlock", wait, self.dirstate.write, + return self.do_lock(self.join("wlock"), wait, self.dirstate.write, self.wreload, desc=_('working directory of %s') % self.origroot) @@ -1692,7 +1697,8 @@ class localrepository(repo.repository): # inconsistent view cl = None try: - cl = appendfile.appendchangelog(self.opener, self.changelog.version) + cl = appendfile.appendchangelog(self.sopener, + self.changelog.version) oldheads = len(cl.heads()) @@ -1735,7 +1741,8 @@ class localrepository(repo.repository): cl.cleanup() # make changelog see real files again - self.changelog = changelog.changelog(self.opener, self.changelog.version) + self.changelog = changelog.changelog(self.sopener, + self.changelog.version) self.changelog.checkinlinesize(tr) newheads = len(self.changelog.heads()) @@ -1779,7 +1786,7 @@ class localrepository(repo.repository): name, size = fp.readline().split('\0', 1) size = int(size) self.ui.debug('adding %s (%s)\n' % (name, util.bytecount(size))) - ofp = self.opener(name, 'w') + ofp = self.sopener(name, 'w') for chunk in util.filechunkiter(fp, limit=size): ofp.write(chunk) ofp.close() diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -742,11 +742,7 @@ class revlog(object): c.append(self.node(r)) return c - def lookup(self, id): - """locate a node based on: - - revision number or str(revision number) - - nodeid or subset of hex nodeid - """ + def _match(self, id): if isinstance(id, (long, int)): # rev return self.node(id) @@ -768,13 +764,18 @@ class revlog(object): return self.node(rev) except (ValueError, OverflowError): pass - try: - if len(id) == 40: + if len(id) == 40: + try: # a full hex nodeid? node = bin(id) r = self.rev(node) return node - elif len(id) < 40: + except TypeError: + pass + + def _partialmatch(self, id): + if len(id) < 40: + try: # hex(node)[:...] bin_id = bin(id[:len(id) & ~1]) # grab an even number of digits node = None @@ -785,8 +786,21 @@ class revlog(object): node = n if node is not None: return node - except TypeError: - pass + except TypeError: + pass + + def lookup(self, id): + """locate a node based on: + - revision number or str(revision number) + - nodeid or subset of hex nodeid + """ + + n = self._match(id) + if n is not None: + return n + n = self._partialmatch(id) + if n: + return n raise RevlogError(_("No match found")) diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py --- a/mercurial/statichttprepo.py +++ b/mercurial/statichttprepo.py @@ -36,6 +36,7 @@ class statichttprepository(localrepo.loc self.ui = ui self.revlogversion = 0 self.opener = opener(self.path) + self.sopener = opener(self.path) self.manifest = manifest.manifest(self.opener) self.changelog = changelog.changelog(self.opener) self.tagscache = None diff --git a/tests/test-tags.out b/tests/test-tags.out --- a/tests/test-tags.out +++ b/tests/test-tags.out @@ -18,20 +18,17 @@ 8216907a933d+8a3ca90d111d+ tip M .hgtags tip 6:e2174d339386 first 0:0acdaf898367 -.hgtags (rev 7:c071f74ab5eb), line 2: cannot parse entry -.hgtags (rev 7:c071f74ab5eb), line 4: node 'foo' is not well formed -localtags, line 1: tag 'invalid' refers to unknown node 1 files updated, 0 files merged, 0 files removed, 0 files unresolved -.hgtags (rev 7:c071f74ab5eb), line 2: cannot parse entry -.hgtags (rev 7:c071f74ab5eb), line 4: node 'foo' is not well formed -.hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed +.hgtags@c071f74ab5eb, line 2: cannot parse entry +.hgtags@c071f74ab5eb, line 4: node 'foo' is not well formed +.hgtags@4ca6f1b1a68c, line 2: node 'x' is not well formed localtags, line 1: tag 'invalid' refers to unknown node tip 8:4ca6f1b1a68c first 0:0acdaf898367 changeset: 8:4ca6f1b1a68c -.hgtags (rev 7:c071f74ab5eb), line 2: cannot parse entry -.hgtags (rev 7:c071f74ab5eb), line 4: node 'foo' is not well formed -.hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed +.hgtags@c071f74ab5eb, line 2: cannot parse entry +.hgtags@c071f74ab5eb, line 4: node 'foo' is not well formed +.hgtags@4ca6f1b1a68c, line 2: node 'x' is not well formed localtags, line 1: tag 'invalid' refers to unknown node tag: tip parent: 3:b2ef3841386b