##// END OF EJS Templates
actually port simplemerge to hg...
actually port simplemerge to hg - use bdiff instead of patiencediff; this is a larger change, since bdiff works on 2 multi-line strings, while patiencediff works on 2 lists; - rename the main class from Merge3 to Merge3Text and add a Merge3 class that derives from Merge3Text. This new Merge3 class has the same interface from the original class, so that the tests still work; - Merge3 uses util.binary to detect binary data and raises util.Abort instead of a specific exception; - don't use the @decorator syntax, to keep python2.3 compatibility; - the test uses unittest, which likes to print how long it took to run. This obviously doesn't play too well with hg's test suite, so we override time.time to fool unittest; - one test has a different (but still valid) output because of the different diff algorithm used; - the TestCase class used by bzr has some extras to help debugging. test-merge3.py used 2 of them: - log method to log some data - assertEqualDiff method to ease viewing diffs of diffs We add a dummy log method and use regular assertEquals instead of assertEqualDiff. - make simplemerge executable and add "#!/usr/bin/env python" header

File last commit:

r4270:29eb88bd default
r4363:2e3c54fb default
Show More
hg-relink
128 lines | 3.5 KiB | text/plain | TextLexer
Brendan Cully
Add hg-relink script to contrib
r4249 #!/usr/bin/env python
#
# Copyright (C) 2007 Brendan Cully <brendan@kublai.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
import os, sys
class ConfigError(Exception): pass
def usage():
print """relink <source> <destination>
Recreate hard links between source and destination repositories"""
class Config:
def __init__(self, args):
if len(args) != 3:
raise ConfigError("wrong number of arguments")
self.src = os.path.abspath(args[1])
self.dst = os.path.abspath(args[2])
for d in (self.src, self.dst):
if not os.path.exists(os.path.join(d, '.hg')):
raise ConfigError("%s: not a mercurial repository" % d)
def collect(src):
seplen = len(os.path.sep)
candidates = []
for dirpath, dirnames, filenames in os.walk(src):
relpath = dirpath[len(src) + seplen:]
for filename in filenames:
Brendan Cully
hg-relink: do not compare .d files
r4270 if not filename.endswith('.i'):
Brendan Cully
Add hg-relink script to contrib
r4249 continue
st = os.stat(os.path.join(dirpath, filename))
candidates.append((os.path.join(relpath, filename), st))
return candidates
def prune(candidates, dst):
Brendan Cully
hg-relink: do not compare .d files
r4270 def getdatafile(path):
if not path.endswith('.i'):
return None, None
df = path[:-1] + 'd'
try:
st = os.stat(df)
except OSError:
return None, None
return df, st
def linkfilter(dst, st):
try:
ts = os.stat(dst)
except OSError:
# Destination doesn't have this file?
return False
if st.st_ino == ts.st_ino:
return False
if st.st_dev != ts.st_dev:
# No point in continuing
raise Exception('Source and destination are on different devices')
if st.st_size != ts.st_size:
# TODO: compare revlog heads
return False
return st
Brendan Cully
Add hg-relink script to contrib
r4249 targets = []
for fn, st in candidates:
tgt = os.path.join(dst, fn)
Brendan Cully
hg-relink: do not compare .d files
r4270 ts = linkfilter(tgt, st)
if not ts:
Brendan Cully
Add hg-relink script to contrib
r4249 continue
targets.append((fn, ts.st_size))
Brendan Cully
hg-relink: do not compare .d files
r4270 df, ts = getdatafile(tgt)
if df:
targets.append((fn[:-1] + 'd', ts.st_size))
Brendan Cully
Add hg-relink script to contrib
r4249
return targets
def relink(src, dst, files):
Brendan Cully
hg-relink: do not compare .d files
r4270 def relinkfile(src, dst):
bak = dst + '.bak'
os.rename(dst, bak)
try:
os.link(src, dst)
except OSError:
os.rename(bak, dst)
raise
os.remove(bak)
Brendan Cully
Add hg-relink script to contrib
r4249 CHUNKLEN = 65536
relinked = 0
savedbytes = 0
for f, sz in files:
source = os.path.join(src, f)
tgt = os.path.join(dst, f)
sfp = file(source)
dfp = file(tgt)
sin = sfp.read(CHUNKLEN)
while sin:
din = dfp.read(CHUNKLEN)
if sin != din:
break
sin = sfp.read(CHUNKLEN)
if sin:
continue
try:
Brendan Cully
hg-relink: do not compare .d files
r4270 relinkfile(source, tgt)
Brendan Cully
Add hg-relink script to contrib
r4249 print 'Relinked %s' % f
relinked += 1
savedbytes += sz
except OSError, inst:
print '%s: %s' % (tgt, str(inst))
print 'Relinked %d files (%d bytes reclaimed)' % (relinked, savedbytes)
Brendan Cully
hg-relink: do not compare .d files
r4270 try:
cfg = Config(sys.argv)
except ConfigError, inst:
print str(inst)
usage()
sys.exit(1)
Brendan Cully
Add hg-relink script to contrib
r4249 src = os.path.join(cfg.src, '.hg')
dst = os.path.join(cfg.dst, '.hg')
candidates = collect(src)
targets = prune(candidates, dst)
relink(src, dst, targets)