# HG changeset patch # User Alexis S. L. Carvalho # Date 1202082427 7200 # Node ID 30d2fecaab7634c0185fd951bf72d7ad7eb6401d # Parent 8e7d64989bb8ecc9609e1272a411397f523e66a9# Parent ee317dbfb9d0b1247ab6f882e530a8d8dc320413 merge with crew-stable diff -r 8e7d64989bb8 -r 30d2fecaab76 hgext/convert/common.py --- a/hgext/convert/common.py Sat Feb 02 21:01:43 2008 +0100 +++ b/hgext/convert/common.py Sun Feb 03 21:47:07 2008 -0200 @@ -30,8 +30,8 @@ class commit(object): def __init__(self, author, date, desc, parents, branch=None, rev=None, extra={}): - self.author = author - self.date = date + self.author = author or 'unknown' + self.date = date or '0 0' self.desc = desc self.parents = parents self.branch = branch diff -r 8e7d64989bb8 -r 30d2fecaab76 hgext/convert/git.py --- a/hgext/convert/git.py Sat Feb 02 21:01:43 2008 +0100 +++ b/hgext/convert/git.py Sun Feb 03 21:47:07 2008 -0200 @@ -102,7 +102,6 @@ tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:] tz = -int(tzs) * (int(tzh) * 3600 + int(tzm)) date = tm + " " + str(tz) - author = author or "unknown" c = commit(parents=parents, date=date, author=author, desc=message, rev=version) diff -r 8e7d64989bb8 -r 30d2fecaab76 hgext/mq.py --- a/hgext/mq.py Sat Feb 02 21:01:43 2008 +0100 +++ b/hgext/mq.py Sun Feb 03 21:47:07 2008 -0200 @@ -600,11 +600,19 @@ raise util.Abort(_("local changes found")) return m, a, r, d + _reserved = ('series', 'status', 'guards') + def check_reserved_name(self, name): + if (name in self._reserved or name.startswith('.hg') + or name.startswith('.mq')): + raise util.Abort(_('"%s" cannot be used as the name of a patch') + % name) + def new(self, repo, patch, *pats, **opts): msg = opts.get('msg') force = opts.get('force') user = opts.get('user') date = opts.get('date') + self.check_reserved_name(patch) if os.path.exists(self.join(patch)): raise util.Abort(_('patch "%s" already exists') % patch) if opts.get('include') or opts.get('exclude') or pats: @@ -872,10 +880,16 @@ start = info[0] rev = revlog.bin(info[1]) + if update: + top = self.check_toppatch(repo) + + if repo.changelog.heads(rev) != [revlog.bin(self.applied[-1].rev)]: + raise util.Abort("popping would remove a revision not " + "managed by this patch queue") + # we know there are no local changes, so we can make a simplified # form of hg.update. if update: - top = self.check_toppatch(repo) qp = self.qparents(repo, rev) changes = repo.changelog.read(qp) mmap = repo.manifest.read(changes[0]) @@ -898,8 +912,8 @@ except: pass repo.dirstate.forget(f) repo.dirstate.setparents(qp, revlog.nullid) + del self.applied[start:end] self.strip(repo, rev, update=False, backup='strip') - del self.applied[start:end] if len(self.applied): self.ui.write("Now at: %s\n" % self.applied[-1].name) else: @@ -926,6 +940,8 @@ self.check_toppatch(repo) (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name) top = revlog.bin(top) + if repo.changelog.heads(top) != [top]: + raise util.Abort("cannot refresh a revision with children") cparents = repo.changelog.parents(top) patchparent = self.qparents(repo, top) message, comments, user, date, patchfound = self.readheaders(patchfn) @@ -1112,12 +1128,13 @@ if not user: user = changes[1] + self.applied.pop() + self.applied_dirty = 1 self.strip(repo, top, update=False, backup='strip') n = repo.commit(filelist, message, user, date, match=matchfn, force=1) - self.applied[-1] = statusentry(revlog.hex(n), patchfn) - self.applied_dirty = 1 + self.applied.append(statusentry(revlog.hex(n), patchfn)) self.removeundo(repo) else: self.printdiff(repo, patchparent, fp=patchf) @@ -1406,6 +1423,7 @@ if not patchname: patchname = normname('%d.diff' % r) + self.check_reserved_name(patchname) checkseries(patchname) checkfile(patchname) self.full_series.insert(0, patchname) @@ -1428,6 +1446,7 @@ raise util.Abort(_('-e is incompatible with import from -')) if not patchname: patchname = normname(filename) + self.check_reserved_name(patchname) if not os.path.isfile(self.join(patchname)): raise util.Abort(_("patch %s does not exist") % patchname) else: @@ -1442,6 +1461,7 @@ raise util.Abort(_("unable to read %s") % patchname) if not patchname: patchname = normname(os.path.basename(filename)) + self.check_reserved_name(patchname) checkfile(patchname) patchf = self.opener(patchname, "w") patchf.write(text) @@ -2147,6 +2167,12 @@ return tagscache mqtags = [(revlog.bin(patch.rev), patch.name) for patch in q.applied] + + if mqtags[-1][0] not in self.changelog.nodemap: + self.ui.warn('mq status file refers to unknown node %s\n' + % revlog.short(mqtags[-1][0])) + return tagscache + mqtags.append((mqtags[-1][0], 'qtip')) mqtags.append((mqtags[0][0], 'qbase')) mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent')) @@ -2163,11 +2189,17 @@ if not q.applied: return super(mqrepo, self)._branchtags() + cl = self.changelog + qbasenode = revlog.bin(q.applied[0].rev) + if qbasenode not in cl.nodemap: + self.ui.warn('mq status file refers to unknown node %s\n' + % revlog.short(qbasenode)) + return super(mqrepo, self)._branchtags() + self.branchcache = {} # avoid recursion in changectx - cl = self.changelog partial, last, lrev = self._readbranchcache() - qbase = cl.rev(revlog.bin(q.applied[0].rev)) + qbase = cl.rev(qbasenode) start = lrev + 1 if start < qbase: # update the cache (excluding the patches) and save it diff -r 8e7d64989bb8 -r 30d2fecaab76 mercurial/commands.py --- a/mercurial/commands.py Sat Feb 02 21:01:43 2008 +0100 +++ b/mercurial/commands.py Sun Feb 03 21:47:07 2008 -0200 @@ -1540,6 +1540,9 @@ repo.rollback() raise util.Abort(_('patch is damaged' ' or loses information')) + # Force a dirstate write so that the next transaction + # backups an up-do-date file. + repo.dirstate.write() finally: os.unlink(tmpname) finally: diff -r 8e7d64989bb8 -r 30d2fecaab76 mercurial/httprepo.py --- a/mercurial/httprepo.py Sat Feb 02 21:01:43 2008 +0100 +++ b/mercurial/httprepo.py Sun Feb 03 21:47:07 2008 -0200 @@ -103,10 +103,13 @@ # must be able to send big bundle as stream. send = _gen_sendfile(keepalive.HTTPConnection) -class basehttphandler(keepalive.HTTPHandler): +class httphandler(keepalive.HTTPHandler): def http_open(self, req): return self.do_open(httpconnection, req) + def __del__(self): + self.close_all() + has_https = hasattr(urllib2, 'HTTPSHandler') if has_https: class httpsconnection(httplib.HTTPSConnection): @@ -114,12 +117,9 @@ # must be able to send big bundle as stream. send = _gen_sendfile(httplib.HTTPSConnection) - class httphandler(basehttphandler, urllib2.HTTPSHandler): + class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler): def https_open(self, req): return self.do_open(httpsconnection, req) -else: - class httphandler(basehttphandler): - pass # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if # it doesn't know about the auth type requested. This can happen if @@ -203,8 +203,9 @@ proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy') # XXX proxyauthinfo = None - self.handler = httphandler() - handlers = [self.handler] + handlers = [httphandler()] + if has_https: + handlers.append(httpshandler()) if proxyurl: # proxy can be proper url or host[:port] @@ -270,11 +271,6 @@ opener.addheaders = [('User-agent', 'mercurial/proto-1.0')] urllib2.install_opener(opener) - def __del__(self): - if self.handler: - self.handler.close_all() - self.handler = None - def url(self): return self.path diff -r 8e7d64989bb8 -r 30d2fecaab76 mercurial/keepalive.py --- a/mercurial/keepalive.py Sat Feb 02 21:01:43 2008 +0100 +++ b/mercurial/keepalive.py Sun Feb 03 21:47:07 2008 -0200 @@ -175,7 +175,7 @@ else: return dict(self._hostmap) -class HTTPHandler(urllib2.HTTPHandler): +class KeepAliveHandler: def __init__(self): self._cm = ConnectionManager() @@ -314,6 +314,9 @@ except socket.error, err: # XXX what error? raise urllib2.URLError(err) +class HTTPHandler(KeepAliveHandler, urllib2.HTTPHandler): + pass + class HTTPResponse(httplib.HTTPResponse): # we need to subclass HTTPResponse in order to # 1) add readline() and readlines() methods diff -r 8e7d64989bb8 -r 30d2fecaab76 mercurial/localrepo.py --- a/mercurial/localrepo.py Sat Feb 02 21:01:43 2008 +0100 +++ b/mercurial/localrepo.py Sun Feb 03 21:47:07 2008 -0200 @@ -120,6 +120,7 @@ self.hook('pretag', throw=True, node=hex(node), tag=name, local=local) def writetag(fp, name, munge, prevtags): + fp.seek(0, 2) if prevtags and prevtags[-1] != '\n': fp.write('\n') fp.write('%s %s\n' % (hex(node), munge and munge(name) or name)) @@ -1981,6 +1982,10 @@ del tr if changesets > 0: + # forcefully update the on-disk branch cache + self.ui.debug(_("updating the branch cache\n")) + self.branchcache = None + self.branchtags() self.hook("changegroup", node=hex(self.changelog.node(cor+1)), source=srctype, url=url) diff -r 8e7d64989bb8 -r 30d2fecaab76 mercurial/sshrepo.py --- a/mercurial/sshrepo.py Sat Feb 02 21:01:43 2008 +0100 +++ b/mercurial/sshrepo.py Sun Feb 03 21:47:07 2008 -0200 @@ -114,14 +114,25 @@ return self.pipei def call(self, cmd, **args): - r = self.do_cmd(cmd, **args) - l = r.readline() + self.do_cmd(cmd, **args) + return self._recv() + + def _recv(self): + l = self.pipei.readline() self.readerr() try: l = int(l) except: self.raise_(util.UnexpectedOutput(_("unexpected response:"), l)) - return r.read(l) + return self.pipei.read(l) + + def _send(self, data, flush=False): + self.pipeo.write("%d\n" % len(data)) + if data: + self.pipeo.write(data) + if flush: + self.pipeo.flush() + self.readerr() def lock(self): self.call("lock") @@ -182,25 +193,22 @@ while 1: d = cg.read(4096) - if not d: break - self.pipeo.write(str(len(d)) + '\n') - self.pipeo.write(d) - self.readerr() + if not d: + break + self._send(d) - self.pipeo.write('0\n') - self.pipeo.flush() + self._send("", flush=True) - self.readerr() - l = int(self.pipei.readline()) - r = self.pipei.read(l) + r = self._recv() if r: # remote may send "unsynced changes" self.raise_(repo.RepoError(_("push failed: %s") % r)) - self.readerr() - l = int(self.pipei.readline()) - r = self.pipei.read(l) - return int(r) + r = self._recv() + try: + return int(r) + except: + self.raise_(util.UnexpectedOutput(_("unexpected response:"), r)) def addchangegroup(self, cg, source, url): d = self.call("addchangegroup") @@ -208,18 +216,21 @@ self.raise_(repo.RepoError(_("push refused: %s") % d)) while 1: d = cg.read(4096) - if not d: break + if not d: + break self.pipeo.write(d) self.readerr() self.pipeo.flush() self.readerr() - l = int(self.pipei.readline()) - r = self.pipei.read(l) + r = self._recv() if not r: return 1 - return int(r) + try: + return int(r) + except: + self.raise_(util.UnexpectedOutput(_("unexpected response:"), r)) def stream_out(self): return self.do_cmd('stream_out') diff -r 8e7d64989bb8 -r 30d2fecaab76 templates/header.tmpl --- a/templates/header.tmpl Sat Feb 02 21:01:43 2008 +0100 +++ b/templates/header.tmpl Sun Feb 03 21:47:07 2008 -0200 @@ -1,6 +1,6 @@ - + diff -r 8e7d64989bb8 -r 30d2fecaab76 templates/old/header.tmpl --- a/templates/old/header.tmpl Sat Feb 02 21:01:43 2008 +0100 +++ b/templates/old/header.tmpl Sun Feb 03 21:47:07 2008 -0200 @@ -1,6 +1,6 @@ - + diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-acl.out --- a/tests/test-acl.out Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-acl.out Sun Feb 03 21:47:07 2008 -0200 @@ -28,6 +28,7 @@ adding foo/file.txt revisions adding quux/file.py revisions added 3 changesets with 3 changes to 3 files +updating the branch cache rolling back last transaction 0:6675d58eff77 @@ -59,6 +60,7 @@ acl: acl.allow not enabled acl: acl.deny not enabled acl: changes have source "push" - skipping +updating the branch cache rolling back last transaction 0:6675d58eff77 @@ -94,6 +96,7 @@ acl: allowing changeset ef1ea85a6374 acl: allowing changeset f9cafe1212c8 acl: allowing changeset 911600dab2ae +updating the branch cache rolling back last transaction 0:6675d58eff77 @@ -383,6 +386,7 @@ acl: allowing changeset ef1ea85a6374 acl: allowing changeset f9cafe1212c8 acl: allowing changeset 911600dab2ae +updating the branch cache rolling back last transaction 0:6675d58eff77 @@ -578,6 +582,7 @@ acl: allowing changeset ef1ea85a6374 acl: allowing changeset f9cafe1212c8 acl: allowing changeset 911600dab2ae +updating the branch cache rolling back last transaction 0:6675d58eff77 diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-hgweb-commands.out Binary file tests/test-hgweb-commands.out has changed diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-hgweb.out --- a/tests/test-hgweb.out Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-hgweb.out Sun Feb 03 21:47:07 2008 -0200 @@ -24,7 +24,7 @@ - + diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-import --- a/tests/test-import Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-import Sun Feb 03 21:47:07 2008 -0200 @@ -125,6 +125,18 @@ hg --cwd b tip --template '{desc}\n' rm -r b +# We weren't backing up the correct dirstate file when importing many patches +# (issue963) +echo '% import patch1 patch2; rollback' +echo line 3 >> a/a +hg --cwd a ci -m'third change' +hg --cwd a export -o '../patch%R' 1 2 +hg clone -qr0 a b +hg --cwd b parents --template 'parent: #rev#\n' +hg --cwd b import ../patch1 ../patch2 +hg --cwd b rollback +hg --cwd b parents --template 'parent: #rev#\n' +rm -r b # bug non regression test # importing a patch in a subdirectory failed at the commit stage diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-import.out --- a/tests/test-import.out Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-import.out Sun Feb 03 21:47:07 2008 -0200 @@ -152,6 +152,12 @@ next line --- +% import patch1 patch2; rollback +parent: 0 +applying ../patch1 +applying ../patch2 +rolling back last transaction +parent: 1 % hg import in a subdirectory requesting all changes adding changesets diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-mq --- a/tests/test-mq Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-mq Sun Feb 03 21:47:07 2008 -0200 @@ -42,6 +42,12 @@ hg --cwd c qinit -c hg -R c/.hg/patches st +echo % qnew should refuse bad patch names +hg -R c qnew series +hg -R c qnew status +hg -R c qnew guards +hg -R c qnew .hgignore + echo % qnew implies add hg -R c qnew test.patch @@ -297,6 +303,13 @@ echo % mq tags hg log --template '{rev} {tags}\n' -r qparent:qtip +echo % bad node in status +hg qpop +hg strip -qn tip +hg tip 2>&1 | sed -e 's/unknown node .*/unknown node/' +hg branches 2>&1 | sed -e 's/unknown node .*/unknown node/' +hg qpop + cat >>$HGRCPATH <> $HGRCPATH +echo 'hgext.mq =' >> $HGRCPATH + +hg init repo +cd repo + +echo foo > foo +hg ci -qAm 'add a file' + +hg qinit + +hg qnew foo +echo foo >> foo +hg qrefresh -m 'append foo' + +hg qnew bar +echo bar >> foo +hg qrefresh -m 'append bar' + +echo '% try to commit on top of a patch' +echo quux >> foo +hg ci -m 'append quux' + +# cheat a bit... +mv .hg/patches .hg/patches2 +hg ci -m 'append quux' +mv .hg/patches2 .hg/patches + +echo '% qpop/qrefresh on the wrong revision' +hg qpop +hg qpop -n patches 2>&1 | sed -e 's/\(using patch queue:\).*/\1/' +hg qrefresh + +hg up -C qtip +echo '% qpop' +hg qpop + +echo '% qrefresh' +hg qrefresh + +echo '% tip:' +hg tip --template '#rev# #desc#\n' diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-mq-safety.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-mq-safety.out Sun Feb 03 21:47:07 2008 -0200 @@ -0,0 +1,14 @@ +% try to commit on top of a patch +abort: cannot commit over an applied mq patch +% qpop/qrefresh on the wrong revision +abort: working directory revision is not qtip +using patch queue: +abort: popping would remove a revision not managed by this patch queue +abort: working directory revision is not qtip +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% qpop +abort: popping would remove a revision not managed by this patch queue +% qrefresh +abort: cannot refresh a revision with children +% tip: +3 append quux diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-mq.out --- a/tests/test-mq.out Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-mq.out Sun Feb 03 21:47:07 2008 -0200 @@ -59,6 +59,11 @@ % qinit -c A .hgignore A series +% qnew should refuse bad patch names +abort: "series" cannot be used as the name of a patch +abort: "status" cannot be used as the name of a patch +abort: "guards" cannot be used as the name of a patch +abort: ".hgignore" cannot be used as the name of a patch % qnew implies add A .hgignore A series @@ -281,6 +286,18 @@ 0 qparent 1 qbase foo 2 qtip bar tip +% bad node in status +Now at: foo +changeset: 0:cb9a9f314b8b +mq status file refers to unknown node +tag: tip +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: a + +mq status file refers to unknown node +default 0:cb9a9f314b8b +abort: working directory revision is not qtip new file diff --git a/new b/new diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-newbranch --- a/tests/test-newbranch Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-newbranch Sun Feb 03 21:47:07 2008 -0200 @@ -41,6 +41,15 @@ hg log -qr foo cat .hg/branch.cache +echo % push should update the branch cache +hg init ../target +echo % pushing just rev 0 +hg push -qr 0 ../target +cat ../target/.hg/branch.cache +echo % pushing everything +hg push -qf ../target +cat ../target/.hg/branch.cache + echo % update with no arguments: tipmost revision of the current branch hg up -q -C 0 hg up -q diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-newbranch.out --- a/tests/test-newbranch.out Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-newbranch.out Sun Feb 03 21:47:07 2008 -0200 @@ -83,6 +83,15 @@ bf1bc2f45e834c75404d0ddab57d53beab56e2f8 default 4909a3732169c0c20011c4f4b8fdff4e3d89b23f foo 67ec16bde7f1575d523313b9bca000f6a6f12dca bar +% push should update the branch cache +% pushing just rev 0 +be8523e69bf892e25817fc97187516b3c0804ae4 0 +be8523e69bf892e25817fc97187516b3c0804ae4 default +% pushing everything +4909a3732169c0c20011c4f4b8fdff4e3d89b23f 4 +bf1bc2f45e834c75404d0ddab57d53beab56e2f8 default +4909a3732169c0c20011c4f4b8fdff4e3d89b23f foo +67ec16bde7f1575d523313b9bca000f6a6f12dca bar % update with no arguments: tipmost revision of the current branch bf1bc2f45e83 4909a3732169 (foo) tip diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-ssh --- a/tests/test-ssh Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-ssh Sun Feb 03 21:47:07 2008 -0200 @@ -27,6 +27,11 @@ sys.exit(bool(r)) EOF +cat < badhook +import sys +sys.stdout.write("KABOOM") +EOF + echo "# creating 'remote'" hg init remote cd remote @@ -91,13 +96,16 @@ echo z > z hg ci -A -m z -d '1000001 0' z +# a bad, evil hook that prints to stdout +echo 'changegroup.stdout = python ../badhook' >> .hg/hgrc cd ../local echo r > r hg ci -A -m z -d '1000002 0' r -echo "# push should succeed" +echo "# push should succeed even though it has an unexpected response" hg push +hg -R ../remote heads cd .. cat dummylog diff -r 8e7d64989bb8 -r 30d2fecaab76 tests/test-ssh.out --- a/tests/test-ssh.out Sat Feb 02 21:01:43 2008 +0100 +++ b/tests/test-ssh.out Sun Feb 03 21:47:07 2008 -0200 @@ -70,7 +70,7 @@ checking files 2 files, 2 changesets, 3 total revisions bleah -# push should succeed +# push should succeed even though it has an unexpected response pushing to ssh://user@dummy/remote searching for changes note: unsynced remote changes! @@ -78,6 +78,21 @@ remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files +abort: unexpected response: +'KABOOM1\n' +changeset: 3:ac7448082955 +tag: tip +parent: 1:572896fe480d +user: test +date: Mon Jan 12 13:46:42 1970 +0000 +summary: z + +changeset: 2:187c6caa0d1e +parent: 0:e34318c26897 +user: test +date: Mon Jan 12 13:46:41 1970 +0000 +summary: z + Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio Got arguments 1:user@dummy 2:hg -R remote serve --stdio Got arguments 1:user@dummy 2:hg -R remote serve --stdio