##// END OF EJS Templates
[PATCH] hgk should parse dates in the diff output...
[PATCH] hgk should parse dates in the diff output -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 [PATCH] hgk should parse dates in the diff output hgk doesn't deal well with the difflib style diffs, it expects the filename to be the last thing on the line. This patch fixes the regexp to stop reading the filename at the first tab. Signed-off-by: Chris Mason <mason@suse.com> manifest hash: 9c5bcf427455dcf306ab6f91b1986723caa83f36 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCpl/HywK+sNU5EO8RAgAjAKCOuZsRtJDbdurTQry+7krtLTtRQQCfXLuN LZEFkcOGS0jiAC6vci/RLJ0= =jkr1 -----END PGP SIGNATURE-----

File last commit:

r273:4f817438 default
r274:5da941ef default
Show More
hg.py
1190 lines | 37.4 KiB | text/x-python | PythonLexer
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 # hg.py - repository classes for mercurial
#
# Copyright 2005 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
mpm@selenic.com
import and startup cleanups...
r249 import sys, struct, os
mpm@selenic.com
implement demand loading hack...
r262 from revlog import *
from demandload import *
demandload(globals(), "re lock urllib urllib2 transaction time socket")
demandload(globals(), "tempfile byterange difflib")
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
class filelog(revlog):
def __init__(self, opener, path):
mpm@selenic.com
Fix transaction handling bug by reverting fileopener change
r144 revlog.__init__(self, opener,
os.path.join("data", path + ".i"),
os.path.join("data", path + ".d"))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def read(self, node):
return self.revision(node)
def add(self, text, transaction, link, p1=None, p2=None):
return self.addrevision(text, transaction, link, p1, p2)
mpm@selenic.com
Add basic annotation support...
r79 def annotate(self, node):
mpm@selenic.com
annotate: deal with merges...
r199
def decorate(text, rev):
return [(rev, l) for l in text.splitlines(1)]
def strip(annotation):
return [e[1] for e in annotation]
def pair(parent, child):
mpm@selenic.com
Annotate was being too clever trying to work in place, and triggering...
r109 new = []
mpm@selenic.com
implement demand loading hack...
r262 sm = difflib.SequenceMatcher(None, strip(parent), strip(child))
mpm@selenic.com
Add basic annotation support...
r79 for o, m, n, s, t in sm.get_opcodes():
mpm@selenic.com
Annotate was being too clever trying to work in place, and triggering...
r109 if o == 'equal':
mpm@selenic.com
annotate: deal with merges...
r199 new += parent[m:n]
mpm@selenic.com
Annotate was being too clever trying to work in place, and triggering...
r109 else:
mpm@selenic.com
annotate: deal with merges...
r199 new += child[s:t]
return new
mpm@selenic.com
annotate: memory efficiency...
r200 # find all ancestors
mpm@selenic.com
hg annotate: actually annotate the given version...
r216 needed = {node:1}
mpm@selenic.com
annotate: deal with merges...
r199 visit = [node]
while visit:
n = visit.pop(0)
for p in self.parents(n):
if p not in needed:
needed[p] = 1
visit.append(p)
mpm@selenic.com
annotate: memory efficiency...
r200 else:
# count how many times we'll use this
needed[p] += 1
mpm@selenic.com
annotate: deal with merges...
r199
mpm@selenic.com
annotate: memory efficiency...
r200 # sort by revision which is a topological order
mpm@selenic.com
annotate: deal with merges...
r199 visit = needed.keys()
visit = [ (self.rev(n), n) for n in visit ]
visit.sort()
visit = [ p[1] for p in visit ]
hist = {}
for n in visit:
curr = decorate(self.read(n), self.linkrev(n))
for p in self.parents(n):
if p != nullid:
curr = pair(hist[p], curr)
mpm@selenic.com
annotate: memory efficiency...
r200 # trim the history of unneeded revs
needed[p] -= 1
if not needed[p]:
del hist[p]
mpm@selenic.com
annotate: deal with merges...
r199 hist[n] = curr
return hist[n]
mpm@selenic.com
Add basic annotation support...
r79
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 class manifest(revlog):
def __init__(self, opener):
self.mapcache = None
self.listcache = None
self.addlist = None
revlog.__init__(self, opener, "00manifest.i", "00manifest.d")
def read(self, node):
if self.mapcache and self.mapcache[0] == node:
mpm@selenic.com
Fix manifest merge swap bug...
r90 return self.mapcache[1].copy()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 text = self.revision(node)
map = {}
mpm@selenic.com
Fix corruption from manifest.listcache optimization...
r25 self.listcache = (text, text.splitlines(1))
for l in self.listcache[1]:
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 (f, n) = l.split('\0')
map[f] = bin(n[:40])
self.mapcache = (node, map)
return map
def diff(self, a, b):
# this is sneaky, as we're not actually using a and b
mpm@selenic.com
Minor safety checks to manifest diff
r140 if self.listcache and self.addlist and self.listcache[0] == a:
mpm@selenic.com
Add paranoia to diff code
r98 d = mdiff.diff(self.listcache[1], self.addlist, 1)
if mdiff.patch(a, d) != b:
sys.stderr.write("*** sortdiff failed, falling back ***\n")
return mdiff.textdiff(a, b)
return d
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 else:
mpm@selenic.com
Fix occassional diff bug with manifests
r44 return mdiff.textdiff(a, b)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def add(self, map, transaction, link, p1=None, p2=None):
files = map.keys()
files.sort()
self.addlist = ["%s\000%s\n" % (f, hex(map[f])) for f in files]
text = "".join(self.addlist)
n = self.addrevision(text, transaction, link, p1, p2)
self.mapcache = (n, map)
mpm@selenic.com
Fix corruption from manifest.listcache optimization...
r25 self.listcache = (text, self.addlist)
mpm@selenic.com
Minor safety checks to manifest diff
r140 self.addlist = None
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
return n
class changelog(revlog):
def __init__(self, opener):
revlog.__init__(self, opener, "00changelog.i", "00changelog.d")
def extract(self, text):
mpm@selenic.com
Move hex/bin bits to revlog...
r37 if not text:
mpm@selenic.com
Date is an int as a string in changelog
r40 return (nullid, "", "0", [], "")
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 last = text.index("\n\n")
desc = text[last + 2:]
l = text[:last].splitlines()
manifest = bin(l[0])
user = l[1]
date = l[2]
files = l[3:]
return (manifest, user, date, files, desc)
def read(self, node):
return self.extract(self.revision(node))
mpm@selenic.com
hg rawcommit command...
r203 def add(self, manifest, list, desc, transaction, p1=None, p2=None,
user=None, date=None):
user = (user or
os.environ.get("HGUSER") or
mpm@selenic.com
From: Thomas Arendsen Hein <thomas@intevation.de>...
r55 os.environ.get("EMAIL") or
os.environ.get("LOGNAME", "unknown") + '@' + socket.getfqdn())
mpm@selenic.com
hg rawcommit command...
r203 date = date or "%d %d" % (time.time(), time.timezone)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 list.sort()
l = [hex(manifest), user, date] + list + ["", desc]
text = "\n".join(l)
return self.addrevision(text, transaction, self.count(), p1, p2)
mpm@selenic.com
change dircache into dirstate...
r220 class dirstate:
mpm@selenic.com
root relative IO and valid commit states...
r244 def __init__(self, opener, ui, root):
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.opener = opener
mpm@selenic.com
root relative IO and valid commit states...
r244 self.root = root
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.dirty = 0
mpm@selenic.com
The actual hg remove fix from Thomas Hein
r20 self.ui = ui
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.map = None
mpm@selenic.com
move repo.current to dirstate.parents()...
r227 self.pl = None
mpm@selenic.com
change dircache into dirstate...
r220
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def __del__(self):
mpm@selenic.com
change dircache into dirstate...
r220 if self.dirty:
self.write()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def __getitem__(self, key):
try:
return self.map[key]
except TypeError:
self.read()
return self[key]
mpm@selenic.com
change dircache into dirstate...
r220
def __contains__(self, key):
if not self.map: self.read()
return key in self.map
mpm@selenic.com
move repo.current to dirstate.parents()...
r227 def parents(self):
if not self.pl:
self.read()
return self.pl
def setparents(self, p1, p2 = nullid):
self.dirty = 1
self.pl = p1, p2
mpm@selenic.com
change dircache into dirstate...
r220 def state(self, key):
try:
return self[key][0]
except KeyError:
return "?"
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def read(self):
if self.map is not None: return self.map
self.map = {}
mpm@selenic.com
move repo.current to dirstate.parents()...
r227 self.pl = [nullid, nullid]
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 try:
mpm@selenic.com
change dircache into dirstate...
r220 st = self.opener("dirstate").read()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 except: return
mpm@selenic.com
move repo.current to dirstate.parents()...
r227 self.pl = [st[:20], st[20: 40]]
pos = 40
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 while pos < len(st):
mpm@selenic.com
change dircache into dirstate...
r220 e = struct.unpack(">cllll", st[pos:pos+17])
l = e[4]
pos += 17
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 f = st[pos:pos + l]
mpm@selenic.com
change dircache into dirstate...
r220 self.map[f] = e[:4]
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 pos += l
mpm@selenic.com
change dircache into dirstate...
r220 def update(self, files, state):
''' current states:
n normal
mpm@selenic.com
add 'm' state to dirstates...
r231 m needs merging
mpm@selenic.com
change dircache into dirstate...
r220 r marked for removal
a marked for addition'''
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 if not files: return
self.read()
self.dirty = 1
for f in files:
mpm@selenic.com
change dircache into dirstate...
r220 if state == "r":
self.map[f] = ('r', 0, 0, 0)
else:
mpm@selenic.com
Remove invalid state from dirstate...
r253 s = os.stat(os.path.join(self.root, f))
self.map[f] = (state, s.st_mode, s.st_size, s.st_mtime)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
change dircache into dirstate...
r220 def forget(self, files):
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 if not files: return
self.read()
self.dirty = 1
for f in files:
mpm@selenic.com
The actual hg remove fix from Thomas Hein
r20 try:
del self.map[f]
except KeyError:
mpm@selenic.com
change dircache into dirstate...
r220 self.ui.warn("not in dirstate: %s!\n" % f)
mpm@selenic.com
The actual hg remove fix from Thomas Hein
r20 pass
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def clear(self):
self.map = {}
self.dirty = 1
def write(self):
mpm@selenic.com
change dircache into dirstate...
r220 st = self.opener("dirstate", "w")
mpm@selenic.com
move repo.current to dirstate.parents()...
r227 st.write("".join(self.pl))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 for f, e in self.map.items():
mpm@selenic.com
change dircache into dirstate...
r220 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 st.write(e + f)
self.dirty = 0
def copy(self):
self.read()
return self.map.copy()
# used to avoid circular references so destructors work
def opener(base):
p = base
def o(path, mode="r"):
mpm@selenic.com
Fix network pull of repo files with "%" in their base64 encoding.
r15 if p[:7] == "http://":
f = os.path.join(p, urllib.quote(path))
return httprangereader(f)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 f = os.path.join(p, path)
mpm@selenic.com
Move hg from storing files in data with base64 encoding to full...
r110 if mode != "r":
try:
s = os.stat(f)
except OSError:
d = os.path.dirname(f)
if not os.path.isdir(d):
os.makedirs(d)
else:
if s.st_nlink > 1:
file(f + ".tmp", "w").write(file(f).read())
os.rename(f+".tmp", f)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
return file(f, mode)
return o
mpm@selenic.com
Add hg:// protocol...
r60 class localrepository:
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def __init__(self, ui, path=None, create=0):
self.remote = 0
if path and path[:7] == "http://":
self.remote = 1
self.path = path
else:
if not path:
p = os.getcwd()
while not os.path.isdir(os.path.join(p, ".hg")):
p = os.path.dirname(p)
if p == "/": raise "No repo found"
path = p
self.path = os.path.join(path, ".hg")
self.root = path
self.ui = ui
if create:
os.mkdir(self.path)
os.mkdir(self.join("data"))
self.opener = opener(self.path)
self.manifest = manifest(self.opener)
self.changelog = changelog(self.opener)
self.ignorelist = None
mpm@selenic.com
Add tag support
r67 self.tags = None
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
if not self.remote:
mpm@selenic.com
root relative IO and valid commit states...
r244 self.dirstate = dirstate(self.opener, ui, self.root)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def ignore(self, f):
if self.ignorelist is None:
self.ignorelist = []
try:
mpm@selenic.com
Add tag support
r67 l = open(os.path.join(self.root, ".hgignore"))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 for pat in l:
mpm@selenic.com
Ignore empty ignore patterns
r9 if pat != "\n":
self.ignorelist.append(re.compile(pat[:-1]))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 except IOError: pass
for pat in self.ignorelist:
if pat.search(f): return True
return False
mpm@selenic.com
Add tag support
r67 def lookup(self, key):
if self.tags is None:
self.tags = {}
try:
mpm@selenic.com
unify checkout and resolve into update...
r254 # read each head of the tags file, ending with the tip
# and add each tag found to the map, with "newer" ones
# taking precedence
mpm@selenic.com
Add tag support
r67 fl = self.file(".hgtags")
mpm@selenic.com
unify checkout and resolve into update...
r254 h = fl.heads()
h.reverse()
for r in h:
for l in fl.revision(r).splitlines():
if l:
n, k = l.split(" ")
self.tags[k] = bin(n)
mpm@selenic.com
Add tag support
r67 except KeyError: pass
try:
return self.tags[key]
except KeyError:
return self.changelog.lookup(key)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def join(self, f):
return os.path.join(self.path, f)
mpm@selenic.com
root relative IO and valid commit states...
r244 def wjoin(self, f):
return os.path.join(self.root, f)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def file(self, f):
mpm@selenic.com
Changes to network protocol...
r192 if f[0] == '/': f = f[1:]
mpm@selenic.com
Fix transaction handling bug by reverting fileopener change
r144 return filelog(self.opener, f)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def transaction(self):
mpm@selenic.com
backup dirstate for undo...
r251 # save dirstate for undo
mpm@selenic.com
Fix empty repository transaction bug...
r263 try:
ds = self.opener("dirstate").read()
except IOError:
ds = ""
mpm@selenic.com
backup dirstate for undo...
r251 self.opener("undo.dirstate", "w").write(ds)
mpm@selenic.com
implement demand loading hack...
r262
return transaction.transaction(self.opener, self.join("journal"),
self.join("undo"))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
hg undo: fixup working dir state...
r210 def recover(self):
mpm@selenic.com
fix repo locking...
r225 lock = self.lock()
mpm@selenic.com
hg undo: fixup working dir state...
r210 if os.path.exists(self.join("recover")):
self.ui.status("attempting to rollback interrupted transaction\n")
mpm@selenic.com
implement demand loading hack...
r262 return transaction.rollback(self.opener, self.join("recover"))
mpm@selenic.com
hg undo: fixup working dir state...
r210 else:
self.ui.warn("no interrupted transaction available\n")
def undo(self):
mpm@selenic.com
fix repo locking...
r225 lock = self.lock()
mpm@selenic.com
hg undo: fixup working dir state...
r210 if os.path.exists(self.join("undo")):
self.ui.status("attempting to rollback last transaction\n")
mpm@selenic.com
implement demand loading hack...
r262 transaction.rollback(self.opener, self.join("undo"))
mpm@selenic.com
backup dirstate for undo...
r251 self.dirstate = None
os.rename(self.join("undo.dirstate"), self.join("dirstate"))
self.dirstate = dirstate(self.opener, self.ui, self.root)
mpm@selenic.com
Make undo and recover friendlier...
r163 else:
mpm@selenic.com
hg undo: fixup working dir state...
r210 self.ui.warn("no undo information available\n")
mpm@selenic.com
Implement recover and undo commands...
r162
mpm@selenic.com
Simply repository locking...
r161 def lock(self, wait = 1):
try:
return lock.lock(self.join("lock"), 0)
except lock.LockHeld, inst:
if wait:
self.ui.warn("waiting for lock held by %s\n" % inst.args[0])
return lock.lock(self.join("lock"), wait)
raise inst
mpm@selenic.com
hg rawcommit command...
r203 def rawcommit(self, files, text, user, date, p1=None, p2=None):
mpm@selenic.com
teach rawcommit about dirstate.parents()...
r228 p1 = p1 or self.dirstate.parents()[0] or nullid
p2 = p2 or self.dirstate.parents()[1] or nullid
mpm@selenic.com
hg rawcommit command...
r203 pchange = self.changelog.read(p1)
pmmap = self.manifest.read(pchange[0])
tr = self.transaction()
mmap = {}
linkrev = self.changelog.count()
for f in files:
try:
t = file(f).read()
except IOError:
self.ui.warn("Read file %s error, skipped\n" % f)
continue
r = self.file(f)
mpm@selenic.com
teach rawcommit about dirstate.parents()...
r228 # FIXME - need to find both parents properly
mpm@selenic.com
hg rawcommit command...
r203 prev = pmmap.get(f, nullid)
mmap[f] = r.add(t, tr, linkrev, prev)
mnode = self.manifest.add(mmap, tr, linkrev, pchange[0])
n = self.changelog.add(mnode, files, text, tr, p1, p2, user ,date, )
tr.close()
mpm@selenic.com
teach rawcommit about dirstate.parents()...
r228 self.dirstate.setparents(p1, p2)
mpm@selenic.com
change dircache into dirstate...
r220 self.dirstate.clear()
self.dirstate.update(mmap.keys(), "n")
mpm@selenic.com
hg rawcommit command...
r203
mpm@selenic.com
teach commit about dirstate.parents()...
r229 def commit(self, files = None, text = ""):
mpm@selenic.com
change dircache into dirstate...
r220 commit = []
remove = []
if files:
for f in files:
s = self.dirstate.state(f)
mpm@selenic.com
root relative IO and valid commit states...
r244 if s in 'nmai':
mpm@selenic.com
change dircache into dirstate...
r220 commit.append(f)
elif s == 'r':
remove.append(f)
else:
mpm@selenic.com
root relative IO and valid commit states...
r244 self.ui.warn("%s not tracked!\n" % f)
mpm@selenic.com
change dircache into dirstate...
r220 else:
mpm@selenic.com
make diffdir default to dirstate.parents()...
r230 (c, a, d, u) = self.diffdir(self.root)
mpm@selenic.com
change dircache into dirstate...
r220 commit = c + a
remove = d
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
change dircache into dirstate...
r220 if not commit and not remove:
mpm@selenic.com
Bail on attempts to do an empty commit
r151 self.ui.status("nothing changed\n")
return
mpm@selenic.com
teach commit about dirstate.parents()...
r229 p1, p2 = self.dirstate.parents()
c1 = self.changelog.read(p1)
c2 = self.changelog.read(p2)
m1 = self.manifest.read(c1[0])
m2 = self.manifest.read(c2[0])
mpm@selenic.com
fix repo locking...
r225 lock = self.lock()
mpm@selenic.com
Bail on attempts to do an empty commit
r151 tr = self.transaction()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 # check in files
new = {}
linkrev = self.changelog.count()
mpm@selenic.com
change dircache into dirstate...
r220 commit.sort()
for f in commit:
mpm@selenic.com
Add -q quiet option...
r83 self.ui.note(f + "\n")
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 try:
mpm@selenic.com
root relative IO and valid commit states...
r244 t = file(self.wjoin(f)).read()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 except IOError:
mpm@selenic.com
change dircache into dirstate...
r220 self.warn("trouble committing %s!\n" % f)
raise
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 r = self.file(f)
mpm@selenic.com
teach commit about dirstate.parents()...
r229 fp1 = m1.get(f, nullid)
fp2 = m2.get(f, nullid)
new[f] = r.add(t, tr, linkrev, fp1, fp2)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
# update manifest
mpm@selenic.com
teach commit about dirstate.parents()...
r229 m1.update(new)
for f in remove: del m1[f]
mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0])
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
# add changeset
new = new.keys()
new.sort()
mpm@selenic.com
teach commit about dirstate.parents()...
r229 edittext = text + "\n" + "HG: manifest hash %s\n" % hex(mn)
mpm@selenic.com
Add manifest hash to commit messages for easy signing...
r185 edittext += "".join(["HG: changed %s\n" % f for f in new])
mpm@selenic.com
Fix corruption from manifest.listcache optimization...
r25 edittext += "".join(["HG: removed %s\n" % f for f in remove])
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 edittext = self.ui.edit(edittext)
mpm@selenic.com
teach commit about dirstate.parents()...
r229 n = self.changelog.add(mn, new, edittext, tr, p1, p2)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 tr.close()
mpm@selenic.com
teach commit about dirstate.parents()...
r229 self.dirstate.setparents(n)
mpm@selenic.com
change dircache into dirstate...
r220 self.dirstate.update(new, "n")
self.dirstate.forget(remove)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
make diffdir default to dirstate.parents()...
r230 def diffdir(self, path, changeset = None):
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 changed = []
mpm@selenic.com
change dircache into dirstate...
r220 added = []
unknown = []
mpm@selenic.com
Fix exception handling for reading current working version
r4 mf = {}
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
Make diffdir take a revision argument
r29 if changeset:
change = self.changelog.read(changeset)
mpm@selenic.com
Fix exception handling for reading current working version
r4 mf = self.manifest.read(change[0])
mpm@selenic.com
make diffdir default to dirstate.parents()...
r230 dc = dict.fromkeys(mf)
else:
changeset = self.dirstate.parents()[0]
change = self.changelog.read(changeset)
mf = self.manifest.read(change[0])
mpm@selenic.com
change dircache into dirstate...
r220 dc = self.dirstate.copy()
mpm@selenic.com
Make diffdir take a revision argument
r29
def fcmp(fn):
mpm@selenic.com
root relative IO and valid commit states...
r244 t1 = file(self.wjoin(fn)).read()
mpm@selenic.com
Make diffdir take a revision argument
r29 t2 = self.file(fn).revision(mf[fn])
return cmp(t1, t2)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 for dir, subdirs, files in os.walk(self.root):
d = dir[len(self.root)+1:]
if ".hg" in subdirs: subdirs.remove(".hg")
for f in files:
fn = os.path.join(d, f)
mpm@selenic.com
Diff in subdirectories from Jake Edge...
r64 try: s = os.stat(os.path.join(self.root, fn))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 except: continue
if fn in dc:
c = dc[fn]
del dc[fn]
mpm@selenic.com
change dircache into dirstate...
r220 if not c:
mpm@selenic.com
Make diffdir take a revision argument
r29 if fcmp(fn):
changed.append(fn)
mpm@selenic.com
add 'm' state to dirstates...
r231 elif c[0] == 'm':
changed.append(fn)
mpm@selenic.com
change dircache into dirstate...
r220 elif c[0] == 'a':
added.append(fn)
elif c[0] == 'r':
unknown.append(fn)
elif c[2] != s.st_size:
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 changed.append(fn)
mpm@selenic.com
change dircache into dirstate...
r220 elif c[1] != s.st_mode or c[3] != s.st_mtime:
mpm@selenic.com
Make diffdir take a revision argument
r29 if fcmp(fn):
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 changed.append(fn)
else:
if self.ignore(fn): continue
mpm@selenic.com
change dircache into dirstate...
r220 unknown.append(fn)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
deleted = dc.keys()
deleted.sort()
mpm@selenic.com
change dircache into dirstate...
r220 return (changed, added, deleted, unknown)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
Add diffrevs function to compare two nodes
r32 def diffrevs(self, node1, node2):
mpm@selenic.com
Support for 0, 1, or 2 diff revs
r33 changed, added = [], []
mpm@selenic.com
Add diffrevs function to compare two nodes
r32
change = self.changelog.read(node1)
mf1 = self.manifest.read(change[0])
mpm@selenic.com
Support for 0, 1, or 2 diff revs
r33 change = self.changelog.read(node2)
mpm@selenic.com
Add diffrevs function to compare two nodes
r32 mf2 = self.manifest.read(change[0])
for fn in mf2:
if mf1.has_key(fn):
if mf1[fn] != mf2[fn]:
changed.append(fn)
del mf1[fn]
else:
added.append(fn)
deleted = mf1.keys()
deleted.sort()
return (changed, added, deleted)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def add(self, list):
mpm@selenic.com
change dircache into dirstate...
r220 for f in list:
mpm@selenic.com
root relative IO and valid commit states...
r244 p = self.wjoin(f)
mpm@selenic.com
change dircache into dirstate...
r220 if not os.path.isfile(p):
self.ui.warn("%s does not exist!\n" % f)
elif self.dirstate.state(f) == 'n':
self.ui.warn("%s already tracked!\n" % f)
else:
self.dirstate.update([f], "a")
def forget(self, list):
for f in list:
if self.dirstate.state(f) not in 'ai':
self.ui.warn("%s not added!\n" % f)
else:
self.dirstate.forget([f])
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def remove(self, list):
for f in list:
mpm@selenic.com
root relative IO and valid commit states...
r244 p = self.wjoin(f)
mpm@selenic.com
change dircache into dirstate...
r220 if os.path.isfile(p):
self.ui.warn("%s still exists!\n" % f)
elif f not in self.dirstate:
self.ui.warn("%s not tracked!\n" % f)
else:
self.dirstate.update([f], "r")
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
make pull work for multiple heads...
r222 def heads(self):
return self.changelog.heads()
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 def branches(self, nodes):
if not nodes: nodes = [self.changelog.tip()]
b = []
for n in nodes:
t = n
while n:
p = self.changelog.parents(n)
if p[1] != nullid or p[0] == nullid:
b.append((t, n, p[0], p[1]))
break
n = p[0]
return b
def between(self, pairs):
r = []
for top, bottom in pairs:
n, l, i = top, [], 0
f = 1
while n != bottom:
p = self.changelog.parents(n)[0]
if i == f:
l.append(n)
f = f * 2
n = p
i += 1
r.append(l)
return r
def newer(self, nodes):
m = {}
nl = []
mpm@selenic.com
Refactor merge code...
r94 pm = {}
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 cl = self.changelog
t = l = cl.count()
mpm@selenic.com
Refactor merge code...
r94
# find the lowest numbered node
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 for n in nodes:
l = min(l, cl.rev(n))
mpm@selenic.com
Refactor merge code...
r94 m[n] = 1
mpm@selenic.com
Add changegroup support
r46
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 for i in xrange(l, t):
n = cl.node(i)
mpm@selenic.com
Refactor merge code...
r94 if n in m: # explicitly listed
pm[n] = 1
nl.append(n)
continue
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 for p in cl.parents(n):
mpm@selenic.com
Refactor merge code...
r94 if p in pm: # parent listed
pm[n] = 1
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 nl.append(n)
mpm@selenic.com
Refactor merge code...
r94 break
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56
return nl
def getchangegroup(self, remote):
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 m = self.changelog.nodemap
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 search = []
fetch = []
mpm@selenic.com
Improve pruning of branches in outstanding changeset algorithm...
r148 seen = {}
seenbranch = {}
mpm@selenic.com
Changes to network protocol...
r192
mpm@selenic.com
merge: short-circuit search for merge into empty repo...
r190 # if we have an empty repo, fetch everything
if self.changelog.tip() == nullid:
mpm@selenic.com
make pull work for multiple heads...
r222 self.ui.status("requesting all changes\n")
mpm@selenic.com
merge: short-circuit search for merge into empty repo...
r190 return remote.changegroup([nullid])
# otherwise, assume we're closer to the tip than the root
mpm@selenic.com
make pull work for multiple heads...
r222 self.ui.status("searching for changes\n")
heads = remote.heads()
unknown = []
for h in heads:
if h not in m:
unknown.append(h)
mpm@selenic.com
Add changegroup support
r46
mpm@selenic.com
make pull work for multiple heads...
r222 if not unknown:
mpm@selenic.com
Changes to network protocol...
r192 self.ui.status("nothing to do!\n")
mpm@selenic.com
Add hg:// protocol...
r60 return None
mpm@selenic.com
make pull work for multiple heads...
r222
unknown = remote.branches(unknown)
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 while unknown:
n = unknown.pop(0)
mpm@selenic.com
Improve pruning of branches in outstanding changeset algorithm...
r148 seen[n[0]] = 1
self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1])))
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 if n == nullid: break
mpm@selenic.com
Improve pruning of branches in outstanding changeset algorithm...
r148 if n in seenbranch:
self.ui.debug("branch already found\n")
continue
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 if n[1] and n[1] in m: # do we know the base?
mpm@selenic.com
Improve pruning of branches in outstanding changeset algorithm...
r148 self.ui.debug("found incomplete branch %s:%s\n"
% (short(n[0]), short(n[1])))
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 search.append(n) # schedule branch range for scanning
mpm@selenic.com
Improve pruning of branches in outstanding changeset algorithm...
r148 seenbranch[n] = 1
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 else:
mpm@selenic.com
Refactor merge code...
r94 if n[2] in m and n[3] in m:
if n[1] not in fetch:
self.ui.debug("found new changeset %s\n" %
short(n[1]))
fetch.append(n[1]) # earliest unknown
continue
mpm@selenic.com
Improve pruning of branches in outstanding changeset algorithm...
r148
r = []
for a in n[2:4]:
if a not in seen: r.append(a)
if r:
self.ui.debug("requesting %s\n" %
" ".join(map(short, r)))
for b in remote.branches(r):
self.ui.debug("received %s:%s\n" %
(short(b[0]), short(b[1])))
if b[0] not in m and b[0] not in seen:
unknown.append(b)
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56
while search:
n = search.pop(0)
l = remote.between([(n[0], n[1])])[0]
p = n[0]
f = 1
for i in l + [n[1]]:
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 if i in m:
mpm@selenic.com
Fix merge bug, I hope
r85 if f <= 2:
mpm@selenic.com
Add -q quiet option...
r83 self.ui.debug("found new branch changeset %s\n" %
short(p))
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 fetch.append(p)
else:
mpm@selenic.com
Add -q quiet option...
r83 self.ui.debug("narrowed branch search to %s:%s\n"
% (short(p), short(i)))
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 search.append((p, i))
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 break
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 p, f = i, f * 2
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 for f in fetch:
if f in m:
mpm@selenic.com
Add -q quiet option...
r83 raise "already have", short(f[:4])
mpm@selenic.com
Refactor merge code...
r94 self.ui.note("adding new changesets starting at " +
mpm@selenic.com
Add -q quiet option...
r83 " ".join([short(f) for f in fetch]) + "\n")
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65
mpm@selenic.com
Add getchangegroup code to efficiently calculate and request a changegroup
r56 return remote.changegroup(fetch)
def changegroup(self, basenodes):
nodes = self.newer(basenodes)
mpm@selenic.com
Add changegroup support
r46 # construct the link map
linkmap = {}
for n in nodes:
linkmap[self.changelog.rev(n)] = n
# construct a list of all changed files
changed = {}
for n in nodes:
c = self.changelog.read(n)
for f in c[3]:
changed[f] = 1
changed = changed.keys()
changed.sort()
# the changegroup is changesets + manifests + all file revs
revs = [ self.changelog.rev(n) for n in nodes ]
mpm@selenic.com
Changes to network protocol...
r192 for y in self.changelog.group(linkmap): yield y
for y in self.manifest.group(linkmap): yield y
mpm@selenic.com
Add changegroup support
r46 for f in changed:
mpm@selenic.com
Changes to network protocol...
r192 yield struct.pack(">l", len(f) + 4) + f
mpm@selenic.com
Add changegroup support
r46 g = self.file(f).group(linkmap)
mpm@selenic.com
Changes to network protocol...
r192 for y in g:
yield y
mpm@selenic.com
Add changegroup support
r46
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 def addchangegroup(self, generator):
mpm@selenic.com
make pull work for multiple heads...
r222
class genread:
def __init__(self, generator):
self.g = generator
self.buf = ""
def read(self, l):
while l > len(self.buf):
try:
self.buf += self.g.next()
except StopIteration:
break
d, self.buf = self.buf[:l], self.buf[l:]
return d
def getchunk():
d = source.read(4)
if not d: return ""
l = struct.unpack(">l", d)[0]
if l <= 4: return ""
return source.read(l - 4)
def getgroup():
while 1:
c = getchunk()
if not c: break
yield c
def csmap(x):
self.ui.debug("add changeset %s\n" % short(x))
return self.changelog.count()
def revmap(x):
return self.changelog.rev(x)
if not generator: return
changesets = files = revisions = 0
mpm@selenic.com
fix repo locking...
r225
mpm@selenic.com
make pull work for multiple heads...
r222 source = genread(generator)
mpm@selenic.com
fix repo locking...
r225 lock = self.lock()
mpm@selenic.com
make pull work for multiple heads...
r222 tr = self.transaction()
# pull off the changeset group
self.ui.status("adding changesets\n")
co = self.changelog.tip()
mpm@selenic.com
fix bad assumption about uniqueness of file versions...
r224 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique
mpm@selenic.com
make pull work for multiple heads...
r222 changesets = self.changelog.rev(cn) - self.changelog.rev(co)
# pull off the manifest group
self.ui.status("adding manifests\n")
mm = self.manifest.tip()
mo = self.manifest.addgroup(getgroup(), revmap, tr)
# process the files
self.ui.status("adding file revisions\n")
while 1:
f = getchunk()
if not f: break
self.ui.debug("adding %s revisions\n" % f)
fl = self.file(f)
o = fl.tip()
n = fl.addgroup(getgroup(), revmap, tr)
revisions += fl.rev(n) - fl.rev(o)
files += 1
self.ui.status(("modified %d files, added %d changesets" +
" and %d new revisions\n")
% (files, changesets, revisions))
tr.close()
return
mpm@selenic.com
unify checkout and resolve into update...
r254 def update(self, node):
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 pl = self.dirstate.parents()
if pl[1] != nullid:
mpm@selenic.com
unify checkout and resolve into update...
r254 self.ui.warn("aborting: outstanding uncommitted merges\n")
mpm@selenic.com
Add changegroup support
r46 return
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 p1, p2 = pl[0], node
m1n = self.changelog.read(p1)[0]
m2n = self.changelog.read(p2)[0]
man = self.manifest.ancestor(m1n, m2n)
m1 = self.manifest.read(m1n)
m2 = self.manifest.read(m2n)
ma = self.manifest.read(man)
(c, a, d, u) = self.diffdir(self.root)
# resolve the manifest to determine which files
# we care about merging
mpm@selenic.com
unify checkout and resolve into update...
r254 self.ui.note("resolving manifests\n")
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 self.ui.debug(" ancestor %s local %s remote %s\n" %
(short(man), short(m1n), short(m2n)))
merge = {}
get = {}
remove = []
mpm@selenic.com
Add changegroup support
r46
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 # construct a working dir manifest
mw = m1.copy()
mpm@selenic.com
unify checkout and resolve into update...
r254 for f in a + c + u:
mw[f] = ""
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 for f in d:
mpm@selenic.com
unify checkout and resolve into update...
r254 if f in mw: del mw[f]
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232
for f, n in mw.iteritems():
if f in m2:
if n != m2[f]:
mpm@selenic.com
unify checkout and resolve into update...
r254 a = ma.get(f, nullid)
if n != a and m2[f] != a:
mpm@selenic.com
merge: Fix bug where we overwrote local when local was newer...
r273 self.ui.debug(" %s versions differ, resolve\n" % f)
mpm@selenic.com
unify checkout and resolve into update...
r254 merge[f] = (m1.get(f, nullid), m2[f])
mpm@selenic.com
merge: Fix bug where we overwrote local when local was newer...
r273 elif m2[f] != a:
self.ui.debug(" remote %s is newer, get\n" % f)
mpm@selenic.com
unify checkout and resolve into update...
r254 get[f] = m2[f]
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 del m2[f]
elif f in ma:
if n != ma[f]:
r = self.ui.prompt(
(" local changed %s which remote deleted\n" % f) +
"(k)eep or (d)elete?", "[kd]", "k")
if r == "d":
remove.append(f)
else:
self.ui.debug("other deleted %s\n" % f)
mpm@selenic.com
unify checkout and resolve into update...
r254 remove.append(f) # other deleted it
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 else:
mpm@selenic.com
unify checkout and resolve into update...
r254 if n == m1.get(f, nullid): # same as parent
self.ui.debug("remote deleted %s\n" % f)
remove.append(f)
else:
self.ui.debug("working dir created %s, keeping\n" % f)
mpm@selenic.com
Add changegroup support
r46
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 for f, n in m2.iteritems():
mpm@selenic.com
minor fixes for update()...
r256 if f[0] == "/": continue
mpm@selenic.com
unify checkout and resolve into update...
r254 if f in ma and n != ma[f]:
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 r = self.ui.prompt(
("remote changed %s which local deleted\n" % f) +
"(k)eep or (d)elete?", "[kd]", "k")
if r == "d": remove.append(f)
else:
mpm@selenic.com
unify checkout and resolve into update...
r254 self.ui.debug("remote created %s\n" % f)
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 get[f] = n
del mw, m1, m2, ma
mpm@selenic.com
unify checkout and resolve into update...
r254 if not merge:
# we don't need to do any magic, just jump to the new rev
mode = 'n'
p1, p2 = p2, nullid
else:
# we have to remember what files we needed to get/change
# because any file that's different from either one of its
# parents must be in the changeset
mode = 'm'
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 self.dirstate.setparents(p1, p2)
mpm@selenic.com
merge: add count of new manifests, files, and revisions...
r191
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 # get the files we don't need to change
files = get.keys()
files.sort()
for f in files:
if f[0] == "/": continue
mpm@selenic.com
merge: Fix bug where we overwrote local when local was newer...
r273 self.ui.note("getting %s\n" % f)
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 t = self.file(f).revision(get[f])
try:
mpm@selenic.com
root relative IO and valid commit states...
r244 file(self.wjoin(f), "w").write(t)
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 except IOError:
os.makedirs(os.path.dirname(f))
mpm@selenic.com
root relative IO and valid commit states...
r244 file(self.wjoin(f), "w").write(t)
mpm@selenic.com
unify checkout and resolve into update...
r254 self.dirstate.update([f], mode)
mpm@selenic.com
Add changegroup support
r46
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 # merge the tricky bits
files = merge.keys()
files.sort()
for f in files:
mpm@selenic.com
minor fixes for update()...
r256 self.ui.status("merging %s\n" % f)
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 m, o = merge[f]
self.merge3(f, m, o)
mpm@selenic.com
unify checkout and resolve into update...
r254 self.dirstate.update([f], 'm')
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232
for f in remove:
self.ui.note("removing %s\n" % f)
mpm@selenic.com
unify checkout and resolve into update...
r254 os.unlink(f)
if mode == 'n':
self.dirstate.forget(remove)
else:
self.dirstate.update(remove, 'r')
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232
def merge3(self, fn, my, other):
"""perform a 3-way merge in the working directory"""
mpm@selenic.com
import and startup cleanups...
r249
mpm@selenic.com
Add updated merge3 code
r96 def temp(prefix, node):
pre = "%s~%s." % (os.path.basename(fn), prefix)
(fd, name) = tempfile.mkstemp("", pre)
f = os.fdopen(fd, "w")
f.write(fl.revision(node))
f.close()
return name
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 fl = self.file(fn)
mpm@selenic.com
Add updated merge3 code
r96 base = fl.ancestor(my, other)
mpm@selenic.com
root relative IO and valid commit states...
r244 a = self.wjoin(fn)
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 b = temp("other", other)
c = temp("base", base)
mpm@selenic.com
Add updated merge3 code
r96
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 self.ui.note("resolving %s\n" % fn)
self.ui.debug("file %s: other %s ancestor %s\n" %
(fn, short(other), short(base)))
mpm@selenic.com
Add updated merge3 code
r96
mpm@selenic.com
Replace tkmerge with hgmerge...
r240 cmd = os.environ.get("HGMERGE", "hgmerge")
r = os.system("%s %s %s %s" % (cmd, a, b, c))
mpm@selenic.com
hg resolve: merge a given node into the working directory...
r232 if r:
self.ui.warn("merging %s failed!\n" % f)
os.unlink(b)
os.unlink(c)
mpm@selenic.com
Add updated merge3 code
r96
mpm@selenic.com
migrate verify...
r247 def verify(self):
filelinkrevs = {}
filenodes = {}
manifestchangeset = {}
changesets = revisions = files = 0
errors = 0
self.ui.status("checking changesets\n")
for i in range(self.changelog.count()):
changesets += 1
n = self.changelog.node(i)
for p in self.changelog.parents(n):
if p not in self.changelog.nodemap:
self.ui.warn("changeset %s has unknown parent %s\n" %
(short(n), short(p)))
errors += 1
try:
changes = self.changelog.read(n)
except Exception, inst:
self.ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
errors += 1
manifestchangeset[changes[0]] = n
for f in changes[3]:
filelinkrevs.setdefault(f, []).append(i)
self.ui.status("checking manifests\n")
for i in range(self.manifest.count()):
n = self.manifest.node(i)
for p in self.manifest.parents(n):
if p not in self.manifest.nodemap:
self.ui.warn("manifest %s has unknown parent %s\n" %
(short(n), short(p)))
errors += 1
ca = self.changelog.node(self.manifest.linkrev(n))
cc = manifestchangeset[n]
if ca != cc:
self.ui.warn("manifest %s points to %s, not %s\n" %
(hex(n), hex(ca), hex(cc)))
errors += 1
try:
delta = mdiff.patchtext(self.manifest.delta(n))
except KeyboardInterrupt:
print "aborted"
sys.exit(0)
except Exception, inst:
self.ui.warn("unpacking manifest %s: %s\n"
% (short(n), inst))
errors += 1
ff = [ l.split('\0') for l in delta.splitlines() ]
for f, fn in ff:
filenodes.setdefault(f, {})[bin(fn)] = 1
self.ui.status("crosschecking files in changesets and manifests\n")
for f in filenodes:
if f not in filelinkrevs:
self.ui.warn("file %s in manifest but not in changesets\n" % f)
errors += 1
for f in filelinkrevs:
if f not in filenodes:
self.ui.warn("file %s in changeset but not in manifest\n" % f)
errors += 1
self.ui.status("checking files\n")
ff = filenodes.keys()
ff.sort()
for f in ff:
if f == "/dev/null": continue
files += 1
fl = self.file(f)
nodes = { nullid: 1 }
for i in range(fl.count()):
revisions += 1
n = fl.node(i)
if n not in filenodes[f]:
self.ui.warn("%s: %d:%s not in manifests\n"
% (f, i, short(n)))
print len(filenodes[f].keys()), fl.count(), f
errors += 1
else:
del filenodes[f][n]
flr = fl.linkrev(n)
if flr not in filelinkrevs[f]:
self.ui.warn("%s:%s points to unexpected changeset %d\n"
% (f, short(n), fl.linkrev(n)))
errors += 1
else:
filelinkrevs[f].remove(flr)
# verify contents
try:
t = fl.read(n)
except Exception, inst:
self.ui.warn("unpacking file %s %s: %s\n"
% (f, short(n), inst))
errors += 1
# verify parents
(p1, p2) = fl.parents(n)
if p1 not in nodes:
self.ui.warn("file %s:%s unknown parent 1 %s" %
(f, short(n), short(p1)))
errors += 1
if p2 not in nodes:
self.ui.warn("file %s:%s unknown parent 2 %s" %
(f, short(n), short(p1)))
errors += 1
nodes[n] = 1
# cross-check
for node in filenodes[f]:
self.ui.warn("node %s in manifests not in %s\n"
% (hex(n), f))
errors += 1
self.ui.status("%d files, %d changesets, %d total revisions\n" %
(files, changesets, revisions))
if errors:
self.ui.warn("%d integrity errors encountered!\n" % errors)
return 1
mpm@selenic.com
Add hg:// protocol...
r60 class remoterepository:
def __init__(self, ui, path):
mpm@selenic.com
Change hg: protocol name to http: and http: to old-http:...
r176 self.url = path
mpm@selenic.com
Add hg:// protocol...
r60 self.ui = ui
def do_cmd(self, cmd, **args):
mpm@selenic.com
Add -q quiet option...
r83 self.ui.debug("sending %s command\n" % cmd)
mpm@selenic.com
Add hg:// protocol...
r60 q = {"cmd": cmd}
q.update(args)
qs = urllib.urlencode(q)
cu = "%s?%s" % (self.url, qs)
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 return urllib.urlopen(cu)
mpm@selenic.com
Add hg:// protocol...
r60
mpm@selenic.com
make pull work for multiple heads...
r222 def heads(self):
d = self.do_cmd("heads").read()
try:
return map(bin, d[:-1].split(" "))
except:
self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
raise
mpm@selenic.com
Add hg:// protocol...
r60 def branches(self, nodes):
n = " ".join(map(hex, nodes))
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 d = self.do_cmd("branches", nodes=n).read()
mpm@selenic.com
merge: catch unexpected responses...
r217 try:
br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
return br
except:
self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
raise
mpm@selenic.com
Add hg:// protocol...
r60
def between(self, pairs):
n = "\n".join(["-".join(map(hex, p)) for p in pairs])
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 d = self.do_cmd("between", pairs=n).read()
mpm@selenic.com
merge: catch unexpected responses...
r217 try:
p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
return p
except:
self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
raise
mpm@selenic.com
Add hg:// protocol...
r60
def changegroup(self, nodes):
n = " ".join(map(hex, nodes))
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 zd = zlib.decompressobj()
f = self.do_cmd("changegroup", roots=n)
mpm@selenic.com
Changes to network protocol...
r192 bytes = 0
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 while 1:
d = f.read(4096)
mpm@selenic.com
Changes to network protocol...
r192 bytes += len(d)
mpm@selenic.com
Fix up a bunch of bugs in the new merge code...
r65 if not d:
yield zd.flush()
break
yield zd.decompress(d)
mpm@selenic.com
Changes to network protocol...
r192 self.ui.note("%d bytes of data transfered\n" % bytes)
mpm@selenic.com
Add hg:// protocol...
r60
def repository(ui, path=None, create=0):
mpm@selenic.com
Change hg: protocol name to http: and http: to old-http:...
r176 if path and path[:7] == "http://":
return remoterepository(ui, path)
mpm@selenic.com
Add hg:// protocol...
r60 if path and path[:5] == "hg://":
mpm@selenic.com
Change hg: protocol name to http: and http: to old-http:...
r176 return remoterepository(ui, path.replace("hg://", "http://"))
if path and path[:11] == "old-http://":
return localrepository(ui, path.replace("old-http://", "http://"))
mpm@selenic.com
Add hg:// protocol...
r60 else:
return localrepository(ui, path, create)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 class httprangereader:
def __init__(self, url):
self.url = url
self.pos = 0
def seek(self, pos):
self.pos = pos
def read(self, bytes=None):
opener = urllib2.build_opener(byterange.HTTPRangeHandler())
urllib2.install_opener(opener)
req = urllib2.Request(self.url)
end = ''
if bytes: end = self.pos + bytes
req.add_header('Range', 'bytes=%d-%s' % (self.pos, end))
f = urllib2.urlopen(req)
return f.read()