##// END OF EJS Templates
convert: apply the appropriate phases to the destination (issue4165)...
Matt Harbison -
r25571:1abfe639 default
parent child Browse files
Show More
@@ -1,470 +1,471
1 # common.py - common code for the convert extension
1 # common.py - common code for the 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 import base64, errno, subprocess, os, datetime, re
8 import base64, errno, subprocess, os, datetime, re
9 import cPickle as pickle
9 import cPickle as pickle
10 from mercurial import util
10 from mercurial import phases, util
11 from mercurial.i18n import _
11 from mercurial.i18n import _
12
12
13 propertycache = util.propertycache
13 propertycache = util.propertycache
14
14
15 def encodeargs(args):
15 def encodeargs(args):
16 def encodearg(s):
16 def encodearg(s):
17 lines = base64.encodestring(s)
17 lines = base64.encodestring(s)
18 lines = [l.splitlines()[0] for l in lines]
18 lines = [l.splitlines()[0] for l in lines]
19 return ''.join(lines)
19 return ''.join(lines)
20
20
21 s = pickle.dumps(args)
21 s = pickle.dumps(args)
22 return encodearg(s)
22 return encodearg(s)
23
23
24 def decodeargs(s):
24 def decodeargs(s):
25 s = base64.decodestring(s)
25 s = base64.decodestring(s)
26 return pickle.loads(s)
26 return pickle.loads(s)
27
27
28 class MissingTool(Exception):
28 class MissingTool(Exception):
29 pass
29 pass
30
30
31 def checktool(exe, name=None, abort=True):
31 def checktool(exe, name=None, abort=True):
32 name = name or exe
32 name = name or exe
33 if not util.findexe(exe):
33 if not util.findexe(exe):
34 if abort:
34 if abort:
35 exc = util.Abort
35 exc = util.Abort
36 else:
36 else:
37 exc = MissingTool
37 exc = MissingTool
38 raise exc(_('cannot find required "%s" tool') % name)
38 raise exc(_('cannot find required "%s" tool') % name)
39
39
40 class NoRepo(Exception):
40 class NoRepo(Exception):
41 pass
41 pass
42
42
43 SKIPREV = 'SKIP'
43 SKIPREV = 'SKIP'
44
44
45 class commit(object):
45 class commit(object):
46 def __init__(self, author, date, desc, parents, branch=None, rev=None,
46 def __init__(self, author, date, desc, parents, branch=None, rev=None,
47 extra={}, sortkey=None, saverev=True):
47 extra={}, sortkey=None, saverev=True, phase=phases.draft):
48 self.author = author or 'unknown'
48 self.author = author or 'unknown'
49 self.date = date or '0 0'
49 self.date = date or '0 0'
50 self.desc = desc
50 self.desc = desc
51 self.parents = parents
51 self.parents = parents
52 self.branch = branch
52 self.branch = branch
53 self.rev = rev
53 self.rev = rev
54 self.extra = extra
54 self.extra = extra
55 self.sortkey = sortkey
55 self.sortkey = sortkey
56 self.saverev = saverev
56 self.saverev = saverev
57 self.phase = phase
57
58
58 class converter_source(object):
59 class converter_source(object):
59 """Conversion source interface"""
60 """Conversion source interface"""
60
61
61 def __init__(self, ui, path=None, rev=None):
62 def __init__(self, ui, path=None, rev=None):
62 """Initialize conversion source (or raise NoRepo("message")
63 """Initialize conversion source (or raise NoRepo("message")
63 exception if path is not a valid repository)"""
64 exception if path is not a valid repository)"""
64 self.ui = ui
65 self.ui = ui
65 self.path = path
66 self.path = path
66 self.rev = rev
67 self.rev = rev
67
68
68 self.encoding = 'utf-8'
69 self.encoding = 'utf-8'
69
70
70 def checkhexformat(self, revstr, mapname='splicemap'):
71 def checkhexformat(self, revstr, mapname='splicemap'):
71 """ fails if revstr is not a 40 byte hex. mercurial and git both uses
72 """ fails if revstr is not a 40 byte hex. mercurial and git both uses
72 such format for their revision numbering
73 such format for their revision numbering
73 """
74 """
74 if not re.match(r'[0-9a-fA-F]{40,40}$', revstr):
75 if not re.match(r'[0-9a-fA-F]{40,40}$', revstr):
75 raise util.Abort(_('%s entry %s is not a valid revision'
76 raise util.Abort(_('%s entry %s is not a valid revision'
76 ' identifier') % (mapname, revstr))
77 ' identifier') % (mapname, revstr))
77
78
78 def before(self):
79 def before(self):
79 pass
80 pass
80
81
81 def after(self):
82 def after(self):
82 pass
83 pass
83
84
84 def setrevmap(self, revmap):
85 def setrevmap(self, revmap):
85 """set the map of already-converted revisions"""
86 """set the map of already-converted revisions"""
86 pass
87 pass
87
88
88 def getheads(self):
89 def getheads(self):
89 """Return a list of this repository's heads"""
90 """Return a list of this repository's heads"""
90 raise NotImplementedError
91 raise NotImplementedError
91
92
92 def getfile(self, name, rev):
93 def getfile(self, name, rev):
93 """Return a pair (data, mode) where data is the file content
94 """Return a pair (data, mode) where data is the file content
94 as a string and mode one of '', 'x' or 'l'. rev is the
95 as a string and mode one of '', 'x' or 'l'. rev is the
95 identifier returned by a previous call to getchanges().
96 identifier returned by a previous call to getchanges().
96 Data is None if file is missing/deleted in rev.
97 Data is None if file is missing/deleted in rev.
97 """
98 """
98 raise NotImplementedError
99 raise NotImplementedError
99
100
100 def getchanges(self, version, full):
101 def getchanges(self, version, full):
101 """Returns a tuple of (files, copies, cleanp2).
102 """Returns a tuple of (files, copies, cleanp2).
102
103
103 files is a sorted list of (filename, id) tuples for all files
104 files is a sorted list of (filename, id) tuples for all files
104 changed between version and its first parent returned by
105 changed between version and its first parent returned by
105 getcommit(). If full, all files in that revision is returned.
106 getcommit(). If full, all files in that revision is returned.
106 id is the source revision id of the file.
107 id is the source revision id of the file.
107
108
108 copies is a dictionary of dest: source
109 copies is a dictionary of dest: source
109
110
110 cleanp2 is the set of files filenames that are clean against p2.
111 cleanp2 is the set of files filenames that are clean against p2.
111 (Files that are clean against p1 are already not in files (unless
112 (Files that are clean against p1 are already not in files (unless
112 full). This makes it possible to handle p2 clean files similarly.)
113 full). This makes it possible to handle p2 clean files similarly.)
113 """
114 """
114 raise NotImplementedError
115 raise NotImplementedError
115
116
116 def getcommit(self, version):
117 def getcommit(self, version):
117 """Return the commit object for version"""
118 """Return the commit object for version"""
118 raise NotImplementedError
119 raise NotImplementedError
119
120
120 def numcommits(self):
121 def numcommits(self):
121 """Return the number of commits in this source.
122 """Return the number of commits in this source.
122
123
123 If unknown, return None.
124 If unknown, return None.
124 """
125 """
125 return None
126 return None
126
127
127 def gettags(self):
128 def gettags(self):
128 """Return the tags as a dictionary of name: revision
129 """Return the tags as a dictionary of name: revision
129
130
130 Tag names must be UTF-8 strings.
131 Tag names must be UTF-8 strings.
131 """
132 """
132 raise NotImplementedError
133 raise NotImplementedError
133
134
134 def recode(self, s, encoding=None):
135 def recode(self, s, encoding=None):
135 if not encoding:
136 if not encoding:
136 encoding = self.encoding or 'utf-8'
137 encoding = self.encoding or 'utf-8'
137
138
138 if isinstance(s, unicode):
139 if isinstance(s, unicode):
139 return s.encode("utf-8")
140 return s.encode("utf-8")
140 try:
141 try:
141 return s.decode(encoding).encode("utf-8")
142 return s.decode(encoding).encode("utf-8")
142 except UnicodeError:
143 except UnicodeError:
143 try:
144 try:
144 return s.decode("latin-1").encode("utf-8")
145 return s.decode("latin-1").encode("utf-8")
145 except UnicodeError:
146 except UnicodeError:
146 return s.decode(encoding, "replace").encode("utf-8")
147 return s.decode(encoding, "replace").encode("utf-8")
147
148
148 def getchangedfiles(self, rev, i):
149 def getchangedfiles(self, rev, i):
149 """Return the files changed by rev compared to parent[i].
150 """Return the files changed by rev compared to parent[i].
150
151
151 i is an index selecting one of the parents of rev. The return
152 i is an index selecting one of the parents of rev. The return
152 value should be the list of files that are different in rev and
153 value should be the list of files that are different in rev and
153 this parent.
154 this parent.
154
155
155 If rev has no parents, i is None.
156 If rev has no parents, i is None.
156
157
157 This function is only needed to support --filemap
158 This function is only needed to support --filemap
158 """
159 """
159 raise NotImplementedError
160 raise NotImplementedError
160
161
161 def converted(self, rev, sinkrev):
162 def converted(self, rev, sinkrev):
162 '''Notify the source that a revision has been converted.'''
163 '''Notify the source that a revision has been converted.'''
163 pass
164 pass
164
165
165 def hasnativeorder(self):
166 def hasnativeorder(self):
166 """Return true if this source has a meaningful, native revision
167 """Return true if this source has a meaningful, native revision
167 order. For instance, Mercurial revisions are store sequentially
168 order. For instance, Mercurial revisions are store sequentially
168 while there is no such global ordering with Darcs.
169 while there is no such global ordering with Darcs.
169 """
170 """
170 return False
171 return False
171
172
172 def hasnativeclose(self):
173 def hasnativeclose(self):
173 """Return true if this source has ability to close branch.
174 """Return true if this source has ability to close branch.
174 """
175 """
175 return False
176 return False
176
177
177 def lookuprev(self, rev):
178 def lookuprev(self, rev):
178 """If rev is a meaningful revision reference in source, return
179 """If rev is a meaningful revision reference in source, return
179 the referenced identifier in the same format used by getcommit().
180 the referenced identifier in the same format used by getcommit().
180 return None otherwise.
181 return None otherwise.
181 """
182 """
182 return None
183 return None
183
184
184 def getbookmarks(self):
185 def getbookmarks(self):
185 """Return the bookmarks as a dictionary of name: revision
186 """Return the bookmarks as a dictionary of name: revision
186
187
187 Bookmark names are to be UTF-8 strings.
188 Bookmark names are to be UTF-8 strings.
188 """
189 """
189 return {}
190 return {}
190
191
191 def checkrevformat(self, revstr, mapname='splicemap'):
192 def checkrevformat(self, revstr, mapname='splicemap'):
192 """revstr is a string that describes a revision in the given
193 """revstr is a string that describes a revision in the given
193 source control system. Return true if revstr has correct
194 source control system. Return true if revstr has correct
194 format.
195 format.
195 """
196 """
196 return True
197 return True
197
198
198 class converter_sink(object):
199 class converter_sink(object):
199 """Conversion sink (target) interface"""
200 """Conversion sink (target) interface"""
200
201
201 def __init__(self, ui, path):
202 def __init__(self, ui, path):
202 """Initialize conversion sink (or raise NoRepo("message")
203 """Initialize conversion sink (or raise NoRepo("message")
203 exception if path is not a valid repository)
204 exception if path is not a valid repository)
204
205
205 created is a list of paths to remove if a fatal error occurs
206 created is a list of paths to remove if a fatal error occurs
206 later"""
207 later"""
207 self.ui = ui
208 self.ui = ui
208 self.path = path
209 self.path = path
209 self.created = []
210 self.created = []
210
211
211 def revmapfile(self):
212 def revmapfile(self):
212 """Path to a file that will contain lines
213 """Path to a file that will contain lines
213 source_rev_id sink_rev_id
214 source_rev_id sink_rev_id
214 mapping equivalent revision identifiers for each system."""
215 mapping equivalent revision identifiers for each system."""
215 raise NotImplementedError
216 raise NotImplementedError
216
217
217 def authorfile(self):
218 def authorfile(self):
218 """Path to a file that will contain lines
219 """Path to a file that will contain lines
219 srcauthor=dstauthor
220 srcauthor=dstauthor
220 mapping equivalent authors identifiers for each system."""
221 mapping equivalent authors identifiers for each system."""
221 return None
222 return None
222
223
223 def putcommit(self, files, copies, parents, commit, source, revmap, full,
224 def putcommit(self, files, copies, parents, commit, source, revmap, full,
224 cleanp2):
225 cleanp2):
225 """Create a revision with all changed files listed in 'files'
226 """Create a revision with all changed files listed in 'files'
226 and having listed parents. 'commit' is a commit object
227 and having listed parents. 'commit' is a commit object
227 containing at a minimum the author, date, and message for this
228 containing at a minimum the author, date, and message for this
228 changeset. 'files' is a list of (path, version) tuples,
229 changeset. 'files' is a list of (path, version) tuples,
229 'copies' is a dictionary mapping destinations to sources,
230 'copies' is a dictionary mapping destinations to sources,
230 'source' is the source repository, and 'revmap' is a mapfile
231 'source' is the source repository, and 'revmap' is a mapfile
231 of source revisions to converted revisions. Only getfile() and
232 of source revisions to converted revisions. Only getfile() and
232 lookuprev() should be called on 'source'. 'full' means that 'files'
233 lookuprev() should be called on 'source'. 'full' means that 'files'
233 is complete and all other files should be removed.
234 is complete and all other files should be removed.
234 'cleanp2' is a set of the filenames that are unchanged from p2
235 'cleanp2' is a set of the filenames that are unchanged from p2
235 (only in the common merge case where there two parents).
236 (only in the common merge case where there two parents).
236
237
237 Note that the sink repository is not told to update itself to
238 Note that the sink repository is not told to update itself to
238 a particular revision (or even what that revision would be)
239 a particular revision (or even what that revision would be)
239 before it receives the file data.
240 before it receives the file data.
240 """
241 """
241 raise NotImplementedError
242 raise NotImplementedError
242
243
243 def puttags(self, tags):
244 def puttags(self, tags):
244 """Put tags into sink.
245 """Put tags into sink.
245
246
246 tags: {tagname: sink_rev_id, ...} where tagname is an UTF-8 string.
247 tags: {tagname: sink_rev_id, ...} where tagname is an UTF-8 string.
247 Return a pair (tag_revision, tag_parent_revision), or (None, None)
248 Return a pair (tag_revision, tag_parent_revision), or (None, None)
248 if nothing was changed.
249 if nothing was changed.
249 """
250 """
250 raise NotImplementedError
251 raise NotImplementedError
251
252
252 def setbranch(self, branch, pbranches):
253 def setbranch(self, branch, pbranches):
253 """Set the current branch name. Called before the first putcommit
254 """Set the current branch name. Called before the first putcommit
254 on the branch.
255 on the branch.
255 branch: branch name for subsequent commits
256 branch: branch name for subsequent commits
256 pbranches: (converted parent revision, parent branch) tuples"""
257 pbranches: (converted parent revision, parent branch) tuples"""
257 pass
258 pass
258
259
259 def setfilemapmode(self, active):
260 def setfilemapmode(self, active):
260 """Tell the destination that we're using a filemap
261 """Tell the destination that we're using a filemap
261
262
262 Some converter_sources (svn in particular) can claim that a file
263 Some converter_sources (svn in particular) can claim that a file
263 was changed in a revision, even if there was no change. This method
264 was changed in a revision, even if there was no change. This method
264 tells the destination that we're using a filemap and that it should
265 tells the destination that we're using a filemap and that it should
265 filter empty revisions.
266 filter empty revisions.
266 """
267 """
267 pass
268 pass
268
269
269 def before(self):
270 def before(self):
270 pass
271 pass
271
272
272 def after(self):
273 def after(self):
273 pass
274 pass
274
275
275 def putbookmarks(self, bookmarks):
276 def putbookmarks(self, bookmarks):
276 """Put bookmarks into sink.
277 """Put bookmarks into sink.
277
278
278 bookmarks: {bookmarkname: sink_rev_id, ...}
279 bookmarks: {bookmarkname: sink_rev_id, ...}
279 where bookmarkname is an UTF-8 string.
280 where bookmarkname is an UTF-8 string.
280 """
281 """
281 pass
282 pass
282
283
283 def hascommitfrommap(self, rev):
284 def hascommitfrommap(self, rev):
284 """Return False if a rev mentioned in a filemap is known to not be
285 """Return False if a rev mentioned in a filemap is known to not be
285 present."""
286 present."""
286 raise NotImplementedError
287 raise NotImplementedError
287
288
288 def hascommitforsplicemap(self, rev):
289 def hascommitforsplicemap(self, rev):
289 """This method is for the special needs for splicemap handling and not
290 """This method is for the special needs for splicemap handling and not
290 for general use. Returns True if the sink contains rev, aborts on some
291 for general use. Returns True if the sink contains rev, aborts on some
291 special cases."""
292 special cases."""
292 raise NotImplementedError
293 raise NotImplementedError
293
294
294 class commandline(object):
295 class commandline(object):
295 def __init__(self, ui, command):
296 def __init__(self, ui, command):
296 self.ui = ui
297 self.ui = ui
297 self.command = command
298 self.command = command
298
299
299 def prerun(self):
300 def prerun(self):
300 pass
301 pass
301
302
302 def postrun(self):
303 def postrun(self):
303 pass
304 pass
304
305
305 def _cmdline(self, cmd, *args, **kwargs):
306 def _cmdline(self, cmd, *args, **kwargs):
306 cmdline = [self.command, cmd] + list(args)
307 cmdline = [self.command, cmd] + list(args)
307 for k, v in kwargs.iteritems():
308 for k, v in kwargs.iteritems():
308 if len(k) == 1:
309 if len(k) == 1:
309 cmdline.append('-' + k)
310 cmdline.append('-' + k)
310 else:
311 else:
311 cmdline.append('--' + k.replace('_', '-'))
312 cmdline.append('--' + k.replace('_', '-'))
312 try:
313 try:
313 if len(k) == 1:
314 if len(k) == 1:
314 cmdline.append('' + v)
315 cmdline.append('' + v)
315 else:
316 else:
316 cmdline[-1] += '=' + v
317 cmdline[-1] += '=' + v
317 except TypeError:
318 except TypeError:
318 pass
319 pass
319 cmdline = [util.shellquote(arg) for arg in cmdline]
320 cmdline = [util.shellquote(arg) for arg in cmdline]
320 if not self.ui.debugflag:
321 if not self.ui.debugflag:
321 cmdline += ['2>', os.devnull]
322 cmdline += ['2>', os.devnull]
322 cmdline = ' '.join(cmdline)
323 cmdline = ' '.join(cmdline)
323 return cmdline
324 return cmdline
324
325
325 def _run(self, cmd, *args, **kwargs):
326 def _run(self, cmd, *args, **kwargs):
326 def popen(cmdline):
327 def popen(cmdline):
327 p = subprocess.Popen(cmdline, shell=True, bufsize=-1,
328 p = subprocess.Popen(cmdline, shell=True, bufsize=-1,
328 close_fds=util.closefds,
329 close_fds=util.closefds,
329 stdout=subprocess.PIPE)
330 stdout=subprocess.PIPE)
330 return p
331 return p
331 return self._dorun(popen, cmd, *args, **kwargs)
332 return self._dorun(popen, cmd, *args, **kwargs)
332
333
333 def _run2(self, cmd, *args, **kwargs):
334 def _run2(self, cmd, *args, **kwargs):
334 return self._dorun(util.popen2, cmd, *args, **kwargs)
335 return self._dorun(util.popen2, cmd, *args, **kwargs)
335
336
336 def _dorun(self, openfunc, cmd, *args, **kwargs):
337 def _dorun(self, openfunc, cmd, *args, **kwargs):
337 cmdline = self._cmdline(cmd, *args, **kwargs)
338 cmdline = self._cmdline(cmd, *args, **kwargs)
338 self.ui.debug('running: %s\n' % (cmdline,))
339 self.ui.debug('running: %s\n' % (cmdline,))
339 self.prerun()
340 self.prerun()
340 try:
341 try:
341 return openfunc(cmdline)
342 return openfunc(cmdline)
342 finally:
343 finally:
343 self.postrun()
344 self.postrun()
344
345
345 def run(self, cmd, *args, **kwargs):
346 def run(self, cmd, *args, **kwargs):
346 p = self._run(cmd, *args, **kwargs)
347 p = self._run(cmd, *args, **kwargs)
347 output = p.communicate()[0]
348 output = p.communicate()[0]
348 self.ui.debug(output)
349 self.ui.debug(output)
349 return output, p.returncode
350 return output, p.returncode
350
351
351 def runlines(self, cmd, *args, **kwargs):
352 def runlines(self, cmd, *args, **kwargs):
352 p = self._run(cmd, *args, **kwargs)
353 p = self._run(cmd, *args, **kwargs)
353 output = p.stdout.readlines()
354 output = p.stdout.readlines()
354 p.wait()
355 p.wait()
355 self.ui.debug(''.join(output))
356 self.ui.debug(''.join(output))
356 return output, p.returncode
357 return output, p.returncode
357
358
358 def checkexit(self, status, output=''):
359 def checkexit(self, status, output=''):
359 if status:
360 if status:
360 if output:
361 if output:
361 self.ui.warn(_('%s error:\n') % self.command)
362 self.ui.warn(_('%s error:\n') % self.command)
362 self.ui.warn(output)
363 self.ui.warn(output)
363 msg = util.explainexit(status)[0]
364 msg = util.explainexit(status)[0]
364 raise util.Abort('%s %s' % (self.command, msg))
365 raise util.Abort('%s %s' % (self.command, msg))
365
366
366 def run0(self, cmd, *args, **kwargs):
367 def run0(self, cmd, *args, **kwargs):
367 output, status = self.run(cmd, *args, **kwargs)
368 output, status = self.run(cmd, *args, **kwargs)
368 self.checkexit(status, output)
369 self.checkexit(status, output)
369 return output
370 return output
370
371
371 def runlines0(self, cmd, *args, **kwargs):
372 def runlines0(self, cmd, *args, **kwargs):
372 output, status = self.runlines(cmd, *args, **kwargs)
373 output, status = self.runlines(cmd, *args, **kwargs)
373 self.checkexit(status, ''.join(output))
374 self.checkexit(status, ''.join(output))
374 return output
375 return output
375
376
376 @propertycache
377 @propertycache
377 def argmax(self):
378 def argmax(self):
378 # POSIX requires at least 4096 bytes for ARG_MAX
379 # POSIX requires at least 4096 bytes for ARG_MAX
379 argmax = 4096
380 argmax = 4096
380 try:
381 try:
381 argmax = os.sysconf("SC_ARG_MAX")
382 argmax = os.sysconf("SC_ARG_MAX")
382 except (AttributeError, ValueError):
383 except (AttributeError, ValueError):
383 pass
384 pass
384
385
385 # Windows shells impose their own limits on command line length,
386 # Windows shells impose their own limits on command line length,
386 # down to 2047 bytes for cmd.exe under Windows NT/2k and 2500 bytes
387 # down to 2047 bytes for cmd.exe under Windows NT/2k and 2500 bytes
387 # for older 4nt.exe. See http://support.microsoft.com/kb/830473 for
388 # for older 4nt.exe. See http://support.microsoft.com/kb/830473 for
388 # details about cmd.exe limitations.
389 # details about cmd.exe limitations.
389
390
390 # Since ARG_MAX is for command line _and_ environment, lower our limit
391 # Since ARG_MAX is for command line _and_ environment, lower our limit
391 # (and make happy Windows shells while doing this).
392 # (and make happy Windows shells while doing this).
392 return argmax // 2 - 1
393 return argmax // 2 - 1
393
394
394 def _limit_arglist(self, arglist, cmd, *args, **kwargs):
395 def _limit_arglist(self, arglist, cmd, *args, **kwargs):
395 cmdlen = len(self._cmdline(cmd, *args, **kwargs))
396 cmdlen = len(self._cmdline(cmd, *args, **kwargs))
396 limit = self.argmax - cmdlen
397 limit = self.argmax - cmdlen
397 bytes = 0
398 bytes = 0
398 fl = []
399 fl = []
399 for fn in arglist:
400 for fn in arglist:
400 b = len(fn) + 3
401 b = len(fn) + 3
401 if bytes + b < limit or len(fl) == 0:
402 if bytes + b < limit or len(fl) == 0:
402 fl.append(fn)
403 fl.append(fn)
403 bytes += b
404 bytes += b
404 else:
405 else:
405 yield fl
406 yield fl
406 fl = [fn]
407 fl = [fn]
407 bytes = b
408 bytes = b
408 if fl:
409 if fl:
409 yield fl
410 yield fl
410
411
411 def xargs(self, arglist, cmd, *args, **kwargs):
412 def xargs(self, arglist, cmd, *args, **kwargs):
412 for l in self._limit_arglist(arglist, cmd, *args, **kwargs):
413 for l in self._limit_arglist(arglist, cmd, *args, **kwargs):
413 self.run0(cmd, *(list(args) + l), **kwargs)
414 self.run0(cmd, *(list(args) + l), **kwargs)
414
415
415 class mapfile(dict):
416 class mapfile(dict):
416 def __init__(self, ui, path):
417 def __init__(self, ui, path):
417 super(mapfile, self).__init__()
418 super(mapfile, self).__init__()
418 self.ui = ui
419 self.ui = ui
419 self.path = path
420 self.path = path
420 self.fp = None
421 self.fp = None
421 self.order = []
422 self.order = []
422 self._read()
423 self._read()
423
424
424 def _read(self):
425 def _read(self):
425 if not self.path:
426 if not self.path:
426 return
427 return
427 try:
428 try:
428 fp = open(self.path, 'r')
429 fp = open(self.path, 'r')
429 except IOError, err:
430 except IOError, err:
430 if err.errno != errno.ENOENT:
431 if err.errno != errno.ENOENT:
431 raise
432 raise
432 return
433 return
433 for i, line in enumerate(fp):
434 for i, line in enumerate(fp):
434 line = line.splitlines()[0].rstrip()
435 line = line.splitlines()[0].rstrip()
435 if not line:
436 if not line:
436 # Ignore blank lines
437 # Ignore blank lines
437 continue
438 continue
438 try:
439 try:
439 key, value = line.rsplit(' ', 1)
440 key, value = line.rsplit(' ', 1)
440 except ValueError:
441 except ValueError:
441 raise util.Abort(
442 raise util.Abort(
442 _('syntax error in %s(%d): key/value pair expected')
443 _('syntax error in %s(%d): key/value pair expected')
443 % (self.path, i + 1))
444 % (self.path, i + 1))
444 if key not in self:
445 if key not in self:
445 self.order.append(key)
446 self.order.append(key)
446 super(mapfile, self).__setitem__(key, value)
447 super(mapfile, self).__setitem__(key, value)
447 fp.close()
448 fp.close()
448
449
449 def __setitem__(self, key, value):
450 def __setitem__(self, key, value):
450 if self.fp is None:
451 if self.fp is None:
451 try:
452 try:
452 self.fp = open(self.path, 'a')
453 self.fp = open(self.path, 'a')
453 except IOError, err:
454 except IOError, err:
454 raise util.Abort(_('could not open map file %r: %s') %
455 raise util.Abort(_('could not open map file %r: %s') %
455 (self.path, err.strerror))
456 (self.path, err.strerror))
456 self.fp.write('%s %s\n' % (key, value))
457 self.fp.write('%s %s\n' % (key, value))
457 self.fp.flush()
458 self.fp.flush()
458 super(mapfile, self).__setitem__(key, value)
459 super(mapfile, self).__setitem__(key, value)
459
460
460 def close(self):
461 def close(self):
461 if self.fp:
462 if self.fp:
462 self.fp.close()
463 self.fp.close()
463 self.fp = None
464 self.fp = None
464
465
465 def makedatetimestamp(t):
466 def makedatetimestamp(t):
466 """Like util.makedate() but for time t instead of current time"""
467 """Like util.makedate() but for time t instead of current time"""
467 delta = (datetime.datetime.utcfromtimestamp(t) -
468 delta = (datetime.datetime.utcfromtimestamp(t) -
468 datetime.datetime.fromtimestamp(t))
469 datetime.datetime.fromtimestamp(t))
469 tz = delta.days * 86400 + delta.seconds
470 tz = delta.days * 86400 + delta.seconds
470 return t, tz
471 return t, tz
@@ -1,536 +1,560
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, exchange
24 from mercurial import hg, util, context, bookmarks, error, scmutil, exchange
25 from mercurial import phases
25
26
26 from common import NoRepo, commit, converter_source, converter_sink, mapfile
27 from common import NoRepo, commit, converter_source, converter_sink, mapfile
27
28
28 import re
29 import re
29 sha1re = re.compile(r'\b[0-9a-f]{12,40}\b')
30 sha1re = re.compile(r'\b[0-9a-f]{12,40}\b')
30
31
31 class mercurial_sink(converter_sink):
32 class mercurial_sink(converter_sink):
32 def __init__(self, ui, path):
33 def __init__(self, ui, path):
33 converter_sink.__init__(self, ui, path)
34 converter_sink.__init__(self, ui, path)
34 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
35 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
35 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
36 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
36 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
37 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
37 self.lastbranch = None
38 self.lastbranch = None
38 if os.path.isdir(path) and len(os.listdir(path)) > 0:
39 if os.path.isdir(path) and len(os.listdir(path)) > 0:
39 try:
40 try:
40 self.repo = hg.repository(self.ui, path)
41 self.repo = hg.repository(self.ui, path)
41 if not self.repo.local():
42 if not self.repo.local():
42 raise NoRepo(_('%s is not a local Mercurial repository')
43 raise NoRepo(_('%s is not a local Mercurial repository')
43 % path)
44 % path)
44 except error.RepoError, err:
45 except error.RepoError, err:
45 ui.traceback()
46 ui.traceback()
46 raise NoRepo(err.args[0])
47 raise NoRepo(err.args[0])
47 else:
48 else:
48 try:
49 try:
49 ui.status(_('initializing destination %s repository\n') % path)
50 ui.status(_('initializing destination %s repository\n') % path)
50 self.repo = hg.repository(self.ui, path, create=True)
51 self.repo = hg.repository(self.ui, path, create=True)
51 if not self.repo.local():
52 if not self.repo.local():
52 raise NoRepo(_('%s is not a local Mercurial repository')
53 raise NoRepo(_('%s is not a local Mercurial repository')
53 % path)
54 % path)
54 self.created.append(path)
55 self.created.append(path)
55 except error.RepoError:
56 except error.RepoError:
56 ui.traceback()
57 ui.traceback()
57 raise NoRepo(_("could not create hg repository %s as sink")
58 raise NoRepo(_("could not create hg repository %s as sink")
58 % path)
59 % path)
59 self.lock = None
60 self.lock = None
60 self.wlock = None
61 self.wlock = None
61 self.filemapmode = False
62 self.filemapmode = False
62 self.subrevmaps = {}
63 self.subrevmaps = {}
63
64
64 def before(self):
65 def before(self):
65 self.ui.debug('run hg sink pre-conversion action\n')
66 self.ui.debug('run hg sink pre-conversion action\n')
66 self.wlock = self.repo.wlock()
67 self.wlock = self.repo.wlock()
67 self.lock = self.repo.lock()
68 self.lock = self.repo.lock()
68
69
69 def after(self):
70 def after(self):
70 self.ui.debug('run hg sink post-conversion action\n')
71 self.ui.debug('run hg sink post-conversion action\n')
71 if self.lock:
72 if self.lock:
72 self.lock.release()
73 self.lock.release()
73 if self.wlock:
74 if self.wlock:
74 self.wlock.release()
75 self.wlock.release()
75
76
76 def revmapfile(self):
77 def revmapfile(self):
77 return self.repo.join("shamap")
78 return self.repo.join("shamap")
78
79
79 def authorfile(self):
80 def authorfile(self):
80 return self.repo.join("authormap")
81 return self.repo.join("authormap")
81
82
82 def setbranch(self, branch, pbranches):
83 def setbranch(self, branch, pbranches):
83 if not self.clonebranches:
84 if not self.clonebranches:
84 return
85 return
85
86
86 setbranch = (branch != self.lastbranch)
87 setbranch = (branch != self.lastbranch)
87 self.lastbranch = branch
88 self.lastbranch = branch
88 if not branch:
89 if not branch:
89 branch = 'default'
90 branch = 'default'
90 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
91 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
91 if pbranches:
92 if pbranches:
92 pbranch = pbranches[0][1]
93 pbranch = pbranches[0][1]
93 else:
94 else:
94 pbranch = 'default'
95 pbranch = 'default'
95
96
96 branchpath = os.path.join(self.path, branch)
97 branchpath = os.path.join(self.path, branch)
97 if setbranch:
98 if setbranch:
98 self.after()
99 self.after()
99 try:
100 try:
100 self.repo = hg.repository(self.ui, branchpath)
101 self.repo = hg.repository(self.ui, branchpath)
101 except Exception:
102 except Exception:
102 self.repo = hg.repository(self.ui, branchpath, create=True)
103 self.repo = hg.repository(self.ui, branchpath, create=True)
103 self.before()
104 self.before()
104
105
105 # pbranches may bring revisions from other branches (merge parents)
106 # pbranches may bring revisions from other branches (merge parents)
106 # Make sure we have them, or pull them.
107 # Make sure we have them, or pull them.
107 missings = {}
108 missings = {}
108 for b in pbranches:
109 for b in pbranches:
109 try:
110 try:
110 self.repo.lookup(b[0])
111 self.repo.lookup(b[0])
111 except Exception:
112 except Exception:
112 missings.setdefault(b[1], []).append(b[0])
113 missings.setdefault(b[1], []).append(b[0])
113
114
114 if missings:
115 if missings:
115 self.after()
116 self.after()
116 for pbranch, heads in sorted(missings.iteritems()):
117 for pbranch, heads in sorted(missings.iteritems()):
117 pbranchpath = os.path.join(self.path, pbranch)
118 pbranchpath = os.path.join(self.path, pbranch)
118 prepo = hg.peer(self.ui, {}, pbranchpath)
119 prepo = hg.peer(self.ui, {}, pbranchpath)
119 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
120 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
120 exchange.pull(self.repo, prepo,
121 exchange.pull(self.repo, prepo,
121 [prepo.lookup(h) for h in heads])
122 [prepo.lookup(h) for h in heads])
122 self.before()
123 self.before()
123
124
124 def _rewritetags(self, source, revmap, data):
125 def _rewritetags(self, source, revmap, data):
125 fp = cStringIO.StringIO()
126 fp = cStringIO.StringIO()
126 for line in data.splitlines():
127 for line in data.splitlines():
127 s = line.split(' ', 1)
128 s = line.split(' ', 1)
128 if len(s) != 2:
129 if len(s) != 2:
129 continue
130 continue
130 revid = revmap.get(source.lookuprev(s[0]))
131 revid = revmap.get(source.lookuprev(s[0]))
131 if not revid:
132 if not revid:
132 if s[0] == hex(nullid):
133 if s[0] == hex(nullid):
133 revid = s[0]
134 revid = s[0]
134 else:
135 else:
135 continue
136 continue
136 fp.write('%s %s\n' % (revid, s[1]))
137 fp.write('%s %s\n' % (revid, s[1]))
137 return fp.getvalue()
138 return fp.getvalue()
138
139
139 def _rewritesubstate(self, source, data):
140 def _rewritesubstate(self, source, data):
140 fp = cStringIO.StringIO()
141 fp = cStringIO.StringIO()
141 for line in data.splitlines():
142 for line in data.splitlines():
142 s = line.split(' ', 1)
143 s = line.split(' ', 1)
143 if len(s) != 2:
144 if len(s) != 2:
144 continue
145 continue
145
146
146 revid = s[0]
147 revid = s[0]
147 subpath = s[1]
148 subpath = s[1]
148 if revid != hex(nullid):
149 if revid != hex(nullid):
149 revmap = self.subrevmaps.get(subpath)
150 revmap = self.subrevmaps.get(subpath)
150 if revmap is None:
151 if revmap is None:
151 revmap = mapfile(self.ui,
152 revmap = mapfile(self.ui,
152 self.repo.wjoin(subpath, '.hg/shamap'))
153 self.repo.wjoin(subpath, '.hg/shamap'))
153 self.subrevmaps[subpath] = revmap
154 self.subrevmaps[subpath] = revmap
154
155
155 # It is reasonable that one or more of the subrepos don't
156 # It is reasonable that one or more of the subrepos don't
156 # need to be converted, in which case they can be cloned
157 # need to be converted, in which case they can be cloned
157 # into place instead of converted. Therefore, only warn
158 # into place instead of converted. Therefore, only warn
158 # once.
159 # once.
159 msg = _('no ".hgsubstate" updates will be made for "%s"\n')
160 msg = _('no ".hgsubstate" updates will be made for "%s"\n')
160 if len(revmap) == 0:
161 if len(revmap) == 0:
161 sub = self.repo.wvfs.reljoin(subpath, '.hg')
162 sub = self.repo.wvfs.reljoin(subpath, '.hg')
162
163
163 if self.repo.wvfs.exists(sub):
164 if self.repo.wvfs.exists(sub):
164 self.ui.warn(msg % subpath)
165 self.ui.warn(msg % subpath)
165
166
166 newid = revmap.get(revid)
167 newid = revmap.get(revid)
167 if not newid:
168 if not newid:
168 if len(revmap) > 0:
169 if len(revmap) > 0:
169 self.ui.warn(_("%s is missing from %s/.hg/shamap\n") %
170 self.ui.warn(_("%s is missing from %s/.hg/shamap\n") %
170 (revid, subpath))
171 (revid, subpath))
171 else:
172 else:
172 revid = newid
173 revid = newid
173
174
174 fp.write('%s %s\n' % (revid, subpath))
175 fp.write('%s %s\n' % (revid, subpath))
175
176
176 return fp.getvalue()
177 return fp.getvalue()
177
178
178 def putcommit(self, files, copies, parents, commit, source, revmap, full,
179 def putcommit(self, files, copies, parents, commit, source, revmap, full,
179 cleanp2):
180 cleanp2):
180 files = dict(files)
181 files = dict(files)
181
182
182 def getfilectx(repo, memctx, f):
183 def getfilectx(repo, memctx, f):
183 if p2ctx and f in cleanp2 and f not in copies:
184 if p2ctx and f in cleanp2 and f not in copies:
184 self.ui.debug('reusing %s from p2\n' % f)
185 self.ui.debug('reusing %s from p2\n' % f)
185 return p2ctx[f]
186 return p2ctx[f]
186 try:
187 try:
187 v = files[f]
188 v = files[f]
188 except KeyError:
189 except KeyError:
189 return None
190 return None
190 data, mode = source.getfile(f, v)
191 data, mode = source.getfile(f, v)
191 if data is None:
192 if data is None:
192 return None
193 return None
193 if f == '.hgtags':
194 if f == '.hgtags':
194 data = self._rewritetags(source, revmap, data)
195 data = self._rewritetags(source, revmap, data)
195 if f == '.hgsubstate':
196 if f == '.hgsubstate':
196 data = self._rewritesubstate(source, data)
197 data = self._rewritesubstate(source, data)
197 return context.memfilectx(self.repo, f, data, 'l' in mode,
198 return context.memfilectx(self.repo, f, data, 'l' in mode,
198 'x' in mode, copies.get(f))
199 'x' in mode, copies.get(f))
199
200
200 pl = []
201 pl = []
201 for p in parents:
202 for p in parents:
202 if p not in pl:
203 if p not in pl:
203 pl.append(p)
204 pl.append(p)
204 parents = pl
205 parents = pl
205 nparents = len(parents)
206 nparents = len(parents)
206 if self.filemapmode and nparents == 1:
207 if self.filemapmode and nparents == 1:
207 m1node = self.repo.changelog.read(bin(parents[0]))[0]
208 m1node = self.repo.changelog.read(bin(parents[0]))[0]
208 parent = parents[0]
209 parent = parents[0]
209
210
210 if len(parents) < 2:
211 if len(parents) < 2:
211 parents.append(nullid)
212 parents.append(nullid)
212 if len(parents) < 2:
213 if len(parents) < 2:
213 parents.append(nullid)
214 parents.append(nullid)
214 p2 = parents.pop(0)
215 p2 = parents.pop(0)
215
216
216 text = commit.desc
217 text = commit.desc
217
218
218 sha1s = re.findall(sha1re, text)
219 sha1s = re.findall(sha1re, text)
219 for sha1 in sha1s:
220 for sha1 in sha1s:
220 oldrev = source.lookuprev(sha1)
221 oldrev = source.lookuprev(sha1)
221 newrev = revmap.get(oldrev)
222 newrev = revmap.get(oldrev)
222 if newrev is not None:
223 if newrev is not None:
223 text = text.replace(sha1, newrev[:len(sha1)])
224 text = text.replace(sha1, newrev[:len(sha1)])
224
225
225 extra = commit.extra.copy()
226 extra = commit.extra.copy()
226
227
227 for label in ('source', 'transplant_source', 'rebase_source'):
228 for label in ('source', 'transplant_source', 'rebase_source'):
228 node = extra.get(label)
229 node = extra.get(label)
229
230
230 if node is None:
231 if node is None:
231 continue
232 continue
232
233
233 # Only transplant stores its reference in binary
234 # Only transplant stores its reference in binary
234 if label == 'transplant_source':
235 if label == 'transplant_source':
235 node = hex(node)
236 node = hex(node)
236
237
237 newrev = revmap.get(node)
238 newrev = revmap.get(node)
238 if newrev is not None:
239 if newrev is not None:
239 if label == 'transplant_source':
240 if label == 'transplant_source':
240 newrev = bin(newrev)
241 newrev = bin(newrev)
241
242
242 extra[label] = newrev
243 extra[label] = newrev
243
244
244 if self.branchnames and commit.branch:
245 if self.branchnames and commit.branch:
245 extra['branch'] = commit.branch
246 extra['branch'] = commit.branch
246 if commit.rev and commit.saverev:
247 if commit.rev and commit.saverev:
247 extra['convert_revision'] = commit.rev
248 extra['convert_revision'] = commit.rev
248
249
249 while parents:
250 while parents:
250 p1 = p2
251 p1 = p2
251 p2 = parents.pop(0)
252 p2 = parents.pop(0)
252 p2ctx = None
253 p2ctx = None
253 if p2 != nullid:
254 if p2 != nullid:
254 p2ctx = self.repo[p2]
255 p2ctx = self.repo[p2]
255 fileset = set(files)
256 fileset = set(files)
256 if full:
257 if full:
257 fileset.update(self.repo[p1])
258 fileset.update(self.repo[p1])
258 fileset.update(self.repo[p2])
259 fileset.update(self.repo[p2])
259 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
260 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
260 getfilectx, commit.author, commit.date, extra)
261 getfilectx, commit.author, commit.date, extra)
261 self.repo.commitctx(ctx)
262
263 # We won't know if the conversion changes the node until after the
264 # commit, so copy the source's phase for now.
265 self.repo.ui.setconfig('phases', 'new-commit',
266 phases.phasenames[commit.phase], 'convert')
267
268 tr = self.repo.transaction("convert")
269
270 try:
271 node = hex(self.repo.commitctx(ctx))
272
273 # If the node value has changed, but the phase is lower than
274 # draft, set it back to draft since it hasn't been exposed
275 # anywhere.
276 if commit.rev != node:
277 ctx = self.repo[node]
278 if ctx.phase() < phases.draft:
279 phases.retractboundary(self.repo, tr, phases.draft,
280 [ctx.node()])
281 tr.close()
282 finally:
283 tr.release()
284
262 text = "(octopus merge fixup)\n"
285 text = "(octopus merge fixup)\n"
263 p2 = hex(self.repo.changelog.tip())
286 p2 = hex(self.repo.changelog.tip())
264
287
265 if self.filemapmode and nparents == 1:
288 if self.filemapmode and nparents == 1:
266 man = self.repo.manifest
289 man = self.repo.manifest
267 mnode = self.repo.changelog.read(bin(p2))[0]
290 mnode = self.repo.changelog.read(bin(p2))[0]
268 closed = 'close' in commit.extra
291 closed = 'close' in commit.extra
269 if not closed and not man.cmp(m1node, man.revision(mnode)):
292 if not closed and not man.cmp(m1node, man.revision(mnode)):
270 self.ui.status(_("filtering out empty revision\n"))
293 self.ui.status(_("filtering out empty revision\n"))
271 self.repo.rollback(force=True)
294 self.repo.rollback(force=True)
272 return parent
295 return parent
273 return p2
296 return p2
274
297
275 def puttags(self, tags):
298 def puttags(self, tags):
276 try:
299 try:
277 parentctx = self.repo[self.tagsbranch]
300 parentctx = self.repo[self.tagsbranch]
278 tagparent = parentctx.node()
301 tagparent = parentctx.node()
279 except error.RepoError:
302 except error.RepoError:
280 parentctx = None
303 parentctx = None
281 tagparent = nullid
304 tagparent = nullid
282
305
283 oldlines = set()
306 oldlines = set()
284 for branch, heads in self.repo.branchmap().iteritems():
307 for branch, heads in self.repo.branchmap().iteritems():
285 for h in heads:
308 for h in heads:
286 if '.hgtags' in self.repo[h]:
309 if '.hgtags' in self.repo[h]:
287 oldlines.update(
310 oldlines.update(
288 set(self.repo[h]['.hgtags'].data().splitlines(True)))
311 set(self.repo[h]['.hgtags'].data().splitlines(True)))
289 oldlines = sorted(list(oldlines))
312 oldlines = sorted(list(oldlines))
290
313
291 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
314 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
292 if newlines == oldlines:
315 if newlines == oldlines:
293 return None, None
316 return None, None
294
317
295 # if the old and new tags match, then there is nothing to update
318 # if the old and new tags match, then there is nothing to update
296 oldtags = set()
319 oldtags = set()
297 newtags = set()
320 newtags = set()
298 for line in oldlines:
321 for line in oldlines:
299 s = line.strip().split(' ', 1)
322 s = line.strip().split(' ', 1)
300 if len(s) != 2:
323 if len(s) != 2:
301 continue
324 continue
302 oldtags.add(s[1])
325 oldtags.add(s[1])
303 for line in newlines:
326 for line in newlines:
304 s = line.strip().split(' ', 1)
327 s = line.strip().split(' ', 1)
305 if len(s) != 2:
328 if len(s) != 2:
306 continue
329 continue
307 if s[1] not in oldtags:
330 if s[1] not in oldtags:
308 newtags.add(s[1].strip())
331 newtags.add(s[1].strip())
309
332
310 if not newtags:
333 if not newtags:
311 return None, None
334 return None, None
312
335
313 data = "".join(newlines)
336 data = "".join(newlines)
314 def getfilectx(repo, memctx, f):
337 def getfilectx(repo, memctx, f):
315 return context.memfilectx(repo, f, data, False, False, None)
338 return context.memfilectx(repo, f, data, False, False, None)
316
339
317 self.ui.status(_("updating tags\n"))
340 self.ui.status(_("updating tags\n"))
318 date = "%s 0" % int(time.mktime(time.gmtime()))
341 date = "%s 0" % int(time.mktime(time.gmtime()))
319 extra = {'branch': self.tagsbranch}
342 extra = {'branch': self.tagsbranch}
320 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
343 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
321 [".hgtags"], getfilectx, "convert-repo", date,
344 [".hgtags"], getfilectx, "convert-repo", date,
322 extra)
345 extra)
323 self.repo.commitctx(ctx)
346 self.repo.commitctx(ctx)
324 return hex(self.repo.changelog.tip()), hex(tagparent)
347 return hex(self.repo.changelog.tip()), hex(tagparent)
325
348
326 def setfilemapmode(self, active):
349 def setfilemapmode(self, active):
327 self.filemapmode = active
350 self.filemapmode = active
328
351
329 def putbookmarks(self, updatedbookmark):
352 def putbookmarks(self, updatedbookmark):
330 if not len(updatedbookmark):
353 if not len(updatedbookmark):
331 return
354 return
332
355
333 self.ui.status(_("updating bookmarks\n"))
356 self.ui.status(_("updating bookmarks\n"))
334 destmarks = self.repo._bookmarks
357 destmarks = self.repo._bookmarks
335 for bookmark in updatedbookmark:
358 for bookmark in updatedbookmark:
336 destmarks[bookmark] = bin(updatedbookmark[bookmark])
359 destmarks[bookmark] = bin(updatedbookmark[bookmark])
337 destmarks.write()
360 destmarks.write()
338
361
339 def hascommitfrommap(self, rev):
362 def hascommitfrommap(self, rev):
340 # the exact semantics of clonebranches is unclear so we can't say no
363 # the exact semantics of clonebranches is unclear so we can't say no
341 return rev in self.repo or self.clonebranches
364 return rev in self.repo or self.clonebranches
342
365
343 def hascommitforsplicemap(self, rev):
366 def hascommitforsplicemap(self, rev):
344 if rev not in self.repo and self.clonebranches:
367 if rev not in self.repo and self.clonebranches:
345 raise util.Abort(_('revision %s not found in destination '
368 raise util.Abort(_('revision %s not found in destination '
346 'repository (lookups with clonebranches=true '
369 'repository (lookups with clonebranches=true '
347 'are not implemented)') % rev)
370 'are not implemented)') % rev)
348 return rev in self.repo
371 return rev in self.repo
349
372
350 class mercurial_source(converter_source):
373 class mercurial_source(converter_source):
351 def __init__(self, ui, path, rev=None):
374 def __init__(self, ui, path, rev=None):
352 converter_source.__init__(self, ui, path, rev)
375 converter_source.__init__(self, ui, path, rev)
353 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
376 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
354 self.ignored = set()
377 self.ignored = set()
355 self.saverev = ui.configbool('convert', 'hg.saverev', False)
378 self.saverev = ui.configbool('convert', 'hg.saverev', False)
356 try:
379 try:
357 self.repo = hg.repository(self.ui, path)
380 self.repo = hg.repository(self.ui, path)
358 # try to provoke an exception if this isn't really a hg
381 # try to provoke an exception if this isn't really a hg
359 # repo, but some other bogus compatible-looking url
382 # repo, but some other bogus compatible-looking url
360 if not self.repo.local():
383 if not self.repo.local():
361 raise error.RepoError
384 raise error.RepoError
362 except error.RepoError:
385 except error.RepoError:
363 ui.traceback()
386 ui.traceback()
364 raise NoRepo(_("%s is not a local Mercurial repository") % path)
387 raise NoRepo(_("%s is not a local Mercurial repository") % path)
365 self.lastrev = None
388 self.lastrev = None
366 self.lastctx = None
389 self.lastctx = None
367 self._changescache = None, None
390 self._changescache = None, None
368 self.convertfp = None
391 self.convertfp = None
369 # Restrict converted revisions to startrev descendants
392 # Restrict converted revisions to startrev descendants
370 startnode = ui.config('convert', 'hg.startrev')
393 startnode = ui.config('convert', 'hg.startrev')
371 hgrevs = ui.config('convert', 'hg.revs')
394 hgrevs = ui.config('convert', 'hg.revs')
372 if hgrevs is None:
395 if hgrevs is None:
373 if startnode is not None:
396 if startnode is not None:
374 try:
397 try:
375 startnode = self.repo.lookup(startnode)
398 startnode = self.repo.lookup(startnode)
376 except error.RepoError:
399 except error.RepoError:
377 raise util.Abort(_('%s is not a valid start revision')
400 raise util.Abort(_('%s is not a valid start revision')
378 % startnode)
401 % startnode)
379 startrev = self.repo.changelog.rev(startnode)
402 startrev = self.repo.changelog.rev(startnode)
380 children = {startnode: 1}
403 children = {startnode: 1}
381 for r in self.repo.changelog.descendants([startrev]):
404 for r in self.repo.changelog.descendants([startrev]):
382 children[self.repo.changelog.node(r)] = 1
405 children[self.repo.changelog.node(r)] = 1
383 self.keep = children.__contains__
406 self.keep = children.__contains__
384 else:
407 else:
385 self.keep = util.always
408 self.keep = util.always
386 if rev:
409 if rev:
387 self._heads = [self.repo[rev].node()]
410 self._heads = [self.repo[rev].node()]
388 else:
411 else:
389 self._heads = self.repo.heads()
412 self._heads = self.repo.heads()
390 else:
413 else:
391 if rev or startnode is not None:
414 if rev or startnode is not None:
392 raise util.Abort(_('hg.revs cannot be combined with '
415 raise util.Abort(_('hg.revs cannot be combined with '
393 'hg.startrev or --rev'))
416 'hg.startrev or --rev'))
394 nodes = set()
417 nodes = set()
395 parents = set()
418 parents = set()
396 for r in scmutil.revrange(self.repo, [hgrevs]):
419 for r in scmutil.revrange(self.repo, [hgrevs]):
397 ctx = self.repo[r]
420 ctx = self.repo[r]
398 nodes.add(ctx.node())
421 nodes.add(ctx.node())
399 parents.update(p.node() for p in ctx.parents())
422 parents.update(p.node() for p in ctx.parents())
400 self.keep = nodes.__contains__
423 self.keep = nodes.__contains__
401 self._heads = nodes - parents
424 self._heads = nodes - parents
402
425
403 def changectx(self, rev):
426 def changectx(self, rev):
404 if self.lastrev != rev:
427 if self.lastrev != rev:
405 self.lastctx = self.repo[rev]
428 self.lastctx = self.repo[rev]
406 self.lastrev = rev
429 self.lastrev = rev
407 return self.lastctx
430 return self.lastctx
408
431
409 def parents(self, ctx):
432 def parents(self, ctx):
410 return [p for p in ctx.parents() if p and self.keep(p.node())]
433 return [p for p in ctx.parents() if p and self.keep(p.node())]
411
434
412 def getheads(self):
435 def getheads(self):
413 return [hex(h) for h in self._heads if self.keep(h)]
436 return [hex(h) for h in self._heads if self.keep(h)]
414
437
415 def getfile(self, name, rev):
438 def getfile(self, name, rev):
416 try:
439 try:
417 fctx = self.changectx(rev)[name]
440 fctx = self.changectx(rev)[name]
418 return fctx.data(), fctx.flags()
441 return fctx.data(), fctx.flags()
419 except error.LookupError:
442 except error.LookupError:
420 return None, None
443 return None, None
421
444
422 def getchanges(self, rev, full):
445 def getchanges(self, rev, full):
423 ctx = self.changectx(rev)
446 ctx = self.changectx(rev)
424 parents = self.parents(ctx)
447 parents = self.parents(ctx)
425 if full or not parents:
448 if full or not parents:
426 files = copyfiles = ctx.manifest()
449 files = copyfiles = ctx.manifest()
427 if parents:
450 if parents:
428 if self._changescache[0] == rev:
451 if self._changescache[0] == rev:
429 m, a, r = self._changescache[1]
452 m, a, r = self._changescache[1]
430 else:
453 else:
431 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
454 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
432 if not full:
455 if not full:
433 files = m + a + r
456 files = m + a + r
434 copyfiles = m + a
457 copyfiles = m + a
435 # getcopies() is also run for roots and before filtering so missing
458 # getcopies() is also run for roots and before filtering so missing
436 # revlogs are detected early
459 # revlogs are detected early
437 copies = self.getcopies(ctx, parents, copyfiles)
460 copies = self.getcopies(ctx, parents, copyfiles)
438 cleanp2 = set()
461 cleanp2 = set()
439 if len(parents) == 2:
462 if len(parents) == 2:
440 cleanp2.update(self.repo.status(parents[1].node(), ctx.node(),
463 cleanp2.update(self.repo.status(parents[1].node(), ctx.node(),
441 clean=True).clean)
464 clean=True).clean)
442 changes = [(f, rev) for f in files if f not in self.ignored]
465 changes = [(f, rev) for f in files if f not in self.ignored]
443 changes.sort()
466 changes.sort()
444 return changes, copies, cleanp2
467 return changes, copies, cleanp2
445
468
446 def getcopies(self, ctx, parents, files):
469 def getcopies(self, ctx, parents, files):
447 copies = {}
470 copies = {}
448 for name in files:
471 for name in files:
449 if name in self.ignored:
472 if name in self.ignored:
450 continue
473 continue
451 try:
474 try:
452 copysource, _copynode = ctx.filectx(name).renamed()
475 copysource, _copynode = ctx.filectx(name).renamed()
453 if copysource in self.ignored:
476 if copysource in self.ignored:
454 continue
477 continue
455 # Ignore copy sources not in parent revisions
478 # Ignore copy sources not in parent revisions
456 found = False
479 found = False
457 for p in parents:
480 for p in parents:
458 if copysource in p:
481 if copysource in p:
459 found = True
482 found = True
460 break
483 break
461 if not found:
484 if not found:
462 continue
485 continue
463 copies[name] = copysource
486 copies[name] = copysource
464 except TypeError:
487 except TypeError:
465 pass
488 pass
466 except error.LookupError, e:
489 except error.LookupError, e:
467 if not self.ignoreerrors:
490 if not self.ignoreerrors:
468 raise
491 raise
469 self.ignored.add(name)
492 self.ignored.add(name)
470 self.ui.warn(_('ignoring: %s\n') % e)
493 self.ui.warn(_('ignoring: %s\n') % e)
471 return copies
494 return copies
472
495
473 def getcommit(self, rev):
496 def getcommit(self, rev):
474 ctx = self.changectx(rev)
497 ctx = self.changectx(rev)
475 parents = [p.hex() for p in self.parents(ctx)]
498 parents = [p.hex() for p in self.parents(ctx)]
476 crev = rev
499 crev = rev
477
500
478 return commit(author=ctx.user(),
501 return commit(author=ctx.user(),
479 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
502 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
480 desc=ctx.description(), rev=crev, parents=parents,
503 desc=ctx.description(), rev=crev, parents=parents,
481 branch=ctx.branch(), extra=ctx.extra(),
504 branch=ctx.branch(), extra=ctx.extra(),
482 sortkey=ctx.rev(), saverev=self.saverev)
505 sortkey=ctx.rev(), saverev=self.saverev,
506 phase=ctx.phase())
483
507
484 def gettags(self):
508 def gettags(self):
485 # This will get written to .hgtags, filter non global tags out.
509 # This will get written to .hgtags, filter non global tags out.
486 tags = [t for t in self.repo.tagslist()
510 tags = [t for t in self.repo.tagslist()
487 if self.repo.tagtype(t[0]) == 'global']
511 if self.repo.tagtype(t[0]) == 'global']
488 return dict([(name, hex(node)) for name, node in tags
512 return dict([(name, hex(node)) for name, node in tags
489 if self.keep(node)])
513 if self.keep(node)])
490
514
491 def getchangedfiles(self, rev, i):
515 def getchangedfiles(self, rev, i):
492 ctx = self.changectx(rev)
516 ctx = self.changectx(rev)
493 parents = self.parents(ctx)
517 parents = self.parents(ctx)
494 if not parents and i is None:
518 if not parents and i is None:
495 i = 0
519 i = 0
496 changes = [], ctx.manifest().keys(), []
520 changes = [], ctx.manifest().keys(), []
497 else:
521 else:
498 i = i or 0
522 i = i or 0
499 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
523 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
500 changes = [[f for f in l if f not in self.ignored] for l in changes]
524 changes = [[f for f in l if f not in self.ignored] for l in changes]
501
525
502 if i == 0:
526 if i == 0:
503 self._changescache = (rev, changes)
527 self._changescache = (rev, changes)
504
528
505 return changes[0] + changes[1] + changes[2]
529 return changes[0] + changes[1] + changes[2]
506
530
507 def converted(self, rev, destrev):
531 def converted(self, rev, destrev):
508 if self.convertfp is None:
532 if self.convertfp is None:
509 self.convertfp = open(self.repo.join('shamap'), 'a')
533 self.convertfp = open(self.repo.join('shamap'), 'a')
510 self.convertfp.write('%s %s\n' % (destrev, rev))
534 self.convertfp.write('%s %s\n' % (destrev, rev))
511 self.convertfp.flush()
535 self.convertfp.flush()
512
536
513 def before(self):
537 def before(self):
514 self.ui.debug('run hg source pre-conversion action\n')
538 self.ui.debug('run hg source pre-conversion action\n')
515
539
516 def after(self):
540 def after(self):
517 self.ui.debug('run hg source post-conversion action\n')
541 self.ui.debug('run hg source post-conversion action\n')
518
542
519 def hasnativeorder(self):
543 def hasnativeorder(self):
520 return True
544 return True
521
545
522 def hasnativeclose(self):
546 def hasnativeclose(self):
523 return True
547 return True
524
548
525 def lookuprev(self, rev):
549 def lookuprev(self, rev):
526 try:
550 try:
527 return hex(self.repo.lookup(rev))
551 return hex(self.repo.lookup(rev))
528 except (error.RepoError, error.LookupError):
552 except (error.RepoError, error.LookupError):
529 return None
553 return None
530
554
531 def getbookmarks(self):
555 def getbookmarks(self):
532 return bookmarks.listbookmarks(self.repo)
556 return bookmarks.listbookmarks(self.repo)
533
557
534 def checkrevformat(self, revstr, mapname='splicemap'):
558 def checkrevformat(self, revstr, mapname='splicemap'):
535 """ Mercurial, revision string is a 40 byte hex """
559 """ Mercurial, revision string is a 40 byte hex """
536 self.checkhexformat(revstr, mapname)
560 self.checkhexformat(revstr, mapname)
@@ -1,470 +1,470
1 #require cvs
1 #require cvs
2
2
3 $ cvscall()
3 $ cvscall()
4 > {
4 > {
5 > cvs -f "$@"
5 > cvs -f "$@"
6 > }
6 > }
7 $ hgcat()
7 $ hgcat()
8 > {
8 > {
9 > hg --cwd src-hg cat -r tip "$1"
9 > hg --cwd src-hg cat -r tip "$1"
10 > }
10 > }
11 $ echo "[extensions]" >> $HGRCPATH
11 $ echo "[extensions]" >> $HGRCPATH
12 $ echo "convert = " >> $HGRCPATH
12 $ echo "convert = " >> $HGRCPATH
13 $ cat > cvshooks.py <<EOF
13 $ cat > cvshooks.py <<EOF
14 > def cvslog(ui,repo,hooktype,log):
14 > def cvslog(ui,repo,hooktype,log):
15 > print "%s hook: %d entries"%(hooktype,len(log))
15 > print "%s hook: %d entries"%(hooktype,len(log))
16 >
16 >
17 > def cvschangesets(ui,repo,hooktype,changesets):
17 > def cvschangesets(ui,repo,hooktype,changesets):
18 > print "%s hook: %d changesets"%(hooktype,len(changesets))
18 > print "%s hook: %d changesets"%(hooktype,len(changesets))
19 > EOF
19 > EOF
20 $ hookpath=`pwd`
20 $ hookpath=`pwd`
21 $ cat <<EOF >> $HGRCPATH
21 $ cat <<EOF >> $HGRCPATH
22 > [hooks]
22 > [hooks]
23 > cvslog = python:$hookpath/cvshooks.py:cvslog
23 > cvslog = python:$hookpath/cvshooks.py:cvslog
24 > cvschangesets = python:$hookpath/cvshooks.py:cvschangesets
24 > cvschangesets = python:$hookpath/cvshooks.py:cvschangesets
25 > EOF
25 > EOF
26
26
27 create cvs repository
27 create cvs repository
28
28
29 $ mkdir cvsrepo
29 $ mkdir cvsrepo
30 $ cd cvsrepo
30 $ cd cvsrepo
31 $ CVSROOT=`pwd`
31 $ CVSROOT=`pwd`
32 $ export CVSROOT
32 $ export CVSROOT
33 $ CVS_OPTIONS=-f
33 $ CVS_OPTIONS=-f
34 $ export CVS_OPTIONS
34 $ export CVS_OPTIONS
35 $ cd ..
35 $ cd ..
36 $ rmdir cvsrepo
36 $ rmdir cvsrepo
37 $ cvscall -q -d "$CVSROOT" init
37 $ cvscall -q -d "$CVSROOT" init
38
38
39 create source directory
39 create source directory
40
40
41 $ mkdir src-temp
41 $ mkdir src-temp
42 $ cd src-temp
42 $ cd src-temp
43 $ echo a > a
43 $ echo a > a
44 $ mkdir b
44 $ mkdir b
45 $ cd b
45 $ cd b
46 $ echo c > c
46 $ echo c > c
47 $ cd ..
47 $ cd ..
48
48
49 import source directory
49 import source directory
50
50
51 $ cvscall -q import -m import src INITIAL start
51 $ cvscall -q import -m import src INITIAL start
52 N src/a
52 N src/a
53 N src/b/c
53 N src/b/c
54
54
55 No conflicts created by this import
55 No conflicts created by this import
56
56
57 $ cd ..
57 $ cd ..
58
58
59 checkout source directory
59 checkout source directory
60
60
61 $ cvscall -q checkout src
61 $ cvscall -q checkout src
62 U src/a
62 U src/a
63 U src/b/c
63 U src/b/c
64
64
65 commit a new revision changing b/c
65 commit a new revision changing b/c
66
66
67 $ cd src
67 $ cd src
68 $ sleep 1
68 $ sleep 1
69 $ echo c >> b/c
69 $ echo c >> b/c
70 $ cvscall -q commit -mci0 . | grep '<--'
70 $ cvscall -q commit -mci0 . | grep '<--'
71 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
71 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
72 $ cd ..
72 $ cd ..
73
73
74 convert fresh repo and also check localtimezone option
74 convert fresh repo and also check localtimezone option
75
75
76 NOTE: This doesn't check all time zones -- it merely determines that
76 NOTE: This doesn't check all time zones -- it merely determines that
77 the configuration option is taking effect.
77 the configuration option is taking effect.
78
78
79 An arbitrary (U.S.) time zone is used here. TZ=US/Hawaii is selected
79 An arbitrary (U.S.) time zone is used here. TZ=US/Hawaii is selected
80 since it does not use DST (unlike other U.S. time zones) and is always
80 since it does not use DST (unlike other U.S. time zones) and is always
81 a fixed difference from UTC.
81 a fixed difference from UTC.
82
82
83 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
83 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
84 initializing destination src-hg repository
84 initializing destination src-hg repository
85 connecting to $TESTTMP/cvsrepo
85 connecting to $TESTTMP/cvsrepo
86 scanning source...
86 scanning source...
87 collecting CVS rlog
87 collecting CVS rlog
88 5 log entries
88 5 log entries
89 cvslog hook: 5 entries
89 cvslog hook: 5 entries
90 creating changesets
90 creating changesets
91 3 changeset entries
91 3 changeset entries
92 cvschangesets hook: 3 changesets
92 cvschangesets hook: 3 changesets
93 sorting...
93 sorting...
94 converting...
94 converting...
95 2 Initial revision
95 2 Initial revision
96 1 ci0
96 1 ci0
97 0 import
97 0 import
98 updating tags
98 updating tags
99 $ hgcat a
99 $ hgcat a
100 a
100 a
101 $ hgcat b/c
101 $ hgcat b/c
102 c
102 c
103 c
103 c
104
104
105 convert fresh repo with --filemap
105 convert fresh repo with --filemap
106
106
107 $ echo include b/c > filemap
107 $ echo include b/c > filemap
108 $ hg convert --filemap filemap src src-filemap
108 $ hg convert --filemap filemap src src-filemap
109 initializing destination src-filemap repository
109 initializing destination src-filemap repository
110 connecting to $TESTTMP/cvsrepo
110 connecting to $TESTTMP/cvsrepo
111 scanning source...
111 scanning source...
112 collecting CVS rlog
112 collecting CVS rlog
113 5 log entries
113 5 log entries
114 cvslog hook: 5 entries
114 cvslog hook: 5 entries
115 creating changesets
115 creating changesets
116 3 changeset entries
116 3 changeset entries
117 cvschangesets hook: 3 changesets
117 cvschangesets hook: 3 changesets
118 sorting...
118 sorting...
119 converting...
119 converting...
120 2 Initial revision
120 2 Initial revision
121 1 ci0
121 1 ci0
122 0 import
122 0 import
123 filtering out empty revision
123 filtering out empty revision
124 repository tip rolled back to revision 1 (undo commit)
124 repository tip rolled back to revision 1 (undo convert)
125 updating tags
125 updating tags
126 $ hgcat b/c
126 $ hgcat b/c
127 c
127 c
128 c
128 c
129 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
129 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
130 2 update tags files: .hgtags
130 2 update tags files: .hgtags
131 1 ci0 files: b/c
131 1 ci0 files: b/c
132 0 Initial revision files: b/c
132 0 Initial revision files: b/c
133
133
134 convert full repository (issue1649)
134 convert full repository (issue1649)
135
135
136 $ cvscall -q -d "$CVSROOT" checkout -d srcfull "." | grep -v CVSROOT
136 $ cvscall -q -d "$CVSROOT" checkout -d srcfull "." | grep -v CVSROOT
137 U srcfull/src/a
137 U srcfull/src/a
138 U srcfull/src/b/c
138 U srcfull/src/b/c
139 $ ls srcfull
139 $ ls srcfull
140 CVS
140 CVS
141 CVSROOT
141 CVSROOT
142 src
142 src
143 $ hg convert srcfull srcfull-hg \
143 $ hg convert srcfull srcfull-hg \
144 > | grep -v 'log entries' | grep -v 'hook:' \
144 > | grep -v 'log entries' | grep -v 'hook:' \
145 > | grep -v '^[0-3] .*' # filter instable changeset order
145 > | grep -v '^[0-3] .*' # filter instable changeset order
146 initializing destination srcfull-hg repository
146 initializing destination srcfull-hg repository
147 connecting to $TESTTMP/cvsrepo
147 connecting to $TESTTMP/cvsrepo
148 scanning source...
148 scanning source...
149 collecting CVS rlog
149 collecting CVS rlog
150 creating changesets
150 creating changesets
151 4 changeset entries
151 4 changeset entries
152 sorting...
152 sorting...
153 converting...
153 converting...
154 updating tags
154 updating tags
155 $ hg cat -r tip --cwd srcfull-hg src/a
155 $ hg cat -r tip --cwd srcfull-hg src/a
156 a
156 a
157 $ hg cat -r tip --cwd srcfull-hg src/b/c
157 $ hg cat -r tip --cwd srcfull-hg src/b/c
158 c
158 c
159 c
159 c
160
160
161 commit new file revisions
161 commit new file revisions
162
162
163 $ cd src
163 $ cd src
164 $ echo a >> a
164 $ echo a >> a
165 $ echo c >> b/c
165 $ echo c >> b/c
166 $ cvscall -q commit -mci1 . | grep '<--'
166 $ cvscall -q commit -mci1 . | grep '<--'
167 $TESTTMP/cvsrepo/src/a,v <-- a
167 $TESTTMP/cvsrepo/src/a,v <-- a
168 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
168 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
169 $ cd ..
169 $ cd ..
170
170
171 convert again
171 convert again
172
172
173 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
173 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
174 connecting to $TESTTMP/cvsrepo
174 connecting to $TESTTMP/cvsrepo
175 scanning source...
175 scanning source...
176 collecting CVS rlog
176 collecting CVS rlog
177 7 log entries
177 7 log entries
178 cvslog hook: 7 entries
178 cvslog hook: 7 entries
179 creating changesets
179 creating changesets
180 4 changeset entries
180 4 changeset entries
181 cvschangesets hook: 4 changesets
181 cvschangesets hook: 4 changesets
182 sorting...
182 sorting...
183 converting...
183 converting...
184 0 ci1
184 0 ci1
185 $ hgcat a
185 $ hgcat a
186 a
186 a
187 a
187 a
188 $ hgcat b/c
188 $ hgcat b/c
189 c
189 c
190 c
190 c
191 c
191 c
192
192
193 convert again with --filemap
193 convert again with --filemap
194
194
195 $ hg convert --filemap filemap src src-filemap
195 $ hg convert --filemap filemap src src-filemap
196 connecting to $TESTTMP/cvsrepo
196 connecting to $TESTTMP/cvsrepo
197 scanning source...
197 scanning source...
198 collecting CVS rlog
198 collecting CVS rlog
199 7 log entries
199 7 log entries
200 cvslog hook: 7 entries
200 cvslog hook: 7 entries
201 creating changesets
201 creating changesets
202 4 changeset entries
202 4 changeset entries
203 cvschangesets hook: 4 changesets
203 cvschangesets hook: 4 changesets
204 sorting...
204 sorting...
205 converting...
205 converting...
206 0 ci1
206 0 ci1
207 $ hgcat b/c
207 $ hgcat b/c
208 c
208 c
209 c
209 c
210 c
210 c
211 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
211 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
212 3 ci1 files: b/c
212 3 ci1 files: b/c
213 2 update tags files: .hgtags
213 2 update tags files: .hgtags
214 1 ci0 files: b/c
214 1 ci0 files: b/c
215 0 Initial revision files: b/c
215 0 Initial revision files: b/c
216
216
217 commit branch
217 commit branch
218
218
219 $ cd src
219 $ cd src
220 $ cvs -q update -r1.1 b/c
220 $ cvs -q update -r1.1 b/c
221 U b/c
221 U b/c
222 $ cvs -q tag -b branch
222 $ cvs -q tag -b branch
223 T a
223 T a
224 T b/c
224 T b/c
225 $ cvs -q update -r branch > /dev/null
225 $ cvs -q update -r branch > /dev/null
226 $ echo d >> b/c
226 $ echo d >> b/c
227 $ cvs -q commit -mci2 . | grep '<--'
227 $ cvs -q commit -mci2 . | grep '<--'
228 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
228 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
229 $ cd ..
229 $ cd ..
230
230
231 convert again
231 convert again
232
232
233 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
233 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
234 connecting to $TESTTMP/cvsrepo
234 connecting to $TESTTMP/cvsrepo
235 scanning source...
235 scanning source...
236 collecting CVS rlog
236 collecting CVS rlog
237 8 log entries
237 8 log entries
238 cvslog hook: 8 entries
238 cvslog hook: 8 entries
239 creating changesets
239 creating changesets
240 5 changeset entries
240 5 changeset entries
241 cvschangesets hook: 5 changesets
241 cvschangesets hook: 5 changesets
242 sorting...
242 sorting...
243 converting...
243 converting...
244 0 ci2
244 0 ci2
245 $ hgcat b/c
245 $ hgcat b/c
246 c
246 c
247 d
247 d
248
248
249 convert again with --filemap
249 convert again with --filemap
250
250
251 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True --filemap filemap src src-filemap
251 $ TZ=US/Hawaii hg convert --config convert.localtimezone=True --filemap filemap src src-filemap
252 connecting to $TESTTMP/cvsrepo
252 connecting to $TESTTMP/cvsrepo
253 scanning source...
253 scanning source...
254 collecting CVS rlog
254 collecting CVS rlog
255 8 log entries
255 8 log entries
256 cvslog hook: 8 entries
256 cvslog hook: 8 entries
257 creating changesets
257 creating changesets
258 5 changeset entries
258 5 changeset entries
259 cvschangesets hook: 5 changesets
259 cvschangesets hook: 5 changesets
260 sorting...
260 sorting...
261 converting...
261 converting...
262 0 ci2
262 0 ci2
263 $ hgcat b/c
263 $ hgcat b/c
264 c
264 c
265 d
265 d
266 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
266 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
267 4 ci2 files: b/c
267 4 ci2 files: b/c
268 3 ci1 files: b/c
268 3 ci1 files: b/c
269 2 update tags files: .hgtags
269 2 update tags files: .hgtags
270 1 ci0 files: b/c
270 1 ci0 files: b/c
271 0 Initial revision files: b/c
271 0 Initial revision files: b/c
272
272
273 commit a new revision with funny log message
273 commit a new revision with funny log message
274
274
275 $ cd src
275 $ cd src
276 $ sleep 1
276 $ sleep 1
277 $ echo e >> a
277 $ echo e >> a
278 $ cvscall -q commit -m'funny
278 $ cvscall -q commit -m'funny
279 > ----------------------------
279 > ----------------------------
280 > log message' . | grep '<--' |\
280 > log message' . | grep '<--' |\
281 > sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
281 > sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
282 checking in src/a,v
282 checking in src/a,v
283
283
284 commit new file revisions with some fuzz
284 commit new file revisions with some fuzz
285
285
286 $ sleep 1
286 $ sleep 1
287 $ echo f >> a
287 $ echo f >> a
288 $ cvscall -q commit -mfuzzy . | grep '<--'
288 $ cvscall -q commit -mfuzzy . | grep '<--'
289 $TESTTMP/cvsrepo/src/a,v <-- a
289 $TESTTMP/cvsrepo/src/a,v <-- a
290 $ sleep 4 # the two changes will be split if fuzz < 4
290 $ sleep 4 # the two changes will be split if fuzz < 4
291 $ echo g >> b/c
291 $ echo g >> b/c
292 $ cvscall -q commit -mfuzzy . | grep '<--'
292 $ cvscall -q commit -mfuzzy . | grep '<--'
293 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
293 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
294 $ cd ..
294 $ cd ..
295
295
296 convert again
296 convert again
297
297
298 $ TZ=US/Hawaii hg convert --config convert.cvsps.fuzz=2 --config convert.localtimezone=True src src-hg
298 $ TZ=US/Hawaii hg convert --config convert.cvsps.fuzz=2 --config convert.localtimezone=True src src-hg
299 connecting to $TESTTMP/cvsrepo
299 connecting to $TESTTMP/cvsrepo
300 scanning source...
300 scanning source...
301 collecting CVS rlog
301 collecting CVS rlog
302 11 log entries
302 11 log entries
303 cvslog hook: 11 entries
303 cvslog hook: 11 entries
304 creating changesets
304 creating changesets
305 8 changeset entries
305 8 changeset entries
306 cvschangesets hook: 8 changesets
306 cvschangesets hook: 8 changesets
307 sorting...
307 sorting...
308 converting...
308 converting...
309 2 funny
309 2 funny
310 1 fuzzy
310 1 fuzzy
311 0 fuzzy
311 0 fuzzy
312 $ hg -R src-hg log -G --template '{rev} ({branches}) {desc} date: {date|date} files: {files}\n'
312 $ hg -R src-hg log -G --template '{rev} ({branches}) {desc} date: {date|date} files: {files}\n'
313 o 8 (branch) fuzzy date: * -1000 files: b/c (glob)
313 o 8 (branch) fuzzy date: * -1000 files: b/c (glob)
314 |
314 |
315 o 7 (branch) fuzzy date: * -1000 files: a (glob)
315 o 7 (branch) fuzzy date: * -1000 files: a (glob)
316 |
316 |
317 o 6 (branch) funny
317 o 6 (branch) funny
318 | ----------------------------
318 | ----------------------------
319 | log message date: * -1000 files: a (glob)
319 | log message date: * -1000 files: a (glob)
320 o 5 (branch) ci2 date: * -1000 files: b/c (glob)
320 o 5 (branch) ci2 date: * -1000 files: b/c (glob)
321
321
322 o 4 () ci1 date: * -1000 files: a b/c (glob)
322 o 4 () ci1 date: * -1000 files: a b/c (glob)
323 |
323 |
324 o 3 () update tags date: * +0000 files: .hgtags (glob)
324 o 3 () update tags date: * +0000 files: .hgtags (glob)
325 |
325 |
326 | o 2 (INITIAL) import date: * -1000 files: (glob)
326 | o 2 (INITIAL) import date: * -1000 files: (glob)
327 | |
327 | |
328 o | 1 () ci0 date: * -1000 files: b/c (glob)
328 o | 1 () ci0 date: * -1000 files: b/c (glob)
329 |/
329 |/
330 o 0 () Initial revision date: * -1000 files: a b/c (glob)
330 o 0 () Initial revision date: * -1000 files: a b/c (glob)
331
331
332
332
333 testing debugcvsps
333 testing debugcvsps
334
334
335 $ cd src
335 $ cd src
336 $ hg debugcvsps --fuzz=2
336 $ hg debugcvsps --fuzz=2
337 collecting CVS rlog
337 collecting CVS rlog
338 11 log entries
338 11 log entries
339 cvslog hook: 11 entries
339 cvslog hook: 11 entries
340 creating changesets
340 creating changesets
341 10 changeset entries
341 10 changeset entries
342 cvschangesets hook: 10 changesets
342 cvschangesets hook: 10 changesets
343 ---------------------
343 ---------------------
344 PatchSet 1
344 PatchSet 1
345 Date: * (glob)
345 Date: * (glob)
346 Author: * (glob)
346 Author: * (glob)
347 Branch: HEAD
347 Branch: HEAD
348 Tag: (none)
348 Tag: (none)
349 Branchpoints: INITIAL
349 Branchpoints: INITIAL
350 Log:
350 Log:
351 Initial revision
351 Initial revision
352
352
353 Members:
353 Members:
354 a:INITIAL->1.1
354 a:INITIAL->1.1
355
355
356 ---------------------
356 ---------------------
357 PatchSet 2
357 PatchSet 2
358 Date: * (glob)
358 Date: * (glob)
359 Author: * (glob)
359 Author: * (glob)
360 Branch: HEAD
360 Branch: HEAD
361 Tag: (none)
361 Tag: (none)
362 Branchpoints: INITIAL, branch
362 Branchpoints: INITIAL, branch
363 Log:
363 Log:
364 Initial revision
364 Initial revision
365
365
366 Members:
366 Members:
367 b/c:INITIAL->1.1
367 b/c:INITIAL->1.1
368
368
369 ---------------------
369 ---------------------
370 PatchSet 3
370 PatchSet 3
371 Date: * (glob)
371 Date: * (glob)
372 Author: * (glob)
372 Author: * (glob)
373 Branch: INITIAL
373 Branch: INITIAL
374 Tag: start
374 Tag: start
375 Log:
375 Log:
376 import
376 import
377
377
378 Members:
378 Members:
379 a:1.1->1.1.1.1
379 a:1.1->1.1.1.1
380 b/c:1.1->1.1.1.1
380 b/c:1.1->1.1.1.1
381
381
382 ---------------------
382 ---------------------
383 PatchSet 4
383 PatchSet 4
384 Date: * (glob)
384 Date: * (glob)
385 Author: * (glob)
385 Author: * (glob)
386 Branch: HEAD
386 Branch: HEAD
387 Tag: (none)
387 Tag: (none)
388 Log:
388 Log:
389 ci0
389 ci0
390
390
391 Members:
391 Members:
392 b/c:1.1->1.2
392 b/c:1.1->1.2
393
393
394 ---------------------
394 ---------------------
395 PatchSet 5
395 PatchSet 5
396 Date: * (glob)
396 Date: * (glob)
397 Author: * (glob)
397 Author: * (glob)
398 Branch: HEAD
398 Branch: HEAD
399 Tag: (none)
399 Tag: (none)
400 Branchpoints: branch
400 Branchpoints: branch
401 Log:
401 Log:
402 ci1
402 ci1
403
403
404 Members:
404 Members:
405 a:1.1->1.2
405 a:1.1->1.2
406
406
407 ---------------------
407 ---------------------
408 PatchSet 6
408 PatchSet 6
409 Date: * (glob)
409 Date: * (glob)
410 Author: * (glob)
410 Author: * (glob)
411 Branch: HEAD
411 Branch: HEAD
412 Tag: (none)
412 Tag: (none)
413 Log:
413 Log:
414 ci1
414 ci1
415
415
416 Members:
416 Members:
417 b/c:1.2->1.3
417 b/c:1.2->1.3
418
418
419 ---------------------
419 ---------------------
420 PatchSet 7
420 PatchSet 7
421 Date: * (glob)
421 Date: * (glob)
422 Author: * (glob)
422 Author: * (glob)
423 Branch: branch
423 Branch: branch
424 Tag: (none)
424 Tag: (none)
425 Log:
425 Log:
426 ci2
426 ci2
427
427
428 Members:
428 Members:
429 b/c:1.1->1.1.2.1
429 b/c:1.1->1.1.2.1
430
430
431 ---------------------
431 ---------------------
432 PatchSet 8
432 PatchSet 8
433 Date: * (glob)
433 Date: * (glob)
434 Author: * (glob)
434 Author: * (glob)
435 Branch: branch
435 Branch: branch
436 Tag: (none)
436 Tag: (none)
437 Log:
437 Log:
438 funny
438 funny
439 ----------------------------
439 ----------------------------
440 log message
440 log message
441
441
442 Members:
442 Members:
443 a:1.2->1.2.2.1
443 a:1.2->1.2.2.1
444
444
445 ---------------------
445 ---------------------
446 PatchSet 9
446 PatchSet 9
447 Date: * (glob)
447 Date: * (glob)
448 Author: * (glob)
448 Author: * (glob)
449 Branch: branch
449 Branch: branch
450 Tag: (none)
450 Tag: (none)
451 Log:
451 Log:
452 fuzzy
452 fuzzy
453
453
454 Members:
454 Members:
455 a:1.2.2.1->1.2.2.2
455 a:1.2.2.1->1.2.2.2
456
456
457 ---------------------
457 ---------------------
458 PatchSet 10
458 PatchSet 10
459 Date: * (glob)
459 Date: * (glob)
460 Author: * (glob)
460 Author: * (glob)
461 Branch: branch
461 Branch: branch
462 Tag: (none)
462 Tag: (none)
463 Log:
463 Log:
464 fuzzy
464 fuzzy
465
465
466 Members:
466 Members:
467 b/c:1.1.2.1->1.1.2.2
467 b/c:1.1.2.1->1.1.2.2
468
468
469
469
470 $ cd ..
470 $ cd ..
@@ -1,673 +1,673
1
1
2 $ HGMERGE=true; export HGMERGE
2 $ HGMERGE=true; export HGMERGE
3 $ echo '[extensions]' >> $HGRCPATH
3 $ echo '[extensions]' >> $HGRCPATH
4 $ echo 'convert =' >> $HGRCPATH
4 $ echo 'convert =' >> $HGRCPATH
5 $ glog()
5 $ glog()
6 > {
6 > {
7 > hg log -G --template '{rev} "{desc}" files: {files}\n' "$@"
7 > hg log -G --template '{rev} "{desc}" files: {files}\n' "$@"
8 > }
8 > }
9 $ hg init source
9 $ hg init source
10 $ cd source
10 $ cd source
11 $ echo foo > foo
11 $ echo foo > foo
12 $ echo baz > baz
12 $ echo baz > baz
13 $ mkdir -p dir/subdir
13 $ mkdir -p dir/subdir
14 $ echo dir/file >> dir/file
14 $ echo dir/file >> dir/file
15 $ echo dir/file2 >> dir/file2
15 $ echo dir/file2 >> dir/file2
16 $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
16 $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
17 $ echo dir/subdir/file3 >> dir/subdir/file3
17 $ echo dir/subdir/file3 >> dir/subdir/file3
18 $ echo dir/subdir/file4 >> dir/subdir/file4
18 $ echo dir/subdir/file4 >> dir/subdir/file4
19 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
19 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
20 $ echo bar > bar
20 $ echo bar > bar
21 $ echo quux > quux
21 $ echo quux > quux
22 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
22 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
23 $ hg copy foo copied
23 $ hg copy foo copied
24 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
24 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
25 $ echo >> foo
25 $ echo >> foo
26 $ hg ci -d '2 0' -m '2: change foo'
26 $ hg ci -d '2 0' -m '2: change foo'
27 $ hg up -qC 1
27 $ hg up -qC 1
28 $ echo >> bar
28 $ echo >> bar
29 $ echo >> quux
29 $ echo >> quux
30 $ hg ci -d '3 0' -m '3: change bar quux'
30 $ hg ci -d '3 0' -m '3: change bar quux'
31 created new head
31 created new head
32 $ hg up -qC 2
32 $ hg up -qC 2
33 $ hg merge -qr 3
33 $ hg merge -qr 3
34 $ echo >> bar
34 $ echo >> bar
35 $ echo >> baz
35 $ echo >> baz
36 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
36 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
37 $ echo >> bar
37 $ echo >> bar
38 $ echo 1 >> baz
38 $ echo 1 >> baz
39 $ echo >> quux
39 $ echo >> quux
40 $ hg ci -d '5 0' -m '5: change bar baz quux'
40 $ hg ci -d '5 0' -m '5: change bar baz quux'
41 $ hg up -qC 4
41 $ hg up -qC 4
42 $ echo >> foo
42 $ echo >> foo
43 $ echo 2 >> baz
43 $ echo 2 >> baz
44 $ hg ci -d '6 0' -m '6: change foo baz'
44 $ hg ci -d '6 0' -m '6: change foo baz'
45 created new head
45 created new head
46 $ hg up -qC 5
46 $ hg up -qC 5
47 $ hg merge -qr 6
47 $ hg merge -qr 6
48 $ echo >> bar
48 $ echo >> bar
49 $ hg ci -d '7 0' -m '7: second merge; change bar'
49 $ hg ci -d '7 0' -m '7: second merge; change bar'
50 $ echo >> foo
50 $ echo >> foo
51 $ hg ci -m '8: change foo'
51 $ hg ci -m '8: change foo'
52 $ glog
52 $ glog
53 @ 8 "8: change foo" files: foo
53 @ 8 "8: change foo" files: foo
54 |
54 |
55 o 7 "7: second merge; change bar" files: bar baz
55 o 7 "7: second merge; change bar" files: bar baz
56 |\
56 |\
57 | o 6 "6: change foo baz" files: baz foo
57 | o 6 "6: change foo baz" files: baz foo
58 | |
58 | |
59 o | 5 "5: change bar baz quux" files: bar baz quux
59 o | 5 "5: change bar baz quux" files: bar baz quux
60 |/
60 |/
61 o 4 "4: first merge; change bar baz" files: bar baz
61 o 4 "4: first merge; change bar baz" files: bar baz
62 |\
62 |\
63 | o 3 "3: change bar quux" files: bar quux
63 | o 3 "3: change bar quux" files: bar quux
64 | |
64 | |
65 o | 2 "2: change foo" files: foo
65 o | 2 "2: change foo" files: foo
66 |/
66 |/
67 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
67 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
68 |
68 |
69 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
69 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
70
70
71
71
72 final file versions in this repo:
72 final file versions in this repo:
73
73
74 $ hg manifest --debug
74 $ hg manifest --debug
75 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
75 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
76 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
76 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
77 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
77 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
78 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
78 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
79 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
79 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
80 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
80 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
81 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
81 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
82 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
82 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
83 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
83 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
84 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
84 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
85 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
85 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
86 $ hg debugrename copied
86 $ hg debugrename copied
87 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
87 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
88
88
89 $ cd ..
89 $ cd ..
90
90
91
91
92 Test interaction with startrev and verify that changing it is handled properly:
92 Test interaction with startrev and verify that changing it is handled properly:
93
93
94 $ > empty
94 $ > empty
95 $ hg convert --filemap empty source movingstart --config convert.hg.startrev=3 -r4
95 $ hg convert --filemap empty source movingstart --config convert.hg.startrev=3 -r4
96 initializing destination movingstart repository
96 initializing destination movingstart repository
97 scanning source...
97 scanning source...
98 sorting...
98 sorting...
99 converting...
99 converting...
100 1 3: change bar quux
100 1 3: change bar quux
101 0 4: first merge; change bar baz
101 0 4: first merge; change bar baz
102 $ hg convert --filemap empty source movingstart
102 $ hg convert --filemap empty source movingstart
103 scanning source...
103 scanning source...
104 sorting...
104 sorting...
105 converting...
105 converting...
106 3 5: change bar baz quux
106 3 5: change bar baz quux
107 2 6: change foo baz
107 2 6: change foo baz
108 1 7: second merge; change bar
108 1 7: second merge; change bar
109 warning: af455ce4166b3c9c88e6309c2b9332171dcea595 parent 61e22ca76c3b3e93df20338c4e02ce286898e825 is missing
109 warning: af455ce4166b3c9c88e6309c2b9332171dcea595 parent 61e22ca76c3b3e93df20338c4e02ce286898e825 is missing
110 warning: cf908b3eeedc301c9272ebae931da966d5b326c7 parent 59e1ab45c888289513b7354484dac8a88217beab is missing
110 warning: cf908b3eeedc301c9272ebae931da966d5b326c7 parent 59e1ab45c888289513b7354484dac8a88217beab is missing
111 0 8: change foo
111 0 8: change foo
112
112
113
113
114 splitrepo tests
114 splitrepo tests
115
115
116 $ splitrepo()
116 $ splitrepo()
117 > {
117 > {
118 > msg="$1"
118 > msg="$1"
119 > files="$2"
119 > files="$2"
120 > opts=$3
120 > opts=$3
121 > echo "% $files: $msg"
121 > echo "% $files: $msg"
122 > prefix=`echo "$files" | sed -e 's/ /-/g'`
122 > prefix=`echo "$files" | sed -e 's/ /-/g'`
123 > fmap="$prefix.fmap"
123 > fmap="$prefix.fmap"
124 > repo="$prefix.repo"
124 > repo="$prefix.repo"
125 > for i in $files; do
125 > for i in $files; do
126 > echo "include $i" >> "$fmap"
126 > echo "include $i" >> "$fmap"
127 > done
127 > done
128 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
128 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
129 > hg up -q -R "$repo"
129 > hg up -q -R "$repo"
130 > glog -R "$repo"
130 > glog -R "$repo"
131 > hg -R "$repo" manifest --debug
131 > hg -R "$repo" manifest --debug
132 > }
132 > }
133 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
133 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
134 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
134 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
135 @ 3 "8: change foo" files: foo
135 @ 3 "8: change foo" files: foo
136 |
136 |
137 o 2 "6: change foo baz" files: foo
137 o 2 "6: change foo baz" files: foo
138 |
138 |
139 o 1 "2: change foo" files: foo
139 o 1 "2: change foo" files: foo
140 |
140 |
141 o 0 "0: add foo baz dir/" files: foo
141 o 0 "0: add foo baz dir/" files: foo
142
142
143 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
143 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
144 $ splitrepo 'merges are not merges anymore' bar
144 $ splitrepo 'merges are not merges anymore' bar
145 % bar: merges are not merges anymore
145 % bar: merges are not merges anymore
146 @ 4 "7: second merge; change bar" files: bar
146 @ 4 "7: second merge; change bar" files: bar
147 |
147 |
148 o 3 "5: change bar baz quux" files: bar
148 o 3 "5: change bar baz quux" files: bar
149 |
149 |
150 o 2 "4: first merge; change bar baz" files: bar
150 o 2 "4: first merge; change bar baz" files: bar
151 |
151 |
152 o 1 "3: change bar quux" files: bar
152 o 1 "3: change bar quux" files: bar
153 |
153 |
154 o 0 "1: add bar quux; copy foo to copied" files: bar
154 o 0 "1: add bar quux; copy foo to copied" files: bar
155
155
156 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
156 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
157 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
157 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
158 % baz: 1st merge is not a merge anymore; 2nd still is
158 % baz: 1st merge is not a merge anymore; 2nd still is
159 @ 4 "7: second merge; change bar" files: baz
159 @ 4 "7: second merge; change bar" files: baz
160 |\
160 |\
161 | o 3 "6: change foo baz" files: baz
161 | o 3 "6: change foo baz" files: baz
162 | |
162 | |
163 o | 2 "5: change bar baz quux" files: baz
163 o | 2 "5: change bar baz quux" files: baz
164 |/
164 |/
165 o 1 "4: first merge; change bar baz" files: baz
165 o 1 "4: first merge; change bar baz" files: baz
166 |
166 |
167 o 0 "0: add foo baz dir/" files: baz
167 o 0 "0: add foo baz dir/" files: baz
168
168
169 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
169 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
170 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
170 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
171 % foo quux: we add additional merges when they are interesting
171 % foo quux: we add additional merges when they are interesting
172 @ 8 "8: change foo" files: foo
172 @ 8 "8: change foo" files: foo
173 |
173 |
174 o 7 "7: second merge; change bar" files:
174 o 7 "7: second merge; change bar" files:
175 |\
175 |\
176 | o 6 "6: change foo baz" files: foo
176 | o 6 "6: change foo baz" files: foo
177 | |
177 | |
178 o | 5 "5: change bar baz quux" files: quux
178 o | 5 "5: change bar baz quux" files: quux
179 |/
179 |/
180 o 4 "4: first merge; change bar baz" files:
180 o 4 "4: first merge; change bar baz" files:
181 |\
181 |\
182 | o 3 "3: change bar quux" files: quux
182 | o 3 "3: change bar quux" files: quux
183 | |
183 | |
184 o | 2 "2: change foo" files: foo
184 o | 2 "2: change foo" files: foo
185 |/
185 |/
186 o 1 "1: add bar quux; copy foo to copied" files: quux
186 o 1 "1: add bar quux; copy foo to copied" files: quux
187 |
187 |
188 o 0 "0: add foo baz dir/" files: foo
188 o 0 "0: add foo baz dir/" files: foo
189
189
190 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
190 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
191 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
191 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
192 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
192 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
193 % bar quux: partial conversion
193 % bar quux: partial conversion
194 @ 1 "3: change bar quux" files: bar quux
194 @ 1 "3: change bar quux" files: bar quux
195 |
195 |
196 o 0 "1: add bar quux; copy foo to copied" files: bar quux
196 o 0 "1: add bar quux; copy foo to copied" files: bar quux
197
197
198 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
198 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
199 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
199 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
200 $ splitrepo 'complete the partial conversion' 'bar quux'
200 $ splitrepo 'complete the partial conversion' 'bar quux'
201 % bar quux: complete the partial conversion
201 % bar quux: complete the partial conversion
202 @ 4 "7: second merge; change bar" files: bar
202 @ 4 "7: second merge; change bar" files: bar
203 |
203 |
204 o 3 "5: change bar baz quux" files: bar quux
204 o 3 "5: change bar baz quux" files: bar quux
205 |
205 |
206 o 2 "4: first merge; change bar baz" files: bar
206 o 2 "4: first merge; change bar baz" files: bar
207 |
207 |
208 o 1 "3: change bar quux" files: bar quux
208 o 1 "3: change bar quux" files: bar quux
209 |
209 |
210 o 0 "1: add bar quux; copy foo to copied" files: bar quux
210 o 0 "1: add bar quux; copy foo to copied" files: bar quux
211
211
212 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
212 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
213 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
213 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
214 $ rm -r foo.repo
214 $ rm -r foo.repo
215 $ splitrepo 'partial conversion' 'foo' '-r 3'
215 $ splitrepo 'partial conversion' 'foo' '-r 3'
216 % foo: partial conversion
216 % foo: partial conversion
217 @ 0 "0: add foo baz dir/" files: foo
217 @ 0 "0: add foo baz dir/" files: foo
218
218
219 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
219 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
220 $ splitrepo 'complete the partial conversion' 'foo'
220 $ splitrepo 'complete the partial conversion' 'foo'
221 % foo: complete the partial conversion
221 % foo: complete the partial conversion
222 @ 3 "8: change foo" files: foo
222 @ 3 "8: change foo" files: foo
223 |
223 |
224 o 2 "6: change foo baz" files: foo
224 o 2 "6: change foo baz" files: foo
225 |
225 |
226 o 1 "2: change foo" files: foo
226 o 1 "2: change foo" files: foo
227 |
227 |
228 o 0 "0: add foo baz dir/" files: foo
228 o 0 "0: add foo baz dir/" files: foo
229
229
230 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
230 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
231 $ splitrepo 'copied file; source not included in new repo' copied
231 $ splitrepo 'copied file; source not included in new repo' copied
232 % copied: copied file; source not included in new repo
232 % copied: copied file; source not included in new repo
233 @ 0 "1: add bar quux; copy foo to copied" files: copied
233 @ 0 "1: add bar quux; copy foo to copied" files: copied
234
234
235 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
235 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
236 $ hg --cwd copied.repo debugrename copied
236 $ hg --cwd copied.repo debugrename copied
237 copied not renamed
237 copied not renamed
238 $ splitrepo 'copied file; source included in new repo' 'foo copied'
238 $ splitrepo 'copied file; source included in new repo' 'foo copied'
239 % foo copied: copied file; source included in new repo
239 % foo copied: copied file; source included in new repo
240 @ 4 "8: change foo" files: foo
240 @ 4 "8: change foo" files: foo
241 |
241 |
242 o 3 "6: change foo baz" files: foo
242 o 3 "6: change foo baz" files: foo
243 |
243 |
244 o 2 "2: change foo" files: foo
244 o 2 "2: change foo" files: foo
245 |
245 |
246 o 1 "1: add bar quux; copy foo to copied" files: copied
246 o 1 "1: add bar quux; copy foo to copied" files: copied
247 |
247 |
248 o 0 "0: add foo baz dir/" files: foo
248 o 0 "0: add foo baz dir/" files: foo
249
249
250 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
250 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
251 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
251 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
252 $ hg --cwd foo-copied.repo debugrename copied
252 $ hg --cwd foo-copied.repo debugrename copied
253 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
253 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
254
254
255 verify the top level 'include .' if there is no other includes:
255 verify the top level 'include .' if there is no other includes:
256
256
257 $ echo "exclude something" > default.fmap
257 $ echo "exclude something" > default.fmap
258 $ hg convert -q --filemap default.fmap -r1 source dummydest2
258 $ hg convert -q --filemap default.fmap -r1 source dummydest2
259 $ hg -R dummydest2 log --template '{rev} {node|short} {desc|firstline}\n'
259 $ hg -R dummydest2 log --template '{rev} {node|short} {desc|firstline}\n'
260 1 61e22ca76c3b 1: add bar quux; copy foo to copied
260 1 61e22ca76c3b 1: add bar quux; copy foo to copied
261 0 c085cf2ee7fe 0: add foo baz dir/
261 0 c085cf2ee7fe 0: add foo baz dir/
262
262
263 $ echo "include somethingelse" >> default.fmap
263 $ echo "include somethingelse" >> default.fmap
264 $ hg convert -q --filemap default.fmap -r1 source dummydest3
264 $ hg convert -q --filemap default.fmap -r1 source dummydest3
265 $ hg -R dummydest3 log --template '{rev} {node|short} {desc|firstline}\n'
265 $ hg -R dummydest3 log --template '{rev} {node|short} {desc|firstline}\n'
266
266
267 $ echo "include ." >> default.fmap
267 $ echo "include ." >> default.fmap
268 $ hg convert -q --filemap default.fmap -r1 source dummydest4
268 $ hg convert -q --filemap default.fmap -r1 source dummydest4
269 $ hg -R dummydest4 log --template '{rev} {node|short} {desc|firstline}\n'
269 $ hg -R dummydest4 log --template '{rev} {node|short} {desc|firstline}\n'
270 1 61e22ca76c3b 1: add bar quux; copy foo to copied
270 1 61e22ca76c3b 1: add bar quux; copy foo to copied
271 0 c085cf2ee7fe 0: add foo baz dir/
271 0 c085cf2ee7fe 0: add foo baz dir/
272
272
273 ensure that the filemap contains duplicated slashes (issue3612)
273 ensure that the filemap contains duplicated slashes (issue3612)
274
274
275 $ cat > renames.fmap <<EOF
275 $ cat > renames.fmap <<EOF
276 > include dir
276 > include dir
277 > exclude dir/file2
277 > exclude dir/file2
278 > rename dir dir2//dir3
278 > rename dir dir2//dir3
279 > include foo
279 > include foo
280 > include copied
280 > include copied
281 > rename foo foo2/
281 > rename foo foo2/
282 > rename copied ./copied2
282 > rename copied ./copied2
283 > exclude dir/subdir
283 > exclude dir/subdir
284 > include dir/subdir/file3
284 > include dir/subdir/file3
285 > EOF
285 > EOF
286 $ rm source/.hg/store/data/dir/file3.i
286 $ rm source/.hg/store/data/dir/file3.i
287 $ rm source/.hg/store/data/dir/file4.i
287 $ rm source/.hg/store/data/dir/file4.i
288 $ hg -q convert --filemap renames.fmap --datesort source dummydest
288 $ hg -q convert --filemap renames.fmap --datesort source dummydest
289 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
289 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
290 [255]
290 [255]
291 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
291 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
292 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
292 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
293 ignoring: data/dir/file4.i@6edd55f559cd: no match found
293 ignoring: data/dir/file4.i@6edd55f559cd: no match found
294 $ hg up -q -R renames.repo
294 $ hg up -q -R renames.repo
295 $ glog -R renames.repo
295 $ glog -R renames.repo
296 @ 4 "8: change foo" files: foo2
296 @ 4 "8: change foo" files: foo2
297 |
297 |
298 o 3 "6: change foo baz" files: foo2
298 o 3 "6: change foo baz" files: foo2
299 |
299 |
300 o 2 "2: change foo" files: foo2
300 o 2 "2: change foo" files: foo2
301 |
301 |
302 o 1 "1: add bar quux; copy foo to copied" files: copied2
302 o 1 "1: add bar quux; copy foo to copied" files: copied2
303 |
303 |
304 o 0 "0: add foo baz dir/" files: dir2/dir3/file dir2/dir3/subdir/file3 foo2
304 o 0 "0: add foo baz dir/" files: dir2/dir3/file dir2/dir3/subdir/file3 foo2
305
305
306 $ hg -R renames.repo verify
306 $ hg -R renames.repo verify
307 checking changesets
307 checking changesets
308 checking manifests
308 checking manifests
309 crosschecking files in changesets and manifests
309 crosschecking files in changesets and manifests
310 checking files
310 checking files
311 4 files, 5 changesets, 7 total revisions
311 4 files, 5 changesets, 7 total revisions
312
312
313 $ hg -R renames.repo manifest --debug
313 $ hg -R renames.repo manifest --debug
314 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
314 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
315 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/dir3/file
315 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/dir3/file
316 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/dir3/subdir/file3
316 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/dir3/subdir/file3
317 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
317 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
318 $ hg --cwd renames.repo debugrename copied2
318 $ hg --cwd renames.repo debugrename copied2
319 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
319 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
320
320
321 copied:
321 copied:
322
322
323 $ hg --cwd source cat copied
323 $ hg --cwd source cat copied
324 foo
324 foo
325
325
326 copied2:
326 copied2:
327
327
328 $ hg --cwd renames.repo cat copied2
328 $ hg --cwd renames.repo cat copied2
329 foo
329 foo
330
330
331 filemap errors
331 filemap errors
332
332
333 $ cat > errors.fmap <<EOF
333 $ cat > errors.fmap <<EOF
334 > include dir/ # beware that comments changes error line numbers!
334 > include dir/ # beware that comments changes error line numbers!
335 > exclude /dir
335 > exclude /dir
336 > rename dir//dir /dir//dir/ "out of sync"
336 > rename dir//dir /dir//dir/ "out of sync"
337 > include
337 > include
338 > EOF
338 > EOF
339 $ hg -q convert --filemap errors.fmap source errors.repo
339 $ hg -q convert --filemap errors.fmap source errors.repo
340 errors.fmap:3: superfluous / in include '/dir'
340 errors.fmap:3: superfluous / in include '/dir'
341 errors.fmap:3: superfluous / in rename '/dir'
341 errors.fmap:3: superfluous / in rename '/dir'
342 errors.fmap:4: unknown directive 'out of sync'
342 errors.fmap:4: unknown directive 'out of sync'
343 errors.fmap:5: path to exclude is missing
343 errors.fmap:5: path to exclude is missing
344 abort: errors in filemap
344 abort: errors in filemap
345 [255]
345 [255]
346
346
347 test branch closing revision pruning if branch is pruned
347 test branch closing revision pruning if branch is pruned
348
348
349 $ hg init branchpruning
349 $ hg init branchpruning
350 $ cd branchpruning
350 $ cd branchpruning
351 $ hg branch foo
351 $ hg branch foo
352 marked working directory as branch foo
352 marked working directory as branch foo
353 (branches are permanent and global, did you want a bookmark?)
353 (branches are permanent and global, did you want a bookmark?)
354 $ echo a > a
354 $ echo a > a
355 $ hg ci -Am adda
355 $ hg ci -Am adda
356 adding a
356 adding a
357 $ hg ci --close-branch -m closefoo
357 $ hg ci --close-branch -m closefoo
358 $ hg up 0
358 $ hg up 0
359 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
360 $ hg branch empty
360 $ hg branch empty
361 marked working directory as branch empty
361 marked working directory as branch empty
362 (branches are permanent and global, did you want a bookmark?)
362 (branches are permanent and global, did you want a bookmark?)
363 $ hg ci -m emptybranch
363 $ hg ci -m emptybranch
364 $ hg ci --close-branch -m closeempty
364 $ hg ci --close-branch -m closeempty
365 $ hg up 0
365 $ hg up 0
366 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
366 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
367 $ hg branch default
367 $ hg branch default
368 marked working directory as branch default
368 marked working directory as branch default
369 (branches are permanent and global, did you want a bookmark?)
369 (branches are permanent and global, did you want a bookmark?)
370 $ echo b > b
370 $ echo b > b
371 $ hg ci -Am addb
371 $ hg ci -Am addb
372 adding b
372 adding b
373 $ hg ci --close-branch -m closedefault
373 $ hg ci --close-branch -m closedefault
374 $ cat > filemap <<EOF
374 $ cat > filemap <<EOF
375 > include b
375 > include b
376 > EOF
376 > EOF
377 $ cd ..
377 $ cd ..
378 $ hg convert branchpruning branchpruning-hg1
378 $ hg convert branchpruning branchpruning-hg1
379 initializing destination branchpruning-hg1 repository
379 initializing destination branchpruning-hg1 repository
380 scanning source...
380 scanning source...
381 sorting...
381 sorting...
382 converting...
382 converting...
383 5 adda
383 5 adda
384 4 closefoo
384 4 closefoo
385 3 emptybranch
385 3 emptybranch
386 2 closeempty
386 2 closeempty
387 1 addb
387 1 addb
388 0 closedefault
388 0 closedefault
389 $ glog -R branchpruning-hg1
389 $ glog -R branchpruning-hg1
390 _ 5 "closedefault" files:
390 _ 5 "closedefault" files:
391 |
391 |
392 o 4 "addb" files: b
392 o 4 "addb" files: b
393 |
393 |
394 | _ 3 "closeempty" files:
394 | _ 3 "closeempty" files:
395 | |
395 | |
396 | o 2 "emptybranch" files:
396 | o 2 "emptybranch" files:
397 |/
397 |/
398 | _ 1 "closefoo" files:
398 | _ 1 "closefoo" files:
399 |/
399 |/
400 o 0 "adda" files: a
400 o 0 "adda" files: a
401
401
402
402
403 exercise incremental conversion at the same time
403 exercise incremental conversion at the same time
404
404
405 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
405 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
406 initializing destination branchpruning-hg2 repository
406 initializing destination branchpruning-hg2 repository
407 scanning source...
407 scanning source...
408 sorting...
408 sorting...
409 converting...
409 converting...
410 0 adda
410 0 adda
411 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
411 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
412 scanning source...
412 scanning source...
413 sorting...
413 sorting...
414 converting...
414 converting...
415 0 addb
415 0 addb
416 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
416 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
417 scanning source...
417 scanning source...
418 sorting...
418 sorting...
419 converting...
419 converting...
420 3 closefoo
420 3 closefoo
421 2 emptybranch
421 2 emptybranch
422 1 closeempty
422 1 closeempty
423 0 closedefault
423 0 closedefault
424 $ glog -R branchpruning-hg2
424 $ glog -R branchpruning-hg2
425 _ 1 "closedefault" files:
425 _ 1 "closedefault" files:
426 |
426 |
427 o 0 "addb" files: b
427 o 0 "addb" files: b
428
428
429
429
430 Test rebuilding of map with unknown revisions in shamap - it used to crash
430 Test rebuilding of map with unknown revisions in shamap - it used to crash
431
431
432 $ cd branchpruning
432 $ cd branchpruning
433 $ hg up -r 2
433 $ hg up -r 2
434 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
434 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
435 $ hg merge 4
435 $ hg merge 4
436 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
436 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
437 (branch merge, don't forget to commit)
437 (branch merge, don't forget to commit)
438 $ hg ci -m 'merging something'
438 $ hg ci -m 'merging something'
439 $ cd ..
439 $ cd ..
440 $ echo "53792d18237d2b64971fa571936869156655338d 6d955580116e82c4b029bd30f321323bae71a7f0" >> branchpruning-hg2/.hg/shamap
440 $ echo "53792d18237d2b64971fa571936869156655338d 6d955580116e82c4b029bd30f321323bae71a7f0" >> branchpruning-hg2/.hg/shamap
441 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2 --debug --config progress.debug=true
441 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2 --debug --config progress.debug=true
442 run hg source pre-conversion action
442 run hg source pre-conversion action
443 run hg sink pre-conversion action
443 run hg sink pre-conversion action
444 scanning source...
444 scanning source...
445 scanning: 1 revisions
445 scanning: 1 revisions
446 sorting...
446 sorting...
447 converting...
447 converting...
448 0 merging something
448 0 merging something
449 source: 2503605b178fe50e8fbbb0e77b97939540aa8c87
449 source: 2503605b178fe50e8fbbb0e77b97939540aa8c87
450 converting: 0/1 revisions (0.00%)
450 converting: 0/1 revisions (0.00%)
451 unknown revmap source: 53792d18237d2b64971fa571936869156655338d
451 unknown revmap source: 53792d18237d2b64971fa571936869156655338d
452 run hg sink post-conversion action
452 run hg sink post-conversion action
453 run hg source post-conversion action
453 run hg source post-conversion action
454
454
455
455
456 filemap rename undoing revision rename
456 filemap rename undoing revision rename
457
457
458 $ hg init renameundo
458 $ hg init renameundo
459 $ cd renameundo
459 $ cd renameundo
460 $ echo 1 > a
460 $ echo 1 > a
461 $ echo 1 > c
461 $ echo 1 > c
462 $ hg ci -qAm add
462 $ hg ci -qAm add
463 $ hg mv -q a b/a
463 $ hg mv -q a b/a
464 $ hg mv -q c b/c
464 $ hg mv -q c b/c
465 $ hg ci -qm rename
465 $ hg ci -qm rename
466 $ echo 2 > b/a
466 $ echo 2 > b/a
467 $ echo 2 > b/c
467 $ echo 2 > b/c
468 $ hg ci -qm modify
468 $ hg ci -qm modify
469 $ cd ..
469 $ cd ..
470
470
471 $ echo "rename b ." > renameundo.fmap
471 $ echo "rename b ." > renameundo.fmap
472 $ hg convert --filemap renameundo.fmap renameundo renameundo2
472 $ hg convert --filemap renameundo.fmap renameundo renameundo2
473 initializing destination renameundo2 repository
473 initializing destination renameundo2 repository
474 scanning source...
474 scanning source...
475 sorting...
475 sorting...
476 converting...
476 converting...
477 2 add
477 2 add
478 1 rename
478 1 rename
479 filtering out empty revision
479 filtering out empty revision
480 repository tip rolled back to revision 0 (undo commit)
480 repository tip rolled back to revision 0 (undo convert)
481 0 modify
481 0 modify
482 $ glog -R renameundo2
482 $ glog -R renameundo2
483 o 1 "modify" files: a c
483 o 1 "modify" files: a c
484 |
484 |
485 o 0 "add" files: a c
485 o 0 "add" files: a c
486
486
487
487
488
488
489 test merge parents/empty merges pruning
489 test merge parents/empty merges pruning
490
490
491 $ glog()
491 $ glog()
492 > {
492 > {
493 > hg log -G --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
493 > hg log -G --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
494 > }
494 > }
495
495
496 test anonymous branch pruning
496 test anonymous branch pruning
497
497
498 $ hg init anonymousbranch
498 $ hg init anonymousbranch
499 $ cd anonymousbranch
499 $ cd anonymousbranch
500 $ echo a > a
500 $ echo a > a
501 $ echo b > b
501 $ echo b > b
502 $ hg ci -Am add
502 $ hg ci -Am add
503 adding a
503 adding a
504 adding b
504 adding b
505 $ echo a >> a
505 $ echo a >> a
506 $ hg ci -m changea
506 $ hg ci -m changea
507 $ hg up 0
507 $ hg up 0
508 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
508 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
509 $ echo b >> b
509 $ echo b >> b
510 $ hg ci -m changeb
510 $ hg ci -m changeb
511 created new head
511 created new head
512 $ hg up 1
512 $ hg up 1
513 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
513 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
514 $ hg merge
514 $ hg merge
515 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
515 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
516 (branch merge, don't forget to commit)
516 (branch merge, don't forget to commit)
517 $ hg ci -m merge
517 $ hg ci -m merge
518 $ cd ..
518 $ cd ..
519
519
520 $ cat > filemap <<EOF
520 $ cat > filemap <<EOF
521 > include a
521 > include a
522 > EOF
522 > EOF
523 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg
523 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg
524 initializing destination anonymousbranch-hg repository
524 initializing destination anonymousbranch-hg repository
525 scanning source...
525 scanning source...
526 sorting...
526 sorting...
527 converting...
527 converting...
528 3 add
528 3 add
529 2 changea
529 2 changea
530 1 changeb
530 1 changeb
531 0 merge
531 0 merge
532 $ glog -R anonymousbranch
532 $ glog -R anonymousbranch
533 @ 3:c71d5201a498@default "merge" files:
533 @ 3:c71d5201a498@default "merge" files:
534 |\
534 |\
535 | o 2:607eb44b17f9@default "changeb" files: b
535 | o 2:607eb44b17f9@default "changeb" files: b
536 | |
536 | |
537 o | 1:1f60ea617824@default "changea" files: a
537 o | 1:1f60ea617824@default "changea" files: a
538 |/
538 |/
539 o 0:0146e6129113@default "add" files: a b
539 o 0:0146e6129113@default "add" files: a b
540
540
541 $ glog -R anonymousbranch-hg
541 $ glog -R anonymousbranch-hg
542 o 1:cda818e7219b@default "changea" files: a
542 o 1:cda818e7219b@default "changea" files: a
543 |
543 |
544 o 0:c334dc3be0da@default "add" files: a
544 o 0:c334dc3be0da@default "add" files: a
545
545
546 $ cat anonymousbranch-hg/.hg/shamap
546 $ cat anonymousbranch-hg/.hg/shamap
547 0146e6129113dba9ac90207cfdf2d7ed35257ae5 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
547 0146e6129113dba9ac90207cfdf2d7ed35257ae5 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
548 1f60ea61782421edf8d051ff4fcb61b330f26a4a cda818e7219b5f7f3fb9f49780054ed6a1905ec3
548 1f60ea61782421edf8d051ff4fcb61b330f26a4a cda818e7219b5f7f3fb9f49780054ed6a1905ec3
549 607eb44b17f9348cd5cbd26e16af87ba77b0b037 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
549 607eb44b17f9348cd5cbd26e16af87ba77b0b037 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
550 c71d5201a498b2658d105a6bf69d7a0df2649aea cda818e7219b5f7f3fb9f49780054ed6a1905ec3
550 c71d5201a498b2658d105a6bf69d7a0df2649aea cda818e7219b5f7f3fb9f49780054ed6a1905ec3
551
551
552 $ cat > filemap <<EOF
552 $ cat > filemap <<EOF
553 > include b
553 > include b
554 > EOF
554 > EOF
555 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg2
555 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg2
556 initializing destination anonymousbranch-hg2 repository
556 initializing destination anonymousbranch-hg2 repository
557 scanning source...
557 scanning source...
558 sorting...
558 sorting...
559 converting...
559 converting...
560 3 add
560 3 add
561 2 changea
561 2 changea
562 1 changeb
562 1 changeb
563 0 merge
563 0 merge
564 $ glog -R anonymousbranch
564 $ glog -R anonymousbranch
565 @ 3:c71d5201a498@default "merge" files:
565 @ 3:c71d5201a498@default "merge" files:
566 |\
566 |\
567 | o 2:607eb44b17f9@default "changeb" files: b
567 | o 2:607eb44b17f9@default "changeb" files: b
568 | |
568 | |
569 o | 1:1f60ea617824@default "changea" files: a
569 o | 1:1f60ea617824@default "changea" files: a
570 |/
570 |/
571 o 0:0146e6129113@default "add" files: a b
571 o 0:0146e6129113@default "add" files: a b
572
572
573 $ glog -R anonymousbranch-hg2
573 $ glog -R anonymousbranch-hg2
574 o 1:62dd350b0df6@default "changeb" files: b
574 o 1:62dd350b0df6@default "changeb" files: b
575 |
575 |
576 o 0:4b9ced861657@default "add" files: b
576 o 0:4b9ced861657@default "add" files: b
577
577
578 $ cat anonymousbranch-hg2/.hg/shamap
578 $ cat anonymousbranch-hg2/.hg/shamap
579 0146e6129113dba9ac90207cfdf2d7ed35257ae5 4b9ced86165703791653059a1db6ed864630a523
579 0146e6129113dba9ac90207cfdf2d7ed35257ae5 4b9ced86165703791653059a1db6ed864630a523
580 1f60ea61782421edf8d051ff4fcb61b330f26a4a 4b9ced86165703791653059a1db6ed864630a523
580 1f60ea61782421edf8d051ff4fcb61b330f26a4a 4b9ced86165703791653059a1db6ed864630a523
581 607eb44b17f9348cd5cbd26e16af87ba77b0b037 62dd350b0df695f7d2c82a02e0499b16fd790f22
581 607eb44b17f9348cd5cbd26e16af87ba77b0b037 62dd350b0df695f7d2c82a02e0499b16fd790f22
582 c71d5201a498b2658d105a6bf69d7a0df2649aea 62dd350b0df695f7d2c82a02e0499b16fd790f22
582 c71d5201a498b2658d105a6bf69d7a0df2649aea 62dd350b0df695f7d2c82a02e0499b16fd790f22
583
583
584 test named branch pruning
584 test named branch pruning
585
585
586 $ hg init namedbranch
586 $ hg init namedbranch
587 $ cd namedbranch
587 $ cd namedbranch
588 $ echo a > a
588 $ echo a > a
589 $ echo b > b
589 $ echo b > b
590 $ hg ci -Am add
590 $ hg ci -Am add
591 adding a
591 adding a
592 adding b
592 adding b
593 $ echo a >> a
593 $ echo a >> a
594 $ hg ci -m changea
594 $ hg ci -m changea
595 $ hg up 0
595 $ hg up 0
596 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
596 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 $ hg branch foo
597 $ hg branch foo
598 marked working directory as branch foo
598 marked working directory as branch foo
599 (branches are permanent and global, did you want a bookmark?)
599 (branches are permanent and global, did you want a bookmark?)
600 $ echo b >> b
600 $ echo b >> b
601 $ hg ci -m changeb
601 $ hg ci -m changeb
602 $ hg up default
602 $ hg up default
603 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
603 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
604 $ hg merge foo
604 $ hg merge foo
605 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
605 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 (branch merge, don't forget to commit)
606 (branch merge, don't forget to commit)
607 $ hg ci -m merge
607 $ hg ci -m merge
608 $ cd ..
608 $ cd ..
609
609
610 $ cat > filemap <<EOF
610 $ cat > filemap <<EOF
611 > include a
611 > include a
612 > EOF
612 > EOF
613 $ hg convert --filemap filemap namedbranch namedbranch-hg
613 $ hg convert --filemap filemap namedbranch namedbranch-hg
614 initializing destination namedbranch-hg repository
614 initializing destination namedbranch-hg repository
615 scanning source...
615 scanning source...
616 sorting...
616 sorting...
617 converting...
617 converting...
618 3 add
618 3 add
619 2 changea
619 2 changea
620 1 changeb
620 1 changeb
621 0 merge
621 0 merge
622 $ glog -R namedbranch
622 $ glog -R namedbranch
623 @ 3:73899bcbe45c@default "merge" files:
623 @ 3:73899bcbe45c@default "merge" files:
624 |\
624 |\
625 | o 2:8097982d19fc@foo "changeb" files: b
625 | o 2:8097982d19fc@foo "changeb" files: b
626 | |
626 | |
627 o | 1:1f60ea617824@default "changea" files: a
627 o | 1:1f60ea617824@default "changea" files: a
628 |/
628 |/
629 o 0:0146e6129113@default "add" files: a b
629 o 0:0146e6129113@default "add" files: a b
630
630
631 $ glog -R namedbranch-hg
631 $ glog -R namedbranch-hg
632 o 1:cda818e7219b@default "changea" files: a
632 o 1:cda818e7219b@default "changea" files: a
633 |
633 |
634 o 0:c334dc3be0da@default "add" files: a
634 o 0:c334dc3be0da@default "add" files: a
635
635
636
636
637 $ cd namedbranch
637 $ cd namedbranch
638 $ hg --config extensions.mq= strip tip
638 $ hg --config extensions.mq= strip tip
639 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
639 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
640 saved backup bundle to $TESTTMP/namedbranch/.hg/strip-backup/73899bcbe45c-92adf160-backup.hg (glob)
640 saved backup bundle to $TESTTMP/namedbranch/.hg/strip-backup/73899bcbe45c-92adf160-backup.hg (glob)
641 $ hg up foo
641 $ hg up foo
642 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
642 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
643 $ hg merge default
643 $ hg merge default
644 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
644 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 (branch merge, don't forget to commit)
645 (branch merge, don't forget to commit)
646 $ hg ci -m merge
646 $ hg ci -m merge
647 $ cd ..
647 $ cd ..
648
648
649 $ hg convert --filemap filemap namedbranch namedbranch-hg2
649 $ hg convert --filemap filemap namedbranch namedbranch-hg2
650 initializing destination namedbranch-hg2 repository
650 initializing destination namedbranch-hg2 repository
651 scanning source...
651 scanning source...
652 sorting...
652 sorting...
653 converting...
653 converting...
654 3 add
654 3 add
655 2 changea
655 2 changea
656 1 changeb
656 1 changeb
657 0 merge
657 0 merge
658 $ glog -R namedbranch
658 $ glog -R namedbranch
659 @ 3:e1959de76e1b@foo "merge" files:
659 @ 3:e1959de76e1b@foo "merge" files:
660 |\
660 |\
661 | o 2:8097982d19fc@foo "changeb" files: b
661 | o 2:8097982d19fc@foo "changeb" files: b
662 | |
662 | |
663 o | 1:1f60ea617824@default "changea" files: a
663 o | 1:1f60ea617824@default "changea" files: a
664 |/
664 |/
665 o 0:0146e6129113@default "add" files: a b
665 o 0:0146e6129113@default "add" files: a b
666
666
667 $ glog -R namedbranch-hg2
667 $ glog -R namedbranch-hg2
668 o 2:dcf314454667@foo "merge" files:
668 o 2:dcf314454667@foo "merge" files:
669 |\
669 |\
670 | o 1:cda818e7219b@default "changea" files: a
670 | o 1:cda818e7219b@default "changea" files: a
671 |/
671 |/
672 o 0:c334dc3be0da@default "add" files: a
672 o 0:c334dc3be0da@default "add" files: a
673
673
@@ -1,552 +1,564
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 tag -l local-tag
20 $ hg log
20 $ hg log
21 changeset: 3:593cbf6fb2b4
21 changeset: 3:593cbf6fb2b4
22 tag: local-tag
22 tag: local-tag
23 tag: tip
23 tag: tip
24 user: test
24 user: test
25 date: Thu Jan 01 00:00:00 1970 +0000
25 date: Thu Jan 01 00:00:00 1970 +0000
26 summary: Added tag some-tag for changeset ad681a868e44
26 summary: Added tag some-tag for changeset ad681a868e44
27
27
28 changeset: 2:ad681a868e44
28 changeset: 2:ad681a868e44
29 tag: some-tag
29 tag: some-tag
30 user: test
30 user: test
31 date: Thu Jan 01 00:00:00 1970 +0000
31 date: Thu Jan 01 00:00:00 1970 +0000
32 summary: add foo/file
32 summary: add foo/file
33
33
34 changeset: 1:cbba8ecc03b7
34 changeset: 1:cbba8ecc03b7
35 user: test
35 user: test
36 date: Thu Jan 01 00:00:00 1970 +0000
36 date: Thu Jan 01 00:00:00 1970 +0000
37 summary: remove foo
37 summary: remove foo
38
38
39 changeset: 0:327daa9251fa
39 changeset: 0:327daa9251fa
40 user: test
40 user: test
41 date: Thu Jan 01 00:00:00 1970 +0000
41 date: Thu Jan 01 00:00:00 1970 +0000
42 summary: add foo and bar
42 summary: add foo and bar
43
43
44 $ hg phase --public -r tip
44 $ cd ..
45 $ cd ..
45 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
46 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
46 initializing destination new repository
47 initializing destination new repository
47 scanning source...
48 scanning source...
48 sorting...
49 sorting...
49 converting...
50 converting...
50 3 add foo and bar
51 3 add foo and bar
51 2 remove foo
52 2 remove foo
52 1 add foo/file
53 1 add foo/file
53 0 Added tag some-tag for changeset ad681a868e44
54 0 Added tag some-tag for changeset ad681a868e44
54 $ cd new
55 $ cd new
56 $ hg log -G --template '{rev} {node|short} ({phase}) "{desc}"\n'
57 o 3 593cbf6fb2b4 (public) "Added tag some-tag for changeset ad681a868e44"
58 |
59 o 2 ad681a868e44 (public) "add foo/file"
60 |
61 o 1 cbba8ecc03b7 (public) "remove foo"
62 |
63 o 0 327daa9251fa (public) "add foo and bar"
64
65
55 $ hg out ../orig
66 $ hg out ../orig
56 comparing with ../orig
67 comparing with ../orig
57 searching for changes
68 searching for changes
58 no changes found
69 no changes found
59 [1]
70 [1]
60
71
61 dirstate should be empty:
72 dirstate should be empty:
62
73
63 $ hg debugstate
74 $ hg debugstate
64 $ hg parents -q
75 $ hg parents -q
65 $ hg up -C
76 $ hg up -C
66 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 $ hg copy bar baz
78 $ hg copy bar baz
68
79
69 put something in the dirstate:
80 put something in the dirstate:
70
81
71 $ hg debugstate > debugstate
82 $ hg debugstate > debugstate
72 $ grep baz debugstate
83 $ grep baz debugstate
73 a 0 -1 unset baz
84 a 0 -1 unset baz
74 copy: bar -> baz
85 copy: bar -> baz
75
86
76 add a new revision in the original repo
87 add a new revision in the original repo
77
88
78 $ cd ../orig
89 $ cd ../orig
79 $ echo baz > baz
90 $ echo baz > baz
80 $ hg ci -qAm 'add baz'
91 $ hg ci -qAm 'add baz'
81 $ cd ..
92 $ cd ..
82 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
93 $ hg convert orig new 2>&1 | grep -v 'subversion python bindings could not be loaded'
83 scanning source...
94 scanning source...
84 sorting...
95 sorting...
85 converting...
96 converting...
86 0 add baz
97 0 add baz
87 $ cd new
98 $ cd new
88 $ hg out ../orig
99 $ hg out ../orig
89 comparing with ../orig
100 comparing with ../orig
90 searching for changes
101 searching for changes
91 no changes found
102 no changes found
92 [1]
103 [1]
93
104
94 dirstate should be the same (no output below):
105 dirstate should be the same (no output below):
95
106
96 $ hg debugstate > new-debugstate
107 $ hg debugstate > new-debugstate
97 $ diff debugstate new-debugstate
108 $ diff debugstate new-debugstate
98
109
99 no copies
110 no copies
100
111
101 $ hg up -C
112 $ hg up -C
102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 $ hg debugrename baz
114 $ hg debugrename baz
104 baz not renamed
115 baz not renamed
105 $ cd ..
116 $ cd ..
106
117
107 test tag rewriting
118 test tag rewriting
108
119
109 $ cat > filemap <<EOF
120 $ cat > filemap <<EOF
110 > exclude foo
121 > exclude foo
111 > EOF
122 > EOF
112 $ hg convert --filemap filemap orig new-filemap 2>&1 | grep -v 'subversion python bindings could not be loaded'
123 $ hg convert --filemap filemap orig new-filemap 2>&1 | grep -v 'subversion python bindings could not be loaded'
113 initializing destination new-filemap repository
124 initializing destination new-filemap repository
114 scanning source...
125 scanning source...
115 sorting...
126 sorting...
116 converting...
127 converting...
117 4 add foo and bar
128 4 add foo and bar
118 3 remove foo
129 3 remove foo
119 2 add foo/file
130 2 add foo/file
120 1 Added tag some-tag for changeset ad681a868e44
131 1 Added tag some-tag for changeset ad681a868e44
121 0 add baz
132 0 add baz
122 $ cd new-filemap
133 $ cd new-filemap
123 $ hg tags
134 $ hg tags
124 tip 2:3c74706b1ff8
135 tip 2:3c74706b1ff8
125 some-tag 0:ba8636729451
136 some-tag 0:ba8636729451
126 $ cd ..
137 $ cd ..
127
138
128
139
129 Test cases for hg-hg roundtrip
140 Test cases for hg-hg roundtrip
130
141
131 Helper
142 Helper
132
143
133 $ glog()
144 $ glog()
134 > {
145 > {
135 > hg log -G --template '{rev} {node|short} "{desc}" files: {files}\n' $*
146 > hg log -G --template '{rev} {node|short} ({phase}) "{desc}" files: {files}\n' $*
136 > }
147 > }
137
148
138 Create a tricky source repo
149 Create a tricky source repo
139
150
140 $ hg init source
151 $ hg init source
141 $ cd source
152 $ cd source
142
153
143 $ echo 0 > 0
154 $ echo 0 > 0
144 $ hg ci -Aqm '0: add 0'
155 $ hg ci -Aqm '0: add 0'
145 $ echo a > a
156 $ echo a > a
146 $ mkdir dir
157 $ mkdir dir
147 $ echo b > dir/b
158 $ echo b > dir/b
148 $ hg ci -qAm '1: add a and dir/b'
159 $ hg ci -qAm '1: add a and dir/b'
149 $ echo c > dir/c
160 $ echo c > dir/c
150 $ hg ci -qAm '2: add dir/c'
161 $ hg ci -qAm '2: add dir/c'
151 $ hg copy a e
162 $ hg copy a e
152 $ echo b >> b
163 $ echo b >> b
153 $ hg ci -qAm '3: copy a to e, change b'
164 $ hg ci -qAm '3: copy a to e, change b'
154 $ hg up -qr -3
165 $ hg up -qr -3
155 $ echo a >> a
166 $ echo a >> a
156 $ hg ci -qAm '4: change a'
167 $ hg ci -qAm '4: change a'
157 $ hg merge
168 $ hg merge
158 merging a and e to e
169 merging a and e to e
159 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
170 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
160 (branch merge, don't forget to commit)
171 (branch merge, don't forget to commit)
161 $ hg copy b dir/d
172 $ hg copy b dir/d
162 $ hg ci -qAm '5: merge 2 and 3, copy b to dir/d'
173 $ hg ci -qAm '5: merge 2 and 3, copy b to dir/d'
163 $ echo a >> a
174 $ echo a >> a
164 $ hg ci -qAm '6: change a'
175 $ hg ci -qAm '6: change a'
165
176
166 $ hg mani
177 $ hg mani
167 0
178 0
168 a
179 a
169 b
180 b
170 dir/b
181 dir/b
171 dir/c
182 dir/c
172 dir/d
183 dir/d
173 e
184 e
185 $ hg phase --public -r tip
174 $ glog
186 $ glog
175 @ 6 0613c8e59a3d "6: change a" files: a
187 @ 6 0613c8e59a3d (public) "6: change a" files: a
176 |
188 |
177 o 5 717e9b37cdb7 "5: merge 2 and 3, copy b to dir/d" files: dir/d e
189 o 5 717e9b37cdb7 (public) "5: merge 2 and 3, copy b to dir/d" files: dir/d e
178 |\
190 |\
179 | o 4 86a55cb968d5 "4: change a" files: a
191 | o 4 86a55cb968d5 (public) "4: change a" files: a
180 | |
192 | |
181 o | 3 0e6e235919dd "3: copy a to e, change b" files: b e
193 o | 3 0e6e235919dd (public) "3: copy a to e, change b" files: b e
182 | |
194 | |
183 o | 2 0394b0d5e4f7 "2: add dir/c" files: dir/c
195 o | 2 0394b0d5e4f7 (public) "2: add dir/c" files: dir/c
184 |/
196 |/
185 o 1 333546584845 "1: add a and dir/b" files: a dir/b
197 o 1 333546584845 (public) "1: add a and dir/b" files: a dir/b
186 |
198 |
187 o 0 d1a24e2ebd23 "0: add 0" files: 0
199 o 0 d1a24e2ebd23 (public) "0: add 0" files: 0
188
200
189 $ cd ..
201 $ cd ..
190
202
191 Convert excluding rev 0 and dir/ (and thus rev2):
203 Convert excluding rev 0 and dir/ (and thus rev2):
192
204
193 $ cat << EOF > filemap
205 $ cat << EOF > filemap
194 > exclude dir
206 > exclude dir
195 > EOF
207 > EOF
196
208
197 $ hg convert --filemap filemap source dest --config convert.hg.revs=1::
209 $ hg convert --filemap filemap source dest --config convert.hg.revs=1::
198 initializing destination dest repository
210 initializing destination dest repository
199 scanning source...
211 scanning source...
200 sorting...
212 sorting...
201 converting...
213 converting...
202 5 1: add a and dir/b
214 5 1: add a and dir/b
203 4 2: add dir/c
215 4 2: add dir/c
204 3 3: copy a to e, change b
216 3 3: copy a to e, change b
205 2 4: change a
217 2 4: change a
206 1 5: merge 2 and 3, copy b to dir/d
218 1 5: merge 2 and 3, copy b to dir/d
207 0 6: change a
219 0 6: change a
208
220
209 Verify that conversion skipped rev 2:
221 Verify that conversion skipped rev 2:
210
222
211 $ glog -R dest
223 $ glog -R dest
212 o 4 78814e84a217 "6: change a" files: a
224 o 4 78814e84a217 (draft) "6: change a" files: a
213 |
225 |
214 o 3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
226 o 3 f7cff662c5e5 (draft) "5: merge 2 and 3, copy b to dir/d" files: e
215 |\
227 |\
216 | o 2 ab40a95b0072 "4: change a" files: a
228 | o 2 ab40a95b0072 (draft) "4: change a" files: a
217 | |
229 | |
218 o | 1 bd51f17597bf "3: copy a to e, change b" files: b e
230 o | 1 bd51f17597bf (draft) "3: copy a to e, change b" files: b e
219 |/
231 |/
220 o 0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
232 o 0 a4a1dae0fe35 (draft) "1: add a and dir/b" files: 0 a
221
233
222
234
223 Verify mapping correct in both directions:
235 Verify mapping correct in both directions:
224
236
225 $ cat source/.hg/shamap
237 $ cat source/.hg/shamap
226 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5 333546584845f70c4cfecb992341aaef0e708166
238 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5 333546584845f70c4cfecb992341aaef0e708166
227 bd51f17597bf32268e68a560b206898c3960cda2 0e6e235919dd8e9285ba8eb5adf703af9ad99378
239 bd51f17597bf32268e68a560b206898c3960cda2 0e6e235919dd8e9285ba8eb5adf703af9ad99378
228 ab40a95b00725307e79c2fd271000aa8af9759f4 86a55cb968d51770cba2a1630d6cc637b574580a
240 ab40a95b00725307e79c2fd271000aa8af9759f4 86a55cb968d51770cba2a1630d6cc637b574580a
229 f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d
241 f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d
230 78814e84a217894517c2de392b903ed05e6871a4 0613c8e59a3ddb9789072ef52f1ed13496489bb4
242 78814e84a217894517c2de392b903ed05e6871a4 0613c8e59a3ddb9789072ef52f1ed13496489bb4
231 $ cat dest/.hg/shamap
243 $ cat dest/.hg/shamap
232 333546584845f70c4cfecb992341aaef0e708166 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
244 333546584845f70c4cfecb992341aaef0e708166 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
233 0394b0d5e4f761ced559fd0bbdc6afc16cb3f7d1 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
245 0394b0d5e4f761ced559fd0bbdc6afc16cb3f7d1 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
234 0e6e235919dd8e9285ba8eb5adf703af9ad99378 bd51f17597bf32268e68a560b206898c3960cda2
246 0e6e235919dd8e9285ba8eb5adf703af9ad99378 bd51f17597bf32268e68a560b206898c3960cda2
235 86a55cb968d51770cba2a1630d6cc637b574580a ab40a95b00725307e79c2fd271000aa8af9759f4
247 86a55cb968d51770cba2a1630d6cc637b574580a ab40a95b00725307e79c2fd271000aa8af9759f4
236 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba
248 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba
237 0613c8e59a3ddb9789072ef52f1ed13496489bb4 78814e84a217894517c2de392b903ed05e6871a4
249 0613c8e59a3ddb9789072ef52f1ed13496489bb4 78814e84a217894517c2de392b903ed05e6871a4
238
250
239 Verify meta data converted correctly:
251 Verify meta data converted correctly:
240
252
241 $ hg -R dest log -r 1 --debug -p --git
253 $ hg -R dest log -r 1 --debug -p --git
242 changeset: 1:bd51f17597bf32268e68a560b206898c3960cda2
254 changeset: 1:bd51f17597bf32268e68a560b206898c3960cda2
243 phase: draft
255 phase: draft
244 parent: 0:a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
256 parent: 0:a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
245 parent: -1:0000000000000000000000000000000000000000
257 parent: -1:0000000000000000000000000000000000000000
246 manifest: 1:040c72ed9b101773c24ac314776bfc846943781f
258 manifest: 1:040c72ed9b101773c24ac314776bfc846943781f
247 user: test
259 user: test
248 date: Thu Jan 01 00:00:00 1970 +0000
260 date: Thu Jan 01 00:00:00 1970 +0000
249 files+: b e
261 files+: b e
250 extra: branch=default
262 extra: branch=default
251 description:
263 description:
252 3: copy a to e, change b
264 3: copy a to e, change b
253
265
254
266
255 diff --git a/b b/b
267 diff --git a/b b/b
256 new file mode 100644
268 new file mode 100644
257 --- /dev/null
269 --- /dev/null
258 +++ b/b
270 +++ b/b
259 @@ -0,0 +1,1 @@
271 @@ -0,0 +1,1 @@
260 +b
272 +b
261 diff --git a/a b/e
273 diff --git a/a b/e
262 copy from a
274 copy from a
263 copy to e
275 copy to e
264
276
265 Verify files included and excluded correctly:
277 Verify files included and excluded correctly:
266
278
267 $ hg -R dest manifest -r tip
279 $ hg -R dest manifest -r tip
268 0
280 0
269 a
281 a
270 b
282 b
271 e
283 e
272
284
273
285
274 Make changes in dest and convert back:
286 Make changes in dest and convert back:
275
287
276 $ hg -R dest up -q
288 $ hg -R dest up -q
277 $ echo dest > dest/dest
289 $ echo dest > dest/dest
278 $ hg -R dest ci -Aqm 'change in dest'
290 $ hg -R dest ci -Aqm 'change in dest'
279 $ hg -R dest tip
291 $ hg -R dest tip
280 changeset: 5:a2e0e3cc6d1d
292 changeset: 5:a2e0e3cc6d1d
281 tag: tip
293 tag: tip
282 user: test
294 user: test
283 date: Thu Jan 01 00:00:00 1970 +0000
295 date: Thu Jan 01 00:00:00 1970 +0000
284 summary: change in dest
296 summary: change in dest
285
297
286
298
287 (converting merges back after using a filemap will probably cause chaos so we
299 (converting merges back after using a filemap will probably cause chaos so we
288 exclude merges.)
300 exclude merges.)
289
301
290 $ hg convert dest source --config convert.hg.revs='!merge()'
302 $ hg convert dest source --config convert.hg.revs='!merge()'
291 scanning source...
303 scanning source...
292 sorting...
304 sorting...
293 converting...
305 converting...
294 0 change in dest
306 0 change in dest
295
307
296 Verify the conversion back:
308 Verify the conversion back:
297
309
298 $ hg -R source log --debug -r tip
310 $ hg -R source log --debug -r tip
299 changeset: 7:e6d364a69ff1248b2099e603b0c145504cade6f0
311 changeset: 7:e6d364a69ff1248b2099e603b0c145504cade6f0
300 tag: tip
312 tag: tip
301 phase: draft
313 phase: draft
302 parent: 6:0613c8e59a3ddb9789072ef52f1ed13496489bb4
314 parent: 6:0613c8e59a3ddb9789072ef52f1ed13496489bb4
303 parent: -1:0000000000000000000000000000000000000000
315 parent: -1:0000000000000000000000000000000000000000
304 manifest: 7:aa3e9542f3b76d4f1f1b2e9c7ce9dbb48b6a95ec
316 manifest: 7:aa3e9542f3b76d4f1f1b2e9c7ce9dbb48b6a95ec
305 user: test
317 user: test
306 date: Thu Jan 01 00:00:00 1970 +0000
318 date: Thu Jan 01 00:00:00 1970 +0000
307 files+: dest
319 files+: dest
308 extra: branch=default
320 extra: branch=default
309 description:
321 description:
310 change in dest
322 change in dest
311
323
312
324
313 Files that had been excluded are still present:
325 Files that had been excluded are still present:
314
326
315 $ hg -R source manifest -r tip
327 $ hg -R source manifest -r tip
316 0
328 0
317 a
329 a
318 b
330 b
319 dest
331 dest
320 dir/b
332 dir/b
321 dir/c
333 dir/c
322 dir/d
334 dir/d
323 e
335 e
324
336
325 More source changes
337 More source changes
326
338
327 $ cd source
339 $ cd source
328 $ echo 1 >> a
340 $ echo 1 >> a
329 $ hg ci -m '8: source first branch'
341 $ hg ci -m '8: source first branch'
330 created new head
342 created new head
331 $ hg up -qr -2
343 $ hg up -qr -2
332 $ echo 2 >> a
344 $ echo 2 >> a
333 $ hg ci -m '9: source second branch'
345 $ hg ci -m '9: source second branch'
334 $ hg merge -q --tool internal:local
346 $ hg merge -q --tool internal:local
335 $ hg ci -m '10: source merge'
347 $ hg ci -m '10: source merge'
336 $ echo >> a
348 $ echo >> a
337 $ hg ci -m '11: source change'
349 $ hg ci -m '11: source change'
338
350
339 $ hg mani
351 $ hg mani
340 0
352 0
341 a
353 a
342 b
354 b
343 dest
355 dest
344 dir/b
356 dir/b
345 dir/c
357 dir/c
346 dir/d
358 dir/d
347 e
359 e
348
360
349 $ glog -r 6:
361 $ glog -r 6:
350 @ 11 0c8927d1f7f4 "11: source change" files: a
362 @ 11 0c8927d1f7f4 (draft) "11: source change" files: a
351 |
363 |
352 o 10 9ccb7ee8d261 "10: source merge" files: a
364 o 10 9ccb7ee8d261 (draft) "10: source merge" files: a
353 |\
365 |\
354 | o 9 f131b1518dba "9: source second branch" files: a
366 | o 9 f131b1518dba (draft) "9: source second branch" files: a
355 | |
367 | |
356 o | 8 669cf0e74b50 "8: source first branch" files: a
368 o | 8 669cf0e74b50 (draft) "8: source first branch" files: a
357 | |
369 | |
358 | o 7 e6d364a69ff1 "change in dest" files: dest
370 | o 7 e6d364a69ff1 (draft) "change in dest" files: dest
359 |/
371 |/
360 o 6 0613c8e59a3d "6: change a" files: a
372 o 6 0613c8e59a3d (public) "6: change a" files: a
361 |
373 |
362 $ cd ..
374 $ cd ..
363
375
364 $ hg convert --filemap filemap source dest --config convert.hg.revs=3:
376 $ hg convert --filemap filemap source dest --config convert.hg.revs=3:
365 scanning source...
377 scanning source...
366 sorting...
378 sorting...
367 converting...
379 converting...
368 3 8: source first branch
380 3 8: source first branch
369 2 9: source second branch
381 2 9: source second branch
370 1 10: source merge
382 1 10: source merge
371 0 11: source change
383 0 11: source change
372
384
373 $ glog -R dest
385 $ glog -R dest
374 o 9 8432d597b263 "11: source change" files: a
386 o 9 8432d597b263 (draft) "11: source change" files: a
375 |
387 |
376 o 8 632ffacdcd6f "10: source merge" files: a
388 o 8 632ffacdcd6f (draft) "10: source merge" files: a
377 |\
389 |\
378 | o 7 049cfee90ee6 "9: source second branch" files: a
390 | o 7 049cfee90ee6 (draft) "9: source second branch" files: a
379 | |
391 | |
380 o | 6 9b6845e036e5 "8: source first branch" files: a
392 o | 6 9b6845e036e5 (draft) "8: source first branch" files: a
381 | |
393 | |
382 | @ 5 a2e0e3cc6d1d "change in dest" files: dest
394 | @ 5 a2e0e3cc6d1d (draft) "change in dest" files: dest
383 |/
395 |/
384 o 4 78814e84a217 "6: change a" files: a
396 o 4 78814e84a217 (draft) "6: change a" files: a
385 |
397 |
386 o 3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
398 o 3 f7cff662c5e5 (draft) "5: merge 2 and 3, copy b to dir/d" files: e
387 |\
399 |\
388 | o 2 ab40a95b0072 "4: change a" files: a
400 | o 2 ab40a95b0072 (draft) "4: change a" files: a
389 | |
401 | |
390 o | 1 bd51f17597bf "3: copy a to e, change b" files: b e
402 o | 1 bd51f17597bf (draft) "3: copy a to e, change b" files: b e
391 |/
403 |/
392 o 0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
404 o 0 a4a1dae0fe35 (draft) "1: add a and dir/b" files: 0 a
393
405
394 $ cd ..
406 $ cd ..
395
407
396 Two way tests
408 Two way tests
397
409
398 $ hg init 0
410 $ hg init 0
399 $ echo f > 0/f
411 $ echo f > 0/f
400 $ echo a > 0/a-only
412 $ echo a > 0/a-only
401 $ echo b > 0/b-only
413 $ echo b > 0/b-only
402 $ hg -R 0 ci -Aqm0
414 $ hg -R 0 ci -Aqm0
403
415
404 $ cat << EOF > filemap-a
416 $ cat << EOF > filemap-a
405 > exclude b-only
417 > exclude b-only
406 > EOF
418 > EOF
407 $ cat << EOF > filemap-b
419 $ cat << EOF > filemap-b
408 > exclude a-only
420 > exclude a-only
409 > EOF
421 > EOF
410 $ hg convert --filemap filemap-a 0 a
422 $ hg convert --filemap filemap-a 0 a
411 initializing destination a repository
423 initializing destination a repository
412 scanning source...
424 scanning source...
413 sorting...
425 sorting...
414 converting...
426 converting...
415 0 0
427 0 0
416 $ hg -R a up -q
428 $ hg -R a up -q
417 $ echo a > a/f
429 $ echo a > a/f
418 $ hg -R a ci -ma
430 $ hg -R a ci -ma
419
431
420 $ hg convert --filemap filemap-b 0 b
432 $ hg convert --filemap filemap-b 0 b
421 initializing destination b repository
433 initializing destination b repository
422 scanning source...
434 scanning source...
423 sorting...
435 sorting...
424 converting...
436 converting...
425 0 0
437 0 0
426 $ hg -R b up -q
438 $ hg -R b up -q
427 $ echo b > b/f
439 $ echo b > b/f
428 $ hg -R b ci -mb
440 $ hg -R b ci -mb
429
441
430 $ tail */.hg/shamap
442 $ tail */.hg/shamap
431 ==> 0/.hg/shamap <==
443 ==> 0/.hg/shamap <==
432 86f3f774ffb682bffb5dc3c1d3b3da637cb9a0d6 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a
444 86f3f774ffb682bffb5dc3c1d3b3da637cb9a0d6 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a
433 dd9f218eb91fb857f2a62fe023e1d64a4e7812fe 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a
445 dd9f218eb91fb857f2a62fe023e1d64a4e7812fe 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a
434
446
435 ==> a/.hg/shamap <==
447 ==> a/.hg/shamap <==
436 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a 86f3f774ffb682bffb5dc3c1d3b3da637cb9a0d6
448 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a 86f3f774ffb682bffb5dc3c1d3b3da637cb9a0d6
437
449
438 ==> b/.hg/shamap <==
450 ==> b/.hg/shamap <==
439 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a dd9f218eb91fb857f2a62fe023e1d64a4e7812fe
451 8a028c7c77f6c7bd6d63bc3f02ca9f779eabf16a dd9f218eb91fb857f2a62fe023e1d64a4e7812fe
440
452
441 $ hg convert a 0
453 $ hg convert a 0
442 scanning source...
454 scanning source...
443 sorting...
455 sorting...
444 converting...
456 converting...
445 0 a
457 0 a
446
458
447 $ hg convert b 0
459 $ hg convert b 0
448 scanning source...
460 scanning source...
449 sorting...
461 sorting...
450 converting...
462 converting...
451 0 b
463 0 b
452
464
453 $ hg -R 0 log -G
465 $ hg -R 0 log -G
454 o changeset: 2:637fbbbe96b6
466 o changeset: 2:637fbbbe96b6
455 | tag: tip
467 | tag: tip
456 | parent: 0:8a028c7c77f6
468 | parent: 0:8a028c7c77f6
457 | user: test
469 | user: test
458 | date: Thu Jan 01 00:00:00 1970 +0000
470 | date: Thu Jan 01 00:00:00 1970 +0000
459 | summary: b
471 | summary: b
460 |
472 |
461 | o changeset: 1:ec7b9c96e692
473 | o changeset: 1:ec7b9c96e692
462 |/ user: test
474 |/ user: test
463 | date: Thu Jan 01 00:00:00 1970 +0000
475 | date: Thu Jan 01 00:00:00 1970 +0000
464 | summary: a
476 | summary: a
465 |
477 |
466 @ changeset: 0:8a028c7c77f6
478 @ changeset: 0:8a028c7c77f6
467 user: test
479 user: test
468 date: Thu Jan 01 00:00:00 1970 +0000
480 date: Thu Jan 01 00:00:00 1970 +0000
469 summary: 0
481 summary: 0
470
482
471 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
483 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
472 scanning source...
484 scanning source...
473 sorting...
485 sorting...
474 converting...
486 converting...
475
487
476 $ hg -R 0 up -r1
488 $ hg -R 0 up -r1
477 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
489 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
478 $ echo f >> 0/f
490 $ echo f >> 0/f
479 $ hg -R 0 ci -mx
491 $ hg -R 0 ci -mx
480
492
481 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
493 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
482 scanning source...
494 scanning source...
483 sorting...
495 sorting...
484 converting...
496 converting...
485 0 x
497 0 x
486
498
487 $ hg -R a log -G -T '{rev} {desc|firstline} ({files})\n'
499 $ hg -R a log -G -T '{rev} {desc|firstline} ({files})\n'
488 o 2 x (f)
500 o 2 x (f)
489 |
501 |
490 @ 1 a (f)
502 @ 1 a (f)
491 |
503 |
492 o 0 0 (a-only f)
504 o 0 0 (a-only f)
493
505
494 $ hg -R a mani -r tip
506 $ hg -R a mani -r tip
495 a-only
507 a-only
496 f
508 f
497
509
498 An additional round, demonstrating that unchanged files don't get converted
510 An additional round, demonstrating that unchanged files don't get converted
499
511
500 $ echo f >> 0/f
512 $ echo f >> 0/f
501 $ echo f >> 0/a-only
513 $ echo f >> 0/a-only
502 $ hg -R 0 ci -m "extra f+a-only change"
514 $ hg -R 0 ci -m "extra f+a-only change"
503
515
504 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
516 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
505 scanning source...
517 scanning source...
506 sorting...
518 sorting...
507 converting...
519 converting...
508 0 extra f+a-only change
520 0 extra f+a-only change
509
521
510 $ hg -R a log -G -T '{rev} {desc|firstline} ({files})\n'
522 $ hg -R a log -G -T '{rev} {desc|firstline} ({files})\n'
511 o 3 extra f+a-only change (f)
523 o 3 extra f+a-only change (f)
512 |
524 |
513 o 2 x (f)
525 o 2 x (f)
514 |
526 |
515 @ 1 a (f)
527 @ 1 a (f)
516 |
528 |
517 o 0 0 (a-only f)
529 o 0 0 (a-only f)
518
530
519
531
520 Conversion after rollback
532 Conversion after rollback
521
533
522 $ hg -R a rollback -f
534 $ hg -R a rollback -f
523 repository tip rolled back to revision 2 (undo commit)
535 repository tip rolled back to revision 2 (undo convert)
524
536
525 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
537 $ hg convert --filemap filemap-b 0 a --config convert.hg.revs=1::
526 scanning source...
538 scanning source...
527 sorting...
539 sorting...
528 converting...
540 converting...
529 0 extra f+a-only change
541 0 extra f+a-only change
530
542
531 $ hg -R a log -G -T '{rev} {desc|firstline} ({files})\n'
543 $ hg -R a log -G -T '{rev} {desc|firstline} ({files})\n'
532 o 3 extra f+a-only change (f)
544 o 3 extra f+a-only change (f)
533 |
545 |
534 o 2 x (f)
546 o 2 x (f)
535 |
547 |
536 @ 1 a (f)
548 @ 1 a (f)
537 |
549 |
538 o 0 0 (a-only f)
550 o 0 0 (a-only f)
539
551
540 Convert with --full adds and removes files that didn't change
552 Convert with --full adds and removes files that didn't change
541
553
542 $ echo f >> 0/f
554 $ echo f >> 0/f
543 $ hg -R 0 ci -m "f"
555 $ hg -R 0 ci -m "f"
544 $ hg convert --filemap filemap-b --full 0 a --config convert.hg.revs=1::
556 $ hg convert --filemap filemap-b --full 0 a --config convert.hg.revs=1::
545 scanning source...
557 scanning source...
546 sorting...
558 sorting...
547 converting...
559 converting...
548 0 f
560 0 f
549 $ hg -R a status --change tip
561 $ hg -R a status --change tip
550 M f
562 M f
551 A b-only
563 A b-only
552 R a-only
564 R a-only
General Comments 0
You need to be logged in to leave comments. Login now