commit: move explicit file checking into repo.commit
authorMatt Mackall <mpm@selenic.com>
Mon, 01 Jun 2009 21:51:00 -0500
changeset 8709 b9e0ddb04c5c
parent 8708 a645904c88c4
child 8710 bcb6e5bebd93
commit: move explicit file checking into repo.commit
mercurial/cmdutil.py
mercurial/localrepo.py
tests/test-commit.out
tests/test-symlink-basic.out
--- a/mercurial/cmdutil.py	Mon Jun 01 20:25:01 2009 -0500
+++ b/mercurial/cmdutil.py	Mon Jun 01 21:51:00 2009 -0500
@@ -1194,42 +1194,7 @@
     if opts.get('addremove'):
         addremove(repo, pats, opts)
 
-    m = match(repo, pats, opts)
-    if pats:
-        modified, added, removed = repo.status(match=m)[:3]
-        files = sorted(modified + added + removed)
-
-        def is_dir(f):
-            name = f + '/'
-            i = bisect.bisect(files, name)
-            return i < len(files) and files[i].startswith(name)
-
-        for f in m.files():
-            if f == '.':
-                continue
-            if f not in files:
-                rf = repo.wjoin(f)
-                rel = repo.pathto(f)
-                try:
-                    mode = os.lstat(rf)[stat.ST_MODE]
-                except OSError:
-                    if is_dir(f): # deleted directory ?
-                        continue
-                    raise util.Abort(_("file %s not found!") % rel)
-                if stat.S_ISDIR(mode):
-                    if not is_dir(f):
-                        raise util.Abort(_("no match under directory %s!")
-                                         % rel)
-                elif not (stat.S_ISREG(mode) or stat.S_ISLNK(mode)):
-                    raise util.Abort(_("can't commit %s: "
-                                       "unsupported file type!") % rel)
-                elif f not in repo.dirstate:
-                    raise util.Abort(_("file %s not tracked!") % rel)
-        m = matchfiles(repo, files)
-    try:
-        return commitfunc(ui, repo, message, m, opts)
-    except ValueError, inst:
-        raise util.Abort(str(inst))
+    return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
 
 def commiteditor(repo, ctx):
     if ctx.description():
--- a/mercurial/localrepo.py	Mon Jun 01 20:25:01 2009 -0500
+++ b/mercurial/localrepo.py	Mon Jun 01 21:51:00 2009 -0500
@@ -14,7 +14,7 @@
 import match as match_
 import merge as merge_
 from lock import release
-import weakref, stat, errno, os, time, inspect
+import weakref, stat, errno, os, time, inspect, bisect
 propertycache = util.propertycache
 
 class localrepository(repo.repository):
@@ -781,6 +781,7 @@
         match can be used to filter the committed files. If editor is
         supplied, it is called to get a commit message.
         """
+
         wlock = self.wlock()
         try:
             p1, p2 = self.dirstate.parents()
@@ -790,10 +791,38 @@
                 raise util.Abort(_('cannot partially commit a merge '
                                    '(do not specify files or patterns)'))
 
+            def fail(f, msg):
+                raise util.Abort('%s: %s' % (f, msg))
+
+            if not match:
+                match = match_.always(self.root, '')
+
+            if not force:
+                vdirs = []
+                match.dir = vdirs.append
+                match.bad = fail
+
             changes = self.status(match=match, clean=force)
             if force:
                 changes[0].extend(changes[6]) # mq may commit unchanged files
 
+            # make sure all explicit patterns are matched
+            if not force and match.files():
+                files = sorted(changes[0] + changes[1] + changes[2])
+
+                for f in match.files():
+                    if f == '.' or f in files: # matched
+                        continue
+                    if f in changes[3]: # missing
+                        fail(f, _('file not found!'))
+                    if f in vdirs: # visited directory
+                        d = f + '/'
+                        i = bisect.bisect(files, d)
+                        if i >= len(files) or not files[i].startswith(d):
+                            fail(f, _("no match under directory!"))
+                    elif f not in self.dirstate:
+                        fail(f, _("file not tracked!"))
+
             if (not force and not extra.get("close") and p2 == nullid
                 and not (changes[0] or changes[1] or changes[2])
                 and self[None].branch() == self['.'].branch()):
--- a/tests/test-commit.out	Mon Jun 01 20:25:01 2009 -0500
+++ b/tests/test-commit.out	Mon Jun 01 21:51:00 2009 -0500
@@ -6,20 +6,19 @@
 abort: date exceeds 32 bits: 111111111111
 % commit added file that has been deleted
 nothing changed
-abort: file bar not found!
+abort: bar: file not found!
 adding dir/file
 dir/file
 committed changeset 2:d2a76177cb42
 adding dir.file
-abort: no match under directory dir!
-abort: no match under directory .!
-abort: no match under directory ../dir2!
+abort: dir: no match under directory!
+abort: bleh: no match under directory!
+abort: dir2: no match under directory!
 dir/file
 committed changeset 3:1cd62a2d8db5
-does-not-exist: No such file or directory
-abort: file does-not-exist not found!
-abort: file baz not tracked!
-abort: file quux not tracked!
+abort: does-not-exist: No such file or directory
+abort: baz: file not tracked!
+abort: quux: file not tracked!
 dir/file
 committed changeset 4:49176991390e
 % partial subdir commit test
--- a/tests/test-symlink-basic.out	Mon Jun 01 20:25:01 2009 -0500
+++ b/tests/test-symlink-basic.out	Mon Jun 01 21:51:00 2009 -0500
@@ -1,4 +1,4 @@
-abort: file dangling not tracked!
+abort: dangling: file not tracked!
 changeset:   0:cabd88b706fc
 tag:         tip
 user:        test