##// END OF EJS Templates
convert: fix crash when existing converted revision didn't come from source...
Mads Kiilerich -
r19863:daeab82f default
parent child Browse files
Show More
@@ -1,404 +1,411
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 posixpath
7 import posixpath
8 import shlex
8 import shlex
9 from mercurial.i18n import _
9 from mercurial.i18n import _
10 from mercurial import util
10 from mercurial import util, error
11 from common import SKIPREV, converter_source
11 from common import SKIPREV, converter_source
12
12
13 def rpairs(name):
13 def rpairs(name):
14 e = len(name)
14 e = len(name)
15 while e != -1:
15 while e != -1:
16 yield name[:e], name[e + 1:]
16 yield name[:e], name[e + 1:]
17 e = name.rfind('/', 0, e)
17 e = name.rfind('/', 0, e)
18 yield '.', name
18 yield '.', name
19
19
20 def normalize(path):
20 def normalize(path):
21 ''' We use posixpath.normpath to support cross-platform path format.
21 ''' We use posixpath.normpath to support cross-platform path format.
22 However, it doesn't handle None input. So we wrap it up. '''
22 However, it doesn't handle None input. So we wrap it up. '''
23 if path is None:
23 if path is None:
24 return None
24 return None
25 return posixpath.normpath(path)
25 return posixpath.normpath(path)
26
26
27 class filemapper(object):
27 class filemapper(object):
28 '''Map and filter filenames when importing.
28 '''Map and filter filenames when importing.
29 A name can be mapped to itself, a new name, or None (omit from new
29 A name can be mapped to itself, a new name, or None (omit from new
30 repository).'''
30 repository).'''
31
31
32 def __init__(self, ui, path=None):
32 def __init__(self, ui, path=None):
33 self.ui = ui
33 self.ui = ui
34 self.include = {}
34 self.include = {}
35 self.exclude = {}
35 self.exclude = {}
36 self.rename = {}
36 self.rename = {}
37 if path:
37 if path:
38 if self.parse(path):
38 if self.parse(path):
39 raise util.Abort(_('errors in filemap'))
39 raise util.Abort(_('errors in filemap'))
40
40
41 def parse(self, path):
41 def parse(self, path):
42 errs = 0
42 errs = 0
43 def check(name, mapping, listname):
43 def check(name, mapping, listname):
44 if not name:
44 if not name:
45 self.ui.warn(_('%s:%d: path to %s is missing\n') %
45 self.ui.warn(_('%s:%d: path to %s is missing\n') %
46 (lex.infile, lex.lineno, listname))
46 (lex.infile, lex.lineno, listname))
47 return 1
47 return 1
48 if name in mapping:
48 if name in mapping:
49 self.ui.warn(_('%s:%d: %r already in %s list\n') %
49 self.ui.warn(_('%s:%d: %r already in %s list\n') %
50 (lex.infile, lex.lineno, name, listname))
50 (lex.infile, lex.lineno, name, listname))
51 return 1
51 return 1
52 if (name.startswith('/') or
52 if (name.startswith('/') or
53 name.endswith('/') or
53 name.endswith('/') or
54 '//' in name):
54 '//' in name):
55 self.ui.warn(_('%s:%d: superfluous / in %s %r\n') %
55 self.ui.warn(_('%s:%d: superfluous / in %s %r\n') %
56 (lex.infile, lex.lineno, listname, name))
56 (lex.infile, lex.lineno, listname, name))
57 return 1
57 return 1
58 return 0
58 return 0
59 lex = shlex.shlex(open(path), path, True)
59 lex = shlex.shlex(open(path), path, True)
60 lex.wordchars += '!@#$%^&*()-=+[]{}|;:,./<>?'
60 lex.wordchars += '!@#$%^&*()-=+[]{}|;:,./<>?'
61 cmd = lex.get_token()
61 cmd = lex.get_token()
62 while cmd:
62 while cmd:
63 if cmd == 'include':
63 if cmd == 'include':
64 name = normalize(lex.get_token())
64 name = normalize(lex.get_token())
65 errs += check(name, self.exclude, 'exclude')
65 errs += check(name, self.exclude, 'exclude')
66 self.include[name] = name
66 self.include[name] = name
67 elif cmd == 'exclude':
67 elif cmd == 'exclude':
68 name = normalize(lex.get_token())
68 name = normalize(lex.get_token())
69 errs += check(name, self.include, 'include')
69 errs += check(name, self.include, 'include')
70 errs += check(name, self.rename, 'rename')
70 errs += check(name, self.rename, 'rename')
71 self.exclude[name] = name
71 self.exclude[name] = name
72 elif cmd == 'rename':
72 elif cmd == 'rename':
73 src = normalize(lex.get_token())
73 src = normalize(lex.get_token())
74 dest = normalize(lex.get_token())
74 dest = normalize(lex.get_token())
75 errs += check(src, self.exclude, 'exclude')
75 errs += check(src, self.exclude, 'exclude')
76 self.rename[src] = dest
76 self.rename[src] = dest
77 elif cmd == 'source':
77 elif cmd == 'source':
78 errs += self.parse(normalize(lex.get_token()))
78 errs += self.parse(normalize(lex.get_token()))
79 else:
79 else:
80 self.ui.warn(_('%s:%d: unknown directive %r\n') %
80 self.ui.warn(_('%s:%d: unknown directive %r\n') %
81 (lex.infile, lex.lineno, cmd))
81 (lex.infile, lex.lineno, cmd))
82 errs += 1
82 errs += 1
83 cmd = lex.get_token()
83 cmd = lex.get_token()
84 return errs
84 return errs
85
85
86 def lookup(self, name, mapping):
86 def lookup(self, name, mapping):
87 name = normalize(name)
87 name = normalize(name)
88 for pre, suf in rpairs(name):
88 for pre, suf in rpairs(name):
89 try:
89 try:
90 return mapping[pre], pre, suf
90 return mapping[pre], pre, suf
91 except KeyError:
91 except KeyError:
92 pass
92 pass
93 return '', name, ''
93 return '', name, ''
94
94
95 def __call__(self, name):
95 def __call__(self, name):
96 if self.include:
96 if self.include:
97 inc = self.lookup(name, self.include)[0]
97 inc = self.lookup(name, self.include)[0]
98 else:
98 else:
99 inc = name
99 inc = name
100 if self.exclude:
100 if self.exclude:
101 exc = self.lookup(name, self.exclude)[0]
101 exc = self.lookup(name, self.exclude)[0]
102 else:
102 else:
103 exc = ''
103 exc = ''
104 if (not self.include and exc) or (len(inc) <= len(exc)):
104 if (not self.include and exc) or (len(inc) <= len(exc)):
105 return None
105 return None
106 newpre, pre, suf = self.lookup(name, self.rename)
106 newpre, pre, suf = self.lookup(name, self.rename)
107 if newpre:
107 if newpre:
108 if newpre == '.':
108 if newpre == '.':
109 return suf
109 return suf
110 if suf:
110 if suf:
111 if newpre.endswith('/'):
111 if newpre.endswith('/'):
112 return newpre + suf
112 return newpre + suf
113 return newpre + '/' + suf
113 return newpre + '/' + suf
114 return newpre
114 return newpre
115 return name
115 return name
116
116
117 def active(self):
117 def active(self):
118 return bool(self.include or self.exclude or self.rename)
118 return bool(self.include or self.exclude or self.rename)
119
119
120 # This class does two additional things compared to a regular source:
120 # This class does two additional things compared to a regular source:
121 #
121 #
122 # - Filter and rename files. This is mostly wrapped by the filemapper
122 # - Filter and rename files. This is mostly wrapped by the filemapper
123 # class above. We hide the original filename in the revision that is
123 # class above. We hide the original filename in the revision that is
124 # returned by getchanges to be able to find things later in getfile.
124 # returned by getchanges to be able to find things later in getfile.
125 #
125 #
126 # - Return only revisions that matter for the files we're interested in.
126 # - Return only revisions that matter for the files we're interested in.
127 # This involves rewriting the parents of the original revision to
127 # This involves rewriting the parents of the original revision to
128 # create a graph that is restricted to those revisions.
128 # create a graph that is restricted to those revisions.
129 #
129 #
130 # This set of revisions includes not only revisions that directly
130 # This set of revisions includes not only revisions that directly
131 # touch files we're interested in, but also merges that merge two
131 # touch files we're interested in, but also merges that merge two
132 # or more interesting revisions.
132 # or more interesting revisions.
133
133
134 class filemap_source(converter_source):
134 class filemap_source(converter_source):
135 def __init__(self, ui, baseconverter, filemap):
135 def __init__(self, ui, baseconverter, filemap):
136 super(filemap_source, self).__init__(ui)
136 super(filemap_source, self).__init__(ui)
137 self.base = baseconverter
137 self.base = baseconverter
138 self.filemapper = filemapper(ui, filemap)
138 self.filemapper = filemapper(ui, filemap)
139 self.commits = {}
139 self.commits = {}
140 # if a revision rev has parent p in the original revision graph, then
140 # if a revision rev has parent p in the original revision graph, then
141 # rev will have parent self.parentmap[p] in the restricted graph.
141 # rev will have parent self.parentmap[p] in the restricted graph.
142 self.parentmap = {}
142 self.parentmap = {}
143 # self.wantedancestors[rev] is the set of all ancestors of rev that
143 # self.wantedancestors[rev] is the set of all ancestors of rev that
144 # are in the restricted graph.
144 # are in the restricted graph.
145 self.wantedancestors = {}
145 self.wantedancestors = {}
146 self.convertedorder = None
146 self.convertedorder = None
147 self._rebuilt = False
147 self._rebuilt = False
148 self.origparents = {}
148 self.origparents = {}
149 self.children = {}
149 self.children = {}
150 self.seenchildren = {}
150 self.seenchildren = {}
151
151
152 def before(self):
152 def before(self):
153 self.base.before()
153 self.base.before()
154
154
155 def after(self):
155 def after(self):
156 self.base.after()
156 self.base.after()
157
157
158 def setrevmap(self, revmap):
158 def setrevmap(self, revmap):
159 # rebuild our state to make things restartable
159 # rebuild our state to make things restartable
160 #
160 #
161 # To avoid calling getcommit for every revision that has already
161 # To avoid calling getcommit for every revision that has already
162 # been converted, we rebuild only the parentmap, delaying the
162 # been converted, we rebuild only the parentmap, delaying the
163 # rebuild of wantedancestors until we need it (i.e. until a
163 # rebuild of wantedancestors until we need it (i.e. until a
164 # merge).
164 # merge).
165 #
165 #
166 # We assume the order argument lists the revisions in
166 # We assume the order argument lists the revisions in
167 # topological order, so that we can infer which revisions were
167 # topological order, so that we can infer which revisions were
168 # wanted by previous runs.
168 # wanted by previous runs.
169 self._rebuilt = not revmap
169 self._rebuilt = not revmap
170 seen = {SKIPREV: SKIPREV}
170 seen = {SKIPREV: SKIPREV}
171 dummyset = set()
171 dummyset = set()
172 converted = []
172 converted = []
173 for rev in revmap.order:
173 for rev in revmap.order:
174 mapped = revmap[rev]
174 mapped = revmap[rev]
175 wanted = mapped not in seen
175 wanted = mapped not in seen
176 if wanted:
176 if wanted:
177 seen[mapped] = rev
177 seen[mapped] = rev
178 self.parentmap[rev] = rev
178 self.parentmap[rev] = rev
179 else:
179 else:
180 self.parentmap[rev] = seen[mapped]
180 self.parentmap[rev] = seen[mapped]
181 self.wantedancestors[rev] = dummyset
181 self.wantedancestors[rev] = dummyset
182 arg = seen[mapped]
182 arg = seen[mapped]
183 if arg == SKIPREV:
183 if arg == SKIPREV:
184 arg = None
184 arg = None
185 converted.append((rev, wanted, arg))
185 converted.append((rev, wanted, arg))
186 self.convertedorder = converted
186 self.convertedorder = converted
187 return self.base.setrevmap(revmap)
187 return self.base.setrevmap(revmap)
188
188
189 def rebuild(self):
189 def rebuild(self):
190 if self._rebuilt:
190 if self._rebuilt:
191 return True
191 return True
192 self._rebuilt = True
192 self._rebuilt = True
193 self.parentmap.clear()
193 self.parentmap.clear()
194 self.wantedancestors.clear()
194 self.wantedancestors.clear()
195 self.seenchildren.clear()
195 self.seenchildren.clear()
196 for rev, wanted, arg in self.convertedorder:
196 for rev, wanted, arg in self.convertedorder:
197 if rev not in self.origparents:
197 if rev not in self.origparents:
198 try:
198 self.origparents[rev] = self.getcommit(rev).parents
199 self.origparents[rev] = self.getcommit(rev).parents
200 except error.RepoLookupError:
201 self.ui.debug("unknown revmap source: %s\n" % rev)
202 continue
199 if arg is not None:
203 if arg is not None:
200 self.children[arg] = self.children.get(arg, 0) + 1
204 self.children[arg] = self.children.get(arg, 0) + 1
201
205
202 for rev, wanted, arg in self.convertedorder:
206 for rev, wanted, arg in self.convertedorder:
207 try:
203 parents = self.origparents[rev]
208 parents = self.origparents[rev]
209 except KeyError:
210 continue # unknown revmap source
204 if wanted:
211 if wanted:
205 self.mark_wanted(rev, parents)
212 self.mark_wanted(rev, parents)
206 else:
213 else:
207 self.mark_not_wanted(rev, arg)
214 self.mark_not_wanted(rev, arg)
208 self._discard(arg, *parents)
215 self._discard(arg, *parents)
209
216
210 return True
217 return True
211
218
212 def getheads(self):
219 def getheads(self):
213 return self.base.getheads()
220 return self.base.getheads()
214
221
215 def getcommit(self, rev):
222 def getcommit(self, rev):
216 # We want to save a reference to the commit objects to be able
223 # We want to save a reference to the commit objects to be able
217 # to rewrite their parents later on.
224 # to rewrite their parents later on.
218 c = self.commits[rev] = self.base.getcommit(rev)
225 c = self.commits[rev] = self.base.getcommit(rev)
219 for p in c.parents:
226 for p in c.parents:
220 self.children[p] = self.children.get(p, 0) + 1
227 self.children[p] = self.children.get(p, 0) + 1
221 return c
228 return c
222
229
223 def _cachedcommit(self, rev):
230 def _cachedcommit(self, rev):
224 if rev in self.commits:
231 if rev in self.commits:
225 return self.commits[rev]
232 return self.commits[rev]
226 return self.base.getcommit(rev)
233 return self.base.getcommit(rev)
227
234
228 def _discard(self, *revs):
235 def _discard(self, *revs):
229 for r in revs:
236 for r in revs:
230 if r is None:
237 if r is None:
231 continue
238 continue
232 self.seenchildren[r] = self.seenchildren.get(r, 0) + 1
239 self.seenchildren[r] = self.seenchildren.get(r, 0) + 1
233 if self.seenchildren[r] == self.children[r]:
240 if self.seenchildren[r] == self.children[r]:
234 self.wantedancestors.pop(r, None)
241 self.wantedancestors.pop(r, None)
235 self.parentmap.pop(r, None)
242 self.parentmap.pop(r, None)
236 del self.seenchildren[r]
243 del self.seenchildren[r]
237 if self._rebuilt:
244 if self._rebuilt:
238 del self.children[r]
245 del self.children[r]
239
246
240 def wanted(self, rev, i):
247 def wanted(self, rev, i):
241 # Return True if we're directly interested in rev.
248 # Return True if we're directly interested in rev.
242 #
249 #
243 # i is an index selecting one of the parents of rev (if rev
250 # i is an index selecting one of the parents of rev (if rev
244 # has no parents, i is None). getchangedfiles will give us
251 # has no parents, i is None). getchangedfiles will give us
245 # the list of files that are different in rev and in the parent
252 # the list of files that are different in rev and in the parent
246 # indicated by i. If we're interested in any of these files,
253 # indicated by i. If we're interested in any of these files,
247 # we're interested in rev.
254 # we're interested in rev.
248 try:
255 try:
249 files = self.base.getchangedfiles(rev, i)
256 files = self.base.getchangedfiles(rev, i)
250 except NotImplementedError:
257 except NotImplementedError:
251 raise util.Abort(_("source repository doesn't support --filemap"))
258 raise util.Abort(_("source repository doesn't support --filemap"))
252 for f in files:
259 for f in files:
253 if self.filemapper(f):
260 if self.filemapper(f):
254 return True
261 return True
255 return False
262 return False
256
263
257 def mark_not_wanted(self, rev, p):
264 def mark_not_wanted(self, rev, p):
258 # Mark rev as not interesting and update data structures.
265 # Mark rev as not interesting and update data structures.
259
266
260 if p is None:
267 if p is None:
261 # A root revision. Use SKIPREV to indicate that it doesn't
268 # A root revision. Use SKIPREV to indicate that it doesn't
262 # map to any revision in the restricted graph. Put SKIPREV
269 # map to any revision in the restricted graph. Put SKIPREV
263 # in the set of wanted ancestors to simplify code elsewhere
270 # in the set of wanted ancestors to simplify code elsewhere
264 self.parentmap[rev] = SKIPREV
271 self.parentmap[rev] = SKIPREV
265 self.wantedancestors[rev] = set((SKIPREV,))
272 self.wantedancestors[rev] = set((SKIPREV,))
266 return
273 return
267
274
268 # Reuse the data from our parent.
275 # Reuse the data from our parent.
269 self.parentmap[rev] = self.parentmap[p]
276 self.parentmap[rev] = self.parentmap[p]
270 self.wantedancestors[rev] = self.wantedancestors[p]
277 self.wantedancestors[rev] = self.wantedancestors[p]
271
278
272 def mark_wanted(self, rev, parents):
279 def mark_wanted(self, rev, parents):
273 # Mark rev ss wanted and update data structures.
280 # Mark rev ss wanted and update data structures.
274
281
275 # rev will be in the restricted graph, so children of rev in
282 # rev will be in the restricted graph, so children of rev in
276 # the original graph should still have rev as a parent in the
283 # the original graph should still have rev as a parent in the
277 # restricted graph.
284 # restricted graph.
278 self.parentmap[rev] = rev
285 self.parentmap[rev] = rev
279
286
280 # The set of wanted ancestors of rev is the union of the sets
287 # The set of wanted ancestors of rev is the union of the sets
281 # of wanted ancestors of its parents. Plus rev itself.
288 # of wanted ancestors of its parents. Plus rev itself.
282 wrev = set()
289 wrev = set()
283 for p in parents:
290 for p in parents:
284 if p in self.wantedancestors:
291 if p in self.wantedancestors:
285 wrev.update(self.wantedancestors[p])
292 wrev.update(self.wantedancestors[p])
286 else:
293 else:
287 self.ui.warn(_('warning: %s parent %s is missing\n') %
294 self.ui.warn(_('warning: %s parent %s is missing\n') %
288 (rev, p))
295 (rev, p))
289 wrev.add(rev)
296 wrev.add(rev)
290 self.wantedancestors[rev] = wrev
297 self.wantedancestors[rev] = wrev
291
298
292 def getchanges(self, rev):
299 def getchanges(self, rev):
293 parents = self.commits[rev].parents
300 parents = self.commits[rev].parents
294 if len(parents) > 1:
301 if len(parents) > 1:
295 self.rebuild()
302 self.rebuild()
296
303
297 # To decide whether we're interested in rev we:
304 # To decide whether we're interested in rev we:
298 #
305 #
299 # - calculate what parents rev will have if it turns out we're
306 # - calculate what parents rev will have if it turns out we're
300 # interested in it. If it's going to have more than 1 parent,
307 # interested in it. If it's going to have more than 1 parent,
301 # we're interested in it.
308 # we're interested in it.
302 #
309 #
303 # - otherwise, we'll compare it with the single parent we found.
310 # - otherwise, we'll compare it with the single parent we found.
304 # If any of the files we're interested in is different in the
311 # If any of the files we're interested in is different in the
305 # the two revisions, we're interested in rev.
312 # the two revisions, we're interested in rev.
306
313
307 # A parent p is interesting if its mapped version (self.parentmap[p]):
314 # A parent p is interesting if its mapped version (self.parentmap[p]):
308 # - is not SKIPREV
315 # - is not SKIPREV
309 # - is still not in the list of parents (we don't want duplicates)
316 # - is still not in the list of parents (we don't want duplicates)
310 # - is not an ancestor of the mapped versions of the other parents or
317 # - is not an ancestor of the mapped versions of the other parents or
311 # there is no parent in the same branch than the current revision.
318 # there is no parent in the same branch than the current revision.
312 mparents = []
319 mparents = []
313 knownparents = set()
320 knownparents = set()
314 branch = self.commits[rev].branch
321 branch = self.commits[rev].branch
315 hasbranchparent = False
322 hasbranchparent = False
316 for i, p1 in enumerate(parents):
323 for i, p1 in enumerate(parents):
317 mp1 = self.parentmap[p1]
324 mp1 = self.parentmap[p1]
318 if mp1 == SKIPREV or mp1 in knownparents:
325 if mp1 == SKIPREV or mp1 in knownparents:
319 continue
326 continue
320 isancestor = util.any(p2 for p2 in parents
327 isancestor = util.any(p2 for p2 in parents
321 if p1 != p2 and mp1 != self.parentmap[p2]
328 if p1 != p2 and mp1 != self.parentmap[p2]
322 and mp1 in self.wantedancestors[p2])
329 and mp1 in self.wantedancestors[p2])
323 if not isancestor and not hasbranchparent and len(parents) > 1:
330 if not isancestor and not hasbranchparent and len(parents) > 1:
324 # This could be expensive, avoid unnecessary calls.
331 # This could be expensive, avoid unnecessary calls.
325 if self._cachedcommit(p1).branch == branch:
332 if self._cachedcommit(p1).branch == branch:
326 hasbranchparent = True
333 hasbranchparent = True
327 mparents.append((p1, mp1, i, isancestor))
334 mparents.append((p1, mp1, i, isancestor))
328 knownparents.add(mp1)
335 knownparents.add(mp1)
329 # Discard parents ancestors of other parents if there is a
336 # Discard parents ancestors of other parents if there is a
330 # non-ancestor one on the same branch than current revision.
337 # non-ancestor one on the same branch than current revision.
331 if hasbranchparent:
338 if hasbranchparent:
332 mparents = [p for p in mparents if not p[3]]
339 mparents = [p for p in mparents if not p[3]]
333 wp = None
340 wp = None
334 if mparents:
341 if mparents:
335 wp = max(p[2] for p in mparents)
342 wp = max(p[2] for p in mparents)
336 mparents = [p[1] for p in mparents]
343 mparents = [p[1] for p in mparents]
337 elif parents:
344 elif parents:
338 wp = 0
345 wp = 0
339
346
340 self.origparents[rev] = parents
347 self.origparents[rev] = parents
341
348
342 closed = False
349 closed = False
343 if 'close' in self.commits[rev].extra:
350 if 'close' in self.commits[rev].extra:
344 # A branch closing revision is only useful if one of its
351 # A branch closing revision is only useful if one of its
345 # parents belong to the branch being closed
352 # parents belong to the branch being closed
346 pbranches = [self._cachedcommit(p).branch for p in mparents]
353 pbranches = [self._cachedcommit(p).branch for p in mparents]
347 if branch in pbranches:
354 if branch in pbranches:
348 closed = True
355 closed = True
349
356
350 if len(mparents) < 2 and not closed and not self.wanted(rev, wp):
357 if len(mparents) < 2 and not closed and not self.wanted(rev, wp):
351 # We don't want this revision.
358 # We don't want this revision.
352 # Update our state and tell the convert process to map this
359 # Update our state and tell the convert process to map this
353 # revision to the same revision its parent as mapped to.
360 # revision to the same revision its parent as mapped to.
354 p = None
361 p = None
355 if parents:
362 if parents:
356 p = parents[wp]
363 p = parents[wp]
357 self.mark_not_wanted(rev, p)
364 self.mark_not_wanted(rev, p)
358 self.convertedorder.append((rev, False, p))
365 self.convertedorder.append((rev, False, p))
359 self._discard(*parents)
366 self._discard(*parents)
360 return self.parentmap[rev]
367 return self.parentmap[rev]
361
368
362 # We want this revision.
369 # We want this revision.
363 # Rewrite the parents of the commit object
370 # Rewrite the parents of the commit object
364 self.commits[rev].parents = mparents
371 self.commits[rev].parents = mparents
365 self.mark_wanted(rev, parents)
372 self.mark_wanted(rev, parents)
366 self.convertedorder.append((rev, True, None))
373 self.convertedorder.append((rev, True, None))
367 self._discard(*parents)
374 self._discard(*parents)
368
375
369 # Get the real changes and do the filtering/mapping. To be
376 # Get the real changes and do the filtering/mapping. To be
370 # able to get the files later on in getfile, we hide the
377 # able to get the files later on in getfile, we hide the
371 # original filename in the rev part of the return value.
378 # original filename in the rev part of the return value.
372 changes, copies = self.base.getchanges(rev)
379 changes, copies = self.base.getchanges(rev)
373 files = {}
380 files = {}
374 for f, r in changes:
381 for f, r in changes:
375 newf = self.filemapper(f)
382 newf = self.filemapper(f)
376 if newf and (newf != f or newf not in files):
383 if newf and (newf != f or newf not in files):
377 files[newf] = (f, r)
384 files[newf] = (f, r)
378 files = sorted(files.items())
385 files = sorted(files.items())
379
386
380 ncopies = {}
387 ncopies = {}
381 for c in copies:
388 for c in copies:
382 newc = self.filemapper(c)
389 newc = self.filemapper(c)
383 if newc:
390 if newc:
384 newsource = self.filemapper(copies[c])
391 newsource = self.filemapper(copies[c])
385 if newsource:
392 if newsource:
386 ncopies[newc] = newsource
393 ncopies[newc] = newsource
387
394
388 return files, ncopies
395 return files, ncopies
389
396
390 def getfile(self, name, rev):
397 def getfile(self, name, rev):
391 realname, realrev = rev
398 realname, realrev = rev
392 return self.base.getfile(realname, realrev)
399 return self.base.getfile(realname, realrev)
393
400
394 def gettags(self):
401 def gettags(self):
395 return self.base.gettags()
402 return self.base.gettags()
396
403
397 def hasnativeorder(self):
404 def hasnativeorder(self):
398 return self.base.hasnativeorder()
405 return self.base.hasnativeorder()
399
406
400 def lookuprev(self, rev):
407 def lookuprev(self, rev):
401 return self.base.lookuprev(rev)
408 return self.base.lookuprev(rev)
402
409
403 def getbookmarks(self):
410 def getbookmarks(self):
404 return self.base.getbookmarks()
411 return self.base.getbookmarks()
@@ -1,630 +1,656
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/file3 >> dir/file3 # to be corrupted in rev 0
17 $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
18 $ echo dir/subdir/file3 >> dir/subdir/file3
18 $ echo dir/subdir/file3 >> dir/subdir/file3
19 $ echo dir/subdir/file4 >> dir/subdir/file4
19 $ echo dir/subdir/file4 >> dir/subdir/file4
20 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
20 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
21 $ echo bar > bar
21 $ echo bar > bar
22 $ echo quux > quux
22 $ echo quux > quux
23 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
23 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
24 $ hg copy foo copied
24 $ hg copy foo copied
25 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
25 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
26 $ echo >> foo
26 $ echo >> foo
27 $ hg ci -d '2 0' -m '2: change foo'
27 $ hg ci -d '2 0' -m '2: change foo'
28 $ hg up -qC 1
28 $ hg up -qC 1
29 $ echo >> bar
29 $ echo >> bar
30 $ echo >> quux
30 $ echo >> quux
31 $ hg ci -d '3 0' -m '3: change bar quux'
31 $ hg ci -d '3 0' -m '3: change bar quux'
32 created new head
32 created new head
33 $ hg up -qC 2
33 $ hg up -qC 2
34 $ hg merge -qr 3
34 $ hg merge -qr 3
35 $ echo >> bar
35 $ echo >> bar
36 $ echo >> baz
36 $ echo >> baz
37 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
37 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
38 $ echo >> bar
38 $ echo >> bar
39 $ echo 1 >> baz
39 $ echo 1 >> baz
40 $ echo >> quux
40 $ echo >> quux
41 $ hg ci -d '5 0' -m '5: change bar baz quux'
41 $ hg ci -d '5 0' -m '5: change bar baz quux'
42 $ hg up -qC 4
42 $ hg up -qC 4
43 $ echo >> foo
43 $ echo >> foo
44 $ echo 2 >> baz
44 $ echo 2 >> baz
45 $ hg ci -d '6 0' -m '6: change foo baz'
45 $ hg ci -d '6 0' -m '6: change foo baz'
46 created new head
46 created new head
47 $ hg up -qC 5
47 $ hg up -qC 5
48 $ hg merge -qr 6
48 $ hg merge -qr 6
49 $ echo >> bar
49 $ echo >> bar
50 $ hg ci -d '7 0' -m '7: second merge; change bar'
50 $ hg ci -d '7 0' -m '7: second merge; change bar'
51 $ echo >> foo
51 $ echo >> foo
52 $ hg ci -m '8: change foo'
52 $ hg ci -m '8: change foo'
53 $ glog
53 $ glog
54 @ 8 "8: change foo" files: foo
54 @ 8 "8: change foo" files: foo
55 |
55 |
56 o 7 "7: second merge; change bar" files: bar baz
56 o 7 "7: second merge; change bar" files: bar baz
57 |\
57 |\
58 | o 6 "6: change foo baz" files: baz foo
58 | o 6 "6: change foo baz" files: baz foo
59 | |
59 | |
60 o | 5 "5: change bar baz quux" files: bar baz quux
60 o | 5 "5: change bar baz quux" files: bar baz quux
61 |/
61 |/
62 o 4 "4: first merge; change bar baz" files: bar baz
62 o 4 "4: first merge; change bar baz" files: bar baz
63 |\
63 |\
64 | o 3 "3: change bar quux" files: bar quux
64 | o 3 "3: change bar quux" files: bar quux
65 | |
65 | |
66 o | 2 "2: change foo" files: foo
66 o | 2 "2: change foo" files: foo
67 |/
67 |/
68 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
68 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
69 |
69 |
70 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
70 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
71
71
72
72
73 final file versions in this repo:
73 final file versions in this repo:
74
74
75 $ hg manifest --debug
75 $ hg manifest --debug
76 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
76 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
77 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
77 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
78 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
78 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
79 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
79 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
80 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
80 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
81 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
81 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
82 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
82 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
83 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
83 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
84 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
84 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
85 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
85 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
86 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
86 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
87 $ hg debugrename copied
87 $ hg debugrename copied
88 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
88 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
89
89
90 $ cd ..
90 $ cd ..
91
91
92
92
93 Test interaction with startrev and verify that changing it is handled properly:
93 Test interaction with startrev and verify that changing it is handled properly:
94
94
95 $ > empty
95 $ > empty
96 $ hg convert --filemap empty source movingstart --config convert.hg.startrev=3 -r4
96 $ hg convert --filemap empty source movingstart --config convert.hg.startrev=3 -r4
97 initializing destination movingstart repository
97 initializing destination movingstart repository
98 scanning source...
98 scanning source...
99 sorting...
99 sorting...
100 converting...
100 converting...
101 1 3: change bar quux
101 1 3: change bar quux
102 0 4: first merge; change bar baz
102 0 4: first merge; change bar baz
103 $ hg convert --filemap empty source movingstart
103 $ hg convert --filemap empty source movingstart
104 scanning source...
104 scanning source...
105 sorting...
105 sorting...
106 converting...
106 converting...
107 3 5: change bar baz quux
107 3 5: change bar baz quux
108 2 6: change foo baz
108 2 6: change foo baz
109 1 7: second merge; change bar
109 1 7: second merge; change bar
110 warning: af455ce4166b3c9c88e6309c2b9332171dcea595 parent 61e22ca76c3b3e93df20338c4e02ce286898e825 is missing
110 warning: af455ce4166b3c9c88e6309c2b9332171dcea595 parent 61e22ca76c3b3e93df20338c4e02ce286898e825 is missing
111 warning: cf908b3eeedc301c9272ebae931da966d5b326c7 parent 59e1ab45c888289513b7354484dac8a88217beab is missing
111 warning: cf908b3eeedc301c9272ebae931da966d5b326c7 parent 59e1ab45c888289513b7354484dac8a88217beab is missing
112 0 8: change foo
112 0 8: change foo
113
113
114
114
115 splitrepo tests
115 splitrepo tests
116
116
117 $ splitrepo()
117 $ splitrepo()
118 > {
118 > {
119 > msg="$1"
119 > msg="$1"
120 > files="$2"
120 > files="$2"
121 > opts=$3
121 > opts=$3
122 > echo "% $files: $msg"
122 > echo "% $files: $msg"
123 > prefix=`echo "$files" | sed -e 's/ /-/g'`
123 > prefix=`echo "$files" | sed -e 's/ /-/g'`
124 > fmap="$prefix.fmap"
124 > fmap="$prefix.fmap"
125 > repo="$prefix.repo"
125 > repo="$prefix.repo"
126 > for i in $files; do
126 > for i in $files; do
127 > echo "include $i" >> "$fmap"
127 > echo "include $i" >> "$fmap"
128 > done
128 > done
129 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
129 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
130 > hg up -q -R "$repo"
130 > hg up -q -R "$repo"
131 > glog -R "$repo"
131 > glog -R "$repo"
132 > hg -R "$repo" manifest --debug
132 > hg -R "$repo" manifest --debug
133 > }
133 > }
134 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
134 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
135 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
135 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
136 @ 3 "8: change foo" files: foo
136 @ 3 "8: change foo" files: foo
137 |
137 |
138 o 2 "6: change foo baz" files: foo
138 o 2 "6: change foo baz" files: foo
139 |
139 |
140 o 1 "2: change foo" files: foo
140 o 1 "2: change foo" files: foo
141 |
141 |
142 o 0 "0: add foo baz dir/" files: foo
142 o 0 "0: add foo baz dir/" files: foo
143
143
144 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
144 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
145 $ splitrepo 'merges are not merges anymore' bar
145 $ splitrepo 'merges are not merges anymore' bar
146 % bar: merges are not merges anymore
146 % bar: merges are not merges anymore
147 @ 4 "7: second merge; change bar" files: bar
147 @ 4 "7: second merge; change bar" files: bar
148 |
148 |
149 o 3 "5: change bar baz quux" files: bar
149 o 3 "5: change bar baz quux" files: bar
150 |
150 |
151 o 2 "4: first merge; change bar baz" files: bar
151 o 2 "4: first merge; change bar baz" files: bar
152 |
152 |
153 o 1 "3: change bar quux" files: bar
153 o 1 "3: change bar quux" files: bar
154 |
154 |
155 o 0 "1: add bar quux; copy foo to copied" files: bar
155 o 0 "1: add bar quux; copy foo to copied" files: bar
156
156
157 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
157 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
158 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
158 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
159 % baz: 1st merge is not a merge anymore; 2nd still is
159 % baz: 1st merge is not a merge anymore; 2nd still is
160 @ 4 "7: second merge; change bar" files: baz
160 @ 4 "7: second merge; change bar" files: baz
161 |\
161 |\
162 | o 3 "6: change foo baz" files: baz
162 | o 3 "6: change foo baz" files: baz
163 | |
163 | |
164 o | 2 "5: change bar baz quux" files: baz
164 o | 2 "5: change bar baz quux" files: baz
165 |/
165 |/
166 o 1 "4: first merge; change bar baz" files: baz
166 o 1 "4: first merge; change bar baz" files: baz
167 |
167 |
168 o 0 "0: add foo baz dir/" files: baz
168 o 0 "0: add foo baz dir/" files: baz
169
169
170 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
170 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
171 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
171 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
172 % foo quux: we add additional merges when they are interesting
172 % foo quux: we add additional merges when they are interesting
173 @ 8 "8: change foo" files: foo
173 @ 8 "8: change foo" files: foo
174 |
174 |
175 o 7 "7: second merge; change bar" files:
175 o 7 "7: second merge; change bar" files:
176 |\
176 |\
177 | o 6 "6: change foo baz" files: foo
177 | o 6 "6: change foo baz" files: foo
178 | |
178 | |
179 o | 5 "5: change bar baz quux" files: quux
179 o | 5 "5: change bar baz quux" files: quux
180 |/
180 |/
181 o 4 "4: first merge; change bar baz" files:
181 o 4 "4: first merge; change bar baz" files:
182 |\
182 |\
183 | o 3 "3: change bar quux" files: quux
183 | o 3 "3: change bar quux" files: quux
184 | |
184 | |
185 o | 2 "2: change foo" files: foo
185 o | 2 "2: change foo" files: foo
186 |/
186 |/
187 o 1 "1: add bar quux; copy foo to copied" files: quux
187 o 1 "1: add bar quux; copy foo to copied" files: quux
188 |
188 |
189 o 0 "0: add foo baz dir/" files: foo
189 o 0 "0: add foo baz dir/" files: foo
190
190
191 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
191 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
192 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
192 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
193 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
193 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
194 % bar quux: partial conversion
194 % bar quux: partial conversion
195 @ 1 "3: change bar quux" files: bar quux
195 @ 1 "3: change bar quux" files: bar quux
196 |
196 |
197 o 0 "1: add bar quux; copy foo to copied" files: bar quux
197 o 0 "1: add bar quux; copy foo to copied" files: bar quux
198
198
199 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
199 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
200 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
200 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
201 $ splitrepo 'complete the partial conversion' 'bar quux'
201 $ splitrepo 'complete the partial conversion' 'bar quux'
202 % bar quux: complete the partial conversion
202 % bar quux: complete the partial conversion
203 @ 4 "7: second merge; change bar" files: bar
203 @ 4 "7: second merge; change bar" files: bar
204 |
204 |
205 o 3 "5: change bar baz quux" files: bar quux
205 o 3 "5: change bar baz quux" files: bar quux
206 |
206 |
207 o 2 "4: first merge; change bar baz" files: bar
207 o 2 "4: first merge; change bar baz" files: bar
208 |
208 |
209 o 1 "3: change bar quux" files: bar quux
209 o 1 "3: change bar quux" files: bar quux
210 |
210 |
211 o 0 "1: add bar quux; copy foo to copied" files: bar quux
211 o 0 "1: add bar quux; copy foo to copied" files: bar quux
212
212
213 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
213 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
214 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
214 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
215 $ rm -r foo.repo
215 $ rm -r foo.repo
216 $ splitrepo 'partial conversion' 'foo' '-r 3'
216 $ splitrepo 'partial conversion' 'foo' '-r 3'
217 % foo: partial conversion
217 % foo: partial conversion
218 @ 0 "0: add foo baz dir/" files: foo
218 @ 0 "0: add foo baz dir/" files: foo
219
219
220 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
220 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
221 $ splitrepo 'complete the partial conversion' 'foo'
221 $ splitrepo 'complete the partial conversion' 'foo'
222 % foo: complete the partial conversion
222 % foo: complete the partial conversion
223 @ 3 "8: change foo" files: foo
223 @ 3 "8: change foo" files: foo
224 |
224 |
225 o 2 "6: change foo baz" files: foo
225 o 2 "6: change foo baz" files: foo
226 |
226 |
227 o 1 "2: change foo" files: foo
227 o 1 "2: change foo" files: foo
228 |
228 |
229 o 0 "0: add foo baz dir/" files: foo
229 o 0 "0: add foo baz dir/" files: foo
230
230
231 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
231 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
232 $ splitrepo 'copied file; source not included in new repo' copied
232 $ splitrepo 'copied file; source not included in new repo' copied
233 % copied: copied file; source not included in new repo
233 % copied: copied file; source not included in new repo
234 @ 0 "1: add bar quux; copy foo to copied" files: copied
234 @ 0 "1: add bar quux; copy foo to copied" files: copied
235
235
236 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
236 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
237 $ hg --cwd copied.repo debugrename copied
237 $ hg --cwd copied.repo debugrename copied
238 copied not renamed
238 copied not renamed
239 $ splitrepo 'copied file; source included in new repo' 'foo copied'
239 $ splitrepo 'copied file; source included in new repo' 'foo copied'
240 % foo copied: copied file; source included in new repo
240 % foo copied: copied file; source included in new repo
241 @ 4 "8: change foo" files: foo
241 @ 4 "8: change foo" files: foo
242 |
242 |
243 o 3 "6: change foo baz" files: foo
243 o 3 "6: change foo baz" files: foo
244 |
244 |
245 o 2 "2: change foo" files: foo
245 o 2 "2: change foo" files: foo
246 |
246 |
247 o 1 "1: add bar quux; copy foo to copied" files: copied
247 o 1 "1: add bar quux; copy foo to copied" files: copied
248 |
248 |
249 o 0 "0: add foo baz dir/" files: foo
249 o 0 "0: add foo baz dir/" files: foo
250
250
251 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
251 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
252 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
252 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
253 $ hg --cwd foo-copied.repo debugrename copied
253 $ hg --cwd foo-copied.repo debugrename copied
254 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
254 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
255
255
256 ensure that the filemap contains duplicated slashes (issue3612)
256 ensure that the filemap contains duplicated slashes (issue3612)
257
257
258 $ cat > renames.fmap <<EOF
258 $ cat > renames.fmap <<EOF
259 > include dir
259 > include dir
260 > exclude dir/file2
260 > exclude dir/file2
261 > rename dir dir2//dir3
261 > rename dir dir2//dir3
262 > include foo
262 > include foo
263 > include copied
263 > include copied
264 > rename foo foo2/
264 > rename foo foo2/
265 > rename copied ./copied2
265 > rename copied ./copied2
266 > exclude dir/subdir
266 > exclude dir/subdir
267 > include dir/subdir/file3
267 > include dir/subdir/file3
268 > EOF
268 > EOF
269 $ rm source/.hg/store/data/dir/file3.i
269 $ rm source/.hg/store/data/dir/file3.i
270 $ rm source/.hg/store/data/dir/file4.i
270 $ rm source/.hg/store/data/dir/file4.i
271 $ hg -q convert --filemap renames.fmap --datesort source dummydest
271 $ hg -q convert --filemap renames.fmap --datesort source dummydest
272 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
272 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
273 [255]
273 [255]
274 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
274 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
275 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
275 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
276 ignoring: data/dir/file4.i@6edd55f559cd: no match found
276 ignoring: data/dir/file4.i@6edd55f559cd: no match found
277 $ hg up -q -R renames.repo
277 $ hg up -q -R renames.repo
278 $ glog -R renames.repo
278 $ glog -R renames.repo
279 @ 4 "8: change foo" files: foo2
279 @ 4 "8: change foo" files: foo2
280 |
280 |
281 o 3 "6: change foo baz" files: foo2
281 o 3 "6: change foo baz" files: foo2
282 |
282 |
283 o 2 "2: change foo" files: foo2
283 o 2 "2: change foo" files: foo2
284 |
284 |
285 o 1 "1: add bar quux; copy foo to copied" files: copied2
285 o 1 "1: add bar quux; copy foo to copied" files: copied2
286 |
286 |
287 o 0 "0: add foo baz dir/" files: dir2/dir3/file dir2/dir3/subdir/file3 foo2
287 o 0 "0: add foo baz dir/" files: dir2/dir3/file dir2/dir3/subdir/file3 foo2
288
288
289 $ hg -R renames.repo verify
289 $ hg -R renames.repo verify
290 checking changesets
290 checking changesets
291 checking manifests
291 checking manifests
292 crosschecking files in changesets and manifests
292 crosschecking files in changesets and manifests
293 checking files
293 checking files
294 4 files, 5 changesets, 7 total revisions
294 4 files, 5 changesets, 7 total revisions
295
295
296 $ hg -R renames.repo manifest --debug
296 $ hg -R renames.repo manifest --debug
297 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
297 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
298 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/dir3/file
298 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/dir3/file
299 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/dir3/subdir/file3
299 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/dir3/subdir/file3
300 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
300 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
301 $ hg --cwd renames.repo debugrename copied2
301 $ hg --cwd renames.repo debugrename copied2
302 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
302 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
303
303
304 copied:
304 copied:
305
305
306 $ hg --cwd source cat copied
306 $ hg --cwd source cat copied
307 foo
307 foo
308
308
309 copied2:
309 copied2:
310
310
311 $ hg --cwd renames.repo cat copied2
311 $ hg --cwd renames.repo cat copied2
312 foo
312 foo
313
313
314 filemap errors
314 filemap errors
315
315
316 $ cat > errors.fmap <<EOF
316 $ cat > errors.fmap <<EOF
317 > include dir/ # beware that comments changes error line numbers!
317 > include dir/ # beware that comments changes error line numbers!
318 > exclude /dir
318 > exclude /dir
319 > rename dir//dir /dir//dir/ "out of sync"
319 > rename dir//dir /dir//dir/ "out of sync"
320 > include
320 > include
321 > EOF
321 > EOF
322 $ hg -q convert --filemap errors.fmap source errors.repo
322 $ hg -q convert --filemap errors.fmap source errors.repo
323 errors.fmap:3: superfluous / in include '/dir'
323 errors.fmap:3: superfluous / in include '/dir'
324 errors.fmap:3: superfluous / in rename '/dir'
324 errors.fmap:3: superfluous / in rename '/dir'
325 errors.fmap:4: unknown directive 'out of sync'
325 errors.fmap:4: unknown directive 'out of sync'
326 errors.fmap:5: path to exclude is missing
326 errors.fmap:5: path to exclude is missing
327 abort: errors in filemap
327 abort: errors in filemap
328 [255]
328 [255]
329
329
330 test branch closing revision pruning if branch is pruned
330 test branch closing revision pruning if branch is pruned
331
331
332 $ hg init branchpruning
332 $ hg init branchpruning
333 $ cd branchpruning
333 $ cd branchpruning
334 $ hg branch foo
334 $ hg branch foo
335 marked working directory as branch foo
335 marked working directory as branch foo
336 (branches are permanent and global, did you want a bookmark?)
336 (branches are permanent and global, did you want a bookmark?)
337 $ echo a > a
337 $ echo a > a
338 $ hg ci -Am adda
338 $ hg ci -Am adda
339 adding a
339 adding a
340 $ hg ci --close-branch -m closefoo
340 $ hg ci --close-branch -m closefoo
341 $ hg up 0
341 $ hg up 0
342 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
342 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
343 $ hg branch empty
343 $ hg branch empty
344 marked working directory as branch empty
344 marked working directory as branch empty
345 (branches are permanent and global, did you want a bookmark?)
345 (branches are permanent and global, did you want a bookmark?)
346 $ hg ci -m emptybranch
346 $ hg ci -m emptybranch
347 $ hg ci --close-branch -m closeempty
347 $ hg ci --close-branch -m closeempty
348 $ hg up 0
348 $ hg up 0
349 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
350 $ hg branch default
350 $ hg branch default
351 marked working directory as branch default
351 marked working directory as branch default
352 (branches are permanent and global, did you want a bookmark?)
352 (branches are permanent and global, did you want a bookmark?)
353 $ echo b > b
353 $ echo b > b
354 $ hg ci -Am addb
354 $ hg ci -Am addb
355 adding b
355 adding b
356 $ hg ci --close-branch -m closedefault
356 $ hg ci --close-branch -m closedefault
357 $ cat > filemap <<EOF
357 $ cat > filemap <<EOF
358 > include b
358 > include b
359 > EOF
359 > EOF
360 $ cd ..
360 $ cd ..
361 $ hg convert branchpruning branchpruning-hg1
361 $ hg convert branchpruning branchpruning-hg1
362 initializing destination branchpruning-hg1 repository
362 initializing destination branchpruning-hg1 repository
363 scanning source...
363 scanning source...
364 sorting...
364 sorting...
365 converting...
365 converting...
366 5 adda
366 5 adda
367 4 closefoo
367 4 closefoo
368 3 emptybranch
368 3 emptybranch
369 2 closeempty
369 2 closeempty
370 1 addb
370 1 addb
371 0 closedefault
371 0 closedefault
372 $ glog -R branchpruning-hg1
372 $ glog -R branchpruning-hg1
373 o 5 "closedefault" files:
373 o 5 "closedefault" files:
374 |
374 |
375 o 4 "addb" files: b
375 o 4 "addb" files: b
376 |
376 |
377 | o 3 "closeempty" files:
377 | o 3 "closeempty" files:
378 | |
378 | |
379 | o 2 "emptybranch" files:
379 | o 2 "emptybranch" files:
380 |/
380 |/
381 | o 1 "closefoo" files:
381 | o 1 "closefoo" files:
382 |/
382 |/
383 o 0 "adda" files: a
383 o 0 "adda" files: a
384
384
385
385
386 exercise incremental conversion at the same time
386 exercise incremental conversion at the same time
387
387
388 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
388 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
389 initializing destination branchpruning-hg2 repository
389 initializing destination branchpruning-hg2 repository
390 scanning source...
390 scanning source...
391 sorting...
391 sorting...
392 converting...
392 converting...
393 0 adda
393 0 adda
394 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
394 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
395 scanning source...
395 scanning source...
396 sorting...
396 sorting...
397 converting...
397 converting...
398 0 addb
398 0 addb
399 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
399 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
400 scanning source...
400 scanning source...
401 sorting...
401 sorting...
402 converting...
402 converting...
403 3 closefoo
403 3 closefoo
404 2 emptybranch
404 2 emptybranch
405 1 closeempty
405 1 closeempty
406 0 closedefault
406 0 closedefault
407 $ glog -R branchpruning-hg2
407 $ glog -R branchpruning-hg2
408 o 1 "closedefault" files:
408 o 1 "closedefault" files:
409 |
409 |
410 o 0 "addb" files: b
410 o 0 "addb" files: b
411
411
412
412
413 Test rebuilding of map with unknown revisions in shamap - it used to crash
414
415 $ cd branchpruning
416 $ hg up -r 2
417 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
418 $ hg merge 4
419 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
420 (branch merge, don't forget to commit)
421 $ hg ci -m 'merging something'
422 $ cd ..
423 $ echo "53792d18237d2b64971fa571936869156655338d 6d955580116e82c4b029bd30f321323bae71a7f0" >> branchpruning-hg2/.hg/shamap
424 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2 --debug
425 run hg source pre-conversion action
426 run hg sink pre-conversion action
427 scanning source...
428 scanning: 1 revisions
429 sorting...
430 converting...
431 0 merging something
432 source: 2503605b178fe50e8fbbb0e77b97939540aa8c87
433 converting: 0/1 revisions (0.00%)
434 unknown revmap source: 53792d18237d2b64971fa571936869156655338d
435 run hg sink post-conversion action
436 run hg source post-conversion action
437
438
413 filemap rename undoing revision rename
439 filemap rename undoing revision rename
414
440
415 $ hg init renameundo
441 $ hg init renameundo
416 $ cd renameundo
442 $ cd renameundo
417 $ echo 1 > a
443 $ echo 1 > a
418 $ echo 1 > c
444 $ echo 1 > c
419 $ hg ci -qAm add
445 $ hg ci -qAm add
420 $ hg mv -q a b/a
446 $ hg mv -q a b/a
421 $ hg mv -q c b/c
447 $ hg mv -q c b/c
422 $ hg ci -qm rename
448 $ hg ci -qm rename
423 $ echo 2 > b/a
449 $ echo 2 > b/a
424 $ echo 2 > b/c
450 $ echo 2 > b/c
425 $ hg ci -qm modify
451 $ hg ci -qm modify
426 $ cd ..
452 $ cd ..
427
453
428 $ echo "rename b ." > renameundo.fmap
454 $ echo "rename b ." > renameundo.fmap
429 $ hg convert --filemap renameundo.fmap renameundo renameundo2
455 $ hg convert --filemap renameundo.fmap renameundo renameundo2
430 initializing destination renameundo2 repository
456 initializing destination renameundo2 repository
431 scanning source...
457 scanning source...
432 sorting...
458 sorting...
433 converting...
459 converting...
434 2 add
460 2 add
435 1 rename
461 1 rename
436 filtering out empty revision
462 filtering out empty revision
437 repository tip rolled back to revision 0 (undo commit)
463 repository tip rolled back to revision 0 (undo commit)
438 0 modify
464 0 modify
439 $ glog -R renameundo2
465 $ glog -R renameundo2
440 o 1 "modify" files: a c
466 o 1 "modify" files: a c
441 |
467 |
442 o 0 "add" files: a c
468 o 0 "add" files: a c
443
469
444
470
445
471
446 test merge parents/empty merges pruning
472 test merge parents/empty merges pruning
447
473
448 $ glog()
474 $ glog()
449 > {
475 > {
450 > hg glog --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
476 > hg glog --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
451 > }
477 > }
452
478
453 test anonymous branch pruning
479 test anonymous branch pruning
454
480
455 $ hg init anonymousbranch
481 $ hg init anonymousbranch
456 $ cd anonymousbranch
482 $ cd anonymousbranch
457 $ echo a > a
483 $ echo a > a
458 $ echo b > b
484 $ echo b > b
459 $ hg ci -Am add
485 $ hg ci -Am add
460 adding a
486 adding a
461 adding b
487 adding b
462 $ echo a >> a
488 $ echo a >> a
463 $ hg ci -m changea
489 $ hg ci -m changea
464 $ hg up 0
490 $ hg up 0
465 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
491 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
466 $ echo b >> b
492 $ echo b >> b
467 $ hg ci -m changeb
493 $ hg ci -m changeb
468 created new head
494 created new head
469 $ hg up 1
495 $ hg up 1
470 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
496 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
471 $ hg merge
497 $ hg merge
472 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 (branch merge, don't forget to commit)
499 (branch merge, don't forget to commit)
474 $ hg ci -m merge
500 $ hg ci -m merge
475 $ cd ..
501 $ cd ..
476
502
477 $ cat > filemap <<EOF
503 $ cat > filemap <<EOF
478 > include a
504 > include a
479 > EOF
505 > EOF
480 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg
506 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg
481 initializing destination anonymousbranch-hg repository
507 initializing destination anonymousbranch-hg repository
482 scanning source...
508 scanning source...
483 sorting...
509 sorting...
484 converting...
510 converting...
485 3 add
511 3 add
486 2 changea
512 2 changea
487 1 changeb
513 1 changeb
488 0 merge
514 0 merge
489 $ glog -R anonymousbranch
515 $ glog -R anonymousbranch
490 @ 3:c71d5201a498@default "merge" files:
516 @ 3:c71d5201a498@default "merge" files:
491 |\
517 |\
492 | o 2:607eb44b17f9@default "changeb" files: b
518 | o 2:607eb44b17f9@default "changeb" files: b
493 | |
519 | |
494 o | 1:1f60ea617824@default "changea" files: a
520 o | 1:1f60ea617824@default "changea" files: a
495 |/
521 |/
496 o 0:0146e6129113@default "add" files: a b
522 o 0:0146e6129113@default "add" files: a b
497
523
498 $ glog -R anonymousbranch-hg
524 $ glog -R anonymousbranch-hg
499 o 1:cda818e7219b@default "changea" files: a
525 o 1:cda818e7219b@default "changea" files: a
500 |
526 |
501 o 0:c334dc3be0da@default "add" files: a
527 o 0:c334dc3be0da@default "add" files: a
502
528
503 $ cat anonymousbranch-hg/.hg/shamap
529 $ cat anonymousbranch-hg/.hg/shamap
504 0146e6129113dba9ac90207cfdf2d7ed35257ae5 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
530 0146e6129113dba9ac90207cfdf2d7ed35257ae5 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
505 1f60ea61782421edf8d051ff4fcb61b330f26a4a cda818e7219b5f7f3fb9f49780054ed6a1905ec3
531 1f60ea61782421edf8d051ff4fcb61b330f26a4a cda818e7219b5f7f3fb9f49780054ed6a1905ec3
506 607eb44b17f9348cd5cbd26e16af87ba77b0b037 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
532 607eb44b17f9348cd5cbd26e16af87ba77b0b037 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
507 c71d5201a498b2658d105a6bf69d7a0df2649aea cda818e7219b5f7f3fb9f49780054ed6a1905ec3
533 c71d5201a498b2658d105a6bf69d7a0df2649aea cda818e7219b5f7f3fb9f49780054ed6a1905ec3
508
534
509 $ cat > filemap <<EOF
535 $ cat > filemap <<EOF
510 > include b
536 > include b
511 > EOF
537 > EOF
512 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg2
538 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg2
513 initializing destination anonymousbranch-hg2 repository
539 initializing destination anonymousbranch-hg2 repository
514 scanning source...
540 scanning source...
515 sorting...
541 sorting...
516 converting...
542 converting...
517 3 add
543 3 add
518 2 changea
544 2 changea
519 1 changeb
545 1 changeb
520 0 merge
546 0 merge
521 $ glog -R anonymousbranch
547 $ glog -R anonymousbranch
522 @ 3:c71d5201a498@default "merge" files:
548 @ 3:c71d5201a498@default "merge" files:
523 |\
549 |\
524 | o 2:607eb44b17f9@default "changeb" files: b
550 | o 2:607eb44b17f9@default "changeb" files: b
525 | |
551 | |
526 o | 1:1f60ea617824@default "changea" files: a
552 o | 1:1f60ea617824@default "changea" files: a
527 |/
553 |/
528 o 0:0146e6129113@default "add" files: a b
554 o 0:0146e6129113@default "add" files: a b
529
555
530 $ glog -R anonymousbranch-hg2
556 $ glog -R anonymousbranch-hg2
531 o 1:62dd350b0df6@default "changeb" files: b
557 o 1:62dd350b0df6@default "changeb" files: b
532 |
558 |
533 o 0:4b9ced861657@default "add" files: b
559 o 0:4b9ced861657@default "add" files: b
534
560
535 $ cat anonymousbranch-hg2/.hg/shamap
561 $ cat anonymousbranch-hg2/.hg/shamap
536 0146e6129113dba9ac90207cfdf2d7ed35257ae5 4b9ced86165703791653059a1db6ed864630a523
562 0146e6129113dba9ac90207cfdf2d7ed35257ae5 4b9ced86165703791653059a1db6ed864630a523
537 1f60ea61782421edf8d051ff4fcb61b330f26a4a 4b9ced86165703791653059a1db6ed864630a523
563 1f60ea61782421edf8d051ff4fcb61b330f26a4a 4b9ced86165703791653059a1db6ed864630a523
538 607eb44b17f9348cd5cbd26e16af87ba77b0b037 62dd350b0df695f7d2c82a02e0499b16fd790f22
564 607eb44b17f9348cd5cbd26e16af87ba77b0b037 62dd350b0df695f7d2c82a02e0499b16fd790f22
539 c71d5201a498b2658d105a6bf69d7a0df2649aea 62dd350b0df695f7d2c82a02e0499b16fd790f22
565 c71d5201a498b2658d105a6bf69d7a0df2649aea 62dd350b0df695f7d2c82a02e0499b16fd790f22
540
566
541 test named branch pruning
567 test named branch pruning
542
568
543 $ hg init namedbranch
569 $ hg init namedbranch
544 $ cd namedbranch
570 $ cd namedbranch
545 $ echo a > a
571 $ echo a > a
546 $ echo b > b
572 $ echo b > b
547 $ hg ci -Am add
573 $ hg ci -Am add
548 adding a
574 adding a
549 adding b
575 adding b
550 $ echo a >> a
576 $ echo a >> a
551 $ hg ci -m changea
577 $ hg ci -m changea
552 $ hg up 0
578 $ hg up 0
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
579 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 $ hg branch foo
580 $ hg branch foo
555 marked working directory as branch foo
581 marked working directory as branch foo
556 (branches are permanent and global, did you want a bookmark?)
582 (branches are permanent and global, did you want a bookmark?)
557 $ echo b >> b
583 $ echo b >> b
558 $ hg ci -m changeb
584 $ hg ci -m changeb
559 $ hg up default
585 $ hg up default
560 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
561 $ hg merge foo
587 $ hg merge foo
562 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
563 (branch merge, don't forget to commit)
589 (branch merge, don't forget to commit)
564 $ hg ci -m merge
590 $ hg ci -m merge
565 $ cd ..
591 $ cd ..
566
592
567 $ cat > filemap <<EOF
593 $ cat > filemap <<EOF
568 > include a
594 > include a
569 > EOF
595 > EOF
570 $ hg convert --filemap filemap namedbranch namedbranch-hg
596 $ hg convert --filemap filemap namedbranch namedbranch-hg
571 initializing destination namedbranch-hg repository
597 initializing destination namedbranch-hg repository
572 scanning source...
598 scanning source...
573 sorting...
599 sorting...
574 converting...
600 converting...
575 3 add
601 3 add
576 2 changea
602 2 changea
577 1 changeb
603 1 changeb
578 0 merge
604 0 merge
579 $ glog -R namedbranch
605 $ glog -R namedbranch
580 @ 3:73899bcbe45c@default "merge" files:
606 @ 3:73899bcbe45c@default "merge" files:
581 |\
607 |\
582 | o 2:8097982d19fc@foo "changeb" files: b
608 | o 2:8097982d19fc@foo "changeb" files: b
583 | |
609 | |
584 o | 1:1f60ea617824@default "changea" files: a
610 o | 1:1f60ea617824@default "changea" files: a
585 |/
611 |/
586 o 0:0146e6129113@default "add" files: a b
612 o 0:0146e6129113@default "add" files: a b
587
613
588 $ glog -R namedbranch-hg
614 $ glog -R namedbranch-hg
589 o 1:cda818e7219b@default "changea" files: a
615 o 1:cda818e7219b@default "changea" files: a
590 |
616 |
591 o 0:c334dc3be0da@default "add" files: a
617 o 0:c334dc3be0da@default "add" files: a
592
618
593
619
594 $ cd namedbranch
620 $ cd namedbranch
595 $ hg --config extensions.mq= strip tip
621 $ hg --config extensions.mq= strip tip
596 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
622 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 saved backup bundle to $TESTTMP/namedbranch/.hg/strip-backup/73899bcbe45c-backup.hg (glob)
623 saved backup bundle to $TESTTMP/namedbranch/.hg/strip-backup/73899bcbe45c-backup.hg (glob)
598 $ hg up foo
624 $ hg up foo
599 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
625 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
600 $ hg merge default
626 $ hg merge default
601 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
602 (branch merge, don't forget to commit)
628 (branch merge, don't forget to commit)
603 $ hg ci -m merge
629 $ hg ci -m merge
604 $ cd ..
630 $ cd ..
605
631
606 $ hg convert --filemap filemap namedbranch namedbranch-hg2
632 $ hg convert --filemap filemap namedbranch namedbranch-hg2
607 initializing destination namedbranch-hg2 repository
633 initializing destination namedbranch-hg2 repository
608 scanning source...
634 scanning source...
609 sorting...
635 sorting...
610 converting...
636 converting...
611 3 add
637 3 add
612 2 changea
638 2 changea
613 1 changeb
639 1 changeb
614 0 merge
640 0 merge
615 $ glog -R namedbranch
641 $ glog -R namedbranch
616 @ 3:e1959de76e1b@foo "merge" files:
642 @ 3:e1959de76e1b@foo "merge" files:
617 |\
643 |\
618 | o 2:8097982d19fc@foo "changeb" files: b
644 | o 2:8097982d19fc@foo "changeb" files: b
619 | |
645 | |
620 o | 1:1f60ea617824@default "changea" files: a
646 o | 1:1f60ea617824@default "changea" files: a
621 |/
647 |/
622 o 0:0146e6129113@default "add" files: a b
648 o 0:0146e6129113@default "add" files: a b
623
649
624 $ glog -R namedbranch-hg2
650 $ glog -R namedbranch-hg2
625 o 2:dcf314454667@foo "merge" files:
651 o 2:dcf314454667@foo "merge" files:
626 |\
652 |\
627 | o 1:cda818e7219b@default "changea" files: a
653 | o 1:cda818e7219b@default "changea" files: a
628 |/
654 |/
629 o 0:c334dc3be0da@default "add" files: a
655 o 0:c334dc3be0da@default "add" files: a
630
656
General Comments 0
You need to be logged in to leave comments. Login now