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