Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/hg.py @ 616:d45d1c90032e
Fix zombie files in merge
# HG changeset patch
# User maf46@burn.cl.cam.ac.uk
# Node ID 57667c9b93a5a743e4629d15a0e6bd76699130c3
# Parent d2994b5298fb20f87dc1d4747635b280db3c0526
Fix zombie files in merge
Keir Fraser observed the following:
> I made a small test case that illustrates the bug in merging changesets
> with 'hg remove's in them:
>
> 1. Create a repository A containing files foo & bar.
> 2. Create clone called B.
> 3. A removes file bar, and commits this removal.
> 4. B edits file foo, and commits this edit.
>
> Now, if B:
> # hg pull ../A; hg update -m; hg commit
> Then bar remains deleted.
>
> If A:
> # hg pull ../B; hg update -m; hg commit
> Then bar is resurrected!
>
> It looks as though, when you merge across a branch, any deletions in
> your own branch are forgotten.
> ...
> Fixing this is a must, as zombie files are a real pain. :-)
Keir later patched our local copy of hg as shown below, which fixes
the problem. I've also enclosed a test which captures the test Keir
outlined...
Files deleted on a branch should not automatically reappear in a merge
Patch notes:
1. The first chunk does not change behaviour, but cleans up the code
to more closely match check of 'force' in the second chunk. I
think it makes the code clearer.
2. The second chunk fixes two bugs --
i. If we choose to keep a remotely-changed locally-deleted file,
then we need to 'get' that file. If we choose to delete it
then no action need be taken (it is already deleted in the
working manifest). Without this fix, choosing to delete would
get a Python traceback.
ii. The test for whether the file was remotely-created is
insufficient. It is only true if f is not in the common
ancestor. Otherwise the file was deleted locally, and should
remain deleted. (this is the most important fix!)
Index: hg/tests/test-merge6
===================================================================
author | maf46@burn.cl.cam.ac.uk |
---|---|
date | Mon, 04 Jul 2005 12:38:34 -0800 |
parents | 48c3eb2bf844 |
children | 004e811f7706 |
rev | line source |
---|---|
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
1 # hg.py - repository classes for mercurial |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
2 # |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
4 # |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
6 # of the GNU General Public License, incorporated herein by reference. |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
7 |
249 | 8 import sys, struct, os |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
418
diff
changeset
|
9 import util |
262 | 10 from revlog import * |
11 from demandload import * | |
12 demandload(globals(), "re lock urllib urllib2 transaction time socket") | |
434 | 13 demandload(globals(), "tempfile httprangereader bdiff") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
14 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
15 class filelog(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
16 def __init__(self, opener, path): |
144
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
17 revlog.__init__(self, opener, |
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
18 os.path.join("data", path + ".i"), |
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
19 os.path.join("data", path + ".d")) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
20 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
21 def read(self, node): |
360 | 22 t = self.revision(node) |
23 if t[:2] != '\1\n': | |
24 return t | |
25 s = t.find('\1\n', 2) | |
26 return t[s+2:] | |
27 | |
28 def readmeta(self, node): | |
29 t = self.revision(node) | |
30 if t[:2] != '\1\n': | |
31 return t | |
32 s = t.find('\1\n', 2) | |
33 mt = t[2:s] | |
34 for l in mt.splitlines(): | |
35 k, v = l.split(": ", 1) | |
36 m[k] = v | |
37 return m | |
38 | |
39 def add(self, text, meta, transaction, link, p1=None, p2=None): | |
40 if meta or text[:2] == '\1\n': | |
41 mt = "" | |
42 if meta: | |
43 mt = [ "%s: %s\n" % (k, v) for k,v in meta.items() ] | |
44 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
|
45 return self.addrevision(text, transaction, link, p1, p2) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
46 |
79 | 47 def annotate(self, node): |
199 | 48 |
49 def decorate(text, rev): | |
436 | 50 return ([rev] * len(text.splitlines()), text) |
199 | 51 |
52 def pair(parent, child): | |
436 | 53 for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]): |
471 | 54 child[0][b1:b2] = parent[0][a1:a2] |
55 return child | |
199 | 56 |
200 | 57 # find all ancestors |
216
201115f2859b
hg annotate: actually annotate the given version
mpm@selenic.com
parents:
210
diff
changeset
|
58 needed = {node:1} |
199 | 59 visit = [node] |
60 while visit: | |
61 n = visit.pop(0) | |
62 for p in self.parents(n): | |
63 if p not in needed: | |
64 needed[p] = 1 | |
65 visit.append(p) | |
200 | 66 else: |
67 # count how many times we'll use this | |
68 needed[p] += 1 | |
199 | 69 |
200 | 70 # sort by revision which is a topological order |
471 | 71 visit = [ (self.rev(n), n) for n in needed.keys() ] |
199 | 72 visit.sort() |
73 hist = {} | |
74 | |
471 | 75 for r,n in visit: |
199 | 76 curr = decorate(self.read(n), self.linkrev(n)) |
77 for p in self.parents(n): | |
78 if p != nullid: | |
79 curr = pair(hist[p], curr) | |
200 | 80 # trim the history of unneeded revs |
81 needed[p] -= 1 | |
82 if not needed[p]: | |
83 del hist[p] | |
199 | 84 hist[n] = curr |
85 | |
436 | 86 return zip(hist[n][0], hist[n][1].splitlines(1)) |
79 | 87 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
88 class manifest(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
89 def __init__(self, opener): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
90 self.mapcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
91 self.listcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
92 self.addlist = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
93 revlog.__init__(self, opener, "00manifest.i", "00manifest.d") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
94 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
95 def read(self, node): |
313 | 96 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
|
97 if self.mapcache and self.mapcache[0] == node: |
561 | 98 return self.mapcache[1] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
99 text = self.revision(node) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
100 map = {} |
276 | 101 flag = {} |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
102 self.listcache = (text, text.splitlines(1)) |
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
103 for l in self.listcache[1]: |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
104 (f, n) = l.split('\0') |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
105 map[f] = bin(n[:40]) |
276 | 106 flag[f] = (n[40:-1] == "x") |
107 self.mapcache = (node, map, flag) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
108 return map |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
109 |
276 | 110 def readflags(self, node): |
313 | 111 if node == nullid: return {} # don't upset local cache |
358
9f4077d7ef6f
[PATCH] manifest.readflags performance buglet
mpm@selenic.com
parents:
350
diff
changeset
|
112 if not self.mapcache or self.mapcache[0] != node: |
276 | 113 self.read(node) |
114 return self.mapcache[2] | |
115 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
116 def diff(self, a, b): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
117 # this is sneaky, as we're not actually using a and b |
140 | 118 if self.listcache and self.addlist and self.listcache[0] == a: |
98 | 119 d = mdiff.diff(self.listcache[1], self.addlist, 1) |
120 if mdiff.patch(a, d) != b: | |
121 sys.stderr.write("*** sortdiff failed, falling back ***\n") | |
122 return mdiff.textdiff(a, b) | |
123 return d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
124 else: |
44 | 125 return mdiff.textdiff(a, b) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
126 |
276 | 127 def add(self, map, flags, transaction, link, p1=None, p2=None): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
128 files = map.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
129 files.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
130 |
276 | 131 self.addlist = ["%s\000%s%s\n" % |
132 (f, hex(map[f]), flags[f] and "x" or '') | |
133 for f in files] | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
134 text = "".join(self.addlist) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
135 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
136 n = self.addrevision(text, transaction, link, p1, p2) |
302 | 137 self.mapcache = (n, map, flags) |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
138 self.listcache = (text, self.addlist) |
140 | 139 self.addlist = None |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
140 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
141 return n |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
142 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
143 class changelog(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
144 def __init__(self, opener): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
145 revlog.__init__(self, opener, "00changelog.i", "00changelog.d") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
146 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
147 def extract(self, text): |
37 | 148 if not text: |
40 | 149 return (nullid, "", "0", [], "") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
150 last = text.index("\n\n") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
151 desc = text[last + 2:] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
152 l = text[:last].splitlines() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
153 manifest = bin(l[0]) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
154 user = l[1] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
155 date = l[2] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
156 files = l[3:] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
157 return (manifest, user, date, files, desc) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
158 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
159 def read(self, node): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
160 return self.extract(self.revision(node)) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
161 |
203 | 162 def add(self, manifest, list, desc, transaction, p1=None, p2=None, |
163 user=None, date=None): | |
164 date = date or "%d %d" % (time.time(), time.timezone) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
165 list.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
166 l = [hex(manifest), user, date] + list + ["", desc] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
167 text = "\n".join(l) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
168 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
|
169 |
220 | 170 class dirstate: |
244 | 171 def __init__(self, opener, ui, root): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
172 self.opener = opener |
244 | 173 self.root = root |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
174 self.dirty = 0 |
20 | 175 self.ui = ui |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
176 self.map = None |
227 | 177 self.pl = None |
363 | 178 self.copies = {} |
220 | 179 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
180 def __del__(self): |
220 | 181 if self.dirty: |
182 self.write() | |
183 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
184 def __getitem__(self, key): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
185 try: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
186 return self.map[key] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
187 except TypeError: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
188 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
189 return self[key] |
220 | 190 |
191 def __contains__(self, key): | |
192 if not self.map: self.read() | |
193 return key in self.map | |
194 | |
227 | 195 def parents(self): |
196 if not self.pl: | |
197 self.read() | |
198 return self.pl | |
199 | |
200 def setparents(self, p1, p2 = nullid): | |
201 self.dirty = 1 | |
202 self.pl = p1, p2 | |
203 | |
220 | 204 def state(self, key): |
205 try: | |
206 return self[key][0] | |
207 except KeyError: | |
208 return "?" | |
209 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
210 def read(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
211 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
|
212 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
213 self.map = {} |
227 | 214 self.pl = [nullid, nullid] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
215 try: |
220 | 216 st = self.opener("dirstate").read() |
311 | 217 if not st: return |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
218 except: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
219 |
227 | 220 self.pl = [st[:20], st[20: 40]] |
221 | |
222 pos = 40 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
223 while pos < len(st): |
220 | 224 e = struct.unpack(">cllll", st[pos:pos+17]) |
225 l = e[4] | |
226 pos += 17 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
227 f = st[pos:pos + l] |
515 | 228 if '\0' in f: |
363 | 229 f, c = f.split('\0') |
230 self.copies[f] = c | |
220 | 231 self.map[f] = e[:4] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
232 pos += l |
363 | 233 |
234 def copy(self, source, dest): | |
235 self.read() | |
236 self.dirty = 1 | |
237 self.copies[dest] = source | |
238 | |
239 def copied(self, file): | |
240 return self.copies.get(file, None) | |
515 | 241 |
220 | 242 def update(self, files, state): |
243 ''' current states: | |
244 n normal | |
231 | 245 m needs merging |
220 | 246 r marked for removal |
247 a marked for addition''' | |
248 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
249 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
250 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
251 self.dirty = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
252 for f in files: |
220 | 253 if state == "r": |
254 self.map[f] = ('r', 0, 0, 0) | |
255 else: | |
253 | 256 s = os.stat(os.path.join(self.root, f)) |
257 self.map[f] = (state, s.st_mode, s.st_size, s.st_mtime) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
258 |
220 | 259 def forget(self, files): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
260 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
261 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
262 self.dirty = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
263 for f in files: |
20 | 264 try: |
265 del self.map[f] | |
266 except KeyError: | |
220 | 267 self.ui.warn("not in dirstate: %s!\n" % f) |
20 | 268 pass |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
269 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
270 def clear(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
271 self.map = {} |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
272 self.dirty = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
273 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
274 def write(self): |
220 | 275 st = self.opener("dirstate", "w") |
227 | 276 st.write("".join(self.pl)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
277 for f, e in self.map.items(): |
363 | 278 c = self.copied(f) |
279 if c: | |
280 f = f + "\0" + c | |
220 | 281 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
|
282 st.write(e + f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
283 self.dirty = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
284 |
536 | 285 def changes(self, files, ignore): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
286 self.read() |
536 | 287 dc = self.map.copy() |
288 lookup, changed, added, unknown = [], [], [], [] | |
289 | |
290 # compare all files by default | |
291 if not files: files = [self.root] | |
292 | |
293 # recursive generator of all files listed | |
294 def walk(files): | |
556 | 295 for f in util.unique(files): |
537 | 296 f = os.path.join(self.root, f) |
536 | 297 if os.path.isdir(f): |
298 for dir, subdirs, fl in os.walk(f): | |
299 d = dir[len(self.root) + 1:] | |
300 if ".hg" in subdirs: subdirs.remove(".hg") | |
301 for fn in fl: | |
302 fn = util.pconvert(os.path.join(d, fn)) | |
303 yield fn | |
304 else: | |
305 yield f[len(self.root) + 1:] | |
306 | |
556 | 307 for fn in util.unique(walk(files)): |
536 | 308 try: s = os.stat(os.path.join(self.root, fn)) |
309 except: continue | |
310 | |
311 if fn in dc: | |
312 c = dc[fn] | |
313 del dc[fn] | |
314 | |
315 if c[0] == 'm': | |
316 changed.append(fn) | |
317 elif c[0] == 'a': | |
318 added.append(fn) | |
319 elif c[0] == 'r': | |
320 unknown.append(fn) | |
321 elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: | |
322 changed.append(fn) | |
323 elif c[1] != s.st_mode or c[3] != s.st_mtime: | |
324 lookup.append(fn) | |
325 else: | |
326 if not ignore(fn): unknown.append(fn) | |
327 | |
328 return (lookup, changed, added, dc.keys(), unknown) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
329 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
330 # used to avoid circular references so destructors work |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
331 def opener(base): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
332 p = base |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
333 def o(path, mode="r"): |
15
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
334 if p[:7] == "http://": |
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
335 f = os.path.join(p, urllib.quote(path)) |
372 | 336 return httprangereader.httprangereader(f) |
15
6daf7757e92b
Fix network pull of repo files with "%" in their base64 encoding.
mpm@selenic.com
parents:
10
diff
changeset
|
337 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
338 f = os.path.join(p, path) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
339 |
292 | 340 mode += "b" # for that other OS |
341 | |
342 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
|
343 try: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
344 s = os.stat(f) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
345 except OSError: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
346 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
|
347 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
|
348 os.makedirs(d) |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
349 else: |
c37c7f784ee3
Move hg from storing files in data with base64 encoding to full
mpm@selenic.com
parents:
109
diff
changeset
|
350 if s.st_nlink > 1: |
417 | 351 file(f + ".tmp", "wb").write(file(f, "rb").read()) |
421 | 352 util.rename(f+".tmp", f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
353 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
354 return file(f, mode) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
355 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
356 return o |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
357 |
499 | 358 class RepoError(Exception): pass |
359 | |
60 | 360 class localrepository: |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
361 def __init__(self, ui, path=None, create=0): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
362 self.remote = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
363 if path and path[:7] == "http://": |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
364 self.remote = 1 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
365 self.path = path |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
366 else: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
367 if not path: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
368 p = os.getcwd() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
369 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
|
370 oldp = p |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
371 p = os.path.dirname(p) |
499 | 372 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
|
373 path = p |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
374 self.path = os.path.join(path, ".hg") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
375 |
405 | 376 if not create and not os.path.isdir(self.path): |
499 | 377 raise RepoError("repository %s not found" % self.path) |
405 | 378 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
379 self.root = path |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
380 self.ui = ui |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
381 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
382 if create: |
515 | 383 os.mkdir(self.path) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
384 os.mkdir(self.join("data")) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
385 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
386 self.opener = opener(self.path) |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
387 self.wopener = opener(self.root) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
388 self.manifest = manifest(self.opener) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
389 self.changelog = changelog(self.opener) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
390 self.ignorelist = None |
343 | 391 self.tagscache = None |
392 self.nodetagscache = None | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
393 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
394 if not self.remote: |
244 | 395 self.dirstate = dirstate(self.opener, ui, self.root) |
337 | 396 try: |
397 self.ui.readconfig(self.opener("hgrc")) | |
398 except IOError: pass | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
399 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
400 def ignore(self, f): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
401 if self.ignorelist is None: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
402 self.ignorelist = [] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
403 try: |
417 | 404 l = file(self.wjoin(".hgignore")) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
405 for pat in l: |
9 | 406 if pat != "\n": |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
418
diff
changeset
|
407 self.ignorelist.append(re.compile(util.pconvert(pat[:-1]))) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
408 except IOError: pass |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
409 for pat in self.ignorelist: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
410 if pat.search(f): return True |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
411 return False |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
412 |
487 | 413 def hook(self, name, **args): |
414 s = self.ui.config("hooks", name) | |
415 if s: | |
416 self.ui.note("running hook %s: %s\n" % (name, s)) | |
417 old = {} | |
418 for k, v in args.items(): | |
419 k = k.upper() | |
420 old[k] = os.environ.get(k, None) | |
421 os.environ[k] = v | |
422 | |
423 r = os.system(s) | |
424 | |
425 for k, v in old.items(): | |
426 if v != None: | |
427 os.environ[k] = v | |
428 else: | |
429 del os.environ[k] | |
430 | |
431 if r: | |
432 self.ui.warn("abort: %s hook failed with status %d!\n" % | |
433 (name, r)) | |
434 return False | |
435 return True | |
436 | |
343 | 437 def tags(self): |
438 '''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
|
439 if not self.tagscache: |
343 | 440 self.tagscache = {} |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
441 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
|
442 try: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
443 bin_n = bin(n) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
444 except TypeError: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
445 bin_n = '' |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
446 self.tagscache[k.strip()] = bin_n |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
447 |
67 | 448 try: |
254 | 449 # read each head of the tags file, ending with the tip |
450 # and add each tag found to the map, with "newer" ones | |
451 # taking precedence | |
67 | 452 fl = self.file(".hgtags") |
254 | 453 h = fl.heads() |
454 h.reverse() | |
455 for r in h: | |
456 for l in fl.revision(r).splitlines(): | |
457 if l: | |
385
e9e1efd5291c
Fixed problems with extra spaces around tags in .hgtags
Thomas Arendsen Hein <thomas@intevation.de>
parents:
383
diff
changeset
|
458 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
|
459 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
|
460 except KeyError: |
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
461 pass |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
462 |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
463 try: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
464 f = self.opener("localtags") |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
465 for l in f: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
466 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
|
467 addtag(self, k, n) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
468 except IOError: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
469 pass |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
470 |
343 | 471 self.tagscache['tip'] = self.changelog.tip() |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
472 |
343 | 473 return self.tagscache |
474 | |
475 def tagslist(self): | |
476 '''return a list of tags ordered by revision''' | |
477 l = [] | |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
478 for t, n in self.tags().items(): |
343 | 479 try: |
480 r = self.changelog.rev(n) | |
481 except: | |
482 r = -2 # sort to the beginning of the list if unknown | |
483 l.append((r,t,n)) | |
484 l.sort() | |
485 return [(t,n) for r,t,n in l] | |
486 | |
487 def nodetags(self, node): | |
488 '''return the tags associated with a node''' | |
489 if not self.nodetagscache: | |
490 self.nodetagscache = {} | |
491 for t,n in self.tags().items(): | |
492 self.nodetagscache.setdefault(n,[]).append(t) | |
493 return self.nodetagscache.get(node, []) | |
494 | |
495 def lookup(self, key): | |
67 | 496 try: |
343 | 497 return self.tags()[key] |
67 | 498 except KeyError: |
499 return self.changelog.lookup(key) | |
500 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
501 def join(self, f): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
502 return os.path.join(self.path, f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
503 |
244 | 504 def wjoin(self, f): |
505 return os.path.join(self.root, f) | |
506 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
507 def file(self, f): |
192 | 508 if f[0] == '/': f = f[1:] |
144
ea9188538222
Fix transaction handling bug by reverting fileopener change
mpm@selenic.com
parents:
140
diff
changeset
|
509 return filelog(self.opener, f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
510 |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
511 def wfile(self, f, mode='r'): |
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
512 return self.wopener(f, mode) |
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
513 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
514 def transaction(self): |
251 | 515 # save dirstate for undo |
263 | 516 try: |
517 ds = self.opener("dirstate").read() | |
518 except IOError: | |
519 ds = "" | |
251 | 520 self.opener("undo.dirstate", "w").write(ds) |
515 | 521 |
582 | 522 return transaction.transaction(self.ui.warn, |
523 self.opener, self.join("journal"), | |
262 | 524 self.join("undo")) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
525 |
210 | 526 def recover(self): |
225 | 527 lock = self.lock() |
557 | 528 if os.path.exists(self.join("journal")): |
501 | 529 self.ui.status("rolling back interrupted transaction\n") |
557 | 530 return transaction.rollback(self.opener, self.join("journal")) |
210 | 531 else: |
532 self.ui.warn("no interrupted transaction available\n") | |
533 | |
534 def undo(self): | |
225 | 535 lock = self.lock() |
210 | 536 if os.path.exists(self.join("undo")): |
501 | 537 self.ui.status("rolling back last transaction\n") |
262 | 538 transaction.rollback(self.opener, self.join("undo")) |
251 | 539 self.dirstate = None |
421 | 540 util.rename(self.join("undo.dirstate"), self.join("dirstate")) |
251 | 541 self.dirstate = dirstate(self.opener, self.ui, self.root) |
163 | 542 else: |
210 | 543 self.ui.warn("no undo information available\n") |
162 | 544 |
161 | 545 def lock(self, wait = 1): |
546 try: | |
547 return lock.lock(self.join("lock"), 0) | |
548 except lock.LockHeld, inst: | |
549 if wait: | |
550 self.ui.warn("waiting for lock held by %s\n" % inst.args[0]) | |
551 return lock.lock(self.join("lock"), wait) | |
552 raise inst | |
553 | |
203 | 554 def rawcommit(self, files, text, user, date, p1=None, p2=None): |
442 | 555 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
|
556 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
|
557 p2 = p2 or self.dirstate.parents()[1] or nullid |
302 | 558 c1 = self.changelog.read(p1) |
559 c2 = self.changelog.read(p2) | |
560 m1 = self.manifest.read(c1[0]) | |
561 mf1 = self.manifest.readflags(c1[0]) | |
562 m2 = self.manifest.read(c2[0]) | |
563 | |
442 | 564 if orig_parent == p1: |
565 update_dirstate = 1 | |
566 else: | |
567 update_dirstate = 0 | |
568 | |
203 | 569 tr = self.transaction() |
302 | 570 mm = m1.copy() |
571 mfm = mf1.copy() | |
203 | 572 linkrev = self.changelog.count() |
573 for f in files: | |
574 try: | |
302 | 575 t = self.wfile(f).read() |
441 | 576 tm = util.is_exec(self.wjoin(f), mfm.get(f, False)) |
302 | 577 r = self.file(f) |
578 mfm[f] = tm | |
360 | 579 mm[f] = r.add(t, {}, tr, linkrev, |
302 | 580 m1.get(f, nullid), m2.get(f, nullid)) |
442 | 581 if update_dirstate: |
582 self.dirstate.update([f], "n") | |
203 | 583 except IOError: |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
584 try: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
585 del mm[f] |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
586 del mfm[f] |
442 | 587 if update_dirstate: |
588 self.dirstate.forget([f]) | |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
589 except: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
590 # deleted from p2? |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
591 pass |
203 | 592 |
302 | 593 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
|
594 user = user or self.ui.username() |
302 | 595 n = self.changelog.add(mnode, files, text, tr, p1, p2, user, date) |
203 | 596 tr.close() |
442 | 597 if update_dirstate: |
598 self.dirstate.setparents(n, nullid) | |
203 | 599 |
317 | 600 def commit(self, files = None, text = "", user = None, date = None): |
220 | 601 commit = [] |
602 remove = [] | |
603 if files: | |
604 for f in files: | |
605 s = self.dirstate.state(f) | |
244 | 606 if s in 'nmai': |
220 | 607 commit.append(f) |
608 elif s == 'r': | |
609 remove.append(f) | |
610 else: | |
244 | 611 self.ui.warn("%s not tracked!\n" % f) |
220 | 612 else: |
536 | 613 (c, a, d, u) = self.changes(None, None) |
220 | 614 commit = c + a |
615 remove = d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
616 |
220 | 617 if not commit and not remove: |
151 | 618 self.ui.status("nothing changed\n") |
619 return | |
620 | |
487 | 621 if not self.hook("precommit"): |
622 return 1 | |
623 | |
229 | 624 p1, p2 = self.dirstate.parents() |
625 c1 = self.changelog.read(p1) | |
626 c2 = self.changelog.read(p2) | |
627 m1 = self.manifest.read(c1[0]) | |
276 | 628 mf1 = self.manifest.readflags(c1[0]) |
229 | 629 m2 = self.manifest.read(c2[0]) |
225 | 630 lock = self.lock() |
151 | 631 tr = self.transaction() |
632 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
633 # check in files |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
634 new = {} |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
635 linkrev = self.changelog.count() |
220 | 636 commit.sort() |
637 for f in commit: | |
83 | 638 self.ui.note(f + "\n") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
639 try: |
441 | 640 mf1[f] = util.is_exec(self.wjoin(f), mf1.get(f, False)) |
418 | 641 t = self.wfile(f).read() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
642 except IOError: |
220 | 643 self.warn("trouble committing %s!\n" % f) |
644 raise | |
645 | |
363 | 646 meta = {} |
647 cp = self.dirstate.copied(f) | |
648 if cp: | |
649 meta["copy"] = cp | |
650 meta["copyrev"] = hex(m1.get(cp, m2.get(cp, nullid))) | |
575 | 651 self.ui.debug(" %s: copy %s:%s\n" % (f, cp, meta["copyrev"])) |
363 | 652 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
653 r = self.file(f) |
229 | 654 fp1 = m1.get(f, nullid) |
655 fp2 = m2.get(f, nullid) | |
363 | 656 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
|
657 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
658 # update manifest |
229 | 659 m1.update(new) |
416
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
660 for f in remove: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
661 if f in m1: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
662 del m1[f] |
276 | 663 mn = self.manifest.add(m1, mf1, tr, linkrev, c1[0], c2[0]) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
664 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
665 # add changeset |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
666 new = new.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
667 new.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
668 |
288 | 669 if not text: |
670 edittext = "\n" + "HG: manifest hash %s\n" % hex(mn) | |
671 edittext += "".join(["HG: changed %s\n" % f for f in new]) | |
672 edittext += "".join(["HG: removed %s\n" % f for f in remove]) | |
673 edittext = self.ui.edit(edittext) | |
674 if not edittext.rstrip(): | |
675 return 1 | |
676 text = edittext | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
677 |
608
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
678 user = user or self.ui.username() |
317 | 679 n = self.changelog.add(mn, new, text, tr, p1, p2, user, date) |
487 | 680 |
681 if not self.hook("commit", node=hex(n)): | |
682 return 1 | |
683 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
684 tr.close() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
685 |
229 | 686 self.dirstate.setparents(n) |
220 | 687 self.dirstate.update(new, "n") |
688 self.dirstate.forget(remove) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
689 |
537 | 690 def changes(self, node1, node2, files=None): |
566 | 691 mf2, u = None, [] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
692 |
536 | 693 def fcmp(fn, mf): |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
694 t1 = self.wfile(fn).read() |
29 | 695 t2 = self.file(fn).revision(mf[fn]) |
696 return cmp(t1, t2) | |
697 | |
536 | 698 # are we comparing the working directory? |
561 | 699 if not node2: |
536 | 700 l, c, a, d, u = self.dirstate.changes(files, self.ignore) |
701 | |
702 # are we comparing working dir against its parent? | |
561 | 703 if not node1: |
536 | 704 if l: |
705 # do a full compare of any files that might have changed | |
706 change = self.changelog.read(self.dirstate.parents()[0]) | |
561 | 707 mf2 = self.manifest.read(change[0]) |
548 | 708 for f in l: |
561 | 709 if fcmp(f, mf2): |
536 | 710 c.append(f) |
561 | 711 |
712 for l in c, a, d, u: | |
713 l.sort() | |
714 | |
536 | 715 return (c, a, d, u) |
515 | 716 |
536 | 717 # are we comparing working dir against non-tip? |
718 # generate a pseudo-manifest for the working dir | |
561 | 719 if not node2: |
720 if not mf2: | |
536 | 721 change = self.changelog.read(self.dirstate.parents()[0]) |
561 | 722 mf2 = self.manifest.read(change[0]).copy() |
536 | 723 for f in a + c + l: |
561 | 724 mf2[f] = "" |
536 | 725 for f in d: |
561 | 726 if f in mf2: del mf2[f] |
536 | 727 else: |
561 | 728 change = self.changelog.read(node2) |
729 mf2 = self.manifest.read(change[0]) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
730 |
566 | 731 # flush lists from dirstate before comparing manifests |
732 c, a = [], [] | |
733 | |
561 | 734 change = self.changelog.read(node1) |
735 mf1 = self.manifest.read(change[0]).copy() | |
32 | 736 |
737 for fn in mf2: | |
738 if mf1.has_key(fn): | |
739 if mf1[fn] != mf2[fn]: | |
561 | 740 if mf2[fn] != "" or fcmp(fn, mf1): |
536 | 741 c.append(fn) |
32 | 742 del mf1[fn] |
743 else: | |
536 | 744 a.append(fn) |
515 | 745 |
536 | 746 d = mf1.keys() |
561 | 747 |
748 for l in c, a, d, u: | |
749 l.sort() | |
515 | 750 |
536 | 751 return (c, a, d, u) |
32 | 752 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
753 def add(self, list): |
220 | 754 for f in list: |
244 | 755 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
|
756 if not os.path.exists(p): |
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
757 self.ui.warn("%s does not exist!\n" % f) |
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
758 elif not os.path.isfile(p): |
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
759 self.ui.warn("%s not added: mercurial only supports files currently\n" % f) |
220 | 760 elif self.dirstate.state(f) == 'n': |
761 self.ui.warn("%s already tracked!\n" % f) | |
762 else: | |
763 self.dirstate.update([f], "a") | |
764 | |
765 def forget(self, list): | |
766 for f in list: | |
767 if self.dirstate.state(f) not in 'ai': | |
768 self.ui.warn("%s not added!\n" % f) | |
769 else: | |
770 self.dirstate.forget([f]) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
771 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
772 def remove(self, list): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
773 for f in list: |
244 | 774 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
|
775 if os.path.exists(p): |
220 | 776 self.ui.warn("%s still exists!\n" % f) |
402 | 777 elif self.dirstate.state(f) == 'a': |
778 self.ui.warn("%s never committed!\n" % f) | |
779 self.dirstate.forget(f) | |
220 | 780 elif f not in self.dirstate: |
781 self.ui.warn("%s not tracked!\n" % f) | |
782 else: | |
783 self.dirstate.update([f], "r") | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
784 |
363 | 785 def copy(self, source, dest): |
786 p = self.wjoin(dest) | |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
787 if not os.path.exists(dest): |
363 | 788 self.ui.warn("%s does not exist!\n" % dest) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
789 elif not os.path.isfile(dest): |
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
790 self.ui.warn("copy failed: %s is not a file\n" % dest) |
363 | 791 else: |
792 if self.dirstate.state(dest) == '?': | |
793 self.dirstate.update([dest], "a") | |
794 self.dirstate.copy(source, dest) | |
795 | |
222 | 796 def heads(self): |
797 return self.changelog.heads() | |
798 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
799 def branches(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
800 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
|
801 b = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
802 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
803 t = n |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
804 while n: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
805 p = self.changelog.parents(n) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
806 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
|
807 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
|
808 break |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
809 n = p[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
810 return b |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
811 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
812 def between(self, pairs): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
813 r = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
814 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
815 for top, bottom in pairs: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
816 n, l, i = top, [], 0 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
817 f = 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
818 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
819 while n != bottom: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
820 p = self.changelog.parents(n)[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
821 if i == f: |
575 | 822 l.append(n) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
823 f = f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
824 n = p |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
825 i += 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
826 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
827 r.append(l) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
828 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
829 return r |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
830 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
831 def newer(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
832 m = {} |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
833 nl = [] |
94 | 834 pm = {} |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
835 cl = self.changelog |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
836 t = l = cl.count() |
94 | 837 |
838 # find the lowest numbered node | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
839 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
840 l = min(l, cl.rev(n)) |
94 | 841 m[n] = 1 |
46 | 842 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
843 for i in xrange(l, t): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
844 n = cl.node(i) |
94 | 845 if n in m: # explicitly listed |
846 pm[n] = 1 | |
847 nl.append(n) | |
848 continue | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
849 for p in cl.parents(n): |
94 | 850 if p in pm: # parent listed |
851 pm[n] = 1 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
852 nl.append(n) |
94 | 853 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
854 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
855 return nl |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
856 |
516 | 857 def findincoming(self, remote): |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
858 m = self.changelog.nodemap |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
859 search = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
860 fetch = [] |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
861 base = {} |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
862 seen = {} |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
863 seenbranch = {} |
192 | 864 |
190
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
865 # if we have an empty repo, fetch everything |
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
866 if self.changelog.tip() == nullid: |
222 | 867 self.ui.status("requesting all changes\n") |
516 | 868 return [nullid] |
190
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
869 |
3dd5ce2fddb6
merge: short-circuit search for merge into empty repo
mpm@selenic.com
parents:
187
diff
changeset
|
870 # otherwise, 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
|
871 # and start by examining the heads |
222 | 872 self.ui.status("searching for changes\n") |
873 heads = remote.heads() | |
874 unknown = [] | |
875 for h in heads: | |
876 if h not in m: | |
877 unknown.append(h) | |
46 | 878 |
222 | 879 if not unknown: |
60 | 880 return None |
324 | 881 |
882 rep = {} | |
883 reqcnt = 0 | |
515 | 884 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
885 # search through remote branches |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
886 # 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
|
887 # head, root, first parent, second parent |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
888 # (a branch always has two parents (or none) by definition) |
222 | 889 unknown = remote.branches(unknown) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
890 while unknown: |
324 | 891 r = [] |
892 while unknown: | |
893 n = unknown.pop(0) | |
894 if n[0] in seen: | |
895 continue | |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
896 |
324 | 897 self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) |
898 if n[0] == nullid: | |
899 break | |
328 | 900 if n in seenbranch: |
324 | 901 self.ui.debug("branch already found\n") |
902 continue | |
903 if n[1] and n[1] in m: # do we know the base? | |
904 self.ui.debug("found incomplete branch %s:%s\n" | |
905 % (short(n[0]), short(n[1]))) | |
906 search.append(n) # schedule branch range for scanning | |
328 | 907 seenbranch[n] = 1 |
324 | 908 else: |
909 if n[1] not in seen and n[1] not in fetch: | |
910 if n[2] in m and n[3] in m: | |
911 self.ui.debug("found new changeset %s\n" % | |
912 short(n[1])) | |
913 fetch.append(n[1]) # earliest unknown | |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
914 base[n[2]] = 1 # latest known |
324 | 915 continue |
916 | |
917 for a in n[2:4]: | |
918 if a not in rep: | |
919 r.append(a) | |
920 rep[a] = 1 | |
921 | |
328 | 922 seen[n[0]] = 1 |
923 | |
324 | 924 if r: |
925 reqcnt += 1 | |
926 self.ui.debug("request %d: %s\n" % | |
927 (reqcnt, " ".join(map(short, r)))) | |
928 for p in range(0, len(r), 10): | |
929 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
|
930 self.ui.debug("received %s:%s\n" % |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
931 (short(b[0]), short(b[1]))) |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
932 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
|
933 unknown.append(b) |
515 | 934 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
935 # 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
|
936 while search: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
937 n = search.pop(0) |
324 | 938 reqcnt += 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
939 l = remote.between([(n[0], n[1])])[0] |
328 | 940 l.append(n[1]) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
941 p = n[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
942 f = 1 |
328 | 943 for i in l: |
944 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
|
945 if i in m: |
85 | 946 if f <= 2: |
83 | 947 self.ui.debug("found new branch changeset %s\n" % |
948 short(p)) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
949 fetch.append(p) |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
950 base[i] = 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
951 else: |
83 | 952 self.ui.debug("narrowed branch search to %s:%s\n" |
953 % (short(p), short(i))) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
954 search.append((p, i)) |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
955 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
956 p, f = i, f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
957 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
958 # 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
|
959 for f in fetch: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
960 if f in m: |
499 | 961 raise RepoError("already have changeset " + short(f[:4])) |
83 | 962 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
963 if base.keys() == [nullid]: |
514
874e577e332e
change unrelated repository error to a warning
mpm@selenic.com
parents:
511
diff
changeset
|
964 self.ui.warn("warning: pulling from an unrelated repository!\n") |
511 | 965 |
94 | 966 self.ui.note("adding new changesets starting at " + |
83 | 967 " ".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
|
968 |
324 | 969 self.ui.debug("%d total queries\n" % reqcnt) |
970 | |
516 | 971 return fetch |
972 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
973 def changegroup(self, basenodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
974 nodes = self.newer(basenodes) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
975 |
46 | 976 # construct the link map |
977 linkmap = {} | |
978 for n in nodes: | |
979 linkmap[self.changelog.rev(n)] = n | |
980 | |
981 # construct a list of all changed files | |
982 changed = {} | |
983 for n in nodes: | |
984 c = self.changelog.read(n) | |
985 for f in c[3]: | |
986 changed[f] = 1 | |
987 changed = changed.keys() | |
988 changed.sort() | |
989 | |
990 # the changegroup is changesets + manifests + all file revs | |
991 revs = [ self.changelog.rev(n) for n in nodes ] | |
992 | |
192 | 993 for y in self.changelog.group(linkmap): yield y |
994 for y in self.manifest.group(linkmap): yield y | |
46 | 995 for f in changed: |
192 | 996 yield struct.pack(">l", len(f) + 4) + f |
46 | 997 g = self.file(f).group(linkmap) |
192 | 998 for y in g: |
999 yield y | |
46 | 1000 |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1001 def addchangegroup(self, generator): |
222 | 1002 |
1003 class genread: | |
1004 def __init__(self, generator): | |
1005 self.g = generator | |
1006 self.buf = "" | |
1007 def read(self, l): | |
1008 while l > len(self.buf): | |
1009 try: | |
1010 self.buf += self.g.next() | |
1011 except StopIteration: | |
1012 break | |
1013 d, self.buf = self.buf[:l], self.buf[l:] | |
1014 return d | |
515 | 1015 |
222 | 1016 def getchunk(): |
1017 d = source.read(4) | |
1018 if not d: return "" | |
1019 l = struct.unpack(">l", d)[0] | |
1020 if l <= 4: return "" | |
1021 return source.read(l - 4) | |
1022 | |
1023 def getgroup(): | |
1024 while 1: | |
1025 c = getchunk() | |
1026 if not c: break | |
1027 yield c | |
1028 | |
1029 def csmap(x): | |
1030 self.ui.debug("add changeset %s\n" % short(x)) | |
1031 return self.changelog.count() | |
1032 | |
1033 def revmap(x): | |
1034 return self.changelog.rev(x) | |
1035 | |
1036 if not generator: return | |
1037 changesets = files = revisions = 0 | |
225 | 1038 |
222 | 1039 source = genread(generator) |
225 | 1040 lock = self.lock() |
222 | 1041 tr = self.transaction() |
1042 | |
1043 # pull off the changeset group | |
1044 self.ui.status("adding changesets\n") | |
1045 co = self.changelog.tip() | |
224
ccbcc4d76f81
fix bad assumption about uniqueness of file versions
mpm@selenic.com
parents:
223
diff
changeset
|
1046 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique |
222 | 1047 changesets = self.changelog.rev(cn) - self.changelog.rev(co) |
1048 | |
1049 # pull off the manifest group | |
1050 self.ui.status("adding manifests\n") | |
1051 mm = self.manifest.tip() | |
1052 mo = self.manifest.addgroup(getgroup(), revmap, tr) | |
1053 | |
1054 # process the files | |
1055 self.ui.status("adding file revisions\n") | |
1056 while 1: | |
1057 f = getchunk() | |
1058 if not f: break | |
1059 self.ui.debug("adding %s revisions\n" % f) | |
1060 fl = self.file(f) | |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1061 o = fl.count() |
222 | 1062 n = fl.addgroup(getgroup(), revmap, tr) |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1063 revisions += fl.count() - o |
222 | 1064 files += 1 |
1065 | |
1066 self.ui.status(("modified %d files, added %d changesets" + | |
1067 " and %d new revisions\n") | |
1068 % (files, changesets, revisions)) | |
1069 | |
1070 tr.close() | |
1071 return | |
1072 | |
588 | 1073 def update(self, node, allow=False, force=False, choose=None, |
1074 moddirstate=True): | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1075 pl = self.dirstate.parents() |
275 | 1076 if not force and pl[1] != nullid: |
254 | 1077 self.ui.warn("aborting: outstanding uncommitted merges\n") |
46 | 1078 return |
1079 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1080 p1, p2 = pl[0], node |
305 | 1081 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
|
1082 m1n = self.changelog.read(p1)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1083 m2n = self.changelog.read(p2)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1084 man = self.manifest.ancestor(m1n, m2n) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1085 m1 = self.manifest.read(m1n) |
276 | 1086 mf1 = self.manifest.readflags(m1n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1087 m2 = self.manifest.read(m2n) |
276 | 1088 mf2 = self.manifest.readflags(m2n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1089 ma = self.manifest.read(man) |
412 | 1090 mfa = self.manifest.readflags(man) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1091 |
536 | 1092 (c, a, d, u) = self.changes(None, None) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1093 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1094 # 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
|
1095 # from p1 to p2? |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1096 linear_path = (pa == p1 or pa == p2) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1097 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1098 # 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
|
1099 # we care about merging |
254 | 1100 self.ui.note("resolving manifests\n") |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1101 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
|
1102 (short(man), short(m1n), short(m2n))) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1103 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1104 merge = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1105 get = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1106 remove = [] |
305 | 1107 mark = {} |
46 | 1108 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1109 # construct a working dir manifest |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1110 mw = m1.copy() |
276 | 1111 mfw = mf1.copy() |
576 | 1112 umap = dict.fromkeys(u) |
1113 | |
254 | 1114 for f in a + c + u: |
1115 mw[f] = "" | |
441 | 1116 mfw[f] = util.is_exec(self.wjoin(f), mfw.get(f, False)) |
576 | 1117 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1118 for f in d: |
254 | 1119 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
|
1120 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1121 # 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
|
1122 # 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
|
1123 # 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
|
1124 # 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
|
1125 # longer in the manifest. |
588 | 1126 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
|
1127 self.dirstate.forget((f,)) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1128 |
576 | 1129 # Compare manifests |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1130 for f, n in mw.iteritems(): |
588 | 1131 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
|
1132 if f in m2: |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1133 s = 0 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1134 |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1135 # is the wfile new since m1, and match m2? |
428 | 1136 if f not in m1: |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1137 t1 = self.wfile(f).read() |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1138 t2 = self.file(f).revision(m2[f]) |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1139 if cmp(t1, t2) == 0: |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1140 mark[f] = 1 |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1141 n = m2[f] |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1142 del t1, t2 |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1143 |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1144 # are files different? |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1145 if n != m2[f]: |
254 | 1146 a = ma.get(f, nullid) |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1147 # are both different from the ancestor? |
254 | 1148 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
|
1149 self.ui.debug(" %s versions differ, resolve\n" % f) |
276 | 1150 # merge executable bits |
1151 # "if we changed or they changed, change in merge" | |
1152 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] | |
1153 mode = ((a^b) | (a^c)) ^ a | |
1154 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
|
1155 s = 1 |
305 | 1156 # are we clobbering? |
1157 # is remote's version newer? | |
1158 # or are we going back in time? | |
1159 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
|
1160 self.ui.debug(" remote %s is newer, get\n" % f) |
254 | 1161 get[f] = m2[f] |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1162 s = 1 |
305 | 1163 else: |
1164 mark[f] = 1 | |
576 | 1165 elif f in umap: |
1166 # this unknown file is the same as the checkout | |
1167 get[f] = m2[f] | |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1168 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1169 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
|
1170 if force: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1171 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1172 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
|
1173 else: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1174 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
|
1175 mode = ((a^b) | (a^c)) ^ a |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1176 if mode != b: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1177 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1178 util.set_exec(self.wjoin(f), mode) |
305 | 1179 mark[f] = 1 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1180 del m2[f] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1181 elif f in ma: |
616 | 1182 if n != ma[f]: |
1183 r = "d" | |
1184 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
|
1185 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
|
1186 (" 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
|
1187 "(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
|
1188 if r == "d": |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1189 remove.append(f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1190 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1191 self.ui.debug("other deleted %s\n" % f) |
254 | 1192 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
|
1193 else: |
254 | 1194 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
|
1195 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
|
1196 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
|
1197 remove.append(f) |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1198 else: |
4862a134e2c2
hg merge: fix time asymmetry bug with deleting files on update to past
mpm@selenic.com
parents:
377
diff
changeset
|
1199 self.ui.debug("local created %s, keeping\n" % f) |
254 | 1200 else: |
1201 self.ui.debug("working dir created %s, keeping\n" % f) | |
46 | 1202 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1203 for f, n in m2.iteritems(): |
588 | 1204 if choose and not choose(f): continue |
256 | 1205 if f[0] == "/": continue |
616 | 1206 if f in ma and n != ma[f]: |
1207 r = "k" | |
1208 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
|
1209 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
|
1210 ("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
|
1211 "(k)eep or (d)elete?", "[kd]", "k") |
616 | 1212 if r == "k": get[f] = n |
1213 elif f not in ma: | |
254 | 1214 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
|
1215 get[f] = n |
616 | 1216 else: |
1217 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
|
1218 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1219 del mw, m1, m2, ma |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1220 |
275 | 1221 if force: |
1222 for f in merge: | |
1223 get[f] = merge[f][1] | |
1224 merge = {} | |
1225 | |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1226 if linear_path: |
254 | 1227 # we don't need to do any magic, just jump to the new rev |
1228 mode = 'n' | |
1229 p1, p2 = p2, nullid | |
1230 else: | |
275 | 1231 if not allow: |
305 | 1232 self.ui.status("this update spans a branch" + |
1233 " affecting the following files:\n") | |
1234 fl = merge.keys() + get.keys() | |
1235 fl.sort() | |
1236 for f in fl: | |
1237 cf = "" | |
1238 if f in merge: cf = " (resolve)" | |
1239 self.ui.status(" %s%s\n" % (f, cf)) | |
1240 self.ui.warn("aborting update spanning branches!\n") | |
1241 self.ui.status("(use update -m to perform a branch merge)\n") | |
275 | 1242 return 1 |
254 | 1243 # we have to remember what files we needed to get/change |
1244 # because any file that's different from either one of its | |
1245 # parents must be in the changeset | |
1246 mode = 'm' | |
588 | 1247 if moddirstate: |
1248 self.dirstate.update(mark.keys(), "m") | |
254 | 1249 |
588 | 1250 if moddirstate: |
1251 self.dirstate.setparents(p1, p2) | |
191
d7e859cf2f1b
merge: add count of new manifests, files, and revisions
mpm@selenic.com
parents:
190
diff
changeset
|
1252 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1253 # 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
|
1254 files = get.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1255 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1256 for f in files: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1257 if f[0] == "/": continue |
273
4f8174389001
merge: Fix bug where we overwrote local when local was newer
mpm@selenic.com
parents:
263
diff
changeset
|
1258 self.ui.note("getting %s\n" % f) |
276 | 1259 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
|
1260 try: |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
1261 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
|
1262 except IOError: |
297
0dbcf3c9ff20
Fixed usage of removed variable 'wp'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
292
diff
changeset
|
1263 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
|
1264 self.wfile(f, "w").write(t) |
441 | 1265 util.set_exec(self.wjoin(f), mf2[f]) |
588 | 1266 if moddirstate: |
1267 self.dirstate.update([f], mode) | |
46 | 1268 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1269 # merge the tricky bits |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1270 files = merge.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1271 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1272 for f in files: |
256 | 1273 self.ui.status("merging %s\n" % f) |
276 | 1274 m, o, flag = merge[f] |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1275 self.merge3(f, m, o) |
441 | 1276 util.set_exec(self.wjoin(f), flag) |
588 | 1277 if moddirstate: |
1278 self.dirstate.update([f], 'm') | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1279 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1280 for f in remove: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1281 self.ui.note("removing %s\n" % f) |
254 | 1282 os.unlink(f) |
578 | 1283 # try removing directories that might now be empty |
1284 try: os.removedirs(os.path.dirname(f)) | |
1285 except: pass | |
588 | 1286 if moddirstate: |
1287 if mode == 'n': | |
1288 self.dirstate.forget(remove) | |
1289 else: | |
1290 self.dirstate.update(remove, 'r') | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1291 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1292 def merge3(self, fn, my, other): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1293 """perform a 3-way merge in the working directory""" |
249 | 1294 |
96 | 1295 def temp(prefix, node): |
1296 pre = "%s~%s." % (os.path.basename(fn), prefix) | |
1297 (fd, name) = tempfile.mkstemp("", pre) | |
417 | 1298 f = os.fdopen(fd, "wb") |
96 | 1299 f.write(fl.revision(node)) |
1300 f.close() | |
1301 return name | |
1302 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1303 fl = self.file(fn) |
96 | 1304 base = fl.ancestor(my, other) |
244 | 1305 a = self.wjoin(fn) |
346 | 1306 b = temp("base", base) |
1307 c = temp("other", other) | |
96 | 1308 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1309 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
|
1310 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
|
1311 (fn, short(other), short(base))) |
96 | 1312 |
608
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
1313 cmd = self.ui.config("ui", "merge") or \ |
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
1314 os.environ.get("HGMERGE", "hgmerge") |
240 | 1315 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
|
1316 if r: |
275 | 1317 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
|
1318 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1319 os.unlink(b) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1320 os.unlink(c) |
96 | 1321 |
247 | 1322 def verify(self): |
1323 filelinkrevs = {} | |
1324 filenodes = {} | |
1325 changesets = revisions = files = 0 | |
1326 errors = 0 | |
1327 | |
302 | 1328 seen = {} |
247 | 1329 self.ui.status("checking changesets\n") |
1330 for i in range(self.changelog.count()): | |
1331 changesets += 1 | |
1332 n = self.changelog.node(i) | |
302 | 1333 if n in seen: |
1334 self.ui.warn("duplicate changeset at revision %d\n" % i) | |
1335 errors += 1 | |
1336 seen[n] = 1 | |
515 | 1337 |
247 | 1338 for p in self.changelog.parents(n): |
1339 if p not in self.changelog.nodemap: | |
1340 self.ui.warn("changeset %s has unknown parent %s\n" % | |
1341 (short(n), short(p))) | |
1342 errors += 1 | |
1343 try: | |
1344 changes = self.changelog.read(n) | |
1345 except Exception, inst: | |
1346 self.ui.warn("unpacking changeset %s: %s\n" % (short(n), inst)) | |
1347 errors += 1 | |
1348 | |
1349 for f in changes[3]: | |
1350 filelinkrevs.setdefault(f, []).append(i) | |
1351 | |
302 | 1352 seen = {} |
247 | 1353 self.ui.status("checking manifests\n") |
1354 for i in range(self.manifest.count()): | |
1355 n = self.manifest.node(i) | |
302 | 1356 if n in seen: |
1357 self.ui.warn("duplicate manifest at revision %d\n" % i) | |
1358 errors += 1 | |
1359 seen[n] = 1 | |
515 | 1360 |
247 | 1361 for p in self.manifest.parents(n): |
1362 if p not in self.manifest.nodemap: | |
1363 self.ui.warn("manifest %s has unknown parent %s\n" % | |
1364 (short(n), short(p))) | |
1365 errors += 1 | |
1366 | |
1367 try: | |
1368 delta = mdiff.patchtext(self.manifest.delta(n)) | |
1369 except KeyboardInterrupt: | |
582 | 1370 self.ui.warn("aborted") |
247 | 1371 sys.exit(0) |
1372 except Exception, inst: | |
1373 self.ui.warn("unpacking manifest %s: %s\n" | |
1374 % (short(n), inst)) | |
1375 errors += 1 | |
1376 | |
1377 ff = [ l.split('\0') for l in delta.splitlines() ] | |
1378 for f, fn in ff: | |
284 | 1379 filenodes.setdefault(f, {})[bin(fn[:40])] = 1 |
247 | 1380 |
1381 self.ui.status("crosschecking files in changesets and manifests\n") | |
1382 for f in filenodes: | |
1383 if f not in filelinkrevs: | |
1384 self.ui.warn("file %s in manifest but not in changesets\n" % f) | |
1385 errors += 1 | |
1386 | |
1387 for f in filelinkrevs: | |
1388 if f not in filenodes: | |
1389 self.ui.warn("file %s in changeset but not in manifest\n" % f) | |
1390 errors += 1 | |
1391 | |
1392 self.ui.status("checking files\n") | |
1393 ff = filenodes.keys() | |
1394 ff.sort() | |
1395 for f in ff: | |
1396 if f == "/dev/null": continue | |
1397 files += 1 | |
1398 fl = self.file(f) | |
1399 nodes = { nullid: 1 } | |
302 | 1400 seen = {} |
247 | 1401 for i in range(fl.count()): |
1402 revisions += 1 | |
1403 n = fl.node(i) | |
1404 | |
302 | 1405 if n in seen: |
1406 self.ui.warn("%s: duplicate revision %d\n" % (f, i)) | |
1407 errors += 1 | |
1408 | |
247 | 1409 if n not in filenodes[f]: |
1410 self.ui.warn("%s: %d:%s not in manifests\n" | |
1411 % (f, i, short(n))) | |
1412 errors += 1 | |
1413 else: | |
1414 del filenodes[f][n] | |
1415 | |
1416 flr = fl.linkrev(n) | |
1417 if flr not in filelinkrevs[f]: | |
1418 self.ui.warn("%s:%s points to unexpected changeset %d\n" | |
1419 % (f, short(n), fl.linkrev(n))) | |
1420 errors += 1 | |
1421 else: | |
1422 filelinkrevs[f].remove(flr) | |
1423 | |
1424 # verify contents | |
1425 try: | |
1426 t = fl.read(n) | |
1427 except Exception, inst: | |
1428 self.ui.warn("unpacking file %s %s: %s\n" | |
1429 % (f, short(n), inst)) | |
1430 errors += 1 | |
1431 | |
1432 # verify parents | |
1433 (p1, p2) = fl.parents(n) | |
1434 if p1 not in nodes: | |
1435 self.ui.warn("file %s:%s unknown parent 1 %s" % | |
1436 (f, short(n), short(p1))) | |
1437 errors += 1 | |
1438 if p2 not in nodes: | |
1439 self.ui.warn("file %s:%s unknown parent 2 %s" % | |
1440 (f, short(n), short(p1))) | |
1441 errors += 1 | |
1442 nodes[n] = 1 | |
1443 | |
1444 # cross-check | |
1445 for node in filenodes[f]: | |
1446 self.ui.warn("node %s in manifests not in %s\n" | |
1447 % (hex(n), f)) | |
1448 errors += 1 | |
1449 | |
1450 self.ui.status("%d files, %d changesets, %d total revisions\n" % | |
1451 (files, changesets, revisions)) | |
1452 | |
1453 if errors: | |
1454 self.ui.warn("%d integrity errors encountered!\n" % errors) | |
1455 return 1 | |
1456 | |
60 | 1457 class remoterepository: |
1458 def __init__(self, ui, path): | |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1459 self.url = path |
60 | 1460 self.ui = ui |
321 | 1461 no_list = [ "localhost", "127.0.0.1" ] |
1462 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
|
1463 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
|
1464 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
|
1465 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
|
1466 host = host[7:] |
321 | 1467 user = ui.config("http_proxy", "user") |
1468 passwd = ui.config("http_proxy", "passwd") | |
1469 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
|
1470 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
|
1471 no = os.environ.get("no_proxy") |
321 | 1472 if no: |
1473 no_list = no_list + no.split(",") | |
515 | 1474 |
321 | 1475 no_proxy = 0 |
1476 for h in no_list: | |
1477 if (path.startswith("http://" + h + "/") or | |
1478 path.startswith("http://" + h + ":") or | |
1479 path == "http://" + h): | |
1480 no_proxy = 1 | |
1481 | |
1482 # Note: urllib2 takes proxy values from the environment and those will | |
1483 # 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
|
1484 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]: |
9294dce4b633
Allow override of HTTP_PROXY, http_proxy and no_proxy; make no_proxy work.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
385
diff
changeset
|
1485 if os.environ.has_key(env): |
9294dce4b633
Allow override of HTTP_PROXY, http_proxy and no_proxy; make no_proxy work.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
385
diff
changeset
|
1486 del os.environ[env] |
321 | 1487 |
1488 proxy_handler = urllib2.BaseHandler() | |
1489 if host and not no_proxy: | |
1490 proxy_handler = urllib2.ProxyHandler({"http" : "http://" + host}) | |
1491 | |
1492 authinfo = None | |
1493 if user and passwd: | |
1494 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() | |
1495 passmgr.add_password(None, host, user, passwd) | |
1496 authinfo = urllib2.ProxyBasicAuthHandler(passmgr) | |
1497 | |
1498 opener = urllib2.build_opener(proxy_handler, authinfo) | |
1499 urllib2.install_opener(opener) | |
60 | 1500 |
1501 def do_cmd(self, cmd, **args): | |
83 | 1502 self.ui.debug("sending %s command\n" % cmd) |
60 | 1503 q = {"cmd": cmd} |
1504 q.update(args) | |
1505 qs = urllib.urlencode(q) | |
1506 cu = "%s?%s" % (self.url, qs) | |
321 | 1507 return urllib2.urlopen(cu) |
60 | 1508 |
222 | 1509 def heads(self): |
1510 d = self.do_cmd("heads").read() | |
1511 try: | |
1512 return map(bin, d[:-1].split(" ")) | |
1513 except: | |
1514 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1515 raise | |
1516 | |
60 | 1517 def branches(self, nodes): |
1518 n = " ".join(map(hex, nodes)) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1519 d = self.do_cmd("branches", nodes=n).read() |
217 | 1520 try: |
1521 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] | |
1522 return br | |
1523 except: | |
1524 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1525 raise | |
60 | 1526 |
1527 def between(self, pairs): | |
1528 n = "\n".join(["-".join(map(hex, p)) for p in pairs]) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1529 d = self.do_cmd("between", pairs=n).read() |
217 | 1530 try: |
1531 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ] | |
1532 return p | |
1533 except: | |
1534 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") | |
1535 raise | |
60 | 1536 |
1537 def changegroup(self, nodes): | |
1538 n = " ".join(map(hex, nodes)) | |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1539 zd = zlib.decompressobj() |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1540 f = self.do_cmd("changegroup", roots=n) |
192 | 1541 bytes = 0 |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1542 while 1: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1543 d = f.read(4096) |
192 | 1544 bytes += len(d) |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1545 if not d: |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1546 yield zd.flush() |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1547 break |
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
1548 yield zd.decompress(d) |
192 | 1549 self.ui.note("%d bytes of data transfered\n" % bytes) |
60 | 1550 |
1551 def repository(ui, path=None, create=0): | |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1552 if path and path[:7] == "http://": |
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1553 return remoterepository(ui, path) |
60 | 1554 if path and path[:5] == "hg://": |
176
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1555 return remoterepository(ui, path.replace("hg://", "http://")) |
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1556 if path and path[:11] == "old-http://": |
1d8e9637a0a4
Change hg: protocol name to http: and http: to old-http:
mpm@selenic.com
parents:
171
diff
changeset
|
1557 return localrepository(ui, path.replace("old-http://", "http://")) |
60 | 1558 else: |
1559 return localrepository(ui, path, create) | |
1560 |