--- 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
--- 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)
--- 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
--- 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:
--- 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
--- 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
--- 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)
--- 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')
--- 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 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
-<link rel="icon" href="#staticurl#hgicon.png" type="image/png">
+<link rel="icon" href="#staticurl#hgicon.png" type="image/png" />
<meta name="robots" content="index, nofollow" />
<link rel="stylesheet" href="#staticurl#style.css" type="text/css" />
--- 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 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
-<link rel="icon" href="?static=hgicon.png" type="image/png">
+<link rel="icon" href="?static=hgicon.png" type="image/png" />
<meta name="robots" content="index, nofollow" />
<link rel="stylesheet" href="?static=style.css" type="text/css" />
--- 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
Binary file tests/test-hgweb-commands.out has changed
--- 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 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
-<link rel="icon" href="/static/hgicon.png" type="image/png">
+<link rel="icon" href="/static/hgicon.png" type="image/png" />
<meta name="robots" content="index, nofollow" />
<link rel="stylesheet" href="/static/style.css" type="text/css" />
--- 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
--- 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
--- 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 <<EOF
[diff]
git = True
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mq-safety Sun Feb 03 21:47:07 2008 -0200
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+echo '[extensions]' >> $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'
--- /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
--- 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
--- 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
--- 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
--- 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 <<EOF > 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
--- 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