Mercurial > hg
changeset 18064:7e2b9f6a2cd0 stable
largefiles: commit directories that only contain largefiles (issue3548)
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.
author | Levi Bard <levi@unity3d.com> |
---|---|
date | Mon, 10 Dec 2012 14:58:42 +0100 |
parents | ebc0fa067c07 |
children | 2acd9c14b0d7 3bc21f6daac4 |
files | hgext/largefiles/reposetup.py tests/test-largefiles.t |
diffstat | 2 files changed, 113 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/largefiles/reposetup.py Thu Dec 06 13:21:27 2012 -0600 +++ b/hgext/largefiles/reposetup.py Mon Dec 10 14:58:42 2012 +0100 @@ -355,11 +355,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. @@ -390,7 +387,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 @@ -463,6 +459,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 Thu Dec 06 13:21:27 2012 -0600 +++ b/tests/test-largefiles.t Mon Dec 10 14:58:42 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: