diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1314,9 +1314,16 @@ def add(ui, repo, match, dryrun, listsub match.bad = lambda x, y: bad.append(x) or oldbad(x, y) names = [] wctx = repo[None] + wctx.status(clean=True) + existing = None + if scmutil.showportabilityalert(ui): + existing = dict([(fn.lower(), fn) for fn in + wctx.added() + wctx.clean() + wctx.modified()]) for f in repo.walk(match): exact = match.exact(f) if exact or f not in repo.dirstate: + if existing: + scmutil.checkcasecollision(ui, f, existing) names.append(f) if ui.verbose or not exact: ui.status(_('adding %s\n') % match.rel(join(f))) diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -22,6 +22,11 @@ def checkportable(ui, f): if msg: portabilityalert(ui, "%s: %r" % (msg, f)) +def checkcasecollision(ui, f, files): + if f.lower() in files and files[f.lower()] != f: + portabilityalert(ui, _('possible case-folding collision for %s') % f) + files[f.lower()] = f + def checkportabilityalert(ui): '''check if the user's config requests nothing, a warning, or abort for non-portable filenames''' diff --git a/tests/test-casecollision.t b/tests/test-casecollision.t new file mode 100644 --- /dev/null +++ b/tests/test-casecollision.t @@ -0,0 +1,34 @@ +run only on case-sensitive filesystems + + $ "$TESTDIR/hghave" no-icasefs || exit 80 + +test file addition with colliding case + + $ hg init repo1 + $ cd repo1 + $ echo a > a + $ echo A > A + $ hg add a + $ hg st + A a + ? A + $ hg add --config ui.portablefilenames=abort A + abort: possible case-folding collision for A + [255] + $ hg st + A a + ? A + $ hg add A + warning: possible case-folding collision for A + $ hg st + A A + A a + $ hg forget A + $ hg st + A a + ? A + $ hg add --config ui.portablefilenames=no A + $ hg st + A A + A a + $ cd ..