##// END OF EJS Templates
merge with stable
Patrick Mezard -
r13969:336bb8b5 merge default
parent child Browse files
Show More
@@ -1,365 +1,377
1 # Copyright 2007 Bryan O'Sullivan <bos@serpentine.com>
1 # Copyright 2007 Bryan O'Sullivan <bos@serpentine.com>
2 # Copyright 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
2 # Copyright 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
3 #
3 #
4 # This software may be used and distributed according to the terms of the
4 # This software may be used and distributed according to the terms of the
5 # GNU General Public License version 2 or any later version.
5 # GNU General Public License version 2 or any later version.
6
6
7 import shlex
7 import shlex
8 from mercurial.i18n import _
8 from mercurial.i18n import _
9 from mercurial import util
9 from mercurial import util
10 from common import SKIPREV, converter_source
10 from common import SKIPREV, converter_source
11
11
12 def rpairs(name):
12 def rpairs(name):
13 e = len(name)
13 e = len(name)
14 while e != -1:
14 while e != -1:
15 yield name[:e], name[e + 1:]
15 yield name[:e], name[e + 1:]
16 e = name.rfind('/', 0, e)
16 e = name.rfind('/', 0, e)
17 yield '.', name
17 yield '.', name
18
18
19 class filemapper(object):
19 class filemapper(object):
20 '''Map and filter filenames when importing.
20 '''Map and filter filenames when importing.
21 A name can be mapped to itself, a new name, or None (omit from new
21 A name can be mapped to itself, a new name, or None (omit from new
22 repository).'''
22 repository).'''
23
23
24 def __init__(self, ui, path=None):
24 def __init__(self, ui, path=None):
25 self.ui = ui
25 self.ui = ui
26 self.include = {}
26 self.include = {}
27 self.exclude = {}
27 self.exclude = {}
28 self.rename = {}
28 self.rename = {}
29 if path:
29 if path:
30 if self.parse(path):
30 if self.parse(path):
31 raise util.Abort(_('errors in filemap'))
31 raise util.Abort(_('errors in filemap'))
32
32
33 def parse(self, path):
33 def parse(self, path):
34 errs = 0
34 errs = 0
35 def check(name, mapping, listname):
35 def check(name, mapping, listname):
36 if not name:
36 if not name:
37 self.ui.warn(_('%s:%d: path to %s is missing\n') %
37 self.ui.warn(_('%s:%d: path to %s is missing\n') %
38 (lex.infile, lex.lineno, listname))
38 (lex.infile, lex.lineno, listname))
39 return 1
39 return 1
40 if name in mapping:
40 if name in mapping:
41 self.ui.warn(_('%s:%d: %r already in %s list\n') %
41 self.ui.warn(_('%s:%d: %r already in %s list\n') %
42 (lex.infile, lex.lineno, name, listname))
42 (lex.infile, lex.lineno, name, listname))
43 return 1
43 return 1
44 if (name.startswith('/') or
44 if (name.startswith('/') or
45 name.endswith('/') or
45 name.endswith('/') or
46 '//' in name):
46 '//' in name):
47 self.ui.warn(_('%s:%d: superfluous / in %s %r\n') %
47 self.ui.warn(_('%s:%d: superfluous / in %s %r\n') %
48 (lex.infile, lex.lineno, listname, name))
48 (lex.infile, lex.lineno, listname, name))
49 return 1
49 return 1
50 return 0
50 return 0
51 lex = shlex.shlex(open(path), path, True)
51 lex = shlex.shlex(open(path), path, True)
52 lex.wordchars += '!@#$%^&*()-=+[]{}|;:,./<>?'
52 lex.wordchars += '!@#$%^&*()-=+[]{}|;:,./<>?'
53 cmd = lex.get_token()
53 cmd = lex.get_token()
54 while cmd:
54 while cmd:
55 if cmd == 'include':
55 if cmd == 'include':
56 name = lex.get_token()
56 name = lex.get_token()
57 errs += check(name, self.exclude, 'exclude')
57 errs += check(name, self.exclude, 'exclude')
58 self.include[name] = name
58 self.include[name] = name
59 elif cmd == 'exclude':
59 elif cmd == 'exclude':
60 name = lex.get_token()
60 name = lex.get_token()
61 errs += check(name, self.include, 'include')
61 errs += check(name, self.include, 'include')
62 errs += check(name, self.rename, 'rename')
62 errs += check(name, self.rename, 'rename')
63 self.exclude[name] = name
63 self.exclude[name] = name
64 elif cmd == 'rename':
64 elif cmd == 'rename':
65 src = lex.get_token()
65 src = lex.get_token()
66 dest = lex.get_token()
66 dest = lex.get_token()
67 errs += check(src, self.exclude, 'exclude')
67 errs += check(src, self.exclude, 'exclude')
68 self.rename[src] = dest
68 self.rename[src] = dest
69 elif cmd == 'source':
69 elif cmd == 'source':
70 errs += self.parse(lex.get_token())
70 errs += self.parse(lex.get_token())
71 else:
71 else:
72 self.ui.warn(_('%s:%d: unknown directive %r\n') %
72 self.ui.warn(_('%s:%d: unknown directive %r\n') %
73 (lex.infile, lex.lineno, cmd))
73 (lex.infile, lex.lineno, cmd))
74 errs += 1
74 errs += 1
75 cmd = lex.get_token()
75 cmd = lex.get_token()
76 return errs
76 return errs
77
77
78 def lookup(self, name, mapping):
78 def lookup(self, name, mapping):
79 for pre, suf in rpairs(name):
79 for pre, suf in rpairs(name):
80 try:
80 try:
81 return mapping[pre], pre, suf
81 return mapping[pre], pre, suf
82 except KeyError:
82 except KeyError:
83 pass
83 pass
84 return '', name, ''
84 return '', name, ''
85
85
86 def __call__(self, name):
86 def __call__(self, name):
87 if self.include:
87 if self.include:
88 inc = self.lookup(name, self.include)[0]
88 inc = self.lookup(name, self.include)[0]
89 else:
89 else:
90 inc = name
90 inc = name
91 if self.exclude:
91 if self.exclude:
92 exc = self.lookup(name, self.exclude)[0]
92 exc = self.lookup(name, self.exclude)[0]
93 else:
93 else:
94 exc = ''
94 exc = ''
95 if (not self.include and exc) or (len(inc) <= len(exc)):
95 if (not self.include and exc) or (len(inc) <= len(exc)):
96 return None
96 return None
97 newpre, pre, suf = self.lookup(name, self.rename)
97 newpre, pre, suf = self.lookup(name, self.rename)
98 if newpre:
98 if newpre:
99 if newpre == '.':
99 if newpre == '.':
100 return suf
100 return suf
101 if suf:
101 if suf:
102 return newpre + '/' + suf
102 return newpre + '/' + suf
103 return newpre
103 return newpre
104 return name
104 return name
105
105
106 def active(self):
106 def active(self):
107 return bool(self.include or self.exclude or self.rename)
107 return bool(self.include or self.exclude or self.rename)
108
108
109 # This class does two additional things compared to a regular source:
109 # This class does two additional things compared to a regular source:
110 #
110 #
111 # - Filter and rename files. This is mostly wrapped by the filemapper
111 # - Filter and rename files. This is mostly wrapped by the filemapper
112 # class above. We hide the original filename in the revision that is
112 # class above. We hide the original filename in the revision that is
113 # returned by getchanges to be able to find things later in getfile.
113 # returned by getchanges to be able to find things later in getfile.
114 #
114 #
115 # - Return only revisions that matter for the files we're interested in.
115 # - Return only revisions that matter for the files we're interested in.
116 # This involves rewriting the parents of the original revision to
116 # This involves rewriting the parents of the original revision to
117 # create a graph that is restricted to those revisions.
117 # create a graph that is restricted to those revisions.
118 #
118 #
119 # This set of revisions includes not only revisions that directly
119 # This set of revisions includes not only revisions that directly
120 # touch files we're interested in, but also merges that merge two
120 # touch files we're interested in, but also merges that merge two
121 # or more interesting revisions.
121 # or more interesting revisions.
122
122
123 class filemap_source(converter_source):
123 class filemap_source(converter_source):
124 def __init__(self, ui, baseconverter, filemap):
124 def __init__(self, ui, baseconverter, filemap):
125 super(filemap_source, self).__init__(ui)
125 super(filemap_source, self).__init__(ui)
126 self.base = baseconverter
126 self.base = baseconverter
127 self.filemapper = filemapper(ui, filemap)
127 self.filemapper = filemapper(ui, filemap)
128 self.commits = {}
128 self.commits = {}
129 # if a revision rev has parent p in the original revision graph, then
129 # if a revision rev has parent p in the original revision graph, then
130 # rev will have parent self.parentmap[p] in the restricted graph.
130 # rev will have parent self.parentmap[p] in the restricted graph.
131 self.parentmap = {}
131 self.parentmap = {}
132 # self.wantedancestors[rev] is the set of all ancestors of rev that
132 # self.wantedancestors[rev] is the set of all ancestors of rev that
133 # are in the restricted graph.
133 # are in the restricted graph.
134 self.wantedancestors = {}
134 self.wantedancestors = {}
135 self.convertedorder = None
135 self.convertedorder = None
136 self._rebuilt = False
136 self._rebuilt = False
137 self.origparents = {}
137 self.origparents = {}
138 self.children = {}
138 self.children = {}
139 self.seenchildren = {}
139 self.seenchildren = {}
140
140
141 def before(self):
141 def before(self):
142 self.base.before()
142 self.base.before()
143
143
144 def after(self):
144 def after(self):
145 self.base.after()
145 self.base.after()
146
146
147 def setrevmap(self, revmap):
147 def setrevmap(self, revmap):
148 # rebuild our state to make things restartable
148 # rebuild our state to make things restartable
149 #
149 #
150 # To avoid calling getcommit for every revision that has already
150 # To avoid calling getcommit for every revision that has already
151 # been converted, we rebuild only the parentmap, delaying the
151 # been converted, we rebuild only the parentmap, delaying the
152 # rebuild of wantedancestors until we need it (i.e. until a
152 # rebuild of wantedancestors until we need it (i.e. until a
153 # merge).
153 # merge).
154 #
154 #
155 # We assume the order argument lists the revisions in
155 # We assume the order argument lists the revisions in
156 # topological order, so that we can infer which revisions were
156 # topological order, so that we can infer which revisions were
157 # wanted by previous runs.
157 # wanted by previous runs.
158 self._rebuilt = not revmap
158 self._rebuilt = not revmap
159 seen = {SKIPREV: SKIPREV}
159 seen = {SKIPREV: SKIPREV}
160 dummyset = set()
160 dummyset = set()
161 converted = []
161 converted = []
162 for rev in revmap.order:
162 for rev in revmap.order:
163 mapped = revmap[rev]
163 mapped = revmap[rev]
164 wanted = mapped not in seen
164 wanted = mapped not in seen
165 if wanted:
165 if wanted:
166 seen[mapped] = rev
166 seen[mapped] = rev
167 self.parentmap[rev] = rev
167 self.parentmap[rev] = rev
168 else:
168 else:
169 self.parentmap[rev] = seen[mapped]
169 self.parentmap[rev] = seen[mapped]
170 self.wantedancestors[rev] = dummyset
170 self.wantedancestors[rev] = dummyset
171 arg = seen[mapped]
171 arg = seen[mapped]
172 if arg == SKIPREV:
172 if arg == SKIPREV:
173 arg = None
173 arg = None
174 converted.append((rev, wanted, arg))
174 converted.append((rev, wanted, arg))
175 self.convertedorder = converted
175 self.convertedorder = converted
176 return self.base.setrevmap(revmap)
176 return self.base.setrevmap(revmap)
177
177
178 def rebuild(self):
178 def rebuild(self):
179 if self._rebuilt:
179 if self._rebuilt:
180 return True
180 return True
181 self._rebuilt = True
181 self._rebuilt = True
182 self.parentmap.clear()
182 self.parentmap.clear()
183 self.wantedancestors.clear()
183 self.wantedancestors.clear()
184 self.seenchildren.clear()
184 self.seenchildren.clear()
185 for rev, wanted, arg in self.convertedorder:
185 for rev, wanted, arg in self.convertedorder:
186 if rev not in self.origparents:
186 if rev not in self.origparents:
187 self.origparents[rev] = self.getcommit(rev).parents
187 self.origparents[rev] = self.getcommit(rev).parents
188 if arg is not None:
188 if arg is not None:
189 self.children[arg] = self.children.get(arg, 0) + 1
189 self.children[arg] = self.children.get(arg, 0) + 1
190
190
191 for rev, wanted, arg in self.convertedorder:
191 for rev, wanted, arg in self.convertedorder:
192 parents = self.origparents[rev]
192 parents = self.origparents[rev]
193 if wanted:
193 if wanted:
194 self.mark_wanted(rev, parents)
194 self.mark_wanted(rev, parents)
195 else:
195 else:
196 self.mark_not_wanted(rev, arg)
196 self.mark_not_wanted(rev, arg)
197 self._discard(arg, *parents)
197 self._discard(arg, *parents)
198
198
199 return True
199 return True
200
200
201 def getheads(self):
201 def getheads(self):
202 return self.base.getheads()
202 return self.base.getheads()
203
203
204 def getcommit(self, rev):
204 def getcommit(self, rev):
205 # We want to save a reference to the commit objects to be able
205 # We want to save a reference to the commit objects to be able
206 # to rewrite their parents later on.
206 # to rewrite their parents later on.
207 c = self.commits[rev] = self.base.getcommit(rev)
207 c = self.commits[rev] = self.base.getcommit(rev)
208 for p in c.parents:
208 for p in c.parents:
209 self.children[p] = self.children.get(p, 0) + 1
209 self.children[p] = self.children.get(p, 0) + 1
210 return c
210 return c
211
211
212 def _cachedcommit(self, rev):
213 if rev in self.commits:
214 return self.commits[rev]
215 return self.base.getcommit(rev)
216
212 def _discard(self, *revs):
217 def _discard(self, *revs):
213 for r in revs:
218 for r in revs:
214 if r is None:
219 if r is None:
215 continue
220 continue
216 self.seenchildren[r] = self.seenchildren.get(r, 0) + 1
221 self.seenchildren[r] = self.seenchildren.get(r, 0) + 1
217 if self.seenchildren[r] == self.children[r]:
222 if self.seenchildren[r] == self.children[r]:
218 del self.wantedancestors[r]
223 del self.wantedancestors[r]
219 del self.parentmap[r]
224 del self.parentmap[r]
220 del self.seenchildren[r]
225 del self.seenchildren[r]
221 if self._rebuilt:
226 if self._rebuilt:
222 del self.children[r]
227 del self.children[r]
223
228
224 def wanted(self, rev, i):
229 def wanted(self, rev, i):
225 # Return True if we're directly interested in rev.
230 # Return True if we're directly interested in rev.
226 #
231 #
227 # i is an index selecting one of the parents of rev (if rev
232 # i is an index selecting one of the parents of rev (if rev
228 # has no parents, i is None). getchangedfiles will give us
233 # has no parents, i is None). getchangedfiles will give us
229 # the list of files that are different in rev and in the parent
234 # the list of files that are different in rev and in the parent
230 # indicated by i. If we're interested in any of these files,
235 # indicated by i. If we're interested in any of these files,
231 # we're interested in rev.
236 # we're interested in rev.
232 try:
237 try:
233 files = self.base.getchangedfiles(rev, i)
238 files = self.base.getchangedfiles(rev, i)
234 except NotImplementedError:
239 except NotImplementedError:
235 raise util.Abort(_("source repository doesn't support --filemap"))
240 raise util.Abort(_("source repository doesn't support --filemap"))
236 for f in files:
241 for f in files:
237 if self.filemapper(f):
242 if self.filemapper(f):
238 return True
243 return True
239 return False
244 return False
240
245
241 def mark_not_wanted(self, rev, p):
246 def mark_not_wanted(self, rev, p):
242 # Mark rev as not interesting and update data structures.
247 # Mark rev as not interesting and update data structures.
243
248
244 if p is None:
249 if p is None:
245 # A root revision. Use SKIPREV to indicate that it doesn't
250 # A root revision. Use SKIPREV to indicate that it doesn't
246 # map to any revision in the restricted graph. Put SKIPREV
251 # map to any revision in the restricted graph. Put SKIPREV
247 # in the set of wanted ancestors to simplify code elsewhere
252 # in the set of wanted ancestors to simplify code elsewhere
248 self.parentmap[rev] = SKIPREV
253 self.parentmap[rev] = SKIPREV
249 self.wantedancestors[rev] = set((SKIPREV,))
254 self.wantedancestors[rev] = set((SKIPREV,))
250 return
255 return
251
256
252 # Reuse the data from our parent.
257 # Reuse the data from our parent.
253 self.parentmap[rev] = self.parentmap[p]
258 self.parentmap[rev] = self.parentmap[p]
254 self.wantedancestors[rev] = self.wantedancestors[p]
259 self.wantedancestors[rev] = self.wantedancestors[p]
255
260
256 def mark_wanted(self, rev, parents):
261 def mark_wanted(self, rev, parents):
257 # Mark rev ss wanted and update data structures.
262 # Mark rev ss wanted and update data structures.
258
263
259 # rev will be in the restricted graph, so children of rev in
264 # rev will be in the restricted graph, so children of rev in
260 # the original graph should still have rev as a parent in the
265 # the original graph should still have rev as a parent in the
261 # restricted graph.
266 # restricted graph.
262 self.parentmap[rev] = rev
267 self.parentmap[rev] = rev
263
268
264 # The set of wanted ancestors of rev is the union of the sets
269 # The set of wanted ancestors of rev is the union of the sets
265 # of wanted ancestors of its parents. Plus rev itself.
270 # of wanted ancestors of its parents. Plus rev itself.
266 wrev = set()
271 wrev = set()
267 for p in parents:
272 for p in parents:
268 wrev.update(self.wantedancestors[p])
273 wrev.update(self.wantedancestors[p])
269 wrev.add(rev)
274 wrev.add(rev)
270 self.wantedancestors[rev] = wrev
275 self.wantedancestors[rev] = wrev
271
276
272 def getchanges(self, rev):
277 def getchanges(self, rev):
273 parents = self.commits[rev].parents
278 parents = self.commits[rev].parents
274 if len(parents) > 1:
279 if len(parents) > 1:
275 self.rebuild()
280 self.rebuild()
276
281
277 # To decide whether we're interested in rev we:
282 # To decide whether we're interested in rev we:
278 #
283 #
279 # - calculate what parents rev will have if it turns out we're
284 # - calculate what parents rev will have if it turns out we're
280 # interested in it. If it's going to have more than 1 parent,
285 # interested in it. If it's going to have more than 1 parent,
281 # we're interested in it.
286 # we're interested in it.
282 #
287 #
283 # - otherwise, we'll compare it with the single parent we found.
288 # - otherwise, we'll compare it with the single parent we found.
284 # If any of the files we're interested in is different in the
289 # If any of the files we're interested in is different in the
285 # the two revisions, we're interested in rev.
290 # the two revisions, we're interested in rev.
286
291
287 # A parent p is interesting if its mapped version (self.parentmap[p]):
292 # A parent p is interesting if its mapped version (self.parentmap[p]):
288 # - is not SKIPREV
293 # - is not SKIPREV
289 # - is still not in the list of parents (we don't want duplicates)
294 # - is still not in the list of parents (we don't want duplicates)
290 # - is not an ancestor of the mapped versions of the other parents
295 # - is not an ancestor of the mapped versions of the other parents
291 mparents = []
296 mparents = []
292 wp = None
297 wp = None
293 for i, p1 in enumerate(parents):
298 for i, p1 in enumerate(parents):
294 mp1 = self.parentmap[p1]
299 mp1 = self.parentmap[p1]
295 if mp1 == SKIPREV or mp1 in mparents:
300 if mp1 == SKIPREV or mp1 in mparents:
296 continue
301 continue
297 for p2 in parents:
302 for p2 in parents:
298 if p1 == p2 or mp1 == self.parentmap[p2]:
303 if p1 == p2 or mp1 == self.parentmap[p2]:
299 continue
304 continue
300 if mp1 in self.wantedancestors[p2]:
305 if mp1 in self.wantedancestors[p2]:
301 break
306 break
302 else:
307 else:
303 mparents.append(mp1)
308 mparents.append(mp1)
304 wp = i
309 wp = i
305
310
306 if wp is None and parents:
311 if wp is None and parents:
307 wp = 0
312 wp = 0
308
313
309 self.origparents[rev] = parents
314 self.origparents[rev] = parents
310
315
311 closed = 'close' in self.commits[rev].extra
316 closed = False
317 if 'close' in self.commits[rev].extra:
318 # A branch closing revision is only useful if one of its
319 # parents belong to the branch being closed
320 branch = self.commits[rev].branch
321 pbranches = [self._cachedcommit(p).branch for p in mparents]
322 if branch in pbranches:
323 closed = True
312
324
313 if len(mparents) < 2 and not closed and not self.wanted(rev, wp):
325 if len(mparents) < 2 and not closed and not self.wanted(rev, wp):
314 # We don't want this revision.
326 # We don't want this revision.
315 # Update our state and tell the convert process to map this
327 # Update our state and tell the convert process to map this
316 # revision to the same revision its parent as mapped to.
328 # revision to the same revision its parent as mapped to.
317 p = None
329 p = None
318 if parents:
330 if parents:
319 p = parents[wp]
331 p = parents[wp]
320 self.mark_not_wanted(rev, p)
332 self.mark_not_wanted(rev, p)
321 self.convertedorder.append((rev, False, p))
333 self.convertedorder.append((rev, False, p))
322 self._discard(*parents)
334 self._discard(*parents)
323 return self.parentmap[rev]
335 return self.parentmap[rev]
324
336
325 # We want this revision.
337 # We want this revision.
326 # Rewrite the parents of the commit object
338 # Rewrite the parents of the commit object
327 self.commits[rev].parents = mparents
339 self.commits[rev].parents = mparents
328 self.mark_wanted(rev, parents)
340 self.mark_wanted(rev, parents)
329 self.convertedorder.append((rev, True, None))
341 self.convertedorder.append((rev, True, None))
330 self._discard(*parents)
342 self._discard(*parents)
331
343
332 # Get the real changes and do the filtering/mapping. To be
344 # Get the real changes and do the filtering/mapping. To be
333 # able to get the files later on in getfile, we hide the
345 # able to get the files later on in getfile, we hide the
334 # original filename in the rev part of the return value.
346 # original filename in the rev part of the return value.
335 changes, copies = self.base.getchanges(rev)
347 changes, copies = self.base.getchanges(rev)
336 newnames = {}
348 newnames = {}
337 files = []
349 files = []
338 for f, r in changes:
350 for f, r in changes:
339 newf = self.filemapper(f)
351 newf = self.filemapper(f)
340 if newf:
352 if newf:
341 files.append((newf, (f, r)))
353 files.append((newf, (f, r)))
342 newnames[f] = newf
354 newnames[f] = newf
343
355
344 ncopies = {}
356 ncopies = {}
345 for c in copies:
357 for c in copies:
346 newc = self.filemapper(c)
358 newc = self.filemapper(c)
347 if newc:
359 if newc:
348 newsource = self.filemapper(copies[c])
360 newsource = self.filemapper(copies[c])
349 if newsource:
361 if newsource:
350 ncopies[newc] = newsource
362 ncopies[newc] = newsource
351
363
352 return files, ncopies
364 return files, ncopies
353
365
354 def getfile(self, name, rev):
366 def getfile(self, name, rev):
355 realname, realrev = rev
367 realname, realrev = rev
356 return self.base.getfile(realname, realrev)
368 return self.base.getfile(realname, realrev)
357
369
358 def gettags(self):
370 def gettags(self):
359 return self.base.gettags()
371 return self.base.gettags()
360
372
361 def hasnativeorder(self):
373 def hasnativeorder(self):
362 return self.base.hasnativeorder()
374 return self.base.hasnativeorder()
363
375
364 def lookuprev(self, rev):
376 def lookuprev(self, rev):
365 return self.base.lookuprev(rev)
377 return self.base.lookuprev(rev)
@@ -1,284 +1,364
1
1
2 $ HGMERGE=true; export HGMERGE
2 $ HGMERGE=true; export HGMERGE
3 $ echo '[extensions]' >> $HGRCPATH
3 $ echo '[extensions]' >> $HGRCPATH
4 $ echo 'graphlog =' >> $HGRCPATH
4 $ echo 'graphlog =' >> $HGRCPATH
5 $ echo 'convert =' >> $HGRCPATH
5 $ echo 'convert =' >> $HGRCPATH
6 $ glog()
6 $ glog()
7 > {
7 > {
8 > hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
8 > hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
9 > }
9 > }
10 $ hg init source
10 $ hg init source
11 $ cd source
11 $ cd source
12 $ echo foo > foo
12 $ echo foo > foo
13 $ echo baz > baz
13 $ echo baz > baz
14 $ mkdir -p dir/subdir
14 $ mkdir -p dir/subdir
15 $ echo dir/file >> dir/file
15 $ echo dir/file >> dir/file
16 $ echo dir/file2 >> dir/file2
16 $ echo dir/file2 >> dir/file2
17 $ echo dir/subdir/file3 >> dir/subdir/file3
17 $ echo dir/subdir/file3 >> dir/subdir/file3
18 $ echo dir/subdir/file4 >> dir/subdir/file4
18 $ echo dir/subdir/file4 >> dir/subdir/file4
19 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
19 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
20 $ echo bar > bar
20 $ echo bar > bar
21 $ echo quux > quux
21 $ echo quux > quux
22 $ hg copy foo copied
22 $ hg copy foo copied
23 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
23 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
24 $ echo >> foo
24 $ echo >> foo
25 $ hg ci -d '2 0' -m '2: change foo'
25 $ hg ci -d '2 0' -m '2: change foo'
26 $ hg up -qC 1
26 $ hg up -qC 1
27 $ echo >> bar
27 $ echo >> bar
28 $ echo >> quux
28 $ echo >> quux
29 $ hg ci -d '3 0' -m '3: change bar quux'
29 $ hg ci -d '3 0' -m '3: change bar quux'
30 created new head
30 created new head
31 $ hg up -qC 2
31 $ hg up -qC 2
32 $ hg merge -qr 3
32 $ hg merge -qr 3
33 $ echo >> bar
33 $ echo >> bar
34 $ echo >> baz
34 $ echo >> baz
35 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
35 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
36 $ echo >> bar
36 $ echo >> bar
37 $ echo 1 >> baz
37 $ echo 1 >> baz
38 $ echo >> quux
38 $ echo >> quux
39 $ hg ci -d '5 0' -m '5: change bar baz quux'
39 $ hg ci -d '5 0' -m '5: change bar baz quux'
40 $ hg up -qC 4
40 $ hg up -qC 4
41 $ echo >> foo
41 $ echo >> foo
42 $ echo 2 >> baz
42 $ echo 2 >> baz
43 $ hg ci -d '6 0' -m '6: change foo baz'
43 $ hg ci -d '6 0' -m '6: change foo baz'
44 created new head
44 created new head
45 $ hg up -qC 5
45 $ hg up -qC 5
46 $ hg merge -qr 6
46 $ hg merge -qr 6
47 $ echo >> bar
47 $ echo >> bar
48 $ hg ci -d '7 0' -m '7: second merge; change bar'
48 $ hg ci -d '7 0' -m '7: second merge; change bar'
49 $ echo >> foo
49 $ echo >> foo
50 $ hg ci -m '8: change foo'
50 $ hg ci -m '8: change foo'
51 $ glog
51 $ glog
52 @ 8 "8: change foo" files: foo
52 @ 8 "8: change foo" files: foo
53 |
53 |
54 o 7 "7: second merge; change bar" files: bar baz
54 o 7 "7: second merge; change bar" files: bar baz
55 |\
55 |\
56 | o 6 "6: change foo baz" files: baz foo
56 | o 6 "6: change foo baz" files: baz foo
57 | |
57 | |
58 o | 5 "5: change bar baz quux" files: bar baz quux
58 o | 5 "5: change bar baz quux" files: bar baz quux
59 |/
59 |/
60 o 4 "4: first merge; change bar baz" files: bar baz
60 o 4 "4: first merge; change bar baz" files: bar baz
61 |\
61 |\
62 | o 3 "3: change bar quux" files: bar quux
62 | o 3 "3: change bar quux" files: bar quux
63 | |
63 | |
64 o | 2 "2: change foo" files: foo
64 o | 2 "2: change foo" files: foo
65 |/
65 |/
66 o 1 "1: add bar quux; copy foo to copied" files: bar copied quux
66 o 1 "1: add bar quux; copy foo to copied" files: bar copied quux
67 |
67 |
68 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/subdir/file3 dir/subdir/file4 foo
68 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/subdir/file3 dir/subdir/file4 foo
69
69
70
70
71 final file versions in this repo:
71 final file versions in this repo:
72
72
73 $ hg manifest --debug
73 $ hg manifest --debug
74 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
74 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
75 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
75 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
76 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
76 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
77 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
77 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
78 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
78 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
79 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
79 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
80 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
80 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
81 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
81 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
82 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
82 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
83 $ hg debugrename copied
83 $ hg debugrename copied
84 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
84 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
85 $ echo
85 $ echo
86
86
87 $ cd ..
87 $ cd ..
88 $ splitrepo()
88 $ splitrepo()
89 > {
89 > {
90 > msg="$1"
90 > msg="$1"
91 > files="$2"
91 > files="$2"
92 > opts=$3
92 > opts=$3
93 > echo "% $files: $msg"
93 > echo "% $files: $msg"
94 > prefix=`echo "$files" | sed -e 's/ /-/g'`
94 > prefix=`echo "$files" | sed -e 's/ /-/g'`
95 > fmap="$prefix.fmap"
95 > fmap="$prefix.fmap"
96 > repo="$prefix.repo"
96 > repo="$prefix.repo"
97 > for i in $files; do
97 > for i in $files; do
98 > echo "include $i" >> "$fmap"
98 > echo "include $i" >> "$fmap"
99 > done
99 > done
100 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
100 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
101 > hg up -q -R "$repo"
101 > hg up -q -R "$repo"
102 > glog -R "$repo"
102 > glog -R "$repo"
103 > hg -R "$repo" manifest --debug
103 > hg -R "$repo" manifest --debug
104 > }
104 > }
105 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
105 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
106 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
106 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
107 @ 3 "8: change foo" files: foo
107 @ 3 "8: change foo" files: foo
108 |
108 |
109 o 2 "6: change foo baz" files: foo
109 o 2 "6: change foo baz" files: foo
110 |
110 |
111 o 1 "2: change foo" files: foo
111 o 1 "2: change foo" files: foo
112 |
112 |
113 o 0 "0: add foo baz dir/" files: foo
113 o 0 "0: add foo baz dir/" files: foo
114
114
115 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
115 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
116 $ splitrepo 'merges are not merges anymore' bar
116 $ splitrepo 'merges are not merges anymore' bar
117 % bar: merges are not merges anymore
117 % bar: merges are not merges anymore
118 @ 4 "7: second merge; change bar" files: bar
118 @ 4 "7: second merge; change bar" files: bar
119 |
119 |
120 o 3 "5: change bar baz quux" files: bar
120 o 3 "5: change bar baz quux" files: bar
121 |
121 |
122 o 2 "4: first merge; change bar baz" files: bar
122 o 2 "4: first merge; change bar baz" files: bar
123 |
123 |
124 o 1 "3: change bar quux" files: bar
124 o 1 "3: change bar quux" files: bar
125 |
125 |
126 o 0 "1: add bar quux; copy foo to copied" files: bar
126 o 0 "1: add bar quux; copy foo to copied" files: bar
127
127
128 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
128 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
129 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
129 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
130 % baz: 1st merge is not a merge anymore; 2nd still is
130 % baz: 1st merge is not a merge anymore; 2nd still is
131 @ 4 "7: second merge; change bar" files: baz
131 @ 4 "7: second merge; change bar" files: baz
132 |\
132 |\
133 | o 3 "6: change foo baz" files: baz
133 | o 3 "6: change foo baz" files: baz
134 | |
134 | |
135 o | 2 "5: change bar baz quux" files: baz
135 o | 2 "5: change bar baz quux" files: baz
136 |/
136 |/
137 o 1 "4: first merge; change bar baz" files: baz
137 o 1 "4: first merge; change bar baz" files: baz
138 |
138 |
139 o 0 "0: add foo baz dir/" files: baz
139 o 0 "0: add foo baz dir/" files: baz
140
140
141 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
141 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
142 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
142 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
143 % foo quux: we add additional merges when they are interesting
143 % foo quux: we add additional merges when they are interesting
144 @ 8 "8: change foo" files: foo
144 @ 8 "8: change foo" files: foo
145 |
145 |
146 o 7 "7: second merge; change bar" files:
146 o 7 "7: second merge; change bar" files:
147 |\
147 |\
148 | o 6 "6: change foo baz" files: foo
148 | o 6 "6: change foo baz" files: foo
149 | |
149 | |
150 o | 5 "5: change bar baz quux" files: quux
150 o | 5 "5: change bar baz quux" files: quux
151 |/
151 |/
152 o 4 "4: first merge; change bar baz" files:
152 o 4 "4: first merge; change bar baz" files:
153 |\
153 |\
154 | o 3 "3: change bar quux" files: quux
154 | o 3 "3: change bar quux" files: quux
155 | |
155 | |
156 o | 2 "2: change foo" files: foo
156 o | 2 "2: change foo" files: foo
157 |/
157 |/
158 o 1 "1: add bar quux; copy foo to copied" files: quux
158 o 1 "1: add bar quux; copy foo to copied" files: quux
159 |
159 |
160 o 0 "0: add foo baz dir/" files: foo
160 o 0 "0: add foo baz dir/" files: foo
161
161
162 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
162 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
163 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
163 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
164 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
164 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
165 % bar quux: partial conversion
165 % bar quux: partial conversion
166 @ 1 "3: change bar quux" files: bar quux
166 @ 1 "3: change bar quux" files: bar quux
167 |
167 |
168 o 0 "1: add bar quux; copy foo to copied" files: bar quux
168 o 0 "1: add bar quux; copy foo to copied" files: bar quux
169
169
170 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
170 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
171 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
171 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
172 $ splitrepo 'complete the partial conversion' 'bar quux'
172 $ splitrepo 'complete the partial conversion' 'bar quux'
173 % bar quux: complete the partial conversion
173 % bar quux: complete the partial conversion
174 @ 4 "7: second merge; change bar" files: bar
174 @ 4 "7: second merge; change bar" files: bar
175 |
175 |
176 o 3 "5: change bar baz quux" files: bar quux
176 o 3 "5: change bar baz quux" files: bar quux
177 |
177 |
178 o 2 "4: first merge; change bar baz" files: bar
178 o 2 "4: first merge; change bar baz" files: bar
179 |
179 |
180 o 1 "3: change bar quux" files: bar quux
180 o 1 "3: change bar quux" files: bar quux
181 |
181 |
182 o 0 "1: add bar quux; copy foo to copied" files: bar quux
182 o 0 "1: add bar quux; copy foo to copied" files: bar quux
183
183
184 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
184 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
185 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
185 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
186 $ rm -r foo.repo
186 $ rm -r foo.repo
187 $ splitrepo 'partial conversion' 'foo' '-r 3'
187 $ splitrepo 'partial conversion' 'foo' '-r 3'
188 % foo: partial conversion
188 % foo: partial conversion
189 @ 0 "0: add foo baz dir/" files: foo
189 @ 0 "0: add foo baz dir/" files: foo
190
190
191 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
191 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
192 $ splitrepo 'complete the partial conversion' 'foo'
192 $ splitrepo 'complete the partial conversion' 'foo'
193 % foo: complete the partial conversion
193 % foo: complete the partial conversion
194 @ 3 "8: change foo" files: foo
194 @ 3 "8: change foo" files: foo
195 |
195 |
196 o 2 "6: change foo baz" files: foo
196 o 2 "6: change foo baz" files: foo
197 |
197 |
198 o 1 "2: change foo" files: foo
198 o 1 "2: change foo" files: foo
199 |
199 |
200 o 0 "0: add foo baz dir/" files: foo
200 o 0 "0: add foo baz dir/" files: foo
201
201
202 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
202 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
203 $ splitrepo 'copied file; source not included in new repo' copied
203 $ splitrepo 'copied file; source not included in new repo' copied
204 % copied: copied file; source not included in new repo
204 % copied: copied file; source not included in new repo
205 @ 0 "1: add bar quux; copy foo to copied" files: copied
205 @ 0 "1: add bar quux; copy foo to copied" files: copied
206
206
207 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
207 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
208 $ hg --cwd copied.repo debugrename copied
208 $ hg --cwd copied.repo debugrename copied
209 copied not renamed
209 copied not renamed
210 $ splitrepo 'copied file; source included in new repo' 'foo copied'
210 $ splitrepo 'copied file; source included in new repo' 'foo copied'
211 % foo copied: copied file; source included in new repo
211 % foo copied: copied file; source included in new repo
212 @ 4 "8: change foo" files: foo
212 @ 4 "8: change foo" files: foo
213 |
213 |
214 o 3 "6: change foo baz" files: foo
214 o 3 "6: change foo baz" files: foo
215 |
215 |
216 o 2 "2: change foo" files: foo
216 o 2 "2: change foo" files: foo
217 |
217 |
218 o 1 "1: add bar quux; copy foo to copied" files: copied
218 o 1 "1: add bar quux; copy foo to copied" files: copied
219 |
219 |
220 o 0 "0: add foo baz dir/" files: foo
220 o 0 "0: add foo baz dir/" files: foo
221
221
222 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
222 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
223 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
223 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
224 $ hg --cwd foo-copied.repo debugrename copied
224 $ hg --cwd foo-copied.repo debugrename copied
225 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
225 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
226 $ cat > renames.fmap <<EOF
226 $ cat > renames.fmap <<EOF
227 > include dir
227 > include dir
228 > exclude dir/file2
228 > exclude dir/file2
229 > rename dir dir2
229 > rename dir dir2
230 > include foo
230 > include foo
231 > include copied
231 > include copied
232 > rename foo foo2
232 > rename foo foo2
233 > rename copied copied2
233 > rename copied copied2
234 > exclude dir/subdir
234 > exclude dir/subdir
235 > include dir/subdir/file3
235 > include dir/subdir/file3
236 > EOF
236 > EOF
237 $ hg -q convert --filemap renames.fmap --datesort source renames.repo
237 $ hg -q convert --filemap renames.fmap --datesort source renames.repo
238 $ hg up -q -R renames.repo
238 $ hg up -q -R renames.repo
239 $ glog -R renames.repo
239 $ glog -R renames.repo
240 @ 4 "8: change foo" files: foo2
240 @ 4 "8: change foo" files: foo2
241 |
241 |
242 o 3 "6: change foo baz" files: foo2
242 o 3 "6: change foo baz" files: foo2
243 |
243 |
244 o 2 "2: change foo" files: foo2
244 o 2 "2: change foo" files: foo2
245 |
245 |
246 o 1 "1: add bar quux; copy foo to copied" files: copied2
246 o 1 "1: add bar quux; copy foo to copied" files: copied2
247 |
247 |
248 o 0 "0: add foo baz dir/" files: dir2/file dir2/subdir/file3 foo2
248 o 0 "0: add foo baz dir/" files: dir2/file dir2/subdir/file3 foo2
249
249
250 $ hg -R renames.repo manifest --debug
250 $ hg -R renames.repo manifest --debug
251 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
251 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
252 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/file
252 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/file
253 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/subdir/file3
253 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/subdir/file3
254 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
254 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
255 $ hg --cwd renames.repo debugrename copied2
255 $ hg --cwd renames.repo debugrename copied2
256 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
256 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
257
257
258 copied:
258 copied:
259
259
260 $ hg --cwd source cat copied
260 $ hg --cwd source cat copied
261 foo
261 foo
262
262
263 copied2:
263 copied2:
264
264
265 $ hg --cwd renames.repo cat copied2
265 $ hg --cwd renames.repo cat copied2
266 foo
266 foo
267
267
268 filemap errors
268 filemap errors
269
269
270 $ cat > errors.fmap <<EOF
270 $ cat > errors.fmap <<EOF
271 > include dir/ # beware that comments changes error line numbers!
271 > include dir/ # beware that comments changes error line numbers!
272 > exclude /dir
272 > exclude /dir
273 > rename dir//dir /dir//dir/ "out of sync"
273 > rename dir//dir /dir//dir/ "out of sync"
274 > include
274 > include
275 > EOF
275 > EOF
276 $ hg -q convert --filemap errors.fmap source errors.repo
276 $ hg -q convert --filemap errors.fmap source errors.repo
277 errors.fmap:1: superfluous / in exclude 'dir/'
277 errors.fmap:1: superfluous / in exclude 'dir/'
278 errors.fmap:3: superfluous / in include '/dir'
278 errors.fmap:3: superfluous / in include '/dir'
279 errors.fmap:3: superfluous / in rename '/dir'
279 errors.fmap:3: superfluous / in rename '/dir'
280 errors.fmap:3: superfluous / in exclude 'dir//dir'
280 errors.fmap:3: superfluous / in exclude 'dir//dir'
281 errors.fmap:4: unknown directive 'out of sync'
281 errors.fmap:4: unknown directive 'out of sync'
282 errors.fmap:5: path to exclude is missing
282 errors.fmap:5: path to exclude is missing
283 abort: errors in filemap
283 abort: errors in filemap
284 [255]
284 [255]
285
286 test branch closing revision pruning if branch is pruned
287
288 $ hg init branchpruning
289 $ cd branchpruning
290 $ hg branch foo
291 marked working directory as branch foo
292 $ echo a > a
293 $ hg ci -Am adda
294 adding a
295 $ hg ci --close-branch -m closefoo
296 $ hg up 0
297 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
298 $ hg branch empty
299 marked working directory as branch empty
300 $ hg ci -m emptybranch
301 $ hg ci --close-branch -m closeempty
302 $ hg up 0
303 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
304 $ hg branch default
305 marked working directory as branch default
306 $ echo b > b
307 $ hg ci -Am addb
308 adding b
309 $ hg ci --close-branch -m closedefault
310 $ cat > filemap <<EOF
311 > include b
312 > EOF
313 $ cd ..
314 $ hg convert branchpruning branchpruning-hg1
315 initializing destination branchpruning-hg1 repository
316 scanning source...
317 sorting...
318 converting...
319 5 adda
320 4 closefoo
321 3 emptybranch
322 2 closeempty
323 1 addb
324 0 closedefault
325 $ glog -R branchpruning-hg1
326 o 5 "closedefault" files:
327 |
328 o 4 "addb" files: b
329 |
330 | o 3 "closeempty" files:
331 | |
332 | o 2 "emptybranch" files:
333 |/
334 | o 1 "closefoo" files:
335 |/
336 o 0 "adda" files: a
337
338
339 exercise incremental conversion at the same time
340
341 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
342 initializing destination branchpruning-hg2 repository
343 scanning source...
344 sorting...
345 converting...
346 0 adda
347 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
348 scanning source...
349 sorting...
350 converting...
351 0 addb
352 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
353 scanning source...
354 sorting...
355 converting...
356 3 closefoo
357 2 emptybranch
358 1 closeempty
359 0 closedefault
360 $ glog -R branchpruning-hg2
361 o 1 "closedefault" files:
362 |
363 o 0 "addb" files: b
364
@@ -1,145 +1,139
1
1
2 $ cat >> $HGRCPATH <<EOF
2 $ cat >> $HGRCPATH <<EOF
3 > [extensions]
3 > [extensions]
4 > convert=
4 > convert=
5 > [convert]
5 > [convert]
6 > hg.saverev=False
6 > hg.saverev=False
7 > EOF
7 > EOF
8 $ hg init orig
8 $ hg init orig
9 $ cd orig
9 $ cd orig
10 $ echo foo > foo
10 $ echo foo > foo
11 $ echo bar > bar
11 $ echo bar > bar
12 $ hg ci -qAm 'add foo bar' -d '0 0'
12 $ hg ci -qAm 'add foo bar' -d '0 0'
13 $ echo >> foo
13 $ echo >> foo
14 $ hg ci -m 'change foo' -d '1 0'
14 $ hg ci -m 'change foo' -d '1 0'
15 $ hg up -qC 0
15 $ hg up -qC 0
16 $ hg copy --after --force foo bar
16 $ hg copy --after --force foo bar
17 $ hg copy foo baz
17 $ hg copy foo baz
18 $ hg ci -m 'make bar and baz copies of foo' -d '2 0'
18 $ hg ci -m 'make bar and baz copies of foo' -d '2 0'
19 created new head
19 created new head
20 $ hg bookmark premerge1
20 $ hg bookmark premerge1
21 $ hg merge
21 $ hg merge
22 merging baz and foo to baz
22 merging baz and foo to baz
23 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
23 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
24 (branch merge, don't forget to commit)
24 (branch merge, don't forget to commit)
25 $ hg ci -m 'merge local copy' -d '3 0'
25 $ hg ci -m 'merge local copy' -d '3 0'
26 $ hg up -C 1
26 $ hg up -C 1
27 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
27 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
28 $ hg bookmark premerge2
28 $ hg bookmark premerge2
29 $ hg merge 2
29 $ hg merge 2
30 merging foo and baz to baz
30 merging foo and baz to baz
31 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
31 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
32 (branch merge, don't forget to commit)
32 (branch merge, don't forget to commit)
33 $ hg ci -m 'merge remote copy' -d '4 0'
33 $ hg ci -m 'merge remote copy' -d '4 0'
34 created new head
34 created new head
35 $ chmod +x baz
35 $ chmod +x baz
36 $ hg ci -m 'mark baz executable' -d '5 0'
36 $ hg ci -m 'mark baz executable' -d '5 0'
37 $ hg branch foo
38 marked working directory as branch foo
39 $ hg ci -m 'branch foo' -d '6 0'
40 $ hg ci --close-branch -m 'close' -d '7 0'
41 $ cd ..
37 $ cd ..
42 $ hg convert --datesort orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
38 $ hg convert --datesort orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
43 initializing destination new repository
39 initializing destination new repository
44 scanning source...
40 scanning source...
45 sorting...
41 sorting...
46 converting...
42 converting...
47 7 add foo bar
43 5 add foo bar
48 6 change foo
44 4 change foo
49 5 make bar and baz copies of foo
45 3 make bar and baz copies of foo
50 4 merge local copy
46 2 merge local copy
51 3 merge remote copy
47 1 merge remote copy
52 2 mark baz executable
48 0 mark baz executable
53 1 branch foo
54 0 close
55 updating bookmarks
49 updating bookmarks
56 $ cd new
50 $ cd new
57 $ hg out ../orig
51 $ hg out ../orig
58 comparing with ../orig
52 comparing with ../orig
59 searching for changes
53 searching for changes
60 no changes found
54 no changes found
61 [1]
55 [1]
62 $ hg bookmarks
56 $ hg bookmarks
63 premerge1 3:973ef48a98a4
57 premerge1 3:973ef48a98a4
64 premerge2 7:0d18d1112f1d
58 premerge2 5:13d9b87cf8f8
65 $ cd ..
59 $ cd ..
66
60
67 check shamap LF and CRLF handling
61 check shamap LF and CRLF handling
68
62
69 $ cat > rewrite.py <<EOF
63 $ cat > rewrite.py <<EOF
70 > import sys
64 > import sys
71 > # Interlace LF and CRLF
65 > # Interlace LF and CRLF
72 > lines = [(l.rstrip() + ((i % 2) and '\n' or '\r\n'))
66 > lines = [(l.rstrip() + ((i % 2) and '\n' or '\r\n'))
73 > for i, l in enumerate(file(sys.argv[1]))]
67 > for i, l in enumerate(file(sys.argv[1]))]
74 > file(sys.argv[1], 'wb').write(''.join(lines))
68 > file(sys.argv[1], 'wb').write(''.join(lines))
75 > EOF
69 > EOF
76 $ python rewrite.py new/.hg/shamap
70 $ python rewrite.py new/.hg/shamap
77 $ cd orig
71 $ cd orig
78 $ hg up -qC 1
72 $ hg up -qC 1
79 $ echo foo >> foo
73 $ echo foo >> foo
80 $ hg ci -qm 'change foo again'
74 $ hg ci -qm 'change foo again'
81 $ hg up -qC 2
75 $ hg up -qC 2
82 $ echo foo >> foo
76 $ echo foo >> foo
83 $ hg ci -qm 'change foo again again'
77 $ hg ci -qm 'change foo again again'
84 $ cd ..
78 $ cd ..
85 $ hg convert --datesort orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
79 $ hg convert --datesort orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
86 scanning source...
80 scanning source...
87 sorting...
81 sorting...
88 converting...
82 converting...
89 1 change foo again again
83 1 change foo again again
90 0 change foo again
84 0 change foo again
91 updating bookmarks
85 updating bookmarks
92
86
93 init broken repository
87 init broken repository
94
88
95 $ hg init broken
89 $ hg init broken
96 $ cd broken
90 $ cd broken
97 $ echo a >> a
91 $ echo a >> a
98 $ echo b >> b
92 $ echo b >> b
99 $ hg ci -qAm init
93 $ hg ci -qAm init
100 $ echo a >> a
94 $ echo a >> a
101 $ echo b >> b
95 $ echo b >> b
102 $ hg copy b c
96 $ hg copy b c
103 $ hg ci -qAm changeall
97 $ hg ci -qAm changeall
104 $ hg up -qC 0
98 $ hg up -qC 0
105 $ echo bc >> b
99 $ echo bc >> b
106 $ hg ci -m changebagain
100 $ hg ci -m changebagain
107 created new head
101 created new head
108 $ HGMERGE=internal:local hg -q merge
102 $ HGMERGE=internal:local hg -q merge
109 $ hg ci -m merge
103 $ hg ci -m merge
110 $ hg mv b d
104 $ hg mv b d
111 $ hg ci -m moveb
105 $ hg ci -m moveb
112
106
113 break it
107 break it
114
108
115 $ rm .hg/store/data/b.*
109 $ rm .hg/store/data/b.*
116 $ cd ..
110 $ cd ..
117 $ hg --config convert.hg.ignoreerrors=True convert broken fixed
111 $ hg --config convert.hg.ignoreerrors=True convert broken fixed
118 initializing destination fixed repository
112 initializing destination fixed repository
119 scanning source...
113 scanning source...
120 sorting...
114 sorting...
121 converting...
115 converting...
122 4 init
116 4 init
123 ignoring: data/b.i@1e88685f5dde: no match found
117 ignoring: data/b.i@1e88685f5dde: no match found
124 3 changeall
118 3 changeall
125 2 changebagain
119 2 changebagain
126 1 merge
120 1 merge
127 0 moveb
121 0 moveb
128 $ hg -R fixed verify
122 $ hg -R fixed verify
129 checking changesets
123 checking changesets
130 checking manifests
124 checking manifests
131 crosschecking files in changesets and manifests
125 crosschecking files in changesets and manifests
132 checking files
126 checking files
133 3 files, 5 changesets, 5 total revisions
127 3 files, 5 changesets, 5 total revisions
134
128
135 manifest -r 0
129 manifest -r 0
136
130
137 $ hg -R fixed manifest -r 0
131 $ hg -R fixed manifest -r 0
138 a
132 a
139
133
140 manifest -r tip
134 manifest -r tip
141
135
142 $ hg -R fixed manifest -r tip
136 $ hg -R fixed manifest -r tip
143 a
137 a
144 c
138 c
145 d
139 d
General Comments 0
You need to be logged in to leave comments. Login now