merge with crew.

This commit is contained in:
Vadim Gelfer 2006-05-11 08:48:52 -07:00
commit edc07498a2
14 changed files with 498 additions and 70 deletions

View File

@ -2,7 +2,25 @@ PREFIX=/usr/local
export PREFIX
PYTHON=python
all: local build doc
help:
@echo 'Commonly used make targets:'
@echo ' all - build program and documentation'
@echo ' install - install program and man pages to PREFIX ($(PREFIX))'
@echo ' install-home - install with setup.py install --home=HOME ($(HOME))'
@echo ' local - build C extensions for inplace usage'
@echo ' tests - run all tests in the automatic test suite'
@echo ' test-foo - run only specified tests (e.g. test-merge1)'
@echo ' dist - run all tests and create a source tarball in dist/'
@echo ' clean - remove files created by other targets'
@echo ' (except installed files or dist source tarball)'
@echo
@echo 'Example for a system-wide installation under /usr/local:'
@echo ' make all && su -c "make install" && hg version'
@echo
@echo 'Example for a local installation (usable in this directory):'
@echo ' make local && ./hg version'
all: build doc
local:
$(PYTHON) setup.py build_ext -i
@ -16,6 +34,7 @@ doc:
clean:
-$(PYTHON) setup.py clean --all # ignore errors of this command
find . -name '*.py[co]' -exec rm -f '{}' ';'
rm -f MANIFEST mercurial/__version__.py mercurial/*.so tests/*.err
$(MAKE) -C doc clean
install: all
@ -38,5 +57,5 @@ test-%:
cd tests && $(PYTHON) run-tests.py $@
.PHONY: all local build doc clean install install-home dist dist-notests tests
.PHONY: help all local build doc clean install install-home dist dist-notests tests

View File

@ -50,7 +50,7 @@ class bundlerevlog(revlog.revlog):
continue
for p in (p1, p2):
if not p in self.nodemap:
raise RevlogError(_("unknown parent %s") % short(p1))
raise revlog.RevlogError(_("unknown parent %s") % short(p1))
if linkmapper is None:
link = n
else:
@ -76,12 +76,12 @@ class bundlerevlog(revlog.revlog):
return False
return rev in self.basemap
def bundlebase(self, rev): return self.basemap[rev]
def chunk(self, rev, df=None):
def chunk(self, rev, df=None, cachelen=4096):
# Warning: in case of bundle, the diff is against bundlebase,
# not against rev - 1
# XXX: could use some caching
if not self.bundle(rev):
return revlog.revlog.chunk(self, rev)
return revlog.revlog.chunk(self, rev, df, cachelen)
self.bundlefile.seek(self.start(rev))
return self.bundlefile.read(self.length(rev))
@ -123,8 +123,8 @@ class bundlerevlog(revlog.revlog):
p1, p2 = self.parents(node)
if node != revlog.hash(text, p1, p2):
raise RevlogError(_("integrity check failed on %s:%d")
% (self.datafile, self.rev(node)))
raise revlog.RevlogError(_("integrity check failed on %s:%d")
% (self.datafile, self.rev(node)))
self.cache = (node, self.rev(node), text)
return text
@ -160,7 +160,6 @@ class bundlerepository(localrepo.localrepository):
def __init__(self, ui, path, bundlename):
localrepo.localrepository.__init__(self, ui, path)
f = open(bundlename, "rb")
s = util.fstat(f)
self.bundlefile = f
header = self.bundlefile.read(6)
if not header.startswith("HG"):

View File

@ -756,13 +756,20 @@ def archive(ui, repo, dest, **opts):
def backout(ui, repo, rev, **opts):
'''reverse effect of earlier changeset
Commit the backed out changes as a new changeset.
Commit the backed out changes as a new changeset. The new
changeset is a child of the backed out changeset.
If you back out a changeset other than the tip, a new head is
created. The --merge option remembers the parent of the working
directory before starting the backout, then merges the new head
with it afterwards, to save you from doing this by hand. The
result of this merge is not committed, as for a normal merge.'''
created. This head is the parent of the working directory. If
you back out an old changeset, your working directory will appear
old after the backout. You should merge the backout changeset
with another head.
The --merge option remembers the parent of the working directory
before starting the backout, then merges the new head with that
changeset afterwards. This saves you from doing the merge by
hand. The result of this merge is not committed, as for a normal
merge.'''
bail_if_changed(repo)
op1, op2 = repo.dirstate.parents()
@ -3021,7 +3028,7 @@ table = {
"recover": (recover, [], _('hg recover')),
"^remove|rm":
(remove,
[('', 'after', None, _('record remove that has already occurred')),
[('A', 'after', None, _('record remove that has already occurred')),
('f', 'force', None, _('remove file even if modified')),
('I', 'include', [], _('include names matching the given patterns')),
('X', 'exclude', [], _('exclude names matching the given patterns'))],
@ -3096,7 +3103,7 @@ table = {
[('u', 'update', None,
_('update the working directory to tip after unbundle'))],
_('hg unbundle [-u] FILE')),
"undo": (undo, [], _('hg undo')),
"debugundo|undo": (undo, [], _('hg undo')),
"^update|up|checkout|co":
(update,
[('b', 'branch', '', _('checkout the head of a specific branch')),

View File

@ -1544,8 +1544,9 @@ class localrepository(object):
" with %d changes to %d files%s\n")
% (changesets, revisions, files, heads))
self.hook('pretxnchangegroup', throw=True,
node=hex(self.changelog.node(cor+1)), source=srctype)
if changesets > 0:
self.hook('pretxnchangegroup', throw=True,
node=hex(self.changelog.node(cor+1)), source=srctype)
tr.close()

View File

@ -9,6 +9,15 @@ from demandload import demandload
import struct, bdiff, util, mpatch
demandload(globals(), "re")
def splitnewlines(text):
'''like str.splitlines, but only split on newlines.'''
lines = [l + '\n' for l in text.split('\n')]
if lines:
if lines[-1] == '\n':
lines.pop()
else:
lines[-1] = lines[-1][:-1]
return lines
def unidiff(a, ad, b, bd, fn, r=None, text=False,
showfunc=False, ignorews=False):
@ -19,7 +28,7 @@ def unidiff(a, ad, b, bd, fn, r=None, text=False,
if not text and (util.binary(a) or util.binary(b)):
l = ['Binary file %s has changed\n' % fn]
elif not a:
b = b.splitlines(1)
b = splitnewlines(b)
if a is None:
l1 = "--- %s\t%s\n" % ("/dev/null", epoch)
else:
@ -28,7 +37,7 @@ def unidiff(a, ad, b, bd, fn, r=None, text=False,
l3 = "@@ -0,0 +1,%d @@\n" % len(b)
l = [l1, l2, l3] + ["+" + e for e in b]
elif not b:
a = a.splitlines(1)
a = splitnewlines(a)
l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
if b is None:
l2 = "+++ %s\t%s\n" % ("/dev/null", epoch)
@ -37,8 +46,8 @@ def unidiff(a, ad, b, bd, fn, r=None, text=False,
l3 = "@@ -1,%d +0,0 @@\n" % len(a)
l = [l1, l2, l3] + ["-" + e for e in a]
else:
al = a.splitlines(1)
bl = b.splitlines(1)
al = splitnewlines(a)
bl = splitnewlines(b)
l = list(bunidiff(a, b, al, bl, "a/" + fn, "b/" + fn,
showfunc=showfunc, ignorews=ignorews))
if not l: return ""

View File

@ -87,6 +87,13 @@ class lazyparser(object):
"""
this class avoids the need to parse the entirety of large indices
"""
# lazyparser is not safe to use on windows if win32 extensions not
# available. it keeps file handle open, which make it not possible
# to break hardlinks on local cloned repos.
safe_to_use = os.name != 'nt' or (not util.is_win_9x() and
hasattr(util, 'win32api'))
def __init__(self, dataf, size, indexformat, shaoffset):
self.dataf = dataf
self.format = indexformat
@ -362,18 +369,14 @@ class revlog(object):
shaoffset = ngshaoffset
if i:
if not self.inlinedata() and st and st.st_size > 10000:
if (lazyparser.safe_to_use and not self.inlinedata() and
st and st.st_size > 10000):
# big index, let's parse it on demand
parser = lazyparser(f, st.st_size, self.indexformat, shaoffset)
self.index = lazyindex(parser)
self.nodemap = lazymap(parser)
else:
i = f.read()
self.parseindex(i)
if self.inlinedata():
# we've already got the entire data file read in, save it
# in the chunk data
self.chunkcache = (0, i)
self.parseindex(f, st)
if self.version != REVLOGV0:
e = list(self.index[0])
type = self.ngtype(e[0])
@ -384,22 +387,49 @@ class revlog(object):
self.index = []
def parseindex(self, data):
def parseindex(self, fp, st):
s = struct.calcsize(self.indexformat)
l = len(data)
self.index = []
self.nodemap = {nullid: -1}
inline = self.inlinedata()
off = 0
n = 0
while off < l:
e = struct.unpack(self.indexformat, data[off:off + s])
self.index.append(e)
self.nodemap[e[-1]] = n
n += 1
off += s
if inline:
off += e[1]
leftover = None
while True:
if st:
data = fp.read(65536)
else:
# hack for httprangereader, it doesn't do partial reads well
data = fp.read()
if not data:
break
if n == 0 and self.inlinedata():
# cache the first chunk
self.chunkcache = (0, data)
off = 0
l = len(data)
while off < l:
if l - off < s:
leftover = data[off:]
break
if leftover:
cur = leftover + data[off:off + s - len(leftover)]
off += s - len(leftover)
leftover = None
else:
cur = data[off:off + s]
off += s
e = struct.unpack(self.indexformat, cur)
self.index.append(e)
self.nodemap[e[-1]] = n
n += 1
if inline:
off += e[1]
if off > l:
# some things don't seek well, just read it
fp.read(off - l)
if not st:
break
def ngoffset(self, q):
if q & 0xFFFF:

View File

@ -489,6 +489,13 @@ def fstat(fp):
posixfile = file
def is_win_9x():
'''return true if run on windows 95, 98 or me.'''
try:
return sys.getwindowsversion()[3] == 1
except AttributeError:
return os.name == 'nt' and 'command' in os.environ.get('comspec', '')
# Platform specific variants
if os.name == 'nt':
demandload(globals(), "msvcrt")
@ -570,6 +577,8 @@ if os.name == 'nt':
try:
# override functions with win32 versions if possible
from util_win32 import *
if not is_win_9x():
posixfile = posixfile_nt
except ImportError:
pass

View File

@ -183,11 +183,11 @@ def system_rcpath_win32():
filename = win32process.GetModuleFileNameEx(proc, 0)
return [os.path.join(os.path.dirname(filename), 'mercurial.ini')]
class posixfile(object):
class posixfile_nt(object):
'''file object with posix-like semantics. on windows, normal
files can not be deleted or renamed if they are open. must open
with win32file.FILE_SHARE_DELETE. this flag does not exist on
windows <= nt.'''
windows < nt, so do not use this class there.'''
# tried to use win32file._open_osfhandle to pass fd to os.fdopen,
# but does not work at all. wrap win32 file api instead.
@ -220,6 +220,10 @@ class posixfile(object):
self.name = name
self.mode = mode
def __iter__(self):
for line in self.read().splitlines(True):
yield line
def read(self, count=-1):
try:
cs = cStringIO.StringIO()

View File

@ -34,10 +34,25 @@ def vlog(*msg):
print m,
print
def splitnewlines(text):
'''like str.splitlines, but only split on newlines.
keep line endings.'''
i = 0
lines = []
while True:
n = text.find('\n', i)
if n == -1:
last = text[i:]
if last:
lines.append(last)
return lines
lines.append(text[i:n+1])
i = n + 1
def show_diff(expected, output):
for line in difflib.unified_diff(expected, output,
"Expected output", "Test output", lineterm=''):
print line
sys.stdout.write(line)
def find_program(program):
"""Search PATH for a executable program"""
@ -125,7 +140,7 @@ def output_coverage():
vlog("# Running: "+cmd)
os.system(cmd)
def run(cmd, split_lines=True):
def run(cmd):
"""Run command in a sub-process, capturing the output (stdout and stderr).
Return the exist code, and output."""
# TODO: Use subprocess.Popen if we're running on Python 2.4
@ -141,9 +156,7 @@ def run(cmd, split_lines=True):
proc.tochild.close()
output = proc.fromchild.read()
ret = proc.wait()
if split_lines:
output = output.splitlines()
return ret, output
return ret, splitnewlines(output)
def run_one(test):
vlog("# Test", test)
@ -180,22 +193,23 @@ def run_one(test):
# If reference output file exists, check test output against it
if os.path.exists(ref):
f = open(ref, "r")
ref_out = f.read().splitlines()
ref_out = splitnewlines(f.read())
f.close()
if out != ref_out:
diffret = 1
print "\nERROR: %s output changed" % (test)
show_diff(ref_out, out)
else:
ref_out = ['']
if out != ref_out:
diffret = 1
print "\nERROR: %s output changed" % (test)
show_diff(ref_out, out)
if ret:
print "\nERROR: %s failed with error code %d" % (test, ret)
elif diffret:
ret = diffret
if ret != 0: # Save errors to a file for diagnosis
f = open(err, "w")
f = open(err, "wb")
for line in out:
f.write(line)
f.write("\n")
f.close()
os.chdir(TESTDIR)
@ -228,24 +242,28 @@ PYTHONDIR = os.path.join(INST, "lib", "python")
COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
try:
install_hg()
try:
install_hg()
tests = 0
failed = 0
tests = 0
failed = 0
if len(args) == 0:
args = os.listdir(".")
for test in args:
if test.startswith("test-"):
if '~' in test or re.search(r'\.(out|err)$', test):
continue
if not run_one(test):
failed += 1
tests += 1
if len(args) == 0:
args = os.listdir(".")
for test in args:
if test.startswith("test-"):
if '~' in test or re.search(r'\.(out|err)$', test):
continue
if not run_one(test):
failed += 1
tests += 1
print "\n# Ran %d tests, %d failed." % (tests, failed)
if coverage:
output_coverage()
print "\n# Ran %d tests, %d failed." % (tests, failed)
if coverage:
output_coverage()
except KeyboardInterrupt:
failed = True
print "\ninterrupted!"
finally:
cleanup_exit()

8
tests/test-diff-newlines Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
hg init
python -c 'print "confuse str.splitlines\nembedded\rnewline"' > a
hg ci -Ama -d '1 0'
echo clean diff >> a
hg ci -mb -d '2 0'
hg diff -r0 -r1

View File

@ -0,0 +1,8 @@
adding a
diff -r 107ba6f817b5 -r 310ce7989cdc a
--- a/a Thu Jan 01 00:00:01 1970 +0000
+++ b/a Thu Jan 01 00:00:02 1970 +0000
@@ -1,2 +1,3 @@ confuse str.splitlines
confuse str.splitlines
embedded newline
+clean diff

View File

@ -77,7 +77,6 @@ list of commands (use "hg help -v" to show aliases and global options):
tags list repository tags
tip show the tip revision
unbundle apply a changegroup file
undo undo the last commit or pull (DEPRECATED)
update update or merge working directory
verify verify the integrity of the repository
version output version and copyright information
@ -120,7 +119,6 @@ list of commands (use "hg help -v" to show aliases and global options):
tags list repository tags
tip show the tip revision
unbundle apply a changegroup file
undo undo the last commit or pull (DEPRECATED)
update update or merge working directory
verify verify the integrity of the repository
version output version and copyright information

46
tests/test-incoming-outgoing Executable file
View File

@ -0,0 +1,46 @@
#!/bin/sh
mkdir test
cd test
hg init
for i in 0 1 2 3 4 5 6 7 8; do
echo $i >> foo
hg commit -A -m $i -d "1000000 0"
done
hg verify
hg serve -p 20059 -d --pid-file=hg.pid
cd ..
hg init new
# http incoming
http_proxy= hg -R new incoming http://localhost:20059/
# local incoming
hg -R new incoming test
# test with --bundle
http_proxy= hg -R new incoming --bundle test.hg http://localhost:20059/
hg -R new incoming --bundle test2.hg test
# test the resulting bundles
hg init temp
hg init temp2
hg -R temp unbundle test.hg
hg -R temp2 unbundle test2.hg
hg -R temp tip
hg -R temp2 tip
rm -rf temp temp2 new
# test outgoing
hg clone test test-dev
cd test-dev
for i in 9 10 11 12 13; do
echo $i >> foo
hg commit -A -m $i -d "1000000 0"
done
hg verify
cd ..
hg -R test-dev outgoing test
http_proxy= hg -R test-dev outgoing http://localhost:20059/
kill `cat test/hg.pid`

View File

@ -0,0 +1,272 @@
adding foo
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
1 files, 9 changesets, 9 total revisions
changeset: 0:9cb21d99fe27
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 0
changeset: 1:d717f5dfad6a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 1
changeset: 2:c0d6b86da426
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 2
changeset: 3:dfacbd43b3fe
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 3
changeset: 4:1f3a964b6022
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 4
changeset: 5:c028bcc7a28a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 5
changeset: 6:a0c0095f3389
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 6
changeset: 7:d4be65f4e891
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 7
changeset: 8:92b83e334ef8
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 8
changeset: 0:9cb21d99fe27
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 0
changeset: 1:d717f5dfad6a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 1
changeset: 2:c0d6b86da426
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 2
changeset: 3:dfacbd43b3fe
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 3
changeset: 4:1f3a964b6022
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 4
changeset: 5:c028bcc7a28a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 5
changeset: 6:a0c0095f3389
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 6
changeset: 7:d4be65f4e891
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 7
changeset: 8:92b83e334ef8
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 8
changeset: 0:9cb21d99fe27
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 0
changeset: 1:d717f5dfad6a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 1
changeset: 2:c0d6b86da426
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 2
changeset: 3:dfacbd43b3fe
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 3
changeset: 4:1f3a964b6022
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 4
changeset: 5:c028bcc7a28a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 5
changeset: 6:a0c0095f3389
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 6
changeset: 7:d4be65f4e891
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 7
changeset: 8:92b83e334ef8
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 8
changeset: 0:9cb21d99fe27
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 0
changeset: 1:d717f5dfad6a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 1
changeset: 2:c0d6b86da426
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 2
changeset: 3:dfacbd43b3fe
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 3
changeset: 4:1f3a964b6022
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 4
changeset: 5:c028bcc7a28a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 5
changeset: 6:a0c0095f3389
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 6
changeset: 7:d4be65f4e891
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 7
changeset: 8:92b83e334ef8
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 8
adding changesets
adding manifests
adding file changes
added 9 changesets with 9 changes to 1 files
(run 'hg update' to get a working copy)
adding changesets
adding manifests
adding file changes
added 9 changesets with 9 changes to 1 files
(run 'hg update' to get a working copy)
changeset: 8:92b83e334ef8
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 8
changeset: 8:92b83e334ef8
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 8
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
1 files, 14 changesets, 14 total revisions
searching for changes
changeset: 9:3741c3ad1096
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 9
changeset: 10:de4143c8d9a5
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 10
changeset: 11:0e1c188b9a7a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 11
changeset: 12:251354d0fdd3
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 12
changeset: 13:bdaadd969642
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 13
searching for changes
changeset: 9:3741c3ad1096
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 9
changeset: 10:de4143c8d9a5
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 10
changeset: 11:0e1c188b9a7a
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 11
changeset: 12:251354d0fdd3
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 12
changeset: 13:bdaadd969642
tag: tip
user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 13