##// END OF EJS Templates
convert: missing p4 tool is only slightly fatal...
Mads Kiilerich -
r7905:d596b1f2 default
parent child Browse files
Show More
@@ -1,176 +1,176 b''
1 #
1 #
2 # Perforce source for convert extension.
2 # Perforce source for convert extension.
3 #
3 #
4 # Copyright 2009, Frank Kingswood <frank@kingswood-consulting.co.uk>
4 # Copyright 2009, Frank Kingswood <frank@kingswood-consulting.co.uk>
5 #
5 #
6 # This software may be used and distributed according to the terms
6 # This software may be used and distributed according to the terms
7 # of the GNU General Public License, incorporated herein by reference.
7 # of the GNU General Public License, incorporated herein by reference.
8 #
8 #
9
9
10 from mercurial import util
10 from mercurial import util
11 from mercurial.i18n import _
11 from mercurial.i18n import _
12
12
13 from common import commit, converter_source, checktool
13 from common import commit, converter_source, checktool
14 import marshal
14 import marshal
15
15
16 def loaditer(f):
16 def loaditer(f):
17 "Yield the dictionary objects generated by p4"
17 "Yield the dictionary objects generated by p4"
18 try:
18 try:
19 while True:
19 while True:
20 d = marshal.load(f)
20 d = marshal.load(f)
21 if not d:
21 if not d:
22 break
22 break
23 yield d
23 yield d
24 except EOFError:
24 except EOFError:
25 pass
25 pass
26
26
27 class p4_source(converter_source):
27 class p4_source(converter_source):
28 def __init__(self, ui, path, rev=None):
28 def __init__(self, ui, path, rev=None):
29 super(p4_source, self).__init__(ui, path, rev=rev)
29 super(p4_source, self).__init__(ui, path, rev=rev)
30
30
31 checktool('p4')
31 checktool('p4', abort=False)
32
32
33 self.p4changes = {}
33 self.p4changes = {}
34 self.heads = {}
34 self.heads = {}
35 self.changeset = {}
35 self.changeset = {}
36 self.files = {}
36 self.files = {}
37 self.tags = {}
37 self.tags = {}
38 self.lastbranch = {}
38 self.lastbranch = {}
39 self.parent = {}
39 self.parent = {}
40 self.encoding = "latin_1"
40 self.encoding = "latin_1"
41 self.depotname = {} # mapping from local name to depot name
41 self.depotname = {} # mapping from local name to depot name
42 self.modecache = {}
42 self.modecache = {}
43
43
44 self._parse(ui, path)
44 self._parse(ui, path)
45
45
46 def _parse_view(self, path):
46 def _parse_view(self, path):
47 "Read changes affecting the path"
47 "Read changes affecting the path"
48 cmd = "p4 -G changes -s submitted '%s'" % path
48 cmd = "p4 -G changes -s submitted '%s'" % path
49 stdout = util.popen(cmd)
49 stdout = util.popen(cmd)
50 for d in loaditer(stdout):
50 for d in loaditer(stdout):
51 c = d.get("change", None)
51 c = d.get("change", None)
52 if c:
52 if c:
53 self.p4changes[c] = True
53 self.p4changes[c] = True
54
54
55 def _parse(self, ui, path):
55 def _parse(self, ui, path):
56 "Prepare list of P4 filenames and revisions to import"
56 "Prepare list of P4 filenames and revisions to import"
57 ui.status(_('reading p4 views\n'))
57 ui.status(_('reading p4 views\n'))
58
58
59 # read client spec or view
59 # read client spec or view
60 if "/" in path:
60 if "/" in path:
61 self._parse_view(path)
61 self._parse_view(path)
62 if path.startswith("//") and path.endswith("/..."):
62 if path.startswith("//") and path.endswith("/..."):
63 views = {path[:-3]:""}
63 views = {path[:-3]:""}
64 else:
64 else:
65 views = {"//": ""}
65 views = {"//": ""}
66 else:
66 else:
67 cmd = "p4 -G client -o '%s'" % path
67 cmd = "p4 -G client -o '%s'" % path
68 clientspec = marshal.load(util.popen(cmd))
68 clientspec = marshal.load(util.popen(cmd))
69
69
70 views = {}
70 views = {}
71 for client in clientspec:
71 for client in clientspec:
72 if client.startswith("View"):
72 if client.startswith("View"):
73 sview, cview = clientspec[client].split()
73 sview, cview = clientspec[client].split()
74 self._parse_view(sview)
74 self._parse_view(sview)
75 if sview.endswith("...") and cview.endswith("..."):
75 if sview.endswith("...") and cview.endswith("..."):
76 sview = sview[:-3]
76 sview = sview[:-3]
77 cview = cview[:-3]
77 cview = cview[:-3]
78 cview = cview[2:]
78 cview = cview[2:]
79 cview = cview[cview.find("/") + 1:]
79 cview = cview[cview.find("/") + 1:]
80 views[sview] = cview
80 views[sview] = cview
81
81
82 # list of changes that affect our source files
82 # list of changes that affect our source files
83 self.p4changes = self.p4changes.keys()
83 self.p4changes = self.p4changes.keys()
84 self.p4changes.sort(key=int)
84 self.p4changes.sort(key=int)
85
85
86 # list with depot pathnames, longest first
86 # list with depot pathnames, longest first
87 vieworder = views.keys()
87 vieworder = views.keys()
88 vieworder.sort(key=lambda x: -len(x))
88 vieworder.sort(key=lambda x: -len(x))
89
89
90 # handle revision limiting
90 # handle revision limiting
91 startrev = self.ui.config('convert', 'p4.startrev', default=0)
91 startrev = self.ui.config('convert', 'p4.startrev', default=0)
92 self.p4changes = [x for x in self.p4changes
92 self.p4changes = [x for x in self.p4changes
93 if ((not startrev or int(x) >= int(startrev)) and
93 if ((not startrev or int(x) >= int(startrev)) and
94 (not self.rev or int(x) <= int(self.rev)))]
94 (not self.rev or int(x) <= int(self.rev)))]
95
95
96 # now read the full changelists to get the list of file revisions
96 # now read the full changelists to get the list of file revisions
97 ui.status(_('collecting p4 changelists\n'))
97 ui.status(_('collecting p4 changelists\n'))
98 lastid = None
98 lastid = None
99 for change in self.p4changes:
99 for change in self.p4changes:
100 cmd = "p4 -G describe %s" % change
100 cmd = "p4 -G describe %s" % change
101 stdout = util.popen(cmd)
101 stdout = util.popen(cmd)
102 d = marshal.load(stdout)
102 d = marshal.load(stdout)
103
103
104 desc = self.recode(d["desc"])
104 desc = self.recode(d["desc"])
105 shortdesc = desc.split("\n", 1)[0]
105 shortdesc = desc.split("\n", 1)[0]
106 t = '%s %s' % (d["change"], repr(shortdesc)[1:-1])
106 t = '%s %s' % (d["change"], repr(shortdesc)[1:-1])
107 ui.status(util.ellipsis(t, 80) + '\n')
107 ui.status(util.ellipsis(t, 80) + '\n')
108
108
109 if lastid:
109 if lastid:
110 parents = [lastid]
110 parents = [lastid]
111 else:
111 else:
112 parents = []
112 parents = []
113
113
114 date = (int(d["time"]), 0) # timezone not set
114 date = (int(d["time"]), 0) # timezone not set
115 c = commit(author=self.recode(d["user"]), date=util.datestr(date),
115 c = commit(author=self.recode(d["user"]), date=util.datestr(date),
116 parents=parents, desc=desc, branch='', extra={"p4": change})
116 parents=parents, desc=desc, branch='', extra={"p4": change})
117
117
118 files = []
118 files = []
119 i = 0
119 i = 0
120 while ("depotFile%d" % i) in d and ("rev%d" % i) in d:
120 while ("depotFile%d" % i) in d and ("rev%d" % i) in d:
121 oldname = d["depotFile%d" % i]
121 oldname = d["depotFile%d" % i]
122 filename = None
122 filename = None
123 for v in vieworder:
123 for v in vieworder:
124 if oldname.startswith(v):
124 if oldname.startswith(v):
125 filename = views[v] + oldname[len(v):]
125 filename = views[v] + oldname[len(v):]
126 break
126 break
127 if filename:
127 if filename:
128 files.append((filename, d["rev%d" % i]))
128 files.append((filename, d["rev%d" % i]))
129 self.depotname[filename] = oldname
129 self.depotname[filename] = oldname
130 i += 1
130 i += 1
131 self.changeset[change] = c
131 self.changeset[change] = c
132 self.files[change] = files
132 self.files[change] = files
133 lastid = change
133 lastid = change
134
134
135 if lastid:
135 if lastid:
136 self.heads = [lastid]
136 self.heads = [lastid]
137
137
138 def getheads(self):
138 def getheads(self):
139 return self.heads
139 return self.heads
140
140
141 def getfile(self, name, rev):
141 def getfile(self, name, rev):
142 cmd = "p4 -G print '%s#%s'" % (self.depotname[name], rev)
142 cmd = "p4 -G print '%s#%s'" % (self.depotname[name], rev)
143 stdout = util.popen(cmd)
143 stdout = util.popen(cmd)
144
144
145 mode = None
145 mode = None
146 data = ""
146 data = ""
147
147
148 for d in loaditer(stdout):
148 for d in loaditer(stdout):
149 if d["code"] == "stat":
149 if d["code"] == "stat":
150 if "+x" in d["type"]:
150 if "+x" in d["type"]:
151 mode = "x"
151 mode = "x"
152 else:
152 else:
153 mode = ""
153 mode = ""
154 elif d["code"] == "text":
154 elif d["code"] == "text":
155 data += d["data"]
155 data += d["data"]
156
156
157 if mode is None:
157 if mode is None:
158 raise IOError()
158 raise IOError()
159
159
160 self.modecache[(name, rev)] = mode
160 self.modecache[(name, rev)] = mode
161 return data
161 return data
162
162
163 def getmode(self, name, rev):
163 def getmode(self, name, rev):
164 return self.modecache[(name, rev)]
164 return self.modecache[(name, rev)]
165
165
166 def getchanges(self, rev):
166 def getchanges(self, rev):
167 return self.files[rev], {}
167 return self.files[rev], {}
168
168
169 def getcommit(self, rev):
169 def getcommit(self, rev):
170 return self.changeset[rev]
170 return self.changeset[rev]
171
171
172 def gettags(self):
172 def gettags(self):
173 return self.tags
173 return self.tags
174
174
175 def getchangedfiles(self, rev, i):
175 def getchangedfiles(self, rev, i):
176 return util.sort([x[0] for x in self.files[rev]])
176 return util.sort([x[0] for x in self.files[rev]])
@@ -1,46 +1,50 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 cat >> $HGRCPATH <<EOF
3 cat >> $HGRCPATH <<EOF
4 [extensions]
4 [extensions]
5 convert=
5 convert=
6 [convert]
6 [convert]
7 hg.saverev=False
7 hg.saverev=False
8 EOF
8 EOF
9
9
10 hg help convert
10 hg help convert
11
11
12 hg init a
12 hg init a
13 cd a
13 cd a
14 echo a > a
14 echo a > a
15 hg ci -d'0 0' -Ama
15 hg ci -d'0 0' -Ama
16 hg cp a b
16 hg cp a b
17 hg ci -d'1 0' -mb
17 hg ci -d'1 0' -mb
18 hg rm a
18 hg rm a
19 hg ci -d'2 0' -mc
19 hg ci -d'2 0' -mc
20 hg mv b a
20 hg mv b a
21 hg ci -d'3 0' -md
21 hg ci -d'3 0' -md
22 echo a >> a
22 echo a >> a
23 hg ci -d'4 0' -me
23 hg ci -d'4 0' -me
24
24
25 cd ..
25 cd ..
26 hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
26 hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
27 hg --cwd a-hg pull ../a
27 hg --cwd a-hg pull ../a
28
28
29 touch bogusfile
29 touch bogusfile
30 echo % should fail
30 echo % should fail
31 hg convert a bogusfile
31 hg convert a bogusfile
32
32
33 mkdir bogusdir
33 mkdir bogusdir
34 chmod 000 bogusdir
34 chmod 000 bogusdir
35
35
36 echo % should fail
36 echo % should fail
37 hg convert a bogusdir
37 hg convert a bogusdir
38
38
39 echo % should succeed
39 echo % should succeed
40 chmod 700 bogusdir
40 chmod 700 bogusdir
41 hg convert a bogusdir
41 hg convert a bogusdir
42
42
43 echo % test pre and post conversion actions
43 echo % test pre and post conversion actions
44 echo 'include b' > filemap
44 echo 'include b' > filemap
45 hg convert --debug --filemap filemap a partialb | \
45 hg convert --debug --filemap filemap a partialb | \
46 grep 'run hg'
46 grep 'run hg'
47
48 echo % converting empty dir should fail "nicely"
49 mkdir emptydir
50 PATH=$BINDIR hg convert emptydir 2>&1 | sed 's,file://.*/emptydir,.../emptydir,g'
@@ -1,228 +1,241 b''
1 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
1 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
2
2
3 convert a foreign SCM repository to a Mercurial one.
3 convert a foreign SCM repository to a Mercurial one.
4
4
5 Accepted source formats [identifiers]:
5 Accepted source formats [identifiers]:
6 - Mercurial [hg]
6 - Mercurial [hg]
7 - CVS [cvs]
7 - CVS [cvs]
8 - Darcs [darcs]
8 - Darcs [darcs]
9 - git [git]
9 - git [git]
10 - Subversion [svn]
10 - Subversion [svn]
11 - Monotone [mtn]
11 - Monotone [mtn]
12 - GNU Arch [gnuarch]
12 - GNU Arch [gnuarch]
13 - Bazaar [bzr]
13 - Bazaar [bzr]
14 - Perforce [p4]
14 - Perforce [p4]
15
15
16 Accepted destination formats [identifiers]:
16 Accepted destination formats [identifiers]:
17 - Mercurial [hg]
17 - Mercurial [hg]
18 - Subversion [svn] (history on branches is not preserved)
18 - Subversion [svn] (history on branches is not preserved)
19
19
20 If no revision is given, all revisions will be converted. Otherwise,
20 If no revision is given, all revisions will be converted. Otherwise,
21 convert will only import up to the named revision (given in a format
21 convert will only import up to the named revision (given in a format
22 understood by the source).
22 understood by the source).
23
23
24 If no destination directory name is specified, it defaults to the
24 If no destination directory name is specified, it defaults to the
25 basename of the source with '-hg' appended. If the destination
25 basename of the source with '-hg' appended. If the destination
26 repository doesn't exist, it will be created.
26 repository doesn't exist, it will be created.
27
27
28 If <REVMAP> isn't given, it will be put in a default location
28 If <REVMAP> isn't given, it will be put in a default location
29 (<dest>/.hg/shamap by default). The <REVMAP> is a simple text
29 (<dest>/.hg/shamap by default). The <REVMAP> is a simple text
30 file that maps each source commit ID to the destination ID for
30 file that maps each source commit ID to the destination ID for
31 that revision, like so:
31 that revision, like so:
32 <source ID> <destination ID>
32 <source ID> <destination ID>
33
33
34 If the file doesn't exist, it's automatically created. It's updated
34 If the file doesn't exist, it's automatically created. It's updated
35 on each commit copied, so convert-repo can be interrupted and can
35 on each commit copied, so convert-repo can be interrupted and can
36 be run repeatedly to copy new commits.
36 be run repeatedly to copy new commits.
37
37
38 The [username mapping] file is a simple text file that maps each source
38 The [username mapping] file is a simple text file that maps each source
39 commit author to a destination commit author. It is handy for source SCMs
39 commit author to a destination commit author. It is handy for source SCMs
40 that use unix logins to identify authors (eg: CVS). One line per author
40 that use unix logins to identify authors (eg: CVS). One line per author
41 mapping and the line format is:
41 mapping and the line format is:
42 srcauthor=whatever string you want
42 srcauthor=whatever string you want
43
43
44 The filemap is a file that allows filtering and remapping of files
44 The filemap is a file that allows filtering and remapping of files
45 and directories. Comment lines start with '#'. Each line can
45 and directories. Comment lines start with '#'. Each line can
46 contain one of the following directives:
46 contain one of the following directives:
47
47
48 include path/to/file
48 include path/to/file
49
49
50 exclude path/to/file
50 exclude path/to/file
51
51
52 rename from/file to/file
52 rename from/file to/file
53
53
54 The 'include' directive causes a file, or all files under a
54 The 'include' directive causes a file, or all files under a
55 directory, to be included in the destination repository, and the
55 directory, to be included in the destination repository, and the
56 exclusion of all other files and dirs not explicitely included.
56 exclusion of all other files and dirs not explicitely included.
57 The 'exclude' directive causes files or directories to be omitted.
57 The 'exclude' directive causes files or directories to be omitted.
58 The 'rename' directive renames a file or directory. To rename from a
58 The 'rename' directive renames a file or directory. To rename from a
59 subdirectory into the root of the repository, use '.' as the path to
59 subdirectory into the root of the repository, use '.' as the path to
60 rename to.
60 rename to.
61
61
62 The splicemap is a file that allows insertion of synthetic
62 The splicemap is a file that allows insertion of synthetic
63 history, letting you specify the parents of a revision. This is
63 history, letting you specify the parents of a revision. This is
64 useful if you want to e.g. give a Subversion merge two parents, or
64 useful if you want to e.g. give a Subversion merge two parents, or
65 graft two disconnected series of history together. Each entry
65 graft two disconnected series of history together. Each entry
66 contains a key, followed by a space, followed by one or two
66 contains a key, followed by a space, followed by one or two
67 values, separated by spaces. The key is the revision ID in the
67 values, separated by spaces. The key is the revision ID in the
68 source revision control system whose parents should be modified
68 source revision control system whose parents should be modified
69 (same format as a key in .hg/shamap). The values are the revision
69 (same format as a key in .hg/shamap). The values are the revision
70 IDs (in either the source or destination revision control system)
70 IDs (in either the source or destination revision control system)
71 that should be used as the new parents for that node.
71 that should be used as the new parents for that node.
72
72
73 Mercurial Source
73 Mercurial Source
74 -----------------
74 -----------------
75
75
76 --config convert.hg.ignoreerrors=False (boolean)
76 --config convert.hg.ignoreerrors=False (boolean)
77 ignore integrity errors when reading. Use it to fix Mercurial
77 ignore integrity errors when reading. Use it to fix Mercurial
78 repositories with missing revlogs, by converting from and to
78 repositories with missing revlogs, by converting from and to
79 Mercurial.
79 Mercurial.
80 --config convert.hg.saverev=False (boolean)
80 --config convert.hg.saverev=False (boolean)
81 store original revision ID in changeset (forces target IDs to change)
81 store original revision ID in changeset (forces target IDs to change)
82 --config convert.hg.startrev=0 (hg revision identifier)
82 --config convert.hg.startrev=0 (hg revision identifier)
83 convert start revision and its descendants
83 convert start revision and its descendants
84
84
85 CVS Source
85 CVS Source
86 ----------
86 ----------
87
87
88 CVS source will use a sandbox (i.e. a checked-out copy) from CVS
88 CVS source will use a sandbox (i.e. a checked-out copy) from CVS
89 to indicate the starting point of what will be converted. Direct
89 to indicate the starting point of what will be converted. Direct
90 access to the repository files is not needed, unless of course
90 access to the repository files is not needed, unless of course
91 the repository is :local:. The conversion uses the top level
91 the repository is :local:. The conversion uses the top level
92 directory in the sandbox to find the CVS repository, and then uses
92 directory in the sandbox to find the CVS repository, and then uses
93 CVS rlog commands to find files to convert. This means that unless
93 CVS rlog commands to find files to convert. This means that unless
94 a filemap is given, all files under the starting directory will be
94 a filemap is given, all files under the starting directory will be
95 converted, and that any directory reorganisation in the CVS
95 converted, and that any directory reorganisation in the CVS
96 sandbox is ignored.
96 sandbox is ignored.
97
97
98 Because CVS does not have changesets, it is necessary to collect
98 Because CVS does not have changesets, it is necessary to collect
99 individual commits to CVS and merge them into changesets. CVS
99 individual commits to CVS and merge them into changesets. CVS
100 source uses its internal changeset merging code by default but can
100 source uses its internal changeset merging code by default but can
101 be configured to call the external 'cvsps' program by setting:
101 be configured to call the external 'cvsps' program by setting:
102 --config convert.cvsps='cvsps -A -u --cvs-direct -q'
102 --config convert.cvsps='cvsps -A -u --cvs-direct -q'
103 This is a legacy option and may be removed in future.
103 This is a legacy option and may be removed in future.
104
104
105 The options shown are the defaults.
105 The options shown are the defaults.
106
106
107 Internal cvsps is selected by setting
107 Internal cvsps is selected by setting
108 --config convert.cvsps=builtin
108 --config convert.cvsps=builtin
109 and has a few more configurable options:
109 and has a few more configurable options:
110 --config convert.cvsps.fuzz=60 (integer)
110 --config convert.cvsps.fuzz=60 (integer)
111 Specify the maximum time (in seconds) that is allowed between
111 Specify the maximum time (in seconds) that is allowed between
112 commits with identical user and log message in a single
112 commits with identical user and log message in a single
113 changeset. When very large files were checked in as part
113 changeset. When very large files were checked in as part
114 of a changeset then the default may not be long enough.
114 of a changeset then the default may not be long enough.
115 --config convert.cvsps.mergeto='{{mergetobranch ([-\w]+)}}'
115 --config convert.cvsps.mergeto='{{mergetobranch ([-\w]+)}}'
116 Specify a regular expression to which commit log messages are
116 Specify a regular expression to which commit log messages are
117 matched. If a match occurs, then the conversion process will
117 matched. If a match occurs, then the conversion process will
118 insert a dummy revision merging the branch on which this log
118 insert a dummy revision merging the branch on which this log
119 message occurs to the branch indicated in the regex.
119 message occurs to the branch indicated in the regex.
120 --config convert.cvsps.mergefrom='{{mergefrombranch ([-\w]+)}}'
120 --config convert.cvsps.mergefrom='{{mergefrombranch ([-\w]+)}}'
121 Specify a regular expression to which commit log messages are
121 Specify a regular expression to which commit log messages are
122 matched. If a match occurs, then the conversion process will
122 matched. If a match occurs, then the conversion process will
123 add the most recent revision on the branch indicated in the
123 add the most recent revision on the branch indicated in the
124 regex as the second parent of the changeset.
124 regex as the second parent of the changeset.
125
125
126 The hgext/convert/cvsps wrapper script allows the builtin changeset
126 The hgext/convert/cvsps wrapper script allows the builtin changeset
127 merging code to be run without doing a conversion. Its parameters and
127 merging code to be run without doing a conversion. Its parameters and
128 output are similar to that of cvsps 2.1.
128 output are similar to that of cvsps 2.1.
129
129
130 Subversion Source
130 Subversion Source
131 -----------------
131 -----------------
132
132
133 Subversion source detects classical trunk/branches/tags layouts.
133 Subversion source detects classical trunk/branches/tags layouts.
134 By default, the supplied "svn://repo/path/" source URL is
134 By default, the supplied "svn://repo/path/" source URL is
135 converted as a single branch. If "svn://repo/path/trunk" exists
135 converted as a single branch. If "svn://repo/path/trunk" exists
136 it replaces the default branch. If "svn://repo/path/branches"
136 it replaces the default branch. If "svn://repo/path/branches"
137 exists, its subdirectories are listed as possible branches. If
137 exists, its subdirectories are listed as possible branches. If
138 "svn://repo/path/tags" exists, it is looked for tags referencing
138 "svn://repo/path/tags" exists, it is looked for tags referencing
139 converted branches. Default "trunk", "branches" and "tags" values
139 converted branches. Default "trunk", "branches" and "tags" values
140 can be overriden with following options. Set them to paths
140 can be overriden with following options. Set them to paths
141 relative to the source URL, or leave them blank to disable
141 relative to the source URL, or leave them blank to disable
142 autodetection.
142 autodetection.
143
143
144 --config convert.svn.branches=branches (directory name)
144 --config convert.svn.branches=branches (directory name)
145 specify the directory containing branches
145 specify the directory containing branches
146 --config convert.svn.tags=tags (directory name)
146 --config convert.svn.tags=tags (directory name)
147 specify the directory containing tags
147 specify the directory containing tags
148 --config convert.svn.trunk=trunk (directory name)
148 --config convert.svn.trunk=trunk (directory name)
149 specify the name of the trunk branch
149 specify the name of the trunk branch
150
150
151 Source history can be retrieved starting at a specific revision,
151 Source history can be retrieved starting at a specific revision,
152 instead of being integrally converted. Only single branch
152 instead of being integrally converted. Only single branch
153 conversions are supported.
153 conversions are supported.
154
154
155 --config convert.svn.startrev=0 (svn revision number)
155 --config convert.svn.startrev=0 (svn revision number)
156 specify start Subversion revision.
156 specify start Subversion revision.
157
157
158 Perforce Source
158 Perforce Source
159 ---------------
159 ---------------
160
160
161 The Perforce (P4) importer can be given a p4 depot path or a client
161 The Perforce (P4) importer can be given a p4 depot path or a client
162 specification as source. It will convert all files in the source to
162 specification as source. It will convert all files in the source to
163 a flat Mercurial repository, ignoring labels, branches and integrations.
163 a flat Mercurial repository, ignoring labels, branches and integrations.
164 Note that when a depot path is given you then usually should specify a
164 Note that when a depot path is given you then usually should specify a
165 target directory, because otherwise the target may be named ...-hg.
165 target directory, because otherwise the target may be named ...-hg.
166
166
167 It is possible to limit the amount of source history to be converted
167 It is possible to limit the amount of source history to be converted
168 by specifying an initial Perforce revision.
168 by specifying an initial Perforce revision.
169
169
170 --config convert.p4.startrev=0 (perforce changelist number)
170 --config convert.p4.startrev=0 (perforce changelist number)
171 specify initial Perforce revision.
171 specify initial Perforce revision.
172
172
173
173
174 Mercurial Destination
174 Mercurial Destination
175 ---------------------
175 ---------------------
176
176
177 --config convert.hg.clonebranches=False (boolean)
177 --config convert.hg.clonebranches=False (boolean)
178 dispatch source branches in separate clones.
178 dispatch source branches in separate clones.
179 --config convert.hg.tagsbranch=default (branch name)
179 --config convert.hg.tagsbranch=default (branch name)
180 tag revisions branch name
180 tag revisions branch name
181 --config convert.hg.usebranchnames=True (boolean)
181 --config convert.hg.usebranchnames=True (boolean)
182 preserve branch names
182 preserve branch names
183
183
184 options:
184 options:
185
185
186 -A --authors username mapping filename
186 -A --authors username mapping filename
187 -d --dest-type destination repository type
187 -d --dest-type destination repository type
188 --filemap remap file names using contents of file
188 --filemap remap file names using contents of file
189 -r --rev import up to target revision REV
189 -r --rev import up to target revision REV
190 -s --source-type source repository type
190 -s --source-type source repository type
191 --splicemap splice synthesized history into place
191 --splicemap splice synthesized history into place
192 --datesort try to sort changesets by date
192 --datesort try to sort changesets by date
193
193
194 use "hg -v help convert" to show global options
194 use "hg -v help convert" to show global options
195 adding a
195 adding a
196 assuming destination a-hg
196 assuming destination a-hg
197 initializing destination a-hg repository
197 initializing destination a-hg repository
198 scanning source...
198 scanning source...
199 sorting...
199 sorting...
200 converting...
200 converting...
201 4 a
201 4 a
202 3 b
202 3 b
203 2 c
203 2 c
204 1 d
204 1 d
205 0 e
205 0 e
206 pulling from ../a
206 pulling from ../a
207 searching for changes
207 searching for changes
208 no changes found
208 no changes found
209 % should fail
209 % should fail
210 initializing destination bogusfile repository
210 initializing destination bogusfile repository
211 abort: cannot create new bundle repository
211 abort: cannot create new bundle repository
212 % should fail
212 % should fail
213 abort: Permission denied: bogusdir
213 abort: Permission denied: bogusdir
214 % should succeed
214 % should succeed
215 initializing destination bogusdir repository
215 initializing destination bogusdir repository
216 scanning source...
216 scanning source...
217 sorting...
217 sorting...
218 converting...
218 converting...
219 4 a
219 4 a
220 3 b
220 3 b
221 2 c
221 2 c
222 1 d
222 1 d
223 0 e
223 0 e
224 % test pre and post conversion actions
224 % test pre and post conversion actions
225 run hg source pre-conversion action
225 run hg source pre-conversion action
226 run hg sink pre-conversion action
226 run hg sink pre-conversion action
227 run hg sink post-conversion action
227 run hg sink post-conversion action
228 run hg source post-conversion action
228 run hg source post-conversion action
229 % converting empty dir should fail nicely
230 assuming destination emptydir-hg
231 initializing destination emptydir-hg repository
232 emptydir does not look like a CVS checkout
233 emptydir does not look like a Git repo
234 .../emptydir does not look like a Subversion repo
235 emptydir is not a local Mercurial repo
236 emptydir does not look like a darcs repo
237 cannot find required "mtn" tool
238 emptydir does not look like a GNU Arch repo
239 emptydir does not look like a Bazaar repo
240 cannot find required "p4" tool
241 abort: emptydir: missing or unsupported repository
General Comments 0
You need to be logged in to leave comments. Login now