Mercurial > public > mercurial-scm > hg
annotate mercurial/hg.py @ 249:619e775aa7f9
import and startup cleanups
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
import and startup cleanups
add commands:run()
add copyright notice to commands
eliminate/reorganize imports to speed up start time:
0.5b:
$ time bash -c 'for i in `seq 100`; do ~/bin/hg > /dev/null; done'
real 0m7.718s
user 0m6.719s
sys 0m0.794s
new:
$ time bash -c 'for i in `seq 100`; do hg > /dev/null; done'
real 0m2.171s
user 0m1.684s
sys 0m0.444s
just python:
$ time bash -c 'for i in `seq 100`; do python -c pass; done'
real 0m0.988s
user 0m0.771s
sys 0m0.207s
Ignoring the fixed cost of loading the Python interpreter, we're 5.6
times faster. With the Python load time, we're still 3.5 times faster.
manifest hash: acce5882a55c76eb165316f5741724c8ce4ef587
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCoihAywK+sNU5EO8RAqMdAJwMe6Ur0R9G6jjayNa5hH2C3c4k/gCeIYvc
N178vaWWGciX9zq+g5qCAls=
=buhv
-----END PGP SIGNATURE-----
author | mpm@selenic.com |
---|---|
date | Sat, 04 Jun 2005 14:16:32 -0800 |
parents | 863b508c5b36 |
children | 3fd8fc14b12f |
rev | line source |
---|---|
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1 # hg.py - repository classes for mercurial |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
2 # |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
4 # |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
6 # of the GNU General Public License, incorporated herein by reference. |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
7 |
249 | 8 import sys, struct, os |
9 from mercurial import lock | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
10 from mercurial.transaction import * |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
11 from mercurial.revlog import * |
79 | 12 from difflib import SequenceMatcher |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
13 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
14 class filelog(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
15 def __init__(self, opener, path): |
144
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
16 revlog.__init__(self, opener, |
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
17 os.path.join("data", path + ".i"), |
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
18 os.path.join("data", path + ".d")) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
19 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
20 def read(self, node): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
21 return self.revision(node) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
22 def add(self, text, transaction, link, p1=None, p2=None): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
23 return self.addrevision(text, transaction, link, p1, p2) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
24 |
79 | 25 def annotate(self, node): |
199 | 26 |
27 def decorate(text, rev): | |
28 return [(rev, l) for l in text.splitlines(1)] | |
29 | |
30 def strip(annotation): | |
31 return [e[1] for e in annotation] | |
32 | |
33 def pair(parent, child): | |
109
95699294f580
Annotate was being too clever trying to work in place, and triggering
mpm@selenic.com
parents:
107
diff
changeset
|
34 new = [] |
199 | 35 sm = SequenceMatcher(None, strip(parent), strip(child)) |
79 | 36 for o, m, n, s, t in sm.get_opcodes(): |
109
95699294f580
Annotate was being too clever trying to work in place, and triggering
mpm@selenic.com
parents:
107
diff
changeset
|
37 if o == 'equal': |
199 | 38 new += parent[m:n] |
109
95699294f580
Annotate was being too clever trying to work in place, and triggering
mpm@selenic.com
parents:
107
diff
changeset
|
39 else: |
199 | 40 new += child[s:t] |
41 return new | |
42 | |
200 | 43 # find all ancestors |
216
201115f2859b
hg annotate: actually annotate the given version
mpm@selenic.com
parents:
210
diff
changeset
|
44 needed = {node:1} |
199 | 45 visit = [node] |
46 while visit: | |
47 n = visit.pop(0) | |
48 for p in self.parents(n): | |
49 if p not in needed: | |
50 needed[p] = 1 | |
51 visit.append(p) | |
200 | 52 else: |
53 # count how many times we'll use this | |
54 needed[p] += 1 | |
199 | 55 |
200 | 56 # sort by revision which is a topological order |
199 | 57 visit = needed.keys() |
58 visit = [ (self.rev(n), n) for n in visit ] | |
59 visit.sort() | |
60 visit = [ p[1] for p in visit ] | |
61 hist = {} | |
62 | |
63 for n in visit: | |
64 curr = decorate(self.read(n), self.linkrev(n)) | |
65 for p in self.parents(n): | |
66 if p != nullid: | |
67 curr = pair(hist[p], curr) | |
200 | 68 # trim the history of unneeded revs |
69 needed[p] -= 1 | |
70 if not needed[p]: | |
71 del hist[p] | |
199 | 72 hist[n] = curr |
73 | |
74 return hist[n] | |
79 | 75 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
76 class manifest(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
77 def __init__(self, opener): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
78 self.mapcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
79 self.listcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
80 self.addlist = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
81 revlog.__init__(self, opener, "00manifest.i", "00manifest.d") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
82 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
83 def read(self, node): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
84 if self.mapcache and self.mapcache[0] == node: |
90 | 85 return self.mapcache[1].copy() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
86 text = self.revision(node) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
87 map = {} |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
88 self.listcache = (text, text.splitlines(1)) |
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
89 for l in self.listcache[1]: |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
90 (f, n) = l.split('\0') |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
91 map[f] = bin(n[:40]) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
92 self.mapcache = (node, map) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
93 return map |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
94 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
95 def diff(self, a, b): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
96 # this is sneaky, as we're not actually using a and b |
140 | 97 if self.listcache and self.addlist and self.listcache[0] == a: |
98 | 98 d = mdiff.diff(self.listcache[1], self.addlist, 1) |
99 if mdiff.patch(a, d) != b: | |
100 sys.stderr.write("*** sortdiff failed, falling back ***\n") | |
101 return mdiff.textdiff(a, b) | |
102 return d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
103 else: |
44 | 104 return mdiff.textdiff(a, b) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
105 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
106 def add(self, map, transaction, link, p1=None, p2=None): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
107 files = map.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
108 files.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
109 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
110 self.addlist = ["%s\000%s\n" % (f, hex(map[f])) for f in files] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
111 text = "".join(self.addlist) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
112 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
113 n = self.addrevision(text, transaction, link, p1, p2) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
114 self.mapcache = (n, map) |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
115 self.listcache = (text, self.addlist) |
140 | 116 self.addlist = None |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
117 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
118 return n |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
119 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
120 class changelog(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
121 def __init__(self, opener): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
122 revlog.__init__(self, opener, "00changelog.i", "00changelog.d") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
123 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
124 def extract(self, text): |
37 | 125 if not text: |
40 | 126 return (nullid, "", "0", [], "") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
127 last = text.index("\n\n") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
128 desc = text[last + 2:] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
129 l = text[:last].splitlines() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
130 manifest = bin(l[0]) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
131 user = l[1] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
132 date = l[2] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
133 files = l[3:] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
134 return (manifest, user, date, files, desc) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
135 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
136 def read(self, node): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
137 return self.extract(self.revision(node)) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
138 |
203 | 139 def add(self, manifest, list, desc, transaction, p1=None, p2=None, |
140 user=None, date=None): | |
249 | 141 import socket, time |
203 | 142 user = (user or |
143 os.environ.get("HGUSER") or | |
55
2add70d51441
From: Thomas Arendsen Hein <thomas@intevation.de>
mpm@selenic.com
parents:
48
diff
changeset
|
144 os.environ.get("EMAIL") or |
2add70d51441
From: Thomas Arendsen Hein <thomas@intevation.de>
mpm@selenic.com
parents:
48
diff
changeset
|
145 os.environ.get("LOGNAME", "unknown") + '@' + socket.getfqdn()) |
203 | 146 date = date or "%d %d" % (time.time(), time.timezone) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
147 list.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
148 l = [hex(manifest), user, date] + list + ["", desc] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
149 text = "\n".join(l) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
150 return self.addrevision(text, transaction, self.count(), p1, p2) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
151 |
220 | 152 class dirstate: |
244 | 153 def __init__(self, opener, ui, root): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
154 self.opener = opener |
244 | 155 self.root = root |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
156 self.dirty = 0 |
20 | 157 self.ui = ui |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
158 self.map = None |
227 | 159 self.pl = None |
220 | 160 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
161 def __del__(self): |
220 | 162 if self.dirty: |
163 self.write() | |
164 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
165 def __getitem__(self, key): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
166 try: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
167 return self.map[key] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
168 except TypeError: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
169 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
170 return self[key] |
220 | 171 |
172 def __contains__(self, key): | |
173 if not self.map: self.read() | |
174 return key in self.map | |
175 | |
227 | 176 def parents(self): |
177 if not self.pl: | |
178 self.read() | |
179 return self.pl | |
180 | |
181 def setparents(self, p1, p2 = nullid): | |
182 self.dirty = 1 | |
183 self.pl = p1, p2 | |
184 | |
220 | 185 def state(self, key): |
186 try: | |
187 return self[key][0] | |
188 except KeyError: | |
189 return "?" | |
190 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
191 def read(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
192 if self.map is not None: return self.map |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
193 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
194 self.map = {} |
227 | 195 self.pl = [nullid, nullid] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
196 try: |
220 | 197 st = self.opener("dirstate").read() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
198 except: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
199 |
227 | 200 self.pl = [st[:20], st[20: 40]] |
201 | |
202 pos = 40 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
203 while pos < len(st): |
220 | 204 e = struct.unpack(">cllll", st[pos:pos+17]) |
205 l = e[4] | |
206 pos += 17 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
207 f = st[pos:pos + l] |
220 | 208 self.map[f] = e[:4] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
209 pos += l |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
210 |
220 | 211 def update(self, files, state): |
212 ''' current states: | |
213 n normal | |
231 | 214 m needs merging |
220 | 215 i invalid |
216 r marked for removal | |
217 a marked for addition''' | |
218 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
219 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
220 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
221 self.dirty = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
222 for f in files: |
220 | 223 if state == "r": |
224 self.map[f] = ('r', 0, 0, 0) | |
225 else: | |
226 try: | |
244 | 227 s = os.stat(os.path.join(self.root, f)) |
220 | 228 self.map[f] = (state, s.st_mode, s.st_size, s.st_mtime) |
229 except OSError: | |
230 if state != "i": raise | |
231 self.map[f] = ('r', 0, 0, 0) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
232 |
220 | 233 def forget(self, files): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
234 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
235 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
236 self.dirty = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
237 for f in files: |
20 | 238 try: |
239 del self.map[f] | |
240 except KeyError: | |
220 | 241 self.ui.warn("not in dirstate: %s!\n" % f) |
20 | 242 pass |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
243 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
244 def clear(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
245 self.map = {} |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
246 self.dirty = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
247 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
248 def write(self): |
220 | 249 st = self.opener("dirstate", "w") |
227 | 250 st.write("".join(self.pl)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
251 for f, e in self.map.items(): |
220 | 252 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
253 st.write(e + f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
254 self.dirty = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
255 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
256 def copy(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
257 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
258 return self.map.copy() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
259 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
260 # used to avoid circular references so destructors work |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
261 def opener(base): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
262 p = base |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
263 def o(path, mode="r"): |
15
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
264 if p[:7] == "http://": |
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
265 f = os.path.join(p, urllib.quote(path)) |
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
266 return httprangereader(f) |
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
267 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
268 f = os.path.join(p, path) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
269 |
110
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
270 if mode != "r": |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
271 try: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
272 s = os.stat(f) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
273 except OSError: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
274 d = os.path.dirname(f) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
275 if not os.path.isdir(d): |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
276 os.makedirs(d) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
277 else: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
278 if s.st_nlink > 1: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
279 file(f + ".tmp", "w").write(file(f).read()) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
280 os.rename(f+".tmp", f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
281 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
282 return file(f, mode) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
283 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
284 return o |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
285 |
60 | 286 class localrepository: |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
287 def __init__(self, ui, path=None, create=0): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
288 self.remote = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
289 if path and path[:7] == "http://": |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
290 self.remote = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
291 self.path = path |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
292 else: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
293 if not path: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
294 p = os.getcwd() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
295 while not os.path.isdir(os.path.join(p, ".hg")): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
296 p = os.path.dirname(p) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
297 if p == "/": raise "No repo found" |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
298 path = p |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
299 self.path = os.path.join(path, ".hg") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
300 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
301 self.root = path |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
302 self.ui = ui |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
303 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
304 if create: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
305 os.mkdir(self.path) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
306 os.mkdir(self.join("data")) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
307 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
308 self.opener = opener(self.path) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
309 self.manifest = manifest(self.opener) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
310 self.changelog = changelog(self.opener) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
311 self.ignorelist = None |
67 | 312 self.tags = None |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
313 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
314 if not self.remote: |
244 | 315 self.dirstate = dirstate(self.opener, ui, self.root) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
316 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
317 def ignore(self, f): |
249 | 318 import re |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
319 if self.ignorelist is None: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
320 self.ignorelist = [] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
321 try: |
67 | 322 l = open(os.path.join(self.root, ".hgignore")) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
323 for pat in l: |
9 | 324 if pat != "\n": |
325 self.ignorelist.append(re.compile(pat[:-1])) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
326 except IOError: pass |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
327 for pat in self.ignorelist: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
328 if pat.search(f): return True |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
329 return False |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
330 |
67 | 331 def lookup(self, key): |
332 if self.tags is None: | |
333 self.tags = {} | |
334 try: | |
335 fl = self.file(".hgtags") | |
336 for l in fl.revision(fl.tip()).splitlines(): | |
337 if l: | |
338 n, k = l.split(" ") | |
339 self.tags[k] = bin(n) | |
340 except KeyError: pass | |
341 try: | |
342 return self.tags[key] | |
343 except KeyError: | |
344 return self.changelog.lookup(key) | |
345 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
346 def join(self, f): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
347 return os.path.join(self.path, f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
348 |
244 | 349 def wjoin(self, f): |
350 return os.path.join(self.root, f) | |
351 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
352 def file(self, f): |
192 | 353 if f[0] == '/': f = f[1:] |
144
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
354 return filelog(self.opener, f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
355 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
356 def transaction(self): |
95 | 357 return transaction(self.opener, self.join("journal"), |
358 self.join("undo")) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
359 |
210 | 360 def recover(self): |
225 | 361 lock = self.lock() |
210 | 362 if os.path.exists(self.join("recover")): |
363 self.ui.status("attempting to rollback interrupted transaction\n") | |
364 return rollback(self.opener, self.join("recover")) | |
365 else: | |
366 self.ui.warn("no interrupted transaction available\n") | |
367 | |
368 def undo(self): | |
225 | 369 lock = self.lock() |
210 | 370 if os.path.exists(self.join("undo")): |
220 | 371 f = self.changelog.read(self.changelog.tip())[3] |
210 | 372 self.ui.status("attempting to rollback last transaction\n") |
373 rollback(self.opener, self.join("undo")) | |
374 self.manifest = manifest(self.opener) | |
375 self.changelog = changelog(self.opener) | |
376 | |
220 | 377 self.ui.status("discarding dirstate\n") |
210 | 378 node = self.changelog.tip() |
379 f.sort() | |
380 | |
227 | 381 self.dirstate.setparents(node) |
220 | 382 self.dirstate.update(f, 'i') |
210 | 383 |
163 | 384 else: |
210 | 385 self.ui.warn("no undo information available\n") |
162 | 386 |
161 | 387 def lock(self, wait = 1): |
388 try: | |
389 return lock.lock(self.join("lock"), 0) | |
390 except lock.LockHeld, inst: | |
391 if wait: | |
392 self.ui.warn("waiting for lock held by %s\n" % inst.args[0]) | |
393 return lock.lock(self.join("lock"), wait) | |
394 raise inst | |
395 | |
203 | 396 def rawcommit(self, files, text, user, date, p1=None, p2=None): |
228 | 397 p1 = p1 or self.dirstate.parents()[0] or nullid |
398 p2 = p2 or self.dirstate.parents()[1] or nullid | |
203 | 399 pchange = self.changelog.read(p1) |
400 pmmap = self.manifest.read(pchange[0]) | |
401 tr = self.transaction() | |
402 mmap = {} | |
403 linkrev = self.changelog.count() | |
404 for f in files: | |
405 try: | |
406 t = file(f).read() | |
407 except IOError: | |
408 self.ui.warn("Read file %s error, skipped\n" % f) | |
409 continue | |
410 r = self.file(f) | |
228 | 411 # FIXME - need to find both parents properly |
203 | 412 prev = pmmap.get(f, nullid) |
413 mmap[f] = r.add(t, tr, linkrev, prev) | |
414 | |
415 mnode = self.manifest.add(mmap, tr, linkrev, pchange[0]) | |
416 n = self.changelog.add(mnode, files, text, tr, p1, p2, user ,date, ) | |
417 tr.close() | |
228 | 418 self.dirstate.setparents(p1, p2) |
220 | 419 self.dirstate.clear() |
420 self.dirstate.update(mmap.keys(), "n") | |
203 | 421 |
229 | 422 def commit(self, files = None, text = ""): |
220 | 423 commit = [] |
424 remove = [] | |
425 if files: | |
426 for f in files: | |
427 s = self.dirstate.state(f) | |
244 | 428 if s in 'nmai': |
220 | 429 commit.append(f) |
430 elif s == 'r': | |
431 remove.append(f) | |
432 else: | |
244 | 433 self.ui.warn("%s not tracked!\n" % f) |
220 | 434 else: |
230 | 435 (c, a, d, u) = self.diffdir(self.root) |
220 | 436 commit = c + a |
437 remove = d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
438 |
220 | 439 if not commit and not remove: |
151 | 440 self.ui.status("nothing changed\n") |
441 return | |
442 | |
229 | 443 p1, p2 = self.dirstate.parents() |
444 c1 = self.changelog.read(p1) | |
445 c2 = self.changelog.read(p2) | |
446 m1 = self.manifest.read(c1[0]) | |
447 m2 = self.manifest.read(c2[0]) | |
225 | 448 lock = self.lock() |
151 | 449 tr = self.transaction() |
450 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
451 # check in files |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
452 new = {} |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
453 linkrev = self.changelog.count() |
220 | 454 commit.sort() |
455 for f in commit: | |
83 | 456 self.ui.note(f + "\n") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
457 try: |
244 | 458 t = file(self.wjoin(f)).read() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
459 except IOError: |
220 | 460 self.warn("trouble committing %s!\n" % f) |
461 raise | |
462 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
463 r = self.file(f) |
229 | 464 fp1 = m1.get(f, nullid) |
465 fp2 = m2.get(f, nullid) | |
466 new[f] = r.add(t, tr, linkrev, fp1, fp2) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
467 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
468 # update manifest |
229 | 469 m1.update(new) |
470 for f in remove: del m1[f] | |
471 mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0]) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
472 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
473 # add changeset |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
474 new = new.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
475 new.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
476 |
229 | 477 edittext = text + "\n" + "HG: manifest hash %s\n" % hex(mn) |
185
db3aa85b9379
Add manifest hash to commit messages for easy signing
mpm@selenic.com
parents:
182
diff
changeset
|
478 edittext += "".join(["HG: changed %s\n" % f for f in new]) |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
479 edittext += "".join(["HG: removed %s\n" % f for f in remove]) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
480 edittext = self.ui.edit(edittext) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
481 |
229 | 482 n = self.changelog.add(mn, new, edittext, tr, p1, p2) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
483 tr.close() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
484 |
229 | 485 self.dirstate.setparents(n) |
220 | 486 self.dirstate.update(new, "n") |
487 self.dirstate.forget(remove) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
488 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
489 def checkout(self, node): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
490 # checkout is really dumb at the moment |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
491 # it ought to basically merge |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
492 change = self.changelog.read(node) |
114
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
493 l = self.manifest.read(change[0]).items() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
494 l.sort() |
114
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
495 |
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
496 for f,n in l: |
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
497 if f[0] == "/": continue |
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
498 self.ui.note(f, "\n") |
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
499 t = self.file(f).revision(n) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
500 try: |
244 | 501 file(self.wjoin(f), "w").write(t) |
114
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
502 except IOError: |
82fb6d09f911
Simplify checkout slightly, replace checkdir with os.makedirs
mpm@selenic.com
parents:
113
diff
changeset
|
503 os.makedirs(os.path.dirname(f)) |
244 | 504 file(self.wjoin(f), "w").write(t) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
505 |
227 | 506 self.dirstate.setparents(node) |
220 | 507 self.dirstate.clear() |
508 self.dirstate.update([f for f,n in l], "n") | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
509 |
230 | 510 def diffdir(self, path, changeset = None): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
511 changed = [] |
220 | 512 added = [] |
513 unknown = [] | |
4
ce3bd728b858
Fix exception handling for reading current working version
mpm@selenic.com
parents:
0
diff
changeset
|
514 mf = {} |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
515 |
29 | 516 if changeset: |
517 change = self.changelog.read(changeset) | |
4
ce3bd728b858
Fix exception handling for reading current working version
mpm@selenic.com
parents:
0
diff
changeset
|
518 mf = self.manifest.read(change[0]) |
230 | 519 dc = dict.fromkeys(mf) |
520 else: | |
521 changeset = self.dirstate.parents()[0] | |
522 change = self.changelog.read(changeset) | |
523 mf = self.manifest.read(change[0]) | |
220 | 524 dc = self.dirstate.copy() |
29 | 525 |
526 def fcmp(fn): | |
244 | 527 t1 = file(self.wjoin(fn)).read() |
29 | 528 t2 = self.file(fn).revision(mf[fn]) |
529 return cmp(t1, t2) | |
530 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
531 for dir, subdirs, files in os.walk(self.root): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
532 d = dir[len(self.root)+1:] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
533 if ".hg" in subdirs: subdirs.remove(".hg") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
534 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
535 for f in files: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
536 fn = os.path.join(d, f) |
64 | 537 try: s = os.stat(os.path.join(self.root, fn)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
538 except: continue |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
539 if fn in dc: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
540 c = dc[fn] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
541 del dc[fn] |
220 | 542 if not c: |
29 | 543 if fcmp(fn): |
544 changed.append(fn) | |
230 | 545 elif c[0] == 'i': |
220 | 546 if fn not in mf: |
547 added.append(fn) | |
548 elif fcmp(fn): | |
549 changed.append(fn) | |
231 | 550 elif c[0] == 'm': |
551 changed.append(fn) | |
220 | 552 elif c[0] == 'a': |
553 added.append(fn) | |
554 elif c[0] == 'r': | |
555 unknown.append(fn) | |
556 elif c[2] != s.st_size: | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
557 changed.append(fn) |
220 | 558 elif c[1] != s.st_mode or c[3] != s.st_mtime: |
29 | 559 if fcmp(fn): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
560 changed.append(fn) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
561 else: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
562 if self.ignore(fn): continue |
220 | 563 unknown.append(fn) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
564 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
565 deleted = dc.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
566 deleted.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
567 |
220 | 568 return (changed, added, deleted, unknown) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
569 |
32 | 570 def diffrevs(self, node1, node2): |
33 | 571 changed, added = [], [] |
32 | 572 |
573 change = self.changelog.read(node1) | |
574 mf1 = self.manifest.read(change[0]) | |
33 | 575 change = self.changelog.read(node2) |
32 | 576 mf2 = self.manifest.read(change[0]) |
577 | |
578 for fn in mf2: | |
579 if mf1.has_key(fn): | |
580 if mf1[fn] != mf2[fn]: | |
581 changed.append(fn) | |
582 del mf1[fn] | |
583 else: | |
584 added.append(fn) | |
585 | |
586 deleted = mf1.keys() | |
587 deleted.sort() | |
588 | |
589 return (changed, added, deleted) | |
590 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
591 def add(self, list): |
220 | 592 for f in list: |
244 | 593 p = self.wjoin(f) |
220 | 594 if not os.path.isfile(p): |
595 self.ui.warn("%s does not exist!\n" % f) | |
596 elif self.dirstate.state(f) == 'n': | |
597 self.ui.warn("%s already tracked!\n" % f) | |
598 else: | |
599 self.dirstate.update([f], "a") | |
600 | |
601 def forget(self, list): | |
602 for f in list: | |
603 if self.dirstate.state(f) not in 'ai': | |
604 self.ui.warn("%s not added!\n" % f) | |
605 else: | |
606 self.dirstate.forget([f]) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
607 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
608 def remove(self, list): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
609 for f in list: |
244 | 610 p = self.wjoin(f) |
220 | 611 if os.path.isfile(p): |
612 self.ui.warn("%s still exists!\n" % f) | |
613 elif f not in self.dirstate: | |
614 self.ui.warn("%s not tracked!\n" % f) | |
615 else: | |
616 self.dirstate.update([f], "r") | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
617 |
222 | 618 def heads(self): |
619 return self.changelog.heads() | |
620 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
621 def branches(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
622 if not nodes: nodes = [self.changelog.tip()] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
623 b = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
624 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
625 t = n |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
626 while n: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
627 p = self.changelog.parents(n) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
628 if p[1] != nullid or p[0] == nullid: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
629 b.append((t, n, p[0], p[1])) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
630 break |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
631 n = p[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
632 return b |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
633 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
634 def between(self, pairs): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
635 r = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
636 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
637 for top, bottom in pairs: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
638 n, l, i = top, [], 0 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
639 f = 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
640 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
641 while n != bottom: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
642 p = self.changelog.parents(n)[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
643 if i == f: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
644 l.append(n) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
645 f = f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
646 n = p |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
647 i += 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
648 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
649 r.append(l) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
650 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
651 return r |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
652 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
653 def newer(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
654 m = {} |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
655 nl = [] |
94 | 656 pm = {} |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
657 cl = self.changelog |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
658 t = l = cl.count() |
94 | 659 |
660 # find the lowest numbered node | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
661 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
662 l = min(l, cl.rev(n)) |
94 | 663 m[n] = 1 |
46 | 664 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
665 for i in xrange(l, t): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
666 n = cl.node(i) |
94 | 667 if n in m: # explicitly listed |
668 pm[n] = 1 | |
669 nl.append(n) | |
670 continue | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
671 for p in cl.parents(n): |
94 | 672 if p in pm: # parent listed |
673 pm[n] = 1 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
674 nl.append(n) |
94 | 675 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
676 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
677 return nl |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
678 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
679 def getchangegroup(self, remote): |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
680 m = self.changelog.nodemap |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
681 search = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
682 fetch = [] |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
683 seen = {} |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
684 seenbranch = {} |
192 | 685 |
190
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
686 # if we have an empty repo, fetch everything |
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
687 if self.changelog.tip() == nullid: |
222 | 688 self.ui.status("requesting all changes\n") |
190
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
689 return remote.changegroup([nullid]) |
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
690 |
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
691 # otherwise, assume we're closer to the tip than the root |
222 | 692 self.ui.status("searching for changes\n") |
693 heads = remote.heads() | |
694 unknown = [] | |
695 for h in heads: | |
696 if h not in m: | |
697 unknown.append(h) | |
46 | 698 |
222 | 699 if not unknown: |
192 | 700 self.ui.status("nothing to do!\n") |
60 | 701 return None |
222 | 702 |
703 unknown = remote.branches(unknown) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
704 while unknown: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
705 n = unknown.pop(0) |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
706 seen[n[0]] = 1 |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
707 |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
708 self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
709 if n == nullid: break |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
710 if n in seenbranch: |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
711 self.ui.debug("branch already found\n") |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
712 continue |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
713 if n[1] and n[1] in m: # do we know the base? |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
714 self.ui.debug("found incomplete branch %s:%s\n" |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
715 % (short(n[0]), short(n[1]))) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
716 search.append(n) # schedule branch range for scanning |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
717 seenbranch[n] = 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
718 else: |
94 | 719 if n[2] in m and n[3] in m: |
720 if n[1] not in fetch: | |
721 self.ui.debug("found new changeset %s\n" % | |
722 short(n[1])) | |
723 fetch.append(n[1]) # earliest unknown | |
724 continue | |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
725 |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
726 r = [] |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
727 for a in n[2:4]: |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
728 if a not in seen: r.append(a) |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
729 |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
730 if r: |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
731 self.ui.debug("requesting %s\n" % |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
732 " ".join(map(short, r))) |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
733 for b in remote.branches(r): |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
734 self.ui.debug("received %s:%s\n" % |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
735 (short(b[0]), short(b[1]))) |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
736 if b[0] not in m and b[0] not in seen: |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
737 unknown.append(b) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
738 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
739 while search: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
740 n = search.pop(0) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
741 l = remote.between([(n[0], n[1])])[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
742 p = n[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
743 f = 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
744 for i in l + [n[1]]: |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
745 if i in m: |
85 | 746 if f <= 2: |
83 | 747 self.ui.debug("found new branch changeset %s\n" % |
748 short(p)) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
749 fetch.append(p) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
750 else: |
83 | 751 self.ui.debug("narrowed branch search to %s:%s\n" |
752 % (short(p), short(i))) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
753 search.append((p, i)) |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
754 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
755 p, f = i, f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
756 |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
757 for f in fetch: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
758 if f in m: |
83 | 759 raise "already have", short(f[:4]) |
760 | |
94 | 761 self.ui.note("adding new changesets starting at " + |
83 | 762 " ".join([short(f) for f in fetch]) + "\n") |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
763 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
764 return remote.changegroup(fetch) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
765 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
766 def changegroup(self, basenodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
767 nodes = self.newer(basenodes) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
768 |
46 | 769 # construct the link map |
770 linkmap = {} | |
771 for n in nodes: | |
772 linkmap[self.changelog.rev(n)] = n | |
773 | |
774 # construct a list of all changed files | |
775 changed = {} | |
776 for n in nodes: | |
777 c = self.changelog.read(n) | |
778 for f in c[3]: | |
779 changed[f] = 1 | |
780 changed = changed.keys() | |
781 changed.sort() | |
782 | |
783 # the changegroup is changesets + manifests + all file revs | |
784 revs = [ self.changelog.rev(n) for n in nodes ] | |
785 | |
192 | 786 for y in self.changelog.group(linkmap): yield y |
787 for y in self.manifest.group(linkmap): yield y | |
46 | 788 for f in changed: |
192 | 789 yield struct.pack(">l", len(f) + 4) + f |
46 | 790 g = self.file(f).group(linkmap) |
192 | 791 for y in g: |
792 yield y | |
46 | 793 |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
794 def addchangegroup(self, generator): |
222 | 795 |
796 class genread: | |
797 def __init__(self, generator): | |
798 self.g = generator | |
799 self.buf = "" | |
800 def read(self, l): | |
801 while l > len(self.buf): | |
802 try: | |
803 self.buf += self.g.next() | |
804 except StopIteration: | |
805 break | |
806 d, self.buf = self.buf[:l], self.buf[l:] | |
807 return d | |
808 | |
809 def getchunk(): | |
810 d = source.read(4) | |
811 if not d: return "" | |
812 l = struct.unpack(">l", d)[0] | |
813 if l <= 4: return "" | |
814 return source.read(l - 4) | |
815 | |
816 def getgroup(): | |
817 while 1: | |
818 c = getchunk() | |
819 if not c: break | |
820 yield c | |
821 | |
822 def csmap(x): | |
823 self.ui.debug("add changeset %s\n" % short(x)) | |
824 return self.changelog.count() | |
825 | |
826 def revmap(x): | |
827 return self.changelog.rev(x) | |
828 | |
829 if not generator: return | |
830 changesets = files = revisions = 0 | |
225 | 831 |
222 | 832 source = genread(generator) |
225 | 833 lock = self.lock() |
222 | 834 tr = self.transaction() |
835 | |
836 # pull off the changeset group | |
837 self.ui.status("adding changesets\n") | |
838 co = self.changelog.tip() | |
224
ccbcc4d76f81
fix bad assumption about uniqueness of file versions
mpm@selenic.com
parents:
223
diff
changeset
|
839 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique |
222 | 840 changesets = self.changelog.rev(cn) - self.changelog.rev(co) |
841 | |
842 # pull off the manifest group | |
843 self.ui.status("adding manifests\n") | |
844 mm = self.manifest.tip() | |
845 mo = self.manifest.addgroup(getgroup(), revmap, tr) | |
846 | |
847 # process the files | |
848 self.ui.status("adding file revisions\n") | |
849 while 1: | |
850 f = getchunk() | |
851 if not f: break | |
852 self.ui.debug("adding %s revisions\n" % f) | |
853 fl = self.file(f) | |
854 o = fl.tip() | |
855 n = fl.addgroup(getgroup(), revmap, tr) | |
856 revisions += fl.rev(n) - fl.rev(o) | |
857 files += 1 | |
858 | |
859 self.ui.status(("modified %d files, added %d changesets" + | |
860 " and %d new revisions\n") | |
861 % (files, changesets, revisions)) | |
862 | |
863 tr.close() | |
864 return | |
865 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
866 def resolve(self, node): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
867 pl = self.dirstate.parents() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
868 if pl[1] != nullid: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
869 self.ui.warn("last merge not committed") |
46 | 870 return |
871 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
872 p1, p2 = pl[0], node |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
873 m1n = self.changelog.read(p1)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
874 m2n = self.changelog.read(p2)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
875 man = self.manifest.ancestor(m1n, m2n) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
876 m1 = self.manifest.read(m1n) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
877 m2 = self.manifest.read(m2n) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
878 ma = self.manifest.read(man) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
879 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
880 (c, a, d, u) = self.diffdir(self.root) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
881 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
882 # resolve the manifest to determine which files |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
883 # we care about merging |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
884 self.ui.status("resolving manifests\n") |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
885 self.ui.debug(" ancestor %s local %s remote %s\n" % |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
886 (short(man), short(m1n), short(m2n))) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
887 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
888 merge = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
889 get = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
890 remove = [] |
46 | 891 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
892 # construct a working dir manifest |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
893 mw = m1.copy() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
894 for f in a + c: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
895 mw[f] = nullid |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
896 for f in d: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
897 del mw[f] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
898 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
899 for f, n in mw.iteritems(): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
900 if f in m2: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
901 if n != m2[f]: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
902 self.ui.debug(" %s versions differ, do resolve\n" % f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
903 merge[f] = (m1.get(f, nullid), m2[f]) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
904 del m2[f] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
905 elif f in ma: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
906 if n != ma[f]: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
907 r = self.ui.prompt( |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
908 (" local changed %s which remote deleted\n" % f) + |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
909 "(k)eep or (d)elete?", "[kd]", "k") |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
910 if r == "d": |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
911 remove.append(f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
912 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
913 self.ui.debug("other deleted %s\n" % f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
914 pass # other deleted it |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
915 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
916 self.ui.debug("local created %s\n" %f) |
46 | 917 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
918 for f, n in m2.iteritems(): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
919 if f in ma: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
920 if n != ma[f]: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
921 r = self.ui.prompt( |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
922 ("remote changed %s which local deleted\n" % f) + |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
923 "(k)eep or (d)elete?", "[kd]", "k") |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
924 if r == "d": remove.append(f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
925 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
926 pass # probably safe |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
927 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
928 self.ui.debug("remote created %s, do resolve\n" % f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
929 get[f] = n |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
930 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
931 del mw, m1, m2, ma |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
932 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
933 self.dirstate.setparents(p1, p2) |
191
d7e859cf2f1b
merge: add count of new manifests, files, and revisions
mpm@selenic.com
parents:
190
diff
changeset
|
934 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
935 # get the files we don't need to change |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
936 files = get.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
937 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
938 for f in files: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
939 if f[0] == "/": continue |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
940 self.ui.note(f, "\n") |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
941 t = self.file(f).revision(get[f]) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
942 try: |
244 | 943 file(self.wjoin(f), "w").write(t) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
944 except IOError: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
945 os.makedirs(os.path.dirname(f)) |
244 | 946 file(self.wjoin(f), "w").write(t) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
947 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
948 # we have to remember what files we needed to get/change |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
949 # because any file that's different from either one of its |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
950 # parents must be in the changeset |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
951 self.dirstate.update(files, 'm') |
46 | 952 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
953 # merge the tricky bits |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
954 files = merge.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
955 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
956 for f in files: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
957 m, o = merge[f] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
958 self.merge3(f, m, o) |
46 | 959 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
960 # same here |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
961 self.dirstate.update(files, 'm') |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
962 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
963 for f in remove: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
964 self.ui.note("removing %s\n" % f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
965 #os.unlink(f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
966 self.dirstate.update(remove, 'r') |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
967 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
968 def merge3(self, fn, my, other): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
969 """perform a 3-way merge in the working directory""" |
249 | 970 |
971 import tempfile | |
96 | 972 |
973 def temp(prefix, node): | |
974 pre = "%s~%s." % (os.path.basename(fn), prefix) | |
975 (fd, name) = tempfile.mkstemp("", pre) | |
976 f = os.fdopen(fd, "w") | |
977 f.write(fl.revision(node)) | |
978 f.close() | |
979 return name | |
980 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
981 fl = self.file(fn) |
96 | 982 base = fl.ancestor(my, other) |
244 | 983 a = self.wjoin(fn) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
984 b = temp("other", other) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
985 c = temp("base", base) |
96 | 986 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
987 self.ui.note("resolving %s\n" % fn) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
988 self.ui.debug("file %s: other %s ancestor %s\n" % |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
989 (fn, short(other), short(base))) |
96 | 990 |
240 | 991 cmd = os.environ.get("HGMERGE", "hgmerge") |
992 r = os.system("%s %s %s %s" % (cmd, a, b, c)) | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
993 if r: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
994 self.ui.warn("merging %s failed!\n" % f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
995 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
996 os.unlink(b) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
997 os.unlink(c) |
96 | 998 |
247 | 999 def verify(self): |
1000 filelinkrevs = {} | |
1001 filenodes = {} | |
1002 manifestchangeset = {} | |
1003 changesets = revisions = files = 0 | |
1004 errors = 0 | |
1005 | |
1006 self.ui.status("checking changesets\n") | |
1007 for i in range(self.changelog.count()): | |
1008 changesets += 1 | |
1009 n = self.changelog.node(i) | |
1010 for p in self.changelog.parents(n): | |
1011 if p not in self.changelog.nodemap: | |
1012 self.ui.warn("changeset %s has unknown parent %s\n" % | |
1013 (short(n), short(p))) | |
1014 errors += 1 | |
1015 try: | |
1016 changes = self.changelog.read(n) | |
1017 except Exception, inst: | |
1018 self.ui.warn("unpacking changeset %s: %s\n" % (short(n), inst)) | |
1019 errors += 1 | |
1020 | |
1021 manifestchangeset[changes[0]] = n | |
1022 for f in changes[3]: | |
1023 filelinkrevs.setdefault(f, []).append(i) | |
1024 | |
1025 self.ui.status("checking manifests\n") | |
1026 for i in range(self.manifest.count()): | |
1027 n = self.manifest.node(i) | |
1028 for p in self.manifest.parents(n): | |
1029 if p not in self.manifest.nodemap: | |
1030 self.ui.warn("manifest %s has unknown parent %s\n" % | |
1031 (short(n), short(p))) | |
1032 errors += 1 | |
1033 ca = self.changelog.node(self.manifest.linkrev(n)) | |
1034 cc = manifestchangeset[n] | |
1035 if ca != cc: | |
1036 self.ui.warn("manifest %s points to %s, not %s\n" % | |
1037 (hex(n), hex(ca), hex(cc))) | |
1038 errors += 1 | |
1039 | |
1040 try: | |
1041 delta = mdiff.patchtext(self.manifest.delta(n)) | |
1042 except KeyboardInterrupt: | |
1043 print "aborted" | |
1044 sys.exit(0) | |
1045 except Exception, inst: | |
1046 self.ui.warn("unpacking manifest %s: %s\n" | |
1047 % (short(n), inst)) | |
1048 errors += 1 | |
1049 | |
1050 ff = [ l.split('\0') for l in delta.splitlines() ] | |
1051 for f, fn in ff: | |
1052 filenodes.setdefault(f, {})[bin(fn)] = 1 | |
1053 | |
1054 self.ui.status("crosschecking files in changesets and manifests\n") | |
1055 for f in filenodes: | |
1056 if f not in filelinkrevs: | |
1057 self.ui.warn("file %s in manifest but not in changesets\n" % f) | |
1058 errors += 1 | |
1059 | |
1060 for f in filelinkrevs: | |
1061 if f not in filenodes: | |
1062 self.ui.warn("file %s in changeset but not in manifest\n" % f) | |
1063 errors += 1 | |
1064 | |
1065 self.ui.status("checking files\n") | |
1066 ff = filenodes.keys() | |
1067 ff.sort() | |
1068 for f in ff: | |
1069 if f == "/dev/null": continue | |
1070 files += 1 | |
1071 fl = self.file(f) | |
1072 nodes = { nullid: 1 } | |
1073 for i in range(fl.count()): | |
1074 revisions += 1 | |
1075 n = fl.node(i) | |
1076 | |
1077 if n not in filenodes[f]: | |
1078 self.ui.warn("%s: %d:%s not in manifests\n" | |
1079 % (f, i, short(n))) | |
1080 print len(filenodes[f].keys()), fl.count(), f | |
1081 errors += 1 | |
1082 else: | |
1083 del filenodes[f][n] | |
1084 | |
1085 flr = fl.linkrev(n) | |
1086 if flr not in filelinkrevs[f]: | |
1087 self.ui.warn("%s:%s points to unexpected changeset %d\n" | |
1088 % (f, short(n), fl.linkrev(n))) | |
1089 errors += 1 | |
1090 else: | |
1091 filelinkrevs[f].remove(flr) | |
1092 | |
1093 # verify contents | |
1094 try: | |
1095 t = fl.read(n) | |
1096 except Exception, inst: | |
1097 self.ui.warn("unpacking file %s %s: %s\n" | |
1098 % (f, short(n), inst)) | |
1099 errors += 1 | |
1100 | |
1101 # verify parents | |
1102 (p1, p2) = fl.parents(n) | |
1103 if p1 not in nodes: | |
1104 self.ui.warn("file %s:%s unknown parent 1 %s" % | |
1105 (f, short(n), short(p1))) | |
1106 errors += 1 | |
1107 if p2 not in nodes: | |
1108 self.ui.warn("file %s:%s unknown parent 2 %s" % | |
1109 (f, short(n), short(p1))) | |
1110 errors += 1 | |
1111 nodes[n] = 1 | |
1112 | |
1113 # cross-check | |
1114 for node in filenodes[f]: | |
1115 self.ui.warn("node %s in manifests not in %s\n" | |
1116 % (hex(n), f)) | |
1117 errors += 1 | |
1118 | |
1119 self.ui.status("%d files, %d changesets, %d total revisions\n" % | |
1120 (files, changesets, revisions)) | |
1121 | |
1122 if errors: | |
1123 self.ui.warn("%d integrity errors encountered!\n" % errors) | |
1124 return 1 | |
1125 | |
60 | 1126 class remoterepository: |
1127 def __init__(self, ui, path): | |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1128 self.url = path |
60 | 1129 self.ui = ui |
1130 | |
1131 def do_cmd(self, cmd, **args): | |
83 | 1132 self.ui.debug("sending %s command\n" % cmd) |
60 | 1133 q = {"cmd": cmd} |
1134 q.update(args) | |
1135 qs = urllib.urlencode(q) | |
1136 cu = "%s?%s" % (self.url, qs) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1137 return urllib.urlopen(cu) |
60 | 1138 |
222 | 1139 def heads(self): |
1140 d = self.do_cmd("heads").read() | |
1141 try: | |
1142 return map(bin, d[:-1].split(" ")) | |
1143 except: | |
1144 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1145 raise | |
1146 | |
60 | 1147 def branches(self, nodes): |
1148 n = " ".join(map(hex, nodes)) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1149 d = self.do_cmd("branches", nodes=n).read() |
217 | 1150 try: |
1151 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] | |
1152 return br | |
1153 except: | |
1154 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1155 raise | |
60 | 1156 |
1157 def between(self, pairs): | |
1158 n = "\n".join(["-".join(map(hex, p)) for p in pairs]) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1159 d = self.do_cmd("between", pairs=n).read() |
217 | 1160 try: |
1161 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ] | |
1162 return p | |
1163 except: | |
1164 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1165 raise | |
60 | 1166 |
1167 def changegroup(self, nodes): | |
1168 n = " ".join(map(hex, nodes)) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1169 zd = zlib.decompressobj() |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1170 f = self.do_cmd("changegroup", roots=n) |
192 | 1171 bytes = 0 |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1172 while 1: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1173 d = f.read(4096) |
192 | 1174 bytes += len(d) |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1175 if not d: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1176 yield zd.flush() |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1177 break |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1178 yield zd.decompress(d) |
192 | 1179 self.ui.note("%d bytes of data transfered\n" % bytes) |
60 | 1180 |
1181 def repository(ui, path=None, create=0): | |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1182 if path and path[:7] == "http://": |
249 | 1183 import urllib, urllib2 |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1184 return remoterepository(ui, path) |
60 | 1185 if path and path[:5] == "hg://": |
249 | 1186 import urllib, urllib2 |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1187 return remoterepository(ui, path.replace("hg://", "http://")) |
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1188 if path and path[:11] == "old-http://": |
249 | 1189 import urllib, urllib2 |
1190 from mercurial import byterange | |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1191 return localrepository(ui, path.replace("old-http://", "http://")) |
60 | 1192 else: |
1193 return localrepository(ui, path, create) | |
1194 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1195 class httprangereader: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1196 def __init__(self, url): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1197 self.url = url |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1198 self.pos = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1199 def seek(self, pos): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1200 self.pos = pos |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1201 def read(self, bytes=None): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1202 opener = urllib2.build_opener(byterange.HTTPRangeHandler()) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1203 urllib2.install_opener(opener) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1204 req = urllib2.Request(self.url) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1205 end = '' |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1206 if bytes: end = self.pos + bytes |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1207 req.add_header('Range', 'bytes=%d-%s' % (self.pos, end)) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1208 f = urllib2.urlopen(req) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1209 return f.read() |