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