##// END OF EJS Templates
convert: mercurial source: convert global tags only - not local tags...
Mads Kiilerich -
r21498:6b8daeea default
parent child Browse files
Show More
@@ -1,446 +1,448
1 # hg.py - hg backend for convert extension
1 # hg.py - hg backend for convert extension
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 # Notes for hg->hg conversion:
8 # Notes for hg->hg conversion:
9 #
9 #
10 # * Old versions of Mercurial didn't trim the whitespace from the ends
10 # * Old versions of Mercurial didn't trim the whitespace from the ends
11 # of commit messages, but new versions do. Changesets created by
11 # of commit messages, but new versions do. Changesets created by
12 # those older versions, then converted, may thus have different
12 # those older versions, then converted, may thus have different
13 # hashes for changesets that are otherwise identical.
13 # hashes for changesets that are otherwise identical.
14 #
14 #
15 # * Using "--config convert.hg.saverev=true" will make the source
15 # * Using "--config convert.hg.saverev=true" will make the source
16 # identifier to be stored in the converted revision. This will cause
16 # identifier to be stored in the converted revision. This will cause
17 # the converted revision to have a different identity than the
17 # the converted revision to have a different identity than the
18 # source.
18 # source.
19
19
20
20
21 import os, time, cStringIO
21 import os, time, cStringIO
22 from mercurial.i18n import _
22 from mercurial.i18n import _
23 from mercurial.node import bin, hex, nullid
23 from mercurial.node import bin, hex, nullid
24 from mercurial import hg, util, context, bookmarks, error, scmutil
24 from mercurial import hg, util, context, bookmarks, error, scmutil
25
25
26 from common import NoRepo, commit, converter_source, converter_sink
26 from common import NoRepo, commit, converter_source, converter_sink
27
27
28 import re
28 import re
29 sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
29 sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
30
30
31 class mercurial_sink(converter_sink):
31 class mercurial_sink(converter_sink):
32 def __init__(self, ui, path):
32 def __init__(self, ui, path):
33 converter_sink.__init__(self, ui, path)
33 converter_sink.__init__(self, ui, path)
34 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
34 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
35 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
35 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
36 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
36 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
37 self.lastbranch = None
37 self.lastbranch = None
38 if os.path.isdir(path) and len(os.listdir(path)) > 0:
38 if os.path.isdir(path) and len(os.listdir(path)) > 0:
39 try:
39 try:
40 self.repo = hg.repository(self.ui, path)
40 self.repo = hg.repository(self.ui, path)
41 if not self.repo.local():
41 if not self.repo.local():
42 raise NoRepo(_('%s is not a local Mercurial repository')
42 raise NoRepo(_('%s is not a local Mercurial repository')
43 % path)
43 % path)
44 except error.RepoError, err:
44 except error.RepoError, err:
45 ui.traceback()
45 ui.traceback()
46 raise NoRepo(err.args[0])
46 raise NoRepo(err.args[0])
47 else:
47 else:
48 try:
48 try:
49 ui.status(_('initializing destination %s repository\n') % path)
49 ui.status(_('initializing destination %s repository\n') % path)
50 self.repo = hg.repository(self.ui, path, create=True)
50 self.repo = hg.repository(self.ui, path, create=True)
51 if not self.repo.local():
51 if not self.repo.local():
52 raise NoRepo(_('%s is not a local Mercurial repository')
52 raise NoRepo(_('%s is not a local Mercurial repository')
53 % path)
53 % path)
54 self.created.append(path)
54 self.created.append(path)
55 except error.RepoError:
55 except error.RepoError:
56 ui.traceback()
56 ui.traceback()
57 raise NoRepo(_("could not create hg repository %s as sink")
57 raise NoRepo(_("could not create hg repository %s as sink")
58 % path)
58 % path)
59 self.lock = None
59 self.lock = None
60 self.wlock = None
60 self.wlock = None
61 self.filemapmode = False
61 self.filemapmode = False
62
62
63 def before(self):
63 def before(self):
64 self.ui.debug('run hg sink pre-conversion action\n')
64 self.ui.debug('run hg sink pre-conversion action\n')
65 self.wlock = self.repo.wlock()
65 self.wlock = self.repo.wlock()
66 self.lock = self.repo.lock()
66 self.lock = self.repo.lock()
67
67
68 def after(self):
68 def after(self):
69 self.ui.debug('run hg sink post-conversion action\n')
69 self.ui.debug('run hg sink post-conversion action\n')
70 if self.lock:
70 if self.lock:
71 self.lock.release()
71 self.lock.release()
72 if self.wlock:
72 if self.wlock:
73 self.wlock.release()
73 self.wlock.release()
74
74
75 def revmapfile(self):
75 def revmapfile(self):
76 return self.repo.join("shamap")
76 return self.repo.join("shamap")
77
77
78 def authorfile(self):
78 def authorfile(self):
79 return self.repo.join("authormap")
79 return self.repo.join("authormap")
80
80
81 def setbranch(self, branch, pbranches):
81 def setbranch(self, branch, pbranches):
82 if not self.clonebranches:
82 if not self.clonebranches:
83 return
83 return
84
84
85 setbranch = (branch != self.lastbranch)
85 setbranch = (branch != self.lastbranch)
86 self.lastbranch = branch
86 self.lastbranch = branch
87 if not branch:
87 if not branch:
88 branch = 'default'
88 branch = 'default'
89 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
89 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
90 pbranch = pbranches and pbranches[0][1] or 'default'
90 pbranch = pbranches and pbranches[0][1] or 'default'
91
91
92 branchpath = os.path.join(self.path, branch)
92 branchpath = os.path.join(self.path, branch)
93 if setbranch:
93 if setbranch:
94 self.after()
94 self.after()
95 try:
95 try:
96 self.repo = hg.repository(self.ui, branchpath)
96 self.repo = hg.repository(self.ui, branchpath)
97 except Exception:
97 except Exception:
98 self.repo = hg.repository(self.ui, branchpath, create=True)
98 self.repo = hg.repository(self.ui, branchpath, create=True)
99 self.before()
99 self.before()
100
100
101 # pbranches may bring revisions from other branches (merge parents)
101 # pbranches may bring revisions from other branches (merge parents)
102 # Make sure we have them, or pull them.
102 # Make sure we have them, or pull them.
103 missings = {}
103 missings = {}
104 for b in pbranches:
104 for b in pbranches:
105 try:
105 try:
106 self.repo.lookup(b[0])
106 self.repo.lookup(b[0])
107 except Exception:
107 except Exception:
108 missings.setdefault(b[1], []).append(b[0])
108 missings.setdefault(b[1], []).append(b[0])
109
109
110 if missings:
110 if missings:
111 self.after()
111 self.after()
112 for pbranch, heads in sorted(missings.iteritems()):
112 for pbranch, heads in sorted(missings.iteritems()):
113 pbranchpath = os.path.join(self.path, pbranch)
113 pbranchpath = os.path.join(self.path, pbranch)
114 prepo = hg.peer(self.ui, {}, pbranchpath)
114 prepo = hg.peer(self.ui, {}, pbranchpath)
115 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
115 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
116 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
116 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
117 self.before()
117 self.before()
118
118
119 def _rewritetags(self, source, revmap, data):
119 def _rewritetags(self, source, revmap, data):
120 fp = cStringIO.StringIO()
120 fp = cStringIO.StringIO()
121 for line in data.splitlines():
121 for line in data.splitlines():
122 s = line.split(' ', 1)
122 s = line.split(' ', 1)
123 if len(s) != 2:
123 if len(s) != 2:
124 continue
124 continue
125 revid = revmap.get(source.lookuprev(s[0]))
125 revid = revmap.get(source.lookuprev(s[0]))
126 if not revid:
126 if not revid:
127 continue
127 continue
128 fp.write('%s %s\n' % (revid, s[1]))
128 fp.write('%s %s\n' % (revid, s[1]))
129 return fp.getvalue()
129 return fp.getvalue()
130
130
131 def putcommit(self, files, copies, parents, commit, source, revmap):
131 def putcommit(self, files, copies, parents, commit, source, revmap):
132
132
133 files = dict(files)
133 files = dict(files)
134 def getfilectx(repo, memctx, f):
134 def getfilectx(repo, memctx, f):
135 v = files[f]
135 v = files[f]
136 data, mode = source.getfile(f, v)
136 data, mode = source.getfile(f, v)
137 if f == '.hgtags':
137 if f == '.hgtags':
138 data = self._rewritetags(source, revmap, data)
138 data = self._rewritetags(source, revmap, data)
139 return context.memfilectx(f, data, 'l' in mode, 'x' in mode,
139 return context.memfilectx(f, data, 'l' in mode, 'x' in mode,
140 copies.get(f))
140 copies.get(f))
141
141
142 pl = []
142 pl = []
143 for p in parents:
143 for p in parents:
144 if p not in pl:
144 if p not in pl:
145 pl.append(p)
145 pl.append(p)
146 parents = pl
146 parents = pl
147 nparents = len(parents)
147 nparents = len(parents)
148 if self.filemapmode and nparents == 1:
148 if self.filemapmode and nparents == 1:
149 m1node = self.repo.changelog.read(bin(parents[0]))[0]
149 m1node = self.repo.changelog.read(bin(parents[0]))[0]
150 parent = parents[0]
150 parent = parents[0]
151
151
152 if len(parents) < 2:
152 if len(parents) < 2:
153 parents.append(nullid)
153 parents.append(nullid)
154 if len(parents) < 2:
154 if len(parents) < 2:
155 parents.append(nullid)
155 parents.append(nullid)
156 p2 = parents.pop(0)
156 p2 = parents.pop(0)
157
157
158 text = commit.desc
158 text = commit.desc
159
159
160 sha1s = re.findall(sha1re, text)
160 sha1s = re.findall(sha1re, text)
161 for sha1 in sha1s:
161 for sha1 in sha1s:
162 oldrev = source.lookuprev(sha1)
162 oldrev = source.lookuprev(sha1)
163 newrev = revmap.get(oldrev)
163 newrev = revmap.get(oldrev)
164 if newrev is not None:
164 if newrev is not None:
165 text = text.replace(sha1, newrev[:len(sha1)])
165 text = text.replace(sha1, newrev[:len(sha1)])
166
166
167 extra = commit.extra.copy()
167 extra = commit.extra.copy()
168 if self.branchnames and commit.branch:
168 if self.branchnames and commit.branch:
169 extra['branch'] = commit.branch
169 extra['branch'] = commit.branch
170 if commit.rev:
170 if commit.rev:
171 extra['convert_revision'] = commit.rev
171 extra['convert_revision'] = commit.rev
172
172
173 while parents:
173 while parents:
174 p1 = p2
174 p1 = p2
175 p2 = parents.pop(0)
175 p2 = parents.pop(0)
176 ctx = context.memctx(self.repo, (p1, p2), text, files.keys(),
176 ctx = context.memctx(self.repo, (p1, p2), text, files.keys(),
177 getfilectx, commit.author, commit.date, extra)
177 getfilectx, commit.author, commit.date, extra)
178 self.repo.commitctx(ctx)
178 self.repo.commitctx(ctx)
179 text = "(octopus merge fixup)\n"
179 text = "(octopus merge fixup)\n"
180 p2 = hex(self.repo.changelog.tip())
180 p2 = hex(self.repo.changelog.tip())
181
181
182 if self.filemapmode and nparents == 1:
182 if self.filemapmode and nparents == 1:
183 man = self.repo.manifest
183 man = self.repo.manifest
184 mnode = self.repo.changelog.read(bin(p2))[0]
184 mnode = self.repo.changelog.read(bin(p2))[0]
185 closed = 'close' in commit.extra
185 closed = 'close' in commit.extra
186 if not closed and not man.cmp(m1node, man.revision(mnode)):
186 if not closed and not man.cmp(m1node, man.revision(mnode)):
187 self.ui.status(_("filtering out empty revision\n"))
187 self.ui.status(_("filtering out empty revision\n"))
188 self.repo.rollback(force=True)
188 self.repo.rollback(force=True)
189 return parent
189 return parent
190 return p2
190 return p2
191
191
192 def puttags(self, tags):
192 def puttags(self, tags):
193 try:
193 try:
194 parentctx = self.repo[self.tagsbranch]
194 parentctx = self.repo[self.tagsbranch]
195 tagparent = parentctx.node()
195 tagparent = parentctx.node()
196 except error.RepoError:
196 except error.RepoError:
197 parentctx = None
197 parentctx = None
198 tagparent = nullid
198 tagparent = nullid
199
199
200 oldlines = set()
200 oldlines = set()
201 for branch, heads in self.repo.branchmap().iteritems():
201 for branch, heads in self.repo.branchmap().iteritems():
202 for h in heads:
202 for h in heads:
203 if '.hgtags' in self.repo[h]:
203 if '.hgtags' in self.repo[h]:
204 oldlines.update(
204 oldlines.update(
205 set(self.repo[h]['.hgtags'].data().splitlines(True)))
205 set(self.repo[h]['.hgtags'].data().splitlines(True)))
206 oldlines = sorted(list(oldlines))
206 oldlines = sorted(list(oldlines))
207
207
208 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
208 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
209 if newlines == oldlines:
209 if newlines == oldlines:
210 return None, None
210 return None, None
211
211
212 # if the old and new tags match, then there is nothing to update
212 # if the old and new tags match, then there is nothing to update
213 oldtags = set()
213 oldtags = set()
214 newtags = set()
214 newtags = set()
215 for line in oldlines:
215 for line in oldlines:
216 s = line.strip().split(' ', 1)
216 s = line.strip().split(' ', 1)
217 if len(s) != 2:
217 if len(s) != 2:
218 continue
218 continue
219 oldtags.add(s[1])
219 oldtags.add(s[1])
220 for line in newlines:
220 for line in newlines:
221 s = line.strip().split(' ', 1)
221 s = line.strip().split(' ', 1)
222 if len(s) != 2:
222 if len(s) != 2:
223 continue
223 continue
224 if s[1] not in oldtags:
224 if s[1] not in oldtags:
225 newtags.add(s[1].strip())
225 newtags.add(s[1].strip())
226
226
227 if not newtags:
227 if not newtags:
228 return None, None
228 return None, None
229
229
230 data = "".join(newlines)
230 data = "".join(newlines)
231 def getfilectx(repo, memctx, f):
231 def getfilectx(repo, memctx, f):
232 return context.memfilectx(f, data, False, False, None)
232 return context.memfilectx(f, data, False, False, None)
233
233
234 self.ui.status(_("updating tags\n"))
234 self.ui.status(_("updating tags\n"))
235 date = "%s 0" % int(time.mktime(time.gmtime()))
235 date = "%s 0" % int(time.mktime(time.gmtime()))
236 extra = {'branch': self.tagsbranch}
236 extra = {'branch': self.tagsbranch}
237 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
237 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
238 [".hgtags"], getfilectx, "convert-repo", date,
238 [".hgtags"], getfilectx, "convert-repo", date,
239 extra)
239 extra)
240 self.repo.commitctx(ctx)
240 self.repo.commitctx(ctx)
241 return hex(self.repo.changelog.tip()), hex(tagparent)
241 return hex(self.repo.changelog.tip()), hex(tagparent)
242
242
243 def setfilemapmode(self, active):
243 def setfilemapmode(self, active):
244 self.filemapmode = active
244 self.filemapmode = active
245
245
246 def putbookmarks(self, updatedbookmark):
246 def putbookmarks(self, updatedbookmark):
247 if not len(updatedbookmark):
247 if not len(updatedbookmark):
248 return
248 return
249
249
250 self.ui.status(_("updating bookmarks\n"))
250 self.ui.status(_("updating bookmarks\n"))
251 destmarks = self.repo._bookmarks
251 destmarks = self.repo._bookmarks
252 for bookmark in updatedbookmark:
252 for bookmark in updatedbookmark:
253 destmarks[bookmark] = bin(updatedbookmark[bookmark])
253 destmarks[bookmark] = bin(updatedbookmark[bookmark])
254 destmarks.write()
254 destmarks.write()
255
255
256 def hascommit(self, rev):
256 def hascommit(self, rev):
257 if rev not in self.repo and self.clonebranches:
257 if rev not in self.repo and self.clonebranches:
258 raise util.Abort(_('revision %s not found in destination '
258 raise util.Abort(_('revision %s not found in destination '
259 'repository (lookups with clonebranches=true '
259 'repository (lookups with clonebranches=true '
260 'are not implemented)') % rev)
260 'are not implemented)') % rev)
261 return rev in self.repo
261 return rev in self.repo
262
262
263 class mercurial_source(converter_source):
263 class mercurial_source(converter_source):
264 def __init__(self, ui, path, rev=None):
264 def __init__(self, ui, path, rev=None):
265 converter_source.__init__(self, ui, path, rev)
265 converter_source.__init__(self, ui, path, rev)
266 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
266 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
267 self.ignored = set()
267 self.ignored = set()
268 self.saverev = ui.configbool('convert', 'hg.saverev', False)
268 self.saverev = ui.configbool('convert', 'hg.saverev', False)
269 try:
269 try:
270 self.repo = hg.repository(self.ui, path)
270 self.repo = hg.repository(self.ui, path)
271 # try to provoke an exception if this isn't really a hg
271 # try to provoke an exception if this isn't really a hg
272 # repo, but some other bogus compatible-looking url
272 # repo, but some other bogus compatible-looking url
273 if not self.repo.local():
273 if not self.repo.local():
274 raise error.RepoError
274 raise error.RepoError
275 except error.RepoError:
275 except error.RepoError:
276 ui.traceback()
276 ui.traceback()
277 raise NoRepo(_("%s is not a local Mercurial repository") % path)
277 raise NoRepo(_("%s is not a local Mercurial repository") % path)
278 self.lastrev = None
278 self.lastrev = None
279 self.lastctx = None
279 self.lastctx = None
280 self._changescache = None
280 self._changescache = None
281 self.convertfp = None
281 self.convertfp = None
282 # Restrict converted revisions to startrev descendants
282 # Restrict converted revisions to startrev descendants
283 startnode = ui.config('convert', 'hg.startrev')
283 startnode = ui.config('convert', 'hg.startrev')
284 hgrevs = ui.config('convert', 'hg.revs')
284 hgrevs = ui.config('convert', 'hg.revs')
285 if hgrevs is None:
285 if hgrevs is None:
286 if startnode is not None:
286 if startnode is not None:
287 try:
287 try:
288 startnode = self.repo.lookup(startnode)
288 startnode = self.repo.lookup(startnode)
289 except error.RepoError:
289 except error.RepoError:
290 raise util.Abort(_('%s is not a valid start revision')
290 raise util.Abort(_('%s is not a valid start revision')
291 % startnode)
291 % startnode)
292 startrev = self.repo.changelog.rev(startnode)
292 startrev = self.repo.changelog.rev(startnode)
293 children = {startnode: 1}
293 children = {startnode: 1}
294 for r in self.repo.changelog.descendants([startrev]):
294 for r in self.repo.changelog.descendants([startrev]):
295 children[self.repo.changelog.node(r)] = 1
295 children[self.repo.changelog.node(r)] = 1
296 self.keep = children.__contains__
296 self.keep = children.__contains__
297 else:
297 else:
298 self.keep = util.always
298 self.keep = util.always
299 if rev:
299 if rev:
300 self._heads = [self.repo[rev].node()]
300 self._heads = [self.repo[rev].node()]
301 else:
301 else:
302 self._heads = self.repo.heads()
302 self._heads = self.repo.heads()
303 else:
303 else:
304 if rev or startnode is not None:
304 if rev or startnode is not None:
305 raise util.Abort(_('hg.revs cannot be combined with '
305 raise util.Abort(_('hg.revs cannot be combined with '
306 'hg.startrev or --rev'))
306 'hg.startrev or --rev'))
307 nodes = set()
307 nodes = set()
308 parents = set()
308 parents = set()
309 for r in scmutil.revrange(self.repo, [hgrevs]):
309 for r in scmutil.revrange(self.repo, [hgrevs]):
310 ctx = self.repo[r]
310 ctx = self.repo[r]
311 nodes.add(ctx.node())
311 nodes.add(ctx.node())
312 parents.update(p.node() for p in ctx.parents())
312 parents.update(p.node() for p in ctx.parents())
313 self.keep = nodes.__contains__
313 self.keep = nodes.__contains__
314 self._heads = nodes - parents
314 self._heads = nodes - parents
315
315
316 def changectx(self, rev):
316 def changectx(self, rev):
317 if self.lastrev != rev:
317 if self.lastrev != rev:
318 self.lastctx = self.repo[rev]
318 self.lastctx = self.repo[rev]
319 self.lastrev = rev
319 self.lastrev = rev
320 return self.lastctx
320 return self.lastctx
321
321
322 def parents(self, ctx):
322 def parents(self, ctx):
323 return [p for p in ctx.parents() if p and self.keep(p.node())]
323 return [p for p in ctx.parents() if p and self.keep(p.node())]
324
324
325 def getheads(self):
325 def getheads(self):
326 return [hex(h) for h in self._heads if self.keep(h)]
326 return [hex(h) for h in self._heads if self.keep(h)]
327
327
328 def getfile(self, name, rev):
328 def getfile(self, name, rev):
329 try:
329 try:
330 fctx = self.changectx(rev)[name]
330 fctx = self.changectx(rev)[name]
331 return fctx.data(), fctx.flags()
331 return fctx.data(), fctx.flags()
332 except error.LookupError, err:
332 except error.LookupError, err:
333 raise IOError(err)
333 raise IOError(err)
334
334
335 def getchanges(self, rev):
335 def getchanges(self, rev):
336 ctx = self.changectx(rev)
336 ctx = self.changectx(rev)
337 parents = self.parents(ctx)
337 parents = self.parents(ctx)
338 if not parents:
338 if not parents:
339 files = sorted(ctx.manifest())
339 files = sorted(ctx.manifest())
340 # getcopies() is not needed for roots, but it is a simple way to
340 # getcopies() is not needed for roots, but it is a simple way to
341 # detect missing revlogs and abort on errors or populate
341 # detect missing revlogs and abort on errors or populate
342 # self.ignored
342 # self.ignored
343 self.getcopies(ctx, parents, files)
343 self.getcopies(ctx, parents, files)
344 return [(f, rev) for f in files if f not in self.ignored], {}
344 return [(f, rev) for f in files if f not in self.ignored], {}
345 if self._changescache and self._changescache[0] == rev:
345 if self._changescache and self._changescache[0] == rev:
346 m, a, r = self._changescache[1]
346 m, a, r = self._changescache[1]
347 else:
347 else:
348 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
348 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
349 # getcopies() detects missing revlogs early, run it before
349 # getcopies() detects missing revlogs early, run it before
350 # filtering the changes.
350 # filtering the changes.
351 copies = self.getcopies(ctx, parents, m + a)
351 copies = self.getcopies(ctx, parents, m + a)
352 changes = [(name, rev) for name in m + a + r
352 changes = [(name, rev) for name in m + a + r
353 if name not in self.ignored]
353 if name not in self.ignored]
354 return sorted(changes), copies
354 return sorted(changes), copies
355
355
356 def getcopies(self, ctx, parents, files):
356 def getcopies(self, ctx, parents, files):
357 copies = {}
357 copies = {}
358 for name in files:
358 for name in files:
359 if name in self.ignored:
359 if name in self.ignored:
360 continue
360 continue
361 try:
361 try:
362 copysource, _copynode = ctx.filectx(name).renamed()
362 copysource, _copynode = ctx.filectx(name).renamed()
363 if copysource in self.ignored:
363 if copysource in self.ignored:
364 continue
364 continue
365 # Ignore copy sources not in parent revisions
365 # Ignore copy sources not in parent revisions
366 found = False
366 found = False
367 for p in parents:
367 for p in parents:
368 if copysource in p:
368 if copysource in p:
369 found = True
369 found = True
370 break
370 break
371 if not found:
371 if not found:
372 continue
372 continue
373 copies[name] = copysource
373 copies[name] = copysource
374 except TypeError:
374 except TypeError:
375 pass
375 pass
376 except error.LookupError, e:
376 except error.LookupError, e:
377 if not self.ignoreerrors:
377 if not self.ignoreerrors:
378 raise
378 raise
379 self.ignored.add(name)
379 self.ignored.add(name)
380 self.ui.warn(_('ignoring: %s\n') % e)
380 self.ui.warn(_('ignoring: %s\n') % e)
381 return copies
381 return copies
382
382
383 def getcommit(self, rev):
383 def getcommit(self, rev):
384 ctx = self.changectx(rev)
384 ctx = self.changectx(rev)
385 parents = [p.hex() for p in self.parents(ctx)]
385 parents = [p.hex() for p in self.parents(ctx)]
386 if self.saverev:
386 if self.saverev:
387 crev = rev
387 crev = rev
388 else:
388 else:
389 crev = None
389 crev = None
390 return commit(author=ctx.user(),
390 return commit(author=ctx.user(),
391 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
391 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
392 desc=ctx.description(), rev=crev, parents=parents,
392 desc=ctx.description(), rev=crev, parents=parents,
393 branch=ctx.branch(), extra=ctx.extra(),
393 branch=ctx.branch(), extra=ctx.extra(),
394 sortkey=ctx.rev())
394 sortkey=ctx.rev())
395
395
396 def gettags(self):
396 def gettags(self):
397 tags = [t for t in self.repo.tagslist() if t[0] != 'tip']
397 # This will get written to .hgtags, filter non global tags out.
398 tags = [t for t in self.repo.tagslist()
399 if self.repo.tagtype(t[0]) == 'global']
398 return dict([(name, hex(node)) for name, node in tags
400 return dict([(name, hex(node)) for name, node in tags
399 if self.keep(node)])
401 if self.keep(node)])
400
402
401 def getchangedfiles(self, rev, i):
403 def getchangedfiles(self, rev, i):
402 ctx = self.changectx(rev)
404 ctx = self.changectx(rev)
403 parents = self.parents(ctx)
405 parents = self.parents(ctx)
404 if not parents and i is None:
406 if not parents and i is None:
405 i = 0
407 i = 0
406 changes = [], ctx.manifest().keys(), []
408 changes = [], ctx.manifest().keys(), []
407 else:
409 else:
408 i = i or 0
410 i = i or 0
409 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
411 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
410 changes = [[f for f in l if f not in self.ignored] for l in changes]
412 changes = [[f for f in l if f not in self.ignored] for l in changes]
411
413
412 if i == 0:
414 if i == 0:
413 self._changescache = (rev, changes)
415 self._changescache = (rev, changes)
414
416
415 return changes[0] + changes[1] + changes[2]
417 return changes[0] + changes[1] + changes[2]
416
418
417 def converted(self, rev, destrev):
419 def converted(self, rev, destrev):
418 if self.convertfp is None:
420 if self.convertfp is None:
419 self.convertfp = open(self.repo.join('shamap'), 'a')
421 self.convertfp = open(self.repo.join('shamap'), 'a')
420 self.convertfp.write('%s %s\n' % (destrev, rev))
422 self.convertfp.write('%s %s\n' % (destrev, rev))
421 self.convertfp.flush()
423 self.convertfp.flush()
422
424
423 def before(self):
425 def before(self):
424 self.ui.debug('run hg source pre-conversion action\n')
426 self.ui.debug('run hg source pre-conversion action\n')
425
427
426 def after(self):
428 def after(self):
427 self.ui.debug('run hg source post-conversion action\n')
429 self.ui.debug('run hg source post-conversion action\n')
428
430
429 def hasnativeorder(self):
431 def hasnativeorder(self):
430 return True
432 return True
431
433
432 def hasnativeclose(self):
434 def hasnativeclose(self):
433 return True
435 return True
434
436
435 def lookuprev(self, rev):
437 def lookuprev(self, rev):
436 try:
438 try:
437 return hex(self.repo.lookup(rev))
439 return hex(self.repo.lookup(rev))
438 except error.RepoError:
440 except error.RepoError:
439 return None
441 return None
440
442
441 def getbookmarks(self):
443 def getbookmarks(self):
442 return bookmarks.listbookmarks(self.repo)
444 return bookmarks.listbookmarks(self.repo)
443
445
444 def checkrevformat(self, revstr, mapname='splicemap'):
446 def checkrevformat(self, revstr, mapname='splicemap'):
445 """ Mercurial, revision string is a 40 byte hex """
447 """ Mercurial, revision string is a 40 byte hex """
446 self.checkhexformat(revstr, mapname)
448 self.checkhexformat(revstr, mapname)
@@ -1,392 +1,394
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 and bar'
12 $ hg ci -qAm 'add foo and bar'
13 $ hg rm foo
13 $ hg rm foo
14 $ hg ci -m 'remove foo'
14 $ hg ci -m 'remove foo'
15 $ mkdir foo
15 $ mkdir foo
16 $ echo file > foo/file
16 $ echo file > foo/file
17 $ hg ci -qAm 'add foo/file'
17 $ hg ci -qAm 'add foo/file'
18 $ hg tag some-tag
18 $ hg tag some-tag
19 $ hg tag -l local-tag
19 $ hg log
20 $ hg log
20 changeset: 3:593cbf6fb2b4
21 changeset: 3:593cbf6fb2b4
22 tag: local-tag
21 tag: tip
23 tag: tip
22 user: test
24 user: test
23 date: Thu Jan 01 00:00:00 1970 +0000
25 date: Thu Jan 01 00:00:00 1970 +0000
24 summary: Added tag some-tag for changeset ad681a868e44
26 summary: Added tag some-tag for changeset ad681a868e44
25
27
26 changeset: 2:ad681a868e44
28 changeset: 2:ad681a868e44
27 tag: some-tag
29 tag: some-tag
28 user: test
30 user: test
29 date: Thu Jan 01 00:00:00 1970 +0000
31 date: Thu Jan 01 00:00:00 1970 +0000
30 summary: add foo/file
32 summary: add foo/file
31
33
32 changeset: 1:cbba8ecc03b7
34 changeset: 1:cbba8ecc03b7
33 user: test
35 user: test
34 date: Thu Jan 01 00:00:00 1970 +0000
36 date: Thu Jan 01 00:00:00 1970 +0000
35 summary: remove foo
37 summary: remove foo
36
38
37 changeset: 0:327daa9251fa
39 changeset: 0:327daa9251fa
38 user: test
40 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
41 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: add foo and bar
42 summary: add foo and bar
41
43
42 $ cd ..
44 $ cd ..
43 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
45 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
44 initializing destination new repository
46 initializing destination new repository
45 scanning source...
47 scanning source...
46 sorting...
48 sorting...
47 converting...
49 converting...
48 3 add foo and bar
50 3 add foo and bar
49 2 remove foo
51 2 remove foo
50 1 add foo/file
52 1 add foo/file
51 0 Added tag some-tag for changeset ad681a868e44
53 0 Added tag some-tag for changeset ad681a868e44
52 $ cd new
54 $ cd new
53 $ hg out ../orig
55 $ hg out ../orig
54 comparing with ../orig
56 comparing with ../orig
55 searching for changes
57 searching for changes
56 no changes found
58 no changes found
57 [1]
59 [1]
58
60
59 dirstate should be empty:
61 dirstate should be empty:
60
62
61 $ hg debugstate
63 $ hg debugstate
62 $ hg parents -q
64 $ hg parents -q
63 $ hg up -C
65 $ hg up -C
64 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
66 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
65 $ hg copy bar baz
67 $ hg copy bar baz
66
68
67 put something in the dirstate:
69 put something in the dirstate:
68
70
69 $ hg debugstate > debugstate
71 $ hg debugstate > debugstate
70 $ grep baz debugstate
72 $ grep baz debugstate
71 a 0 -1 unset baz
73 a 0 -1 unset baz
72 copy: bar -> baz
74 copy: bar -> baz
73
75
74 add a new revision in the original repo
76 add a new revision in the original repo
75
77
76 $ cd ../orig
78 $ cd ../orig
77 $ echo baz > baz
79 $ echo baz > baz
78 $ hg ci -qAm 'add baz'
80 $ hg ci -qAm 'add baz'
79 $ cd ..
81 $ cd ..
80 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
82 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
81 scanning source...
83 scanning source...
82 sorting...
84 sorting...
83 converting...
85 converting...
84 0 add baz
86 0 add baz
85 $ cd new
87 $ cd new
86 $ hg out ../orig
88 $ hg out ../orig
87 comparing with ../orig
89 comparing with ../orig
88 searching for changes
90 searching for changes
89 no changes found
91 no changes found
90 [1]
92 [1]
91
93
92 dirstate should be the same (no output below):
94 dirstate should be the same (no output below):
93
95
94 $ hg debugstate > new-debugstate
96 $ hg debugstate > new-debugstate
95 $ diff debugstate new-debugstate
97 $ diff debugstate new-debugstate
96
98
97 no copies
99 no copies
98
100
99 $ hg up -C
101 $ hg up -C
100 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 $ hg debugrename baz
103 $ hg debugrename baz
102 baz not renamed
104 baz not renamed
103 $ cd ..
105 $ cd ..
104
106
105 test tag rewriting
107 test tag rewriting
106
108
107 $ cat > filemap <<EOF
109 $ cat > filemap <<EOF
108 > exclude foo
110 > exclude foo
109 > EOF
111 > EOF
110 $ hg convert --filemap filemap orig new-filemap 2>&1 | grep -v 'subversion python bindings could not be loaded'
112 $ hg convert --filemap filemap orig new-filemap 2>&1 | grep -v 'subversion python bindings could not be loaded'
111 initializing destination new-filemap repository
113 initializing destination new-filemap repository
112 scanning source...
114 scanning source...
113 sorting...
115 sorting...
114 converting...
116 converting...
115 4 add foo and bar
117 4 add foo and bar
116 3 remove foo
118 3 remove foo
117 2 add foo/file
119 2 add foo/file
118 1 Added tag some-tag for changeset ad681a868e44
120 1 Added tag some-tag for changeset ad681a868e44
119 0 add baz
121 0 add baz
120 $ cd new-filemap
122 $ cd new-filemap
121 $ hg tags
123 $ hg tags
122 tip 2:3c74706b1ff8
124 tip 2:3c74706b1ff8
123 some-tag 0:ba8636729451
125 some-tag 0:ba8636729451
124 $ cd ..
126 $ cd ..
125
127
126
128
127 Test cases for hg-hg roundtrip
129 Test cases for hg-hg roundtrip
128
130
129 Helper
131 Helper
130
132
131 $ glog()
133 $ glog()
132 > {
134 > {
133 > hg log -G --template '{rev} {node|short} "{desc}" files: {files}\n' $*
135 > hg log -G --template '{rev} {node|short} "{desc}" files: {files}\n' $*
134 > }
136 > }
135
137
136 Create a tricky source repo
138 Create a tricky source repo
137
139
138 $ hg init source
140 $ hg init source
139 $ cd source
141 $ cd source
140
142
141 $ echo 0 > 0
143 $ echo 0 > 0
142 $ hg ci -Aqm '0: add 0'
144 $ hg ci -Aqm '0: add 0'
143 $ echo a > a
145 $ echo a > a
144 $ mkdir dir
146 $ mkdir dir
145 $ echo b > dir/b
147 $ echo b > dir/b
146 $ hg ci -qAm '1: add a and dir/b'
148 $ hg ci -qAm '1: add a and dir/b'
147 $ echo c > dir/c
149 $ echo c > dir/c
148 $ hg ci -qAm '2: add dir/c'
150 $ hg ci -qAm '2: add dir/c'
149 $ hg copy a e
151 $ hg copy a e
150 $ echo b >> b
152 $ echo b >> b
151 $ hg ci -qAm '3: copy a to e, change b'
153 $ hg ci -qAm '3: copy a to e, change b'
152 $ hg up -qr -3
154 $ hg up -qr -3
153 $ echo a >> a
155 $ echo a >> a
154 $ hg ci -qAm '4: change a'
156 $ hg ci -qAm '4: change a'
155 $ hg merge
157 $ hg merge
156 merging a and e to e
158 merging a and e to e
157 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
159 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
158 (branch merge, don't forget to commit)
160 (branch merge, don't forget to commit)
159 $ hg copy b dir/d
161 $ hg copy b dir/d
160 $ hg ci -qAm '5: merge 2 and 3, copy b to dir/d'
162 $ hg ci -qAm '5: merge 2 and 3, copy b to dir/d'
161 $ echo a >> a
163 $ echo a >> a
162 $ hg ci -qAm '6: change a'
164 $ hg ci -qAm '6: change a'
163
165
164 $ hg mani
166 $ hg mani
165 0
167 0
166 a
168 a
167 b
169 b
168 dir/b
170 dir/b
169 dir/c
171 dir/c
170 dir/d
172 dir/d
171 e
173 e
172 $ glog
174 $ glog
173 @ 6 0613c8e59a3d "6: change a" files: a
175 @ 6 0613c8e59a3d "6: change a" files: a
174 |
176 |
175 o 5 717e9b37cdb7 "5: merge 2 and 3, copy b to dir/d" files: dir/d e
177 o 5 717e9b37cdb7 "5: merge 2 and 3, copy b to dir/d" files: dir/d e
176 |\
178 |\
177 | o 4 86a55cb968d5 "4: change a" files: a
179 | o 4 86a55cb968d5 "4: change a" files: a
178 | |
180 | |
179 o | 3 0e6e235919dd "3: copy a to e, change b" files: b e
181 o | 3 0e6e235919dd "3: copy a to e, change b" files: b e
180 | |
182 | |
181 o | 2 0394b0d5e4f7 "2: add dir/c" files: dir/c
183 o | 2 0394b0d5e4f7 "2: add dir/c" files: dir/c
182 |/
184 |/
183 o 1 333546584845 "1: add a and dir/b" files: a dir/b
185 o 1 333546584845 "1: add a and dir/b" files: a dir/b
184 |
186 |
185 o 0 d1a24e2ebd23 "0: add 0" files: 0
187 o 0 d1a24e2ebd23 "0: add 0" files: 0
186
188
187 $ cd ..
189 $ cd ..
188
190
189 Convert excluding rev 0 and dir/ (and thus rev2):
191 Convert excluding rev 0 and dir/ (and thus rev2):
190
192
191 $ cat << EOF > filemap
193 $ cat << EOF > filemap
192 > exclude dir
194 > exclude dir
193 > EOF
195 > EOF
194
196
195 $ hg convert --filemap filemap source dest --config convert.hg.revs=1::
197 $ hg convert --filemap filemap source dest --config convert.hg.revs=1::
196 initializing destination dest repository
198 initializing destination dest repository
197 scanning source...
199 scanning source...
198 sorting...
200 sorting...
199 converting...
201 converting...
200 5 1: add a and dir/b
202 5 1: add a and dir/b
201 4 2: add dir/c
203 4 2: add dir/c
202 3 3: copy a to e, change b
204 3 3: copy a to e, change b
203 2 4: change a
205 2 4: change a
204 1 5: merge 2 and 3, copy b to dir/d
206 1 5: merge 2 and 3, copy b to dir/d
205 0 6: change a
207 0 6: change a
206
208
207 Verify that conversion skipped rev 2:
209 Verify that conversion skipped rev 2:
208
210
209 $ glog -R dest
211 $ glog -R dest
210 o 4 78814e84a217 "6: change a" files: a
212 o 4 78814e84a217 "6: change a" files: a
211 |
213 |
212 o 3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
214 o 3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
213 |\
215 |\
214 | o 2 ab40a95b0072 "4: change a" files: a
216 | o 2 ab40a95b0072 "4: change a" files: a
215 | |
217 | |
216 o | 1 bd51f17597bf "3: copy a to e, change b" files: b e
218 o | 1 bd51f17597bf "3: copy a to e, change b" files: b e
217 |/
219 |/
218 o 0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
220 o 0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
219
221
220
222
221 Verify mapping correct in both directions:
223 Verify mapping correct in both directions:
222
224
223 $ cat source/.hg/shamap
225 $ cat source/.hg/shamap
224 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5 333546584845f70c4cfecb992341aaef0e708166
226 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5 333546584845f70c4cfecb992341aaef0e708166
225 bd51f17597bf32268e68a560b206898c3960cda2 0e6e235919dd8e9285ba8eb5adf703af9ad99378
227 bd51f17597bf32268e68a560b206898c3960cda2 0e6e235919dd8e9285ba8eb5adf703af9ad99378
226 ab40a95b00725307e79c2fd271000aa8af9759f4 86a55cb968d51770cba2a1630d6cc637b574580a
228 ab40a95b00725307e79c2fd271000aa8af9759f4 86a55cb968d51770cba2a1630d6cc637b574580a
227 f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d
229 f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d
228 78814e84a217894517c2de392b903ed05e6871a4 0613c8e59a3ddb9789072ef52f1ed13496489bb4
230 78814e84a217894517c2de392b903ed05e6871a4 0613c8e59a3ddb9789072ef52f1ed13496489bb4
229 $ cat dest/.hg/shamap
231 $ cat dest/.hg/shamap
230 333546584845f70c4cfecb992341aaef0e708166 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
232 333546584845f70c4cfecb992341aaef0e708166 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
231 0394b0d5e4f761ced559fd0bbdc6afc16cb3f7d1 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
233 0394b0d5e4f761ced559fd0bbdc6afc16cb3f7d1 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
232 0e6e235919dd8e9285ba8eb5adf703af9ad99378 bd51f17597bf32268e68a560b206898c3960cda2
234 0e6e235919dd8e9285ba8eb5adf703af9ad99378 bd51f17597bf32268e68a560b206898c3960cda2
233 86a55cb968d51770cba2a1630d6cc637b574580a ab40a95b00725307e79c2fd271000aa8af9759f4
235 86a55cb968d51770cba2a1630d6cc637b574580a ab40a95b00725307e79c2fd271000aa8af9759f4
234 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba
236 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba
235 0613c8e59a3ddb9789072ef52f1ed13496489bb4 78814e84a217894517c2de392b903ed05e6871a4
237 0613c8e59a3ddb9789072ef52f1ed13496489bb4 78814e84a217894517c2de392b903ed05e6871a4
236
238
237 Verify meta data converted correctly:
239 Verify meta data converted correctly:
238
240
239 $ hg -R dest log -r 1 --debug -p --git
241 $ hg -R dest log -r 1 --debug -p --git
240 changeset: 1:bd51f17597bf32268e68a560b206898c3960cda2
242 changeset: 1:bd51f17597bf32268e68a560b206898c3960cda2
241 phase: draft
243 phase: draft
242 parent: 0:a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
244 parent: 0:a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
243 parent: -1:0000000000000000000000000000000000000000
245 parent: -1:0000000000000000000000000000000000000000
244 manifest: 1:040c72ed9b101773c24ac314776bfc846943781f
246 manifest: 1:040c72ed9b101773c24ac314776bfc846943781f
245 user: test
247 user: test
246 date: Thu Jan 01 00:00:00 1970 +0000
248 date: Thu Jan 01 00:00:00 1970 +0000
247 files+: b e
249 files+: b e
248 extra: branch=default
250 extra: branch=default
249 description:
251 description:
250 3: copy a to e, change b
252 3: copy a to e, change b
251
253
252
254
253 diff --git a/b b/b
255 diff --git a/b b/b
254 new file mode 100644
256 new file mode 100644
255 --- /dev/null
257 --- /dev/null
256 +++ b/b
258 +++ b/b
257 @@ -0,0 +1,1 @@
259 @@ -0,0 +1,1 @@
258 +b
260 +b
259 diff --git a/a b/e
261 diff --git a/a b/e
260 copy from a
262 copy from a
261 copy to e
263 copy to e
262
264
263 Verify files included and excluded correctly:
265 Verify files included and excluded correctly:
264
266
265 $ hg -R dest manifest -r tip
267 $ hg -R dest manifest -r tip
266 0
268 0
267 a
269 a
268 b
270 b
269 e
271 e
270
272
271
273
272 Make changes in dest and convert back:
274 Make changes in dest and convert back:
273
275
274 $ hg -R dest up -q
276 $ hg -R dest up -q
275 $ echo dest > dest/dest
277 $ echo dest > dest/dest
276 $ hg -R dest ci -Aqm 'change in dest'
278 $ hg -R dest ci -Aqm 'change in dest'
277 $ hg -R dest tip
279 $ hg -R dest tip
278 changeset: 5:a2e0e3cc6d1d
280 changeset: 5:a2e0e3cc6d1d
279 tag: tip
281 tag: tip
280 user: test
282 user: test
281 date: Thu Jan 01 00:00:00 1970 +0000
283 date: Thu Jan 01 00:00:00 1970 +0000
282 summary: change in dest
284 summary: change in dest
283
285
284
286
285 (converting merges back after using a filemap will probably cause chaos so we
287 (converting merges back after using a filemap will probably cause chaos so we
286 exclude merges.)
288 exclude merges.)
287
289
288 $ hg convert dest source --config convert.hg.revs='!merge()'
290 $ hg convert dest source --config convert.hg.revs='!merge()'
289 scanning source...
291 scanning source...
290 sorting...
292 sorting...
291 converting...
293 converting...
292 0 change in dest
294 0 change in dest
293
295
294 Verify the conversion back:
296 Verify the conversion back:
295
297
296 $ hg -R source log --debug -r tip
298 $ hg -R source log --debug -r tip
297 changeset: 7:e6d364a69ff1248b2099e603b0c145504cade6f0
299 changeset: 7:e6d364a69ff1248b2099e603b0c145504cade6f0
298 tag: tip
300 tag: tip
299 phase: draft
301 phase: draft
300 parent: 6:0613c8e59a3ddb9789072ef52f1ed13496489bb4
302 parent: 6:0613c8e59a3ddb9789072ef52f1ed13496489bb4
301 parent: -1:0000000000000000000000000000000000000000
303 parent: -1:0000000000000000000000000000000000000000
302 manifest: 7:aa3e9542f3b76d4f1f1b2e9c7ce9dbb48b6a95ec
304 manifest: 7:aa3e9542f3b76d4f1f1b2e9c7ce9dbb48b6a95ec
303 user: test
305 user: test
304 date: Thu Jan 01 00:00:00 1970 +0000
306 date: Thu Jan 01 00:00:00 1970 +0000
305 files+: dest
307 files+: dest
306 extra: branch=default
308 extra: branch=default
307 description:
309 description:
308 change in dest
310 change in dest
309
311
310
312
311 Files that had been excluded are still present:
313 Files that had been excluded are still present:
312
314
313 $ hg -R source manifest -r tip
315 $ hg -R source manifest -r tip
314 0
316 0
315 a
317 a
316 b
318 b
317 dest
319 dest
318 dir/b
320 dir/b
319 dir/c
321 dir/c
320 dir/d
322 dir/d
321 e
323 e
322
324
323 More source changes
325 More source changes
324
326
325 $ cd source
327 $ cd source
326 $ echo 1 >> a
328 $ echo 1 >> a
327 $ hg ci -m '8: source first branch'
329 $ hg ci -m '8: source first branch'
328 created new head
330 created new head
329 $ hg up -qr -2
331 $ hg up -qr -2
330 $ echo 2 >> a
332 $ echo 2 >> a
331 $ hg ci -m '9: source second branch'
333 $ hg ci -m '9: source second branch'
332 $ hg merge -q --tool internal:local
334 $ hg merge -q --tool internal:local
333 $ hg ci -m '10: source merge'
335 $ hg ci -m '10: source merge'
334 $ echo >> a
336 $ echo >> a
335 $ hg ci -m '11: source change'
337 $ hg ci -m '11: source change'
336
338
337 $ hg mani
339 $ hg mani
338 0
340 0
339 a
341 a
340 b
342 b
341 dest
343 dest
342 dir/b
344 dir/b
343 dir/c
345 dir/c
344 dir/d
346 dir/d
345 e
347 e
346
348
347 $ glog -r 6:
349 $ glog -r 6:
348 @ 11 0c8927d1f7f4 "11: source change" files: a
350 @ 11 0c8927d1f7f4 "11: source change" files: a
349 |
351 |
350 o 10 9ccb7ee8d261 "10: source merge" files: a
352 o 10 9ccb7ee8d261 "10: source merge" files: a
351 |\
353 |\
352 | o 9 f131b1518dba "9: source second branch" files: a
354 | o 9 f131b1518dba "9: source second branch" files: a
353 | |
355 | |
354 o | 8 669cf0e74b50 "8: source first branch" files: a
356 o | 8 669cf0e74b50 "8: source first branch" files: a
355 | |
357 | |
356 | o 7 e6d364a69ff1 "change in dest" files: dest
358 | o 7 e6d364a69ff1 "change in dest" files: dest
357 |/
359 |/
358 o 6 0613c8e59a3d "6: change a" files: a
360 o 6 0613c8e59a3d "6: change a" files: a
359 |
361 |
360 $ cd ..
362 $ cd ..
361
363
362 $ hg convert --filemap filemap source dest --config convert.hg.revs=3:
364 $ hg convert --filemap filemap source dest --config convert.hg.revs=3:
363 scanning source...
365 scanning source...
364 sorting...
366 sorting...
365 converting...
367 converting...
366 3 8: source first branch
368 3 8: source first branch
367 2 9: source second branch
369 2 9: source second branch
368 1 10: source merge
370 1 10: source merge
369 0 11: source change
371 0 11: source change
370
372
371 $ glog -R dest
373 $ glog -R dest
372 o 9 8432d597b263 "11: source change" files: a
374 o 9 8432d597b263 "11: source change" files: a
373 |
375 |
374 o 8 632ffacdcd6f "10: source merge" files: a
376 o 8 632ffacdcd6f "10: source merge" files: a
375 |\
377 |\
376 | o 7 049cfee90ee6 "9: source second branch" files: a
378 | o 7 049cfee90ee6 "9: source second branch" files: a
377 | |
379 | |
378 o | 6 9b6845e036e5 "8: source first branch" files: a
380 o | 6 9b6845e036e5 "8: source first branch" files: a
379 | |
381 | |
380 | @ 5 a2e0e3cc6d1d "change in dest" files: dest
382 | @ 5 a2e0e3cc6d1d "change in dest" files: dest
381 |/
383 |/
382 o 4 78814e84a217 "6: change a" files: a
384 o 4 78814e84a217 "6: change a" files: a
383 |
385 |
384 o 3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
386 o 3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
385 |\
387 |\
386 | o 2 ab40a95b0072 "4: change a" files: a
388 | o 2 ab40a95b0072 "4: change a" files: a
387 | |
389 | |
388 o | 1 bd51f17597bf "3: copy a to e, change b" files: b e
390 o | 1 bd51f17597bf "3: copy a to e, change b" files: b e
389 |/
391 |/
390 o 0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
392 o 0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
391
393
392 $ cd ..
394 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now