# HG changeset patch # User Dirkjan Ochtman # Date 1214638081 -7200 # Node ID 39319a457ddac02e209461eb3d0ed2145ccc0106 # Parent 54ccf41761c9edd2fa1f0fbb9e4967e2b0a88faa# Parent f67d1468ac50a88eea7ac2804f646ee3ddbe0c41 merge with mpm diff -r 54ccf41761c9 -r 39319a457dda contrib/dumprevlog --- a/contrib/dumprevlog Thu Jun 26 13:37:47 2008 -0700 +++ b/contrib/dumprevlog Sat Jun 28 09:28:01 2008 +0200 @@ -12,7 +12,7 @@ binopen = lambda fn: open(fn, 'rb') r = revlog.revlog(binopen, f) print "file:", f - for i in xrange(r.count()): + for i in r: n = r.node(i) p = r.parents(n) d = r.revision(n) diff -r 54ccf41761c9 -r 39319a457dda hgext/acl.py --- a/hgext/acl.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/acl.py Sat Jun 28 09:28:01 2008 +0200 @@ -91,7 +91,7 @@ def check(self, node): '''return if access allowed, raise exception if not.''' - files = self.repo.changectx(node).files() + files = self.repo[node].files() if self.deniable: for f in files: if self.deny(f): @@ -118,7 +118,5 @@ ui.debug(_('acl: changes have source "%s" - skipping\n') % source) return - start = repo.changelog.rev(bin(node)) - end = repo.changelog.count() - for rev in xrange(start, end): + for rev in xrange(repo[node].rev(), len(repo)): c.check(repo.changelog.node(rev)) diff -r 54ccf41761c9 -r 39319a457dda hgext/bugzilla.py --- a/hgext/bugzilla.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/bugzilla.py Sat Jun 28 09:28:01 2008 +0200 @@ -99,9 +99,7 @@ def filter_real_bug_ids(self, ids): '''filter not-existing bug ids from list.''' self.run('select bug_id from bugs where bug_id in %s' % buglist(ids)) - ids = [c[0] for c in self.cursor.fetchall()] - ids.sort() - return ids + return util.sort([c[0] for c in self.cursor.fetchall()]) def filter_unknown_bug_ids(self, node, ids): '''filter bug ids from list that already refer to this changeset.''' @@ -114,9 +112,7 @@ self.ui.status(_('bug %d already knows about changeset %s\n') % (id, short(node))) unknown.pop(id, None) - ids = unknown.keys() - ids.sort() - return ids + return util.sort(unknown.keys()) def notify(self, ids): '''tell bugzilla to send mail.''' @@ -300,7 +296,7 @@ hooktype) try: bz = bugzilla(ui, repo) - ctx = repo.changectx(node) + ctx = repo[node] ids = bz.find_bug_ids(ctx) if ids: for id in ids: diff -r 54ccf41761c9 -r 39319a457dda hgext/children.py --- a/hgext/children.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/children.py Sat Jun 28 09:28:01 2008 +0200 @@ -25,7 +25,7 @@ if file_: ctx = repo.filectx(file_, changeid=rev) else: - ctx = repo.changectx(rev) + ctx = repo[rev] displayer = cmdutil.show_changeset(ui, repo, opts) for node in [cp.node() for cp in ctx.children()]: diff -r 54ccf41761c9 -r 39319a457dda hgext/churn.py --- a/hgext/churn.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/churn.py Sat Jun 28 09:28:01 2008 +0200 @@ -7,7 +7,7 @@ '''allow graphing the number of lines changed per contributor''' from mercurial.i18n import gettext as _ -from mercurial import mdiff, cmdutil, util, node +from mercurial import patch, cmdutil, util, node import os, sys def get_tty_width(): @@ -31,98 +31,41 @@ pass return 80 -def __gather(ui, repo, node1, node2): - def dirtywork(f, mmap1, mmap2): - lines = 0 - - to = mmap1 and repo.file(f).read(mmap1[f]) or None - tn = mmap2 and repo.file(f).read(mmap2[f]) or None - - diff = mdiff.unidiff(to, "", tn, "", f, f).split("\n") - - for line in diff: - if not line: - continue # skip EOF - if line.startswith(" "): - continue # context line - if line.startswith("--- ") or line.startswith("+++ "): - continue # begining of diff - if line.startswith("@@ "): - continue # info line - - # changed lines - lines += 1 - - return lines - - ## - - lines = 0 - - changes = repo.status(node1, node2)[:5] - - modified, added, removed, deleted, unknown = changes - - who = repo.changelog.read(node2)[1] - who = util.email(who) # get the email of the person - - mmap1 = repo.manifest.read(repo.changelog.read(node1)[0]) - mmap2 = repo.manifest.read(repo.changelog.read(node2)[0]) - for f in modified: - lines += dirtywork(f, mmap1, mmap2) - - for f in added: - lines += dirtywork(f, None, mmap2) - - for f in removed: - lines += dirtywork(f, mmap1, None) - - for f in deleted: - lines += dirtywork(f, mmap1, mmap2) - - for f in unknown: - lines += dirtywork(f, mmap1, mmap2) - - return (who, lines) - -def gather_stats(ui, repo, amap, revs=None, progress=False): +def countrevs(ui, repo, amap, revs, progress=False): stats = {} - - cl = repo.changelog - + count = pct = 0 if not revs: - revs = range(0, cl.count()) - - nr_revs = len(revs) - cur_rev = 0 + revs = range(len(repo)) for rev in revs: - cur_rev += 1 # next revision - - node2 = cl.node(rev) - node1 = cl.parents(node2)[0] - - if cl.parents(node2)[1] != node.nullid: + ctx2 = repo[rev] + parents = ctx2.parents() + if len(parents) > 1: ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,)) continue - who, lines = __gather(ui, repo, node1, node2) + ctx1 = parents[0] + lines = 0 + ui.pushbuffer() + patch.diff(repo, ctx1.node(), ctx2.node()) + diff = ui.popbuffer() - # remap the owner if possible - if who in amap: - ui.note("using '%s' alias for '%s'\n" % (amap[who], who)) - who = amap[who] + for l in diff.split('\n'): + if (l.startswith("+") and not l.startswith("+++ ") or + l.startswith("-") and not l.startswith("--- ")): + lines += 1 - if not who in stats: - stats[who] = 0 - stats[who] += lines - - ui.note("rev %d: %d lines by %s\n" % (rev, lines, who)) + user = util.email(ctx2.user()) + user = amap.get(user, user) # remap + stats[user] = stats.get(user, 0) + lines + ui.debug("rev %d: %d lines by %s\n" % (rev, lines, user)) if progress: - nr_revs = max(nr_revs, 1) - if int(100.0*(cur_rev - 1)/nr_revs) < int(100.0*cur_rev/nr_revs): - ui.write("\rGenerating stats: %d%%" % (int(100.0*cur_rev/nr_revs),)) + count += 1 + newpct = int(100.0 * count / max(len(revs), 1)) + if pct < newpct: + pct = newpct + ui.write("\rGenerating stats: %d%%" % pct) sys.stdout.flush() if progress: @@ -139,61 +82,32 @@ ''' def pad(s, l): - if len(s) < l: - return s + " " * (l-len(s)) - return s[0:l] - - def graph(n, maximum, width, char): - maximum = max(1, maximum) - n = int(n * width / float(maximum)) - - return char * (n) - - def get_aliases(f): - aliases = {} - - for l in f.readlines(): - l = l.strip() - alias, actual = l.split() - aliases[alias] = actual - - return aliases + return (s + " " * l)[:l] amap = {} aliases = opts.get('aliases') if aliases: - try: - f = open(aliases,"r") - except OSError, e: - print "Error: " + e - return + for l in open(aliases, "r"): + l = l.strip() + alias, actual = l.split() + amap[alias] = actual - amap = get_aliases(f) - f.close() - - revs = [int(r) for r in cmdutil.revrange(repo, opts['rev'])] - revs.sort() - stats = gather_stats(ui, repo, amap, revs, opts.get('progress')) + revs = util.sort([int(r) for r in cmdutil.revrange(repo, opts['rev'])]) + stats = countrevs(ui, repo, amap, revs, opts.get('progress')) + if not stats: + return - # make a list of tuples (name, lines) and sort it in descending order - ordered = stats.items() - if not ordered: - return - ordered.sort(lambda x, y: cmp(y[1], x[1])) - max_churn = ordered[0][1] + stats = util.sort([(-l, u, l) for u,l in stats.items()]) + maxchurn = float(max(1, stats[0][2])) + maxuser = max([len(u) for k, u, l in stats]) - tty_width = get_tty_width() - ui.note(_("assuming %i character terminal\n") % tty_width) - tty_width -= 1 - - max_user_width = max([len(user) for user, churn in ordered]) + ttywidth = get_tty_width() + ui.debug(_("assuming %i character terminal\n") % ttywidth) + width = ttywidth - maxuser - 2 - 6 - 2 - 2 - graph_width = tty_width - max_user_width - 1 - 6 - 2 - 2 - - for user, churn in ordered: - print "%s %6d %s" % (pad(user, max_user_width), - churn, - graph(churn, max_churn, graph_width, '*')) + for k, user, churn in stats: + print "%s %6d %s" % (pad(user, maxuser), churn, + "*" * int(churn * width / maxchurn)) cmdtable = { "churn": diff -r 54ccf41761c9 -r 39319a457dda hgext/convert/cvs.py --- a/hgext/convert/cvs.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/convert/cvs.py Sat Jun 28 09:28:01 2008 +0200 @@ -337,10 +337,7 @@ def getchanges(self, rev): self.modecache = {} - files = self.files[rev] - cl = files.items() - cl.sort() - return (cl, {}) + return util.sort(self.files[rev].items()), {} def getcommit(self, rev): return self.changeset[rev] @@ -349,7 +346,4 @@ return self.tags def getchangedfiles(self, rev, i): - files = self.files[rev].keys() - files.sort() - return files - + return util.sort(self.files[rev].keys()) diff -r 54ccf41761c9 -r 39319a457dda hgext/convert/cvsps.py --- a/hgext/convert/cvsps.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/convert/cvsps.py Sat Jun 28 09:28:01 2008 +0200 @@ -297,8 +297,7 @@ if store: # clean up the results and save in the log. store = False - e.tags = [scache(x) for x in tags.get(e.revision, [])] - e.tags.sort() + e.tags = util.sort([scache(x) for x in tags.get(e.revision, [])]) e.comment = scache('\n'.join(e.comment)) revn = len(e.revision) @@ -468,9 +467,7 @@ for tag in e.tags: tags[tag] = True # remember tags only if this is the latest changeset to have it - tagnames = [tag for tag in tags if globaltags[tag] is c] - tagnames.sort() - c.tags = tagnames + c.tags = util.sort([tag for tag in tags if globaltags[tag] is c]) # Find parent changesets, handle {{mergetobranch BRANCHNAME}} # by inserting dummy changesets with two parents, and handle diff -r 54ccf41761c9 -r 39319a457dda hgext/convert/darcs.py --- a/hgext/convert/darcs.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/convert/darcs.py Sat Jun 28 09:28:01 2008 +0200 @@ -110,9 +110,8 @@ copies[elt.get('from')] = elt.get('to') else: changes.append((elt.text.strip(), rev)) - changes.sort() self.lastrev = rev - return changes, copies + return util.sort(changes), copies def getfile(self, name, rev): if rev != self.lastrev: diff -r 54ccf41761c9 -r 39319a457dda hgext/convert/gnuarch.py --- a/hgext/convert/gnuarch.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/convert/gnuarch.py Sat Jun 28 09:28:01 2008 +0200 @@ -130,10 +130,8 @@ for c in cps: copies[c] = cps[c] - changes.sort() self.lastrev = rev - - return changes, copies + return util.sort(changes), copies def getcommit(self, rev): changes = self.changes[rev] diff -r 54ccf41761c9 -r 39319a457dda hgext/convert/hg.py --- a/hgext/convert/hg.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/convert/hg.py Sat Jun 28 09:28:01 2008 +0200 @@ -157,21 +157,18 @@ def puttags(self, tags): try: - parentctx = self.repo.changectx(self.tagsbranch) + parentctx = self.repo[self.tagsbranch] tagparent = parentctx.node() except RepoError, inst: parentctx = None tagparent = nullid try: - old = parentctx.filectx(".hgtags").data() - oldlines = old.splitlines(1) - oldlines.sort() + oldlines = util.sort(parentctx['.hgtags'].data().splitlines(1)) except: oldlines = [] - newlines = [("%s %s\n" % (tags[tag], tag)) for tag in tags.keys()] - newlines.sort() + newlines = util.sort([("%s %s\n" % (tags[tag], tag)) for tag in tags]) if newlines == oldlines: return None @@ -212,25 +209,24 @@ def changectx(self, rev): if self.lastrev != rev: - self.lastctx = self.repo.changectx(rev) + self.lastctx = self.repo[rev] self.lastrev = rev return self.lastctx def getheads(self): if self.rev: - return [hex(self.repo.changectx(self.rev).node())] + return [hex(self.repo[self.rev].node())] else: return [hex(node) for node in self.repo.heads()] def getfile(self, name, rev): try: - return self.changectx(rev).filectx(name).data() + return self.changectx(rev)[name].data() except revlog.LookupError, err: raise IOError(err) def getmode(self, name, rev): - m = self.changectx(rev).manifest() - return (m.execf(name) and 'x' or '') + (m.linkf(name) and 'l' or '') + return self.changectx(rev).manifest().flags(name) def getchanges(self, rev): ctx = self.changectx(rev) @@ -239,8 +235,7 @@ else: m, a, r = self.repo.status(ctx.parents()[0].node(), ctx.node())[:3] changes = [(name, rev) for name in m + a + r] - changes.sort() - return (changes, self.getcopies(ctx, m + a)) + return util.sort(changes), self.getcopies(ctx, m + a) def getcopies(self, ctx, files): copies = {} diff -r 54ccf41761c9 -r 39319a457dda hgext/convert/subversion.py --- a/hgext/convert/subversion.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/convert/subversion.py Sat Jun 28 09:28:01 2008 +0200 @@ -658,8 +658,7 @@ # This will fail if a directory was copied # from another branch and then some of its files # were deleted in the same transaction. - children = self._find_children(path, revnum) - children.sort() + children = util.sort(self._find_children(path, revnum)) for child in children: # Can we move a child directory and its # parent in the same commit? (probably can). Could @@ -732,8 +731,7 @@ parents = [] # check whether this revision is the start of a branch or part # of a branch renaming - orig_paths = orig_paths.items() - orig_paths.sort() + orig_paths = util.sort(orig_paths.items()) root_paths = [(p,e) for p,e in orig_paths if self.module.startswith(p)] if root_paths: path, ent = root_paths[-1] @@ -1045,10 +1043,9 @@ return dirs def add_dirs(self, files): - add_dirs = [d for d in self.dirs_of(files) + add_dirs = [d for d in util.sort(self.dirs_of(files)) if not os.path.exists(self.wjoin(d, '.svn', 'entries'))] if add_dirs: - add_dirs.sort() self.xargs(add_dirs, 'add', non_recursive=True, quiet=True) return add_dirs @@ -1058,8 +1055,7 @@ return files def tidy_dirs(self, names): - dirs = list(self.dirs_of(names)) - dirs.sort() + dirs = util.sort(self.dirs_of(names)) dirs.reverse() deleted = [] for d in dirs: diff -r 54ccf41761c9 -r 39319a457dda hgext/extdiff.py --- a/hgext/extdiff.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/extdiff.py Sat Jun 28 09:28:01 2008 +0200 @@ -52,7 +52,6 @@ def snapshot_node(ui, repo, files, node, tmproot): '''snapshot files as of some revision''' - mf = repo.changectx(node).manifest() dirname = os.path.basename(repo.root) if dirname == "": dirname = "root" @@ -61,17 +60,18 @@ os.mkdir(base) ui.note(_('making snapshot of %d files from rev %s\n') % (len(files), short(node))) + ctx = repo[node] for fn in files: - if not fn in mf: + wfn = util.pconvert(fn) + if not wfn in ctx: # skipping new file after a merge ? continue - wfn = util.pconvert(fn) ui.note(' %s\n' % wfn) dest = os.path.join(base, wfn) destdir = os.path.dirname(dest) if not os.path.isdir(destdir): os.makedirs(destdir) - data = repo.wwritedata(wfn, repo.file(wfn).read(mf[wfn])) + data = repo.wwritedata(wfn, ctx[wfn].data()) open(dest, 'wb').write(data) return dirname @@ -122,8 +122,7 @@ ''' node1, node2 = cmdutil.revpair(repo, opts['rev']) matcher = cmdutil.match(repo, pats, opts) - modified, added, removed, deleted, unknown = repo.status( - node1, node2, matcher)[:5] + modified, added, removed = repo.status(node1, node2, matcher)[:3] if not (modified or added or removed): return 0 diff -r 54ccf41761c9 -r 39319a457dda hgext/gpg.py --- a/hgext/gpg.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/gpg.py Sat Jun 28 09:28:01 2008 +0200 @@ -239,7 +239,7 @@ repo.opener("localsigs", "ab").write(sigmessage) return - for x in repo.status()[:5]: + for x in repo.status(unknown=True)[:5]: if ".hgsigs" in x and not opts["force"]: raise util.Abort(_("working copy of .hgsigs is changed " "(please commit .hgsigs manually " diff -r 54ccf41761c9 -r 39319a457dda hgext/graphlog.py --- a/hgext/graphlog.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/graphlog.py Sat Jun 28 09:28:01 2008 +0200 @@ -13,6 +13,7 @@ from mercurial.i18n import _ from mercurial.node import nullrev from mercurial.util import Abort, canonpath +from mercurial import util def revision_grapher(repo, start_rev, stop_rev): """incremental revision grapher @@ -53,8 +54,7 @@ for parent in parents: if parent not in next_revs: parents_to_add.append(parent) - parents_to_add.sort() - next_revs[rev_index:rev_index + 1] = parents_to_add + next_revs[rev_index:rev_index + 1] = util.sort(parents_to_add) edges = [] for parent in parents: @@ -89,7 +89,7 @@ assert start_rev >= stop_rev curr_rev = start_rev revs = [] - filerev = repo.file(path).count() - 1 + filerev = len(repo.file(path)) - 1 while filerev >= 0: fctx = repo.filectx(path, fileid=filerev) @@ -105,8 +105,7 @@ for parent in parents: if parent not in next_revs: parents_to_add.append(parent) - parents_to_add.sort() - next_revs[rev_index:rev_index + 1] = parents_to_add + next_revs[rev_index:rev_index + 1] = util.sort(parents_to_add) edges = [] for parent in parents: @@ -198,7 +197,7 @@ revs = revrange(repo, rev_opt) return (max(revs), min(revs)) else: - return (repo.changelog.count() - 1, 0) + return (len(repo) - 1, 0) def graphlog(ui, repo, path=None, **opts): """show revision history alongside an ASCII revision graph diff -r 54ccf41761c9 -r 39319a457dda hgext/hgk.py --- a/hgext/hgk.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/hgk.py Sat Jun 28 09:28:01 2008 +0200 @@ -52,12 +52,10 @@ """diff trees from two commits""" def __difftree(repo, node1, node2, files=[]): assert node2 is not None - mmap = repo.changectx(node1).manifest() - mmap2 = repo.changectx(node2).manifest() + mmap = repo[node1].manifest() + mmap2 = repo[node2].manifest() m = cmdutil.match(repo, files) - status = repo.status(node1, node2, match=m)[:5] - modified, added, removed, deleted, unknown = status - + modified, added, removed = repo.status(node1, node2, m)[:3] empty = short(nullid) for f in modified: @@ -103,7 +101,7 @@ def catcommit(ui, repo, n, prefix, ctx=None): nlprefix = '\n' + prefix; if ctx is None: - ctx = repo.changectx(n) + ctx = repo[n] (p1, p2) = ctx.parents() ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ?? if p1: ui.write("parent %s\n" % short(p1.node())) @@ -175,7 +173,7 @@ # you can specify a commit to stop at by starting the sha1 with ^ def revtree(ui, args, repo, full="tree", maxnr=0, parents=False): def chlogwalk(): - count = repo.changelog.count() + count = len(repo) i = count l = [0] * 100 chunk = 100 @@ -191,7 +189,7 @@ l[chunk - x:] = [0] * (chunk - x) break if full != None: - l[x] = repo.changectx(i + x) + l[x] = repo[i + x] l[x].changeset() # force reading else: l[x] = 1 diff -r 54ccf41761c9 -r 39319a457dda hgext/inotify/__init__.py --- a/hgext/inotify/__init__.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/inotify/__init__.py Sat Jun 28 09:28:01 2008 +0200 @@ -47,13 +47,12 @@ # to recurse. inotifyserver = False - def status(self, match, list_ignored, list_clean, - list_unknown=True): + def status(self, match, ignored, clean, unknown=True): files = match.files() try: - if not list_ignored and not self.inotifyserver: + if not ignored and not self.inotifyserver: result = client.query(ui, repo, files, match, False, - list_clean, list_unknown) + clean, unknown) if result is not None: return result except socket.error, err: @@ -82,15 +81,14 @@ if query: try: return query(ui, repo, files or [], match, - list_ignored, list_clean, list_unknown) + ignored, clean, unknown) except socket.error, err: ui.warn(_('could not talk to new inotify ' 'server: %s\n') % err[1]) ui.print_exc() return super(inotifydirstate, self).status( - match, list_ignored, list_clean, - list_unknown) + match, ignored, clean, unknown) repo.dirstate.__class__ = inotifydirstate diff -r 54ccf41761c9 -r 39319a457dda hgext/inotify/client.py --- a/hgext/inotify/client.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/inotify/client.py Sat Jun 28 09:28:01 2008 +0200 @@ -11,7 +11,7 @@ import common import os, select, socket, stat, struct, sys -def query(ui, repo, names, match, list_ignored, list_clean, list_unknown=True): +def query(ui, repo, names, match, ignored, clean, unknown=True): sock = socket.socket(socket.AF_UNIX) sockpath = repo.join('inotify.sock') sock.connect(sockpath) @@ -20,10 +20,10 @@ for n in names or []: yield n states = 'almrx!' - if list_ignored: + if ignored: raise ValueError('this is insanity') - if list_clean: states += 'n' - if list_unknown: states += '?' + if clean: states += 'n' + if unknown: states += '?' yield states req = '\0'.join(genquery()) diff -r 54ccf41761c9 -r 39319a457dda hgext/inotify/server.py --- a/hgext/inotify/server.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/inotify/server.py Sat Jun 28 09:28:01 2008 +0200 @@ -534,9 +534,7 @@ self.ui.note('%s processing %d deferred events as %d\n' % (self.event_time(), self.deferred, len(self.eventq))) - eventq = self.eventq.items() - eventq.sort() - for wpath, evts in eventq: + for wpath, evts in util.sort(self.eventq.items()): for evt in evts: self.deferred_event(wpath, evt) self.eventq.clear() diff -r 54ccf41761c9 -r 39319a457dda hgext/keyword.py --- a/hgext/keyword.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/keyword.py Sat Jun 28 09:28:01 2008 +0200 @@ -78,7 +78,7 @@ "Log = {desc}" expands to the first line of the changeset description. ''' -from mercurial import commands, cmdutil, context, dispatch, filelog, revlog +from mercurial import commands, cmdutil, dispatch, filelog, revlog from mercurial import patch, localrepo, templater, templatefilters, util from mercurial.hgweb import webcommands from mercurial.node import nullid, hex @@ -142,7 +142,7 @@ def getnode(self, path, fnode): '''Derives changenode from file path and filenode.''' # used by kwfilelog.read and kwexpand - c = context.filectx(self.repo, path, fileid=fnode) + c = self.repo.filectx(path, fileid=fnode) return c.node() def substitute(self, data, path, node, subfunc): @@ -163,25 +163,26 @@ return self.substitute(data, path, changenode, self.re_kw.sub) return data - def iskwfile(self, path, islink): + def iskwfile(self, path, flagfunc): '''Returns true if path matches [keyword] pattern and is not a symbolic link. Caveat: localrepository._link fails on Windows.''' - return self.matcher(path) and not islink(path) + return self.matcher(path) and not 'l' in flagfunc(path) def overwrite(self, node, expand, files): '''Overwrites selected files expanding/shrinking keywords.''' - ctx = self.repo.changectx(node) - mf = ctx.manifest() if node is not None: # commit + ctx = self.repo[node] + mf = ctx.manifest() files = [f for f in ctx.files() if f in mf] notify = self.ui.debug else: # kwexpand/kwshrink + ctx = self.repo['.'] + mf = ctx.manifest() notify = self.ui.note - candidates = [f for f in files if self.iskwfile(f, mf.linkf)] + candidates = [f for f in files if self.iskwfile(f, ctx.flags)] if candidates: self.restrict = True # do not expand when reading - candidates.sort() action = expand and 'expanding' or 'shrinking' for f in candidates: fp = self.repo.file(f) @@ -251,12 +252,12 @@ return t2 != text return revlog.revlog.cmp(self, node, text) -def _status(ui, repo, kwt, *pats, **opts): +def _status(ui, repo, kwt, unknown, *pats, **opts): '''Bails out if [keyword] configuration is not active. Returns status of working directory.''' if kwt: matcher = cmdutil.match(repo, pats, opts) - return repo.status(match=matcher, list_clean=True) + return repo.status(match=matcher, unknown=unknown, clean=True) if ui.configitems('keyword'): raise util.Abort(_('[keyword] patterns cannot match')) raise util.Abort(_('no [keyword] patterns configured')) @@ -266,15 +267,15 @@ if repo.dirstate.parents()[1] != nullid: raise util.Abort(_('outstanding uncommitted merge')) kwt = kwtools['templater'] - status = _status(ui, repo, kwt, *pats, **opts) - modified, added, removed, deleted, unknown, ignored, clean = status + status = _status(ui, repo, kwt, False, *pats, **opts) + modified, added, removed, deleted = status[:4] if modified or added or removed or deleted: raise util.Abort(_('outstanding uncommitted changes')) wlock = lock = None try: wlock = repo.wlock() lock = repo.lock() - kwt.overwrite(None, expand, clean) + kwt.overwrite(None, expand, status[6]) finally: del wlock, lock @@ -378,15 +379,11 @@ That is, files matched by [keyword] config patterns but not symlinks. ''' kwt = kwtools['templater'] - status = _status(ui, repo, kwt, *pats, **opts) + status = _status(ui, repo, kwt, opts.get('untracked'), *pats, **opts) modified, added, removed, deleted, unknown, ignored, clean = status - files = modified + added + clean - if opts.get('untracked'): - files += unknown - files.sort() - wctx = repo.workingctx() - islink = lambda p: 'l' in wctx.fileflags(p) - kwfiles = [f for f in files if kwt.iskwfile(f, islink)] + files = util.sort(modified + added + clean + unknown) + wctx = repo[None] + kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)] cwd = pats and repo.getcwd() or '' kwfstats = not opts.get('ignore') and (('K', kwfiles),) or () if opts.get('all') or opts.get('ignore'): @@ -511,7 +508,7 @@ comparing against working dir.''' if node2 is not None: kwt.matcher = util.never - elif node1 is not None and node1 != repo.changectx().node(): + elif node1 is not None and node1 != repo['.'].node(): kwt.restrict = True patch_diff(repo, node1, node2, match, fp, changes, opts) diff -r 54ccf41761c9 -r 39319a457dda hgext/mq.py --- a/hgext/mq.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/mq.py Sat Jun 28 09:28:01 2008 +0200 @@ -143,8 +143,7 @@ bad = self.check_guard(guard) if bad: raise util.Abort(bad) - guards = dict.fromkeys(guards).keys() - guards.sort() + guards = util.sort(util.unique(guards)) self.ui.debug('active guards: %s\n' % ' '.join(guards)) self.active_guards = guards self.guards_dirty = True @@ -342,7 +341,7 @@ hg.clean(repo, head) self.strip(repo, n, update=False, backup='strip') - ctx = repo.changectx(rev) + ctx = repo[rev] ret = hg.merge(repo, rev) if ret: raise util.Abort(_("update returned %d") % ret) @@ -536,8 +535,7 @@ return (err, n) def _clean_series(self, patches): - indices = [self.find_series(p) for p in patches] - indices.sort() + indices = util.sort([self.find_series(p) for p in patches]) for i in indices[-1::-1]: del self.full_series[i] self.parse_series() @@ -545,10 +543,10 @@ def finish(self, repo, revs): revs.sort() - firstrev = repo.changelog.rev(revlog.bin(self.applied[0].rev)) + firstrev = repo[self.applied[0].rev].rev() appliedbase = 0 patches = [] - for rev in revs: + for rev in util.sort(revs): if rev < firstrev: raise util.Abort(_('revision %d is not managed') % rev) base = revlog.bin(self.applied[appliedbase].rev) @@ -852,7 +850,7 @@ self.ui.warn(_('cleaning up working directory...')) node = repo.dirstate.parents()[0] hg.revert(repo, node, None) - unknown = repo.status()[4] + unknown = repo.status(unknown=True)[4] # only remove unknown files that we know we touched or # created while patching for f in unknown: @@ -933,7 +931,7 @@ 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] + m, a, r, d = repo.status(qp, top)[:4] if d: raise util.Abort("deletions found between repo revs") for f in m: @@ -1066,11 +1064,11 @@ # patch already # # this should really read: - # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5] + # mm, dd, aa, aa2 = repo.status(tip, patchparent)[:4] # 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] + mm, aa, dd, aa2 = repo.status(patchparent, tip)[:4] changes = repo.changelog.read(tip) man = repo.manifest.read(changes[0]) aaa = aa[:] @@ -1078,7 +1076,7 @@ match = cmdutil.matchfiles(repo, mm + aa + dd) else: match = cmdutil.matchall(repo) - m, a, r, d, u = repo.status(match=match)[:5] + m, a, r, d = repo.status(match=match)[:4] # we might end up with files that were added between # tip and the dirstate parent, but then changed in the @@ -1111,7 +1109,7 @@ m = util.unique(mm) r = util.unique(dd) a = util.unique(aa) - c = [filter(matchfn, l) for l in (m, a, r, [], u)] + c = [filter(matchfn, l) for l in (m, a, r)] match = cmdutil.matchfiles(repo, util.unique(c[0] + c[1] + c[2])) patch.diff(repo, patchparent, match=match, fp=patchf, changes=c, opts=self.diffopts()) @@ -1261,8 +1259,7 @@ self.guards_path) and not fl.startswith('.')): msng_list.append(fl) - msng_list.sort() - for x in msng_list: + for x in util.sort(msng_list): pfx = self.ui.verbose and ('D ') or '' self.ui.write("%s%s\n" % (pfx, displayname(x))) @@ -2319,7 +2316,7 @@ # we might as well use it, but we won't save it. # update the cache up to the tip - self._updatebranchcache(partial, start, cl.count()) + self._updatebranchcache(partial, start, len(cl)) return partial diff -r 54ccf41761c9 -r 39319a457dda hgext/notify.py --- a/hgext/notify.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/notify.py Sat Jun 28 09:28:01 2008 +0200 @@ -156,9 +156,7 @@ if fnmatch.fnmatch(self.repo.root, pat): for user in users.split(','): subs[self.fixmail(user)] = 1 - subs = subs.keys() - subs.sort() - return subs + return util.sort(subs) def url(self, path=None): return self.ui.config('web', 'baseurl') + (path or self.root) @@ -269,11 +267,11 @@ node = bin(node) ui.pushbuffer() if hooktype == 'changegroup': - start = repo.changelog.rev(node) - end = repo.changelog.count() + start = repo[node].rev() + end = len(repo) count = end - start for rev in xrange(start, end): - n.node(repo.changelog.node(rev)) + n.node(repo[node].rev()) n.diff(node, repo.changelog.tip()) else: count = 1 diff -r 54ccf41761c9 -r 39319a457dda hgext/purge.py --- a/hgext/purge.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/purge.py Sat Jun 28 09:28:01 2008 +0200 @@ -56,79 +56,42 @@ files that this program would delete use the --print option. ''' act = not opts['print'] - ignored = bool(opts['all']) - abort_on_err = bool(opts['abort_on_err']) - eol = opts['print0'] and '\0' or '\n' - if eol == '\0': - # --print0 implies --print - act = False - force = bool(opts['force']) - - def error(msg): - if abort_on_err: - raise util.Abort(msg) - else: - ui.warn(_('warning: %s\n') % msg) + eol = '\n' + if opts['print0']: + eol = '\0' + act = False # --print0 implies --print def remove(remove_func, name): if act: try: remove_func(os.path.join(repo.root, name)) except OSError, e: - error(_('%s cannot be removed') % name) + m = _('%s cannot be removed') % name + if opts['abort_on_err']: + raise util.Abort(m) + ui.warn(_('warning: %s\n') % m) else: ui.write('%s%s' % (name, eol)) - if not force: - _check_fs(ui, repo) - directories = [] - files = [] match = cmdutil.match(repo, dirs, opts) match.dir = directories.append - for src, f, st in repo.dirstate.statwalk(match, ignored=ignored): - if src == 'f' and f not in repo.dirstate: - files.append(f) - - directories.sort() + status = repo.status(match=match, ignored=opts['all'], unknown=True) - for f in files: - if f not in repo.dirstate: - ui.note(_('Removing file %s\n') % f) - remove(os.remove, f) + for f in util.sort(status[4] + status[5]): + ui.note(_('Removing file %s\n') % f) + remove(os.remove, f) - for f in directories[::-1]: + for f in util.sort(directories)[::-1]: if match(f) and not os.listdir(repo.wjoin(f)): ui.note(_('Removing directory %s\n') % f) remove(os.rmdir, f) -def _check_fs(ui, repo): - """Abort if there is the chance of having problems with name-mangling fs - - In a name mangling filesystem (e.g. a case insensitive one) - dirstate.walk() can yield filenames different from the ones - stored in the dirstate. This already confuses the status and - add commands, but with purge this may cause data loss. - - To prevent this, this function will abort if there are uncommitted - changes. - """ - - # We can't use (files, match) to do a partial walk here - we wouldn't - # notice a modified README file if the user ran "hg purge readme" - modified, added, removed, deleted = repo.status()[:4] - if modified or added or removed or deleted: - if not util.checkfolding(repo.path) and not ui.quiet: - ui.warn(_("Purging on name mangling filesystems is not " - "fully supported.\n")) - raise util.Abort(_("outstanding uncommitted changes")) - cmdtable = { 'purge|clean': (purge, [('a', 'abort-on-err', None, _('abort if an error occurs')), ('', 'all', None, _('purge ignored files too')), - ('f', 'force', None, _('purge even when there are uncommitted changes')), ('p', 'print', None, _('print the file names instead of deleting them')), ('0', 'print0', None, _('end filenames with NUL, for use with xargs' ' (implies -p)')), diff -r 54ccf41761c9 -r 39319a457dda hgext/record.py --- a/hgext/record.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/record.py Sat Jun 28 09:28:01 2008 +0200 @@ -405,8 +405,8 @@ if match.files(): changes = None else: - changes = repo.status(match=match)[:5] - modified, added, removed = changes[:3] + changes = repo.status(match=match)[:3] + modified, added, removed = changes match = cmdutil.matchfiles(repo, modified + added + removed) diffopts = mdiff.diffopts(git=True, nodates=True) fp = cStringIO.StringIO() @@ -431,7 +431,7 @@ if changes is None: match = cmdutil.matchfiles(repo, newfiles) - changes = repo.status(match=match)[:5] + changes = repo.status(match=match) modified = dict.fromkeys(changes[0]) # 2. backup changed files, so we can restore them in the end diff -r 54ccf41761c9 -r 39319a457dda hgext/transplant.py --- a/hgext/transplant.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/transplant.py Sat Jun 28 09:28:01 2008 +0200 @@ -88,9 +88,7 @@ def apply(self, repo, source, revmap, merges, opts={}): '''apply the revisions in revmap one by one in revision order''' - revs = revmap.keys() - revs.sort() - + revs = util.sort(revmap) p1, p2 = repo.dirstate.parents() pulls = [] diffopts = patch.diffopts(self.ui, opts) @@ -310,9 +308,7 @@ if not os.path.isdir(self.path): os.mkdir(self.path) series = self.opener('series', 'w') - revs = revmap.keys() - revs.sort() - for rev in revs: + for rev in util.sort(revmap): series.write(revlog.hex(revmap[rev]) + '\n') if merges: series.write('# Merges\n') @@ -572,10 +568,6 @@ for r in merges: revmap[source.changelog.rev(r)] = r - revs = revmap.keys() - revs.sort() - pulls = [] - tp.apply(repo, source, revmap, merges, opts) finally: if bundle: diff -r 54ccf41761c9 -r 39319a457dda hgext/win32text.py --- a/hgext/win32text.py Thu Jun 26 13:37:47 2008 -0700 +++ b/hgext/win32text.py Sat Jun 28 09:28:01 2008 +0200 @@ -98,8 +98,8 @@ def forbidnewline(ui, repo, hooktype, node, newline, **kwargs): halt = False - for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()): - c = repo.changectx(rev) + for rev in xrange(repo[node].rev(), len(repo)): + c = repo[rev] for f in c.files(): if f not in c: continue diff -r 54ccf41761c9 -r 39319a457dda mercurial/archival.py --- a/mercurial/archival.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/archival.py Sat Jun 28 09:28:01 2008 +0200 @@ -208,18 +208,17 @@ data = repo.wwritedata(name, data) archiver.addfile(name, mode, islink, data) - ctx = repo.changectx(node) if kind not in archivers: raise util.Abort(_("unknown archive type '%s'" % kind)) + + ctx = repo[node] archiver = archivers[kind](dest, prefix, mtime or ctx.date()[0]) - m = ctx.manifest() - items = m.items() - items.sort() + if repo.ui.configbool("ui", "archivemeta", True): write('.hg_archival.txt', 0644, False, lambda: 'repo: %s\nnode: %s\n' % ( hex(repo.changelog.node(0)), hex(node))) - for filename, filenode in items: - write(filename, m.execf(filename) and 0755 or 0644, m.linkf(filename), - lambda: repo.file(filename).read(filenode)) + for f in ctx: + ff = ctx.flags(f) + write(f, 'x' in ff and 0755 or 0644, 'l' in ff, ctx[f].data) archiver.done() diff -r 54ccf41761c9 -r 39319a457dda mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/bundlerepo.py Sat Jun 28 09:28:01 2008 +0200 @@ -34,7 +34,7 @@ for chunk in changegroup.chunkiter(bundlefile): pos = bundlefile.tell() yield chunk, pos - len(chunk) - n = self.count() + n = len(self) prev = None for chunk, start in chunkpositer(): size = len(chunk) diff -r 54ccf41761c9 -r 39319a457dda mercurial/changelog.py --- a/mercurial/changelog.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/changelog.py Sat Jun 28 09:28:01 2008 +0200 @@ -82,7 +82,7 @@ "delay visibility of index updates to other readers" self._realopener = self.opener self.opener = self._delayopener - self._delaycount = self.count() + self._delaycount = len(self) self._delaybuf = [] self._delayname = None @@ -108,7 +108,7 @@ # if we're doing an initial clone, divert to another file if self._delaycount == 0: self._delayname = fp.name - if not self.count(): + if not len(self): # make sure to truncate the file mode = mode.replace('a', 'w') return self._realopener(name + ".a", mode) @@ -130,9 +130,7 @@ def encode_extra(self, d): # keys must be sorted to produce a deterministic changelog entry - keys = d.keys() - keys.sort() - items = [_string_escape('%s:%s' % (k, d[k])) for k in keys] + items = [_string_escape('%s:%s' % (k, d[k])) for k in util.sort(d)] return "\0".join(items) def read(self, node): @@ -175,7 +173,7 @@ files = l[3:] return (manifest, user, (time, timezone), files, desc, extra) - def add(self, manifest, list, desc, transaction, p1=None, p2=None, + def add(self, manifest, files, desc, transaction, p1=None, p2=None, user=None, date=None, extra={}): user, desc = util.fromlocal(user), util.fromlocal(desc) @@ -189,7 +187,6 @@ if extra: extra = self.encode_extra(extra) parseddate = "%s %s" % (parseddate, extra) - list.sort() - l = [hex(manifest), user, parseddate] + list + ["", desc] + l = [hex(manifest), user, parseddate] + util.sort(files) + ["", desc] text = "\n".join(l) - return self.addrevision(text, transaction, self.count(), p1, p2) + return self.addrevision(text, transaction, len(self), p1, p2) diff -r 54ccf41761c9 -r 39319a457dda mercurial/cmdutil.py --- a/mercurial/cmdutil.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/cmdutil.py Sat Jun 28 09:28:01 2008 +0200 @@ -126,7 +126,7 @@ if revrangesep in revs[0]: start, end = revs[0].split(revrangesep, 1) start = revfix(repo, start, 0) - end = revfix(repo, end, repo.changelog.count() - 1) + end = revfix(repo, end, len(repo) - 1) else: start = revfix(repo, revs[0], None) elif len(revs) == 2: @@ -151,7 +151,7 @@ if revrangesep in spec: start, end = spec.split(revrangesep, 1) start = revfix(repo, start, 0) - end = revfix(repo, end, repo.changelog.count() - 1) + end = revfix(repo, end, len(repo) - 1) step = start > end and -1 or 1 for rev in xrange(start, end+step, step): if rev in seen: @@ -245,7 +245,7 @@ '''find renamed files -- yields (before, after, score) tuples''' if added is None or removed is None: added, removed = repo.status()[1:3] - ctx = repo.changectx() + ctx = repo['.'] for a in added: aa = repo.wread(a) bestname, bestscore = None, threshold @@ -653,9 +653,7 @@ self.ui.write(_("copies: %s\n") % ' '.join(copies)) if extra and self.ui.debugflag: - extraitems = extra.items() - extraitems.sort() - for key, value in extraitems: + for key, value in util.sort(extra.items()): self.ui.write(_("extra: %s=%s\n") % (key, value.encode('string_escape'))) @@ -799,9 +797,7 @@ return showlist('tag', self.repo.nodetags(changenode), **args) def showextras(**args): - extras = changes[5].items() - extras.sort() - for key, value in extras: + for key, value in util.sort(changes[5].items()): args = args.copy() args.update(dict(key=key, value=value)) yield self.t('extra', **args) @@ -930,7 +926,7 @@ def finddate(ui, repo, date): """Find the tipmost changeset that matches the given date spec""" df = util.matchdate(date) - get = util.cachefunc(lambda r: repo.changectx(r).changeset()) + get = util.cachefunc(lambda r: repo[r].changeset()) changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None}) results = {} for st, rev, fns in changeiter: @@ -988,11 +984,11 @@ m = match(repo, pats, opts) follow = opts.get('follow') or opts.get('follow_first') - if repo.changelog.count() == 0: + if not len(repo): return [], m if follow: - defrange = '%s:0' % repo.changectx().rev() + defrange = '%s:0' % repo['.'].rev() else: defrange = '-1:0' revs = revrange(repo, opts['rev'] or [defrange]) @@ -1007,9 +1003,9 @@ if not slowpath: # Only files, no patterns. Check the history of each file. def filerevgen(filelog, node): - cl_count = repo.changelog.count() + cl_count = len(repo) if node is None: - last = filelog.count() - 1 + last = len(filelog) - 1 else: last = filelog.rev(node) for i, window in increasing_windows(last, nullrev): @@ -1032,7 +1028,7 @@ minrev, maxrev = min(revs), max(revs) for file_, node in iterfiles(): filelog = repo.file(file_) - if filelog.count() == 0: + if not len(filelog): if node is None: # A zero count may be a directory or deleted file, so # try to find matching entries on the slow path. @@ -1058,8 +1054,7 @@ # The slow path checks files modified in every changeset. def changerevgen(): - for i, window in increasing_windows(repo.changelog.count()-1, - nullrev): + for i, window in increasing_windows(len(repo) - 1, nullrev): for j in xrange(i - window, i + 1): yield j, change(j)[3] @@ -1130,9 +1125,7 @@ for i, window in increasing_windows(0, len(revs)): yield 'window', revs[0] < revs[-1], revs[-1] nrevs = [rev for rev in revs[i:i+window] if want(rev)] - srevs = list(nrevs) - srevs.sort() - for rev in srevs: + for rev in util.sort(list(nrevs)): fns = fncache.get(rev) if not fns: def fns_generator(): @@ -1159,9 +1152,8 @@ m = match(repo, pats, opts) if pats: - status = repo.status(match=m) - modified, added, removed, deleted, unknown = status[:5] - files = modified + added + removed + modified, added, removed = repo.status(match=m)[:3] + files = util.sort(modified + added + removed) slist = None for f in m.files(): if f == '.': @@ -1175,11 +1167,8 @@ raise util.Abort(_("file %s not found!") % rel) if stat.S_ISDIR(mode): name = f + '/' - if slist is None: - slist = list(files) - slist.sort() - i = bisect.bisect(slist, name) - if i >= len(slist) or not slist[i].startswith(name): + i = bisect.bisect(files, name) + if i >= len(files) or not files[i].startswith(name): raise util.Abort(_("no match under directory %s!") % rel) elif not (stat.S_ISREG(mode) or stat.S_ISLNK(mode)): diff -r 54ccf41761c9 -r 39319a457dda mercurial/commands.py --- a/mercurial/commands.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/commands.py Sat Jun 28 09:28:01 2008 +0200 @@ -107,7 +107,7 @@ lastfunc = funcmap[-1] funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1]) - ctx = repo.changectx(opts['rev']) + ctx = repo[opts['rev']] m = cmdutil.match(repo, pats, opts) for abs in repo.walk(m, ctx.node()): @@ -154,7 +154,7 @@ The default is the basename of the archive, with suffixes removed. ''' - ctx = repo.changectx(opts['rev']) + ctx = repo[opts['rev']] if not ctx: raise util.Abort(_('repository has no revisions')) node = ctx.node() @@ -189,7 +189,7 @@ hand. The result of this merge is not committed, as for a normal merge. - See 'hg help dates' for a list of formats valid for -d/--date. + See \'hg help dates\' for a list of formats valid for -d/--date. ''' if rev and node: raise util.Abort(_("please specify just one revision")) @@ -359,7 +359,7 @@ if label: if not opts.get('force') and label in repo.branchtags(): - if label not in [p.branch() for p in repo.workingctx().parents()]: + if label not in [p.branch() for p in repo.parents()]: raise util.Abort(_('a branch of the same name already exists' ' (use --force to override)')) repo.dirstate.setbranch(util.fromlocal(label)) @@ -378,11 +378,10 @@ Use the command 'hg update' to switch to an existing branch. """ hexfunc = ui.debugflag and hex or short - activebranches = [util.tolocal(repo.changectx(n).branch()) + activebranches = [util.tolocal(repo[n].branch()) for n in repo.heads()] - branches = [(tag in activebranches, repo.changelog.rev(node), tag) - for tag, node in repo.branchtags().items()] - branches.sort() + branches = util.sort([(tag in activebranches, repo.changelog.rev(node), tag) + for tag, node in repo.branchtags().items()]) branches.reverse() for isactive, node, tag in branches: @@ -483,7 +482,7 @@ %d dirname of file being printed, or '.' if in repo root %p root-relative path name of file being printed """ - ctx = repo.changectx(opts['rev']) + ctx = repo[opts['rev']] err = 1 m = cmdutil.match(repo, (file1,) + pats, opts) for abs in repo.walk(m, ctx.node()): @@ -635,35 +634,30 @@ ui.write("%s\n" % "\n".join(options)) return - clist = cmdutil.findpossible(ui, cmd, table).keys() - clist.sort() - ui.write("%s\n" % "\n".join(clist)) + ui.write("%s\n" % "\n".join(util.sort(cmdutil.findpossible(ui, cmd, table)))) def debugfsinfo(ui, path = "."): file('.debugfsinfo', 'w').write('') ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no')) ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no')) - ui.write('case-sensitive: %s\n' % (util.checkfolding('.debugfsinfo') + ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo') and 'yes' or 'no')) os.unlink('.debugfsinfo') -def debugrebuildstate(ui, repo, rev=""): +def debugrebuildstate(ui, repo, rev="tip"): """rebuild the dirstate as it would look like for the given revision""" - if rev == "": - rev = repo.changelog.tip() - ctx = repo.changectx(rev) - files = ctx.manifest() + ctx = repo[rev] wlock = repo.wlock() try: - repo.dirstate.rebuild(rev, files) + repo.dirstate.rebuild(ctx.node(), ctx.manifest()) finally: del wlock def debugcheckstate(ui, repo): """validate the correctness of the current dirstate""" parent1, parent2 = repo.dirstate.parents() - m1 = repo.changectx(parent1).manifest() - m2 = repo.changectx(parent2).manifest() + m1 = repo[parent1].manifest() + m2 = repo[parent2].manifest() errors = 0 for f in repo.dirstate: state = repo.dirstate[f] @@ -730,11 +724,9 @@ def debugstate(ui, repo, nodates=None): """show the contents of the current dirstate""" - k = repo.dirstate._map.items() - k.sort() timestr = "" showdate = not nodates - for file_, ent in k: + for file_, ent in util.sort(repo.dirstate._map.items()): if showdate: if ent[3] == -1: # Pad or slice to locale representation @@ -776,7 +768,7 @@ r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_) ui.write(" rev offset length base linkrev" + " nodeid p1 p2\n") - for i in xrange(r.count()): + for i in r: node = r.node(i) try: pp = r.parents(node) @@ -790,7 +782,7 @@ """dump an index DAG as a .dot file""" r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_) ui.write("digraph G {\n") - for i in xrange(r.count()): + for i in r: node = r.node(i) pp = r.parents(node) ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i)) @@ -913,7 +905,7 @@ def debugrename(ui, repo, file1, *pats, **opts): """dump rename information""" - ctx = repo.changectx(opts.get('rev', 'tip')) + ctx = repo[opts.get('rev')] m = cmdutil.match(repo, (file1,) + pats, opts) for abs in repo.walk(m, ctx.node()): fctx = ctx.filectx(abs) @@ -1122,7 +1114,7 @@ fstate = {} skip = {} - get = util.cachefunc(lambda r: repo.changectx(r).changeset()) + get = util.cachefunc(lambda r: repo[r].changeset()) changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) found = False follow = opts.get('follow') @@ -1130,7 +1122,7 @@ if st == 'window': matches.clear() elif st == 'add': - ctx = repo.changectx(rev) + ctx = repo[rev] matches[rev] = {} for fn in fns: if fn in skip: @@ -1145,9 +1137,7 @@ except revlog.LookupError: pass elif st == 'iter': - states = matches[rev].items() - states.sort() - for fn, m in states: + for fn, m in util.sort(matches[rev].items()): copy = copies.get(rev, {}).get(fn) if fn in skip: if copy: @@ -1165,9 +1155,7 @@ fstate[copy] = m prev[fn] = rev - fstate = fstate.items() - fstate.sort() - for fn, state in fstate: + for fn, state in util.sort(fstate.items()): if fn in skip: continue if fn not in copies.get(prev[fn], {}): @@ -1202,7 +1190,7 @@ heads = [] visitedset = util.set() for branchrev in branchrevs: - branch = repo.changectx(branchrev).branch() + branch = repo[branchrev].branch() if branch in visitedset: continue visitedset.add(branch) @@ -1307,8 +1295,7 @@ return ui.status(header) - fns = h.keys() - fns.sort() + fns = util.sort(h) m = max(map(len, fns)) for f in fns: if ui.verbose: @@ -1454,7 +1441,7 @@ "can't query remote revision number, branch, or tags") output = [hexfunc(srepo.lookup(rev))] elif not rev: - ctx = repo.workingctx() + ctx = repo[None] parents = ctx.parents() changed = False if default or id or num: @@ -1466,7 +1453,7 @@ output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]), (changed) and "+" or "")) else: - ctx = repo.changectx(rev) + ctx = repo[rev] if default or id: output = [hexfunc(ctx.node())] if num: @@ -1563,7 +1550,7 @@ message = None ui.debug(_('message:\n%s\n') % message) - wp = repo.workingctx().parents() + wp = repo.parents() if opts.get('exact'): if not nodeid or not p1: raise util.Abort(_('not a mercurial patch')) @@ -1756,7 +1743,7 @@ """ - get = util.cachefunc(lambda r: repo.changectx(r).changeset()) + get = util.cachefunc(lambda r: repo[r].changeset()) changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) limit = cmdutil.loglimit(opts) @@ -1765,7 +1752,7 @@ if opts['copies'] and opts['rev']: endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1 else: - endrev = repo.changelog.count() + endrev = len(repo) rcache = {} ncache = {} def getrenamed(fn, rev): @@ -1777,7 +1764,7 @@ rcache[fn] = {} ncache[fn] = {} fl = repo.file(fn) - for i in xrange(fl.count()): + for i in fl: node = fl.node(i) lr = fl.linkrev(node) renamed = fl.renamed(node) @@ -1793,7 +1780,7 @@ # filectx logic. try: - return repo.changectx(rev).filectx(fn).renamed() + return repo[rev][fn].renamed() except revlog.LookupError: pass return None @@ -1869,17 +1856,13 @@ if not node: node = rev - m = repo.changectx(node).manifest() - files = m.keys() - files.sort() - - for f in files: + decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '} + ctx = repo[node] + for f in ctx: if ui.debugflag: - ui.write("%40s " % hex(m[f])) + ui.write("%40s " % hex(ctx.manifest()[f])) if ui.verbose: - type = m.execf(f) and "*" or m.linkf(f) and "@" or " " - perm = m.execf(f) and "755" or "644" - ui.write("%3s %1s " % (perm, type)) + ui.write(decor[ctx.flags(f)]) ui.write("%s\n" % f) def merge(ui, repo, node=None, force=None, rev=None): @@ -1902,7 +1885,7 @@ node = rev if not node: - branch = repo.workingctx().branch() + branch = repo.changectx(None).branch() bheads = repo.branchheads() if len(bheads) > 2: raise util.Abort(_("branch '%s' has %d heads - " @@ -1916,7 +1899,7 @@ "please merge with an explicit rev") % branch) msg = _('there is nothing to merge') - if parent != repo.lookup(repo.workingctx().branch()): + if parent != repo.lookup(repo[None].branch()): msg = _('%s - use "hg update" instead') % msg raise util.Abort(msg) @@ -1973,9 +1956,9 @@ """ rev = opts.get('rev') if rev: - ctx = repo.changectx(rev) + ctx = repo[rev] else: - ctx = repo.workingctx() + ctx = repo[None] if file_: m = cmdutil.match(repo, (file_,), opts) @@ -2204,46 +2187,27 @@ raise util.Abort(_('no files specified')) m = cmdutil.match(repo, pats, opts) - mardu = map(dict.fromkeys, repo.status(match=m))[:5] - modified, added, removed, deleted, unknown = mardu - - remove, forget = [], [] - for abs in repo.walk(m): - - reason = None - if abs in removed or abs in unknown: - continue - - # last column - elif abs in deleted: - remove.append(abs) - - # rest of the third row - elif after and not force: - reason = _('still exists (use -f to force removal)') - - # rest of the first column - elif abs in added: - if not force: - reason = _('has been marked for add (use -f to force removal)') - else: - forget.append(abs) - - # rest of the third column - elif abs in modified: - if not force: - reason = _('is modified (use -f to force removal)') - else: - remove.append(abs) - - # rest of the second column - elif not reason: - remove.append(abs) - - if reason: - ui.warn(_('not removing %s: file %s\n') % (m.rel(abs), reason)) - elif ui.verbose or not m.exact(abs): - ui.status(_('removing %s\n') % m.rel(abs)) + s = repo.status(match=m, clean=True) + modified, added, deleted, clean = s[0], s[1], s[3], s[6] + + def warn(files, reason): + for f in files: + ui.warn(_('not removing %s: file %s (use -f to force removal)\n') + % (m.rel(f), reason)) + + if force: + remove, forget = modified + deleted + clean, added + elif after: + remove, forget = deleted, [] + warn(modified + added + clean, _('still exists')) + else: + remove, forget = deleted + clean, [] + warn(modified, _('is modified')) + warn(added, _('has been marked for add')) + + for f in util.sort(remove + forget): + if ui.verbose or not m.exact(f): + ui.status(_('removing %s\n') % m.rel(f)) repo.forget(forget) repo.remove(remove, unlink=not after) @@ -2297,7 +2261,7 @@ elif opts.get("unmark"): ms.mark(f, "u") else: - wctx = repo.workingctx() + wctx = repo[None] mctx = wctx.parents()[-1] ms.resolve(f, wctx, mctx) @@ -2348,7 +2312,7 @@ if not opts['rev'] and p2 != nullid: raise util.Abort(_('uncommitted merge - please provide a ' 'specific revision')) - ctx = repo.changectx(opts['rev']) + ctx = repo[opts['rev']] node = ctx.node() mf = ctx.manifest() if node == parent: @@ -2425,10 +2389,7 @@ (deleted, revert, remove, False, False), ) - entries = names.items() - entries.sort() - - for abs, (rel, exact) in entries: + for abs, (rel, exact) in util.sort(names.items()): mfentry = mf.get(abs) target = repo.wjoin(abs) def handle(xlist, dobackup): @@ -2466,7 +2427,7 @@ if pmf is None: # only need parent manifest in this unlikely case, # so do not read by default - pmf = repo.changectx(parent).manifest() + pmf = repo[parent].manifest() if abs in pmf: if mfentry: # if version of file is same in parent and target @@ -2480,7 +2441,7 @@ if not opts.get('dry_run'): def checkout(f): fc = ctx[f] - repo.wwrite(f, fc.data(), fc.fileflags()) + repo.wwrite(f, fc.data(), fc.flags()) audit_path = util.path_auditor(repo.root) for f in remove[0]: @@ -2668,13 +2629,13 @@ changestates = zip(states, 'MAR!?IC', stat) if (opts['all'] or opts['copies']) and not opts['no_status']: - ctxn = repo.changectx(nullid) - ctx1 = repo.changectx(node1) - ctx2 = repo.changectx(node2) + ctxn = repo[nullid] + ctx1 = repo[node1] + ctx2 = repo[node2] added = stat[1] if node2 is None: added = stat[0] + stat[1] # merged? - ctx2 = repo.workingctx() + for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].items(): if k in added: copy[k] = v @@ -2713,7 +2674,7 @@ See 'hg help dates' for a list of formats valid for -d/--date. """ - rev_ = None + rev_ = "." names = (name1,) + names if len(names) != len(dict.fromkeys(names)): raise util.Abort(_('tag names must be unique')) @@ -2744,7 +2705,7 @@ if not rev_ and repo.dirstate.parents()[1] != nullid: raise util.Abort(_('uncommitted merge - please provide a ' 'specific revision')) - r = repo.changectx(rev_).node() + r = repo[rev_].node() if not message: message = (_('Added tag %s for changeset %s') % @@ -2801,7 +2762,7 @@ that repository becomes the current tip. The "tip" tag is special and cannot be renamed or assigned to a different changeset. """ - cmdutil.show_changeset(ui, repo, opts).show(nullrev+repo.changelog.count()) + cmdutil.show_changeset(ui, repo, opts).show(len(repo) - 1) def unbundle(ui, repo, fname1, *fnames, **opts): """apply one or more changegroup files diff -r 54ccf41761c9 -r 39319a457dda mercurial/context.py --- a/mercurial/context.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/context.py Sat Jun 28 09:28:01 2008 +0200 @@ -12,19 +12,11 @@ class changectx(object): """A changecontext object makes access to data related to a particular changeset convenient.""" - def __init__(self, repo, changeid=None): + def __init__(self, repo, changeid=''): """changeid is a revision number, node, or tag""" + if changeid == '': + changeid = '.' self._repo = repo - - if not changeid and changeid != 0: - p1, p2 = self._repo.dirstate.parents() - self._rev = self._repo.changelog.rev(p1) - if self._rev == -1: - changeid = 'tip' - else: - self._node = p1 - return - self._node = self._repo.lookup(changeid) self._rev = self._repo.changelog.rev(self._node) @@ -63,6 +55,12 @@ md = self._repo.manifest.readdelta(self._changeset[0]) self._manifestdelta = md return self._manifestdelta + elif name == '_parents': + p = self._repo.changelog.parents(self._node) + if p[1] == nullid: + p = p[:-1] + self._parents = [changectx(self._repo, x) for x in p] + return self._parents else: raise AttributeError, name @@ -73,9 +71,7 @@ return self.filectx(key) def __iter__(self): - a = self._manifest.keys() - a.sort() - for f in a: + for f in util.sort(self._manifest): yield f def changeset(self): return self._changeset @@ -93,8 +89,7 @@ def parents(self): """return contexts for each parent changeset""" - p = self._repo.changelog.parents(self._node) - return [changectx(self._repo, x) for x in p] + return self._parents def children(self): """return contexts for each child changeset""" @@ -121,7 +116,7 @@ def filenode(self, path): return self._fileinfo(path)[0] - def fileflags(self, path): + def flags(self, path): try: return self._fileinfo(path)[1] except revlog.LookupError: @@ -137,10 +132,7 @@ def filectxs(self): """generate a file context for each file in this changeset's manifest""" - mf = self.manifest() - m = mf.keys() - m.sort() - for f in m: + for f in util.sort(mf): yield self.filectx(f, fileid=mf[f]) def ancestor(self, c2): @@ -240,9 +232,7 @@ def filerev(self): return self._filerev def filenode(self): return self._filenode - def fileflags(self): return self._changectx.fileflags(self._path) - def isexec(self): return 'x' in self.fileflags() - def islink(self): return 'l' in self.fileflags() + def flags(self): return self._changectx.flags(self._path) def filelog(self): return self._filelog def rev(self): @@ -388,12 +378,11 @@ # sort by revision (per file) which is a topological order visit = [] for f in files: - fn = [(n.rev(), n) for n in needed.keys() if n._path == f] + fn = [(n.rev(), n) for n in needed if n._path == f] visit.extend(fn) - visit.sort() + hist = {} - - for r, f in visit: + for r, f in util.sort(visit): curr = decorate(f.data(), f) for p in parents(f): if p != nullid: @@ -468,7 +457,7 @@ self._user = self._repo.ui.username() if parents: p1, p2 = parents - self._parents = [self._repo.changectx(p) for p in (p1, p2)] + self._parents = [changectx(self._repo, p) for p in (p1, p2)] if changes: self._status = list(changes) @@ -492,15 +481,18 @@ return True def __getattr__(self, name): - if name == '_parents': - self._parents = self._repo.parents() - return self._parents if name == '_status': - self._status = self._repo.status() + self._status = self._repo.status(unknown=True) return self._status if name == '_manifest': self._buildmanifest() return self._manifest + elif name == '_parents': + p = self._repo.dirstate.parents() + if p[1] == nullid: + p = p[:-1] + self._parents = [changectx(self._repo, x) for x in p] + return self._parents else: raise AttributeError, name @@ -509,16 +501,14 @@ man = self._parents[0].manifest().copy() copied = self._repo.dirstate.copies() - is_exec = util.execfunc(self._repo.root, - lambda p: man.execf(copied.get(p,p))) - is_link = util.linkfunc(self._repo.root, - lambda p: man.linkf(copied.get(p,p))) + cf = lambda x: man.flags(copied.get(x, x)) + ff = self._repo.dirstate.flagfunc(cf) modified, added, removed, deleted, unknown = self._status[:5] for i, l in (("a", added), ("m", modified), ("u", unknown)): for f in l: man[f] = man.get(copied.get(f, f), nullid) + i try: - man.set(f, is_exec(f), is_link(f)) + man.set(f, ff(f)) except OSError: pass @@ -534,9 +524,7 @@ def date(self): return self._date def description(self): return self._text def files(self): - f = self.modified() + self.added() + self.removed() - f.sort() - return f + return util.sort(self._status[0] + self._status[1] + self._status[2]) def modified(self): return self._status[0] def added(self): return self._status[1] @@ -552,14 +540,10 @@ [t.extend(p.tags()) for p in self.parents()] return t - def parents(self): - """return contexts for each parent changeset""" - return self._parents - def children(self): return [] - def fileflags(self, path): + def flags(self, path): if '_manifest' in self.__dict__: try: return self._manifest.flags(path) @@ -569,12 +553,9 @@ pnode = self._parents[0].changeset()[0] orig = self._repo.dirstate.copies().get(path, path) node, flag = self._repo.manifest.find(pnode, orig) - is_link = util.linkfunc(self._repo.root, - lambda p: flag and 'l' in flag) - is_exec = util.execfunc(self._repo.root, - lambda p: flag and 'x' in flag) try: - return (is_link(path) and 'l' or '') + (is_exec(path) and 'x' or '') + ff = self._repo.dirstate.flagfunc(lambda x: flag or '') + return ff(path) except OSError: pass @@ -698,9 +679,8 @@ self._user = user or self._repo.ui.username() parents = [(p or nullid) for p in parents] p1, p2 = parents - self._parents = [self._repo.changectx(p) for p in (p1, p2)] - files = list(files) - files.sort() + self._parents = [changectx(self._repo, p) for p in (p1, p2)] + files = util.sort(list(files)) self._status = [files, [], [], [], []] self._filectxfn = filectxfn @@ -728,6 +708,7 @@ def clean(self): return self._status[5] def branch(self): return self._extra['branch'] def extra(self): return self._extra + def flags(self, f): return self[f].flags() def parents(self): """return contexts for each parent changeset""" @@ -754,7 +735,7 @@ def __str__(self): return "%s@%s" % (self.path(), self._changectx) def path(self): return self._path def data(self): return self._data - def fileflags(self): return self._flags + def flags(self): return self._flags def isexec(self): return 'x' in self._flags def islink(self): return 'l' in self._flags def renamed(self): return self._copied diff -r 54ccf41761c9 -r 39319a457dda mercurial/copies.py --- a/mercurial/copies.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/copies.py Sat Jun 28 09:28:01 2008 +0200 @@ -11,9 +11,7 @@ def _nonoverlap(d1, d2, d3): "Return list of elements in d1 not in d2 or d3" - l = [d for d in d1 if d not in d3 and d not in d2] - l.sort() - return l + return util.sort([d for d in d1 if d not in d3 and d not in d2]) def _dirname(f): s = f.rfind("/") @@ -49,9 +47,7 @@ visit += [(p, depth - 1) for p in fc.parents()] # return old names sorted by depth - old = old.values() - old.sort() - return [o[1] for o in old] + return [o[1] for o in util.sort(old.values())] def _findlimit(repo, a, b): "find the earliest revision that's an ancestor of a or b but not both" @@ -67,7 +63,7 @@ # - quit when interesting revs is zero cl = repo.changelog - working = cl.count() # pseudo rev for the working directory + working = len(cl) # pseudo rev for the working directory if a is None: a = working if b is None: diff -r 54ccf41761c9 -r 39319a457dda mercurial/dirstate.py --- a/mercurial/dirstate.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/dirstate.py Sat Jun 28 09:28:01 2008 +0200 @@ -70,14 +70,17 @@ elif name == '_slash': self._slash = self._ui.configbool('ui', 'slash') and os.sep != '/' return self._slash + elif name == '_checklink': + self._checklink = util.checklink(self._root) + return self._checklink elif name == '_checkexec': self._checkexec = util.checkexec(self._root) return self._checkexec - elif name == '_folding': - self._folding = not util.checkfolding(self._join('.hg')) - return self._folding + elif name == '_checkcase': + self._checkcase = not util.checkcase(self._join('.hg')) + return self._checkcase elif name == 'normalize': - if self._folding: + if self._checkcase: self.normalize = self._normalize else: self.normalize = lambda x: x @@ -88,8 +91,33 @@ def _join(self, f): return os.path.join(self._root, f) - def folding(self): - return self._folding + def flagfunc(self, fallback): + if self._checklink: + if self._checkexec: + def f(x): + p = os.path.join(self._root, x) + if os.path.islink(p): + return 'l' + if util.is_exec(p): + return 'x' + return '' + return f + def f(x): + if os.path.islink(os.path.join(self._root, x)): + return 'l' + if 'x' in fallback(x): + return 'x' + return '' + return f + if self._checkexec: + def f(x): + if 'l' in fallback(x): + return 'l' + if util.is_exec(os.path.join(self._root, x)): + return 'x' + return '' + return f + return fallback def getcwd(self): cwd = os.getcwd() @@ -125,9 +153,7 @@ return key in self._map def __iter__(self): - a = self._map.keys() - a.sort() - for x in a: + for x in util.sort(self._map): yield x def parents(self): @@ -356,7 +382,7 @@ def rebuild(self, parent, files): self.clear() for f in files: - if files.execf(f): + if 'x' in files.flags(f): self._map[f] = ('n', 0777, -1, 0, 0) else: self._map[f] = ('n', 0666, -1, 0, 0) @@ -408,8 +434,7 @@ if not unknown: return ret - b = self._map.keys() - b.sort() + b = util.sort(self._map) blen = len(b) for x in unknown: @@ -447,12 +472,7 @@ return True return False - def walk(self, match): - # filter out the src and stat - for src, f, st in self.statwalk(match): - yield f - - def statwalk(self, match, unknown=True, ignored=False): + def walk(self, match, unknown, ignored): ''' walk recursively through the directory tree, finding all files matched by the match function @@ -537,9 +557,10 @@ continue for f, kind, st in entries: np = pconvert(join(nd, f)) + nn = self.normalize(np) if np in known: continue - known[np] = 1 + known[nn] = 1 p = join(top, f) # don't trip over symlinks if kind == stat.S_IFDIR: @@ -548,19 +569,18 @@ if hasattr(match, 'dir'): match.dir(np) if np in dc and match(np): - add((np, 'm', st)) + add((nn, 'm', st)) elif imatch(np): if supported(np, st.st_mode): - add((np, 'f', st)) + add((nn, 'f', st)) elif np in dc: - add((np, 'm', st)) - found.sort() - return found + add((nn, 'm', st)) + return util.sort(found) # step one, find all files that match our criteria - files.sort() - for ff in files: + for ff in util.sort(files): nf = normpath(ff) + nn = self.normalize(nf) f = _join(ff) try: st = lstat(f) @@ -581,9 +601,9 @@ for f, src, st in findfiles(f): yield src, f, st else: - if nf in known: + if nn in known: continue - known[nf] = 1 + known[nn] = 1 if match(nf): if supported(ff, st.st_mode, verbose=True): yield 'f', self.normalize(nf), st @@ -592,16 +612,15 @@ # step two run through anything left in the dc hash and yield # if we haven't already seen it - ks = dc.keys() - ks.sort() - for k in ks: + for k in util.sort(dc): if k in known: continue known[k] = 1 if imatch(k): yield 'm', k, None - def status(self, match, list_ignored, list_clean, list_unknown): + def status(self, match, ignored, clean, unknown): + listignored, listclean, listunknown = ignored, clean, unknown lookup, modified, added, unknown, ignored = [], [], [], [], [] removed, deleted, clean = [], [], [] @@ -618,13 +637,12 @@ dadd = deleted.append cadd = clean.append - for src, fn, st in self.statwalk(match, unknown=list_unknown, - ignored=list_ignored): + for src, fn, st in self.walk(match, listunknown, listignored): if fn not in dmap: - if (list_ignored or match.exact(fn)) and self._dirignore(fn): - if list_ignored: + if (listignored or match.exact(fn)) and self._dirignore(fn): + if listignored: iadd(fn) - elif list_unknown: + elif listunknown: uadd(fn) continue @@ -657,7 +675,7 @@ madd(fn) elif time != int(st.st_mtime): ladd(fn) - elif list_clean: + elif listclean: cadd(fn) elif state == 'm': madd(fn) diff -r 54ccf41761c9 -r 39319a457dda mercurial/filemerge.py --- a/mercurial/filemerge.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/filemerge.py Sat Jun 28 09:28:01 2008 +0200 @@ -63,8 +63,7 @@ if t not in tools: tools[t] = int(_toolstr(ui, t, "priority", "0")) names = tools.keys() - tools = [(-p,t) for t,p in tools.items()] - tools.sort() + tools = util.sort([(-p,t) for t,p in tools.items()]) uimerge = ui.config("ui", "merge") if uimerge: if uimerge not in names: @@ -132,7 +131,7 @@ ui = repo.ui fd = fcd.path() binary = isbin(fcd) or isbin(fco) or isbin(fca) - symlink = fcd.islink() or fco.islink() + symlink = 'l' in fcd.flags() + fco.flags() tool, toolpath = _picktool(repo, ui, fd, binary, symlink) ui.debug(_("picked tool '%s' for %s (binary %s symlink %s)\n") % (tool, fd, binary, symlink)) @@ -146,7 +145,7 @@ if tool == "internal:local": return 0 if tool == "internal:other": - repo.wwrite(fd, fco.data(), fco.fileflags()) + repo.wwrite(fd, fco.data(), fco.flags()) return 0 if tool == "internal:fail": return 1 @@ -180,9 +179,9 @@ env = dict(HG_FILE=fd, HG_MY_NODE=short(mynode), HG_OTHER_NODE=str(fco.changectx()), - HG_MY_ISLINK=fcd.islink(), - HG_OTHER_ISLINK=fco.islink(), - HG_BASE_ISLINK=fca.islink()) + HG_MY_ISLINK='l' in fcd.flags(), + HG_OTHER_ISLINK='l' in fco.flags(), + HG_BASE_ISLINK='l' in fca.flags()) if tool == "internal:merge": r = simplemerge.simplemerge(a, b, c, label=['local', 'other']) diff -r 54ccf41761c9 -r 39319a457dda mercurial/graphmod.py --- a/mercurial/graphmod.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/graphmod.py Sat Jun 28 09:28:01 2008 +0200 @@ -69,6 +69,6 @@ edges.append((col, next.index(p), colors[p])) # Yield and move on - yield (repo.changectx(curr_rev), (idx, color), edges) + yield (repo[curr_rev], (idx, color), edges) revs = next curr_rev -= 1 diff -r 54ccf41761c9 -r 39319a457dda mercurial/hbisect.py --- a/mercurial/hbisect.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/hbisect.py Sat Jun 28 09:28:01 2008 +0200 @@ -20,12 +20,12 @@ badrev = min([changelog.rev(n) for n in bad]) goodrevs = [changelog.rev(n) for n in good] # build ancestors array - ancestors = [[]] * (changelog.count() + 1) # an extra for [-1] + ancestors = [[]] * (len(changelog) + 1) # an extra for [-1] # clear good revs from array for node in goodrevs: ancestors[node] = None - for rev in xrange(changelog.count(), -1, -1): + for rev in xrange(len(changelog), -1, -1): if ancestors[rev] is None: for prev in clparents(rev): ancestors[prev] = None @@ -60,7 +60,6 @@ children[prev] = [rev] visit.append(prev) - candidates.sort() # have we narrowed it down to one entry? tot = len(candidates) if tot == 1: @@ -71,7 +70,7 @@ best_rev = None best_len = -1 poison = {} - for rev in candidates: + for rev in util.sort(candidates): if rev in poison: for c in children.get(rev, []): poison[c] = True # poison children diff -r 54ccf41761c9 -r 39319a457dda mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/hgweb/hgweb_mod.py Sat Jun 28 09:28:01 2008 +0200 @@ -306,8 +306,8 @@ linenumber="% 8s" % lineno) r = self.repo - c1 = r.changectx(node1) - c2 = r.changectx(node2) + c1 = r[node1] + c2 = r[node2] date1 = util.datestr(c1.date()) date2 = util.datestr(c2.date()) diff -r 54ccf41761c9 -r 39319a457dda mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/hgweb/hgwebdir_mod.py Sat Jun 28 09:28:01 2008 +0200 @@ -19,8 +19,8 @@ class hgwebdir(object): def __init__(self, config, parentui=None): def cleannames(items): - return [(util.pconvert(name).strip('/'), path) - for name, path in items] + return util.sort([(util.pconvert(name).strip('/'), path) + for name, path in items]) self.parentui = parentui or ui.ui(report_untrusted=False, interactive = False) @@ -34,7 +34,6 @@ self.repos_sorted = ('', False) elif isinstance(config, dict): self.repos = cleannames(config.items()) - self.repos.sort() else: if isinstance(config, util.configparser): cp = config diff -r 54ccf41761c9 -r 39319a457dda mercurial/hgweb/webcommands.py --- a/mercurial/hgweb/webcommands.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/hgweb/webcommands.py Sat Jun 28 09:28:01 2008 +0200 @@ -13,7 +13,7 @@ from mercurial.repo import RepoError from common import paritygen, staticfile, get_contact, ErrorResponse from common import HTTP_OK, HTTP_NOT_FOUND -from mercurial import graphmod +from mercurial import graphmod, util # __all__ is populated with the allowed commands. Be sure to add to it if # you're adding a new command, or the new command won't work. @@ -110,10 +110,10 @@ qw = query.lower().split() def revgen(): - for i in xrange(cl.count() - 1, 0, -100): + for i in xrange(len(cl) - 1, 0, -100): l = [] for j in xrange(max(0, i - 100), i + 1): - ctx = web.repo.changectx(j) + ctx = web.repo[j] l.append(ctx) l.reverse() for e in l: @@ -168,9 +168,9 @@ if 'rev' in req.form: hi = req.form['rev'][0] else: - hi = web.repo.changelog.count() - 1 + hi = len(web.repo) - 1 try: - ctx = web.repo.changectx(hi) + ctx = web.repo[hi] except RepoError: return _search(web, tmpl, hi) # XXX redirect to 404 page? @@ -178,7 +178,7 @@ cl = web.repo.changelog l = [] # build a list in forward order for efficiency for i in xrange(start, end): - ctx = web.repo.changectx(i) + ctx = web.repo[i] n = ctx.node() showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) @@ -205,7 +205,7 @@ maxchanges = shortlog and web.maxshortchanges or web.maxchanges cl = web.repo.changelog - count = cl.count() + count = len(cl) pos = ctx.rev() start = max(0, pos - maxchanges + 1) end = min(count, start + maxchanges) @@ -288,9 +288,7 @@ raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path) def filelist(**map): - fl = files.keys() - fl.sort() - for f in fl: + for f in util.sort(files): full, fnode = files[f] if not fnode: continue @@ -299,14 +297,12 @@ yield {"file": full, "parity": parity.next(), "basename": f, - "date": fctx.changectx().date(), + "date": fctx.date(), "size": fctx.size(), "permissions": mf.flags(full)} def dirlist(**map): - fl = files.keys() - fl.sort() - for f in fl: + for f in util.sort(files): full, fnode = files[f] if fnode: continue @@ -343,7 +339,7 @@ count = count + 1 yield {"parity": parity.next(), "tag": k, - "date": web.repo.changectx(n).date(), + "date": web.repo[n].date(), "node": hex(n)} return tmpl("tags", @@ -371,27 +367,24 @@ parity=parity.next(), tag=k, node=hex(n), - date=web.repo.changectx(n).date()) + date=web.repo[n].date()) def branches(**map): parity = paritygen(web.stripecount) b = web.repo.branchtags() l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.items()] - l.sort() - - for r,n,t in l: - ctx = web.repo.changectx(n) + for r,n,t in util.sort(l): yield {'parity': parity.next(), 'branch': t, 'node': hex(n), - 'date': ctx.date()} + 'date': web.repo[n].date()} def changelist(**map): parity = paritygen(web.stripecount, offset=start-end) l = [] # build a list in forward order for efficiency for i in xrange(start, end): - ctx = web.repo.changectx(i) + ctx = web.repo[i] n = ctx.node() hn = hex(n) @@ -410,7 +403,7 @@ yield l cl = web.repo.changelog - count = cl.count() + count = len(cl) start = max(0, count - web.maxchanges) end = min(count, start + web.maxchanges) @@ -499,7 +492,7 @@ fctx = webutil.filectx(web.repo, req) f = fctx.path() fl = fctx.filelog() - count = fl.count() + count = len(fl) pagelen = web.maxshortchanges pos = fctx.filerev() start = max(0, pos - pagelen + 1) @@ -580,7 +573,7 @@ rev = webutil.changectx(web.repo, req).rev() bg_height = 39 - max_rev = web.repo.changelog.count() - 1 + max_rev = len(web.repo) - 1 revcount = min(max_rev, int(req.form.get('revcount', [25])[0])) revnode = web.repo.changelog.node(rev) revnode_hex = hex(revnode) @@ -589,7 +582,7 @@ lessrev = max(0, rev - revcount / 2) maxchanges = web.maxshortchanges or web.maxchanges - count = web.repo.changelog.count() + count = len(web.repo) changenav = webutil.revnavgen(rev, maxchanges, count, web.repo.changectx) tree = list(graphmod.graph(web.repo, rev, rev - revcount)) diff -r 54ccf41761c9 -r 39319a457dda mercurial/hgweb/webutil.py --- a/mercurial/hgweb/webutil.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/hgweb/webutil.py Sat Jun 28 09:28:01 2008 +0200 @@ -112,19 +112,17 @@ return util.canonpath(repo.root, '', path) def changectx(repo, req): + changeid = "tip" if 'node' in req.form: changeid = req.form['node'][0] elif 'manifest' in req.form: changeid = req.form['manifest'][0] - else: - changeid = repo.changelog.count() - 1 try: - ctx = repo.changectx(changeid) + ctx = repo[changeid] except RepoError: man = repo.manifest - mn = man.lookup(changeid) - ctx = repo.changectx(man.linkrev(mn)) + ctx = repo[man.linkrev(man.lookup(changeid))] return ctx @@ -135,8 +133,7 @@ else: changeid = req.form['filenode'][0] try: - ctx = repo.changectx(changeid) - fctx = ctx.filectx(path) + fctx = repo[changeid][path] except RepoError: fctx = repo.filectx(path, fileid=changeid) diff -r 54ccf41761c9 -r 39319a457dda mercurial/hook.py --- a/mercurial/hook.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/hook.py Sat Jun 28 09:28:01 2008 +0200 @@ -96,10 +96,9 @@ oldstdout = os.dup(sys.__stdout__.fileno()) os.dup2(sys.__stderr__.fileno(), sys.__stdout__.fileno()) - hooks = [(hname, cmd) for hname, cmd in ui.configitems("hooks") - if hname.split(".", 1)[0] == name and cmd] - hooks.sort() - for hname, cmd in hooks: + for hname, cmd in util.sort(ui.configitems('hooks')): + if hname.split('.')[0] != name or not cmd: + continue if callable(cmd): r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r elif cmd.startswith('python:'): diff -r 54ccf41761c9 -r 39319a457dda mercurial/localrepo.py --- a/mercurial/localrepo.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/localrepo.py Sat Jun 28 09:28:01 2008 +0200 @@ -117,6 +117,21 @@ else: raise AttributeError, name + def __getitem__(self, changeid): + if changeid == None: + return context.workingctx(self) + return context.changectx(self, changeid) + + def __nonzero__(self): + return True + + def __len__(self): + return len(self.changelog) + + def __iter__(self): + for i in xrange(len(self)): + yield i + def url(self): return 'file:' + self.root @@ -330,7 +345,7 @@ last = {} ret = [] for node in heads: - c = self.changectx(node) + c = self[node] rev = c.rev() try: fnode = c.filenode('.hgtags') @@ -351,8 +366,7 @@ except: r = -2 # sort to the beginning of the list if unknown l.append((r, t, n)) - l.sort() - return [(t, n) for r, t, n in l] + return [(t, n) for r, t, n in util.sort(l)] def nodetags(self, node): '''return the tags associated with a node''' @@ -363,7 +377,7 @@ return self.nodetagscache.get(node, []) def _branchtags(self, partial, lrev): - tiprev = self.changelog.count() - 1 + tiprev = len(self) - 1 if lrev != tiprev: self._updatebranchcache(partial, lrev+1, tiprev+1) self._writebranchcache(partial, self.changelog.tip(), tiprev) @@ -408,8 +422,7 @@ try: last, lrev = lines.pop(0).split(" ", 1) last, lrev = bin(last), int(lrev) - if not (lrev < self.changelog.count() and - self.changelog.node(lrev) == last): # sanity check + if lrev >= len(self) or self[lrev].node() != last: # invalidate the cache raise ValueError('invalidating branch cache (tip differs)') for l in lines: @@ -436,18 +449,13 @@ def _updatebranchcache(self, partial, start, end): for r in xrange(start, end): - c = self.changectx(r) + c = self[r] b = c.branch() partial[b] = c.node() def lookup(self, key): if key == '.': - key, second = self.dirstate.parents() - if key == nullid: - raise repo.RepoError(_("no revision checked out")) - if second != nullid: - self.ui.warn(_("warning: working directory has two parents, " - "tag '.' uses the first\n")) + return self.dirstate.parents()[0] elif key == 'null': return nullid n = self.changelog._match(key) @@ -488,24 +496,12 @@ f = f[1:] return filelog.filelog(self.sopener, f) - def changectx(self, changeid=None): - return context.changectx(self, changeid) - - def workingctx(self): - return context.workingctx(self) + def changectx(self, changeid): + return self[changeid] def parents(self, changeid=None): - ''' - get list of changectxs for parents of changeid or working directory - ''' - if changeid is None: - pl = self.dirstate.parents() - else: - n = self.changelog.lookup(changeid) - pl = self.changelog.parents(n) - if pl[1] == nullid: - return [self.changectx(pl[0])] - return [self.changectx(pl[0]), self.changectx(pl[1])] + '''get list of changectxs for parents of changeid''' + return self[changeid].parents() def filectx(self, path, changeid=None, fileid=None): """changeid can be a changeset revision, node, or tag. @@ -814,7 +810,7 @@ tr = None valid = 0 # don't save the dirstate if this isn't set try: - commit = wctx.modified() + wctx.added() + commit = util.sort(wctx.modified() + wctx.added()) remove = wctx.removed() extra = wctx.extra().copy() branchname = extra['branch'] @@ -846,25 +842,21 @@ # check in files new = {} changed = [] - linkrev = self.changelog.count() - commit.sort() + linkrev = len(self) for f in commit: self.ui.note(f + "\n") try: fctx = wctx.filectx(f) + newflags = fctx.flags() new[f] = self.filecommit(fctx, m1, m2, linkrev, trp, changed) - new_exec = fctx.isexec() - new_link = fctx.islink() if ((not changed or changed[-1] != f) and m2.get(f) != new[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: + if m1.flags(f) != newflags: changed.append(f) - m1.set(f, new_exec, new_link) + m1.set(f, newflags) if use_dirstate: self.dirstate.normal(f) @@ -877,10 +869,9 @@ # update manifest m1.update(new) - remove.sort() removed = [] - for f in remove: + for f in util.sort(remove): if f in m1: del m1[f] removed.append(f) @@ -956,10 +947,7 @@ # for dirstate.walk, files=['.'] means "walk the whole tree". # follow that here, too fdict.pop('.', None) - mdict = self.manifest.read(self.changelog.read(node)[0]) - mfiles = mdict.keys() - mfiles.sort() - for fn in mfiles: + for fn in self[node]: for ffn in fdict: # match if the file is the exact name or a directory if ffn == fn or fn.startswith("%s/" % ffn): @@ -967,18 +955,16 @@ break if match(fn): yield fn - ffiles = fdict.keys() - ffiles.sort() - for fn in ffiles: + for fn in util.sort(fdict): if match.bad(fn, 'No such file in rev ' + short(node)) \ and match(fn): yield fn else: - for fn in self.dirstate.walk(match): + for src, fn, st in self.dirstate.walk(match, True, False): yield fn def status(self, node1=None, node2=None, match=None, - list_ignored=False, list_clean=False, list_unknown=True): + ignored=False, clean=False, unknown=False): """return status of files between two nodes or node and working directory If node1 is None, use the first dirstate parent instead. @@ -1000,6 +986,7 @@ if not match: match = match_.always(self.root, self.getcwd()) + listignored, listclean, listunknown = ignored, clean, unknown modified, added, removed, deleted, unknown = [], [], [], [], [] ignored, clean = [], [] @@ -1016,27 +1003,22 @@ # are we comparing the working directory? if not node2: (lookup, modified, added, removed, deleted, unknown, - ignored, clean) = self.dirstate.status(match, list_ignored, - list_clean, list_unknown) + ignored, clean) = self.dirstate.status(match, listignored, + listclean, listunknown) # are we comparing working dir against its parent? if compareworking: if lookup: fixup = [] # do a full compare of any files that might have changed - ctx = self.changectx() - mexec = lambda f: 'x' in ctx.fileflags(f) - mlink = lambda f: 'l' in ctx.fileflags(f) - is_exec = util.execfunc(self.root, mexec) - is_link = util.linkfunc(self.root, mlink) - def flags(f): - return is_link(f) and 'l' or is_exec(f) and 'x' or '' + ctx = self['.'] + ff = self.dirstate.flagfunc(ctx.flags) for f in lookup: - if (f not in ctx or flags(f) != ctx.fileflags(f) + if (f not in ctx or ff(f) != ctx.flags(f) or ctx[f].cmp(self.wread(f))): modified.append(f) else: fixup.append(f) - if list_clean: + if listclean: clean.append(f) # update dirstate for files that are actually clean @@ -1057,11 +1039,10 @@ # generate a pseudo-manifest for the working dir # XXX: create it in dirstate.py ? mf2 = mfmatches(self.dirstate.parents()[0]) - is_exec = util.execfunc(self.root, mf2.execf) - is_link = util.linkfunc(self.root, mf2.linkf) + ff = self.dirstate.flagfunc(mf2.flags) for f in lookup + modified + added: mf2[f] = "" - mf2.set(f, is_exec(f), is_link(f)) + mf2.set(f, ff(f)) for f in removed: if f in mf2: del mf2[f] @@ -1076,16 +1057,14 @@ # make sure to sort the files so we talk to the disk in a # reasonable order - mf2keys = mf2.keys() - mf2keys.sort() getnode = lambda fn: mf1.get(fn, nullid) - for fn in mf2keys: + for fn in util.sort(mf2): if fn in mf1: if (mf1.flags(fn) != mf2.flags(fn) or (mf1[fn] != mf2[fn] and (mf2[fn] != "" or fcmp(fn, getnode)))): modified.append(fn) - elif list_clean: + elif listclean: clean.append(fn) del mf1[fn] else: @@ -1201,11 +1180,11 @@ heads = self.changelog.heads(start) # sort the output in rev descending order heads = [(-self.changelog.rev(h), h) for h in heads] - heads.sort() - return [n for (r, n) in heads] + return [n for (r, n) in util.sort(heads)] def branchheads(self, branch=None, start=None): - branch = branch is None and self.workingctx().branch() or branch + if branch is None: + branch = self[None].branch() branches = self.branchtags() if branch not in branches: return [] @@ -1243,7 +1222,7 @@ if rev in ancestors: ancestors.update(self.changelog.parentrevs(rev)) ancestors.remove(rev) - elif self.changectx(rev).branch() == branch: + elif self[rev].branch() == branch: heads.append(rev) ancestors.update(self.changelog.parentrevs(rev)) heads = [self.changelog.node(rev) for rev in heads] @@ -1658,7 +1637,7 @@ # Nor do we know which filenodes are missing. msng_filenode_set = {} - junk = mnfst.index[mnfst.count() - 1] # Get around a bug in lazyindex + junk = mnfst.index[len(mnfst) - 1] # Get around a bug in lazyindex junk = None # A changeset always belongs to itself, so the changenode lookup @@ -1853,12 +1832,10 @@ add_extra_nodes(fname, msng_filenode_set.setdefault(fname, {})) changedfiles[fname] = 1 - changedfiles = changedfiles.keys() - changedfiles.sort() # Go through all our files in order sorted by name. - for fname in changedfiles: + for fname in util.sort(changedfiles): filerevlog = self.file(fname) - if filerevlog.count() == 0: + if not len(filerevlog): raise util.Abort(_("empty or missing revlog for %s") % fname) # Toss out the filenodes that the recipient isn't really # missing. @@ -1909,10 +1886,10 @@ def identity(x): return x - def gennodelst(revlog): - for r in xrange(0, revlog.count()): - n = revlog.node(r) - if revlog.linkrev(n) in revset: + def gennodelst(log): + for r in log: + n = log.node(r) + if log.linkrev(n) in revset: yield n def changed_file_collector(changedfileset): @@ -1934,17 +1911,15 @@ for chnk in cl.group(nodes, identity, changed_file_collector(changedfiles)): yield chnk - changedfiles = changedfiles.keys() - changedfiles.sort() mnfst = self.manifest nodeiter = gennodelst(mnfst) for chnk in mnfst.group(nodeiter, lookuprevlink_func(mnfst)): yield chnk - for fname in changedfiles: + for fname in util.sort(changedfiles): filerevlog = self.file(fname) - if filerevlog.count() == 0: + if not len(filerevlog): raise util.Abort(_("empty or missing revlog for %s") % fname) nodeiter = gennodelst(filerevlog) nodeiter = list(nodeiter) @@ -1973,7 +1948,7 @@ """ def csmap(x): self.ui.debug(_("add changeset %s\n") % short(x)) - return cl.count() + return len(cl) def revmap(x): return cl.rev(x) @@ -1996,11 +1971,11 @@ trp = weakref.proxy(tr) # pull off the changeset group self.ui.status(_("adding changesets\n")) - cor = cl.count() - 1 + cor = len(cl) - 1 chunkiter = changegroup.chunkiter(source) if cl.addgroup(chunkiter, csmap, trp) is None and not emptyok: raise util.Abort(_("received changelog group is empty")) - cnr = cl.count() - 1 + cnr = len(cl) - 1 changesets = cnr - cor # pull off the manifest group @@ -2020,11 +1995,11 @@ break self.ui.debug(_("adding %s revisions\n") % f) fl = self.file(f) - o = fl.count() + o = len(fl) chunkiter = changegroup.chunkiter(source) if fl.addgroup(chunkiter, revmap, trp) is None: raise util.Abort(_("received file revlog group is empty")) - revisions += fl.count() - o + revisions += len(fl) - o files += 1 # make changelog see real files again diff -r 54ccf41761c9 -r 39319a457dda mercurial/manifest.py --- a/mercurial/manifest.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/manifest.py Sat Jun 28 09:28:01 2008 +0200 @@ -8,7 +8,7 @@ from node import bin, hex, nullid from revlog import revlog, RevlogError from i18n import _ -import array, struct, mdiff, parsers +import array, struct, mdiff, parsers, util class manifestdict(dict): def __init__(self, mapping=None, flags=None): @@ -18,16 +18,8 @@ self._flags = flags def flags(self, f): return self._flags.get(f, "") - def execf(self, f): - "test for executable in manifest flags" - return "x" in self.flags(f) - def linkf(self, f): - "test for symlink in manifest flags" - return "l" in self.flags(f) - def set(self, f, execf=False, linkf=False): - if linkf: self._flags[f] = "l" - elif execf: self._flags[f] = "x" - else: self._flags[f] = "" + def set(self, f, flags): + self._flags[f] = flags def copy(self): return manifestdict(dict.copy(self), dict.copy(self._flags)) @@ -134,9 +126,7 @@ # if we're using the listcache, make sure it is valid and # parented by the same node we're diffing against if not (changed and self.listcache and p1 and self.mapcache[0] == p1): - files = map.keys() - files.sort() - + files = util.sort(map) for f in files: checkforbidden(f) diff -r 54ccf41761c9 -r 39319a457dda mercurial/merge.py --- a/mercurial/merge.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/merge.py Sat Jun 28 09:28:01 2008 +0200 @@ -262,11 +262,10 @@ "apply the merge action list to the working directory" updated, merged, removed, unresolved = 0, 0, 0, 0 - action.sort() - ms = mergestate(repo) ms.reset(wctx.parents()[0].node()) moves = [] + action.sort() # prescan for merges for a in action: @@ -409,7 +408,7 @@ wlock = repo.wlock() try: - wc = repo.workingctx() + wc = repo[None] if node is None: # tip of current branch try: @@ -421,7 +420,7 @@ raise util.Abort(_("branch %s not found") % wc.branch()) overwrite = force and not branchmerge pl = wc.parents() - p1, p2 = pl[0], repo.changectx(node) + p1, p2 = pl[0], repo[node] pa = p1.ancestor(p2) fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2) fastforward = False @@ -460,7 +459,7 @@ action = [] if not force: _checkunknown(wc, p2) - if not util.checkfolding(repo.path): + if not util.checkcase(repo.path): _checkcollision(p2) action += _forgetremoved(wc, p2, branchmerge) action += manifestmerge(repo, wc, p2, pa, overwrite, partial) diff -r 54ccf41761c9 -r 39319a457dda mercurial/patch.py --- a/mercurial/patch.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/patch.py Sat Jun 28 09:28:01 2008 +0200 @@ -8,7 +8,7 @@ from i18n import _ from node import hex, nullid, short -import base85, cmdutil, mdiff, util, context, revlog, diffhelpers, copies +import base85, cmdutil, mdiff, util, revlog, diffhelpers, copies import cStringIO, email.Parser, os, popen2, re, errno import sys, tempfile, zlib @@ -1039,9 +1039,12 @@ continue elif state == 'git': gitpatches = values + cwd = os.getcwd() for gp in gitpatches: if gp.op in ('COPY', 'RENAME'): - copyfile(gp.oldpath, gp.path) + src, dst = [util.canonpath(cwd, cwd, x) + for x in [gp.oldpath, gp.path]] + copyfile(src, dst) changed[gp.path] = (gp.op, gp) else: raise util.Abort(_('unsupported parser state: %s') % state) @@ -1091,8 +1094,7 @@ repo.copy(src, dst) removes = removes.keys() if removes: - removes.sort() - repo.remove(removes, True) + repo.remove(util.sort(removes), True) for f in patches: ctype, gp = patches[f] if gp and gp.mode: @@ -1110,9 +1112,7 @@ cmdutil.addremove(repo, cfiles) files = patches.keys() files.extend([r for r in removes if r not in files]) - files.sort() - - return files + return util.sort(files) def b85diff(to, tn): '''print base85-encoded binary diff''' @@ -1180,30 +1180,19 @@ # reading the data for node1 early allows it to play nicely # with repo.status and the revlog cache. - ctx1 = context.changectx(repo, node1) + ctx1 = repo[node1] # force manifest reading man1 = ctx1.manifest() date1 = util.datestr(ctx1.date()) if not changes: - changes = repo.status(node1, node2, match=match)[:5] - modified, added, removed, deleted, unknown = changes + changes = repo.status(node1, node2, match=match) + modified, added, removed = changes[:3] if not modified and not added and not removed: return - if node2: - ctx2 = context.changectx(repo, node2) - execf2 = ctx2.manifest().execf - linkf2 = ctx2.manifest().linkf - else: - ctx2 = context.workingctx(repo) - execf2 = util.execfunc(repo.root, None) - linkf2 = util.linkfunc(repo.root, None) - if execf2 is None: - mc = ctx2.parents()[0].manifest().copy() - execf2 = mc.execf - linkf2 = mc.linkf + ctx2 = repo[node2] if repo.ui.quiet: r = None @@ -1212,15 +1201,14 @@ r = [hexfunc(node) for node in [node1, node2] if node] if opts.git: - copy, diverge = copies.copies(repo, ctx1, ctx2, repo.changectx(nullid)) + copy, diverge = copies.copies(repo, ctx1, ctx2, repo[nullid]) for k, v in copy.items(): copy[v] = k - all = modified + added + removed - all.sort() gone = {} + gitmode = {'l': '120000', 'x': '100755', '': '100644'} - for f in all: + for f in util.sort(modified + added + removed): to = None tn = None dodiff = True @@ -1231,18 +1219,16 @@ tn = getfilectx(f, ctx2).data() a, b = f, f if opts.git: - def gitmode(x, l): - return l and '120000' or (x and '100755' or '100644') def addmodehdr(header, omode, nmode): if omode != nmode: header.append('old mode %s\n' % omode) header.append('new mode %s\n' % nmode) if f in added: - mode = gitmode(execf2(f), linkf2(f)) + mode = gitmode[ctx2.flags(f)] if f in copy: a = copy[f] - omode = gitmode(man1.execf(a), man1.linkf(a)) + omode = gitmode[man1.flags(a)] addmodehdr(header, omode, mode) if a in removed and a not in gone: op = 'rename' @@ -1261,11 +1247,11 @@ if f in copy and copy[f] in added and copy[copy[f]] == f: dodiff = False else: - mode = gitmode(man1.execf(f), man1.linkf(f)) - header.append('deleted file mode %s\n' % mode) + header.append('deleted file mode %s\n' % + gitmode[man1.flags(f)]) else: - omode = gitmode(man1.execf(f), man1.linkf(f)) - nmode = gitmode(execf2(f), linkf2(f)) + omode = gitmode[man1.flags(f)] + nmode = gitmode[ctx2.flags(f)] addmodehdr(header, omode, nmode) if util.binary(to) or util.binary(tn): dodiff = 'binary' @@ -1291,7 +1277,7 @@ revwidth = max([len(str(rev)) for rev in revs]) def single(rev, seqno, fp): - ctx = repo.changectx(rev) + ctx = repo[rev] node = ctx.node() parents = [p.node() for p in ctx.parents() if p] branch = ctx.branch() diff -r 54ccf41761c9 -r 39319a457dda mercurial/repair.py --- a/mercurial/repair.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/repair.py Sat Jun 28 09:28:01 2008 +0200 @@ -23,8 +23,8 @@ """find out the filelogs affected by the strip""" files = {} - for x in xrange(striprev, repo.changelog.count()): - for name in repo.changectx(x).files(): + for x in xrange(striprev, len(repo)): + for name in repo[x].files(): if name in files: continue files[name] = 1 @@ -37,7 +37,7 @@ """return the nodes that have to be saved before the strip""" def collectone(revlog): extra = [] - startrev = count = revlog.count() + startrev = count = len(revlog) # find the truncation point of the revlog for i in xrange(0, count): node = revlog.node(i) @@ -84,7 +84,7 @@ tostrip = {striprev: 1} saveheads = {} savebases = [] - for r in xrange(striprev + 1, cl.count()): + for r in xrange(striprev + 1, len(cl)): parents = cl.parentrevs(r) if parents[0] in tostrip or parents[1] in tostrip: # r is a descendant of striprev diff -r 54ccf41761c9 -r 39319a457dda mercurial/revlog.py --- a/mercurial/revlog.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/revlog.py Sat Jun 28 09:28:01 2008 +0200 @@ -515,9 +515,11 @@ def tip(self): return self.node(len(self.index) - 2) - def count(self): + def __len__(self): return len(self.index) - 1 - + def __iter__(self): + for i in xrange(len(self)): + yield i def rev(self, node): try: return self.nodemap[node] @@ -620,12 +622,11 @@ lowestrev = nullrev if (lowestrev == nullrev) and (heads is None): # We want _all_ the nodes! - return ([self.node(r) for r in xrange(0, self.count())], - [nullid], list(self.heads())) + return ([self.node(r) for r in self], [nullid], list(self.heads())) if heads is None: # All nodes are ancestors, so the latest ancestor is the last # node. - highestrev = self.count() - 1 + highestrev = len(self) - 1 # Set ancestors to None to signal that every node is an ancestor. ancestors = None # Set heads to an empty dictionary for later discovery of heads @@ -754,15 +755,15 @@ as if they had no children """ if start is None and stop is None: - count = self.count() + count = len(self) if not count: return [nullid] ishead = [1] * (count + 1) index = self.index - for r in xrange(count): + for r in self: e = index[r] ishead[e[5]] = ishead[e[6]] = 0 - return [self.node(r) for r in xrange(count) if ishead[r]] + return [self.node(r) for r in self if ishead[r]] if start is None: start = nullid @@ -774,7 +775,7 @@ heads = {startrev: 1} parentrevs = self.parentrevs - for r in xrange(startrev + 1, self.count()): + for r in xrange(startrev + 1, len(self)): for p in parentrevs(r): if p in reachable: if r not in stoprevs: @@ -789,7 +790,7 @@ """find the children of a given node""" c = [] p = self.rev(node) - for r in range(p + 1, self.count()): + for r in range(p + 1, len(self)): prevs = [pr for pr in self.parentrevs(r) if pr != nullrev] if prevs: for pr in prevs: @@ -818,8 +819,8 @@ if str(rev) != id: raise ValueError if rev < 0: - rev = self.count() + rev - if rev < 0 or rev >= self.count(): + rev = len(self) + rev + if rev < 0 or rev >= len(self): raise ValueError return self.node(rev) except (ValueError, OverflowError): @@ -982,7 +983,7 @@ df = self.opener(self.datafile, 'w') try: calc = self._io.size - for r in xrange(self.count()): + for r in self: start = self.start(r) + (r + 1) * calc length = self.length(r) fp.seek(start) @@ -995,7 +996,7 @@ fp = self.opener(self.indexfile, 'w', atomictemp=True) self.version &= ~(REVLOGNGINLINEDATA) self._inline = False - for i in xrange(self.count()): + for i in self: e = self._io.packentry(self.index[i], self.node, self.version, i) fp.write(e) @@ -1031,7 +1032,7 @@ if node in self.nodemap: return node - curr = self.count() + curr = len(self) prev = curr - 1 base = self.base(prev) offset = self.end(prev) @@ -1146,7 +1147,7 @@ """ #track the base of the current delta log - r = self.count() + r = len(self) t = r - 1 node = None @@ -1265,13 +1266,13 @@ trust that the caller has saved the revisions that shouldn't be removed and that it'll readd them after this truncation. """ - if self.count() == 0: + if len(self) == 0: return if isinstance(self.index, lazyindex): self._loadindexmap() - for rev in xrange(0, self.count()): + for rev in self: if self.index[rev][4] >= minlink: break else: @@ -1292,15 +1293,15 @@ # then reset internal state in memory to forget those revisions self._cache = None self._chunkcache = None - for x in xrange(rev, self.count()): + for x in xrange(rev, len(self)): del self.nodemap[self.node(x)] del self.index[rev:-1] def checksize(self): expected = 0 - if self.count(): - expected = max(0, self.end(self.count() - 1)) + if len(self): + expected = max(0, self.end(len(self) - 1)) try: f = self.opener(self.datafile) @@ -1321,10 +1322,10 @@ di = actual - (i * s) if self._inline: databytes = 0 - for r in xrange(self.count()): + for r in self: databytes += max(0, self.length(r)) dd = 0 - di = actual - self.count() * s - databytes + di = actual - len(self) * s - databytes except IOError, inst: if inst.errno != errno.ENOENT: raise diff -r 54ccf41761c9 -r 39319a457dda mercurial/streamclone.py --- a/mercurial/streamclone.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/streamclone.py Sat Jun 28 09:28:01 2008 +0200 @@ -34,8 +34,7 @@ for x in walk(os.path.join(root, 'data'), True): yield x # write manifest before changelog - meta = list(walk(root, False)) - meta.sort() + meta = util.sort(walk(root, False)) meta.reverse() for x in meta: yield x diff -r 54ccf41761c9 -r 39319a457dda mercurial/ui.py --- a/mercurial/ui.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/ui.py Sat Jun 28 09:28:01 2008 +0200 @@ -312,15 +312,11 @@ items = self._configitems(section, untrusted=untrusted, abort=True) if self.debugflag and not untrusted and self.ucdata: uitems = self._configitems(section, untrusted=True, abort=False) - keys = uitems.keys() - keys.sort() - for k in keys: + for k in util.sort(uitems): if uitems[k] != items.get(k): self.warn(_("Ignoring untrusted configuration option " "%s.%s = %s\n") % (section, k, uitems[k])) - x = items.items() - x.sort() - return x + return util.sort(items.items()) def walkconfig(self, untrusted=False): cdata = self._get_cdata(untrusted) diff -r 54ccf41761c9 -r 39319a457dda mercurial/util.py --- a/mercurial/util.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/util.py Sat Jun 28 09:28:01 2008 +0200 @@ -252,6 +252,12 @@ """return the uniq elements of iterable g""" return dict.fromkeys(g).keys() +def sort(l): + if not isinstance(l, list): + l = list(l) + l.sort() + return l + class Abort(Exception): """Raised if a command needs to print an error and exit.""" @@ -839,7 +845,7 @@ # File system features -def checkfolding(path): +def checkcase(path): """ Check whether the given path is on a case-sensitive filesystem @@ -933,12 +939,6 @@ return False return not (new_file_has_exec or exec_flags_cannot_flip) -def execfunc(path, fallback): - '''return an is_exec() function with default to fallback''' - if checkexec(path): - return lambda x: is_exec(os.path.join(path, x)) - return fallback - def checklink(path): """check whether the given path is on a symlink-capable filesystem""" # mktemp is not racy because symlink creation will fail if the @@ -951,12 +951,6 @@ except (OSError, AttributeError): return False -def linkfunc(path, fallback): - '''return an is_link() function with default to fallback''' - if checklink(path): - return lambda x: os.path.islink(os.path.join(path, x)) - return fallback - _umask = os.umask(0) os.umask(_umask) diff -r 54ccf41761c9 -r 39319a457dda mercurial/verify.py --- a/mercurial/verify.py Thu Jun 26 13:37:47 2008 -0700 +++ b/mercurial/verify.py Sat Jun 28 09:28:01 2008 +0200 @@ -7,7 +7,7 @@ from node import nullid, short from i18n import _ -import revlog +import revlog, util def verify(repo): lock = repo.lock() @@ -17,265 +17,201 @@ del lock def _verify(repo): + mflinkrevs = {} filelinkrevs = {} filenodes = {} - changesets = revisions = files = 0 - firstbad = [None] + revisions = 0 + badrevs = {} errors = [0] warnings = [0] - neededmanifests = {} + ui = repo.ui + cl = repo.changelog + mf = repo.manifest def err(linkrev, msg, filename=None): if linkrev != None: - if firstbad[0] != None: - firstbad[0] = min(firstbad[0], linkrev) - else: - firstbad[0] = linkrev + badrevs[linkrev] = True else: - linkrev = "?" + linkrev = '?' msg = "%s: %s" % (linkrev, msg) if filename: msg = "%s@%s" % (filename, msg) - repo.ui.warn(" " + msg + "\n") + ui.warn(" " + msg + "\n") errors[0] += 1 + def exc(linkrev, msg, inst, filename=None): + if isinstance(inst, KeyboardInterrupt): + ui.warn(_("interrupted")) + raise + err(linkrev, "%s: %s" % (msg, inst), filename) + def warn(msg): - repo.ui.warn(msg + "\n") + ui.warn(msg + "\n") warnings[0] += 1 - def checksize(obj, name): + def checklog(obj, name): + if not len(obj) and (havecl or havemf): + err(0, _("empty or missing %s") % name) + return + d = obj.checksize() if d[0]: err(None, _("data length off by %d bytes") % d[0], name) if d[1]: err(None, _("index contains %d extra bytes") % d[1], name) - def checkversion(obj, name): if obj.version != revlog.REVLOGV0: if not revlogv1: warn(_("warning: `%s' uses revlog format 1") % name) elif revlogv1: warn(_("warning: `%s' uses revlog format 0") % name) - revlogv1 = repo.changelog.version != revlog.REVLOGV0 - if repo.ui.verbose or not revlogv1: - repo.ui.status(_("repository uses revlog format %d\n") % + def checkentry(obj, i, node, seen, linkrevs, f): + lr = obj.linkrev(node) + if lr < 0 or (havecl and lr not in linkrevs): + t = "unexpected" + if lr < 0 or lr >= len(cl): + t = "nonexistent" + err(None, _("rev %d point to %s changeset %d") % (i, t, lr), f) + if linkrevs: + warn(_(" (expected %s)") % " ".join(map(str,linkrevs))) + lr = None # can't be trusted + + try: + p1, p2 = obj.parents(node) + if p1 not in seen and p1 != nullid: + err(lr, _("unknown parent 1 %s of %s") % + (short(p1), short(n)), f) + if p2 not in seen and p2 != nullid: + err(lr, _("unknown parent 2 %s of %s") % + (short(p2), short(p1)), f) + except Exception, inst: + exc(lr, _("checking parents of %s") % short(node), inst, f) + + if node in seen: + err(lr, _("duplicate revision %d (%d)") % (i, seen[n]), f) + seen[n] = i + return lr + + revlogv1 = cl.version != revlog.REVLOGV0 + if ui.verbose or not revlogv1: + ui.status(_("repository uses revlog format %d\n") % (revlogv1 and 1 or 0)) - havecl = havemf = 1 - seen = {} - repo.ui.status(_("checking changesets\n")) - if repo.changelog.count() == 0 and repo.manifest.count() > 1: - havecl = 0 - err(0, _("empty or missing 00changelog.i")) - else: - checksize(repo.changelog, "changelog") - - for i in xrange(repo.changelog.count()): - changesets += 1 - n = repo.changelog.node(i) - l = repo.changelog.linkrev(n) - if l != i: - err(i, _("incorrect link (%d) for changeset") %(l)) - if n in seen: - err(i, _("duplicates changeset at revision %d") % seen[n]) - seen[n] = i - - for p in repo.changelog.parents(n): - if p not in repo.changelog.nodemap: - err(i, _("changeset has unknown parent %s") % short(p)) - try: - changes = repo.changelog.read(n) - except KeyboardInterrupt: - repo.ui.warn(_("interrupted")) - raise - except Exception, inst: - err(i, _("unpacking changeset: %s") % inst) - continue + havecl = len(cl) > 0 + havemf = len(mf) > 0 - if changes[0] not in neededmanifests: - neededmanifests[changes[0]] = i - - for f in changes[3]: - filelinkrevs.setdefault(f, []).append(i) - + ui.status(_("checking changesets\n")) seen = {} - repo.ui.status(_("checking manifests\n")) - if repo.changelog.count() > 0 and repo.manifest.count() == 0: - havemf = 0 - err(0, _("empty or missing 00manifest.i")) - else: - checkversion(repo.manifest, "manifest") - checksize(repo.manifest, "manifest") - - for i in xrange(repo.manifest.count()): - n = repo.manifest.node(i) - l = repo.manifest.linkrev(n) - - if l < 0 or (havecl and l >= repo.changelog.count()): - err(None, _("bad link (%d) at manifest revision %d") % (l, i)) - - if n in neededmanifests: - del neededmanifests[n] - - if n in seen: - err(l, _("duplicates manifest from %d") % seen[n]) - - seen[n] = l - - for p in repo.manifest.parents(n): - if p not in repo.manifest.nodemap: - err(l, _("manifest has unknown parent %s") % short(p)) + checklog(cl, "changelog") + for i in repo: + n = cl.node(i) + checkentry(cl, i, n, seen, [i], "changelog") try: - for f, fn in repo.manifest.readdelta(n).iteritems(): - fns = filenodes.setdefault(f, {}) - if fn not in fns: - fns[fn] = n - except KeyboardInterrupt: - repo.ui.warn(_("interrupted")) - raise + changes = cl.read(n) + mflinkrevs.setdefault(changes[0], []).append(i) + for f in changes[3]: + filelinkrevs.setdefault(f, []).append(i) except Exception, inst: - err(l, _("reading manifest delta: %s") % inst) - continue - - repo.ui.status(_("crosschecking files in changesets and manifests\n")) + exc(i, _("unpacking changeset %s") % short(n), inst) - if havemf > 0: - nm = [(c, m) for m, c in neededmanifests.items()] - nm.sort() - for c, m in nm: - err(c, _("changeset refers to unknown manifest %s") % short(m)) - del neededmanifests, nm + ui.status(_("checking manifests\n")) + seen = {} + checklog(mf, "manifest") + for i in mf: + n = mf.node(i) + lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest") + if n in mflinkrevs: + del mflinkrevs[n] - if havecl: - fl = filenodes.keys() - fl.sort() - for f in fl: - if f not in filelinkrevs: - lrs = [repo.manifest.linkrev(n) for n in filenodes[f]] - lrs.sort() - err(lrs[0], _("in manifest but not in changeset"), f) - del fl + try: + for f, fn in mf.readdelta(n).iteritems(): + if not f: + err(lr, _("file without name in manifest")) + elif f != "/dev/null": + fns = filenodes.setdefault(f, {}) + if fn not in fns: + fns[fn] = n + except Exception, inst: + exc(lr, _("reading manifest delta %s") % short(n), inst) + + ui.status(_("crosschecking files in changesets and manifests\n")) if havemf: - fl = filelinkrevs.keys() - fl.sort() - for f in fl: + for c, m in util.sort([(c, m) for m in mflinkrevs for c in mflinkrevs[m]]): + err(c, _("changeset refers to unknown manifest %s") % short(m)) + del mflinkrevs + + for f in util.sort(filelinkrevs): if f not in filenodes: lr = filelinkrevs[f][0] err(lr, _("in changeset but not in manifest"), f) - del fl - repo.ui.status(_("checking files\n")) - ff = dict.fromkeys(filenodes.keys() + filelinkrevs.keys()).keys() - ff.sort() - for f in ff: - if f == "/dev/null": - continue - files += 1 - if not f: - lr = filelinkrevs[f][0] - err(lr, _("file without name in manifest")) - continue + if havecl: + for f in util.sort(filenodes): + if f not in filelinkrevs: + try: + lr = min([repo.file(f).linkrev(n) for n in filenodes[f]]) + except: + lr = None + err(lr, _("in manifest but not in changeset"), f) + + ui.status(_("checking files\n")) + files = util.sort(util.unique(filenodes.keys() + filelinkrevs.keys())) + for f in files: fl = repo.file(f) - checkversion(fl, f) - checksize(fl, f) - - if fl.count() == 0: - err(filelinkrevs[f][0], _("empty or missing revlog"), f) - continue - + checklog(fl, f) seen = {} - nodes = {nullid: 1} - for i in xrange(fl.count()): + for i in fl: revisions += 1 n = fl.node(i) - flr = fl.linkrev(n) - - if flr < 0 or (havecl and flr not in filelinkrevs.get(f, [])): - if flr < 0 or flr >= repo.changelog.count(): - err(None, _("rev %d point to nonexistent changeset %d") - % (i, flr), f) - else: - err(None, _("rev %d points to unexpected changeset %d") - % (i, flr), f) - if f in filelinkrevs: - warn(_(" (expected %s)") % filelinkrevs[f][0]) - flr = None # can't be trusted - else: - if havecl: - filelinkrevs[f].remove(flr) - - if n in seen: - err(flr, _("duplicate revision %d") % i, f) + lr = checkentry(fl, i, n, seen, filelinkrevs.get(f, []), f) if f in filenodes: if havemf and n not in filenodes[f]: - err(flr, _("%s not in manifests") % (short(n)), f) + err(lr, _("%s not in manifests") % (short(n)), f) else: del filenodes[f][n] # verify contents try: t = fl.read(n) - except KeyboardInterrupt: - repo.ui.warn(_("interrupted")) - raise + rp = fl.renamed(n) + if len(t) != fl.size(i): + if not fl._readmeta(n): # ancient copy? + err(lr, _("unpacked size is %s, %s expected") % + (len(t), fl.size(i)), f) except Exception, inst: - err(flr, _("unpacking %s: %s") % (short(n), inst), f) - - # verify parents - try: - (p1, p2) = fl.parents(n) - if p1 not in nodes: - err(flr, _("unknown parent 1 %s of %s") % - (short(p1), short(n)), f) - if p2 not in nodes: - err(flr, _("unknown parent 2 %s of %s") % - (short(p2), short(p1)), f) - except KeyboardInterrupt: - repo.ui.warn(_("interrupted")) - raise - except Exception, inst: - err(flr, _("checking parents of %s: %s") % (short(n), inst), f) - nodes[n] = 1 + exc(lr, _("unpacking %s") % short(n), inst, f) # check renames try: - rp = fl.renamed(n) if rp: fl2 = repo.file(rp[0]) - if fl2.count() == 0: - err(flr, _("empty or missing copy source revlog %s:%s") + if not len(fl2): + err(lr, _("empty or missing copy source revlog %s:%s") % (rp[0], short(rp[1])), f) elif rp[1] == nullid: - err(flr, _("copy source revision is nullid %s:%s") + err(lr, _("copy source revision is nullid %s:%s") % (rp[0], short(rp[1])), f) else: rev = fl2.rev(rp[1]) - except KeyboardInterrupt: - repo.ui.warn(_("interrupted")) - raise except Exception, inst: - err(flr, _("checking rename of %s: %s") % - (short(n), inst), f) + exc(lr, _("checking rename of %s") % short(n), inst, f) # cross-check if f in filenodes: - fns = [(repo.manifest.linkrev(filenodes[f][n]), n) - for n in filenodes[f]] - fns.sort() - for lr, node in fns: + fns = [(mf.linkrev(l), n) for n,l in filenodes[f].items()] + for lr, node in util.sort(fns): err(lr, _("%s in manifests not found") % short(node), f) - repo.ui.status(_("%d files, %d changesets, %d total revisions\n") % - (files, changesets, revisions)) - + ui.status(_("%d files, %d changesets, %d total revisions\n") % + (len(files), len(cl), revisions)) if warnings[0]: - repo.ui.warn(_("%d warnings encountered!\n") % warnings[0]) + ui.warn(_("%d warnings encountered!\n") % warnings[0]) if errors[0]: - repo.ui.warn(_("%d integrity errors encountered!\n") % errors[0]) - if firstbad[0]: - repo.ui.warn(_("(first damaged changeset appears to be %d)\n") - % firstbad[0]) + ui.warn(_("%d integrity errors encountered!\n") % errors[0]) + if badrevs: + ui.warn(_("(first damaged changeset appears to be %d)\n") + % min(badrevs)) return 1 diff -r 54ccf41761c9 -r 39319a457dda tests/test-children.out --- a/tests/test-children.out Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-children.out Sat Jun 28 09:28:01 2008 +0200 @@ -5,6 +5,18 @@ % hg children at revision 3 (tip) 0 files updated, 0 files merged, 1 files removed, 0 files unresolved % hg children at nullrev (should be 0 and 3) +changeset: 0:4df8521a7374 +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: 0 + +changeset: 3:e2962852269d +tag: tip +parent: -1:000000000000 +user: test +date: Thu Jan 01 00:00:03 1970 +0000 +summary: 3 + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved % hg children at revision 1 (should be 2) changeset: 2:8f5eea5023c2 diff -r 54ccf41761c9 -r 39319a457dda tests/test-context.py --- a/tests/test-context.py Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-context.py Sat Jun 28 09:28:01 2008 +0200 @@ -16,4 +16,4 @@ repo.add(['foo']) repo.commit(text='commit1', date="0 0") -print "workingfilectx.date =", repo.workingctx().filectx('foo').date() +print "workingfilectx.date =", repo[None]['foo'].date() diff -r 54ccf41761c9 -r 39319a457dda tests/test-convert-filemap --- a/tests/test-convert-filemap Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-convert-filemap Sat Jun 28 09:28:01 2008 +0200 @@ -80,6 +80,7 @@ echo "include $i" >> "$fmap" done hg -q convert $opts --filemap "$fmap" --datesort source "$repo" + hg up -q -R "$repo" glog -R "$repo" hg -R "$repo" manifest --debug } @@ -115,6 +116,7 @@ rename copied copied2 EOF hg -q convert --filemap renames.fmap --datesort source renames.repo +hg up -q -R renames.repo glog -R renames.repo hg -R renames.repo manifest --debug hg --cwd renames.repo debugrename copied2 diff -r 54ccf41761c9 -r 39319a457dda tests/test-convert-filemap.out --- a/tests/test-convert-filemap.out Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-convert-filemap.out Sat Jun 28 09:28:01 2008 +0200 @@ -29,7 +29,7 @@ copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd -o 3 "8: change foo" files: foo +@ 3 "8: change foo" files: foo | o 2 "6: change foo baz" files: foo | @@ -39,7 +39,7 @@ 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo % bar: merges are not merges anymore -o 4 "7: second merge; change bar" files: bar +@ 4 "7: second merge; change bar" files: bar | o 3 "5: change bar baz quux" files: bar | @@ -51,7 +51,7 @@ 9463f52fe115e377cf2878d4fc548117211063f2 644 bar % baz: 1st merge is not a merge anymore; 2nd still is -o 4 "7: second merge; change bar" files: baz +@ 4 "7: second merge; change bar" files: baz |\ | o 3 "6: change foo baz" files: baz | | @@ -63,7 +63,7 @@ 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz % foo quux: we add additional merges when they are interesting -o 8 "8: change foo" files: foo +@ 8 "8: change foo" files: foo | o 7 "7: second merge; change bar" files: |\ @@ -84,14 +84,14 @@ 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux % bar quux: partial conversion -o 1 "3: change bar quux" files: bar quux +@ 1 "3: change bar quux" files: bar quux | o 0 "1: add bar quux; copy foo to copied" files: bar quux b79105bedc55102f394e90a789c9c380117c1b4a 644 bar db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux % bar quux: complete the partial conversion -o 4 "7: second merge; change bar" files: bar +@ 4 "7: second merge; change bar" files: bar | o 3 "5: change bar baz quux" files: bar quux | @@ -104,11 +104,11 @@ 9463f52fe115e377cf2878d4fc548117211063f2 644 bar bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux % foo: partial conversion -o 0 "0: add foo baz dir/" files: foo +@ 0 "0: add foo baz dir/" files: foo 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo % foo: complete the partial conversion -o 3 "8: change foo" files: foo +@ 3 "8: change foo" files: foo | o 2 "6: change foo baz" files: foo | @@ -118,12 +118,12 @@ 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo % copied: copied file; source not included in new repo -o 0 "1: add bar quux; copy foo to copied" files: copied +@ 0 "1: add bar quux; copy foo to copied" files: copied 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied copied not renamed % foo copied: copied file; source included in new repo -o 4 "8: change foo" files: foo +@ 4 "8: change foo" files: foo | o 3 "6: change foo baz" files: foo | @@ -136,7 +136,7 @@ 6ca237634e1f6bee1b6db94292fb44f092a25842 644 copied 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd -o 4 "8: change foo" files: foo2 +@ 4 "8: change foo" files: foo2 | o 3 "6: change foo baz" files: foo2 | diff -r 54ccf41761c9 -r 39319a457dda tests/test-convert-git --- a/tests/test-convert-git Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-convert-git Sat Jun 28 09:28:01 2008 +0200 @@ -53,7 +53,7 @@ cd .. hg convert --datesort git-repo - +hg up -q -R git-repo-hg hg -R git-repo-hg tip -v count=10 @@ -117,12 +117,14 @@ echo "include $i" >> "$fmap" done hg -q convert $opts --filemap "$fmap" --datesort git-repo2 "$repo" + hg up -q -R "$repo" glog -R "$repo" hg -R "$repo" manifest --debug } echo '% full conversion' hg -q convert --datesort git-repo2 fullrepo +hg up -q -R fullrepo glog -R fullrepo hg -R fullrepo manifest --debug diff -r 54ccf41761c9 -r 39319a457dda tests/test-convert-git.out --- a/tests/test-convert-git.out Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-convert-git.out Sat Jun 28 09:28:01 2008 +0200 @@ -24,7 +24,7 @@ % full conversion -o 9 "Discard change to foo" files: foo +@ 9 "Discard change to foo" files: foo |\ | o 8 "change foo" files: foo | | @@ -49,7 +49,7 @@ 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux % foo bar baz: octopus merge -o 8 "Discard change to foo" files: foo +@ 8 "Discard change to foo" files: foo |\ | o 7 "change foo" files: foo | | @@ -71,7 +71,7 @@ 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo % foo baz quux: only some parents of an octopus merge; "discard" a head -o 6 "Discard change to foo" files: foo +@ 6 "Discard change to foo" files: foo | o 5 "change foo" files: foo | diff -r 54ccf41761c9 -r 39319a457dda tests/test-import --- a/tests/test-import Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-import Sat Jun 28 09:28:01 2008 +0200 @@ -261,3 +261,15 @@ hg status cat a cd .. + +echo % 'test paths outside repo root' +mkdir outside +touch outside/foo +hg init inside +cd inside +hg import - < /dev/null -if [ $? -ne 0 ]; then - echo "refused to run" -fi -if [ -f untracked_file ]; then - echo "untracked_file still around" -fi -hg purge -p --force +hg st + +hg purge -p hg purge -v 2> /dev/null -if [ $? -ne 0 ]; then - echo "refused to run" -fi -if [ -f untracked_file ]; then - echo "untracked_file still around" -fi -hg purge -v --force +hg st + +hg purge -v hg revert --all --quiet -ls +hg st -a echo '% tracked file in ignored directory (issue621)' echo directory >> .hgignore diff -r 54ccf41761c9 -r 39319a457dda tests/test-purge.out --- a/tests/test-purge.out Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-purge.out Sat Jun 28 09:28:01 2008 +0200 @@ -51,14 +51,12 @@ directory r1 % abort with missing files until we support name mangling filesystems -refused to run -untracked_file still around untracked_file -refused to run -untracked_file still around +! r1 +? untracked_file +untracked_file Removing file untracked_file -directory -r1 +! r1 % tracked file in ignored directory (issue621) untracked_file Removing file untracked_file diff -r 54ccf41761c9 -r 39319a457dda tests/test-remove.out --- a/tests/test-remove.out Thu Jun 26 13:37:47 2008 -0700 +++ b/tests/test-remove.out Sat Jun 28 09:28:01 2008 +0200 @@ -70,15 +70,15 @@ adding test/bar adding test/foo % dir, options none +removing test/bar removing test/foo -removing test/bar R test/bar R test/foo ./foo 2 files updated, 0 files merged, 0 files removed, 0 files unresolved % dir, options -f +removing test/bar removing test/foo -removing test/bar R test/bar R test/foo ./foo @@ -91,8 +91,8 @@ ./test/foo 1 files updated, 0 files merged, 0 files removed, 0 files unresolved % dir, options -Af +removing test/bar removing test/foo -removing test/bar R test/bar R test/foo ./foo