##// END OF EJS Templates
Add ui.slash hgrc setting...
Alexis S. L. Carvalho -
r4527:b422b558 default
parent child Browse files
Show More
@@ -1,551 +1,556
1 HGRC(5)
1 HGRC(5)
2 =======
2 =======
3 Bryan O'Sullivan <bos@serpentine.com>
3 Bryan O'Sullivan <bos@serpentine.com>
4
4
5 NAME
5 NAME
6 ----
6 ----
7 hgrc - configuration files for Mercurial
7 hgrc - configuration files for Mercurial
8
8
9 SYNOPSIS
9 SYNOPSIS
10 --------
10 --------
11
11
12 The Mercurial system uses a set of configuration files to control
12 The Mercurial system uses a set of configuration files to control
13 aspects of its behaviour.
13 aspects of its behaviour.
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 The names of these files depend on the system on which Mercurial is
19 The names of these files depend on the system on which Mercurial is
20 installed.
20 installed.
21
21
22 (Unix) <install-root>/etc/mercurial/hgrc.d/*.rc::
22 (Unix) <install-root>/etc/mercurial/hgrc.d/*.rc::
23 (Unix) <install-root>/etc/mercurial/hgrc::
23 (Unix) <install-root>/etc/mercurial/hgrc::
24 Per-installation configuration files, searched for in the
24 Per-installation configuration files, searched for in the
25 directory where Mercurial is installed. For example, if installed
25 directory where Mercurial is installed. For example, if installed
26 in /shared/tools, Mercurial will look in
26 in /shared/tools, Mercurial will look in
27 /shared/tools/etc/mercurial/hgrc. Options in these files apply to
27 /shared/tools/etc/mercurial/hgrc. Options in these files apply to
28 all Mercurial commands executed by any user in any directory.
28 all Mercurial commands executed by any user in any directory.
29
29
30 (Unix) /etc/mercurial/hgrc.d/*.rc::
30 (Unix) /etc/mercurial/hgrc.d/*.rc::
31 (Unix) /etc/mercurial/hgrc::
31 (Unix) /etc/mercurial/hgrc::
32 (Windows) C:\Mercurial\Mercurial.ini::
32 (Windows) C:\Mercurial\Mercurial.ini::
33 Per-system configuration files, for the system on which Mercurial
33 Per-system configuration files, for the system on which Mercurial
34 is running. Options in these files apply to all Mercurial
34 is running. Options in these files apply to all Mercurial
35 commands executed by any user in any directory. Options in these
35 commands executed by any user in any directory. Options in these
36 files override per-installation options.
36 files override per-installation options.
37
37
38 (Unix) $HOME/.hgrc::
38 (Unix) $HOME/.hgrc::
39 (Windows) C:\Documents and Settings\USERNAME\Mercurial.ini::
39 (Windows) C:\Documents and Settings\USERNAME\Mercurial.ini::
40 (Windows) $HOME\Mercurial.ini::
40 (Windows) $HOME\Mercurial.ini::
41 Per-user configuration file, for the user running Mercurial.
41 Per-user configuration file, for the user running Mercurial.
42 Options in this file apply to all Mercurial commands executed by
42 Options in this file apply to all Mercurial commands executed by
43 any user in any directory. Options in this file override
43 any user in any directory. Options in this file override
44 per-installation and per-system options.
44 per-installation and per-system options.
45 On Windows system, one of these is chosen exclusively according
45 On Windows system, one of these is chosen exclusively according
46 to definition of HOME environment variable.
46 to definition of HOME environment variable.
47
47
48 (Unix, Windows) <repo>/.hg/hgrc::
48 (Unix, Windows) <repo>/.hg/hgrc::
49 Per-repository configuration options that only apply in a
49 Per-repository configuration options that only apply in a
50 particular repository. This file is not version-controlled, and
50 particular repository. This file is not version-controlled, and
51 will not get transferred during a "clone" operation. Options in
51 will not get transferred during a "clone" operation. Options in
52 this file override options in all other configuration files.
52 this file override options in all other configuration files.
53 On Unix, most of this file will be ignored if it doesn't belong
53 On Unix, most of this file will be ignored if it doesn't belong
54 to a trusted user or to a trusted group. See the documentation
54 to a trusted user or to a trusted group. See the documentation
55 for the trusted section below for more details.
55 for the trusted section below for more details.
56
56
57 SYNTAX
57 SYNTAX
58 ------
58 ------
59
59
60 A configuration file consists of sections, led by a "[section]" header
60 A configuration file consists of sections, led by a "[section]" header
61 and followed by "name: value" entries; "name=value" is also accepted.
61 and followed by "name: value" entries; "name=value" is also accepted.
62
62
63 [spam]
63 [spam]
64 eggs=ham
64 eggs=ham
65 green=
65 green=
66 eggs
66 eggs
67
67
68 Each line contains one entry. If the lines that follow are indented,
68 Each line contains one entry. If the lines that follow are indented,
69 they are treated as continuations of that entry.
69 they are treated as continuations of that entry.
70
70
71 Leading whitespace is removed from values. Empty lines are skipped.
71 Leading whitespace is removed from values. Empty lines are skipped.
72
72
73 The optional values can contain format strings which refer to other
73 The optional values can contain format strings which refer to other
74 values in the same section, or values in a special DEFAULT section.
74 values in the same section, or values in a special DEFAULT section.
75
75
76 Lines beginning with "#" or ";" are ignored and may be used to provide
76 Lines beginning with "#" or ";" are ignored and may be used to provide
77 comments.
77 comments.
78
78
79 SECTIONS
79 SECTIONS
80 --------
80 --------
81
81
82 This section describes the different sections that may appear in a
82 This section describes the different sections that may appear in a
83 Mercurial "hgrc" file, the purpose of each section, its possible
83 Mercurial "hgrc" file, the purpose of each section, its possible
84 keys, and their possible values.
84 keys, and their possible values.
85
85
86 decode/encode::
86 decode/encode::
87 Filters for transforming files on checkout/checkin. This would
87 Filters for transforming files on checkout/checkin. This would
88 typically be used for newline processing or other
88 typically be used for newline processing or other
89 localization/canonicalization of files.
89 localization/canonicalization of files.
90
90
91 Filters consist of a filter pattern followed by a filter command.
91 Filters consist of a filter pattern followed by a filter command.
92 Filter patterns are globs by default, rooted at the repository
92 Filter patterns are globs by default, rooted at the repository
93 root. For example, to match any file ending in ".txt" in the root
93 root. For example, to match any file ending in ".txt" in the root
94 directory only, use the pattern "*.txt". To match any file ending
94 directory only, use the pattern "*.txt". To match any file ending
95 in ".c" anywhere in the repository, use the pattern "**.c".
95 in ".c" anywhere in the repository, use the pattern "**.c".
96
96
97 The filter command can start with a specifier, either "pipe:" or
97 The filter command can start with a specifier, either "pipe:" or
98 "tempfile:". If no specifier is given, "pipe:" is used by default.
98 "tempfile:". If no specifier is given, "pipe:" is used by default.
99
99
100 A "pipe:" command must accept data on stdin and return the
100 A "pipe:" command must accept data on stdin and return the
101 transformed data on stdout.
101 transformed data on stdout.
102
102
103 Pipe example:
103 Pipe example:
104
104
105 [encode]
105 [encode]
106 # uncompress gzip files on checkin to improve delta compression
106 # uncompress gzip files on checkin to improve delta compression
107 # note: not necessarily a good idea, just an example
107 # note: not necessarily a good idea, just an example
108 *.gz = pipe: gunzip
108 *.gz = pipe: gunzip
109
109
110 [decode]
110 [decode]
111 # recompress gzip files when writing them to the working dir (we
111 # recompress gzip files when writing them to the working dir (we
112 # can safely omit "pipe:", because it's the default)
112 # can safely omit "pipe:", because it's the default)
113 *.gz = gzip
113 *.gz = gzip
114
114
115 A "tempfile:" command is a template. The string INFILE is replaced
115 A "tempfile:" command is a template. The string INFILE is replaced
116 with the name of a temporary file that contains the data to be
116 with the name of a temporary file that contains the data to be
117 filtered by the command. The string OUTFILE is replaced with the
117 filtered by the command. The string OUTFILE is replaced with the
118 name of an empty temporary file, where the filtered data must be
118 name of an empty temporary file, where the filtered data must be
119 written by the command.
119 written by the command.
120
120
121 NOTE: the tempfile mechanism is recommended for Windows systems,
121 NOTE: the tempfile mechanism is recommended for Windows systems,
122 where the standard shell I/O redirection operators often have
122 where the standard shell I/O redirection operators often have
123 strange effects. In particular, if you are doing line ending
123 strange effects. In particular, if you are doing line ending
124 conversion on Windows using the popular dos2unix and unix2dos
124 conversion on Windows using the popular dos2unix and unix2dos
125 programs, you *must* use the tempfile mechanism, as using pipes will
125 programs, you *must* use the tempfile mechanism, as using pipes will
126 corrupt the contents of your files.
126 corrupt the contents of your files.
127
127
128 Tempfile example:
128 Tempfile example:
129
129
130 [encode]
130 [encode]
131 # convert files to unix line ending conventions on checkin
131 # convert files to unix line ending conventions on checkin
132 **.txt = tempfile: dos2unix -n INFILE OUTFILE
132 **.txt = tempfile: dos2unix -n INFILE OUTFILE
133
133
134 [decode]
134 [decode]
135 # convert files to windows line ending conventions when writing
135 # convert files to windows line ending conventions when writing
136 # them to the working dir
136 # them to the working dir
137 **.txt = tempfile: unix2dos -n INFILE OUTFILE
137 **.txt = tempfile: unix2dos -n INFILE OUTFILE
138
138
139 defaults::
139 defaults::
140 Use the [defaults] section to define command defaults, i.e. the
140 Use the [defaults] section to define command defaults, i.e. the
141 default options/arguments to pass to the specified commands.
141 default options/arguments to pass to the specified commands.
142
142
143 The following example makes 'hg log' run in verbose mode, and
143 The following example makes 'hg log' run in verbose mode, and
144 'hg status' show only the modified files, by default.
144 'hg status' show only the modified files, by default.
145
145
146 [defaults]
146 [defaults]
147 log = -v
147 log = -v
148 status = -m
148 status = -m
149
149
150 The actual commands, instead of their aliases, must be used when
150 The actual commands, instead of their aliases, must be used when
151 defining command defaults. The command defaults will also be
151 defining command defaults. The command defaults will also be
152 applied to the aliases of the commands defined.
152 applied to the aliases of the commands defined.
153
153
154 diff::
154 diff::
155 Settings used when displaying diffs. They are all boolean and
155 Settings used when displaying diffs. They are all boolean and
156 defaults to False.
156 defaults to False.
157 git;;
157 git;;
158 Use git extended diff format.
158 Use git extended diff format.
159 nodates;;
159 nodates;;
160 Don't include dates in diff headers.
160 Don't include dates in diff headers.
161 showfunc;;
161 showfunc;;
162 Show which function each change is in.
162 Show which function each change is in.
163 ignorews;;
163 ignorews;;
164 Ignore white space when comparing lines.
164 Ignore white space when comparing lines.
165 ignorewsamount;;
165 ignorewsamount;;
166 Ignore changes in the amount of white space.
166 Ignore changes in the amount of white space.
167 ignoreblanklines;;
167 ignoreblanklines;;
168 Ignore changes whose lines are all blank.
168 Ignore changes whose lines are all blank.
169
169
170 email::
170 email::
171 Settings for extensions that send email messages.
171 Settings for extensions that send email messages.
172 from;;
172 from;;
173 Optional. Email address to use in "From" header and SMTP envelope
173 Optional. Email address to use in "From" header and SMTP envelope
174 of outgoing messages.
174 of outgoing messages.
175 to;;
175 to;;
176 Optional. Comma-separated list of recipients' email addresses.
176 Optional. Comma-separated list of recipients' email addresses.
177 cc;;
177 cc;;
178 Optional. Comma-separated list of carbon copy recipients'
178 Optional. Comma-separated list of carbon copy recipients'
179 email addresses.
179 email addresses.
180 bcc;;
180 bcc;;
181 Optional. Comma-separated list of blind carbon copy
181 Optional. Comma-separated list of blind carbon copy
182 recipients' email addresses. Cannot be set interactively.
182 recipients' email addresses. Cannot be set interactively.
183 method;;
183 method;;
184 Optional. Method to use to send email messages. If value is
184 Optional. Method to use to send email messages. If value is
185 "smtp" (default), use SMTP (see section "[smtp]" for
185 "smtp" (default), use SMTP (see section "[smtp]" for
186 configuration). Otherwise, use as name of program to run that
186 configuration). Otherwise, use as name of program to run that
187 acts like sendmail (takes "-f" option for sender, list of
187 acts like sendmail (takes "-f" option for sender, list of
188 recipients on command line, message on stdin). Normally, setting
188 recipients on command line, message on stdin). Normally, setting
189 this to "sendmail" or "/usr/sbin/sendmail" is enough to use
189 this to "sendmail" or "/usr/sbin/sendmail" is enough to use
190 sendmail to send messages.
190 sendmail to send messages.
191
191
192 Email example:
192 Email example:
193
193
194 [email]
194 [email]
195 from = Joseph User <joe.user@example.com>
195 from = Joseph User <joe.user@example.com>
196 method = /usr/sbin/sendmail
196 method = /usr/sbin/sendmail
197
197
198 extensions::
198 extensions::
199 Mercurial has an extension mechanism for adding new features. To
199 Mercurial has an extension mechanism for adding new features. To
200 enable an extension, create an entry for it in this section.
200 enable an extension, create an entry for it in this section.
201
201
202 If you know that the extension is already in Python's search path,
202 If you know that the extension is already in Python's search path,
203 you can give the name of the module, followed by "=", with nothing
203 you can give the name of the module, followed by "=", with nothing
204 after the "=".
204 after the "=".
205
205
206 Otherwise, give a name that you choose, followed by "=", followed by
206 Otherwise, give a name that you choose, followed by "=", followed by
207 the path to the ".py" file (including the file name extension) that
207 the path to the ".py" file (including the file name extension) that
208 defines the extension.
208 defines the extension.
209
209
210 Example for ~/.hgrc:
210 Example for ~/.hgrc:
211
211
212 [extensions]
212 [extensions]
213 # (the mq extension will get loaded from mercurial's path)
213 # (the mq extension will get loaded from mercurial's path)
214 hgext.mq =
214 hgext.mq =
215 # (this extension will get loaded from the file specified)
215 # (this extension will get loaded from the file specified)
216 myfeature = ~/.hgext/myfeature.py
216 myfeature = ~/.hgext/myfeature.py
217
217
218 format::
218 format::
219
219
220 usestore;;
220 usestore;;
221 Enable or disable the "store" repository format which improves
221 Enable or disable the "store" repository format which improves
222 compatibility with systems that fold case or otherwise mangle
222 compatibility with systems that fold case or otherwise mangle
223 filenames. Enabled by default. Disabling this option will allow
223 filenames. Enabled by default. Disabling this option will allow
224 you to store longer filenames in some situations at the expense of
224 you to store longer filenames in some situations at the expense of
225 compatibility.
225 compatibility.
226
226
227 hooks::
227 hooks::
228 Commands or Python functions that get automatically executed by
228 Commands or Python functions that get automatically executed by
229 various actions such as starting or finishing a commit. Multiple
229 various actions such as starting or finishing a commit. Multiple
230 hooks can be run for the same action by appending a suffix to the
230 hooks can be run for the same action by appending a suffix to the
231 action. Overriding a site-wide hook can be done by changing its
231 action. Overriding a site-wide hook can be done by changing its
232 value or setting it to an empty string.
232 value or setting it to an empty string.
233
233
234 Example .hg/hgrc:
234 Example .hg/hgrc:
235
235
236 [hooks]
236 [hooks]
237 # do not use the site-wide hook
237 # do not use the site-wide hook
238 incoming =
238 incoming =
239 incoming.email = /my/email/hook
239 incoming.email = /my/email/hook
240 incoming.autobuild = /my/build/hook
240 incoming.autobuild = /my/build/hook
241
241
242 Most hooks are run with environment variables set that give added
242 Most hooks are run with environment variables set that give added
243 useful information. For each hook below, the environment variables
243 useful information. For each hook below, the environment variables
244 it is passed are listed with names of the form "$HG_foo".
244 it is passed are listed with names of the form "$HG_foo".
245
245
246 changegroup;;
246 changegroup;;
247 Run after a changegroup has been added via push, pull or
247 Run after a changegroup has been added via push, pull or
248 unbundle. ID of the first new changeset is in $HG_NODE. URL from
248 unbundle. ID of the first new changeset is in $HG_NODE. URL from
249 which changes came is in $HG_URL.
249 which changes came is in $HG_URL.
250 commit;;
250 commit;;
251 Run after a changeset has been created in the local repository.
251 Run after a changeset has been created in the local repository.
252 ID of the newly created changeset is in $HG_NODE. Parent
252 ID of the newly created changeset is in $HG_NODE. Parent
253 changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
253 changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
254 incoming;;
254 incoming;;
255 Run after a changeset has been pulled, pushed, or unbundled into
255 Run after a changeset has been pulled, pushed, or unbundled into
256 the local repository. The ID of the newly arrived changeset is in
256 the local repository. The ID of the newly arrived changeset is in
257 $HG_NODE. URL that was source of changes came is in $HG_URL.
257 $HG_NODE. URL that was source of changes came is in $HG_URL.
258 outgoing;;
258 outgoing;;
259 Run after sending changes from local repository to another. ID of
259 Run after sending changes from local repository to another. ID of
260 first changeset sent is in $HG_NODE. Source of operation is in
260 first changeset sent is in $HG_NODE. Source of operation is in
261 $HG_SOURCE; see "preoutgoing" hook for description.
261 $HG_SOURCE; see "preoutgoing" hook for description.
262 prechangegroup;;
262 prechangegroup;;
263 Run before a changegroup is added via push, pull or unbundle.
263 Run before a changegroup is added via push, pull or unbundle.
264 Exit status 0 allows the changegroup to proceed. Non-zero status
264 Exit status 0 allows the changegroup to proceed. Non-zero status
265 will cause the push, pull or unbundle to fail. URL from which
265 will cause the push, pull or unbundle to fail. URL from which
266 changes will come is in $HG_URL.
266 changes will come is in $HG_URL.
267 precommit;;
267 precommit;;
268 Run before starting a local commit. Exit status 0 allows the
268 Run before starting a local commit. Exit status 0 allows the
269 commit to proceed. Non-zero status will cause the commit to fail.
269 commit to proceed. Non-zero status will cause the commit to fail.
270 Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
270 Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
271 preoutgoing;;
271 preoutgoing;;
272 Run before computing changes to send from the local repository to
272 Run before computing changes to send from the local repository to
273 another. Non-zero status will cause failure. This lets you
273 another. Non-zero status will cause failure. This lets you
274 prevent pull over http or ssh. Also prevents against local pull,
274 prevent pull over http or ssh. Also prevents against local pull,
275 push (outbound) or bundle commands, but not effective, since you
275 push (outbound) or bundle commands, but not effective, since you
276 can just copy files instead then. Source of operation is in
276 can just copy files instead then. Source of operation is in
277 $HG_SOURCE. If "serve", operation is happening on behalf of
277 $HG_SOURCE. If "serve", operation is happening on behalf of
278 remote ssh or http repository. If "push", "pull" or "bundle",
278 remote ssh or http repository. If "push", "pull" or "bundle",
279 operation is happening on behalf of repository on same system.
279 operation is happening on behalf of repository on same system.
280 pretag;;
280 pretag;;
281 Run before creating a tag. Exit status 0 allows the tag to be
281 Run before creating a tag. Exit status 0 allows the tag to be
282 created. Non-zero status will cause the tag to fail. ID of
282 created. Non-zero status will cause the tag to fail. ID of
283 changeset to tag is in $HG_NODE. Name of tag is in $HG_TAG. Tag
283 changeset to tag is in $HG_NODE. Name of tag is in $HG_TAG. Tag
284 is local if $HG_LOCAL=1, in repo if $HG_LOCAL=0.
284 is local if $HG_LOCAL=1, in repo if $HG_LOCAL=0.
285 pretxnchangegroup;;
285 pretxnchangegroup;;
286 Run after a changegroup has been added via push, pull or unbundle,
286 Run after a changegroup has been added via push, pull or unbundle,
287 but before the transaction has been committed. Changegroup is
287 but before the transaction has been committed. Changegroup is
288 visible to hook program. This lets you validate incoming changes
288 visible to hook program. This lets you validate incoming changes
289 before accepting them. Passed the ID of the first new changeset
289 before accepting them. Passed the ID of the first new changeset
290 in $HG_NODE. Exit status 0 allows the transaction to commit.
290 in $HG_NODE. Exit status 0 allows the transaction to commit.
291 Non-zero status will cause the transaction to be rolled back and
291 Non-zero status will cause the transaction to be rolled back and
292 the push, pull or unbundle will fail. URL that was source of
292 the push, pull or unbundle will fail. URL that was source of
293 changes is in $HG_URL.
293 changes is in $HG_URL.
294 pretxncommit;;
294 pretxncommit;;
295 Run after a changeset has been created but the transaction not yet
295 Run after a changeset has been created but the transaction not yet
296 committed. Changeset is visible to hook program. This lets you
296 committed. Changeset is visible to hook program. This lets you
297 validate commit message and changes. Exit status 0 allows the
297 validate commit message and changes. Exit status 0 allows the
298 commit to proceed. Non-zero status will cause the transaction to
298 commit to proceed. Non-zero status will cause the transaction to
299 be rolled back. ID of changeset is in $HG_NODE. Parent changeset
299 be rolled back. ID of changeset is in $HG_NODE. Parent changeset
300 IDs are in $HG_PARENT1 and $HG_PARENT2.
300 IDs are in $HG_PARENT1 and $HG_PARENT2.
301 preupdate;;
301 preupdate;;
302 Run before updating the working directory. Exit status 0 allows
302 Run before updating the working directory. Exit status 0 allows
303 the update to proceed. Non-zero status will prevent the update.
303 the update to proceed. Non-zero status will prevent the update.
304 Changeset ID of first new parent is in $HG_PARENT1. If merge, ID
304 Changeset ID of first new parent is in $HG_PARENT1. If merge, ID
305 of second new parent is in $HG_PARENT2.
305 of second new parent is in $HG_PARENT2.
306 tag;;
306 tag;;
307 Run after a tag is created. ID of tagged changeset is in
307 Run after a tag is created. ID of tagged changeset is in
308 $HG_NODE. Name of tag is in $HG_TAG. Tag is local if
308 $HG_NODE. Name of tag is in $HG_TAG. Tag is local if
309 $HG_LOCAL=1, in repo if $HG_LOCAL=0.
309 $HG_LOCAL=1, in repo if $HG_LOCAL=0.
310 update;;
310 update;;
311 Run after updating the working directory. Changeset ID of first
311 Run after updating the working directory. Changeset ID of first
312 new parent is in $HG_PARENT1. If merge, ID of second new parent
312 new parent is in $HG_PARENT1. If merge, ID of second new parent
313 is in $HG_PARENT2. If update succeeded, $HG_ERROR=0. If update
313 is in $HG_PARENT2. If update succeeded, $HG_ERROR=0. If update
314 failed (e.g. because conflicts not resolved), $HG_ERROR=1.
314 failed (e.g. because conflicts not resolved), $HG_ERROR=1.
315
315
316 Note: In earlier releases, the names of hook environment variables
316 Note: In earlier releases, the names of hook environment variables
317 did not have a "HG_" prefix. The old unprefixed names are no longer
317 did not have a "HG_" prefix. The old unprefixed names are no longer
318 provided in the environment.
318 provided in the environment.
319
319
320 The syntax for Python hooks is as follows:
320 The syntax for Python hooks is as follows:
321
321
322 hookname = python:modulename.submodule.callable
322 hookname = python:modulename.submodule.callable
323
323
324 Python hooks are run within the Mercurial process. Each hook is
324 Python hooks are run within the Mercurial process. Each hook is
325 called with at least three keyword arguments: a ui object (keyword
325 called with at least three keyword arguments: a ui object (keyword
326 "ui"), a repository object (keyword "repo"), and a "hooktype"
326 "ui"), a repository object (keyword "repo"), and a "hooktype"
327 keyword that tells what kind of hook is used. Arguments listed as
327 keyword that tells what kind of hook is used. Arguments listed as
328 environment variables above are passed as keyword arguments, with no
328 environment variables above are passed as keyword arguments, with no
329 "HG_" prefix, and names in lower case.
329 "HG_" prefix, and names in lower case.
330
330
331 If a Python hook returns a "true" value or raises an exception, this
331 If a Python hook returns a "true" value or raises an exception, this
332 is treated as failure of the hook.
332 is treated as failure of the hook.
333
333
334 http_proxy::
334 http_proxy::
335 Used to access web-based Mercurial repositories through a HTTP
335 Used to access web-based Mercurial repositories through a HTTP
336 proxy.
336 proxy.
337 host;;
337 host;;
338 Host name and (optional) port of the proxy server, for example
338 Host name and (optional) port of the proxy server, for example
339 "myproxy:8000".
339 "myproxy:8000".
340 no;;
340 no;;
341 Optional. Comma-separated list of host names that should bypass
341 Optional. Comma-separated list of host names that should bypass
342 the proxy.
342 the proxy.
343 passwd;;
343 passwd;;
344 Optional. Password to authenticate with at the proxy server.
344 Optional. Password to authenticate with at the proxy server.
345 user;;
345 user;;
346 Optional. User name to authenticate with at the proxy server.
346 Optional. User name to authenticate with at the proxy server.
347
347
348 smtp::
348 smtp::
349 Configuration for extensions that need to send email messages.
349 Configuration for extensions that need to send email messages.
350 host;;
350 host;;
351 Host name of mail server, e.g. "mail.example.com".
351 Host name of mail server, e.g. "mail.example.com".
352 port;;
352 port;;
353 Optional. Port to connect to on mail server. Default: 25.
353 Optional. Port to connect to on mail server. Default: 25.
354 tls;;
354 tls;;
355 Optional. Whether to connect to mail server using TLS. True or
355 Optional. Whether to connect to mail server using TLS. True or
356 False. Default: False.
356 False. Default: False.
357 username;;
357 username;;
358 Optional. User name to authenticate to SMTP server with.
358 Optional. User name to authenticate to SMTP server with.
359 If username is specified, password must also be specified.
359 If username is specified, password must also be specified.
360 Default: none.
360 Default: none.
361 password;;
361 password;;
362 Optional. Password to authenticate to SMTP server with.
362 Optional. Password to authenticate to SMTP server with.
363 If username is specified, password must also be specified.
363 If username is specified, password must also be specified.
364 Default: none.
364 Default: none.
365 local_hostname;;
365 local_hostname;;
366 Optional. It's the hostname that the sender can use to identify itself
366 Optional. It's the hostname that the sender can use to identify itself
367 to the MTA.
367 to the MTA.
368
368
369 paths::
369 paths::
370 Assigns symbolic names to repositories. The left side is the
370 Assigns symbolic names to repositories. The left side is the
371 symbolic name, and the right gives the directory or URL that is the
371 symbolic name, and the right gives the directory or URL that is the
372 location of the repository. Default paths can be declared by
372 location of the repository. Default paths can be declared by
373 setting the following entries.
373 setting the following entries.
374 default;;
374 default;;
375 Directory or URL to use when pulling if no source is specified.
375 Directory or URL to use when pulling if no source is specified.
376 Default is set to repository from which the current repository
376 Default is set to repository from which the current repository
377 was cloned.
377 was cloned.
378 default-push;;
378 default-push;;
379 Optional. Directory or URL to use when pushing if no destination
379 Optional. Directory or URL to use when pushing if no destination
380 is specified.
380 is specified.
381
381
382 server::
382 server::
383 Controls generic server settings.
383 Controls generic server settings.
384 uncompressed;;
384 uncompressed;;
385 Whether to allow clients to clone a repo using the uncompressed
385 Whether to allow clients to clone a repo using the uncompressed
386 streaming protocol. This transfers about 40% more data than a
386 streaming protocol. This transfers about 40% more data than a
387 regular clone, but uses less memory and CPU on both server and
387 regular clone, but uses less memory and CPU on both server and
388 client. Over a LAN (100Mbps or better) or a very fast WAN, an
388 client. Over a LAN (100Mbps or better) or a very fast WAN, an
389 uncompressed streaming clone is a lot faster (~10x) than a regular
389 uncompressed streaming clone is a lot faster (~10x) than a regular
390 clone. Over most WAN connections (anything slower than about
390 clone. Over most WAN connections (anything slower than about
391 6Mbps), uncompressed streaming is slower, because of the extra
391 6Mbps), uncompressed streaming is slower, because of the extra
392 data transfer overhead. Default is False.
392 data transfer overhead. Default is False.
393
393
394 trusted::
394 trusted::
395 For security reasons, Mercurial will not use the settings in
395 For security reasons, Mercurial will not use the settings in
396 the .hg/hgrc file from a repository if it doesn't belong to a
396 the .hg/hgrc file from a repository if it doesn't belong to a
397 trusted user or to a trusted group. The main exception is the
397 trusted user or to a trusted group. The main exception is the
398 web interface, which automatically uses some safe settings, since
398 web interface, which automatically uses some safe settings, since
399 it's common to serve repositories from different users.
399 it's common to serve repositories from different users.
400
400
401 This section specifies what users and groups are trusted. The
401 This section specifies what users and groups are trusted. The
402 current user is always trusted. To trust everybody, list a user
402 current user is always trusted. To trust everybody, list a user
403 or a group with name "*".
403 or a group with name "*".
404
404
405 users;;
405 users;;
406 Comma-separated list of trusted users.
406 Comma-separated list of trusted users.
407 groups;;
407 groups;;
408 Comma-separated list of trusted groups.
408 Comma-separated list of trusted groups.
409
409
410 ui::
410 ui::
411 User interface controls.
411 User interface controls.
412 debug;;
412 debug;;
413 Print debugging information. True or False. Default is False.
413 Print debugging information. True or False. Default is False.
414 editor;;
414 editor;;
415 The editor to use during a commit. Default is $EDITOR or "vi".
415 The editor to use during a commit. Default is $EDITOR or "vi".
416 fallbackencoding;;
416 fallbackencoding;;
417 Encoding to try if it's not possible to decode the changelog using
417 Encoding to try if it's not possible to decode the changelog using
418 UTF-8. Default is ISO-8859-1.
418 UTF-8. Default is ISO-8859-1.
419 ignore;;
419 ignore;;
420 A file to read per-user ignore patterns from. This file should be in
420 A file to read per-user ignore patterns from. This file should be in
421 the same format as a repository-wide .hgignore file. This option
421 the same format as a repository-wide .hgignore file. This option
422 supports hook syntax, so if you want to specify multiple ignore
422 supports hook syntax, so if you want to specify multiple ignore
423 files, you can do so by setting something like
423 files, you can do so by setting something like
424 "ignore.other = ~/.hgignore2". For details of the ignore file
424 "ignore.other = ~/.hgignore2". For details of the ignore file
425 format, see the hgignore(5) man page.
425 format, see the hgignore(5) man page.
426 interactive;;
426 interactive;;
427 Allow to prompt the user. True or False. Default is True.
427 Allow to prompt the user. True or False. Default is True.
428 logtemplate;;
428 logtemplate;;
429 Template string for commands that print changesets.
429 Template string for commands that print changesets.
430 style;;
430 style;;
431 Name of style to use for command output.
431 Name of style to use for command output.
432 merge;;
432 merge;;
433 The conflict resolution program to use during a manual merge.
433 The conflict resolution program to use during a manual merge.
434 Default is "hgmerge".
434 Default is "hgmerge".
435 patch;;
435 patch;;
436 command to use to apply patches. Look for 'gpatch' or 'patch' in PATH if
436 command to use to apply patches. Look for 'gpatch' or 'patch' in PATH if
437 unset.
437 unset.
438 quiet;;
438 quiet;;
439 Reduce the amount of output printed. True or False. Default is False.
439 Reduce the amount of output printed. True or False. Default is False.
440 remotecmd;;
440 remotecmd;;
441 remote command to use for clone/push/pull operations. Default is 'hg'.
441 remote command to use for clone/push/pull operations. Default is 'hg'.
442 slash;;
443 Display paths using a slash ("/") as the path separator. This only
444 makes a difference on systems where the default path separator is not
445 the slash character (e.g. Windows uses the backslash character ("\")).
446 Default is False.
442 ssh;;
447 ssh;;
443 command to use for SSH connections. Default is 'ssh'.
448 command to use for SSH connections. Default is 'ssh'.
444 strict;;
449 strict;;
445 Require exact command names, instead of allowing unambiguous
450 Require exact command names, instead of allowing unambiguous
446 abbreviations. True or False. Default is False.
451 abbreviations. True or False. Default is False.
447 timeout;;
452 timeout;;
448 The timeout used when a lock is held (in seconds), a negative value
453 The timeout used when a lock is held (in seconds), a negative value
449 means no timeout. Default is 600.
454 means no timeout. Default is 600.
450 username;;
455 username;;
451 The committer of a changeset created when running "commit".
456 The committer of a changeset created when running "commit".
452 Typically a person's name and email address, e.g. "Fred Widget
457 Typically a person's name and email address, e.g. "Fred Widget
453 <fred@example.com>". Default is $EMAIL or username@hostname.
458 <fred@example.com>". Default is $EMAIL or username@hostname.
454 If the username in hgrc is empty, it has to be specified manually or
459 If the username in hgrc is empty, it has to be specified manually or
455 in a different hgrc file (e.g. $HOME/.hgrc, if the admin set "username ="
460 in a different hgrc file (e.g. $HOME/.hgrc, if the admin set "username ="
456 in the system hgrc).
461 in the system hgrc).
457 verbose;;
462 verbose;;
458 Increase the amount of output printed. True or False. Default is False.
463 Increase the amount of output printed. True or False. Default is False.
459
464
460
465
461 web::
466 web::
462 Web interface configuration.
467 Web interface configuration.
463 accesslog;;
468 accesslog;;
464 Where to output the access log. Default is stdout.
469 Where to output the access log. Default is stdout.
465 address;;
470 address;;
466 Interface address to bind to. Default is all.
471 Interface address to bind to. Default is all.
467 allow_archive;;
472 allow_archive;;
468 List of archive format (bz2, gz, zip) allowed for downloading.
473 List of archive format (bz2, gz, zip) allowed for downloading.
469 Default is empty.
474 Default is empty.
470 allowbz2;;
475 allowbz2;;
471 (DEPRECATED) Whether to allow .tar.bz2 downloading of repo revisions.
476 (DEPRECATED) Whether to allow .tar.bz2 downloading of repo revisions.
472 Default is false.
477 Default is false.
473 allowgz;;
478 allowgz;;
474 (DEPRECATED) Whether to allow .tar.gz downloading of repo revisions.
479 (DEPRECATED) Whether to allow .tar.gz downloading of repo revisions.
475 Default is false.
480 Default is false.
476 allowpull;;
481 allowpull;;
477 Whether to allow pulling from the repository. Default is true.
482 Whether to allow pulling from the repository. Default is true.
478 allow_push;;
483 allow_push;;
479 Whether to allow pushing to the repository. If empty or not set,
484 Whether to allow pushing to the repository. If empty or not set,
480 push is not allowed. If the special value "*", any remote user
485 push is not allowed. If the special value "*", any remote user
481 can push, including unauthenticated users. Otherwise, the remote
486 can push, including unauthenticated users. Otherwise, the remote
482 user must have been authenticated, and the authenticated user name
487 user must have been authenticated, and the authenticated user name
483 must be present in this list (separated by whitespace or ",").
488 must be present in this list (separated by whitespace or ",").
484 The contents of the allow_push list are examined after the
489 The contents of the allow_push list are examined after the
485 deny_push list.
490 deny_push list.
486 allowzip;;
491 allowzip;;
487 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
492 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
488 Default is false. This feature creates temporary files.
493 Default is false. This feature creates temporary files.
489 baseurl;;
494 baseurl;;
490 Base URL to use when publishing URLs in other locations, so
495 Base URL to use when publishing URLs in other locations, so
491 third-party tools like email notification hooks can construct URLs.
496 third-party tools like email notification hooks can construct URLs.
492 Example: "http://hgserver/repos/"
497 Example: "http://hgserver/repos/"
493 contact;;
498 contact;;
494 Name or email address of the person in charge of the repository.
499 Name or email address of the person in charge of the repository.
495 Default is "unknown".
500 Default is "unknown".
496 deny_push;;
501 deny_push;;
497 Whether to deny pushing to the repository. If empty or not set,
502 Whether to deny pushing to the repository. If empty or not set,
498 push is not denied. If the special value "*", all remote users
503 push is not denied. If the special value "*", all remote users
499 are denied push. Otherwise, unauthenticated users are all denied,
504 are denied push. Otherwise, unauthenticated users are all denied,
500 and any authenticated user name present in this list (separated by
505 and any authenticated user name present in this list (separated by
501 whitespace or ",") is also denied. The contents of the deny_push
506 whitespace or ",") is also denied. The contents of the deny_push
502 list are examined before the allow_push list.
507 list are examined before the allow_push list.
503 description;;
508 description;;
504 Textual description of the repository's purpose or contents.
509 Textual description of the repository's purpose or contents.
505 Default is "unknown".
510 Default is "unknown".
506 errorlog;;
511 errorlog;;
507 Where to output the error log. Default is stderr.
512 Where to output the error log. Default is stderr.
508 ipv6;;
513 ipv6;;
509 Whether to use IPv6. Default is false.
514 Whether to use IPv6. Default is false.
510 name;;
515 name;;
511 Repository name to use in the web interface. Default is current
516 Repository name to use in the web interface. Default is current
512 working directory.
517 working directory.
513 maxchanges;;
518 maxchanges;;
514 Maximum number of changes to list on the changelog. Default is 10.
519 Maximum number of changes to list on the changelog. Default is 10.
515 maxfiles;;
520 maxfiles;;
516 Maximum number of files to list per changeset. Default is 10.
521 Maximum number of files to list per changeset. Default is 10.
517 port;;
522 port;;
518 Port to listen on. Default is 8000.
523 Port to listen on. Default is 8000.
519 push_ssl;;
524 push_ssl;;
520 Whether to require that inbound pushes be transported over SSL to
525 Whether to require that inbound pushes be transported over SSL to
521 prevent password sniffing. Default is true.
526 prevent password sniffing. Default is true.
522 staticurl;;
527 staticurl;;
523 Base URL to use for static files. If unset, static files (e.g.
528 Base URL to use for static files. If unset, static files (e.g.
524 the hgicon.png favicon) will be served by the CGI script itself.
529 the hgicon.png favicon) will be served by the CGI script itself.
525 Use this setting to serve them directly with the HTTP server.
530 Use this setting to serve them directly with the HTTP server.
526 Example: "http://hgserver/static/"
531 Example: "http://hgserver/static/"
527 stripes;;
532 stripes;;
528 How many lines a "zebra stripe" should span in multiline output.
533 How many lines a "zebra stripe" should span in multiline output.
529 Default is 1; set to 0 to disable.
534 Default is 1; set to 0 to disable.
530 style;;
535 style;;
531 Which template map style to use.
536 Which template map style to use.
532 templates;;
537 templates;;
533 Where to find the HTML templates. Default is install path.
538 Where to find the HTML templates. Default is install path.
534
539
535
540
536 AUTHOR
541 AUTHOR
537 ------
542 ------
538 Bryan O'Sullivan <bos@serpentine.com>.
543 Bryan O'Sullivan <bos@serpentine.com>.
539
544
540 Mercurial was written by Matt Mackall <mpm@selenic.com>.
545 Mercurial was written by Matt Mackall <mpm@selenic.com>.
541
546
542 SEE ALSO
547 SEE ALSO
543 --------
548 --------
544 hg(1), hgignore(5)
549 hg(1), hgignore(5)
545
550
546 COPYING
551 COPYING
547 -------
552 -------
548 This manual page is copyright 2005 Bryan O'Sullivan.
553 This manual page is copyright 2005 Bryan O'Sullivan.
549 Mercurial is copyright 2005, 2006 Matt Mackall.
554 Mercurial is copyright 2005, 2006 Matt Mackall.
550 Free use of this software is granted under the terms of the GNU General
555 Free use of this software is granted under the terms of the GNU General
551 Public License (GPL).
556 Public License (GPL).
@@ -1,596 +1,602
1 """
1 """
2 dirstate.py - working directory tracking for mercurial
2 dirstate.py - working directory tracking for mercurial
3
3
4 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5
5
6 This software may be used and distributed according to the terms
6 This software may be used and distributed according to the terms
7 of the GNU General Public License, incorporated herein by reference.
7 of the GNU General Public License, incorporated herein by reference.
8 """
8 """
9
9
10 from node import *
10 from node import *
11 from i18n import _
11 from i18n import _
12 import struct, os, time, bisect, stat, strutil, util, re, errno
12 import struct, os, time, bisect, stat, strutil, util, re, errno
13 import cStringIO
13 import cStringIO
14
14
15 class dirstate(object):
15 class dirstate(object):
16 format = ">cllll"
16 format = ">cllll"
17
17
18 def __init__(self, opener, ui, root):
18 def __init__(self, opener, ui, root):
19 self.opener = opener
19 self.opener = opener
20 self.root = root
20 self.root = root
21 self.dirty = 0
21 self.dirty = 0
22 self.ui = ui
22 self.ui = ui
23 self.map = None
23 self.map = None
24 self.fp = None
24 self.fp = None
25 self.pl = None
25 self.pl = None
26 self.dirs = None
26 self.dirs = None
27 self.copymap = {}
27 self.copymap = {}
28 self.ignorefunc = None
28 self.ignorefunc = None
29 self._branch = None
29 self._branch = None
30 self._slash = None
30
31
31 def wjoin(self, f):
32 def wjoin(self, f):
32 return os.path.join(self.root, f)
33 return os.path.join(self.root, f)
33
34
34 def getcwd(self):
35 def getcwd(self):
35 cwd = os.getcwd()
36 cwd = os.getcwd()
36 if cwd == self.root: return ''
37 if cwd == self.root: return ''
37 # self.root ends with a path separator if self.root is '/' or 'C:\'
38 # self.root ends with a path separator if self.root is '/' or 'C:\'
38 rootsep = self.root
39 rootsep = self.root
39 if not rootsep.endswith(os.sep):
40 if not rootsep.endswith(os.sep):
40 rootsep += os.sep
41 rootsep += os.sep
41 if cwd.startswith(rootsep):
42 if cwd.startswith(rootsep):
42 return cwd[len(rootsep):]
43 return cwd[len(rootsep):]
43 else:
44 else:
44 # we're outside the repo. return an absolute path.
45 # we're outside the repo. return an absolute path.
45 return cwd
46 return cwd
46
47
47 def pathto(self, f, cwd=None):
48 def pathto(self, f, cwd=None):
48 if cwd is None:
49 if cwd is None:
49 cwd = self.getcwd()
50 cwd = self.getcwd()
50 return util.pathto(self.root, cwd, f)
51 path = util.pathto(self.root, cwd, f)
52 if self._slash is None:
53 self._slash = self.ui.configbool('ui', 'slash') and os.sep != '/'
54 if self._slash:
55 path = path.replace(os.sep, '/')
56 return path
51
57
52 def hgignore(self):
58 def hgignore(self):
53 '''return the contents of .hgignore files as a list of patterns.
59 '''return the contents of .hgignore files as a list of patterns.
54
60
55 the files parsed for patterns include:
61 the files parsed for patterns include:
56 .hgignore in the repository root
62 .hgignore in the repository root
57 any additional files specified in the [ui] section of ~/.hgrc
63 any additional files specified in the [ui] section of ~/.hgrc
58
64
59 trailing white space is dropped.
65 trailing white space is dropped.
60 the escape character is backslash.
66 the escape character is backslash.
61 comments start with #.
67 comments start with #.
62 empty lines are skipped.
68 empty lines are skipped.
63
69
64 lines can be of the following formats:
70 lines can be of the following formats:
65
71
66 syntax: regexp # defaults following lines to non-rooted regexps
72 syntax: regexp # defaults following lines to non-rooted regexps
67 syntax: glob # defaults following lines to non-rooted globs
73 syntax: glob # defaults following lines to non-rooted globs
68 re:pattern # non-rooted regular expression
74 re:pattern # non-rooted regular expression
69 glob:pattern # non-rooted glob
75 glob:pattern # non-rooted glob
70 pattern # pattern of the current default type'''
76 pattern # pattern of the current default type'''
71 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
77 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
72 def parselines(fp):
78 def parselines(fp):
73 for line in fp:
79 for line in fp:
74 if not line.endswith('\n'):
80 if not line.endswith('\n'):
75 line += '\n'
81 line += '\n'
76 escape = False
82 escape = False
77 for i in xrange(len(line)):
83 for i in xrange(len(line)):
78 if escape: escape = False
84 if escape: escape = False
79 elif line[i] == '\\': escape = True
85 elif line[i] == '\\': escape = True
80 elif line[i] == '#': break
86 elif line[i] == '#': break
81 line = line[:i].rstrip()
87 line = line[:i].rstrip()
82 if line: yield line
88 if line: yield line
83 repoignore = self.wjoin('.hgignore')
89 repoignore = self.wjoin('.hgignore')
84 files = [repoignore]
90 files = [repoignore]
85 files.extend(self.ui.hgignorefiles())
91 files.extend(self.ui.hgignorefiles())
86 pats = {}
92 pats = {}
87 for f in files:
93 for f in files:
88 try:
94 try:
89 pats[f] = []
95 pats[f] = []
90 fp = open(f)
96 fp = open(f)
91 syntax = 'relre:'
97 syntax = 'relre:'
92 for line in parselines(fp):
98 for line in parselines(fp):
93 if line.startswith('syntax:'):
99 if line.startswith('syntax:'):
94 s = line[7:].strip()
100 s = line[7:].strip()
95 try:
101 try:
96 syntax = syntaxes[s]
102 syntax = syntaxes[s]
97 except KeyError:
103 except KeyError:
98 self.ui.warn(_("%s: ignoring invalid "
104 self.ui.warn(_("%s: ignoring invalid "
99 "syntax '%s'\n") % (f, s))
105 "syntax '%s'\n") % (f, s))
100 continue
106 continue
101 pat = syntax + line
107 pat = syntax + line
102 for s in syntaxes.values():
108 for s in syntaxes.values():
103 if line.startswith(s):
109 if line.startswith(s):
104 pat = line
110 pat = line
105 break
111 break
106 pats[f].append(pat)
112 pats[f].append(pat)
107 except IOError, inst:
113 except IOError, inst:
108 if f != repoignore:
114 if f != repoignore:
109 self.ui.warn(_("skipping unreadable ignore file"
115 self.ui.warn(_("skipping unreadable ignore file"
110 " '%s': %s\n") % (f, inst.strerror))
116 " '%s': %s\n") % (f, inst.strerror))
111 return pats
117 return pats
112
118
113 def ignore(self, fn):
119 def ignore(self, fn):
114 '''default match function used by dirstate and
120 '''default match function used by dirstate and
115 localrepository. this honours the repository .hgignore file
121 localrepository. this honours the repository .hgignore file
116 and any other files specified in the [ui] section of .hgrc.'''
122 and any other files specified in the [ui] section of .hgrc.'''
117 if not self.ignorefunc:
123 if not self.ignorefunc:
118 ignore = self.hgignore()
124 ignore = self.hgignore()
119 allpats = []
125 allpats = []
120 [allpats.extend(patlist) for patlist in ignore.values()]
126 [allpats.extend(patlist) for patlist in ignore.values()]
121 if allpats:
127 if allpats:
122 try:
128 try:
123 files, self.ignorefunc, anypats = (
129 files, self.ignorefunc, anypats = (
124 util.matcher(self.root, inc=allpats, src='.hgignore'))
130 util.matcher(self.root, inc=allpats, src='.hgignore'))
125 except util.Abort:
131 except util.Abort:
126 # Re-raise an exception where the src is the right file
132 # Re-raise an exception where the src is the right file
127 for f, patlist in ignore.items():
133 for f, patlist in ignore.items():
128 files, self.ignorefunc, anypats = (
134 files, self.ignorefunc, anypats = (
129 util.matcher(self.root, inc=patlist, src=f))
135 util.matcher(self.root, inc=patlist, src=f))
130 else:
136 else:
131 self.ignorefunc = util.never
137 self.ignorefunc = util.never
132 return self.ignorefunc(fn)
138 return self.ignorefunc(fn)
133
139
134 def __del__(self):
140 def __del__(self):
135 if self.dirty:
141 if self.dirty:
136 self.write()
142 self.write()
137
143
138 def __getitem__(self, key):
144 def __getitem__(self, key):
139 try:
145 try:
140 return self.map[key]
146 return self.map[key]
141 except TypeError:
147 except TypeError:
142 self.lazyread()
148 self.lazyread()
143 return self[key]
149 return self[key]
144
150
145 _unknown = ('?', 0, 0, 0)
151 _unknown = ('?', 0, 0, 0)
146
152
147 def get(self, key):
153 def get(self, key):
148 try:
154 try:
149 return self[key]
155 return self[key]
150 except KeyError:
156 except KeyError:
151 return self._unknown
157 return self._unknown
152
158
153 def __contains__(self, key):
159 def __contains__(self, key):
154 self.lazyread()
160 self.lazyread()
155 return key in self.map
161 return key in self.map
156
162
157 def parents(self):
163 def parents(self):
158 if self.pl is None:
164 if self.pl is None:
159 self.pl = [nullid, nullid]
165 self.pl = [nullid, nullid]
160 try:
166 try:
161 self.fp = self.opener('dirstate')
167 self.fp = self.opener('dirstate')
162 st = self.fp.read(40)
168 st = self.fp.read(40)
163 if len(st) == 40:
169 if len(st) == 40:
164 self.pl = st[:20], st[20:40]
170 self.pl = st[:20], st[20:40]
165 except IOError, err:
171 except IOError, err:
166 if err.errno != errno.ENOENT: raise
172 if err.errno != errno.ENOENT: raise
167 return self.pl
173 return self.pl
168
174
169 def branch(self):
175 def branch(self):
170 if not self._branch:
176 if not self._branch:
171 try:
177 try:
172 self._branch = self.opener("branch").read().strip()\
178 self._branch = self.opener("branch").read().strip()\
173 or "default"
179 or "default"
174 except IOError:
180 except IOError:
175 self._branch = "default"
181 self._branch = "default"
176 return self._branch
182 return self._branch
177
183
178 def markdirty(self):
184 def markdirty(self):
179 if not self.dirty:
185 if not self.dirty:
180 self.dirty = 1
186 self.dirty = 1
181
187
182 def setparents(self, p1, p2=nullid):
188 def setparents(self, p1, p2=nullid):
183 self.lazyread()
189 self.lazyread()
184 self.markdirty()
190 self.markdirty()
185 self.pl = p1, p2
191 self.pl = p1, p2
186
192
187 def setbranch(self, branch):
193 def setbranch(self, branch):
188 self._branch = branch
194 self._branch = branch
189 self.opener("branch", "w").write(branch + '\n')
195 self.opener("branch", "w").write(branch + '\n')
190
196
191 def state(self, key):
197 def state(self, key):
192 try:
198 try:
193 return self[key][0]
199 return self[key][0]
194 except KeyError:
200 except KeyError:
195 return "?"
201 return "?"
196
202
197 def lazyread(self):
203 def lazyread(self):
198 if self.map is None:
204 if self.map is None:
199 self.read()
205 self.read()
200
206
201 def parse(self, st):
207 def parse(self, st):
202 self.pl = [st[:20], st[20: 40]]
208 self.pl = [st[:20], st[20: 40]]
203
209
204 # deref fields so they will be local in loop
210 # deref fields so they will be local in loop
205 map = self.map
211 map = self.map
206 copymap = self.copymap
212 copymap = self.copymap
207 format = self.format
213 format = self.format
208 unpack = struct.unpack
214 unpack = struct.unpack
209
215
210 pos = 40
216 pos = 40
211 e_size = struct.calcsize(format)
217 e_size = struct.calcsize(format)
212
218
213 while pos < len(st):
219 while pos < len(st):
214 newpos = pos + e_size
220 newpos = pos + e_size
215 e = unpack(format, st[pos:newpos])
221 e = unpack(format, st[pos:newpos])
216 l = e[4]
222 l = e[4]
217 pos = newpos
223 pos = newpos
218 newpos = pos + l
224 newpos = pos + l
219 f = st[pos:newpos]
225 f = st[pos:newpos]
220 if '\0' in f:
226 if '\0' in f:
221 f, c = f.split('\0')
227 f, c = f.split('\0')
222 copymap[f] = c
228 copymap[f] = c
223 map[f] = e[:4]
229 map[f] = e[:4]
224 pos = newpos
230 pos = newpos
225
231
226 def read(self):
232 def read(self):
227 self.map = {}
233 self.map = {}
228 self.pl = [nullid, nullid]
234 self.pl = [nullid, nullid]
229 try:
235 try:
230 if self.fp:
236 if self.fp:
231 self.fp.seek(0)
237 self.fp.seek(0)
232 st = self.fp.read()
238 st = self.fp.read()
233 self.fp = None
239 self.fp = None
234 else:
240 else:
235 st = self.opener("dirstate").read()
241 st = self.opener("dirstate").read()
236 if st:
242 if st:
237 self.parse(st)
243 self.parse(st)
238 except IOError, err:
244 except IOError, err:
239 if err.errno != errno.ENOENT: raise
245 if err.errno != errno.ENOENT: raise
240
246
241 def reload(self):
247 def reload(self):
242 def mtime():
248 def mtime():
243 m = self.map and self.map.get('.hgignore')
249 m = self.map and self.map.get('.hgignore')
244 return m and m[-1]
250 return m and m[-1]
245
251
246 old_mtime = self.ignorefunc and mtime()
252 old_mtime = self.ignorefunc and mtime()
247 self.read()
253 self.read()
248 if old_mtime != mtime():
254 if old_mtime != mtime():
249 self.ignorefunc = None
255 self.ignorefunc = None
250
256
251 def copy(self, source, dest):
257 def copy(self, source, dest):
252 self.lazyread()
258 self.lazyread()
253 self.markdirty()
259 self.markdirty()
254 self.copymap[dest] = source
260 self.copymap[dest] = source
255
261
256 def copied(self, file):
262 def copied(self, file):
257 return self.copymap.get(file, None)
263 return self.copymap.get(file, None)
258
264
259 def copies(self):
265 def copies(self):
260 return self.copymap
266 return self.copymap
261
267
262 def initdirs(self):
268 def initdirs(self):
263 if self.dirs is None:
269 if self.dirs is None:
264 self.dirs = {}
270 self.dirs = {}
265 for f in self.map:
271 for f in self.map:
266 self.updatedirs(f, 1)
272 self.updatedirs(f, 1)
267
273
268 def updatedirs(self, path, delta):
274 def updatedirs(self, path, delta):
269 if self.dirs is not None:
275 if self.dirs is not None:
270 for c in strutil.findall(path, '/'):
276 for c in strutil.findall(path, '/'):
271 pc = path[:c]
277 pc = path[:c]
272 self.dirs.setdefault(pc, 0)
278 self.dirs.setdefault(pc, 0)
273 self.dirs[pc] += delta
279 self.dirs[pc] += delta
274
280
275 def checkinterfering(self, files):
281 def checkinterfering(self, files):
276 def prefixes(f):
282 def prefixes(f):
277 for c in strutil.rfindall(f, '/'):
283 for c in strutil.rfindall(f, '/'):
278 yield f[:c]
284 yield f[:c]
279 self.lazyread()
285 self.lazyread()
280 self.initdirs()
286 self.initdirs()
281 seendirs = {}
287 seendirs = {}
282 for f in files:
288 for f in files:
283 # shadows
289 # shadows
284 if self.dirs.get(f):
290 if self.dirs.get(f):
285 raise util.Abort(_('directory named %r already in dirstate') %
291 raise util.Abort(_('directory named %r already in dirstate') %
286 f)
292 f)
287 for d in prefixes(f):
293 for d in prefixes(f):
288 if d in seendirs:
294 if d in seendirs:
289 break
295 break
290 if d in self.map:
296 if d in self.map:
291 raise util.Abort(_('file named %r already in dirstate') %
297 raise util.Abort(_('file named %r already in dirstate') %
292 d)
298 d)
293 seendirs[d] = True
299 seendirs[d] = True
294 # disallowed
300 # disallowed
295 if '\r' in f or '\n' in f:
301 if '\r' in f or '\n' in f:
296 raise util.Abort(_("'\\n' and '\\r' disallowed in filenames"))
302 raise util.Abort(_("'\\n' and '\\r' disallowed in filenames"))
297
303
298 def update(self, files, state, **kw):
304 def update(self, files, state, **kw):
299 ''' current states:
305 ''' current states:
300 n normal
306 n normal
301 m needs merging
307 m needs merging
302 r marked for removal
308 r marked for removal
303 a marked for addition'''
309 a marked for addition'''
304
310
305 if not files: return
311 if not files: return
306 self.lazyread()
312 self.lazyread()
307 self.markdirty()
313 self.markdirty()
308 if state == "a":
314 if state == "a":
309 self.initdirs()
315 self.initdirs()
310 self.checkinterfering(files)
316 self.checkinterfering(files)
311 for f in files:
317 for f in files:
312 if state == "r":
318 if state == "r":
313 self.map[f] = ('r', 0, 0, 0)
319 self.map[f] = ('r', 0, 0, 0)
314 self.updatedirs(f, -1)
320 self.updatedirs(f, -1)
315 else:
321 else:
316 if state == "a":
322 if state == "a":
317 self.updatedirs(f, 1)
323 self.updatedirs(f, 1)
318 s = os.lstat(self.wjoin(f))
324 s = os.lstat(self.wjoin(f))
319 st_size = kw.get('st_size', s.st_size)
325 st_size = kw.get('st_size', s.st_size)
320 st_mtime = kw.get('st_mtime', s.st_mtime)
326 st_mtime = kw.get('st_mtime', s.st_mtime)
321 self.map[f] = (state, s.st_mode, st_size, st_mtime)
327 self.map[f] = (state, s.st_mode, st_size, st_mtime)
322 if self.copymap.has_key(f):
328 if self.copymap.has_key(f):
323 del self.copymap[f]
329 del self.copymap[f]
324
330
325 def forget(self, files):
331 def forget(self, files):
326 if not files: return
332 if not files: return
327 self.lazyread()
333 self.lazyread()
328 self.markdirty()
334 self.markdirty()
329 self.initdirs()
335 self.initdirs()
330 for f in files:
336 for f in files:
331 try:
337 try:
332 del self.map[f]
338 del self.map[f]
333 self.updatedirs(f, -1)
339 self.updatedirs(f, -1)
334 except KeyError:
340 except KeyError:
335 self.ui.warn(_("not in dirstate: %s!\n") % f)
341 self.ui.warn(_("not in dirstate: %s!\n") % f)
336 pass
342 pass
337
343
338 def clear(self):
344 def clear(self):
339 self.map = {}
345 self.map = {}
340 self.copymap = {}
346 self.copymap = {}
341 self.dirs = None
347 self.dirs = None
342 self.markdirty()
348 self.markdirty()
343
349
344 def rebuild(self, parent, files):
350 def rebuild(self, parent, files):
345 self.clear()
351 self.clear()
346 for f in files:
352 for f in files:
347 if files.execf(f):
353 if files.execf(f):
348 self.map[f] = ('n', 0777, -1, 0)
354 self.map[f] = ('n', 0777, -1, 0)
349 else:
355 else:
350 self.map[f] = ('n', 0666, -1, 0)
356 self.map[f] = ('n', 0666, -1, 0)
351 self.pl = (parent, nullid)
357 self.pl = (parent, nullid)
352 self.markdirty()
358 self.markdirty()
353
359
354 def write(self):
360 def write(self):
355 if not self.dirty:
361 if not self.dirty:
356 return
362 return
357 cs = cStringIO.StringIO()
363 cs = cStringIO.StringIO()
358 cs.write("".join(self.pl))
364 cs.write("".join(self.pl))
359 for f, e in self.map.iteritems():
365 for f, e in self.map.iteritems():
360 c = self.copied(f)
366 c = self.copied(f)
361 if c:
367 if c:
362 f = f + "\0" + c
368 f = f + "\0" + c
363 e = struct.pack(self.format, e[0], e[1], e[2], e[3], len(f))
369 e = struct.pack(self.format, e[0], e[1], e[2], e[3], len(f))
364 cs.write(e)
370 cs.write(e)
365 cs.write(f)
371 cs.write(f)
366 st = self.opener("dirstate", "w", atomictemp=True)
372 st = self.opener("dirstate", "w", atomictemp=True)
367 st.write(cs.getvalue())
373 st.write(cs.getvalue())
368 st.rename()
374 st.rename()
369 self.dirty = 0
375 self.dirty = 0
370
376
371 def filterfiles(self, files):
377 def filterfiles(self, files):
372 ret = {}
378 ret = {}
373 unknown = []
379 unknown = []
374
380
375 for x in files:
381 for x in files:
376 if x == '.':
382 if x == '.':
377 return self.map.copy()
383 return self.map.copy()
378 if x not in self.map:
384 if x not in self.map:
379 unknown.append(x)
385 unknown.append(x)
380 else:
386 else:
381 ret[x] = self.map[x]
387 ret[x] = self.map[x]
382
388
383 if not unknown:
389 if not unknown:
384 return ret
390 return ret
385
391
386 b = self.map.keys()
392 b = self.map.keys()
387 b.sort()
393 b.sort()
388 blen = len(b)
394 blen = len(b)
389
395
390 for x in unknown:
396 for x in unknown:
391 bs = bisect.bisect(b, "%s%s" % (x, '/'))
397 bs = bisect.bisect(b, "%s%s" % (x, '/'))
392 while bs < blen:
398 while bs < blen:
393 s = b[bs]
399 s = b[bs]
394 if len(s) > len(x) and s.startswith(x):
400 if len(s) > len(x) and s.startswith(x):
395 ret[s] = self.map[s]
401 ret[s] = self.map[s]
396 else:
402 else:
397 break
403 break
398 bs += 1
404 bs += 1
399 return ret
405 return ret
400
406
401 def supported_type(self, f, st, verbose=False):
407 def supported_type(self, f, st, verbose=False):
402 if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode):
408 if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode):
403 return True
409 return True
404 if verbose:
410 if verbose:
405 kind = 'unknown'
411 kind = 'unknown'
406 if stat.S_ISCHR(st.st_mode): kind = _('character device')
412 if stat.S_ISCHR(st.st_mode): kind = _('character device')
407 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
413 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
408 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
414 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
409 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
415 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
410 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
416 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
411 self.ui.warn(_('%s: unsupported file type (type is %s)\n')
417 self.ui.warn(_('%s: unsupported file type (type is %s)\n')
412 % (self.pathto(f), kind))
418 % (self.pathto(f), kind))
413 return False
419 return False
414
420
415 def walk(self, files=None, match=util.always, badmatch=None):
421 def walk(self, files=None, match=util.always, badmatch=None):
416 # filter out the stat
422 # filter out the stat
417 for src, f, st in self.statwalk(files, match, badmatch=badmatch):
423 for src, f, st in self.statwalk(files, match, badmatch=badmatch):
418 yield src, f
424 yield src, f
419
425
420 def statwalk(self, files=None, match=util.always, ignored=False,
426 def statwalk(self, files=None, match=util.always, ignored=False,
421 badmatch=None, directories=False):
427 badmatch=None, directories=False):
422 '''
428 '''
423 walk recursively through the directory tree, finding all files
429 walk recursively through the directory tree, finding all files
424 matched by the match function
430 matched by the match function
425
431
426 results are yielded in a tuple (src, filename, st), where src
432 results are yielded in a tuple (src, filename, st), where src
427 is one of:
433 is one of:
428 'f' the file was found in the directory tree
434 'f' the file was found in the directory tree
429 'd' the file is a directory of the tree
435 'd' the file is a directory of the tree
430 'm' the file was only in the dirstate and not in the tree
436 'm' the file was only in the dirstate and not in the tree
431 'b' file was not found and matched badmatch
437 'b' file was not found and matched badmatch
432
438
433 and st is the stat result if the file was found in the directory.
439 and st is the stat result if the file was found in the directory.
434 '''
440 '''
435 self.lazyread()
441 self.lazyread()
436
442
437 # walk all files by default
443 # walk all files by default
438 if not files:
444 if not files:
439 files = ['.']
445 files = ['.']
440 dc = self.map.copy()
446 dc = self.map.copy()
441 else:
447 else:
442 files = util.unique(files)
448 files = util.unique(files)
443 dc = self.filterfiles(files)
449 dc = self.filterfiles(files)
444
450
445 def imatch(file_):
451 def imatch(file_):
446 if file_ not in dc and self.ignore(file_):
452 if file_ not in dc and self.ignore(file_):
447 return False
453 return False
448 return match(file_)
454 return match(file_)
449
455
450 ignore = self.ignore
456 ignore = self.ignore
451 if ignored:
457 if ignored:
452 imatch = match
458 imatch = match
453 ignore = util.never
459 ignore = util.never
454
460
455 # self.root may end with a path separator when self.root == '/'
461 # self.root may end with a path separator when self.root == '/'
456 common_prefix_len = len(self.root)
462 common_prefix_len = len(self.root)
457 if not self.root.endswith(os.sep):
463 if not self.root.endswith(os.sep):
458 common_prefix_len += 1
464 common_prefix_len += 1
459 # recursion free walker, faster than os.walk.
465 # recursion free walker, faster than os.walk.
460 def findfiles(s):
466 def findfiles(s):
461 work = [s]
467 work = [s]
462 if directories:
468 if directories:
463 yield 'd', util.normpath(s[common_prefix_len:]), os.lstat(s)
469 yield 'd', util.normpath(s[common_prefix_len:]), os.lstat(s)
464 while work:
470 while work:
465 top = work.pop()
471 top = work.pop()
466 names = os.listdir(top)
472 names = os.listdir(top)
467 names.sort()
473 names.sort()
468 # nd is the top of the repository dir tree
474 # nd is the top of the repository dir tree
469 nd = util.normpath(top[common_prefix_len:])
475 nd = util.normpath(top[common_prefix_len:])
470 if nd == '.':
476 if nd == '.':
471 nd = ''
477 nd = ''
472 else:
478 else:
473 # do not recurse into a repo contained in this
479 # do not recurse into a repo contained in this
474 # one. use bisect to find .hg directory so speed
480 # one. use bisect to find .hg directory so speed
475 # is good on big directory.
481 # is good on big directory.
476 hg = bisect.bisect_left(names, '.hg')
482 hg = bisect.bisect_left(names, '.hg')
477 if hg < len(names) and names[hg] == '.hg':
483 if hg < len(names) and names[hg] == '.hg':
478 if os.path.isdir(os.path.join(top, '.hg')):
484 if os.path.isdir(os.path.join(top, '.hg')):
479 continue
485 continue
480 for f in names:
486 for f in names:
481 np = util.pconvert(os.path.join(nd, f))
487 np = util.pconvert(os.path.join(nd, f))
482 if seen(np):
488 if seen(np):
483 continue
489 continue
484 p = os.path.join(top, f)
490 p = os.path.join(top, f)
485 # don't trip over symlinks
491 # don't trip over symlinks
486 st = os.lstat(p)
492 st = os.lstat(p)
487 if stat.S_ISDIR(st.st_mode):
493 if stat.S_ISDIR(st.st_mode):
488 if not ignore(np):
494 if not ignore(np):
489 work.append(p)
495 work.append(p)
490 if directories:
496 if directories:
491 yield 'd', np, st
497 yield 'd', np, st
492 if imatch(np) and np in dc:
498 if imatch(np) and np in dc:
493 yield 'm', np, st
499 yield 'm', np, st
494 elif imatch(np):
500 elif imatch(np):
495 if self.supported_type(np, st):
501 if self.supported_type(np, st):
496 yield 'f', np, st
502 yield 'f', np, st
497 elif np in dc:
503 elif np in dc:
498 yield 'm', np, st
504 yield 'm', np, st
499
505
500 known = {'.hg': 1}
506 known = {'.hg': 1}
501 def seen(fn):
507 def seen(fn):
502 if fn in known: return True
508 if fn in known: return True
503 known[fn] = 1
509 known[fn] = 1
504
510
505 # step one, find all files that match our criteria
511 # step one, find all files that match our criteria
506 files.sort()
512 files.sort()
507 for ff in files:
513 for ff in files:
508 nf = util.normpath(ff)
514 nf = util.normpath(ff)
509 f = self.wjoin(ff)
515 f = self.wjoin(ff)
510 try:
516 try:
511 st = os.lstat(f)
517 st = os.lstat(f)
512 except OSError, inst:
518 except OSError, inst:
513 found = False
519 found = False
514 for fn in dc:
520 for fn in dc:
515 if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
521 if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
516 found = True
522 found = True
517 break
523 break
518 if not found:
524 if not found:
519 if inst.errno != errno.ENOENT or not badmatch:
525 if inst.errno != errno.ENOENT or not badmatch:
520 self.ui.warn('%s: %s\n' % (self.pathto(ff),
526 self.ui.warn('%s: %s\n' % (self.pathto(ff),
521 inst.strerror))
527 inst.strerror))
522 elif badmatch and badmatch(ff) and imatch(nf):
528 elif badmatch and badmatch(ff) and imatch(nf):
523 yield 'b', ff, None
529 yield 'b', ff, None
524 continue
530 continue
525 if stat.S_ISDIR(st.st_mode):
531 if stat.S_ISDIR(st.st_mode):
526 cmp1 = (lambda x, y: cmp(x[1], y[1]))
532 cmp1 = (lambda x, y: cmp(x[1], y[1]))
527 sorted_ = [ x for x in findfiles(f) ]
533 sorted_ = [ x for x in findfiles(f) ]
528 sorted_.sort(cmp1)
534 sorted_.sort(cmp1)
529 for e in sorted_:
535 for e in sorted_:
530 yield e
536 yield e
531 else:
537 else:
532 if not seen(nf) and match(nf):
538 if not seen(nf) and match(nf):
533 if self.supported_type(ff, st, verbose=True):
539 if self.supported_type(ff, st, verbose=True):
534 yield 'f', nf, st
540 yield 'f', nf, st
535 elif ff in dc:
541 elif ff in dc:
536 yield 'm', nf, st
542 yield 'm', nf, st
537
543
538 # step two run through anything left in the dc hash and yield
544 # step two run through anything left in the dc hash and yield
539 # if we haven't already seen it
545 # if we haven't already seen it
540 ks = dc.keys()
546 ks = dc.keys()
541 ks.sort()
547 ks.sort()
542 for k in ks:
548 for k in ks:
543 if not seen(k) and imatch(k):
549 if not seen(k) and imatch(k):
544 yield 'm', k, None
550 yield 'm', k, None
545
551
546 def status(self, files=None, match=util.always, list_ignored=False,
552 def status(self, files=None, match=util.always, list_ignored=False,
547 list_clean=False):
553 list_clean=False):
548 lookup, modified, added, unknown, ignored = [], [], [], [], []
554 lookup, modified, added, unknown, ignored = [], [], [], [], []
549 removed, deleted, clean = [], [], []
555 removed, deleted, clean = [], [], []
550
556
551 for src, fn, st in self.statwalk(files, match, ignored=list_ignored):
557 for src, fn, st in self.statwalk(files, match, ignored=list_ignored):
552 try:
558 try:
553 type_, mode, size, time = self[fn]
559 type_, mode, size, time = self[fn]
554 except KeyError:
560 except KeyError:
555 if list_ignored and self.ignore(fn):
561 if list_ignored and self.ignore(fn):
556 ignored.append(fn)
562 ignored.append(fn)
557 else:
563 else:
558 unknown.append(fn)
564 unknown.append(fn)
559 continue
565 continue
560 if src == 'm':
566 if src == 'm':
561 nonexistent = True
567 nonexistent = True
562 if not st:
568 if not st:
563 try:
569 try:
564 st = os.lstat(self.wjoin(fn))
570 st = os.lstat(self.wjoin(fn))
565 except OSError, inst:
571 except OSError, inst:
566 if inst.errno != errno.ENOENT:
572 if inst.errno != errno.ENOENT:
567 raise
573 raise
568 st = None
574 st = None
569 # We need to re-check that it is a valid file
575 # We need to re-check that it is a valid file
570 if st and self.supported_type(fn, st):
576 if st and self.supported_type(fn, st):
571 nonexistent = False
577 nonexistent = False
572 # XXX: what to do with file no longer present in the fs
578 # XXX: what to do with file no longer present in the fs
573 # who are not removed in the dirstate ?
579 # who are not removed in the dirstate ?
574 if nonexistent and type_ in "nm":
580 if nonexistent and type_ in "nm":
575 deleted.append(fn)
581 deleted.append(fn)
576 continue
582 continue
577 # check the common case first
583 # check the common case first
578 if type_ == 'n':
584 if type_ == 'n':
579 if not st:
585 if not st:
580 st = os.lstat(self.wjoin(fn))
586 st = os.lstat(self.wjoin(fn))
581 if size >= 0 and (size != st.st_size
587 if size >= 0 and (size != st.st_size
582 or (mode ^ st.st_mode) & 0100):
588 or (mode ^ st.st_mode) & 0100):
583 modified.append(fn)
589 modified.append(fn)
584 elif time != int(st.st_mtime):
590 elif time != int(st.st_mtime):
585 lookup.append(fn)
591 lookup.append(fn)
586 elif list_clean:
592 elif list_clean:
587 clean.append(fn)
593 clean.append(fn)
588 elif type_ == 'm':
594 elif type_ == 'm':
589 modified.append(fn)
595 modified.append(fn)
590 elif type_ == 'a':
596 elif type_ == 'a':
591 added.append(fn)
597 added.append(fn)
592 elif type_ == 'r':
598 elif type_ == 'r':
593 removed.append(fn)
599 removed.append(fn)
594
600
595 return (lookup, modified, added, removed, deleted, unknown, ignored,
601 return (lookup, modified, added, removed, deleted, unknown, ignored,
596 clean)
602 clean)
General Comments 0
You need to be logged in to leave comments. Login now