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