Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/sparse.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | d783f945a701 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
42 excludes = set() | 42 excludes = set() |
43 profiles = set() | 43 profiles = set() |
44 current = None | 44 current = None |
45 havesection = False | 45 havesection = False |
46 | 46 |
47 for line in raw.split('\n'): | 47 for line in raw.split(b'\n'): |
48 line = line.strip() | 48 line = line.strip() |
49 if not line or line.startswith('#'): | 49 if not line or line.startswith(b'#'): |
50 # empty or comment line, skip | 50 # empty or comment line, skip |
51 continue | 51 continue |
52 elif line.startswith('%include '): | 52 elif line.startswith(b'%include '): |
53 line = line[9:].strip() | 53 line = line[9:].strip() |
54 if line: | 54 if line: |
55 profiles.add(line) | 55 profiles.add(line) |
56 elif line == '[include]': | 56 elif line == b'[include]': |
57 if havesection and current != includes: | 57 if havesection and current != includes: |
58 # TODO pass filename into this API so we can report it. | 58 # TODO pass filename into this API so we can report it. |
59 raise error.Abort( | 59 raise error.Abort( |
60 _( | 60 _( |
61 '%(action)s config cannot have includes ' | 61 b'%(action)s config cannot have includes ' |
62 'after excludes' | 62 b'after excludes' |
63 ) | 63 ) |
64 % {'action': action} | 64 % {b'action': action} |
65 ) | 65 ) |
66 havesection = True | 66 havesection = True |
67 current = includes | 67 current = includes |
68 continue | 68 continue |
69 elif line == '[exclude]': | 69 elif line == b'[exclude]': |
70 havesection = True | 70 havesection = True |
71 current = excludes | 71 current = excludes |
72 elif line: | 72 elif line: |
73 if current is None: | 73 if current is None: |
74 raise error.Abort( | 74 raise error.Abort( |
75 _('%(action)s config entry outside of ' 'section: %(line)s') | 75 _( |
76 % {'action': action, 'line': line}, | 76 b'%(action)s config entry outside of ' |
77 b'section: %(line)s' | |
78 ) | |
79 % {b'action': action, b'line': line}, | |
77 hint=_( | 80 hint=_( |
78 'add an [include] or [exclude] line ' | 81 b'add an [include] or [exclude] line ' |
79 'to declare the entry type' | 82 b'to declare the entry type' |
80 ), | 83 ), |
81 ) | 84 ) |
82 | 85 |
83 if line.strip().startswith('/'): | 86 if line.strip().startswith(b'/'): |
84 ui.warn( | 87 ui.warn( |
85 _( | 88 _( |
86 'warning: %(action)s profile cannot use' | 89 b'warning: %(action)s profile cannot use' |
87 ' paths starting with /, ignoring %(line)s\n' | 90 b' paths starting with /, ignoring %(line)s\n' |
88 ) | 91 ) |
89 % {'action': action, 'line': line} | 92 % {b'action': action, b'line': line} |
90 ) | 93 ) |
91 continue | 94 continue |
92 current.add(line) | 95 current.add(line) |
93 | 96 |
94 return includes, excludes, profiles | 97 return includes, excludes, profiles |
110 """ | 113 """ |
111 # Feature isn't enabled. No-op. | 114 # Feature isn't enabled. No-op. |
112 if not enabled: | 115 if not enabled: |
113 return set(), set(), set() | 116 return set(), set(), set() |
114 | 117 |
115 raw = repo.vfs.tryread('sparse') | 118 raw = repo.vfs.tryread(b'sparse') |
116 if not raw: | 119 if not raw: |
117 return set(), set(), set() | 120 return set(), set(), set() |
118 | 121 |
119 if rev is None: | 122 if rev is None: |
120 raise error.Abort( | 123 raise error.Abort( |
121 _('cannot parse sparse patterns from working ' 'directory') | 124 _(b'cannot parse sparse patterns from working ' b'directory') |
122 ) | 125 ) |
123 | 126 |
124 includes, excludes, profiles = parseconfig(repo.ui, raw, 'sparse') | 127 includes, excludes, profiles = parseconfig(repo.ui, raw, b'sparse') |
125 ctx = repo[rev] | 128 ctx = repo[rev] |
126 | 129 |
127 if profiles: | 130 if profiles: |
128 visited = set() | 131 visited = set() |
129 while profiles: | 132 while profiles: |
135 | 138 |
136 try: | 139 try: |
137 raw = readprofile(repo, profile, rev) | 140 raw = readprofile(repo, profile, rev) |
138 except error.ManifestLookupError: | 141 except error.ManifestLookupError: |
139 msg = ( | 142 msg = ( |
140 "warning: sparse profile '%s' not found " | 143 b"warning: sparse profile '%s' not found " |
141 "in rev %s - ignoring it\n" % (profile, ctx) | 144 b"in rev %s - ignoring it\n" % (profile, ctx) |
142 ) | 145 ) |
143 # experimental config: sparse.missingwarning | 146 # experimental config: sparse.missingwarning |
144 if repo.ui.configbool('sparse', 'missingwarning'): | 147 if repo.ui.configbool(b'sparse', b'missingwarning'): |
145 repo.ui.warn(msg) | 148 repo.ui.warn(msg) |
146 else: | 149 else: |
147 repo.ui.debug(msg) | 150 repo.ui.debug(msg) |
148 continue | 151 continue |
149 | 152 |
150 pincludes, pexcludes, subprofs = parseconfig(repo.ui, raw, 'sparse') | 153 pincludes, pexcludes, subprofs = parseconfig( |
154 repo.ui, raw, b'sparse' | |
155 ) | |
151 includes.update(pincludes) | 156 includes.update(pincludes) |
152 excludes.update(pexcludes) | 157 excludes.update(pexcludes) |
153 profiles.update(subprofs) | 158 profiles.update(subprofs) |
154 | 159 |
155 profiles = visited | 160 profiles = visited |
156 | 161 |
157 if includes: | 162 if includes: |
158 includes.add('.hg*') | 163 includes.add(b'.hg*') |
159 | 164 |
160 return includes, excludes, profiles | 165 return includes, excludes, profiles |
161 | 166 |
162 | 167 |
163 def activeconfig(repo): | 168 def activeconfig(repo): |
190 | 195 |
191 This is used to construct a cache key for matchers. | 196 This is used to construct a cache key for matchers. |
192 """ | 197 """ |
193 cache = repo._sparsesignaturecache | 198 cache = repo._sparsesignaturecache |
194 | 199 |
195 signature = cache.get('signature') | 200 signature = cache.get(b'signature') |
196 | 201 |
197 if includetemp: | 202 if includetemp: |
198 tempsignature = cache.get('tempsignature') | 203 tempsignature = cache.get(b'tempsignature') |
199 else: | 204 else: |
200 tempsignature = '0' | 205 tempsignature = b'0' |
201 | 206 |
202 if signature is None or (includetemp and tempsignature is None): | 207 if signature is None or (includetemp and tempsignature is None): |
203 signature = hex(hashlib.sha1(repo.vfs.tryread('sparse')).digest()) | 208 signature = hex(hashlib.sha1(repo.vfs.tryread(b'sparse')).digest()) |
204 cache['signature'] = signature | 209 cache[b'signature'] = signature |
205 | 210 |
206 if includetemp: | 211 if includetemp: |
207 raw = repo.vfs.tryread('tempsparse') | 212 raw = repo.vfs.tryread(b'tempsparse') |
208 tempsignature = hex(hashlib.sha1(raw).digest()) | 213 tempsignature = hex(hashlib.sha1(raw).digest()) |
209 cache['tempsignature'] = tempsignature | 214 cache[b'tempsignature'] = tempsignature |
210 | 215 |
211 return '%s %s' % (signature, tempsignature) | 216 return b'%s %s' % (signature, tempsignature) |
212 | 217 |
213 | 218 |
214 def writeconfig(repo, includes, excludes, profiles): | 219 def writeconfig(repo, includes, excludes, profiles): |
215 """Write the sparse config file given a sparse configuration.""" | 220 """Write the sparse config file given a sparse configuration.""" |
216 with repo.vfs('sparse', 'wb') as fh: | 221 with repo.vfs(b'sparse', b'wb') as fh: |
217 for p in sorted(profiles): | 222 for p in sorted(profiles): |
218 fh.write('%%include %s\n' % p) | 223 fh.write(b'%%include %s\n' % p) |
219 | 224 |
220 if includes: | 225 if includes: |
221 fh.write('[include]\n') | 226 fh.write(b'[include]\n') |
222 for i in sorted(includes): | 227 for i in sorted(includes): |
223 fh.write(i) | 228 fh.write(i) |
224 fh.write('\n') | 229 fh.write(b'\n') |
225 | 230 |
226 if excludes: | 231 if excludes: |
227 fh.write('[exclude]\n') | 232 fh.write(b'[exclude]\n') |
228 for e in sorted(excludes): | 233 for e in sorted(excludes): |
229 fh.write(e) | 234 fh.write(e) |
230 fh.write('\n') | 235 fh.write(b'\n') |
231 | 236 |
232 repo._sparsesignaturecache.clear() | 237 repo._sparsesignaturecache.clear() |
233 | 238 |
234 | 239 |
235 def readtemporaryincludes(repo): | 240 def readtemporaryincludes(repo): |
236 raw = repo.vfs.tryread('tempsparse') | 241 raw = repo.vfs.tryread(b'tempsparse') |
237 if not raw: | 242 if not raw: |
238 return set() | 243 return set() |
239 | 244 |
240 return set(raw.split('\n')) | 245 return set(raw.split(b'\n')) |
241 | 246 |
242 | 247 |
243 def writetemporaryincludes(repo, includes): | 248 def writetemporaryincludes(repo, includes): |
244 repo.vfs.write('tempsparse', '\n'.join(sorted(includes))) | 249 repo.vfs.write(b'tempsparse', b'\n'.join(sorted(includes))) |
245 repo._sparsesignaturecache.clear() | 250 repo._sparsesignaturecache.clear() |
246 | 251 |
247 | 252 |
248 def addtemporaryincludes(repo, additional): | 253 def addtemporaryincludes(repo, additional): |
249 includes = readtemporaryincludes(repo) | 254 includes = readtemporaryincludes(repo) |
251 includes.add(i) | 256 includes.add(i) |
252 writetemporaryincludes(repo, includes) | 257 writetemporaryincludes(repo, includes) |
253 | 258 |
254 | 259 |
255 def prunetemporaryincludes(repo): | 260 def prunetemporaryincludes(repo): |
256 if not enabled or not repo.vfs.exists('tempsparse'): | 261 if not enabled or not repo.vfs.exists(b'tempsparse'): |
257 return | 262 return |
258 | 263 |
259 s = repo.status() | 264 s = repo.status() |
260 if s.modified or s.added or s.removed or s.deleted: | 265 if s.modified or s.added or s.removed or s.deleted: |
261 # Still have pending changes. Don't bother trying to prune. | 266 # Still have pending changes. Don't bother trying to prune. |
266 actions = [] | 271 actions = [] |
267 dropped = [] | 272 dropped = [] |
268 tempincludes = readtemporaryincludes(repo) | 273 tempincludes = readtemporaryincludes(repo) |
269 for file in tempincludes: | 274 for file in tempincludes: |
270 if file in dirstate and not sparsematch(file): | 275 if file in dirstate and not sparsematch(file): |
271 message = _('dropping temporarily included sparse files') | 276 message = _(b'dropping temporarily included sparse files') |
272 actions.append((file, None, message)) | 277 actions.append((file, None, message)) |
273 dropped.append(file) | 278 dropped.append(file) |
274 | 279 |
275 typeactions = mergemod.emptyactions() | 280 typeactions = mergemod.emptyactions() |
276 typeactions['r'] = actions | 281 typeactions[b'r'] = actions |
277 mergemod.applyupdates( | 282 mergemod.applyupdates( |
278 repo, typeactions, repo[None], repo['.'], False, wantfiledata=False | 283 repo, typeactions, repo[None], repo[b'.'], False, wantfiledata=False |
279 ) | 284 ) |
280 | 285 |
281 # Fix dirstate | 286 # Fix dirstate |
282 for file in dropped: | 287 for file in dropped: |
283 dirstate.drop(file) | 288 dirstate.drop(file) |
284 | 289 |
285 repo.vfs.unlink('tempsparse') | 290 repo.vfs.unlink(b'tempsparse') |
286 repo._sparsesignaturecache.clear() | 291 repo._sparsesignaturecache.clear() |
287 msg = _( | 292 msg = _( |
288 'cleaned up %d temporarily added file(s) from the ' 'sparse checkout\n' | 293 b'cleaned up %d temporarily added file(s) from the ' |
294 b'sparse checkout\n' | |
289 ) | 295 ) |
290 repo.ui.status(msg % len(tempincludes)) | 296 repo.ui.status(msg % len(tempincludes)) |
291 | 297 |
292 | 298 |
293 def forceincludematcher(matcher, includes): | 299 def forceincludematcher(matcher, includes): |
294 """Returns a matcher that returns true for any of the forced includes | 300 """Returns a matcher that returns true for any of the forced includes |
295 before testing against the actual matcher.""" | 301 before testing against the actual matcher.""" |
296 kindpats = [('path', include, '') for include in includes] | 302 kindpats = [(b'path', include, b'') for include in includes] |
297 includematcher = matchmod.includematcher('', kindpats) | 303 includematcher = matchmod.includematcher(b'', kindpats) |
298 return matchmod.unionmatcher([includematcher, matcher]) | 304 return matchmod.unionmatcher([includematcher, matcher]) |
299 | 305 |
300 | 306 |
301 def matcher(repo, revs=None, includetemp=True): | 307 def matcher(repo, revs=None, includetemp=True): |
302 """Obtain a matcher for sparse working directories for the given revs. | 308 """Obtain a matcher for sparse working directories for the given revs. |
317 if node != nullid | 323 if node != nullid |
318 ] | 324 ] |
319 | 325 |
320 signature = configsignature(repo, includetemp=includetemp) | 326 signature = configsignature(repo, includetemp=includetemp) |
321 | 327 |
322 key = '%s %s' % (signature, ' '.join(map(pycompat.bytestr, revs))) | 328 key = b'%s %s' % (signature, b' '.join(map(pycompat.bytestr, revs))) |
323 | 329 |
324 result = repo._sparsematchercache.get(key) | 330 result = repo._sparsematchercache.get(key) |
325 if result: | 331 if result: |
326 return result | 332 return result |
327 | 333 |
331 includes, excludes, profiles = patternsforrev(repo, rev) | 337 includes, excludes, profiles = patternsforrev(repo, rev) |
332 | 338 |
333 if includes or excludes: | 339 if includes or excludes: |
334 matcher = matchmod.match( | 340 matcher = matchmod.match( |
335 repo.root, | 341 repo.root, |
336 '', | 342 b'', |
337 [], | 343 [], |
338 include=includes, | 344 include=includes, |
339 exclude=excludes, | 345 exclude=excludes, |
340 default='relpath', | 346 default=b'relpath', |
341 ) | 347 ) |
342 matchers.append(matcher) | 348 matchers.append(matcher) |
343 except IOError: | 349 except IOError: |
344 pass | 350 pass |
345 | 351 |
386 for file, action in actions.iteritems(): | 392 for file, action in actions.iteritems(): |
387 type, args, msg = action | 393 type, args, msg = action |
388 files.add(file) | 394 files.add(file) |
389 if sparsematch(file): | 395 if sparsematch(file): |
390 prunedactions[file] = action | 396 prunedactions[file] = action |
391 elif type == 'm': | 397 elif type == b'm': |
392 temporaryfiles.append(file) | 398 temporaryfiles.append(file) |
393 prunedactions[file] = action | 399 prunedactions[file] = action |
394 elif branchmerge: | 400 elif branchmerge: |
395 if type != 'k': | 401 if type != b'k': |
396 temporaryfiles.append(file) | 402 temporaryfiles.append(file) |
397 prunedactions[file] = action | 403 prunedactions[file] = action |
398 elif type == 'f': | 404 elif type == b'f': |
399 prunedactions[file] = action | 405 prunedactions[file] = action |
400 elif file in wctx: | 406 elif file in wctx: |
401 prunedactions[file] = ('r', args, msg) | 407 prunedactions[file] = (b'r', args, msg) |
402 | 408 |
403 if branchmerge and type == mergemod.ACTION_MERGE: | 409 if branchmerge and type == mergemod.ACTION_MERGE: |
404 f1, f2, fa, move, anc = args | 410 f1, f2, fa, move, anc = args |
405 if not sparsematch(f1): | 411 if not sparsematch(f1): |
406 temporaryfiles.append(f1) | 412 temporaryfiles.append(f1) |
407 | 413 |
408 if len(temporaryfiles) > 0: | 414 if len(temporaryfiles) > 0: |
409 repo.ui.status( | 415 repo.ui.status( |
410 _( | 416 _( |
411 'temporarily included %d file(s) in the sparse ' | 417 b'temporarily included %d file(s) in the sparse ' |
412 'checkout for merging\n' | 418 b'checkout for merging\n' |
413 ) | 419 ) |
414 % len(temporaryfiles) | 420 % len(temporaryfiles) |
415 ) | 421 ) |
416 addtemporaryincludes(repo, temporaryfiles) | 422 addtemporaryincludes(repo, temporaryfiles) |
417 | 423 |
418 # Add the new files to the working copy so they can be merged, etc | 424 # Add the new files to the working copy so they can be merged, etc |
419 actions = [] | 425 actions = [] |
420 message = 'temporarily adding to sparse checkout' | 426 message = b'temporarily adding to sparse checkout' |
421 wctxmanifest = repo[None].manifest() | 427 wctxmanifest = repo[None].manifest() |
422 for file in temporaryfiles: | 428 for file in temporaryfiles: |
423 if file in wctxmanifest: | 429 if file in wctxmanifest: |
424 fctx = repo[None][file] | 430 fctx = repo[None][file] |
425 actions.append((file, (fctx.flags(), False), message)) | 431 actions.append((file, (fctx.flags(), False), message)) |
426 | 432 |
427 typeactions = mergemod.emptyactions() | 433 typeactions = mergemod.emptyactions() |
428 typeactions['g'] = actions | 434 typeactions[b'g'] = actions |
429 mergemod.applyupdates( | 435 mergemod.applyupdates( |
430 repo, typeactions, repo[None], repo['.'], False, wantfiledata=False | 436 repo, typeactions, repo[None], repo[b'.'], False, wantfiledata=False |
431 ) | 437 ) |
432 | 438 |
433 dirstate = repo.dirstate | 439 dirstate = repo.dirstate |
434 for file, flags, msg in actions: | 440 for file, flags, msg in actions: |
435 dirstate.normal(file) | 441 dirstate.normal(file) |
444 for file in mf: | 450 for file in mf: |
445 old = oldsparsematch(file) | 451 old = oldsparsematch(file) |
446 new = sparsematch(file) | 452 new = sparsematch(file) |
447 if not old and new: | 453 if not old and new: |
448 flags = mf.flags(file) | 454 flags = mf.flags(file) |
449 prunedactions[file] = ('g', (flags, False), '') | 455 prunedactions[file] = (b'g', (flags, False), b'') |
450 elif old and not new: | 456 elif old and not new: |
451 prunedactions[file] = ('r', [], '') | 457 prunedactions[file] = (b'r', [], b'') |
452 | 458 |
453 return prunedactions | 459 return prunedactions |
454 | 460 |
455 | 461 |
456 def refreshwdir(repo, origstatus, origsparsematch, force=False): | 462 def refreshwdir(repo, origstatus, origsparsematch, force=False): |
470 sparsematch = matcher(repo) | 476 sparsematch = matcher(repo) |
471 abort = False | 477 abort = False |
472 | 478 |
473 for f in pending: | 479 for f in pending: |
474 if not sparsematch(f): | 480 if not sparsematch(f): |
475 repo.ui.warn(_("pending changes to '%s'\n") % f) | 481 repo.ui.warn(_(b"pending changes to '%s'\n") % f) |
476 abort = not force | 482 abort = not force |
477 | 483 |
478 if abort: | 484 if abort: |
479 raise error.Abort( | 485 raise error.Abort( |
480 _('could not update sparseness due to pending ' 'changes') | 486 _(b'could not update sparseness due to pending ' b'changes') |
481 ) | 487 ) |
482 | 488 |
483 # Calculate actions | 489 # Calculate actions |
484 dirstate = repo.dirstate | 490 dirstate = repo.dirstate |
485 ctx = repo['.'] | 491 ctx = repo[b'.'] |
486 added = [] | 492 added = [] |
487 lookup = [] | 493 lookup = [] |
488 dropped = [] | 494 dropped = [] |
489 mf = ctx.manifest() | 495 mf = ctx.manifest() |
490 files = set(mf) | 496 files = set(mf) |
497 # Add files that are newly included, or that don't exist in | 503 # Add files that are newly included, or that don't exist in |
498 # the dirstate yet. | 504 # the dirstate yet. |
499 if (new and not old) or (old and new and not file in dirstate): | 505 if (new and not old) or (old and new and not file in dirstate): |
500 fl = mf.flags(file) | 506 fl = mf.flags(file) |
501 if repo.wvfs.exists(file): | 507 if repo.wvfs.exists(file): |
502 actions[file] = ('e', (fl,), '') | 508 actions[file] = (b'e', (fl,), b'') |
503 lookup.append(file) | 509 lookup.append(file) |
504 else: | 510 else: |
505 actions[file] = ('g', (fl, False), '') | 511 actions[file] = (b'g', (fl, False), b'') |
506 added.append(file) | 512 added.append(file) |
507 # Drop files that are newly excluded, or that still exist in | 513 # Drop files that are newly excluded, or that still exist in |
508 # the dirstate. | 514 # the dirstate. |
509 elif (old and not new) or (not old and not new and file in dirstate): | 515 elif (old and not new) or (not old and not new and file in dirstate): |
510 dropped.append(file) | 516 dropped.append(file) |
511 if file not in pending: | 517 if file not in pending: |
512 actions[file] = ('r', [], '') | 518 actions[file] = (b'r', [], b'') |
513 | 519 |
514 # Verify there are no pending changes in newly included files | 520 # Verify there are no pending changes in newly included files |
515 abort = False | 521 abort = False |
516 for file in lookup: | 522 for file in lookup: |
517 repo.ui.warn(_("pending changes to '%s'\n") % file) | 523 repo.ui.warn(_(b"pending changes to '%s'\n") % file) |
518 abort = not force | 524 abort = not force |
519 if abort: | 525 if abort: |
520 raise error.Abort( | 526 raise error.Abort( |
521 _( | 527 _( |
522 'cannot change sparseness due to pending ' | 528 b'cannot change sparseness due to pending ' |
523 'changes (delete the files or use ' | 529 b'changes (delete the files or use ' |
524 '--force to bring them back dirty)' | 530 b'--force to bring them back dirty)' |
525 ) | 531 ) |
526 ) | 532 ) |
527 | 533 |
528 # Check for files that were only in the dirstate. | 534 # Check for files that were only in the dirstate. |
529 for file, state in dirstate.iteritems(): | 535 for file, state in dirstate.iteritems(): |
537 typeactions = mergemod.emptyactions() | 543 typeactions = mergemod.emptyactions() |
538 for f, (m, args, msg) in actions.iteritems(): | 544 for f, (m, args, msg) in actions.iteritems(): |
539 typeactions[m].append((f, args, msg)) | 545 typeactions[m].append((f, args, msg)) |
540 | 546 |
541 mergemod.applyupdates( | 547 mergemod.applyupdates( |
542 repo, typeactions, repo[None], repo['.'], False, wantfiledata=False | 548 repo, typeactions, repo[None], repo[b'.'], False, wantfiledata=False |
543 ) | 549 ) |
544 | 550 |
545 # Fix dirstate | 551 # Fix dirstate |
546 for file in added: | 552 for file in added: |
547 dirstate.normal(file) | 553 dirstate.normal(file) |
575 | 581 |
576 def _updateconfigandrefreshwdir( | 582 def _updateconfigandrefreshwdir( |
577 repo, includes, excludes, profiles, force=False, removing=False | 583 repo, includes, excludes, profiles, force=False, removing=False |
578 ): | 584 ): |
579 """Update the sparse config and working directory state.""" | 585 """Update the sparse config and working directory state.""" |
580 raw = repo.vfs.tryread('sparse') | 586 raw = repo.vfs.tryread(b'sparse') |
581 oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw, 'sparse') | 587 oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw, b'sparse') |
582 | 588 |
583 oldstatus = repo.status() | 589 oldstatus = repo.status() |
584 oldmatch = matcher(repo) | 590 oldmatch = matcher(repo) |
585 oldrequires = set(repo.requirements) | 591 oldrequires = set(repo.requirements) |
586 | 592 |
590 # re-read. We ideally want to update the cached matcher on the | 596 # re-read. We ideally want to update the cached matcher on the |
591 # repo instance then flush the new config to disk once wdir is | 597 # repo instance then flush the new config to disk once wdir is |
592 # updated. But this requires massive rework to matcher() and its | 598 # updated. But this requires massive rework to matcher() and its |
593 # consumers. | 599 # consumers. |
594 | 600 |
595 if 'exp-sparse' in oldrequires and removing: | 601 if b'exp-sparse' in oldrequires and removing: |
596 repo.requirements.discard('exp-sparse') | 602 repo.requirements.discard(b'exp-sparse') |
597 scmutil.writerequires(repo.vfs, repo.requirements) | 603 scmutil.writerequires(repo.vfs, repo.requirements) |
598 elif 'exp-sparse' not in oldrequires: | 604 elif b'exp-sparse' not in oldrequires: |
599 repo.requirements.add('exp-sparse') | 605 repo.requirements.add(b'exp-sparse') |
600 scmutil.writerequires(repo.vfs, repo.requirements) | 606 scmutil.writerequires(repo.vfs, repo.requirements) |
601 | 607 |
602 try: | 608 try: |
603 writeconfig(repo, includes, excludes, profiles) | 609 writeconfig(repo, includes, excludes, profiles) |
604 return refreshwdir(repo, oldstatus, oldmatch, force=force) | 610 return refreshwdir(repo, oldstatus, oldmatch, force=force) |
616 | 622 |
617 The remaining sparse config only has profiles, if defined. The working | 623 The remaining sparse config only has profiles, if defined. The working |
618 directory is refreshed, as needed. | 624 directory is refreshed, as needed. |
619 """ | 625 """ |
620 with repo.wlock(): | 626 with repo.wlock(): |
621 raw = repo.vfs.tryread('sparse') | 627 raw = repo.vfs.tryread(b'sparse') |
622 includes, excludes, profiles = parseconfig(repo.ui, raw, 'sparse') | 628 includes, excludes, profiles = parseconfig(repo.ui, raw, b'sparse') |
623 | 629 |
624 if not includes and not excludes: | 630 if not includes and not excludes: |
625 return | 631 return |
626 | 632 |
627 _updateconfigandrefreshwdir(repo, set(), set(), profiles, force=force) | 633 _updateconfigandrefreshwdir(repo, set(), set(), profiles, force=force) |
633 The updated sparse config is written out and the working directory | 639 The updated sparse config is written out and the working directory |
634 is refreshed, as needed. | 640 is refreshed, as needed. |
635 """ | 641 """ |
636 with repo.wlock(): | 642 with repo.wlock(): |
637 # read current configuration | 643 # read current configuration |
638 raw = repo.vfs.tryread('sparse') | 644 raw = repo.vfs.tryread(b'sparse') |
639 includes, excludes, profiles = parseconfig(repo.ui, raw, 'sparse') | 645 includes, excludes, profiles = parseconfig(repo.ui, raw, b'sparse') |
640 aincludes, aexcludes, aprofiles = activeconfig(repo) | 646 aincludes, aexcludes, aprofiles = activeconfig(repo) |
641 | 647 |
642 # Import rules on top; only take in rules that are not yet | 648 # Import rules on top; only take in rules that are not yet |
643 # part of the active rules. | 649 # part of the active rules. |
644 changed = False | 650 changed = False |
645 for p in paths: | 651 for p in paths: |
646 with util.posixfile(util.expandpath(p), mode='rb') as fh: | 652 with util.posixfile(util.expandpath(p), mode=b'rb') as fh: |
647 raw = fh.read() | 653 raw = fh.read() |
648 | 654 |
649 iincludes, iexcludes, iprofiles = parseconfig( | 655 iincludes, iexcludes, iprofiles = parseconfig( |
650 repo.ui, raw, 'sparse' | 656 repo.ui, raw, b'sparse' |
651 ) | 657 ) |
652 oldsize = len(includes) + len(excludes) + len(profiles) | 658 oldsize = len(includes) + len(excludes) + len(profiles) |
653 includes.update(iincludes - aincludes) | 659 includes.update(iincludes - aincludes) |
654 excludes.update(iexcludes - aexcludes) | 660 excludes.update(iexcludes - aexcludes) |
655 profiles.update(iprofiles - aprofiles) | 661 profiles.update(iprofiles - aprofiles) |
694 Only one of the actions may be performed. | 700 Only one of the actions may be performed. |
695 | 701 |
696 The new config is written out and a working directory refresh is performed. | 702 The new config is written out and a working directory refresh is performed. |
697 """ | 703 """ |
698 with repo.wlock(): | 704 with repo.wlock(): |
699 raw = repo.vfs.tryread('sparse') | 705 raw = repo.vfs.tryread(b'sparse') |
700 oldinclude, oldexclude, oldprofiles = parseconfig( | 706 oldinclude, oldexclude, oldprofiles = parseconfig( |
701 repo.ui, raw, 'sparse' | 707 repo.ui, raw, b'sparse' |
702 ) | 708 ) |
703 | 709 |
704 if reset: | 710 if reset: |
705 newinclude = set() | 711 newinclude = set() |
706 newexclude = set() | 712 newexclude = set() |
709 newinclude = set(oldinclude) | 715 newinclude = set(oldinclude) |
710 newexclude = set(oldexclude) | 716 newexclude = set(oldexclude) |
711 newprofiles = set(oldprofiles) | 717 newprofiles = set(oldprofiles) |
712 | 718 |
713 if any(os.path.isabs(pat) for pat in pats): | 719 if any(os.path.isabs(pat) for pat in pats): |
714 raise error.Abort(_('paths cannot be absolute')) | 720 raise error.Abort(_(b'paths cannot be absolute')) |
715 | 721 |
716 if not usereporootpaths: | 722 if not usereporootpaths: |
717 # let's treat paths as relative to cwd | 723 # let's treat paths as relative to cwd |
718 root, cwd = repo.root, repo.getcwd() | 724 root, cwd = repo.root, repo.getcwd() |
719 abspats = [] | 725 abspats = [] |
720 for kindpat in pats: | 726 for kindpat in pats: |
721 kind, pat = matchmod._patsplit(kindpat, None) | 727 kind, pat = matchmod._patsplit(kindpat, None) |
722 if kind in matchmod.cwdrelativepatternkinds or kind is None: | 728 if kind in matchmod.cwdrelativepatternkinds or kind is None: |
723 ap = (kind + ':' if kind else '') + pathutil.canonpath( | 729 ap = (kind + b':' if kind else b'') + pathutil.canonpath( |
724 root, cwd, pat | 730 root, cwd, pat |
725 ) | 731 ) |
726 abspats.append(ap) | 732 abspats.append(ap) |
727 else: | 733 else: |
728 abspats.append(kindpat) | 734 abspats.append(kindpat) |
776 added=0, | 782 added=0, |
777 dropped=0, | 783 dropped=0, |
778 conflicting=0, | 784 conflicting=0, |
779 ): | 785 ): |
780 """Print output summarizing sparse config changes.""" | 786 """Print output summarizing sparse config changes.""" |
781 with ui.formatter('sparse', opts) as fm: | 787 with ui.formatter(b'sparse', opts) as fm: |
782 fm.startitem() | 788 fm.startitem() |
783 fm.condwrite( | 789 fm.condwrite( |
784 ui.verbose, | 790 ui.verbose, |
785 'profiles_added', | 791 b'profiles_added', |
786 _('Profiles changed: %d\n'), | 792 _(b'Profiles changed: %d\n'), |
787 profilecount, | 793 profilecount, |
788 ) | 794 ) |
789 fm.condwrite( | 795 fm.condwrite( |
790 ui.verbose, | 796 ui.verbose, |
791 'include_rules_added', | 797 b'include_rules_added', |
792 _('Include rules changed: %d\n'), | 798 _(b'Include rules changed: %d\n'), |
793 includecount, | 799 includecount, |
794 ) | 800 ) |
795 fm.condwrite( | 801 fm.condwrite( |
796 ui.verbose, | 802 ui.verbose, |
797 'exclude_rules_added', | 803 b'exclude_rules_added', |
798 _('Exclude rules changed: %d\n'), | 804 _(b'Exclude rules changed: %d\n'), |
799 excludecount, | 805 excludecount, |
800 ) | 806 ) |
801 | 807 |
802 # In 'plain' verbose mode, mergemod.applyupdates already outputs what | 808 # In 'plain' verbose mode, mergemod.applyupdates already outputs what |
803 # files are added or removed outside of the templating formatter | 809 # files are added or removed outside of the templating formatter |
804 # framework. No point in repeating ourselves in that case. | 810 # framework. No point in repeating ourselves in that case. |
805 if not fm.isplain(): | 811 if not fm.isplain(): |
806 fm.condwrite( | 812 fm.condwrite( |
807 ui.verbose, 'files_added', _('Files added: %d\n'), added | 813 ui.verbose, b'files_added', _(b'Files added: %d\n'), added |
808 ) | 814 ) |
809 fm.condwrite( | 815 fm.condwrite( |
810 ui.verbose, 'files_dropped', _('Files dropped: %d\n'), dropped | 816 ui.verbose, b'files_dropped', _(b'Files dropped: %d\n'), dropped |
811 ) | 817 ) |
812 fm.condwrite( | 818 fm.condwrite( |
813 ui.verbose, | 819 ui.verbose, |
814 'files_conflicting', | 820 b'files_conflicting', |
815 _('Files conflicting: %d\n'), | 821 _(b'Files conflicting: %d\n'), |
816 conflicting, | 822 conflicting, |
817 ) | 823 ) |