##// END OF EJS Templates
dirstate-tree: Empty shell for a second Rust DirstateMap implementation...
Simon Sapin -
r47865:473abf47 default
parent child Browse files
Show More
@@ -0,0 +1,216 b''
1 use std::path::PathBuf;
2 use std::time::Duration;
3
4 use crate::matchers::Matcher;
5 use crate::utils::hg_path::{HgPath, HgPathBuf};
6 use crate::CopyMapIter;
7 use crate::DirstateEntry;
8 use crate::DirstateError;
9 use crate::DirstateMapError;
10 use crate::DirstateParents;
11 use crate::DirstateStatus;
12 use crate::EntryState;
13 use crate::FastHashMap;
14 use crate::HgPathCow;
15 use crate::PatternFileWarning;
16 use crate::StateMapIter;
17 use crate::StatusError;
18 use crate::StatusOptions;
19
20 pub struct DirstateMap {
21 // TODO
22 }
23
24 impl DirstateMap {
25 pub fn new() -> Self {
26 todo!()
27 }
28 }
29
30 impl super::dispatch::DirstateMapMethods for DirstateMap {
31 fn clear(&mut self) {
32 todo!()
33 }
34
35 fn add_file(
36 &mut self,
37 _filename: &HgPath,
38 _old_state: EntryState,
39 _entry: DirstateEntry,
40 ) -> Result<(), DirstateMapError> {
41 todo!()
42 }
43
44 fn remove_file(
45 &mut self,
46 _filename: &HgPath,
47 _old_state: EntryState,
48 _size: i32,
49 ) -> Result<(), DirstateMapError> {
50 todo!()
51 }
52
53 fn drop_file(
54 &mut self,
55 _filename: &HgPath,
56 _old_state: EntryState,
57 ) -> Result<bool, DirstateMapError> {
58 todo!()
59 }
60
61 fn clear_ambiguous_times(
62 &mut self,
63 _filenames: Vec<HgPathBuf>,
64 _now: i32,
65 ) {
66 todo!()
67 }
68
69 fn non_normal_entries_contains(&mut self, _key: &HgPath) -> bool {
70 todo!()
71 }
72
73 fn non_normal_entries_remove(&mut self, _key: &HgPath) -> bool {
74 todo!()
75 }
76
77 fn non_normal_or_other_parent_paths(
78 &mut self,
79 ) -> Box<dyn Iterator<Item = &HgPathBuf> + '_> {
80 todo!()
81 }
82
83 fn set_non_normal_other_parent_entries(&mut self, _force: bool) {
84 todo!()
85 }
86
87 fn iter_non_normal_paths(
88 &mut self,
89 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
90 todo!()
91 }
92
93 fn iter_non_normal_paths_panic(
94 &self,
95 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
96 todo!()
97 }
98
99 fn iter_other_parent_paths(
100 &mut self,
101 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
102 todo!()
103 }
104
105 fn has_tracked_dir(
106 &mut self,
107 _directory: &HgPath,
108 ) -> Result<bool, DirstateMapError> {
109 todo!()
110 }
111
112 fn has_dir(
113 &mut self,
114 _directory: &HgPath,
115 ) -> Result<bool, DirstateMapError> {
116 todo!()
117 }
118
119 fn parents(
120 &mut self,
121 _file_contents: &[u8],
122 ) -> Result<&DirstateParents, DirstateError> {
123 todo!()
124 }
125
126 fn set_parents(&mut self, _parents: &DirstateParents) {
127 todo!()
128 }
129
130 fn read<'a>(
131 &mut self,
132 _file_contents: &'a [u8],
133 ) -> Result<Option<&'a DirstateParents>, DirstateError> {
134 todo!()
135 }
136
137 fn pack(
138 &mut self,
139 _parents: DirstateParents,
140 _now: Duration,
141 ) -> Result<Vec<u8>, DirstateError> {
142 todo!()
143 }
144
145 fn build_file_fold_map(&mut self) -> &FastHashMap<HgPathBuf, HgPathBuf> {
146 todo!()
147 }
148
149 fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> {
150 todo!()
151 }
152
153 fn set_dirs(&mut self) -> Result<(), DirstateMapError> {
154 todo!()
155 }
156
157 fn status<'a>(
158 &'a self,
159 _matcher: &'a (dyn Matcher + Sync),
160 _root_dir: PathBuf,
161 _ignore_files: Vec<PathBuf>,
162 _options: StatusOptions,
163 ) -> Result<
164 (
165 (Vec<HgPathCow<'a>>, DirstateStatus<'a>),
166 Vec<PatternFileWarning>,
167 ),
168 StatusError,
169 > {
170 todo!()
171 }
172
173 fn copy_map_len(&self) -> usize {
174 todo!()
175 }
176
177 fn copy_map_iter(&self) -> CopyMapIter<'_> {
178 todo!()
179 }
180
181 fn copy_map_contains_key(&self, _key: &HgPath) -> bool {
182 todo!()
183 }
184
185 fn copy_map_get(&self, _key: &HgPath) -> Option<&HgPathBuf> {
186 todo!()
187 }
188
189 fn copy_map_remove(&mut self, _key: &HgPath) -> Option<HgPathBuf> {
190 todo!()
191 }
192
193 fn copy_map_insert(
194 &mut self,
195 _key: HgPathBuf,
196 _value: HgPathBuf,
197 ) -> Option<HgPathBuf> {
198 todo!()
199 }
200
201 fn len(&self) -> usize {
202 todo!()
203 }
204
205 fn contains_key(&self, _key: &HgPath) -> bool {
206 todo!()
207 }
208
209 fn get(&self, _key: &HgPath) -> Option<&DirstateEntry> {
210 todo!()
211 }
212
213 fn iter(&self) -> StateMapIter<'_> {
214 todo!()
215 }
216 }
@@ -1,2691 +1,2696 b''
1 # configitems.py - centralized declaration of configuration option
1 # configitems.py - centralized declaration of configuration option
2 #
2 #
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import functools
10 import functools
11 import re
11 import re
12
12
13 from . import (
13 from . import (
14 encoding,
14 encoding,
15 error,
15 error,
16 )
16 )
17
17
18
18
19 def loadconfigtable(ui, extname, configtable):
19 def loadconfigtable(ui, extname, configtable):
20 """update config item known to the ui with the extension ones"""
20 """update config item known to the ui with the extension ones"""
21 for section, items in sorted(configtable.items()):
21 for section, items in sorted(configtable.items()):
22 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 knownitems = ui._knownconfig.setdefault(section, itemregister())
23 knownkeys = set(knownitems)
23 knownkeys = set(knownitems)
24 newkeys = set(items)
24 newkeys = set(items)
25 for key in sorted(knownkeys & newkeys):
25 for key in sorted(knownkeys & newkeys):
26 msg = b"extension '%s' overwrite config item '%s.%s'"
26 msg = b"extension '%s' overwrite config item '%s.%s'"
27 msg %= (extname, section, key)
27 msg %= (extname, section, key)
28 ui.develwarn(msg, config=b'warn-config')
28 ui.develwarn(msg, config=b'warn-config')
29
29
30 knownitems.update(items)
30 knownitems.update(items)
31
31
32
32
33 class configitem(object):
33 class configitem(object):
34 """represent a known config item
34 """represent a known config item
35
35
36 :section: the official config section where to find this item,
36 :section: the official config section where to find this item,
37 :name: the official name within the section,
37 :name: the official name within the section,
38 :default: default value for this item,
38 :default: default value for this item,
39 :alias: optional list of tuples as alternatives,
39 :alias: optional list of tuples as alternatives,
40 :generic: this is a generic definition, match name using regular expression.
40 :generic: this is a generic definition, match name using regular expression.
41 """
41 """
42
42
43 def __init__(
43 def __init__(
44 self,
44 self,
45 section,
45 section,
46 name,
46 name,
47 default=None,
47 default=None,
48 alias=(),
48 alias=(),
49 generic=False,
49 generic=False,
50 priority=0,
50 priority=0,
51 experimental=False,
51 experimental=False,
52 ):
52 ):
53 self.section = section
53 self.section = section
54 self.name = name
54 self.name = name
55 self.default = default
55 self.default = default
56 self.alias = list(alias)
56 self.alias = list(alias)
57 self.generic = generic
57 self.generic = generic
58 self.priority = priority
58 self.priority = priority
59 self.experimental = experimental
59 self.experimental = experimental
60 self._re = None
60 self._re = None
61 if generic:
61 if generic:
62 self._re = re.compile(self.name)
62 self._re = re.compile(self.name)
63
63
64
64
65 class itemregister(dict):
65 class itemregister(dict):
66 """A specialized dictionary that can handle wild-card selection"""
66 """A specialized dictionary that can handle wild-card selection"""
67
67
68 def __init__(self):
68 def __init__(self):
69 super(itemregister, self).__init__()
69 super(itemregister, self).__init__()
70 self._generics = set()
70 self._generics = set()
71
71
72 def update(self, other):
72 def update(self, other):
73 super(itemregister, self).update(other)
73 super(itemregister, self).update(other)
74 self._generics.update(other._generics)
74 self._generics.update(other._generics)
75
75
76 def __setitem__(self, key, item):
76 def __setitem__(self, key, item):
77 super(itemregister, self).__setitem__(key, item)
77 super(itemregister, self).__setitem__(key, item)
78 if item.generic:
78 if item.generic:
79 self._generics.add(item)
79 self._generics.add(item)
80
80
81 def get(self, key):
81 def get(self, key):
82 baseitem = super(itemregister, self).get(key)
82 baseitem = super(itemregister, self).get(key)
83 if baseitem is not None and not baseitem.generic:
83 if baseitem is not None and not baseitem.generic:
84 return baseitem
84 return baseitem
85
85
86 # search for a matching generic item
86 # search for a matching generic item
87 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
87 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
88 for item in generics:
88 for item in generics:
89 # we use 'match' instead of 'search' to make the matching simpler
89 # we use 'match' instead of 'search' to make the matching simpler
90 # for people unfamiliar with regular expression. Having the match
90 # for people unfamiliar with regular expression. Having the match
91 # rooted to the start of the string will produce less surprising
91 # rooted to the start of the string will produce less surprising
92 # result for user writing simple regex for sub-attribute.
92 # result for user writing simple regex for sub-attribute.
93 #
93 #
94 # For example using "color\..*" match produces an unsurprising
94 # For example using "color\..*" match produces an unsurprising
95 # result, while using search could suddenly match apparently
95 # result, while using search could suddenly match apparently
96 # unrelated configuration that happens to contains "color."
96 # unrelated configuration that happens to contains "color."
97 # anywhere. This is a tradeoff where we favor requiring ".*" on
97 # anywhere. This is a tradeoff where we favor requiring ".*" on
98 # some match to avoid the need to prefix most pattern with "^".
98 # some match to avoid the need to prefix most pattern with "^".
99 # The "^" seems more error prone.
99 # The "^" seems more error prone.
100 if item._re.match(key):
100 if item._re.match(key):
101 return item
101 return item
102
102
103 return None
103 return None
104
104
105
105
106 coreitems = {}
106 coreitems = {}
107
107
108
108
109 def _register(configtable, *args, **kwargs):
109 def _register(configtable, *args, **kwargs):
110 item = configitem(*args, **kwargs)
110 item = configitem(*args, **kwargs)
111 section = configtable.setdefault(item.section, itemregister())
111 section = configtable.setdefault(item.section, itemregister())
112 if item.name in section:
112 if item.name in section:
113 msg = b"duplicated config item registration for '%s.%s'"
113 msg = b"duplicated config item registration for '%s.%s'"
114 raise error.ProgrammingError(msg % (item.section, item.name))
114 raise error.ProgrammingError(msg % (item.section, item.name))
115 section[item.name] = item
115 section[item.name] = item
116
116
117
117
118 # special value for case where the default is derived from other values
118 # special value for case where the default is derived from other values
119 dynamicdefault = object()
119 dynamicdefault = object()
120
120
121 # Registering actual config items
121 # Registering actual config items
122
122
123
123
124 def getitemregister(configtable):
124 def getitemregister(configtable):
125 f = functools.partial(_register, configtable)
125 f = functools.partial(_register, configtable)
126 # export pseudo enum as configitem.*
126 # export pseudo enum as configitem.*
127 f.dynamicdefault = dynamicdefault
127 f.dynamicdefault = dynamicdefault
128 return f
128 return f
129
129
130
130
131 coreconfigitem = getitemregister(coreitems)
131 coreconfigitem = getitemregister(coreitems)
132
132
133
133
134 def _registerdiffopts(section, configprefix=b''):
134 def _registerdiffopts(section, configprefix=b''):
135 coreconfigitem(
135 coreconfigitem(
136 section,
136 section,
137 configprefix + b'nodates',
137 configprefix + b'nodates',
138 default=False,
138 default=False,
139 )
139 )
140 coreconfigitem(
140 coreconfigitem(
141 section,
141 section,
142 configprefix + b'showfunc',
142 configprefix + b'showfunc',
143 default=False,
143 default=False,
144 )
144 )
145 coreconfigitem(
145 coreconfigitem(
146 section,
146 section,
147 configprefix + b'unified',
147 configprefix + b'unified',
148 default=None,
148 default=None,
149 )
149 )
150 coreconfigitem(
150 coreconfigitem(
151 section,
151 section,
152 configprefix + b'git',
152 configprefix + b'git',
153 default=False,
153 default=False,
154 )
154 )
155 coreconfigitem(
155 coreconfigitem(
156 section,
156 section,
157 configprefix + b'ignorews',
157 configprefix + b'ignorews',
158 default=False,
158 default=False,
159 )
159 )
160 coreconfigitem(
160 coreconfigitem(
161 section,
161 section,
162 configprefix + b'ignorewsamount',
162 configprefix + b'ignorewsamount',
163 default=False,
163 default=False,
164 )
164 )
165 coreconfigitem(
165 coreconfigitem(
166 section,
166 section,
167 configprefix + b'ignoreblanklines',
167 configprefix + b'ignoreblanklines',
168 default=False,
168 default=False,
169 )
169 )
170 coreconfigitem(
170 coreconfigitem(
171 section,
171 section,
172 configprefix + b'ignorewseol',
172 configprefix + b'ignorewseol',
173 default=False,
173 default=False,
174 )
174 )
175 coreconfigitem(
175 coreconfigitem(
176 section,
176 section,
177 configprefix + b'nobinary',
177 configprefix + b'nobinary',
178 default=False,
178 default=False,
179 )
179 )
180 coreconfigitem(
180 coreconfigitem(
181 section,
181 section,
182 configprefix + b'noprefix',
182 configprefix + b'noprefix',
183 default=False,
183 default=False,
184 )
184 )
185 coreconfigitem(
185 coreconfigitem(
186 section,
186 section,
187 configprefix + b'word-diff',
187 configprefix + b'word-diff',
188 default=False,
188 default=False,
189 )
189 )
190
190
191
191
192 coreconfigitem(
192 coreconfigitem(
193 b'alias',
193 b'alias',
194 b'.*',
194 b'.*',
195 default=dynamicdefault,
195 default=dynamicdefault,
196 generic=True,
196 generic=True,
197 )
197 )
198 coreconfigitem(
198 coreconfigitem(
199 b'auth',
199 b'auth',
200 b'cookiefile',
200 b'cookiefile',
201 default=None,
201 default=None,
202 )
202 )
203 _registerdiffopts(section=b'annotate')
203 _registerdiffopts(section=b'annotate')
204 # bookmarks.pushing: internal hack for discovery
204 # bookmarks.pushing: internal hack for discovery
205 coreconfigitem(
205 coreconfigitem(
206 b'bookmarks',
206 b'bookmarks',
207 b'pushing',
207 b'pushing',
208 default=list,
208 default=list,
209 )
209 )
210 # bundle.mainreporoot: internal hack for bundlerepo
210 # bundle.mainreporoot: internal hack for bundlerepo
211 coreconfigitem(
211 coreconfigitem(
212 b'bundle',
212 b'bundle',
213 b'mainreporoot',
213 b'mainreporoot',
214 default=b'',
214 default=b'',
215 )
215 )
216 coreconfigitem(
216 coreconfigitem(
217 b'censor',
217 b'censor',
218 b'policy',
218 b'policy',
219 default=b'abort',
219 default=b'abort',
220 experimental=True,
220 experimental=True,
221 )
221 )
222 coreconfigitem(
222 coreconfigitem(
223 b'chgserver',
223 b'chgserver',
224 b'idletimeout',
224 b'idletimeout',
225 default=3600,
225 default=3600,
226 )
226 )
227 coreconfigitem(
227 coreconfigitem(
228 b'chgserver',
228 b'chgserver',
229 b'skiphash',
229 b'skiphash',
230 default=False,
230 default=False,
231 )
231 )
232 coreconfigitem(
232 coreconfigitem(
233 b'cmdserver',
233 b'cmdserver',
234 b'log',
234 b'log',
235 default=None,
235 default=None,
236 )
236 )
237 coreconfigitem(
237 coreconfigitem(
238 b'cmdserver',
238 b'cmdserver',
239 b'max-log-files',
239 b'max-log-files',
240 default=7,
240 default=7,
241 )
241 )
242 coreconfigitem(
242 coreconfigitem(
243 b'cmdserver',
243 b'cmdserver',
244 b'max-log-size',
244 b'max-log-size',
245 default=b'1 MB',
245 default=b'1 MB',
246 )
246 )
247 coreconfigitem(
247 coreconfigitem(
248 b'cmdserver',
248 b'cmdserver',
249 b'max-repo-cache',
249 b'max-repo-cache',
250 default=0,
250 default=0,
251 experimental=True,
251 experimental=True,
252 )
252 )
253 coreconfigitem(
253 coreconfigitem(
254 b'cmdserver',
254 b'cmdserver',
255 b'message-encodings',
255 b'message-encodings',
256 default=list,
256 default=list,
257 )
257 )
258 coreconfigitem(
258 coreconfigitem(
259 b'cmdserver',
259 b'cmdserver',
260 b'track-log',
260 b'track-log',
261 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
261 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
262 )
262 )
263 coreconfigitem(
263 coreconfigitem(
264 b'cmdserver',
264 b'cmdserver',
265 b'shutdown-on-interrupt',
265 b'shutdown-on-interrupt',
266 default=True,
266 default=True,
267 )
267 )
268 coreconfigitem(
268 coreconfigitem(
269 b'color',
269 b'color',
270 b'.*',
270 b'.*',
271 default=None,
271 default=None,
272 generic=True,
272 generic=True,
273 )
273 )
274 coreconfigitem(
274 coreconfigitem(
275 b'color',
275 b'color',
276 b'mode',
276 b'mode',
277 default=b'auto',
277 default=b'auto',
278 )
278 )
279 coreconfigitem(
279 coreconfigitem(
280 b'color',
280 b'color',
281 b'pagermode',
281 b'pagermode',
282 default=dynamicdefault,
282 default=dynamicdefault,
283 )
283 )
284 coreconfigitem(
284 coreconfigitem(
285 b'command-templates',
285 b'command-templates',
286 b'graphnode',
286 b'graphnode',
287 default=None,
287 default=None,
288 alias=[(b'ui', b'graphnodetemplate')],
288 alias=[(b'ui', b'graphnodetemplate')],
289 )
289 )
290 coreconfigitem(
290 coreconfigitem(
291 b'command-templates',
291 b'command-templates',
292 b'log',
292 b'log',
293 default=None,
293 default=None,
294 alias=[(b'ui', b'logtemplate')],
294 alias=[(b'ui', b'logtemplate')],
295 )
295 )
296 coreconfigitem(
296 coreconfigitem(
297 b'command-templates',
297 b'command-templates',
298 b'mergemarker',
298 b'mergemarker',
299 default=(
299 default=(
300 b'{node|short} '
300 b'{node|short} '
301 b'{ifeq(tags, "tip", "", '
301 b'{ifeq(tags, "tip", "", '
302 b'ifeq(tags, "", "", "{tags} "))}'
302 b'ifeq(tags, "", "", "{tags} "))}'
303 b'{if(bookmarks, "{bookmarks} ")}'
303 b'{if(bookmarks, "{bookmarks} ")}'
304 b'{ifeq(branch, "default", "", "{branch} ")}'
304 b'{ifeq(branch, "default", "", "{branch} ")}'
305 b'- {author|user}: {desc|firstline}'
305 b'- {author|user}: {desc|firstline}'
306 ),
306 ),
307 alias=[(b'ui', b'mergemarkertemplate')],
307 alias=[(b'ui', b'mergemarkertemplate')],
308 )
308 )
309 coreconfigitem(
309 coreconfigitem(
310 b'command-templates',
310 b'command-templates',
311 b'pre-merge-tool-output',
311 b'pre-merge-tool-output',
312 default=None,
312 default=None,
313 alias=[(b'ui', b'pre-merge-tool-output-template')],
313 alias=[(b'ui', b'pre-merge-tool-output-template')],
314 )
314 )
315 coreconfigitem(
315 coreconfigitem(
316 b'command-templates',
316 b'command-templates',
317 b'oneline-summary',
317 b'oneline-summary',
318 default=None,
318 default=None,
319 )
319 )
320 coreconfigitem(
320 coreconfigitem(
321 b'command-templates',
321 b'command-templates',
322 b'oneline-summary.*',
322 b'oneline-summary.*',
323 default=dynamicdefault,
323 default=dynamicdefault,
324 generic=True,
324 generic=True,
325 )
325 )
326 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
326 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
327 coreconfigitem(
327 coreconfigitem(
328 b'commands',
328 b'commands',
329 b'commit.post-status',
329 b'commit.post-status',
330 default=False,
330 default=False,
331 )
331 )
332 coreconfigitem(
332 coreconfigitem(
333 b'commands',
333 b'commands',
334 b'grep.all-files',
334 b'grep.all-files',
335 default=False,
335 default=False,
336 experimental=True,
336 experimental=True,
337 )
337 )
338 coreconfigitem(
338 coreconfigitem(
339 b'commands',
339 b'commands',
340 b'merge.require-rev',
340 b'merge.require-rev',
341 default=False,
341 default=False,
342 )
342 )
343 coreconfigitem(
343 coreconfigitem(
344 b'commands',
344 b'commands',
345 b'push.require-revs',
345 b'push.require-revs',
346 default=False,
346 default=False,
347 )
347 )
348 coreconfigitem(
348 coreconfigitem(
349 b'commands',
349 b'commands',
350 b'resolve.confirm',
350 b'resolve.confirm',
351 default=False,
351 default=False,
352 )
352 )
353 coreconfigitem(
353 coreconfigitem(
354 b'commands',
354 b'commands',
355 b'resolve.explicit-re-merge',
355 b'resolve.explicit-re-merge',
356 default=False,
356 default=False,
357 )
357 )
358 coreconfigitem(
358 coreconfigitem(
359 b'commands',
359 b'commands',
360 b'resolve.mark-check',
360 b'resolve.mark-check',
361 default=b'none',
361 default=b'none',
362 )
362 )
363 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
363 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
364 coreconfigitem(
364 coreconfigitem(
365 b'commands',
365 b'commands',
366 b'show.aliasprefix',
366 b'show.aliasprefix',
367 default=list,
367 default=list,
368 )
368 )
369 coreconfigitem(
369 coreconfigitem(
370 b'commands',
370 b'commands',
371 b'status.relative',
371 b'status.relative',
372 default=False,
372 default=False,
373 )
373 )
374 coreconfigitem(
374 coreconfigitem(
375 b'commands',
375 b'commands',
376 b'status.skipstates',
376 b'status.skipstates',
377 default=[],
377 default=[],
378 experimental=True,
378 experimental=True,
379 )
379 )
380 coreconfigitem(
380 coreconfigitem(
381 b'commands',
381 b'commands',
382 b'status.terse',
382 b'status.terse',
383 default=b'',
383 default=b'',
384 )
384 )
385 coreconfigitem(
385 coreconfigitem(
386 b'commands',
386 b'commands',
387 b'status.verbose',
387 b'status.verbose',
388 default=False,
388 default=False,
389 )
389 )
390 coreconfigitem(
390 coreconfigitem(
391 b'commands',
391 b'commands',
392 b'update.check',
392 b'update.check',
393 default=None,
393 default=None,
394 )
394 )
395 coreconfigitem(
395 coreconfigitem(
396 b'commands',
396 b'commands',
397 b'update.requiredest',
397 b'update.requiredest',
398 default=False,
398 default=False,
399 )
399 )
400 coreconfigitem(
400 coreconfigitem(
401 b'committemplate',
401 b'committemplate',
402 b'.*',
402 b'.*',
403 default=None,
403 default=None,
404 generic=True,
404 generic=True,
405 )
405 )
406 coreconfigitem(
406 coreconfigitem(
407 b'convert',
407 b'convert',
408 b'bzr.saverev',
408 b'bzr.saverev',
409 default=True,
409 default=True,
410 )
410 )
411 coreconfigitem(
411 coreconfigitem(
412 b'convert',
412 b'convert',
413 b'cvsps.cache',
413 b'cvsps.cache',
414 default=True,
414 default=True,
415 )
415 )
416 coreconfigitem(
416 coreconfigitem(
417 b'convert',
417 b'convert',
418 b'cvsps.fuzz',
418 b'cvsps.fuzz',
419 default=60,
419 default=60,
420 )
420 )
421 coreconfigitem(
421 coreconfigitem(
422 b'convert',
422 b'convert',
423 b'cvsps.logencoding',
423 b'cvsps.logencoding',
424 default=None,
424 default=None,
425 )
425 )
426 coreconfigitem(
426 coreconfigitem(
427 b'convert',
427 b'convert',
428 b'cvsps.mergefrom',
428 b'cvsps.mergefrom',
429 default=None,
429 default=None,
430 )
430 )
431 coreconfigitem(
431 coreconfigitem(
432 b'convert',
432 b'convert',
433 b'cvsps.mergeto',
433 b'cvsps.mergeto',
434 default=None,
434 default=None,
435 )
435 )
436 coreconfigitem(
436 coreconfigitem(
437 b'convert',
437 b'convert',
438 b'git.committeractions',
438 b'git.committeractions',
439 default=lambda: [b'messagedifferent'],
439 default=lambda: [b'messagedifferent'],
440 )
440 )
441 coreconfigitem(
441 coreconfigitem(
442 b'convert',
442 b'convert',
443 b'git.extrakeys',
443 b'git.extrakeys',
444 default=list,
444 default=list,
445 )
445 )
446 coreconfigitem(
446 coreconfigitem(
447 b'convert',
447 b'convert',
448 b'git.findcopiesharder',
448 b'git.findcopiesharder',
449 default=False,
449 default=False,
450 )
450 )
451 coreconfigitem(
451 coreconfigitem(
452 b'convert',
452 b'convert',
453 b'git.remoteprefix',
453 b'git.remoteprefix',
454 default=b'remote',
454 default=b'remote',
455 )
455 )
456 coreconfigitem(
456 coreconfigitem(
457 b'convert',
457 b'convert',
458 b'git.renamelimit',
458 b'git.renamelimit',
459 default=400,
459 default=400,
460 )
460 )
461 coreconfigitem(
461 coreconfigitem(
462 b'convert',
462 b'convert',
463 b'git.saverev',
463 b'git.saverev',
464 default=True,
464 default=True,
465 )
465 )
466 coreconfigitem(
466 coreconfigitem(
467 b'convert',
467 b'convert',
468 b'git.similarity',
468 b'git.similarity',
469 default=50,
469 default=50,
470 )
470 )
471 coreconfigitem(
471 coreconfigitem(
472 b'convert',
472 b'convert',
473 b'git.skipsubmodules',
473 b'git.skipsubmodules',
474 default=False,
474 default=False,
475 )
475 )
476 coreconfigitem(
476 coreconfigitem(
477 b'convert',
477 b'convert',
478 b'hg.clonebranches',
478 b'hg.clonebranches',
479 default=False,
479 default=False,
480 )
480 )
481 coreconfigitem(
481 coreconfigitem(
482 b'convert',
482 b'convert',
483 b'hg.ignoreerrors',
483 b'hg.ignoreerrors',
484 default=False,
484 default=False,
485 )
485 )
486 coreconfigitem(
486 coreconfigitem(
487 b'convert',
487 b'convert',
488 b'hg.preserve-hash',
488 b'hg.preserve-hash',
489 default=False,
489 default=False,
490 )
490 )
491 coreconfigitem(
491 coreconfigitem(
492 b'convert',
492 b'convert',
493 b'hg.revs',
493 b'hg.revs',
494 default=None,
494 default=None,
495 )
495 )
496 coreconfigitem(
496 coreconfigitem(
497 b'convert',
497 b'convert',
498 b'hg.saverev',
498 b'hg.saverev',
499 default=False,
499 default=False,
500 )
500 )
501 coreconfigitem(
501 coreconfigitem(
502 b'convert',
502 b'convert',
503 b'hg.sourcename',
503 b'hg.sourcename',
504 default=None,
504 default=None,
505 )
505 )
506 coreconfigitem(
506 coreconfigitem(
507 b'convert',
507 b'convert',
508 b'hg.startrev',
508 b'hg.startrev',
509 default=None,
509 default=None,
510 )
510 )
511 coreconfigitem(
511 coreconfigitem(
512 b'convert',
512 b'convert',
513 b'hg.tagsbranch',
513 b'hg.tagsbranch',
514 default=b'default',
514 default=b'default',
515 )
515 )
516 coreconfigitem(
516 coreconfigitem(
517 b'convert',
517 b'convert',
518 b'hg.usebranchnames',
518 b'hg.usebranchnames',
519 default=True,
519 default=True,
520 )
520 )
521 coreconfigitem(
521 coreconfigitem(
522 b'convert',
522 b'convert',
523 b'ignoreancestorcheck',
523 b'ignoreancestorcheck',
524 default=False,
524 default=False,
525 experimental=True,
525 experimental=True,
526 )
526 )
527 coreconfigitem(
527 coreconfigitem(
528 b'convert',
528 b'convert',
529 b'localtimezone',
529 b'localtimezone',
530 default=False,
530 default=False,
531 )
531 )
532 coreconfigitem(
532 coreconfigitem(
533 b'convert',
533 b'convert',
534 b'p4.encoding',
534 b'p4.encoding',
535 default=dynamicdefault,
535 default=dynamicdefault,
536 )
536 )
537 coreconfigitem(
537 coreconfigitem(
538 b'convert',
538 b'convert',
539 b'p4.startrev',
539 b'p4.startrev',
540 default=0,
540 default=0,
541 )
541 )
542 coreconfigitem(
542 coreconfigitem(
543 b'convert',
543 b'convert',
544 b'skiptags',
544 b'skiptags',
545 default=False,
545 default=False,
546 )
546 )
547 coreconfigitem(
547 coreconfigitem(
548 b'convert',
548 b'convert',
549 b'svn.debugsvnlog',
549 b'svn.debugsvnlog',
550 default=True,
550 default=True,
551 )
551 )
552 coreconfigitem(
552 coreconfigitem(
553 b'convert',
553 b'convert',
554 b'svn.trunk',
554 b'svn.trunk',
555 default=None,
555 default=None,
556 )
556 )
557 coreconfigitem(
557 coreconfigitem(
558 b'convert',
558 b'convert',
559 b'svn.tags',
559 b'svn.tags',
560 default=None,
560 default=None,
561 )
561 )
562 coreconfigitem(
562 coreconfigitem(
563 b'convert',
563 b'convert',
564 b'svn.branches',
564 b'svn.branches',
565 default=None,
565 default=None,
566 )
566 )
567 coreconfigitem(
567 coreconfigitem(
568 b'convert',
568 b'convert',
569 b'svn.startrev',
569 b'svn.startrev',
570 default=0,
570 default=0,
571 )
571 )
572 coreconfigitem(
572 coreconfigitem(
573 b'convert',
573 b'convert',
574 b'svn.dangerous-set-commit-dates',
574 b'svn.dangerous-set-commit-dates',
575 default=False,
575 default=False,
576 )
576 )
577 coreconfigitem(
577 coreconfigitem(
578 b'debug',
578 b'debug',
579 b'dirstate.delaywrite',
579 b'dirstate.delaywrite',
580 default=0,
580 default=0,
581 )
581 )
582 coreconfigitem(
582 coreconfigitem(
583 b'debug',
583 b'debug',
584 b'revlog.verifyposition.changelog',
584 b'revlog.verifyposition.changelog',
585 default=b'',
585 default=b'',
586 )
586 )
587 coreconfigitem(
587 coreconfigitem(
588 b'defaults',
588 b'defaults',
589 b'.*',
589 b'.*',
590 default=None,
590 default=None,
591 generic=True,
591 generic=True,
592 )
592 )
593 coreconfigitem(
593 coreconfigitem(
594 b'devel',
594 b'devel',
595 b'all-warnings',
595 b'all-warnings',
596 default=False,
596 default=False,
597 )
597 )
598 coreconfigitem(
598 coreconfigitem(
599 b'devel',
599 b'devel',
600 b'bundle2.debug',
600 b'bundle2.debug',
601 default=False,
601 default=False,
602 )
602 )
603 coreconfigitem(
603 coreconfigitem(
604 b'devel',
604 b'devel',
605 b'bundle.delta',
605 b'bundle.delta',
606 default=b'',
606 default=b'',
607 )
607 )
608 coreconfigitem(
608 coreconfigitem(
609 b'devel',
609 b'devel',
610 b'cache-vfs',
610 b'cache-vfs',
611 default=None,
611 default=None,
612 )
612 )
613 coreconfigitem(
613 coreconfigitem(
614 b'devel',
614 b'devel',
615 b'check-locks',
615 b'check-locks',
616 default=False,
616 default=False,
617 )
617 )
618 coreconfigitem(
618 coreconfigitem(
619 b'devel',
619 b'devel',
620 b'check-relroot',
620 b'check-relroot',
621 default=False,
621 default=False,
622 )
622 )
623 # Track copy information for all file, not just "added" one (very slow)
623 # Track copy information for all file, not just "added" one (very slow)
624 coreconfigitem(
624 coreconfigitem(
625 b'devel',
625 b'devel',
626 b'copy-tracing.trace-all-files',
626 b'copy-tracing.trace-all-files',
627 default=False,
627 default=False,
628 )
628 )
629 coreconfigitem(
629 coreconfigitem(
630 b'devel',
630 b'devel',
631 b'default-date',
631 b'default-date',
632 default=None,
632 default=None,
633 )
633 )
634 coreconfigitem(
634 coreconfigitem(
635 b'devel',
635 b'devel',
636 b'deprec-warn',
636 b'deprec-warn',
637 default=False,
637 default=False,
638 )
638 )
639 coreconfigitem(
639 coreconfigitem(
640 b'devel',
640 b'devel',
641 b'disableloaddefaultcerts',
641 b'disableloaddefaultcerts',
642 default=False,
642 default=False,
643 )
643 )
644 coreconfigitem(
644 coreconfigitem(
645 b'devel',
645 b'devel',
646 b'warn-empty-changegroup',
646 b'warn-empty-changegroup',
647 default=False,
647 default=False,
648 )
648 )
649 coreconfigitem(
649 coreconfigitem(
650 b'devel',
650 b'devel',
651 b'legacy.exchange',
651 b'legacy.exchange',
652 default=list,
652 default=list,
653 )
653 )
654 # When True, revlogs use a special reference version of the nodemap, that is not
654 # When True, revlogs use a special reference version of the nodemap, that is not
655 # performant but is "known" to behave properly.
655 # performant but is "known" to behave properly.
656 coreconfigitem(
656 coreconfigitem(
657 b'devel',
657 b'devel',
658 b'persistent-nodemap',
658 b'persistent-nodemap',
659 default=False,
659 default=False,
660 )
660 )
661 coreconfigitem(
661 coreconfigitem(
662 b'devel',
662 b'devel',
663 b'servercafile',
663 b'servercafile',
664 default=b'',
664 default=b'',
665 )
665 )
666 coreconfigitem(
666 coreconfigitem(
667 b'devel',
667 b'devel',
668 b'serverexactprotocol',
668 b'serverexactprotocol',
669 default=b'',
669 default=b'',
670 )
670 )
671 coreconfigitem(
671 coreconfigitem(
672 b'devel',
672 b'devel',
673 b'serverrequirecert',
673 b'serverrequirecert',
674 default=False,
674 default=False,
675 )
675 )
676 coreconfigitem(
676 coreconfigitem(
677 b'devel',
677 b'devel',
678 b'strip-obsmarkers',
678 b'strip-obsmarkers',
679 default=True,
679 default=True,
680 )
680 )
681 coreconfigitem(
681 coreconfigitem(
682 b'devel',
682 b'devel',
683 b'warn-config',
683 b'warn-config',
684 default=None,
684 default=None,
685 )
685 )
686 coreconfigitem(
686 coreconfigitem(
687 b'devel',
687 b'devel',
688 b'warn-config-default',
688 b'warn-config-default',
689 default=None,
689 default=None,
690 )
690 )
691 coreconfigitem(
691 coreconfigitem(
692 b'devel',
692 b'devel',
693 b'user.obsmarker',
693 b'user.obsmarker',
694 default=None,
694 default=None,
695 )
695 )
696 coreconfigitem(
696 coreconfigitem(
697 b'devel',
697 b'devel',
698 b'warn-config-unknown',
698 b'warn-config-unknown',
699 default=None,
699 default=None,
700 )
700 )
701 coreconfigitem(
701 coreconfigitem(
702 b'devel',
702 b'devel',
703 b'debug.copies',
703 b'debug.copies',
704 default=False,
704 default=False,
705 )
705 )
706 coreconfigitem(
706 coreconfigitem(
707 b'devel',
707 b'devel',
708 b'copy-tracing.multi-thread',
708 b'copy-tracing.multi-thread',
709 default=True,
709 default=True,
710 )
710 )
711 coreconfigitem(
711 coreconfigitem(
712 b'devel',
712 b'devel',
713 b'debug.extensions',
713 b'debug.extensions',
714 default=False,
714 default=False,
715 )
715 )
716 coreconfigitem(
716 coreconfigitem(
717 b'devel',
717 b'devel',
718 b'debug.repo-filters',
718 b'debug.repo-filters',
719 default=False,
719 default=False,
720 )
720 )
721 coreconfigitem(
721 coreconfigitem(
722 b'devel',
722 b'devel',
723 b'debug.peer-request',
723 b'debug.peer-request',
724 default=False,
724 default=False,
725 )
725 )
726 # If discovery.exchange-heads is False, the discovery will not start with
726 # If discovery.exchange-heads is False, the discovery will not start with
727 # remote head fetching and local head querying.
727 # remote head fetching and local head querying.
728 coreconfigitem(
728 coreconfigitem(
729 b'devel',
729 b'devel',
730 b'discovery.exchange-heads',
730 b'discovery.exchange-heads',
731 default=True,
731 default=True,
732 )
732 )
733 # If discovery.grow-sample is False, the sample size used in set discovery will
733 # If discovery.grow-sample is False, the sample size used in set discovery will
734 # not be increased through the process
734 # not be increased through the process
735 coreconfigitem(
735 coreconfigitem(
736 b'devel',
736 b'devel',
737 b'discovery.grow-sample',
737 b'discovery.grow-sample',
738 default=True,
738 default=True,
739 )
739 )
740 # When discovery.grow-sample.dynamic is True, the default, the sample size is
740 # When discovery.grow-sample.dynamic is True, the default, the sample size is
741 # adapted to the shape of the undecided set (it is set to the max of:
741 # adapted to the shape of the undecided set (it is set to the max of:
742 # <target-size>, len(roots(undecided)), len(heads(undecided)
742 # <target-size>, len(roots(undecided)), len(heads(undecided)
743 coreconfigitem(
743 coreconfigitem(
744 b'devel',
744 b'devel',
745 b'discovery.grow-sample.dynamic',
745 b'discovery.grow-sample.dynamic',
746 default=True,
746 default=True,
747 )
747 )
748 # discovery.grow-sample.rate control the rate at which the sample grow
748 # discovery.grow-sample.rate control the rate at which the sample grow
749 coreconfigitem(
749 coreconfigitem(
750 b'devel',
750 b'devel',
751 b'discovery.grow-sample.rate',
751 b'discovery.grow-sample.rate',
752 default=1.05,
752 default=1.05,
753 )
753 )
754 # If discovery.randomize is False, random sampling during discovery are
754 # If discovery.randomize is False, random sampling during discovery are
755 # deterministic. It is meant for integration tests.
755 # deterministic. It is meant for integration tests.
756 coreconfigitem(
756 coreconfigitem(
757 b'devel',
757 b'devel',
758 b'discovery.randomize',
758 b'discovery.randomize',
759 default=True,
759 default=True,
760 )
760 )
761 # Control the initial size of the discovery sample
761 # Control the initial size of the discovery sample
762 coreconfigitem(
762 coreconfigitem(
763 b'devel',
763 b'devel',
764 b'discovery.sample-size',
764 b'discovery.sample-size',
765 default=200,
765 default=200,
766 )
766 )
767 # Control the initial size of the discovery for initial change
767 # Control the initial size of the discovery for initial change
768 coreconfigitem(
768 coreconfigitem(
769 b'devel',
769 b'devel',
770 b'discovery.sample-size.initial',
770 b'discovery.sample-size.initial',
771 default=100,
771 default=100,
772 )
772 )
773 _registerdiffopts(section=b'diff')
773 _registerdiffopts(section=b'diff')
774 coreconfigitem(
774 coreconfigitem(
775 b'diff',
775 b'diff',
776 b'merge',
776 b'merge',
777 default=False,
777 default=False,
778 experimental=True,
778 experimental=True,
779 )
779 )
780 coreconfigitem(
780 coreconfigitem(
781 b'email',
781 b'email',
782 b'bcc',
782 b'bcc',
783 default=None,
783 default=None,
784 )
784 )
785 coreconfigitem(
785 coreconfigitem(
786 b'email',
786 b'email',
787 b'cc',
787 b'cc',
788 default=None,
788 default=None,
789 )
789 )
790 coreconfigitem(
790 coreconfigitem(
791 b'email',
791 b'email',
792 b'charsets',
792 b'charsets',
793 default=list,
793 default=list,
794 )
794 )
795 coreconfigitem(
795 coreconfigitem(
796 b'email',
796 b'email',
797 b'from',
797 b'from',
798 default=None,
798 default=None,
799 )
799 )
800 coreconfigitem(
800 coreconfigitem(
801 b'email',
801 b'email',
802 b'method',
802 b'method',
803 default=b'smtp',
803 default=b'smtp',
804 )
804 )
805 coreconfigitem(
805 coreconfigitem(
806 b'email',
806 b'email',
807 b'reply-to',
807 b'reply-to',
808 default=None,
808 default=None,
809 )
809 )
810 coreconfigitem(
810 coreconfigitem(
811 b'email',
811 b'email',
812 b'to',
812 b'to',
813 default=None,
813 default=None,
814 )
814 )
815 coreconfigitem(
815 coreconfigitem(
816 b'experimental',
816 b'experimental',
817 b'archivemetatemplate',
817 b'archivemetatemplate',
818 default=dynamicdefault,
818 default=dynamicdefault,
819 )
819 )
820 coreconfigitem(
820 coreconfigitem(
821 b'experimental',
821 b'experimental',
822 b'auto-publish',
822 b'auto-publish',
823 default=b'publish',
823 default=b'publish',
824 )
824 )
825 coreconfigitem(
825 coreconfigitem(
826 b'experimental',
826 b'experimental',
827 b'bundle-phases',
827 b'bundle-phases',
828 default=False,
828 default=False,
829 )
829 )
830 coreconfigitem(
830 coreconfigitem(
831 b'experimental',
831 b'experimental',
832 b'bundle2-advertise',
832 b'bundle2-advertise',
833 default=True,
833 default=True,
834 )
834 )
835 coreconfigitem(
835 coreconfigitem(
836 b'experimental',
836 b'experimental',
837 b'bundle2-output-capture',
837 b'bundle2-output-capture',
838 default=False,
838 default=False,
839 )
839 )
840 coreconfigitem(
840 coreconfigitem(
841 b'experimental',
841 b'experimental',
842 b'bundle2.pushback',
842 b'bundle2.pushback',
843 default=False,
843 default=False,
844 )
844 )
845 coreconfigitem(
845 coreconfigitem(
846 b'experimental',
846 b'experimental',
847 b'bundle2lazylocking',
847 b'bundle2lazylocking',
848 default=False,
848 default=False,
849 )
849 )
850 coreconfigitem(
850 coreconfigitem(
851 b'experimental',
851 b'experimental',
852 b'bundlecomplevel',
852 b'bundlecomplevel',
853 default=None,
853 default=None,
854 )
854 )
855 coreconfigitem(
855 coreconfigitem(
856 b'experimental',
856 b'experimental',
857 b'bundlecomplevel.bzip2',
857 b'bundlecomplevel.bzip2',
858 default=None,
858 default=None,
859 )
859 )
860 coreconfigitem(
860 coreconfigitem(
861 b'experimental',
861 b'experimental',
862 b'bundlecomplevel.gzip',
862 b'bundlecomplevel.gzip',
863 default=None,
863 default=None,
864 )
864 )
865 coreconfigitem(
865 coreconfigitem(
866 b'experimental',
866 b'experimental',
867 b'bundlecomplevel.none',
867 b'bundlecomplevel.none',
868 default=None,
868 default=None,
869 )
869 )
870 coreconfigitem(
870 coreconfigitem(
871 b'experimental',
871 b'experimental',
872 b'bundlecomplevel.zstd',
872 b'bundlecomplevel.zstd',
873 default=None,
873 default=None,
874 )
874 )
875 coreconfigitem(
875 coreconfigitem(
876 b'experimental',
876 b'experimental',
877 b'bundlecompthreads',
877 b'bundlecompthreads',
878 default=None,
878 default=None,
879 )
879 )
880 coreconfigitem(
880 coreconfigitem(
881 b'experimental',
881 b'experimental',
882 b'bundlecompthreads.bzip2',
882 b'bundlecompthreads.bzip2',
883 default=None,
883 default=None,
884 )
884 )
885 coreconfigitem(
885 coreconfigitem(
886 b'experimental',
886 b'experimental',
887 b'bundlecompthreads.gzip',
887 b'bundlecompthreads.gzip',
888 default=None,
888 default=None,
889 )
889 )
890 coreconfigitem(
890 coreconfigitem(
891 b'experimental',
891 b'experimental',
892 b'bundlecompthreads.none',
892 b'bundlecompthreads.none',
893 default=None,
893 default=None,
894 )
894 )
895 coreconfigitem(
895 coreconfigitem(
896 b'experimental',
896 b'experimental',
897 b'bundlecompthreads.zstd',
897 b'bundlecompthreads.zstd',
898 default=None,
898 default=None,
899 )
899 )
900 coreconfigitem(
900 coreconfigitem(
901 b'experimental',
901 b'experimental',
902 b'changegroup3',
902 b'changegroup3',
903 default=False,
903 default=False,
904 )
904 )
905 coreconfigitem(
905 coreconfigitem(
906 b'experimental',
906 b'experimental',
907 b'changegroup4',
907 b'changegroup4',
908 default=False,
908 default=False,
909 )
909 )
910 coreconfigitem(
910 coreconfigitem(
911 b'experimental',
911 b'experimental',
912 b'cleanup-as-archived',
912 b'cleanup-as-archived',
913 default=False,
913 default=False,
914 )
914 )
915 coreconfigitem(
915 coreconfigitem(
916 b'experimental',
916 b'experimental',
917 b'clientcompressionengines',
917 b'clientcompressionengines',
918 default=list,
918 default=list,
919 )
919 )
920 coreconfigitem(
920 coreconfigitem(
921 b'experimental',
921 b'experimental',
922 b'copytrace',
922 b'copytrace',
923 default=b'on',
923 default=b'on',
924 )
924 )
925 coreconfigitem(
925 coreconfigitem(
926 b'experimental',
926 b'experimental',
927 b'copytrace.movecandidateslimit',
927 b'copytrace.movecandidateslimit',
928 default=100,
928 default=100,
929 )
929 )
930 coreconfigitem(
930 coreconfigitem(
931 b'experimental',
931 b'experimental',
932 b'copytrace.sourcecommitlimit',
932 b'copytrace.sourcecommitlimit',
933 default=100,
933 default=100,
934 )
934 )
935 coreconfigitem(
935 coreconfigitem(
936 b'experimental',
936 b'experimental',
937 b'copies.read-from',
937 b'copies.read-from',
938 default=b"filelog-only",
938 default=b"filelog-only",
939 )
939 )
940 coreconfigitem(
940 coreconfigitem(
941 b'experimental',
941 b'experimental',
942 b'copies.write-to',
942 b'copies.write-to',
943 default=b'filelog-only',
943 default=b'filelog-only',
944 )
944 )
945 coreconfigitem(
945 coreconfigitem(
946 b'experimental',
946 b'experimental',
947 b'crecordtest',
947 b'crecordtest',
948 default=None,
948 default=None,
949 )
949 )
950 coreconfigitem(
950 coreconfigitem(
951 b'experimental',
951 b'experimental',
952 b'directaccess',
952 b'directaccess',
953 default=False,
953 default=False,
954 )
954 )
955 coreconfigitem(
955 coreconfigitem(
956 b'experimental',
956 b'experimental',
957 b'directaccess.revnums',
957 b'directaccess.revnums',
958 default=False,
958 default=False,
959 )
959 )
960 coreconfigitem(
960 coreconfigitem(
961 b'experimental',
961 b'experimental',
962 b'dirstate-tree.in-memory',
963 default=False,
964 )
965 coreconfigitem(
966 b'experimental',
962 b'editortmpinhg',
967 b'editortmpinhg',
963 default=False,
968 default=False,
964 )
969 )
965 coreconfigitem(
970 coreconfigitem(
966 b'experimental',
971 b'experimental',
967 b'evolution',
972 b'evolution',
968 default=list,
973 default=list,
969 )
974 )
970 coreconfigitem(
975 coreconfigitem(
971 b'experimental',
976 b'experimental',
972 b'evolution.allowdivergence',
977 b'evolution.allowdivergence',
973 default=False,
978 default=False,
974 alias=[(b'experimental', b'allowdivergence')],
979 alias=[(b'experimental', b'allowdivergence')],
975 )
980 )
976 coreconfigitem(
981 coreconfigitem(
977 b'experimental',
982 b'experimental',
978 b'evolution.allowunstable',
983 b'evolution.allowunstable',
979 default=None,
984 default=None,
980 )
985 )
981 coreconfigitem(
986 coreconfigitem(
982 b'experimental',
987 b'experimental',
983 b'evolution.createmarkers',
988 b'evolution.createmarkers',
984 default=None,
989 default=None,
985 )
990 )
986 coreconfigitem(
991 coreconfigitem(
987 b'experimental',
992 b'experimental',
988 b'evolution.effect-flags',
993 b'evolution.effect-flags',
989 default=True,
994 default=True,
990 alias=[(b'experimental', b'effect-flags')],
995 alias=[(b'experimental', b'effect-flags')],
991 )
996 )
992 coreconfigitem(
997 coreconfigitem(
993 b'experimental',
998 b'experimental',
994 b'evolution.exchange',
999 b'evolution.exchange',
995 default=None,
1000 default=None,
996 )
1001 )
997 coreconfigitem(
1002 coreconfigitem(
998 b'experimental',
1003 b'experimental',
999 b'evolution.bundle-obsmarker',
1004 b'evolution.bundle-obsmarker',
1000 default=False,
1005 default=False,
1001 )
1006 )
1002 coreconfigitem(
1007 coreconfigitem(
1003 b'experimental',
1008 b'experimental',
1004 b'evolution.bundle-obsmarker:mandatory',
1009 b'evolution.bundle-obsmarker:mandatory',
1005 default=True,
1010 default=True,
1006 )
1011 )
1007 coreconfigitem(
1012 coreconfigitem(
1008 b'experimental',
1013 b'experimental',
1009 b'log.topo',
1014 b'log.topo',
1010 default=False,
1015 default=False,
1011 )
1016 )
1012 coreconfigitem(
1017 coreconfigitem(
1013 b'experimental',
1018 b'experimental',
1014 b'evolution.report-instabilities',
1019 b'evolution.report-instabilities',
1015 default=True,
1020 default=True,
1016 )
1021 )
1017 coreconfigitem(
1022 coreconfigitem(
1018 b'experimental',
1023 b'experimental',
1019 b'evolution.track-operation',
1024 b'evolution.track-operation',
1020 default=True,
1025 default=True,
1021 )
1026 )
1022 # repo-level config to exclude a revset visibility
1027 # repo-level config to exclude a revset visibility
1023 #
1028 #
1024 # The target use case is to use `share` to expose different subset of the same
1029 # The target use case is to use `share` to expose different subset of the same
1025 # repository, especially server side. See also `server.view`.
1030 # repository, especially server side. See also `server.view`.
1026 coreconfigitem(
1031 coreconfigitem(
1027 b'experimental',
1032 b'experimental',
1028 b'extra-filter-revs',
1033 b'extra-filter-revs',
1029 default=None,
1034 default=None,
1030 )
1035 )
1031 coreconfigitem(
1036 coreconfigitem(
1032 b'experimental',
1037 b'experimental',
1033 b'maxdeltachainspan',
1038 b'maxdeltachainspan',
1034 default=-1,
1039 default=-1,
1035 )
1040 )
1036 # tracks files which were undeleted (merge might delete them but we explicitly
1041 # tracks files which were undeleted (merge might delete them but we explicitly
1037 # kept/undeleted them) and creates new filenodes for them
1042 # kept/undeleted them) and creates new filenodes for them
1038 coreconfigitem(
1043 coreconfigitem(
1039 b'experimental',
1044 b'experimental',
1040 b'merge-track-salvaged',
1045 b'merge-track-salvaged',
1041 default=False,
1046 default=False,
1042 )
1047 )
1043 coreconfigitem(
1048 coreconfigitem(
1044 b'experimental',
1049 b'experimental',
1045 b'mergetempdirprefix',
1050 b'mergetempdirprefix',
1046 default=None,
1051 default=None,
1047 )
1052 )
1048 coreconfigitem(
1053 coreconfigitem(
1049 b'experimental',
1054 b'experimental',
1050 b'mmapindexthreshold',
1055 b'mmapindexthreshold',
1051 default=None,
1056 default=None,
1052 )
1057 )
1053 coreconfigitem(
1058 coreconfigitem(
1054 b'experimental',
1059 b'experimental',
1055 b'narrow',
1060 b'narrow',
1056 default=False,
1061 default=False,
1057 )
1062 )
1058 coreconfigitem(
1063 coreconfigitem(
1059 b'experimental',
1064 b'experimental',
1060 b'nonnormalparanoidcheck',
1065 b'nonnormalparanoidcheck',
1061 default=False,
1066 default=False,
1062 )
1067 )
1063 coreconfigitem(
1068 coreconfigitem(
1064 b'experimental',
1069 b'experimental',
1065 b'exportableenviron',
1070 b'exportableenviron',
1066 default=list,
1071 default=list,
1067 )
1072 )
1068 coreconfigitem(
1073 coreconfigitem(
1069 b'experimental',
1074 b'experimental',
1070 b'extendedheader.index',
1075 b'extendedheader.index',
1071 default=None,
1076 default=None,
1072 )
1077 )
1073 coreconfigitem(
1078 coreconfigitem(
1074 b'experimental',
1079 b'experimental',
1075 b'extendedheader.similarity',
1080 b'extendedheader.similarity',
1076 default=False,
1081 default=False,
1077 )
1082 )
1078 coreconfigitem(
1083 coreconfigitem(
1079 b'experimental',
1084 b'experimental',
1080 b'graphshorten',
1085 b'graphshorten',
1081 default=False,
1086 default=False,
1082 )
1087 )
1083 coreconfigitem(
1088 coreconfigitem(
1084 b'experimental',
1089 b'experimental',
1085 b'graphstyle.parent',
1090 b'graphstyle.parent',
1086 default=dynamicdefault,
1091 default=dynamicdefault,
1087 )
1092 )
1088 coreconfigitem(
1093 coreconfigitem(
1089 b'experimental',
1094 b'experimental',
1090 b'graphstyle.missing',
1095 b'graphstyle.missing',
1091 default=dynamicdefault,
1096 default=dynamicdefault,
1092 )
1097 )
1093 coreconfigitem(
1098 coreconfigitem(
1094 b'experimental',
1099 b'experimental',
1095 b'graphstyle.grandparent',
1100 b'graphstyle.grandparent',
1096 default=dynamicdefault,
1101 default=dynamicdefault,
1097 )
1102 )
1098 coreconfigitem(
1103 coreconfigitem(
1099 b'experimental',
1104 b'experimental',
1100 b'hook-track-tags',
1105 b'hook-track-tags',
1101 default=False,
1106 default=False,
1102 )
1107 )
1103 coreconfigitem(
1108 coreconfigitem(
1104 b'experimental',
1109 b'experimental',
1105 b'httppeer.advertise-v2',
1110 b'httppeer.advertise-v2',
1106 default=False,
1111 default=False,
1107 )
1112 )
1108 coreconfigitem(
1113 coreconfigitem(
1109 b'experimental',
1114 b'experimental',
1110 b'httppeer.v2-encoder-order',
1115 b'httppeer.v2-encoder-order',
1111 default=None,
1116 default=None,
1112 )
1117 )
1113 coreconfigitem(
1118 coreconfigitem(
1114 b'experimental',
1119 b'experimental',
1115 b'httppostargs',
1120 b'httppostargs',
1116 default=False,
1121 default=False,
1117 )
1122 )
1118 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1123 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1119 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1124 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1120
1125
1121 coreconfigitem(
1126 coreconfigitem(
1122 b'experimental',
1127 b'experimental',
1123 b'obsmarkers-exchange-debug',
1128 b'obsmarkers-exchange-debug',
1124 default=False,
1129 default=False,
1125 )
1130 )
1126 coreconfigitem(
1131 coreconfigitem(
1127 b'experimental',
1132 b'experimental',
1128 b'remotenames',
1133 b'remotenames',
1129 default=False,
1134 default=False,
1130 )
1135 )
1131 coreconfigitem(
1136 coreconfigitem(
1132 b'experimental',
1137 b'experimental',
1133 b'removeemptydirs',
1138 b'removeemptydirs',
1134 default=True,
1139 default=True,
1135 )
1140 )
1136 coreconfigitem(
1141 coreconfigitem(
1137 b'experimental',
1142 b'experimental',
1138 b'revert.interactive.select-to-keep',
1143 b'revert.interactive.select-to-keep',
1139 default=False,
1144 default=False,
1140 )
1145 )
1141 coreconfigitem(
1146 coreconfigitem(
1142 b'experimental',
1147 b'experimental',
1143 b'revisions.prefixhexnode',
1148 b'revisions.prefixhexnode',
1144 default=False,
1149 default=False,
1145 )
1150 )
1146 coreconfigitem(
1151 coreconfigitem(
1147 b'experimental',
1152 b'experimental',
1148 b'revlogv2',
1153 b'revlogv2',
1149 default=None,
1154 default=None,
1150 )
1155 )
1151 coreconfigitem(
1156 coreconfigitem(
1152 b'experimental',
1157 b'experimental',
1153 b'revisions.disambiguatewithin',
1158 b'revisions.disambiguatewithin',
1154 default=None,
1159 default=None,
1155 )
1160 )
1156 coreconfigitem(
1161 coreconfigitem(
1157 b'experimental',
1162 b'experimental',
1158 b'rust.index',
1163 b'rust.index',
1159 default=False,
1164 default=False,
1160 )
1165 )
1161 coreconfigitem(
1166 coreconfigitem(
1162 b'experimental',
1167 b'experimental',
1163 b'server.filesdata.recommended-batch-size',
1168 b'server.filesdata.recommended-batch-size',
1164 default=50000,
1169 default=50000,
1165 )
1170 )
1166 coreconfigitem(
1171 coreconfigitem(
1167 b'experimental',
1172 b'experimental',
1168 b'server.manifestdata.recommended-batch-size',
1173 b'server.manifestdata.recommended-batch-size',
1169 default=100000,
1174 default=100000,
1170 )
1175 )
1171 coreconfigitem(
1176 coreconfigitem(
1172 b'experimental',
1177 b'experimental',
1173 b'server.stream-narrow-clones',
1178 b'server.stream-narrow-clones',
1174 default=False,
1179 default=False,
1175 )
1180 )
1176 coreconfigitem(
1181 coreconfigitem(
1177 b'experimental',
1182 b'experimental',
1178 b'single-head-per-branch',
1183 b'single-head-per-branch',
1179 default=False,
1184 default=False,
1180 )
1185 )
1181 coreconfigitem(
1186 coreconfigitem(
1182 b'experimental',
1187 b'experimental',
1183 b'single-head-per-branch:account-closed-heads',
1188 b'single-head-per-branch:account-closed-heads',
1184 default=False,
1189 default=False,
1185 )
1190 )
1186 coreconfigitem(
1191 coreconfigitem(
1187 b'experimental',
1192 b'experimental',
1188 b'single-head-per-branch:public-changes-only',
1193 b'single-head-per-branch:public-changes-only',
1189 default=False,
1194 default=False,
1190 )
1195 )
1191 coreconfigitem(
1196 coreconfigitem(
1192 b'experimental',
1197 b'experimental',
1193 b'sshserver.support-v2',
1198 b'sshserver.support-v2',
1194 default=False,
1199 default=False,
1195 )
1200 )
1196 coreconfigitem(
1201 coreconfigitem(
1197 b'experimental',
1202 b'experimental',
1198 b'sparse-read',
1203 b'sparse-read',
1199 default=False,
1204 default=False,
1200 )
1205 )
1201 coreconfigitem(
1206 coreconfigitem(
1202 b'experimental',
1207 b'experimental',
1203 b'sparse-read.density-threshold',
1208 b'sparse-read.density-threshold',
1204 default=0.50,
1209 default=0.50,
1205 )
1210 )
1206 coreconfigitem(
1211 coreconfigitem(
1207 b'experimental',
1212 b'experimental',
1208 b'sparse-read.min-gap-size',
1213 b'sparse-read.min-gap-size',
1209 default=b'65K',
1214 default=b'65K',
1210 )
1215 )
1211 coreconfigitem(
1216 coreconfigitem(
1212 b'experimental',
1217 b'experimental',
1213 b'treemanifest',
1218 b'treemanifest',
1214 default=False,
1219 default=False,
1215 )
1220 )
1216 coreconfigitem(
1221 coreconfigitem(
1217 b'experimental',
1222 b'experimental',
1218 b'update.atomic-file',
1223 b'update.atomic-file',
1219 default=False,
1224 default=False,
1220 )
1225 )
1221 coreconfigitem(
1226 coreconfigitem(
1222 b'experimental',
1227 b'experimental',
1223 b'sshpeer.advertise-v2',
1228 b'sshpeer.advertise-v2',
1224 default=False,
1229 default=False,
1225 )
1230 )
1226 coreconfigitem(
1231 coreconfigitem(
1227 b'experimental',
1232 b'experimental',
1228 b'web.apiserver',
1233 b'web.apiserver',
1229 default=False,
1234 default=False,
1230 )
1235 )
1231 coreconfigitem(
1236 coreconfigitem(
1232 b'experimental',
1237 b'experimental',
1233 b'web.api.http-v2',
1238 b'web.api.http-v2',
1234 default=False,
1239 default=False,
1235 )
1240 )
1236 coreconfigitem(
1241 coreconfigitem(
1237 b'experimental',
1242 b'experimental',
1238 b'web.api.debugreflect',
1243 b'web.api.debugreflect',
1239 default=False,
1244 default=False,
1240 )
1245 )
1241 coreconfigitem(
1246 coreconfigitem(
1242 b'experimental',
1247 b'experimental',
1243 b'worker.wdir-get-thread-safe',
1248 b'worker.wdir-get-thread-safe',
1244 default=False,
1249 default=False,
1245 )
1250 )
1246 coreconfigitem(
1251 coreconfigitem(
1247 b'experimental',
1252 b'experimental',
1248 b'worker.repository-upgrade',
1253 b'worker.repository-upgrade',
1249 default=False,
1254 default=False,
1250 )
1255 )
1251 coreconfigitem(
1256 coreconfigitem(
1252 b'experimental',
1257 b'experimental',
1253 b'xdiff',
1258 b'xdiff',
1254 default=False,
1259 default=False,
1255 )
1260 )
1256 coreconfigitem(
1261 coreconfigitem(
1257 b'extensions',
1262 b'extensions',
1258 b'.*',
1263 b'.*',
1259 default=None,
1264 default=None,
1260 generic=True,
1265 generic=True,
1261 )
1266 )
1262 coreconfigitem(
1267 coreconfigitem(
1263 b'extdata',
1268 b'extdata',
1264 b'.*',
1269 b'.*',
1265 default=None,
1270 default=None,
1266 generic=True,
1271 generic=True,
1267 )
1272 )
1268 coreconfigitem(
1273 coreconfigitem(
1269 b'format',
1274 b'format',
1270 b'bookmarks-in-store',
1275 b'bookmarks-in-store',
1271 default=False,
1276 default=False,
1272 )
1277 )
1273 coreconfigitem(
1278 coreconfigitem(
1274 b'format',
1279 b'format',
1275 b'chunkcachesize',
1280 b'chunkcachesize',
1276 default=None,
1281 default=None,
1277 experimental=True,
1282 experimental=True,
1278 )
1283 )
1279 coreconfigitem(
1284 coreconfigitem(
1280 b'format',
1285 b'format',
1281 b'dotencode',
1286 b'dotencode',
1282 default=True,
1287 default=True,
1283 )
1288 )
1284 coreconfigitem(
1289 coreconfigitem(
1285 b'format',
1290 b'format',
1286 b'generaldelta',
1291 b'generaldelta',
1287 default=False,
1292 default=False,
1288 experimental=True,
1293 experimental=True,
1289 )
1294 )
1290 coreconfigitem(
1295 coreconfigitem(
1291 b'format',
1296 b'format',
1292 b'manifestcachesize',
1297 b'manifestcachesize',
1293 default=None,
1298 default=None,
1294 experimental=True,
1299 experimental=True,
1295 )
1300 )
1296 coreconfigitem(
1301 coreconfigitem(
1297 b'format',
1302 b'format',
1298 b'maxchainlen',
1303 b'maxchainlen',
1299 default=dynamicdefault,
1304 default=dynamicdefault,
1300 experimental=True,
1305 experimental=True,
1301 )
1306 )
1302 coreconfigitem(
1307 coreconfigitem(
1303 b'format',
1308 b'format',
1304 b'obsstore-version',
1309 b'obsstore-version',
1305 default=None,
1310 default=None,
1306 )
1311 )
1307 coreconfigitem(
1312 coreconfigitem(
1308 b'format',
1313 b'format',
1309 b'sparse-revlog',
1314 b'sparse-revlog',
1310 default=True,
1315 default=True,
1311 )
1316 )
1312 coreconfigitem(
1317 coreconfigitem(
1313 b'format',
1318 b'format',
1314 b'revlog-compression',
1319 b'revlog-compression',
1315 default=lambda: [b'zstd', b'zlib'],
1320 default=lambda: [b'zstd', b'zlib'],
1316 alias=[(b'experimental', b'format.compression')],
1321 alias=[(b'experimental', b'format.compression')],
1317 )
1322 )
1318 coreconfigitem(
1323 coreconfigitem(
1319 b'format',
1324 b'format',
1320 b'usefncache',
1325 b'usefncache',
1321 default=True,
1326 default=True,
1322 )
1327 )
1323 coreconfigitem(
1328 coreconfigitem(
1324 b'format',
1329 b'format',
1325 b'usegeneraldelta',
1330 b'usegeneraldelta',
1326 default=True,
1331 default=True,
1327 )
1332 )
1328 coreconfigitem(
1333 coreconfigitem(
1329 b'format',
1334 b'format',
1330 b'usestore',
1335 b'usestore',
1331 default=True,
1336 default=True,
1332 )
1337 )
1333
1338
1334
1339
1335 def _persistent_nodemap_default():
1340 def _persistent_nodemap_default():
1336 """compute `use-persistent-nodemap` default value
1341 """compute `use-persistent-nodemap` default value
1337
1342
1338 The feature is disabled unless a fast implementation is available.
1343 The feature is disabled unless a fast implementation is available.
1339 """
1344 """
1340 from . import policy
1345 from . import policy
1341
1346
1342 return policy.importrust('revlog') is not None
1347 return policy.importrust('revlog') is not None
1343
1348
1344
1349
1345 coreconfigitem(
1350 coreconfigitem(
1346 b'format',
1351 b'format',
1347 b'use-persistent-nodemap',
1352 b'use-persistent-nodemap',
1348 default=_persistent_nodemap_default,
1353 default=_persistent_nodemap_default,
1349 )
1354 )
1350 # TODO needs to grow a docket file to at least store the last offset of the data
1355 # TODO needs to grow a docket file to at least store the last offset of the data
1351 # file when rewriting sidedata.
1356 # file when rewriting sidedata.
1352 # Will also need a way of dealing with garbage data if we allow rewriting
1357 # Will also need a way of dealing with garbage data if we allow rewriting
1353 # *existing* sidedata.
1358 # *existing* sidedata.
1354 # Exchange-wise, we will also need to do something more efficient than keeping
1359 # Exchange-wise, we will also need to do something more efficient than keeping
1355 # references to the affected revlogs, especially memory-wise when rewriting
1360 # references to the affected revlogs, especially memory-wise when rewriting
1356 # sidedata.
1361 # sidedata.
1357 # Also... compress the sidedata? (this should be coming very soon)
1362 # Also... compress the sidedata? (this should be coming very soon)
1358 coreconfigitem(
1363 coreconfigitem(
1359 b'format',
1364 b'format',
1360 b'exp-revlogv2.2',
1365 b'exp-revlogv2.2',
1361 default=False,
1366 default=False,
1362 experimental=True,
1367 experimental=True,
1363 )
1368 )
1364 coreconfigitem(
1369 coreconfigitem(
1365 b'format',
1370 b'format',
1366 b'exp-use-copies-side-data-changeset',
1371 b'exp-use-copies-side-data-changeset',
1367 default=False,
1372 default=False,
1368 experimental=True,
1373 experimental=True,
1369 )
1374 )
1370 coreconfigitem(
1375 coreconfigitem(
1371 b'format',
1376 b'format',
1372 b'exp-use-side-data',
1377 b'exp-use-side-data',
1373 default=False,
1378 default=False,
1374 experimental=True,
1379 experimental=True,
1375 )
1380 )
1376 coreconfigitem(
1381 coreconfigitem(
1377 b'format',
1382 b'format',
1378 b'use-share-safe',
1383 b'use-share-safe',
1379 default=False,
1384 default=False,
1380 )
1385 )
1381 coreconfigitem(
1386 coreconfigitem(
1382 b'format',
1387 b'format',
1383 b'internal-phase',
1388 b'internal-phase',
1384 default=False,
1389 default=False,
1385 experimental=True,
1390 experimental=True,
1386 )
1391 )
1387 coreconfigitem(
1392 coreconfigitem(
1388 b'fsmonitor',
1393 b'fsmonitor',
1389 b'warn_when_unused',
1394 b'warn_when_unused',
1390 default=True,
1395 default=True,
1391 )
1396 )
1392 coreconfigitem(
1397 coreconfigitem(
1393 b'fsmonitor',
1398 b'fsmonitor',
1394 b'warn_update_file_count',
1399 b'warn_update_file_count',
1395 default=50000,
1400 default=50000,
1396 )
1401 )
1397 coreconfigitem(
1402 coreconfigitem(
1398 b'fsmonitor',
1403 b'fsmonitor',
1399 b'warn_update_file_count_rust',
1404 b'warn_update_file_count_rust',
1400 default=400000,
1405 default=400000,
1401 )
1406 )
1402 coreconfigitem(
1407 coreconfigitem(
1403 b'help',
1408 b'help',
1404 br'hidden-command\..*',
1409 br'hidden-command\..*',
1405 default=False,
1410 default=False,
1406 generic=True,
1411 generic=True,
1407 )
1412 )
1408 coreconfigitem(
1413 coreconfigitem(
1409 b'help',
1414 b'help',
1410 br'hidden-topic\..*',
1415 br'hidden-topic\..*',
1411 default=False,
1416 default=False,
1412 generic=True,
1417 generic=True,
1413 )
1418 )
1414 coreconfigitem(
1419 coreconfigitem(
1415 b'hooks',
1420 b'hooks',
1416 b'[^:]*',
1421 b'[^:]*',
1417 default=dynamicdefault,
1422 default=dynamicdefault,
1418 generic=True,
1423 generic=True,
1419 )
1424 )
1420 coreconfigitem(
1425 coreconfigitem(
1421 b'hooks',
1426 b'hooks',
1422 b'.*:run-with-plain',
1427 b'.*:run-with-plain',
1423 default=True,
1428 default=True,
1424 generic=True,
1429 generic=True,
1425 )
1430 )
1426 coreconfigitem(
1431 coreconfigitem(
1427 b'hgweb-paths',
1432 b'hgweb-paths',
1428 b'.*',
1433 b'.*',
1429 default=list,
1434 default=list,
1430 generic=True,
1435 generic=True,
1431 )
1436 )
1432 coreconfigitem(
1437 coreconfigitem(
1433 b'hostfingerprints',
1438 b'hostfingerprints',
1434 b'.*',
1439 b'.*',
1435 default=list,
1440 default=list,
1436 generic=True,
1441 generic=True,
1437 )
1442 )
1438 coreconfigitem(
1443 coreconfigitem(
1439 b'hostsecurity',
1444 b'hostsecurity',
1440 b'ciphers',
1445 b'ciphers',
1441 default=None,
1446 default=None,
1442 )
1447 )
1443 coreconfigitem(
1448 coreconfigitem(
1444 b'hostsecurity',
1449 b'hostsecurity',
1445 b'minimumprotocol',
1450 b'minimumprotocol',
1446 default=dynamicdefault,
1451 default=dynamicdefault,
1447 )
1452 )
1448 coreconfigitem(
1453 coreconfigitem(
1449 b'hostsecurity',
1454 b'hostsecurity',
1450 b'.*:minimumprotocol$',
1455 b'.*:minimumprotocol$',
1451 default=dynamicdefault,
1456 default=dynamicdefault,
1452 generic=True,
1457 generic=True,
1453 )
1458 )
1454 coreconfigitem(
1459 coreconfigitem(
1455 b'hostsecurity',
1460 b'hostsecurity',
1456 b'.*:ciphers$',
1461 b'.*:ciphers$',
1457 default=dynamicdefault,
1462 default=dynamicdefault,
1458 generic=True,
1463 generic=True,
1459 )
1464 )
1460 coreconfigitem(
1465 coreconfigitem(
1461 b'hostsecurity',
1466 b'hostsecurity',
1462 b'.*:fingerprints$',
1467 b'.*:fingerprints$',
1463 default=list,
1468 default=list,
1464 generic=True,
1469 generic=True,
1465 )
1470 )
1466 coreconfigitem(
1471 coreconfigitem(
1467 b'hostsecurity',
1472 b'hostsecurity',
1468 b'.*:verifycertsfile$',
1473 b'.*:verifycertsfile$',
1469 default=None,
1474 default=None,
1470 generic=True,
1475 generic=True,
1471 )
1476 )
1472
1477
1473 coreconfigitem(
1478 coreconfigitem(
1474 b'http_proxy',
1479 b'http_proxy',
1475 b'always',
1480 b'always',
1476 default=False,
1481 default=False,
1477 )
1482 )
1478 coreconfigitem(
1483 coreconfigitem(
1479 b'http_proxy',
1484 b'http_proxy',
1480 b'host',
1485 b'host',
1481 default=None,
1486 default=None,
1482 )
1487 )
1483 coreconfigitem(
1488 coreconfigitem(
1484 b'http_proxy',
1489 b'http_proxy',
1485 b'no',
1490 b'no',
1486 default=list,
1491 default=list,
1487 )
1492 )
1488 coreconfigitem(
1493 coreconfigitem(
1489 b'http_proxy',
1494 b'http_proxy',
1490 b'passwd',
1495 b'passwd',
1491 default=None,
1496 default=None,
1492 )
1497 )
1493 coreconfigitem(
1498 coreconfigitem(
1494 b'http_proxy',
1499 b'http_proxy',
1495 b'user',
1500 b'user',
1496 default=None,
1501 default=None,
1497 )
1502 )
1498
1503
1499 coreconfigitem(
1504 coreconfigitem(
1500 b'http',
1505 b'http',
1501 b'timeout',
1506 b'timeout',
1502 default=None,
1507 default=None,
1503 )
1508 )
1504
1509
1505 coreconfigitem(
1510 coreconfigitem(
1506 b'logtoprocess',
1511 b'logtoprocess',
1507 b'commandexception',
1512 b'commandexception',
1508 default=None,
1513 default=None,
1509 )
1514 )
1510 coreconfigitem(
1515 coreconfigitem(
1511 b'logtoprocess',
1516 b'logtoprocess',
1512 b'commandfinish',
1517 b'commandfinish',
1513 default=None,
1518 default=None,
1514 )
1519 )
1515 coreconfigitem(
1520 coreconfigitem(
1516 b'logtoprocess',
1521 b'logtoprocess',
1517 b'command',
1522 b'command',
1518 default=None,
1523 default=None,
1519 )
1524 )
1520 coreconfigitem(
1525 coreconfigitem(
1521 b'logtoprocess',
1526 b'logtoprocess',
1522 b'develwarn',
1527 b'develwarn',
1523 default=None,
1528 default=None,
1524 )
1529 )
1525 coreconfigitem(
1530 coreconfigitem(
1526 b'logtoprocess',
1531 b'logtoprocess',
1527 b'uiblocked',
1532 b'uiblocked',
1528 default=None,
1533 default=None,
1529 )
1534 )
1530 coreconfigitem(
1535 coreconfigitem(
1531 b'merge',
1536 b'merge',
1532 b'checkunknown',
1537 b'checkunknown',
1533 default=b'abort',
1538 default=b'abort',
1534 )
1539 )
1535 coreconfigitem(
1540 coreconfigitem(
1536 b'merge',
1541 b'merge',
1537 b'checkignored',
1542 b'checkignored',
1538 default=b'abort',
1543 default=b'abort',
1539 )
1544 )
1540 coreconfigitem(
1545 coreconfigitem(
1541 b'experimental',
1546 b'experimental',
1542 b'merge.checkpathconflicts',
1547 b'merge.checkpathconflicts',
1543 default=False,
1548 default=False,
1544 )
1549 )
1545 coreconfigitem(
1550 coreconfigitem(
1546 b'merge',
1551 b'merge',
1547 b'followcopies',
1552 b'followcopies',
1548 default=True,
1553 default=True,
1549 )
1554 )
1550 coreconfigitem(
1555 coreconfigitem(
1551 b'merge',
1556 b'merge',
1552 b'on-failure',
1557 b'on-failure',
1553 default=b'continue',
1558 default=b'continue',
1554 )
1559 )
1555 coreconfigitem(
1560 coreconfigitem(
1556 b'merge',
1561 b'merge',
1557 b'preferancestor',
1562 b'preferancestor',
1558 default=lambda: [b'*'],
1563 default=lambda: [b'*'],
1559 experimental=True,
1564 experimental=True,
1560 )
1565 )
1561 coreconfigitem(
1566 coreconfigitem(
1562 b'merge',
1567 b'merge',
1563 b'strict-capability-check',
1568 b'strict-capability-check',
1564 default=False,
1569 default=False,
1565 )
1570 )
1566 coreconfigitem(
1571 coreconfigitem(
1567 b'merge-tools',
1572 b'merge-tools',
1568 b'.*',
1573 b'.*',
1569 default=None,
1574 default=None,
1570 generic=True,
1575 generic=True,
1571 )
1576 )
1572 coreconfigitem(
1577 coreconfigitem(
1573 b'merge-tools',
1578 b'merge-tools',
1574 br'.*\.args$',
1579 br'.*\.args$',
1575 default=b"$local $base $other",
1580 default=b"$local $base $other",
1576 generic=True,
1581 generic=True,
1577 priority=-1,
1582 priority=-1,
1578 )
1583 )
1579 coreconfigitem(
1584 coreconfigitem(
1580 b'merge-tools',
1585 b'merge-tools',
1581 br'.*\.binary$',
1586 br'.*\.binary$',
1582 default=False,
1587 default=False,
1583 generic=True,
1588 generic=True,
1584 priority=-1,
1589 priority=-1,
1585 )
1590 )
1586 coreconfigitem(
1591 coreconfigitem(
1587 b'merge-tools',
1592 b'merge-tools',
1588 br'.*\.check$',
1593 br'.*\.check$',
1589 default=list,
1594 default=list,
1590 generic=True,
1595 generic=True,
1591 priority=-1,
1596 priority=-1,
1592 )
1597 )
1593 coreconfigitem(
1598 coreconfigitem(
1594 b'merge-tools',
1599 b'merge-tools',
1595 br'.*\.checkchanged$',
1600 br'.*\.checkchanged$',
1596 default=False,
1601 default=False,
1597 generic=True,
1602 generic=True,
1598 priority=-1,
1603 priority=-1,
1599 )
1604 )
1600 coreconfigitem(
1605 coreconfigitem(
1601 b'merge-tools',
1606 b'merge-tools',
1602 br'.*\.executable$',
1607 br'.*\.executable$',
1603 default=dynamicdefault,
1608 default=dynamicdefault,
1604 generic=True,
1609 generic=True,
1605 priority=-1,
1610 priority=-1,
1606 )
1611 )
1607 coreconfigitem(
1612 coreconfigitem(
1608 b'merge-tools',
1613 b'merge-tools',
1609 br'.*\.fixeol$',
1614 br'.*\.fixeol$',
1610 default=False,
1615 default=False,
1611 generic=True,
1616 generic=True,
1612 priority=-1,
1617 priority=-1,
1613 )
1618 )
1614 coreconfigitem(
1619 coreconfigitem(
1615 b'merge-tools',
1620 b'merge-tools',
1616 br'.*\.gui$',
1621 br'.*\.gui$',
1617 default=False,
1622 default=False,
1618 generic=True,
1623 generic=True,
1619 priority=-1,
1624 priority=-1,
1620 )
1625 )
1621 coreconfigitem(
1626 coreconfigitem(
1622 b'merge-tools',
1627 b'merge-tools',
1623 br'.*\.mergemarkers$',
1628 br'.*\.mergemarkers$',
1624 default=b'basic',
1629 default=b'basic',
1625 generic=True,
1630 generic=True,
1626 priority=-1,
1631 priority=-1,
1627 )
1632 )
1628 coreconfigitem(
1633 coreconfigitem(
1629 b'merge-tools',
1634 b'merge-tools',
1630 br'.*\.mergemarkertemplate$',
1635 br'.*\.mergemarkertemplate$',
1631 default=dynamicdefault, # take from command-templates.mergemarker
1636 default=dynamicdefault, # take from command-templates.mergemarker
1632 generic=True,
1637 generic=True,
1633 priority=-1,
1638 priority=-1,
1634 )
1639 )
1635 coreconfigitem(
1640 coreconfigitem(
1636 b'merge-tools',
1641 b'merge-tools',
1637 br'.*\.priority$',
1642 br'.*\.priority$',
1638 default=0,
1643 default=0,
1639 generic=True,
1644 generic=True,
1640 priority=-1,
1645 priority=-1,
1641 )
1646 )
1642 coreconfigitem(
1647 coreconfigitem(
1643 b'merge-tools',
1648 b'merge-tools',
1644 br'.*\.premerge$',
1649 br'.*\.premerge$',
1645 default=dynamicdefault,
1650 default=dynamicdefault,
1646 generic=True,
1651 generic=True,
1647 priority=-1,
1652 priority=-1,
1648 )
1653 )
1649 coreconfigitem(
1654 coreconfigitem(
1650 b'merge-tools',
1655 b'merge-tools',
1651 br'.*\.symlink$',
1656 br'.*\.symlink$',
1652 default=False,
1657 default=False,
1653 generic=True,
1658 generic=True,
1654 priority=-1,
1659 priority=-1,
1655 )
1660 )
1656 coreconfigitem(
1661 coreconfigitem(
1657 b'pager',
1662 b'pager',
1658 b'attend-.*',
1663 b'attend-.*',
1659 default=dynamicdefault,
1664 default=dynamicdefault,
1660 generic=True,
1665 generic=True,
1661 )
1666 )
1662 coreconfigitem(
1667 coreconfigitem(
1663 b'pager',
1668 b'pager',
1664 b'ignore',
1669 b'ignore',
1665 default=list,
1670 default=list,
1666 )
1671 )
1667 coreconfigitem(
1672 coreconfigitem(
1668 b'pager',
1673 b'pager',
1669 b'pager',
1674 b'pager',
1670 default=dynamicdefault,
1675 default=dynamicdefault,
1671 )
1676 )
1672 coreconfigitem(
1677 coreconfigitem(
1673 b'patch',
1678 b'patch',
1674 b'eol',
1679 b'eol',
1675 default=b'strict',
1680 default=b'strict',
1676 )
1681 )
1677 coreconfigitem(
1682 coreconfigitem(
1678 b'patch',
1683 b'patch',
1679 b'fuzz',
1684 b'fuzz',
1680 default=2,
1685 default=2,
1681 )
1686 )
1682 coreconfigitem(
1687 coreconfigitem(
1683 b'paths',
1688 b'paths',
1684 b'default',
1689 b'default',
1685 default=None,
1690 default=None,
1686 )
1691 )
1687 coreconfigitem(
1692 coreconfigitem(
1688 b'paths',
1693 b'paths',
1689 b'default-push',
1694 b'default-push',
1690 default=None,
1695 default=None,
1691 )
1696 )
1692 coreconfigitem(
1697 coreconfigitem(
1693 b'paths',
1698 b'paths',
1694 b'.*',
1699 b'.*',
1695 default=None,
1700 default=None,
1696 generic=True,
1701 generic=True,
1697 )
1702 )
1698 coreconfigitem(
1703 coreconfigitem(
1699 b'phases',
1704 b'phases',
1700 b'checksubrepos',
1705 b'checksubrepos',
1701 default=b'follow',
1706 default=b'follow',
1702 )
1707 )
1703 coreconfigitem(
1708 coreconfigitem(
1704 b'phases',
1709 b'phases',
1705 b'new-commit',
1710 b'new-commit',
1706 default=b'draft',
1711 default=b'draft',
1707 )
1712 )
1708 coreconfigitem(
1713 coreconfigitem(
1709 b'phases',
1714 b'phases',
1710 b'publish',
1715 b'publish',
1711 default=True,
1716 default=True,
1712 )
1717 )
1713 coreconfigitem(
1718 coreconfigitem(
1714 b'profiling',
1719 b'profiling',
1715 b'enabled',
1720 b'enabled',
1716 default=False,
1721 default=False,
1717 )
1722 )
1718 coreconfigitem(
1723 coreconfigitem(
1719 b'profiling',
1724 b'profiling',
1720 b'format',
1725 b'format',
1721 default=b'text',
1726 default=b'text',
1722 )
1727 )
1723 coreconfigitem(
1728 coreconfigitem(
1724 b'profiling',
1729 b'profiling',
1725 b'freq',
1730 b'freq',
1726 default=1000,
1731 default=1000,
1727 )
1732 )
1728 coreconfigitem(
1733 coreconfigitem(
1729 b'profiling',
1734 b'profiling',
1730 b'limit',
1735 b'limit',
1731 default=30,
1736 default=30,
1732 )
1737 )
1733 coreconfigitem(
1738 coreconfigitem(
1734 b'profiling',
1739 b'profiling',
1735 b'nested',
1740 b'nested',
1736 default=0,
1741 default=0,
1737 )
1742 )
1738 coreconfigitem(
1743 coreconfigitem(
1739 b'profiling',
1744 b'profiling',
1740 b'output',
1745 b'output',
1741 default=None,
1746 default=None,
1742 )
1747 )
1743 coreconfigitem(
1748 coreconfigitem(
1744 b'profiling',
1749 b'profiling',
1745 b'showmax',
1750 b'showmax',
1746 default=0.999,
1751 default=0.999,
1747 )
1752 )
1748 coreconfigitem(
1753 coreconfigitem(
1749 b'profiling',
1754 b'profiling',
1750 b'showmin',
1755 b'showmin',
1751 default=dynamicdefault,
1756 default=dynamicdefault,
1752 )
1757 )
1753 coreconfigitem(
1758 coreconfigitem(
1754 b'profiling',
1759 b'profiling',
1755 b'showtime',
1760 b'showtime',
1756 default=True,
1761 default=True,
1757 )
1762 )
1758 coreconfigitem(
1763 coreconfigitem(
1759 b'profiling',
1764 b'profiling',
1760 b'sort',
1765 b'sort',
1761 default=b'inlinetime',
1766 default=b'inlinetime',
1762 )
1767 )
1763 coreconfigitem(
1768 coreconfigitem(
1764 b'profiling',
1769 b'profiling',
1765 b'statformat',
1770 b'statformat',
1766 default=b'hotpath',
1771 default=b'hotpath',
1767 )
1772 )
1768 coreconfigitem(
1773 coreconfigitem(
1769 b'profiling',
1774 b'profiling',
1770 b'time-track',
1775 b'time-track',
1771 default=dynamicdefault,
1776 default=dynamicdefault,
1772 )
1777 )
1773 coreconfigitem(
1778 coreconfigitem(
1774 b'profiling',
1779 b'profiling',
1775 b'type',
1780 b'type',
1776 default=b'stat',
1781 default=b'stat',
1777 )
1782 )
1778 coreconfigitem(
1783 coreconfigitem(
1779 b'progress',
1784 b'progress',
1780 b'assume-tty',
1785 b'assume-tty',
1781 default=False,
1786 default=False,
1782 )
1787 )
1783 coreconfigitem(
1788 coreconfigitem(
1784 b'progress',
1789 b'progress',
1785 b'changedelay',
1790 b'changedelay',
1786 default=1,
1791 default=1,
1787 )
1792 )
1788 coreconfigitem(
1793 coreconfigitem(
1789 b'progress',
1794 b'progress',
1790 b'clear-complete',
1795 b'clear-complete',
1791 default=True,
1796 default=True,
1792 )
1797 )
1793 coreconfigitem(
1798 coreconfigitem(
1794 b'progress',
1799 b'progress',
1795 b'debug',
1800 b'debug',
1796 default=False,
1801 default=False,
1797 )
1802 )
1798 coreconfigitem(
1803 coreconfigitem(
1799 b'progress',
1804 b'progress',
1800 b'delay',
1805 b'delay',
1801 default=3,
1806 default=3,
1802 )
1807 )
1803 coreconfigitem(
1808 coreconfigitem(
1804 b'progress',
1809 b'progress',
1805 b'disable',
1810 b'disable',
1806 default=False,
1811 default=False,
1807 )
1812 )
1808 coreconfigitem(
1813 coreconfigitem(
1809 b'progress',
1814 b'progress',
1810 b'estimateinterval',
1815 b'estimateinterval',
1811 default=60.0,
1816 default=60.0,
1812 )
1817 )
1813 coreconfigitem(
1818 coreconfigitem(
1814 b'progress',
1819 b'progress',
1815 b'format',
1820 b'format',
1816 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1821 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1817 )
1822 )
1818 coreconfigitem(
1823 coreconfigitem(
1819 b'progress',
1824 b'progress',
1820 b'refresh',
1825 b'refresh',
1821 default=0.1,
1826 default=0.1,
1822 )
1827 )
1823 coreconfigitem(
1828 coreconfigitem(
1824 b'progress',
1829 b'progress',
1825 b'width',
1830 b'width',
1826 default=dynamicdefault,
1831 default=dynamicdefault,
1827 )
1832 )
1828 coreconfigitem(
1833 coreconfigitem(
1829 b'pull',
1834 b'pull',
1830 b'confirm',
1835 b'confirm',
1831 default=False,
1836 default=False,
1832 )
1837 )
1833 coreconfigitem(
1838 coreconfigitem(
1834 b'push',
1839 b'push',
1835 b'pushvars.server',
1840 b'pushvars.server',
1836 default=False,
1841 default=False,
1837 )
1842 )
1838 coreconfigitem(
1843 coreconfigitem(
1839 b'rewrite',
1844 b'rewrite',
1840 b'backup-bundle',
1845 b'backup-bundle',
1841 default=True,
1846 default=True,
1842 alias=[(b'ui', b'history-editing-backup')],
1847 alias=[(b'ui', b'history-editing-backup')],
1843 )
1848 )
1844 coreconfigitem(
1849 coreconfigitem(
1845 b'rewrite',
1850 b'rewrite',
1846 b'update-timestamp',
1851 b'update-timestamp',
1847 default=False,
1852 default=False,
1848 )
1853 )
1849 coreconfigitem(
1854 coreconfigitem(
1850 b'rewrite',
1855 b'rewrite',
1851 b'empty-successor',
1856 b'empty-successor',
1852 default=b'skip',
1857 default=b'skip',
1853 experimental=True,
1858 experimental=True,
1854 )
1859 )
1855 coreconfigitem(
1860 coreconfigitem(
1856 b'storage',
1861 b'storage',
1857 b'new-repo-backend',
1862 b'new-repo-backend',
1858 default=b'revlogv1',
1863 default=b'revlogv1',
1859 experimental=True,
1864 experimental=True,
1860 )
1865 )
1861 coreconfigitem(
1866 coreconfigitem(
1862 b'storage',
1867 b'storage',
1863 b'revlog.optimize-delta-parent-choice',
1868 b'revlog.optimize-delta-parent-choice',
1864 default=True,
1869 default=True,
1865 alias=[(b'format', b'aggressivemergedeltas')],
1870 alias=[(b'format', b'aggressivemergedeltas')],
1866 )
1871 )
1867 # experimental as long as rust is experimental (or a C version is implemented)
1872 # experimental as long as rust is experimental (or a C version is implemented)
1868 coreconfigitem(
1873 coreconfigitem(
1869 b'storage',
1874 b'storage',
1870 b'revlog.persistent-nodemap.mmap',
1875 b'revlog.persistent-nodemap.mmap',
1871 default=True,
1876 default=True,
1872 )
1877 )
1873 # experimental as long as format.use-persistent-nodemap is.
1878 # experimental as long as format.use-persistent-nodemap is.
1874 coreconfigitem(
1879 coreconfigitem(
1875 b'storage',
1880 b'storage',
1876 b'revlog.persistent-nodemap.slow-path',
1881 b'revlog.persistent-nodemap.slow-path',
1877 default=b"abort",
1882 default=b"abort",
1878 )
1883 )
1879
1884
1880 coreconfigitem(
1885 coreconfigitem(
1881 b'storage',
1886 b'storage',
1882 b'revlog.reuse-external-delta',
1887 b'revlog.reuse-external-delta',
1883 default=True,
1888 default=True,
1884 )
1889 )
1885 coreconfigitem(
1890 coreconfigitem(
1886 b'storage',
1891 b'storage',
1887 b'revlog.reuse-external-delta-parent',
1892 b'revlog.reuse-external-delta-parent',
1888 default=None,
1893 default=None,
1889 )
1894 )
1890 coreconfigitem(
1895 coreconfigitem(
1891 b'storage',
1896 b'storage',
1892 b'revlog.zlib.level',
1897 b'revlog.zlib.level',
1893 default=None,
1898 default=None,
1894 )
1899 )
1895 coreconfigitem(
1900 coreconfigitem(
1896 b'storage',
1901 b'storage',
1897 b'revlog.zstd.level',
1902 b'revlog.zstd.level',
1898 default=None,
1903 default=None,
1899 )
1904 )
1900 coreconfigitem(
1905 coreconfigitem(
1901 b'server',
1906 b'server',
1902 b'bookmarks-pushkey-compat',
1907 b'bookmarks-pushkey-compat',
1903 default=True,
1908 default=True,
1904 )
1909 )
1905 coreconfigitem(
1910 coreconfigitem(
1906 b'server',
1911 b'server',
1907 b'bundle1',
1912 b'bundle1',
1908 default=True,
1913 default=True,
1909 )
1914 )
1910 coreconfigitem(
1915 coreconfigitem(
1911 b'server',
1916 b'server',
1912 b'bundle1gd',
1917 b'bundle1gd',
1913 default=None,
1918 default=None,
1914 )
1919 )
1915 coreconfigitem(
1920 coreconfigitem(
1916 b'server',
1921 b'server',
1917 b'bundle1.pull',
1922 b'bundle1.pull',
1918 default=None,
1923 default=None,
1919 )
1924 )
1920 coreconfigitem(
1925 coreconfigitem(
1921 b'server',
1926 b'server',
1922 b'bundle1gd.pull',
1927 b'bundle1gd.pull',
1923 default=None,
1928 default=None,
1924 )
1929 )
1925 coreconfigitem(
1930 coreconfigitem(
1926 b'server',
1931 b'server',
1927 b'bundle1.push',
1932 b'bundle1.push',
1928 default=None,
1933 default=None,
1929 )
1934 )
1930 coreconfigitem(
1935 coreconfigitem(
1931 b'server',
1936 b'server',
1932 b'bundle1gd.push',
1937 b'bundle1gd.push',
1933 default=None,
1938 default=None,
1934 )
1939 )
1935 coreconfigitem(
1940 coreconfigitem(
1936 b'server',
1941 b'server',
1937 b'bundle2.stream',
1942 b'bundle2.stream',
1938 default=True,
1943 default=True,
1939 alias=[(b'experimental', b'bundle2.stream')],
1944 alias=[(b'experimental', b'bundle2.stream')],
1940 )
1945 )
1941 coreconfigitem(
1946 coreconfigitem(
1942 b'server',
1947 b'server',
1943 b'compressionengines',
1948 b'compressionengines',
1944 default=list,
1949 default=list,
1945 )
1950 )
1946 coreconfigitem(
1951 coreconfigitem(
1947 b'server',
1952 b'server',
1948 b'concurrent-push-mode',
1953 b'concurrent-push-mode',
1949 default=b'check-related',
1954 default=b'check-related',
1950 )
1955 )
1951 coreconfigitem(
1956 coreconfigitem(
1952 b'server',
1957 b'server',
1953 b'disablefullbundle',
1958 b'disablefullbundle',
1954 default=False,
1959 default=False,
1955 )
1960 )
1956 coreconfigitem(
1961 coreconfigitem(
1957 b'server',
1962 b'server',
1958 b'maxhttpheaderlen',
1963 b'maxhttpheaderlen',
1959 default=1024,
1964 default=1024,
1960 )
1965 )
1961 coreconfigitem(
1966 coreconfigitem(
1962 b'server',
1967 b'server',
1963 b'pullbundle',
1968 b'pullbundle',
1964 default=False,
1969 default=False,
1965 )
1970 )
1966 coreconfigitem(
1971 coreconfigitem(
1967 b'server',
1972 b'server',
1968 b'preferuncompressed',
1973 b'preferuncompressed',
1969 default=False,
1974 default=False,
1970 )
1975 )
1971 coreconfigitem(
1976 coreconfigitem(
1972 b'server',
1977 b'server',
1973 b'streamunbundle',
1978 b'streamunbundle',
1974 default=False,
1979 default=False,
1975 )
1980 )
1976 coreconfigitem(
1981 coreconfigitem(
1977 b'server',
1982 b'server',
1978 b'uncompressed',
1983 b'uncompressed',
1979 default=True,
1984 default=True,
1980 )
1985 )
1981 coreconfigitem(
1986 coreconfigitem(
1982 b'server',
1987 b'server',
1983 b'uncompressedallowsecret',
1988 b'uncompressedallowsecret',
1984 default=False,
1989 default=False,
1985 )
1990 )
1986 coreconfigitem(
1991 coreconfigitem(
1987 b'server',
1992 b'server',
1988 b'view',
1993 b'view',
1989 default=b'served',
1994 default=b'served',
1990 )
1995 )
1991 coreconfigitem(
1996 coreconfigitem(
1992 b'server',
1997 b'server',
1993 b'validate',
1998 b'validate',
1994 default=False,
1999 default=False,
1995 )
2000 )
1996 coreconfigitem(
2001 coreconfigitem(
1997 b'server',
2002 b'server',
1998 b'zliblevel',
2003 b'zliblevel',
1999 default=-1,
2004 default=-1,
2000 )
2005 )
2001 coreconfigitem(
2006 coreconfigitem(
2002 b'server',
2007 b'server',
2003 b'zstdlevel',
2008 b'zstdlevel',
2004 default=3,
2009 default=3,
2005 )
2010 )
2006 coreconfigitem(
2011 coreconfigitem(
2007 b'share',
2012 b'share',
2008 b'pool',
2013 b'pool',
2009 default=None,
2014 default=None,
2010 )
2015 )
2011 coreconfigitem(
2016 coreconfigitem(
2012 b'share',
2017 b'share',
2013 b'poolnaming',
2018 b'poolnaming',
2014 default=b'identity',
2019 default=b'identity',
2015 )
2020 )
2016 coreconfigitem(
2021 coreconfigitem(
2017 b'share',
2022 b'share',
2018 b'safe-mismatch.source-not-safe',
2023 b'safe-mismatch.source-not-safe',
2019 default=b'abort',
2024 default=b'abort',
2020 )
2025 )
2021 coreconfigitem(
2026 coreconfigitem(
2022 b'share',
2027 b'share',
2023 b'safe-mismatch.source-safe',
2028 b'safe-mismatch.source-safe',
2024 default=b'abort',
2029 default=b'abort',
2025 )
2030 )
2026 coreconfigitem(
2031 coreconfigitem(
2027 b'share',
2032 b'share',
2028 b'safe-mismatch.source-not-safe.warn',
2033 b'safe-mismatch.source-not-safe.warn',
2029 default=True,
2034 default=True,
2030 )
2035 )
2031 coreconfigitem(
2036 coreconfigitem(
2032 b'share',
2037 b'share',
2033 b'safe-mismatch.source-safe.warn',
2038 b'safe-mismatch.source-safe.warn',
2034 default=True,
2039 default=True,
2035 )
2040 )
2036 coreconfigitem(
2041 coreconfigitem(
2037 b'shelve',
2042 b'shelve',
2038 b'maxbackups',
2043 b'maxbackups',
2039 default=10,
2044 default=10,
2040 )
2045 )
2041 coreconfigitem(
2046 coreconfigitem(
2042 b'smtp',
2047 b'smtp',
2043 b'host',
2048 b'host',
2044 default=None,
2049 default=None,
2045 )
2050 )
2046 coreconfigitem(
2051 coreconfigitem(
2047 b'smtp',
2052 b'smtp',
2048 b'local_hostname',
2053 b'local_hostname',
2049 default=None,
2054 default=None,
2050 )
2055 )
2051 coreconfigitem(
2056 coreconfigitem(
2052 b'smtp',
2057 b'smtp',
2053 b'password',
2058 b'password',
2054 default=None,
2059 default=None,
2055 )
2060 )
2056 coreconfigitem(
2061 coreconfigitem(
2057 b'smtp',
2062 b'smtp',
2058 b'port',
2063 b'port',
2059 default=dynamicdefault,
2064 default=dynamicdefault,
2060 )
2065 )
2061 coreconfigitem(
2066 coreconfigitem(
2062 b'smtp',
2067 b'smtp',
2063 b'tls',
2068 b'tls',
2064 default=b'none',
2069 default=b'none',
2065 )
2070 )
2066 coreconfigitem(
2071 coreconfigitem(
2067 b'smtp',
2072 b'smtp',
2068 b'username',
2073 b'username',
2069 default=None,
2074 default=None,
2070 )
2075 )
2071 coreconfigitem(
2076 coreconfigitem(
2072 b'sparse',
2077 b'sparse',
2073 b'missingwarning',
2078 b'missingwarning',
2074 default=True,
2079 default=True,
2075 experimental=True,
2080 experimental=True,
2076 )
2081 )
2077 coreconfigitem(
2082 coreconfigitem(
2078 b'subrepos',
2083 b'subrepos',
2079 b'allowed',
2084 b'allowed',
2080 default=dynamicdefault, # to make backporting simpler
2085 default=dynamicdefault, # to make backporting simpler
2081 )
2086 )
2082 coreconfigitem(
2087 coreconfigitem(
2083 b'subrepos',
2088 b'subrepos',
2084 b'hg:allowed',
2089 b'hg:allowed',
2085 default=dynamicdefault,
2090 default=dynamicdefault,
2086 )
2091 )
2087 coreconfigitem(
2092 coreconfigitem(
2088 b'subrepos',
2093 b'subrepos',
2089 b'git:allowed',
2094 b'git:allowed',
2090 default=dynamicdefault,
2095 default=dynamicdefault,
2091 )
2096 )
2092 coreconfigitem(
2097 coreconfigitem(
2093 b'subrepos',
2098 b'subrepos',
2094 b'svn:allowed',
2099 b'svn:allowed',
2095 default=dynamicdefault,
2100 default=dynamicdefault,
2096 )
2101 )
2097 coreconfigitem(
2102 coreconfigitem(
2098 b'templates',
2103 b'templates',
2099 b'.*',
2104 b'.*',
2100 default=None,
2105 default=None,
2101 generic=True,
2106 generic=True,
2102 )
2107 )
2103 coreconfigitem(
2108 coreconfigitem(
2104 b'templateconfig',
2109 b'templateconfig',
2105 b'.*',
2110 b'.*',
2106 default=dynamicdefault,
2111 default=dynamicdefault,
2107 generic=True,
2112 generic=True,
2108 )
2113 )
2109 coreconfigitem(
2114 coreconfigitem(
2110 b'trusted',
2115 b'trusted',
2111 b'groups',
2116 b'groups',
2112 default=list,
2117 default=list,
2113 )
2118 )
2114 coreconfigitem(
2119 coreconfigitem(
2115 b'trusted',
2120 b'trusted',
2116 b'users',
2121 b'users',
2117 default=list,
2122 default=list,
2118 )
2123 )
2119 coreconfigitem(
2124 coreconfigitem(
2120 b'ui',
2125 b'ui',
2121 b'_usedassubrepo',
2126 b'_usedassubrepo',
2122 default=False,
2127 default=False,
2123 )
2128 )
2124 coreconfigitem(
2129 coreconfigitem(
2125 b'ui',
2130 b'ui',
2126 b'allowemptycommit',
2131 b'allowemptycommit',
2127 default=False,
2132 default=False,
2128 )
2133 )
2129 coreconfigitem(
2134 coreconfigitem(
2130 b'ui',
2135 b'ui',
2131 b'archivemeta',
2136 b'archivemeta',
2132 default=True,
2137 default=True,
2133 )
2138 )
2134 coreconfigitem(
2139 coreconfigitem(
2135 b'ui',
2140 b'ui',
2136 b'askusername',
2141 b'askusername',
2137 default=False,
2142 default=False,
2138 )
2143 )
2139 coreconfigitem(
2144 coreconfigitem(
2140 b'ui',
2145 b'ui',
2141 b'available-memory',
2146 b'available-memory',
2142 default=None,
2147 default=None,
2143 )
2148 )
2144
2149
2145 coreconfigitem(
2150 coreconfigitem(
2146 b'ui',
2151 b'ui',
2147 b'clonebundlefallback',
2152 b'clonebundlefallback',
2148 default=False,
2153 default=False,
2149 )
2154 )
2150 coreconfigitem(
2155 coreconfigitem(
2151 b'ui',
2156 b'ui',
2152 b'clonebundleprefers',
2157 b'clonebundleprefers',
2153 default=list,
2158 default=list,
2154 )
2159 )
2155 coreconfigitem(
2160 coreconfigitem(
2156 b'ui',
2161 b'ui',
2157 b'clonebundles',
2162 b'clonebundles',
2158 default=True,
2163 default=True,
2159 )
2164 )
2160 coreconfigitem(
2165 coreconfigitem(
2161 b'ui',
2166 b'ui',
2162 b'color',
2167 b'color',
2163 default=b'auto',
2168 default=b'auto',
2164 )
2169 )
2165 coreconfigitem(
2170 coreconfigitem(
2166 b'ui',
2171 b'ui',
2167 b'commitsubrepos',
2172 b'commitsubrepos',
2168 default=False,
2173 default=False,
2169 )
2174 )
2170 coreconfigitem(
2175 coreconfigitem(
2171 b'ui',
2176 b'ui',
2172 b'debug',
2177 b'debug',
2173 default=False,
2178 default=False,
2174 )
2179 )
2175 coreconfigitem(
2180 coreconfigitem(
2176 b'ui',
2181 b'ui',
2177 b'debugger',
2182 b'debugger',
2178 default=None,
2183 default=None,
2179 )
2184 )
2180 coreconfigitem(
2185 coreconfigitem(
2181 b'ui',
2186 b'ui',
2182 b'editor',
2187 b'editor',
2183 default=dynamicdefault,
2188 default=dynamicdefault,
2184 )
2189 )
2185 coreconfigitem(
2190 coreconfigitem(
2186 b'ui',
2191 b'ui',
2187 b'detailed-exit-code',
2192 b'detailed-exit-code',
2188 default=False,
2193 default=False,
2189 experimental=True,
2194 experimental=True,
2190 )
2195 )
2191 coreconfigitem(
2196 coreconfigitem(
2192 b'ui',
2197 b'ui',
2193 b'fallbackencoding',
2198 b'fallbackencoding',
2194 default=None,
2199 default=None,
2195 )
2200 )
2196 coreconfigitem(
2201 coreconfigitem(
2197 b'ui',
2202 b'ui',
2198 b'forcecwd',
2203 b'forcecwd',
2199 default=None,
2204 default=None,
2200 )
2205 )
2201 coreconfigitem(
2206 coreconfigitem(
2202 b'ui',
2207 b'ui',
2203 b'forcemerge',
2208 b'forcemerge',
2204 default=None,
2209 default=None,
2205 )
2210 )
2206 coreconfigitem(
2211 coreconfigitem(
2207 b'ui',
2212 b'ui',
2208 b'formatdebug',
2213 b'formatdebug',
2209 default=False,
2214 default=False,
2210 )
2215 )
2211 coreconfigitem(
2216 coreconfigitem(
2212 b'ui',
2217 b'ui',
2213 b'formatjson',
2218 b'formatjson',
2214 default=False,
2219 default=False,
2215 )
2220 )
2216 coreconfigitem(
2221 coreconfigitem(
2217 b'ui',
2222 b'ui',
2218 b'formatted',
2223 b'formatted',
2219 default=None,
2224 default=None,
2220 )
2225 )
2221 coreconfigitem(
2226 coreconfigitem(
2222 b'ui',
2227 b'ui',
2223 b'interactive',
2228 b'interactive',
2224 default=None,
2229 default=None,
2225 )
2230 )
2226 coreconfigitem(
2231 coreconfigitem(
2227 b'ui',
2232 b'ui',
2228 b'interface',
2233 b'interface',
2229 default=None,
2234 default=None,
2230 )
2235 )
2231 coreconfigitem(
2236 coreconfigitem(
2232 b'ui',
2237 b'ui',
2233 b'interface.chunkselector',
2238 b'interface.chunkselector',
2234 default=None,
2239 default=None,
2235 )
2240 )
2236 coreconfigitem(
2241 coreconfigitem(
2237 b'ui',
2242 b'ui',
2238 b'large-file-limit',
2243 b'large-file-limit',
2239 default=10000000,
2244 default=10000000,
2240 )
2245 )
2241 coreconfigitem(
2246 coreconfigitem(
2242 b'ui',
2247 b'ui',
2243 b'logblockedtimes',
2248 b'logblockedtimes',
2244 default=False,
2249 default=False,
2245 )
2250 )
2246 coreconfigitem(
2251 coreconfigitem(
2247 b'ui',
2252 b'ui',
2248 b'merge',
2253 b'merge',
2249 default=None,
2254 default=None,
2250 )
2255 )
2251 coreconfigitem(
2256 coreconfigitem(
2252 b'ui',
2257 b'ui',
2253 b'mergemarkers',
2258 b'mergemarkers',
2254 default=b'basic',
2259 default=b'basic',
2255 )
2260 )
2256 coreconfigitem(
2261 coreconfigitem(
2257 b'ui',
2262 b'ui',
2258 b'message-output',
2263 b'message-output',
2259 default=b'stdio',
2264 default=b'stdio',
2260 )
2265 )
2261 coreconfigitem(
2266 coreconfigitem(
2262 b'ui',
2267 b'ui',
2263 b'nontty',
2268 b'nontty',
2264 default=False,
2269 default=False,
2265 )
2270 )
2266 coreconfigitem(
2271 coreconfigitem(
2267 b'ui',
2272 b'ui',
2268 b'origbackuppath',
2273 b'origbackuppath',
2269 default=None,
2274 default=None,
2270 )
2275 )
2271 coreconfigitem(
2276 coreconfigitem(
2272 b'ui',
2277 b'ui',
2273 b'paginate',
2278 b'paginate',
2274 default=True,
2279 default=True,
2275 )
2280 )
2276 coreconfigitem(
2281 coreconfigitem(
2277 b'ui',
2282 b'ui',
2278 b'patch',
2283 b'patch',
2279 default=None,
2284 default=None,
2280 )
2285 )
2281 coreconfigitem(
2286 coreconfigitem(
2282 b'ui',
2287 b'ui',
2283 b'portablefilenames',
2288 b'portablefilenames',
2284 default=b'warn',
2289 default=b'warn',
2285 )
2290 )
2286 coreconfigitem(
2291 coreconfigitem(
2287 b'ui',
2292 b'ui',
2288 b'promptecho',
2293 b'promptecho',
2289 default=False,
2294 default=False,
2290 )
2295 )
2291 coreconfigitem(
2296 coreconfigitem(
2292 b'ui',
2297 b'ui',
2293 b'quiet',
2298 b'quiet',
2294 default=False,
2299 default=False,
2295 )
2300 )
2296 coreconfigitem(
2301 coreconfigitem(
2297 b'ui',
2302 b'ui',
2298 b'quietbookmarkmove',
2303 b'quietbookmarkmove',
2299 default=False,
2304 default=False,
2300 )
2305 )
2301 coreconfigitem(
2306 coreconfigitem(
2302 b'ui',
2307 b'ui',
2303 b'relative-paths',
2308 b'relative-paths',
2304 default=b'legacy',
2309 default=b'legacy',
2305 )
2310 )
2306 coreconfigitem(
2311 coreconfigitem(
2307 b'ui',
2312 b'ui',
2308 b'remotecmd',
2313 b'remotecmd',
2309 default=b'hg',
2314 default=b'hg',
2310 )
2315 )
2311 coreconfigitem(
2316 coreconfigitem(
2312 b'ui',
2317 b'ui',
2313 b'report_untrusted',
2318 b'report_untrusted',
2314 default=True,
2319 default=True,
2315 )
2320 )
2316 coreconfigitem(
2321 coreconfigitem(
2317 b'ui',
2322 b'ui',
2318 b'rollback',
2323 b'rollback',
2319 default=True,
2324 default=True,
2320 )
2325 )
2321 coreconfigitem(
2326 coreconfigitem(
2322 b'ui',
2327 b'ui',
2323 b'signal-safe-lock',
2328 b'signal-safe-lock',
2324 default=True,
2329 default=True,
2325 )
2330 )
2326 coreconfigitem(
2331 coreconfigitem(
2327 b'ui',
2332 b'ui',
2328 b'slash',
2333 b'slash',
2329 default=False,
2334 default=False,
2330 )
2335 )
2331 coreconfigitem(
2336 coreconfigitem(
2332 b'ui',
2337 b'ui',
2333 b'ssh',
2338 b'ssh',
2334 default=b'ssh',
2339 default=b'ssh',
2335 )
2340 )
2336 coreconfigitem(
2341 coreconfigitem(
2337 b'ui',
2342 b'ui',
2338 b'ssherrorhint',
2343 b'ssherrorhint',
2339 default=None,
2344 default=None,
2340 )
2345 )
2341 coreconfigitem(
2346 coreconfigitem(
2342 b'ui',
2347 b'ui',
2343 b'statuscopies',
2348 b'statuscopies',
2344 default=False,
2349 default=False,
2345 )
2350 )
2346 coreconfigitem(
2351 coreconfigitem(
2347 b'ui',
2352 b'ui',
2348 b'strict',
2353 b'strict',
2349 default=False,
2354 default=False,
2350 )
2355 )
2351 coreconfigitem(
2356 coreconfigitem(
2352 b'ui',
2357 b'ui',
2353 b'style',
2358 b'style',
2354 default=b'',
2359 default=b'',
2355 )
2360 )
2356 coreconfigitem(
2361 coreconfigitem(
2357 b'ui',
2362 b'ui',
2358 b'supportcontact',
2363 b'supportcontact',
2359 default=None,
2364 default=None,
2360 )
2365 )
2361 coreconfigitem(
2366 coreconfigitem(
2362 b'ui',
2367 b'ui',
2363 b'textwidth',
2368 b'textwidth',
2364 default=78,
2369 default=78,
2365 )
2370 )
2366 coreconfigitem(
2371 coreconfigitem(
2367 b'ui',
2372 b'ui',
2368 b'timeout',
2373 b'timeout',
2369 default=b'600',
2374 default=b'600',
2370 )
2375 )
2371 coreconfigitem(
2376 coreconfigitem(
2372 b'ui',
2377 b'ui',
2373 b'timeout.warn',
2378 b'timeout.warn',
2374 default=0,
2379 default=0,
2375 )
2380 )
2376 coreconfigitem(
2381 coreconfigitem(
2377 b'ui',
2382 b'ui',
2378 b'timestamp-output',
2383 b'timestamp-output',
2379 default=False,
2384 default=False,
2380 )
2385 )
2381 coreconfigitem(
2386 coreconfigitem(
2382 b'ui',
2387 b'ui',
2383 b'traceback',
2388 b'traceback',
2384 default=False,
2389 default=False,
2385 )
2390 )
2386 coreconfigitem(
2391 coreconfigitem(
2387 b'ui',
2392 b'ui',
2388 b'tweakdefaults',
2393 b'tweakdefaults',
2389 default=False,
2394 default=False,
2390 )
2395 )
2391 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2396 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2392 coreconfigitem(
2397 coreconfigitem(
2393 b'ui',
2398 b'ui',
2394 b'verbose',
2399 b'verbose',
2395 default=False,
2400 default=False,
2396 )
2401 )
2397 coreconfigitem(
2402 coreconfigitem(
2398 b'verify',
2403 b'verify',
2399 b'skipflags',
2404 b'skipflags',
2400 default=None,
2405 default=None,
2401 )
2406 )
2402 coreconfigitem(
2407 coreconfigitem(
2403 b'web',
2408 b'web',
2404 b'allowbz2',
2409 b'allowbz2',
2405 default=False,
2410 default=False,
2406 )
2411 )
2407 coreconfigitem(
2412 coreconfigitem(
2408 b'web',
2413 b'web',
2409 b'allowgz',
2414 b'allowgz',
2410 default=False,
2415 default=False,
2411 )
2416 )
2412 coreconfigitem(
2417 coreconfigitem(
2413 b'web',
2418 b'web',
2414 b'allow-pull',
2419 b'allow-pull',
2415 alias=[(b'web', b'allowpull')],
2420 alias=[(b'web', b'allowpull')],
2416 default=True,
2421 default=True,
2417 )
2422 )
2418 coreconfigitem(
2423 coreconfigitem(
2419 b'web',
2424 b'web',
2420 b'allow-push',
2425 b'allow-push',
2421 alias=[(b'web', b'allow_push')],
2426 alias=[(b'web', b'allow_push')],
2422 default=list,
2427 default=list,
2423 )
2428 )
2424 coreconfigitem(
2429 coreconfigitem(
2425 b'web',
2430 b'web',
2426 b'allowzip',
2431 b'allowzip',
2427 default=False,
2432 default=False,
2428 )
2433 )
2429 coreconfigitem(
2434 coreconfigitem(
2430 b'web',
2435 b'web',
2431 b'archivesubrepos',
2436 b'archivesubrepos',
2432 default=False,
2437 default=False,
2433 )
2438 )
2434 coreconfigitem(
2439 coreconfigitem(
2435 b'web',
2440 b'web',
2436 b'cache',
2441 b'cache',
2437 default=True,
2442 default=True,
2438 )
2443 )
2439 coreconfigitem(
2444 coreconfigitem(
2440 b'web',
2445 b'web',
2441 b'comparisoncontext',
2446 b'comparisoncontext',
2442 default=5,
2447 default=5,
2443 )
2448 )
2444 coreconfigitem(
2449 coreconfigitem(
2445 b'web',
2450 b'web',
2446 b'contact',
2451 b'contact',
2447 default=None,
2452 default=None,
2448 )
2453 )
2449 coreconfigitem(
2454 coreconfigitem(
2450 b'web',
2455 b'web',
2451 b'deny_push',
2456 b'deny_push',
2452 default=list,
2457 default=list,
2453 )
2458 )
2454 coreconfigitem(
2459 coreconfigitem(
2455 b'web',
2460 b'web',
2456 b'guessmime',
2461 b'guessmime',
2457 default=False,
2462 default=False,
2458 )
2463 )
2459 coreconfigitem(
2464 coreconfigitem(
2460 b'web',
2465 b'web',
2461 b'hidden',
2466 b'hidden',
2462 default=False,
2467 default=False,
2463 )
2468 )
2464 coreconfigitem(
2469 coreconfigitem(
2465 b'web',
2470 b'web',
2466 b'labels',
2471 b'labels',
2467 default=list,
2472 default=list,
2468 )
2473 )
2469 coreconfigitem(
2474 coreconfigitem(
2470 b'web',
2475 b'web',
2471 b'logoimg',
2476 b'logoimg',
2472 default=b'hglogo.png',
2477 default=b'hglogo.png',
2473 )
2478 )
2474 coreconfigitem(
2479 coreconfigitem(
2475 b'web',
2480 b'web',
2476 b'logourl',
2481 b'logourl',
2477 default=b'https://mercurial-scm.org/',
2482 default=b'https://mercurial-scm.org/',
2478 )
2483 )
2479 coreconfigitem(
2484 coreconfigitem(
2480 b'web',
2485 b'web',
2481 b'accesslog',
2486 b'accesslog',
2482 default=b'-',
2487 default=b'-',
2483 )
2488 )
2484 coreconfigitem(
2489 coreconfigitem(
2485 b'web',
2490 b'web',
2486 b'address',
2491 b'address',
2487 default=b'',
2492 default=b'',
2488 )
2493 )
2489 coreconfigitem(
2494 coreconfigitem(
2490 b'web',
2495 b'web',
2491 b'allow-archive',
2496 b'allow-archive',
2492 alias=[(b'web', b'allow_archive')],
2497 alias=[(b'web', b'allow_archive')],
2493 default=list,
2498 default=list,
2494 )
2499 )
2495 coreconfigitem(
2500 coreconfigitem(
2496 b'web',
2501 b'web',
2497 b'allow_read',
2502 b'allow_read',
2498 default=list,
2503 default=list,
2499 )
2504 )
2500 coreconfigitem(
2505 coreconfigitem(
2501 b'web',
2506 b'web',
2502 b'baseurl',
2507 b'baseurl',
2503 default=None,
2508 default=None,
2504 )
2509 )
2505 coreconfigitem(
2510 coreconfigitem(
2506 b'web',
2511 b'web',
2507 b'cacerts',
2512 b'cacerts',
2508 default=None,
2513 default=None,
2509 )
2514 )
2510 coreconfigitem(
2515 coreconfigitem(
2511 b'web',
2516 b'web',
2512 b'certificate',
2517 b'certificate',
2513 default=None,
2518 default=None,
2514 )
2519 )
2515 coreconfigitem(
2520 coreconfigitem(
2516 b'web',
2521 b'web',
2517 b'collapse',
2522 b'collapse',
2518 default=False,
2523 default=False,
2519 )
2524 )
2520 coreconfigitem(
2525 coreconfigitem(
2521 b'web',
2526 b'web',
2522 b'csp',
2527 b'csp',
2523 default=None,
2528 default=None,
2524 )
2529 )
2525 coreconfigitem(
2530 coreconfigitem(
2526 b'web',
2531 b'web',
2527 b'deny_read',
2532 b'deny_read',
2528 default=list,
2533 default=list,
2529 )
2534 )
2530 coreconfigitem(
2535 coreconfigitem(
2531 b'web',
2536 b'web',
2532 b'descend',
2537 b'descend',
2533 default=True,
2538 default=True,
2534 )
2539 )
2535 coreconfigitem(
2540 coreconfigitem(
2536 b'web',
2541 b'web',
2537 b'description',
2542 b'description',
2538 default=b"",
2543 default=b"",
2539 )
2544 )
2540 coreconfigitem(
2545 coreconfigitem(
2541 b'web',
2546 b'web',
2542 b'encoding',
2547 b'encoding',
2543 default=lambda: encoding.encoding,
2548 default=lambda: encoding.encoding,
2544 )
2549 )
2545 coreconfigitem(
2550 coreconfigitem(
2546 b'web',
2551 b'web',
2547 b'errorlog',
2552 b'errorlog',
2548 default=b'-',
2553 default=b'-',
2549 )
2554 )
2550 coreconfigitem(
2555 coreconfigitem(
2551 b'web',
2556 b'web',
2552 b'ipv6',
2557 b'ipv6',
2553 default=False,
2558 default=False,
2554 )
2559 )
2555 coreconfigitem(
2560 coreconfigitem(
2556 b'web',
2561 b'web',
2557 b'maxchanges',
2562 b'maxchanges',
2558 default=10,
2563 default=10,
2559 )
2564 )
2560 coreconfigitem(
2565 coreconfigitem(
2561 b'web',
2566 b'web',
2562 b'maxfiles',
2567 b'maxfiles',
2563 default=10,
2568 default=10,
2564 )
2569 )
2565 coreconfigitem(
2570 coreconfigitem(
2566 b'web',
2571 b'web',
2567 b'maxshortchanges',
2572 b'maxshortchanges',
2568 default=60,
2573 default=60,
2569 )
2574 )
2570 coreconfigitem(
2575 coreconfigitem(
2571 b'web',
2576 b'web',
2572 b'motd',
2577 b'motd',
2573 default=b'',
2578 default=b'',
2574 )
2579 )
2575 coreconfigitem(
2580 coreconfigitem(
2576 b'web',
2581 b'web',
2577 b'name',
2582 b'name',
2578 default=dynamicdefault,
2583 default=dynamicdefault,
2579 )
2584 )
2580 coreconfigitem(
2585 coreconfigitem(
2581 b'web',
2586 b'web',
2582 b'port',
2587 b'port',
2583 default=8000,
2588 default=8000,
2584 )
2589 )
2585 coreconfigitem(
2590 coreconfigitem(
2586 b'web',
2591 b'web',
2587 b'prefix',
2592 b'prefix',
2588 default=b'',
2593 default=b'',
2589 )
2594 )
2590 coreconfigitem(
2595 coreconfigitem(
2591 b'web',
2596 b'web',
2592 b'push_ssl',
2597 b'push_ssl',
2593 default=True,
2598 default=True,
2594 )
2599 )
2595 coreconfigitem(
2600 coreconfigitem(
2596 b'web',
2601 b'web',
2597 b'refreshinterval',
2602 b'refreshinterval',
2598 default=20,
2603 default=20,
2599 )
2604 )
2600 coreconfigitem(
2605 coreconfigitem(
2601 b'web',
2606 b'web',
2602 b'server-header',
2607 b'server-header',
2603 default=None,
2608 default=None,
2604 )
2609 )
2605 coreconfigitem(
2610 coreconfigitem(
2606 b'web',
2611 b'web',
2607 b'static',
2612 b'static',
2608 default=None,
2613 default=None,
2609 )
2614 )
2610 coreconfigitem(
2615 coreconfigitem(
2611 b'web',
2616 b'web',
2612 b'staticurl',
2617 b'staticurl',
2613 default=None,
2618 default=None,
2614 )
2619 )
2615 coreconfigitem(
2620 coreconfigitem(
2616 b'web',
2621 b'web',
2617 b'stripes',
2622 b'stripes',
2618 default=1,
2623 default=1,
2619 )
2624 )
2620 coreconfigitem(
2625 coreconfigitem(
2621 b'web',
2626 b'web',
2622 b'style',
2627 b'style',
2623 default=b'paper',
2628 default=b'paper',
2624 )
2629 )
2625 coreconfigitem(
2630 coreconfigitem(
2626 b'web',
2631 b'web',
2627 b'templates',
2632 b'templates',
2628 default=None,
2633 default=None,
2629 )
2634 )
2630 coreconfigitem(
2635 coreconfigitem(
2631 b'web',
2636 b'web',
2632 b'view',
2637 b'view',
2633 default=b'served',
2638 default=b'served',
2634 experimental=True,
2639 experimental=True,
2635 )
2640 )
2636 coreconfigitem(
2641 coreconfigitem(
2637 b'worker',
2642 b'worker',
2638 b'backgroundclose',
2643 b'backgroundclose',
2639 default=dynamicdefault,
2644 default=dynamicdefault,
2640 )
2645 )
2641 # Windows defaults to a limit of 512 open files. A buffer of 128
2646 # Windows defaults to a limit of 512 open files. A buffer of 128
2642 # should give us enough headway.
2647 # should give us enough headway.
2643 coreconfigitem(
2648 coreconfigitem(
2644 b'worker',
2649 b'worker',
2645 b'backgroundclosemaxqueue',
2650 b'backgroundclosemaxqueue',
2646 default=384,
2651 default=384,
2647 )
2652 )
2648 coreconfigitem(
2653 coreconfigitem(
2649 b'worker',
2654 b'worker',
2650 b'backgroundcloseminfilecount',
2655 b'backgroundcloseminfilecount',
2651 default=2048,
2656 default=2048,
2652 )
2657 )
2653 coreconfigitem(
2658 coreconfigitem(
2654 b'worker',
2659 b'worker',
2655 b'backgroundclosethreadcount',
2660 b'backgroundclosethreadcount',
2656 default=4,
2661 default=4,
2657 )
2662 )
2658 coreconfigitem(
2663 coreconfigitem(
2659 b'worker',
2664 b'worker',
2660 b'enabled',
2665 b'enabled',
2661 default=True,
2666 default=True,
2662 )
2667 )
2663 coreconfigitem(
2668 coreconfigitem(
2664 b'worker',
2669 b'worker',
2665 b'numcpus',
2670 b'numcpus',
2666 default=None,
2671 default=None,
2667 )
2672 )
2668
2673
2669 # Rebase related configuration moved to core because other extension are doing
2674 # Rebase related configuration moved to core because other extension are doing
2670 # strange things. For example, shelve import the extensions to reuse some bit
2675 # strange things. For example, shelve import the extensions to reuse some bit
2671 # without formally loading it.
2676 # without formally loading it.
2672 coreconfigitem(
2677 coreconfigitem(
2673 b'commands',
2678 b'commands',
2674 b'rebase.requiredest',
2679 b'rebase.requiredest',
2675 default=False,
2680 default=False,
2676 )
2681 )
2677 coreconfigitem(
2682 coreconfigitem(
2678 b'experimental',
2683 b'experimental',
2679 b'rebaseskipobsolete',
2684 b'rebaseskipobsolete',
2680 default=True,
2685 default=True,
2681 )
2686 )
2682 coreconfigitem(
2687 coreconfigitem(
2683 b'rebase',
2688 b'rebase',
2684 b'singletransaction',
2689 b'singletransaction',
2685 default=False,
2690 default=False,
2686 )
2691 )
2687 coreconfigitem(
2692 coreconfigitem(
2688 b'rebase',
2693 b'rebase',
2689 b'experimental.inmemory',
2694 b'experimental.inmemory',
2690 default=False,
2695 default=False,
2691 )
2696 )
@@ -1,1953 +1,1958 b''
1 # dirstate.py - working directory tracking for mercurial
1 # dirstate.py - working directory tracking for mercurial
2 #
2 #
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2007 Olivia Mackall <olivia@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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import collections
10 import collections
11 import contextlib
11 import contextlib
12 import errno
12 import errno
13 import os
13 import os
14 import stat
14 import stat
15
15
16 from .i18n import _
16 from .i18n import _
17 from .pycompat import delattr
17 from .pycompat import delattr
18
18
19 from hgdemandimport import tracing
19 from hgdemandimport import tracing
20
20
21 from . import (
21 from . import (
22 encoding,
22 encoding,
23 error,
23 error,
24 match as matchmod,
24 match as matchmod,
25 pathutil,
25 pathutil,
26 policy,
26 policy,
27 pycompat,
27 pycompat,
28 scmutil,
28 scmutil,
29 sparse,
29 sparse,
30 txnutil,
30 txnutil,
31 util,
31 util,
32 )
32 )
33
33
34 from .interfaces import (
34 from .interfaces import (
35 dirstate as intdirstate,
35 dirstate as intdirstate,
36 util as interfaceutil,
36 util as interfaceutil,
37 )
37 )
38
38
39 parsers = policy.importmod('parsers')
39 parsers = policy.importmod('parsers')
40 rustmod = policy.importrust('dirstate')
40 rustmod = policy.importrust('dirstate')
41
41
42 propertycache = util.propertycache
42 propertycache = util.propertycache
43 filecache = scmutil.filecache
43 filecache = scmutil.filecache
44 _rangemask = 0x7FFFFFFF
44 _rangemask = 0x7FFFFFFF
45
45
46 dirstatetuple = parsers.dirstatetuple
46 dirstatetuple = parsers.dirstatetuple
47
47
48
48
49 class repocache(filecache):
49 class repocache(filecache):
50 """filecache for files in .hg/"""
50 """filecache for files in .hg/"""
51
51
52 def join(self, obj, fname):
52 def join(self, obj, fname):
53 return obj._opener.join(fname)
53 return obj._opener.join(fname)
54
54
55
55
56 class rootcache(filecache):
56 class rootcache(filecache):
57 """filecache for files in the repository root"""
57 """filecache for files in the repository root"""
58
58
59 def join(self, obj, fname):
59 def join(self, obj, fname):
60 return obj._join(fname)
60 return obj._join(fname)
61
61
62
62
63 def _getfsnow(vfs):
63 def _getfsnow(vfs):
64 '''Get "now" timestamp on filesystem'''
64 '''Get "now" timestamp on filesystem'''
65 tmpfd, tmpname = vfs.mkstemp()
65 tmpfd, tmpname = vfs.mkstemp()
66 try:
66 try:
67 return os.fstat(tmpfd)[stat.ST_MTIME]
67 return os.fstat(tmpfd)[stat.ST_MTIME]
68 finally:
68 finally:
69 os.close(tmpfd)
69 os.close(tmpfd)
70 vfs.unlink(tmpname)
70 vfs.unlink(tmpname)
71
71
72
72
73 @interfaceutil.implementer(intdirstate.idirstate)
73 @interfaceutil.implementer(intdirstate.idirstate)
74 class dirstate(object):
74 class dirstate(object):
75 def __init__(
75 def __init__(
76 self, opener, ui, root, validate, sparsematchfn, nodeconstants
76 self, opener, ui, root, validate, sparsematchfn, nodeconstants
77 ):
77 ):
78 """Create a new dirstate object.
78 """Create a new dirstate object.
79
79
80 opener is an open()-like callable that can be used to open the
80 opener is an open()-like callable that can be used to open the
81 dirstate file; root is the root of the directory tracked by
81 dirstate file; root is the root of the directory tracked by
82 the dirstate.
82 the dirstate.
83 """
83 """
84 self._nodeconstants = nodeconstants
84 self._nodeconstants = nodeconstants
85 self._opener = opener
85 self._opener = opener
86 self._validate = validate
86 self._validate = validate
87 self._root = root
87 self._root = root
88 self._sparsematchfn = sparsematchfn
88 self._sparsematchfn = sparsematchfn
89 # ntpath.join(root, '') of Python 2.7.9 does not add sep if root is
89 # ntpath.join(root, '') of Python 2.7.9 does not add sep if root is
90 # UNC path pointing to root share (issue4557)
90 # UNC path pointing to root share (issue4557)
91 self._rootdir = pathutil.normasprefix(root)
91 self._rootdir = pathutil.normasprefix(root)
92 self._dirty = False
92 self._dirty = False
93 self._lastnormaltime = 0
93 self._lastnormaltime = 0
94 self._ui = ui
94 self._ui = ui
95 self._filecache = {}
95 self._filecache = {}
96 self._parentwriters = 0
96 self._parentwriters = 0
97 self._filename = b'dirstate'
97 self._filename = b'dirstate'
98 self._pendingfilename = b'%s.pending' % self._filename
98 self._pendingfilename = b'%s.pending' % self._filename
99 self._plchangecallbacks = {}
99 self._plchangecallbacks = {}
100 self._origpl = None
100 self._origpl = None
101 self._updatedfiles = set()
101 self._updatedfiles = set()
102 self._mapcls = dirstatemap
102 self._mapcls = dirstatemap
103 # Access and cache cwd early, so we don't access it for the first time
103 # Access and cache cwd early, so we don't access it for the first time
104 # after a working-copy update caused it to not exist (accessing it then
104 # after a working-copy update caused it to not exist (accessing it then
105 # raises an exception).
105 # raises an exception).
106 self._cwd
106 self._cwd
107
107
108 def prefetch_parents(self):
108 def prefetch_parents(self):
109 """make sure the parents are loaded
109 """make sure the parents are loaded
110
110
111 Used to avoid a race condition.
111 Used to avoid a race condition.
112 """
112 """
113 self._pl
113 self._pl
114
114
115 @contextlib.contextmanager
115 @contextlib.contextmanager
116 def parentchange(self):
116 def parentchange(self):
117 """Context manager for handling dirstate parents.
117 """Context manager for handling dirstate parents.
118
118
119 If an exception occurs in the scope of the context manager,
119 If an exception occurs in the scope of the context manager,
120 the incoherent dirstate won't be written when wlock is
120 the incoherent dirstate won't be written when wlock is
121 released.
121 released.
122 """
122 """
123 self._parentwriters += 1
123 self._parentwriters += 1
124 yield
124 yield
125 # Typically we want the "undo" step of a context manager in a
125 # Typically we want the "undo" step of a context manager in a
126 # finally block so it happens even when an exception
126 # finally block so it happens even when an exception
127 # occurs. In this case, however, we only want to decrement
127 # occurs. In this case, however, we only want to decrement
128 # parentwriters if the code in the with statement exits
128 # parentwriters if the code in the with statement exits
129 # normally, so we don't have a try/finally here on purpose.
129 # normally, so we don't have a try/finally here on purpose.
130 self._parentwriters -= 1
130 self._parentwriters -= 1
131
131
132 def pendingparentchange(self):
132 def pendingparentchange(self):
133 """Returns true if the dirstate is in the middle of a set of changes
133 """Returns true if the dirstate is in the middle of a set of changes
134 that modify the dirstate parent.
134 that modify the dirstate parent.
135 """
135 """
136 return self._parentwriters > 0
136 return self._parentwriters > 0
137
137
138 @propertycache
138 @propertycache
139 def _map(self):
139 def _map(self):
140 """Return the dirstate contents (see documentation for dirstatemap)."""
140 """Return the dirstate contents (see documentation for dirstatemap)."""
141 self._map = self._mapcls(
141 self._map = self._mapcls(
142 self._ui, self._opener, self._root, self._nodeconstants
142 self._ui, self._opener, self._root, self._nodeconstants
143 )
143 )
144 return self._map
144 return self._map
145
145
146 @property
146 @property
147 def _sparsematcher(self):
147 def _sparsematcher(self):
148 """The matcher for the sparse checkout.
148 """The matcher for the sparse checkout.
149
149
150 The working directory may not include every file from a manifest. The
150 The working directory may not include every file from a manifest. The
151 matcher obtained by this property will match a path if it is to be
151 matcher obtained by this property will match a path if it is to be
152 included in the working directory.
152 included in the working directory.
153 """
153 """
154 # TODO there is potential to cache this property. For now, the matcher
154 # TODO there is potential to cache this property. For now, the matcher
155 # is resolved on every access. (But the called function does use a
155 # is resolved on every access. (But the called function does use a
156 # cache to keep the lookup fast.)
156 # cache to keep the lookup fast.)
157 return self._sparsematchfn()
157 return self._sparsematchfn()
158
158
159 @repocache(b'branch')
159 @repocache(b'branch')
160 def _branch(self):
160 def _branch(self):
161 try:
161 try:
162 return self._opener.read(b"branch").strip() or b"default"
162 return self._opener.read(b"branch").strip() or b"default"
163 except IOError as inst:
163 except IOError as inst:
164 if inst.errno != errno.ENOENT:
164 if inst.errno != errno.ENOENT:
165 raise
165 raise
166 return b"default"
166 return b"default"
167
167
168 @property
168 @property
169 def _pl(self):
169 def _pl(self):
170 return self._map.parents()
170 return self._map.parents()
171
171
172 def hasdir(self, d):
172 def hasdir(self, d):
173 return self._map.hastrackeddir(d)
173 return self._map.hastrackeddir(d)
174
174
175 @rootcache(b'.hgignore')
175 @rootcache(b'.hgignore')
176 def _ignore(self):
176 def _ignore(self):
177 files = self._ignorefiles()
177 files = self._ignorefiles()
178 if not files:
178 if not files:
179 return matchmod.never()
179 return matchmod.never()
180
180
181 pats = [b'include:%s' % f for f in files]
181 pats = [b'include:%s' % f for f in files]
182 return matchmod.match(self._root, b'', [], pats, warn=self._ui.warn)
182 return matchmod.match(self._root, b'', [], pats, warn=self._ui.warn)
183
183
184 @propertycache
184 @propertycache
185 def _slash(self):
185 def _slash(self):
186 return self._ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/'
186 return self._ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/'
187
187
188 @propertycache
188 @propertycache
189 def _checklink(self):
189 def _checklink(self):
190 return util.checklink(self._root)
190 return util.checklink(self._root)
191
191
192 @propertycache
192 @propertycache
193 def _checkexec(self):
193 def _checkexec(self):
194 return bool(util.checkexec(self._root))
194 return bool(util.checkexec(self._root))
195
195
196 @propertycache
196 @propertycache
197 def _checkcase(self):
197 def _checkcase(self):
198 return not util.fscasesensitive(self._join(b'.hg'))
198 return not util.fscasesensitive(self._join(b'.hg'))
199
199
200 def _join(self, f):
200 def _join(self, f):
201 # much faster than os.path.join()
201 # much faster than os.path.join()
202 # it's safe because f is always a relative path
202 # it's safe because f is always a relative path
203 return self._rootdir + f
203 return self._rootdir + f
204
204
205 def flagfunc(self, buildfallback):
205 def flagfunc(self, buildfallback):
206 if self._checklink and self._checkexec:
206 if self._checklink and self._checkexec:
207
207
208 def f(x):
208 def f(x):
209 try:
209 try:
210 st = os.lstat(self._join(x))
210 st = os.lstat(self._join(x))
211 if util.statislink(st):
211 if util.statislink(st):
212 return b'l'
212 return b'l'
213 if util.statisexec(st):
213 if util.statisexec(st):
214 return b'x'
214 return b'x'
215 except OSError:
215 except OSError:
216 pass
216 pass
217 return b''
217 return b''
218
218
219 return f
219 return f
220
220
221 fallback = buildfallback()
221 fallback = buildfallback()
222 if self._checklink:
222 if self._checklink:
223
223
224 def f(x):
224 def f(x):
225 if os.path.islink(self._join(x)):
225 if os.path.islink(self._join(x)):
226 return b'l'
226 return b'l'
227 if b'x' in fallback(x):
227 if b'x' in fallback(x):
228 return b'x'
228 return b'x'
229 return b''
229 return b''
230
230
231 return f
231 return f
232 if self._checkexec:
232 if self._checkexec:
233
233
234 def f(x):
234 def f(x):
235 if b'l' in fallback(x):
235 if b'l' in fallback(x):
236 return b'l'
236 return b'l'
237 if util.isexec(self._join(x)):
237 if util.isexec(self._join(x)):
238 return b'x'
238 return b'x'
239 return b''
239 return b''
240
240
241 return f
241 return f
242 else:
242 else:
243 return fallback
243 return fallback
244
244
245 @propertycache
245 @propertycache
246 def _cwd(self):
246 def _cwd(self):
247 # internal config: ui.forcecwd
247 # internal config: ui.forcecwd
248 forcecwd = self._ui.config(b'ui', b'forcecwd')
248 forcecwd = self._ui.config(b'ui', b'forcecwd')
249 if forcecwd:
249 if forcecwd:
250 return forcecwd
250 return forcecwd
251 return encoding.getcwd()
251 return encoding.getcwd()
252
252
253 def getcwd(self):
253 def getcwd(self):
254 """Return the path from which a canonical path is calculated.
254 """Return the path from which a canonical path is calculated.
255
255
256 This path should be used to resolve file patterns or to convert
256 This path should be used to resolve file patterns or to convert
257 canonical paths back to file paths for display. It shouldn't be
257 canonical paths back to file paths for display. It shouldn't be
258 used to get real file paths. Use vfs functions instead.
258 used to get real file paths. Use vfs functions instead.
259 """
259 """
260 cwd = self._cwd
260 cwd = self._cwd
261 if cwd == self._root:
261 if cwd == self._root:
262 return b''
262 return b''
263 # self._root ends with a path separator if self._root is '/' or 'C:\'
263 # self._root ends with a path separator if self._root is '/' or 'C:\'
264 rootsep = self._root
264 rootsep = self._root
265 if not util.endswithsep(rootsep):
265 if not util.endswithsep(rootsep):
266 rootsep += pycompat.ossep
266 rootsep += pycompat.ossep
267 if cwd.startswith(rootsep):
267 if cwd.startswith(rootsep):
268 return cwd[len(rootsep) :]
268 return cwd[len(rootsep) :]
269 else:
269 else:
270 # we're outside the repo. return an absolute path.
270 # we're outside the repo. return an absolute path.
271 return cwd
271 return cwd
272
272
273 def pathto(self, f, cwd=None):
273 def pathto(self, f, cwd=None):
274 if cwd is None:
274 if cwd is None:
275 cwd = self.getcwd()
275 cwd = self.getcwd()
276 path = util.pathto(self._root, cwd, f)
276 path = util.pathto(self._root, cwd, f)
277 if self._slash:
277 if self._slash:
278 return util.pconvert(path)
278 return util.pconvert(path)
279 return path
279 return path
280
280
281 def __getitem__(self, key):
281 def __getitem__(self, key):
282 """Return the current state of key (a filename) in the dirstate.
282 """Return the current state of key (a filename) in the dirstate.
283
283
284 States are:
284 States are:
285 n normal
285 n normal
286 m needs merging
286 m needs merging
287 r marked for removal
287 r marked for removal
288 a marked for addition
288 a marked for addition
289 ? not tracked
289 ? not tracked
290 """
290 """
291 return self._map.get(key, (b"?",))[0]
291 return self._map.get(key, (b"?",))[0]
292
292
293 def __contains__(self, key):
293 def __contains__(self, key):
294 return key in self._map
294 return key in self._map
295
295
296 def __iter__(self):
296 def __iter__(self):
297 return iter(sorted(self._map))
297 return iter(sorted(self._map))
298
298
299 def items(self):
299 def items(self):
300 return pycompat.iteritems(self._map)
300 return pycompat.iteritems(self._map)
301
301
302 iteritems = items
302 iteritems = items
303
303
304 def parents(self):
304 def parents(self):
305 return [self._validate(p) for p in self._pl]
305 return [self._validate(p) for p in self._pl]
306
306
307 def p1(self):
307 def p1(self):
308 return self._validate(self._pl[0])
308 return self._validate(self._pl[0])
309
309
310 def p2(self):
310 def p2(self):
311 return self._validate(self._pl[1])
311 return self._validate(self._pl[1])
312
312
313 def branch(self):
313 def branch(self):
314 return encoding.tolocal(self._branch)
314 return encoding.tolocal(self._branch)
315
315
316 def setparents(self, p1, p2=None):
316 def setparents(self, p1, p2=None):
317 """Set dirstate parents to p1 and p2.
317 """Set dirstate parents to p1 and p2.
318
318
319 When moving from two parents to one, 'm' merged entries a
319 When moving from two parents to one, 'm' merged entries a
320 adjusted to normal and previous copy records discarded and
320 adjusted to normal and previous copy records discarded and
321 returned by the call.
321 returned by the call.
322
322
323 See localrepo.setparents()
323 See localrepo.setparents()
324 """
324 """
325 if p2 is None:
325 if p2 is None:
326 p2 = self._nodeconstants.nullid
326 p2 = self._nodeconstants.nullid
327 if self._parentwriters == 0:
327 if self._parentwriters == 0:
328 raise ValueError(
328 raise ValueError(
329 b"cannot set dirstate parent outside of "
329 b"cannot set dirstate parent outside of "
330 b"dirstate.parentchange context manager"
330 b"dirstate.parentchange context manager"
331 )
331 )
332
332
333 self._dirty = True
333 self._dirty = True
334 oldp2 = self._pl[1]
334 oldp2 = self._pl[1]
335 if self._origpl is None:
335 if self._origpl is None:
336 self._origpl = self._pl
336 self._origpl = self._pl
337 self._map.setparents(p1, p2)
337 self._map.setparents(p1, p2)
338 copies = {}
338 copies = {}
339 if (
339 if (
340 oldp2 != self._nodeconstants.nullid
340 oldp2 != self._nodeconstants.nullid
341 and p2 == self._nodeconstants.nullid
341 and p2 == self._nodeconstants.nullid
342 ):
342 ):
343 candidatefiles = self._map.non_normal_or_other_parent_paths()
343 candidatefiles = self._map.non_normal_or_other_parent_paths()
344
344
345 for f in candidatefiles:
345 for f in candidatefiles:
346 s = self._map.get(f)
346 s = self._map.get(f)
347 if s is None:
347 if s is None:
348 continue
348 continue
349
349
350 # Discard 'm' markers when moving away from a merge state
350 # Discard 'm' markers when moving away from a merge state
351 if s[0] == b'm':
351 if s[0] == b'm':
352 source = self._map.copymap.get(f)
352 source = self._map.copymap.get(f)
353 if source:
353 if source:
354 copies[f] = source
354 copies[f] = source
355 self.normallookup(f)
355 self.normallookup(f)
356 # Also fix up otherparent markers
356 # Also fix up otherparent markers
357 elif s[0] == b'n' and s[2] == -2:
357 elif s[0] == b'n' and s[2] == -2:
358 source = self._map.copymap.get(f)
358 source = self._map.copymap.get(f)
359 if source:
359 if source:
360 copies[f] = source
360 copies[f] = source
361 self.add(f)
361 self.add(f)
362 return copies
362 return copies
363
363
364 def setbranch(self, branch):
364 def setbranch(self, branch):
365 self.__class__._branch.set(self, encoding.fromlocal(branch))
365 self.__class__._branch.set(self, encoding.fromlocal(branch))
366 f = self._opener(b'branch', b'w', atomictemp=True, checkambig=True)
366 f = self._opener(b'branch', b'w', atomictemp=True, checkambig=True)
367 try:
367 try:
368 f.write(self._branch + b'\n')
368 f.write(self._branch + b'\n')
369 f.close()
369 f.close()
370
370
371 # make sure filecache has the correct stat info for _branch after
371 # make sure filecache has the correct stat info for _branch after
372 # replacing the underlying file
372 # replacing the underlying file
373 ce = self._filecache[b'_branch']
373 ce = self._filecache[b'_branch']
374 if ce:
374 if ce:
375 ce.refresh()
375 ce.refresh()
376 except: # re-raises
376 except: # re-raises
377 f.discard()
377 f.discard()
378 raise
378 raise
379
379
380 def invalidate(self):
380 def invalidate(self):
381 """Causes the next access to reread the dirstate.
381 """Causes the next access to reread the dirstate.
382
382
383 This is different from localrepo.invalidatedirstate() because it always
383 This is different from localrepo.invalidatedirstate() because it always
384 rereads the dirstate. Use localrepo.invalidatedirstate() if you want to
384 rereads the dirstate. Use localrepo.invalidatedirstate() if you want to
385 check whether the dirstate has changed before rereading it."""
385 check whether the dirstate has changed before rereading it."""
386
386
387 for a in ("_map", "_branch", "_ignore"):
387 for a in ("_map", "_branch", "_ignore"):
388 if a in self.__dict__:
388 if a in self.__dict__:
389 delattr(self, a)
389 delattr(self, a)
390 self._lastnormaltime = 0
390 self._lastnormaltime = 0
391 self._dirty = False
391 self._dirty = False
392 self._updatedfiles.clear()
392 self._updatedfiles.clear()
393 self._parentwriters = 0
393 self._parentwriters = 0
394 self._origpl = None
394 self._origpl = None
395
395
396 def copy(self, source, dest):
396 def copy(self, source, dest):
397 """Mark dest as a copy of source. Unmark dest if source is None."""
397 """Mark dest as a copy of source. Unmark dest if source is None."""
398 if source == dest:
398 if source == dest:
399 return
399 return
400 self._dirty = True
400 self._dirty = True
401 if source is not None:
401 if source is not None:
402 self._map.copymap[dest] = source
402 self._map.copymap[dest] = source
403 self._updatedfiles.add(source)
403 self._updatedfiles.add(source)
404 self._updatedfiles.add(dest)
404 self._updatedfiles.add(dest)
405 elif self._map.copymap.pop(dest, None):
405 elif self._map.copymap.pop(dest, None):
406 self._updatedfiles.add(dest)
406 self._updatedfiles.add(dest)
407
407
408 def copied(self, file):
408 def copied(self, file):
409 return self._map.copymap.get(file, None)
409 return self._map.copymap.get(file, None)
410
410
411 def copies(self):
411 def copies(self):
412 return self._map.copymap
412 return self._map.copymap
413
413
414 def _addpath(self, f, state, mode, size, mtime):
414 def _addpath(self, f, state, mode, size, mtime):
415 oldstate = self[f]
415 oldstate = self[f]
416 if state == b'a' or oldstate == b'r':
416 if state == b'a' or oldstate == b'r':
417 scmutil.checkfilename(f)
417 scmutil.checkfilename(f)
418 if self._map.hastrackeddir(f):
418 if self._map.hastrackeddir(f):
419 raise error.Abort(
419 raise error.Abort(
420 _(b'directory %r already in dirstate') % pycompat.bytestr(f)
420 _(b'directory %r already in dirstate') % pycompat.bytestr(f)
421 )
421 )
422 # shadows
422 # shadows
423 for d in pathutil.finddirs(f):
423 for d in pathutil.finddirs(f):
424 if self._map.hastrackeddir(d):
424 if self._map.hastrackeddir(d):
425 break
425 break
426 entry = self._map.get(d)
426 entry = self._map.get(d)
427 if entry is not None and entry[0] != b'r':
427 if entry is not None and entry[0] != b'r':
428 raise error.Abort(
428 raise error.Abort(
429 _(b'file %r in dirstate clashes with %r')
429 _(b'file %r in dirstate clashes with %r')
430 % (pycompat.bytestr(d), pycompat.bytestr(f))
430 % (pycompat.bytestr(d), pycompat.bytestr(f))
431 )
431 )
432 self._dirty = True
432 self._dirty = True
433 self._updatedfiles.add(f)
433 self._updatedfiles.add(f)
434 self._map.addfile(f, oldstate, state, mode, size, mtime)
434 self._map.addfile(f, oldstate, state, mode, size, mtime)
435
435
436 def normal(self, f, parentfiledata=None):
436 def normal(self, f, parentfiledata=None):
437 """Mark a file normal and clean.
437 """Mark a file normal and clean.
438
438
439 parentfiledata: (mode, size, mtime) of the clean file
439 parentfiledata: (mode, size, mtime) of the clean file
440
440
441 parentfiledata should be computed from memory (for mode,
441 parentfiledata should be computed from memory (for mode,
442 size), as or close as possible from the point where we
442 size), as or close as possible from the point where we
443 determined the file was clean, to limit the risk of the
443 determined the file was clean, to limit the risk of the
444 file having been changed by an external process between the
444 file having been changed by an external process between the
445 moment where the file was determined to be clean and now."""
445 moment where the file was determined to be clean and now."""
446 if parentfiledata:
446 if parentfiledata:
447 (mode, size, mtime) = parentfiledata
447 (mode, size, mtime) = parentfiledata
448 else:
448 else:
449 s = os.lstat(self._join(f))
449 s = os.lstat(self._join(f))
450 mode = s.st_mode
450 mode = s.st_mode
451 size = s.st_size
451 size = s.st_size
452 mtime = s[stat.ST_MTIME]
452 mtime = s[stat.ST_MTIME]
453 self._addpath(f, b'n', mode, size & _rangemask, mtime & _rangemask)
453 self._addpath(f, b'n', mode, size & _rangemask, mtime & _rangemask)
454 self._map.copymap.pop(f, None)
454 self._map.copymap.pop(f, None)
455 if f in self._map.nonnormalset:
455 if f in self._map.nonnormalset:
456 self._map.nonnormalset.remove(f)
456 self._map.nonnormalset.remove(f)
457 if mtime > self._lastnormaltime:
457 if mtime > self._lastnormaltime:
458 # Remember the most recent modification timeslot for status(),
458 # Remember the most recent modification timeslot for status(),
459 # to make sure we won't miss future size-preserving file content
459 # to make sure we won't miss future size-preserving file content
460 # modifications that happen within the same timeslot.
460 # modifications that happen within the same timeslot.
461 self._lastnormaltime = mtime
461 self._lastnormaltime = mtime
462
462
463 def normallookup(self, f):
463 def normallookup(self, f):
464 '''Mark a file normal, but possibly dirty.'''
464 '''Mark a file normal, but possibly dirty.'''
465 if self._pl[1] != self._nodeconstants.nullid:
465 if self._pl[1] != self._nodeconstants.nullid:
466 # if there is a merge going on and the file was either
466 # if there is a merge going on and the file was either
467 # in state 'm' (-1) or coming from other parent (-2) before
467 # in state 'm' (-1) or coming from other parent (-2) before
468 # being removed, restore that state.
468 # being removed, restore that state.
469 entry = self._map.get(f)
469 entry = self._map.get(f)
470 if entry is not None:
470 if entry is not None:
471 if entry[0] == b'r' and entry[2] in (-1, -2):
471 if entry[0] == b'r' and entry[2] in (-1, -2):
472 source = self._map.copymap.get(f)
472 source = self._map.copymap.get(f)
473 if entry[2] == -1:
473 if entry[2] == -1:
474 self.merge(f)
474 self.merge(f)
475 elif entry[2] == -2:
475 elif entry[2] == -2:
476 self.otherparent(f)
476 self.otherparent(f)
477 if source:
477 if source:
478 self.copy(source, f)
478 self.copy(source, f)
479 return
479 return
480 if entry[0] == b'm' or entry[0] == b'n' and entry[2] == -2:
480 if entry[0] == b'm' or entry[0] == b'n' and entry[2] == -2:
481 return
481 return
482 self._addpath(f, b'n', 0, -1, -1)
482 self._addpath(f, b'n', 0, -1, -1)
483 self._map.copymap.pop(f, None)
483 self._map.copymap.pop(f, None)
484
484
485 def otherparent(self, f):
485 def otherparent(self, f):
486 '''Mark as coming from the other parent, always dirty.'''
486 '''Mark as coming from the other parent, always dirty.'''
487 if self._pl[1] == self._nodeconstants.nullid:
487 if self._pl[1] == self._nodeconstants.nullid:
488 raise error.Abort(
488 raise error.Abort(
489 _(b"setting %r to other parent only allowed in merges") % f
489 _(b"setting %r to other parent only allowed in merges") % f
490 )
490 )
491 if f in self and self[f] == b'n':
491 if f in self and self[f] == b'n':
492 # merge-like
492 # merge-like
493 self._addpath(f, b'm', 0, -2, -1)
493 self._addpath(f, b'm', 0, -2, -1)
494 else:
494 else:
495 # add-like
495 # add-like
496 self._addpath(f, b'n', 0, -2, -1)
496 self._addpath(f, b'n', 0, -2, -1)
497 self._map.copymap.pop(f, None)
497 self._map.copymap.pop(f, None)
498
498
499 def add(self, f):
499 def add(self, f):
500 '''Mark a file added.'''
500 '''Mark a file added.'''
501 self._addpath(f, b'a', 0, -1, -1)
501 self._addpath(f, b'a', 0, -1, -1)
502 self._map.copymap.pop(f, None)
502 self._map.copymap.pop(f, None)
503
503
504 def remove(self, f):
504 def remove(self, f):
505 '''Mark a file removed.'''
505 '''Mark a file removed.'''
506 self._dirty = True
506 self._dirty = True
507 oldstate = self[f]
507 oldstate = self[f]
508 size = 0
508 size = 0
509 if self._pl[1] != self._nodeconstants.nullid:
509 if self._pl[1] != self._nodeconstants.nullid:
510 entry = self._map.get(f)
510 entry = self._map.get(f)
511 if entry is not None:
511 if entry is not None:
512 # backup the previous state
512 # backup the previous state
513 if entry[0] == b'm': # merge
513 if entry[0] == b'm': # merge
514 size = -1
514 size = -1
515 elif entry[0] == b'n' and entry[2] == -2: # other parent
515 elif entry[0] == b'n' and entry[2] == -2: # other parent
516 size = -2
516 size = -2
517 self._map.otherparentset.add(f)
517 self._map.otherparentset.add(f)
518 self._updatedfiles.add(f)
518 self._updatedfiles.add(f)
519 self._map.removefile(f, oldstate, size)
519 self._map.removefile(f, oldstate, size)
520 if size == 0:
520 if size == 0:
521 self._map.copymap.pop(f, None)
521 self._map.copymap.pop(f, None)
522
522
523 def merge(self, f):
523 def merge(self, f):
524 '''Mark a file merged.'''
524 '''Mark a file merged.'''
525 if self._pl[1] == self._nodeconstants.nullid:
525 if self._pl[1] == self._nodeconstants.nullid:
526 return self.normallookup(f)
526 return self.normallookup(f)
527 return self.otherparent(f)
527 return self.otherparent(f)
528
528
529 def drop(self, f):
529 def drop(self, f):
530 '''Drop a file from the dirstate'''
530 '''Drop a file from the dirstate'''
531 oldstate = self[f]
531 oldstate = self[f]
532 if self._map.dropfile(f, oldstate):
532 if self._map.dropfile(f, oldstate):
533 self._dirty = True
533 self._dirty = True
534 self._updatedfiles.add(f)
534 self._updatedfiles.add(f)
535 self._map.copymap.pop(f, None)
535 self._map.copymap.pop(f, None)
536
536
537 def _discoverpath(self, path, normed, ignoremissing, exists, storemap):
537 def _discoverpath(self, path, normed, ignoremissing, exists, storemap):
538 if exists is None:
538 if exists is None:
539 exists = os.path.lexists(os.path.join(self._root, path))
539 exists = os.path.lexists(os.path.join(self._root, path))
540 if not exists:
540 if not exists:
541 # Maybe a path component exists
541 # Maybe a path component exists
542 if not ignoremissing and b'/' in path:
542 if not ignoremissing and b'/' in path:
543 d, f = path.rsplit(b'/', 1)
543 d, f = path.rsplit(b'/', 1)
544 d = self._normalize(d, False, ignoremissing, None)
544 d = self._normalize(d, False, ignoremissing, None)
545 folded = d + b"/" + f
545 folded = d + b"/" + f
546 else:
546 else:
547 # No path components, preserve original case
547 # No path components, preserve original case
548 folded = path
548 folded = path
549 else:
549 else:
550 # recursively normalize leading directory components
550 # recursively normalize leading directory components
551 # against dirstate
551 # against dirstate
552 if b'/' in normed:
552 if b'/' in normed:
553 d, f = normed.rsplit(b'/', 1)
553 d, f = normed.rsplit(b'/', 1)
554 d = self._normalize(d, False, ignoremissing, True)
554 d = self._normalize(d, False, ignoremissing, True)
555 r = self._root + b"/" + d
555 r = self._root + b"/" + d
556 folded = d + b"/" + util.fspath(f, r)
556 folded = d + b"/" + util.fspath(f, r)
557 else:
557 else:
558 folded = util.fspath(normed, self._root)
558 folded = util.fspath(normed, self._root)
559 storemap[normed] = folded
559 storemap[normed] = folded
560
560
561 return folded
561 return folded
562
562
563 def _normalizefile(self, path, isknown, ignoremissing=False, exists=None):
563 def _normalizefile(self, path, isknown, ignoremissing=False, exists=None):
564 normed = util.normcase(path)
564 normed = util.normcase(path)
565 folded = self._map.filefoldmap.get(normed, None)
565 folded = self._map.filefoldmap.get(normed, None)
566 if folded is None:
566 if folded is None:
567 if isknown:
567 if isknown:
568 folded = path
568 folded = path
569 else:
569 else:
570 folded = self._discoverpath(
570 folded = self._discoverpath(
571 path, normed, ignoremissing, exists, self._map.filefoldmap
571 path, normed, ignoremissing, exists, self._map.filefoldmap
572 )
572 )
573 return folded
573 return folded
574
574
575 def _normalize(self, path, isknown, ignoremissing=False, exists=None):
575 def _normalize(self, path, isknown, ignoremissing=False, exists=None):
576 normed = util.normcase(path)
576 normed = util.normcase(path)
577 folded = self._map.filefoldmap.get(normed, None)
577 folded = self._map.filefoldmap.get(normed, None)
578 if folded is None:
578 if folded is None:
579 folded = self._map.dirfoldmap.get(normed, None)
579 folded = self._map.dirfoldmap.get(normed, None)
580 if folded is None:
580 if folded is None:
581 if isknown:
581 if isknown:
582 folded = path
582 folded = path
583 else:
583 else:
584 # store discovered result in dirfoldmap so that future
584 # store discovered result in dirfoldmap so that future
585 # normalizefile calls don't start matching directories
585 # normalizefile calls don't start matching directories
586 folded = self._discoverpath(
586 folded = self._discoverpath(
587 path, normed, ignoremissing, exists, self._map.dirfoldmap
587 path, normed, ignoremissing, exists, self._map.dirfoldmap
588 )
588 )
589 return folded
589 return folded
590
590
591 def normalize(self, path, isknown=False, ignoremissing=False):
591 def normalize(self, path, isknown=False, ignoremissing=False):
592 """
592 """
593 normalize the case of a pathname when on a casefolding filesystem
593 normalize the case of a pathname when on a casefolding filesystem
594
594
595 isknown specifies whether the filename came from walking the
595 isknown specifies whether the filename came from walking the
596 disk, to avoid extra filesystem access.
596 disk, to avoid extra filesystem access.
597
597
598 If ignoremissing is True, missing path are returned
598 If ignoremissing is True, missing path are returned
599 unchanged. Otherwise, we try harder to normalize possibly
599 unchanged. Otherwise, we try harder to normalize possibly
600 existing path components.
600 existing path components.
601
601
602 The normalized case is determined based on the following precedence:
602 The normalized case is determined based on the following precedence:
603
603
604 - version of name already stored in the dirstate
604 - version of name already stored in the dirstate
605 - version of name stored on disk
605 - version of name stored on disk
606 - version provided via command arguments
606 - version provided via command arguments
607 """
607 """
608
608
609 if self._checkcase:
609 if self._checkcase:
610 return self._normalize(path, isknown, ignoremissing)
610 return self._normalize(path, isknown, ignoremissing)
611 return path
611 return path
612
612
613 def clear(self):
613 def clear(self):
614 self._map.clear()
614 self._map.clear()
615 self._lastnormaltime = 0
615 self._lastnormaltime = 0
616 self._updatedfiles.clear()
616 self._updatedfiles.clear()
617 self._dirty = True
617 self._dirty = True
618
618
619 def rebuild(self, parent, allfiles, changedfiles=None):
619 def rebuild(self, parent, allfiles, changedfiles=None):
620 if changedfiles is None:
620 if changedfiles is None:
621 # Rebuild entire dirstate
621 # Rebuild entire dirstate
622 to_lookup = allfiles
622 to_lookup = allfiles
623 to_drop = []
623 to_drop = []
624 lastnormaltime = self._lastnormaltime
624 lastnormaltime = self._lastnormaltime
625 self.clear()
625 self.clear()
626 self._lastnormaltime = lastnormaltime
626 self._lastnormaltime = lastnormaltime
627 elif len(changedfiles) < 10:
627 elif len(changedfiles) < 10:
628 # Avoid turning allfiles into a set, which can be expensive if it's
628 # Avoid turning allfiles into a set, which can be expensive if it's
629 # large.
629 # large.
630 to_lookup = []
630 to_lookup = []
631 to_drop = []
631 to_drop = []
632 for f in changedfiles:
632 for f in changedfiles:
633 if f in allfiles:
633 if f in allfiles:
634 to_lookup.append(f)
634 to_lookup.append(f)
635 else:
635 else:
636 to_drop.append(f)
636 to_drop.append(f)
637 else:
637 else:
638 changedfilesset = set(changedfiles)
638 changedfilesset = set(changedfiles)
639 to_lookup = changedfilesset & set(allfiles)
639 to_lookup = changedfilesset & set(allfiles)
640 to_drop = changedfilesset - to_lookup
640 to_drop = changedfilesset - to_lookup
641
641
642 if self._origpl is None:
642 if self._origpl is None:
643 self._origpl = self._pl
643 self._origpl = self._pl
644 self._map.setparents(parent, self._nodeconstants.nullid)
644 self._map.setparents(parent, self._nodeconstants.nullid)
645
645
646 for f in to_lookup:
646 for f in to_lookup:
647 self.normallookup(f)
647 self.normallookup(f)
648 for f in to_drop:
648 for f in to_drop:
649 self.drop(f)
649 self.drop(f)
650
650
651 self._dirty = True
651 self._dirty = True
652
652
653 def identity(self):
653 def identity(self):
654 """Return identity of dirstate itself to detect changing in storage
654 """Return identity of dirstate itself to detect changing in storage
655
655
656 If identity of previous dirstate is equal to this, writing
656 If identity of previous dirstate is equal to this, writing
657 changes based on the former dirstate out can keep consistency.
657 changes based on the former dirstate out can keep consistency.
658 """
658 """
659 return self._map.identity
659 return self._map.identity
660
660
661 def write(self, tr):
661 def write(self, tr):
662 if not self._dirty:
662 if not self._dirty:
663 return
663 return
664
664
665 filename = self._filename
665 filename = self._filename
666 if tr:
666 if tr:
667 # 'dirstate.write()' is not only for writing in-memory
667 # 'dirstate.write()' is not only for writing in-memory
668 # changes out, but also for dropping ambiguous timestamp.
668 # changes out, but also for dropping ambiguous timestamp.
669 # delayed writing re-raise "ambiguous timestamp issue".
669 # delayed writing re-raise "ambiguous timestamp issue".
670 # See also the wiki page below for detail:
670 # See also the wiki page below for detail:
671 # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan
671 # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan
672
672
673 # emulate dropping timestamp in 'parsers.pack_dirstate'
673 # emulate dropping timestamp in 'parsers.pack_dirstate'
674 now = _getfsnow(self._opener)
674 now = _getfsnow(self._opener)
675 self._map.clearambiguoustimes(self._updatedfiles, now)
675 self._map.clearambiguoustimes(self._updatedfiles, now)
676
676
677 # emulate that all 'dirstate.normal' results are written out
677 # emulate that all 'dirstate.normal' results are written out
678 self._lastnormaltime = 0
678 self._lastnormaltime = 0
679 self._updatedfiles.clear()
679 self._updatedfiles.clear()
680
680
681 # delay writing in-memory changes out
681 # delay writing in-memory changes out
682 tr.addfilegenerator(
682 tr.addfilegenerator(
683 b'dirstate',
683 b'dirstate',
684 (self._filename,),
684 (self._filename,),
685 self._writedirstate,
685 self._writedirstate,
686 location=b'plain',
686 location=b'plain',
687 )
687 )
688 return
688 return
689
689
690 st = self._opener(filename, b"w", atomictemp=True, checkambig=True)
690 st = self._opener(filename, b"w", atomictemp=True, checkambig=True)
691 self._writedirstate(st)
691 self._writedirstate(st)
692
692
693 def addparentchangecallback(self, category, callback):
693 def addparentchangecallback(self, category, callback):
694 """add a callback to be called when the wd parents are changed
694 """add a callback to be called when the wd parents are changed
695
695
696 Callback will be called with the following arguments:
696 Callback will be called with the following arguments:
697 dirstate, (oldp1, oldp2), (newp1, newp2)
697 dirstate, (oldp1, oldp2), (newp1, newp2)
698
698
699 Category is a unique identifier to allow overwriting an old callback
699 Category is a unique identifier to allow overwriting an old callback
700 with a newer callback.
700 with a newer callback.
701 """
701 """
702 self._plchangecallbacks[category] = callback
702 self._plchangecallbacks[category] = callback
703
703
704 def _writedirstate(self, st):
704 def _writedirstate(self, st):
705 # notify callbacks about parents change
705 # notify callbacks about parents change
706 if self._origpl is not None and self._origpl != self._pl:
706 if self._origpl is not None and self._origpl != self._pl:
707 for c, callback in sorted(
707 for c, callback in sorted(
708 pycompat.iteritems(self._plchangecallbacks)
708 pycompat.iteritems(self._plchangecallbacks)
709 ):
709 ):
710 callback(self, self._origpl, self._pl)
710 callback(self, self._origpl, self._pl)
711 self._origpl = None
711 self._origpl = None
712 # use the modification time of the newly created temporary file as the
712 # use the modification time of the newly created temporary file as the
713 # filesystem's notion of 'now'
713 # filesystem's notion of 'now'
714 now = util.fstat(st)[stat.ST_MTIME] & _rangemask
714 now = util.fstat(st)[stat.ST_MTIME] & _rangemask
715
715
716 # enough 'delaywrite' prevents 'pack_dirstate' from dropping
716 # enough 'delaywrite' prevents 'pack_dirstate' from dropping
717 # timestamp of each entries in dirstate, because of 'now > mtime'
717 # timestamp of each entries in dirstate, because of 'now > mtime'
718 delaywrite = self._ui.configint(b'debug', b'dirstate.delaywrite')
718 delaywrite = self._ui.configint(b'debug', b'dirstate.delaywrite')
719 if delaywrite > 0:
719 if delaywrite > 0:
720 # do we have any files to delay for?
720 # do we have any files to delay for?
721 for f, e in pycompat.iteritems(self._map):
721 for f, e in pycompat.iteritems(self._map):
722 if e[0] == b'n' and e[3] == now:
722 if e[0] == b'n' and e[3] == now:
723 import time # to avoid useless import
723 import time # to avoid useless import
724
724
725 # rather than sleep n seconds, sleep until the next
725 # rather than sleep n seconds, sleep until the next
726 # multiple of n seconds
726 # multiple of n seconds
727 clock = time.time()
727 clock = time.time()
728 start = int(clock) - (int(clock) % delaywrite)
728 start = int(clock) - (int(clock) % delaywrite)
729 end = start + delaywrite
729 end = start + delaywrite
730 time.sleep(end - clock)
730 time.sleep(end - clock)
731 now = end # trust our estimate that the end is near now
731 now = end # trust our estimate that the end is near now
732 break
732 break
733
733
734 self._map.write(st, now)
734 self._map.write(st, now)
735 self._lastnormaltime = 0
735 self._lastnormaltime = 0
736 self._dirty = False
736 self._dirty = False
737
737
738 def _dirignore(self, f):
738 def _dirignore(self, f):
739 if self._ignore(f):
739 if self._ignore(f):
740 return True
740 return True
741 for p in pathutil.finddirs(f):
741 for p in pathutil.finddirs(f):
742 if self._ignore(p):
742 if self._ignore(p):
743 return True
743 return True
744 return False
744 return False
745
745
746 def _ignorefiles(self):
746 def _ignorefiles(self):
747 files = []
747 files = []
748 if os.path.exists(self._join(b'.hgignore')):
748 if os.path.exists(self._join(b'.hgignore')):
749 files.append(self._join(b'.hgignore'))
749 files.append(self._join(b'.hgignore'))
750 for name, path in self._ui.configitems(b"ui"):
750 for name, path in self._ui.configitems(b"ui"):
751 if name == b'ignore' or name.startswith(b'ignore.'):
751 if name == b'ignore' or name.startswith(b'ignore.'):
752 # we need to use os.path.join here rather than self._join
752 # we need to use os.path.join here rather than self._join
753 # because path is arbitrary and user-specified
753 # because path is arbitrary and user-specified
754 files.append(os.path.join(self._rootdir, util.expandpath(path)))
754 files.append(os.path.join(self._rootdir, util.expandpath(path)))
755 return files
755 return files
756
756
757 def _ignorefileandline(self, f):
757 def _ignorefileandline(self, f):
758 files = collections.deque(self._ignorefiles())
758 files = collections.deque(self._ignorefiles())
759 visited = set()
759 visited = set()
760 while files:
760 while files:
761 i = files.popleft()
761 i = files.popleft()
762 patterns = matchmod.readpatternfile(
762 patterns = matchmod.readpatternfile(
763 i, self._ui.warn, sourceinfo=True
763 i, self._ui.warn, sourceinfo=True
764 )
764 )
765 for pattern, lineno, line in patterns:
765 for pattern, lineno, line in patterns:
766 kind, p = matchmod._patsplit(pattern, b'glob')
766 kind, p = matchmod._patsplit(pattern, b'glob')
767 if kind == b"subinclude":
767 if kind == b"subinclude":
768 if p not in visited:
768 if p not in visited:
769 files.append(p)
769 files.append(p)
770 continue
770 continue
771 m = matchmod.match(
771 m = matchmod.match(
772 self._root, b'', [], [pattern], warn=self._ui.warn
772 self._root, b'', [], [pattern], warn=self._ui.warn
773 )
773 )
774 if m(f):
774 if m(f):
775 return (i, lineno, line)
775 return (i, lineno, line)
776 visited.add(i)
776 visited.add(i)
777 return (None, -1, b"")
777 return (None, -1, b"")
778
778
779 def _walkexplicit(self, match, subrepos):
779 def _walkexplicit(self, match, subrepos):
780 """Get stat data about the files explicitly specified by match.
780 """Get stat data about the files explicitly specified by match.
781
781
782 Return a triple (results, dirsfound, dirsnotfound).
782 Return a triple (results, dirsfound, dirsnotfound).
783 - results is a mapping from filename to stat result. It also contains
783 - results is a mapping from filename to stat result. It also contains
784 listings mapping subrepos and .hg to None.
784 listings mapping subrepos and .hg to None.
785 - dirsfound is a list of files found to be directories.
785 - dirsfound is a list of files found to be directories.
786 - dirsnotfound is a list of files that the dirstate thinks are
786 - dirsnotfound is a list of files that the dirstate thinks are
787 directories and that were not found."""
787 directories and that were not found."""
788
788
789 def badtype(mode):
789 def badtype(mode):
790 kind = _(b'unknown')
790 kind = _(b'unknown')
791 if stat.S_ISCHR(mode):
791 if stat.S_ISCHR(mode):
792 kind = _(b'character device')
792 kind = _(b'character device')
793 elif stat.S_ISBLK(mode):
793 elif stat.S_ISBLK(mode):
794 kind = _(b'block device')
794 kind = _(b'block device')
795 elif stat.S_ISFIFO(mode):
795 elif stat.S_ISFIFO(mode):
796 kind = _(b'fifo')
796 kind = _(b'fifo')
797 elif stat.S_ISSOCK(mode):
797 elif stat.S_ISSOCK(mode):
798 kind = _(b'socket')
798 kind = _(b'socket')
799 elif stat.S_ISDIR(mode):
799 elif stat.S_ISDIR(mode):
800 kind = _(b'directory')
800 kind = _(b'directory')
801 return _(b'unsupported file type (type is %s)') % kind
801 return _(b'unsupported file type (type is %s)') % kind
802
802
803 badfn = match.bad
803 badfn = match.bad
804 dmap = self._map
804 dmap = self._map
805 lstat = os.lstat
805 lstat = os.lstat
806 getkind = stat.S_IFMT
806 getkind = stat.S_IFMT
807 dirkind = stat.S_IFDIR
807 dirkind = stat.S_IFDIR
808 regkind = stat.S_IFREG
808 regkind = stat.S_IFREG
809 lnkkind = stat.S_IFLNK
809 lnkkind = stat.S_IFLNK
810 join = self._join
810 join = self._join
811 dirsfound = []
811 dirsfound = []
812 foundadd = dirsfound.append
812 foundadd = dirsfound.append
813 dirsnotfound = []
813 dirsnotfound = []
814 notfoundadd = dirsnotfound.append
814 notfoundadd = dirsnotfound.append
815
815
816 if not match.isexact() and self._checkcase:
816 if not match.isexact() and self._checkcase:
817 normalize = self._normalize
817 normalize = self._normalize
818 else:
818 else:
819 normalize = None
819 normalize = None
820
820
821 files = sorted(match.files())
821 files = sorted(match.files())
822 subrepos.sort()
822 subrepos.sort()
823 i, j = 0, 0
823 i, j = 0, 0
824 while i < len(files) and j < len(subrepos):
824 while i < len(files) and j < len(subrepos):
825 subpath = subrepos[j] + b"/"
825 subpath = subrepos[j] + b"/"
826 if files[i] < subpath:
826 if files[i] < subpath:
827 i += 1
827 i += 1
828 continue
828 continue
829 while i < len(files) and files[i].startswith(subpath):
829 while i < len(files) and files[i].startswith(subpath):
830 del files[i]
830 del files[i]
831 j += 1
831 j += 1
832
832
833 if not files or b'' in files:
833 if not files or b'' in files:
834 files = [b'']
834 files = [b'']
835 # constructing the foldmap is expensive, so don't do it for the
835 # constructing the foldmap is expensive, so don't do it for the
836 # common case where files is ['']
836 # common case where files is ['']
837 normalize = None
837 normalize = None
838 results = dict.fromkeys(subrepos)
838 results = dict.fromkeys(subrepos)
839 results[b'.hg'] = None
839 results[b'.hg'] = None
840
840
841 for ff in files:
841 for ff in files:
842 if normalize:
842 if normalize:
843 nf = normalize(ff, False, True)
843 nf = normalize(ff, False, True)
844 else:
844 else:
845 nf = ff
845 nf = ff
846 if nf in results:
846 if nf in results:
847 continue
847 continue
848
848
849 try:
849 try:
850 st = lstat(join(nf))
850 st = lstat(join(nf))
851 kind = getkind(st.st_mode)
851 kind = getkind(st.st_mode)
852 if kind == dirkind:
852 if kind == dirkind:
853 if nf in dmap:
853 if nf in dmap:
854 # file replaced by dir on disk but still in dirstate
854 # file replaced by dir on disk but still in dirstate
855 results[nf] = None
855 results[nf] = None
856 foundadd((nf, ff))
856 foundadd((nf, ff))
857 elif kind == regkind or kind == lnkkind:
857 elif kind == regkind or kind == lnkkind:
858 results[nf] = st
858 results[nf] = st
859 else:
859 else:
860 badfn(ff, badtype(kind))
860 badfn(ff, badtype(kind))
861 if nf in dmap:
861 if nf in dmap:
862 results[nf] = None
862 results[nf] = None
863 except OSError as inst: # nf not found on disk - it is dirstate only
863 except OSError as inst: # nf not found on disk - it is dirstate only
864 if nf in dmap: # does it exactly match a missing file?
864 if nf in dmap: # does it exactly match a missing file?
865 results[nf] = None
865 results[nf] = None
866 else: # does it match a missing directory?
866 else: # does it match a missing directory?
867 if self._map.hasdir(nf):
867 if self._map.hasdir(nf):
868 notfoundadd(nf)
868 notfoundadd(nf)
869 else:
869 else:
870 badfn(ff, encoding.strtolocal(inst.strerror))
870 badfn(ff, encoding.strtolocal(inst.strerror))
871
871
872 # match.files() may contain explicitly-specified paths that shouldn't
872 # match.files() may contain explicitly-specified paths that shouldn't
873 # be taken; drop them from the list of files found. dirsfound/notfound
873 # be taken; drop them from the list of files found. dirsfound/notfound
874 # aren't filtered here because they will be tested later.
874 # aren't filtered here because they will be tested later.
875 if match.anypats():
875 if match.anypats():
876 for f in list(results):
876 for f in list(results):
877 if f == b'.hg' or f in subrepos:
877 if f == b'.hg' or f in subrepos:
878 # keep sentinel to disable further out-of-repo walks
878 # keep sentinel to disable further out-of-repo walks
879 continue
879 continue
880 if not match(f):
880 if not match(f):
881 del results[f]
881 del results[f]
882
882
883 # Case insensitive filesystems cannot rely on lstat() failing to detect
883 # Case insensitive filesystems cannot rely on lstat() failing to detect
884 # a case-only rename. Prune the stat object for any file that does not
884 # a case-only rename. Prune the stat object for any file that does not
885 # match the case in the filesystem, if there are multiple files that
885 # match the case in the filesystem, if there are multiple files that
886 # normalize to the same path.
886 # normalize to the same path.
887 if match.isexact() and self._checkcase:
887 if match.isexact() and self._checkcase:
888 normed = {}
888 normed = {}
889
889
890 for f, st in pycompat.iteritems(results):
890 for f, st in pycompat.iteritems(results):
891 if st is None:
891 if st is None:
892 continue
892 continue
893
893
894 nc = util.normcase(f)
894 nc = util.normcase(f)
895 paths = normed.get(nc)
895 paths = normed.get(nc)
896
896
897 if paths is None:
897 if paths is None:
898 paths = set()
898 paths = set()
899 normed[nc] = paths
899 normed[nc] = paths
900
900
901 paths.add(f)
901 paths.add(f)
902
902
903 for norm, paths in pycompat.iteritems(normed):
903 for norm, paths in pycompat.iteritems(normed):
904 if len(paths) > 1:
904 if len(paths) > 1:
905 for path in paths:
905 for path in paths:
906 folded = self._discoverpath(
906 folded = self._discoverpath(
907 path, norm, True, None, self._map.dirfoldmap
907 path, norm, True, None, self._map.dirfoldmap
908 )
908 )
909 if path != folded:
909 if path != folded:
910 results[path] = None
910 results[path] = None
911
911
912 return results, dirsfound, dirsnotfound
912 return results, dirsfound, dirsnotfound
913
913
914 def walk(self, match, subrepos, unknown, ignored, full=True):
914 def walk(self, match, subrepos, unknown, ignored, full=True):
915 """
915 """
916 Walk recursively through the directory tree, finding all files
916 Walk recursively through the directory tree, finding all files
917 matched by match.
917 matched by match.
918
918
919 If full is False, maybe skip some known-clean files.
919 If full is False, maybe skip some known-clean files.
920
920
921 Return a dict mapping filename to stat-like object (either
921 Return a dict mapping filename to stat-like object (either
922 mercurial.osutil.stat instance or return value of os.stat()).
922 mercurial.osutil.stat instance or return value of os.stat()).
923
923
924 """
924 """
925 # full is a flag that extensions that hook into walk can use -- this
925 # full is a flag that extensions that hook into walk can use -- this
926 # implementation doesn't use it at all. This satisfies the contract
926 # implementation doesn't use it at all. This satisfies the contract
927 # because we only guarantee a "maybe".
927 # because we only guarantee a "maybe".
928
928
929 if ignored:
929 if ignored:
930 ignore = util.never
930 ignore = util.never
931 dirignore = util.never
931 dirignore = util.never
932 elif unknown:
932 elif unknown:
933 ignore = self._ignore
933 ignore = self._ignore
934 dirignore = self._dirignore
934 dirignore = self._dirignore
935 else:
935 else:
936 # if not unknown and not ignored, drop dir recursion and step 2
936 # if not unknown and not ignored, drop dir recursion and step 2
937 ignore = util.always
937 ignore = util.always
938 dirignore = util.always
938 dirignore = util.always
939
939
940 matchfn = match.matchfn
940 matchfn = match.matchfn
941 matchalways = match.always()
941 matchalways = match.always()
942 matchtdir = match.traversedir
942 matchtdir = match.traversedir
943 dmap = self._map
943 dmap = self._map
944 listdir = util.listdir
944 listdir = util.listdir
945 lstat = os.lstat
945 lstat = os.lstat
946 dirkind = stat.S_IFDIR
946 dirkind = stat.S_IFDIR
947 regkind = stat.S_IFREG
947 regkind = stat.S_IFREG
948 lnkkind = stat.S_IFLNK
948 lnkkind = stat.S_IFLNK
949 join = self._join
949 join = self._join
950
950
951 exact = skipstep3 = False
951 exact = skipstep3 = False
952 if match.isexact(): # match.exact
952 if match.isexact(): # match.exact
953 exact = True
953 exact = True
954 dirignore = util.always # skip step 2
954 dirignore = util.always # skip step 2
955 elif match.prefix(): # match.match, no patterns
955 elif match.prefix(): # match.match, no patterns
956 skipstep3 = True
956 skipstep3 = True
957
957
958 if not exact and self._checkcase:
958 if not exact and self._checkcase:
959 normalize = self._normalize
959 normalize = self._normalize
960 normalizefile = self._normalizefile
960 normalizefile = self._normalizefile
961 skipstep3 = False
961 skipstep3 = False
962 else:
962 else:
963 normalize = self._normalize
963 normalize = self._normalize
964 normalizefile = None
964 normalizefile = None
965
965
966 # step 1: find all explicit files
966 # step 1: find all explicit files
967 results, work, dirsnotfound = self._walkexplicit(match, subrepos)
967 results, work, dirsnotfound = self._walkexplicit(match, subrepos)
968 if matchtdir:
968 if matchtdir:
969 for d in work:
969 for d in work:
970 matchtdir(d[0])
970 matchtdir(d[0])
971 for d in dirsnotfound:
971 for d in dirsnotfound:
972 matchtdir(d)
972 matchtdir(d)
973
973
974 skipstep3 = skipstep3 and not (work or dirsnotfound)
974 skipstep3 = skipstep3 and not (work or dirsnotfound)
975 work = [d for d in work if not dirignore(d[0])]
975 work = [d for d in work if not dirignore(d[0])]
976
976
977 # step 2: visit subdirectories
977 # step 2: visit subdirectories
978 def traverse(work, alreadynormed):
978 def traverse(work, alreadynormed):
979 wadd = work.append
979 wadd = work.append
980 while work:
980 while work:
981 tracing.counter('dirstate.walk work', len(work))
981 tracing.counter('dirstate.walk work', len(work))
982 nd = work.pop()
982 nd = work.pop()
983 visitentries = match.visitchildrenset(nd)
983 visitentries = match.visitchildrenset(nd)
984 if not visitentries:
984 if not visitentries:
985 continue
985 continue
986 if visitentries == b'this' or visitentries == b'all':
986 if visitentries == b'this' or visitentries == b'all':
987 visitentries = None
987 visitentries = None
988 skip = None
988 skip = None
989 if nd != b'':
989 if nd != b'':
990 skip = b'.hg'
990 skip = b'.hg'
991 try:
991 try:
992 with tracing.log('dirstate.walk.traverse listdir %s', nd):
992 with tracing.log('dirstate.walk.traverse listdir %s', nd):
993 entries = listdir(join(nd), stat=True, skip=skip)
993 entries = listdir(join(nd), stat=True, skip=skip)
994 except OSError as inst:
994 except OSError as inst:
995 if inst.errno in (errno.EACCES, errno.ENOENT):
995 if inst.errno in (errno.EACCES, errno.ENOENT):
996 match.bad(
996 match.bad(
997 self.pathto(nd), encoding.strtolocal(inst.strerror)
997 self.pathto(nd), encoding.strtolocal(inst.strerror)
998 )
998 )
999 continue
999 continue
1000 raise
1000 raise
1001 for f, kind, st in entries:
1001 for f, kind, st in entries:
1002 # Some matchers may return files in the visitentries set,
1002 # Some matchers may return files in the visitentries set,
1003 # instead of 'this', if the matcher explicitly mentions them
1003 # instead of 'this', if the matcher explicitly mentions them
1004 # and is not an exactmatcher. This is acceptable; we do not
1004 # and is not an exactmatcher. This is acceptable; we do not
1005 # make any hard assumptions about file-or-directory below
1005 # make any hard assumptions about file-or-directory below
1006 # based on the presence of `f` in visitentries. If
1006 # based on the presence of `f` in visitentries. If
1007 # visitchildrenset returned a set, we can always skip the
1007 # visitchildrenset returned a set, we can always skip the
1008 # entries *not* in the set it provided regardless of whether
1008 # entries *not* in the set it provided regardless of whether
1009 # they're actually a file or a directory.
1009 # they're actually a file or a directory.
1010 if visitentries and f not in visitentries:
1010 if visitentries and f not in visitentries:
1011 continue
1011 continue
1012 if normalizefile:
1012 if normalizefile:
1013 # even though f might be a directory, we're only
1013 # even though f might be a directory, we're only
1014 # interested in comparing it to files currently in the
1014 # interested in comparing it to files currently in the
1015 # dmap -- therefore normalizefile is enough
1015 # dmap -- therefore normalizefile is enough
1016 nf = normalizefile(
1016 nf = normalizefile(
1017 nd and (nd + b"/" + f) or f, True, True
1017 nd and (nd + b"/" + f) or f, True, True
1018 )
1018 )
1019 else:
1019 else:
1020 nf = nd and (nd + b"/" + f) or f
1020 nf = nd and (nd + b"/" + f) or f
1021 if nf not in results:
1021 if nf not in results:
1022 if kind == dirkind:
1022 if kind == dirkind:
1023 if not ignore(nf):
1023 if not ignore(nf):
1024 if matchtdir:
1024 if matchtdir:
1025 matchtdir(nf)
1025 matchtdir(nf)
1026 wadd(nf)
1026 wadd(nf)
1027 if nf in dmap and (matchalways or matchfn(nf)):
1027 if nf in dmap and (matchalways or matchfn(nf)):
1028 results[nf] = None
1028 results[nf] = None
1029 elif kind == regkind or kind == lnkkind:
1029 elif kind == regkind or kind == lnkkind:
1030 if nf in dmap:
1030 if nf in dmap:
1031 if matchalways or matchfn(nf):
1031 if matchalways or matchfn(nf):
1032 results[nf] = st
1032 results[nf] = st
1033 elif (matchalways or matchfn(nf)) and not ignore(
1033 elif (matchalways or matchfn(nf)) and not ignore(
1034 nf
1034 nf
1035 ):
1035 ):
1036 # unknown file -- normalize if necessary
1036 # unknown file -- normalize if necessary
1037 if not alreadynormed:
1037 if not alreadynormed:
1038 nf = normalize(nf, False, True)
1038 nf = normalize(nf, False, True)
1039 results[nf] = st
1039 results[nf] = st
1040 elif nf in dmap and (matchalways or matchfn(nf)):
1040 elif nf in dmap and (matchalways or matchfn(nf)):
1041 results[nf] = None
1041 results[nf] = None
1042
1042
1043 for nd, d in work:
1043 for nd, d in work:
1044 # alreadynormed means that processwork doesn't have to do any
1044 # alreadynormed means that processwork doesn't have to do any
1045 # expensive directory normalization
1045 # expensive directory normalization
1046 alreadynormed = not normalize or nd == d
1046 alreadynormed = not normalize or nd == d
1047 traverse([d], alreadynormed)
1047 traverse([d], alreadynormed)
1048
1048
1049 for s in subrepos:
1049 for s in subrepos:
1050 del results[s]
1050 del results[s]
1051 del results[b'.hg']
1051 del results[b'.hg']
1052
1052
1053 # step 3: visit remaining files from dmap
1053 # step 3: visit remaining files from dmap
1054 if not skipstep3 and not exact:
1054 if not skipstep3 and not exact:
1055 # If a dmap file is not in results yet, it was either
1055 # If a dmap file is not in results yet, it was either
1056 # a) not matching matchfn b) ignored, c) missing, or d) under a
1056 # a) not matching matchfn b) ignored, c) missing, or d) under a
1057 # symlink directory.
1057 # symlink directory.
1058 if not results and matchalways:
1058 if not results and matchalways:
1059 visit = [f for f in dmap]
1059 visit = [f for f in dmap]
1060 else:
1060 else:
1061 visit = [f for f in dmap if f not in results and matchfn(f)]
1061 visit = [f for f in dmap if f not in results and matchfn(f)]
1062 visit.sort()
1062 visit.sort()
1063
1063
1064 if unknown:
1064 if unknown:
1065 # unknown == True means we walked all dirs under the roots
1065 # unknown == True means we walked all dirs under the roots
1066 # that wasn't ignored, and everything that matched was stat'ed
1066 # that wasn't ignored, and everything that matched was stat'ed
1067 # and is already in results.
1067 # and is already in results.
1068 # The rest must thus be ignored or under a symlink.
1068 # The rest must thus be ignored or under a symlink.
1069 audit_path = pathutil.pathauditor(self._root, cached=True)
1069 audit_path = pathutil.pathauditor(self._root, cached=True)
1070
1070
1071 for nf in iter(visit):
1071 for nf in iter(visit):
1072 # If a stat for the same file was already added with a
1072 # If a stat for the same file was already added with a
1073 # different case, don't add one for this, since that would
1073 # different case, don't add one for this, since that would
1074 # make it appear as if the file exists under both names
1074 # make it appear as if the file exists under both names
1075 # on disk.
1075 # on disk.
1076 if (
1076 if (
1077 normalizefile
1077 normalizefile
1078 and normalizefile(nf, True, True) in results
1078 and normalizefile(nf, True, True) in results
1079 ):
1079 ):
1080 results[nf] = None
1080 results[nf] = None
1081 # Report ignored items in the dmap as long as they are not
1081 # Report ignored items in the dmap as long as they are not
1082 # under a symlink directory.
1082 # under a symlink directory.
1083 elif audit_path.check(nf):
1083 elif audit_path.check(nf):
1084 try:
1084 try:
1085 results[nf] = lstat(join(nf))
1085 results[nf] = lstat(join(nf))
1086 # file was just ignored, no links, and exists
1086 # file was just ignored, no links, and exists
1087 except OSError:
1087 except OSError:
1088 # file doesn't exist
1088 # file doesn't exist
1089 results[nf] = None
1089 results[nf] = None
1090 else:
1090 else:
1091 # It's either missing or under a symlink directory
1091 # It's either missing or under a symlink directory
1092 # which we in this case report as missing
1092 # which we in this case report as missing
1093 results[nf] = None
1093 results[nf] = None
1094 else:
1094 else:
1095 # We may not have walked the full directory tree above,
1095 # We may not have walked the full directory tree above,
1096 # so stat and check everything we missed.
1096 # so stat and check everything we missed.
1097 iv = iter(visit)
1097 iv = iter(visit)
1098 for st in util.statfiles([join(i) for i in visit]):
1098 for st in util.statfiles([join(i) for i in visit]):
1099 results[next(iv)] = st
1099 results[next(iv)] = st
1100 return results
1100 return results
1101
1101
1102 def _rust_status(self, matcher, list_clean, list_ignored, list_unknown):
1102 def _rust_status(self, matcher, list_clean, list_ignored, list_unknown):
1103 # Force Rayon (Rust parallelism library) to respect the number of
1103 # Force Rayon (Rust parallelism library) to respect the number of
1104 # workers. This is a temporary workaround until Rust code knows
1104 # workers. This is a temporary workaround until Rust code knows
1105 # how to read the config file.
1105 # how to read the config file.
1106 numcpus = self._ui.configint(b"worker", b"numcpus")
1106 numcpus = self._ui.configint(b"worker", b"numcpus")
1107 if numcpus is not None:
1107 if numcpus is not None:
1108 encoding.environ.setdefault(b'RAYON_NUM_THREADS', b'%d' % numcpus)
1108 encoding.environ.setdefault(b'RAYON_NUM_THREADS', b'%d' % numcpus)
1109
1109
1110 workers_enabled = self._ui.configbool(b"worker", b"enabled", True)
1110 workers_enabled = self._ui.configbool(b"worker", b"enabled", True)
1111 if not workers_enabled:
1111 if not workers_enabled:
1112 encoding.environ[b"RAYON_NUM_THREADS"] = b"1"
1112 encoding.environ[b"RAYON_NUM_THREADS"] = b"1"
1113
1113
1114 (
1114 (
1115 lookup,
1115 lookup,
1116 modified,
1116 modified,
1117 added,
1117 added,
1118 removed,
1118 removed,
1119 deleted,
1119 deleted,
1120 clean,
1120 clean,
1121 ignored,
1121 ignored,
1122 unknown,
1122 unknown,
1123 warnings,
1123 warnings,
1124 bad,
1124 bad,
1125 traversed,
1125 traversed,
1126 ) = rustmod.status(
1126 ) = rustmod.status(
1127 self._map._rustmap,
1127 self._map._rustmap,
1128 matcher,
1128 matcher,
1129 self._rootdir,
1129 self._rootdir,
1130 self._ignorefiles(),
1130 self._ignorefiles(),
1131 self._checkexec,
1131 self._checkexec,
1132 self._lastnormaltime,
1132 self._lastnormaltime,
1133 bool(list_clean),
1133 bool(list_clean),
1134 bool(list_ignored),
1134 bool(list_ignored),
1135 bool(list_unknown),
1135 bool(list_unknown),
1136 bool(matcher.traversedir),
1136 bool(matcher.traversedir),
1137 )
1137 )
1138
1138
1139 if matcher.traversedir:
1139 if matcher.traversedir:
1140 for dir in traversed:
1140 for dir in traversed:
1141 matcher.traversedir(dir)
1141 matcher.traversedir(dir)
1142
1142
1143 if self._ui.warn:
1143 if self._ui.warn:
1144 for item in warnings:
1144 for item in warnings:
1145 if isinstance(item, tuple):
1145 if isinstance(item, tuple):
1146 file_path, syntax = item
1146 file_path, syntax = item
1147 msg = _(b"%s: ignoring invalid syntax '%s'\n") % (
1147 msg = _(b"%s: ignoring invalid syntax '%s'\n") % (
1148 file_path,
1148 file_path,
1149 syntax,
1149 syntax,
1150 )
1150 )
1151 self._ui.warn(msg)
1151 self._ui.warn(msg)
1152 else:
1152 else:
1153 msg = _(b"skipping unreadable pattern file '%s': %s\n")
1153 msg = _(b"skipping unreadable pattern file '%s': %s\n")
1154 self._ui.warn(
1154 self._ui.warn(
1155 msg
1155 msg
1156 % (
1156 % (
1157 pathutil.canonpath(
1157 pathutil.canonpath(
1158 self._rootdir, self._rootdir, item
1158 self._rootdir, self._rootdir, item
1159 ),
1159 ),
1160 b"No such file or directory",
1160 b"No such file or directory",
1161 )
1161 )
1162 )
1162 )
1163
1163
1164 for (fn, message) in bad:
1164 for (fn, message) in bad:
1165 matcher.bad(fn, encoding.strtolocal(message))
1165 matcher.bad(fn, encoding.strtolocal(message))
1166
1166
1167 status = scmutil.status(
1167 status = scmutil.status(
1168 modified=modified,
1168 modified=modified,
1169 added=added,
1169 added=added,
1170 removed=removed,
1170 removed=removed,
1171 deleted=deleted,
1171 deleted=deleted,
1172 unknown=unknown,
1172 unknown=unknown,
1173 ignored=ignored,
1173 ignored=ignored,
1174 clean=clean,
1174 clean=clean,
1175 )
1175 )
1176 return (lookup, status)
1176 return (lookup, status)
1177
1177
1178 def status(self, match, subrepos, ignored, clean, unknown):
1178 def status(self, match, subrepos, ignored, clean, unknown):
1179 """Determine the status of the working copy relative to the
1179 """Determine the status of the working copy relative to the
1180 dirstate and return a pair of (unsure, status), where status is of type
1180 dirstate and return a pair of (unsure, status), where status is of type
1181 scmutil.status and:
1181 scmutil.status and:
1182
1182
1183 unsure:
1183 unsure:
1184 files that might have been modified since the dirstate was
1184 files that might have been modified since the dirstate was
1185 written, but need to be read to be sure (size is the same
1185 written, but need to be read to be sure (size is the same
1186 but mtime differs)
1186 but mtime differs)
1187 status.modified:
1187 status.modified:
1188 files that have definitely been modified since the dirstate
1188 files that have definitely been modified since the dirstate
1189 was written (different size or mode)
1189 was written (different size or mode)
1190 status.clean:
1190 status.clean:
1191 files that have definitely not been modified since the
1191 files that have definitely not been modified since the
1192 dirstate was written
1192 dirstate was written
1193 """
1193 """
1194 listignored, listclean, listunknown = ignored, clean, unknown
1194 listignored, listclean, listunknown = ignored, clean, unknown
1195 lookup, modified, added, unknown, ignored = [], [], [], [], []
1195 lookup, modified, added, unknown, ignored = [], [], [], [], []
1196 removed, deleted, clean = [], [], []
1196 removed, deleted, clean = [], [], []
1197
1197
1198 dmap = self._map
1198 dmap = self._map
1199 dmap.preload()
1199 dmap.preload()
1200
1200
1201 use_rust = True
1201 use_rust = True
1202
1202
1203 allowed_matchers = (
1203 allowed_matchers = (
1204 matchmod.alwaysmatcher,
1204 matchmod.alwaysmatcher,
1205 matchmod.exactmatcher,
1205 matchmod.exactmatcher,
1206 matchmod.includematcher,
1206 matchmod.includematcher,
1207 )
1207 )
1208
1208
1209 if rustmod is None:
1209 if rustmod is None:
1210 use_rust = False
1210 use_rust = False
1211 elif self._checkcase:
1211 elif self._checkcase:
1212 # Case-insensitive filesystems are not handled yet
1212 # Case-insensitive filesystems are not handled yet
1213 use_rust = False
1213 use_rust = False
1214 elif subrepos:
1214 elif subrepos:
1215 use_rust = False
1215 use_rust = False
1216 elif sparse.enabled:
1216 elif sparse.enabled:
1217 use_rust = False
1217 use_rust = False
1218 elif not isinstance(match, allowed_matchers):
1218 elif not isinstance(match, allowed_matchers):
1219 # Some matchers have yet to be implemented
1219 # Some matchers have yet to be implemented
1220 use_rust = False
1220 use_rust = False
1221
1221
1222 if use_rust:
1222 if use_rust:
1223 try:
1223 try:
1224 return self._rust_status(
1224 return self._rust_status(
1225 match, listclean, listignored, listunknown
1225 match, listclean, listignored, listunknown
1226 )
1226 )
1227 except rustmod.FallbackError:
1227 except rustmod.FallbackError:
1228 pass
1228 pass
1229
1229
1230 def noop(f):
1230 def noop(f):
1231 pass
1231 pass
1232
1232
1233 dcontains = dmap.__contains__
1233 dcontains = dmap.__contains__
1234 dget = dmap.__getitem__
1234 dget = dmap.__getitem__
1235 ladd = lookup.append # aka "unsure"
1235 ladd = lookup.append # aka "unsure"
1236 madd = modified.append
1236 madd = modified.append
1237 aadd = added.append
1237 aadd = added.append
1238 uadd = unknown.append if listunknown else noop
1238 uadd = unknown.append if listunknown else noop
1239 iadd = ignored.append if listignored else noop
1239 iadd = ignored.append if listignored else noop
1240 radd = removed.append
1240 radd = removed.append
1241 dadd = deleted.append
1241 dadd = deleted.append
1242 cadd = clean.append if listclean else noop
1242 cadd = clean.append if listclean else noop
1243 mexact = match.exact
1243 mexact = match.exact
1244 dirignore = self._dirignore
1244 dirignore = self._dirignore
1245 checkexec = self._checkexec
1245 checkexec = self._checkexec
1246 copymap = self._map.copymap
1246 copymap = self._map.copymap
1247 lastnormaltime = self._lastnormaltime
1247 lastnormaltime = self._lastnormaltime
1248
1248
1249 # We need to do full walks when either
1249 # We need to do full walks when either
1250 # - we're listing all clean files, or
1250 # - we're listing all clean files, or
1251 # - match.traversedir does something, because match.traversedir should
1251 # - match.traversedir does something, because match.traversedir should
1252 # be called for every dir in the working dir
1252 # be called for every dir in the working dir
1253 full = listclean or match.traversedir is not None
1253 full = listclean or match.traversedir is not None
1254 for fn, st in pycompat.iteritems(
1254 for fn, st in pycompat.iteritems(
1255 self.walk(match, subrepos, listunknown, listignored, full=full)
1255 self.walk(match, subrepos, listunknown, listignored, full=full)
1256 ):
1256 ):
1257 if not dcontains(fn):
1257 if not dcontains(fn):
1258 if (listignored or mexact(fn)) and dirignore(fn):
1258 if (listignored or mexact(fn)) and dirignore(fn):
1259 if listignored:
1259 if listignored:
1260 iadd(fn)
1260 iadd(fn)
1261 else:
1261 else:
1262 uadd(fn)
1262 uadd(fn)
1263 continue
1263 continue
1264
1264
1265 # This is equivalent to 'state, mode, size, time = dmap[fn]' but not
1265 # This is equivalent to 'state, mode, size, time = dmap[fn]' but not
1266 # written like that for performance reasons. dmap[fn] is not a
1266 # written like that for performance reasons. dmap[fn] is not a
1267 # Python tuple in compiled builds. The CPython UNPACK_SEQUENCE
1267 # Python tuple in compiled builds. The CPython UNPACK_SEQUENCE
1268 # opcode has fast paths when the value to be unpacked is a tuple or
1268 # opcode has fast paths when the value to be unpacked is a tuple or
1269 # a list, but falls back to creating a full-fledged iterator in
1269 # a list, but falls back to creating a full-fledged iterator in
1270 # general. That is much slower than simply accessing and storing the
1270 # general. That is much slower than simply accessing and storing the
1271 # tuple members one by one.
1271 # tuple members one by one.
1272 t = dget(fn)
1272 t = dget(fn)
1273 state = t[0]
1273 state = t[0]
1274 mode = t[1]
1274 mode = t[1]
1275 size = t[2]
1275 size = t[2]
1276 time = t[3]
1276 time = t[3]
1277
1277
1278 if not st and state in b"nma":
1278 if not st and state in b"nma":
1279 dadd(fn)
1279 dadd(fn)
1280 elif state == b'n':
1280 elif state == b'n':
1281 if (
1281 if (
1282 size >= 0
1282 size >= 0
1283 and (
1283 and (
1284 (size != st.st_size and size != st.st_size & _rangemask)
1284 (size != st.st_size and size != st.st_size & _rangemask)
1285 or ((mode ^ st.st_mode) & 0o100 and checkexec)
1285 or ((mode ^ st.st_mode) & 0o100 and checkexec)
1286 )
1286 )
1287 or size == -2 # other parent
1287 or size == -2 # other parent
1288 or fn in copymap
1288 or fn in copymap
1289 ):
1289 ):
1290 if stat.S_ISLNK(st.st_mode) and size != st.st_size:
1290 if stat.S_ISLNK(st.st_mode) and size != st.st_size:
1291 # issue6456: Size returned may be longer due to
1291 # issue6456: Size returned may be longer due to
1292 # encryption on EXT-4 fscrypt, undecided.
1292 # encryption on EXT-4 fscrypt, undecided.
1293 ladd(fn)
1293 ladd(fn)
1294 else:
1294 else:
1295 madd(fn)
1295 madd(fn)
1296 elif (
1296 elif (
1297 time != st[stat.ST_MTIME]
1297 time != st[stat.ST_MTIME]
1298 and time != st[stat.ST_MTIME] & _rangemask
1298 and time != st[stat.ST_MTIME] & _rangemask
1299 ):
1299 ):
1300 ladd(fn)
1300 ladd(fn)
1301 elif st[stat.ST_MTIME] == lastnormaltime:
1301 elif st[stat.ST_MTIME] == lastnormaltime:
1302 # fn may have just been marked as normal and it may have
1302 # fn may have just been marked as normal and it may have
1303 # changed in the same second without changing its size.
1303 # changed in the same second without changing its size.
1304 # This can happen if we quickly do multiple commits.
1304 # This can happen if we quickly do multiple commits.
1305 # Force lookup, so we don't miss such a racy file change.
1305 # Force lookup, so we don't miss such a racy file change.
1306 ladd(fn)
1306 ladd(fn)
1307 elif listclean:
1307 elif listclean:
1308 cadd(fn)
1308 cadd(fn)
1309 elif state == b'm':
1309 elif state == b'm':
1310 madd(fn)
1310 madd(fn)
1311 elif state == b'a':
1311 elif state == b'a':
1312 aadd(fn)
1312 aadd(fn)
1313 elif state == b'r':
1313 elif state == b'r':
1314 radd(fn)
1314 radd(fn)
1315 status = scmutil.status(
1315 status = scmutil.status(
1316 modified, added, removed, deleted, unknown, ignored, clean
1316 modified, added, removed, deleted, unknown, ignored, clean
1317 )
1317 )
1318 return (lookup, status)
1318 return (lookup, status)
1319
1319
1320 def matches(self, match):
1320 def matches(self, match):
1321 """
1321 """
1322 return files in the dirstate (in whatever state) filtered by match
1322 return files in the dirstate (in whatever state) filtered by match
1323 """
1323 """
1324 dmap = self._map
1324 dmap = self._map
1325 if rustmod is not None:
1325 if rustmod is not None:
1326 dmap = self._map._rustmap
1326 dmap = self._map._rustmap
1327
1327
1328 if match.always():
1328 if match.always():
1329 return dmap.keys()
1329 return dmap.keys()
1330 files = match.files()
1330 files = match.files()
1331 if match.isexact():
1331 if match.isexact():
1332 # fast path -- filter the other way around, since typically files is
1332 # fast path -- filter the other way around, since typically files is
1333 # much smaller than dmap
1333 # much smaller than dmap
1334 return [f for f in files if f in dmap]
1334 return [f for f in files if f in dmap]
1335 if match.prefix() and all(fn in dmap for fn in files):
1335 if match.prefix() and all(fn in dmap for fn in files):
1336 # fast path -- all the values are known to be files, so just return
1336 # fast path -- all the values are known to be files, so just return
1337 # that
1337 # that
1338 return list(files)
1338 return list(files)
1339 return [f for f in dmap if match(f)]
1339 return [f for f in dmap if match(f)]
1340
1340
1341 def _actualfilename(self, tr):
1341 def _actualfilename(self, tr):
1342 if tr:
1342 if tr:
1343 return self._pendingfilename
1343 return self._pendingfilename
1344 else:
1344 else:
1345 return self._filename
1345 return self._filename
1346
1346
1347 def savebackup(self, tr, backupname):
1347 def savebackup(self, tr, backupname):
1348 '''Save current dirstate into backup file'''
1348 '''Save current dirstate into backup file'''
1349 filename = self._actualfilename(tr)
1349 filename = self._actualfilename(tr)
1350 assert backupname != filename
1350 assert backupname != filename
1351
1351
1352 # use '_writedirstate' instead of 'write' to write changes certainly,
1352 # use '_writedirstate' instead of 'write' to write changes certainly,
1353 # because the latter omits writing out if transaction is running.
1353 # because the latter omits writing out if transaction is running.
1354 # output file will be used to create backup of dirstate at this point.
1354 # output file will be used to create backup of dirstate at this point.
1355 if self._dirty or not self._opener.exists(filename):
1355 if self._dirty or not self._opener.exists(filename):
1356 self._writedirstate(
1356 self._writedirstate(
1357 self._opener(filename, b"w", atomictemp=True, checkambig=True)
1357 self._opener(filename, b"w", atomictemp=True, checkambig=True)
1358 )
1358 )
1359
1359
1360 if tr:
1360 if tr:
1361 # ensure that subsequent tr.writepending returns True for
1361 # ensure that subsequent tr.writepending returns True for
1362 # changes written out above, even if dirstate is never
1362 # changes written out above, even if dirstate is never
1363 # changed after this
1363 # changed after this
1364 tr.addfilegenerator(
1364 tr.addfilegenerator(
1365 b'dirstate',
1365 b'dirstate',
1366 (self._filename,),
1366 (self._filename,),
1367 self._writedirstate,
1367 self._writedirstate,
1368 location=b'plain',
1368 location=b'plain',
1369 )
1369 )
1370
1370
1371 # ensure that pending file written above is unlinked at
1371 # ensure that pending file written above is unlinked at
1372 # failure, even if tr.writepending isn't invoked until the
1372 # failure, even if tr.writepending isn't invoked until the
1373 # end of this transaction
1373 # end of this transaction
1374 tr.registertmp(filename, location=b'plain')
1374 tr.registertmp(filename, location=b'plain')
1375
1375
1376 self._opener.tryunlink(backupname)
1376 self._opener.tryunlink(backupname)
1377 # hardlink backup is okay because _writedirstate is always called
1377 # hardlink backup is okay because _writedirstate is always called
1378 # with an "atomictemp=True" file.
1378 # with an "atomictemp=True" file.
1379 util.copyfile(
1379 util.copyfile(
1380 self._opener.join(filename),
1380 self._opener.join(filename),
1381 self._opener.join(backupname),
1381 self._opener.join(backupname),
1382 hardlink=True,
1382 hardlink=True,
1383 )
1383 )
1384
1384
1385 def restorebackup(self, tr, backupname):
1385 def restorebackup(self, tr, backupname):
1386 '''Restore dirstate by backup file'''
1386 '''Restore dirstate by backup file'''
1387 # this "invalidate()" prevents "wlock.release()" from writing
1387 # this "invalidate()" prevents "wlock.release()" from writing
1388 # changes of dirstate out after restoring from backup file
1388 # changes of dirstate out after restoring from backup file
1389 self.invalidate()
1389 self.invalidate()
1390 filename = self._actualfilename(tr)
1390 filename = self._actualfilename(tr)
1391 o = self._opener
1391 o = self._opener
1392 if util.samefile(o.join(backupname), o.join(filename)):
1392 if util.samefile(o.join(backupname), o.join(filename)):
1393 o.unlink(backupname)
1393 o.unlink(backupname)
1394 else:
1394 else:
1395 o.rename(backupname, filename, checkambig=True)
1395 o.rename(backupname, filename, checkambig=True)
1396
1396
1397 def clearbackup(self, tr, backupname):
1397 def clearbackup(self, tr, backupname):
1398 '''Clear backup file'''
1398 '''Clear backup file'''
1399 self._opener.unlink(backupname)
1399 self._opener.unlink(backupname)
1400
1400
1401
1401
1402 class dirstatemap(object):
1402 class dirstatemap(object):
1403 """Map encapsulating the dirstate's contents.
1403 """Map encapsulating the dirstate's contents.
1404
1404
1405 The dirstate contains the following state:
1405 The dirstate contains the following state:
1406
1406
1407 - `identity` is the identity of the dirstate file, which can be used to
1407 - `identity` is the identity of the dirstate file, which can be used to
1408 detect when changes have occurred to the dirstate file.
1408 detect when changes have occurred to the dirstate file.
1409
1409
1410 - `parents` is a pair containing the parents of the working copy. The
1410 - `parents` is a pair containing the parents of the working copy. The
1411 parents are updated by calling `setparents`.
1411 parents are updated by calling `setparents`.
1412
1412
1413 - the state map maps filenames to tuples of (state, mode, size, mtime),
1413 - the state map maps filenames to tuples of (state, mode, size, mtime),
1414 where state is a single character representing 'normal', 'added',
1414 where state is a single character representing 'normal', 'added',
1415 'removed', or 'merged'. It is read by treating the dirstate as a
1415 'removed', or 'merged'. It is read by treating the dirstate as a
1416 dict. File state is updated by calling the `addfile`, `removefile` and
1416 dict. File state is updated by calling the `addfile`, `removefile` and
1417 `dropfile` methods.
1417 `dropfile` methods.
1418
1418
1419 - `copymap` maps destination filenames to their source filename.
1419 - `copymap` maps destination filenames to their source filename.
1420
1420
1421 The dirstate also provides the following views onto the state:
1421 The dirstate also provides the following views onto the state:
1422
1422
1423 - `nonnormalset` is a set of the filenames that have state other
1423 - `nonnormalset` is a set of the filenames that have state other
1424 than 'normal', or are normal but have an mtime of -1 ('normallookup').
1424 than 'normal', or are normal but have an mtime of -1 ('normallookup').
1425
1425
1426 - `otherparentset` is a set of the filenames that are marked as coming
1426 - `otherparentset` is a set of the filenames that are marked as coming
1427 from the second parent when the dirstate is currently being merged.
1427 from the second parent when the dirstate is currently being merged.
1428
1428
1429 - `filefoldmap` is a dict mapping normalized filenames to the denormalized
1429 - `filefoldmap` is a dict mapping normalized filenames to the denormalized
1430 form that they appear as in the dirstate.
1430 form that they appear as in the dirstate.
1431
1431
1432 - `dirfoldmap` is a dict mapping normalized directory names to the
1432 - `dirfoldmap` is a dict mapping normalized directory names to the
1433 denormalized form that they appear as in the dirstate.
1433 denormalized form that they appear as in the dirstate.
1434 """
1434 """
1435
1435
1436 def __init__(self, ui, opener, root, nodeconstants):
1436 def __init__(self, ui, opener, root, nodeconstants):
1437 self._ui = ui
1437 self._ui = ui
1438 self._opener = opener
1438 self._opener = opener
1439 self._root = root
1439 self._root = root
1440 self._filename = b'dirstate'
1440 self._filename = b'dirstate'
1441 self._nodelen = 20
1441 self._nodelen = 20
1442 self._nodeconstants = nodeconstants
1442 self._nodeconstants = nodeconstants
1443
1443
1444 self._parents = None
1444 self._parents = None
1445 self._dirtyparents = False
1445 self._dirtyparents = False
1446
1446
1447 # for consistent view between _pl() and _read() invocations
1447 # for consistent view between _pl() and _read() invocations
1448 self._pendingmode = None
1448 self._pendingmode = None
1449
1449
1450 @propertycache
1450 @propertycache
1451 def _map(self):
1451 def _map(self):
1452 self._map = {}
1452 self._map = {}
1453 self.read()
1453 self.read()
1454 return self._map
1454 return self._map
1455
1455
1456 @propertycache
1456 @propertycache
1457 def copymap(self):
1457 def copymap(self):
1458 self.copymap = {}
1458 self.copymap = {}
1459 self._map
1459 self._map
1460 return self.copymap
1460 return self.copymap
1461
1461
1462 def clear(self):
1462 def clear(self):
1463 self._map.clear()
1463 self._map.clear()
1464 self.copymap.clear()
1464 self.copymap.clear()
1465 self.setparents(self._nodeconstants.nullid, self._nodeconstants.nullid)
1465 self.setparents(self._nodeconstants.nullid, self._nodeconstants.nullid)
1466 util.clearcachedproperty(self, b"_dirs")
1466 util.clearcachedproperty(self, b"_dirs")
1467 util.clearcachedproperty(self, b"_alldirs")
1467 util.clearcachedproperty(self, b"_alldirs")
1468 util.clearcachedproperty(self, b"filefoldmap")
1468 util.clearcachedproperty(self, b"filefoldmap")
1469 util.clearcachedproperty(self, b"dirfoldmap")
1469 util.clearcachedproperty(self, b"dirfoldmap")
1470 util.clearcachedproperty(self, b"nonnormalset")
1470 util.clearcachedproperty(self, b"nonnormalset")
1471 util.clearcachedproperty(self, b"otherparentset")
1471 util.clearcachedproperty(self, b"otherparentset")
1472
1472
1473 def items(self):
1473 def items(self):
1474 return pycompat.iteritems(self._map)
1474 return pycompat.iteritems(self._map)
1475
1475
1476 # forward for python2,3 compat
1476 # forward for python2,3 compat
1477 iteritems = items
1477 iteritems = items
1478
1478
1479 def __len__(self):
1479 def __len__(self):
1480 return len(self._map)
1480 return len(self._map)
1481
1481
1482 def __iter__(self):
1482 def __iter__(self):
1483 return iter(self._map)
1483 return iter(self._map)
1484
1484
1485 def get(self, key, default=None):
1485 def get(self, key, default=None):
1486 return self._map.get(key, default)
1486 return self._map.get(key, default)
1487
1487
1488 def __contains__(self, key):
1488 def __contains__(self, key):
1489 return key in self._map
1489 return key in self._map
1490
1490
1491 def __getitem__(self, key):
1491 def __getitem__(self, key):
1492 return self._map[key]
1492 return self._map[key]
1493
1493
1494 def keys(self):
1494 def keys(self):
1495 return self._map.keys()
1495 return self._map.keys()
1496
1496
1497 def preload(self):
1497 def preload(self):
1498 """Loads the underlying data, if it's not already loaded"""
1498 """Loads the underlying data, if it's not already loaded"""
1499 self._map
1499 self._map
1500
1500
1501 def addfile(self, f, oldstate, state, mode, size, mtime):
1501 def addfile(self, f, oldstate, state, mode, size, mtime):
1502 """Add a tracked file to the dirstate."""
1502 """Add a tracked file to the dirstate."""
1503 if oldstate in b"?r" and "_dirs" in self.__dict__:
1503 if oldstate in b"?r" and "_dirs" in self.__dict__:
1504 self._dirs.addpath(f)
1504 self._dirs.addpath(f)
1505 if oldstate == b"?" and "_alldirs" in self.__dict__:
1505 if oldstate == b"?" and "_alldirs" in self.__dict__:
1506 self._alldirs.addpath(f)
1506 self._alldirs.addpath(f)
1507 self._map[f] = dirstatetuple(state, mode, size, mtime)
1507 self._map[f] = dirstatetuple(state, mode, size, mtime)
1508 if state != b'n' or mtime == -1:
1508 if state != b'n' or mtime == -1:
1509 self.nonnormalset.add(f)
1509 self.nonnormalset.add(f)
1510 if size == -2:
1510 if size == -2:
1511 self.otherparentset.add(f)
1511 self.otherparentset.add(f)
1512
1512
1513 def removefile(self, f, oldstate, size):
1513 def removefile(self, f, oldstate, size):
1514 """
1514 """
1515 Mark a file as removed in the dirstate.
1515 Mark a file as removed in the dirstate.
1516
1516
1517 The `size` parameter is used to store sentinel values that indicate
1517 The `size` parameter is used to store sentinel values that indicate
1518 the file's previous state. In the future, we should refactor this
1518 the file's previous state. In the future, we should refactor this
1519 to be more explicit about what that state is.
1519 to be more explicit about what that state is.
1520 """
1520 """
1521 if oldstate not in b"?r" and "_dirs" in self.__dict__:
1521 if oldstate not in b"?r" and "_dirs" in self.__dict__:
1522 self._dirs.delpath(f)
1522 self._dirs.delpath(f)
1523 if oldstate == b"?" and "_alldirs" in self.__dict__:
1523 if oldstate == b"?" and "_alldirs" in self.__dict__:
1524 self._alldirs.addpath(f)
1524 self._alldirs.addpath(f)
1525 if "filefoldmap" in self.__dict__:
1525 if "filefoldmap" in self.__dict__:
1526 normed = util.normcase(f)
1526 normed = util.normcase(f)
1527 self.filefoldmap.pop(normed, None)
1527 self.filefoldmap.pop(normed, None)
1528 self._map[f] = dirstatetuple(b'r', 0, size, 0)
1528 self._map[f] = dirstatetuple(b'r', 0, size, 0)
1529 self.nonnormalset.add(f)
1529 self.nonnormalset.add(f)
1530
1530
1531 def dropfile(self, f, oldstate):
1531 def dropfile(self, f, oldstate):
1532 """
1532 """
1533 Remove a file from the dirstate. Returns True if the file was
1533 Remove a file from the dirstate. Returns True if the file was
1534 previously recorded.
1534 previously recorded.
1535 """
1535 """
1536 exists = self._map.pop(f, None) is not None
1536 exists = self._map.pop(f, None) is not None
1537 if exists:
1537 if exists:
1538 if oldstate != b"r" and "_dirs" in self.__dict__:
1538 if oldstate != b"r" and "_dirs" in self.__dict__:
1539 self._dirs.delpath(f)
1539 self._dirs.delpath(f)
1540 if "_alldirs" in self.__dict__:
1540 if "_alldirs" in self.__dict__:
1541 self._alldirs.delpath(f)
1541 self._alldirs.delpath(f)
1542 if "filefoldmap" in self.__dict__:
1542 if "filefoldmap" in self.__dict__:
1543 normed = util.normcase(f)
1543 normed = util.normcase(f)
1544 self.filefoldmap.pop(normed, None)
1544 self.filefoldmap.pop(normed, None)
1545 self.nonnormalset.discard(f)
1545 self.nonnormalset.discard(f)
1546 return exists
1546 return exists
1547
1547
1548 def clearambiguoustimes(self, files, now):
1548 def clearambiguoustimes(self, files, now):
1549 for f in files:
1549 for f in files:
1550 e = self.get(f)
1550 e = self.get(f)
1551 if e is not None and e[0] == b'n' and e[3] == now:
1551 if e is not None and e[0] == b'n' and e[3] == now:
1552 self._map[f] = dirstatetuple(e[0], e[1], e[2], -1)
1552 self._map[f] = dirstatetuple(e[0], e[1], e[2], -1)
1553 self.nonnormalset.add(f)
1553 self.nonnormalset.add(f)
1554
1554
1555 def nonnormalentries(self):
1555 def nonnormalentries(self):
1556 '''Compute the nonnormal dirstate entries from the dmap'''
1556 '''Compute the nonnormal dirstate entries from the dmap'''
1557 try:
1557 try:
1558 return parsers.nonnormalotherparententries(self._map)
1558 return parsers.nonnormalotherparententries(self._map)
1559 except AttributeError:
1559 except AttributeError:
1560 nonnorm = set()
1560 nonnorm = set()
1561 otherparent = set()
1561 otherparent = set()
1562 for fname, e in pycompat.iteritems(self._map):
1562 for fname, e in pycompat.iteritems(self._map):
1563 if e[0] != b'n' or e[3] == -1:
1563 if e[0] != b'n' or e[3] == -1:
1564 nonnorm.add(fname)
1564 nonnorm.add(fname)
1565 if e[0] == b'n' and e[2] == -2:
1565 if e[0] == b'n' and e[2] == -2:
1566 otherparent.add(fname)
1566 otherparent.add(fname)
1567 return nonnorm, otherparent
1567 return nonnorm, otherparent
1568
1568
1569 @propertycache
1569 @propertycache
1570 def filefoldmap(self):
1570 def filefoldmap(self):
1571 """Returns a dictionary mapping normalized case paths to their
1571 """Returns a dictionary mapping normalized case paths to their
1572 non-normalized versions.
1572 non-normalized versions.
1573 """
1573 """
1574 try:
1574 try:
1575 makefilefoldmap = parsers.make_file_foldmap
1575 makefilefoldmap = parsers.make_file_foldmap
1576 except AttributeError:
1576 except AttributeError:
1577 pass
1577 pass
1578 else:
1578 else:
1579 return makefilefoldmap(
1579 return makefilefoldmap(
1580 self._map, util.normcasespec, util.normcasefallback
1580 self._map, util.normcasespec, util.normcasefallback
1581 )
1581 )
1582
1582
1583 f = {}
1583 f = {}
1584 normcase = util.normcase
1584 normcase = util.normcase
1585 for name, s in pycompat.iteritems(self._map):
1585 for name, s in pycompat.iteritems(self._map):
1586 if s[0] != b'r':
1586 if s[0] != b'r':
1587 f[normcase(name)] = name
1587 f[normcase(name)] = name
1588 f[b'.'] = b'.' # prevents useless util.fspath() invocation
1588 f[b'.'] = b'.' # prevents useless util.fspath() invocation
1589 return f
1589 return f
1590
1590
1591 def hastrackeddir(self, d):
1591 def hastrackeddir(self, d):
1592 """
1592 """
1593 Returns True if the dirstate contains a tracked (not removed) file
1593 Returns True if the dirstate contains a tracked (not removed) file
1594 in this directory.
1594 in this directory.
1595 """
1595 """
1596 return d in self._dirs
1596 return d in self._dirs
1597
1597
1598 def hasdir(self, d):
1598 def hasdir(self, d):
1599 """
1599 """
1600 Returns True if the dirstate contains a file (tracked or removed)
1600 Returns True if the dirstate contains a file (tracked or removed)
1601 in this directory.
1601 in this directory.
1602 """
1602 """
1603 return d in self._alldirs
1603 return d in self._alldirs
1604
1604
1605 @propertycache
1605 @propertycache
1606 def _dirs(self):
1606 def _dirs(self):
1607 return pathutil.dirs(self._map, b'r')
1607 return pathutil.dirs(self._map, b'r')
1608
1608
1609 @propertycache
1609 @propertycache
1610 def _alldirs(self):
1610 def _alldirs(self):
1611 return pathutil.dirs(self._map)
1611 return pathutil.dirs(self._map)
1612
1612
1613 def _opendirstatefile(self):
1613 def _opendirstatefile(self):
1614 fp, mode = txnutil.trypending(self._root, self._opener, self._filename)
1614 fp, mode = txnutil.trypending(self._root, self._opener, self._filename)
1615 if self._pendingmode is not None and self._pendingmode != mode:
1615 if self._pendingmode is not None and self._pendingmode != mode:
1616 fp.close()
1616 fp.close()
1617 raise error.Abort(
1617 raise error.Abort(
1618 _(b'working directory state may be changed parallelly')
1618 _(b'working directory state may be changed parallelly')
1619 )
1619 )
1620 self._pendingmode = mode
1620 self._pendingmode = mode
1621 return fp
1621 return fp
1622
1622
1623 def parents(self):
1623 def parents(self):
1624 if not self._parents:
1624 if not self._parents:
1625 try:
1625 try:
1626 fp = self._opendirstatefile()
1626 fp = self._opendirstatefile()
1627 st = fp.read(2 * self._nodelen)
1627 st = fp.read(2 * self._nodelen)
1628 fp.close()
1628 fp.close()
1629 except IOError as err:
1629 except IOError as err:
1630 if err.errno != errno.ENOENT:
1630 if err.errno != errno.ENOENT:
1631 raise
1631 raise
1632 # File doesn't exist, so the current state is empty
1632 # File doesn't exist, so the current state is empty
1633 st = b''
1633 st = b''
1634
1634
1635 l = len(st)
1635 l = len(st)
1636 if l == self._nodelen * 2:
1636 if l == self._nodelen * 2:
1637 self._parents = (
1637 self._parents = (
1638 st[: self._nodelen],
1638 st[: self._nodelen],
1639 st[self._nodelen : 2 * self._nodelen],
1639 st[self._nodelen : 2 * self._nodelen],
1640 )
1640 )
1641 elif l == 0:
1641 elif l == 0:
1642 self._parents = (
1642 self._parents = (
1643 self._nodeconstants.nullid,
1643 self._nodeconstants.nullid,
1644 self._nodeconstants.nullid,
1644 self._nodeconstants.nullid,
1645 )
1645 )
1646 else:
1646 else:
1647 raise error.Abort(
1647 raise error.Abort(
1648 _(b'working directory state appears damaged!')
1648 _(b'working directory state appears damaged!')
1649 )
1649 )
1650
1650
1651 return self._parents
1651 return self._parents
1652
1652
1653 def setparents(self, p1, p2):
1653 def setparents(self, p1, p2):
1654 self._parents = (p1, p2)
1654 self._parents = (p1, p2)
1655 self._dirtyparents = True
1655 self._dirtyparents = True
1656
1656
1657 def read(self):
1657 def read(self):
1658 # ignore HG_PENDING because identity is used only for writing
1658 # ignore HG_PENDING because identity is used only for writing
1659 self.identity = util.filestat.frompath(
1659 self.identity = util.filestat.frompath(
1660 self._opener.join(self._filename)
1660 self._opener.join(self._filename)
1661 )
1661 )
1662
1662
1663 try:
1663 try:
1664 fp = self._opendirstatefile()
1664 fp = self._opendirstatefile()
1665 try:
1665 try:
1666 st = fp.read()
1666 st = fp.read()
1667 finally:
1667 finally:
1668 fp.close()
1668 fp.close()
1669 except IOError as err:
1669 except IOError as err:
1670 if err.errno != errno.ENOENT:
1670 if err.errno != errno.ENOENT:
1671 raise
1671 raise
1672 return
1672 return
1673 if not st:
1673 if not st:
1674 return
1674 return
1675
1675
1676 if util.safehasattr(parsers, b'dict_new_presized'):
1676 if util.safehasattr(parsers, b'dict_new_presized'):
1677 # Make an estimate of the number of files in the dirstate based on
1677 # Make an estimate of the number of files in the dirstate based on
1678 # its size. This trades wasting some memory for avoiding costly
1678 # its size. This trades wasting some memory for avoiding costly
1679 # resizes. Each entry have a prefix of 17 bytes followed by one or
1679 # resizes. Each entry have a prefix of 17 bytes followed by one or
1680 # two path names. Studies on various large-scale real-world repositories
1680 # two path names. Studies on various large-scale real-world repositories
1681 # found 54 bytes a reasonable upper limit for the average path names.
1681 # found 54 bytes a reasonable upper limit for the average path names.
1682 # Copy entries are ignored for the sake of this estimate.
1682 # Copy entries are ignored for the sake of this estimate.
1683 self._map = parsers.dict_new_presized(len(st) // 71)
1683 self._map = parsers.dict_new_presized(len(st) // 71)
1684
1684
1685 # Python's garbage collector triggers a GC each time a certain number
1685 # Python's garbage collector triggers a GC each time a certain number
1686 # of container objects (the number being defined by
1686 # of container objects (the number being defined by
1687 # gc.get_threshold()) are allocated. parse_dirstate creates a tuple
1687 # gc.get_threshold()) are allocated. parse_dirstate creates a tuple
1688 # for each file in the dirstate. The C version then immediately marks
1688 # for each file in the dirstate. The C version then immediately marks
1689 # them as not to be tracked by the collector. However, this has no
1689 # them as not to be tracked by the collector. However, this has no
1690 # effect on when GCs are triggered, only on what objects the GC looks
1690 # effect on when GCs are triggered, only on what objects the GC looks
1691 # into. This means that O(number of files) GCs are unavoidable.
1691 # into. This means that O(number of files) GCs are unavoidable.
1692 # Depending on when in the process's lifetime the dirstate is parsed,
1692 # Depending on when in the process's lifetime the dirstate is parsed,
1693 # this can get very expensive. As a workaround, disable GC while
1693 # this can get very expensive. As a workaround, disable GC while
1694 # parsing the dirstate.
1694 # parsing the dirstate.
1695 #
1695 #
1696 # (we cannot decorate the function directly since it is in a C module)
1696 # (we cannot decorate the function directly since it is in a C module)
1697 parse_dirstate = util.nogc(parsers.parse_dirstate)
1697 parse_dirstate = util.nogc(parsers.parse_dirstate)
1698 p = parse_dirstate(self._map, self.copymap, st)
1698 p = parse_dirstate(self._map, self.copymap, st)
1699 if not self._dirtyparents:
1699 if not self._dirtyparents:
1700 self.setparents(*p)
1700 self.setparents(*p)
1701
1701
1702 # Avoid excess attribute lookups by fast pathing certain checks
1702 # Avoid excess attribute lookups by fast pathing certain checks
1703 self.__contains__ = self._map.__contains__
1703 self.__contains__ = self._map.__contains__
1704 self.__getitem__ = self._map.__getitem__
1704 self.__getitem__ = self._map.__getitem__
1705 self.get = self._map.get
1705 self.get = self._map.get
1706
1706
1707 def write(self, st, now):
1707 def write(self, st, now):
1708 st.write(
1708 st.write(
1709 parsers.pack_dirstate(self._map, self.copymap, self.parents(), now)
1709 parsers.pack_dirstate(self._map, self.copymap, self.parents(), now)
1710 )
1710 )
1711 st.close()
1711 st.close()
1712 self._dirtyparents = False
1712 self._dirtyparents = False
1713 self.nonnormalset, self.otherparentset = self.nonnormalentries()
1713 self.nonnormalset, self.otherparentset = self.nonnormalentries()
1714
1714
1715 @propertycache
1715 @propertycache
1716 def nonnormalset(self):
1716 def nonnormalset(self):
1717 nonnorm, otherparents = self.nonnormalentries()
1717 nonnorm, otherparents = self.nonnormalentries()
1718 self.otherparentset = otherparents
1718 self.otherparentset = otherparents
1719 return nonnorm
1719 return nonnorm
1720
1720
1721 @propertycache
1721 @propertycache
1722 def otherparentset(self):
1722 def otherparentset(self):
1723 nonnorm, otherparents = self.nonnormalentries()
1723 nonnorm, otherparents = self.nonnormalentries()
1724 self.nonnormalset = nonnorm
1724 self.nonnormalset = nonnorm
1725 return otherparents
1725 return otherparents
1726
1726
1727 def non_normal_or_other_parent_paths(self):
1727 def non_normal_or_other_parent_paths(self):
1728 return self.nonnormalset.union(self.otherparentset)
1728 return self.nonnormalset.union(self.otherparentset)
1729
1729
1730 @propertycache
1730 @propertycache
1731 def identity(self):
1731 def identity(self):
1732 self._map
1732 self._map
1733 return self.identity
1733 return self.identity
1734
1734
1735 @propertycache
1735 @propertycache
1736 def dirfoldmap(self):
1736 def dirfoldmap(self):
1737 f = {}
1737 f = {}
1738 normcase = util.normcase
1738 normcase = util.normcase
1739 for name in self._dirs:
1739 for name in self._dirs:
1740 f[normcase(name)] = name
1740 f[normcase(name)] = name
1741 return f
1741 return f
1742
1742
1743
1743
1744 if rustmod is not None:
1744 if rustmod is not None:
1745
1745
1746 class dirstatemap(object):
1746 class dirstatemap(object):
1747 def __init__(self, ui, opener, root, nodeconstants):
1747 def __init__(self, ui, opener, root, nodeconstants):
1748 self._nodeconstants = nodeconstants
1748 self._nodeconstants = nodeconstants
1749 self._ui = ui
1749 self._ui = ui
1750 self._opener = opener
1750 self._opener = opener
1751 self._root = root
1751 self._root = root
1752 self._filename = b'dirstate'
1752 self._filename = b'dirstate'
1753 self._parents = None
1753 self._parents = None
1754 self._dirtyparents = False
1754 self._dirtyparents = False
1755
1755
1756 # for consistent view between _pl() and _read() invocations
1756 # for consistent view between _pl() and _read() invocations
1757 self._pendingmode = None
1757 self._pendingmode = None
1758
1758
1759 def addfile(self, *args, **kwargs):
1759 def addfile(self, *args, **kwargs):
1760 return self._rustmap.addfile(*args, **kwargs)
1760 return self._rustmap.addfile(*args, **kwargs)
1761
1761
1762 def removefile(self, *args, **kwargs):
1762 def removefile(self, *args, **kwargs):
1763 return self._rustmap.removefile(*args, **kwargs)
1763 return self._rustmap.removefile(*args, **kwargs)
1764
1764
1765 def dropfile(self, *args, **kwargs):
1765 def dropfile(self, *args, **kwargs):
1766 return self._rustmap.dropfile(*args, **kwargs)
1766 return self._rustmap.dropfile(*args, **kwargs)
1767
1767
1768 def clearambiguoustimes(self, *args, **kwargs):
1768 def clearambiguoustimes(self, *args, **kwargs):
1769 return self._rustmap.clearambiguoustimes(*args, **kwargs)
1769 return self._rustmap.clearambiguoustimes(*args, **kwargs)
1770
1770
1771 def nonnormalentries(self):
1771 def nonnormalentries(self):
1772 return self._rustmap.nonnormalentries()
1772 return self._rustmap.nonnormalentries()
1773
1773
1774 def get(self, *args, **kwargs):
1774 def get(self, *args, **kwargs):
1775 return self._rustmap.get(*args, **kwargs)
1775 return self._rustmap.get(*args, **kwargs)
1776
1776
1777 @propertycache
1777 @propertycache
1778 def _rustmap(self):
1778 def _rustmap(self):
1779 """
1779 """
1780 Fills the Dirstatemap when called.
1780 Fills the Dirstatemap when called.
1781 Use `self._inner_rustmap` if reading the dirstate is not necessary.
1781 Use `self._inner_rustmap` if reading the dirstate is not necessary.
1782 """
1782 """
1783 self._rustmap = self._inner_rustmap
1783 self._rustmap = self._inner_rustmap
1784 self.read()
1784 self.read()
1785 return self._rustmap
1785 return self._rustmap
1786
1786
1787 @propertycache
1787 @propertycache
1788 def _inner_rustmap(self):
1788 def _inner_rustmap(self):
1789 """
1789 """
1790 Does not fill the Dirstatemap when called. This allows for
1790 Does not fill the Dirstatemap when called. This allows for
1791 optimizations where only setting/getting the parents is needed.
1791 optimizations where only setting/getting the parents is needed.
1792 """
1792 """
1793 self._inner_rustmap = rustmod.DirstateMap(self._root)
1793 use_dirstate_tree = self._ui.configbool(
1794 b"experimental",
1795 b"dirstate-tree.in-memory",
1796 False,
1797 )
1798 self._inner_rustmap = rustmod.DirstateMap(use_dirstate_tree)
1794 return self._inner_rustmap
1799 return self._inner_rustmap
1795
1800
1796 @property
1801 @property
1797 def copymap(self):
1802 def copymap(self):
1798 return self._rustmap.copymap()
1803 return self._rustmap.copymap()
1799
1804
1800 def preload(self):
1805 def preload(self):
1801 self._rustmap
1806 self._rustmap
1802
1807
1803 def clear(self):
1808 def clear(self):
1804 self._rustmap.clear()
1809 self._rustmap.clear()
1805 self._inner_rustmap.clear()
1810 self._inner_rustmap.clear()
1806 self.setparents(
1811 self.setparents(
1807 self._nodeconstants.nullid, self._nodeconstants.nullid
1812 self._nodeconstants.nullid, self._nodeconstants.nullid
1808 )
1813 )
1809 util.clearcachedproperty(self, b"_dirs")
1814 util.clearcachedproperty(self, b"_dirs")
1810 util.clearcachedproperty(self, b"_alldirs")
1815 util.clearcachedproperty(self, b"_alldirs")
1811 util.clearcachedproperty(self, b"dirfoldmap")
1816 util.clearcachedproperty(self, b"dirfoldmap")
1812
1817
1813 def items(self):
1818 def items(self):
1814 return self._rustmap.items()
1819 return self._rustmap.items()
1815
1820
1816 def keys(self):
1821 def keys(self):
1817 return iter(self._rustmap)
1822 return iter(self._rustmap)
1818
1823
1819 def __contains__(self, key):
1824 def __contains__(self, key):
1820 return key in self._rustmap
1825 return key in self._rustmap
1821
1826
1822 def __getitem__(self, item):
1827 def __getitem__(self, item):
1823 return self._rustmap[item]
1828 return self._rustmap[item]
1824
1829
1825 def __len__(self):
1830 def __len__(self):
1826 return len(self._rustmap)
1831 return len(self._rustmap)
1827
1832
1828 def __iter__(self):
1833 def __iter__(self):
1829 return iter(self._rustmap)
1834 return iter(self._rustmap)
1830
1835
1831 # forward for python2,3 compat
1836 # forward for python2,3 compat
1832 iteritems = items
1837 iteritems = items
1833
1838
1834 def _opendirstatefile(self):
1839 def _opendirstatefile(self):
1835 fp, mode = txnutil.trypending(
1840 fp, mode = txnutil.trypending(
1836 self._root, self._opener, self._filename
1841 self._root, self._opener, self._filename
1837 )
1842 )
1838 if self._pendingmode is not None and self._pendingmode != mode:
1843 if self._pendingmode is not None and self._pendingmode != mode:
1839 fp.close()
1844 fp.close()
1840 raise error.Abort(
1845 raise error.Abort(
1841 _(b'working directory state may be changed parallelly')
1846 _(b'working directory state may be changed parallelly')
1842 )
1847 )
1843 self._pendingmode = mode
1848 self._pendingmode = mode
1844 return fp
1849 return fp
1845
1850
1846 def setparents(self, p1, p2):
1851 def setparents(self, p1, p2):
1847 self._rustmap.setparents(p1, p2)
1852 self._rustmap.setparents(p1, p2)
1848 self._parents = (p1, p2)
1853 self._parents = (p1, p2)
1849 self._dirtyparents = True
1854 self._dirtyparents = True
1850
1855
1851 def parents(self):
1856 def parents(self):
1852 if not self._parents:
1857 if not self._parents:
1853 try:
1858 try:
1854 fp = self._opendirstatefile()
1859 fp = self._opendirstatefile()
1855 st = fp.read(40)
1860 st = fp.read(40)
1856 fp.close()
1861 fp.close()
1857 except IOError as err:
1862 except IOError as err:
1858 if err.errno != errno.ENOENT:
1863 if err.errno != errno.ENOENT:
1859 raise
1864 raise
1860 # File doesn't exist, so the current state is empty
1865 # File doesn't exist, so the current state is empty
1861 st = b''
1866 st = b''
1862
1867
1863 try:
1868 try:
1864 self._parents = self._inner_rustmap.parents(st)
1869 self._parents = self._inner_rustmap.parents(st)
1865 except ValueError:
1870 except ValueError:
1866 raise error.Abort(
1871 raise error.Abort(
1867 _(b'working directory state appears damaged!')
1872 _(b'working directory state appears damaged!')
1868 )
1873 )
1869
1874
1870 return self._parents
1875 return self._parents
1871
1876
1872 def read(self):
1877 def read(self):
1873 # ignore HG_PENDING because identity is used only for writing
1878 # ignore HG_PENDING because identity is used only for writing
1874 self.identity = util.filestat.frompath(
1879 self.identity = util.filestat.frompath(
1875 self._opener.join(self._filename)
1880 self._opener.join(self._filename)
1876 )
1881 )
1877
1882
1878 try:
1883 try:
1879 fp = self._opendirstatefile()
1884 fp = self._opendirstatefile()
1880 try:
1885 try:
1881 st = fp.read()
1886 st = fp.read()
1882 finally:
1887 finally:
1883 fp.close()
1888 fp.close()
1884 except IOError as err:
1889 except IOError as err:
1885 if err.errno != errno.ENOENT:
1890 if err.errno != errno.ENOENT:
1886 raise
1891 raise
1887 return
1892 return
1888 if not st:
1893 if not st:
1889 return
1894 return
1890
1895
1891 parse_dirstate = util.nogc(self._rustmap.read)
1896 parse_dirstate = util.nogc(self._rustmap.read)
1892 parents = parse_dirstate(st)
1897 parents = parse_dirstate(st)
1893 if parents and not self._dirtyparents:
1898 if parents and not self._dirtyparents:
1894 self.setparents(*parents)
1899 self.setparents(*parents)
1895
1900
1896 self.__contains__ = self._rustmap.__contains__
1901 self.__contains__ = self._rustmap.__contains__
1897 self.__getitem__ = self._rustmap.__getitem__
1902 self.__getitem__ = self._rustmap.__getitem__
1898 self.get = self._rustmap.get
1903 self.get = self._rustmap.get
1899
1904
1900 def write(self, st, now):
1905 def write(self, st, now):
1901 parents = self.parents()
1906 parents = self.parents()
1902 st.write(self._rustmap.write(parents[0], parents[1], now))
1907 st.write(self._rustmap.write(parents[0], parents[1], now))
1903 st.close()
1908 st.close()
1904 self._dirtyparents = False
1909 self._dirtyparents = False
1905
1910
1906 @propertycache
1911 @propertycache
1907 def filefoldmap(self):
1912 def filefoldmap(self):
1908 """Returns a dictionary mapping normalized case paths to their
1913 """Returns a dictionary mapping normalized case paths to their
1909 non-normalized versions.
1914 non-normalized versions.
1910 """
1915 """
1911 return self._rustmap.filefoldmapasdict()
1916 return self._rustmap.filefoldmapasdict()
1912
1917
1913 def hastrackeddir(self, d):
1918 def hastrackeddir(self, d):
1914 self._dirs # Trigger Python's propertycache
1919 self._dirs # Trigger Python's propertycache
1915 return self._rustmap.hastrackeddir(d)
1920 return self._rustmap.hastrackeddir(d)
1916
1921
1917 def hasdir(self, d):
1922 def hasdir(self, d):
1918 self._dirs # Trigger Python's propertycache
1923 self._dirs # Trigger Python's propertycache
1919 return self._rustmap.hasdir(d)
1924 return self._rustmap.hasdir(d)
1920
1925
1921 @propertycache
1926 @propertycache
1922 def _dirs(self):
1927 def _dirs(self):
1923 return self._rustmap.getdirs()
1928 return self._rustmap.getdirs()
1924
1929
1925 @propertycache
1930 @propertycache
1926 def _alldirs(self):
1931 def _alldirs(self):
1927 return self._rustmap.getalldirs()
1932 return self._rustmap.getalldirs()
1928
1933
1929 @propertycache
1934 @propertycache
1930 def identity(self):
1935 def identity(self):
1931 self._rustmap
1936 self._rustmap
1932 return self.identity
1937 return self.identity
1933
1938
1934 @property
1939 @property
1935 def nonnormalset(self):
1940 def nonnormalset(self):
1936 nonnorm = self._rustmap.non_normal_entries()
1941 nonnorm = self._rustmap.non_normal_entries()
1937 return nonnorm
1942 return nonnorm
1938
1943
1939 @propertycache
1944 @propertycache
1940 def otherparentset(self):
1945 def otherparentset(self):
1941 otherparents = self._rustmap.other_parent_entries()
1946 otherparents = self._rustmap.other_parent_entries()
1942 return otherparents
1947 return otherparents
1943
1948
1944 def non_normal_or_other_parent_paths(self):
1949 def non_normal_or_other_parent_paths(self):
1945 return self._rustmap.non_normal_or_other_parent_paths()
1950 return self._rustmap.non_normal_or_other_parent_paths()
1946
1951
1947 @propertycache
1952 @propertycache
1948 def dirfoldmap(self):
1953 def dirfoldmap(self):
1949 f = {}
1954 f = {}
1950 normcase = util.normcase
1955 normcase = util.normcase
1951 for name in self._dirs:
1956 for name in self._dirs:
1952 f[normcase(name)] = name
1957 f[normcase(name)] = name
1953 return f
1958 return f
@@ -1,1 +1,2 b''
1 pub mod dirstate_map;
1 pub mod dispatch;
2 pub mod dispatch;
@@ -1,567 +1,571 b''
1 // dirstate_map.rs
1 // dirstate_map.rs
2 //
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
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 //! Bindings for the `hg::dirstate::dirstate_map` file provided by the
8 //! Bindings for the `hg::dirstate::dirstate_map` file provided by the
9 //! `hg-core` package.
9 //! `hg-core` package.
10
10
11 use std::cell::{Ref, RefCell};
11 use std::cell::{Ref, RefCell};
12 use std::convert::TryInto;
12 use std::convert::TryInto;
13 use std::time::Duration;
13 use std::time::Duration;
14
14
15 use cpython::{
15 use cpython::{
16 exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList,
16 exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList,
17 PyObject, PyResult, PySet, PyString, PyTuple, Python, PythonObject,
17 PyObject, PyResult, PySet, PyString, PyTuple, Python, PythonObject,
18 ToPyObject, UnsafePyLeaked,
18 ToPyObject, UnsafePyLeaked,
19 };
19 };
20
20
21 use crate::{
21 use crate::{
22 dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
22 dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
23 dirstate::non_normal_entries::{
23 dirstate::non_normal_entries::{
24 NonNormalEntries, NonNormalEntriesIterator,
24 NonNormalEntries, NonNormalEntriesIterator,
25 },
25 },
26 dirstate::{dirs_multiset::Dirs, make_dirstate_tuple},
26 dirstate::{dirs_multiset::Dirs, make_dirstate_tuple},
27 parsers::dirstate_parents_to_pytuple,
27 parsers::dirstate_parents_to_pytuple,
28 };
28 };
29 use hg::{
29 use hg::{
30 dirstate_tree::dispatch::DirstateMapMethods,
30 dirstate_tree::dispatch::DirstateMapMethods,
31 errors::HgError,
31 errors::HgError,
32 revlog::Node,
32 revlog::Node,
33 utils::hg_path::{HgPath, HgPathBuf},
33 utils::hg_path::{HgPath, HgPathBuf},
34 DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap,
34 DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap,
35 DirstateMapError, DirstateParents, EntryState, StateMapIter,
35 DirstateMapError, DirstateParents, EntryState, StateMapIter,
36 };
36 };
37
37
38 // TODO
38 // TODO
39 // This object needs to share references to multiple members of its Rust
39 // This object needs to share references to multiple members of its Rust
40 // inner struct, namely `copy_map`, `dirs` and `all_dirs`.
40 // inner struct, namely `copy_map`, `dirs` and `all_dirs`.
41 // Right now `CopyMap` is done, but it needs to have an explicit reference
41 // Right now `CopyMap` is done, but it needs to have an explicit reference
42 // to `RustDirstateMap` which itself needs to have an encapsulation for
42 // to `RustDirstateMap` which itself needs to have an encapsulation for
43 // every method in `CopyMap` (copymapcopy, etc.).
43 // every method in `CopyMap` (copymapcopy, etc.).
44 // This is ugly and hard to maintain.
44 // This is ugly and hard to maintain.
45 // The same logic applies to `dirs` and `all_dirs`, however the `Dirs`
45 // The same logic applies to `dirs` and `all_dirs`, however the `Dirs`
46 // `py_class!` is already implemented and does not mention
46 // `py_class!` is already implemented and does not mention
47 // `RustDirstateMap`, rightfully so.
47 // `RustDirstateMap`, rightfully so.
48 // All attributes also have to have a separate refcount data attribute for
48 // All attributes also have to have a separate refcount data attribute for
49 // leaks, with all methods that go along for reference sharing.
49 // leaks, with all methods that go along for reference sharing.
50 py_class!(pub class DirstateMap |py| {
50 py_class!(pub class DirstateMap |py| {
51 @shared data inner: Box<dyn DirstateMapMethods + Send>;
51 @shared data inner: Box<dyn DirstateMapMethods + Send>;
52
52
53 def __new__(_cls, _root: PyObject) -> PyResult<Self> {
53 def __new__(_cls, use_dirstate_tree: bool) -> PyResult<Self> {
54 let inner = Box::new(RustDirstateMap::default());
54 let inner = if use_dirstate_tree {
55 Box::new(hg::dirstate_tree::dirstate_map::DirstateMap::new()) as _
56 } else {
57 Box::new(RustDirstateMap::default()) as _
58 };
55 Self::create_instance(py, inner)
59 Self::create_instance(py, inner)
56 }
60 }
57
61
58 def clear(&self) -> PyResult<PyObject> {
62 def clear(&self) -> PyResult<PyObject> {
59 self.inner(py).borrow_mut().clear();
63 self.inner(py).borrow_mut().clear();
60 Ok(py.None())
64 Ok(py.None())
61 }
65 }
62
66
63 def get(
67 def get(
64 &self,
68 &self,
65 key: PyObject,
69 key: PyObject,
66 default: Option<PyObject> = None
70 default: Option<PyObject> = None
67 ) -> PyResult<Option<PyObject>> {
71 ) -> PyResult<Option<PyObject>> {
68 let key = key.extract::<PyBytes>(py)?;
72 let key = key.extract::<PyBytes>(py)?;
69 match self.inner(py).borrow().get(HgPath::new(key.data(py))) {
73 match self.inner(py).borrow().get(HgPath::new(key.data(py))) {
70 Some(entry) => {
74 Some(entry) => {
71 Ok(Some(make_dirstate_tuple(py, entry)?))
75 Ok(Some(make_dirstate_tuple(py, entry)?))
72 },
76 },
73 None => Ok(default)
77 None => Ok(default)
74 }
78 }
75 }
79 }
76
80
77 def addfile(
81 def addfile(
78 &self,
82 &self,
79 f: PyObject,
83 f: PyObject,
80 oldstate: PyObject,
84 oldstate: PyObject,
81 state: PyObject,
85 state: PyObject,
82 mode: PyObject,
86 mode: PyObject,
83 size: PyObject,
87 size: PyObject,
84 mtime: PyObject
88 mtime: PyObject
85 ) -> PyResult<PyObject> {
89 ) -> PyResult<PyObject> {
86 self.inner(py).borrow_mut().add_file(
90 self.inner(py).borrow_mut().add_file(
87 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
91 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
88 oldstate.extract::<PyBytes>(py)?.data(py)[0]
92 oldstate.extract::<PyBytes>(py)?.data(py)[0]
89 .try_into()
93 .try_into()
90 .map_err(|e: HgError| {
94 .map_err(|e: HgError| {
91 PyErr::new::<exc::ValueError, _>(py, e.to_string())
95 PyErr::new::<exc::ValueError, _>(py, e.to_string())
92 })?,
96 })?,
93 DirstateEntry {
97 DirstateEntry {
94 state: state.extract::<PyBytes>(py)?.data(py)[0]
98 state: state.extract::<PyBytes>(py)?.data(py)[0]
95 .try_into()
99 .try_into()
96 .map_err(|e: HgError| {
100 .map_err(|e: HgError| {
97 PyErr::new::<exc::ValueError, _>(py, e.to_string())
101 PyErr::new::<exc::ValueError, _>(py, e.to_string())
98 })?,
102 })?,
99 mode: mode.extract(py)?,
103 mode: mode.extract(py)?,
100 size: size.extract(py)?,
104 size: size.extract(py)?,
101 mtime: mtime.extract(py)?,
105 mtime: mtime.extract(py)?,
102 },
106 },
103 ).and(Ok(py.None())).or_else(|e: DirstateMapError| {
107 ).and(Ok(py.None())).or_else(|e: DirstateMapError| {
104 Err(PyErr::new::<exc::ValueError, _>(py, e.to_string()))
108 Err(PyErr::new::<exc::ValueError, _>(py, e.to_string()))
105 })
109 })
106 }
110 }
107
111
108 def removefile(
112 def removefile(
109 &self,
113 &self,
110 f: PyObject,
114 f: PyObject,
111 oldstate: PyObject,
115 oldstate: PyObject,
112 size: PyObject
116 size: PyObject
113 ) -> PyResult<PyObject> {
117 ) -> PyResult<PyObject> {
114 self.inner(py).borrow_mut()
118 self.inner(py).borrow_mut()
115 .remove_file(
119 .remove_file(
116 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
120 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
117 oldstate.extract::<PyBytes>(py)?.data(py)[0]
121 oldstate.extract::<PyBytes>(py)?.data(py)[0]
118 .try_into()
122 .try_into()
119 .map_err(|e: HgError| {
123 .map_err(|e: HgError| {
120 PyErr::new::<exc::ValueError, _>(py, e.to_string())
124 PyErr::new::<exc::ValueError, _>(py, e.to_string())
121 })?,
125 })?,
122 size.extract(py)?,
126 size.extract(py)?,
123 )
127 )
124 .or_else(|_| {
128 .or_else(|_| {
125 Err(PyErr::new::<exc::OSError, _>(
129 Err(PyErr::new::<exc::OSError, _>(
126 py,
130 py,
127 "Dirstate error".to_string(),
131 "Dirstate error".to_string(),
128 ))
132 ))
129 })?;
133 })?;
130 Ok(py.None())
134 Ok(py.None())
131 }
135 }
132
136
133 def dropfile(
137 def dropfile(
134 &self,
138 &self,
135 f: PyObject,
139 f: PyObject,
136 oldstate: PyObject
140 oldstate: PyObject
137 ) -> PyResult<PyBool> {
141 ) -> PyResult<PyBool> {
138 self.inner(py).borrow_mut()
142 self.inner(py).borrow_mut()
139 .drop_file(
143 .drop_file(
140 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
144 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
141 oldstate.extract::<PyBytes>(py)?.data(py)[0]
145 oldstate.extract::<PyBytes>(py)?.data(py)[0]
142 .try_into()
146 .try_into()
143 .map_err(|e: HgError| {
147 .map_err(|e: HgError| {
144 PyErr::new::<exc::ValueError, _>(py, e.to_string())
148 PyErr::new::<exc::ValueError, _>(py, e.to_string())
145 })?,
149 })?,
146 )
150 )
147 .and_then(|b| Ok(b.to_py_object(py)))
151 .and_then(|b| Ok(b.to_py_object(py)))
148 .or_else(|e| {
152 .or_else(|e| {
149 Err(PyErr::new::<exc::OSError, _>(
153 Err(PyErr::new::<exc::OSError, _>(
150 py,
154 py,
151 format!("Dirstate error: {}", e.to_string()),
155 format!("Dirstate error: {}", e.to_string()),
152 ))
156 ))
153 })
157 })
154 }
158 }
155
159
156 def clearambiguoustimes(
160 def clearambiguoustimes(
157 &self,
161 &self,
158 files: PyObject,
162 files: PyObject,
159 now: PyObject
163 now: PyObject
160 ) -> PyResult<PyObject> {
164 ) -> PyResult<PyObject> {
161 let files: PyResult<Vec<HgPathBuf>> = files
165 let files: PyResult<Vec<HgPathBuf>> = files
162 .iter(py)?
166 .iter(py)?
163 .map(|filename| {
167 .map(|filename| {
164 Ok(HgPathBuf::from_bytes(
168 Ok(HgPathBuf::from_bytes(
165 filename?.extract::<PyBytes>(py)?.data(py),
169 filename?.extract::<PyBytes>(py)?.data(py),
166 ))
170 ))
167 })
171 })
168 .collect();
172 .collect();
169 self.inner(py).borrow_mut()
173 self.inner(py).borrow_mut()
170 .clear_ambiguous_times(files?, now.extract(py)?);
174 .clear_ambiguous_times(files?, now.extract(py)?);
171 Ok(py.None())
175 Ok(py.None())
172 }
176 }
173
177
174 def other_parent_entries(&self) -> PyResult<PyObject> {
178 def other_parent_entries(&self) -> PyResult<PyObject> {
175 let mut inner_shared = self.inner(py).borrow_mut();
179 let mut inner_shared = self.inner(py).borrow_mut();
176 let set = PySet::empty(py)?;
180 let set = PySet::empty(py)?;
177 for path in inner_shared.iter_other_parent_paths() {
181 for path in inner_shared.iter_other_parent_paths() {
178 set.add(py, PyBytes::new(py, path.as_bytes()))?;
182 set.add(py, PyBytes::new(py, path.as_bytes()))?;
179 }
183 }
180 Ok(set.into_object())
184 Ok(set.into_object())
181 }
185 }
182
186
183 def non_normal_entries(&self) -> PyResult<NonNormalEntries> {
187 def non_normal_entries(&self) -> PyResult<NonNormalEntries> {
184 NonNormalEntries::from_inner(py, self.clone_ref(py))
188 NonNormalEntries::from_inner(py, self.clone_ref(py))
185 }
189 }
186
190
187 def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> {
191 def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> {
188 let key = key.extract::<PyBytes>(py)?;
192 let key = key.extract::<PyBytes>(py)?;
189 Ok(self
193 Ok(self
190 .inner(py)
194 .inner(py)
191 .borrow_mut()
195 .borrow_mut()
192 .non_normal_entries_contains(HgPath::new(key.data(py))))
196 .non_normal_entries_contains(HgPath::new(key.data(py))))
193 }
197 }
194
198
195 def non_normal_entries_display(&self) -> PyResult<PyString> {
199 def non_normal_entries_display(&self) -> PyResult<PyString> {
196 Ok(
200 Ok(
197 PyString::new(
201 PyString::new(
198 py,
202 py,
199 &format!(
203 &format!(
200 "NonNormalEntries: {}",
204 "NonNormalEntries: {}",
201 hg::utils::join_display(
205 hg::utils::join_display(
202 self
206 self
203 .inner(py)
207 .inner(py)
204 .borrow_mut()
208 .borrow_mut()
205 .iter_non_normal_paths(),
209 .iter_non_normal_paths(),
206 ", "
210 ", "
207 )
211 )
208 )
212 )
209 )
213 )
210 )
214 )
211 }
215 }
212
216
213 def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> {
217 def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> {
214 let key = key.extract::<PyBytes>(py)?;
218 let key = key.extract::<PyBytes>(py)?;
215 self
219 self
216 .inner(py)
220 .inner(py)
217 .borrow_mut()
221 .borrow_mut()
218 .non_normal_entries_remove(HgPath::new(key.data(py)));
222 .non_normal_entries_remove(HgPath::new(key.data(py)));
219 Ok(py.None())
223 Ok(py.None())
220 }
224 }
221
225
222 def non_normal_or_other_parent_paths(&self) -> PyResult<PyList> {
226 def non_normal_or_other_parent_paths(&self) -> PyResult<PyList> {
223 let mut inner = self.inner(py).borrow_mut();
227 let mut inner = self.inner(py).borrow_mut();
224
228
225 let ret = PyList::new(py, &[]);
229 let ret = PyList::new(py, &[]);
226 for filename in inner.non_normal_or_other_parent_paths() {
230 for filename in inner.non_normal_or_other_parent_paths() {
227 let as_pystring = PyBytes::new(py, filename.as_bytes());
231 let as_pystring = PyBytes::new(py, filename.as_bytes());
228 ret.append(py, as_pystring.into_object());
232 ret.append(py, as_pystring.into_object());
229 }
233 }
230 Ok(ret)
234 Ok(ret)
231 }
235 }
232
236
233 def non_normal_entries_iter(&self) -> PyResult<NonNormalEntriesIterator> {
237 def non_normal_entries_iter(&self) -> PyResult<NonNormalEntriesIterator> {
234 // Make sure the sets are defined before we no longer have a mutable
238 // Make sure the sets are defined before we no longer have a mutable
235 // reference to the dmap.
239 // reference to the dmap.
236 self.inner(py)
240 self.inner(py)
237 .borrow_mut()
241 .borrow_mut()
238 .set_non_normal_other_parent_entries(false);
242 .set_non_normal_other_parent_entries(false);
239
243
240 let leaked_ref = self.inner(py).leak_immutable();
244 let leaked_ref = self.inner(py).leak_immutable();
241
245
242 NonNormalEntriesIterator::from_inner(py, unsafe {
246 NonNormalEntriesIterator::from_inner(py, unsafe {
243 leaked_ref.map(py, |o| {
247 leaked_ref.map(py, |o| {
244 o.iter_non_normal_paths_panic()
248 o.iter_non_normal_paths_panic()
245 })
249 })
246 })
250 })
247 }
251 }
248
252
249 def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
253 def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
250 let d = d.extract::<PyBytes>(py)?;
254 let d = d.extract::<PyBytes>(py)?;
251 Ok(self.inner(py).borrow_mut()
255 Ok(self.inner(py).borrow_mut()
252 .has_tracked_dir(HgPath::new(d.data(py)))
256 .has_tracked_dir(HgPath::new(d.data(py)))
253 .map_err(|e| {
257 .map_err(|e| {
254 PyErr::new::<exc::ValueError, _>(py, e.to_string())
258 PyErr::new::<exc::ValueError, _>(py, e.to_string())
255 })?
259 })?
256 .to_py_object(py))
260 .to_py_object(py))
257 }
261 }
258
262
259 def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
263 def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
260 let d = d.extract::<PyBytes>(py)?;
264 let d = d.extract::<PyBytes>(py)?;
261 Ok(self.inner(py).borrow_mut()
265 Ok(self.inner(py).borrow_mut()
262 .has_dir(HgPath::new(d.data(py)))
266 .has_dir(HgPath::new(d.data(py)))
263 .map_err(|e| {
267 .map_err(|e| {
264 PyErr::new::<exc::ValueError, _>(py, e.to_string())
268 PyErr::new::<exc::ValueError, _>(py, e.to_string())
265 })?
269 })?
266 .to_py_object(py))
270 .to_py_object(py))
267 }
271 }
268
272
269 def parents(&self, st: PyObject) -> PyResult<PyTuple> {
273 def parents(&self, st: PyObject) -> PyResult<PyTuple> {
270 self.inner(py).borrow_mut()
274 self.inner(py).borrow_mut()
271 .parents(st.extract::<PyBytes>(py)?.data(py))
275 .parents(st.extract::<PyBytes>(py)?.data(py))
272 .map(|parents| dirstate_parents_to_pytuple(py, parents))
276 .map(|parents| dirstate_parents_to_pytuple(py, parents))
273 .or_else(|_| {
277 .or_else(|_| {
274 Err(PyErr::new::<exc::OSError, _>(
278 Err(PyErr::new::<exc::OSError, _>(
275 py,
279 py,
276 "Dirstate error".to_string(),
280 "Dirstate error".to_string(),
277 ))
281 ))
278 })
282 })
279 }
283 }
280
284
281 def setparents(&self, p1: PyObject, p2: PyObject) -> PyResult<PyObject> {
285 def setparents(&self, p1: PyObject, p2: PyObject) -> PyResult<PyObject> {
282 let p1 = extract_node_id(py, &p1)?;
286 let p1 = extract_node_id(py, &p1)?;
283 let p2 = extract_node_id(py, &p2)?;
287 let p2 = extract_node_id(py, &p2)?;
284
288
285 self.inner(py).borrow_mut()
289 self.inner(py).borrow_mut()
286 .set_parents(&DirstateParents { p1, p2 });
290 .set_parents(&DirstateParents { p1, p2 });
287 Ok(py.None())
291 Ok(py.None())
288 }
292 }
289
293
290 def read(&self, st: PyObject) -> PyResult<Option<PyObject>> {
294 def read(&self, st: PyObject) -> PyResult<Option<PyObject>> {
291 match self.inner(py).borrow_mut()
295 match self.inner(py).borrow_mut()
292 .read(st.extract::<PyBytes>(py)?.data(py))
296 .read(st.extract::<PyBytes>(py)?.data(py))
293 {
297 {
294 Ok(Some(parents)) => Ok(Some(
298 Ok(Some(parents)) => Ok(Some(
295 dirstate_parents_to_pytuple(py, parents)
299 dirstate_parents_to_pytuple(py, parents)
296 .into_object()
300 .into_object()
297 )),
301 )),
298 Ok(None) => Ok(Some(py.None())),
302 Ok(None) => Ok(Some(py.None())),
299 Err(_) => Err(PyErr::new::<exc::OSError, _>(
303 Err(_) => Err(PyErr::new::<exc::OSError, _>(
300 py,
304 py,
301 "Dirstate error".to_string(),
305 "Dirstate error".to_string(),
302 )),
306 )),
303 }
307 }
304 }
308 }
305 def write(
309 def write(
306 &self,
310 &self,
307 p1: PyObject,
311 p1: PyObject,
308 p2: PyObject,
312 p2: PyObject,
309 now: PyObject
313 now: PyObject
310 ) -> PyResult<PyBytes> {
314 ) -> PyResult<PyBytes> {
311 let now = Duration::new(now.extract(py)?, 0);
315 let now = Duration::new(now.extract(py)?, 0);
312 let parents = DirstateParents {
316 let parents = DirstateParents {
313 p1: extract_node_id(py, &p1)?,
317 p1: extract_node_id(py, &p1)?,
314 p2: extract_node_id(py, &p2)?,
318 p2: extract_node_id(py, &p2)?,
315 };
319 };
316
320
317 match self.inner(py).borrow_mut().pack(parents, now) {
321 match self.inner(py).borrow_mut().pack(parents, now) {
318 Ok(packed) => Ok(PyBytes::new(py, &packed)),
322 Ok(packed) => Ok(PyBytes::new(py, &packed)),
319 Err(_) => Err(PyErr::new::<exc::OSError, _>(
323 Err(_) => Err(PyErr::new::<exc::OSError, _>(
320 py,
324 py,
321 "Dirstate error".to_string(),
325 "Dirstate error".to_string(),
322 )),
326 )),
323 }
327 }
324 }
328 }
325
329
326 def filefoldmapasdict(&self) -> PyResult<PyDict> {
330 def filefoldmapasdict(&self) -> PyResult<PyDict> {
327 let dict = PyDict::new(py);
331 let dict = PyDict::new(py);
328 for (key, value) in
332 for (key, value) in
329 self.inner(py).borrow_mut().build_file_fold_map().iter()
333 self.inner(py).borrow_mut().build_file_fold_map().iter()
330 {
334 {
331 dict.set_item(
335 dict.set_item(
332 py,
336 py,
333 PyBytes::new(py, key.as_bytes()).into_object(),
337 PyBytes::new(py, key.as_bytes()).into_object(),
334 PyBytes::new(py, value.as_bytes()).into_object(),
338 PyBytes::new(py, value.as_bytes()).into_object(),
335 )?;
339 )?;
336 }
340 }
337 Ok(dict)
341 Ok(dict)
338 }
342 }
339
343
340 def __len__(&self) -> PyResult<usize> {
344 def __len__(&self) -> PyResult<usize> {
341 Ok(self.inner(py).borrow().len())
345 Ok(self.inner(py).borrow().len())
342 }
346 }
343
347
344 def __contains__(&self, key: PyObject) -> PyResult<bool> {
348 def __contains__(&self, key: PyObject) -> PyResult<bool> {
345 let key = key.extract::<PyBytes>(py)?;
349 let key = key.extract::<PyBytes>(py)?;
346 Ok(self.inner(py).borrow().contains_key(HgPath::new(key.data(py))))
350 Ok(self.inner(py).borrow().contains_key(HgPath::new(key.data(py))))
347 }
351 }
348
352
349 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
353 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
350 let key = key.extract::<PyBytes>(py)?;
354 let key = key.extract::<PyBytes>(py)?;
351 let key = HgPath::new(key.data(py));
355 let key = HgPath::new(key.data(py));
352 match self.inner(py).borrow().get(key) {
356 match self.inner(py).borrow().get(key) {
353 Some(entry) => {
357 Some(entry) => {
354 Ok(make_dirstate_tuple(py, entry)?)
358 Ok(make_dirstate_tuple(py, entry)?)
355 },
359 },
356 None => Err(PyErr::new::<exc::KeyError, _>(
360 None => Err(PyErr::new::<exc::KeyError, _>(
357 py,
361 py,
358 String::from_utf8_lossy(key.as_bytes()),
362 String::from_utf8_lossy(key.as_bytes()),
359 )),
363 )),
360 }
364 }
361 }
365 }
362
366
363 def keys(&self) -> PyResult<DirstateMapKeysIterator> {
367 def keys(&self) -> PyResult<DirstateMapKeysIterator> {
364 let leaked_ref = self.inner(py).leak_immutable();
368 let leaked_ref = self.inner(py).leak_immutable();
365 DirstateMapKeysIterator::from_inner(
369 DirstateMapKeysIterator::from_inner(
366 py,
370 py,
367 unsafe { leaked_ref.map(py, |o| o.iter()) },
371 unsafe { leaked_ref.map(py, |o| o.iter()) },
368 )
372 )
369 }
373 }
370
374
371 def items(&self) -> PyResult<DirstateMapItemsIterator> {
375 def items(&self) -> PyResult<DirstateMapItemsIterator> {
372 let leaked_ref = self.inner(py).leak_immutable();
376 let leaked_ref = self.inner(py).leak_immutable();
373 DirstateMapItemsIterator::from_inner(
377 DirstateMapItemsIterator::from_inner(
374 py,
378 py,
375 unsafe { leaked_ref.map(py, |o| o.iter()) },
379 unsafe { leaked_ref.map(py, |o| o.iter()) },
376 )
380 )
377 }
381 }
378
382
379 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
383 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
380 let leaked_ref = self.inner(py).leak_immutable();
384 let leaked_ref = self.inner(py).leak_immutable();
381 DirstateMapKeysIterator::from_inner(
385 DirstateMapKeysIterator::from_inner(
382 py,
386 py,
383 unsafe { leaked_ref.map(py, |o| o.iter()) },
387 unsafe { leaked_ref.map(py, |o| o.iter()) },
384 )
388 )
385 }
389 }
386
390
387 def getdirs(&self) -> PyResult<Dirs> {
391 def getdirs(&self) -> PyResult<Dirs> {
388 // TODO don't copy, share the reference
392 // TODO don't copy, share the reference
389 self.inner(py).borrow_mut().set_dirs()
393 self.inner(py).borrow_mut().set_dirs()
390 .map_err(|e| {
394 .map_err(|e| {
391 PyErr::new::<exc::ValueError, _>(py, e.to_string())
395 PyErr::new::<exc::ValueError, _>(py, e.to_string())
392 })?;
396 })?;
393 Dirs::from_inner(
397 Dirs::from_inner(
394 py,
398 py,
395 DirsMultiset::from_dirstate(
399 DirsMultiset::from_dirstate(
396 self.inner(py).borrow().iter(),
400 self.inner(py).borrow().iter(),
397 Some(EntryState::Removed),
401 Some(EntryState::Removed),
398 )
402 )
399 .map_err(|e| {
403 .map_err(|e| {
400 PyErr::new::<exc::ValueError, _>(py, e.to_string())
404 PyErr::new::<exc::ValueError, _>(py, e.to_string())
401 })?,
405 })?,
402 )
406 )
403 }
407 }
404 def getalldirs(&self) -> PyResult<Dirs> {
408 def getalldirs(&self) -> PyResult<Dirs> {
405 // TODO don't copy, share the reference
409 // TODO don't copy, share the reference
406 self.inner(py).borrow_mut().set_all_dirs()
410 self.inner(py).borrow_mut().set_all_dirs()
407 .map_err(|e| {
411 .map_err(|e| {
408 PyErr::new::<exc::ValueError, _>(py, e.to_string())
412 PyErr::new::<exc::ValueError, _>(py, e.to_string())
409 })?;
413 })?;
410 Dirs::from_inner(
414 Dirs::from_inner(
411 py,
415 py,
412 DirsMultiset::from_dirstate(
416 DirsMultiset::from_dirstate(
413 self.inner(py).borrow().iter(),
417 self.inner(py).borrow().iter(),
414 None,
418 None,
415 ).map_err(|e| {
419 ).map_err(|e| {
416 PyErr::new::<exc::ValueError, _>(py, e.to_string())
420 PyErr::new::<exc::ValueError, _>(py, e.to_string())
417 })?,
421 })?,
418 )
422 )
419 }
423 }
420
424
421 // TODO all copymap* methods, see docstring above
425 // TODO all copymap* methods, see docstring above
422 def copymapcopy(&self) -> PyResult<PyDict> {
426 def copymapcopy(&self) -> PyResult<PyDict> {
423 let dict = PyDict::new(py);
427 let dict = PyDict::new(py);
424 for (key, value) in self.inner(py).borrow().copy_map_iter() {
428 for (key, value) in self.inner(py).borrow().copy_map_iter() {
425 dict.set_item(
429 dict.set_item(
426 py,
430 py,
427 PyBytes::new(py, key.as_bytes()),
431 PyBytes::new(py, key.as_bytes()),
428 PyBytes::new(py, value.as_bytes()),
432 PyBytes::new(py, value.as_bytes()),
429 )?;
433 )?;
430 }
434 }
431 Ok(dict)
435 Ok(dict)
432 }
436 }
433
437
434 def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
438 def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
435 let key = key.extract::<PyBytes>(py)?;
439 let key = key.extract::<PyBytes>(py)?;
436 match self.inner(py).borrow().copy_map_get(HgPath::new(key.data(py))) {
440 match self.inner(py).borrow().copy_map_get(HgPath::new(key.data(py))) {
437 Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())),
441 Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())),
438 None => Err(PyErr::new::<exc::KeyError, _>(
442 None => Err(PyErr::new::<exc::KeyError, _>(
439 py,
443 py,
440 String::from_utf8_lossy(key.data(py)),
444 String::from_utf8_lossy(key.data(py)),
441 )),
445 )),
442 }
446 }
443 }
447 }
444 def copymap(&self) -> PyResult<CopyMap> {
448 def copymap(&self) -> PyResult<CopyMap> {
445 CopyMap::from_inner(py, self.clone_ref(py))
449 CopyMap::from_inner(py, self.clone_ref(py))
446 }
450 }
447
451
448 def copymaplen(&self) -> PyResult<usize> {
452 def copymaplen(&self) -> PyResult<usize> {
449 Ok(self.inner(py).borrow().copy_map_len())
453 Ok(self.inner(py).borrow().copy_map_len())
450 }
454 }
451 def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
455 def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
452 let key = key.extract::<PyBytes>(py)?;
456 let key = key.extract::<PyBytes>(py)?;
453 Ok(self
457 Ok(self
454 .inner(py)
458 .inner(py)
455 .borrow()
459 .borrow()
456 .copy_map_contains_key(HgPath::new(key.data(py))))
460 .copy_map_contains_key(HgPath::new(key.data(py))))
457 }
461 }
458 def copymapget(
462 def copymapget(
459 &self,
463 &self,
460 key: PyObject,
464 key: PyObject,
461 default: Option<PyObject>
465 default: Option<PyObject>
462 ) -> PyResult<Option<PyObject>> {
466 ) -> PyResult<Option<PyObject>> {
463 let key = key.extract::<PyBytes>(py)?;
467 let key = key.extract::<PyBytes>(py)?;
464 match self
468 match self
465 .inner(py)
469 .inner(py)
466 .borrow()
470 .borrow()
467 .copy_map_get(HgPath::new(key.data(py)))
471 .copy_map_get(HgPath::new(key.data(py)))
468 {
472 {
469 Some(copy) => Ok(Some(
473 Some(copy) => Ok(Some(
470 PyBytes::new(py, copy.as_bytes()).into_object(),
474 PyBytes::new(py, copy.as_bytes()).into_object(),
471 )),
475 )),
472 None => Ok(default),
476 None => Ok(default),
473 }
477 }
474 }
478 }
475 def copymapsetitem(
479 def copymapsetitem(
476 &self,
480 &self,
477 key: PyObject,
481 key: PyObject,
478 value: PyObject
482 value: PyObject
479 ) -> PyResult<PyObject> {
483 ) -> PyResult<PyObject> {
480 let key = key.extract::<PyBytes>(py)?;
484 let key = key.extract::<PyBytes>(py)?;
481 let value = value.extract::<PyBytes>(py)?;
485 let value = value.extract::<PyBytes>(py)?;
482 self.inner(py).borrow_mut().copy_map_insert(
486 self.inner(py).borrow_mut().copy_map_insert(
483 HgPathBuf::from_bytes(key.data(py)),
487 HgPathBuf::from_bytes(key.data(py)),
484 HgPathBuf::from_bytes(value.data(py)),
488 HgPathBuf::from_bytes(value.data(py)),
485 );
489 );
486 Ok(py.None())
490 Ok(py.None())
487 }
491 }
488 def copymappop(
492 def copymappop(
489 &self,
493 &self,
490 key: PyObject,
494 key: PyObject,
491 default: Option<PyObject>
495 default: Option<PyObject>
492 ) -> PyResult<Option<PyObject>> {
496 ) -> PyResult<Option<PyObject>> {
493 let key = key.extract::<PyBytes>(py)?;
497 let key = key.extract::<PyBytes>(py)?;
494 match self
498 match self
495 .inner(py)
499 .inner(py)
496 .borrow_mut()
500 .borrow_mut()
497 .copy_map_remove(HgPath::new(key.data(py)))
501 .copy_map_remove(HgPath::new(key.data(py)))
498 {
502 {
499 Some(_) => Ok(None),
503 Some(_) => Ok(None),
500 None => Ok(default),
504 None => Ok(default),
501 }
505 }
502 }
506 }
503
507
504 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
508 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
505 let leaked_ref = self.inner(py).leak_immutable();
509 let leaked_ref = self.inner(py).leak_immutable();
506 CopyMapKeysIterator::from_inner(
510 CopyMapKeysIterator::from_inner(
507 py,
511 py,
508 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
512 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
509 )
513 )
510 }
514 }
511
515
512 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
516 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
513 let leaked_ref = self.inner(py).leak_immutable();
517 let leaked_ref = self.inner(py).leak_immutable();
514 CopyMapItemsIterator::from_inner(
518 CopyMapItemsIterator::from_inner(
515 py,
519 py,
516 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
520 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
517 )
521 )
518 }
522 }
519
523
520 });
524 });
521
525
522 impl DirstateMap {
526 impl DirstateMap {
523 pub fn get_inner<'a>(
527 pub fn get_inner<'a>(
524 &'a self,
528 &'a self,
525 py: Python<'a>,
529 py: Python<'a>,
526 ) -> Ref<'a, Box<dyn DirstateMapMethods + Send>> {
530 ) -> Ref<'a, Box<dyn DirstateMapMethods + Send>> {
527 self.inner(py).borrow()
531 self.inner(py).borrow()
528 }
532 }
529 fn translate_key(
533 fn translate_key(
530 py: Python,
534 py: Python,
531 res: (&HgPathBuf, &DirstateEntry),
535 res: (&HgPathBuf, &DirstateEntry),
532 ) -> PyResult<Option<PyBytes>> {
536 ) -> PyResult<Option<PyBytes>> {
533 Ok(Some(PyBytes::new(py, res.0.as_bytes())))
537 Ok(Some(PyBytes::new(py, res.0.as_bytes())))
534 }
538 }
535 fn translate_key_value(
539 fn translate_key_value(
536 py: Python,
540 py: Python,
537 res: (&HgPathBuf, &DirstateEntry),
541 res: (&HgPathBuf, &DirstateEntry),
538 ) -> PyResult<Option<(PyBytes, PyObject)>> {
542 ) -> PyResult<Option<(PyBytes, PyObject)>> {
539 let (f, entry) = res;
543 let (f, entry) = res;
540 Ok(Some((
544 Ok(Some((
541 PyBytes::new(py, f.as_bytes()),
545 PyBytes::new(py, f.as_bytes()),
542 make_dirstate_tuple(py, &entry)?,
546 make_dirstate_tuple(py, &entry)?,
543 )))
547 )))
544 }
548 }
545 }
549 }
546
550
547 py_shared_iterator!(
551 py_shared_iterator!(
548 DirstateMapKeysIterator,
552 DirstateMapKeysIterator,
549 UnsafePyLeaked<StateMapIter<'static>>,
553 UnsafePyLeaked<StateMapIter<'static>>,
550 DirstateMap::translate_key,
554 DirstateMap::translate_key,
551 Option<PyBytes>
555 Option<PyBytes>
552 );
556 );
553
557
554 py_shared_iterator!(
558 py_shared_iterator!(
555 DirstateMapItemsIterator,
559 DirstateMapItemsIterator,
556 UnsafePyLeaked<StateMapIter<'static>>,
560 UnsafePyLeaked<StateMapIter<'static>>,
557 DirstateMap::translate_key_value,
561 DirstateMap::translate_key_value,
558 Option<(PyBytes, PyObject)>
562 Option<(PyBytes, PyObject)>
559 );
563 );
560
564
561 fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<Node> {
565 fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<Node> {
562 let bytes = obj.extract::<PyBytes>(py)?;
566 let bytes = obj.extract::<PyBytes>(py)?;
563 match bytes.data(py).try_into() {
567 match bytes.data(py).try_into() {
564 Ok(s) => Ok(s),
568 Ok(s) => Ok(s),
565 Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())),
569 Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())),
566 }
570 }
567 }
571 }
General Comments 0
You need to be logged in to leave comments. Login now