##// END OF EJS Templates
help: fix some instances of 'the the'
Mads Kiilerich -
r17251:98166640 stable
parent child Browse files
Show More
@@ -1,31 +1,31 b''
1 WiX installer source files
1 WiX installer source files
2 ==========================
2 ==========================
3
3
4 The files in this folder are used by the thg-winbuild [1] package
4 The files in this folder are used by the thg-winbuild [1] package
5 building architecture to create a Mercurial MSI installer. These files
5 building architecture to create a Mercurial MSI installer. These files
6 are versioned within the Mercurial source tree because the WXS files
6 are versioned within the Mercurial source tree because the WXS files
7 must kept up to date with distribution changes within their branch. In
7 must kept up to date with distribution changes within their branch. In
8 other words, the default branch WXS files are expected to diverge from
8 other words, the default branch WXS files are expected to diverge from
9 the stable branch WXS files. Storing them within the same repository is
9 the stable branch WXS files. Storing them within the same repository is
10 the only sane way to keep the the source tree and the installer in sync.
10 the only sane way to keep the source tree and the installer in sync.
11
11
12 The MSI installer builder uses only the mercurial.ini file from the
12 The MSI installer builder uses only the mercurial.ini file from the
13 contrib/win32 folder, the contents of which have been historically used
13 contrib/win32 folder, the contents of which have been historically used
14 to create an InnoSetup based installer. The rest of the files there are
14 to create an InnoSetup based installer. The rest of the files there are
15 ignored.
15 ignored.
16
16
17 The MSI packages built by thg-winbuild require elevated (admin)
17 The MSI packages built by thg-winbuild require elevated (admin)
18 privileges to be installed due to the installation of MSVC CRT libraries
18 privileges to be installed due to the installation of MSVC CRT libraries
19 under the C:\WINDOWS\WinSxS folder. Thus the InnoSetup installers may
19 under the C:\WINDOWS\WinSxS folder. Thus the InnoSetup installers may
20 still be useful to some users.
20 still be useful to some users.
21
21
22 To build your own MSI packages, clone the thg-winbuild [1] repository
22 To build your own MSI packages, clone the thg-winbuild [1] repository
23 and follow the README.txt [2] instructions closely. There are fewer
23 and follow the README.txt [2] instructions closely. There are fewer
24 prerequisites for a WiX [3] installer than an InnoSetup installer, but
24 prerequisites for a WiX [3] installer than an InnoSetup installer, but
25 they are more specific.
25 they are more specific.
26
26
27 Direct questions or comments to Steve Borho <steve@borho.org>
27 Direct questions or comments to Steve Borho <steve@borho.org>
28
28
29 [1] http://bitbucket.org/tortoisehg/thg-winbuild
29 [1] http://bitbucket.org/tortoisehg/thg-winbuild
30 [2] http://bitbucket.org/tortoisehg/thg-winbuild/src/tip/README.txt
30 [2] http://bitbucket.org/tortoisehg/thg-winbuild/src/tip/README.txt
31 [3] http://wix.sourceforge.net/
31 [3] http://wix.sourceforge.net/
@@ -1,370 +1,370 b''
1 # convert.py Foreign SCM converter
1 # convert.py Foreign SCM converter
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
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 revisions from foreign VCS repositories into Mercurial'''
8 '''import revisions from foreign VCS repositories into Mercurial'''
9
9
10 import convcmd
10 import convcmd
11 import cvsps
11 import cvsps
12 import subversion
12 import subversion
13 from mercurial import commands, templatekw
13 from mercurial import commands, templatekw
14 from mercurial.i18n import _
14 from mercurial.i18n import _
15
15
16 testedwith = 'internal'
16 testedwith = 'internal'
17
17
18 # Commands definition was moved elsewhere to ease demandload job.
18 # Commands definition was moved elsewhere to ease demandload job.
19
19
20 def convert(ui, src, dest=None, revmapfile=None, **opts):
20 def convert(ui, src, dest=None, revmapfile=None, **opts):
21 """convert a foreign SCM repository to a Mercurial one.
21 """convert a foreign SCM repository to a Mercurial one.
22
22
23 Accepted source formats [identifiers]:
23 Accepted source formats [identifiers]:
24
24
25 - Mercurial [hg]
25 - Mercurial [hg]
26 - CVS [cvs]
26 - CVS [cvs]
27 - Darcs [darcs]
27 - Darcs [darcs]
28 - git [git]
28 - git [git]
29 - Subversion [svn]
29 - Subversion [svn]
30 - Monotone [mtn]
30 - Monotone [mtn]
31 - GNU Arch [gnuarch]
31 - GNU Arch [gnuarch]
32 - Bazaar [bzr]
32 - Bazaar [bzr]
33 - Perforce [p4]
33 - Perforce [p4]
34
34
35 Accepted destination formats [identifiers]:
35 Accepted destination formats [identifiers]:
36
36
37 - Mercurial [hg]
37 - Mercurial [hg]
38 - Subversion [svn] (history on branches is not preserved)
38 - Subversion [svn] (history on branches is not preserved)
39
39
40 If no revision is given, all revisions will be converted.
40 If no revision is given, all revisions will be converted.
41 Otherwise, convert will only import up to the named revision
41 Otherwise, convert will only import up to the named revision
42 (given in a format understood by the source).
42 (given in a format understood by the source).
43
43
44 If no destination directory name is specified, it defaults to the
44 If no destination directory name is specified, it defaults to the
45 basename of the source with ``-hg`` appended. If the destination
45 basename of the source with ``-hg`` appended. If the destination
46 repository doesn't exist, it will be created.
46 repository doesn't exist, it will be created.
47
47
48 By default, all sources except Mercurial will use --branchsort.
48 By default, all sources except Mercurial will use --branchsort.
49 Mercurial uses --sourcesort to preserve original revision numbers
49 Mercurial uses --sourcesort to preserve original revision numbers
50 order. Sort modes have the following effects:
50 order. Sort modes have the following effects:
51
51
52 --branchsort convert from parent to child revision when possible,
52 --branchsort convert from parent to child revision when possible,
53 which means branches are usually converted one after
53 which means branches are usually converted one after
54 the other. It generates more compact repositories.
54 the other. It generates more compact repositories.
55
55
56 --datesort sort revisions by date. Converted repositories have
56 --datesort sort revisions by date. Converted repositories have
57 good-looking changelogs but are often an order of
57 good-looking changelogs but are often an order of
58 magnitude larger than the same ones generated by
58 magnitude larger than the same ones generated by
59 --branchsort.
59 --branchsort.
60
60
61 --sourcesort try to preserve source revisions order, only
61 --sourcesort try to preserve source revisions order, only
62 supported by Mercurial sources.
62 supported by Mercurial sources.
63
63
64 If ``REVMAP`` isn't given, it will be put in a default location
64 If ``REVMAP`` isn't given, it will be put in a default location
65 (``<dest>/.hg/shamap`` by default). The ``REVMAP`` is a simple
65 (``<dest>/.hg/shamap`` by default). The ``REVMAP`` is a simple
66 text file that maps each source commit ID to the destination ID
66 text file that maps each source commit ID to the destination ID
67 for that revision, like so::
67 for that revision, like so::
68
68
69 <source ID> <destination ID>
69 <source ID> <destination ID>
70
70
71 If the file doesn't exist, it's automatically created. It's
71 If the file doesn't exist, it's automatically created. It's
72 updated on each commit copied, so :hg:`convert` can be interrupted
72 updated on each commit copied, so :hg:`convert` can be interrupted
73 and can be run repeatedly to copy new commits.
73 and can be run repeatedly to copy new commits.
74
74
75 The authormap is a simple text file that maps each source commit
75 The authormap is a simple text file that maps each source commit
76 author to a destination commit author. It is handy for source SCMs
76 author to a destination commit author. It is handy for source SCMs
77 that use unix logins to identify authors (eg: CVS). One line per
77 that use unix logins to identify authors (eg: CVS). One line per
78 author mapping and the line format is::
78 author mapping and the line format is::
79
79
80 source author = destination author
80 source author = destination author
81
81
82 Empty lines and lines starting with a ``#`` are ignored.
82 Empty lines and lines starting with a ``#`` are ignored.
83
83
84 The filemap is a file that allows filtering and remapping of files
84 The filemap is a file that allows filtering and remapping of files
85 and directories. Each line can contain one of the following
85 and directories. Each line can contain one of the following
86 directives::
86 directives::
87
87
88 include path/to/file-or-dir
88 include path/to/file-or-dir
89
89
90 exclude path/to/file-or-dir
90 exclude path/to/file-or-dir
91
91
92 rename path/to/source path/to/destination
92 rename path/to/source path/to/destination
93
93
94 Comment lines start with ``#``. A specified path matches if it
94 Comment lines start with ``#``. A specified path matches if it
95 equals the full relative name of a file or one of its parent
95 equals the full relative name of a file or one of its parent
96 directories. The ``include`` or ``exclude`` directive with the
96 directories. The ``include`` or ``exclude`` directive with the
97 longest matching path applies, so line order does not matter.
97 longest matching path applies, so line order does not matter.
98
98
99 The ``include`` directive causes a file, or all files under a
99 The ``include`` directive causes a file, or all files under a
100 directory, to be included in the destination repository, and the
100 directory, to be included in the destination repository, and the
101 exclusion of all other files and directories not explicitly
101 exclusion of all other files and directories not explicitly
102 included. The ``exclude`` directive causes files or directories to
102 included. The ``exclude`` directive causes files or directories to
103 be omitted. The ``rename`` directive renames a file or directory if
103 be omitted. The ``rename`` directive renames a file or directory if
104 it is converted. To rename from a subdirectory into the root of
104 it is converted. To rename from a subdirectory into the root of
105 the repository, use ``.`` as the path to rename to.
105 the repository, use ``.`` as the path to rename to.
106
106
107 The splicemap is a file that allows insertion of synthetic
107 The splicemap is a file that allows insertion of synthetic
108 history, letting you specify the parents of a revision. This is
108 history, letting you specify the parents of a revision. This is
109 useful if you want to e.g. give a Subversion merge two parents, or
109 useful if you want to e.g. give a Subversion merge two parents, or
110 graft two disconnected series of history together. Each entry
110 graft two disconnected series of history together. Each entry
111 contains a key, followed by a space, followed by one or two
111 contains a key, followed by a space, followed by one or two
112 comma-separated values::
112 comma-separated values::
113
113
114 key parent1, parent2
114 key parent1, parent2
115
115
116 The key is the revision ID in the source
116 The key is the revision ID in the source
117 revision control system whose parents should be modified (same
117 revision control system whose parents should be modified (same
118 format as a key in .hg/shamap). The values are the revision IDs
118 format as a key in .hg/shamap). The values are the revision IDs
119 (in either the source or destination revision control system) that
119 (in either the source or destination revision control system) that
120 should be used as the new parents for that node. For example, if
120 should be used as the new parents for that node. For example, if
121 you have merged "release-1.0" into "trunk", then you should
121 you have merged "release-1.0" into "trunk", then you should
122 specify the revision on "trunk" as the first parent and the one on
122 specify the revision on "trunk" as the first parent and the one on
123 the "release-1.0" branch as the second.
123 the "release-1.0" branch as the second.
124
124
125 The branchmap is a file that allows you to rename a branch when it is
125 The branchmap is a file that allows you to rename a branch when it is
126 being brought in from whatever external repository. When used in
126 being brought in from whatever external repository. When used in
127 conjunction with a splicemap, it allows for a powerful combination
127 conjunction with a splicemap, it allows for a powerful combination
128 to help fix even the most badly mismanaged repositories and turn them
128 to help fix even the most badly mismanaged repositories and turn them
129 into nicely structured Mercurial repositories. The branchmap contains
129 into nicely structured Mercurial repositories. The branchmap contains
130 lines of the form::
130 lines of the form::
131
131
132 original_branch_name new_branch_name
132 original_branch_name new_branch_name
133
133
134 where "original_branch_name" is the name of the branch in the
134 where "original_branch_name" is the name of the branch in the
135 source repository, and "new_branch_name" is the name of the branch
135 source repository, and "new_branch_name" is the name of the branch
136 is the destination repository. No whitespace is allowed in the
136 is the destination repository. No whitespace is allowed in the
137 branch names. This can be used to (for instance) move code in one
137 branch names. This can be used to (for instance) move code in one
138 repository from "default" to a named branch.
138 repository from "default" to a named branch.
139
139
140 Mercurial Source
140 Mercurial Source
141 ''''''''''''''''
141 ''''''''''''''''
142
142
143 The Mercurial source recognizes the following configuration
143 The Mercurial source recognizes the following configuration
144 options, which you can set on the command line with ``--config``:
144 options, which you can set on the command line with ``--config``:
145
145
146 :convert.hg.ignoreerrors: ignore integrity errors when reading.
146 :convert.hg.ignoreerrors: ignore integrity errors when reading.
147 Use it to fix Mercurial repositories with missing revlogs, by
147 Use it to fix Mercurial repositories with missing revlogs, by
148 converting from and to Mercurial. Default is False.
148 converting from and to Mercurial. Default is False.
149
149
150 :convert.hg.saverev: store original revision ID in changeset
150 :convert.hg.saverev: store original revision ID in changeset
151 (forces target IDs to change). It takes a boolean argument and
151 (forces target IDs to change). It takes a boolean argument and
152 defaults to False.
152 defaults to False.
153
153
154 :convert.hg.startrev: convert start revision and its descendants.
154 :convert.hg.startrev: convert start revision and its descendants.
155 It takes a hg revision identifier and defaults to 0.
155 It takes a hg revision identifier and defaults to 0.
156
156
157 CVS Source
157 CVS Source
158 ''''''''''
158 ''''''''''
159
159
160 CVS source will use a sandbox (i.e. a checked-out copy) from CVS
160 CVS source will use a sandbox (i.e. a checked-out copy) from CVS
161 to indicate the starting point of what will be converted. Direct
161 to indicate the starting point of what will be converted. Direct
162 access to the repository files is not needed, unless of course the
162 access to the repository files is not needed, unless of course the
163 repository is ``:local:``. The conversion uses the top level
163 repository is ``:local:``. The conversion uses the top level
164 directory in the sandbox to find the CVS repository, and then uses
164 directory in the sandbox to find the CVS repository, and then uses
165 CVS rlog commands to find files to convert. This means that unless
165 CVS rlog commands to find files to convert. This means that unless
166 a filemap is given, all files under the starting directory will be
166 a filemap is given, all files under the starting directory will be
167 converted, and that any directory reorganization in the CVS
167 converted, and that any directory reorganization in the CVS
168 sandbox is ignored.
168 sandbox is ignored.
169
169
170 The following options can be used with ``--config``:
170 The following options can be used with ``--config``:
171
171
172 :convert.cvsps.cache: Set to False to disable remote log caching,
172 :convert.cvsps.cache: Set to False to disable remote log caching,
173 for testing and debugging purposes. Default is True.
173 for testing and debugging purposes. Default is True.
174
174
175 :convert.cvsps.fuzz: Specify the maximum time (in seconds) that is
175 :convert.cvsps.fuzz: Specify the maximum time (in seconds) that is
176 allowed between commits with identical user and log message in
176 allowed between commits with identical user and log message in
177 a single changeset. When very large files were checked in as
177 a single changeset. When very large files were checked in as
178 part of a changeset then the default may not be long enough.
178 part of a changeset then the default may not be long enough.
179 The default is 60.
179 The default is 60.
180
180
181 :convert.cvsps.mergeto: Specify a regular expression to which
181 :convert.cvsps.mergeto: Specify a regular expression to which
182 commit log messages are matched. If a match occurs, then the
182 commit log messages are matched. If a match occurs, then the
183 conversion process will insert a dummy revision merging the
183 conversion process will insert a dummy revision merging the
184 branch on which this log message occurs to the branch
184 branch on which this log message occurs to the branch
185 indicated in the regex. Default is ``{{mergetobranch
185 indicated in the regex. Default is ``{{mergetobranch
186 ([-\\w]+)}}``
186 ([-\\w]+)}}``
187
187
188 :convert.cvsps.mergefrom: Specify a regular expression to which
188 :convert.cvsps.mergefrom: Specify a regular expression to which
189 commit log messages are matched. If a match occurs, then the
189 commit log messages are matched. If a match occurs, then the
190 conversion process will add the most recent revision on the
190 conversion process will add the most recent revision on the
191 branch indicated in the regex as the second parent of the
191 branch indicated in the regex as the second parent of the
192 changeset. Default is ``{{mergefrombranch ([-\\w]+)}}``
192 changeset. Default is ``{{mergefrombranch ([-\\w]+)}}``
193
193
194 :hook.cvslog: Specify a Python function to be called at the end of
194 :hook.cvslog: Specify a Python function to be called at the end of
195 gathering the CVS log. The function is passed a list with the
195 gathering the CVS log. The function is passed a list with the
196 log entries, and can modify the entries in-place, or add or
196 log entries, and can modify the entries in-place, or add or
197 delete them.
197 delete them.
198
198
199 :hook.cvschangesets: Specify a Python function to be called after
199 :hook.cvschangesets: Specify a Python function to be called after
200 the changesets are calculated from the the CVS log. The
200 the changesets are calculated from the CVS log. The
201 function is passed a list with the changeset entries, and can
201 function is passed a list with the changeset entries, and can
202 modify the changesets in-place, or add or delete them.
202 modify the changesets in-place, or add or delete them.
203
203
204 An additional "debugcvsps" Mercurial command allows the builtin
204 An additional "debugcvsps" Mercurial command allows the builtin
205 changeset merging code to be run without doing a conversion. Its
205 changeset merging code to be run without doing a conversion. Its
206 parameters and output are similar to that of cvsps 2.1. Please see
206 parameters and output are similar to that of cvsps 2.1. Please see
207 the command help for more details.
207 the command help for more details.
208
208
209 Subversion Source
209 Subversion Source
210 '''''''''''''''''
210 '''''''''''''''''
211
211
212 Subversion source detects classical trunk/branches/tags layouts.
212 Subversion source detects classical trunk/branches/tags layouts.
213 By default, the supplied ``svn://repo/path/`` source URL is
213 By default, the supplied ``svn://repo/path/`` source URL is
214 converted as a single branch. If ``svn://repo/path/trunk`` exists
214 converted as a single branch. If ``svn://repo/path/trunk`` exists
215 it replaces the default branch. If ``svn://repo/path/branches``
215 it replaces the default branch. If ``svn://repo/path/branches``
216 exists, its subdirectories are listed as possible branches. If
216 exists, its subdirectories are listed as possible branches. If
217 ``svn://repo/path/tags`` exists, it is looked for tags referencing
217 ``svn://repo/path/tags`` exists, it is looked for tags referencing
218 converted branches. Default ``trunk``, ``branches`` and ``tags``
218 converted branches. Default ``trunk``, ``branches`` and ``tags``
219 values can be overridden with following options. Set them to paths
219 values can be overridden with following options. Set them to paths
220 relative to the source URL, or leave them blank to disable auto
220 relative to the source URL, or leave them blank to disable auto
221 detection.
221 detection.
222
222
223 The following options can be set with ``--config``:
223 The following options can be set with ``--config``:
224
224
225 :convert.svn.branches: specify the directory containing branches.
225 :convert.svn.branches: specify the directory containing branches.
226 The default is ``branches``.
226 The default is ``branches``.
227
227
228 :convert.svn.tags: specify the directory containing tags. The
228 :convert.svn.tags: specify the directory containing tags. The
229 default is ``tags``.
229 default is ``tags``.
230
230
231 :convert.svn.trunk: specify the name of the trunk branch. The
231 :convert.svn.trunk: specify the name of the trunk branch. The
232 default is ``trunk``.
232 default is ``trunk``.
233
233
234 Source history can be retrieved starting at a specific revision,
234 Source history can be retrieved starting at a specific revision,
235 instead of being integrally converted. Only single branch
235 instead of being integrally converted. Only single branch
236 conversions are supported.
236 conversions are supported.
237
237
238 :convert.svn.startrev: specify start Subversion revision number.
238 :convert.svn.startrev: specify start Subversion revision number.
239 The default is 0.
239 The default is 0.
240
240
241 Perforce Source
241 Perforce Source
242 '''''''''''''''
242 '''''''''''''''
243
243
244 The Perforce (P4) importer can be given a p4 depot path or a
244 The Perforce (P4) importer can be given a p4 depot path or a
245 client specification as source. It will convert all files in the
245 client specification as source. It will convert all files in the
246 source to a flat Mercurial repository, ignoring labels, branches
246 source to a flat Mercurial repository, ignoring labels, branches
247 and integrations. Note that when a depot path is given you then
247 and integrations. Note that when a depot path is given you then
248 usually should specify a target directory, because otherwise the
248 usually should specify a target directory, because otherwise the
249 target may be named ``...-hg``.
249 target may be named ``...-hg``.
250
250
251 It is possible to limit the amount of source history to be
251 It is possible to limit the amount of source history to be
252 converted by specifying an initial Perforce revision:
252 converted by specifying an initial Perforce revision:
253
253
254 :convert.p4.startrev: specify initial Perforce revision (a
254 :convert.p4.startrev: specify initial Perforce revision (a
255 Perforce changelist number).
255 Perforce changelist number).
256
256
257 Mercurial Destination
257 Mercurial Destination
258 '''''''''''''''''''''
258 '''''''''''''''''''''
259
259
260 The following options are supported:
260 The following options are supported:
261
261
262 :convert.hg.clonebranches: dispatch source branches in separate
262 :convert.hg.clonebranches: dispatch source branches in separate
263 clones. The default is False.
263 clones. The default is False.
264
264
265 :convert.hg.tagsbranch: branch name for tag revisions, defaults to
265 :convert.hg.tagsbranch: branch name for tag revisions, defaults to
266 ``default``.
266 ``default``.
267
267
268 :convert.hg.usebranchnames: preserve branch names. The default is
268 :convert.hg.usebranchnames: preserve branch names. The default is
269 True.
269 True.
270 """
270 """
271 return convcmd.convert(ui, src, dest, revmapfile, **opts)
271 return convcmd.convert(ui, src, dest, revmapfile, **opts)
272
272
273 def debugsvnlog(ui, **opts):
273 def debugsvnlog(ui, **opts):
274 return subversion.debugsvnlog(ui, **opts)
274 return subversion.debugsvnlog(ui, **opts)
275
275
276 def debugcvsps(ui, *args, **opts):
276 def debugcvsps(ui, *args, **opts):
277 '''create changeset information from CVS
277 '''create changeset information from CVS
278
278
279 This command is intended as a debugging tool for the CVS to
279 This command is intended as a debugging tool for the CVS to
280 Mercurial converter, and can be used as a direct replacement for
280 Mercurial converter, and can be used as a direct replacement for
281 cvsps.
281 cvsps.
282
282
283 Hg debugcvsps reads the CVS rlog for current directory (or any
283 Hg debugcvsps reads the CVS rlog for current directory (or any
284 named directory) in the CVS repository, and converts the log to a
284 named directory) in the CVS repository, and converts the log to a
285 series of changesets based on matching commit log entries and
285 series of changesets based on matching commit log entries and
286 dates.'''
286 dates.'''
287 return cvsps.debugcvsps(ui, *args, **opts)
287 return cvsps.debugcvsps(ui, *args, **opts)
288
288
289 commands.norepo += " convert debugsvnlog debugcvsps"
289 commands.norepo += " convert debugsvnlog debugcvsps"
290
290
291 cmdtable = {
291 cmdtable = {
292 "convert":
292 "convert":
293 (convert,
293 (convert,
294 [('', 'authors', '',
294 [('', 'authors', '',
295 _('username mapping filename (DEPRECATED, use --authormap instead)'),
295 _('username mapping filename (DEPRECATED, use --authormap instead)'),
296 _('FILE')),
296 _('FILE')),
297 ('s', 'source-type', '',
297 ('s', 'source-type', '',
298 _('source repository type'), _('TYPE')),
298 _('source repository type'), _('TYPE')),
299 ('d', 'dest-type', '',
299 ('d', 'dest-type', '',
300 _('destination repository type'), _('TYPE')),
300 _('destination repository type'), _('TYPE')),
301 ('r', 'rev', '',
301 ('r', 'rev', '',
302 _('import up to target revision REV'), _('REV')),
302 _('import up to target revision REV'), _('REV')),
303 ('A', 'authormap', '',
303 ('A', 'authormap', '',
304 _('remap usernames using this file'), _('FILE')),
304 _('remap usernames using this file'), _('FILE')),
305 ('', 'filemap', '',
305 ('', 'filemap', '',
306 _('remap file names using contents of file'), _('FILE')),
306 _('remap file names using contents of file'), _('FILE')),
307 ('', 'splicemap', '',
307 ('', 'splicemap', '',
308 _('splice synthesized history into place'), _('FILE')),
308 _('splice synthesized history into place'), _('FILE')),
309 ('', 'branchmap', '',
309 ('', 'branchmap', '',
310 _('change branch names while converting'), _('FILE')),
310 _('change branch names while converting'), _('FILE')),
311 ('', 'branchsort', None, _('try to sort changesets by branches')),
311 ('', 'branchsort', None, _('try to sort changesets by branches')),
312 ('', 'datesort', None, _('try to sort changesets by date')),
312 ('', 'datesort', None, _('try to sort changesets by date')),
313 ('', 'sourcesort', None, _('preserve source changesets order'))],
313 ('', 'sourcesort', None, _('preserve source changesets order'))],
314 _('hg convert [OPTION]... SOURCE [DEST [REVMAP]]')),
314 _('hg convert [OPTION]... SOURCE [DEST [REVMAP]]')),
315 "debugsvnlog":
315 "debugsvnlog":
316 (debugsvnlog,
316 (debugsvnlog,
317 [],
317 [],
318 'hg debugsvnlog'),
318 'hg debugsvnlog'),
319 "debugcvsps":
319 "debugcvsps":
320 (debugcvsps,
320 (debugcvsps,
321 [
321 [
322 # Main options shared with cvsps-2.1
322 # Main options shared with cvsps-2.1
323 ('b', 'branches', [], _('only return changes on specified branches')),
323 ('b', 'branches', [], _('only return changes on specified branches')),
324 ('p', 'prefix', '', _('prefix to remove from file names')),
324 ('p', 'prefix', '', _('prefix to remove from file names')),
325 ('r', 'revisions', [],
325 ('r', 'revisions', [],
326 _('only return changes after or between specified tags')),
326 _('only return changes after or between specified tags')),
327 ('u', 'update-cache', None, _("update cvs log cache")),
327 ('u', 'update-cache', None, _("update cvs log cache")),
328 ('x', 'new-cache', None, _("create new cvs log cache")),
328 ('x', 'new-cache', None, _("create new cvs log cache")),
329 ('z', 'fuzz', 60, _('set commit time fuzz in seconds')),
329 ('z', 'fuzz', 60, _('set commit time fuzz in seconds')),
330 ('', 'root', '', _('specify cvsroot')),
330 ('', 'root', '', _('specify cvsroot')),
331 # Options specific to builtin cvsps
331 # Options specific to builtin cvsps
332 ('', 'parents', '', _('show parent changesets')),
332 ('', 'parents', '', _('show parent changesets')),
333 ('', 'ancestors', '',
333 ('', 'ancestors', '',
334 _('show current changeset in ancestor branches')),
334 _('show current changeset in ancestor branches')),
335 # Options that are ignored for compatibility with cvsps-2.1
335 # Options that are ignored for compatibility with cvsps-2.1
336 ('A', 'cvs-direct', None, _('ignored for compatibility')),
336 ('A', 'cvs-direct', None, _('ignored for compatibility')),
337 ],
337 ],
338 _('hg debugcvsps [OPTION]... [PATH]...')),
338 _('hg debugcvsps [OPTION]... [PATH]...')),
339 }
339 }
340
340
341 def kwconverted(ctx, name):
341 def kwconverted(ctx, name):
342 rev = ctx.extra().get('convert_revision', '')
342 rev = ctx.extra().get('convert_revision', '')
343 if rev.startswith('svn:'):
343 if rev.startswith('svn:'):
344 if name == 'svnrev':
344 if name == 'svnrev':
345 return str(subversion.revsplit(rev)[2])
345 return str(subversion.revsplit(rev)[2])
346 elif name == 'svnpath':
346 elif name == 'svnpath':
347 return subversion.revsplit(rev)[1]
347 return subversion.revsplit(rev)[1]
348 elif name == 'svnuuid':
348 elif name == 'svnuuid':
349 return subversion.revsplit(rev)[0]
349 return subversion.revsplit(rev)[0]
350 return rev
350 return rev
351
351
352 def kwsvnrev(repo, ctx, **args):
352 def kwsvnrev(repo, ctx, **args):
353 """:svnrev: String. Converted subversion revision number."""
353 """:svnrev: String. Converted subversion revision number."""
354 return kwconverted(ctx, 'svnrev')
354 return kwconverted(ctx, 'svnrev')
355
355
356 def kwsvnpath(repo, ctx, **args):
356 def kwsvnpath(repo, ctx, **args):
357 """:svnpath: String. Converted subversion revision project path."""
357 """:svnpath: String. Converted subversion revision project path."""
358 return kwconverted(ctx, 'svnpath')
358 return kwconverted(ctx, 'svnpath')
359
359
360 def kwsvnuuid(repo, ctx, **args):
360 def kwsvnuuid(repo, ctx, **args):
361 """:svnuuid: String. Converted subversion revision repository identifier."""
361 """:svnuuid: String. Converted subversion revision repository identifier."""
362 return kwconverted(ctx, 'svnuuid')
362 return kwconverted(ctx, 'svnuuid')
363
363
364 def extsetup(ui):
364 def extsetup(ui):
365 templatekw.keywords['svnrev'] = kwsvnrev
365 templatekw.keywords['svnrev'] = kwsvnrev
366 templatekw.keywords['svnpath'] = kwsvnpath
366 templatekw.keywords['svnpath'] = kwsvnpath
367 templatekw.keywords['svnuuid'] = kwsvnuuid
367 templatekw.keywords['svnuuid'] = kwsvnuuid
368
368
369 # tell hggettext to extract docstrings from these functions:
369 # tell hggettext to extract docstrings from these functions:
370 i18nfunctions = [kwsvnrev, kwsvnpath, kwsvnuuid]
370 i18nfunctions = [kwsvnrev, kwsvnpath, kwsvnuuid]
@@ -1,370 +1,370 b''
1 # discovery.py - protocol changeset discovery functions
1 # discovery.py - protocol changeset discovery functions
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
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 from node import nullid, short
8 from node import nullid, short
9 from i18n import _
9 from i18n import _
10 import util, setdiscovery, treediscovery, phases, obsolete
10 import util, setdiscovery, treediscovery, phases, obsolete
11
11
12 def findcommonincoming(repo, remote, heads=None, force=False):
12 def findcommonincoming(repo, remote, heads=None, force=False):
13 """Return a tuple (common, anyincoming, heads) used to identify the common
13 """Return a tuple (common, anyincoming, heads) used to identify the common
14 subset of nodes between repo and remote.
14 subset of nodes between repo and remote.
15
15
16 "common" is a list of (at least) the heads of the common subset.
16 "common" is a list of (at least) the heads of the common subset.
17 "anyincoming" is testable as a boolean indicating if any nodes are missing
17 "anyincoming" is testable as a boolean indicating if any nodes are missing
18 locally. If remote does not support getbundle, this actually is a list of
18 locally. If remote does not support getbundle, this actually is a list of
19 roots of the nodes that would be incoming, to be supplied to
19 roots of the nodes that would be incoming, to be supplied to
20 changegroupsubset. No code except for pull should be relying on this fact
20 changegroupsubset. No code except for pull should be relying on this fact
21 any longer.
21 any longer.
22 "heads" is either the supplied heads, or else the remote's heads.
22 "heads" is either the supplied heads, or else the remote's heads.
23
23
24 If you pass heads and they are all known locally, the reponse lists justs
24 If you pass heads and they are all known locally, the reponse lists justs
25 these heads in "common" and in "heads".
25 these heads in "common" and in "heads".
26
26
27 Please use findcommonoutgoing to compute the set of outgoing nodes to give
27 Please use findcommonoutgoing to compute the set of outgoing nodes to give
28 extensions a good hook into outgoing.
28 extensions a good hook into outgoing.
29 """
29 """
30
30
31 if not remote.capable('getbundle'):
31 if not remote.capable('getbundle'):
32 return treediscovery.findcommonincoming(repo, remote, heads, force)
32 return treediscovery.findcommonincoming(repo, remote, heads, force)
33
33
34 if heads:
34 if heads:
35 allknown = True
35 allknown = True
36 nm = repo.changelog.nodemap
36 nm = repo.changelog.nodemap
37 for h in heads:
37 for h in heads:
38 if nm.get(h) is None:
38 if nm.get(h) is None:
39 allknown = False
39 allknown = False
40 break
40 break
41 if allknown:
41 if allknown:
42 return (heads, False, heads)
42 return (heads, False, heads)
43
43
44 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
44 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
45 abortwhenunrelated=not force)
45 abortwhenunrelated=not force)
46 common, anyinc, srvheads = res
46 common, anyinc, srvheads = res
47 return (list(common), anyinc, heads or list(srvheads))
47 return (list(common), anyinc, heads or list(srvheads))
48
48
49 class outgoing(object):
49 class outgoing(object):
50 '''Represents the set of nodes present in a local repo but not in a
50 '''Represents the set of nodes present in a local repo but not in a
51 (possibly) remote one.
51 (possibly) remote one.
52
52
53 Members:
53 Members:
54
54
55 missing is a list of all nodes present in local but not in remote.
55 missing is a list of all nodes present in local but not in remote.
56 common is a list of all nodes shared between the two repos.
56 common is a list of all nodes shared between the two repos.
57 excluded is the list of missing changeset that shouldn't be sent remotely.
57 excluded is the list of missing changeset that shouldn't be sent remotely.
58 missingheads is the list of heads of missing.
58 missingheads is the list of heads of missing.
59 commonheads is the list of heads of common.
59 commonheads is the list of heads of common.
60
60
61 The sets are computed on demand from the heads, unless provided upfront
61 The sets are computed on demand from the heads, unless provided upfront
62 by discovery.'''
62 by discovery.'''
63
63
64 def __init__(self, revlog, commonheads, missingheads):
64 def __init__(self, revlog, commonheads, missingheads):
65 self.commonheads = commonheads
65 self.commonheads = commonheads
66 self.missingheads = missingheads
66 self.missingheads = missingheads
67 self._revlog = revlog
67 self._revlog = revlog
68 self._common = None
68 self._common = None
69 self._missing = None
69 self._missing = None
70 self.excluded = []
70 self.excluded = []
71
71
72 def _computecommonmissing(self):
72 def _computecommonmissing(self):
73 sets = self._revlog.findcommonmissing(self.commonheads,
73 sets = self._revlog.findcommonmissing(self.commonheads,
74 self.missingheads)
74 self.missingheads)
75 self._common, self._missing = sets
75 self._common, self._missing = sets
76
76
77 @util.propertycache
77 @util.propertycache
78 def common(self):
78 def common(self):
79 if self._common is None:
79 if self._common is None:
80 self._computecommonmissing()
80 self._computecommonmissing()
81 return self._common
81 return self._common
82
82
83 @util.propertycache
83 @util.propertycache
84 def missing(self):
84 def missing(self):
85 if self._missing is None:
85 if self._missing is None:
86 self._computecommonmissing()
86 self._computecommonmissing()
87 return self._missing
87 return self._missing
88
88
89 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
89 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
90 commoninc=None, portable=False):
90 commoninc=None, portable=False):
91 '''Return an outgoing instance to identify the nodes present in repo but
91 '''Return an outgoing instance to identify the nodes present in repo but
92 not in other.
92 not in other.
93
93
94 If onlyheads is given, only nodes ancestral to nodes in onlyheads
94 If onlyheads is given, only nodes ancestral to nodes in onlyheads
95 (inclusive) are included. If you already know the local repo's heads,
95 (inclusive) are included. If you already know the local repo's heads,
96 passing them in onlyheads is faster than letting them be recomputed here.
96 passing them in onlyheads is faster than letting them be recomputed here.
97
97
98 If commoninc is given, it must the the result of a prior call to
98 If commoninc is given, it must be the result of a prior call to
99 findcommonincoming(repo, other, force) to avoid recomputing it here.
99 findcommonincoming(repo, other, force) to avoid recomputing it here.
100
100
101 If portable is given, compute more conservative common and missingheads,
101 If portable is given, compute more conservative common and missingheads,
102 to make bundles created from the instance more portable.'''
102 to make bundles created from the instance more portable.'''
103 # declare an empty outgoing object to be filled later
103 # declare an empty outgoing object to be filled later
104 og = outgoing(repo.changelog, None, None)
104 og = outgoing(repo.changelog, None, None)
105
105
106 # get common set if not provided
106 # get common set if not provided
107 if commoninc is None:
107 if commoninc is None:
108 commoninc = findcommonincoming(repo, other, force=force)
108 commoninc = findcommonincoming(repo, other, force=force)
109 og.commonheads, _any, _hds = commoninc
109 og.commonheads, _any, _hds = commoninc
110
110
111 # compute outgoing
111 # compute outgoing
112 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
112 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
113 if not mayexclude:
113 if not mayexclude:
114 og.missingheads = onlyheads or repo.heads()
114 og.missingheads = onlyheads or repo.heads()
115 elif onlyheads is None:
115 elif onlyheads is None:
116 # use visible heads as it should be cached
116 # use visible heads as it should be cached
117 og.missingheads = visibleheads(repo)
117 og.missingheads = visibleheads(repo)
118 # extinct changesets are silently ignored
118 # extinct changesets are silently ignored
119 og.excluded = [ctx.node() for ctx in repo.set('secret() or extinct()')]
119 og.excluded = [ctx.node() for ctx in repo.set('secret() or extinct()')]
120 else:
120 else:
121 # compute common, missing and exclude secret stuff
121 # compute common, missing and exclude secret stuff
122 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
122 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
123 og._common, allmissing = sets
123 og._common, allmissing = sets
124 og._missing = missing = []
124 og._missing = missing = []
125 og.excluded = excluded = []
125 og.excluded = excluded = []
126 for node in allmissing:
126 for node in allmissing:
127 ctx = repo[node]
127 ctx = repo[node]
128 if ctx.phase() >= phases.secret or ctx.extinct():
128 if ctx.phase() >= phases.secret or ctx.extinct():
129 excluded.append(node)
129 excluded.append(node)
130 else:
130 else:
131 missing.append(node)
131 missing.append(node)
132 if len(missing) == len(allmissing):
132 if len(missing) == len(allmissing):
133 missingheads = onlyheads
133 missingheads = onlyheads
134 else: # update missing heads
134 else: # update missing heads
135 missingheads = phases.newheads(repo, onlyheads, excluded)
135 missingheads = phases.newheads(repo, onlyheads, excluded)
136 og.missingheads = missingheads
136 og.missingheads = missingheads
137 if portable:
137 if portable:
138 # recompute common and missingheads as if -r<rev> had been given for
138 # recompute common and missingheads as if -r<rev> had been given for
139 # each head of missing, and --base <rev> for each head of the proper
139 # each head of missing, and --base <rev> for each head of the proper
140 # ancestors of missing
140 # ancestors of missing
141 og._computecommonmissing()
141 og._computecommonmissing()
142 cl = repo.changelog
142 cl = repo.changelog
143 missingrevs = set(cl.rev(n) for n in og._missing)
143 missingrevs = set(cl.rev(n) for n in og._missing)
144 og._common = set(cl.ancestors(missingrevs)) - missingrevs
144 og._common = set(cl.ancestors(missingrevs)) - missingrevs
145 commonheads = set(og.commonheads)
145 commonheads = set(og.commonheads)
146 og.missingheads = [h for h in og.missingheads if h not in commonheads]
146 og.missingheads = [h for h in og.missingheads if h not in commonheads]
147
147
148 return og
148 return og
149
149
150 def _headssummary(repo, remote, outgoing):
150 def _headssummary(repo, remote, outgoing):
151 """compute a summary of branch and heads status before and after push
151 """compute a summary of branch and heads status before and after push
152
152
153 return {'branch': ([remoteheads], [newheads], [unsyncedheads])} mapping
153 return {'branch': ([remoteheads], [newheads], [unsyncedheads])} mapping
154
154
155 - branch: the branch name
155 - branch: the branch name
156 - remoteheads: the list of remote heads known locally
156 - remoteheads: the list of remote heads known locally
157 None is the branch is new
157 None is the branch is new
158 - newheads: the new remote heads (known locally) with outgoing pushed
158 - newheads: the new remote heads (known locally) with outgoing pushed
159 - unsyncedheads: the list of remote heads unknown locally.
159 - unsyncedheads: the list of remote heads unknown locally.
160 """
160 """
161 cl = repo.changelog
161 cl = repo.changelog
162 headssum = {}
162 headssum = {}
163 # A. Create set of branches involved in the push.
163 # A. Create set of branches involved in the push.
164 branches = set(repo[n].branch() for n in outgoing.missing)
164 branches = set(repo[n].branch() for n in outgoing.missing)
165 remotemap = remote.branchmap()
165 remotemap = remote.branchmap()
166 newbranches = branches - set(remotemap)
166 newbranches = branches - set(remotemap)
167 branches.difference_update(newbranches)
167 branches.difference_update(newbranches)
168
168
169 # A. register remote heads
169 # A. register remote heads
170 remotebranches = set()
170 remotebranches = set()
171 for branch, heads in remote.branchmap().iteritems():
171 for branch, heads in remote.branchmap().iteritems():
172 remotebranches.add(branch)
172 remotebranches.add(branch)
173 known = []
173 known = []
174 unsynced = []
174 unsynced = []
175 for h in heads:
175 for h in heads:
176 if h in cl.nodemap:
176 if h in cl.nodemap:
177 known.append(h)
177 known.append(h)
178 else:
178 else:
179 unsynced.append(h)
179 unsynced.append(h)
180 headssum[branch] = (known, list(known), unsynced)
180 headssum[branch] = (known, list(known), unsynced)
181 # B. add new branch data
181 # B. add new branch data
182 missingctx = list(repo[n] for n in outgoing.missing)
182 missingctx = list(repo[n] for n in outgoing.missing)
183 touchedbranches = set()
183 touchedbranches = set()
184 for ctx in missingctx:
184 for ctx in missingctx:
185 branch = ctx.branch()
185 branch = ctx.branch()
186 touchedbranches.add(branch)
186 touchedbranches.add(branch)
187 if branch not in headssum:
187 if branch not in headssum:
188 headssum[branch] = (None, [], [])
188 headssum[branch] = (None, [], [])
189
189
190 # C drop data about untouched branches:
190 # C drop data about untouched branches:
191 for branch in remotebranches - touchedbranches:
191 for branch in remotebranches - touchedbranches:
192 del headssum[branch]
192 del headssum[branch]
193
193
194 # D. Update newmap with outgoing changes.
194 # D. Update newmap with outgoing changes.
195 # This will possibly add new heads and remove existing ones.
195 # This will possibly add new heads and remove existing ones.
196 newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems()
196 newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems()
197 if heads[0] is not None)
197 if heads[0] is not None)
198 repo._updatebranchcache(newmap, missingctx)
198 repo._updatebranchcache(newmap, missingctx)
199 for branch, newheads in newmap.iteritems():
199 for branch, newheads in newmap.iteritems():
200 headssum[branch][1][:] = newheads
200 headssum[branch][1][:] = newheads
201 return headssum
201 return headssum
202
202
203 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
203 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
204 """Compute branchmapsummary for repo without branchmap support"""
204 """Compute branchmapsummary for repo without branchmap support"""
205
205
206 cl = repo.changelog
206 cl = repo.changelog
207 # 1-4b. old servers: Check for new topological heads.
207 # 1-4b. old servers: Check for new topological heads.
208 # Construct {old,new}map with branch = None (topological branch).
208 # Construct {old,new}map with branch = None (topological branch).
209 # (code based on _updatebranchcache)
209 # (code based on _updatebranchcache)
210 oldheads = set(h for h in remoteheads if h in cl.nodemap)
210 oldheads = set(h for h in remoteheads if h in cl.nodemap)
211 # all nodes in outgoing.missing are children of either:
211 # all nodes in outgoing.missing are children of either:
212 # - an element of oldheads
212 # - an element of oldheads
213 # - another element of outgoing.missing
213 # - another element of outgoing.missing
214 # - nullrev
214 # - nullrev
215 # This explains why the new head are very simple to compute.
215 # This explains why the new head are very simple to compute.
216 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
216 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
217 newheads = list(c.node() for c in r)
217 newheads = list(c.node() for c in r)
218 unsynced = inc and set([None]) or set()
218 unsynced = inc and set([None]) or set()
219 return {None: (oldheads, newheads, unsynced)}
219 return {None: (oldheads, newheads, unsynced)}
220
220
221 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
221 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
222 """Check that a push won't add any outgoing head
222 """Check that a push won't add any outgoing head
223
223
224 raise Abort error and display ui message as needed.
224 raise Abort error and display ui message as needed.
225 """
225 """
226 # Check for each named branch if we're creating new remote heads.
226 # Check for each named branch if we're creating new remote heads.
227 # To be a remote head after push, node must be either:
227 # To be a remote head after push, node must be either:
228 # - unknown locally
228 # - unknown locally
229 # - a local outgoing head descended from update
229 # - a local outgoing head descended from update
230 # - a remote head that's known locally and not
230 # - a remote head that's known locally and not
231 # ancestral to an outgoing head
231 # ancestral to an outgoing head
232 if remoteheads == [nullid]:
232 if remoteheads == [nullid]:
233 # remote is empty, nothing to check.
233 # remote is empty, nothing to check.
234 return
234 return
235
235
236 if remote.capable('branchmap'):
236 if remote.capable('branchmap'):
237 headssum = _headssummary(repo, remote, outgoing)
237 headssum = _headssummary(repo, remote, outgoing)
238 else:
238 else:
239 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
239 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
240 newbranches = [branch for branch, heads in headssum.iteritems()
240 newbranches = [branch for branch, heads in headssum.iteritems()
241 if heads[0] is None]
241 if heads[0] is None]
242 # 1. Check for new branches on the remote.
242 # 1. Check for new branches on the remote.
243 if newbranches and not newbranch: # new branch requires --new-branch
243 if newbranches and not newbranch: # new branch requires --new-branch
244 branchnames = ', '.join(sorted(newbranches))
244 branchnames = ', '.join(sorted(newbranches))
245 raise util.Abort(_("push creates new remote branches: %s!")
245 raise util.Abort(_("push creates new remote branches: %s!")
246 % branchnames,
246 % branchnames,
247 hint=_("use 'hg push --new-branch' to create"
247 hint=_("use 'hg push --new-branch' to create"
248 " new remote branches"))
248 " new remote branches"))
249
249
250 # 2 compute newly pushed bookmarks. We
250 # 2 compute newly pushed bookmarks. We
251 # we don't warned about bookmarked heads.
251 # we don't warned about bookmarked heads.
252 localbookmarks = repo._bookmarks
252 localbookmarks = repo._bookmarks
253 remotebookmarks = remote.listkeys('bookmarks')
253 remotebookmarks = remote.listkeys('bookmarks')
254 bookmarkedheads = set()
254 bookmarkedheads = set()
255 for bm in localbookmarks:
255 for bm in localbookmarks:
256 rnode = remotebookmarks.get(bm)
256 rnode = remotebookmarks.get(bm)
257 if rnode and rnode in repo:
257 if rnode and rnode in repo:
258 lctx, rctx = repo[bm], repo[rnode]
258 lctx, rctx = repo[bm], repo[rnode]
259 if rctx == lctx.ancestor(rctx):
259 if rctx == lctx.ancestor(rctx):
260 bookmarkedheads.add(lctx.node())
260 bookmarkedheads.add(lctx.node())
261
261
262 # 3. Check for new heads.
262 # 3. Check for new heads.
263 # If there are more heads after the push than before, a suitable
263 # If there are more heads after the push than before, a suitable
264 # error message, depending on unsynced status, is displayed.
264 # error message, depending on unsynced status, is displayed.
265 error = None
265 error = None
266 unsynced = False
266 unsynced = False
267 allmissing = set(outgoing.missing)
267 allmissing = set(outgoing.missing)
268 for branch, heads in headssum.iteritems():
268 for branch, heads in headssum.iteritems():
269 if heads[0] is None:
269 if heads[0] is None:
270 # Maybe we should abort if we push more that one head
270 # Maybe we should abort if we push more that one head
271 # for new branches ?
271 # for new branches ?
272 continue
272 continue
273 if heads[2]:
273 if heads[2]:
274 unsynced = True
274 unsynced = True
275 oldhs = set(heads[0])
275 oldhs = set(heads[0])
276 candidate_newhs = set(heads[1])
276 candidate_newhs = set(heads[1])
277 # add unsynced data
277 # add unsynced data
278 oldhs.update(heads[2])
278 oldhs.update(heads[2])
279 candidate_newhs.update(heads[2])
279 candidate_newhs.update(heads[2])
280 dhs = None
280 dhs = None
281 if repo.obsstore:
281 if repo.obsstore:
282 # remove future heads which are actually obsolete by another
282 # remove future heads which are actually obsolete by another
283 # pushed element:
283 # pushed element:
284 #
284 #
285 # XXX There is several case this case does not handle properly
285 # XXX There is several case this case does not handle properly
286 #
286 #
287 # (1) if <nh> is public, it won't be affected by obsolete marker
287 # (1) if <nh> is public, it won't be affected by obsolete marker
288 # and a new is created
288 # and a new is created
289 #
289 #
290 # (2) if the new heads have ancestors which are not obsolete and
290 # (2) if the new heads have ancestors which are not obsolete and
291 # not ancestors of any other heads we will have a new head too.
291 # not ancestors of any other heads we will have a new head too.
292 #
292 #
293 # This two case will be easy to handle for know changeset but much
293 # This two case will be easy to handle for know changeset but much
294 # more tricky for unsynced changes.
294 # more tricky for unsynced changes.
295 newhs = set()
295 newhs = set()
296 for nh in candidate_newhs:
296 for nh in candidate_newhs:
297 for suc in obsolete.anysuccessors(repo.obsstore, nh):
297 for suc in obsolete.anysuccessors(repo.obsstore, nh):
298 if suc != nh and suc in allmissing:
298 if suc != nh and suc in allmissing:
299 break
299 break
300 else:
300 else:
301 newhs.add(nh)
301 newhs.add(nh)
302 else:
302 else:
303 newhs = candidate_newhs
303 newhs = candidate_newhs
304 if len(newhs) > len(oldhs):
304 if len(newhs) > len(oldhs):
305 # strip updates to existing remote heads from the new heads list
305 # strip updates to existing remote heads from the new heads list
306 dhs = list(newhs - bookmarkedheads - oldhs)
306 dhs = list(newhs - bookmarkedheads - oldhs)
307 if dhs:
307 if dhs:
308 if error is None:
308 if error is None:
309 if branch not in ('default', None):
309 if branch not in ('default', None):
310 error = _("push creates new remote head %s "
310 error = _("push creates new remote head %s "
311 "on branch '%s'!") % (short(dhs[0]), branch)
311 "on branch '%s'!") % (short(dhs[0]), branch)
312 else:
312 else:
313 error = _("push creates new remote head %s!"
313 error = _("push creates new remote head %s!"
314 ) % short(dhs[0])
314 ) % short(dhs[0])
315 if heads[2]: # unsynced
315 if heads[2]: # unsynced
316 hint = _("you should pull and merge or "
316 hint = _("you should pull and merge or "
317 "use push -f to force")
317 "use push -f to force")
318 else:
318 else:
319 hint = _("did you forget to merge? "
319 hint = _("did you forget to merge? "
320 "use push -f to force")
320 "use push -f to force")
321 if branch is not None:
321 if branch is not None:
322 repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
322 repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
323 for h in dhs:
323 for h in dhs:
324 repo.ui.note(_("new remote head %s\n") % short(h))
324 repo.ui.note(_("new remote head %s\n") % short(h))
325 if error:
325 if error:
326 raise util.Abort(error, hint=hint)
326 raise util.Abort(error, hint=hint)
327
327
328 # 6. Check for unsynced changes on involved branches.
328 # 6. Check for unsynced changes on involved branches.
329 if unsynced:
329 if unsynced:
330 repo.ui.warn(_("note: unsynced remote changes!\n"))
330 repo.ui.warn(_("note: unsynced remote changes!\n"))
331
331
332 def visibleheads(repo):
332 def visibleheads(repo):
333 """return the set of visible head of this repo"""
333 """return the set of visible head of this repo"""
334 # XXX we want a cache on this
334 # XXX we want a cache on this
335 sroots = repo._phasecache.phaseroots[phases.secret]
335 sroots = repo._phasecache.phaseroots[phases.secret]
336 if sroots or repo.obsstore:
336 if sroots or repo.obsstore:
337 # XXX very slow revset. storing heads or secret "boundary"
337 # XXX very slow revset. storing heads or secret "boundary"
338 # would help.
338 # would help.
339 revset = repo.set('heads(not (%ln:: + extinct()))', sroots)
339 revset = repo.set('heads(not (%ln:: + extinct()))', sroots)
340
340
341 vheads = [ctx.node() for ctx in revset]
341 vheads = [ctx.node() for ctx in revset]
342 if not vheads:
342 if not vheads:
343 vheads.append(nullid)
343 vheads.append(nullid)
344 else:
344 else:
345 vheads = repo.heads()
345 vheads = repo.heads()
346 return vheads
346 return vheads
347
347
348
348
349 def visiblebranchmap(repo):
349 def visiblebranchmap(repo):
350 """return a branchmap for the visible set"""
350 """return a branchmap for the visible set"""
351 # XXX Recomputing this data on the fly is very slow. We should build a
351 # XXX Recomputing this data on the fly is very slow. We should build a
352 # XXX cached version while computin the standard branchmap version.
352 # XXX cached version while computin the standard branchmap version.
353 sroots = repo._phasecache.phaseroots[phases.secret]
353 sroots = repo._phasecache.phaseroots[phases.secret]
354 if sroots or repo.obsstore:
354 if sroots or repo.obsstore:
355 vbranchmap = {}
355 vbranchmap = {}
356 for branch, nodes in repo.branchmap().iteritems():
356 for branch, nodes in repo.branchmap().iteritems():
357 # search for secret heads.
357 # search for secret heads.
358 for n in nodes:
358 for n in nodes:
359 if repo[n].phase() >= phases.secret:
359 if repo[n].phase() >= phases.secret:
360 nodes = None
360 nodes = None
361 break
361 break
362 # if secret heads were found we must compute them again
362 # if secret heads were found we must compute them again
363 if nodes is None:
363 if nodes is None:
364 s = repo.set('heads(branch(%s) - secret() - extinct())',
364 s = repo.set('heads(branch(%s) - secret() - extinct())',
365 branch)
365 branch)
366 nodes = [c.node() for c in s]
366 nodes = [c.node() for c in s]
367 vbranchmap[branch] = nodes
367 vbranchmap[branch] = nodes
368 else:
368 else:
369 vbranchmap = repo.branchmap()
369 vbranchmap = repo.branchmap()
370 return vbranchmap
370 return vbranchmap
@@ -1,1437 +1,1437 b''
1 The Mercurial system uses a set of configuration files to control
1 The Mercurial system uses a set of configuration files to control
2 aspects of its behavior.
2 aspects of its behavior.
3
3
4 The configuration files use a simple ini-file format. A configuration
4 The configuration files use a simple ini-file format. A configuration
5 file consists of sections, led by a ``[section]`` header and followed
5 file consists of sections, led by a ``[section]`` header and followed
6 by ``name = value`` entries::
6 by ``name = value`` entries::
7
7
8 [ui]
8 [ui]
9 username = Firstname Lastname <firstname.lastname@example.net>
9 username = Firstname Lastname <firstname.lastname@example.net>
10 verbose = True
10 verbose = True
11
11
12 The above entries will be referred to as ``ui.username`` and
12 The above entries will be referred to as ``ui.username`` and
13 ``ui.verbose``, respectively. See the Syntax section below.
13 ``ui.verbose``, respectively. See the Syntax section below.
14
14
15 Files
15 Files
16 -----
16 -----
17
17
18 Mercurial reads configuration data from several files, if they exist.
18 Mercurial reads configuration data from several files, if they exist.
19 These files do not exist by default and you will have to create the
19 These files do not exist by default and you will have to create the
20 appropriate configuration files yourself: global configuration like
20 appropriate configuration files yourself: global configuration like
21 the username setting is typically put into
21 the username setting is typically put into
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
24
24
25 The names of these files depend on the system on which Mercurial is
25 The names of these files depend on the system on which Mercurial is
26 installed. ``*.rc`` files from a single directory are read in
26 installed. ``*.rc`` files from a single directory are read in
27 alphabetical order, later ones overriding earlier ones. Where multiple
27 alphabetical order, later ones overriding earlier ones. Where multiple
28 paths are given below, settings from earlier paths override later
28 paths are given below, settings from earlier paths override later
29 ones.
29 ones.
30
30
31 | (All) ``<repo>/.hg/hgrc``
31 | (All) ``<repo>/.hg/hgrc``
32
32
33 Per-repository configuration options that only apply in a
33 Per-repository configuration options that only apply in a
34 particular repository. This file is not version-controlled, and
34 particular repository. This file is not version-controlled, and
35 will not get transferred during a "clone" operation. Options in
35 will not get transferred during a "clone" operation. Options in
36 this file override options in all other configuration files. On
36 this file override options in all other configuration files. On
37 Plan 9 and Unix, most of this file will be ignored if it doesn't
37 Plan 9 and Unix, most of this file will be ignored if it doesn't
38 belong to a trusted user or to a trusted group. See the documentation
38 belong to a trusted user or to a trusted group. See the documentation
39 for the ``[trusted]`` section below for more details.
39 for the ``[trusted]`` section below for more details.
40
40
41 | (Plan 9) ``$home/lib/hgrc``
41 | (Plan 9) ``$home/lib/hgrc``
42 | (Unix) ``$HOME/.hgrc``
42 | (Unix) ``$HOME/.hgrc``
43 | (Windows) ``%USERPROFILE%\.hgrc``
43 | (Windows) ``%USERPROFILE%\.hgrc``
44 | (Windows) ``%USERPROFILE%\Mercurial.ini``
44 | (Windows) ``%USERPROFILE%\Mercurial.ini``
45 | (Windows) ``%HOME%\.hgrc``
45 | (Windows) ``%HOME%\.hgrc``
46 | (Windows) ``%HOME%\Mercurial.ini``
46 | (Windows) ``%HOME%\Mercurial.ini``
47
47
48 Per-user configuration file(s), for the user running Mercurial. On
48 Per-user configuration file(s), for the user running Mercurial. On
49 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
49 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
50 files apply to all Mercurial commands executed by this user in any
50 files apply to all Mercurial commands executed by this user in any
51 directory. Options in these files override per-system and per-installation
51 directory. Options in these files override per-system and per-installation
52 options.
52 options.
53
53
54 | (Plan 9) ``/lib/mercurial/hgrc``
54 | (Plan 9) ``/lib/mercurial/hgrc``
55 | (Plan 9) ``/lib/mercurial/hgrc.d/*.rc``
55 | (Plan 9) ``/lib/mercurial/hgrc.d/*.rc``
56 | (Unix) ``/etc/mercurial/hgrc``
56 | (Unix) ``/etc/mercurial/hgrc``
57 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
57 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
58
58
59 Per-system configuration files, for the system on which Mercurial
59 Per-system configuration files, for the system on which Mercurial
60 is running. Options in these files apply to all Mercurial commands
60 is running. Options in these files apply to all Mercurial commands
61 executed by any user in any directory. Options in these files
61 executed by any user in any directory. Options in these files
62 override per-installation options.
62 override per-installation options.
63
63
64 | (Plan 9) ``<install-root>/lib/mercurial/hgrc``
64 | (Plan 9) ``<install-root>/lib/mercurial/hgrc``
65 | (Plan 9) ``<install-root>/lib/mercurial/hgrc.d/*.rc``
65 | (Plan 9) ``<install-root>/lib/mercurial/hgrc.d/*.rc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc``
67 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
67 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
68
68
69 Per-installation configuration files, searched for in the
69 Per-installation configuration files, searched for in the
70 directory where Mercurial is installed. ``<install-root>`` is the
70 directory where Mercurial is installed. ``<install-root>`` is the
71 parent directory of the **hg** executable (or symlink) being run. For
71 parent directory of the **hg** executable (or symlink) being run. For
72 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
72 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
73 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
73 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
74 to all Mercurial commands executed by any user in any directory.
74 to all Mercurial commands executed by any user in any directory.
75
75
76 | (Windows) ``<install-dir>\Mercurial.ini`` **or**
76 | (Windows) ``<install-dir>\Mercurial.ini`` **or**
77 | (Windows) ``<install-dir>\hgrc.d\*.rc`` **or**
77 | (Windows) ``<install-dir>\hgrc.d\*.rc`` **or**
78 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
78 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
79
79
80 Per-installation/system configuration files, for the system on
80 Per-installation/system configuration files, for the system on
81 which Mercurial is running. Options in these files apply to all
81 which Mercurial is running. Options in these files apply to all
82 Mercurial commands executed by any user in any directory. Registry
82 Mercurial commands executed by any user in any directory. Registry
83 keys contain PATH-like strings, every part of which must reference
83 keys contain PATH-like strings, every part of which must reference
84 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
84 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
85 be read. Mercurial checks each of these locations in the specified
85 be read. Mercurial checks each of these locations in the specified
86 order until one or more configuration files are detected.
86 order until one or more configuration files are detected.
87
87
88 Syntax
88 Syntax
89 ------
89 ------
90
90
91 A configuration file consists of sections, led by a ``[section]`` header
91 A configuration file consists of sections, led by a ``[section]`` header
92 and followed by ``name = value`` entries (sometimes called
92 and followed by ``name = value`` entries (sometimes called
93 ``configuration keys``)::
93 ``configuration keys``)::
94
94
95 [spam]
95 [spam]
96 eggs=ham
96 eggs=ham
97 green=
97 green=
98 eggs
98 eggs
99
99
100 Each line contains one entry. If the lines that follow are indented,
100 Each line contains one entry. If the lines that follow are indented,
101 they are treated as continuations of that entry. Leading whitespace is
101 they are treated as continuations of that entry. Leading whitespace is
102 removed from values. Empty lines are skipped. Lines beginning with
102 removed from values. Empty lines are skipped. Lines beginning with
103 ``#`` or ``;`` are ignored and may be used to provide comments.
103 ``#`` or ``;`` are ignored and may be used to provide comments.
104
104
105 Configuration keys can be set multiple times, in which case Mercurial
105 Configuration keys can be set multiple times, in which case Mercurial
106 will use the value that was configured last. As an example::
106 will use the value that was configured last. As an example::
107
107
108 [spam]
108 [spam]
109 eggs=large
109 eggs=large
110 ham=serrano
110 ham=serrano
111 eggs=small
111 eggs=small
112
112
113 This would set the configuration key named ``eggs`` to ``small``.
113 This would set the configuration key named ``eggs`` to ``small``.
114
114
115 It is also possible to define a section multiple times. A section can
115 It is also possible to define a section multiple times. A section can
116 be redefined on the same and/or on different configuration files. For
116 be redefined on the same and/or on different configuration files. For
117 example::
117 example::
118
118
119 [foo]
119 [foo]
120 eggs=large
120 eggs=large
121 ham=serrano
121 ham=serrano
122 eggs=small
122 eggs=small
123
123
124 [bar]
124 [bar]
125 eggs=ham
125 eggs=ham
126 green=
126 green=
127 eggs
127 eggs
128
128
129 [foo]
129 [foo]
130 ham=prosciutto
130 ham=prosciutto
131 eggs=medium
131 eggs=medium
132 bread=toasted
132 bread=toasted
133
133
134 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
134 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
135 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
135 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
136 respectively. As you can see there only thing that matters is the last
136 respectively. As you can see there only thing that matters is the last
137 value that was set for each of the configuration keys.
137 value that was set for each of the configuration keys.
138
138
139 If a configuration key is set multiple times in different
139 If a configuration key is set multiple times in different
140 configuration files the final value will depend on the order in which
140 configuration files the final value will depend on the order in which
141 the different configuration files are read, with settings from earlier
141 the different configuration files are read, with settings from earlier
142 paths overriding later ones as described on the ``Files`` section
142 paths overriding later ones as described on the ``Files`` section
143 above.
143 above.
144
144
145 A line of the form ``%include file`` will include ``file`` into the
145 A line of the form ``%include file`` will include ``file`` into the
146 current configuration file. The inclusion is recursive, which means
146 current configuration file. The inclusion is recursive, which means
147 that included files can include other files. Filenames are relative to
147 that included files can include other files. Filenames are relative to
148 the configuration file in which the ``%include`` directive is found.
148 the configuration file in which the ``%include`` directive is found.
149 Environment variables and ``~user`` constructs are expanded in
149 Environment variables and ``~user`` constructs are expanded in
150 ``file``. This lets you do something like::
150 ``file``. This lets you do something like::
151
151
152 %include ~/.hgrc.d/$HOST.rc
152 %include ~/.hgrc.d/$HOST.rc
153
153
154 to include a different configuration file on each computer you use.
154 to include a different configuration file on each computer you use.
155
155
156 A line with ``%unset name`` will remove ``name`` from the current
156 A line with ``%unset name`` will remove ``name`` from the current
157 section, if it has been set previously.
157 section, if it has been set previously.
158
158
159 The values are either free-form text strings, lists of text strings,
159 The values are either free-form text strings, lists of text strings,
160 or Boolean values. Boolean values can be set to true using any of "1",
160 or Boolean values. Boolean values can be set to true using any of "1",
161 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
161 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
162 (all case insensitive).
162 (all case insensitive).
163
163
164 List values are separated by whitespace or comma, except when values are
164 List values are separated by whitespace or comma, except when values are
165 placed in double quotation marks::
165 placed in double quotation marks::
166
166
167 allow_read = "John Doe, PhD", brian, betty
167 allow_read = "John Doe, PhD", brian, betty
168
168
169 Quotation marks can be escaped by prefixing them with a backslash. Only
169 Quotation marks can be escaped by prefixing them with a backslash. Only
170 quotation marks at the beginning of a word is counted as a quotation
170 quotation marks at the beginning of a word is counted as a quotation
171 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
171 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
172
172
173 Sections
173 Sections
174 --------
174 --------
175
175
176 This section describes the different sections that may appear in a
176 This section describes the different sections that may appear in a
177 Mercurial configuration file, the purpose of each section, its possible
177 Mercurial configuration file, the purpose of each section, its possible
178 keys, and their possible values.
178 keys, and their possible values.
179
179
180 ``alias``
180 ``alias``
181 """""""""
181 """""""""
182
182
183 Defines command aliases.
183 Defines command aliases.
184 Aliases allow you to define your own commands in terms of other
184 Aliases allow you to define your own commands in terms of other
185 commands (or aliases), optionally including arguments. Positional
185 commands (or aliases), optionally including arguments. Positional
186 arguments in the form of ``$1``, ``$2``, etc in the alias definition
186 arguments in the form of ``$1``, ``$2``, etc in the alias definition
187 are expanded by Mercurial before execution. Positional arguments not
187 are expanded by Mercurial before execution. Positional arguments not
188 already used by ``$N`` in the definition are put at the end of the
188 already used by ``$N`` in the definition are put at the end of the
189 command to be executed.
189 command to be executed.
190
190
191 Alias definitions consist of lines of the form::
191 Alias definitions consist of lines of the form::
192
192
193 <alias> = <command> [<argument>]...
193 <alias> = <command> [<argument>]...
194
194
195 For example, this definition::
195 For example, this definition::
196
196
197 latest = log --limit 5
197 latest = log --limit 5
198
198
199 creates a new command ``latest`` that shows only the five most recent
199 creates a new command ``latest`` that shows only the five most recent
200 changesets. You can define subsequent aliases using earlier ones::
200 changesets. You can define subsequent aliases using earlier ones::
201
201
202 stable5 = latest -b stable
202 stable5 = latest -b stable
203
203
204 .. note:: It is possible to create aliases with the same names as
204 .. note:: It is possible to create aliases with the same names as
205 existing commands, which will then override the original
205 existing commands, which will then override the original
206 definitions. This is almost always a bad idea!
206 definitions. This is almost always a bad idea!
207
207
208 An alias can start with an exclamation point (``!``) to make it a
208 An alias can start with an exclamation point (``!``) to make it a
209 shell alias. A shell alias is executed with the shell and will let you
209 shell alias. A shell alias is executed with the shell and will let you
210 run arbitrary commands. As an example, ::
210 run arbitrary commands. As an example, ::
211
211
212 echo = !echo $@
212 echo = !echo $@
213
213
214 will let you do ``hg echo foo`` to have ``foo`` printed in your
214 will let you do ``hg echo foo`` to have ``foo`` printed in your
215 terminal. A better example might be::
215 terminal. A better example might be::
216
216
217 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
217 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
218
218
219 which will make ``hg purge`` delete all unknown files in the
219 which will make ``hg purge`` delete all unknown files in the
220 repository in the same manner as the purge extension.
220 repository in the same manner as the purge extension.
221
221
222 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
222 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
223 expand to the command arguments. Unmatched arguments are
223 expand to the command arguments. Unmatched arguments are
224 removed. ``$0`` expands to the alias name and ``$@`` expands to all
224 removed. ``$0`` expands to the alias name and ``$@`` expands to all
225 arguments separated by a space. These expansions happen before the
225 arguments separated by a space. These expansions happen before the
226 command is passed to the shell.
226 command is passed to the shell.
227
227
228 Shell aliases are executed in an environment where ``$HG`` expands to
228 Shell aliases are executed in an environment where ``$HG`` expands to
229 the path of the Mercurial that was used to execute the alias. This is
229 the path of the Mercurial that was used to execute the alias. This is
230 useful when you want to call further Mercurial commands in a shell
230 useful when you want to call further Mercurial commands in a shell
231 alias, as was done above for the purge alias. In addition,
231 alias, as was done above for the purge alias. In addition,
232 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
232 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
233 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
233 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
234
234
235 .. note:: Some global configuration options such as ``-R`` are
235 .. note:: Some global configuration options such as ``-R`` are
236 processed before shell aliases and will thus not be passed to
236 processed before shell aliases and will thus not be passed to
237 aliases.
237 aliases.
238
238
239
239
240 ``annotate``
240 ``annotate``
241 """"""""""""
241 """"""""""""
242
242
243 Settings used when displaying file annotations. All values are
243 Settings used when displaying file annotations. All values are
244 Booleans and default to False. See ``diff`` section for related
244 Booleans and default to False. See ``diff`` section for related
245 options for the diff command.
245 options for the diff command.
246
246
247 ``ignorews``
247 ``ignorews``
248 Ignore white space when comparing lines.
248 Ignore white space when comparing lines.
249
249
250 ``ignorewsamount``
250 ``ignorewsamount``
251 Ignore changes in the amount of white space.
251 Ignore changes in the amount of white space.
252
252
253 ``ignoreblanklines``
253 ``ignoreblanklines``
254 Ignore changes whose lines are all blank.
254 Ignore changes whose lines are all blank.
255
255
256
256
257 ``auth``
257 ``auth``
258 """"""""
258 """"""""
259
259
260 Authentication credentials for HTTP authentication. This section
260 Authentication credentials for HTTP authentication. This section
261 allows you to store usernames and passwords for use when logging
261 allows you to store usernames and passwords for use when logging
262 *into* HTTP servers. See the ``[web]`` configuration section if
262 *into* HTTP servers. See the ``[web]`` configuration section if
263 you want to configure *who* can login to your HTTP server.
263 you want to configure *who* can login to your HTTP server.
264
264
265 Each line has the following format::
265 Each line has the following format::
266
266
267 <name>.<argument> = <value>
267 <name>.<argument> = <value>
268
268
269 where ``<name>`` is used to group arguments into authentication
269 where ``<name>`` is used to group arguments into authentication
270 entries. Example::
270 entries. Example::
271
271
272 foo.prefix = hg.intevation.org/mercurial
272 foo.prefix = hg.intevation.org/mercurial
273 foo.username = foo
273 foo.username = foo
274 foo.password = bar
274 foo.password = bar
275 foo.schemes = http https
275 foo.schemes = http https
276
276
277 bar.prefix = secure.example.org
277 bar.prefix = secure.example.org
278 bar.key = path/to/file.key
278 bar.key = path/to/file.key
279 bar.cert = path/to/file.cert
279 bar.cert = path/to/file.cert
280 bar.schemes = https
280 bar.schemes = https
281
281
282 Supported arguments:
282 Supported arguments:
283
283
284 ``prefix``
284 ``prefix``
285 Either ``*`` or a URI prefix with or without the scheme part.
285 Either ``*`` or a URI prefix with or without the scheme part.
286 The authentication entry with the longest matching prefix is used
286 The authentication entry with the longest matching prefix is used
287 (where ``*`` matches everything and counts as a match of length
287 (where ``*`` matches everything and counts as a match of length
288 1). If the prefix doesn't include a scheme, the match is performed
288 1). If the prefix doesn't include a scheme, the match is performed
289 against the URI with its scheme stripped as well, and the schemes
289 against the URI with its scheme stripped as well, and the schemes
290 argument, q.v., is then subsequently consulted.
290 argument, q.v., is then subsequently consulted.
291
291
292 ``username``
292 ``username``
293 Optional. Username to authenticate with. If not given, and the
293 Optional. Username to authenticate with. If not given, and the
294 remote site requires basic or digest authentication, the user will
294 remote site requires basic or digest authentication, the user will
295 be prompted for it. Environment variables are expanded in the
295 be prompted for it. Environment variables are expanded in the
296 username letting you do ``foo.username = $USER``. If the URI
296 username letting you do ``foo.username = $USER``. If the URI
297 includes a username, only ``[auth]`` entries with a matching
297 includes a username, only ``[auth]`` entries with a matching
298 username or without a username will be considered.
298 username or without a username will be considered.
299
299
300 ``password``
300 ``password``
301 Optional. Password to authenticate with. If not given, and the
301 Optional. Password to authenticate with. If not given, and the
302 remote site requires basic or digest authentication, the user
302 remote site requires basic or digest authentication, the user
303 will be prompted for it.
303 will be prompted for it.
304
304
305 ``key``
305 ``key``
306 Optional. PEM encoded client certificate key file. Environment
306 Optional. PEM encoded client certificate key file. Environment
307 variables are expanded in the filename.
307 variables are expanded in the filename.
308
308
309 ``cert``
309 ``cert``
310 Optional. PEM encoded client certificate chain file. Environment
310 Optional. PEM encoded client certificate chain file. Environment
311 variables are expanded in the filename.
311 variables are expanded in the filename.
312
312
313 ``schemes``
313 ``schemes``
314 Optional. Space separated list of URI schemes to use this
314 Optional. Space separated list of URI schemes to use this
315 authentication entry with. Only used if the prefix doesn't include
315 authentication entry with. Only used if the prefix doesn't include
316 a scheme. Supported schemes are http and https. They will match
316 a scheme. Supported schemes are http and https. They will match
317 static-http and static-https respectively, as well.
317 static-http and static-https respectively, as well.
318 Default: https.
318 Default: https.
319
319
320 If no suitable authentication entry is found, the user is prompted
320 If no suitable authentication entry is found, the user is prompted
321 for credentials as usual if required by the remote.
321 for credentials as usual if required by the remote.
322
322
323
323
324 ``decode/encode``
324 ``decode/encode``
325 """""""""""""""""
325 """""""""""""""""
326
326
327 Filters for transforming files on checkout/checkin. This would
327 Filters for transforming files on checkout/checkin. This would
328 typically be used for newline processing or other
328 typically be used for newline processing or other
329 localization/canonicalization of files.
329 localization/canonicalization of files.
330
330
331 Filters consist of a filter pattern followed by a filter command.
331 Filters consist of a filter pattern followed by a filter command.
332 Filter patterns are globs by default, rooted at the repository root.
332 Filter patterns are globs by default, rooted at the repository root.
333 For example, to match any file ending in ``.txt`` in the root
333 For example, to match any file ending in ``.txt`` in the root
334 directory only, use the pattern ``*.txt``. To match any file ending
334 directory only, use the pattern ``*.txt``. To match any file ending
335 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
335 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
336 For each file only the first matching filter applies.
336 For each file only the first matching filter applies.
337
337
338 The filter command can start with a specifier, either ``pipe:`` or
338 The filter command can start with a specifier, either ``pipe:`` or
339 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
339 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
340
340
341 A ``pipe:`` command must accept data on stdin and return the transformed
341 A ``pipe:`` command must accept data on stdin and return the transformed
342 data on stdout.
342 data on stdout.
343
343
344 Pipe example::
344 Pipe example::
345
345
346 [encode]
346 [encode]
347 # uncompress gzip files on checkin to improve delta compression
347 # uncompress gzip files on checkin to improve delta compression
348 # note: not necessarily a good idea, just an example
348 # note: not necessarily a good idea, just an example
349 *.gz = pipe: gunzip
349 *.gz = pipe: gunzip
350
350
351 [decode]
351 [decode]
352 # recompress gzip files when writing them to the working dir (we
352 # recompress gzip files when writing them to the working dir (we
353 # can safely omit "pipe:", because it's the default)
353 # can safely omit "pipe:", because it's the default)
354 *.gz = gzip
354 *.gz = gzip
355
355
356 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
356 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
357 with the name of a temporary file that contains the data to be
357 with the name of a temporary file that contains the data to be
358 filtered by the command. The string ``OUTFILE`` is replaced with the name
358 filtered by the command. The string ``OUTFILE`` is replaced with the name
359 of an empty temporary file, where the filtered data must be written by
359 of an empty temporary file, where the filtered data must be written by
360 the command.
360 the command.
361
361
362 .. note:: The tempfile mechanism is recommended for Windows systems,
362 .. note:: The tempfile mechanism is recommended for Windows systems,
363 where the standard shell I/O redirection operators often have
363 where the standard shell I/O redirection operators often have
364 strange effects and may corrupt the contents of your files.
364 strange effects and may corrupt the contents of your files.
365
365
366 This filter mechanism is used internally by the ``eol`` extension to
366 This filter mechanism is used internally by the ``eol`` extension to
367 translate line ending characters between Windows (CRLF) and Unix (LF)
367 translate line ending characters between Windows (CRLF) and Unix (LF)
368 format. We suggest you use the ``eol`` extension for convenience.
368 format. We suggest you use the ``eol`` extension for convenience.
369
369
370
370
371 ``defaults``
371 ``defaults``
372 """"""""""""
372 """"""""""""
373
373
374 (defaults are deprecated. Don't use them. Use aliases instead)
374 (defaults are deprecated. Don't use them. Use aliases instead)
375
375
376 Use the ``[defaults]`` section to define command defaults, i.e. the
376 Use the ``[defaults]`` section to define command defaults, i.e. the
377 default options/arguments to pass to the specified commands.
377 default options/arguments to pass to the specified commands.
378
378
379 The following example makes :hg:`log` run in verbose mode, and
379 The following example makes :hg:`log` run in verbose mode, and
380 :hg:`status` show only the modified files, by default::
380 :hg:`status` show only the modified files, by default::
381
381
382 [defaults]
382 [defaults]
383 log = -v
383 log = -v
384 status = -m
384 status = -m
385
385
386 The actual commands, instead of their aliases, must be used when
386 The actual commands, instead of their aliases, must be used when
387 defining command defaults. The command defaults will also be applied
387 defining command defaults. The command defaults will also be applied
388 to the aliases of the commands defined.
388 to the aliases of the commands defined.
389
389
390
390
391 ``diff``
391 ``diff``
392 """"""""
392 """"""""
393
393
394 Settings used when displaying diffs. Everything except for ``unified``
394 Settings used when displaying diffs. Everything except for ``unified``
395 is a Boolean and defaults to False. See ``annotate`` section for
395 is a Boolean and defaults to False. See ``annotate`` section for
396 related options for the annotate command.
396 related options for the annotate command.
397
397
398 ``git``
398 ``git``
399 Use git extended diff format.
399 Use git extended diff format.
400
400
401 ``nodates``
401 ``nodates``
402 Don't include dates in diff headers.
402 Don't include dates in diff headers.
403
403
404 ``showfunc``
404 ``showfunc``
405 Show which function each change is in.
405 Show which function each change is in.
406
406
407 ``ignorews``
407 ``ignorews``
408 Ignore white space when comparing lines.
408 Ignore white space when comparing lines.
409
409
410 ``ignorewsamount``
410 ``ignorewsamount``
411 Ignore changes in the amount of white space.
411 Ignore changes in the amount of white space.
412
412
413 ``ignoreblanklines``
413 ``ignoreblanklines``
414 Ignore changes whose lines are all blank.
414 Ignore changes whose lines are all blank.
415
415
416 ``unified``
416 ``unified``
417 Number of lines of context to show.
417 Number of lines of context to show.
418
418
419 ``email``
419 ``email``
420 """""""""
420 """""""""
421
421
422 Settings for extensions that send email messages.
422 Settings for extensions that send email messages.
423
423
424 ``from``
424 ``from``
425 Optional. Email address to use in "From" header and SMTP envelope
425 Optional. Email address to use in "From" header and SMTP envelope
426 of outgoing messages.
426 of outgoing messages.
427
427
428 ``to``
428 ``to``
429 Optional. Comma-separated list of recipients' email addresses.
429 Optional. Comma-separated list of recipients' email addresses.
430
430
431 ``cc``
431 ``cc``
432 Optional. Comma-separated list of carbon copy recipients'
432 Optional. Comma-separated list of carbon copy recipients'
433 email addresses.
433 email addresses.
434
434
435 ``bcc``
435 ``bcc``
436 Optional. Comma-separated list of blind carbon copy recipients'
436 Optional. Comma-separated list of blind carbon copy recipients'
437 email addresses.
437 email addresses.
438
438
439 ``method``
439 ``method``
440 Optional. Method to use to send email messages. If value is ``smtp``
440 Optional. Method to use to send email messages. If value is ``smtp``
441 (default), use SMTP (see the ``[smtp]`` section for configuration).
441 (default), use SMTP (see the ``[smtp]`` section for configuration).
442 Otherwise, use as name of program to run that acts like sendmail
442 Otherwise, use as name of program to run that acts like sendmail
443 (takes ``-f`` option for sender, list of recipients on command line,
443 (takes ``-f`` option for sender, list of recipients on command line,
444 message on stdin). Normally, setting this to ``sendmail`` or
444 message on stdin). Normally, setting this to ``sendmail`` or
445 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
445 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
446
446
447 ``charsets``
447 ``charsets``
448 Optional. Comma-separated list of character sets considered
448 Optional. Comma-separated list of character sets considered
449 convenient for recipients. Addresses, headers, and parts not
449 convenient for recipients. Addresses, headers, and parts not
450 containing patches of outgoing messages will be encoded in the
450 containing patches of outgoing messages will be encoded in the
451 first character set to which conversion from local encoding
451 first character set to which conversion from local encoding
452 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
452 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
453 conversion fails, the text in question is sent as is. Defaults to
453 conversion fails, the text in question is sent as is. Defaults to
454 empty (explicit) list.
454 empty (explicit) list.
455
455
456 Order of outgoing email character sets:
456 Order of outgoing email character sets:
457
457
458 1. ``us-ascii``: always first, regardless of settings
458 1. ``us-ascii``: always first, regardless of settings
459 2. ``email.charsets``: in order given by user
459 2. ``email.charsets``: in order given by user
460 3. ``ui.fallbackencoding``: if not in email.charsets
460 3. ``ui.fallbackencoding``: if not in email.charsets
461 4. ``$HGENCODING``: if not in email.charsets
461 4. ``$HGENCODING``: if not in email.charsets
462 5. ``utf-8``: always last, regardless of settings
462 5. ``utf-8``: always last, regardless of settings
463
463
464 Email example::
464 Email example::
465
465
466 [email]
466 [email]
467 from = Joseph User <joe.user@example.com>
467 from = Joseph User <joe.user@example.com>
468 method = /usr/sbin/sendmail
468 method = /usr/sbin/sendmail
469 # charsets for western Europeans
469 # charsets for western Europeans
470 # us-ascii, utf-8 omitted, as they are tried first and last
470 # us-ascii, utf-8 omitted, as they are tried first and last
471 charsets = iso-8859-1, iso-8859-15, windows-1252
471 charsets = iso-8859-1, iso-8859-15, windows-1252
472
472
473
473
474 ``extensions``
474 ``extensions``
475 """"""""""""""
475 """"""""""""""
476
476
477 Mercurial has an extension mechanism for adding new features. To
477 Mercurial has an extension mechanism for adding new features. To
478 enable an extension, create an entry for it in this section.
478 enable an extension, create an entry for it in this section.
479
479
480 If you know that the extension is already in Python's search path,
480 If you know that the extension is already in Python's search path,
481 you can give the name of the module, followed by ``=``, with nothing
481 you can give the name of the module, followed by ``=``, with nothing
482 after the ``=``.
482 after the ``=``.
483
483
484 Otherwise, give a name that you choose, followed by ``=``, followed by
484 Otherwise, give a name that you choose, followed by ``=``, followed by
485 the path to the ``.py`` file (including the file name extension) that
485 the path to the ``.py`` file (including the file name extension) that
486 defines the extension.
486 defines the extension.
487
487
488 To explicitly disable an extension that is enabled in an hgrc of
488 To explicitly disable an extension that is enabled in an hgrc of
489 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
489 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
490 or ``foo = !`` when path is not supplied.
490 or ``foo = !`` when path is not supplied.
491
491
492 Example for ``~/.hgrc``::
492 Example for ``~/.hgrc``::
493
493
494 [extensions]
494 [extensions]
495 # (the mq extension will get loaded from Mercurial's path)
495 # (the mq extension will get loaded from Mercurial's path)
496 mq =
496 mq =
497 # (this extension will get loaded from the file specified)
497 # (this extension will get loaded from the file specified)
498 myfeature = ~/.hgext/myfeature.py
498 myfeature = ~/.hgext/myfeature.py
499
499
500
500
501 ``format``
501 ``format``
502 """"""""""
502 """"""""""
503
503
504 ``usestore``
504 ``usestore``
505 Enable or disable the "store" repository format which improves
505 Enable or disable the "store" repository format which improves
506 compatibility with systems that fold case or otherwise mangle
506 compatibility with systems that fold case or otherwise mangle
507 filenames. Enabled by default. Disabling this option will allow
507 filenames. Enabled by default. Disabling this option will allow
508 you to store longer filenames in some situations at the expense of
508 you to store longer filenames in some situations at the expense of
509 compatibility and ensures that the on-disk format of newly created
509 compatibility and ensures that the on-disk format of newly created
510 repositories will be compatible with Mercurial before version 0.9.4.
510 repositories will be compatible with Mercurial before version 0.9.4.
511
511
512 ``usefncache``
512 ``usefncache``
513 Enable or disable the "fncache" repository format which enhances
513 Enable or disable the "fncache" repository format which enhances
514 the "store" repository format (which has to be enabled to use
514 the "store" repository format (which has to be enabled to use
515 fncache) to allow longer filenames and avoids using Windows
515 fncache) to allow longer filenames and avoids using Windows
516 reserved names, e.g. "nul". Enabled by default. Disabling this
516 reserved names, e.g. "nul". Enabled by default. Disabling this
517 option ensures that the on-disk format of newly created
517 option ensures that the on-disk format of newly created
518 repositories will be compatible with Mercurial before version 1.1.
518 repositories will be compatible with Mercurial before version 1.1.
519
519
520 ``dotencode``
520 ``dotencode``
521 Enable or disable the "dotencode" repository format which enhances
521 Enable or disable the "dotencode" repository format which enhances
522 the "fncache" repository format (which has to be enabled to use
522 the "fncache" repository format (which has to be enabled to use
523 dotencode) to avoid issues with filenames starting with ._ on
523 dotencode) to avoid issues with filenames starting with ._ on
524 Mac OS X and spaces on Windows. Enabled by default. Disabling this
524 Mac OS X and spaces on Windows. Enabled by default. Disabling this
525 option ensures that the on-disk format of newly created
525 option ensures that the on-disk format of newly created
526 repositories will be compatible with Mercurial before version 1.7.
526 repositories will be compatible with Mercurial before version 1.7.
527
527
528 ``graph``
528 ``graph``
529 """""""""
529 """""""""
530
530
531 Web graph view configuration. This section let you change graph
531 Web graph view configuration. This section let you change graph
532 elements display properties by branches, for instance to make the
532 elements display properties by branches, for instance to make the
533 ``default`` branch stand out.
533 ``default`` branch stand out.
534
534
535 Each line has the following format::
535 Each line has the following format::
536
536
537 <branch>.<argument> = <value>
537 <branch>.<argument> = <value>
538
538
539 where ``<branch>`` is the name of the branch being
539 where ``<branch>`` is the name of the branch being
540 customized. Example::
540 customized. Example::
541
541
542 [graph]
542 [graph]
543 # 2px width
543 # 2px width
544 default.width = 2
544 default.width = 2
545 # red color
545 # red color
546 default.color = FF0000
546 default.color = FF0000
547
547
548 Supported arguments:
548 Supported arguments:
549
549
550 ``width``
550 ``width``
551 Set branch edges width in pixels.
551 Set branch edges width in pixels.
552
552
553 ``color``
553 ``color``
554 Set branch edges color in hexadecimal RGB notation.
554 Set branch edges color in hexadecimal RGB notation.
555
555
556 ``hooks``
556 ``hooks``
557 """""""""
557 """""""""
558
558
559 Commands or Python functions that get automatically executed by
559 Commands or Python functions that get automatically executed by
560 various actions such as starting or finishing a commit. Multiple
560 various actions such as starting or finishing a commit. Multiple
561 hooks can be run for the same action by appending a suffix to the
561 hooks can be run for the same action by appending a suffix to the
562 action. Overriding a site-wide hook can be done by changing its
562 action. Overriding a site-wide hook can be done by changing its
563 value or setting it to an empty string. Hooks can be prioritized
563 value or setting it to an empty string. Hooks can be prioritized
564 by adding a prefix of ``priority`` to the hook name on a new line
564 by adding a prefix of ``priority`` to the hook name on a new line
565 and setting the priority. The default priority is 0 if
565 and setting the priority. The default priority is 0 if
566 not specified.
566 not specified.
567
567
568 Example ``.hg/hgrc``::
568 Example ``.hg/hgrc``::
569
569
570 [hooks]
570 [hooks]
571 # update working directory after adding changesets
571 # update working directory after adding changesets
572 changegroup.update = hg update
572 changegroup.update = hg update
573 # do not use the site-wide hook
573 # do not use the site-wide hook
574 incoming =
574 incoming =
575 incoming.email = /my/email/hook
575 incoming.email = /my/email/hook
576 incoming.autobuild = /my/build/hook
576 incoming.autobuild = /my/build/hook
577 # force autobuild hook to run before other incoming hooks
577 # force autobuild hook to run before other incoming hooks
578 priority.incoming.autobuild = 1
578 priority.incoming.autobuild = 1
579
579
580 Most hooks are run with environment variables set that give useful
580 Most hooks are run with environment variables set that give useful
581 additional information. For each hook below, the environment
581 additional information. For each hook below, the environment
582 variables it is passed are listed with names of the form ``$HG_foo``.
582 variables it is passed are listed with names of the form ``$HG_foo``.
583
583
584 ``changegroup``
584 ``changegroup``
585 Run after a changegroup has been added via push, pull or unbundle.
585 Run after a changegroup has been added via push, pull or unbundle.
586 ID of the first new changeset is in ``$HG_NODE``. URL from which
586 ID of the first new changeset is in ``$HG_NODE``. URL from which
587 changes came is in ``$HG_URL``.
587 changes came is in ``$HG_URL``.
588
588
589 ``commit``
589 ``commit``
590 Run after a changeset has been created in the local repository. ID
590 Run after a changeset has been created in the local repository. ID
591 of the newly created changeset is in ``$HG_NODE``. Parent changeset
591 of the newly created changeset is in ``$HG_NODE``. Parent changeset
592 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
592 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
593
593
594 ``incoming``
594 ``incoming``
595 Run after a changeset has been pulled, pushed, or unbundled into
595 Run after a changeset has been pulled, pushed, or unbundled into
596 the local repository. The ID of the newly arrived changeset is in
596 the local repository. The ID of the newly arrived changeset is in
597 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
597 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
598
598
599 ``outgoing``
599 ``outgoing``
600 Run after sending changes from local repository to another. ID of
600 Run after sending changes from local repository to another. ID of
601 first changeset sent is in ``$HG_NODE``. Source of operation is in
601 first changeset sent is in ``$HG_NODE``. Source of operation is in
602 ``$HG_SOURCE``; see "preoutgoing" hook for description.
602 ``$HG_SOURCE``; see "preoutgoing" hook for description.
603
603
604 ``post-<command>``
604 ``post-<command>``
605 Run after successful invocations of the associated command. The
605 Run after successful invocations of the associated command. The
606 contents of the command line are passed as ``$HG_ARGS`` and the result
606 contents of the command line are passed as ``$HG_ARGS`` and the result
607 code in ``$HG_RESULT``. Parsed command line arguments are passed as
607 code in ``$HG_RESULT``. Parsed command line arguments are passed as
608 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
608 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
609 the python data internally passed to <command>. ``$HG_OPTS`` is a
609 the python data internally passed to <command>. ``$HG_OPTS`` is a
610 dictionary of options (with unspecified options set to their defaults).
610 dictionary of options (with unspecified options set to their defaults).
611 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
611 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
612
612
613 ``pre-<command>``
613 ``pre-<command>``
614 Run before executing the associated command. The contents of the
614 Run before executing the associated command. The contents of the
615 command line are passed as ``$HG_ARGS``. Parsed command line arguments
615 command line are passed as ``$HG_ARGS``. Parsed command line arguments
616 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
616 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
617 representations of the data internally passed to <command>. ``$HG_OPTS``
617 representations of the data internally passed to <command>. ``$HG_OPTS``
618 is a dictionary of options (with unspecified options set to their
618 is a dictionary of options (with unspecified options set to their
619 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
619 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
620 failure, the command doesn't execute and Mercurial returns the failure
620 failure, the command doesn't execute and Mercurial returns the failure
621 code.
621 code.
622
622
623 ``prechangegroup``
623 ``prechangegroup``
624 Run before a changegroup is added via push, pull or unbundle. Exit
624 Run before a changegroup is added via push, pull or unbundle. Exit
625 status 0 allows the changegroup to proceed. Non-zero status will
625 status 0 allows the changegroup to proceed. Non-zero status will
626 cause the push, pull or unbundle to fail. URL from which changes
626 cause the push, pull or unbundle to fail. URL from which changes
627 will come is in ``$HG_URL``.
627 will come is in ``$HG_URL``.
628
628
629 ``precommit``
629 ``precommit``
630 Run before starting a local commit. Exit status 0 allows the
630 Run before starting a local commit. Exit status 0 allows the
631 commit to proceed. Non-zero status will cause the commit to fail.
631 commit to proceed. Non-zero status will cause the commit to fail.
632 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
632 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
633
633
634 ``prelistkeys``
634 ``prelistkeys``
635 Run before listing pushkeys (like bookmarks) in the
635 Run before listing pushkeys (like bookmarks) in the
636 repository. Non-zero status will cause failure. The key namespace is
636 repository. Non-zero status will cause failure. The key namespace is
637 in ``$HG_NAMESPACE``.
637 in ``$HG_NAMESPACE``.
638
638
639 ``preoutgoing``
639 ``preoutgoing``
640 Run before collecting changes to send from the local repository to
640 Run before collecting changes to send from the local repository to
641 another. Non-zero status will cause failure. This lets you prevent
641 another. Non-zero status will cause failure. This lets you prevent
642 pull over HTTP or SSH. Also prevents against local pull, push
642 pull over HTTP or SSH. Also prevents against local pull, push
643 (outbound) or bundle commands, but not effective, since you can
643 (outbound) or bundle commands, but not effective, since you can
644 just copy files instead then. Source of operation is in
644 just copy files instead then. Source of operation is in
645 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
645 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
646 SSH or HTTP repository. If "push", "pull" or "bundle", operation
646 SSH or HTTP repository. If "push", "pull" or "bundle", operation
647 is happening on behalf of repository on same system.
647 is happening on behalf of repository on same system.
648
648
649 ``prepushkey``
649 ``prepushkey``
650 Run before a pushkey (like a bookmark) is added to the
650 Run before a pushkey (like a bookmark) is added to the
651 repository. Non-zero status will cause the key to be rejected. The
651 repository. Non-zero status will cause the key to be rejected. The
652 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
652 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
653 the old value (if any) is in ``$HG_OLD``, and the new value is in
653 the old value (if any) is in ``$HG_OLD``, and the new value is in
654 ``$HG_NEW``.
654 ``$HG_NEW``.
655
655
656 ``pretag``
656 ``pretag``
657 Run before creating a tag. Exit status 0 allows the tag to be
657 Run before creating a tag. Exit status 0 allows the tag to be
658 created. Non-zero status will cause the tag to fail. ID of
658 created. Non-zero status will cause the tag to fail. ID of
659 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
659 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
660 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
660 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
661
661
662 ``pretxnchangegroup``
662 ``pretxnchangegroup``
663 Run after a changegroup has been added via push, pull or unbundle,
663 Run after a changegroup has been added via push, pull or unbundle,
664 but before the transaction has been committed. Changegroup is
664 but before the transaction has been committed. Changegroup is
665 visible to hook program. This lets you validate incoming changes
665 visible to hook program. This lets you validate incoming changes
666 before accepting them. Passed the ID of the first new changeset in
666 before accepting them. Passed the ID of the first new changeset in
667 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
667 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
668 status will cause the transaction to be rolled back and the push,
668 status will cause the transaction to be rolled back and the push,
669 pull or unbundle will fail. URL that was source of changes is in
669 pull or unbundle will fail. URL that was source of changes is in
670 ``$HG_URL``.
670 ``$HG_URL``.
671
671
672 ``pretxncommit``
672 ``pretxncommit``
673 Run after a changeset has been created but the transaction not yet
673 Run after a changeset has been created but the transaction not yet
674 committed. Changeset is visible to hook program. This lets you
674 committed. Changeset is visible to hook program. This lets you
675 validate commit message and changes. Exit status 0 allows the
675 validate commit message and changes. Exit status 0 allows the
676 commit to proceed. Non-zero status will cause the transaction to
676 commit to proceed. Non-zero status will cause the transaction to
677 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
677 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
678 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
678 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
679
679
680 ``preupdate``
680 ``preupdate``
681 Run before updating the working directory. Exit status 0 allows
681 Run before updating the working directory. Exit status 0 allows
682 the update to proceed. Non-zero status will prevent the update.
682 the update to proceed. Non-zero status will prevent the update.
683 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
683 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
684 of second new parent is in ``$HG_PARENT2``.
684 of second new parent is in ``$HG_PARENT2``.
685
685
686 ``listkeys``
686 ``listkeys``
687 Run after listing pushkeys (like bookmarks) in the repository. The
687 Run after listing pushkeys (like bookmarks) in the repository. The
688 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
688 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
689 dictionary containing the keys and values.
689 dictionary containing the keys and values.
690
690
691 ``pushkey``
691 ``pushkey``
692 Run after a pushkey (like a bookmark) is added to the
692 Run after a pushkey (like a bookmark) is added to the
693 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
693 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
694 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
694 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
695 value is in ``$HG_NEW``.
695 value is in ``$HG_NEW``.
696
696
697 ``tag``
697 ``tag``
698 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
698 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
699 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
699 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
700 repository if ``$HG_LOCAL=0``.
700 repository if ``$HG_LOCAL=0``.
701
701
702 ``update``
702 ``update``
703 Run after updating the working directory. Changeset ID of first
703 Run after updating the working directory. Changeset ID of first
704 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
704 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
705 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
705 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
706 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
706 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
707
707
708 .. note:: It is generally better to use standard hooks rather than the
708 .. note:: It is generally better to use standard hooks rather than the
709 generic pre- and post- command hooks as they are guaranteed to be
709 generic pre- and post- command hooks as they are guaranteed to be
710 called in the appropriate contexts for influencing transactions.
710 called in the appropriate contexts for influencing transactions.
711 Also, hooks like "commit" will be called in all contexts that
711 Also, hooks like "commit" will be called in all contexts that
712 generate a commit (e.g. tag) and not just the commit command.
712 generate a commit (e.g. tag) and not just the commit command.
713
713
714 .. note:: Environment variables with empty values may not be passed to
714 .. note:: Environment variables with empty values may not be passed to
715 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
715 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
716 will have an empty value under Unix-like platforms for non-merge
716 will have an empty value under Unix-like platforms for non-merge
717 changesets, while it will not be available at all under Windows.
717 changesets, while it will not be available at all under Windows.
718
718
719 The syntax for Python hooks is as follows::
719 The syntax for Python hooks is as follows::
720
720
721 hookname = python:modulename.submodule.callable
721 hookname = python:modulename.submodule.callable
722 hookname = python:/path/to/python/module.py:callable
722 hookname = python:/path/to/python/module.py:callable
723
723
724 Python hooks are run within the Mercurial process. Each hook is
724 Python hooks are run within the Mercurial process. Each hook is
725 called with at least three keyword arguments: a ui object (keyword
725 called with at least three keyword arguments: a ui object (keyword
726 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
726 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
727 keyword that tells what kind of hook is used. Arguments listed as
727 keyword that tells what kind of hook is used. Arguments listed as
728 environment variables above are passed as keyword arguments, with no
728 environment variables above are passed as keyword arguments, with no
729 ``HG_`` prefix, and names in lower case.
729 ``HG_`` prefix, and names in lower case.
730
730
731 If a Python hook returns a "true" value or raises an exception, this
731 If a Python hook returns a "true" value or raises an exception, this
732 is treated as a failure.
732 is treated as a failure.
733
733
734
734
735 ``hostfingerprints``
735 ``hostfingerprints``
736 """"""""""""""""""""
736 """"""""""""""""""""
737
737
738 Fingerprints of the certificates of known HTTPS servers.
738 Fingerprints of the certificates of known HTTPS servers.
739 A HTTPS connection to a server with a fingerprint configured here will
739 A HTTPS connection to a server with a fingerprint configured here will
740 only succeed if the servers certificate matches the fingerprint.
740 only succeed if the servers certificate matches the fingerprint.
741 This is very similar to how ssh known hosts works.
741 This is very similar to how ssh known hosts works.
742 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
742 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
743 The CA chain and web.cacerts is not used for servers with a fingerprint.
743 The CA chain and web.cacerts is not used for servers with a fingerprint.
744
744
745 For example::
745 For example::
746
746
747 [hostfingerprints]
747 [hostfingerprints]
748 hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
748 hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
749
749
750 This feature is only supported when using Python 2.6 or later.
750 This feature is only supported when using Python 2.6 or later.
751
751
752
752
753 ``http_proxy``
753 ``http_proxy``
754 """"""""""""""
754 """"""""""""""
755
755
756 Used to access web-based Mercurial repositories through a HTTP
756 Used to access web-based Mercurial repositories through a HTTP
757 proxy.
757 proxy.
758
758
759 ``host``
759 ``host``
760 Host name and (optional) port of the proxy server, for example
760 Host name and (optional) port of the proxy server, for example
761 "myproxy:8000".
761 "myproxy:8000".
762
762
763 ``no``
763 ``no``
764 Optional. Comma-separated list of host names that should bypass
764 Optional. Comma-separated list of host names that should bypass
765 the proxy.
765 the proxy.
766
766
767 ``passwd``
767 ``passwd``
768 Optional. Password to authenticate with at the proxy server.
768 Optional. Password to authenticate with at the proxy server.
769
769
770 ``user``
770 ``user``
771 Optional. User name to authenticate with at the proxy server.
771 Optional. User name to authenticate with at the proxy server.
772
772
773 ``always``
773 ``always``
774 Optional. Always use the proxy, even for localhost and any entries
774 Optional. Always use the proxy, even for localhost and any entries
775 in ``http_proxy.no``. True or False. Default: False.
775 in ``http_proxy.no``. True or False. Default: False.
776
776
777 ``merge-patterns``
777 ``merge-patterns``
778 """"""""""""""""""
778 """"""""""""""""""
779
779
780 This section specifies merge tools to associate with particular file
780 This section specifies merge tools to associate with particular file
781 patterns. Tools matched here will take precedence over the default
781 patterns. Tools matched here will take precedence over the default
782 merge tool. Patterns are globs by default, rooted at the repository
782 merge tool. Patterns are globs by default, rooted at the repository
783 root.
783 root.
784
784
785 Example::
785 Example::
786
786
787 [merge-patterns]
787 [merge-patterns]
788 **.c = kdiff3
788 **.c = kdiff3
789 **.jpg = myimgmerge
789 **.jpg = myimgmerge
790
790
791 ``merge-tools``
791 ``merge-tools``
792 """""""""""""""
792 """""""""""""""
793
793
794 This section configures external merge tools to use for file-level
794 This section configures external merge tools to use for file-level
795 merges.
795 merges.
796
796
797 Example ``~/.hgrc``::
797 Example ``~/.hgrc``::
798
798
799 [merge-tools]
799 [merge-tools]
800 # Override stock tool location
800 # Override stock tool location
801 kdiff3.executable = ~/bin/kdiff3
801 kdiff3.executable = ~/bin/kdiff3
802 # Specify command line
802 # Specify command line
803 kdiff3.args = $base $local $other -o $output
803 kdiff3.args = $base $local $other -o $output
804 # Give higher priority
804 # Give higher priority
805 kdiff3.priority = 1
805 kdiff3.priority = 1
806
806
807 # Define new tool
807 # Define new tool
808 myHtmlTool.args = -m $local $other $base $output
808 myHtmlTool.args = -m $local $other $base $output
809 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
809 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
810 myHtmlTool.priority = 1
810 myHtmlTool.priority = 1
811
811
812 Supported arguments:
812 Supported arguments:
813
813
814 ``priority``
814 ``priority``
815 The priority in which to evaluate this tool.
815 The priority in which to evaluate this tool.
816 Default: 0.
816 Default: 0.
817
817
818 ``executable``
818 ``executable``
819 Either just the name of the executable or its pathname. On Windows,
819 Either just the name of the executable or its pathname. On Windows,
820 the path can use environment variables with ${ProgramFiles} syntax.
820 the path can use environment variables with ${ProgramFiles} syntax.
821 Default: the tool name.
821 Default: the tool name.
822
822
823 ``args``
823 ``args``
824 The arguments to pass to the tool executable. You can refer to the
824 The arguments to pass to the tool executable. You can refer to the
825 files being merged as well as the output file through these
825 files being merged as well as the output file through these
826 variables: ``$base``, ``$local``, ``$other``, ``$output``.
826 variables: ``$base``, ``$local``, ``$other``, ``$output``.
827 Default: ``$local $base $other``
827 Default: ``$local $base $other``
828
828
829 ``premerge``
829 ``premerge``
830 Attempt to run internal non-interactive 3-way merge tool before
830 Attempt to run internal non-interactive 3-way merge tool before
831 launching external tool. Options are ``true``, ``false``, or ``keep``
831 launching external tool. Options are ``true``, ``false``, or ``keep``
832 to leave markers in the file if the premerge fails.
832 to leave markers in the file if the premerge fails.
833 Default: True
833 Default: True
834
834
835 ``binary``
835 ``binary``
836 This tool can merge binary files. Defaults to False, unless tool
836 This tool can merge binary files. Defaults to False, unless tool
837 was selected by file pattern match.
837 was selected by file pattern match.
838
838
839 ``symlink``
839 ``symlink``
840 This tool can merge symlinks. Defaults to False, even if tool was
840 This tool can merge symlinks. Defaults to False, even if tool was
841 selected by file pattern match.
841 selected by file pattern match.
842
842
843 ``check``
843 ``check``
844 A list of merge success-checking options:
844 A list of merge success-checking options:
845
845
846 ``changed``
846 ``changed``
847 Ask whether merge was successful when the merged file shows no changes.
847 Ask whether merge was successful when the merged file shows no changes.
848 ``conflicts``
848 ``conflicts``
849 Check whether there are conflicts even though the tool reported success.
849 Check whether there are conflicts even though the tool reported success.
850 ``prompt``
850 ``prompt``
851 Always prompt for merge success, regardless of success reported by tool.
851 Always prompt for merge success, regardless of success reported by tool.
852
852
853 ``checkchanged``
853 ``checkchanged``
854 True is equivalent to ``check = changed``.
854 True is equivalent to ``check = changed``.
855 Default: False
855 Default: False
856
856
857 ``checkconflicts``
857 ``checkconflicts``
858 True is equivalent to ``check = conflicts``.
858 True is equivalent to ``check = conflicts``.
859 Default: False
859 Default: False
860
860
861 ``fixeol``
861 ``fixeol``
862 Attempt to fix up EOL changes caused by the merge tool.
862 Attempt to fix up EOL changes caused by the merge tool.
863 Default: False
863 Default: False
864
864
865 ``gui``
865 ``gui``
866 This tool requires a graphical interface to run. Default: False
866 This tool requires a graphical interface to run. Default: False
867
867
868 ``regkey``
868 ``regkey``
869 Windows registry key which describes install location of this
869 Windows registry key which describes install location of this
870 tool. Mercurial will search for this key first under
870 tool. Mercurial will search for this key first under
871 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
871 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
872 Default: None
872 Default: None
873
873
874 ``regkeyalt``
874 ``regkeyalt``
875 An alternate Windows registry key to try if the first key is not
875 An alternate Windows registry key to try if the first key is not
876 found. The alternate key uses the same ``regname`` and ``regappend``
876 found. The alternate key uses the same ``regname`` and ``regappend``
877 semantics of the primary key. The most common use for this key
877 semantics of the primary key. The most common use for this key
878 is to search for 32bit applications on 64bit operating systems.
878 is to search for 32bit applications on 64bit operating systems.
879 Default: None
879 Default: None
880
880
881 ``regname``
881 ``regname``
882 Name of value to read from specified registry key. Defaults to the
882 Name of value to read from specified registry key. Defaults to the
883 unnamed (default) value.
883 unnamed (default) value.
884
884
885 ``regappend``
885 ``regappend``
886 String to append to the value read from the registry, typically
886 String to append to the value read from the registry, typically
887 the executable name of the tool.
887 the executable name of the tool.
888 Default: None
888 Default: None
889
889
890
890
891 ``patch``
891 ``patch``
892 """""""""
892 """""""""
893
893
894 Settings used when applying patches, for instance through the 'import'
894 Settings used when applying patches, for instance through the 'import'
895 command or with Mercurial Queues extension.
895 command or with Mercurial Queues extension.
896
896
897 ``eol``
897 ``eol``
898 When set to 'strict' patch content and patched files end of lines
898 When set to 'strict' patch content and patched files end of lines
899 are preserved. When set to ``lf`` or ``crlf``, both files end of
899 are preserved. When set to ``lf`` or ``crlf``, both files end of
900 lines are ignored when patching and the result line endings are
900 lines are ignored when patching and the result line endings are
901 normalized to either LF (Unix) or CRLF (Windows). When set to
901 normalized to either LF (Unix) or CRLF (Windows). When set to
902 ``auto``, end of lines are again ignored while patching but line
902 ``auto``, end of lines are again ignored while patching but line
903 endings in patched files are normalized to their original setting
903 endings in patched files are normalized to their original setting
904 on a per-file basis. If target file does not exist or has no end
904 on a per-file basis. If target file does not exist or has no end
905 of line, patch line endings are preserved.
905 of line, patch line endings are preserved.
906 Default: strict.
906 Default: strict.
907
907
908
908
909 ``paths``
909 ``paths``
910 """""""""
910 """""""""
911
911
912 Assigns symbolic names to repositories. The left side is the
912 Assigns symbolic names to repositories. The left side is the
913 symbolic name, and the right gives the directory or URL that is the
913 symbolic name, and the right gives the directory or URL that is the
914 location of the repository. Default paths can be declared by setting
914 location of the repository. Default paths can be declared by setting
915 the following entries.
915 the following entries.
916
916
917 ``default``
917 ``default``
918 Directory or URL to use when pulling if no source is specified.
918 Directory or URL to use when pulling if no source is specified.
919 Default is set to repository from which the current repository was
919 Default is set to repository from which the current repository was
920 cloned.
920 cloned.
921
921
922 ``default-push``
922 ``default-push``
923 Optional. Directory or URL to use when pushing if no destination
923 Optional. Directory or URL to use when pushing if no destination
924 is specified.
924 is specified.
925
925
926 ``phases``
926 ``phases``
927 """"""""""
927 """"""""""
928
928
929 Specifies default handling of phases. See :hg:`help phases` for more
929 Specifies default handling of phases. See :hg:`help phases` for more
930 information about working with phases.
930 information about working with phases.
931
931
932 ``publish``
932 ``publish``
933 Controls draft phase behavior when working as a server. When true,
933 Controls draft phase behavior when working as a server. When true,
934 pushed changesets are set to public in both client and server and
934 pushed changesets are set to public in both client and server and
935 pulled or cloned changesets are set to public in the client.
935 pulled or cloned changesets are set to public in the client.
936 Default: True
936 Default: True
937
937
938 ``new-commit``
938 ``new-commit``
939 Phase of newly-created commits.
939 Phase of newly-created commits.
940 Default: draft
940 Default: draft
941
941
942 ``profiling``
942 ``profiling``
943 """""""""""""
943 """""""""""""
944
944
945 Specifies profiling type, format, and file output. Two profilers are
945 Specifies profiling type, format, and file output. Two profilers are
946 supported: an instrumenting profiler (named ``ls``), and a sampling
946 supported: an instrumenting profiler (named ``ls``), and a sampling
947 profiler (named ``stat``).
947 profiler (named ``stat``).
948
948
949 In this section description, 'profiling data' stands for the raw data
949 In this section description, 'profiling data' stands for the raw data
950 collected during profiling, while 'profiling report' stands for a
950 collected during profiling, while 'profiling report' stands for a
951 statistical text report generated from the profiling data. The
951 statistical text report generated from the profiling data. The
952 profiling is done using lsprof.
952 profiling is done using lsprof.
953
953
954 ``type``
954 ``type``
955 The type of profiler to use.
955 The type of profiler to use.
956 Default: ls.
956 Default: ls.
957
957
958 ``ls``
958 ``ls``
959 Use Python's built-in instrumenting profiler. This profiler
959 Use Python's built-in instrumenting profiler. This profiler
960 works on all platforms, but each line number it reports is the
960 works on all platforms, but each line number it reports is the
961 first line of a function. This restriction makes it difficult to
961 first line of a function. This restriction makes it difficult to
962 identify the expensive parts of a non-trivial function.
962 identify the expensive parts of a non-trivial function.
963 ``stat``
963 ``stat``
964 Use a third-party statistical profiler, statprof. This profiler
964 Use a third-party statistical profiler, statprof. This profiler
965 currently runs only on Unix systems, and is most useful for
965 currently runs only on Unix systems, and is most useful for
966 profiling commands that run for longer than about 0.1 seconds.
966 profiling commands that run for longer than about 0.1 seconds.
967
967
968 ``format``
968 ``format``
969 Profiling format. Specific to the ``ls`` instrumenting profiler.
969 Profiling format. Specific to the ``ls`` instrumenting profiler.
970 Default: text.
970 Default: text.
971
971
972 ``text``
972 ``text``
973 Generate a profiling report. When saving to a file, it should be
973 Generate a profiling report. When saving to a file, it should be
974 noted that only the report is saved, and the profiling data is
974 noted that only the report is saved, and the profiling data is
975 not kept.
975 not kept.
976 ``kcachegrind``
976 ``kcachegrind``
977 Format profiling data for kcachegrind use: when saving to a
977 Format profiling data for kcachegrind use: when saving to a
978 file, the generated file can directly be loaded into
978 file, the generated file can directly be loaded into
979 kcachegrind.
979 kcachegrind.
980
980
981 ``frequency``
981 ``frequency``
982 Sampling frequency. Specific to the ``stat`` sampling profiler.
982 Sampling frequency. Specific to the ``stat`` sampling profiler.
983 Default: 1000.
983 Default: 1000.
984
984
985 ``output``
985 ``output``
986 File path where profiling data or report should be saved. If the
986 File path where profiling data or report should be saved. If the
987 file exists, it is replaced. Default: None, data is printed on
987 file exists, it is replaced. Default: None, data is printed on
988 stderr
988 stderr
989
989
990 ``revsetalias``
990 ``revsetalias``
991 """""""""""""""
991 """""""""""""""
992
992
993 Alias definitions for revsets. See :hg:`help revsets` for details.
993 Alias definitions for revsets. See :hg:`help revsets` for details.
994
994
995 ``server``
995 ``server``
996 """"""""""
996 """"""""""
997
997
998 Controls generic server settings.
998 Controls generic server settings.
999
999
1000 ``uncompressed``
1000 ``uncompressed``
1001 Whether to allow clients to clone a repository using the
1001 Whether to allow clients to clone a repository using the
1002 uncompressed streaming protocol. This transfers about 40% more
1002 uncompressed streaming protocol. This transfers about 40% more
1003 data than a regular clone, but uses less memory and CPU on both
1003 data than a regular clone, but uses less memory and CPU on both
1004 server and client. Over a LAN (100 Mbps or better) or a very fast
1004 server and client. Over a LAN (100 Mbps or better) or a very fast
1005 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1005 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1006 regular clone. Over most WAN connections (anything slower than
1006 regular clone. Over most WAN connections (anything slower than
1007 about 6 Mbps), uncompressed streaming is slower, because of the
1007 about 6 Mbps), uncompressed streaming is slower, because of the
1008 extra data transfer overhead. This mode will also temporarily hold
1008 extra data transfer overhead. This mode will also temporarily hold
1009 the write lock while determining what data to transfer.
1009 the write lock while determining what data to transfer.
1010 Default is True.
1010 Default is True.
1011
1011
1012 ``preferuncompressed``
1012 ``preferuncompressed``
1013 When set, clients will try to use the uncompressed streaming
1013 When set, clients will try to use the uncompressed streaming
1014 protocol. Default is False.
1014 protocol. Default is False.
1015
1015
1016 ``validate``
1016 ``validate``
1017 Whether to validate the completeness of pushed changesets by
1017 Whether to validate the completeness of pushed changesets by
1018 checking that all new file revisions specified in manifests are
1018 checking that all new file revisions specified in manifests are
1019 present. Default is False.
1019 present. Default is False.
1020
1020
1021 ``smtp``
1021 ``smtp``
1022 """"""""
1022 """"""""
1023
1023
1024 Configuration for extensions that need to send email messages.
1024 Configuration for extensions that need to send email messages.
1025
1025
1026 ``host``
1026 ``host``
1027 Host name of mail server, e.g. "mail.example.com".
1027 Host name of mail server, e.g. "mail.example.com".
1028
1028
1029 ``port``
1029 ``port``
1030 Optional. Port to connect to on mail server. Default: 25.
1030 Optional. Port to connect to on mail server. Default: 25.
1031
1031
1032 ``tls``
1032 ``tls``
1033 Optional. Method to enable TLS when connecting to mail server: starttls,
1033 Optional. Method to enable TLS when connecting to mail server: starttls,
1034 smtps or none. Default: none.
1034 smtps or none. Default: none.
1035
1035
1036 ``username``
1036 ``username``
1037 Optional. User name for authenticating with the SMTP server.
1037 Optional. User name for authenticating with the SMTP server.
1038 Default: none.
1038 Default: none.
1039
1039
1040 ``password``
1040 ``password``
1041 Optional. Password for authenticating with the SMTP server. If not
1041 Optional. Password for authenticating with the SMTP server. If not
1042 specified, interactive sessions will prompt the user for a
1042 specified, interactive sessions will prompt the user for a
1043 password; non-interactive sessions will fail. Default: none.
1043 password; non-interactive sessions will fail. Default: none.
1044
1044
1045 ``local_hostname``
1045 ``local_hostname``
1046 Optional. It's the hostname that the sender can use to identify
1046 Optional. It's the hostname that the sender can use to identify
1047 itself to the MTA.
1047 itself to the MTA.
1048
1048
1049
1049
1050 ``subpaths``
1050 ``subpaths``
1051 """"""""""""
1051 """"""""""""
1052
1052
1053 Subrepository source URLs can go stale if a remote server changes name
1053 Subrepository source URLs can go stale if a remote server changes name
1054 or becomes temporarily unavailable. This section lets you define
1054 or becomes temporarily unavailable. This section lets you define
1055 rewrite rules of the form::
1055 rewrite rules of the form::
1056
1056
1057 <pattern> = <replacement>
1057 <pattern> = <replacement>
1058
1058
1059 where ``pattern`` is a regular expression matching a subrepository
1059 where ``pattern`` is a regular expression matching a subrepository
1060 source URL and ``replacement`` is the replacement string used to
1060 source URL and ``replacement`` is the replacement string used to
1061 rewrite it. Groups can be matched in ``pattern`` and referenced in
1061 rewrite it. Groups can be matched in ``pattern`` and referenced in
1062 ``replacements``. For instance::
1062 ``replacements``. For instance::
1063
1063
1064 http://server/(.*)-hg/ = http://hg.server/\1/
1064 http://server/(.*)-hg/ = http://hg.server/\1/
1065
1065
1066 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1066 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1067
1067
1068 Relative subrepository paths are first made absolute, and the the
1068 Relative subrepository paths are first made absolute, and the
1069 rewrite rules are then applied on the full (absolute) path. The rules
1069 rewrite rules are then applied on the full (absolute) path. The rules
1070 are applied in definition order.
1070 are applied in definition order.
1071
1071
1072 ``trusted``
1072 ``trusted``
1073 """""""""""
1073 """""""""""
1074
1074
1075 Mercurial will not use the settings in the
1075 Mercurial will not use the settings in the
1076 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1076 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1077 user or to a trusted group, as various hgrc features allow arbitrary
1077 user or to a trusted group, as various hgrc features allow arbitrary
1078 commands to be run. This issue is often encountered when configuring
1078 commands to be run. This issue is often encountered when configuring
1079 hooks or extensions for shared repositories or servers. However,
1079 hooks or extensions for shared repositories or servers. However,
1080 the web interface will use some safe settings from the ``[web]``
1080 the web interface will use some safe settings from the ``[web]``
1081 section.
1081 section.
1082
1082
1083 This section specifies what users and groups are trusted. The
1083 This section specifies what users and groups are trusted. The
1084 current user is always trusted. To trust everybody, list a user or a
1084 current user is always trusted. To trust everybody, list a user or a
1085 group with name ``*``. These settings must be placed in an
1085 group with name ``*``. These settings must be placed in an
1086 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1086 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1087 user or service running Mercurial.
1087 user or service running Mercurial.
1088
1088
1089 ``users``
1089 ``users``
1090 Comma-separated list of trusted users.
1090 Comma-separated list of trusted users.
1091
1091
1092 ``groups``
1092 ``groups``
1093 Comma-separated list of trusted groups.
1093 Comma-separated list of trusted groups.
1094
1094
1095
1095
1096 ``ui``
1096 ``ui``
1097 """"""
1097 """"""
1098
1098
1099 User interface controls.
1099 User interface controls.
1100
1100
1101 ``archivemeta``
1101 ``archivemeta``
1102 Whether to include the .hg_archival.txt file containing meta data
1102 Whether to include the .hg_archival.txt file containing meta data
1103 (hashes for the repository base and for tip) in archives created
1103 (hashes for the repository base and for tip) in archives created
1104 by the :hg:`archive` command or downloaded via hgweb.
1104 by the :hg:`archive` command or downloaded via hgweb.
1105 Default is True.
1105 Default is True.
1106
1106
1107 ``askusername``
1107 ``askusername``
1108 Whether to prompt for a username when committing. If True, and
1108 Whether to prompt for a username when committing. If True, and
1109 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1109 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1110 be prompted to enter a username. If no username is entered, the
1110 be prompted to enter a username. If no username is entered, the
1111 default ``USER@HOST`` is used instead.
1111 default ``USER@HOST`` is used instead.
1112 Default is False.
1112 Default is False.
1113
1113
1114 ``commitsubrepos``
1114 ``commitsubrepos``
1115 Whether to commit modified subrepositories when committing the
1115 Whether to commit modified subrepositories when committing the
1116 parent repository. If False and one subrepository has uncommitted
1116 parent repository. If False and one subrepository has uncommitted
1117 changes, abort the commit.
1117 changes, abort the commit.
1118 Default is False.
1118 Default is False.
1119
1119
1120 ``debug``
1120 ``debug``
1121 Print debugging information. True or False. Default is False.
1121 Print debugging information. True or False. Default is False.
1122
1122
1123 ``editor``
1123 ``editor``
1124 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1124 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1125
1125
1126 ``fallbackencoding``
1126 ``fallbackencoding``
1127 Encoding to try if it's not possible to decode the changelog using
1127 Encoding to try if it's not possible to decode the changelog using
1128 UTF-8. Default is ISO-8859-1.
1128 UTF-8. Default is ISO-8859-1.
1129
1129
1130 ``ignore``
1130 ``ignore``
1131 A file to read per-user ignore patterns from. This file should be
1131 A file to read per-user ignore patterns from. This file should be
1132 in the same format as a repository-wide .hgignore file. This
1132 in the same format as a repository-wide .hgignore file. This
1133 option supports hook syntax, so if you want to specify multiple
1133 option supports hook syntax, so if you want to specify multiple
1134 ignore files, you can do so by setting something like
1134 ignore files, you can do so by setting something like
1135 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1135 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1136 format, see the ``hgignore(5)`` man page.
1136 format, see the ``hgignore(5)`` man page.
1137
1137
1138 ``interactive``
1138 ``interactive``
1139 Allow to prompt the user. True or False. Default is True.
1139 Allow to prompt the user. True or False. Default is True.
1140
1140
1141 ``logtemplate``
1141 ``logtemplate``
1142 Template string for commands that print changesets.
1142 Template string for commands that print changesets.
1143
1143
1144 ``merge``
1144 ``merge``
1145 The conflict resolution program to use during a manual merge.
1145 The conflict resolution program to use during a manual merge.
1146 For more information on merge tools see :hg:`help merge-tools`.
1146 For more information on merge tools see :hg:`help merge-tools`.
1147 For configuring merge tools see the ``[merge-tools]`` section.
1147 For configuring merge tools see the ``[merge-tools]`` section.
1148
1148
1149 ``portablefilenames``
1149 ``portablefilenames``
1150 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1150 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1151 Default is ``warn``.
1151 Default is ``warn``.
1152 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1152 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1153 platforms, if a file with a non-portable filename is added (e.g. a file
1153 platforms, if a file with a non-portable filename is added (e.g. a file
1154 with a name that can't be created on Windows because it contains reserved
1154 with a name that can't be created on Windows because it contains reserved
1155 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1155 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1156 collision with an existing file).
1156 collision with an existing file).
1157 If set to ``ignore`` (or ``false``), no warning is printed.
1157 If set to ``ignore`` (or ``false``), no warning is printed.
1158 If set to ``abort``, the command is aborted.
1158 If set to ``abort``, the command is aborted.
1159 On Windows, this configuration option is ignored and the command aborted.
1159 On Windows, this configuration option is ignored and the command aborted.
1160
1160
1161 ``quiet``
1161 ``quiet``
1162 Reduce the amount of output printed. True or False. Default is False.
1162 Reduce the amount of output printed. True or False. Default is False.
1163
1163
1164 ``remotecmd``
1164 ``remotecmd``
1165 remote command to use for clone/push/pull operations. Default is ``hg``.
1165 remote command to use for clone/push/pull operations. Default is ``hg``.
1166
1166
1167 ``reportoldssl``
1167 ``reportoldssl``
1168 Warn if an SSL certificate is unable to be due to using Python
1168 Warn if an SSL certificate is unable to be due to using Python
1169 2.5 or earlier. True or False. Default is True.
1169 2.5 or earlier. True or False. Default is True.
1170
1170
1171 ``report_untrusted``
1171 ``report_untrusted``
1172 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1172 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1173 trusted user or group. True or False. Default is True.
1173 trusted user or group. True or False. Default is True.
1174
1174
1175 ``slash``
1175 ``slash``
1176 Display paths using a slash (``/``) as the path separator. This
1176 Display paths using a slash (``/``) as the path separator. This
1177 only makes a difference on systems where the default path
1177 only makes a difference on systems where the default path
1178 separator is not the slash character (e.g. Windows uses the
1178 separator is not the slash character (e.g. Windows uses the
1179 backslash character (``\``)).
1179 backslash character (``\``)).
1180 Default is False.
1180 Default is False.
1181
1181
1182 ``ssh``
1182 ``ssh``
1183 command to use for SSH connections. Default is ``ssh``.
1183 command to use for SSH connections. Default is ``ssh``.
1184
1184
1185 ``strict``
1185 ``strict``
1186 Require exact command names, instead of allowing unambiguous
1186 Require exact command names, instead of allowing unambiguous
1187 abbreviations. True or False. Default is False.
1187 abbreviations. True or False. Default is False.
1188
1188
1189 ``style``
1189 ``style``
1190 Name of style to use for command output.
1190 Name of style to use for command output.
1191
1191
1192 ``timeout``
1192 ``timeout``
1193 The timeout used when a lock is held (in seconds), a negative value
1193 The timeout used when a lock is held (in seconds), a negative value
1194 means no timeout. Default is 600.
1194 means no timeout. Default is 600.
1195
1195
1196 ``traceback``
1196 ``traceback``
1197 Mercurial always prints a traceback when an unknown exception
1197 Mercurial always prints a traceback when an unknown exception
1198 occurs. Setting this to True will make Mercurial print a traceback
1198 occurs. Setting this to True will make Mercurial print a traceback
1199 on all exceptions, even those recognized by Mercurial (such as
1199 on all exceptions, even those recognized by Mercurial (such as
1200 IOError or MemoryError). Default is False.
1200 IOError or MemoryError). Default is False.
1201
1201
1202 ``username``
1202 ``username``
1203 The committer of a changeset created when running "commit".
1203 The committer of a changeset created when running "commit".
1204 Typically a person's name and email address, e.g. ``Fred Widget
1204 Typically a person's name and email address, e.g. ``Fred Widget
1205 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1205 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1206 the username in hgrc is empty, it has to be specified manually or
1206 the username in hgrc is empty, it has to be specified manually or
1207 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1207 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1208 ``username =`` in the system hgrc). Environment variables in the
1208 ``username =`` in the system hgrc). Environment variables in the
1209 username are expanded.
1209 username are expanded.
1210
1210
1211 ``verbose``
1211 ``verbose``
1212 Increase the amount of output printed. True or False. Default is False.
1212 Increase the amount of output printed. True or False. Default is False.
1213
1213
1214
1214
1215 ``web``
1215 ``web``
1216 """""""
1216 """""""
1217
1217
1218 Web interface configuration. The settings in this section apply to
1218 Web interface configuration. The settings in this section apply to
1219 both the builtin webserver (started by :hg:`serve`) and the script you
1219 both the builtin webserver (started by :hg:`serve`) and the script you
1220 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1220 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1221 and WSGI).
1221 and WSGI).
1222
1222
1223 The Mercurial webserver does no authentication (it does not prompt for
1223 The Mercurial webserver does no authentication (it does not prompt for
1224 usernames and passwords to validate *who* users are), but it does do
1224 usernames and passwords to validate *who* users are), but it does do
1225 authorization (it grants or denies access for *authenticated users*
1225 authorization (it grants or denies access for *authenticated users*
1226 based on settings in this section). You must either configure your
1226 based on settings in this section). You must either configure your
1227 webserver to do authentication for you, or disable the authorization
1227 webserver to do authentication for you, or disable the authorization
1228 checks.
1228 checks.
1229
1229
1230 For a quick setup in a trusted environment, e.g., a private LAN, where
1230 For a quick setup in a trusted environment, e.g., a private LAN, where
1231 you want it to accept pushes from anybody, you can use the following
1231 you want it to accept pushes from anybody, you can use the following
1232 command line::
1232 command line::
1233
1233
1234 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1234 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1235
1235
1236 Note that this will allow anybody to push anything to the server and
1236 Note that this will allow anybody to push anything to the server and
1237 that this should not be used for public servers.
1237 that this should not be used for public servers.
1238
1238
1239 The full set of options is:
1239 The full set of options is:
1240
1240
1241 ``accesslog``
1241 ``accesslog``
1242 Where to output the access log. Default is stdout.
1242 Where to output the access log. Default is stdout.
1243
1243
1244 ``address``
1244 ``address``
1245 Interface address to bind to. Default is all.
1245 Interface address to bind to. Default is all.
1246
1246
1247 ``allow_archive``
1247 ``allow_archive``
1248 List of archive format (bz2, gz, zip) allowed for downloading.
1248 List of archive format (bz2, gz, zip) allowed for downloading.
1249 Default is empty.
1249 Default is empty.
1250
1250
1251 ``allowbz2``
1251 ``allowbz2``
1252 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1252 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1253 revisions.
1253 revisions.
1254 Default is False.
1254 Default is False.
1255
1255
1256 ``allowgz``
1256 ``allowgz``
1257 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1257 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1258 revisions.
1258 revisions.
1259 Default is False.
1259 Default is False.
1260
1260
1261 ``allowpull``
1261 ``allowpull``
1262 Whether to allow pulling from the repository. Default is True.
1262 Whether to allow pulling from the repository. Default is True.
1263
1263
1264 ``allow_push``
1264 ``allow_push``
1265 Whether to allow pushing to the repository. If empty or not set,
1265 Whether to allow pushing to the repository. If empty or not set,
1266 push is not allowed. If the special value ``*``, any remote user can
1266 push is not allowed. If the special value ``*``, any remote user can
1267 push, including unauthenticated users. Otherwise, the remote user
1267 push, including unauthenticated users. Otherwise, the remote user
1268 must have been authenticated, and the authenticated user name must
1268 must have been authenticated, and the authenticated user name must
1269 be present in this list. The contents of the allow_push list are
1269 be present in this list. The contents of the allow_push list are
1270 examined after the deny_push list.
1270 examined after the deny_push list.
1271
1271
1272 ``guessmime``
1272 ``guessmime``
1273 Control MIME types for raw download of file content.
1273 Control MIME types for raw download of file content.
1274 Set to True to let hgweb guess the content type from the file
1274 Set to True to let hgweb guess the content type from the file
1275 extension. This will serve HTML files as ``text/html`` and might
1275 extension. This will serve HTML files as ``text/html`` and might
1276 allow cross-site scripting attacks when serving untrusted
1276 allow cross-site scripting attacks when serving untrusted
1277 repositories. Default is False.
1277 repositories. Default is False.
1278
1278
1279 ``allow_read``
1279 ``allow_read``
1280 If the user has not already been denied repository access due to
1280 If the user has not already been denied repository access due to
1281 the contents of deny_read, this list determines whether to grant
1281 the contents of deny_read, this list determines whether to grant
1282 repository access to the user. If this list is not empty, and the
1282 repository access to the user. If this list is not empty, and the
1283 user is unauthenticated or not present in the list, then access is
1283 user is unauthenticated or not present in the list, then access is
1284 denied for the user. If the list is empty or not set, then access
1284 denied for the user. If the list is empty or not set, then access
1285 is permitted to all users by default. Setting allow_read to the
1285 is permitted to all users by default. Setting allow_read to the
1286 special value ``*`` is equivalent to it not being set (i.e. access
1286 special value ``*`` is equivalent to it not being set (i.e. access
1287 is permitted to all users). The contents of the allow_read list are
1287 is permitted to all users). The contents of the allow_read list are
1288 examined after the deny_read list.
1288 examined after the deny_read list.
1289
1289
1290 ``allowzip``
1290 ``allowzip``
1291 (DEPRECATED) Whether to allow .zip downloading of repository
1291 (DEPRECATED) Whether to allow .zip downloading of repository
1292 revisions. Default is False. This feature creates temporary files.
1292 revisions. Default is False. This feature creates temporary files.
1293
1293
1294 ``baseurl``
1294 ``baseurl``
1295 Base URL to use when publishing URLs in other locations, so
1295 Base URL to use when publishing URLs in other locations, so
1296 third-party tools like email notification hooks can construct
1296 third-party tools like email notification hooks can construct
1297 URLs. Example: ``http://hgserver/repos/``.
1297 URLs. Example: ``http://hgserver/repos/``.
1298
1298
1299 ``cacerts``
1299 ``cacerts``
1300 Path to file containing a list of PEM encoded certificate
1300 Path to file containing a list of PEM encoded certificate
1301 authority certificates. Environment variables and ``~user``
1301 authority certificates. Environment variables and ``~user``
1302 constructs are expanded in the filename. If specified on the
1302 constructs are expanded in the filename. If specified on the
1303 client, then it will verify the identity of remote HTTPS servers
1303 client, then it will verify the identity of remote HTTPS servers
1304 with these certificates.
1304 with these certificates.
1305
1305
1306 This feature is only supported when using Python 2.6 or later. If you wish
1306 This feature is only supported when using Python 2.6 or later. If you wish
1307 to use it with earlier versions of Python, install the backported
1307 to use it with earlier versions of Python, install the backported
1308 version of the ssl library that is available from
1308 version of the ssl library that is available from
1309 ``http://pypi.python.org``.
1309 ``http://pypi.python.org``.
1310
1310
1311 To disable SSL verification temporarily, specify ``--insecure`` from
1311 To disable SSL verification temporarily, specify ``--insecure`` from
1312 command line.
1312 command line.
1313
1313
1314 You can use OpenSSL's CA certificate file if your platform has
1314 You can use OpenSSL's CA certificate file if your platform has
1315 one. On most Linux systems this will be
1315 one. On most Linux systems this will be
1316 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1316 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1317 generate this file manually. The form must be as follows::
1317 generate this file manually. The form must be as follows::
1318
1318
1319 -----BEGIN CERTIFICATE-----
1319 -----BEGIN CERTIFICATE-----
1320 ... (certificate in base64 PEM encoding) ...
1320 ... (certificate in base64 PEM encoding) ...
1321 -----END CERTIFICATE-----
1321 -----END CERTIFICATE-----
1322 -----BEGIN CERTIFICATE-----
1322 -----BEGIN CERTIFICATE-----
1323 ... (certificate in base64 PEM encoding) ...
1323 ... (certificate in base64 PEM encoding) ...
1324 -----END CERTIFICATE-----
1324 -----END CERTIFICATE-----
1325
1325
1326 ``cache``
1326 ``cache``
1327 Whether to support caching in hgweb. Defaults to True.
1327 Whether to support caching in hgweb. Defaults to True.
1328
1328
1329 ``collapse``
1329 ``collapse``
1330 With ``descend`` enabled, repositories in subdirectories are shown at
1330 With ``descend`` enabled, repositories in subdirectories are shown at
1331 a single level alongside repositories in the current path. With
1331 a single level alongside repositories in the current path. With
1332 ``collapse`` also enabled, repositories residing at a deeper level than
1332 ``collapse`` also enabled, repositories residing at a deeper level than
1333 the current path are grouped behind navigable directory entries that
1333 the current path are grouped behind navigable directory entries that
1334 lead to the locations of these repositories. In effect, this setting
1334 lead to the locations of these repositories. In effect, this setting
1335 collapses each collection of repositories found within a subdirectory
1335 collapses each collection of repositories found within a subdirectory
1336 into a single entry for that subdirectory. Default is False.
1336 into a single entry for that subdirectory. Default is False.
1337
1337
1338 ``contact``
1338 ``contact``
1339 Name or email address of the person in charge of the repository.
1339 Name or email address of the person in charge of the repository.
1340 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1340 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1341
1341
1342 ``deny_push``
1342 ``deny_push``
1343 Whether to deny pushing to the repository. If empty or not set,
1343 Whether to deny pushing to the repository. If empty or not set,
1344 push is not denied. If the special value ``*``, all remote users are
1344 push is not denied. If the special value ``*``, all remote users are
1345 denied push. Otherwise, unauthenticated users are all denied, and
1345 denied push. Otherwise, unauthenticated users are all denied, and
1346 any authenticated user name present in this list is also denied. The
1346 any authenticated user name present in this list is also denied. The
1347 contents of the deny_push list are examined before the allow_push list.
1347 contents of the deny_push list are examined before the allow_push list.
1348
1348
1349 ``deny_read``
1349 ``deny_read``
1350 Whether to deny reading/viewing of the repository. If this list is
1350 Whether to deny reading/viewing of the repository. If this list is
1351 not empty, unauthenticated users are all denied, and any
1351 not empty, unauthenticated users are all denied, and any
1352 authenticated user name present in this list is also denied access to
1352 authenticated user name present in this list is also denied access to
1353 the repository. If set to the special value ``*``, all remote users
1353 the repository. If set to the special value ``*``, all remote users
1354 are denied access (rarely needed ;). If deny_read is empty or not set,
1354 are denied access (rarely needed ;). If deny_read is empty or not set,
1355 the determination of repository access depends on the presence and
1355 the determination of repository access depends on the presence and
1356 content of the allow_read list (see description). If both
1356 content of the allow_read list (see description). If both
1357 deny_read and allow_read are empty or not set, then access is
1357 deny_read and allow_read are empty or not set, then access is
1358 permitted to all users by default. If the repository is being
1358 permitted to all users by default. If the repository is being
1359 served via hgwebdir, denied users will not be able to see it in
1359 served via hgwebdir, denied users will not be able to see it in
1360 the list of repositories. The contents of the deny_read list have
1360 the list of repositories. The contents of the deny_read list have
1361 priority over (are examined before) the contents of the allow_read
1361 priority over (are examined before) the contents of the allow_read
1362 list.
1362 list.
1363
1363
1364 ``descend``
1364 ``descend``
1365 hgwebdir indexes will not descend into subdirectories. Only repositories
1365 hgwebdir indexes will not descend into subdirectories. Only repositories
1366 directly in the current path will be shown (other repositories are still
1366 directly in the current path will be shown (other repositories are still
1367 available from the index corresponding to their containing path).
1367 available from the index corresponding to their containing path).
1368
1368
1369 ``description``
1369 ``description``
1370 Textual description of the repository's purpose or contents.
1370 Textual description of the repository's purpose or contents.
1371 Default is "unknown".
1371 Default is "unknown".
1372
1372
1373 ``encoding``
1373 ``encoding``
1374 Character encoding name. Default is the current locale charset.
1374 Character encoding name. Default is the current locale charset.
1375 Example: "UTF-8"
1375 Example: "UTF-8"
1376
1376
1377 ``errorlog``
1377 ``errorlog``
1378 Where to output the error log. Default is stderr.
1378 Where to output the error log. Default is stderr.
1379
1379
1380 ``comparisoncontext``
1380 ``comparisoncontext``
1381 Number of lines of context to show in side-by-side file comparison. If
1381 Number of lines of context to show in side-by-side file comparison. If
1382 negative or the value ``full``, whole files are shown. Default is 5.
1382 negative or the value ``full``, whole files are shown. Default is 5.
1383 This setting can be overridden by a ``context`` request parameter to the
1383 This setting can be overridden by a ``context`` request parameter to the
1384 ``comparison`` command, taking the same values.
1384 ``comparison`` command, taking the same values.
1385
1385
1386 ``hidden``
1386 ``hidden``
1387 Whether to hide the repository in the hgwebdir index.
1387 Whether to hide the repository in the hgwebdir index.
1388 Default is False.
1388 Default is False.
1389
1389
1390 ``ipv6``
1390 ``ipv6``
1391 Whether to use IPv6. Default is False.
1391 Whether to use IPv6. Default is False.
1392
1392
1393 ``logoimg``
1393 ``logoimg``
1394 File name of the logo image that some templates display on each page.
1394 File name of the logo image that some templates display on each page.
1395 The file name is relative to ``staticurl``. That is, the full path to
1395 The file name is relative to ``staticurl``. That is, the full path to
1396 the logo image is "staticurl/logoimg".
1396 the logo image is "staticurl/logoimg".
1397 If unset, ``hglogo.png`` will be used.
1397 If unset, ``hglogo.png`` will be used.
1398
1398
1399 ``logourl``
1399 ``logourl``
1400 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1400 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1401 will be used.
1401 will be used.
1402
1402
1403 ``name``
1403 ``name``
1404 Repository name to use in the web interface. Default is current
1404 Repository name to use in the web interface. Default is current
1405 working directory.
1405 working directory.
1406
1406
1407 ``maxchanges``
1407 ``maxchanges``
1408 Maximum number of changes to list on the changelog. Default is 10.
1408 Maximum number of changes to list on the changelog. Default is 10.
1409
1409
1410 ``maxfiles``
1410 ``maxfiles``
1411 Maximum number of files to list per changeset. Default is 10.
1411 Maximum number of files to list per changeset. Default is 10.
1412
1412
1413 ``port``
1413 ``port``
1414 Port to listen on. Default is 8000.
1414 Port to listen on. Default is 8000.
1415
1415
1416 ``prefix``
1416 ``prefix``
1417 Prefix path to serve from. Default is '' (server root).
1417 Prefix path to serve from. Default is '' (server root).
1418
1418
1419 ``push_ssl``
1419 ``push_ssl``
1420 Whether to require that inbound pushes be transported over SSL to
1420 Whether to require that inbound pushes be transported over SSL to
1421 prevent password sniffing. Default is True.
1421 prevent password sniffing. Default is True.
1422
1422
1423 ``staticurl``
1423 ``staticurl``
1424 Base URL to use for static files. If unset, static files (e.g. the
1424 Base URL to use for static files. If unset, static files (e.g. the
1425 hgicon.png favicon) will be served by the CGI script itself. Use
1425 hgicon.png favicon) will be served by the CGI script itself. Use
1426 this setting to serve them directly with the HTTP server.
1426 this setting to serve them directly with the HTTP server.
1427 Example: ``http://hgserver/static/``.
1427 Example: ``http://hgserver/static/``.
1428
1428
1429 ``stripes``
1429 ``stripes``
1430 How many lines a "zebra stripe" should span in multiline output.
1430 How many lines a "zebra stripe" should span in multiline output.
1431 Default is 1; set to 0 to disable.
1431 Default is 1; set to 0 to disable.
1432
1432
1433 ``style``
1433 ``style``
1434 Which template map style to use.
1434 Which template map style to use.
1435
1435
1436 ``templates``
1436 ``templates``
1437 Where to find the HTML templates. Default is install path.
1437 Where to find the HTML templates. Default is install path.
@@ -1,188 +1,188 b''
1 # hook.py - hook support for mercurial
1 # hook.py - hook support for mercurial
2 #
2 #
3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
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 from i18n import _
8 from i18n import _
9 import os, sys
9 import os, sys
10 import extensions, util
10 import extensions, util
11
11
12 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
12 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
13 '''call python hook. hook is callable object, looked up as
13 '''call python hook. hook is callable object, looked up as
14 name in python module. if callable returns "true", hook
14 name in python module. if callable returns "true", hook
15 fails, else passes. if hook raises exception, treated as
15 fails, else passes. if hook raises exception, treated as
16 hook failure. exception propagates if throw is "true".
16 hook failure. exception propagates if throw is "true".
17
17
18 reason for "true" meaning "hook failed" is so that
18 reason for "true" meaning "hook failed" is so that
19 unmodified commands (e.g. mercurial.commands.update) can
19 unmodified commands (e.g. mercurial.commands.update) can
20 be run as hooks without wrappers to convert return values.'''
20 be run as hooks without wrappers to convert return values.'''
21
21
22 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
22 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
23 obj = funcname
23 obj = funcname
24 if not util.safehasattr(obj, '__call__'):
24 if not util.safehasattr(obj, '__call__'):
25 d = funcname.rfind('.')
25 d = funcname.rfind('.')
26 if d == -1:
26 if d == -1:
27 raise util.Abort(_('%s hook is invalid ("%s" not in '
27 raise util.Abort(_('%s hook is invalid ("%s" not in '
28 'a module)') % (hname, funcname))
28 'a module)') % (hname, funcname))
29 modname = funcname[:d]
29 modname = funcname[:d]
30 oldpaths = sys.path
30 oldpaths = sys.path
31 if util.mainfrozen():
31 if util.mainfrozen():
32 # binary installs require sys.path manipulation
32 # binary installs require sys.path manipulation
33 modpath, modfile = os.path.split(modname)
33 modpath, modfile = os.path.split(modname)
34 if modpath and modfile:
34 if modpath and modfile:
35 sys.path = sys.path[:] + [modpath]
35 sys.path = sys.path[:] + [modpath]
36 modname = modfile
36 modname = modfile
37 try:
37 try:
38 obj = __import__(modname)
38 obj = __import__(modname)
39 except ImportError:
39 except ImportError:
40 e1 = sys.exc_type, sys.exc_value, sys.exc_traceback
40 e1 = sys.exc_type, sys.exc_value, sys.exc_traceback
41 try:
41 try:
42 # extensions are loaded with hgext_ prefix
42 # extensions are loaded with hgext_ prefix
43 obj = __import__("hgext_%s" % modname)
43 obj = __import__("hgext_%s" % modname)
44 except ImportError:
44 except ImportError:
45 e2 = sys.exc_type, sys.exc_value, sys.exc_traceback
45 e2 = sys.exc_type, sys.exc_value, sys.exc_traceback
46 if ui.tracebackflag:
46 if ui.tracebackflag:
47 ui.warn(_('exception from first failed import attempt:\n'))
47 ui.warn(_('exception from first failed import attempt:\n'))
48 ui.traceback(e1)
48 ui.traceback(e1)
49 if ui.tracebackflag:
49 if ui.tracebackflag:
50 ui.warn(_('exception from second failed import attempt:\n'))
50 ui.warn(_('exception from second failed import attempt:\n'))
51 ui.traceback(e2)
51 ui.traceback(e2)
52 raise util.Abort(_('%s hook is invalid '
52 raise util.Abort(_('%s hook is invalid '
53 '(import of "%s" failed)') %
53 '(import of "%s" failed)') %
54 (hname, modname))
54 (hname, modname))
55 sys.path = oldpaths
55 sys.path = oldpaths
56 try:
56 try:
57 for p in funcname.split('.')[1:]:
57 for p in funcname.split('.')[1:]:
58 obj = getattr(obj, p)
58 obj = getattr(obj, p)
59 except AttributeError:
59 except AttributeError:
60 raise util.Abort(_('%s hook is invalid '
60 raise util.Abort(_('%s hook is invalid '
61 '("%s" is not defined)') %
61 '("%s" is not defined)') %
62 (hname, funcname))
62 (hname, funcname))
63 if not util.safehasattr(obj, '__call__'):
63 if not util.safehasattr(obj, '__call__'):
64 raise util.Abort(_('%s hook is invalid '
64 raise util.Abort(_('%s hook is invalid '
65 '("%s" is not callable)') %
65 '("%s" is not callable)') %
66 (hname, funcname))
66 (hname, funcname))
67 try:
67 try:
68 try:
68 try:
69 # redirect IO descriptors the the ui descriptors so hooks
69 # redirect IO descriptors to the ui descriptors so hooks
70 # that write directly to these don't mess up the command
70 # that write directly to these don't mess up the command
71 # protocol when running through the command server
71 # protocol when running through the command server
72 old = sys.stdout, sys.stderr, sys.stdin
72 old = sys.stdout, sys.stderr, sys.stdin
73 sys.stdout, sys.stderr, sys.stdin = ui.fout, ui.ferr, ui.fin
73 sys.stdout, sys.stderr, sys.stdin = ui.fout, ui.ferr, ui.fin
74
74
75 r = obj(ui=ui, repo=repo, hooktype=name, **args)
75 r = obj(ui=ui, repo=repo, hooktype=name, **args)
76 except KeyboardInterrupt:
76 except KeyboardInterrupt:
77 raise
77 raise
78 except Exception, exc:
78 except Exception, exc:
79 if isinstance(exc, util.Abort):
79 if isinstance(exc, util.Abort):
80 ui.warn(_('error: %s hook failed: %s\n') %
80 ui.warn(_('error: %s hook failed: %s\n') %
81 (hname, exc.args[0]))
81 (hname, exc.args[0]))
82 else:
82 else:
83 ui.warn(_('error: %s hook raised an exception: '
83 ui.warn(_('error: %s hook raised an exception: '
84 '%s\n') % (hname, exc))
84 '%s\n') % (hname, exc))
85 if throw:
85 if throw:
86 raise
86 raise
87 ui.traceback()
87 ui.traceback()
88 return True
88 return True
89 finally:
89 finally:
90 sys.stdout, sys.stderr, sys.stdin = old
90 sys.stdout, sys.stderr, sys.stdin = old
91 if r:
91 if r:
92 if throw:
92 if throw:
93 raise util.Abort(_('%s hook failed') % hname)
93 raise util.Abort(_('%s hook failed') % hname)
94 ui.warn(_('warning: %s hook failed\n') % hname)
94 ui.warn(_('warning: %s hook failed\n') % hname)
95 return r
95 return r
96
96
97 def _exthook(ui, repo, name, cmd, args, throw):
97 def _exthook(ui, repo, name, cmd, args, throw):
98 ui.note(_("running hook %s: %s\n") % (name, cmd))
98 ui.note(_("running hook %s: %s\n") % (name, cmd))
99
99
100 env = {}
100 env = {}
101 for k, v in args.iteritems():
101 for k, v in args.iteritems():
102 if util.safehasattr(v, '__call__'):
102 if util.safehasattr(v, '__call__'):
103 v = v()
103 v = v()
104 if isinstance(v, dict):
104 if isinstance(v, dict):
105 # make the dictionary element order stable across Python
105 # make the dictionary element order stable across Python
106 # implementations
106 # implementations
107 v = ('{' +
107 v = ('{' +
108 ', '.join('%r: %r' % i for i in sorted(v.iteritems())) +
108 ', '.join('%r: %r' % i for i in sorted(v.iteritems())) +
109 '}')
109 '}')
110 env['HG_' + k.upper()] = v
110 env['HG_' + k.upper()] = v
111
111
112 if repo:
112 if repo:
113 cwd = repo.root
113 cwd = repo.root
114 else:
114 else:
115 cwd = os.getcwd()
115 cwd = os.getcwd()
116 if 'HG_URL' in env and env['HG_URL'].startswith('remote:http'):
116 if 'HG_URL' in env and env['HG_URL'].startswith('remote:http'):
117 r = util.system(cmd, environ=env, cwd=cwd, out=ui)
117 r = util.system(cmd, environ=env, cwd=cwd, out=ui)
118 else:
118 else:
119 r = util.system(cmd, environ=env, cwd=cwd, out=ui.fout)
119 r = util.system(cmd, environ=env, cwd=cwd, out=ui.fout)
120 if r:
120 if r:
121 desc, r = util.explainexit(r)
121 desc, r = util.explainexit(r)
122 if throw:
122 if throw:
123 raise util.Abort(_('%s hook %s') % (name, desc))
123 raise util.Abort(_('%s hook %s') % (name, desc))
124 ui.warn(_('warning: %s hook %s\n') % (name, desc))
124 ui.warn(_('warning: %s hook %s\n') % (name, desc))
125 return r
125 return r
126
126
127 def _allhooks(ui):
127 def _allhooks(ui):
128 hooks = []
128 hooks = []
129 for name, cmd in ui.configitems('hooks'):
129 for name, cmd in ui.configitems('hooks'):
130 if not name.startswith('priority'):
130 if not name.startswith('priority'):
131 priority = ui.configint('hooks', 'priority.%s' % name, 0)
131 priority = ui.configint('hooks', 'priority.%s' % name, 0)
132 hooks.append((-priority, len(hooks), name, cmd))
132 hooks.append((-priority, len(hooks), name, cmd))
133 return [(k, v) for p, o, k, v in sorted(hooks)]
133 return [(k, v) for p, o, k, v in sorted(hooks)]
134
134
135 _redirect = False
135 _redirect = False
136 def redirect(state):
136 def redirect(state):
137 global _redirect
137 global _redirect
138 _redirect = state
138 _redirect = state
139
139
140 def hook(ui, repo, name, throw=False, **args):
140 def hook(ui, repo, name, throw=False, **args):
141 if not ui.callhooks:
141 if not ui.callhooks:
142 return False
142 return False
143
143
144 r = False
144 r = False
145
145
146 oldstdout = -1
146 oldstdout = -1
147 if _redirect:
147 if _redirect:
148 try:
148 try:
149 stdoutno = sys.__stdout__.fileno()
149 stdoutno = sys.__stdout__.fileno()
150 stderrno = sys.__stderr__.fileno()
150 stderrno = sys.__stderr__.fileno()
151 # temporarily redirect stdout to stderr, if possible
151 # temporarily redirect stdout to stderr, if possible
152 if stdoutno >= 0 and stderrno >= 0:
152 if stdoutno >= 0 and stderrno >= 0:
153 sys.__stdout__.flush()
153 sys.__stdout__.flush()
154 oldstdout = os.dup(stdoutno)
154 oldstdout = os.dup(stdoutno)
155 os.dup2(stderrno, stdoutno)
155 os.dup2(stderrno, stdoutno)
156 except AttributeError:
156 except AttributeError:
157 # __stdout/err__ doesn't have fileno(), it's not a real file
157 # __stdout/err__ doesn't have fileno(), it's not a real file
158 pass
158 pass
159
159
160 try:
160 try:
161 for hname, cmd in _allhooks(ui):
161 for hname, cmd in _allhooks(ui):
162 if hname.split('.')[0] != name or not cmd:
162 if hname.split('.')[0] != name or not cmd:
163 continue
163 continue
164 if util.safehasattr(cmd, '__call__'):
164 if util.safehasattr(cmd, '__call__'):
165 r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
165 r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
166 elif cmd.startswith('python:'):
166 elif cmd.startswith('python:'):
167 if cmd.count(':') >= 2:
167 if cmd.count(':') >= 2:
168 path, cmd = cmd[7:].rsplit(':', 1)
168 path, cmd = cmd[7:].rsplit(':', 1)
169 path = util.expandpath(path)
169 path = util.expandpath(path)
170 if repo:
170 if repo:
171 path = os.path.join(repo.root, path)
171 path = os.path.join(repo.root, path)
172 try:
172 try:
173 mod = extensions.loadpath(path, 'hghook.%s' % hname)
173 mod = extensions.loadpath(path, 'hghook.%s' % hname)
174 except Exception:
174 except Exception:
175 ui.write(_("loading %s hook failed:\n") % hname)
175 ui.write(_("loading %s hook failed:\n") % hname)
176 raise
176 raise
177 hookfn = getattr(mod, cmd)
177 hookfn = getattr(mod, cmd)
178 else:
178 else:
179 hookfn = cmd[7:].strip()
179 hookfn = cmd[7:].strip()
180 r = _pythonhook(ui, repo, name, hname, hookfn, args, throw) or r
180 r = _pythonhook(ui, repo, name, hname, hookfn, args, throw) or r
181 else:
181 else:
182 r = _exthook(ui, repo, hname, cmd, args, throw) or r
182 r = _exthook(ui, repo, hname, cmd, args, throw) or r
183 finally:
183 finally:
184 if _redirect and oldstdout >= 0:
184 if _redirect and oldstdout >= 0:
185 os.dup2(oldstdout, stdoutno)
185 os.dup2(oldstdout, stdoutno)
186 os.close(oldstdout)
186 os.close(oldstdout)
187
187
188 return r
188 return r
@@ -1,764 +1,764 b''
1 # This library is free software; you can redistribute it and/or
1 # This library is free software; you can redistribute it and/or
2 # modify it under the terms of the GNU Lesser General Public
2 # modify it under the terms of the GNU Lesser General Public
3 # License as published by the Free Software Foundation; either
3 # License as published by the Free Software Foundation; either
4 # version 2.1 of the License, or (at your option) any later version.
4 # version 2.1 of the License, or (at your option) any later version.
5 #
5 #
6 # This library is distributed in the hope that it will be useful,
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
9 # Lesser General Public License for more details.
10 #
10 #
11 # You should have received a copy of the GNU Lesser General Public
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, see
12 # License along with this library; if not, see
13 # <http://www.gnu.org/licenses/>.
13 # <http://www.gnu.org/licenses/>.
14
14
15 # This file is part of urlgrabber, a high-level cross-protocol url-grabber
15 # This file is part of urlgrabber, a high-level cross-protocol url-grabber
16 # Copyright 2002-2004 Michael D. Stenner, Ryan Tomayko
16 # Copyright 2002-2004 Michael D. Stenner, Ryan Tomayko
17
17
18 # Modified by Benoit Boissinot:
18 # Modified by Benoit Boissinot:
19 # - fix for digest auth (inspired from urllib2.py @ Python v2.4)
19 # - fix for digest auth (inspired from urllib2.py @ Python v2.4)
20 # Modified by Dirkjan Ochtman:
20 # Modified by Dirkjan Ochtman:
21 # - import md5 function from a local util module
21 # - import md5 function from a local util module
22 # Modified by Martin Geisler:
22 # Modified by Martin Geisler:
23 # - moved md5 function from local util module to this module
23 # - moved md5 function from local util module to this module
24 # Modified by Augie Fackler:
24 # Modified by Augie Fackler:
25 # - add safesend method and use it to prevent broken pipe errors
25 # - add safesend method and use it to prevent broken pipe errors
26 # on large POST requests
26 # on large POST requests
27
27
28 """An HTTP handler for urllib2 that supports HTTP 1.1 and keepalive.
28 """An HTTP handler for urllib2 that supports HTTP 1.1 and keepalive.
29
29
30 >>> import urllib2
30 >>> import urllib2
31 >>> from keepalive import HTTPHandler
31 >>> from keepalive import HTTPHandler
32 >>> keepalive_handler = HTTPHandler()
32 >>> keepalive_handler = HTTPHandler()
33 >>> opener = urllib2.build_opener(keepalive_handler)
33 >>> opener = urllib2.build_opener(keepalive_handler)
34 >>> urllib2.install_opener(opener)
34 >>> urllib2.install_opener(opener)
35 >>>
35 >>>
36 >>> fo = urllib2.urlopen('http://www.python.org')
36 >>> fo = urllib2.urlopen('http://www.python.org')
37
37
38 If a connection to a given host is requested, and all of the existing
38 If a connection to a given host is requested, and all of the existing
39 connections are still in use, another connection will be opened. If
39 connections are still in use, another connection will be opened. If
40 the handler tries to use an existing connection but it fails in some
40 the handler tries to use an existing connection but it fails in some
41 way, it will be closed and removed from the pool.
41 way, it will be closed and removed from the pool.
42
42
43 To remove the handler, simply re-run build_opener with no arguments, and
43 To remove the handler, simply re-run build_opener with no arguments, and
44 install that opener.
44 install that opener.
45
45
46 You can explicitly close connections by using the close_connection()
46 You can explicitly close connections by using the close_connection()
47 method of the returned file-like object (described below) or you can
47 method of the returned file-like object (described below) or you can
48 use the handler methods:
48 use the handler methods:
49
49
50 close_connection(host)
50 close_connection(host)
51 close_all()
51 close_all()
52 open_connections()
52 open_connections()
53
53
54 NOTE: using the close_connection and close_all methods of the handler
54 NOTE: using the close_connection and close_all methods of the handler
55 should be done with care when using multiple threads.
55 should be done with care when using multiple threads.
56 * there is nothing that prevents another thread from creating new
56 * there is nothing that prevents another thread from creating new
57 connections immediately after connections are closed
57 connections immediately after connections are closed
58 * no checks are done to prevent in-use connections from being closed
58 * no checks are done to prevent in-use connections from being closed
59
59
60 >>> keepalive_handler.close_all()
60 >>> keepalive_handler.close_all()
61
61
62 EXTRA ATTRIBUTES AND METHODS
62 EXTRA ATTRIBUTES AND METHODS
63
63
64 Upon a status of 200, the object returned has a few additional
64 Upon a status of 200, the object returned has a few additional
65 attributes and methods, which should not be used if you want to
65 attributes and methods, which should not be used if you want to
66 remain consistent with the normal urllib2-returned objects:
66 remain consistent with the normal urllib2-returned objects:
67
67
68 close_connection() - close the connection to the host
68 close_connection() - close the connection to the host
69 readlines() - you know, readlines()
69 readlines() - you know, readlines()
70 status - the return status (ie 404)
70 status - the return status (ie 404)
71 reason - english translation of status (ie 'File not found')
71 reason - english translation of status (ie 'File not found')
72
72
73 If you want the best of both worlds, use this inside an
73 If you want the best of both worlds, use this inside an
74 AttributeError-catching try:
74 AttributeError-catching try:
75
75
76 >>> try: status = fo.status
76 >>> try: status = fo.status
77 >>> except AttributeError: status = None
77 >>> except AttributeError: status = None
78
78
79 Unfortunately, these are ONLY there if status == 200, so it's not
79 Unfortunately, these are ONLY there if status == 200, so it's not
80 easy to distinguish between non-200 responses. The reason is that
80 easy to distinguish between non-200 responses. The reason is that
81 urllib2 tries to do clever things with error codes 301, 302, 401,
81 urllib2 tries to do clever things with error codes 301, 302, 401,
82 and 407, and it wraps the object upon return.
82 and 407, and it wraps the object upon return.
83
83
84 For python versions earlier than 2.4, you can avoid this fancy error
84 For python versions earlier than 2.4, you can avoid this fancy error
85 handling by setting the module-level global HANDLE_ERRORS to zero.
85 handling by setting the module-level global HANDLE_ERRORS to zero.
86 You see, prior to 2.4, it's the HTTP Handler's job to determine what
86 You see, prior to 2.4, it's the HTTP Handler's job to determine what
87 to handle specially, and what to just pass up. HANDLE_ERRORS == 0
87 to handle specially, and what to just pass up. HANDLE_ERRORS == 0
88 means "pass everything up". In python 2.4, however, this job no
88 means "pass everything up". In python 2.4, however, this job no
89 longer belongs to the HTTP Handler and is now done by a NEW handler,
89 longer belongs to the HTTP Handler and is now done by a NEW handler,
90 HTTPErrorProcessor. Here's the bottom line:
90 HTTPErrorProcessor. Here's the bottom line:
91
91
92 python version < 2.4
92 python version < 2.4
93 HANDLE_ERRORS == 1 (default) pass up 200, treat the rest as
93 HANDLE_ERRORS == 1 (default) pass up 200, treat the rest as
94 errors
94 errors
95 HANDLE_ERRORS == 0 pass everything up, error processing is
95 HANDLE_ERRORS == 0 pass everything up, error processing is
96 left to the calling code
96 left to the calling code
97 python version >= 2.4
97 python version >= 2.4
98 HANDLE_ERRORS == 1 pass up 200, treat the rest as errors
98 HANDLE_ERRORS == 1 pass up 200, treat the rest as errors
99 HANDLE_ERRORS == 0 (default) pass everything up, let the
99 HANDLE_ERRORS == 0 (default) pass everything up, let the
100 other handlers (specifically,
100 other handlers (specifically,
101 HTTPErrorProcessor) decide what to do
101 HTTPErrorProcessor) decide what to do
102
102
103 In practice, setting the variable either way makes little difference
103 In practice, setting the variable either way makes little difference
104 in python 2.4, so for the most consistent behavior across versions,
104 in python 2.4, so for the most consistent behavior across versions,
105 you probably just want to use the defaults, which will give you
105 you probably just want to use the defaults, which will give you
106 exceptions on errors.
106 exceptions on errors.
107
107
108 """
108 """
109
109
110 # $Id: keepalive.py,v 1.14 2006/04/04 21:00:32 mstenner Exp $
110 # $Id: keepalive.py,v 1.14 2006/04/04 21:00:32 mstenner Exp $
111
111
112 import errno
112 import errno
113 import httplib
113 import httplib
114 import socket
114 import socket
115 import thread
115 import thread
116 import urllib2
116 import urllib2
117
117
118 DEBUG = None
118 DEBUG = None
119
119
120 import sys
120 import sys
121 if sys.version_info < (2, 4):
121 if sys.version_info < (2, 4):
122 HANDLE_ERRORS = 1
122 HANDLE_ERRORS = 1
123 else: HANDLE_ERRORS = 0
123 else: HANDLE_ERRORS = 0
124
124
125 class ConnectionManager(object):
125 class ConnectionManager(object):
126 """
126 """
127 The connection manager must be able to:
127 The connection manager must be able to:
128 * keep track of all existing
128 * keep track of all existing
129 """
129 """
130 def __init__(self):
130 def __init__(self):
131 self._lock = thread.allocate_lock()
131 self._lock = thread.allocate_lock()
132 self._hostmap = {} # map hosts to a list of connections
132 self._hostmap = {} # map hosts to a list of connections
133 self._connmap = {} # map connections to host
133 self._connmap = {} # map connections to host
134 self._readymap = {} # map connection to ready state
134 self._readymap = {} # map connection to ready state
135
135
136 def add(self, host, connection, ready):
136 def add(self, host, connection, ready):
137 self._lock.acquire()
137 self._lock.acquire()
138 try:
138 try:
139 if host not in self._hostmap:
139 if host not in self._hostmap:
140 self._hostmap[host] = []
140 self._hostmap[host] = []
141 self._hostmap[host].append(connection)
141 self._hostmap[host].append(connection)
142 self._connmap[connection] = host
142 self._connmap[connection] = host
143 self._readymap[connection] = ready
143 self._readymap[connection] = ready
144 finally:
144 finally:
145 self._lock.release()
145 self._lock.release()
146
146
147 def remove(self, connection):
147 def remove(self, connection):
148 self._lock.acquire()
148 self._lock.acquire()
149 try:
149 try:
150 try:
150 try:
151 host = self._connmap[connection]
151 host = self._connmap[connection]
152 except KeyError:
152 except KeyError:
153 pass
153 pass
154 else:
154 else:
155 del self._connmap[connection]
155 del self._connmap[connection]
156 del self._readymap[connection]
156 del self._readymap[connection]
157 self._hostmap[host].remove(connection)
157 self._hostmap[host].remove(connection)
158 if not self._hostmap[host]: del self._hostmap[host]
158 if not self._hostmap[host]: del self._hostmap[host]
159 finally:
159 finally:
160 self._lock.release()
160 self._lock.release()
161
161
162 def set_ready(self, connection, ready):
162 def set_ready(self, connection, ready):
163 try:
163 try:
164 self._readymap[connection] = ready
164 self._readymap[connection] = ready
165 except KeyError:
165 except KeyError:
166 pass
166 pass
167
167
168 def get_ready_conn(self, host):
168 def get_ready_conn(self, host):
169 conn = None
169 conn = None
170 self._lock.acquire()
170 self._lock.acquire()
171 try:
171 try:
172 if host in self._hostmap:
172 if host in self._hostmap:
173 for c in self._hostmap[host]:
173 for c in self._hostmap[host]:
174 if self._readymap[c]:
174 if self._readymap[c]:
175 self._readymap[c] = 0
175 self._readymap[c] = 0
176 conn = c
176 conn = c
177 break
177 break
178 finally:
178 finally:
179 self._lock.release()
179 self._lock.release()
180 return conn
180 return conn
181
181
182 def get_all(self, host=None):
182 def get_all(self, host=None):
183 if host:
183 if host:
184 return list(self._hostmap.get(host, []))
184 return list(self._hostmap.get(host, []))
185 else:
185 else:
186 return dict(self._hostmap)
186 return dict(self._hostmap)
187
187
188 class KeepAliveHandler(object):
188 class KeepAliveHandler(object):
189 def __init__(self):
189 def __init__(self):
190 self._cm = ConnectionManager()
190 self._cm = ConnectionManager()
191
191
192 #### Connection Management
192 #### Connection Management
193 def open_connections(self):
193 def open_connections(self):
194 """return a list of connected hosts and the number of connections
194 """return a list of connected hosts and the number of connections
195 to each. [('foo.com:80', 2), ('bar.org', 1)]"""
195 to each. [('foo.com:80', 2), ('bar.org', 1)]"""
196 return [(host, len(li)) for (host, li) in self._cm.get_all().items()]
196 return [(host, len(li)) for (host, li) in self._cm.get_all().items()]
197
197
198 def close_connection(self, host):
198 def close_connection(self, host):
199 """close connection(s) to <host>
199 """close connection(s) to <host>
200 host is the host:port spec, as in 'www.cnn.com:8080' as passed in.
200 host is the host:port spec, as in 'www.cnn.com:8080' as passed in.
201 no error occurs if there is no connection to that host."""
201 no error occurs if there is no connection to that host."""
202 for h in self._cm.get_all(host):
202 for h in self._cm.get_all(host):
203 self._cm.remove(h)
203 self._cm.remove(h)
204 h.close()
204 h.close()
205
205
206 def close_all(self):
206 def close_all(self):
207 """close all open connections"""
207 """close all open connections"""
208 for host, conns in self._cm.get_all().iteritems():
208 for host, conns in self._cm.get_all().iteritems():
209 for h in conns:
209 for h in conns:
210 self._cm.remove(h)
210 self._cm.remove(h)
211 h.close()
211 h.close()
212
212
213 def _request_closed(self, request, host, connection):
213 def _request_closed(self, request, host, connection):
214 """tells us that this request is now closed and the the
214 """tells us that this request is now closed and that the
215 connection is ready for another request"""
215 connection is ready for another request"""
216 self._cm.set_ready(connection, 1)
216 self._cm.set_ready(connection, 1)
217
217
218 def _remove_connection(self, host, connection, close=0):
218 def _remove_connection(self, host, connection, close=0):
219 if close:
219 if close:
220 connection.close()
220 connection.close()
221 self._cm.remove(connection)
221 self._cm.remove(connection)
222
222
223 #### Transaction Execution
223 #### Transaction Execution
224 def http_open(self, req):
224 def http_open(self, req):
225 return self.do_open(HTTPConnection, req)
225 return self.do_open(HTTPConnection, req)
226
226
227 def do_open(self, http_class, req):
227 def do_open(self, http_class, req):
228 host = req.get_host()
228 host = req.get_host()
229 if not host:
229 if not host:
230 raise urllib2.URLError('no host given')
230 raise urllib2.URLError('no host given')
231
231
232 try:
232 try:
233 h = self._cm.get_ready_conn(host)
233 h = self._cm.get_ready_conn(host)
234 while h:
234 while h:
235 r = self._reuse_connection(h, req, host)
235 r = self._reuse_connection(h, req, host)
236
236
237 # if this response is non-None, then it worked and we're
237 # if this response is non-None, then it worked and we're
238 # done. Break out, skipping the else block.
238 # done. Break out, skipping the else block.
239 if r:
239 if r:
240 break
240 break
241
241
242 # connection is bad - possibly closed by server
242 # connection is bad - possibly closed by server
243 # discard it and ask for the next free connection
243 # discard it and ask for the next free connection
244 h.close()
244 h.close()
245 self._cm.remove(h)
245 self._cm.remove(h)
246 h = self._cm.get_ready_conn(host)
246 h = self._cm.get_ready_conn(host)
247 else:
247 else:
248 # no (working) free connections were found. Create a new one.
248 # no (working) free connections were found. Create a new one.
249 h = http_class(host)
249 h = http_class(host)
250 if DEBUG:
250 if DEBUG:
251 DEBUG.info("creating new connection to %s (%d)",
251 DEBUG.info("creating new connection to %s (%d)",
252 host, id(h))
252 host, id(h))
253 self._cm.add(host, h, 0)
253 self._cm.add(host, h, 0)
254 self._start_transaction(h, req)
254 self._start_transaction(h, req)
255 r = h.getresponse()
255 r = h.getresponse()
256 except (socket.error, httplib.HTTPException), err:
256 except (socket.error, httplib.HTTPException), err:
257 raise urllib2.URLError(err)
257 raise urllib2.URLError(err)
258
258
259 # if not a persistent connection, don't try to reuse it
259 # if not a persistent connection, don't try to reuse it
260 if r.will_close:
260 if r.will_close:
261 self._cm.remove(h)
261 self._cm.remove(h)
262
262
263 if DEBUG:
263 if DEBUG:
264 DEBUG.info("STATUS: %s, %s", r.status, r.reason)
264 DEBUG.info("STATUS: %s, %s", r.status, r.reason)
265 r._handler = self
265 r._handler = self
266 r._host = host
266 r._host = host
267 r._url = req.get_full_url()
267 r._url = req.get_full_url()
268 r._connection = h
268 r._connection = h
269 r.code = r.status
269 r.code = r.status
270 r.headers = r.msg
270 r.headers = r.msg
271 r.msg = r.reason
271 r.msg = r.reason
272
272
273 if r.status == 200 or not HANDLE_ERRORS:
273 if r.status == 200 or not HANDLE_ERRORS:
274 return r
274 return r
275 else:
275 else:
276 return self.parent.error('http', req, r,
276 return self.parent.error('http', req, r,
277 r.status, r.msg, r.headers)
277 r.status, r.msg, r.headers)
278
278
279 def _reuse_connection(self, h, req, host):
279 def _reuse_connection(self, h, req, host):
280 """start the transaction with a re-used connection
280 """start the transaction with a re-used connection
281 return a response object (r) upon success or None on failure.
281 return a response object (r) upon success or None on failure.
282 This DOES not close or remove bad connections in cases where
282 This DOES not close or remove bad connections in cases where
283 it returns. However, if an unexpected exception occurs, it
283 it returns. However, if an unexpected exception occurs, it
284 will close and remove the connection before re-raising.
284 will close and remove the connection before re-raising.
285 """
285 """
286 try:
286 try:
287 self._start_transaction(h, req)
287 self._start_transaction(h, req)
288 r = h.getresponse()
288 r = h.getresponse()
289 # note: just because we got something back doesn't mean it
289 # note: just because we got something back doesn't mean it
290 # worked. We'll check the version below, too.
290 # worked. We'll check the version below, too.
291 except (socket.error, httplib.HTTPException):
291 except (socket.error, httplib.HTTPException):
292 r = None
292 r = None
293 except: # re-raises
293 except: # re-raises
294 # adding this block just in case we've missed
294 # adding this block just in case we've missed
295 # something we will still raise the exception, but
295 # something we will still raise the exception, but
296 # lets try and close the connection and remove it
296 # lets try and close the connection and remove it
297 # first. We previously got into a nasty loop
297 # first. We previously got into a nasty loop
298 # where an exception was uncaught, and so the
298 # where an exception was uncaught, and so the
299 # connection stayed open. On the next try, the
299 # connection stayed open. On the next try, the
300 # same exception was raised, etc. The tradeoff is
300 # same exception was raised, etc. The tradeoff is
301 # that it's now possible this call will raise
301 # that it's now possible this call will raise
302 # a DIFFERENT exception
302 # a DIFFERENT exception
303 if DEBUG:
303 if DEBUG:
304 DEBUG.error("unexpected exception - closing "
304 DEBUG.error("unexpected exception - closing "
305 "connection to %s (%d)", host, id(h))
305 "connection to %s (%d)", host, id(h))
306 self._cm.remove(h)
306 self._cm.remove(h)
307 h.close()
307 h.close()
308 raise
308 raise
309
309
310 if r is None or r.version == 9:
310 if r is None or r.version == 9:
311 # httplib falls back to assuming HTTP 0.9 if it gets a
311 # httplib falls back to assuming HTTP 0.9 if it gets a
312 # bad header back. This is most likely to happen if
312 # bad header back. This is most likely to happen if
313 # the socket has been closed by the server since we
313 # the socket has been closed by the server since we
314 # last used the connection.
314 # last used the connection.
315 if DEBUG:
315 if DEBUG:
316 DEBUG.info("failed to re-use connection to %s (%d)",
316 DEBUG.info("failed to re-use connection to %s (%d)",
317 host, id(h))
317 host, id(h))
318 r = None
318 r = None
319 else:
319 else:
320 if DEBUG:
320 if DEBUG:
321 DEBUG.info("re-using connection to %s (%d)", host, id(h))
321 DEBUG.info("re-using connection to %s (%d)", host, id(h))
322
322
323 return r
323 return r
324
324
325 def _start_transaction(self, h, req):
325 def _start_transaction(self, h, req):
326 # What follows mostly reimplements HTTPConnection.request()
326 # What follows mostly reimplements HTTPConnection.request()
327 # except it adds self.parent.addheaders in the mix.
327 # except it adds self.parent.addheaders in the mix.
328 headers = req.headers.copy()
328 headers = req.headers.copy()
329 if sys.version_info >= (2, 4):
329 if sys.version_info >= (2, 4):
330 headers.update(req.unredirected_hdrs)
330 headers.update(req.unredirected_hdrs)
331 headers.update(self.parent.addheaders)
331 headers.update(self.parent.addheaders)
332 headers = dict((n.lower(), v) for n, v in headers.items())
332 headers = dict((n.lower(), v) for n, v in headers.items())
333 skipheaders = {}
333 skipheaders = {}
334 for n in ('host', 'accept-encoding'):
334 for n in ('host', 'accept-encoding'):
335 if n in headers:
335 if n in headers:
336 skipheaders['skip_' + n.replace('-', '_')] = 1
336 skipheaders['skip_' + n.replace('-', '_')] = 1
337 try:
337 try:
338 if req.has_data():
338 if req.has_data():
339 data = req.get_data()
339 data = req.get_data()
340 h.putrequest('POST', req.get_selector(), **skipheaders)
340 h.putrequest('POST', req.get_selector(), **skipheaders)
341 if 'content-type' not in headers:
341 if 'content-type' not in headers:
342 h.putheader('Content-type',
342 h.putheader('Content-type',
343 'application/x-www-form-urlencoded')
343 'application/x-www-form-urlencoded')
344 if 'content-length' not in headers:
344 if 'content-length' not in headers:
345 h.putheader('Content-length', '%d' % len(data))
345 h.putheader('Content-length', '%d' % len(data))
346 else:
346 else:
347 h.putrequest('GET', req.get_selector(), **skipheaders)
347 h.putrequest('GET', req.get_selector(), **skipheaders)
348 except (socket.error), err:
348 except (socket.error), err:
349 raise urllib2.URLError(err)
349 raise urllib2.URLError(err)
350 for k, v in headers.items():
350 for k, v in headers.items():
351 h.putheader(k, v)
351 h.putheader(k, v)
352 h.endheaders()
352 h.endheaders()
353 if req.has_data():
353 if req.has_data():
354 h.send(data)
354 h.send(data)
355
355
356 class HTTPHandler(KeepAliveHandler, urllib2.HTTPHandler):
356 class HTTPHandler(KeepAliveHandler, urllib2.HTTPHandler):
357 pass
357 pass
358
358
359 class HTTPResponse(httplib.HTTPResponse):
359 class HTTPResponse(httplib.HTTPResponse):
360 # we need to subclass HTTPResponse in order to
360 # we need to subclass HTTPResponse in order to
361 # 1) add readline() and readlines() methods
361 # 1) add readline() and readlines() methods
362 # 2) add close_connection() methods
362 # 2) add close_connection() methods
363 # 3) add info() and geturl() methods
363 # 3) add info() and geturl() methods
364
364
365 # in order to add readline(), read must be modified to deal with a
365 # in order to add readline(), read must be modified to deal with a
366 # buffer. example: readline must read a buffer and then spit back
366 # buffer. example: readline must read a buffer and then spit back
367 # one line at a time. The only real alternative is to read one
367 # one line at a time. The only real alternative is to read one
368 # BYTE at a time (ick). Once something has been read, it can't be
368 # BYTE at a time (ick). Once something has been read, it can't be
369 # put back (ok, maybe it can, but that's even uglier than this),
369 # put back (ok, maybe it can, but that's even uglier than this),
370 # so if you THEN do a normal read, you must first take stuff from
370 # so if you THEN do a normal read, you must first take stuff from
371 # the buffer.
371 # the buffer.
372
372
373 # the read method wraps the original to accomodate buffering,
373 # the read method wraps the original to accomodate buffering,
374 # although read() never adds to the buffer.
374 # although read() never adds to the buffer.
375 # Both readline and readlines have been stolen with almost no
375 # Both readline and readlines have been stolen with almost no
376 # modification from socket.py
376 # modification from socket.py
377
377
378
378
379 def __init__(self, sock, debuglevel=0, strict=0, method=None):
379 def __init__(self, sock, debuglevel=0, strict=0, method=None):
380 if method: # the httplib in python 2.3 uses the method arg
380 if method: # the httplib in python 2.3 uses the method arg
381 httplib.HTTPResponse.__init__(self, sock, debuglevel, method)
381 httplib.HTTPResponse.__init__(self, sock, debuglevel, method)
382 else: # 2.2 doesn't
382 else: # 2.2 doesn't
383 httplib.HTTPResponse.__init__(self, sock, debuglevel)
383 httplib.HTTPResponse.__init__(self, sock, debuglevel)
384 self.fileno = sock.fileno
384 self.fileno = sock.fileno
385 self.code = None
385 self.code = None
386 self._rbuf = ''
386 self._rbuf = ''
387 self._rbufsize = 8096
387 self._rbufsize = 8096
388 self._handler = None # inserted by the handler later
388 self._handler = None # inserted by the handler later
389 self._host = None # (same)
389 self._host = None # (same)
390 self._url = None # (same)
390 self._url = None # (same)
391 self._connection = None # (same)
391 self._connection = None # (same)
392
392
393 _raw_read = httplib.HTTPResponse.read
393 _raw_read = httplib.HTTPResponse.read
394
394
395 def close(self):
395 def close(self):
396 if self.fp:
396 if self.fp:
397 self.fp.close()
397 self.fp.close()
398 self.fp = None
398 self.fp = None
399 if self._handler:
399 if self._handler:
400 self._handler._request_closed(self, self._host,
400 self._handler._request_closed(self, self._host,
401 self._connection)
401 self._connection)
402
402
403 def close_connection(self):
403 def close_connection(self):
404 self._handler._remove_connection(self._host, self._connection, close=1)
404 self._handler._remove_connection(self._host, self._connection, close=1)
405 self.close()
405 self.close()
406
406
407 def info(self):
407 def info(self):
408 return self.headers
408 return self.headers
409
409
410 def geturl(self):
410 def geturl(self):
411 return self._url
411 return self._url
412
412
413 def read(self, amt=None):
413 def read(self, amt=None):
414 # the _rbuf test is only in this first if for speed. It's not
414 # the _rbuf test is only in this first if for speed. It's not
415 # logically necessary
415 # logically necessary
416 if self._rbuf and not amt is None:
416 if self._rbuf and not amt is None:
417 L = len(self._rbuf)
417 L = len(self._rbuf)
418 if amt > L:
418 if amt > L:
419 amt -= L
419 amt -= L
420 else:
420 else:
421 s = self._rbuf[:amt]
421 s = self._rbuf[:amt]
422 self._rbuf = self._rbuf[amt:]
422 self._rbuf = self._rbuf[amt:]
423 return s
423 return s
424
424
425 s = self._rbuf + self._raw_read(amt)
425 s = self._rbuf + self._raw_read(amt)
426 self._rbuf = ''
426 self._rbuf = ''
427 return s
427 return s
428
428
429 # stolen from Python SVN #68532 to fix issue1088
429 # stolen from Python SVN #68532 to fix issue1088
430 def _read_chunked(self, amt):
430 def _read_chunked(self, amt):
431 chunk_left = self.chunk_left
431 chunk_left = self.chunk_left
432 value = ''
432 value = ''
433
433
434 # XXX This accumulates chunks by repeated string concatenation,
434 # XXX This accumulates chunks by repeated string concatenation,
435 # which is not efficient as the number or size of chunks gets big.
435 # which is not efficient as the number or size of chunks gets big.
436 while True:
436 while True:
437 if chunk_left is None:
437 if chunk_left is None:
438 line = self.fp.readline()
438 line = self.fp.readline()
439 i = line.find(';')
439 i = line.find(';')
440 if i >= 0:
440 if i >= 0:
441 line = line[:i] # strip chunk-extensions
441 line = line[:i] # strip chunk-extensions
442 try:
442 try:
443 chunk_left = int(line, 16)
443 chunk_left = int(line, 16)
444 except ValueError:
444 except ValueError:
445 # close the connection as protocol synchronisation is
445 # close the connection as protocol synchronisation is
446 # probably lost
446 # probably lost
447 self.close()
447 self.close()
448 raise httplib.IncompleteRead(value)
448 raise httplib.IncompleteRead(value)
449 if chunk_left == 0:
449 if chunk_left == 0:
450 break
450 break
451 if amt is None:
451 if amt is None:
452 value += self._safe_read(chunk_left)
452 value += self._safe_read(chunk_left)
453 elif amt < chunk_left:
453 elif amt < chunk_left:
454 value += self._safe_read(amt)
454 value += self._safe_read(amt)
455 self.chunk_left = chunk_left - amt
455 self.chunk_left = chunk_left - amt
456 return value
456 return value
457 elif amt == chunk_left:
457 elif amt == chunk_left:
458 value += self._safe_read(amt)
458 value += self._safe_read(amt)
459 self._safe_read(2) # toss the CRLF at the end of the chunk
459 self._safe_read(2) # toss the CRLF at the end of the chunk
460 self.chunk_left = None
460 self.chunk_left = None
461 return value
461 return value
462 else:
462 else:
463 value += self._safe_read(chunk_left)
463 value += self._safe_read(chunk_left)
464 amt -= chunk_left
464 amt -= chunk_left
465
465
466 # we read the whole chunk, get another
466 # we read the whole chunk, get another
467 self._safe_read(2) # toss the CRLF at the end of the chunk
467 self._safe_read(2) # toss the CRLF at the end of the chunk
468 chunk_left = None
468 chunk_left = None
469
469
470 # read and discard trailer up to the CRLF terminator
470 # read and discard trailer up to the CRLF terminator
471 ### note: we shouldn't have any trailers!
471 ### note: we shouldn't have any trailers!
472 while True:
472 while True:
473 line = self.fp.readline()
473 line = self.fp.readline()
474 if not line:
474 if not line:
475 # a vanishingly small number of sites EOF without
475 # a vanishingly small number of sites EOF without
476 # sending the trailer
476 # sending the trailer
477 break
477 break
478 if line == '\r\n':
478 if line == '\r\n':
479 break
479 break
480
480
481 # we read everything; close the "file"
481 # we read everything; close the "file"
482 self.close()
482 self.close()
483
483
484 return value
484 return value
485
485
486 def readline(self, limit=-1):
486 def readline(self, limit=-1):
487 i = self._rbuf.find('\n')
487 i = self._rbuf.find('\n')
488 while i < 0 and not (0 < limit <= len(self._rbuf)):
488 while i < 0 and not (0 < limit <= len(self._rbuf)):
489 new = self._raw_read(self._rbufsize)
489 new = self._raw_read(self._rbufsize)
490 if not new:
490 if not new:
491 break
491 break
492 i = new.find('\n')
492 i = new.find('\n')
493 if i >= 0:
493 if i >= 0:
494 i = i + len(self._rbuf)
494 i = i + len(self._rbuf)
495 self._rbuf = self._rbuf + new
495 self._rbuf = self._rbuf + new
496 if i < 0:
496 if i < 0:
497 i = len(self._rbuf)
497 i = len(self._rbuf)
498 else:
498 else:
499 i = i + 1
499 i = i + 1
500 if 0 <= limit < len(self._rbuf):
500 if 0 <= limit < len(self._rbuf):
501 i = limit
501 i = limit
502 data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
502 data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
503 return data
503 return data
504
504
505 def readlines(self, sizehint = 0):
505 def readlines(self, sizehint = 0):
506 total = 0
506 total = 0
507 list = []
507 list = []
508 while True:
508 while True:
509 line = self.readline()
509 line = self.readline()
510 if not line:
510 if not line:
511 break
511 break
512 list.append(line)
512 list.append(line)
513 total += len(line)
513 total += len(line)
514 if sizehint and total >= sizehint:
514 if sizehint and total >= sizehint:
515 break
515 break
516 return list
516 return list
517
517
518 def safesend(self, str):
518 def safesend(self, str):
519 """Send `str' to the server.
519 """Send `str' to the server.
520
520
521 Shamelessly ripped off from httplib to patch a bad behavior.
521 Shamelessly ripped off from httplib to patch a bad behavior.
522 """
522 """
523 # _broken_pipe_resp is an attribute we set in this function
523 # _broken_pipe_resp is an attribute we set in this function
524 # if the socket is closed while we're sending data but
524 # if the socket is closed while we're sending data but
525 # the server sent us a response before hanging up.
525 # the server sent us a response before hanging up.
526 # In that case, we want to pretend to send the rest of the
526 # In that case, we want to pretend to send the rest of the
527 # outgoing data, and then let the user use getresponse()
527 # outgoing data, and then let the user use getresponse()
528 # (which we wrap) to get this last response before
528 # (which we wrap) to get this last response before
529 # opening a new socket.
529 # opening a new socket.
530 if getattr(self, '_broken_pipe_resp', None) is not None:
530 if getattr(self, '_broken_pipe_resp', None) is not None:
531 return
531 return
532
532
533 if self.sock is None:
533 if self.sock is None:
534 if self.auto_open:
534 if self.auto_open:
535 self.connect()
535 self.connect()
536 else:
536 else:
537 raise httplib.NotConnected
537 raise httplib.NotConnected
538
538
539 # send the data to the server. if we get a broken pipe, then close
539 # send the data to the server. if we get a broken pipe, then close
540 # the socket. we want to reconnect when somebody tries to send again.
540 # the socket. we want to reconnect when somebody tries to send again.
541 #
541 #
542 # NOTE: we DO propagate the error, though, because we cannot simply
542 # NOTE: we DO propagate the error, though, because we cannot simply
543 # ignore the error... the caller will know if they can retry.
543 # ignore the error... the caller will know if they can retry.
544 if self.debuglevel > 0:
544 if self.debuglevel > 0:
545 print "send:", repr(str)
545 print "send:", repr(str)
546 try:
546 try:
547 blocksize = 8192
547 blocksize = 8192
548 read = getattr(str, 'read', None)
548 read = getattr(str, 'read', None)
549 if read is not None:
549 if read is not None:
550 if self.debuglevel > 0:
550 if self.debuglevel > 0:
551 print "sendIng a read()able"
551 print "sendIng a read()able"
552 data = read(blocksize)
552 data = read(blocksize)
553 while data:
553 while data:
554 self.sock.sendall(data)
554 self.sock.sendall(data)
555 data = read(blocksize)
555 data = read(blocksize)
556 else:
556 else:
557 self.sock.sendall(str)
557 self.sock.sendall(str)
558 except socket.error, v:
558 except socket.error, v:
559 reraise = True
559 reraise = True
560 if v[0] == errno.EPIPE: # Broken pipe
560 if v[0] == errno.EPIPE: # Broken pipe
561 if self._HTTPConnection__state == httplib._CS_REQ_SENT:
561 if self._HTTPConnection__state == httplib._CS_REQ_SENT:
562 self._broken_pipe_resp = None
562 self._broken_pipe_resp = None
563 self._broken_pipe_resp = self.getresponse()
563 self._broken_pipe_resp = self.getresponse()
564 reraise = False
564 reraise = False
565 self.close()
565 self.close()
566 if reraise:
566 if reraise:
567 raise
567 raise
568
568
569 def wrapgetresponse(cls):
569 def wrapgetresponse(cls):
570 """Wraps getresponse in cls with a broken-pipe sane version.
570 """Wraps getresponse in cls with a broken-pipe sane version.
571 """
571 """
572 def safegetresponse(self):
572 def safegetresponse(self):
573 # In safesend() we might set the _broken_pipe_resp
573 # In safesend() we might set the _broken_pipe_resp
574 # attribute, in which case the socket has already
574 # attribute, in which case the socket has already
575 # been closed and we just need to give them the response
575 # been closed and we just need to give them the response
576 # back. Otherwise, we use the normal response path.
576 # back. Otherwise, we use the normal response path.
577 r = getattr(self, '_broken_pipe_resp', None)
577 r = getattr(self, '_broken_pipe_resp', None)
578 if r is not None:
578 if r is not None:
579 return r
579 return r
580 return cls.getresponse(self)
580 return cls.getresponse(self)
581 safegetresponse.__doc__ = cls.getresponse.__doc__
581 safegetresponse.__doc__ = cls.getresponse.__doc__
582 return safegetresponse
582 return safegetresponse
583
583
584 class HTTPConnection(httplib.HTTPConnection):
584 class HTTPConnection(httplib.HTTPConnection):
585 # use the modified response class
585 # use the modified response class
586 response_class = HTTPResponse
586 response_class = HTTPResponse
587 send = safesend
587 send = safesend
588 getresponse = wrapgetresponse(httplib.HTTPConnection)
588 getresponse = wrapgetresponse(httplib.HTTPConnection)
589
589
590
590
591 #########################################################################
591 #########################################################################
592 ##### TEST FUNCTIONS
592 ##### TEST FUNCTIONS
593 #########################################################################
593 #########################################################################
594
594
595 def error_handler(url):
595 def error_handler(url):
596 global HANDLE_ERRORS
596 global HANDLE_ERRORS
597 orig = HANDLE_ERRORS
597 orig = HANDLE_ERRORS
598 keepalive_handler = HTTPHandler()
598 keepalive_handler = HTTPHandler()
599 opener = urllib2.build_opener(keepalive_handler)
599 opener = urllib2.build_opener(keepalive_handler)
600 urllib2.install_opener(opener)
600 urllib2.install_opener(opener)
601 pos = {0: 'off', 1: 'on'}
601 pos = {0: 'off', 1: 'on'}
602 for i in (0, 1):
602 for i in (0, 1):
603 print " fancy error handling %s (HANDLE_ERRORS = %i)" % (pos[i], i)
603 print " fancy error handling %s (HANDLE_ERRORS = %i)" % (pos[i], i)
604 HANDLE_ERRORS = i
604 HANDLE_ERRORS = i
605 try:
605 try:
606 fo = urllib2.urlopen(url)
606 fo = urllib2.urlopen(url)
607 fo.read()
607 fo.read()
608 fo.close()
608 fo.close()
609 try:
609 try:
610 status, reason = fo.status, fo.reason
610 status, reason = fo.status, fo.reason
611 except AttributeError:
611 except AttributeError:
612 status, reason = None, None
612 status, reason = None, None
613 except IOError, e:
613 except IOError, e:
614 print " EXCEPTION: %s" % e
614 print " EXCEPTION: %s" % e
615 raise
615 raise
616 else:
616 else:
617 print " status = %s, reason = %s" % (status, reason)
617 print " status = %s, reason = %s" % (status, reason)
618 HANDLE_ERRORS = orig
618 HANDLE_ERRORS = orig
619 hosts = keepalive_handler.open_connections()
619 hosts = keepalive_handler.open_connections()
620 print "open connections:", hosts
620 print "open connections:", hosts
621 keepalive_handler.close_all()
621 keepalive_handler.close_all()
622
622
623 def md5(s):
623 def md5(s):
624 try:
624 try:
625 from hashlib import md5 as _md5
625 from hashlib import md5 as _md5
626 except ImportError:
626 except ImportError:
627 from md5 import md5 as _md5
627 from md5 import md5 as _md5
628 global md5
628 global md5
629 md5 = _md5
629 md5 = _md5
630 return _md5(s)
630 return _md5(s)
631
631
632 def continuity(url):
632 def continuity(url):
633 format = '%25s: %s'
633 format = '%25s: %s'
634
634
635 # first fetch the file with the normal http handler
635 # first fetch the file with the normal http handler
636 opener = urllib2.build_opener()
636 opener = urllib2.build_opener()
637 urllib2.install_opener(opener)
637 urllib2.install_opener(opener)
638 fo = urllib2.urlopen(url)
638 fo = urllib2.urlopen(url)
639 foo = fo.read()
639 foo = fo.read()
640 fo.close()
640 fo.close()
641 m = md5.new(foo)
641 m = md5.new(foo)
642 print format % ('normal urllib', m.hexdigest())
642 print format % ('normal urllib', m.hexdigest())
643
643
644 # now install the keepalive handler and try again
644 # now install the keepalive handler and try again
645 opener = urllib2.build_opener(HTTPHandler())
645 opener = urllib2.build_opener(HTTPHandler())
646 urllib2.install_opener(opener)
646 urllib2.install_opener(opener)
647
647
648 fo = urllib2.urlopen(url)
648 fo = urllib2.urlopen(url)
649 foo = fo.read()
649 foo = fo.read()
650 fo.close()
650 fo.close()
651 m = md5.new(foo)
651 m = md5.new(foo)
652 print format % ('keepalive read', m.hexdigest())
652 print format % ('keepalive read', m.hexdigest())
653
653
654 fo = urllib2.urlopen(url)
654 fo = urllib2.urlopen(url)
655 foo = ''
655 foo = ''
656 while True:
656 while True:
657 f = fo.readline()
657 f = fo.readline()
658 if f:
658 if f:
659 foo = foo + f
659 foo = foo + f
660 else: break
660 else: break
661 fo.close()
661 fo.close()
662 m = md5.new(foo)
662 m = md5.new(foo)
663 print format % ('keepalive readline', m.hexdigest())
663 print format % ('keepalive readline', m.hexdigest())
664
664
665 def comp(N, url):
665 def comp(N, url):
666 print ' making %i connections to:\n %s' % (N, url)
666 print ' making %i connections to:\n %s' % (N, url)
667
667
668 sys.stdout.write(' first using the normal urllib handlers')
668 sys.stdout.write(' first using the normal urllib handlers')
669 # first use normal opener
669 # first use normal opener
670 opener = urllib2.build_opener()
670 opener = urllib2.build_opener()
671 urllib2.install_opener(opener)
671 urllib2.install_opener(opener)
672 t1 = fetch(N, url)
672 t1 = fetch(N, url)
673 print ' TIME: %.3f s' % t1
673 print ' TIME: %.3f s' % t1
674
674
675 sys.stdout.write(' now using the keepalive handler ')
675 sys.stdout.write(' now using the keepalive handler ')
676 # now install the keepalive handler and try again
676 # now install the keepalive handler and try again
677 opener = urllib2.build_opener(HTTPHandler())
677 opener = urllib2.build_opener(HTTPHandler())
678 urllib2.install_opener(opener)
678 urllib2.install_opener(opener)
679 t2 = fetch(N, url)
679 t2 = fetch(N, url)
680 print ' TIME: %.3f s' % t2
680 print ' TIME: %.3f s' % t2
681 print ' improvement factor: %.2f' % (t1 / t2)
681 print ' improvement factor: %.2f' % (t1 / t2)
682
682
683 def fetch(N, url, delay=0):
683 def fetch(N, url, delay=0):
684 import time
684 import time
685 lens = []
685 lens = []
686 starttime = time.time()
686 starttime = time.time()
687 for i in range(N):
687 for i in range(N):
688 if delay and i > 0:
688 if delay and i > 0:
689 time.sleep(delay)
689 time.sleep(delay)
690 fo = urllib2.urlopen(url)
690 fo = urllib2.urlopen(url)
691 foo = fo.read()
691 foo = fo.read()
692 fo.close()
692 fo.close()
693 lens.append(len(foo))
693 lens.append(len(foo))
694 diff = time.time() - starttime
694 diff = time.time() - starttime
695
695
696 j = 0
696 j = 0
697 for i in lens[1:]:
697 for i in lens[1:]:
698 j = j + 1
698 j = j + 1
699 if not i == lens[0]:
699 if not i == lens[0]:
700 print "WARNING: inconsistent length on read %i: %i" % (j, i)
700 print "WARNING: inconsistent length on read %i: %i" % (j, i)
701
701
702 return diff
702 return diff
703
703
704 def test_timeout(url):
704 def test_timeout(url):
705 global DEBUG
705 global DEBUG
706 dbbackup = DEBUG
706 dbbackup = DEBUG
707 class FakeLogger(object):
707 class FakeLogger(object):
708 def debug(self, msg, *args):
708 def debug(self, msg, *args):
709 print msg % args
709 print msg % args
710 info = warning = error = debug
710 info = warning = error = debug
711 DEBUG = FakeLogger()
711 DEBUG = FakeLogger()
712 print " fetching the file to establish a connection"
712 print " fetching the file to establish a connection"
713 fo = urllib2.urlopen(url)
713 fo = urllib2.urlopen(url)
714 data1 = fo.read()
714 data1 = fo.read()
715 fo.close()
715 fo.close()
716
716
717 i = 20
717 i = 20
718 print " waiting %i seconds for the server to close the connection" % i
718 print " waiting %i seconds for the server to close the connection" % i
719 while i > 0:
719 while i > 0:
720 sys.stdout.write('\r %2i' % i)
720 sys.stdout.write('\r %2i' % i)
721 sys.stdout.flush()
721 sys.stdout.flush()
722 time.sleep(1)
722 time.sleep(1)
723 i -= 1
723 i -= 1
724 sys.stderr.write('\r')
724 sys.stderr.write('\r')
725
725
726 print " fetching the file a second time"
726 print " fetching the file a second time"
727 fo = urllib2.urlopen(url)
727 fo = urllib2.urlopen(url)
728 data2 = fo.read()
728 data2 = fo.read()
729 fo.close()
729 fo.close()
730
730
731 if data1 == data2:
731 if data1 == data2:
732 print ' data are identical'
732 print ' data are identical'
733 else:
733 else:
734 print ' ERROR: DATA DIFFER'
734 print ' ERROR: DATA DIFFER'
735
735
736 DEBUG = dbbackup
736 DEBUG = dbbackup
737
737
738
738
739 def test(url, N=10):
739 def test(url, N=10):
740 print "checking error hander (do this on a non-200)"
740 print "checking error hander (do this on a non-200)"
741 try: error_handler(url)
741 try: error_handler(url)
742 except IOError:
742 except IOError:
743 print "exiting - exception will prevent further tests"
743 print "exiting - exception will prevent further tests"
744 sys.exit()
744 sys.exit()
745 print
745 print
746 print "performing continuity test (making sure stuff isn't corrupted)"
746 print "performing continuity test (making sure stuff isn't corrupted)"
747 continuity(url)
747 continuity(url)
748 print
748 print
749 print "performing speed comparison"
749 print "performing speed comparison"
750 comp(N, url)
750 comp(N, url)
751 print
751 print
752 print "performing dropped-connection check"
752 print "performing dropped-connection check"
753 test_timeout(url)
753 test_timeout(url)
754
754
755 if __name__ == '__main__':
755 if __name__ == '__main__':
756 import time
756 import time
757 import sys
757 import sys
758 try:
758 try:
759 N = int(sys.argv[1])
759 N = int(sys.argv[1])
760 url = sys.argv[2]
760 url = sys.argv[2]
761 except (IndexError, ValueError):
761 except (IndexError, ValueError):
762 print "%s <integer> <url>" % sys.argv[0]
762 print "%s <integer> <url>" % sys.argv[0]
763 else:
763 else:
764 test(url, N)
764 test(url, N)
@@ -1,447 +1,447 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > convert=
3 > convert=
4 > [convert]
4 > [convert]
5 > hg.saverev=False
5 > hg.saverev=False
6 > EOF
6 > EOF
7 $ hg help convert
7 $ hg help convert
8 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
8 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
9
9
10 convert a foreign SCM repository to a Mercurial one.
10 convert a foreign SCM repository to a Mercurial one.
11
11
12 Accepted source formats [identifiers]:
12 Accepted source formats [identifiers]:
13
13
14 - Mercurial [hg]
14 - Mercurial [hg]
15 - CVS [cvs]
15 - CVS [cvs]
16 - Darcs [darcs]
16 - Darcs [darcs]
17 - git [git]
17 - git [git]
18 - Subversion [svn]
18 - Subversion [svn]
19 - Monotone [mtn]
19 - Monotone [mtn]
20 - GNU Arch [gnuarch]
20 - GNU Arch [gnuarch]
21 - Bazaar [bzr]
21 - Bazaar [bzr]
22 - Perforce [p4]
22 - Perforce [p4]
23
23
24 Accepted destination formats [identifiers]:
24 Accepted destination formats [identifiers]:
25
25
26 - Mercurial [hg]
26 - Mercurial [hg]
27 - Subversion [svn] (history on branches is not preserved)
27 - Subversion [svn] (history on branches is not preserved)
28
28
29 If no revision is given, all revisions will be converted. Otherwise,
29 If no revision is given, all revisions will be converted. Otherwise,
30 convert will only import up to the named revision (given in a format
30 convert will only import up to the named revision (given in a format
31 understood by the source).
31 understood by the source).
32
32
33 If no destination directory name is specified, it defaults to the basename
33 If no destination directory name is specified, it defaults to the basename
34 of the source with "-hg" appended. If the destination repository doesn't
34 of the source with "-hg" appended. If the destination repository doesn't
35 exist, it will be created.
35 exist, it will be created.
36
36
37 By default, all sources except Mercurial will use --branchsort. Mercurial
37 By default, all sources except Mercurial will use --branchsort. Mercurial
38 uses --sourcesort to preserve original revision numbers order. Sort modes
38 uses --sourcesort to preserve original revision numbers order. Sort modes
39 have the following effects:
39 have the following effects:
40
40
41 --branchsort convert from parent to child revision when possible, which
41 --branchsort convert from parent to child revision when possible, which
42 means branches are usually converted one after the other.
42 means branches are usually converted one after the other.
43 It generates more compact repositories.
43 It generates more compact repositories.
44 --datesort sort revisions by date. Converted repositories have good-
44 --datesort sort revisions by date. Converted repositories have good-
45 looking changelogs but are often an order of magnitude
45 looking changelogs but are often an order of magnitude
46 larger than the same ones generated by --branchsort.
46 larger than the same ones generated by --branchsort.
47 --sourcesort try to preserve source revisions order, only supported by
47 --sourcesort try to preserve source revisions order, only supported by
48 Mercurial sources.
48 Mercurial sources.
49
49
50 If "REVMAP" isn't given, it will be put in a default location
50 If "REVMAP" isn't given, it will be put in a default location
51 ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
51 ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
52 maps each source commit ID to the destination ID for that revision, like
52 maps each source commit ID to the destination ID for that revision, like
53 so:
53 so:
54
54
55 <source ID> <destination ID>
55 <source ID> <destination ID>
56
56
57 If the file doesn't exist, it's automatically created. It's updated on
57 If the file doesn't exist, it's automatically created. It's updated on
58 each commit copied, so "hg convert" can be interrupted and can be run
58 each commit copied, so "hg convert" can be interrupted and can be run
59 repeatedly to copy new commits.
59 repeatedly to copy new commits.
60
60
61 The authormap is a simple text file that maps each source commit author to
61 The authormap is a simple text file that maps each source commit author to
62 a destination commit author. It is handy for source SCMs that use unix
62 a destination commit author. It is handy for source SCMs that use unix
63 logins to identify authors (eg: CVS). One line per author mapping and the
63 logins to identify authors (eg: CVS). One line per author mapping and the
64 line format is:
64 line format is:
65
65
66 source author = destination author
66 source author = destination author
67
67
68 Empty lines and lines starting with a "#" are ignored.
68 Empty lines and lines starting with a "#" are ignored.
69
69
70 The filemap is a file that allows filtering and remapping of files and
70 The filemap is a file that allows filtering and remapping of files and
71 directories. Each line can contain one of the following directives:
71 directories. Each line can contain one of the following directives:
72
72
73 include path/to/file-or-dir
73 include path/to/file-or-dir
74
74
75 exclude path/to/file-or-dir
75 exclude path/to/file-or-dir
76
76
77 rename path/to/source path/to/destination
77 rename path/to/source path/to/destination
78
78
79 Comment lines start with "#". A specified path matches if it equals the
79 Comment lines start with "#". A specified path matches if it equals the
80 full relative name of a file or one of its parent directories. The
80 full relative name of a file or one of its parent directories. The
81 "include" or "exclude" directive with the longest matching path applies,
81 "include" or "exclude" directive with the longest matching path applies,
82 so line order does not matter.
82 so line order does not matter.
83
83
84 The "include" directive causes a file, or all files under a directory, to
84 The "include" directive causes a file, or all files under a directory, to
85 be included in the destination repository, and the exclusion of all other
85 be included in the destination repository, and the exclusion of all other
86 files and directories not explicitly included. The "exclude" directive
86 files and directories not explicitly included. The "exclude" directive
87 causes files or directories to be omitted. The "rename" directive renames
87 causes files or directories to be omitted. The "rename" directive renames
88 a file or directory if it is converted. To rename from a subdirectory into
88 a file or directory if it is converted. To rename from a subdirectory into
89 the root of the repository, use "." as the path to rename to.
89 the root of the repository, use "." as the path to rename to.
90
90
91 The splicemap is a file that allows insertion of synthetic history,
91 The splicemap is a file that allows insertion of synthetic history,
92 letting you specify the parents of a revision. This is useful if you want
92 letting you specify the parents of a revision. This is useful if you want
93 to e.g. give a Subversion merge two parents, or graft two disconnected
93 to e.g. give a Subversion merge two parents, or graft two disconnected
94 series of history together. Each entry contains a key, followed by a
94 series of history together. Each entry contains a key, followed by a
95 space, followed by one or two comma-separated values:
95 space, followed by one or two comma-separated values:
96
96
97 key parent1, parent2
97 key parent1, parent2
98
98
99 The key is the revision ID in the source revision control system whose
99 The key is the revision ID in the source revision control system whose
100 parents should be modified (same format as a key in .hg/shamap). The
100 parents should be modified (same format as a key in .hg/shamap). The
101 values are the revision IDs (in either the source or destination revision
101 values are the revision IDs (in either the source or destination revision
102 control system) that should be used as the new parents for that node. For
102 control system) that should be used as the new parents for that node. For
103 example, if you have merged "release-1.0" into "trunk", then you should
103 example, if you have merged "release-1.0" into "trunk", then you should
104 specify the revision on "trunk" as the first parent and the one on the
104 specify the revision on "trunk" as the first parent and the one on the
105 "release-1.0" branch as the second.
105 "release-1.0" branch as the second.
106
106
107 The branchmap is a file that allows you to rename a branch when it is
107 The branchmap is a file that allows you to rename a branch when it is
108 being brought in from whatever external repository. When used in
108 being brought in from whatever external repository. When used in
109 conjunction with a splicemap, it allows for a powerful combination to help
109 conjunction with a splicemap, it allows for a powerful combination to help
110 fix even the most badly mismanaged repositories and turn them into nicely
110 fix even the most badly mismanaged repositories and turn them into nicely
111 structured Mercurial repositories. The branchmap contains lines of the
111 structured Mercurial repositories. The branchmap contains lines of the
112 form:
112 form:
113
113
114 original_branch_name new_branch_name
114 original_branch_name new_branch_name
115
115
116 where "original_branch_name" is the name of the branch in the source
116 where "original_branch_name" is the name of the branch in the source
117 repository, and "new_branch_name" is the name of the branch is the
117 repository, and "new_branch_name" is the name of the branch is the
118 destination repository. No whitespace is allowed in the branch names. This
118 destination repository. No whitespace is allowed in the branch names. This
119 can be used to (for instance) move code in one repository from "default"
119 can be used to (for instance) move code in one repository from "default"
120 to a named branch.
120 to a named branch.
121
121
122 Mercurial Source
122 Mercurial Source
123 ''''''''''''''''
123 ''''''''''''''''
124
124
125 The Mercurial source recognizes the following configuration options, which
125 The Mercurial source recognizes the following configuration options, which
126 you can set on the command line with "--config":
126 you can set on the command line with "--config":
127
127
128 convert.hg.ignoreerrors
128 convert.hg.ignoreerrors
129 ignore integrity errors when reading. Use it to fix
129 ignore integrity errors when reading. Use it to fix
130 Mercurial repositories with missing revlogs, by converting
130 Mercurial repositories with missing revlogs, by converting
131 from and to Mercurial. Default is False.
131 from and to Mercurial. Default is False.
132 convert.hg.saverev
132 convert.hg.saverev
133 store original revision ID in changeset (forces target IDs
133 store original revision ID in changeset (forces target IDs
134 to change). It takes a boolean argument and defaults to
134 to change). It takes a boolean argument and defaults to
135 False.
135 False.
136 convert.hg.startrev
136 convert.hg.startrev
137 convert start revision and its descendants. It takes a hg
137 convert start revision and its descendants. It takes a hg
138 revision identifier and defaults to 0.
138 revision identifier and defaults to 0.
139
139
140 CVS Source
140 CVS Source
141 ''''''''''
141 ''''''''''
142
142
143 CVS source will use a sandbox (i.e. a checked-out copy) from CVS to
143 CVS source will use a sandbox (i.e. a checked-out copy) from CVS to
144 indicate the starting point of what will be converted. Direct access to
144 indicate the starting point of what will be converted. Direct access to
145 the repository files is not needed, unless of course the repository is
145 the repository files is not needed, unless of course the repository is
146 ":local:". The conversion uses the top level directory in the sandbox to
146 ":local:". The conversion uses the top level directory in the sandbox to
147 find the CVS repository, and then uses CVS rlog commands to find files to
147 find the CVS repository, and then uses CVS rlog commands to find files to
148 convert. This means that unless a filemap is given, all files under the
148 convert. This means that unless a filemap is given, all files under the
149 starting directory will be converted, and that any directory
149 starting directory will be converted, and that any directory
150 reorganization in the CVS sandbox is ignored.
150 reorganization in the CVS sandbox is ignored.
151
151
152 The following options can be used with "--config":
152 The following options can be used with "--config":
153
153
154 convert.cvsps.cache
154 convert.cvsps.cache
155 Set to False to disable remote log caching, for testing and
155 Set to False to disable remote log caching, for testing and
156 debugging purposes. Default is True.
156 debugging purposes. Default is True.
157 convert.cvsps.fuzz
157 convert.cvsps.fuzz
158 Specify the maximum time (in seconds) that is allowed
158 Specify the maximum time (in seconds) that is allowed
159 between commits with identical user and log message in a
159 between commits with identical user and log message in a
160 single changeset. When very large files were checked in as
160 single changeset. When very large files were checked in as
161 part of a changeset then the default may not be long enough.
161 part of a changeset then the default may not be long enough.
162 The default is 60.
162 The default is 60.
163 convert.cvsps.mergeto
163 convert.cvsps.mergeto
164 Specify a regular expression to which commit log messages
164 Specify a regular expression to which commit log messages
165 are matched. If a match occurs, then the conversion process
165 are matched. If a match occurs, then the conversion process
166 will insert a dummy revision merging the branch on which
166 will insert a dummy revision merging the branch on which
167 this log message occurs to the branch indicated in the
167 this log message occurs to the branch indicated in the
168 regex. Default is "{{mergetobranch ([-\w]+)}}"
168 regex. Default is "{{mergetobranch ([-\w]+)}}"
169 convert.cvsps.mergefrom
169 convert.cvsps.mergefrom
170 Specify a regular expression to which commit log messages
170 Specify a regular expression to which commit log messages
171 are matched. If a match occurs, then the conversion process
171 are matched. If a match occurs, then the conversion process
172 will add the most recent revision on the branch indicated in
172 will add the most recent revision on the branch indicated in
173 the regex as the second parent of the changeset. Default is
173 the regex as the second parent of the changeset. Default is
174 "{{mergefrombranch ([-\w]+)}}"
174 "{{mergefrombranch ([-\w]+)}}"
175 hook.cvslog Specify a Python function to be called at the end of
175 hook.cvslog Specify a Python function to be called at the end of
176 gathering the CVS log. The function is passed a list with
176 gathering the CVS log. The function is passed a list with
177 the log entries, and can modify the entries in-place, or add
177 the log entries, and can modify the entries in-place, or add
178 or delete them.
178 or delete them.
179 hook.cvschangesets
179 hook.cvschangesets
180 Specify a Python function to be called after the changesets
180 Specify a Python function to be called after the changesets
181 are calculated from the the CVS log. The function is passed
181 are calculated from the CVS log. The function is passed a
182 a list with the changeset entries, and can modify the
182 list with the changeset entries, and can modify the
183 changesets in-place, or add or delete them.
183 changesets in-place, or add or delete them.
184
184
185 An additional "debugcvsps" Mercurial command allows the builtin changeset
185 An additional "debugcvsps" Mercurial command allows the builtin changeset
186 merging code to be run without doing a conversion. Its parameters and
186 merging code to be run without doing a conversion. Its parameters and
187 output are similar to that of cvsps 2.1. Please see the command help for
187 output are similar to that of cvsps 2.1. Please see the command help for
188 more details.
188 more details.
189
189
190 Subversion Source
190 Subversion Source
191 '''''''''''''''''
191 '''''''''''''''''
192
192
193 Subversion source detects classical trunk/branches/tags layouts. By
193 Subversion source detects classical trunk/branches/tags layouts. By
194 default, the supplied "svn://repo/path/" source URL is converted as a
194 default, the supplied "svn://repo/path/" source URL is converted as a
195 single branch. If "svn://repo/path/trunk" exists it replaces the default
195 single branch. If "svn://repo/path/trunk" exists it replaces the default
196 branch. If "svn://repo/path/branches" exists, its subdirectories are
196 branch. If "svn://repo/path/branches" exists, its subdirectories are
197 listed as possible branches. If "svn://repo/path/tags" exists, it is
197 listed as possible branches. If "svn://repo/path/tags" exists, it is
198 looked for tags referencing converted branches. Default "trunk",
198 looked for tags referencing converted branches. Default "trunk",
199 "branches" and "tags" values can be overridden with following options. Set
199 "branches" and "tags" values can be overridden with following options. Set
200 them to paths relative to the source URL, or leave them blank to disable
200 them to paths relative to the source URL, or leave them blank to disable
201 auto detection.
201 auto detection.
202
202
203 The following options can be set with "--config":
203 The following options can be set with "--config":
204
204
205 convert.svn.branches
205 convert.svn.branches
206 specify the directory containing branches. The default is
206 specify the directory containing branches. The default is
207 "branches".
207 "branches".
208 convert.svn.tags
208 convert.svn.tags
209 specify the directory containing tags. The default is
209 specify the directory containing tags. The default is
210 "tags".
210 "tags".
211 convert.svn.trunk
211 convert.svn.trunk
212 specify the name of the trunk branch. The default is
212 specify the name of the trunk branch. The default is
213 "trunk".
213 "trunk".
214
214
215 Source history can be retrieved starting at a specific revision, instead
215 Source history can be retrieved starting at a specific revision, instead
216 of being integrally converted. Only single branch conversions are
216 of being integrally converted. Only single branch conversions are
217 supported.
217 supported.
218
218
219 convert.svn.startrev
219 convert.svn.startrev
220 specify start Subversion revision number. The default is 0.
220 specify start Subversion revision number. The default is 0.
221
221
222 Perforce Source
222 Perforce Source
223 '''''''''''''''
223 '''''''''''''''
224
224
225 The Perforce (P4) importer can be given a p4 depot path or a client
225 The Perforce (P4) importer can be given a p4 depot path or a client
226 specification as source. It will convert all files in the source to a flat
226 specification as source. It will convert all files in the source to a flat
227 Mercurial repository, ignoring labels, branches and integrations. Note
227 Mercurial repository, ignoring labels, branches and integrations. Note
228 that when a depot path is given you then usually should specify a target
228 that when a depot path is given you then usually should specify a target
229 directory, because otherwise the target may be named "...-hg".
229 directory, because otherwise the target may be named "...-hg".
230
230
231 It is possible to limit the amount of source history to be converted by
231 It is possible to limit the amount of source history to be converted by
232 specifying an initial Perforce revision:
232 specifying an initial Perforce revision:
233
233
234 convert.p4.startrev
234 convert.p4.startrev
235 specify initial Perforce revision (a Perforce changelist
235 specify initial Perforce revision (a Perforce changelist
236 number).
236 number).
237
237
238 Mercurial Destination
238 Mercurial Destination
239 '''''''''''''''''''''
239 '''''''''''''''''''''
240
240
241 The following options are supported:
241 The following options are supported:
242
242
243 convert.hg.clonebranches
243 convert.hg.clonebranches
244 dispatch source branches in separate clones. The default is
244 dispatch source branches in separate clones. The default is
245 False.
245 False.
246 convert.hg.tagsbranch
246 convert.hg.tagsbranch
247 branch name for tag revisions, defaults to "default".
247 branch name for tag revisions, defaults to "default".
248 convert.hg.usebranchnames
248 convert.hg.usebranchnames
249 preserve branch names. The default is True.
249 preserve branch names. The default is True.
250
250
251 options:
251 options:
252
252
253 -s --source-type TYPE source repository type
253 -s --source-type TYPE source repository type
254 -d --dest-type TYPE destination repository type
254 -d --dest-type TYPE destination repository type
255 -r --rev REV import up to target revision REV
255 -r --rev REV import up to target revision REV
256 -A --authormap FILE remap usernames using this file
256 -A --authormap FILE remap usernames using this file
257 --filemap FILE remap file names using contents of file
257 --filemap FILE remap file names using contents of file
258 --splicemap FILE splice synthesized history into place
258 --splicemap FILE splice synthesized history into place
259 --branchmap FILE change branch names while converting
259 --branchmap FILE change branch names while converting
260 --branchsort try to sort changesets by branches
260 --branchsort try to sort changesets by branches
261 --datesort try to sort changesets by date
261 --datesort try to sort changesets by date
262 --sourcesort preserve source changesets order
262 --sourcesort preserve source changesets order
263
263
264 use "hg -v help convert" to show more info
264 use "hg -v help convert" to show more info
265 $ hg init a
265 $ hg init a
266 $ cd a
266 $ cd a
267 $ echo a > a
267 $ echo a > a
268 $ hg ci -d'0 0' -Ama
268 $ hg ci -d'0 0' -Ama
269 adding a
269 adding a
270 $ hg cp a b
270 $ hg cp a b
271 $ hg ci -d'1 0' -mb
271 $ hg ci -d'1 0' -mb
272 $ hg rm a
272 $ hg rm a
273 $ hg ci -d'2 0' -mc
273 $ hg ci -d'2 0' -mc
274 $ hg mv b a
274 $ hg mv b a
275 $ hg ci -d'3 0' -md
275 $ hg ci -d'3 0' -md
276 $ echo a >> a
276 $ echo a >> a
277 $ hg ci -d'4 0' -me
277 $ hg ci -d'4 0' -me
278 $ cd ..
278 $ cd ..
279 $ hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
279 $ hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
280 assuming destination a-hg
280 assuming destination a-hg
281 initializing destination a-hg repository
281 initializing destination a-hg repository
282 scanning source...
282 scanning source...
283 sorting...
283 sorting...
284 converting...
284 converting...
285 4 a
285 4 a
286 3 b
286 3 b
287 2 c
287 2 c
288 1 d
288 1 d
289 0 e
289 0 e
290 $ hg --cwd a-hg pull ../a
290 $ hg --cwd a-hg pull ../a
291 pulling from ../a
291 pulling from ../a
292 searching for changes
292 searching for changes
293 no changes found
293 no changes found
294
294
295 conversion to existing file should fail
295 conversion to existing file should fail
296
296
297 $ touch bogusfile
297 $ touch bogusfile
298 $ hg convert a bogusfile
298 $ hg convert a bogusfile
299 initializing destination bogusfile repository
299 initializing destination bogusfile repository
300 abort: cannot create new bundle repository
300 abort: cannot create new bundle repository
301 [255]
301 [255]
302
302
303 #if unix-permissions
303 #if unix-permissions
304
304
305 conversion to dir without permissions should fail
305 conversion to dir without permissions should fail
306
306
307 $ mkdir bogusdir
307 $ mkdir bogusdir
308 $ chmod 000 bogusdir
308 $ chmod 000 bogusdir
309
309
310 $ hg convert a bogusdir
310 $ hg convert a bogusdir
311 abort: Permission denied: bogusdir
311 abort: Permission denied: bogusdir
312 [255]
312 [255]
313
313
314 user permissions should succeed
314 user permissions should succeed
315
315
316 $ chmod 700 bogusdir
316 $ chmod 700 bogusdir
317 $ hg convert a bogusdir
317 $ hg convert a bogusdir
318 initializing destination bogusdir repository
318 initializing destination bogusdir repository
319 scanning source...
319 scanning source...
320 sorting...
320 sorting...
321 converting...
321 converting...
322 4 a
322 4 a
323 3 b
323 3 b
324 2 c
324 2 c
325 1 d
325 1 d
326 0 e
326 0 e
327
327
328 #endif
328 #endif
329
329
330 test pre and post conversion actions
330 test pre and post conversion actions
331
331
332 $ echo 'include b' > filemap
332 $ echo 'include b' > filemap
333 $ hg convert --debug --filemap filemap a partialb | \
333 $ hg convert --debug --filemap filemap a partialb | \
334 > grep 'run hg'
334 > grep 'run hg'
335 run hg source pre-conversion action
335 run hg source pre-conversion action
336 run hg sink pre-conversion action
336 run hg sink pre-conversion action
337 run hg sink post-conversion action
337 run hg sink post-conversion action
338 run hg source post-conversion action
338 run hg source post-conversion action
339
339
340 converting empty dir should fail "nicely
340 converting empty dir should fail "nicely
341
341
342 $ mkdir emptydir
342 $ mkdir emptydir
343
343
344 override $PATH to ensure p4 not visible; use $PYTHON in case we're
344 override $PATH to ensure p4 not visible; use $PYTHON in case we're
345 running from a devel copy, not a temp installation
345 running from a devel copy, not a temp installation
346
346
347 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
347 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
348 assuming destination emptydir-hg
348 assuming destination emptydir-hg
349 initializing destination emptydir-hg repository
349 initializing destination emptydir-hg repository
350 emptydir does not look like a CVS checkout
350 emptydir does not look like a CVS checkout
351 emptydir does not look like a Git repository
351 emptydir does not look like a Git repository
352 emptydir does not look like a Subversion repository
352 emptydir does not look like a Subversion repository
353 emptydir is not a local Mercurial repository
353 emptydir is not a local Mercurial repository
354 emptydir does not look like a darcs repository
354 emptydir does not look like a darcs repository
355 emptydir does not look like a monotone repository
355 emptydir does not look like a monotone repository
356 emptydir does not look like a GNU Arch repository
356 emptydir does not look like a GNU Arch repository
357 emptydir does not look like a Bazaar repository
357 emptydir does not look like a Bazaar repository
358 cannot find required "p4" tool
358 cannot find required "p4" tool
359 abort: emptydir: missing or unsupported repository
359 abort: emptydir: missing or unsupported repository
360 [255]
360 [255]
361
361
362 convert with imaginary source type
362 convert with imaginary source type
363
363
364 $ hg convert --source-type foo a a-foo
364 $ hg convert --source-type foo a a-foo
365 initializing destination a-foo repository
365 initializing destination a-foo repository
366 abort: foo: invalid source repository type
366 abort: foo: invalid source repository type
367 [255]
367 [255]
368
368
369 convert with imaginary sink type
369 convert with imaginary sink type
370
370
371 $ hg convert --dest-type foo a a-foo
371 $ hg convert --dest-type foo a a-foo
372 abort: foo: invalid destination repository type
372 abort: foo: invalid destination repository type
373 [255]
373 [255]
374
374
375 testing: convert must not produce duplicate entries in fncache
375 testing: convert must not produce duplicate entries in fncache
376
376
377 $ hg convert a b
377 $ hg convert a b
378 initializing destination b repository
378 initializing destination b repository
379 scanning source...
379 scanning source...
380 sorting...
380 sorting...
381 converting...
381 converting...
382 4 a
382 4 a
383 3 b
383 3 b
384 2 c
384 2 c
385 1 d
385 1 d
386 0 e
386 0 e
387
387
388 contents of fncache file:
388 contents of fncache file:
389
389
390 $ cat b/.hg/store/fncache | sort
390 $ cat b/.hg/store/fncache | sort
391 data/a.i
391 data/a.i
392 data/b.i
392 data/b.i
393
393
394 test bogus URL
394 test bogus URL
395
395
396 $ hg convert -q bzr+ssh://foobar@selenic.com/baz baz
396 $ hg convert -q bzr+ssh://foobar@selenic.com/baz baz
397 abort: bzr+ssh://foobar@selenic.com/baz: missing or unsupported repository
397 abort: bzr+ssh://foobar@selenic.com/baz: missing or unsupported repository
398 [255]
398 [255]
399
399
400 test revset converted() lookup
400 test revset converted() lookup
401
401
402 $ hg --config convert.hg.saverev=True convert a c
402 $ hg --config convert.hg.saverev=True convert a c
403 initializing destination c repository
403 initializing destination c repository
404 scanning source...
404 scanning source...
405 sorting...
405 sorting...
406 converting...
406 converting...
407 4 a
407 4 a
408 3 b
408 3 b
409 2 c
409 2 c
410 1 d
410 1 d
411 0 e
411 0 e
412 $ echo f > c/f
412 $ echo f > c/f
413 $ hg -R c ci -d'0 0' -Amf
413 $ hg -R c ci -d'0 0' -Amf
414 adding f
414 adding f
415 created new head
415 created new head
416 $ hg -R c log -r "converted(09d945a62ce6)"
416 $ hg -R c log -r "converted(09d945a62ce6)"
417 changeset: 1:98c3dd46a874
417 changeset: 1:98c3dd46a874
418 user: test
418 user: test
419 date: Thu Jan 01 00:00:01 1970 +0000
419 date: Thu Jan 01 00:00:01 1970 +0000
420 summary: b
420 summary: b
421
421
422 $ hg -R c log -r "converted()"
422 $ hg -R c log -r "converted()"
423 changeset: 0:31ed57b2037c
423 changeset: 0:31ed57b2037c
424 user: test
424 user: test
425 date: Thu Jan 01 00:00:00 1970 +0000
425 date: Thu Jan 01 00:00:00 1970 +0000
426 summary: a
426 summary: a
427
427
428 changeset: 1:98c3dd46a874
428 changeset: 1:98c3dd46a874
429 user: test
429 user: test
430 date: Thu Jan 01 00:00:01 1970 +0000
430 date: Thu Jan 01 00:00:01 1970 +0000
431 summary: b
431 summary: b
432
432
433 changeset: 2:3b9ca06ef716
433 changeset: 2:3b9ca06ef716
434 user: test
434 user: test
435 date: Thu Jan 01 00:00:02 1970 +0000
435 date: Thu Jan 01 00:00:02 1970 +0000
436 summary: c
436 summary: c
437
437
438 changeset: 3:4e0debd37cf2
438 changeset: 3:4e0debd37cf2
439 user: test
439 user: test
440 date: Thu Jan 01 00:00:03 1970 +0000
440 date: Thu Jan 01 00:00:03 1970 +0000
441 summary: d
441 summary: d
442
442
443 changeset: 4:9de3bc9349c5
443 changeset: 4:9de3bc9349c5
444 user: test
444 user: test
445 date: Thu Jan 01 00:00:04 1970 +0000
445 date: Thu Jan 01 00:00:04 1970 +0000
446 summary: e
446 summary: e
447
447
General Comments 0
You need to be logged in to leave comments. Login now