# HG changeset patch # User Matt Mackall # Date 1328827819 21600 # Node ID 7e30f5f2285f09fa28bdcc3228a3d0fc7c7906db # Parent 914bc95e227bf4328f72c7c13bf80f01f942266c merge: refactor unknown file conflict checking Previously, we would do a full working directory walk including unknown files to perform a merge. In many cases, this was painful because unknown files greatly outnumbered tracked files and generally had no useful effect on the merge. Here we instead wait until we find a file in the destination that's not tracked locally and detect if it exists and is not ignored. This is usually cheaper but can be -more- expensive in the case where we're adding a huge number of files. On the other hand, the cost of statting the new files should be dwarfed by the cost of eventually writing them. In this version, case collisions are detected implicitly by os.path.exists and wctx[f] lookup. diff -r 914bc95e227b -r 7e30f5f2285f hgext/largefiles/overrides.py --- a/hgext/largefiles/overrides.py Thu Feb 09 13:16:20 2012 -0600 +++ b/hgext/largefiles/overrides.py Thu Feb 09 16:50:19 2012 -0600 @@ -265,13 +265,10 @@ # The overridden function filters the unknown files by removing any # largefiles. This makes the merge proceed and we can then handle this # case further in the overridden manifestmerge function below. -def override_checkunknown(origfn, wctx, mctx, folding): - origunknown = wctx.unknown() - wctx._unknown = filter(lambda f: lfutil.standin(f) not in wctx, origunknown) - try: - return origfn(wctx, mctx, folding) - finally: - wctx._unknown = origunknown +def override_checkunknownfile(origfn, repo, wctx, mctx, f): + if lfutil.standin(f) in wctx: + return False + return origfn(repo, wctx, mctx, f) # The manifest merge handles conflicts on the manifest level. We want # to handle changes in largefile-ness of files at this level too. diff -r 914bc95e227b -r 7e30f5f2285f hgext/largefiles/uisetup.py --- a/hgext/largefiles/uisetup.py Thu Feb 09 13:16:20 2012 -0600 +++ b/hgext/largefiles/uisetup.py Thu Feb 09 16:50:19 2012 -0600 @@ -64,8 +64,8 @@ overrides.override_update) entry = extensions.wrapcommand(commands.table, 'pull', overrides.override_pull) - entry = extensions.wrapfunction(merge, '_checkunknown', - overrides.override_checkunknown) + entry = extensions.wrapfunction(merge, '_checkunknownfile', + overrides.override_checkunknownfile) entry = extensions.wrapfunction(merge, 'manifestmerge', overrides.override_manifestmerge) entry = extensions.wrapfunction(filemerge, 'filemerge', diff -r 914bc95e227b -r 7e30f5f2285f mercurial/merge.py --- a/mercurial/merge.py Thu Feb 09 13:16:20 2012 -0600 +++ b/mercurial/merge.py Thu Feb 09 16:50:19 2012 -0600 @@ -81,22 +81,19 @@ self.mark(dfile, 'r') return r -def _checkunknown(wctx, mctx, folding): +def _checkunknownfile(repo, wctx, mctx, f): + return (not repo.dirstate._ignore(f) + and os.path.exists(repo.wjoin(f)) + and mctx[f].cmp(wctx[f])) + +def _checkunknown(repo, wctx, mctx): "check for collisions between unknown files and files in mctx" - if folding: - foldf = util.normcase - else: - foldf = lambda fn: fn - folded = {} - for fn in mctx: - folded[foldf(fn)] = fn error = False - for fn in wctx.unknown(): - f = foldf(fn) - if f in folded and mctx[folded[f]].cmp(wctx[f]): + for f in mctx: + if f not in wctx and _checkunknownfile(repo, wctx, mctx, f): error = True - wctx._repo.ui.warn(_("%s: untracked file differs\n") % fn) + wctx._repo.ui.warn(_("%s: untracked file differs\n") % f) if error: raise util.Abort(_("untracked files in working directory differ " "from files in requested revision")) @@ -565,7 +562,7 @@ wc.status(unknown=True) # prime cache folding = not util.checkcase(repo.path) if not force: - _checkunknown(wc, p2, folding) + _checkunknown(repo, wc, p2) if folding: _checkcollision(p2, branchmerge and p1) action += _forgetremoved(wc, p2, branchmerge)