hgext/sparse.py
changeset 33322 fa6c2c3064fd
parent 33321 d09e948dc303
child 33323 252500520d60
equal deleted inserted replaced
33321:d09e948dc303 33322:fa6c2c3064fd
    71   [exclude]
    71   [exclude]
    72   tools/tests/**
    72   tools/tests/**
    73 """
    73 """
    74 
    74 
    75 from __future__ import absolute_import
    75 from __future__ import absolute_import
    76 
       
    77 import collections
       
    78 
    76 
    79 from mercurial.i18n import _
    77 from mercurial.i18n import _
    80 from mercurial.node import nullid
    78 from mercurial.node import nullid
    81 from mercurial import (
    79 from mercurial import (
    82     cmdutil,
    80     cmdutil,
   137     if cls is object:
   135     if cls is object:
   138         raise AttributeError(_("type '%s' has no property '%s'") % (origcls,
   136         raise AttributeError(_("type '%s' has no property '%s'") % (origcls,
   139                              propname))
   137                              propname))
   140 
   138 
   141 def _setupupdates(ui):
   139 def _setupupdates(ui):
   142     def _calculateupdates(orig, repo, wctx, mctx, ancestors, branchmerge, *arg,
   140     extensions.wrapfunction(mergemod, 'calculateupdates',
   143                           **kwargs):
   141                             sparse.calculateupdates)
   144         """Filter updates to only lay out files that match the sparse rules.
       
   145         """
       
   146         actions, diverge, renamedelete = orig(repo, wctx, mctx, ancestors,
       
   147                                               branchmerge, *arg, **kwargs)
       
   148 
       
   149         oldrevs = [pctx.rev() for pctx in wctx.parents()]
       
   150         oldsparsematch = sparse.matcher(repo, oldrevs)
       
   151 
       
   152         if oldsparsematch.always():
       
   153             return actions, diverge, renamedelete
       
   154 
       
   155         files = set()
       
   156         prunedactions = {}
       
   157 
       
   158         if branchmerge:
       
   159             # If we're merging, use the wctx filter, since we're merging into
       
   160             # the wctx.
       
   161             sparsematch = sparse.matcher(repo, [wctx.parents()[0].rev()])
       
   162         else:
       
   163             # If we're updating, use the target context's filter, since we're
       
   164             # moving to the target context.
       
   165             sparsematch = sparse.matcher(repo, [mctx.rev()])
       
   166 
       
   167         temporaryfiles = []
       
   168         for file, action in actions.iteritems():
       
   169             type, args, msg = action
       
   170             files.add(file)
       
   171             if sparsematch(file):
       
   172                 prunedactions[file] = action
       
   173             elif type == 'm':
       
   174                 temporaryfiles.append(file)
       
   175                 prunedactions[file] = action
       
   176             elif branchmerge:
       
   177                 if type != 'k':
       
   178                     temporaryfiles.append(file)
       
   179                     prunedactions[file] = action
       
   180             elif type == 'f':
       
   181                 prunedactions[file] = action
       
   182             elif file in wctx:
       
   183                 prunedactions[file] = ('r', args, msg)
       
   184 
       
   185         if len(temporaryfiles) > 0:
       
   186             ui.status(_("temporarily included %d file(s) in the sparse checkout"
       
   187                 " for merging\n") % len(temporaryfiles))
       
   188             sparse.addtemporaryincludes(repo, temporaryfiles)
       
   189 
       
   190             # Add the new files to the working copy so they can be merged, etc
       
   191             actions = []
       
   192             message = 'temporarily adding to sparse checkout'
       
   193             wctxmanifest = repo[None].manifest()
       
   194             for file in temporaryfiles:
       
   195                 if file in wctxmanifest:
       
   196                     fctx = repo[None][file]
       
   197                     actions.append((file, (fctx.flags(), False), message))
       
   198 
       
   199             typeactions = collections.defaultdict(list)
       
   200             typeactions['g'] = actions
       
   201             mergemod.applyupdates(repo, typeactions, repo[None], repo['.'],
       
   202                                   False)
       
   203 
       
   204             dirstate = repo.dirstate
       
   205             for file, flags, msg in actions:
       
   206                 dirstate.normal(file)
       
   207 
       
   208         profiles = sparse.activeprofiles(repo)
       
   209         changedprofiles = profiles & files
       
   210         # If an active profile changed during the update, refresh the checkout.
       
   211         # Don't do this during a branch merge, since all incoming changes should
       
   212         # have been handled by the temporary includes above.
       
   213         if changedprofiles and not branchmerge:
       
   214             mf = mctx.manifest()
       
   215             for file in mf:
       
   216                 old = oldsparsematch(file)
       
   217                 new = sparsematch(file)
       
   218                 if not old and new:
       
   219                     flags = mf.flags(file)
       
   220                     prunedactions[file] = ('g', (flags, False), '')
       
   221                 elif old and not new:
       
   222                     prunedactions[file] = ('r', [], '')
       
   223 
       
   224         return prunedactions, diverge, renamedelete
       
   225 
       
   226     extensions.wrapfunction(mergemod, 'calculateupdates', _calculateupdates)
       
   227 
   142 
   228 def _setupcommit(ui):
   143 def _setupcommit(ui):
   229     def _refreshoncommit(orig, self, node):
   144     def _refreshoncommit(orig, self, node):
   230         """Refresh the checkout when commits touch .hgsparse
   145         """Refresh the checkout when commits touch .hgsparse
   231         """
   146         """