Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/hg.py @ 764:eea96285cbf9
Don't mark files with 'm'erge unless we're actually merging branches
For 3-way merges, we were marking files as 'm', which should only be
used for branch merges. This was causing files to show up in 'hg
status' that aren't actually modified.
author | mpm@selenic.com |
---|---|
date | Fri, 22 Jul 2005 19:23:00 -0500 |
parents | 8760d0c83b9b |
children | 1e31d97c3d70 |
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") | |
434 | 13 demandload(globals(), "tempfile httprangereader bdiff") |
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 = "" | |
251 | 678 self.opener("undo.dirstate", "w").write(ds) |
515 | 679 |
582 | 680 return transaction.transaction(self.ui.warn, |
681 self.opener, self.join("journal"), | |
262 | 682 self.join("undo")) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
683 |
210 | 684 def recover(self): |
225 | 685 lock = self.lock() |
557 | 686 if os.path.exists(self.join("journal")): |
501 | 687 self.ui.status("rolling back interrupted transaction\n") |
557 | 688 return transaction.rollback(self.opener, self.join("journal")) |
210 | 689 else: |
690 self.ui.warn("no interrupted transaction available\n") | |
691 | |
692 def undo(self): | |
225 | 693 lock = self.lock() |
210 | 694 if os.path.exists(self.join("undo")): |
501 | 695 self.ui.status("rolling back last transaction\n") |
262 | 696 transaction.rollback(self.opener, self.join("undo")) |
251 | 697 self.dirstate = None |
421 | 698 util.rename(self.join("undo.dirstate"), self.join("dirstate")) |
251 | 699 self.dirstate = dirstate(self.opener, self.ui, self.root) |
163 | 700 else: |
210 | 701 self.ui.warn("no undo information available\n") |
162 | 702 |
161 | 703 def lock(self, wait = 1): |
704 try: | |
705 return lock.lock(self.join("lock"), 0) | |
706 except lock.LockHeld, inst: | |
707 if wait: | |
708 self.ui.warn("waiting for lock held by %s\n" % inst.args[0]) | |
709 return lock.lock(self.join("lock"), wait) | |
710 raise inst | |
711 | |
203 | 712 def rawcommit(self, files, text, user, date, p1=None, p2=None): |
442 | 713 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
|
714 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
|
715 p2 = p2 or self.dirstate.parents()[1] or nullid |
302 | 716 c1 = self.changelog.read(p1) |
717 c2 = self.changelog.read(p2) | |
718 m1 = self.manifest.read(c1[0]) | |
719 mf1 = self.manifest.readflags(c1[0]) | |
720 m2 = self.manifest.read(c2[0]) | |
721 | |
442 | 722 if orig_parent == p1: |
723 update_dirstate = 1 | |
724 else: | |
725 update_dirstate = 0 | |
726 | |
203 | 727 tr = self.transaction() |
302 | 728 mm = m1.copy() |
729 mfm = mf1.copy() | |
203 | 730 linkrev = self.changelog.count() |
731 for f in files: | |
732 try: | |
302 | 733 t = self.wfile(f).read() |
441 | 734 tm = util.is_exec(self.wjoin(f), mfm.get(f, False)) |
302 | 735 r = self.file(f) |
736 mfm[f] = tm | |
360 | 737 mm[f] = r.add(t, {}, tr, linkrev, |
302 | 738 m1.get(f, nullid), m2.get(f, nullid)) |
442 | 739 if update_dirstate: |
740 self.dirstate.update([f], "n") | |
203 | 741 except IOError: |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
742 try: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
743 del mm[f] |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
744 del mfm[f] |
442 | 745 if update_dirstate: |
746 self.dirstate.forget([f]) | |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
747 except: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
748 # deleted from p2? |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
749 pass |
203 | 750 |
302 | 751 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
|
752 user = user or self.ui.username() |
302 | 753 n = self.changelog.add(mnode, files, text, tr, p1, p2, user, date) |
203 | 754 tr.close() |
442 | 755 if update_dirstate: |
756 self.dirstate.setparents(n, nullid) | |
203 | 757 |
317 | 758 def commit(self, files = None, text = "", user = None, date = None): |
220 | 759 commit = [] |
760 remove = [] | |
761 if files: | |
762 for f in files: | |
763 s = self.dirstate.state(f) | |
244 | 764 if s in 'nmai': |
220 | 765 commit.append(f) |
766 elif s == 'r': | |
767 remove.append(f) | |
768 else: | |
244 | 769 self.ui.warn("%s not tracked!\n" % f) |
220 | 770 else: |
723 | 771 (c, a, d, u) = self.changes() |
220 | 772 commit = c + a |
773 remove = d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
774 |
220 | 775 if not commit and not remove: |
151 | 776 self.ui.status("nothing changed\n") |
777 return | |
778 | |
487 | 779 if not self.hook("precommit"): |
780 return 1 | |
781 | |
229 | 782 p1, p2 = self.dirstate.parents() |
783 c1 = self.changelog.read(p1) | |
784 c2 = self.changelog.read(p2) | |
785 m1 = self.manifest.read(c1[0]) | |
276 | 786 mf1 = self.manifest.readflags(c1[0]) |
229 | 787 m2 = self.manifest.read(c2[0]) |
225 | 788 lock = self.lock() |
151 | 789 tr = self.transaction() |
790 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
791 # check in files |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
792 new = {} |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
793 linkrev = self.changelog.count() |
220 | 794 commit.sort() |
795 for f in commit: | |
83 | 796 self.ui.note(f + "\n") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
797 try: |
441 | 798 mf1[f] = util.is_exec(self.wjoin(f), mf1.get(f, False)) |
418 | 799 t = self.wfile(f).read() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
800 except IOError: |
667
31a9aa890016
A number of minor fixes to problems that pychecker found.
mark.williamson@cl.cam.ac.uk
parents:
660
diff
changeset
|
801 self.ui.warn("trouble committing %s!\n" % f) |
220 | 802 raise |
803 | |
363 | 804 meta = {} |
805 cp = self.dirstate.copied(f) | |
806 if cp: | |
807 meta["copy"] = cp | |
808 meta["copyrev"] = hex(m1.get(cp, m2.get(cp, nullid))) | |
575 | 809 self.ui.debug(" %s: copy %s:%s\n" % (f, cp, meta["copyrev"])) |
363 | 810 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
811 r = self.file(f) |
229 | 812 fp1 = m1.get(f, nullid) |
813 fp2 = m2.get(f, nullid) | |
363 | 814 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
|
815 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
816 # update manifest |
229 | 817 m1.update(new) |
416
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
818 for f in remove: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
819 if f in m1: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
820 del m1[f] |
741 | 821 mn = self.manifest.add(m1, mf1, tr, linkrev, c1[0], c2[0], |
822 (new, remove)) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
823 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
824 # add changeset |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
825 new = new.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
826 new.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
827 |
288 | 828 if not text: |
829 edittext = "\n" + "HG: manifest hash %s\n" % hex(mn) | |
830 edittext += "".join(["HG: changed %s\n" % f for f in new]) | |
831 edittext += "".join(["HG: removed %s\n" % f for f in remove]) | |
832 edittext = self.ui.edit(edittext) | |
833 if not edittext.rstrip(): | |
834 return 1 | |
835 text = edittext | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
836 |
608
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
837 user = user or self.ui.username() |
317 | 838 n = self.changelog.add(mn, new, text, tr, p1, p2, user, date) |
487 | 839 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
840 tr.close() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
841 |
229 | 842 self.dirstate.setparents(n) |
220 | 843 self.dirstate.update(new, "n") |
844 self.dirstate.forget(remove) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
845 |
660
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
846 if not self.hook("commit", node=hex(n)): |
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
847 return 1 |
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
848 |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
849 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
|
850 if node: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
851 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
|
852 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
|
853 else: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
854 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
|
855 yield src, fn |
723 | 856 |
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 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
|
858 match = util.always): |
566 | 859 mf2, u = None, [] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
860 |
536 | 861 def fcmp(fn, mf): |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
862 t1 = self.wfile(fn).read() |
29 | 863 t2 = self.file(fn).revision(mf[fn]) |
864 return cmp(t1, t2) | |
865 | |
723 | 866 def mfmatches(node): |
867 mf = dict(self.manifest.read(node)) | |
868 for fn in mf.keys(): | |
869 if not match(fn): | |
870 del mf[fn] | |
871 return mf | |
741 | 872 |
536 | 873 # are we comparing the working directory? |
561 | 874 if not node2: |
723 | 875 l, c, a, d, u = self.dirstate.changes(files, match) |
536 | 876 |
877 # are we comparing working dir against its parent? | |
561 | 878 if not node1: |
536 | 879 if l: |
880 # do a full compare of any files that might have changed | |
881 change = self.changelog.read(self.dirstate.parents()[0]) | |
723 | 882 mf2 = mfmatches(change[0]) |
548 | 883 for f in l: |
561 | 884 if fcmp(f, mf2): |
536 | 885 c.append(f) |
561 | 886 |
887 for l in c, a, d, u: | |
888 l.sort() | |
889 | |
536 | 890 return (c, a, d, u) |
515 | 891 |
536 | 892 # are we comparing working dir against non-tip? |
893 # generate a pseudo-manifest for the working dir | |
561 | 894 if not node2: |
895 if not mf2: | |
536 | 896 change = self.changelog.read(self.dirstate.parents()[0]) |
723 | 897 mf2 = mfmatches(change[0]) |
536 | 898 for f in a + c + l: |
561 | 899 mf2[f] = "" |
536 | 900 for f in d: |
561 | 901 if f in mf2: del mf2[f] |
536 | 902 else: |
561 | 903 change = self.changelog.read(node2) |
723 | 904 mf2 = mfmatches(change[0]) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
905 |
566 | 906 # flush lists from dirstate before comparing manifests |
907 c, a = [], [] | |
908 | |
561 | 909 change = self.changelog.read(node1) |
723 | 910 mf1 = mfmatches(change[0]) |
32 | 911 |
912 for fn in mf2: | |
913 if mf1.has_key(fn): | |
914 if mf1[fn] != mf2[fn]: | |
561 | 915 if mf2[fn] != "" or fcmp(fn, mf1): |
536 | 916 c.append(fn) |
32 | 917 del mf1[fn] |
918 else: | |
536 | 919 a.append(fn) |
515 | 920 |
536 | 921 d = mf1.keys() |
561 | 922 |
923 for l in c, a, d, u: | |
924 l.sort() | |
515 | 925 |
536 | 926 return (c, a, d, u) |
32 | 927 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
928 def add(self, list): |
220 | 929 for f in list: |
244 | 930 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
|
931 if not os.path.exists(p): |
659 | 932 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
|
933 elif not os.path.isfile(p): |
741 | 934 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
|
935 elif self.dirstate.state(f) in 'an': |
220 | 936 self.ui.warn("%s already tracked!\n" % f) |
937 else: | |
938 self.dirstate.update([f], "a") | |
939 | |
940 def forget(self, list): | |
941 for f in list: | |
942 if self.dirstate.state(f) not in 'ai': | |
943 self.ui.warn("%s not added!\n" % f) | |
944 else: | |
945 self.dirstate.forget([f]) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
946 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
947 def remove(self, list): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
948 for f in list: |
244 | 949 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
|
950 if os.path.exists(p): |
220 | 951 self.ui.warn("%s still exists!\n" % f) |
402 | 952 elif self.dirstate.state(f) == 'a': |
953 self.ui.warn("%s never committed!\n" % f) | |
657
22bc6fb9aefc
dirstate.forget() takes a list
Matt Mackall <mpm@selenic.com>
parents:
656
diff
changeset
|
954 self.dirstate.forget([f]) |
220 | 955 elif f not in self.dirstate: |
956 self.ui.warn("%s not tracked!\n" % f) | |
957 else: | |
958 self.dirstate.update([f], "r") | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
959 |
363 | 960 def copy(self, source, dest): |
961 p = self.wjoin(dest) | |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
962 if not os.path.exists(dest): |
363 | 963 self.ui.warn("%s does not exist!\n" % dest) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
964 elif not os.path.isfile(dest): |
659 | 965 self.ui.warn("copy failed: %s is not a file\n" % dest) |
363 | 966 else: |
967 if self.dirstate.state(dest) == '?': | |
968 self.dirstate.update([dest], "a") | |
969 self.dirstate.copy(source, dest) | |
970 | |
222 | 971 def heads(self): |
972 return self.changelog.heads() | |
973 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
974 def branches(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
975 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
|
976 b = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
977 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
978 t = n |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
979 while n: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
980 p = self.changelog.parents(n) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
981 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
|
982 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
|
983 break |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
984 n = p[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
985 return b |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
986 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
987 def between(self, pairs): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
988 r = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
989 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
990 for top, bottom in pairs: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
991 n, l, i = top, [], 0 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
992 f = 1 |
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 while n != bottom: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
995 p = self.changelog.parents(n)[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
996 if i == f: |
575 | 997 l.append(n) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
998 f = f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
999 n = p |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1000 i += 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1001 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1002 r.append(l) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1003 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1004 return r |
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 def newer(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1007 m = {} |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1008 nl = [] |
94 | 1009 pm = {} |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1010 cl = self.changelog |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1011 t = l = cl.count() |
94 | 1012 |
1013 # find the lowest numbered node | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1014 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1015 l = min(l, cl.rev(n)) |
94 | 1016 m[n] = 1 |
46 | 1017 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1018 for i in xrange(l, t): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1019 n = cl.node(i) |
94 | 1020 if n in m: # explicitly listed |
1021 pm[n] = 1 | |
1022 nl.append(n) | |
1023 continue | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1024 for p in cl.parents(n): |
94 | 1025 if p in pm: # parent listed |
1026 pm[n] = 1 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1027 nl.append(n) |
94 | 1028 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1029 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1030 return nl |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1031 |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1032 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
|
1033 m = self.changelog.nodemap |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1034 search = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1035 fetch = [] |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1036 seen = {} |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1037 seenbranch = {} |
192 | 1038 |
636
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1039 # 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
|
1040 # and start by examining the heads |
222 | 1041 self.ui.status("searching for changes\n") |
1042 heads = remote.heads() | |
1043 unknown = [] | |
1044 for h in heads: | |
1045 if h not in m: | |
1046 unknown.append(h) | |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1047 else: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1048 base[h] = 1 |
46 | 1049 |
222 | 1050 if not unknown: |
60 | 1051 return None |
324 | 1052 |
1053 rep = {} | |
1054 reqcnt = 0 | |
515 | 1055 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1056 # search through remote branches |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1057 # 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
|
1058 # head, root, first parent, second parent |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1059 # (a branch always has two parents (or none) by definition) |
222 | 1060 unknown = remote.branches(unknown) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1061 while unknown: |
324 | 1062 r = [] |
1063 while unknown: | |
1064 n = unknown.pop(0) | |
1065 if n[0] in seen: | |
1066 continue | |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1067 |
324 | 1068 self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) |
1069 if n[0] == nullid: | |
1070 break | |
328 | 1071 if n in seenbranch: |
324 | 1072 self.ui.debug("branch already found\n") |
1073 continue | |
1074 if n[1] and n[1] in m: # do we know the base? | |
1075 self.ui.debug("found incomplete branch %s:%s\n" | |
1076 % (short(n[0]), short(n[1]))) | |
1077 search.append(n) # schedule branch range for scanning | |
328 | 1078 seenbranch[n] = 1 |
324 | 1079 else: |
1080 if n[1] not in seen and n[1] not in fetch: | |
1081 if n[2] in m and n[3] in m: | |
1082 self.ui.debug("found new changeset %s\n" % | |
1083 short(n[1])) | |
1084 fetch.append(n[1]) # earliest unknown | |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1085 base[n[2]] = 1 # latest known |
324 | 1086 continue |
1087 | |
1088 for a in n[2:4]: | |
1089 if a not in rep: | |
1090 r.append(a) | |
1091 rep[a] = 1 | |
1092 | |
328 | 1093 seen[n[0]] = 1 |
1094 | |
324 | 1095 if r: |
1096 reqcnt += 1 | |
1097 self.ui.debug("request %d: %s\n" % | |
1098 (reqcnt, " ".join(map(short, r)))) | |
1099 for p in range(0, len(r), 10): | |
1100 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
|
1101 self.ui.debug("received %s:%s\n" % |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1102 (short(b[0]), short(b[1]))) |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
1103 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
|
1104 unknown.append(b) |
515 | 1105 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1106 # 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
|
1107 while search: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1108 n = search.pop(0) |
324 | 1109 reqcnt += 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1110 l = remote.between([(n[0], n[1])])[0] |
328 | 1111 l.append(n[1]) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1112 p = n[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1113 f = 1 |
328 | 1114 for i in l: |
1115 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
|
1116 if i in m: |
85 | 1117 if f <= 2: |
83 | 1118 self.ui.debug("found new branch changeset %s\n" % |
1119 short(p)) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1120 fetch.append(p) |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1121 base[i] = 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1122 else: |
83 | 1123 self.ui.debug("narrowed branch search to %s:%s\n" |
1124 % (short(p), short(i))) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1125 search.append((p, i)) |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1126 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1127 p, f = i, f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1128 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1129 # 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
|
1130 for f in fetch: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1131 if f in m: |
499 | 1132 raise RepoError("already have changeset " + short(f[:4])) |
83 | 1133 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
1134 if base.keys() == [nullid]: |
514
874e577e332e
change unrelated repository error to a warning
mpm@selenic.com
parents:
511
diff
changeset
|
1135 self.ui.warn("warning: pulling from an unrelated repository!\n") |
511 | 1136 |
94 | 1137 self.ui.note("adding new changesets starting at " + |
83 | 1138 " ".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
|
1139 |
324 | 1140 self.ui.debug("%d total queries\n" % reqcnt) |
1141 | |
516 | 1142 return fetch |
1143 | |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1144 def findoutgoing(self, remote): |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1145 base = {} |
637
31e090c34d3b
Fix up the broken bits in findoutgoing
Matt Mackall <mpm@selenic.com>
parents:
636
diff
changeset
|
1146 self.findincoming(remote, base) |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1147 remain = dict.fromkeys(self.changelog.nodemap) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1148 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1149 # 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
|
1150 del remain[nullid] |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1151 remove = base.keys() |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1152 while remove: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1153 n = remove.pop(0) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1154 if n in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1155 del remain[n] |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1156 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
|
1157 remove.append(p) |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1158 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1159 # 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
|
1160 subset = [] |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1161 for n in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1162 p1, p2 = self.changelog.parents(n) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1163 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
|
1164 subset.append(n) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1165 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1166 # 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
|
1167 return subset |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
1168 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1169 def pull(self, remote): |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1170 lock = self.lock() |
636
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1171 |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1172 # 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
|
1173 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
|
1174 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
|
1175 fetch = [nullid] |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1176 else: |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1177 fetch = self.findincoming(remote) |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
1178 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1179 if not fetch: |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1180 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
|
1181 return 1 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1182 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1183 cg = remote.changegroup(fetch) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1184 return self.addchangegroup(cg) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1185 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1186 def push(self, remote): |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1187 lock = remote.lock() |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1188 update = self.findoutgoing(remote) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1189 if not update: |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1190 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
|
1191 return 1 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1192 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1193 cg = self.changegroup(update) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1194 return remote.addchangegroup(cg) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
1195 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
1196 def changegroup(self, basenodes): |
222 | 1197 class genread: |
1198 def __init__(self, generator): | |
1199 self.g = generator | |
1200 self.buf = "" | |
1201 def read(self, l): | |
1202 while l > len(self.buf): | |
1203 try: | |
1204 self.buf += self.g.next() | |
1205 except StopIteration: | |
1206 break | |
1207 d, self.buf = self.buf[:l], self.buf[l:] | |
1208 return d | |
515 | 1209 |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1210 def gengroup(): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1211 nodes = self.newer(basenodes) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1212 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1213 # construct the link map |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1214 linkmap = {} |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1215 for n in nodes: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1216 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
|
1217 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1218 # 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
|
1219 changed = {} |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1220 for n in nodes: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1221 c = self.changelog.read(n) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1222 for f in c[3]: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1223 changed[f] = 1 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1224 changed = changed.keys() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1225 changed.sort() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1226 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1227 # 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
|
1228 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
|
1229 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1230 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
|
1231 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
|
1232 for f in changed: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1233 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
|
1234 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
|
1235 for y in g: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1236 yield y |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1237 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1238 yield struct.pack(">l", 0) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1239 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1240 return genread(gengroup()) |
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 def addchangegroup(self, source): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1243 |
222 | 1244 def getchunk(): |
1245 d = source.read(4) | |
1246 if not d: return "" | |
1247 l = struct.unpack(">l", d)[0] | |
1248 if l <= 4: return "" | |
1249 return source.read(l - 4) | |
1250 | |
1251 def getgroup(): | |
1252 while 1: | |
1253 c = getchunk() | |
1254 if not c: break | |
1255 yield c | |
1256 | |
1257 def csmap(x): | |
1258 self.ui.debug("add changeset %s\n" % short(x)) | |
1259 return self.changelog.count() | |
1260 | |
1261 def revmap(x): | |
1262 return self.changelog.rev(x) | |
1263 | |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1264 if not source: return |
222 | 1265 changesets = files = revisions = 0 |
225 | 1266 |
222 | 1267 tr = self.transaction() |
1268 | |
1269 # pull off the changeset group | |
1270 self.ui.status("adding changesets\n") | |
1271 co = self.changelog.tip() | |
224
ccbcc4d76f81
fix bad assumption about uniqueness of file versions
mpm@selenic.com
parents:
223
diff
changeset
|
1272 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique |
222 | 1273 changesets = self.changelog.rev(cn) - self.changelog.rev(co) |
1274 | |
1275 # pull off the manifest group | |
1276 self.ui.status("adding manifests\n") | |
1277 mm = self.manifest.tip() | |
1278 mo = self.manifest.addgroup(getgroup(), revmap, tr) | |
1279 | |
1280 # process the files | |
1281 self.ui.status("adding file revisions\n") | |
1282 while 1: | |
1283 f = getchunk() | |
1284 if not f: break | |
1285 self.ui.debug("adding %s revisions\n" % f) | |
1286 fl = self.file(f) | |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1287 o = fl.count() |
222 | 1288 n = fl.addgroup(getgroup(), revmap, tr) |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1289 revisions += fl.count() - o |
222 | 1290 files += 1 |
1291 | |
1292 self.ui.status(("modified %d files, added %d changesets" + | |
1293 " and %d new revisions\n") | |
1294 % (files, changesets, revisions)) | |
1295 | |
1296 tr.close() | |
1297 return | |
1298 | |
588 | 1299 def update(self, node, allow=False, force=False, choose=None, |
1300 moddirstate=True): | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1301 pl = self.dirstate.parents() |
275 | 1302 if not force and pl[1] != nullid: |
254 | 1303 self.ui.warn("aborting: outstanding uncommitted merges\n") |
690 | 1304 return 1 |
46 | 1305 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1306 p1, p2 = pl[0], node |
305 | 1307 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
|
1308 m1n = self.changelog.read(p1)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1309 m2n = self.changelog.read(p2)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1310 man = self.manifest.ancestor(m1n, m2n) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1311 m1 = self.manifest.read(m1n) |
276 | 1312 mf1 = self.manifest.readflags(m1n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1313 m2 = self.manifest.read(m2n) |
276 | 1314 mf2 = self.manifest.readflags(m2n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1315 ma = self.manifest.read(man) |
412 | 1316 mfa = self.manifest.readflags(man) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1317 |
723 | 1318 (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
|
1319 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1320 # 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
|
1321 # from p1 to p2? |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1322 linear_path = (pa == p1 or pa == p2) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1323 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1324 # 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
|
1325 # we care about merging |
254 | 1326 self.ui.note("resolving manifests\n") |
650
2c934c7b79dc
Fix bug in reverting deleted files
Matt Mackall <mpm@selenic.com>
parents:
649
diff
changeset
|
1327 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
|
1328 (force, allow, moddirstate, linear_path)) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1329 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
|
1330 (short(man), short(m1n), short(m2n))) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1331 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1332 merge = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1333 get = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1334 remove = [] |
305 | 1335 mark = {} |
46 | 1336 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1337 # construct a working dir manifest |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1338 mw = m1.copy() |
276 | 1339 mfw = mf1.copy() |
576 | 1340 umap = dict.fromkeys(u) |
1341 | |
254 | 1342 for f in a + c + u: |
1343 mw[f] = "" | |
441 | 1344 mfw[f] = util.is_exec(self.wjoin(f), mfw.get(f, False)) |
576 | 1345 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1346 for f in d: |
254 | 1347 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
|
1348 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1349 # 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
|
1350 # 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
|
1351 # 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
|
1352 # 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
|
1353 # longer in the manifest. |
588 | 1354 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
|
1355 self.dirstate.forget((f,)) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1356 |
576 | 1357 # Compare manifests |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1358 for f, n in mw.iteritems(): |
588 | 1359 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
|
1360 if f in m2: |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1361 s = 0 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1362 |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1363 # is the wfile new since m1, and match m2? |
428 | 1364 if f not in m1: |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1365 t1 = self.wfile(f).read() |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1366 t2 = self.file(f).revision(m2[f]) |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1367 if cmp(t1, t2) == 0: |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1368 mark[f] = 1 |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1369 n = m2[f] |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1370 del t1, t2 |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1371 |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1372 # are files different? |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1373 if n != m2[f]: |
254 | 1374 a = ma.get(f, nullid) |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1375 # are both different from the ancestor? |
254 | 1376 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
|
1377 self.ui.debug(" %s versions differ, resolve\n" % f) |
276 | 1378 # merge executable bits |
1379 # "if we changed or they changed, change in merge" | |
1380 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] | |
1381 mode = ((a^b) | (a^c)) ^ a | |
1382 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
|
1383 s = 1 |
305 | 1384 # are we clobbering? |
1385 # is remote's version newer? | |
1386 # or are we going back in time? | |
1387 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
|
1388 self.ui.debug(" remote %s is newer, get\n" % f) |
254 | 1389 get[f] = m2[f] |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1390 s = 1 |
305 | 1391 else: |
1392 mark[f] = 1 | |
576 | 1393 elif f in umap: |
1394 # this unknown file is the same as the checkout | |
1395 get[f] = m2[f] | |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1396 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1397 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
|
1398 if force: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1399 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1400 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
|
1401 else: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1402 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
|
1403 mode = ((a^b) | (a^c)) ^ a |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1404 if mode != b: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1405 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1406 util.set_exec(self.wjoin(f), mode) |
305 | 1407 mark[f] = 1 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1408 del m2[f] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1409 elif f in ma: |
616 | 1410 if n != ma[f]: |
1411 r = "d" | |
1412 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
|
1413 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
|
1414 (" 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
|
1415 "(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
|
1416 if r == "d": |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1417 remove.append(f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1418 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1419 self.ui.debug("other deleted %s\n" % f) |
254 | 1420 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
|
1421 else: |
254 | 1422 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
|
1423 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
|
1424 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
|
1425 remove.append(f) |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1426 else: |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1427 self.ui.debug("local created %s, keeping\n" % f) |
254 | 1428 else: |
1429 self.ui.debug("working dir created %s, keeping\n" % f) | |
46 | 1430 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1431 for f, n in m2.iteritems(): |
588 | 1432 if choose and not choose(f): continue |
256 | 1433 if f[0] == "/": continue |
616 | 1434 if f in ma and n != ma[f]: |
1435 r = "k" | |
1436 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
|
1437 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
|
1438 ("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
|
1439 "(k)eep or (d)elete?", "[kd]", "k") |
616 | 1440 if r == "k": get[f] = n |
1441 elif f not in ma: | |
254 | 1442 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
|
1443 get[f] = n |
616 | 1444 else: |
680
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1445 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
|
1446 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
|
1447 get[f] = n |
680
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1448 else: |
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1449 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
|
1450 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1451 del mw, m1, m2, ma |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1452 |
275 | 1453 if force: |
1454 for f in merge: | |
1455 get[f] = merge[f][1] | |
1456 merge = {} | |
1457 | |
690 | 1458 if linear_path or force: |
254 | 1459 # we don't need to do any magic, just jump to the new rev |
1460 mode = 'n' | |
1461 p1, p2 = p2, nullid | |
1462 else: | |
275 | 1463 if not allow: |
305 | 1464 self.ui.status("this update spans a branch" + |
1465 " affecting the following files:\n") | |
1466 fl = merge.keys() + get.keys() | |
1467 fl.sort() | |
1468 for f in fl: | |
1469 cf = "" | |
1470 if f in merge: cf = " (resolve)" | |
1471 self.ui.status(" %s%s\n" % (f, cf)) | |
1472 self.ui.warn("aborting update spanning branches!\n") | |
1473 self.ui.status("(use update -m to perform a branch merge)\n") | |
275 | 1474 return 1 |
254 | 1475 # we have to remember what files we needed to get/change |
1476 # because any file that's different from either one of its | |
1477 # parents must be in the changeset | |
1478 mode = 'm' | |
588 | 1479 if moddirstate: |
1480 self.dirstate.update(mark.keys(), "m") | |
254 | 1481 |
588 | 1482 if moddirstate: |
1483 self.dirstate.setparents(p1, p2) | |
191
d7e859cf2f1b
merge: add count of new manifests, files, and revisions
mpm@selenic.com
parents:
190
diff
changeset
|
1484 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1485 # 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
|
1486 files = get.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1487 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1488 for f in files: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1489 if f[0] == "/": continue |
273
4f8174389001
merge: Fix bug where we overwrote local when local was newer
mpm@selenic.com
parents:
263
diff
changeset
|
1490 self.ui.note("getting %s\n" % f) |
276 | 1491 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
|
1492 try: |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
1493 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
|
1494 except IOError: |
297
0dbcf3c9ff20
Fixed usage of removed variable 'wp'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
292
diff
changeset
|
1495 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
|
1496 self.wfile(f, "w").write(t) |
441 | 1497 util.set_exec(self.wjoin(f), mf2[f]) |
588 | 1498 if moddirstate: |
1499 self.dirstate.update([f], mode) | |
46 | 1500 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1501 # merge the tricky bits |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1502 files = merge.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1503 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1504 for f in files: |
256 | 1505 self.ui.status("merging %s\n" % f) |
276 | 1506 m, o, flag = merge[f] |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1507 self.merge3(f, m, o) |
441 | 1508 util.set_exec(self.wjoin(f), flag) |
588 | 1509 if moddirstate: |
764
eea96285cbf9
Don't mark files with 'm'erge unless we're actually merging branches
mpm@selenic.com
parents:
753
diff
changeset
|
1510 self.dirstate.update([f], mode) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1511 |
681 | 1512 remove.sort() |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1513 for f in remove: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1514 self.ui.note("removing %s\n" % f) |
690 | 1515 try: |
1516 os.unlink(f) | |
1517 except OSError, inst: | |
1518 self.ui.warn("update failed to remove %s: %s!\n" % (f, inst)) | |
578 | 1519 # try removing directories that might now be empty |
1520 try: os.removedirs(os.path.dirname(f)) | |
1521 except: pass | |
588 | 1522 if moddirstate: |
1523 if mode == 'n': | |
1524 self.dirstate.forget(remove) | |
1525 else: | |
1526 self.dirstate.update(remove, 'r') | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1527 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1528 def merge3(self, fn, my, other): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1529 """perform a 3-way merge in the working directory""" |
249 | 1530 |
96 | 1531 def temp(prefix, node): |
1532 pre = "%s~%s." % (os.path.basename(fn), prefix) | |
1533 (fd, name) = tempfile.mkstemp("", pre) | |
417 | 1534 f = os.fdopen(fd, "wb") |
96 | 1535 f.write(fl.revision(node)) |
1536 f.close() | |
1537 return name | |
1538 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1539 fl = self.file(fn) |
96 | 1540 base = fl.ancestor(my, other) |
244 | 1541 a = self.wjoin(fn) |
346 | 1542 b = temp("base", base) |
1543 c = temp("other", other) | |
96 | 1544 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1545 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
|
1546 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
|
1547 (fn, short(other), short(base))) |
96 | 1548 |
703
fb6f85ecc863
merge program setting from hgrc wasn't used.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
691
diff
changeset
|
1549 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
|
1550 or "hgmerge") |
240 | 1551 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
|
1552 if r: |
275 | 1553 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
|
1554 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1555 os.unlink(b) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1556 os.unlink(c) |
96 | 1557 |
247 | 1558 def verify(self): |
1559 filelinkrevs = {} | |
1560 filenodes = {} | |
1561 changesets = revisions = files = 0 | |
1562 errors = 0 | |
1563 | |
302 | 1564 seen = {} |
247 | 1565 self.ui.status("checking changesets\n") |
1566 for i in range(self.changelog.count()): | |
1567 changesets += 1 | |
1568 n = self.changelog.node(i) | |
302 | 1569 if n in seen: |
1570 self.ui.warn("duplicate changeset at revision %d\n" % i) | |
1571 errors += 1 | |
1572 seen[n] = 1 | |
515 | 1573 |
247 | 1574 for p in self.changelog.parents(n): |
1575 if p not in self.changelog.nodemap: | |
1576 self.ui.warn("changeset %s has unknown parent %s\n" % | |
1577 (short(n), short(p))) | |
1578 errors += 1 | |
1579 try: | |
1580 changes = self.changelog.read(n) | |
1581 except Exception, inst: | |
1582 self.ui.warn("unpacking changeset %s: %s\n" % (short(n), inst)) | |
1583 errors += 1 | |
1584 | |
1585 for f in changes[3]: | |
1586 filelinkrevs.setdefault(f, []).append(i) | |
1587 | |
302 | 1588 seen = {} |
247 | 1589 self.ui.status("checking manifests\n") |
1590 for i in range(self.manifest.count()): | |
1591 n = self.manifest.node(i) | |
302 | 1592 if n in seen: |
1593 self.ui.warn("duplicate manifest at revision %d\n" % i) | |
1594 errors += 1 | |
1595 seen[n] = 1 | |
515 | 1596 |
247 | 1597 for p in self.manifest.parents(n): |
1598 if p not in self.manifest.nodemap: | |
1599 self.ui.warn("manifest %s has unknown parent %s\n" % | |
1600 (short(n), short(p))) | |
1601 errors += 1 | |
1602 | |
1603 try: | |
1604 delta = mdiff.patchtext(self.manifest.delta(n)) | |
1605 except KeyboardInterrupt: | |
582 | 1606 self.ui.warn("aborted") |
247 | 1607 sys.exit(0) |
1608 except Exception, inst: | |
1609 self.ui.warn("unpacking manifest %s: %s\n" | |
1610 % (short(n), inst)) | |
1611 errors += 1 | |
1612 | |
1613 ff = [ l.split('\0') for l in delta.splitlines() ] | |
1614 for f, fn in ff: | |
284 | 1615 filenodes.setdefault(f, {})[bin(fn[:40])] = 1 |
247 | 1616 |
1617 self.ui.status("crosschecking files in changesets and manifests\n") | |
1618 for f in filenodes: | |
1619 if f not in filelinkrevs: | |
1620 self.ui.warn("file %s in manifest but not in changesets\n" % f) | |
1621 errors += 1 | |
1622 | |
1623 for f in filelinkrevs: | |
1624 if f not in filenodes: | |
1625 self.ui.warn("file %s in changeset but not in manifest\n" % f) | |
1626 errors += 1 | |
1627 | |
1628 self.ui.status("checking files\n") | |
1629 ff = filenodes.keys() | |
1630 ff.sort() | |
1631 for f in ff: | |
1632 if f == "/dev/null": continue | |
1633 files += 1 | |
1634 fl = self.file(f) | |
1635 nodes = { nullid: 1 } | |
302 | 1636 seen = {} |
247 | 1637 for i in range(fl.count()): |
1638 revisions += 1 | |
1639 n = fl.node(i) | |
1640 | |
302 | 1641 if n in seen: |
1642 self.ui.warn("%s: duplicate revision %d\n" % (f, i)) | |
1643 errors += 1 | |
1644 | |
247 | 1645 if n not in filenodes[f]: |
1646 self.ui.warn("%s: %d:%s not in manifests\n" | |
1647 % (f, i, short(n))) | |
1648 errors += 1 | |
1649 else: | |
1650 del filenodes[f][n] | |
1651 | |
1652 flr = fl.linkrev(n) | |
1653 if flr not in filelinkrevs[f]: | |
1654 self.ui.warn("%s:%s points to unexpected changeset %d\n" | |
1655 % (f, short(n), fl.linkrev(n))) | |
1656 errors += 1 | |
1657 else: | |
1658 filelinkrevs[f].remove(flr) | |
1659 | |
1660 # verify contents | |
1661 try: | |
1662 t = fl.read(n) | |
1663 except Exception, inst: | |
1664 self.ui.warn("unpacking file %s %s: %s\n" | |
1665 % (f, short(n), inst)) | |
1666 errors += 1 | |
1667 | |
1668 # verify parents | |
1669 (p1, p2) = fl.parents(n) | |
1670 if p1 not in nodes: | |
1671 self.ui.warn("file %s:%s unknown parent 1 %s" % | |
1672 (f, short(n), short(p1))) | |
1673 errors += 1 | |
1674 if p2 not in nodes: | |
1675 self.ui.warn("file %s:%s unknown parent 2 %s" % | |
1676 (f, short(n), short(p1))) | |
1677 errors += 1 | |
1678 nodes[n] = 1 | |
1679 | |
1680 # cross-check | |
1681 for node in filenodes[f]: | |
1682 self.ui.warn("node %s in manifests not in %s\n" | |
721 | 1683 % (hex(node), f)) |
247 | 1684 errors += 1 |
1685 | |
1686 self.ui.status("%d files, %d changesets, %d total revisions\n" % | |
1687 (files, changesets, revisions)) | |
1688 | |
1689 if errors: | |
1690 self.ui.warn("%d integrity errors encountered!\n" % errors) | |
1691 return 1 | |
1692 | |
623
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1693 class httprepository: |
60 | 1694 def __init__(self, ui, path): |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1695 self.url = path |
60 | 1696 self.ui = ui |
321 | 1697 no_list = [ "localhost", "127.0.0.1" ] |
1698 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
|
1699 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
|
1700 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
|
1701 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
|
1702 host = host[7:] |
321 | 1703 user = ui.config("http_proxy", "user") |
1704 passwd = ui.config("http_proxy", "passwd") | |
1705 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
|
1706 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
|
1707 no = os.environ.get("no_proxy") |
321 | 1708 if no: |
1709 no_list = no_list + no.split(",") | |
515 | 1710 |
321 | 1711 no_proxy = 0 |
1712 for h in no_list: | |
1713 if (path.startswith("http://" + h + "/") or | |
1714 path.startswith("http://" + h + ":") or | |
1715 path == "http://" + h): | |
1716 no_proxy = 1 | |
1717 | |
1718 # Note: urllib2 takes proxy values from the environment and those will | |
1719 # 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
|
1720 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
|
1721 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
|
1722 del os.environ[env] |
321 | 1723 |
1724 proxy_handler = urllib2.BaseHandler() | |
1725 if host and not no_proxy: | |
1726 proxy_handler = urllib2.ProxyHandler({"http" : "http://" + host}) | |
1727 | |
1728 authinfo = None | |
1729 if user and passwd: | |
1730 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() | |
1731 passmgr.add_password(None, host, user, passwd) | |
1732 authinfo = urllib2.ProxyBasicAuthHandler(passmgr) | |
1733 | |
1734 opener = urllib2.build_opener(proxy_handler, authinfo) | |
1735 urllib2.install_opener(opener) | |
60 | 1736 |
634
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1737 def dev(self): |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1738 return -1 |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1739 |
60 | 1740 def do_cmd(self, cmd, **args): |
83 | 1741 self.ui.debug("sending %s command\n" % cmd) |
60 | 1742 q = {"cmd": cmd} |
1743 q.update(args) | |
1744 qs = urllib.urlencode(q) | |
1745 cu = "%s?%s" % (self.url, qs) | |
752 | 1746 resp = urllib2.urlopen(cu) |
753 | 1747 proto = resp.headers['content-type'] |
752 | 1748 |
753 | 1749 # accept old "text/plain" and "application/hg-changegroup" for now |
1750 if not proto.startswith('application/mercurial') and \ | |
1751 not proto.startswith('text/plain') and \ | |
1752 not proto.startswith('application/hg-changegroup'): | |
752 | 1753 raise RepoError("'%s' does not appear to be an hg repository" |
1754 % self.url) | |
1755 | |
753 | 1756 if proto.startswith('application/mercurial'): |
1757 version = proto[22:] | |
1758 if float(version) > 0.1: | |
1759 raise RepoError("'%s' uses newer protocol %s" % | |
1760 (self.url, version)) | |
1761 | |
752 | 1762 return resp |
60 | 1763 |
222 | 1764 def heads(self): |
1765 d = self.do_cmd("heads").read() | |
1766 try: | |
1767 return map(bin, d[:-1].split(" ")) | |
1768 except: | |
1769 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1770 raise | |
1771 | |
60 | 1772 def branches(self, nodes): |
1773 n = " ".join(map(hex, nodes)) | |
752 | 1774 d = self.do_cmd("branches", nodes=n).read() |
217 | 1775 try: |
1776 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] | |
1777 return br | |
1778 except: | |
1779 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1780 raise | |
60 | 1781 |
1782 def between(self, pairs): | |
1783 n = "\n".join(["-".join(map(hex, p)) for p in pairs]) | |
752 | 1784 d = self.do_cmd("between", pairs=n).read() |
217 | 1785 try: |
1786 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ] | |
1787 return p | |
1788 except: | |
1789 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1790 raise | |
60 | 1791 |
1792 def changegroup(self, nodes): | |
1793 n = " ".join(map(hex, nodes)) | |
752 | 1794 f = self.do_cmd("changegroup", roots=n) |
192 | 1795 bytes = 0 |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1796 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1797 class zread: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1798 def __init__(self, f): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1799 self.zd = zlib.decompressobj() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1800 self.f = f |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1801 self.buf = "" |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1802 def read(self, l): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1803 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
|
1804 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
|
1805 if r: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1806 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
|
1807 else: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1808 self.buf += self.zd.flush() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1809 break |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1810 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
|
1811 return d |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1812 |
752 | 1813 return zread(f) |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
1814 |
638
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1815 class remotelock: |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1816 def __init__(self, repo): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1817 self.repo = repo |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1818 def release(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1819 self.repo.unlock() |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1820 self.repo = None |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1821 def __del__(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1822 if self.repo: |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1823 self.release() |
60 | 1824 |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1825 class sshrepository: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1826 def __init__(self, ui, path): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1827 self.url = path |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1828 self.ui = ui |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1829 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1830 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
|
1831 if not m: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1832 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
|
1833 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1834 self.user = m.group(2) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1835 self.host = m.group(3) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1836 self.port = m.group(5) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1837 self.path = m.group(7) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1838 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1839 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
|
1840 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
|
1841 path = self.path or "" |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1842 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1843 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
|
1844 cmd = cmd % (args, path) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1845 |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1846 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
|
1847 |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1848 def readerr(self): |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1849 while 1: |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1850 r,w,x = select.select([self.pipee], [], [], 0) |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1851 if not r: break |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1852 l = self.pipee.readline() |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1853 if not l: break |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1854 self.ui.status("remote: ", l) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1855 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1856 def __del__(self): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1857 self.pipeo.close() |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1858 self.pipei.close() |
648
8c89408a7154
Attempt to read all remaining remote output at close
Matt Mackall <mpm@selenic.com>
parents:
646
diff
changeset
|
1859 for l in self.pipee: |
8c89408a7154
Attempt to read all remaining remote output at close
Matt Mackall <mpm@selenic.com>
parents:
646
diff
changeset
|
1860 self.ui.status("remote: ", l) |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1861 self.pipee.close() |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1862 |
634
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1863 def dev(self): |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1864 return -1 |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
1865 |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1866 def do_cmd(self, cmd, **args): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1867 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
|
1868 self.pipeo.write("%s\n" % cmd) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1869 for k, v in args.items(): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1870 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
|
1871 self.pipeo.write(v) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1872 self.pipeo.flush() |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1873 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1874 return self.pipei |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1875 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1876 def call(self, cmd, **args): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1877 r = self.do_cmd(cmd, **args) |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1878 l = r.readline() |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1879 self.readerr() |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1880 try: |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1881 l = int(l) |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1882 except: |
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1883 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
|
1884 return r.read(l) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1885 |
638
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1886 def lock(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1887 self.call("lock") |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1888 return remotelock(self) |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1889 |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1890 def unlock(self): |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1891 self.call("unlock") |
35f7adfefa69
Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents:
637
diff
changeset
|
1892 |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1893 def heads(self): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1894 d = self.call("heads") |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1895 try: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1896 return map(bin, d[:-1].split(" ")) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1897 except: |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1898 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
|
1899 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1900 def branches(self, nodes): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1901 n = " ".join(map(hex, nodes)) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1902 d = self.call("branches", nodes=n) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1903 try: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1904 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
|
1905 return br |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1906 except: |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1907 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
|
1908 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1909 def between(self, pairs): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1910 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
|
1911 d = self.call("between", pairs=n) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1912 try: |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1913 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
|
1914 return p |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1915 except: |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1916 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
|
1917 |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1918 def changegroup(self, nodes): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1919 n = " ".join(map(hex, nodes)) |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1920 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
|
1921 return self.pipei |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1922 |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1923 def addchangegroup(self, cg): |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1924 d = self.call("addchangegroup") |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1925 if d: |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1926 raise RepoError("push refused: %s", d) |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1927 |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1928 while 1: |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1929 d = cg.read(4096) |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1930 if not d: break |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1931 self.pipeo.write(d) |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1932 self.readerr() |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1933 |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1934 self.pipeo.flush() |
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1935 |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1936 self.readerr() |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1937 l = int(self.pipei.readline()) |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
1938 return self.pipei.read(l) != "" |
639
31cebba881a0
Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents:
638
diff
changeset
|
1939 |
60 | 1940 def repository(ui, path=None, create=0): |
623
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1941 if path: |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1942 if path.startswith("http://"): |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1943 return httprepository(ui, path) |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1944 if path.startswith("hg://"): |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1945 return httprepository(ui, path.replace("hg://", "http://")) |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1946 if path.startswith("old-http://"): |
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1947 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
|
1948 if path.startswith("ssh://"): |
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
1949 return sshrepository(ui, path) |
60 | 1950 |
623
314867960a4a
Change remote repository to httprepository
Matt Mackall <mpm@selenic.com>
parents:
622
diff
changeset
|
1951 return localrepository(ui, path, create) |