Mercurial > public > mercurial-scm > hg
diff mercurial/sparse.py @ 33324:33d0859c37bd
sparse: move working directory refreshing into core
This is a pretty straightforward move of the code.
I converted the "force" argument to a keyword argument.
Like other recent changes, this code is tightly coupled with
working directory update code in merge.py. I suspect the code
will become more tightly coupled over time, possibly even moved
to merge.py. For now, let's get the code in core.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Thu, 06 Jul 2017 14:53:08 -0700 |
parents | 252500520d60 |
children | 38df146d0697 |
line wrap: on
line diff
--- a/mercurial/sparse.py Thu Jul 06 16:29:31 2017 -0700 +++ b/mercurial/sparse.py Thu Jul 06 14:53:08 2017 -0700 @@ -382,3 +382,102 @@ prunedactions[file] = ('r', [], '') return prunedactions + +def refreshwdir(repo, origstatus, origsparsematch, force=False): + """Refreshes working directory by taking sparse config into account. + + The old status and sparse matcher is compared against the current sparse + matcher. + + Will abort if a file with pending changes is being excluded or included + unless ``force`` is True. + """ + modified, added, removed, deleted, unknown, ignored, clean = origstatus + + # Verify there are no pending changes + pending = set() + pending.update(modified) + pending.update(added) + pending.update(removed) + sparsematch = matcher(repo) + abort = False + + for f in pending: + if not sparsematch(f): + repo.ui.warn(_("pending changes to '%s'\n") % f) + abort = not force + + if abort: + raise error.Abort(_('could not update sparseness due to pending ' + 'changes')) + + # Calculate actions + dirstate = repo.dirstate + ctx = repo['.'] + added = [] + lookup = [] + dropped = [] + mf = ctx.manifest() + files = set(mf) + + actions = {} + + for file in files: + old = origsparsematch(file) + new = sparsematch(file) + # Add files that are newly included, or that don't exist in + # the dirstate yet. + if (new and not old) or (old and new and not file in dirstate): + fl = mf.flags(file) + if repo.wvfs.exists(file): + actions[file] = ('e', (fl,), '') + lookup.append(file) + else: + actions[file] = ('g', (fl, False), '') + added.append(file) + # Drop files that are newly excluded, or that still exist in + # the dirstate. + elif (old and not new) or (not old and not new and file in dirstate): + dropped.append(file) + if file not in pending: + actions[file] = ('r', [], '') + + # Verify there are no pending changes in newly included files + abort = False + for file in lookup: + repo.ui.warn(_("pending changes to '%s'\n") % file) + abort = not force + if abort: + raise error.Abort(_('cannot change sparseness due to pending ' + 'changes (delete the files or use ' + '--force to bring them back dirty)')) + + # Check for files that were only in the dirstate. + for file, state in dirstate.iteritems(): + if not file in files: + old = origsparsematch(file) + new = sparsematch(file) + if old and not new: + dropped.append(file) + + # Apply changes to disk + typeactions = dict((m, []) for m in 'a f g am cd dc r dm dg m e k'.split()) + for f, (m, args, msg) in actions.iteritems(): + if m not in typeactions: + typeactions[m] = [] + typeactions[m].append((f, args, msg)) + + mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False) + + # Fix dirstate + for file in added: + dirstate.normal(file) + + for file in dropped: + dirstate.drop(file) + + for file in lookup: + # File exists on disk, and we're bringing it back in an unknown state. + dirstate.normallookup(file) + + return added, dropped, lookup