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