Mercurial > hg
diff contrib/hg-relink @ 4270:29eb88bd5c8d
hg-relink: do not compare .d files
author | Brendan Cully <brendan@kublai.com> |
---|---|
date | Fri, 23 Mar 2007 14:11:31 -0700 |
parents | 7663780b55a7 |
children | 46293a0c7e9f |
line wrap: on
line diff
--- a/contrib/hg-relink Wed Mar 21 14:06:25 2007 -0700 +++ b/contrib/hg-relink Fri Mar 23 14:11:31 2007 -0700 @@ -23,20 +23,13 @@ if not os.path.exists(os.path.join(d, '.hg')): raise ConfigError("%s: not a mercurial repository" % d) -try: - cfg = Config(sys.argv) -except ConfigError, inst: - print str(inst) - usage() - sys.exit(1) - 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: - if not (filename.endswith('.i') or filename.endswith('.d')): + if not filename.endswith('.i'): continue st = os.stat(os.path.join(dirpath, filename)) candidates.append((os.path.join(relpath, filename), st)) @@ -44,25 +37,56 @@ return candidates def prune(candidates, dst): + 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 + targets = [] for fn, st in candidates: tgt = os.path.join(dst, fn) - try: - ts = os.stat(tgt) - except OSError: - # Destination doesn't have this file? - continue - if st.st_ino == ts.st_ino: - continue - if st.st_dev != ts.st_dev: - raise Exception('Source and destination are on different devices') - if st.st_size != ts.st_size: + ts = linkfilter(tgt, st) + if not ts: continue targets.append((fn, ts.st_size)) + df, ts = getdatafile(tgt) + if df: + targets.append((fn[:-1] + 'd', ts.st_size)) return targets def relink(src, dst, files): + 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) + CHUNKLEN = 65536 relinked = 0 savedbytes = 0 @@ -81,21 +105,22 @@ if sin: continue try: - os.rename(tgt, tgt + '.bak') - try: - os.link(source, tgt) - except OSError: - os.rename(tgt + '.bak', tgt) - raise + relinkfile(source, tgt) print 'Relinked %s' % f relinked += 1 savedbytes += sz - os.remove(tgt + '.bak') except OSError, inst: print '%s: %s' % (tgt, str(inst)) print 'Relinked %d files (%d bytes reclaimed)' % (relinked, savedbytes) +try: + cfg = Config(sys.argv) +except ConfigError, inst: + print str(inst) + usage() + sys.exit(1) + src = os.path.join(cfg.src, '.hg') dst = os.path.join(cfg.dst, '.hg') candidates = collect(src)