Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/hg.py @ 859:6390c377a9e6
Trap OSError when deleting env vars
On the other OS, it seems that case insensitivity for
environment vars can bite users when using some unknown
combination of python 2.4.1 and win2kSP4+minsys (and
probably other vversions of these softwares).
The best way to avoid problems in those weird cases is to
ignore OSError exception during env var deletion.
author | Edouard Gomez <ed.gomez@free.fr> |
---|---|
date | Tue, 09 Aug 2005 09:36:34 -0800 |
parents | fbe964ae7325 |
children | 6d6095823b82 c2e77581bc84 9a0af739cf55 bc9ca4d51d23 |
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 |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
418
diff
changeset
|
9 import util |
262 | 10 from revlog import * |
11 from demandload import * | |
12 demandload(globals(), "re lock urllib urllib2 transaction time socket") | |
765 | 13 demandload(globals(), "tempfile httprangereader bdiff urlparse") |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
14 demandload(globals(), "bisect select") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
15 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
16 class filelog(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
17 def __init__(self, opener, path): |
144
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
18 revlog.__init__(self, opener, |
786
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
19 os.path.join("data", self.encodedir(path + ".i")), |
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
20 os.path.join("data", self.encodedir(path + ".d"))) |
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
21 |
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
22 # This avoids a collision between a file named foo and a dir named |
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
23 # foo.i or foo.d |
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
24 def encodedir(self, path): |
856
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
25 return (path |
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
26 .replace(".hg/", ".hg.hg/") |
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
27 .replace(".i/", ".i.hg/") |
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
28 .replace(".d/", ".d.hg/")) |
786
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
29 |
902b12d55751
Fix the directory and revlog collision problem
mpm@selenic.com
parents:
785
diff
changeset
|
30 def decodedir(self, path): |
856
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
31 return (path |
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
32 .replace(".d.hg/", ".d/") |
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
33 .replace(".i.hg/", ".i/") |
fbe964ae7325
Fixed encoding of directories ending in .d or .i:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
839
diff
changeset
|
34 .replace(".hg.hg/", ".hg/")) |
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): |
360 | 37 t = self.revision(node) |
686
d7d68d27ebe5
Reapply startswith() changes that got lost with stale edit
Matt Mackall <mpm@selenic.com>
parents:
681
diff
changeset
|
38 if not t.startswith('\1\n'): |
360 | 39 return t |
40 s = t.find('\1\n', 2) | |
41 return t[s+2:] | |
42 | |
43 def readmeta(self, node): | |
44 t = self.revision(node) | |
686
d7d68d27ebe5
Reapply startswith() changes that got lost with stale edit
Matt Mackall <mpm@selenic.com>
parents:
681
diff
changeset
|
45 if not t.startswith('\1\n'): |
360 | 46 return t |
47 s = t.find('\1\n', 2) | |
48 mt = t[2:s] | |
49 for l in mt.splitlines(): | |
50 k, v = l.split(": ", 1) | |
51 m[k] = v | |
52 return m | |
53 | |
54 def add(self, text, meta, transaction, link, p1=None, p2=None): | |
686
d7d68d27ebe5
Reapply startswith() changes that got lost with stale edit
Matt Mackall <mpm@selenic.com>
parents:
681
diff
changeset
|
55 if meta or text.startswith('\1\n'): |
360 | 56 mt = "" |
57 if meta: | |
58 mt = [ "%s: %s\n" % (k, v) for k,v in meta.items() ] | |
59 text = "\1\n" + "".join(mt) + "\1\n" + text | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
60 return self.addrevision(text, transaction, link, p1, p2) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
61 |
79 | 62 def annotate(self, node): |
199 | 63 |
64 def decorate(text, rev): | |
436 | 65 return ([rev] * len(text.splitlines()), text) |
199 | 66 |
67 def pair(parent, child): | |
436 | 68 for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]): |
471 | 69 child[0][b1:b2] = parent[0][a1:a2] |
70 return child | |
199 | 71 |
200 | 72 # find all ancestors |
216
201115f2859b
hg annotate: actually annotate the given version
mpm@selenic.com
parents:
210
diff
changeset
|
73 needed = {node:1} |
199 | 74 visit = [node] |
75 while visit: | |
76 n = visit.pop(0) | |
77 for p in self.parents(n): | |
78 if p not in needed: | |
79 needed[p] = 1 | |
80 visit.append(p) | |
200 | 81 else: |
82 # count how many times we'll use this | |
83 needed[p] += 1 | |
199 | 84 |
200 | 85 # sort by revision which is a topological order |
471 | 86 visit = [ (self.rev(n), n) for n in needed.keys() ] |
199 | 87 visit.sort() |
88 hist = {} | |
89 | |
471 | 90 for r,n in visit: |
199 | 91 curr = decorate(self.read(n), self.linkrev(n)) |
92 for p in self.parents(n): | |
93 if p != nullid: | |
94 curr = pair(hist[p], curr) | |
200 | 95 # trim the history of unneeded revs |
96 needed[p] -= 1 | |
97 if not needed[p]: | |
98 del hist[p] | |
199 | 99 hist[n] = curr |
100 | |
436 | 101 return zip(hist[n][0], hist[n][1].splitlines(1)) |
79 | 102 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
103 class manifest(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
104 def __init__(self, opener): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
105 self.mapcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
106 self.listcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
107 self.addlist = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
108 revlog.__init__(self, opener, "00manifest.i", "00manifest.d") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
109 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
110 def read(self, node): |
313 | 111 if node == nullid: return {} # don't upset local cache |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
112 if self.mapcache and self.mapcache[0] == node: |
561 | 113 return self.mapcache[1] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
114 text = self.revision(node) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
115 map = {} |
276 | 116 flag = {} |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
117 self.listcache = (text, text.splitlines(1)) |
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
118 for l in self.listcache[1]: |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
119 (f, n) = l.split('\0') |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
120 map[f] = bin(n[:40]) |
276 | 121 flag[f] = (n[40:-1] == "x") |
122 self.mapcache = (node, map, flag) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
123 return map |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
124 |
276 | 125 def readflags(self, node): |
313 | 126 if node == nullid: return {} # don't upset local cache |
358
9f4077d7ef6f
[PATCH] manifest.readflags performance buglet
mpm@selenic.com
parents:
350
diff
changeset
|
127 if not self.mapcache or self.mapcache[0] != node: |
276 | 128 self.read(node) |
129 return self.mapcache[2] | |
130 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
131 def diff(self, a, b): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
132 # this is sneaky, as we're not actually using a and b |
140 | 133 if self.listcache and self.addlist and self.listcache[0] == a: |
98 | 134 d = mdiff.diff(self.listcache[1], self.addlist, 1) |
135 if mdiff.patch(a, d) != b: | |
136 sys.stderr.write("*** sortdiff failed, falling back ***\n") | |
137 return mdiff.textdiff(a, b) | |
138 return d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
139 else: |
44 | 140 return mdiff.textdiff(a, b) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
141 |
741 | 142 def add(self, map, flags, transaction, link, p1=None, p2=None, |
143 changed=None): | |
644 | 144 # directly generate the mdiff delta from the data collected during |
145 # the bisect loop below | |
146 def gendelta(delta): | |
147 i = 0 | |
148 result = [] | |
149 while i < len(delta): | |
150 start = delta[i][2] | |
151 end = delta[i][3] | |
152 l = delta[i][4] | |
153 if l == None: | |
154 l = "" | |
741 | 155 while i < len(delta) - 1 and start <= delta[i+1][2] \ |
156 and end >= delta[i+1][2]: | |
644 | 157 if delta[i+1][3] > end: |
158 end = delta[i+1][3] | |
159 if delta[i+1][4]: | |
160 l += delta[i+1][4] | |
161 i += 1 | |
162 result.append(struct.pack(">lll", start, end, len(l)) + l) | |
163 i += 1 | |
164 return result | |
165 | |
166 # apply the changes collected during the bisect loop to our addlist | |
167 def addlistdelta(addlist, delta): | |
168 # apply the deltas to the addlist. start from the bottom up | |
169 # so changes to the offsets don't mess things up. | |
170 i = len(delta) | |
171 while i > 0: | |
172 i -= 1 | |
173 start = delta[i][0] | |
174 end = delta[i][1] | |
175 if delta[i][4]: | |
176 addlist[start:end] = [delta[i][4]] | |
177 else: | |
178 del addlist[start:end] | |
179 return addlist | |
180 | |
181 # calculate the byte offset of the start of each line in the | |
182 # manifest | |
183 def calcoffsets(addlist): | |
184 offsets = [0] * (len(addlist) + 1) | |
185 offset = 0 | |
186 i = 0 | |
187 while i < len(addlist): | |
188 offsets[i] = offset | |
189 offset += len(addlist[i]) | |
190 i += 1 | |
191 offsets[i] = offset | |
192 return offsets | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
193 |
644 | 194 # if we're using the listcache, make sure it is valid and |
195 # parented by the same node we're diffing against | |
741 | 196 if not changed or not self.listcache or not p1 or \ |
197 self.mapcache[0] != p1: | |
644 | 198 files = map.keys() |
199 files.sort() | |
200 | |
201 self.addlist = ["%s\000%s%s\n" % | |
202 (f, hex(map[f]), flags[f] and "x" or '') | |
203 for f in files] | |
204 cachedelta = None | |
205 else: | |
206 addlist = self.listcache[1] | |
207 | |
208 # find the starting offset for each line in the add list | |
209 offsets = calcoffsets(addlist) | |
210 | |
211 # combine the changed lists into one list for sorting | |
212 work = [[x, 0] for x in changed[0]] | |
213 work[len(work):] = [[x, 1] for x in changed[1]] | |
214 work.sort() | |
215 | |
216 delta = [] | |
217 bs = 0 | |
218 | |
219 for w in work: | |
220 f = w[0] | |
741 | 221 # bs will either be the index of the item or the insert point |
644 | 222 bs = bisect.bisect(addlist, f, bs) |
223 if bs < len(addlist): | |
224 fn = addlist[bs][:addlist[bs].index('\0')] | |
225 else: | |
226 fn = None | |
227 if w[1] == 0: | |
741 | 228 l = "%s\000%s%s\n" % (f, hex(map[f]), |
229 flags[f] and "x" or '') | |
644 | 230 else: |
231 l = None | |
232 start = bs | |
233 if fn != f: | |
234 # item not found, insert a new one | |
659 | 235 end = bs |
644 | 236 if w[1] == 1: |
713
7c385bd5f993
Added missing newline after two error messages.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
705
diff
changeset
|
237 sys.stderr.write("failed to remove %s from manifest\n" |
7c385bd5f993
Added missing newline after two error messages.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
705
diff
changeset
|
238 % f) |
644 | 239 sys.exit(1) |
240 else: | |
241 # item is found, replace/delete the existing line | |
242 end = bs + 1 | |
243 delta.append([start, end, offsets[start], offsets[end], l]) | |
244 | |
245 self.addlist = addlistdelta(addlist, delta) | |
246 if self.mapcache[0] == self.tip(): | |
247 cachedelta = "".join(gendelta(delta)) | |
248 else: | |
249 cachedelta = None | |
250 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
251 text = "".join(self.addlist) |
644 | 252 if cachedelta and mdiff.patch(self.listcache[0], cachedelta) != text: |
713
7c385bd5f993
Added missing newline after two error messages.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
705
diff
changeset
|
253 sys.stderr.write("manifest delta failure\n") |
644 | 254 sys.exit(1) |
255 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) | |
302 | 256 self.mapcache = (n, map, flags) |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
257 self.listcache = (text, self.addlist) |
140 | 258 self.addlist = None |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
259 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
260 return n |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
261 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
262 class changelog(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
263 def __init__(self, opener): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
264 revlog.__init__(self, opener, "00changelog.i", "00changelog.d") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
265 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
266 def extract(self, text): |
37 | 267 if not text: |
40 | 268 return (nullid, "", "0", [], "") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
269 last = text.index("\n\n") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
270 desc = text[last + 2:] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
271 l = text[:last].splitlines() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
272 manifest = bin(l[0]) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
273 user = l[1] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
274 date = l[2] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
275 files = l[3:] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
276 return (manifest, user, date, files, desc) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
277 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
278 def read(self, node): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
279 return self.extract(self.revision(node)) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
280 |
203 | 281 def add(self, manifest, list, desc, transaction, p1=None, p2=None, |
282 user=None, date=None): | |
283 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
|
284 list.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
285 l = [hex(manifest), user, date] + list + ["", desc] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
286 text = "\n".join(l) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
287 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
|
288 |
220 | 289 class dirstate: |
244 | 290 def __init__(self, opener, ui, root): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
291 self.opener = opener |
244 | 292 self.root = root |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
293 self.dirty = 0 |
20 | 294 self.ui = ui |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
295 self.map = None |
227 | 296 self.pl = None |
363 | 297 self.copies = {} |
723 | 298 self.ignorefunc = None |
299 | |
300 def wjoin(self, f): | |
301 return os.path.join(self.root, f) | |
302 | |
303 def ignore(self, f): | |
304 if not self.ignorefunc: | |
305 bigpat = [] | |
306 try: | |
307 l = file(self.wjoin(".hgignore")) | |
308 for pat in l: | |
309 if pat != "\n": | |
310 p = util.pconvert(pat[:-1]) | |
311 try: | |
312 r = re.compile(p) | |
313 except: | |
314 self.ui.warn("ignoring invalid ignore" | |
315 + " regular expression '%s'\n" % p) | |
316 else: | |
317 bigpat.append(util.pconvert(pat[:-1])) | |
318 except IOError: pass | |
319 | |
735
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
320 if bigpat: |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
321 s = "(?:%s)" % (")|(?:".join(bigpat)) |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
322 r = re.compile(s) |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
323 self.ignorefunc = r.search |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
324 else: |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
325 self.ignorefunc = util.never |
723 | 326 |
327 return self.ignorefunc(f) | |
220 | 328 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
329 def __del__(self): |
220 | 330 if self.dirty: |
331 self.write() | |
332 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
333 def __getitem__(self, key): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
334 try: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
335 return self.map[key] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
336 except TypeError: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
337 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
338 return self[key] |
220 | 339 |
340 def __contains__(self, key): | |
341 if not self.map: self.read() | |
342 return key in self.map | |
343 | |
227 | 344 def parents(self): |
345 if not self.pl: | |
346 self.read() | |
347 return self.pl | |
348 | |
723 | 349 def markdirty(self): |
350 if not self.dirty: | |
351 self.dirty = 1 | |
352 | |
227 | 353 def setparents(self, p1, p2 = nullid): |
723 | 354 self.markdirty() |
227 | 355 self.pl = p1, p2 |
356 | |
220 | 357 def state(self, key): |
358 try: | |
359 return self[key][0] | |
360 except KeyError: | |
361 return "?" | |
362 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
363 def read(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
364 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
|
365 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
366 self.map = {} |
227 | 367 self.pl = [nullid, nullid] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
368 try: |
220 | 369 st = self.opener("dirstate").read() |
311 | 370 if not st: return |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
371 except: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
372 |
227 | 373 self.pl = [st[:20], st[20: 40]] |
374 | |
375 pos = 40 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
376 while pos < len(st): |
220 | 377 e = struct.unpack(">cllll", st[pos:pos+17]) |
378 l = e[4] | |
379 pos += 17 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
380 f = st[pos:pos + l] |
515 | 381 if '\0' in f: |
363 | 382 f, c = f.split('\0') |
383 self.copies[f] = c | |
220 | 384 self.map[f] = e[:4] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
385 pos += l |
363 | 386 |
387 def copy(self, source, dest): | |
388 self.read() | |
723 | 389 self.markdirty() |
363 | 390 self.copies[dest] = source |
391 | |
392 def copied(self, file): | |
393 return self.copies.get(file, None) | |
515 | 394 |
220 | 395 def update(self, files, state): |
396 ''' current states: | |
397 n normal | |
231 | 398 m needs merging |
220 | 399 r marked for removal |
400 a marked for addition''' | |
401 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
402 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
403 self.read() |
723 | 404 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
405 for f in files: |
220 | 406 if state == "r": |
407 self.map[f] = ('r', 0, 0, 0) | |
408 else: | |
253 | 409 s = os.stat(os.path.join(self.root, f)) |
410 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
|
411 |
220 | 412 def forget(self, files): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
413 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
414 self.read() |
723 | 415 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
416 for f in files: |
20 | 417 try: |
418 del self.map[f] | |
419 except KeyError: | |
220 | 420 self.ui.warn("not in dirstate: %s!\n" % f) |
20 | 421 pass |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
422 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
423 def clear(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
424 self.map = {} |
723 | 425 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
426 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
427 def write(self): |
220 | 428 st = self.opener("dirstate", "w") |
227 | 429 st.write("".join(self.pl)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
430 for f, e in self.map.items(): |
363 | 431 c = self.copied(f) |
432 if c: | |
433 f = f + "\0" + c | |
220 | 434 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
|
435 st.write(e + f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
436 self.dirty = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
437 |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
438 def walk(self, files = None, match = util.always): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
439 self.read() |
536 | 440 dc = self.map.copy() |
723 | 441 # walk all files by default |
536 | 442 if not files: files = [self.root] |
821
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
443 known = {'.hg': 1} |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
444 def seen(fn): |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
445 if fn in known: return True |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
446 known[fn] = 1 |
723 | 447 def traverse(): |
556 | 448 for f in util.unique(files): |
537 | 449 f = os.path.join(self.root, f) |
536 | 450 if os.path.isdir(f): |
451 for dir, subdirs, fl in os.walk(f): | |
452 d = dir[len(self.root) + 1:] | |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
453 nd = os.path.normpath(d) |
821
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
454 if seen(nd): |
723 | 455 subdirs[:] = [] |
456 continue | |
669
8aa2a282eda4
.hgignore speedups patch incorporating Matt's feedback.
mwilli2@localhost.localdomain
parents:
667
diff
changeset
|
457 for sd in subdirs: |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
458 ds = os.path.join(nd, sd +'/') |
723 | 459 if self.ignore(ds) or not match(ds): |
669
8aa2a282eda4
.hgignore speedups patch incorporating Matt's feedback.
mwilli2@localhost.localdomain
parents:
667
diff
changeset
|
460 subdirs.remove(sd) |
822
b678e6d4f92d
Attempt to yield names in sorted order when walking.
Bryan O'Sullivan <bos@serpentine.com>
parents:
821
diff
changeset
|
461 subdirs.sort() |
b678e6d4f92d
Attempt to yield names in sorted order when walking.
Bryan O'Sullivan <bos@serpentine.com>
parents:
821
diff
changeset
|
462 fl.sort() |
536 | 463 for fn in fl: |
464 fn = util.pconvert(os.path.join(d, fn)) | |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
465 yield 'f', fn |
536 | 466 else: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
467 yield 'f', f[len(self.root) + 1:] |
536 | 468 |
822
b678e6d4f92d
Attempt to yield names in sorted order when walking.
Bryan O'Sullivan <bos@serpentine.com>
parents:
821
diff
changeset
|
469 ks = dc.keys() |
b678e6d4f92d
Attempt to yield names in sorted order when walking.
Bryan O'Sullivan <bos@serpentine.com>
parents:
821
diff
changeset
|
470 ks.sort() |
b678e6d4f92d
Attempt to yield names in sorted order when walking.
Bryan O'Sullivan <bos@serpentine.com>
parents:
821
diff
changeset
|
471 for k in ks: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
472 yield 'm', k |
669
8aa2a282eda4
.hgignore speedups patch incorporating Matt's feedback.
mwilli2@localhost.localdomain
parents:
667
diff
changeset
|
473 |
723 | 474 # yield only files that match: all in dirstate, others only if |
475 # not in .hgignore | |
669
8aa2a282eda4
.hgignore speedups patch incorporating Matt's feedback.
mwilli2@localhost.localdomain
parents:
667
diff
changeset
|
476 |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
477 for src, fn in util.unique(traverse()): |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
478 fn = os.path.normpath(fn) |
821
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
479 if seen(fn): continue |
723 | 480 if fn in dc: |
481 del dc[fn] | |
482 elif self.ignore(fn): | |
483 continue | |
484 if match(fn): | |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
485 yield src, fn |
723 | 486 |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
487 def changes(self, files = None, match = util.always): |
723 | 488 self.read() |
489 dc = self.map.copy() | |
490 lookup, changed, added, unknown = [], [], [], [] | |
491 | |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
492 for src, fn in self.walk(files, match): |
536 | 493 try: s = os.stat(os.path.join(self.root, fn)) |
494 except: continue | |
495 | |
496 if fn in dc: | |
497 c = dc[fn] | |
498 del dc[fn] | |
499 | |
500 if c[0] == 'm': | |
501 changed.append(fn) | |
502 elif c[0] == 'a': | |
503 added.append(fn) | |
504 elif c[0] == 'r': | |
505 unknown.append(fn) | |
506 elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: | |
507 changed.append(fn) | |
508 elif c[1] != s.st_mode or c[3] != s.st_mtime: | |
509 lookup.append(fn) | |
510 else: | |
723 | 511 if match(fn): unknown.append(fn) |
536 | 512 |
730
d2dc7663d512
Only walk over files that match our criteria.
Bryan O'Sullivan <bos@serpentine.com>
parents:
726
diff
changeset
|
513 return (lookup, changed, added, filter(match, dc.keys()), unknown) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
514 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
515 # used to avoid circular references so destructors work |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
516 def opener(base): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
517 p = base |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
518 def o(path, mode="r"): |
686
d7d68d27ebe5
Reapply startswith() changes that got lost with stale edit
Matt Mackall <mpm@selenic.com>
parents:
681
diff
changeset
|
519 if p.startswith("http://"): |
15
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
520 f = os.path.join(p, urllib.quote(path)) |
372 | 521 return httprangereader.httprangereader(f) |
15
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
522 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
523 f = os.path.join(p, path) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
524 |
292 | 525 mode += "b" # for that other OS |
526 | |
527 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
|
528 try: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
529 s = os.stat(f) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
530 except OSError: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
531 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
|
532 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
|
533 os.makedirs(d) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
534 else: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
535 if s.st_nlink > 1: |
417 | 536 file(f + ".tmp", "wb").write(file(f, "rb").read()) |
421 | 537 util.rename(f+".tmp", f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
538 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
539 return file(f, mode) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
540 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
541 return o |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
542 |
499 | 543 class RepoError(Exception): pass |
544 | |
60 | 545 class localrepository: |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
546 def __init__(self, ui, path=None, create=0): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
547 self.remote = 0 |
686
d7d68d27ebe5
Reapply startswith() changes that got lost with stale edit
Matt Mackall <mpm@selenic.com>
parents:
681
diff
changeset
|
548 if path and path.startswith("http://"): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
549 self.remote = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
550 self.path = path |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
551 else: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
552 if not path: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
553 p = os.getcwd() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
554 while not os.path.isdir(os.path.join(p, ".hg")): |
420
dbe86d465e09
[PATCH] Repo locator fix for the other `OS'
mpm@selenic.com
parents:
419
diff
changeset
|
555 oldp = p |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
556 p = os.path.dirname(p) |
499 | 557 if p == oldp: raise RepoError("no repo found") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
558 path = p |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
559 self.path = os.path.join(path, ".hg") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
560 |
405 | 561 if not create and not os.path.isdir(self.path): |
499 | 562 raise RepoError("repository %s not found" % self.path) |
405 | 563 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
564 self.root = path |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
565 self.ui = ui |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
566 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
567 if create: |
515 | 568 os.mkdir(self.path) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
569 os.mkdir(self.join("data")) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
570 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
571 self.opener = opener(self.path) |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
572 self.wopener = opener(self.root) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
573 self.manifest = manifest(self.opener) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
574 self.changelog = changelog(self.opener) |
343 | 575 self.tagscache = None |
576 self.nodetagscache = None | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
577 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
578 if not self.remote: |
244 | 579 self.dirstate = dirstate(self.opener, ui, self.root) |
337 | 580 try: |
581 self.ui.readconfig(self.opener("hgrc")) | |
582 except IOError: pass | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
583 |
487 | 584 def hook(self, name, **args): |
585 s = self.ui.config("hooks", name) | |
586 if s: | |
587 self.ui.note("running hook %s: %s\n" % (name, s)) | |
588 old = {} | |
589 for k, v in args.items(): | |
590 k = k.upper() | |
591 old[k] = os.environ.get(k, None) | |
592 os.environ[k] = v | |
593 | |
594 r = os.system(s) | |
595 | |
596 for k, v in old.items(): | |
597 if v != None: | |
598 os.environ[k] = v | |
599 else: | |
600 del os.environ[k] | |
601 | |
602 if r: | |
603 self.ui.warn("abort: %s hook failed with status %d!\n" % | |
604 (name, r)) | |
605 return False | |
606 return True | |
607 | |
343 | 608 def tags(self): |
609 '''return a mapping of tag to node''' | |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
610 if not self.tagscache: |
343 | 611 self.tagscache = {} |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
612 def addtag(self, k, n): |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
613 try: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
614 bin_n = bin(n) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
615 except TypeError: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
616 bin_n = '' |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
617 self.tagscache[k.strip()] = bin_n |
659 | 618 |
67 | 619 try: |
254 | 620 # read each head of the tags file, ending with the tip |
621 # and add each tag found to the map, with "newer" ones | |
622 # taking precedence | |
67 | 623 fl = self.file(".hgtags") |
254 | 624 h = fl.heads() |
625 h.reverse() | |
626 for r in h: | |
627 for l in fl.revision(r).splitlines(): | |
628 if l: | |
385
e9e1efd5291c
Fixed problems with extra spaces around tags in .hgtags
Thomas Arendsen Hein <thomas@intevation.de>
parents:
383
diff
changeset
|
629 n, k = l.split(" ", 1) |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
630 addtag(self, k, n) |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
631 except KeyError: |
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
632 pass |
659 | 633 |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
634 try: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
635 f = self.opener("localtags") |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
636 for l in f: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
637 n, k = l.split(" ", 1) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
638 addtag(self, k, n) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
639 except IOError: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
640 pass |
659 | 641 |
343 | 642 self.tagscache['tip'] = self.changelog.tip() |
659 | 643 |
343 | 644 return self.tagscache |
645 | |
646 def tagslist(self): | |
647 '''return a list of tags ordered by revision''' | |
648 l = [] | |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
649 for t, n in self.tags().items(): |
343 | 650 try: |
651 r = self.changelog.rev(n) | |
652 except: | |
653 r = -2 # sort to the beginning of the list if unknown | |
654 l.append((r,t,n)) | |
655 l.sort() | |
656 return [(t,n) for r,t,n in l] | |
657 | |
658 def nodetags(self, node): | |
659 '''return the tags associated with a node''' | |
660 if not self.nodetagscache: | |
661 self.nodetagscache = {} | |
662 for t,n in self.tags().items(): | |
663 self.nodetagscache.setdefault(n,[]).append(t) | |
664 return self.nodetagscache.get(node, []) | |
665 | |
666 def lookup(self, key): | |
67 | 667 try: |
343 | 668 return self.tags()[key] |
67 | 669 except KeyError: |
658
f8098ae9f5b6
Generate a friendlier except for failed lookups
Matt Mackall <mpm@selenic.com>
parents:
657
diff
changeset
|
670 try: |
f8098ae9f5b6
Generate a friendlier except for failed lookups
Matt Mackall <mpm@selenic.com>
parents:
657
diff
changeset
|
671 return self.changelog.lookup(key) |
f8098ae9f5b6
Generate a friendlier except for failed lookups
Matt Mackall <mpm@selenic.com>
parents:
657
diff
changeset
|
672 except: |
f8098ae9f5b6
Generate a friendlier except for failed lookups
Matt Mackall <mpm@selenic.com>
parents:
657
diff
changeset
|
673 raise RepoError("unknown revision '%s'" % key) |
67 | 674 |
634
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
675 def dev(self): |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
676 if self.remote: return -1 |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
677 return os.stat(self.path).st_dev |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
678 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
679 def join(self, f): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
680 return os.path.join(self.path, f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
681 |
244 | 682 def wjoin(self, f): |
683 return os.path.join(self.root, f) | |
684 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
685 def file(self, f): |
192 | 686 if f[0] == '/': f = f[1:] |
144
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
687 return filelog(self.opener, f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
688 |
627 | 689 def getcwd(self): |
690 cwd = os.getcwd() | |
691 if cwd == self.root: return '' | |
692 return cwd[len(self.root) + 1:] | |
693 | |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
694 def wfile(self, f, mode='r'): |
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
695 return self.wopener(f, mode) |
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
696 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
697 def transaction(self): |
251 | 698 # save dirstate for undo |
263 | 699 try: |
700 ds = self.opener("dirstate").read() | |
701 except IOError: | |
702 ds = "" | |
785 | 703 self.opener("journal.dirstate", "w").write(ds) |
515 | 704 |
785 | 705 def after(): |
706 util.rename(self.join("journal"), self.join("undo")) | |
707 util.rename(self.join("journal.dirstate"), | |
708 self.join("undo.dirstate")) | |
709 | |
710 return transaction.transaction(self.ui.warn, self.opener, | |
711 self.join("journal"), after) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
712 |
210 | 713 def recover(self): |
225 | 714 lock = self.lock() |
557 | 715 if os.path.exists(self.join("journal")): |
501 | 716 self.ui.status("rolling back interrupted transaction\n") |
557 | 717 return transaction.rollback(self.opener, self.join("journal")) |
210 | 718 else: |
719 self.ui.warn("no interrupted transaction available\n") | |
720 | |
721 def undo(self): | |
225 | 722 lock = self.lock() |
210 | 723 if os.path.exists(self.join("undo")): |
501 | 724 self.ui.status("rolling back last transaction\n") |
262 | 725 transaction.rollback(self.opener, self.join("undo")) |
251 | 726 self.dirstate = None |
421 | 727 util.rename(self.join("undo.dirstate"), self.join("dirstate")) |
251 | 728 self.dirstate = dirstate(self.opener, self.ui, self.root) |
163 | 729 else: |
210 | 730 self.ui.warn("no undo information available\n") |
162 | 731 |
161 | 732 def lock(self, wait = 1): |
733 try: | |
734 return lock.lock(self.join("lock"), 0) | |
735 except lock.LockHeld, inst: | |
736 if wait: | |
737 self.ui.warn("waiting for lock held by %s\n" % inst.args[0]) | |
738 return lock.lock(self.join("lock"), wait) | |
739 raise inst | |
740 | |
203 | 741 def rawcommit(self, files, text, user, date, p1=None, p2=None): |
442 | 742 orig_parent = self.dirstate.parents()[0] or nullid |
452
a1e91c24dab5
rawcommit: do lookup of parents at the appropriate layer
mpm@selenic.com
parents:
442
diff
changeset
|
743 p1 = p1 or self.dirstate.parents()[0] or nullid |
a1e91c24dab5
rawcommit: do lookup of parents at the appropriate layer
mpm@selenic.com
parents:
442
diff
changeset
|
744 p2 = p2 or self.dirstate.parents()[1] or nullid |
302 | 745 c1 = self.changelog.read(p1) |
746 c2 = self.changelog.read(p2) | |
747 m1 = self.manifest.read(c1[0]) | |
748 mf1 = self.manifest.readflags(c1[0]) | |
749 m2 = self.manifest.read(c2[0]) | |
750 | |
442 | 751 if orig_parent == p1: |
752 update_dirstate = 1 | |
753 else: | |
754 update_dirstate = 0 | |
755 | |
203 | 756 tr = self.transaction() |
302 | 757 mm = m1.copy() |
758 mfm = mf1.copy() | |
203 | 759 linkrev = self.changelog.count() |
760 for f in files: | |
761 try: | |
302 | 762 t = self.wfile(f).read() |
441 | 763 tm = util.is_exec(self.wjoin(f), mfm.get(f, False)) |
302 | 764 r = self.file(f) |
765 mfm[f] = tm | |
360 | 766 mm[f] = r.add(t, {}, tr, linkrev, |
302 | 767 m1.get(f, nullid), m2.get(f, nullid)) |
442 | 768 if update_dirstate: |
769 self.dirstate.update([f], "n") | |
203 | 770 except IOError: |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
771 try: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
772 del mm[f] |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
773 del mfm[f] |
442 | 774 if update_dirstate: |
775 self.dirstate.forget([f]) | |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
776 except: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
777 # deleted from p2? |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
778 pass |
203 | 779 |
302 | 780 mnode = self.manifest.add(mm, mfm, tr, linkrev, c1[0], c2[0]) |
608
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
781 user = user or self.ui.username() |
302 | 782 n = self.changelog.add(mnode, files, text, tr, p1, p2, user, date) |
203 | 783 tr.close() |
442 | 784 if update_dirstate: |
785 self.dirstate.setparents(n, nullid) | |
203 | 786 |
813
80fd2958235a
Adapt commit to use file matching code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
786
diff
changeset
|
787 def commit(self, files = None, text = "", user = None, date = None, |
80fd2958235a
Adapt commit to use file matching code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
786
diff
changeset
|
788 match = util.always): |
220 | 789 commit = [] |
790 remove = [] | |
791 if files: | |
792 for f in files: | |
793 s = self.dirstate.state(f) | |
244 | 794 if s in 'nmai': |
220 | 795 commit.append(f) |
796 elif s == 'r': | |
797 remove.append(f) | |
798 else: | |
244 | 799 self.ui.warn("%s not tracked!\n" % f) |
220 | 800 else: |
813
80fd2958235a
Adapt commit to use file matching code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
786
diff
changeset
|
801 (c, a, d, u) = self.changes(match = match) |
220 | 802 commit = c + a |
803 remove = d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
804 |
220 | 805 if not commit and not remove: |
151 | 806 self.ui.status("nothing changed\n") |
807 return | |
808 | |
487 | 809 if not self.hook("precommit"): |
810 return 1 | |
811 | |
229 | 812 p1, p2 = self.dirstate.parents() |
813 c1 = self.changelog.read(p1) | |
814 c2 = self.changelog.read(p2) | |
815 m1 = self.manifest.read(c1[0]) | |
276 | 816 mf1 = self.manifest.readflags(c1[0]) |
229 | 817 m2 = self.manifest.read(c2[0]) |
225 | 818 lock = self.lock() |
151 | 819 tr = self.transaction() |
820 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
821 # check in files |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
822 new = {} |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
823 linkrev = self.changelog.count() |
220 | 824 commit.sort() |
825 for f in commit: | |
83 | 826 self.ui.note(f + "\n") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
827 try: |
441 | 828 mf1[f] = util.is_exec(self.wjoin(f), mf1.get(f, False)) |
418 | 829 t = self.wfile(f).read() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
830 except IOError: |
667
31a9aa890016
A number of minor fixes to problems that pychecker found.
mark.williamson@cl.cam.ac.uk
parents:
660
diff
changeset
|
831 self.ui.warn("trouble committing %s!\n" % f) |
220 | 832 raise |
833 | |
363 | 834 meta = {} |
835 cp = self.dirstate.copied(f) | |
836 if cp: | |
837 meta["copy"] = cp | |
838 meta["copyrev"] = hex(m1.get(cp, m2.get(cp, nullid))) | |
575 | 839 self.ui.debug(" %s: copy %s:%s\n" % (f, cp, meta["copyrev"])) |
363 | 840 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
841 r = self.file(f) |
229 | 842 fp1 = m1.get(f, nullid) |
843 fp2 = m2.get(f, nullid) | |
363 | 844 new[f] = r.add(t, meta, tr, linkrev, fp1, fp2) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
845 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
846 # update manifest |
229 | 847 m1.update(new) |
416
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
848 for f in remove: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
849 if f in m1: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
850 del m1[f] |
741 | 851 mn = self.manifest.add(m1, mf1, tr, linkrev, c1[0], c2[0], |
852 (new, remove)) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
853 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
854 # add changeset |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
855 new = new.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
856 new.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
857 |
288 | 858 if not text: |
859 edittext = "\n" + "HG: manifest hash %s\n" % hex(mn) | |
860 edittext += "".join(["HG: changed %s\n" % f for f in new]) | |
861 edittext += "".join(["HG: removed %s\n" % f for f in remove]) | |
862 edittext = self.ui.edit(edittext) | |
863 if not edittext.rstrip(): | |
864 return 1 | |
865 text = edittext | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
866 |
608
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
867 user = user or self.ui.username() |
317 | 868 n = self.changelog.add(mn, new, text, tr, p1, p2, user, date) |
487 | 869 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
870 tr.close() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
871 |
229 | 872 self.dirstate.setparents(n) |
220 | 873 self.dirstate.update(new, "n") |
874 self.dirstate.forget(remove) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
875 |
660
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
876 if not self.hook("commit", node=hex(n)): |
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
877 return 1 |
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
878 |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
879 def walk(self, node = None, files = [], match = util.always): |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
880 if node: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
881 for fn in self.manifest.read(self.changelog.read(node)[0]): |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
882 if match(fn): yield 'm', fn |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
883 else: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
884 for src, fn in self.dirstate.walk(files, match): |
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
885 yield src, fn |
723 | 886 |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
887 def changes(self, node1 = None, node2 = None, files = [], |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
888 match = util.always): |
566 | 889 mf2, u = None, [] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
890 |
536 | 891 def fcmp(fn, mf): |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
892 t1 = self.wfile(fn).read() |
29 | 893 t2 = self.file(fn).revision(mf[fn]) |
894 return cmp(t1, t2) | |
895 | |
723 | 896 def mfmatches(node): |
897 mf = dict(self.manifest.read(node)) | |
898 for fn in mf.keys(): | |
899 if not match(fn): | |
900 del mf[fn] | |
901 return mf | |
741 | 902 |
536 | 903 # are we comparing the working directory? |
561 | 904 if not node2: |
723 | 905 l, c, a, d, u = self.dirstate.changes(files, match) |
536 | 906 |
907 # are we comparing working dir against its parent? | |
561 | 908 if not node1: |
536 | 909 if l: |
910 # do a full compare of any files that might have changed | |
911 change = self.changelog.read(self.dirstate.parents()[0]) | |
723 | 912 mf2 = mfmatches(change[0]) |
548 | 913 for f in l: |
561 | 914 if fcmp(f, mf2): |
536 | 915 c.append(f) |
561 | 916 |
917 for l in c, a, d, u: | |
918 l.sort() | |
919 | |
536 | 920 return (c, a, d, u) |
515 | 921 |
536 | 922 # are we comparing working dir against non-tip? |
923 # generate a pseudo-manifest for the working dir | |
561 | 924 if not node2: |
925 if not mf2: | |
536 | 926 change = self.changelog.read(self.dirstate.parents()[0]) |
723 | 927 mf2 = mfmatches(change[0]) |
536 | 928 for f in a + c + l: |
561 | 929 mf2[f] = "" |
536 | 930 for f in d: |
561 | 931 if f in mf2: del mf2[f] |
536 | 932 else: |
561 | 933 change = self.changelog.read(node2) |
723 | 934 mf2 = mfmatches(change[0]) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
935 |
566 | 936 # flush lists from dirstate before comparing manifests |
937 c, a = [], [] | |
938 | |
561 | 939 change = self.changelog.read(node1) |
723 | 940 mf1 = mfmatches(change[0]) |
32 | 941 |
942 for fn in mf2: | |
943 if mf1.has_key(fn): | |
944 if mf1[fn] != mf2[fn]: | |
561 | 945 if mf2[fn] != "" or fcmp(fn, mf1): |
536 | 946 c.append(fn) |
32 | 947 del mf1[fn] |
948 else: | |
536 | 949 a.append(fn) |
515 | 950 |
536 | 951 d = mf1.keys() |
561 | 952 |
953 for l in c, a, d, u: | |
954 l.sort() | |
515 | 955 |
536 | 956 return (c, a, d, u) |
32 | 957 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
958 def add(self, list): |
220 | 959 for f in list: |
244 | 960 p = self.wjoin(f) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
961 if not os.path.exists(p): |
659 | 962 self.ui.warn("%s does not exist!\n" % f) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
963 elif not os.path.isfile(p): |
741 | 964 self.ui.warn("%s not added: only files supported currently\n" % f) |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
965 elif self.dirstate.state(f) in 'an': |
220 | 966 self.ui.warn("%s already tracked!\n" % f) |
967 else: | |
968 self.dirstate.update([f], "a") | |
969 | |
970 def forget(self, list): | |
971 for f in list: | |
972 if self.dirstate.state(f) not in 'ai': | |
973 self.ui.warn("%s not added!\n" % f) | |
974 else: | |
975 self.dirstate.forget([f]) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
976 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
977 def remove(self, list): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
978 for f in list: |
244 | 979 p = self.wjoin(f) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
980 if os.path.exists(p): |
220 | 981 self.ui.warn("%s still exists!\n" % f) |
402 | 982 elif self.dirstate.state(f) == 'a': |
983 self.ui.warn("%s never committed!\n" % f) | |
657
22bc6fb9aefc
dirstate.forget() takes a list
Matt Mackall <mpm@selenic.com>
parents:
656
diff
changeset
|
984 self.dirstate.forget([f]) |
220 | 985 elif f not in self.dirstate: |
986 self.ui.warn("%s not tracked!\n" % f) | |
987 else: | |
988 self.dirstate.update([f], "r") | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
989 |
363 | 990 def copy(self, source, dest): |
991 p = self.wjoin(dest) | |
781 | 992 if not os.path.exists(p): |
363 | 993 self.ui.warn("%s does not exist!\n" % dest) |
781 | 994 elif not os.path.isfile(p): |
659 | 995 self.ui.warn("copy failed: %s is not a file\n" % dest) |
363 | 996 else: |
997 if self.dirstate.state(dest) == '?': | |
998 self.dirstate.update([dest], "a") | |
999 self.dirstate.copy(source, dest) | |
1000 | |
222 | 1001 def heads(self): |
1002 return self.changelog.heads() | |
1003 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1004 def branches(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1005 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
|
1006 b = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1007 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1008 t = n |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1009 while n: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1010 p = self.changelog.parents(n) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1011 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
|
1012 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
|
1013 break |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1014 n = p[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1015 return b |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1016 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1017 def between(self, pairs): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1018 r = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1019 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1020 for top, bottom in pairs: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1021 n, l, i = top, [], 0 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1022 f = 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1023 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1024 while n != bottom: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1025 p = self.changelog.parents(n)[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1026 if i == f: |
575 | 1027 l.append(n) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1028 f = f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1029 n = p |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1030 i += 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1031 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1032 r.append(l) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1033 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1034 return r |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1035 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1036 def newer(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1037 m = {} |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1038 nl = [] |
94 | 1039 pm = {} |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1040 cl = self.changelog |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1041 t = l = cl.count() |
94 | 1042 |
1043 # find the lowest numbered node | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1044 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1045 l = min(l, cl.rev(n)) |
94 | 1046 m[n] = 1 |
46 | 1047 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1048 for i in xrange(l, t): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1049 n = cl.node(i) |
94 | 1050 if n in m: # explicitly listed |
1051 pm[n] = 1 | |
1052 nl.append(n) | |
1053 continue | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1054 for p in cl.parents(n): |
94 | 1055 if p in pm: # parent listed |
1056 pm[n] = 1 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1057 nl.append(n) |
94 | 1058 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1059 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1060 return nl |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1061 |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1062 def findincoming(self, remote, base=None, heads=None): |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1063 m = self.changelog.nodemap |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1064 search = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1065 fetch = [] |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1066 seen = {} |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1067 seenbranch = {} |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1068 if base == None: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1069 base = {} |
192 | 1070 |
636
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1071 # assume we're closer to the tip than the root |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1072 # and start by examining the heads |
222 | 1073 self.ui.status("searching for changes\n") |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1074 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1075 if not heads: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1076 heads = remote.heads() |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1077 |
222 | 1078 unknown = [] |
1079 for h in heads: | |
1080 if h not in m: | |
1081 unknown.append(h) | |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1082 else: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1083 base[h] = 1 |
46 | 1084 |
222 | 1085 if not unknown: |
60 | 1086 return None |
324 | 1087 |
1088 rep = {} | |
1089 reqcnt = 0 | |
515 | 1090 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1091 # search through remote branches |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1092 # a 'branch' here is a linear segment of history, with four parts: |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1093 # head, root, first parent, second parent |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1094 # (a branch always has two parents (or none) by definition) |
222 | 1095 unknown = remote.branches(unknown) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1096 while unknown: |
324 | 1097 r = [] |
1098 while unknown: | |
1099 n = unknown.pop(0) | |
1100 if n[0] in seen: | |
1101 continue | |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1102 |
324 | 1103 self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) |
1104 if n[0] == nullid: | |
1105 break | |
328 | 1106 if n in seenbranch: |
324 | 1107 self.ui.debug("branch already found\n") |
1108 continue | |
1109 if n[1] and n[1] in m: # do we know the base? | |
1110 self.ui.debug("found incomplete branch %s:%s\n" | |
1111 % (short(n[0]), short(n[1]))) | |
1112 search.append(n) # schedule branch range for scanning | |
328 | 1113 seenbranch[n] = 1 |
324 | 1114 else: |
1115 if n[1] not in seen and n[1] not in fetch: | |
1116 if n[2] in m and n[3] in m: | |
1117 self.ui.debug("found new changeset %s\n" % | |
1118 short(n[1])) | |
1119 fetch.append(n[1]) # earliest unknown | |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1120 base[n[2]] = 1 # latest known |
324 | 1121 continue |
1122 | |
1123 for a in n[2:4]: | |
1124 if a not in rep: | |
1125 r.append(a) | |
1126 rep[a] = 1 | |
1127 | |
328 | 1128 seen[n[0]] = 1 |
1129 | |
324 | 1130 if r: |
1131 reqcnt += 1 | |
1132 self.ui.debug("request %d: %s\n" % | |
1133 (reqcnt, " ".join(map(short, r)))) | |
1134 for p in range(0, len(r), 10): | |
1135 for b in remote.branches(r[p:p+10]): | |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1136 self.ui.debug("received %s:%s\n" % |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1137 (short(b[0]), short(b[1]))) |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1138 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
|
1139 unknown.append(b) |
515 | 1140 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1141 # do binary search on the branches we found |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1142 while search: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1143 n = search.pop(0) |
324 | 1144 reqcnt += 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1145 l = remote.between([(n[0], n[1])])[0] |
328 | 1146 l.append(n[1]) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1147 p = n[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1148 f = 1 |
328 | 1149 for i in l: |
1150 self.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i))) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1151 if i in m: |
85 | 1152 if f <= 2: |
83 | 1153 self.ui.debug("found new branch changeset %s\n" % |
1154 short(p)) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1155 fetch.append(p) |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1156 base[i] = 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1157 else: |
83 | 1158 self.ui.debug("narrowed branch search to %s:%s\n" |
1159 % (short(p), short(i))) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1160 search.append((p, i)) |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1161 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1162 p, f = i, f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1163 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1164 # sanity check our fetch list |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1165 for f in fetch: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1166 if f in m: |
499 | 1167 raise RepoError("already have changeset " + short(f[:4])) |
83 | 1168 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1169 if base.keys() == [nullid]: |
514
874e577e332e
change unrelated repository error to a warning
mpm@selenic.com
parents:
511
diff
changeset
|
1170 self.ui.warn("warning: pulling from an unrelated repository!\n") |
511 | 1171 |
94 | 1172 self.ui.note("adding new changesets starting at " + |
83 | 1173 " ".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
|
1174 |
324 | 1175 self.ui.debug("%d total queries\n" % reqcnt) |
1176 | |
516 | 1177 return fetch |
1178 | |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1179 def findoutgoing(self, remote, base=None, heads=None): |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1180 if base == None: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1181 base = {} |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1182 self.findincoming(remote, base, heads) |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1183 |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1184 remain = dict.fromkeys(self.changelog.nodemap) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1185 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1186 # prune everything remote has from the tree |
637
31e090c34d3b
Fix up the broken bits in findoutgoing
Matt Mackall <mpm@selenic.com>
parents:
636
diff
changeset
|
1187 del remain[nullid] |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1188 remove = base.keys() |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1189 while remove: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1190 n = remove.pop(0) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1191 if n in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1192 del remain[n] |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1193 for p in self.changelog.parents(n): |
637
31e090c34d3b
Fix up the broken bits in findoutgoing
Matt Mackall <mpm@selenic.com>
parents:
636
diff
changeset
|
1194 remove.append(p) |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1195 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1196 # find every node whose parents have been pruned |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1197 subset = [] |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1198 for n in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1199 p1, p2 = self.changelog.parents(n) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1200 if p1 not in remain and p2 not in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1201 subset.append(n) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1202 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1203 # this is the set of all roots we have to push |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1204 return subset |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1205 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1206 def pull(self, remote): |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1207 lock = self.lock() |
636
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1208 |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1209 # if we have an empty repo, fetch everything |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1210 if self.changelog.tip() == nullid: |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1211 self.ui.status("requesting all changes\n") |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1212 fetch = [nullid] |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1213 else: |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1214 fetch = self.findincoming(remote) |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1215 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1216 if not fetch: |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1217 self.ui.status("no changes found\n") |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1218 return 1 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1219 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1220 cg = remote.changegroup(fetch) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1221 return self.addchangegroup(cg) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1222 |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1223 def push(self, remote, force=False): |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1224 lock = remote.lock() |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1225 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1226 base = {} |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1227 heads = remote.heads() |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1228 inc = self.findincoming(remote, base, heads) |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1229 if not force and inc: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1230 self.ui.warn("abort: unsynced remote changes!\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1231 self.ui.status("(did you forget to sync? use push -f to force)\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1232 return 1 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1233 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1234 update = self.findoutgoing(remote, base) |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1235 if not update: |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1236 self.ui.status("no changes found\n") |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1237 return 1 |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1238 elif not force: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1239 if len(heads) < len(self.changelog.heads()): |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1240 self.ui.warn("abort: push creates new remote branches!\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1241 self.ui.status("(did you forget to merge?" + |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1242 " use push -f to force)\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
1243 return 1 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1244 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1245 cg = self.changegroup(update) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1246 return remote.addchangegroup(cg) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1247 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1248 def changegroup(self, basenodes): |
222 | 1249 class genread: |
1250 def __init__(self, generator): | |
1251 self.g = generator | |
1252 self.buf = "" | |
1253 def read(self, l): | |
1254 while l > len(self.buf): | |
1255 try: | |
1256 self.buf += self.g.next() | |
1257 except StopIteration: | |
1258 break | |
1259 d, self.buf = self.buf[:l], self.buf[l:] | |
1260 return d | |
515 | 1261 |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1262 def gengroup(): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1263 nodes = self.newer(basenodes) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1264 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1265 # construct the link map |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1266 linkmap = {} |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1267 for n in nodes: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1268 linkmap[self.changelog.rev(n)] = n |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1269 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1270 # construct a list of all changed files |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1271 changed = {} |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1272 for n in nodes: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1273 c = self.changelog.read(n) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1274 for f in c[3]: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1275 changed[f] = 1 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1276 changed = changed.keys() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1277 changed.sort() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1278 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1279 # the changegroup is changesets + manifests + all file revs |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1280 revs = [ self.changelog.rev(n) for n in nodes ] |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1281 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1282 for y in self.changelog.group(linkmap): yield y |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1283 for y in self.manifest.group(linkmap): yield y |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1284 for f in changed: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1285 yield struct.pack(">l", len(f) + 4) + f |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1286 g = self.file(f).group(linkmap) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1287 for y in g: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1288 yield y |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1289 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1290 yield struct.pack(">l", 0) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1291 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1292 return genread(gengroup()) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1293 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1294 def addchangegroup(self, source): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1295 |
222 | 1296 def getchunk(): |
1297 d = source.read(4) | |
1298 if not d: return "" | |
1299 l = struct.unpack(">l", d)[0] | |
1300 if l <= 4: return "" | |
1301 return source.read(l - 4) | |
1302 | |
1303 def getgroup(): | |
1304 while 1: | |
1305 c = getchunk() | |
1306 if not c: break | |
1307 yield c | |
1308 | |
1309 def csmap(x): | |
1310 self.ui.debug("add changeset %s\n" % short(x)) | |
1311 return self.changelog.count() | |
1312 | |
1313 def revmap(x): | |
1314 return self.changelog.rev(x) | |
1315 | |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1316 if not source: return |
222 | 1317 changesets = files = revisions = 0 |
225 | 1318 |
222 | 1319 tr = self.transaction() |
1320 | |
1321 # pull off the changeset group | |
1322 self.ui.status("adding changesets\n") | |
1323 co = self.changelog.tip() | |
224
ccbcc4d76f81
fix bad assumption about uniqueness of file versions
mpm@selenic.com
parents:
223
diff
changeset
|
1324 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique |
222 | 1325 changesets = self.changelog.rev(cn) - self.changelog.rev(co) |
1326 | |
1327 # pull off the manifest group | |
1328 self.ui.status("adding manifests\n") | |
1329 mm = self.manifest.tip() | |
1330 mo = self.manifest.addgroup(getgroup(), revmap, tr) | |
1331 | |
1332 # process the files | |
772 | 1333 self.ui.status("adding file changes\n") |
222 | 1334 while 1: |
1335 f = getchunk() | |
1336 if not f: break | |
1337 self.ui.debug("adding %s revisions\n" % f) | |
1338 fl = self.file(f) | |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1339 o = fl.count() |
222 | 1340 n = fl.addgroup(getgroup(), revmap, tr) |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1341 revisions += fl.count() - o |
222 | 1342 files += 1 |
1343 | |
772 | 1344 self.ui.status(("added %d changesets" + |
1345 " with %d changes to %d files\n") | |
1346 % (changesets, revisions, files)) | |
222 | 1347 |
1348 tr.close() | |
780 | 1349 |
1350 if not self.hook("changegroup"): | |
1351 return 1 | |
1352 | |
222 | 1353 return |
1354 | |
588 | 1355 def update(self, node, allow=False, force=False, choose=None, |
1356 moddirstate=True): | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1357 pl = self.dirstate.parents() |
275 | 1358 if not force and pl[1] != nullid: |
254 | 1359 self.ui.warn("aborting: outstanding uncommitted merges\n") |
690 | 1360 return 1 |
46 | 1361 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1362 p1, p2 = pl[0], node |
305 | 1363 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
|
1364 m1n = self.changelog.read(p1)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1365 m2n = self.changelog.read(p2)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1366 man = self.manifest.ancestor(m1n, m2n) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1367 m1 = self.manifest.read(m1n) |
276 | 1368 mf1 = self.manifest.readflags(m1n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1369 m2 = self.manifest.read(m2n) |
276 | 1370 mf2 = self.manifest.readflags(m2n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1371 ma = self.manifest.read(man) |
412 | 1372 mfa = self.manifest.readflags(man) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1373 |
723 | 1374 (c, a, d, u) = self.changes() |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1375 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1376 # is this a jump, or a merge? i.e. is there a linear path |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1377 # from p1 to p2? |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1378 linear_path = (pa == p1 or pa == p2) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1379 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1380 # 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
|
1381 # we care about merging |
254 | 1382 self.ui.note("resolving manifests\n") |
650
2c934c7b79dc
Fix bug in reverting deleted files
Matt Mackall <mpm@selenic.com>
parents:
649
diff
changeset
|
1383 self.ui.debug(" force %s allow %s moddirstate %s linear %s\n" % |
2c934c7b79dc
Fix bug in reverting deleted files
Matt Mackall <mpm@selenic.com>
parents:
649
diff
changeset
|
1384 (force, allow, moddirstate, linear_path)) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1385 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
|
1386 (short(man), short(m1n), short(m2n))) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1387 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1388 merge = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1389 get = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1390 remove = [] |
305 | 1391 mark = {} |
46 | 1392 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1393 # construct a working dir manifest |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1394 mw = m1.copy() |
276 | 1395 mfw = mf1.copy() |
576 | 1396 umap = dict.fromkeys(u) |
1397 | |
254 | 1398 for f in a + c + u: |
1399 mw[f] = "" | |
441 | 1400 mfw[f] = util.is_exec(self.wjoin(f), mfw.get(f, False)) |
576 | 1401 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1402 for f in d: |
254 | 1403 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
|
1404 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1405 # If we're jumping between revisions (as opposed to merging), |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1406 # and if neither the working directory nor the target rev has |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1407 # the file, then we need to remove it from the dirstate, to |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1408 # prevent the dirstate from listing the file when it is no |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1409 # longer in the manifest. |
588 | 1410 if moddirstate and linear_path and f not in m2: |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1411 self.dirstate.forget((f,)) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1412 |
576 | 1413 # Compare manifests |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1414 for f, n in mw.iteritems(): |
588 | 1415 if choose and not choose(f): continue |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1416 if f in m2: |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1417 s = 0 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1418 |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1419 # is the wfile new since m1, and match m2? |
428 | 1420 if f not in m1: |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1421 t1 = self.wfile(f).read() |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1422 t2 = self.file(f).revision(m2[f]) |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1423 if cmp(t1, t2) == 0: |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1424 mark[f] = 1 |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1425 n = m2[f] |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1426 del t1, t2 |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1427 |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1428 # are files different? |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1429 if n != m2[f]: |
254 | 1430 a = ma.get(f, nullid) |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1431 # are both different from the ancestor? |
254 | 1432 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
|
1433 self.ui.debug(" %s versions differ, resolve\n" % f) |
276 | 1434 # merge executable bits |
1435 # "if we changed or they changed, change in merge" | |
1436 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] | |
1437 mode = ((a^b) | (a^c)) ^ a | |
1438 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
|
1439 s = 1 |
305 | 1440 # are we clobbering? |
1441 # is remote's version newer? | |
1442 # or are we going back in time? | |
1443 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
|
1444 self.ui.debug(" remote %s is newer, get\n" % f) |
254 | 1445 get[f] = m2[f] |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1446 s = 1 |
305 | 1447 else: |
1448 mark[f] = 1 | |
576 | 1449 elif f in umap: |
1450 # this unknown file is the same as the checkout | |
1451 get[f] = m2[f] | |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1452 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1453 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
|
1454 if force: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1455 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1456 util.set_exec(self.wjoin(f), mf2[f]) |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1457 else: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1458 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
|
1459 mode = ((a^b) | (a^c)) ^ a |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1460 if mode != b: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1461 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1462 util.set_exec(self.wjoin(f), mode) |
305 | 1463 mark[f] = 1 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1464 del m2[f] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1465 elif f in ma: |
616 | 1466 if n != ma[f]: |
1467 r = "d" | |
1468 if not force and (linear_path or allow): | |
415
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1469 r = self.ui.prompt( |
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1470 (" local changed %s which remote deleted\n" % f) + |
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1471 "(k)eep or (d)elete?", "[kd]", "k") |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1472 if r == "d": |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1473 remove.append(f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1474 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1475 self.ui.debug("other deleted %s\n" % f) |
254 | 1476 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
|
1477 else: |
254 | 1478 if n == m1.get(f, nullid): # same as parent |
383
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1479 if p2 == pa: # going backwards? |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1480 self.ui.debug("remote deleted %s\n" % f) |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1481 remove.append(f) |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1482 else: |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1483 self.ui.debug("local created %s, keeping\n" % f) |
254 | 1484 else: |
1485 self.ui.debug("working dir created %s, keeping\n" % f) | |
46 | 1486 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1487 for f, n in m2.iteritems(): |
588 | 1488 if choose and not choose(f): continue |
256 | 1489 if f[0] == "/": continue |
616 | 1490 if f in ma and n != ma[f]: |
1491 r = "k" | |
1492 if not force and (linear_path or allow): | |
415
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1493 r = self.ui.prompt( |
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1494 ("remote changed %s which local deleted\n" % f) + |
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1495 "(k)eep or (d)elete?", "[kd]", "k") |
616 | 1496 if r == "k": get[f] = n |
1497 elif f not in ma: | |
254 | 1498 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
|
1499 get[f] = n |
616 | 1500 else: |
680
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1501 if force or p2 == pa: # going backwards? |
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1502 self.ui.debug("local deleted %s, recreating\n" % f) |
650
2c934c7b79dc
Fix bug in reverting deleted files
Matt Mackall <mpm@selenic.com>
parents:
649
diff
changeset
|
1503 get[f] = n |
680
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1504 else: |
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1505 self.ui.debug("local deleted %s\n" % f) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1506 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1507 del mw, m1, m2, ma |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1508 |
275 | 1509 if force: |
1510 for f in merge: | |
1511 get[f] = merge[f][1] | |
1512 merge = {} | |
1513 | |
690 | 1514 if linear_path or force: |
254 | 1515 # we don't need to do any magic, just jump to the new rev |
1516 mode = 'n' | |
1517 p1, p2 = p2, nullid | |
1518 else: | |
275 | 1519 if not allow: |
305 | 1520 self.ui.status("this update spans a branch" + |
1521 " affecting the following files:\n") | |
1522 fl = merge.keys() + get.keys() | |
1523 fl.sort() | |
1524 for f in fl: | |
1525 cf = "" | |
1526 if f in merge: cf = " (resolve)" | |
1527 self.ui.status(" %s%s\n" % (f, cf)) | |
1528 self.ui.warn("aborting update spanning branches!\n") | |
788 | 1529 self.ui.status("(use update -m to merge across branches" + |
1530 " or -C to lose changes)\n") | |
275 | 1531 return 1 |
254 | 1532 # we have to remember what files we needed to get/change |
1533 # because any file that's different from either one of its | |
1534 # parents must be in the changeset | |
1535 mode = 'm' | |
588 | 1536 if moddirstate: |
1537 self.dirstate.update(mark.keys(), "m") | |
254 | 1538 |
588 | 1539 if moddirstate: |
1540 self.dirstate.setparents(p1, p2) | |
191
d7e859cf2f1b
merge: add count of new manifests, files, and revisions
mpm@selenic.com
parents:
190
diff
changeset
|
1541 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1542 # 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
|
1543 files = get.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1544 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1545 for f in files: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1546 if f[0] == "/": continue |
273
4f8174389001
merge: Fix bug where we overwrote local when local was newer
mpm@selenic.com
parents:
263
diff
changeset
|
1547 self.ui.note("getting %s\n" % f) |
276 | 1548 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
|
1549 try: |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
1550 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
|
1551 except IOError: |
297
0dbcf3c9ff20
Fixed usage of removed variable 'wp'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
292
diff
changeset
|
1552 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
|
1553 self.wfile(f, "w").write(t) |
441 | 1554 util.set_exec(self.wjoin(f), mf2[f]) |
588 | 1555 if moddirstate: |
1556 self.dirstate.update([f], mode) | |
46 | 1557 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1558 # merge the tricky bits |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1559 files = merge.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1560 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1561 for f in files: |
256 | 1562 self.ui.status("merging %s\n" % f) |
276 | 1563 m, o, flag = merge[f] |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1564 self.merge3(f, m, o) |
441 | 1565 util.set_exec(self.wjoin(f), flag) |
768
20e95c245bc3
Fix local file changes being ignored after non-branch merge
mpm@selenic.com
parents:
765
diff
changeset
|
1566 if moddirstate and mode == 'm': |
20e95c245bc3
Fix local file changes being ignored after non-branch merge
mpm@selenic.com
parents:
765
diff
changeset
|
1567 # only update dirstate on branch merge, otherwise we |
20e95c245bc3
Fix local file changes being ignored after non-branch merge
mpm@selenic.com
parents:
765
diff
changeset
|
1568 # could mark files with changes as unchanged |
764
eea96285cbf9
Don't mark files with 'm'erge unless we're actually merging branches
mpm@selenic.com
parents:
753
diff
changeset
|
1569 self.dirstate.update([f], mode) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1570 |
681 | 1571 remove.sort() |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1572 for f in remove: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1573 self.ui.note("removing %s\n" % f) |
690 | 1574 try: |
1575 os.unlink(f) | |
1576 except OSError, inst: | |
1577 self.ui.warn("update failed to remove %s: %s!\n" % (f, inst)) | |
578 | 1578 # try removing directories that might now be empty |
1579 try: os.removedirs(os.path.dirname(f)) | |
1580 except: pass | |
588 | 1581 if moddirstate: |
1582 if mode == 'n': | |
1583 self.dirstate.forget(remove) | |
1584 else: | |
1585 self.dirstate.update(remove, 'r') | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1586 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1587 def merge3(self, fn, my, other): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1588 """perform a 3-way merge in the working directory""" |
249 | 1589 |
96 | 1590 def temp(prefix, node): |
1591 pre = "%s~%s." % (os.path.basename(fn), prefix) | |
1592 (fd, name) = tempfile.mkstemp("", pre) | |
417 | 1593 f = os.fdopen(fd, "wb") |
96 | 1594 f.write(fl.revision(node)) |
1595 f.close() | |
1596 return name | |
1597 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1598 fl = self.file(fn) |
96 | 1599 base = fl.ancestor(my, other) |
244 | 1600 a = self.wjoin(fn) |
346 | 1601 b = temp("base", base) |
1602 c = temp("other", other) | |
96 | 1603 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1604 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
|
1605 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
|
1606 (fn, short(other), short(base))) |
96 | 1607 |
703
fb6f85ecc863
merge program setting from hgrc wasn't used.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
691
diff
changeset
|
1608 cmd = (os.environ.get("HGMERGE") or self.ui.config("ui", "merge") |
fb6f85ecc863
merge program setting from hgrc wasn't used.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
691
diff
changeset
|
1609 or "hgmerge") |
240 | 1610 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
|
1611 if r: |
275 | 1612 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
|
1613 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1614 os.unlink(b) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1615 os.unlink(c) |
96 | 1616 |
247 | 1617 def verify(self): |
1618 filelinkrevs = {} | |
1619 filenodes = {} | |
1620 changesets = revisions = files = 0 | |
1621 errors = 0 | |
1622 | |
302 | 1623 seen = {} |
247 | 1624 self.ui.status("checking changesets\n") |
1625 for i in range(self.changelog.count()): | |
1626 changesets += 1 | |
1627 n = self.changelog.node(i) | |
302 | 1628 if n in seen: |
1629 self.ui.warn("duplicate changeset at revision %d\n" % i) | |
1630 errors += 1 | |
1631 seen[n] = 1 | |
515 | 1632 |
247 | 1633 for p in self.changelog.parents(n): |
1634 if p not in self.changelog.nodemap: | |
1635 self.ui.warn("changeset %s has unknown parent %s\n" % | |
1636 (short(n), short(p))) | |
1637 errors += 1 | |
1638 try: | |
1639 changes = self.changelog.read(n) | |
1640 except Exception, inst: | |
1641 self.ui.warn("unpacking changeset %s: %s\n" % (short(n), inst)) | |
1642 errors += 1 | |
1643 | |
1644 for f in changes[3]: | |
1645 filelinkrevs.setdefault(f, []).append(i) | |
1646 | |
302 | 1647 seen = {} |
247 | 1648 self.ui.status("checking manifests\n") |
1649 for i in range(self.manifest.count()): | |
1650 n = self.manifest.node(i) | |
302 | 1651 if n in seen: |
1652 self.ui.warn("duplicate manifest at revision %d\n" % i) | |
1653 errors += 1 | |
1654 seen[n] = 1 | |
515 | 1655 |
247 | 1656 for p in self.manifest.parents(n): |
1657 if p not in self.manifest.nodemap: | |
1658 self.ui.warn("manifest %s has unknown parent %s\n" % | |
1659 (short(n), short(p))) | |
1660 errors += 1 | |
1661 | |
1662 try: | |
1663 delta = mdiff.patchtext(self.manifest.delta(n)) | |
1664 except KeyboardInterrupt: | |
582 | 1665 self.ui.warn("aborted") |
247 | 1666 sys.exit(0) |
1667 except Exception, inst: | |
1668 self.ui.warn("unpacking manifest %s: %s\n" | |
1669 % (short(n), inst)) | |
1670 errors += 1 | |
1671 | |
1672 ff = [ l.split('\0') for l in delta.splitlines() ] | |
1673 for f, fn in ff: | |
284 | 1674 filenodes.setdefault(f, {})[bin(fn[:40])] = 1 |
247 | 1675 |
1676 self.ui.status("crosschecking files in changesets and manifests\n") | |
1677 for f in filenodes: | |
1678 if f not in filelinkrevs: | |
1679 self.ui.warn("file %s in manifest but not in changesets\n" % f) | |
1680 errors += 1 | |
1681 | |
1682 for f in filelinkrevs: | |
1683 if f not in filenodes: | |
1684 self.ui.warn("file %s in changeset but not in manifest\n" % f) | |
1685 errors += 1 | |
1686 | |
1687 self.ui.status("checking files\n") | |
1688 ff = filenodes.keys() | |
1689 ff.sort() | |
1690 for f in ff: | |
1691 if f == "/dev/null": continue | |
1692 files += 1 | |
1693 fl = self.file(f) | |
1694 nodes = { nullid: 1 } | |
302 | 1695 seen = {} |
247 | 1696 for i in range(fl.count()): |
1697 revisions += 1 | |
1698 n = fl.node(i) | |
1699 | |
302 | 1700 if n in seen: |
1701 self.ui.warn("%s: duplicate revision %d\n" % (f, i)) | |
1702 errors += 1 | |
1703 | |
247 | 1704 if n not in filenodes[f]: |
1705 self.ui.warn("%s: %d:%s not in manifests\n" | |
1706 % (f, i, short(n))) | |
1707 errors += 1 | |
1708 else: | |
1709 del filenodes[f][n] | |
1710 | |
1711 flr = fl.linkrev(n) | |
1712 if flr not in filelinkrevs[f]: | |
1713 self.ui.warn("%s:%s points to unexpected changeset %d\n" | |
1714 % (f, short(n), fl.linkrev(n))) | |
1715 errors += 1 | |
1716 else: | |
1717 filelinkrevs[f].remove(flr) | |
1718 | |
1719 # verify contents | |
1720 try: | |
1721 t = fl.read(n) | |
1722 except Exception, inst: | |
1723 self.ui.warn("unpacking file %s %s: %s\n" | |
1724 % (f, short(n), inst)) | |
1725 errors += 1 | |
1726 | |
1727 # verify parents | |
1728 (p1, p2) = fl.parents(n) | |
1729 if p1 not in nodes: | |
1730 self.ui.warn("file %s:%s unknown parent 1 %s" % | |
1731 (f, short(n), short(p1))) | |
1732 errors += 1 | |
1733 if p2 not in nodes: | |
1734 self.ui.warn("file %s:%s unknown parent 2 %s" % | |
1735 (f, short(n), short(p1))) | |
1736 errors += 1 | |
1737 nodes[n] = 1 | |
1738 | |
1739 # cross-check | |
1740 for node in filenodes[f]: | |
1741 self.ui.warn("node %s in manifests not in %s\n" | |
721 | 1742 % (hex(node), f)) |
247 | 1743 errors += 1 |
1744 | |
1745 self.ui.status("%d files, %d changesets, %d total revisions\n" % | |
1746 (files, changesets, revisions)) | |
1747 | |
1748 if errors: | |
1749 self.ui.warn("%d integrity errors encountered!\n" % errors) | |
1750 return 1 | |
1751 | |
623
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1752 class httprepository: |
60 | 1753 def __init__(self, ui, path): |
765 | 1754 # fix missing / after hostname |
1755 s = urlparse.urlsplit(path) | |
1756 partial = s[2] | |
1757 if not partial: partial = "/" | |
1758 self.url = urlparse.urlunsplit((s[0], s[1], partial, '', '')) | |
60 | 1759 self.ui = ui |
321 | 1760 no_list = [ "localhost", "127.0.0.1" ] |
1761 host = ui.config("http_proxy", "host") | |
424
9294dce4b633
Allow override of HTTP_PROXY, http_proxy and no_proxy; make no_proxy work.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
385
diff
changeset
|
1762 if host is None: |
9294dce4b633
Allow override of HTTP_PROXY, http_proxy and no_proxy; make no_proxy work.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
385
diff
changeset
|
1763 host = os.environ.get("http_proxy") |
426
8c90ab5644c9
Allow hgrc's proxy host and $http_proxy env var to start with http://
Thomas Arendsen Hein <thomas@intevation.de>
parents:
424
diff
changeset
|
1764 if host and host.startswith('http://'): |
8c90ab5644c9
Allow hgrc's proxy host and $http_proxy env var to start with http://
Thomas Arendsen Hein <thomas@intevation.de>
parents:
424
diff
changeset
|
1765 host = host[7:] |
321 | 1766 user = ui.config("http_proxy", "user") |
1767 passwd = ui.config("http_proxy", "passwd") | |
1768 no = ui.config("http_proxy", "no") | |
424
9294dce4b633
Allow override of HTTP_PROXY, http_proxy and no_proxy; make no_proxy work.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
385
diff
changeset
|
1769 if no is None: |
9294dce4b633
Allow override of HTTP_PROXY, http_proxy and no_proxy; make no_proxy work.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
385
diff
changeset
|
1770 no = os.environ.get("no_proxy") |
321 | 1771 if no: |
1772 no_list = no_list + no.split(",") | |
515 | 1773 |
321 | 1774 no_proxy = 0 |
1775 for h in no_list: | |
1776 if (path.startswith("http://" + h + "/") or | |
1777 path.startswith("http://" + h + ":") or | |
1778 path == "http://" + h): | |
1779 no_proxy = 1 | |
1780 | |
1781 # Note: urllib2 takes proxy values from the environment and those will | |
1782 # take precedence | |
424
9294dce4b633
Allow override of HTTP_PROXY, http_proxy and no_proxy; make no_proxy work.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
385
diff
changeset
|
1783 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]: |
859
6390c377a9e6
Trap OSError when deleting env vars
Edouard Gomez <ed.gomez@free.fr>
parents:
856
diff
changeset
|
1784 try: |
6390c377a9e6
Trap OSError when deleting env vars
Edouard Gomez <ed.gomez@free.fr>
parents:
856
diff
changeset
|
1785 if os.environ.has_key(env): |
6390c377a9e6
Trap OSError when deleting env vars
Edouard Gomez <ed.gomez@free.fr>
parents:
856
diff
changeset
|
1786 del os.environ[env] |
6390c377a9e6
Trap OSError when deleting env vars
Edouard Gomez <ed.gomez@free.fr>
parents:
856
diff
changeset
|
1787 except OSError: |
6390c377a9e6
Trap OSError when deleting env vars
Edouard Gomez <ed.gomez@free.fr>
parents:
856
diff
changeset
|
1788 pass |
321 | 1789 |
1790 proxy_handler = urllib2.BaseHandler() | |
1791 if host and not no_proxy: | |
1792 proxy_handler = urllib2.ProxyHandler({"http" : "http://" + host}) | |
1793 | |
1794 authinfo = None | |
1795 if user and passwd: | |
1796 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() | |
1797 passmgr.add_password(None, host, user, passwd) | |
1798 authinfo = urllib2.ProxyBasicAuthHandler(passmgr) | |
1799 | |
1800 opener = urllib2.build_opener(proxy_handler, authinfo) | |
1801 urllib2.install_opener(opener) | |
60 | 1802 |
634
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1803 def dev(self): |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1804 return -1 |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1805 |
60 | 1806 def do_cmd(self, cmd, **args): |
83 | 1807 self.ui.debug("sending %s command\n" % cmd) |
60 | 1808 q = {"cmd": cmd} |
1809 q.update(args) | |
1810 qs = urllib.urlencode(q) | |
1811 cu = "%s?%s" % (self.url, qs) | |
752 | 1812 resp = urllib2.urlopen(cu) |
753 | 1813 proto = resp.headers['content-type'] |
752 | 1814 |
753 | 1815 # accept old "text/plain" and "application/hg-changegroup" for now |
1816 if not proto.startswith('application/mercurial') and \ | |
1817 not proto.startswith('text/plain') and \ | |
1818 not proto.startswith('application/hg-changegroup'): | |
752 | 1819 raise RepoError("'%s' does not appear to be an hg repository" |
1820 % self.url) | |
1821 | |
753 | 1822 if proto.startswith('application/mercurial'): |
1823 version = proto[22:] | |
1824 if float(version) > 0.1: | |
1825 raise RepoError("'%s' uses newer protocol %s" % | |
1826 (self.url, version)) | |
1827 | |
752 | 1828 return resp |
60 | 1829 |
222 | 1830 def heads(self): |
1831 d = self.do_cmd("heads").read() | |
1832 try: | |
1833 return map(bin, d[:-1].split(" ")) | |
1834 except: | |
1835 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1836 raise | |
1837 | |
60 | 1838 def branches(self, nodes): |
1839 n = " ".join(map(hex, nodes)) | |
752 | 1840 d = self.do_cmd("branches", nodes=n).read() |
217 | 1841 try: |
1842 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] | |
1843 return br | |
1844 except: | |
1845 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1846 raise | |
60 | 1847 |
1848 def between(self, pairs): | |
1849 n = "\n".join(["-".join(map(hex, p)) for p in pairs]) | |
752 | 1850 d = self.do_cmd("between", pairs=n).read() |
217 | 1851 try: |
1852 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ] | |
1853 return p | |
1854 except: | |
1855 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1856 raise | |
60 | 1857 |
1858 def changegroup(self, nodes): | |
1859 n = " ".join(map(hex, nodes)) | |
752 | 1860 f = self.do_cmd("changegroup", roots=n) |
192 | 1861 bytes = 0 |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1862 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1863 class zread: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1864 def __init__(self, f): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1865 self.zd = zlib.decompressobj() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1866 self.f = f |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1867 self.buf = "" |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1868 def read(self, l): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1869 while l > len(self.buf): |
751
0b245edec124
When pulling from a non hg repository URL (e.g. http://www.kernel.org/hg)
Muli Ben-Yehuda <mulix@mulix.org>
parents:
741
diff
changeset
|
1870 r = self.f.read(4096) |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1871 if r: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1872 self.buf += self.zd.decompress(r) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1873 else: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1874 self.buf += self.zd.flush() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1875 break |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1876 d, self.buf = self.buf[:l], self.buf[l:] |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1877 return d |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1878 |
752 | 1879 return zread(f) |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1880 |
638
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1881 class remotelock: |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1882 def __init__(self, repo): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1883 self.repo = repo |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1884 def release(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1885 self.repo.unlock() |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1886 self.repo = None |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1887 def __del__(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1888 if self.repo: |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1889 self.release() |
60 | 1890 |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1891 class sshrepository: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1892 def __init__(self, ui, path): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1893 self.url = path |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1894 self.ui = ui |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1895 |
817 | 1896 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))', path) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1897 if not m: |
817 | 1898 raise RepoError("couldn't parse destination %s" % path) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1899 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1900 self.user = m.group(2) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1901 self.host = m.group(3) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1902 self.port = m.group(5) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1903 self.path = m.group(7) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1904 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1905 args = self.user and ("%s@%s" % (self.user, self.host)) or self.host |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1906 args = self.port and ("%s -p %s") % (args, self.port) or args |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1907 path = self.path or "" |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1908 |
817 | 1909 if not path: |
1910 raise RepoError("no remote repository path specified") | |
1911 | |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1912 cmd = "ssh %s 'hg -R %s serve --stdio'" |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1913 cmd = cmd % (args, path) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1914 |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1915 self.pipeo, self.pipei, self.pipee = os.popen3(cmd) |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1916 |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1917 def readerr(self): |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1918 while 1: |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1919 r,w,x = select.select([self.pipee], [], [], 0) |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1920 if not r: break |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1921 l = self.pipee.readline() |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1922 if not l: break |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1923 self.ui.status("remote: ", l) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1924 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1925 def __del__(self): |
817 | 1926 try: |
1927 self.pipeo.close() | |
1928 self.pipei.close() | |
1929 for l in self.pipee: | |
1930 self.ui.status("remote: ", l) | |
1931 self.pipee.close() | |
1932 except: | |
1933 pass | |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1934 |
634
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1935 def dev(self): |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1936 return -1 |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1937 |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1938 def do_cmd(self, cmd, **args): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1939 self.ui.debug("sending %s command\n" % cmd) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1940 self.pipeo.write("%s\n" % cmd) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1941 for k, v in args.items(): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1942 self.pipeo.write("%s %d\n" % (k, len(v))) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1943 self.pipeo.write(v) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1944 self.pipeo.flush() |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1945 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1946 return self.pipei |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1947 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1948 def call(self, cmd, **args): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1949 r = self.do_cmd(cmd, **args) |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1950 l = r.readline() |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1951 self.readerr() |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1952 try: |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1953 l = int(l) |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1954 except: |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1955 raise RepoError("unexpected response '%s'" % l) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1956 return r.read(l) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1957 |
638
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1958 def lock(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1959 self.call("lock") |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1960 return remotelock(self) |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1961 |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1962 def unlock(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1963 self.call("unlock") |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1964 |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1965 def heads(self): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1966 d = self.call("heads") |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1967 try: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1968 return map(bin, d[:-1].split(" ")) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1969 except: |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1970 raise RepoError("unexpected response '%s'" % (d[:400] + "...")) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1971 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1972 def branches(self, nodes): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1973 n = " ".join(map(hex, nodes)) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1974 d = self.call("branches", nodes=n) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1975 try: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1976 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1977 return br |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1978 except: |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1979 raise RepoError("unexpected response '%s'" % (d[:400] + "...")) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1980 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1981 def between(self, pairs): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1982 n = "\n".join(["-".join(map(hex, p)) for p in pairs]) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1983 d = self.call("between", pairs=n) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1984 try: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1985 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ] |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1986 return p |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1987 except: |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1988 raise RepoError("unexpected response '%s'" % (d[:400] + "...")) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1989 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1990 def changegroup(self, nodes): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1991 n = " ".join(map(hex, nodes)) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1992 f = self.do_cmd("changegroup", roots=n) |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1993 return self.pipei |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1994 |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1995 def addchangegroup(self, cg): |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1996 d = self.call("addchangegroup") |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1997 if d: |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1998 raise RepoError("push refused: %s", d) |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1999 |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2000 while 1: |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2001 d = cg.read(4096) |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2002 if not d: break |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2003 self.pipeo.write(d) |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
2004 self.readerr() |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2005 |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2006 self.pipeo.flush() |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2007 |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
2008 self.readerr() |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2009 l = int(self.pipei.readline()) |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
2010 return self.pipei.read(l) != "" |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
2011 |
60 | 2012 def repository(ui, path=None, create=0): |
623
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2013 if path: |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2014 if path.startswith("http://"): |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2015 return httprepository(ui, path) |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2016 if path.startswith("hg://"): |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2017 return httprepository(ui, path.replace("hg://", "http://")) |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2018 if path.startswith("old-http://"): |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2019 return localrepository(ui, path.replace("old-http://", "http://")) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
2020 if path.startswith("ssh://"): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
2021 return sshrepository(ui, path) |
60 | 2022 |
623
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
2023 return localrepository(ui, path, create) |