Mercurial > public > mercurial-scm > hg
annotate mercurial/localrepo.py @ 1375:f2b00be33e2c
Fix traceback when nothing was added during unbundle
The changegroup and commit hook are now run only when
something is modified.
The correct number of changesets added is printed.
author | Benoit Boissinot <benoit.boissinot@ens-lyon.org> |
---|---|
date | Mon, 03 Oct 2005 14:45:14 -0700 |
parents | a0c68981a5f4 |
children | b113e7db06e9 |
rev | line source |
---|---|
1089 | 1 # localrepo.py - read/write repository class for mercurial |
0
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 |
1097 | 8 import struct, os, util |
1100 | 9 import filelog, manifest, changelog, dirstate, repo |
1089 | 10 from node import * |
262 | 11 from demandload import * |
1353
a0c68981a5f4
Fix misleading abort message when permissions are bad.
Eric Hopper <hopper@omnifarious.org>
parents:
1349
diff
changeset
|
12 demandload(globals(), "re lock transaction tempfile stat mdiff errno") |
499 | 13 |
60 | 14 class localrepository: |
1102 | 15 def __init__(self, ui, path=None, create=0): |
1101 | 16 if not path: |
17 p = os.getcwd() | |
18 while not os.path.isdir(os.path.join(p, ".hg")): | |
19 oldp = p | |
20 p = os.path.dirname(p) | |
21 if p == oldp: raise repo.RepoError("no repo found") | |
22 path = p | |
23 self.path = os.path.join(path, ".hg") | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
24 |
1101 | 25 if not create and not os.path.isdir(self.path): |
26 raise repo.RepoError("repository %s not found" % self.path) | |
405 | 27 |
933
9c43d68ad59f
Fixed --repository option when handling relative path
tksoh@users.sf.net
parents:
926
diff
changeset
|
28 self.root = os.path.abspath(path) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
29 self.ui = ui |
1102 | 30 self.opener = util.opener(self.path) |
31 self.wopener = util.opener(self.root) | |
1100 | 32 self.manifest = manifest.manifest(self.opener) |
33 self.changelog = changelog.changelog(self.opener) | |
343 | 34 self.tagscache = None |
35 self.nodetagscache = None | |
1258 | 36 self.encodepats = None |
37 self.decodepats = None | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
38 |
1133
899b619a7eb2
Create [web] section with short username as contact on hg init and hg clone.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1117
diff
changeset
|
39 if create: |
899b619a7eb2
Create [web] section with short username as contact on hg init and hg clone.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1117
diff
changeset
|
40 os.mkdir(self.path) |
899b619a7eb2
Create [web] section with short username as contact on hg init and hg clone.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1117
diff
changeset
|
41 os.mkdir(self.join("data")) |
899b619a7eb2
Create [web] section with short username as contact on hg init and hg clone.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1117
diff
changeset
|
42 |
1101 | 43 self.dirstate = dirstate.dirstate(self.opener, ui, self.root) |
44 try: | |
45 self.ui.readconfig(self.opener("hgrc")) | |
46 except IOError: pass | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
47 |
487 | 48 def hook(self, name, **args): |
49 s = self.ui.config("hooks", name) | |
50 if s: | |
51 self.ui.note("running hook %s: %s\n" % (name, s)) | |
52 old = {} | |
53 for k, v in args.items(): | |
54 k = k.upper() | |
55 old[k] = os.environ.get(k, None) | |
56 os.environ[k] = v | |
57 | |
1346 | 58 # Hooks run in the repository root |
59 olddir = os.getcwd() | |
60 os.chdir(self.root) | |
487 | 61 r = os.system(s) |
1346 | 62 os.chdir(olddir) |
487 | 63 |
64 for k, v in old.items(): | |
65 if v != None: | |
66 os.environ[k] = v | |
67 else: | |
68 del os.environ[k] | |
69 | |
70 if r: | |
71 self.ui.warn("abort: %s hook failed with status %d!\n" % | |
72 (name, r)) | |
73 return False | |
74 return True | |
75 | |
343 | 76 def tags(self): |
77 '''return a mapping of tag to node''' | |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
78 if not self.tagscache: |
343 | 79 self.tagscache = {} |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
80 def addtag(self, k, n): |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
81 try: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
82 bin_n = bin(n) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
83 except TypeError: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
84 bin_n = '' |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
85 self.tagscache[k.strip()] = bin_n |
659 | 86 |
67 | 87 try: |
254 | 88 # read each head of the tags file, ending with the tip |
89 # and add each tag found to the map, with "newer" ones | |
90 # taking precedence | |
67 | 91 fl = self.file(".hgtags") |
254 | 92 h = fl.heads() |
93 h.reverse() | |
94 for r in h: | |
994
88c15682d9b0
Fix callers to file.revision to use file.read
mpm@selenic.com
parents:
993
diff
changeset
|
95 for l in fl.read(r).splitlines(): |
254 | 96 if l: |
385
e9e1efd5291c
Fixed problems with extra spaces around tags in .hgtags
Thomas Arendsen Hein <thomas@intevation.de>
parents:
383
diff
changeset
|
97 n, k = l.split(" ", 1) |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
98 addtag(self, k, n) |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
99 except KeyError: |
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
100 pass |
659 | 101 |
609
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
102 try: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
103 f = self.opener("localtags") |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
104 for l in f: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
105 n, k = l.split(" ", 1) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
106 addtag(self, k, n) |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
107 except IOError: |
2acf1f5df2e6
[PATCH] hg tag: local tag support in file .hg/localtags
Matt Mackall <mpm@selenic.com>
parents:
608
diff
changeset
|
108 pass |
659 | 109 |
343 | 110 self.tagscache['tip'] = self.changelog.tip() |
659 | 111 |
343 | 112 return self.tagscache |
113 | |
114 def tagslist(self): | |
115 '''return a list of tags ordered by revision''' | |
116 l = [] | |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
471
diff
changeset
|
117 for t, n in self.tags().items(): |
343 | 118 try: |
119 r = self.changelog.rev(n) | |
120 except: | |
121 r = -2 # sort to the beginning of the list if unknown | |
122 l.append((r,t,n)) | |
123 l.sort() | |
124 return [(t,n) for r,t,n in l] | |
125 | |
126 def nodetags(self, node): | |
127 '''return the tags associated with a node''' | |
128 if not self.nodetagscache: | |
129 self.nodetagscache = {} | |
130 for t,n in self.tags().items(): | |
131 self.nodetagscache.setdefault(n,[]).append(t) | |
132 return self.nodetagscache.get(node, []) | |
133 | |
134 def lookup(self, key): | |
67 | 135 try: |
343 | 136 return self.tags()[key] |
67 | 137 except KeyError: |
658
f8098ae9f5b6
Generate a friendlier except for failed lookups
Matt Mackall <mpm@selenic.com>
parents:
657
diff
changeset
|
138 try: |
f8098ae9f5b6
Generate a friendlier except for failed lookups
Matt Mackall <mpm@selenic.com>
parents:
657
diff
changeset
|
139 return self.changelog.lookup(key) |
f8098ae9f5b6
Generate a friendlier except for failed lookups
Matt Mackall <mpm@selenic.com>
parents:
657
diff
changeset
|
140 except: |
1100 | 141 raise repo.RepoError("unknown revision '%s'" % key) |
67 | 142 |
634
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
143 def dev(self): |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
144 return os.stat(self.path).st_dev |
da5378d39269
Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents:
627
diff
changeset
|
145 |
926 | 146 def local(self): |
1101 | 147 return True |
926 | 148 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
149 def join(self, f): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
150 return os.path.join(self.path, f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
151 |
244 | 152 def wjoin(self, f): |
153 return os.path.join(self.root, f) | |
154 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
155 def file(self, f): |
192 | 156 if f[0] == '/': f = f[1:] |
1100 | 157 return filelog.filelog(self.opener, f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
158 |
627 | 159 def getcwd(self): |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
160 return self.dirstate.getcwd() |
627 | 161 |
291
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
162 def wfile(self, f, mode='r'): |
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
163 return self.wopener(f, mode) |
2c4f2be05587
Add wopener for opening files in the working directory
mpm@selenic.com
parents:
288
diff
changeset
|
164 |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
165 def wread(self, filename): |
1258 | 166 if self.encodepats == None: |
167 l = [] | |
168 for pat, cmd in self.ui.configitems("encode"): | |
169 mf = util.matcher("", "/", [pat], [], [])[1] | |
170 l.append((mf, cmd)) | |
171 self.encodepats = l | |
172 | |
173 data = self.wopener(filename, 'r').read() | |
174 | |
175 for mf, cmd in self.encodepats: | |
176 if mf(filename): | |
177 self.ui.debug("filtering %s through %s\n" % (filename, cmd)) | |
178 data = util.filter(data, cmd) | |
179 break | |
180 | |
181 return data | |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
182 |
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
183 def wwrite(self, filename, data, fd=None): |
1258 | 184 if self.decodepats == None: |
185 l = [] | |
186 for pat, cmd in self.ui.configitems("decode"): | |
187 mf = util.matcher("", "/", [pat], [], [])[1] | |
188 l.append((mf, cmd)) | |
189 self.decodepats = l | |
190 | |
191 for mf, cmd in self.decodepats: | |
192 if mf(filename): | |
193 self.ui.debug("filtering %s through %s\n" % (filename, cmd)) | |
194 data = util.filter(data, cmd) | |
195 break | |
196 | |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
197 if fd: |
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
198 return fd.write(data) |
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
199 return self.wopener(filename, 'w').write(data) |
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
200 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
201 def transaction(self): |
251 | 202 # save dirstate for undo |
263 | 203 try: |
204 ds = self.opener("dirstate").read() | |
205 except IOError: | |
206 ds = "" | |
785 | 207 self.opener("journal.dirstate", "w").write(ds) |
515 | 208 |
785 | 209 def after(): |
210 util.rename(self.join("journal"), self.join("undo")) | |
211 util.rename(self.join("journal.dirstate"), | |
212 self.join("undo.dirstate")) | |
213 | |
214 return transaction.transaction(self.ui.warn, self.opener, | |
215 self.join("journal"), after) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
216 |
210 | 217 def recover(self): |
225 | 218 lock = self.lock() |
557 | 219 if os.path.exists(self.join("journal")): |
501 | 220 self.ui.status("rolling back interrupted transaction\n") |
557 | 221 return transaction.rollback(self.opener, self.join("journal")) |
210 | 222 else: |
223 self.ui.warn("no interrupted transaction available\n") | |
224 | |
225 def undo(self): | |
225 | 226 lock = self.lock() |
210 | 227 if os.path.exists(self.join("undo")): |
501 | 228 self.ui.status("rolling back last transaction\n") |
262 | 229 transaction.rollback(self.opener, self.join("undo")) |
251 | 230 self.dirstate = None |
421 | 231 util.rename(self.join("undo.dirstate"), self.join("dirstate")) |
1100 | 232 self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) |
163 | 233 else: |
210 | 234 self.ui.warn("no undo information available\n") |
162 | 235 |
1062 | 236 def lock(self, wait=1): |
161 | 237 try: |
238 return lock.lock(self.join("lock"), 0) | |
239 except lock.LockHeld, inst: | |
240 if wait: | |
241 self.ui.warn("waiting for lock held by %s\n" % inst.args[0]) | |
242 return lock.lock(self.join("lock"), wait) | |
243 raise inst | |
244 | |
203 | 245 def rawcommit(self, files, text, user, date, p1=None, p2=None): |
442 | 246 orig_parent = self.dirstate.parents()[0] or nullid |
452
a1e91c24dab5
rawcommit: do lookup of parents at the appropriate layer
mpm@selenic.com
parents:
442
diff
changeset
|
247 p1 = p1 or self.dirstate.parents()[0] or nullid |
a1e91c24dab5
rawcommit: do lookup of parents at the appropriate layer
mpm@selenic.com
parents:
442
diff
changeset
|
248 p2 = p2 or self.dirstate.parents()[1] or nullid |
302 | 249 c1 = self.changelog.read(p1) |
250 c2 = self.changelog.read(p2) | |
251 m1 = self.manifest.read(c1[0]) | |
252 mf1 = self.manifest.readflags(c1[0]) | |
253 m2 = self.manifest.read(c2[0]) | |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
254 changed = [] |
302 | 255 |
442 | 256 if orig_parent == p1: |
257 update_dirstate = 1 | |
258 else: | |
259 update_dirstate = 0 | |
260 | |
203 | 261 tr = self.transaction() |
302 | 262 mm = m1.copy() |
263 mfm = mf1.copy() | |
203 | 264 linkrev = self.changelog.count() |
265 for f in files: | |
266 try: | |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
267 t = self.wread(f) |
441 | 268 tm = util.is_exec(self.wjoin(f), mfm.get(f, False)) |
302 | 269 r = self.file(f) |
270 mfm[f] = tm | |
990 | 271 |
272 fp1 = m1.get(f, nullid) | |
273 fp2 = m2.get(f, nullid) | |
274 | |
275 # is the same revision on two branches of a merge? | |
276 if fp2 == fp1: | |
277 fp2 = nullid | |
278 | |
279 if fp2 != nullid: | |
280 # is one parent an ancestor of the other? | |
281 fpa = r.ancestor(fp1, fp2) | |
282 if fpa == fp1: | |
283 fp1, fp2 = fp2, nullid | |
284 elif fpa == fp2: | |
285 fp2 = nullid | |
286 | |
287 # is the file unmodified from the parent? | |
288 if t == r.read(fp1): | |
289 # record the proper existing parent in manifest | |
290 # no need to add a revision | |
291 mm[f] = fp1 | |
292 continue | |
293 | |
294 mm[f] = r.add(t, {}, tr, linkrev, fp1, fp2) | |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
295 changed.append(f) |
442 | 296 if update_dirstate: |
297 self.dirstate.update([f], "n") | |
203 | 298 except IOError: |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
299 try: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
300 del mm[f] |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
301 del mfm[f] |
442 | 302 if update_dirstate: |
303 self.dirstate.forget([f]) | |
314
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
304 except: |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
305 # deleted from p2? |
3402cb9a4c06
More tweaking to rawcommit for repo conversion
mpm@selenic.com
parents:
313
diff
changeset
|
306 pass |
203 | 307 |
302 | 308 mnode = self.manifest.add(mm, mfm, tr, linkrev, c1[0], c2[0]) |
608
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
309 user = user or self.ui.username() |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
310 n = self.changelog.add(mnode, changed, text, tr, p1, p2, user, date) |
203 | 311 tr.close() |
442 | 312 if update_dirstate: |
313 self.dirstate.setparents(n, nullid) | |
203 | 314 |
813
80fd2958235a
Adapt commit to use file matching code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
786
diff
changeset
|
315 def commit(self, files = None, text = "", user = None, date = None, |
900
ba8cf1f2210c
Add force option to repo.commit, allowing commits where no files change
mason@suse.com
parents:
898
diff
changeset
|
316 match = util.always, force=False): |
220 | 317 commit = [] |
318 remove = [] | |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
319 changed = [] |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
320 |
220 | 321 if files: |
322 for f in files: | |
323 s = self.dirstate.state(f) | |
244 | 324 if s in 'nmai': |
220 | 325 commit.append(f) |
326 elif s == 'r': | |
327 remove.append(f) | |
328 else: | |
244 | 329 self.ui.warn("%s not tracked!\n" % f) |
220 | 330 else: |
1062 | 331 (c, a, d, u) = self.changes(match=match) |
220 | 332 commit = c + a |
333 remove = d | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
334 |
990 | 335 p1, p2 = self.dirstate.parents() |
336 c1 = self.changelog.read(p1) | |
337 c2 = self.changelog.read(p2) | |
338 m1 = self.manifest.read(c1[0]) | |
339 mf1 = self.manifest.readflags(c1[0]) | |
340 m2 = self.manifest.read(c2[0]) | |
341 | |
342 if not commit and not remove and not force and p2 == nullid: | |
151 | 343 self.ui.status("nothing changed\n") |
901
120cba94d5aa
Change repo.comit to return None on error or the new revision number on
mason@suse.com
parents:
900
diff
changeset
|
344 return None |
151 | 345 |
487 | 346 if not self.hook("precommit"): |
901
120cba94d5aa
Change repo.comit to return None on error or the new revision number on
mason@suse.com
parents:
900
diff
changeset
|
347 return None |
487 | 348 |
225 | 349 lock = self.lock() |
151 | 350 tr = self.transaction() |
351 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
352 # check in files |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
353 new = {} |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
354 linkrev = self.changelog.count() |
220 | 355 commit.sort() |
356 for f in commit: | |
83 | 357 self.ui.note(f + "\n") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
358 try: |
441 | 359 mf1[f] = util.is_exec(self.wjoin(f), mf1.get(f, False)) |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
360 t = self.wread(f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
361 except IOError: |
667
31a9aa890016
A number of minor fixes to problems that pychecker found.
mark.williamson@cl.cam.ac.uk
parents:
660
diff
changeset
|
362 self.ui.warn("trouble committing %s!\n" % f) |
220 | 363 raise |
364 | |
1117 | 365 r = self.file(f) |
366 | |
363 | 367 meta = {} |
368 cp = self.dirstate.copied(f) | |
369 if cp: | |
370 meta["copy"] = cp | |
371 meta["copyrev"] = hex(m1.get(cp, m2.get(cp, nullid))) | |
575 | 372 self.ui.debug(" %s: copy %s:%s\n" % (f, cp, meta["copyrev"])) |
1117 | 373 fp1, fp2 = nullid, nullid |
374 else: | |
375 fp1 = m1.get(f, nullid) | |
376 fp2 = m2.get(f, nullid) | |
990 | 377 |
378 # is the same revision on two branches of a merge? | |
379 if fp2 == fp1: | |
380 fp2 = nullid | |
381 | |
382 if fp2 != nullid: | |
383 # is one parent an ancestor of the other? | |
384 fpa = r.ancestor(fp1, fp2) | |
385 if fpa == fp1: | |
386 fp1, fp2 = fp2, nullid | |
387 elif fpa == fp2: | |
388 fp2 = nullid | |
389 | |
390 # is the file unmodified from the parent? | |
391 if not meta and t == r.read(fp1): | |
392 # record the proper existing parent in manifest | |
393 # no need to add a revision | |
394 new[f] = fp1 | |
395 continue | |
396 | |
363 | 397 new[f] = r.add(t, meta, tr, linkrev, fp1, fp2) |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
398 # remember what we've added so that we can later calculate |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
399 # the files to pull from a set of changesets |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
400 changed.append(f) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
401 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
402 # update manifest |
229 | 403 m1.update(new) |
416
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
404 for f in remove: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
405 if f in m1: |
5e9e8b8d2629
[PATCH] Removal of a file added by merging branches
mpm@selenic.com
parents:
415
diff
changeset
|
406 del m1[f] |
741 | 407 mn = self.manifest.add(m1, mf1, tr, linkrev, c1[0], c2[0], |
408 (new, remove)) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
409 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
410 # add changeset |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
411 new = new.keys() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
412 new.sort() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
413 |
288 | 414 if not text: |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
415 edittext = "" |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
416 if p2 != nullid: |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
417 edittext += "HG: branch merge\n" |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
418 edittext += "\n" + "HG: manifest hash %s\n" % hex(mn) |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
419 edittext += "".join(["HG: changed %s\n" % f for f in changed]) |
288 | 420 edittext += "".join(["HG: removed %s\n" % f for f in remove]) |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
421 if not changed and not remove: |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
422 edittext += "HG: no files changed\n" |
288 | 423 edittext = self.ui.edit(edittext) |
424 if not edittext.rstrip(): | |
901
120cba94d5aa
Change repo.comit to return None on error or the new revision number on
mason@suse.com
parents:
900
diff
changeset
|
425 return None |
288 | 426 text = edittext |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
427 |
608
d2994b5298fb
Add username/merge/editor to .hgrc
Matt Mackall <mpm@selenic.com>
parents:
588
diff
changeset
|
428 user = user or self.ui.username() |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
429 n = self.changelog.add(mn, changed, text, tr, p1, p2, user, date) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
430 tr.close() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
431 |
229 | 432 self.dirstate.setparents(n) |
220 | 433 self.dirstate.update(new, "n") |
434 self.dirstate.forget(remove) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
435 |
660
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
436 if not self.hook("commit", node=hex(n)): |
901
120cba94d5aa
Change repo.comit to return None on error or the new revision number on
mason@suse.com
parents:
900
diff
changeset
|
437 return None |
120cba94d5aa
Change repo.comit to return None on error or the new revision number on
mason@suse.com
parents:
900
diff
changeset
|
438 return n |
660
2c83350784c3
Move commit hook after commit completes
Matt Mackall <mpm@selenic.com>
parents:
659
diff
changeset
|
439 |
1062 | 440 def walk(self, node=None, files=[], match=util.always): |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
441 if node: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
442 for fn in self.manifest.read(self.changelog.read(node)[0]): |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
443 if match(fn): yield 'm', fn |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
444 else: |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
445 for src, fn in self.dirstate.walk(files, match): |
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
446 yield src, fn |
723 | 447 |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
448 def changes(self, node1 = None, node2 = None, files = [], |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
449 match = util.always): |
566 | 450 mf2, u = None, [] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
451 |
536 | 452 def fcmp(fn, mf): |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
453 t1 = self.wread(fn) |
994
88c15682d9b0
Fix callers to file.revision to use file.read
mpm@selenic.com
parents:
993
diff
changeset
|
454 t2 = self.file(fn).read(mf.get(fn, nullid)) |
29 | 455 return cmp(t1, t2) |
456 | |
723 | 457 def mfmatches(node): |
458 mf = dict(self.manifest.read(node)) | |
459 for fn in mf.keys(): | |
460 if not match(fn): | |
461 del mf[fn] | |
462 return mf | |
741 | 463 |
536 | 464 # are we comparing the working directory? |
561 | 465 if not node2: |
723 | 466 l, c, a, d, u = self.dirstate.changes(files, match) |
536 | 467 |
468 # are we comparing working dir against its parent? | |
561 | 469 if not node1: |
536 | 470 if l: |
471 # do a full compare of any files that might have changed | |
472 change = self.changelog.read(self.dirstate.parents()[0]) | |
723 | 473 mf2 = mfmatches(change[0]) |
548 | 474 for f in l: |
561 | 475 if fcmp(f, mf2): |
536 | 476 c.append(f) |
561 | 477 |
478 for l in c, a, d, u: | |
479 l.sort() | |
480 | |
536 | 481 return (c, a, d, u) |
515 | 482 |
536 | 483 # are we comparing working dir against non-tip? |
484 # generate a pseudo-manifest for the working dir | |
561 | 485 if not node2: |
486 if not mf2: | |
536 | 487 change = self.changelog.read(self.dirstate.parents()[0]) |
723 | 488 mf2 = mfmatches(change[0]) |
536 | 489 for f in a + c + l: |
561 | 490 mf2[f] = "" |
536 | 491 for f in d: |
561 | 492 if f in mf2: del mf2[f] |
536 | 493 else: |
561 | 494 change = self.changelog.read(node2) |
723 | 495 mf2 = mfmatches(change[0]) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
496 |
566 | 497 # flush lists from dirstate before comparing manifests |
498 c, a = [], [] | |
499 | |
561 | 500 change = self.changelog.read(node1) |
723 | 501 mf1 = mfmatches(change[0]) |
32 | 502 |
503 for fn in mf2: | |
504 if mf1.has_key(fn): | |
505 if mf1[fn] != mf2[fn]: | |
561 | 506 if mf2[fn] != "" or fcmp(fn, mf1): |
536 | 507 c.append(fn) |
32 | 508 del mf1[fn] |
509 else: | |
536 | 510 a.append(fn) |
515 | 511 |
536 | 512 d = mf1.keys() |
561 | 513 |
514 for l in c, a, d, u: | |
515 l.sort() | |
515 | 516 |
536 | 517 return (c, a, d, u) |
32 | 518 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
519 def add(self, list): |
220 | 520 for f in list: |
244 | 521 p = self.wjoin(f) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
522 if not os.path.exists(p): |
659 | 523 self.ui.warn("%s does not exist!\n" % f) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
524 elif not os.path.isfile(p): |
741 | 525 self.ui.warn("%s not added: only files supported currently\n" % f) |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
723
diff
changeset
|
526 elif self.dirstate.state(f) in 'an': |
220 | 527 self.ui.warn("%s already tracked!\n" % f) |
528 else: | |
529 self.dirstate.update([f], "a") | |
530 | |
531 def forget(self, list): | |
532 for f in list: | |
533 if self.dirstate.state(f) not in 'ai': | |
534 self.ui.warn("%s not added!\n" % f) | |
535 else: | |
536 self.dirstate.forget([f]) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
537 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
538 def remove(self, list): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
539 for f in list: |
244 | 540 p = self.wjoin(f) |
611
48c3eb2bf844
* clean up error handling when user requests to use a non file object
shaleh@speakeasy.net
parents:
609
diff
changeset
|
541 if os.path.exists(p): |
220 | 542 self.ui.warn("%s still exists!\n" % f) |
402 | 543 elif self.dirstate.state(f) == 'a': |
544 self.ui.warn("%s never committed!\n" % f) | |
657
22bc6fb9aefc
dirstate.forget() takes a list
Matt Mackall <mpm@selenic.com>
parents:
656
diff
changeset
|
545 self.dirstate.forget([f]) |
220 | 546 elif f not in self.dirstate: |
547 self.ui.warn("%s not tracked!\n" % f) | |
548 else: | |
549 self.dirstate.update([f], "r") | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
550 |
363 | 551 def copy(self, source, dest): |
552 p = self.wjoin(dest) | |
781 | 553 if not os.path.exists(p): |
363 | 554 self.ui.warn("%s does not exist!\n" % dest) |
781 | 555 elif not os.path.isfile(p): |
659 | 556 self.ui.warn("copy failed: %s is not a file\n" % dest) |
363 | 557 else: |
558 if self.dirstate.state(dest) == '?': | |
559 self.dirstate.update([dest], "a") | |
560 self.dirstate.copy(source, dest) | |
561 | |
222 | 562 def heads(self): |
563 return self.changelog.heads() | |
564 | |
898 | 565 # branchlookup returns a dict giving a list of branches for |
566 # each head. A branch is defined as the tag of a node or | |
567 # the branch of the node's parents. If a node has multiple | |
568 # branch tags, tags are eliminated if they are visible from other | |
569 # branch tags. | |
570 # | |
571 # So, for this graph: a->b->c->d->e | |
572 # \ / | |
573 # aa -----/ | |
919 | 574 # a has tag 2.6.12 |
898 | 575 # d has tag 2.6.13 |
576 # e would have branch tags for 2.6.12 and 2.6.13. Because the node | |
577 # for 2.6.12 can be reached from the node 2.6.13, that is eliminated | |
578 # from the list. | |
579 # | |
580 # It is possible that more than one head will have the same branch tag. | |
581 # callers need to check the result for multiple heads under the same | |
582 # branch tag if that is a problem for them (ie checkout of a specific | |
583 # branch). | |
584 # | |
585 # passing in a specific branch will limit the depth of the search | |
586 # through the parents. It won't limit the branches returned in the | |
587 # result though. | |
588 def branchlookup(self, heads=None, branch=None): | |
589 if not heads: | |
590 heads = self.heads() | |
591 headt = [ h for h in heads ] | |
592 chlog = self.changelog | |
593 branches = {} | |
594 merges = [] | |
595 seenmerge = {} | |
596 | |
597 # traverse the tree once for each head, recording in the branches | |
598 # dict which tags are visible from this head. The branches | |
599 # dict also records which tags are visible from each tag | |
600 # while we traverse. | |
601 while headt or merges: | |
602 if merges: | |
603 n, found = merges.pop() | |
604 visit = [n] | |
605 else: | |
606 h = headt.pop() | |
607 visit = [h] | |
608 found = [h] | |
609 seen = {} | |
610 while visit: | |
611 n = visit.pop() | |
612 if n in seen: | |
613 continue | |
614 pp = chlog.parents(n) | |
615 tags = self.nodetags(n) | |
616 if tags: | |
617 for x in tags: | |
618 if x == 'tip': | |
619 continue | |
620 for f in found: | |
621 branches.setdefault(f, {})[n] = 1 | |
622 branches.setdefault(n, {})[n] = 1 | |
623 break | |
624 if n not in found: | |
625 found.append(n) | |
626 if branch in tags: | |
627 continue | |
628 seen[n] = 1 | |
629 if pp[1] != nullid and n not in seenmerge: | |
630 merges.append((pp[1], [x for x in found])) | |
631 seenmerge[n] = 1 | |
632 if pp[0] != nullid: | |
633 visit.append(pp[0]) | |
634 # traverse the branches dict, eliminating branch tags from each | |
635 # head that are visible from another branch tag for that head. | |
636 out = {} | |
637 viscache = {} | |
638 for h in heads: | |
639 def visible(node): | |
640 if node in viscache: | |
641 return viscache[node] | |
642 ret = {} | |
643 visit = [node] | |
644 while visit: | |
645 x = visit.pop() | |
646 if x in viscache: | |
647 ret.update(viscache[x]) | |
648 elif x not in ret: | |
649 ret[x] = 1 | |
650 if x in branches: | |
651 visit[len(visit):] = branches[x].keys() | |
652 viscache[node] = ret | |
653 return ret | |
654 if h not in branches: | |
655 continue | |
656 # O(n^2), but somewhat limited. This only searches the | |
657 # tags visible from a specific head, not all the tags in the | |
658 # whole repo. | |
659 for b in branches[h]: | |
660 vis = False | |
661 for bb in branches[h].keys(): | |
662 if b != bb: | |
663 if b in visible(bb): | |
664 vis = True | |
665 break | |
666 if not vis: | |
667 l = out.setdefault(h, []) | |
668 l[len(l):] = self.nodetags(b) | |
669 return out | |
670 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
671 def branches(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
672 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
|
673 b = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
674 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
675 t = n |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
676 while n: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
677 p = self.changelog.parents(n) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
678 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
|
679 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
|
680 break |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
681 n = p[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
682 return b |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
683 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
684 def between(self, pairs): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
685 r = [] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
686 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
687 for top, bottom in pairs: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
688 n, l, i = top, [], 0 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
689 f = 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
690 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
691 while n != bottom: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
692 p = self.changelog.parents(n)[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
693 if i == f: |
575 | 694 l.append(n) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
695 f = f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
696 n = p |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
697 i += 1 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
698 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
699 r.append(l) |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
700 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
701 return r |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
702 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
703 def newer(self, nodes): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
704 m = {} |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
705 nl = [] |
94 | 706 pm = {} |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
707 cl = self.changelog |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
708 t = l = cl.count() |
94 | 709 |
710 # find the lowest numbered node | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
711 for n in nodes: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
712 l = min(l, cl.rev(n)) |
94 | 713 m[n] = 1 |
46 | 714 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
715 for i in xrange(l, t): |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
716 n = cl.node(i) |
94 | 717 if n in m: # explicitly listed |
718 pm[n] = 1 | |
719 nl.append(n) | |
720 continue | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
721 for p in cl.parents(n): |
94 | 722 if p in pm: # parent listed |
723 pm[n] = 1 | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
724 nl.append(n) |
94 | 725 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
726 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
727 return nl |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
728 |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
729 def findincoming(self, remote, base=None, heads=None): |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
730 m = self.changelog.nodemap |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
731 search = [] |
1072 | 732 fetch = {} |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
733 seen = {} |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
734 seenbranch = {} |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
735 if base == None: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
736 base = {} |
192 | 737 |
636
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
738 # assume we're closer to the tip than the root |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
739 # and start by examining the heads |
222 | 740 self.ui.status("searching for changes\n") |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
741 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
742 if not heads: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
743 heads = remote.heads() |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
744 |
222 | 745 unknown = [] |
746 for h in heads: | |
747 if h not in m: | |
748 unknown.append(h) | |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
749 else: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
750 base[h] = 1 |
46 | 751 |
222 | 752 if not unknown: |
60 | 753 return None |
324 | 754 |
755 rep = {} | |
756 reqcnt = 0 | |
515 | 757 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
758 # search through remote branches |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
759 # a 'branch' here is a linear segment of history, with four parts: |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
760 # head, root, first parent, second parent |
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
761 # (a branch always has two parents (or none) by definition) |
222 | 762 unknown = remote.branches(unknown) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
763 while unknown: |
324 | 764 r = [] |
765 while unknown: | |
766 n = unknown.pop(0) | |
767 if n[0] in seen: | |
768 continue | |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
769 |
324 | 770 self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) |
771 if n[0] == nullid: | |
772 break | |
328 | 773 if n in seenbranch: |
324 | 774 self.ui.debug("branch already found\n") |
775 continue | |
776 if n[1] and n[1] in m: # do we know the base? | |
777 self.ui.debug("found incomplete branch %s:%s\n" | |
778 % (short(n[0]), short(n[1]))) | |
779 search.append(n) # schedule branch range for scanning | |
328 | 780 seenbranch[n] = 1 |
324 | 781 else: |
782 if n[1] not in seen and n[1] not in fetch: | |
783 if n[2] in m and n[3] in m: | |
784 self.ui.debug("found new changeset %s\n" % | |
785 short(n[1])) | |
1072 | 786 fetch[n[1]] = 1 # earliest unknown |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
787 base[n[2]] = 1 # latest known |
324 | 788 continue |
789 | |
790 for a in n[2:4]: | |
791 if a not in rep: | |
792 r.append(a) | |
793 rep[a] = 1 | |
794 | |
328 | 795 seen[n[0]] = 1 |
796 | |
324 | 797 if r: |
798 reqcnt += 1 | |
799 self.ui.debug("request %d: %s\n" % | |
800 (reqcnt, " ".join(map(short, r)))) | |
801 for p in range(0, len(r), 10): | |
802 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
|
803 self.ui.debug("received %s:%s\n" % |
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
804 (short(b[0]), short(b[1]))) |
1072 | 805 if b[0] in m: |
806 self.ui.debug("found base node %s\n" % short(b[0])) | |
807 base[b[0]] = 1 | |
808 elif b[0] not in seen: | |
148
c32286d0a665
Improve pruning of branches in outstanding changeset algorithm
mpm@selenic.com
parents:
146
diff
changeset
|
809 unknown.append(b) |
515 | 810 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
811 # do binary search on the branches we found |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
812 while search: |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
813 n = search.pop(0) |
324 | 814 reqcnt += 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
815 l = remote.between([(n[0], n[1])])[0] |
328 | 816 l.append(n[1]) |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
817 p = n[0] |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
818 f = 1 |
328 | 819 for i in l: |
820 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
|
821 if i in m: |
85 | 822 if f <= 2: |
83 | 823 self.ui.debug("found new branch changeset %s\n" % |
824 short(p)) | |
1072 | 825 fetch[p] = 1 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
826 base[i] = 1 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
827 else: |
83 | 828 self.ui.debug("narrowed branch search to %s:%s\n" |
829 % (short(p), short(i))) | |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
830 search.append((p, i)) |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
831 break |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
832 p, f = i, f * 2 |
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
833 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
834 # sanity check our fetch list |
1072 | 835 for f in fetch.keys(): |
65
d40cc5aacc31
Fix up a bunch of bugs in the new merge code
mpm@selenic.com
parents:
64
diff
changeset
|
836 if f in m: |
1100 | 837 raise repo.RepoError("already have changeset " + short(f[:4])) |
83 | 838 |
579
ffeb2c3a1966
Actually warn on pulling from an unrelated repository
mpm@selenic.com
parents:
578
diff
changeset
|
839 if base.keys() == [nullid]: |
514
874e577e332e
change unrelated repository error to a warning
mpm@selenic.com
parents:
511
diff
changeset
|
840 self.ui.warn("warning: pulling from an unrelated repository!\n") |
511 | 841 |
1072 | 842 self.ui.note("found new changesets starting at " + |
83 | 843 " ".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
|
844 |
324 | 845 self.ui.debug("%d total queries\n" % reqcnt) |
846 | |
1072 | 847 return fetch.keys() |
516 | 848 |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
849 def findoutgoing(self, remote, base=None, heads=None): |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
850 if base == None: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
851 base = {} |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
852 self.findincoming(remote, base, heads) |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
853 |
1072 | 854 self.ui.debug("common changesets up to " |
855 + " ".join(map(short, base.keys())) + "\n") | |
856 | |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
857 remain = dict.fromkeys(self.changelog.nodemap) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
858 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
859 # prune everything remote has from the tree |
637
31e090c34d3b
Fix up the broken bits in findoutgoing
Matt Mackall <mpm@selenic.com>
parents:
636
diff
changeset
|
860 del remain[nullid] |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
861 remove = base.keys() |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
862 while remove: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
863 n = remove.pop(0) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
864 if n in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
865 del remain[n] |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
866 for p in self.changelog.parents(n): |
637
31e090c34d3b
Fix up the broken bits in findoutgoing
Matt Mackall <mpm@selenic.com>
parents:
636
diff
changeset
|
867 remove.append(p) |
621
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
868 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
869 # find every node whose parents have been pruned |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
870 subset = [] |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
871 for n in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
872 p1, p2 = self.changelog.parents(n) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
873 if p1 not in remain and p2 not in remain: |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
874 subset.append(n) |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
875 |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
876 # this is the set of all roots we have to push |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
877 return subset |
004e811f7706
Add a function to calculate the outgoing changegroup
Matt Mackall <mpm@selenic.com>
parents:
616
diff
changeset
|
878 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
879 def pull(self, remote): |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
880 lock = self.lock() |
636
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
881 |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
882 # if we have an empty repo, fetch everything |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
883 if self.changelog.tip() == nullid: |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
884 self.ui.status("requesting all changes\n") |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
885 fetch = [nullid] |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
886 else: |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
887 fetch = self.findincoming(remote) |
ac0ec421e3a5
Move the empty changeset detection out of findincoming to pull
Matt Mackall <mpm@selenic.com>
parents:
635
diff
changeset
|
888 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
889 if not fetch: |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
890 self.ui.status("no changes found\n") |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
891 return 1 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
892 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
893 cg = remote.changegroup(fetch) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
894 return self.addchangegroup(cg) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
895 |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
896 def push(self, remote, force=False): |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
897 lock = remote.lock() |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
898 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
899 base = {} |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
900 heads = remote.heads() |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
901 inc = self.findincoming(remote, base, heads) |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
902 if not force and inc: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
903 self.ui.warn("abort: unsynced remote changes!\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
904 self.ui.status("(did you forget to sync? use push -f to force)\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
905 return 1 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
906 |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
907 update = self.findoutgoing(remote, base) |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
908 if not update: |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
909 self.ui.status("no changes found\n") |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
910 return 1 |
816
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
911 elif not force: |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
912 if len(heads) < len(self.changelog.heads()): |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
913 self.ui.warn("abort: push creates new remote branches!\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
914 self.ui.status("(did you forget to merge?" + |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
915 " use push -f to force)\n") |
8674b7803714
Warn on pushing unsynced repo or adding new heads
mpm@selenic.com
parents:
814
diff
changeset
|
916 return 1 |
622
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
917 |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
918 cg = self.changegroup(update) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
919 return remote.addchangegroup(cg) |
e9fe5d5e67f7
Add generic repo commands for pull and push
Matt Mackall <mpm@selenic.com>
parents:
621
diff
changeset
|
920 |
56
ad2ea1185f04
Add getchangegroup code to efficiently calculate and request a changegroup
mpm@selenic.com
parents:
55
diff
changeset
|
921 def changegroup(self, basenodes): |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1133
diff
changeset
|
922 genread = util.chunkbuffer |
515 | 923 |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
924 def gengroup(): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
925 nodes = self.newer(basenodes) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
926 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
927 # construct the link map |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
928 linkmap = {} |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
929 for n in nodes: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
930 linkmap[self.changelog.rev(n)] = n |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
931 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
932 # construct a list of all changed files |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
933 changed = {} |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
934 for n in nodes: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
935 c = self.changelog.read(n) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
936 for f in c[3]: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
937 changed[f] = 1 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
938 changed = changed.keys() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
939 changed.sort() |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
940 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
941 # the changegroup is changesets + manifests + all file revs |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
942 revs = [ self.changelog.rev(n) for n in nodes ] |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
943 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
944 for y in self.changelog.group(linkmap): yield y |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
945 for y in self.manifest.group(linkmap): yield y |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
946 for f in changed: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
947 yield struct.pack(">l", len(f) + 4) + f |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
948 g = self.file(f).group(linkmap) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
949 for y in g: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
950 yield y |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
951 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
952 yield struct.pack(">l", 0) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
953 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
954 return genread(gengroup()) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
955 |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
956 def addchangegroup(self, source): |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
957 |
222 | 958 def getchunk(): |
959 d = source.read(4) | |
960 if not d: return "" | |
961 l = struct.unpack(">l", d)[0] | |
962 if l <= 4: return "" | |
1280
50553b99a5c9
pull/unbundle: raise an exception on premature EOF
mpm@selenic.com
parents:
1260
diff
changeset
|
963 d = source.read(l - 4) |
50553b99a5c9
pull/unbundle: raise an exception on premature EOF
mpm@selenic.com
parents:
1260
diff
changeset
|
964 if len(d) < l - 4: |
50553b99a5c9
pull/unbundle: raise an exception on premature EOF
mpm@selenic.com
parents:
1260
diff
changeset
|
965 raise repo.RepoError("premature EOF reading chunk" + |
50553b99a5c9
pull/unbundle: raise an exception on premature EOF
mpm@selenic.com
parents:
1260
diff
changeset
|
966 " (got %d bytes, expected %d)" |
50553b99a5c9
pull/unbundle: raise an exception on premature EOF
mpm@selenic.com
parents:
1260
diff
changeset
|
967 % (len(d), l - 4)) |
50553b99a5c9
pull/unbundle: raise an exception on premature EOF
mpm@selenic.com
parents:
1260
diff
changeset
|
968 return d |
222 | 969 |
970 def getgroup(): | |
971 while 1: | |
972 c = getchunk() | |
973 if not c: break | |
974 yield c | |
975 | |
976 def csmap(x): | |
977 self.ui.debug("add changeset %s\n" % short(x)) | |
978 return self.changelog.count() | |
979 | |
980 def revmap(x): | |
981 return self.changelog.rev(x) | |
982 | |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
634
diff
changeset
|
983 if not source: return |
222 | 984 changesets = files = revisions = 0 |
225 | 985 |
222 | 986 tr = self.transaction() |
987 | |
1040
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
988 oldheads = len(self.changelog.heads()) |
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
989 |
222 | 990 # pull off the changeset group |
991 self.ui.status("adding changesets\n") | |
992 co = self.changelog.tip() | |
224
ccbcc4d76f81
fix bad assumption about uniqueness of file versions
mpm@selenic.com
parents:
223
diff
changeset
|
993 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique |
1316 | 994 cnr, cor = map(self.changelog.rev, (cn, co)) |
1375
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
995 if cn == nullid: |
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
996 cnr = cor |
1316 | 997 changesets = cnr - cor |
222 | 998 |
999 # pull off the manifest group | |
1000 self.ui.status("adding manifests\n") | |
1001 mm = self.manifest.tip() | |
1002 mo = self.manifest.addgroup(getgroup(), revmap, tr) | |
1003 | |
1004 # process the files | |
772 | 1005 self.ui.status("adding file changes\n") |
222 | 1006 while 1: |
1007 f = getchunk() | |
1008 if not f: break | |
1009 self.ui.debug("adding %s revisions\n" % f) | |
1010 fl = self.file(f) | |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1011 o = fl.count() |
222 | 1012 n = fl.addgroup(getgroup(), revmap, tr) |
529
aace5b681fe9
Attempt to fix negative revision count from pull
mpm@selenic.com
parents:
522
diff
changeset
|
1013 revisions += fl.count() - o |
222 | 1014 files += 1 |
1015 | |
1040
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
1016 newheads = len(self.changelog.heads()) |
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
1017 heads = "" |
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
1018 if oldheads and newheads > oldheads: |
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
1019 heads = " (+%d heads)" % (newheads - oldheads) |
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
1020 |
772 | 1021 self.ui.status(("added %d changesets" + |
1040
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
1022 " with %d changes to %d files%s\n") |
35e883d1ff9b
Show number of new heads when doing a pull
mpm@selenic.com
parents:
1019
diff
changeset
|
1023 % (changesets, revisions, files, heads)) |
222 | 1024 |
1025 tr.close() | |
780 | 1026 |
1375
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
1027 if changesets > 0: |
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
1028 if not self.hook("changegroup", |
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
1029 node=hex(self.changelog.node(cor+1))): |
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
1030 self.ui.warn("abort: changegroup hook returned failure!\n") |
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
1031 return 1 |
780 | 1032 |
1375
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
1033 for i in range(cor + 1, cnr + 1): |
f2b00be33e2c
Fix traceback when nothing was added during unbundle
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1353
diff
changeset
|
1034 self.hook("commit", node=hex(self.changelog.node(i))) |
1316 | 1035 |
222 | 1036 return |
1037 | |
588 | 1038 def update(self, node, allow=False, force=False, choose=None, |
1039 moddirstate=True): | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1040 pl = self.dirstate.parents() |
275 | 1041 if not force and pl[1] != nullid: |
254 | 1042 self.ui.warn("aborting: outstanding uncommitted merges\n") |
690 | 1043 return 1 |
46 | 1044 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1045 p1, p2 = pl[0], node |
305 | 1046 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
|
1047 m1n = self.changelog.read(p1)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1048 m2n = self.changelog.read(p2)[0] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1049 man = self.manifest.ancestor(m1n, m2n) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1050 m1 = self.manifest.read(m1n) |
276 | 1051 mf1 = self.manifest.readflags(m1n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1052 m2 = self.manifest.read(m2n) |
276 | 1053 mf2 = self.manifest.readflags(m2n) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1054 ma = self.manifest.read(man) |
412 | 1055 mfa = self.manifest.readflags(man) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1056 |
723 | 1057 (c, a, d, u) = self.changes() |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1058 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1059 # 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
|
1060 # from p1 to p2? |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1061 linear_path = (pa == p1 or pa == p2) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1062 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1063 # 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
|
1064 # we care about merging |
254 | 1065 self.ui.note("resolving manifests\n") |
650
2c934c7b79dc
Fix bug in reverting deleted files
Matt Mackall <mpm@selenic.com>
parents:
649
diff
changeset
|
1066 self.ui.debug(" force %s allow %s moddirstate %s linear %s\n" % |
2c934c7b79dc
Fix bug in reverting deleted files
Matt Mackall <mpm@selenic.com>
parents:
649
diff
changeset
|
1067 (force, allow, moddirstate, linear_path)) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1068 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
|
1069 (short(man), short(m1n), short(m2n))) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1070 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1071 merge = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1072 get = {} |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1073 remove = [] |
46 | 1074 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1075 # construct a working dir manifest |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1076 mw = m1.copy() |
276 | 1077 mfw = mf1.copy() |
576 | 1078 umap = dict.fromkeys(u) |
1079 | |
254 | 1080 for f in a + c + u: |
1081 mw[f] = "" | |
441 | 1082 mfw[f] = util.is_exec(self.wjoin(f), mfw.get(f, False)) |
576 | 1083 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1084 for f in d: |
254 | 1085 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
|
1086 |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1087 # 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
|
1088 # 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
|
1089 # 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
|
1090 # 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
|
1091 # longer in the manifest. |
588 | 1092 if moddirstate and linear_path and f not in m2: |
408
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1093 self.dirstate.forget((f,)) |
3695fbd2c33b
[PATCH] Merging files that are deleted in both branches
mpm@selenic.com
parents:
407
diff
changeset
|
1094 |
576 | 1095 # Compare manifests |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1096 for f, n in mw.iteritems(): |
588 | 1097 if choose and not choose(f): continue |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1098 if f in m2: |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1099 s = 0 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1100 |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1101 # is the wfile new since m1, and match m2? |
428 | 1102 if f not in m1: |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
1103 t1 = self.wread(f) |
994
88c15682d9b0
Fix callers to file.revision to use file.read
mpm@selenic.com
parents:
993
diff
changeset
|
1104 t2 = self.file(f).read(m2[f]) |
407
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1105 if cmp(t1, t2) == 0: |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1106 n = m2[f] |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1107 del t1, t2 |
0e0d0670b2bc
[PATCH] Merging identical changes from another branch
mpm@selenic.com
parents:
405
diff
changeset
|
1108 |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1109 # are files different? |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1110 if n != m2[f]: |
254 | 1111 a = ma.get(f, nullid) |
296
a3d83bf86755
hg update: fix clobbering files when going backwards
mpm@selenic.com
parents:
292
diff
changeset
|
1112 # are both different from the ancestor? |
254 | 1113 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
|
1114 self.ui.debug(" %s versions differ, resolve\n" % f) |
276 | 1115 # merge executable bits |
1116 # "if we changed or they changed, change in merge" | |
1117 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] | |
1118 mode = ((a^b) | (a^c)) ^ a | |
1119 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
|
1120 s = 1 |
305 | 1121 # are we clobbering? |
1122 # is remote's version newer? | |
1123 # or are we going back in time? | |
1124 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
|
1125 self.ui.debug(" remote %s is newer, get\n" % f) |
254 | 1126 get[f] = m2[f] |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1127 s = 1 |
576 | 1128 elif f in umap: |
1129 # this unknown file is the same as the checkout | |
1130 get[f] = m2[f] | |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1131 |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1132 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
|
1133 if force: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1134 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1135 util.set_exec(self.wjoin(f), mf2[f]) |
277
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1136 else: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1137 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
|
1138 mode = ((a^b) | (a^c)) ^ a |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1139 if mode != b: |
79279550c8ff
merge: update permissions even if file contents didn't change
mpm@selenic.com
parents:
276
diff
changeset
|
1140 self.ui.debug(" updating permissions for %s\n" % f) |
441 | 1141 util.set_exec(self.wjoin(f), mode) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1142 del m2[f] |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1143 elif f in ma: |
616 | 1144 if n != ma[f]: |
1145 r = "d" | |
1146 if not force and (linear_path or allow): | |
415
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1147 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
|
1148 (" 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
|
1149 "(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
|
1150 if r == "d": |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1151 remove.append(f) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1152 else: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1153 self.ui.debug("other deleted %s\n" % f) |
254 | 1154 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
|
1155 else: |
1236
67a28636ea64
Fix bug with co -C across branches, update tests
mpm@selenic.com
parents:
1234
diff
changeset
|
1156 # file is created on branch or in working directory |
67a28636ea64
Fix bug with co -C across branches, update tests
mpm@selenic.com
parents:
1234
diff
changeset
|
1157 if force and f not in umap: |
67a28636ea64
Fix bug with co -C across branches, update tests
mpm@selenic.com
parents:
1234
diff
changeset
|
1158 self.ui.debug("remote deleted %s, clobbering\n" % f) |
67a28636ea64
Fix bug with co -C across branches, update tests
mpm@selenic.com
parents:
1234
diff
changeset
|
1159 remove.append(f) |
67a28636ea64
Fix bug with co -C across branches, update tests
mpm@selenic.com
parents:
1234
diff
changeset
|
1160 elif n == m1.get(f, nullid): # same as parent |
1234
9ee8428d84a1
Revert unrelated changes in previous commit
mpm@selenic.com
parents:
1233
diff
changeset
|
1161 if p2 == pa: # going backwards? |
9ee8428d84a1
Revert unrelated changes in previous commit
mpm@selenic.com
parents:
1233
diff
changeset
|
1162 self.ui.debug("remote deleted %s\n" % f) |
9ee8428d84a1
Revert unrelated changes in previous commit
mpm@selenic.com
parents:
1233
diff
changeset
|
1163 remove.append(f) |
9ee8428d84a1
Revert unrelated changes in previous commit
mpm@selenic.com
parents:
1233
diff
changeset
|
1164 else: |
1236
67a28636ea64
Fix bug with co -C across branches, update tests
mpm@selenic.com
parents:
1234
diff
changeset
|
1165 self.ui.debug("local modified %s, keeping\n" % f) |
254 | 1166 else: |
1167 self.ui.debug("working dir created %s, keeping\n" % f) | |
46 | 1168 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1169 for f, n in m2.iteritems(): |
588 | 1170 if choose and not choose(f): continue |
256 | 1171 if f[0] == "/": continue |
616 | 1172 if f in ma and n != ma[f]: |
1173 r = "k" | |
1174 if not force and (linear_path or allow): | |
415
c2b9502a4e96
[PATCH] Don't prompt user for keep-vs-delete when the merge is about to be aborted
mpm@selenic.com
parents:
413
diff
changeset
|
1175 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
|
1176 ("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
|
1177 "(k)eep or (d)elete?", "[kd]", "k") |
616 | 1178 if r == "k": get[f] = n |
1179 elif f not in ma: | |
254 | 1180 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
|
1181 get[f] = n |
616 | 1182 else: |
680
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1183 if force or p2 == pa: # going backwards? |
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1184 self.ui.debug("local deleted %s, recreating\n" % f) |
650
2c934c7b79dc
Fix bug in reverting deleted files
Matt Mackall <mpm@selenic.com>
parents:
649
diff
changeset
|
1185 get[f] = n |
680
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1186 else: |
4b7b79d2db2c
Handle undeletion of files when checking out old revisions
Matt Mackall <mpm@selenic.com>
parents:
679
diff
changeset
|
1187 self.ui.debug("local deleted %s\n" % f) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1188 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1189 del mw, m1, m2, ma |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1190 |
275 | 1191 if force: |
1192 for f in merge: | |
1193 get[f] = merge[f][1] | |
1194 merge = {} | |
1195 | |
690 | 1196 if linear_path or force: |
254 | 1197 # we don't need to do any magic, just jump to the new rev |
993 | 1198 branch_merge = False |
254 | 1199 p1, p2 = p2, nullid |
1200 else: | |
275 | 1201 if not allow: |
305 | 1202 self.ui.status("this update spans a branch" + |
1203 " affecting the following files:\n") | |
1204 fl = merge.keys() + get.keys() | |
1205 fl.sort() | |
1206 for f in fl: | |
1207 cf = "" | |
1208 if f in merge: cf = " (resolve)" | |
1209 self.ui.status(" %s%s\n" % (f, cf)) | |
1210 self.ui.warn("aborting update spanning branches!\n") | |
788 | 1211 self.ui.status("(use update -m to merge across branches" + |
1212 " or -C to lose changes)\n") | |
275 | 1213 return 1 |
993 | 1214 branch_merge = True |
254 | 1215 |
588 | 1216 if moddirstate: |
1217 self.dirstate.setparents(p1, p2) | |
191
d7e859cf2f1b
merge: add count of new manifests, files, and revisions
mpm@selenic.com
parents:
190
diff
changeset
|
1218 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1219 # 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
|
1220 files = get.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1221 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1222 for f in files: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1223 if f[0] == "/": continue |
273
4f8174389001
merge: Fix bug where we overwrote local when local was newer
mpm@selenic.com
parents:
263
diff
changeset
|
1224 self.ui.note("getting %s\n" % f) |
276 | 1225 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
|
1226 try: |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
1227 self.wwrite(f, t) |
1353
a0c68981a5f4
Fix misleading abort message when permissions are bad.
Eric Hopper <hopper@omnifarious.org>
parents:
1349
diff
changeset
|
1228 except IOError, e: |
a0c68981a5f4
Fix misleading abort message when permissions are bad.
Eric Hopper <hopper@omnifarious.org>
parents:
1349
diff
changeset
|
1229 if e.errno != errno.ENOENT: |
a0c68981a5f4
Fix misleading abort message when permissions are bad.
Eric Hopper <hopper@omnifarious.org>
parents:
1349
diff
changeset
|
1230 raise |
297
0dbcf3c9ff20
Fixed usage of removed variable 'wp'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
292
diff
changeset
|
1231 os.makedirs(os.path.dirname(self.wjoin(f))) |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
1232 self.wwrite(f, t) |
441 | 1233 util.set_exec(self.wjoin(f), mf2[f]) |
588 | 1234 if moddirstate: |
993 | 1235 if branch_merge: |
1236 self.dirstate.update([f], 'n', st_mtime=-1) | |
992
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
1237 else: |
f859e9cba1b9
Fix up some bugs introduced by recent merge changes
mpm@selenic.com
parents:
991
diff
changeset
|
1238 self.dirstate.update([f], 'n') |
46 | 1239 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1240 # merge the tricky bits |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1241 files = merge.keys() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1242 files.sort() |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1243 for f in files: |
256 | 1244 self.ui.status("merging %s\n" % f) |
993 | 1245 my, other, flag = merge[f] |
1246 self.merge3(f, my, other) | |
441 | 1247 util.set_exec(self.wjoin(f), flag) |
862
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
1248 if moddirstate: |
993 | 1249 if branch_merge: |
1250 # We've done a branch merge, mark this file as merged | |
1251 # so that we properly record the merger later | |
1252 self.dirstate.update([f], 'm') | |
862
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
1253 else: |
993 | 1254 # We've update-merged a locally modified file, so |
1255 # we set the dirstate to emulate a normal checkout | |
1256 # of that file some time in the past. Thus our | |
1257 # merge will appear as a normal local file | |
1258 # modification. | |
1259 f_len = len(self.file(f).read(other)) | |
1260 self.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1261 |
681 | 1262 remove.sort() |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1263 for f in remove: |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1264 self.ui.note("removing %s\n" % f) |
690 | 1265 try: |
934
ff484cc157d6
Fix path handling for deleting files on merge
mpm@selenic.com
parents:
933
diff
changeset
|
1266 os.unlink(self.wjoin(f)) |
690 | 1267 except OSError, inst: |
1268 self.ui.warn("update failed to remove %s: %s!\n" % (f, inst)) | |
578 | 1269 # try removing directories that might now be empty |
934
ff484cc157d6
Fix path handling for deleting files on merge
mpm@selenic.com
parents:
933
diff
changeset
|
1270 try: os.removedirs(os.path.dirname(self.wjoin(f))) |
578 | 1271 except: pass |
588 | 1272 if moddirstate: |
993 | 1273 if branch_merge: |
1274 self.dirstate.update(remove, 'r') | |
1275 else: | |
588 | 1276 self.dirstate.forget(remove) |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1277 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1278 def merge3(self, fn, my, other): |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1279 """perform a 3-way merge in the working directory""" |
249 | 1280 |
96 | 1281 def temp(prefix, node): |
1282 pre = "%s~%s." % (os.path.basename(fn), prefix) | |
1283 (fd, name) = tempfile.mkstemp("", pre) | |
417 | 1284 f = os.fdopen(fd, "wb") |
1019
a9cca981c423
Create helper functions for I/O to files in the working directory
mpm@selenic.com
parents:
1013
diff
changeset
|
1285 self.wwrite(fn, fl.read(node), f) |
96 | 1286 f.close() |
1287 return name | |
1288 | |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1289 fl = self.file(fn) |
96 | 1290 base = fl.ancestor(my, other) |
244 | 1291 a = self.wjoin(fn) |
346 | 1292 b = temp("base", base) |
1293 c = temp("other", other) | |
96 | 1294 |
232
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1295 self.ui.note("resolving %s\n" % fn) |
1349
c6295d2a361e
More info on file merge for update --debug
Matt Mackall <mpm@selenic.com>
parents:
1346
diff
changeset
|
1296 self.ui.debug("file %s: my %s other %s ancestor %s\n" % |
c6295d2a361e
More info on file merge for update --debug
Matt Mackall <mpm@selenic.com>
parents:
1346
diff
changeset
|
1297 (fn, short(my), short(other), short(base))) |
96 | 1298 |
703
fb6f85ecc863
merge program setting from hgrc wasn't used.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
691
diff
changeset
|
1299 cmd = (os.environ.get("HGMERGE") or self.ui.config("ui", "merge") |
fb6f85ecc863
merge program setting from hgrc wasn't used.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
691
diff
changeset
|
1300 or "hgmerge") |
240 | 1301 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
|
1302 if r: |
275 | 1303 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
|
1304 |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1305 os.unlink(b) |
fc4a6e5b5812
hg resolve: merge a given node into the working directory
mpm@selenic.com
parents:
231
diff
changeset
|
1306 os.unlink(c) |
96 | 1307 |
247 | 1308 def verify(self): |
1309 filelinkrevs = {} | |
1310 filenodes = {} | |
1311 changesets = revisions = files = 0 | |
1312 errors = 0 | |
1313 | |
302 | 1314 seen = {} |
247 | 1315 self.ui.status("checking changesets\n") |
1316 for i in range(self.changelog.count()): | |
1317 changesets += 1 | |
1318 n = self.changelog.node(i) | |
302 | 1319 if n in seen: |
1320 self.ui.warn("duplicate changeset at revision %d\n" % i) | |
1321 errors += 1 | |
1322 seen[n] = 1 | |
515 | 1323 |
247 | 1324 for p in self.changelog.parents(n): |
1325 if p not in self.changelog.nodemap: | |
1326 self.ui.warn("changeset %s has unknown parent %s\n" % | |
1327 (short(n), short(p))) | |
1328 errors += 1 | |
1329 try: | |
1330 changes = self.changelog.read(n) | |
1331 except Exception, inst: | |
1332 self.ui.warn("unpacking changeset %s: %s\n" % (short(n), inst)) | |
1333 errors += 1 | |
1334 | |
1335 for f in changes[3]: | |
1336 filelinkrevs.setdefault(f, []).append(i) | |
1337 | |
302 | 1338 seen = {} |
247 | 1339 self.ui.status("checking manifests\n") |
1340 for i in range(self.manifest.count()): | |
1341 n = self.manifest.node(i) | |
302 | 1342 if n in seen: |
1343 self.ui.warn("duplicate manifest at revision %d\n" % i) | |
1344 errors += 1 | |
1345 seen[n] = 1 | |
515 | 1346 |
247 | 1347 for p in self.manifest.parents(n): |
1348 if p not in self.manifest.nodemap: | |
1349 self.ui.warn("manifest %s has unknown parent %s\n" % | |
1350 (short(n), short(p))) | |
1351 errors += 1 | |
1352 | |
1353 try: | |
1354 delta = mdiff.patchtext(self.manifest.delta(n)) | |
1355 except KeyboardInterrupt: | |
1097 | 1356 self.ui.warn("interrupted") |
1357 raise | |
247 | 1358 except Exception, inst: |
1359 self.ui.warn("unpacking manifest %s: %s\n" | |
1360 % (short(n), inst)) | |
1361 errors += 1 | |
1362 | |
1363 ff = [ l.split('\0') for l in delta.splitlines() ] | |
1364 for f, fn in ff: | |
284 | 1365 filenodes.setdefault(f, {})[bin(fn[:40])] = 1 |
247 | 1366 |
1367 self.ui.status("crosschecking files in changesets and manifests\n") | |
1368 for f in filenodes: | |
1369 if f not in filelinkrevs: | |
1370 self.ui.warn("file %s in manifest but not in changesets\n" % f) | |
1371 errors += 1 | |
1372 | |
1373 for f in filelinkrevs: | |
1374 if f not in filenodes: | |
1375 self.ui.warn("file %s in changeset but not in manifest\n" % f) | |
1376 errors += 1 | |
1377 | |
1378 self.ui.status("checking files\n") | |
1379 ff = filenodes.keys() | |
1380 ff.sort() | |
1381 for f in ff: | |
1382 if f == "/dev/null": continue | |
1383 files += 1 | |
1384 fl = self.file(f) | |
1385 nodes = { nullid: 1 } | |
302 | 1386 seen = {} |
247 | 1387 for i in range(fl.count()): |
1388 revisions += 1 | |
1389 n = fl.node(i) | |
1390 | |
302 | 1391 if n in seen: |
1392 self.ui.warn("%s: duplicate revision %d\n" % (f, i)) | |
1393 errors += 1 | |
1394 | |
247 | 1395 if n not in filenodes[f]: |
1396 self.ui.warn("%s: %d:%s not in manifests\n" | |
1397 % (f, i, short(n))) | |
1398 errors += 1 | |
1399 else: | |
1400 del filenodes[f][n] | |
1401 | |
1402 flr = fl.linkrev(n) | |
1403 if flr not in filelinkrevs[f]: | |
1404 self.ui.warn("%s:%s points to unexpected changeset %d\n" | |
1405 % (f, short(n), fl.linkrev(n))) | |
1406 errors += 1 | |
1407 else: | |
1408 filelinkrevs[f].remove(flr) | |
1409 | |
1410 # verify contents | |
1411 try: | |
1412 t = fl.read(n) | |
1413 except Exception, inst: | |
1414 self.ui.warn("unpacking file %s %s: %s\n" | |
1415 % (f, short(n), inst)) | |
1416 errors += 1 | |
1417 | |
1418 # verify parents | |
1419 (p1, p2) = fl.parents(n) | |
1420 if p1 not in nodes: | |
1421 self.ui.warn("file %s:%s unknown parent 1 %s" % | |
1422 (f, short(n), short(p1))) | |
1423 errors += 1 | |
1424 if p2 not in nodes: | |
1425 self.ui.warn("file %s:%s unknown parent 2 %s" % | |
1426 (f, short(n), short(p1))) | |
1427 errors += 1 | |
1428 nodes[n] = 1 | |
1429 | |
1430 # cross-check | |
1431 for node in filenodes[f]: | |
1432 self.ui.warn("node %s in manifests not in %s\n" | |
721 | 1433 % (hex(node), f)) |
247 | 1434 errors += 1 |
1435 | |
1436 self.ui.status("%d files, %d changesets, %d total revisions\n" % | |
1437 (files, changesets, revisions)) | |
1438 | |
1439 if errors: | |
1440 self.ui.warn("%d integrity errors encountered!\n" % errors) | |
1441 return 1 |