# HG changeset patch # User Josef "Jeff" Sipek # Date 1140319482 18000 # Node ID a1e6e02e9d05e45b45fcaa2e95c9bcc6e944d9d9 # Parent b08b87cecc3719d4e6420f8c15a04d7a9e71a007# Parent 57de7e1a81d266d294429b3c7507ac34d9ab382f Merge with mpm diff -r b08b87cecc37 -r a1e6e02e9d05 doc/hg.1.txt --- a/doc/hg.1.txt Sat Feb 18 22:01:09 2006 -0500 +++ b/doc/hg.1.txt Sat Feb 18 22:24:42 2006 -0500 @@ -223,9 +223,11 @@ probably with undesirable results. options: - -a, --text treat all files as text - -I, --include include names matching the given patterns - -X, --exclude exclude names matching the given patterns + -a, --text treat all files as text + -I, --include include names matching the given patterns + -p, --show-function show which function each change is in + -X, --exclude exclude names matching the given patterns + -w, --ignore-all-space ignore white space when comparing lines export [-o filespec] [revision] ...:: Print the changeset header and diffs for one or more revisions. @@ -600,9 +602,12 @@ This lists both regular and local tags. -tip:: +tip [-p]:: Show the tip revision. + options: + -p, --patch show patch + unbundle :: (EXPERIMENTAL) diff -r b08b87cecc37 -r a1e6e02e9d05 doc/hgrc.5.txt --- a/doc/hgrc.5.txt Sat Feb 18 22:01:09 2006 -0500 +++ b/doc/hgrc.5.txt Sat Feb 18 22:24:42 2006 -0500 @@ -145,20 +145,71 @@ incoming.email = /my/email/hook incoming.autobuild = /my/build/hook + Most hooks are run with environment variables set that give added + useful information. For each hook below, the environment variables + it is passed are listed with names of the form "$HG_foo". + changegroup;; - Run after a changegroup has been added via push or pull. Passed - the ID of the first new changeset in $NODE. + Run after a changegroup has been added via push, pull or + unbundle. ID of the first new changeset is in $HG_NODE. commit;; Run after a changeset has been created in the local repository. - Passed the ID of the newly created changeset in environment - variable $NODE. + ID of the newly created changeset is in $HG_NODE. Parent + changeset IDs are in $HG_PARENT1 and $HG_PARENT2. incoming;; Run after a changeset has been pulled, pushed, or unbundled into - the local repository. Passed the ID of the newly arrived - changeset in environment variable $NODE. + the local repository. The ID of the newly arrived changeset is in + $HG_NODE. + outgoing;; + Run after sending changes from local repository to another. ID of + first changeset sent is in $HG_NODE. Source of operation is in + $HG_SOURCE; see "preoutgoing" hook for description. + prechangegroup;; + Run before a changegroup is added via push, pull or unbundle. + Exit status 0 allows the changegroup to proceed. Non-zero status + will cause the push, pull or unbundle to fail. precommit;; - Run before starting a commit. Exit status 0 allows the commit to - proceed. Non-zero status will cause the commit to fail. + Run before starting a local commit. Exit status 0 allows the + commit to proceed. Non-zero status will cause the commit to fail. + Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2. + preoutgoing;; + Run before computing changes to send from the local repository to + another. Non-zero status will cause failure. This lets you + prevent pull over http or ssh. Also prevents against local pull, + push (outbound) or bundle commands, but not effective, since you + can just copy files instead then. Source of operation is in + $HG_SOURCE. If "serve", operation is happening on behalf of + remote ssh or http repository. If "push", "pull" or "bundle", + operation is happening on behalf of repository on same system. + pretag;; + Run before creating a tag. Exit status 0 allows the tag to be + created. Non-zero status will cause the tag to fail. ID of + changeset to tag is in $HG_NODE. Name of tag is in $HG_TAG. Tag + is local if $HG_LOCAL=1, in repo if $HG_LOCAL=0. + pretxnchangegroup;; + Run after a changegroup has been added via push, pull or unbundle, + but before the transaction has been committed. Changegroup is + visible to hook program. This lets you validate incoming changes + before accepting them. Passed the ID of the first new changeset + in $HG_NODE. Exit status 0 allows the transaction to commit. + Non-zero status will cause the transaction to be rolled back and + the push, pull or unbundle will fail. + pretxncommit;; + Run after a changeset has been created but the transaction not yet + committed. Changeset is visible to hook program. This lets you + validate commit message and changes. Exit status 0 allows the + commit to proceed. Non-zero status will cause the transaction to + be rolled back. ID of changeset is in $HG_NODE. Parent changeset + IDs are in $HG_PARENT1 and $HG_PARENT2. + tag;; + Run after a tag is created. ID of tagged changeset is in + $HG_NODE. Name of tag is in $HG_TAG. Tag is local if + $HG_LOCAL=1, in repo if $HG_LOCAL=0. + + In earlier releases, the names of hook environment variables did not + have a "HG_" prefix. These unprefixed names are still provided in + the environment for backwards compatibility, but their use is + deprecated, and they will be removed in a future release. http_proxy:: Used to access web-based Mercurial repositories through a HTTP diff -r b08b87cecc37 -r a1e6e02e9d05 mercurial/commands.py --- a/mercurial/commands.py Sat Feb 18 22:01:09 2006 -0500 +++ b/mercurial/commands.py Sat Feb 18 22:24:42 2006 -0500 @@ -261,7 +261,7 @@ mode) def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always, - changes=None, text=False): + changes=None, text=False, opts={}): if not changes: changes = repo.changes(node1, node2, files, match=match) modified, added, removed, deleted, unknown = changes @@ -296,8 +296,8 @@ date1 = util.datestr(change[2]) diffopts = ui.diffopts() - showfunc = diffopts['showfunc'] - ignorews = diffopts['ignorews'] + showfunc = opts.get('show_function') or diffopts['showfunc'] + ignorews = opts.get('ignore_all_space') or diffopts['ignorews'] for f in modified: to = None if f in mmap: @@ -622,7 +622,7 @@ dest = ui.expandpath(dest, repo.root) other = hg.repository(ui, dest) o = repo.findoutgoing(other) - cg = repo.changegroup(o) + cg = repo.changegroup(o, 'bundle') try: f.write("HG10") @@ -1140,7 +1140,7 @@ fns, matchfn, anypats = matchpats(repo, pats, opts) dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn, - text=opts['text']) + text=opts['text'], opts=opts) def doexport(ui, repo, changeset, seqno, total, revwidth, opts): node = repo.lookup(changeset) @@ -1681,7 +1681,7 @@ dodiff(ui, ui, repo, prev, n) ui.write("\n") -def parents(ui, repo, rev=None): +def parents(ui, repo, rev=None, branch=None): """show the parents of the working dir or revision Print the working directory's parent revisions. @@ -1691,9 +1691,12 @@ else: p = repo.dirstate.parents() + br = None + if branch is not None: + br = repo.branchlookup(p) for n in p: if n != nullid: - show_changeset(ui, repo, changenode=n) + show_changeset(ui, repo, changenode=n, brinfo=br) def paths(ui, search=None): """show definition of symbolic path names @@ -1996,7 +1999,7 @@ arg, roots = getarg() nodes = map(bin, roots.split(" ")) - cg = repo.changegroup(nodes) + cg = repo.changegroup(nodes, 'serve') while 1: d = cg.read(4096) if not d: @@ -2113,8 +2116,12 @@ if name.find(c) >= 0: raise util.Abort(_("%s cannot be used in a tag name") % repr(c)) + repo.hook('pretag', throw=True, node=r, tag=name, + local=int(not not opts['local'])) + if opts['local']: repo.opener("localtags", "a").write("%s %s\n" % (r, name)) + repo.hook('tag', node=r, tag=name, local=1) return for x in repo.changes(): @@ -2130,6 +2137,7 @@ _("Added tag %s for changeset %s") % (name, r)) try: repo.commit([".hgtags"], message, opts['user'], opts['date']) + repo.hook('tag', node=r, tag=name, local=0) except ValueError, inst: raise util.Abort(str(inst)) @@ -2150,13 +2158,15 @@ r = " ?:?" ui.write("%-30s %s\n" % (t, r)) -def tip(ui, repo): +def tip(ui, repo, **opts): """show the tip revision Show the tip revision. """ n = repo.changelog.tip() show_changeset(ui, repo, changenode=n) + if opts['patch']: + dodiff(ui, ui, repo, repo.changelog.parents(n)[0], n) def unbundle(ui, repo, fname, **opts): """apply a changegroup file @@ -2332,7 +2342,12 @@ [('r', 'rev', [], _('revision')), ('a', 'text', None, _('treat all files as text')), ('I', 'include', [], _('include names matching the given patterns')), - ('X', 'exclude', [], _('exclude names matching the given patterns'))], + ('p', 'show-function', None, + _('show which function each change is in')), + ('w', 'ignore-all-space', None, + _('ignore white space when comparing lines')), + ('X', 'exclude', [], + _('exclude names matching the given patterns'))], _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')), "^export": (export, @@ -2407,7 +2422,10 @@ ('p', 'patch', None, _('show patch')), ('n', 'newest-first', None, _('show newest record first'))], _('hg outgoing [-p] [-n] [-M] [DEST]')), - "^parents": (parents, [], _('hg parents [REV]')), + "^parents": + (parents, + [('b', 'branch', None, _('show branches'))], + _('hg parents [-b] [REV]')), "paths": (paths, [], _('hg paths [NAME]')), "^pull": (pull, @@ -2490,7 +2508,7 @@ ('r', 'rev', '', _('revision to tag'))], _('hg tag [-r REV] [OPTION]... NAME')), "tags": (tags, [], _('hg tags')), - "tip": (tip, [], _('hg tip')), + "tip": (tip, [('p', 'patch', None, _('show patch'))], _('hg tip')), "unbundle": (unbundle, [('u', 'update', None, @@ -2530,17 +2548,20 @@ def find(cmd): """Return (aliases, command table entry) for command string.""" choice = None + count = 0 for e in table.keys(): aliases = e.lstrip("^").split("|") if cmd in aliases: return aliases, table[e] for a in aliases: if a.startswith(cmd): - if choice: - raise AmbiguousCommand(cmd) - else: - choice = aliases, table[e] - break + count += 1 + choice = aliases, table[e] + break + + if count > 1: + raise AmbiguousCommand(cmd) + if choice: return choice diff -r b08b87cecc37 -r a1e6e02e9d05 mercurial/hgweb.py --- a/mercurial/hgweb.py Sat Feb 18 22:01:09 2006 -0500 +++ b/mercurial/hgweb.py Sat Feb 18 22:24:42 2006 -0500 @@ -965,7 +965,7 @@ nodes = map(bin, req.form['roots'][0].split(" ")) z = zlib.compressobj() - f = self.repo.changegroup(nodes) + f = self.repo.changegroup(nodes, 'serve') while 1: chunk = f.read(4096) if not chunk: diff -r b08b87cecc37 -r a1e6e02e9d05 mercurial/httprepo.py --- a/mercurial/httprepo.py Sat Feb 18 22:01:09 2006 -0500 +++ b/mercurial/httprepo.py Sat Feb 18 22:24:42 2006 -0500 @@ -119,7 +119,7 @@ self.ui.warn(_("unexpected response:\n") + d[:400] + "\n...\n") raise - def changegroup(self, nodes): + def changegroup(self, nodes, kind): n = " ".join(map(hex, nodes)) f = self.do_cmd("changegroup", roots=n) bytes = 0 diff -r b08b87cecc37 -r a1e6e02e9d05 mercurial/localrepo.py --- a/mercurial/localrepo.py Sat Feb 18 22:01:09 2006 -0500 +++ b/mercurial/localrepo.py Sat Feb 18 22:24:42 2006 -0500 @@ -48,30 +48,36 @@ except IOError: pass - def hook(self, name, **args): + def hook(self, name, throw=False, **args): def runhook(name, cmd): self.ui.note(_("running hook %s: %s\n") % (name, cmd)) old = {} for k, v in args.items(): k = k.upper() + old['HG_' + k] = os.environ.get(k, None) old[k] = os.environ.get(k, None) - os.environ[k] = v + os.environ['HG_' + k] = str(v) + os.environ[k] = str(v) - # Hooks run in the repository root - olddir = os.getcwd() - os.chdir(self.root) - r = os.system(cmd) - os.chdir(olddir) + try: + # Hooks run in the repository root + olddir = os.getcwd() + os.chdir(self.root) + r = os.system(cmd) + finally: + for k, v in old.items(): + if v is not None: + os.environ[k] = v + else: + del os.environ[k] - for k, v in old.items(): - if v != None: - os.environ[k] = v - else: - del os.environ[k] + os.chdir(olddir) if r: - self.ui.warn(_("abort: %s hook failed with status %d!\n") % - (name, r)) + desc, r = util.explain_exit(r) + if throw: + raise util.Abort(_('%s hook %s') % (name, desc)) + self.ui.warn(_('error: %s hook %s\n') % (name, desc)) return False return True @@ -268,6 +274,25 @@ self.dirstate.read() return wlock + def checkfilemerge(self, filename, text, filelog, manifest1, manifest2): + "determine whether a new filenode is needed" + fp1 = manifest1.get(filename, nullid) + fp2 = manifest2.get(filename, nullid) + + if fp2 != nullid: + # is one parent an ancestor of the other? + fpa = filelog.ancestor(fp1, fp2) + if fpa == fp1: + fp1, fp2 = fp2, nullid + elif fpa == fp2: + fp2 = nullid + + # is the file unmodified from the parent? report existing entry + if fp2 == nullid and text == filelog.read(fp1): + return (fp1, None, None) + + return (None, fp1, fp2) + def rawcommit(self, files, text, user, date, p1=None, p2=None, wlock=None): orig_parent = self.dirstate.parents()[0] or nullid p1 = p1 or self.dirstate.parents()[0] or nullid @@ -298,27 +323,10 @@ r = self.file(f) mfm[f] = tm - fp1 = m1.get(f, nullid) - fp2 = m2.get(f, nullid) - - # is the same revision on two branches of a merge? - if fp2 == fp1: - fp2 = nullid - - if fp2 != nullid: - # is one parent an ancestor of the other? - fpa = r.ancestor(fp1, fp2) - if fpa == fp1: - fp1, fp2 = fp2, nullid - elif fpa == fp2: - fp2 = nullid - - # is the file unmodified from the parent? - if t == r.read(fp1): - # record the proper existing parent in manifest - # no need to add a revision - mm[f] = fp1 - continue + (entry, fp1, fp2) = self.checkfilemerge(f, t, r, m1, m2) + if entry: + mm[f] = entry + continue mm[f] = r.add(t, {}, tr, linkrev, fp1, fp2) changed.append(f) @@ -372,8 +380,11 @@ self.ui.status(_("nothing changed\n")) return None - if not self.hook("precommit"): - return None + xp1 = hex(p1) + if p2 == nullid: xp2 = '' + else: xp2 = hex(p2) + + self.hook("precommit", throw=True, parent1=xp1, parent2=xp2) if not wlock: wlock = self.wlock() @@ -403,22 +414,9 @@ self.ui.debug(_(" %s: copy %s:%s\n") % (f, cp, meta["copyrev"])) fp1, fp2 = nullid, nullid else: - fp1 = m1.get(f, nullid) - fp2 = m2.get(f, nullid) - - if fp2 != nullid: - # is one parent an ancestor of the other? - fpa = r.ancestor(fp1, fp2) - if fpa == fp1: - fp1, fp2 = fp2, nullid - elif fpa == fp2: - fp2 = nullid - - # is the file unmodified from the parent? - if not meta and t == r.read(fp1) and fp2 == nullid: - # record the proper existing parent in manifest - # no need to add a revision - new[f] = fp1 + entry, fp1, fp2 = self.checkfilemerge(f, t, r, m1, m2) + if entry: + new[f] = entry continue new[f] = r.add(t, meta, tr, linkrev, fp1, fp2) @@ -459,14 +457,15 @@ user = user or self.ui.username() n = self.changelog.add(mn, changed + remove, text, tr, p1, p2, user, date) + self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, + parent2=xp2) tr.close() self.dirstate.setparents(n) self.dirstate.update(new, "n") self.dirstate.forget(remove) - if not self.hook("commit", node=hex(n)): - return None + self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) return n def walk(self, node=None, files=[], match=util.always): @@ -947,9 +946,9 @@ return 1 if heads is None: - cg = remote.changegroup(fetch) + cg = remote.changegroup(fetch, 'pull') else: - cg = remote.changegroupsubset(fetch, heads) + cg = remote.changegroupsubset(fetch, heads, 'pull') return self.addchangegroup(cg) def push(self, remote, force=False): @@ -974,10 +973,10 @@ " use push -f to force)\n")) return 1 - cg = self.changegroup(update) + cg = self.changegroup(update, 'push') return remote.addchangegroup(cg) - def changegroupsubset(self, bases, heads): + def changegroupsubset(self, bases, heads, source): """This function generates a changegroup consisting of all the nodes that are descendents of any of the bases, and ancestors of any of the heads. @@ -989,6 +988,8 @@ Another wrinkle is doing the reverse, figuring out which changeset in the changegroup a particular filenode or manifestnode belongs to.""" + self.hook('preoutgoing', throw=True, source=source) + # Set up some initial variables # Make it easy to refer to self.changelog cl = self.changelog @@ -1241,14 +1242,19 @@ # Signal that no more groups are left. yield struct.pack(">l", 0) + self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source) + return util.chunkbuffer(gengroup()) - def changegroup(self, basenodes): + def changegroup(self, basenodes, source): """Generate a changegroup of all nodes that we have that a recipient doesn't. This is much easier than the previous function as we can assume that the recipient has any changenode we aren't sending them.""" + + self.hook('preoutgoing', throw=True, source=source) + cl = self.changelog nodes = cl.nodesbetween(basenodes, None)[0] revset = dict.fromkeys([cl.rev(n) for n in nodes]) @@ -1300,6 +1306,7 @@ yield chnk yield struct.pack(">l", 0) + self.hook('outgoing', node=hex(nodes[0]), source=source) return util.chunkbuffer(gengroup()) @@ -1335,6 +1342,9 @@ if not source: return + + self.hook('prechangegroup', throw=True) + changesets = files = revisions = 0 tr = self.transaction() @@ -1377,19 +1387,17 @@ " with %d changes to %d files%s\n") % (changesets, revisions, files, heads)) + self.hook('pretxnchangegroup', throw=True, + node=hex(self.changelog.node(cor+1))) + tr.close() if changesets > 0: - if not self.hook("changegroup", - node=hex(self.changelog.node(cor+1))): - self.ui.warn(_("abort: changegroup hook returned failure!\n")) - return 1 + self.hook("changegroup", node=hex(self.changelog.node(cor+1))) for i in range(cor + 1, cnr + 1): self.hook("incoming", node=hex(self.changelog.node(i))) - return - def update(self, node, allow=False, force=False, choose=None, moddirstate=True, forcemerge=False, wlock=None): pl = self.dirstate.parents() diff -r b08b87cecc37 -r a1e6e02e9d05 mercurial/mdiff.py --- a/mercurial/mdiff.py Sat Feb 18 22:01:09 2006 -0500 +++ b/mercurial/mdiff.py Sat Feb 18 22:24:42 2006 -0500 @@ -18,16 +18,22 @@ if not text and (util.binary(a) or util.binary(b)): l = ['Binary file %s has changed\n' % fn] - elif a == None: + elif not a: b = b.splitlines(1) - l1 = "--- %s\t%s\n" % ("/dev/null", epoch) + if a is None: + l1 = "--- %s\t%s\n" % ("/dev/null", epoch) + else: + l1 = "--- %s\t%s\n" % ("a/" + fn, ad) l2 = "+++ %s\t%s\n" % ("b/" + fn, bd) l3 = "@@ -0,0 +1,%d @@\n" % len(b) l = [l1, l2, l3] + ["+" + e for e in b] - elif b == None: + elif not b: a = a.splitlines(1) l1 = "--- %s\t%s\n" % ("a/" + fn, ad) - l2 = "+++ %s\t%s\n" % ("/dev/null", epoch) + if b is None: + l2 = "+++ %s\t%s\n" % ("/dev/null", epoch) + else: + l2 = "+++ %s\t%s\n" % ("b/" + fn, bd) l3 = "@@ -1,%d +0,0 @@\n" % len(a) l = [l1, l2, l3] + ["-" + e for e in a] else: diff -r b08b87cecc37 -r a1e6e02e9d05 mercurial/mpatch.c --- a/mercurial/mpatch.c Sat Feb 18 22:01:09 2006 -0500 +++ b/mercurial/mpatch.c Sat Feb 18 22:24:42 2006 -0500 @@ -43,6 +43,7 @@ #endif static char mpatch_doc[] = "Efficient binary patching."; +static PyObject *mpatch_Error; struct frag { int start, end, len; @@ -65,8 +66,11 @@ a = NULL; } else a->head = a->tail = a->base; + return a; } - return a; + if (!PyErr_Occurred()) + PyErr_NoMemory(); + return NULL; } static void lfree(struct flist *a) @@ -215,6 +219,9 @@ /* assume worst case size, we won't have many of these lists */ l = lalloc(len / 12); + if (!l) + return NULL; + lt = l->tail; while (bin < end) { @@ -227,6 +234,13 @@ lt++; } + if (bin != end) { + if (!PyErr_Occurred()) + PyErr_SetString(mpatch_Error, "patch cannot be decoded"); + lfree(l); + return NULL; + } + l->tail = lt; return l; } @@ -238,6 +252,12 @@ struct frag *f = l->head; while (f != l->tail) { + if (f->start < last || f->end > len) { + if (!PyErr_Occurred()) + PyErr_SetString(mpatch_Error, + "invalid patch"); + return -1; + } outlen += f->start - last; last = f->end; outlen += f->len; @@ -248,13 +268,19 @@ return outlen; } -static void apply(char *buf, char *orig, int len, struct flist *l) +static int apply(char *buf, char *orig, int len, struct flist *l) { struct frag *f = l->head; int last = 0; char *p = buf; while (f != l->tail) { + if (f->start < last || f->end > len) { + if (!PyErr_Occurred()) + PyErr_SetString(mpatch_Error, + "invalid patch"); + return 0; + } memcpy(p, orig + last, f->start - last); p += f->start - last; memcpy(p, f->data, f->len); @@ -263,6 +289,7 @@ f++; } memcpy(p, orig + last, len - last); + return 1; } /* recursively generate a patch of all bins between start and end */ @@ -304,16 +331,25 @@ patch = fold(bins, 0, len); if (!patch) - return PyErr_NoMemory(); + return NULL; outlen = calcsize(PyString_Size(text), patch); + if (outlen < 0) { + result = NULL; + goto cleanup; + } result = PyString_FromStringAndSize(NULL, outlen); - if (result) { - in = PyString_AsString(text); - out = PyString_AsString(result); - apply(out, in, PyString_Size(text), patch); + if (!result) { + result = NULL; + goto cleanup; } - + in = PyString_AsString(text); + out = PyString_AsString(result); + if (!apply(out, in, PyString_Size(text), patch)) { + Py_DECREF(result); + result = NULL; + } +cleanup: lfree(patch); return result; } @@ -327,5 +363,6 @@ initmpatch(void) { Py_InitModule3("mpatch", methods, mpatch_doc); + mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); } diff -r b08b87cecc37 -r a1e6e02e9d05 mercurial/sshrepo.py --- a/mercurial/sshrepo.py Sat Feb 18 22:01:09 2006 -0500 +++ b/mercurial/sshrepo.py Sat Feb 18 22:24:42 2006 -0500 @@ -110,7 +110,7 @@ except: raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")) - def changegroup(self, nodes): + def changegroup(self, nodes, kind): n = " ".join(map(hex, nodes)) f = self.do_cmd("changegroup", roots=n) return self.pipei diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-diffdir --- a/tests/test-diffdir Sat Feb 18 22:01:09 2006 -0500 +++ b/tests/test-diffdir Sat Feb 18 22:24:42 2006 -0500 @@ -12,3 +12,7 @@ hg diff -r tip | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \ -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" + +echo foo > a +hg diff | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \ + -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-diffdir.out --- a/tests/test-diffdir.out Sat Feb 18 22:01:09 2006 -0500 +++ b/tests/test-diffdir.out Sat Feb 18 22:24:42 2006 -0500 @@ -8,3 +8,13 @@ +++ b/b @@ -0,0 +1,1 @@ +123 +diff -r 3903775176ed a +--- a/a ++++ b/a +@@ -0,0 +1,1 @@ ++foo +diff -r 3903775176ed b +--- /dev/null ++++ b/b +@@ -0,0 +1,1 @@ ++123 diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-excessive-merge --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-excessive-merge Sat Feb 18 22:24:42 2006 -0500 @@ -0,0 +1,46 @@ +#!/bin/sh + +hg init + +echo foo > a +echo foo > b +hg add a b + +hg ci -m "test" -d "0 0" + +echo blah > a + +hg ci -m "branch a" -d "0 0" + +hg co 0 + +echo blah > b + +hg ci -m "branch b" -d "0 0" +HGMERGE=true hg up -m 1 + +hg ci -m "merge b/a -> blah" -d "0 0" + +hg co 1 +HGMERGE=true hg up -m 2 +hg ci -m "merge a/b -> blah" -d "0 0" + +hg log +hg debugindex .hg/00changelog.i + +echo + +echo 1 +hg manifest 1 +echo 2 +hg manifest 2 +echo 3 +hg manifest 3 +echo 4 +hg manifest 4 + +echo + +hg debugindex .hg/data/a.i + +hg verify \ No newline at end of file diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-excessive-merge.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-excessive-merge.out Sat Feb 18 22:24:42 2006 -0500 @@ -0,0 +1,59 @@ +changeset: 4:2ee31f665a86 +tag: tip +parent: 1:96155394af80 +parent: 2:92cc4c306b19 +user: test +date: Thu Jan 1 00:00:00 1970 +0000 +summary: merge a/b -> blah + +changeset: 3:e16a66a37edd +parent: 2:92cc4c306b19 +parent: 1:96155394af80 +user: test +date: Thu Jan 1 00:00:00 1970 +0000 +summary: merge b/a -> blah + +changeset: 2:92cc4c306b19 +parent: 0:5e0375449e74 +user: test +date: Thu Jan 1 00:00:00 1970 +0000 +summary: branch b + +changeset: 1:96155394af80 +user: test +date: Thu Jan 1 00:00:00 1970 +0000 +summary: branch a + +changeset: 0:5e0375449e74 +user: test +date: Thu Jan 1 00:00:00 1970 +0000 +summary: test + + rev offset length base linkrev nodeid p1 p2 + 0 0 60 0 0 5e0375449e74 000000000000 000000000000 + 1 60 62 1 1 96155394af80 5e0375449e74 000000000000 + 2 122 62 2 2 92cc4c306b19 5e0375449e74 000000000000 + 3 184 69 3 3 e16a66a37edd 92cc4c306b19 96155394af80 + 4 253 29 3 4 2ee31f665a86 96155394af80 92cc4c306b19 + +1 +79d7492df40aa0fa093ec4209be78043c181f094 644 a +2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 b +2 +2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 a +79d7492df40aa0fa093ec4209be78043c181f094 644 b +3 +79d7492df40aa0fa093ec4209be78043c181f094 644 a +79d7492df40aa0fa093ec4209be78043c181f094 644 b +4 +79d7492df40aa0fa093ec4209be78043c181f094 644 a +79d7492df40aa0fa093ec4209be78043c181f094 644 b + + rev offset length base linkrev nodeid p1 p2 + 0 0 5 0 0 2ed2a3912a0b 000000000000 000000000000 + 1 5 6 1 1 79d7492df40a 2ed2a3912a0b 000000000000 +checking changesets +checking manifests +crosschecking files in changesets and manifests +checking files +2 files, 5 changesets, 4 total revisions diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-help.out --- a/tests/test-help.out Sat Feb 18 22:01:09 2006 -0500 +++ b/tests/test-help.out Sat Feb 18 22:24:42 2006 -0500 @@ -171,10 +171,12 @@ options: - -r --rev revision - -a --text treat all files as text - -I --include include names matching the given patterns - -X --exclude exclude names matching the given patterns + -r --rev revision + -a --text treat all files as text + -I --include include names matching the given patterns + -p --show-function show which function each change is in + -w --ignore-all-space ignore white space when comparing lines + -X --exclude exclude names matching the given patterns hg status [OPTION]... [FILE]... show changed files in the working directory diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-hook --- a/tests/test-hook Sat Feb 18 22:01:09 2006 -0500 +++ b/tests/test-hook Sat Feb 18 22:24:42 2006 -0500 @@ -1,10 +1,90 @@ #!/bin/sh -hg init +# commit hooks can see env vars +hg init a +cd a echo "[hooks]" > .hg/hgrc -echo 'precommit = echo precommit hook' >> .hg/hgrc -echo 'commit = echo commit hook: $NODE' >> .hg/hgrc +echo 'commit = echo commit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc echo 'commit.b = echo commit hook b' >> .hg/hgrc +echo 'precommit = echo precommit hook: p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc +echo 'pretxncommit = echo pretxncommit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2; hg -q tip' >> .hg/hgrc echo a > a hg add a -hg commit -m "test" -d "0 0" +hg commit -m a -d "0 0" + +hg clone . ../b +cd ../b + +# changegroup hooks can see env vars +echo '[hooks]' > .hg/hgrc +echo 'prechangegroup = echo prechangegroup hook' >> .hg/hgrc +echo 'changegroup = echo changegroup hook: n=$HG_NODE' >> .hg/hgrc +echo 'incoming = echo incoming hook: n=$HG_NODE' >> .hg/hgrc + +# pretxncommit and commit hooks can see both parents of merge +cd ../a +echo b >> a +hg commit -m a1 -d "1 0" +hg update -C 0 +echo b > b +hg add b +hg commit -m b -d '1 0' +hg update -m 1 +hg commit -m merge -d '2 0' + +cd ../b +hg pull ../a + +# tag hooks can see env vars +cd ../a +echo 'pretag = echo pretag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc +echo 'tag = echo tag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc +hg tag -d '3 0' a +hg tag -l la + +# pretag hook can forbid tagging +echo 'pretag.forbid = echo pretag.forbid hook; exit 1' >> .hg/hgrc +hg tag -d '4 0' fa +hg tag -l fla + +# pretxncommit hook can see changeset, can roll back txn, changeset +# no more there after +echo 'pretxncommit.forbid = echo pretxncommit.forbid hook: tip=`hg -q tip`; exit 1' >> .hg/hgrc +echo z > z +hg add z +hg -q tip +hg commit -m 'fail' -d '4 0' +hg -q tip + +# precommit hook can prevent commit +echo 'precommit.forbid = echo precommit.forbid hook; exit 1' >> .hg/hgrc +hg commit -m 'fail' -d '4 0' +hg -q tip + +# prechangegroup hook can prevent incoming changes +cd ../b +hg -q tip +echo '[hooks]' > .hg/hgrc +echo 'prechangegroup.forbid = echo prechangegroup.forbid hook; exit 1' >> .hg/hgrc +hg pull ../a + +# pretxnchangegroup hook can see incoming changes, can roll back txn, +# incoming changes no longer there after +echo '[hooks]' > .hg/hgrc +echo 'pretxnchangegroup.forbid = echo pretxnchangegroup.forbid hook: tip=`hg -q tip`; exit 1' >> .hg/hgrc +hg pull ../a +hg -q tip + +# outgoing hooks can see env vars +rm .hg/hgrc +echo '[hooks]' > ../a/.hg/hgrc +echo 'preoutgoing = echo preoutgoing hook: s=$HG_SOURCE' >> ../a/.hg/hgrc +echo 'outgoing = echo outgoing hook: n=$HG_NODE s=$HG_SOURCE' >> ../a/.hg/hgrc +hg pull ../a +hg undo + +# preoutgoing hook can prevent outgoing changes +echo 'preoutgoing.forbid = echo preoutgoing.forbid hook; exit 1' >> ../a/.hg/hgrc +hg pull ../a + +exit 0 diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-hook.out --- a/tests/test-hook.out Sat Feb 18 22:01:09 2006 -0500 +++ b/tests/test-hook.out Sat Feb 18 22:24:42 2006 -0500 @@ -1,3 +1,88 @@ -precommit hook +precommit hook: p1=0000000000000000000000000000000000000000 p2= +pretxncommit hook: n=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p1=0000000000000000000000000000000000000000 p2= +0:cb9a9f314b8b +commit hook b +commit hook: n=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p1=0000000000000000000000000000000000000000 p2= +precommit hook: p1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p2= +pretxncommit hook: n=ab228980c14deea8b9555d91c9581127383e40fd p1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p2= +1:ab228980c14d +commit hook b +commit hook: n=ab228980c14deea8b9555d91c9581127383e40fd p1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p2= +precommit hook: p1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p2= +pretxncommit hook: n=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 p1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p2= +2:ee9deb46ab31 +commit hook b +commit hook: n=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 p1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b p2= +precommit hook: p1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 p2=ab228980c14deea8b9555d91c9581127383e40fd +pretxncommit hook: n=07f3376c1e655977439df2a814e3cc14b27abac2 p1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 p2=ab228980c14deea8b9555d91c9581127383e40fd +3:07f3376c1e65 +commit hook b +commit hook: n=07f3376c1e655977439df2a814e3cc14b27abac2 p1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 p2=ab228980c14deea8b9555d91c9581127383e40fd +prechangegroup hook +changegroup hook: n=ab228980c14deea8b9555d91c9581127383e40fd +incoming hook: n=ab228980c14deea8b9555d91c9581127383e40fd +incoming hook: n=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 +incoming hook: n=07f3376c1e655977439df2a814e3cc14b27abac2 +pulling from ../a +searching for changes +adding changesets +adding manifests +adding file changes +added 3 changesets with 2 changes to 2 files +(run 'hg update' to get a working copy) +pretag hook: t=a n=07f3376c1e655977439df2a814e3cc14b27abac2 l=0 +precommit hook: p1=07f3376c1e655977439df2a814e3cc14b27abac2 p2= +pretxncommit hook: n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 p1=07f3376c1e655977439df2a814e3cc14b27abac2 p2= +4:3cd2c6a5a36c commit hook b -commit hook: acb14030fe0a21b60322c440ad2d20cf7685a376 +commit hook: n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 p1=07f3376c1e655977439df2a814e3cc14b27abac2 p2= +tag hook: t=a n=07f3376c1e655977439df2a814e3cc14b27abac2 l=0 +pretag hook: t=la n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 l=1 +tag hook: t=la n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 l=1 +pretag hook: t=fa n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 l=0 +pretag.forbid hook +abort: pretag.forbid hook exited with status 1 +pretag hook: t=fla n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 l=1 +pretag.forbid hook +abort: pretag.forbid hook exited with status 1 +4:3cd2c6a5a36c +precommit hook: p1=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 p2= +pretxncommit.forbid hook: tip=5:469a61fe67d6 +abort: pretxncommit.forbid hook exited with status 1 +transaction abort! +rollback completed +4:3cd2c6a5a36c +precommit.forbid hook +abort: precommit.forbid hook exited with status 1 +4:3cd2c6a5a36c +3:07f3376c1e65 +prechangegroup.forbid hook +pulling from ../a +searching for changes +abort: prechangegroup.forbid hook exited with status 1 +pretxnchangegroup.forbid hook: tip=4:3cd2c6a5a36c +pulling from ../a +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files +abort: pretxnchangegroup.forbid hook exited with status 1 +transaction abort! +rollback completed +3:07f3376c1e65 +preoutgoing hook: s=pull +outgoing hook: n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 s=pull +pulling from ../a +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files +(run 'hg update' to get a working copy) +rolling back last transaction +preoutgoing hook: s=pull +preoutgoing.forbid hook +pulling from ../a +searching for changes +abort: preoutgoing.forbid hook exited with status 1 diff -r b08b87cecc37 -r a1e6e02e9d05 tests/test-ro-message --- a/tests/test-ro-message Sat Feb 18 22:01:09 2006 -0500 +++ b/tests/test-ro-message Sat Feb 18 22:24:42 2006 -0500 @@ -14,4 +14,4 @@ "$HG" commit -m 'Clarifying the vehicle.' "$HG" update -C 1 chmod a-w b/vehicle -"$HG" update -m 2 2>&1 | sed 's|^\(.*[ ]\)/tmp/[^/]*/\(.*\)$|\1\2|g' +"$HG" update -m 2 2>&1 | sed 's|^\(.*[ ]\).*/\([^/]*/[^/]*/[^/]*\)$|\1\2|g'