# HG changeset patch # User mpm@selenic.com # Date 1120202896 28800 # Node ID 4fc63e22b1fe707bb542ab1149403daa9a77cdf8 # Parent 53872e2be33a09350ee57384574f9fcab78f1b41# Parent c8ae964109c1eb09a17a9f6e478f48571101dac0 Merge with TAH -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Merge with TAH manifest hash: 1742d7ba2093dc643b57e45167cb2d794212cbb9 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCxPCQywK+sNU5EO8RAkr0AJ9qut/31lCLQ/xY3FWaF3c21RhS7wCfW1eV 3WexPDsJldMAr3V5vc9eowA= =pJYu -----END PGP SIGNATURE----- diff -r c8ae964109c1 -r 4fc63e22b1fe TODO --- a/TODO Fri Jul 01 07:40:32 2005 +0100 +++ b/TODO Thu Jun 30 23:28:16 2005 -0800 @@ -20,7 +20,6 @@ - make showing removed files (in history etc.) faster. Commands: -- hg diff Makefile should avoid walking the tree - hg add should work - hg status : file rev, changeset rev, changed, added, deleted, sha-1 @@ -43,4 +42,3 @@ - some web servers think hgweb.cgi.[di] is a CGI script with old-http:// (use quoting (see foo.d in Core) or document server configurations?) - link children in hgweb -- search field searching in descriptions, file names, what else? diff -r c8ae964109c1 -r 4fc63e22b1fe hgeditor diff -r c8ae964109c1 -r 4fc63e22b1fe hgmerge diff -r c8ae964109c1 -r 4fc63e22b1fe mercurial/commands.py --- a/mercurial/commands.py Fri Jul 01 07:40:32 2005 +0100 +++ b/mercurial/commands.py Thu Jun 30 23:28:16 2005 -0800 @@ -32,19 +32,24 @@ return [ util.pconvert(os.path.normpath(os.path.join(p, x))) for x in args ] return args -def dodiff(ui, repo, path, files = None, node1 = None, node2 = None): +def dodiff(ui, repo, files = None, node1 = None, node2 = None): def date(c): return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) + (c, a, d, u) = repo.changes(None, node1, files) + if files: + c, a, d = map(lambda x: filterfiles(files, x), (c, a, d)) + + if not c and not a and not d: + return + if node2: change = repo.changelog.read(node2) mmap2 = repo.manifest.read(change[0]) - (c, a, d) = repo.diffrevs(node1, node2) def read(f): return repo.file(f).read(mmap2[f]) date2 = date(change) else: date2 = time.asctime() - (c, a, d, u) = repo.diffdir(path, node1) if not node1: node1 = repo.dirstate.parents()[0] def read(f): return repo.wfile(f).read() @@ -59,9 +64,6 @@ mmap = repo.manifest.read(change[0]) date1 = date(change) - if files: - c, a, d = map(lambda x: filterfiles(files, x), (c, a, d)) - for f in c: to = None if f in mmap: @@ -124,7 +126,7 @@ ui.status("date: %s\n" % time.asctime( time.localtime(float(changes[2].split(' ')[0])))) if ui.debugflag: - files = repo.diffrevs(changelog.parents(changenode)[0], changenode) + files = repo.changes(changelog.parents(changenode)[0], changenode) for key, value in zip(["files:", "files+:", "files-:"], files): if value: ui.note("%-12s %s\n" % (key, " ".join(value))) @@ -214,7 +216,7 @@ elif s not in 'nmai' and isfile: u.append(f) else: - (c, a, d, u) = repo.diffdir(repo.root) + (c, a, d, u) = repo.changes(None, None) repo.add(u) repo.remove(d) @@ -413,7 +415,7 @@ else: files = relpath(repo, [""]) - dodiff(ui, repo, os.getcwd(), files, *revs) + dodiff(ui, repo, files, *revs) def export(ui, repo, changeset): """dump the changeset header and diffs for a revision""" @@ -430,7 +432,7 @@ print change[4].rstrip() print - dodiff(ui, repo, "", None, prev, node) + dodiff(ui, repo, None, prev, node) def forget(ui, repo, file, *files): """don't add the specified files on the next commit""" @@ -449,7 +451,7 @@ return hexfunc = ui.verbose and hg.hex or hg.short - (c, a, d, u) = repo.diffdir(repo.root) + (c, a, d, u) = repo.changes(None, None) output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]), (c or a or d) and "+" or "")] @@ -647,7 +649,7 @@ R = removed ? = not tracked''' - (c, a, d, u) = repo.diffdir(os.getcwd()) + (c, a, d, u) = repo.changes(None, None) (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u)) for f in c: print "C", f @@ -662,7 +664,7 @@ ui.warn("abort: 'tip' is a reserved name!\n") return -1 - (c, a, d, u) = repo.diffdir(repo.root) + (c, a, d, u) = repo.changes(None, None) for x in (c, a, d, u): if ".hgtags" in x: ui.warn("abort: working copy of .hgtags is changed!\n") diff -r c8ae964109c1 -r 4fc63e22b1fe mercurial/hg.py --- a/mercurial/hg.py Fri Jul 01 07:40:32 2005 +0100 +++ b/mercurial/hg.py Thu Jun 30 23:28:16 2005 -0800 @@ -288,9 +288,57 @@ st.write(e + f) self.dirty = 0 - def dup(self): + def changes(self, files, ignore): self.read() - return self.map.copy() + dc = self.map.copy() + lookup, changed, added, unknown = [], [], [], [] + + # compare all files by default + if not files: files = [self.root] + + def uniq(g): + seen = {} + for f in g: + if f not in seen: + seen[f] = 1 + yield f + + # recursive generator of all files listed + def walk(files): + for f in uniq(files): + f = os.path.join(self.root, f) + if os.path.isdir(f): + for dir, subdirs, fl in os.walk(f): + d = dir[len(self.root) + 1:] + if ".hg" in subdirs: subdirs.remove(".hg") + for fn in fl: + fn = util.pconvert(os.path.join(d, fn)) + yield fn + else: + yield f[len(self.root) + 1:] + + for fn in uniq(walk(files)): + try: s = os.stat(os.path.join(self.root, fn)) + except: continue + + if fn in dc: + c = dc[fn] + del dc[fn] + + if c[0] == 'm': + changed.append(fn) + elif c[0] == 'a': + added.append(fn) + elif c[0] == 'r': + unknown.append(fn) + elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: + changed.append(fn) + elif c[1] != s.st_mode or c[3] != s.st_mtime: + lookup.append(fn) + else: + if not ignore(fn): unknown.append(fn) + + return (lookup, changed, added, dc.keys(), unknown) # used to avoid circular references so destructors work def opener(base): @@ -568,7 +616,7 @@ else: self.ui.warn("%s not tracked!\n" % f) else: - (c, a, d, u) = self.diffdir(self.root) + (c, a, d, u) = self.changes(None, None) commit = c + a remove = d @@ -644,81 +692,60 @@ self.dirstate.update(new, "n") self.dirstate.forget(remove) - def diffdir(self, path, changeset = None): - changed = [] - added = [] - unknown = [] - mf = {} + def changes(self, node1, node2, files=None): + # changed, added, deleted, unknown + c, a, d, u, mf1 = [], [], [], [], None - if changeset: - change = self.changelog.read(changeset) - mf = self.manifest.read(change[0]) - dc = dict.fromkeys(mf) - else: - changeset = self.dirstate.parents()[0] - change = self.changelog.read(changeset) - mf = self.manifest.read(change[0]) - dc = self.dirstate.dup() - - def fcmp(fn): + def fcmp(fn, mf): t1 = self.wfile(fn).read() t2 = self.file(fn).revision(mf[fn]) return cmp(t1, t2) - for dir, subdirs, files in os.walk(path): - d = dir[len(self.root)+1:] - if ".hg" in subdirs: subdirs.remove(".hg") + # are we comparing the working directory? + if not node1: + l, c, a, d, u = self.dirstate.changes(files, self.ignore) + + # are we comparing working dir against its parent? + if not node2: + if l: + # do a full compare of any files that might have changed + change = self.changelog.read(self.dirstate.parents()[0]) + mf1 = self.manifest.read(change[0]) + for f in lookup: + if fcmp(f, mf): + c.append(f) + return (c, a, d, u) - for f in files: - fn = util.pconvert(os.path.join(d, f)) - try: s = os.stat(os.path.join(self.root, fn)) - except: continue - if fn in dc: - c = dc[fn] - del dc[fn] - if not c: - if fcmp(fn): - changed.append(fn) - elif c[0] == 'm': - changed.append(fn) - elif c[0] == 'a': - added.append(fn) - elif c[0] == 'r': - unknown.append(fn) - elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: - changed.append(fn) - elif c[1] != s.st_mode or c[3] != s.st_mtime: - if fcmp(fn): - changed.append(fn) - else: - if self.ignore(fn): continue - unknown.append(fn) + # are we comparing working dir against non-tip? + # generate a pseudo-manifest for the working dir + if not node1: + if not mf1: + change = self.changelog.read(self.dirstate.parents()[0]) + mf1 = self.manifest.read(change[0]) + for f in a + c + l: + mf1[f] = "" + for f in d: + if f in mf1: del mf1[f] + else: + change = self.changelog.read(node1) + mf1 = self.manifest.read(change[0]) - deleted = dc.keys() - deleted.sort() - - return (changed, added, deleted, unknown) - - def diffrevs(self, node1, node2): - changed, added = [], [] - - change = self.changelog.read(node1) - mf1 = self.manifest.read(change[0]) change = self.changelog.read(node2) mf2 = self.manifest.read(change[0]) for fn in mf2: if mf1.has_key(fn): if mf1[fn] != mf2[fn]: - changed.append(fn) + if mf1[fn] != "" or fcmp(fn, mf2): + c.append(fn) del mf1[fn] else: - added.append(fn) + a.append(fn) - deleted = mf1.keys() - deleted.sort() + d = mf1.keys() + d.sort() - return (changed, added, deleted) + return (c, a, d, u) def add(self, list): for f in list: @@ -1044,7 +1071,7 @@ ma = self.manifest.read(man) mfa = self.manifest.readflags(man) - (c, a, d, u) = self.diffdir(self.root) + (c, a, d, u) = self.changes(None, None) # is this a jump, or a merge? i.e. is there a linear path # from p1 to p2? diff -r c8ae964109c1 -r 4fc63e22b1fe mercurial/hgweb.py --- a/mercurial/hgweb.py Fri Jul 01 07:40:32 2005 +0100 +++ b/mercurial/hgweb.py Thu Jun 30 23:28:16 2005 -0800 @@ -194,7 +194,7 @@ date1 = self.date(change1) date2 = self.date(change2) - c, a, d = r.diffrevs(node1, node2) + c, a, d, u = r.changes(node1, node2) c, a, d = map(lambda x: filterfiles(x, files), (c, a, d)) for f in c: @@ -286,6 +286,68 @@ manifest = hex(mf), rev = pos, changesets = count, entries = changelist) + def search(self, query): + + def changelist(): + cl = self.repo.changelog + count = 0 + qw = query.lower().split() + + def revgen(): + for i in range(cl.count() - 1, 0, -100): + l = [] + for j in range(max(0, i - 100), i): + n = cl.node(j) + changes = cl.read(n) + l.insert(0, (n, j, changes)) + for e in l: + yield e + + for n, i, changes in revgen(): + miss = 0 + for q in qw: + if not (q in changes[1].lower() or + q in changes[4].lower() or + q in " ".join(changes[3][:20]).lower()): + miss = 1 + break + if miss: continue + + count += 1 + hn = hex(n) + p1, p2 = cl.parents(n) + t = float(changes[2].split(' ')[0]) + + yield self.t( + 'searchentry', + parity = count & 1, + author = changes[1], + parent1 = self.parent("changelogparent", + hex(p1), cl.rev(p1)), + parent2 = self.parent("changelogparent", + hex(p2), cl.rev(p2)), + p1 = hex(p1), p2 = hex(p2), + p1rev = cl.rev(p1), p2rev = cl.rev(p2), + manifest = hex(changes[0]), + desc = changes[4], + date = t, + files = self.listfilediffs(changes[3], n), + rev = i, + node = hn) + + if count >= self.maxchanges: break + + cl = self.repo.changelog + mf = cl.read(cl.tip())[0] + + yield self.t('search', + header = self.header(), + footer = self.footer(), + query = query, + repo = self.reponame, + manifest = hex(mf), + entries = changelist) + def changeset(self, nodeid): n = bin(nodeid) cl = self.repo.changelog @@ -586,13 +648,16 @@ self.t = templater(m, self.filters) if not args.has_key('cmd') or args['cmd'][0] == 'changelog': - hi = self.repo.changelog.count() - 1 + c = self.repo.changelog.count() - 1 + hi = c if args.has_key('rev'): hi = args['rev'][0] try: hi = self.repo.changelog.rev(self.repo.lookup(hi)) - except KeyError: pass - + except KeyError: + write(self.search(hi)) + return + write(self.changelog(hi)) elif args['cmd'][0] == 'changeset': diff -r c8ae964109c1 -r 4fc63e22b1fe mercurial/revlog.py diff -r c8ae964109c1 -r 4fc63e22b1fe templates/map --- a/templates/map Fri Jul 01 07:40:32 2005 +0100 +++ b/templates/map Thu Jun 30 23:28:16 2005 -0800 @@ -1,11 +1,13 @@ header = header.tmpl footer = footer.tmpl +search = search.tmpl changelog = changelog.tmpl naventry = "#label# " filedifflink = "#file# " filenodelink = "#file# " fileellipses = "..." changelogentry = changelogentry.tmpl +searchentry = searchentry.tmpl changeset = changeset.tmpl manifest = manifest.tmpl manifestdirentry = "drwxr-xr-x #basename#/" diff -r c8ae964109c1 -r 4fc63e22b1fe templates/search.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/search.tmpl Thu Jun 30 23:28:16 2005 -0800 @@ -0,0 +1,28 @@ +#header# +#repo|escape#: searching for #query|escape# + + + + + +

searching for #query|escape#

+ +
+search: + + +
+ +#entries# + +
+search: + + +
+ +#footer# diff -r c8ae964109c1 -r 4fc63e22b1fe templates/searchentry.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/searchentry.tmpl Thu Jun 30 23:28:16 2005 -0800 @@ -0,0 +1,22 @@ +
+ + + + + + + +#parent1# +#parent2# + + + + + + + + + +
#date|age# ago: #desc|firstline|escape#
changeset #rev#: #node|short#
author: #author|obfuscate#
date: #date|date#
files#files#
+
+ diff -r c8ae964109c1 -r 4fc63e22b1fe tests/fish-merge diff -r c8ae964109c1 -r 4fc63e22b1fe tests/run-tests diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-bad-pull diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-bad-pull.out --- a/tests/test-bad-pull.out Fri Jul 01 07:40:32 2005 +0100 +++ b/tests/test-bad-pull.out Thu Jun 30 23:28:16 2005 -0800 @@ -9,8 +9,8 @@ + ls copy ls: copy: No such file or directory + cat ++ python dumb.py + sleep 2 -+ python dumb.py + hg clone http://localhost:20059/foo copy2 requesting all changes adding changesets diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-basic diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-conflict diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-copy diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-diffdir --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-diffdir Thu Jun 30 23:28:16 2005 -0800 @@ -0,0 +1,12 @@ +#!/bin/sh + +hg init +touch a +hg add a +hg ci -t "a" -u test -d "0 0" + +echo 123 > b +hg add b +hg diff | sed "s/\(\(---\|+++\).*\)\t.*/\1/" + +hg diff -r tip | sed "s/\(\(---\|+++\).*\)\t.*/\1/" diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-diffdir.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-diffdir.out Thu Jun 30 23:28:16 2005 -0800 @@ -0,0 +1,10 @@ +diff -r 3903775176ed b +--- /dev/null ++++ b/b +@@ -0,0 +1,1 @@ ++123 +diff -r 3903775176ed b +--- /dev/null ++++ b/b +@@ -0,0 +1,1 @@ ++123 diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-help diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-pull diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-rawcommit1.out diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-simple-update diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-tags diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-undo diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-up-local-change diff -r c8ae964109c1 -r 4fc63e22b1fe tests/test-up-local-change.out