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