|
1 # convert.py Foreign SCM converter |
|
2 # |
|
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
|
4 # |
|
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. |
|
7 |
|
8 '''import revisions from foreign VCS repositories into Mercurial''' |
|
9 |
|
10 import convcmd |
|
11 import cvsps |
|
12 import subversion |
|
13 from mercurial import commands |
|
14 from mercurial.i18n import _ |
|
15 |
|
16 # Commands definition was moved elsewhere to ease demandload job. |
|
17 |
|
18 def convert(ui, src, dest=None, revmapfile=None, **opts): |
|
19 """convert a foreign SCM repository to a Mercurial one. |
|
20 |
|
21 Accepted source formats [identifiers]: |
|
22 |
|
23 - Mercurial [hg] |
|
24 - CVS [cvs] |
|
25 - Darcs [darcs] |
|
26 - git [git] |
|
27 - Subversion [svn] |
|
28 - Monotone [mtn] |
|
29 - GNU Arch [gnuarch] |
|
30 - Bazaar [bzr] |
|
31 - Perforce [p4] |
|
32 |
|
33 Accepted destination formats [identifiers]: |
|
34 |
|
35 - Mercurial [hg] |
|
36 - Subversion [svn] (history on branches is not preserved) |
|
37 |
|
38 If no revision is given, all revisions will be converted. |
|
39 Otherwise, convert will only import up to the named revision |
|
40 (given in a format understood by the source). |
|
41 |
|
42 If no destination directory name is specified, it defaults to the |
|
43 basename of the source with ``-hg`` appended. If the destination |
|
44 repository doesn't exist, it will be created. |
|
45 |
|
46 By default, all sources except Mercurial will use --branchsort. |
|
47 Mercurial uses --sourcesort to preserve original revision numbers |
|
48 order. Sort modes have the following effects: |
|
49 |
|
50 --branchsort convert from parent to child revision when possible, |
|
51 which means branches are usually converted one after |
|
52 the other. It generates more compact repositories. |
|
53 |
|
54 --datesort sort revisions by date. Converted repositories have |
|
55 good-looking changelogs but are often an order of |
|
56 magnitude larger than the same ones generated by |
|
57 --branchsort. |
|
58 |
|
59 --sourcesort try to preserve source revisions order, only |
|
60 supported by Mercurial sources. |
|
61 |
|
62 If <REVMAP> isn't given, it will be put in a default location |
|
63 (<dest>/.hg/shamap by default). The <REVMAP> is a simple text file |
|
64 that maps each source commit ID to the destination ID for that |
|
65 revision, like so:: |
|
66 |
|
67 <source ID> <destination ID> |
|
68 |
|
69 If the file doesn't exist, it's automatically created. It's |
|
70 updated on each commit copied, so :hg:`convert` can be interrupted |
|
71 and can be run repeatedly to copy new commits. |
|
72 |
|
73 The authormap is a simple text file that maps each source commit |
|
74 author to a destination commit author. It is handy for source SCMs |
|
75 that use unix logins to identify authors (eg: CVS). One line per |
|
76 author mapping and the line format is:: |
|
77 |
|
78 source author = destination author |
|
79 |
|
80 Empty lines and lines starting with a ``#`` are ignored. |
|
81 |
|
82 The filemap is a file that allows filtering and remapping of files |
|
83 and directories. Each line can contain one of the following |
|
84 directives:: |
|
85 |
|
86 include path/to/file-or-dir |
|
87 |
|
88 exclude path/to/file-or-dir |
|
89 |
|
90 rename path/to/source path/to/destination |
|
91 |
|
92 Comment lines start with ``#``. A specified path matches if it |
|
93 equals the full relative name of a file or one of its parent |
|
94 directories. The ``include`` or ``exclude`` directive with the |
|
95 longest matching path applies, so line order does not matter. |
|
96 |
|
97 The ``include`` directive causes a file, or all files under a |
|
98 directory, to be included in the destination repository, and the |
|
99 exclusion of all other files and directories not explicitly |
|
100 included. The ``exclude`` directive causes files or directories to |
|
101 be omitted. The ``rename`` directive renames a file or directory if |
|
102 it is converted. To rename from a subdirectory into the root of |
|
103 the repository, use ``.`` as the path to rename to. |
|
104 |
|
105 The splicemap is a file that allows insertion of synthetic |
|
106 history, letting you specify the parents of a revision. This is |
|
107 useful if you want to e.g. give a Subversion merge two parents, or |
|
108 graft two disconnected series of history together. Each entry |
|
109 contains a key, followed by a space, followed by one or two |
|
110 comma-separated values:: |
|
111 |
|
112 key parent1, parent2 |
|
113 |
|
114 The key is the revision ID in the source |
|
115 revision control system whose parents should be modified (same |
|
116 format as a key in .hg/shamap). The values are the revision IDs |
|
117 (in either the source or destination revision control system) that |
|
118 should be used as the new parents for that node. For example, if |
|
119 you have merged "release-1.0" into "trunk", then you should |
|
120 specify the revision on "trunk" as the first parent and the one on |
|
121 the "release-1.0" branch as the second. |
|
122 |
|
123 The branchmap is a file that allows you to rename a branch when it is |
|
124 being brought in from whatever external repository. When used in |
|
125 conjunction with a splicemap, it allows for a powerful combination |
|
126 to help fix even the most badly mismanaged repositories and turn them |
|
127 into nicely structured Mercurial repositories. The branchmap contains |
|
128 lines of the form:: |
|
129 |
|
130 original_branch_name new_branch_name |
|
131 |
|
132 where "original_branch_name" is the name of the branch in the |
|
133 source repository, and "new_branch_name" is the name of the branch |
|
134 is the destination repository. No whitespace is allowed in the |
|
135 branch names. This can be used to (for instance) move code in one |
|
136 repository from "default" to a named branch. |
|
137 |
|
138 Mercurial Source |
|
139 '''''''''''''''' |
|
140 |
|
141 --config convert.hg.ignoreerrors=False (boolean) |
|
142 ignore integrity errors when reading. Use it to fix Mercurial |
|
143 repositories with missing revlogs, by converting from and to |
|
144 Mercurial. |
|
145 --config convert.hg.saverev=False (boolean) |
|
146 store original revision ID in changeset (forces target IDs to |
|
147 change) |
|
148 --config convert.hg.startrev=0 (hg revision identifier) |
|
149 convert start revision and its descendants |
|
150 |
|
151 CVS Source |
|
152 '''''''''' |
|
153 |
|
154 CVS source will use a sandbox (i.e. a checked-out copy) from CVS |
|
155 to indicate the starting point of what will be converted. Direct |
|
156 access to the repository files is not needed, unless of course the |
|
157 repository is :local:. The conversion uses the top level directory |
|
158 in the sandbox to find the CVS repository, and then uses CVS rlog |
|
159 commands to find files to convert. This means that unless a |
|
160 filemap is given, all files under the starting directory will be |
|
161 converted, and that any directory reorganization in the CVS |
|
162 sandbox is ignored. |
|
163 |
|
164 The options shown are the defaults. |
|
165 |
|
166 --config convert.cvsps.cache=True (boolean) |
|
167 Set to False to disable remote log caching, for testing and |
|
168 debugging purposes. |
|
169 --config convert.cvsps.fuzz=60 (integer) |
|
170 Specify the maximum time (in seconds) that is allowed between |
|
171 commits with identical user and log message in a single |
|
172 changeset. When very large files were checked in as part of a |
|
173 changeset then the default may not be long enough. |
|
174 --config convert.cvsps.mergeto='{{mergetobranch ([-\\w]+)}}' |
|
175 Specify a regular expression to which commit log messages are |
|
176 matched. If a match occurs, then the conversion process will |
|
177 insert a dummy revision merging the branch on which this log |
|
178 message occurs to the branch indicated in the regex. |
|
179 --config convert.cvsps.mergefrom='{{mergefrombranch ([-\\w]+)}}' |
|
180 Specify a regular expression to which commit log messages are |
|
181 matched. If a match occurs, then the conversion process will |
|
182 add the most recent revision on the branch indicated in the |
|
183 regex as the second parent of the changeset. |
|
184 --config hook.cvslog |
|
185 Specify a Python function to be called at the end of gathering |
|
186 the CVS log. The function is passed a list with the log entries, |
|
187 and can modify the entries in-place, or add or delete them. |
|
188 --config hook.cvschangesets |
|
189 Specify a Python function to be called after the changesets |
|
190 are calculated from the the CVS log. The function is passed |
|
191 a list with the changeset entries, and can modify the changesets |
|
192 in-place, or add or delete them. |
|
193 |
|
194 An additional "debugcvsps" Mercurial command allows the builtin |
|
195 changeset merging code to be run without doing a conversion. Its |
|
196 parameters and output are similar to that of cvsps 2.1. Please see |
|
197 the command help for more details. |
|
198 |
|
199 Subversion Source |
|
200 ''''''''''''''''' |
|
201 |
|
202 Subversion source detects classical trunk/branches/tags layouts. |
|
203 By default, the supplied "svn://repo/path/" source URL is |
|
204 converted as a single branch. If "svn://repo/path/trunk" exists it |
|
205 replaces the default branch. If "svn://repo/path/branches" exists, |
|
206 its subdirectories are listed as possible branches. If |
|
207 "svn://repo/path/tags" exists, it is looked for tags referencing |
|
208 converted branches. Default "trunk", "branches" and "tags" values |
|
209 can be overridden with following options. Set them to paths |
|
210 relative to the source URL, or leave them blank to disable auto |
|
211 detection. |
|
212 |
|
213 --config convert.svn.branches=branches (directory name) |
|
214 specify the directory containing branches |
|
215 --config convert.svn.tags=tags (directory name) |
|
216 specify the directory containing tags |
|
217 --config convert.svn.trunk=trunk (directory name) |
|
218 specify the name of the trunk branch |
|
219 |
|
220 Source history can be retrieved starting at a specific revision, |
|
221 instead of being integrally converted. Only single branch |
|
222 conversions are supported. |
|
223 |
|
224 --config convert.svn.startrev=0 (svn revision number) |
|
225 specify start Subversion revision. |
|
226 |
|
227 Perforce Source |
|
228 ''''''''''''''' |
|
229 |
|
230 The Perforce (P4) importer can be given a p4 depot path or a |
|
231 client specification as source. It will convert all files in the |
|
232 source to a flat Mercurial repository, ignoring labels, branches |
|
233 and integrations. Note that when a depot path is given you then |
|
234 usually should specify a target directory, because otherwise the |
|
235 target may be named ...-hg. |
|
236 |
|
237 It is possible to limit the amount of source history to be |
|
238 converted by specifying an initial Perforce revision. |
|
239 |
|
240 --config convert.p4.startrev=0 (perforce changelist number) |
|
241 specify initial Perforce revision. |
|
242 |
|
243 Mercurial Destination |
|
244 ''''''''''''''''''''' |
|
245 |
|
246 --config convert.hg.clonebranches=False (boolean) |
|
247 dispatch source branches in separate clones. |
|
248 --config convert.hg.tagsbranch=default (branch name) |
|
249 tag revisions branch name |
|
250 --config convert.hg.usebranchnames=True (boolean) |
|
251 preserve branch names |
|
252 |
|
253 """ |
|
254 return convcmd.convert(ui, src, dest, revmapfile, **opts) |
|
255 |
|
256 def debugsvnlog(ui, **opts): |
|
257 return subversion.debugsvnlog(ui, **opts) |
|
258 |
|
259 def debugcvsps(ui, *args, **opts): |
|
260 '''create changeset information from CVS |
|
261 |
|
262 This command is intended as a debugging tool for the CVS to |
|
263 Mercurial converter, and can be used as a direct replacement for |
|
264 cvsps. |
|
265 |
|
266 Hg debugcvsps reads the CVS rlog for current directory (or any |
|
267 named directory) in the CVS repository, and converts the log to a |
|
268 series of changesets based on matching commit log entries and |
|
269 dates.''' |
|
270 return cvsps.debugcvsps(ui, *args, **opts) |
|
271 |
|
272 commands.norepo += " convert debugsvnlog debugcvsps" |
|
273 |
|
274 cmdtable = { |
|
275 "convert": |
|
276 (convert, |
|
277 [('', 'authors', '', |
|
278 _('username mapping filename (DEPRECATED, use --authormap instead)'), |
|
279 _('FILE')), |
|
280 ('s', 'source-type', '', |
|
281 _('source repository type'), _('TYPE')), |
|
282 ('d', 'dest-type', '', |
|
283 _('destination repository type'), _('TYPE')), |
|
284 ('r', 'rev', '', |
|
285 _('import up to target revision REV'), _('REV')), |
|
286 ('A', 'authormap', '', |
|
287 _('remap usernames using this file'), _('FILE')), |
|
288 ('', 'filemap', '', |
|
289 _('remap file names using contents of file'), _('FILE')), |
|
290 ('', 'splicemap', '', |
|
291 _('splice synthesized history into place'), _('FILE')), |
|
292 ('', 'branchmap', '', |
|
293 _('change branch names while converting'), _('FILE')), |
|
294 ('', 'branchsort', None, _('try to sort changesets by branches')), |
|
295 ('', 'datesort', None, _('try to sort changesets by date')), |
|
296 ('', 'sourcesort', None, _('preserve source changesets order'))], |
|
297 _('hg convert [OPTION]... SOURCE [DEST [REVMAP]]')), |
|
298 "debugsvnlog": |
|
299 (debugsvnlog, |
|
300 [], |
|
301 'hg debugsvnlog'), |
|
302 "debugcvsps": |
|
303 (debugcvsps, |
|
304 [ |
|
305 # Main options shared with cvsps-2.1 |
|
306 ('b', 'branches', [], _('only return changes on specified branches')), |
|
307 ('p', 'prefix', '', _('prefix to remove from file names')), |
|
308 ('r', 'revisions', [], |
|
309 _('only return changes after or between specified tags')), |
|
310 ('u', 'update-cache', None, _("update cvs log cache")), |
|
311 ('x', 'new-cache', None, _("create new cvs log cache")), |
|
312 ('z', 'fuzz', 60, _('set commit time fuzz in seconds')), |
|
313 ('', 'root', '', _('specify cvsroot')), |
|
314 # Options specific to builtin cvsps |
|
315 ('', 'parents', '', _('show parent changesets')), |
|
316 ('', 'ancestors', '', _('show current changeset in ancestor branches')), |
|
317 # Options that are ignored for compatibility with cvsps-2.1 |
|
318 ('A', 'cvs-direct', None, _('ignored for compatibility')), |
|
319 ], |
|
320 _('hg debugcvsps [OPTION]... [PATH]...')), |
|
321 } |