mercurial/sparse.py
changeset 33555 6755b719048c
parent 33551 1d1779734c99
child 33556 22371eabb3b1
equal deleted inserted replaced
33554:2943141f5e07 33555:6755b719048c
   519         origsparsematch = matcher(repo)
   519         origsparsematch = matcher(repo)
   520         refreshwdir(repo, origstatus, origsparsematch, force=True)
   520         refreshwdir(repo, origstatus, origsparsematch, force=True)
   521 
   521 
   522     prunetemporaryincludes(repo)
   522     prunetemporaryincludes(repo)
   523 
   523 
       
   524 def _updateconfigandrefreshwdir(repo, includes, excludes, profiles,
       
   525                                 force=False):
       
   526     """Update the sparse config and working directory state."""
       
   527     raw = repo.vfs.tryread('sparse')
       
   528     oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw)
       
   529 
       
   530     oldstatus = repo.status()
       
   531     oldmatch = matcher(repo)
       
   532 
       
   533     # TODO remove this try..except once the matcher integrates better
       
   534     # with dirstate. We currently have to write the updated config
       
   535     # because that will invalidate the matcher cache and force a
       
   536     # re-read. We ideally want to update the cached matcher on the
       
   537     # repo instance then flush the new config to disk once wdir is
       
   538     # updated. But this requires massive rework to matcher() and its
       
   539     # consumers.
       
   540 
       
   541     writeconfig(repo, includes, excludes, profiles)
       
   542 
       
   543     try:
       
   544         return refreshwdir(repo, oldstatus, oldmatch, force=force)
       
   545     except Exception:
       
   546         writeconfig(repo, oldincludes, oldexcludes, oldprofiles)
       
   547         raise
       
   548 
   524 def clearrules(repo, force=False):
   549 def clearrules(repo, force=False):
   525     """Clears include/exclude rules from the sparse config.
   550     """Clears include/exclude rules from the sparse config.
   526 
   551 
   527     The remaining sparse config only has profiles, if defined. The working
   552     The remaining sparse config only has profiles, if defined. The working
   528     directory is refreshed, as needed.
   553     directory is refreshed, as needed.
   532         includes, excludes, profiles = parseconfig(repo.ui, raw)
   557         includes, excludes, profiles = parseconfig(repo.ui, raw)
   533 
   558 
   534         if not includes and not excludes:
   559         if not includes and not excludes:
   535             return
   560             return
   536 
   561 
   537         oldstatus = repo.status()
   562         _updateconfigandrefreshwdir(repo, set(), set(), profiles, force=force)
   538         oldmatch = matcher(repo)
       
   539         writeconfig(repo, set(), set(), profiles)
       
   540         refreshwdir(repo, oldstatus, oldmatch, force=force)
       
   541 
   563 
   542 def importfromfiles(repo, opts, paths, force=False):
   564 def importfromfiles(repo, opts, paths, force=False):
   543     """Import sparse config rules from files.
   565     """Import sparse config rules from files.
   544 
   566 
   545     The updated sparse config is written out and the working directory
   567     The updated sparse config is written out and the working directory
   546     is refreshed, as needed.
   568     is refreshed, as needed.
   547     """
   569     """
   548     with repo.wlock():
   570     with repo.wlock():
   549         # read current configuration
   571         # read current configuration
   550         raw = repo.vfs.tryread('sparse')
   572         raw = repo.vfs.tryread('sparse')
   551         oincludes, oexcludes, oprofiles = parseconfig(repo.ui, raw)
   573         includes, excludes, profiles = parseconfig(repo.ui, raw)
   552         includes, excludes, profiles = map(
       
   553                 set, (oincludes, oexcludes, oprofiles))
       
   554 
       
   555         aincludes, aexcludes, aprofiles = activeconfig(repo)
   574         aincludes, aexcludes, aprofiles = activeconfig(repo)
   556 
   575 
   557         # Import rules on top; only take in rules that are not yet
   576         # Import rules on top; only take in rules that are not yet
   558         # part of the active rules.
   577         # part of the active rules.
   559         changed = False
   578         changed = False
   575         if changed:
   594         if changed:
   576             profilecount = len(profiles - aprofiles)
   595             profilecount = len(profiles - aprofiles)
   577             includecount = len(includes - aincludes)
   596             includecount = len(includes - aincludes)
   578             excludecount = len(excludes - aexcludes)
   597             excludecount = len(excludes - aexcludes)
   579 
   598 
   580             oldstatus = repo.status()
   599             fcounts = map(len, _updateconfigandrefreshwdir(
   581             oldsparsematch = matcher(repo)
   600                 repo, includes, excludes, profiles, force=force))
   582 
       
   583             # TODO remove this try..except once the matcher integrates better
       
   584             # with dirstate. We currently have to write the updated config
       
   585             # because that will invalidate the matcher cache and force a
       
   586             # re-read. We ideally want to update the cached matcher on the
       
   587             # repo instance then flush the new config to disk once wdir is
       
   588             # updated. But this requires massive rework to matcher() and its
       
   589             # consumers.
       
   590             writeconfig(repo, includes, excludes, profiles)
       
   591 
       
   592             try:
       
   593                 fcounts = map(
       
   594                     len,
       
   595                     refreshwdir(repo, oldstatus, oldsparsematch, force=force))
       
   596             except Exception:
       
   597                 writeconfig(repo, oincludes, oexcludes, oprofiles)
       
   598                 raise
       
   599 
   601 
   600         printchanges(repo.ui, opts, profilecount, includecount, excludecount,
   602         printchanges(repo.ui, opts, profilecount, includecount, excludecount,
   601                      *fcounts)
   603                      *fcounts)
   602 
   604 
   603 def updateconfig(repo, pats, opts, include=False, exclude=False, reset=False,
   605 def updateconfig(repo, pats, opts, include=False, exclude=False, reset=False,
   608     Only one of the actions may be performed.
   610     Only one of the actions may be performed.
   609 
   611 
   610     The new config is written out and a working directory refresh is performed.
   612     The new config is written out and a working directory refresh is performed.
   611     """
   613     """
   612     with repo.wlock():
   614     with repo.wlock():
   613         oldmatcher = matcher(repo)
       
   614 
       
   615         raw = repo.vfs.tryread('sparse')
   615         raw = repo.vfs.tryread('sparse')
   616         oldinclude, oldexclude, oldprofiles = parseconfig(repo.ui, raw)
   616         oldinclude, oldexclude, oldprofiles = parseconfig(repo.ui, raw)
   617 
   617 
   618         if reset:
   618         if reset:
   619             newinclude = set()
   619             newinclude = set()
   621             newprofiles = set()
   621             newprofiles = set()
   622         else:
   622         else:
   623             newinclude = set(oldinclude)
   623             newinclude = set(oldinclude)
   624             newexclude = set(oldexclude)
   624             newexclude = set(oldexclude)
   625             newprofiles = set(oldprofiles)
   625             newprofiles = set(oldprofiles)
   626 
       
   627         oldstatus = repo.status()
       
   628 
   626 
   629         if any(pat.startswith('/') for pat in pats):
   627         if any(pat.startswith('/') for pat in pats):
   630             repo.ui.warn(_('warning: paths cannot start with /, ignoring: %s\n')
   628             repo.ui.warn(_('warning: paths cannot start with /, ignoring: %s\n')
   631                          % ([pat for pat in pats if pat.startswith('/')]))
   629                          % ([pat for pat in pats if pat.startswith('/')]))
   632         elif include:
   630         elif include:
   646         includecount = (len(newinclude - oldinclude) -
   644         includecount = (len(newinclude - oldinclude) -
   647                         len(oldinclude - newinclude))
   645                         len(oldinclude - newinclude))
   648         excludecount = (len(newexclude - oldexclude) -
   646         excludecount = (len(newexclude - oldexclude) -
   649                         len(oldexclude - newexclude))
   647                         len(oldexclude - newexclude))
   650 
   648 
   651         # TODO clean up this writeconfig() + try..except pattern once we can.
   649         fcounts = map(len, _updateconfigandrefreshwdir(
   652         # See comment in importfromfiles() explaining it.
   650             repo, newinclude, newexclude, newprofiles, force=force))
   653         writeconfig(repo, newinclude, newexclude, newprofiles)
   651 
   654 
   652         printchanges(repo.ui, opts, profilecount, includecount,
   655         try:
   653                      excludecount, *fcounts)
   656             fcounts = map(
       
   657                 len,
       
   658                 refreshwdir(repo, oldstatus, oldmatcher, force=force))
       
   659 
       
   660             printchanges(repo.ui, opts, profilecount, includecount,
       
   661                          excludecount, *fcounts)
       
   662         except Exception:
       
   663             writeconfig(repo, oldinclude, oldexclude, oldprofiles)
       
   664             raise
       
   665 
   654 
   666 def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0,
   655 def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0,
   667                  added=0, dropped=0, conflicting=0):
   656                  added=0, dropped=0, conflicting=0):
   668     """Print output summarizing sparse config changes."""
   657     """Print output summarizing sparse config changes."""
   669     with ui.formatter('sparse', opts) as fm:
   658     with ui.formatter('sparse', opts) as fm: