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