[PATCH v2] largefiles: Commit directories that only contain largefiles (issue3548)
Levi Bard
taktaktaktaktaktaktaktaktaktak at gmail.com
Wed Dec 12 08:48:23 CST 2012
# HG changeset patch
# User Levi Bard <levi at unity3d.com>
# Date 1355147922 -3600
# Node ID e7e98a8bfe36017d32965856e8ef9a8cb4929353
# Parent 40374059d227850ec2f5fb4f21a1b619136e2a6a
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.
diff -r 40374059d227 -r e7e98a8bfe36 hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py Tue Nov 27 22:24:02 2012 +0100
+++ b/hgext/largefiles/lfutil.py Mon Dec 10 14:58:42 2012 +0100
@@ -306,7 +306,7 @@
def isstandin(filename):
'''Return true if filename is a big file standin. filename must be
in Mercurial's internal form (slash-separated).'''
- return filename.startswith(shortname + '/')
+ return filename.startswith(shortname + '/') or filename == shortname
def splitstandin(filename):
# Split on / because that's what dirstate always uses, even on Windows.
diff -r 40374059d227 -r e7e98a8bfe36 hgext/largefiles/reposetup.py
--- a/hgext/largefiles/reposetup.py Tue Nov 27 22:24:02 2012 +0100
+++ b/hgext/largefiles/reposetup.py Mon Dec 10 14:58:42 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):
diff -r 40374059d227 -r e7e98a8bfe36 tests/test-largefiles.t
--- a/tests/test-largefiles.t Tue Nov 27 22:24:02 2012 +0100
+++ 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:
More information about the Mercurial-devel
mailing list