changeset 18065:2acd9c14b0d7

merge with stable
author Mads Kiilerich <madski@unity3d.com>
date Thu, 13 Dec 2012 21:34:55 +0100
parents 34a1a639d835 (current diff) 7e2b9f6a2cd0 (diff)
children abe9799a86d6
files hgext/largefiles/reposetup.py
diffstat 2 files changed, 113 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/largefiles/reposetup.py	Fri Dec 07 10:37:43 2012 -0800
+++ b/hgext/largefiles/reposetup.py	Thu Dec 13 21:34:55 2012 +0100
@@ -359,11 +359,8 @@
                     lfdirstate.write()
                     return result
 
-                for f in match.files():
-                    if lfutil.isstandin(f):
-                        raise util.Abort(
-                            _('file "%s" is a largefile standin') % f,
-                            hint=('commit the largefile itself instead'))
+                lfiles = lfutil.listlfiles(self)
+                match._files = self._subdirlfs(match.files(), lfiles)
 
                 # Case 2: user calls commit with specified patterns: refresh
                 # any matching big files.
@@ -394,7 +391,6 @@
                 # standins corresponding to the big files requested by the
                 # user.  Have to modify _files to prevent commit() from
                 # complaining "not tracked" for big files.
-                lfiles = lfutil.listlfiles(self)
                 match = copy.copy(match)
                 origmatchfn = match.matchfn
 
@@ -467,6 +463,60 @@
             return super(lfilesrepo, self).push(remote, force, revs,
                 newbranch)
 
+        def _subdirlfs(self, files, lfiles):
+            '''
+            Adjust matched file list
+            If we pass a directory to commit whose only commitable files
+            are largefiles, the core commit code aborts before finding
+            the largefiles.
+            So we do the following:
+            For directories that only have largefiles as matches,
+            we explicitly add the largefiles to the matchlist and remove
+            the directory.
+            In other cases, we leave the match list unmodified.
+            '''
+            actualfiles = []
+            dirs = []
+            regulars = []
+
+            for f in files:
+                if lfutil.isstandin(f + '/'):
+                    raise util.Abort(
+                        _('file "%s" is a largefile standin') % f,
+                        hint=('commit the largefile itself instead'))
+                # Scan directories
+                if os.path.isdir(self.wjoin(f)):
+                    dirs.append(f)
+                else:
+                    regulars.append(f)
+
+            for f in dirs:
+                matcheddir = False
+                d = self.dirstate.normalize(f) + '/'
+                # Check for matched normal files
+                for mf in regulars:
+                    if self.dirstate.normalize(mf).startswith(d):
+                        actualfiles.append(f)
+                        matcheddir = True
+                        break
+                if not matcheddir:
+                    # If no normal match, manually append
+                    # any matching largefiles
+                    for lf in lfiles:
+                        if self.dirstate.normalize(lf).startswith(d):
+                            actualfiles.append(lf)
+                            if not matcheddir:
+                                actualfiles.append(lfutil.standin(f))
+                                matcheddir = True
+                # Nothing in dir, so readd it
+                # and let commit reject it
+                if not matcheddir:
+                    actualfiles.append(f)
+
+            # Always add normal files
+            actualfiles += regulars
+            return actualfiles
+
     repo.__class__ = lfilesrepo
 
     def checkrequireslfiles(ui, repo, **kwargs):
--- a/tests/test-largefiles.t	Fri Dec 07 10:37:43 2012 -0800
+++ b/tests/test-largefiles.t	Thu Dec 13 21:34:55 2012 +0100
@@ -345,6 +345,63 @@
   A sub2/large6
   A sub2/large7
 
+Committing directories containing only largefiles.
+
+  $ mkdir -p z/y/x/m
+  $ touch z/y/x/m/large1
+  $ touch z/y/x/large2
+  $ hg add --large z/y/x/m/large1 z/y/x/large2
+  $ hg commit -m "Subdir with directory only containing largefiles" z
+  Invoking status precommit hook
+  M large3
+  A large5
+  A sub2/large6
+  A sub2/large7
+  A z/y/x/large2
+  A z/y/x/m/large1
+  $ hg rollback --quiet
+  $ touch z/y/x/m/normal
+  $ hg add z/y/x/m/normal
+  $ hg commit -m "Subdir with mixed contents" z
+  Invoking status precommit hook
+  M large3
+  A large5
+  A sub2/large6
+  A sub2/large7
+  A z/y/x/large2
+  A z/y/x/m/large1
+  A z/y/x/m/normal
+  $ hg st
+  M large3
+  A large5
+  A sub2/large6
+  A sub2/large7
+  $ hg rollback --quiet
+  $ hg revert z/y/x/large2 z/y/x/m/large1
+  $ rm z/y/x/large2 z/y/x/m/large1
+  $ hg commit -m "Subdir with normal contents" z
+  Invoking status precommit hook
+  M large3
+  A large5
+  A sub2/large6
+  A sub2/large7
+  A z/y/x/m/normal
+  $ hg st
+  M large3
+  A large5
+  A sub2/large6
+  A sub2/large7
+  $ hg rollback --quiet
+  $ hg revert --quiet z
+  $ hg commit -m "Empty subdir" z
+  abort: z: no match under directory!
+  [255]
+  $ rm -rf z
+  $ hg ci -m "standin" .hglf
+  abort: file ".hglf" is a largefile standin
+  (commit the largefile itself instead)
+  [255]
+
 Test "hg status" with combination of 'file pattern' and 'directory
 pattern' for largefiles: