git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v7 0/7] git-p4: add support for large file systems
@ 2015-09-21 22:41 larsxschneider
  2015-09-21 22:41 ` [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader larsxschneider
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

diff to v6:
* fix spaces in .gitattributes for Git-LFS files (old "[:space:]", new "[[:space:]]")
* generated patch on top of next (95c4325) to resolve merge conflicts

I am sorry about the "[:space:]" bug this late. I had the fix in my development
branch but missed to apply it in this patch series.

@Junio:
Your conflict resolution in pu looks good. Nevertheless, I made this patch on
top of next to ease the integration. I hope this is ok.

Cheers,
Lars

Lars Schneider (7):
  git-p4: add optional type specifier to gitConfig reader
  git-p4: add gitConfigInt reader
  git-p4: return an empty list if a list config has no values
  git-p4: add file streaming progress in verbose mode
  git-p4: check free space during streaming
  git-p4: add support for large file systems
  git-p4: add Git LFS backend for large file system

 Documentation/git-p4.txt   |  32 +++++
 git-p4.py                  | 278 ++++++++++++++++++++++++++++++++++++++++---
 t/t9823-git-p4-mock-lfs.sh | 170 ++++++++++++++++++++++++++
 t/t9824-git-p4-git-lfs.sh  | 288 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 751 insertions(+), 17 deletions(-)
 create mode 100755 t/t9823-git-p4-mock-lfs.sh
 create mode 100755 t/t9824-git-p4-git-lfs.sh

--
2.5.1

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
@ 2015-09-21 22:41 ` larsxschneider
  2015-09-22 21:49   ` Junio C Hamano
  2015-09-21 22:41 ` [PATCH v7 2/7] git-p4: add gitConfigInt reader larsxschneider
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

The functions “gitConfig” and “gitConfigBool” are almost identical. Make “gitConfig” more generic by adding an optional type specifier. Use the type specifier “—bool” with “gitConfig” to implement “gitConfigBool. This prepares the implementation of other type specifiers such as “—int”.

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
Acked-by: Luke Diamand <luke@diamand.org>
---
 git-p4.py | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/git-p4.py b/git-p4.py
index 215f556..2659079 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -604,9 +604,12 @@ def gitBranchExists(branch):
 
 _gitConfig = {}
 
-def gitConfig(key):
+def gitConfig(key, typeSpecifier=None):
     if not _gitConfig.has_key(key):
-        cmd = [ "git", "config", key ]
+        cmd = [ "git", "config" ]
+        if typeSpecifier:
+            cmd += [ typeSpecifier ]
+        cmd += [ key ]
         s = read_pipe(cmd, ignore_error=True)
         _gitConfig[key] = s.strip()
     return _gitConfig[key]
@@ -617,10 +620,7 @@ def gitConfigBool(key):
        in the config."""
 
     if not _gitConfig.has_key(key):
-        cmd = [ "git", "config", "--bool", key ]
-        s = read_pipe(cmd, ignore_error=True)
-        v = s.strip()
-        _gitConfig[key] = v == "true"
+        _gitConfig[key] = gitConfig(key, '--bool') == "true"
     return _gitConfig[key]
 
 def gitConfigList(key):
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v7 2/7] git-p4: add gitConfigInt reader
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
  2015-09-21 22:41 ` [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader larsxschneider
@ 2015-09-21 22:41 ` larsxschneider
  2015-09-21 22:41 ` [PATCH v7 3/7] git-p4: return an empty list if a list config has no values larsxschneider
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

Add a git config reader for integer variables. Please note that the git config implementation automatically supports k, m, and g suffixes.

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 git-p4.py | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/git-p4.py b/git-p4.py
index 2659079..2715895 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -623,6 +623,17 @@ def gitConfigBool(key):
         _gitConfig[key] = gitConfig(key, '--bool') == "true"
     return _gitConfig[key]
 
+def gitConfigInt(key):
+    if not _gitConfig.has_key(key):
+        cmd = [ "git", "config", "--int", key ]
+        s = read_pipe(cmd, ignore_error=True)
+        v = s.strip()
+        try:
+            _gitConfig[key] = int(gitConfig(key, '--int'))
+        except ValueError:
+            _gitConfig[key] = None
+    return _gitConfig[key]
+
 def gitConfigList(key):
     if not _gitConfig.has_key(key):
         s = read_pipe(["git", "config", "--get-all", key], ignore_error=True)
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v7 3/7] git-p4: return an empty list if a list config has no values
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
  2015-09-21 22:41 ` [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader larsxschneider
  2015-09-21 22:41 ` [PATCH v7 2/7] git-p4: add gitConfigInt reader larsxschneider
@ 2015-09-21 22:41 ` larsxschneider
  2015-09-21 22:41 ` [PATCH v7 4/7] git-p4: add file streaming progress in verbose mode larsxschneider
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 git-p4.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/git-p4.py b/git-p4.py
index 2715895..e7d1b3f 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -638,6 +638,8 @@ def gitConfigList(key):
     if not _gitConfig.has_key(key):
         s = read_pipe(["git", "config", "--get-all", key], ignore_error=True)
         _gitConfig[key] = s.strip().split(os.linesep)
+        if _gitConfig[key] == ['']:
+            _gitConfig[key] = []
     return _gitConfig[key]
 
 def p4BranchesInGit(branchesAreInRemotes=True):
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v7 4/7] git-p4: add file streaming progress in verbose mode
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
                   ` (2 preceding siblings ...)
  2015-09-21 22:41 ` [PATCH v7 3/7] git-p4: return an empty list if a list config has no values larsxschneider
@ 2015-09-21 22:41 ` larsxschneider
  2015-09-21 22:41 ` [PATCH v7 5/7] git-p4: check free space during streaming larsxschneider
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

If a file is streamed from P4 to Git then the verbose mode prints
continuously the progress as percentage like this:
//depot/file.bin 20% (10 MB)

Upon completion the progress is overwritten with depot source, local
file and size like this:
//depot/file.bin --> local/file.bin (10 MB)

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 git-p4.py | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/git-p4.py b/git-p4.py
index e7d1b3f..fabc900 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -2171,7 +2171,9 @@ class P4Sync(Command, P4UserMap):
     def streamOneP4File(self, file, contents):
         relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes)
         if verbose:
-            sys.stderr.write("%s\n" % relPath)
+            size = int(self.stream_file['fileSize'])
+            sys.stdout.write('\r%s --> %s (%i MB)\n' % (file['depotFile'], relPath, size/1024/1024))
+            sys.stdout.flush()
 
         (type_base, type_mods) = split_p4_type(file["type"])
 
@@ -2258,7 +2260,8 @@ class P4Sync(Command, P4UserMap):
     def streamOneP4Deletion(self, file):
         relPath = self.stripRepoPath(file['path'], self.branchPrefixes)
         if verbose:
-            sys.stderr.write("delete %s\n" % relPath)
+            sys.stdout.write("delete %s\n" % relPath)
+            sys.stdout.flush()
         self.gitStream.write("D %s\n" % relPath)
 
     # handle another chunk of streaming data
@@ -2298,10 +2301,23 @@ class P4Sync(Command, P4UserMap):
         # 'data' field we need to append to our array
         for k in marshalled.keys():
             if k == 'data':
+                if 'streamContentSize' not in self.stream_file:
+                    self.stream_file['streamContentSize'] = 0
+                self.stream_file['streamContentSize'] += len(marshalled['data'])
                 self.stream_contents.append(marshalled['data'])
             else:
                 self.stream_file[k] = marshalled[k]
 
+        if (verbose and
+            'streamContentSize' in self.stream_file and
+            'fileSize' in self.stream_file and
+            'depotFile' in self.stream_file):
+            size = int(self.stream_file["fileSize"])
+            if size > 0:
+                progress = 100*self.stream_file['streamContentSize']/size
+                sys.stdout.write('\r%s %d%% (%i MB)' % (self.stream_file['depotFile'], progress, int(size/1024/1024)))
+                sys.stdout.flush()
+
         self.stream_have_file_info = True
 
     # Stream directly from "p4 files" into "git fast-import"
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v7 5/7] git-p4: check free space during streaming
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
                   ` (3 preceding siblings ...)
  2015-09-21 22:41 ` [PATCH v7 4/7] git-p4: add file streaming progress in verbose mode larsxschneider
@ 2015-09-21 22:41 ` larsxschneider
  2015-09-21 22:41 ` [PATCH v7 6/7] git-p4: add support for large file systems larsxschneider
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

git-p4 will just halt if there is not enough disk space while
streaming content from P4 to Git. Add a check to ensure at least
4 times (arbitrarily chosen) the size of a streamed file is available.

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 git-p4.py | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/git-p4.py b/git-p4.py
index fabc900..3931989 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -104,6 +104,16 @@ def chdir(path, is_client_path=False):
         path = os.getcwd()
     os.environ['PWD'] = path
 
+def calcDiskFree(dirname):
+    """Return free space in bytes on the disk of the given dirname."""
+    if platform.system() == 'Windows':
+        free_bytes = ctypes.c_ulonglong(0)
+        ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(dirname), None, None, ctypes.pointer(free_bytes))
+        return free_bytes.value
+    else:
+        st = os.statvfs(dirname)
+        return st.f_bavail * st.f_frsize
+
 def die(msg):
     if verbose:
         raise Exception(msg)
@@ -2045,6 +2055,14 @@ class P4Sync(Command, P4UserMap):
         self.clientSpecDirs = None
         self.tempBranches = []
         self.tempBranchLocation = "git-p4-tmp"
+        self.largeFileSystem = None
+        self.cloneDestination = None
+
+        if gitConfig('git-p4.largeFileSystem'):
+            largeFileSystemConstructor = globals()[gitConfig('git-p4.largeFileSystem')]
+            self.largeFileSystem = largeFileSystemConstructor(
+                lambda git_mode, relPath, contents: self.writeToGitStream(git_mode, relPath, contents)
+            )
 
         if gitConfig("git-p4.syncFromOrigin") == "false":
             self.syncWithOrigin = False
@@ -2273,6 +2291,14 @@ class P4Sync(Command, P4UserMap):
             if marshalled["code"] == "error":
                 if "data" in marshalled:
                     err = marshalled["data"].rstrip()
+
+        if not err and self.cloneDestination and 'fileSize' in self.stream_file:
+            required_bytes = int((4 * int(self.stream_file["fileSize"])) - calcDiskFree(self.cloneDestination))
+            if required_bytes > 0:
+                err = 'Not enough space left on %s! Free at least %i MB.' % (
+                    os.path.abspath(self.cloneDestination), required_bytes/1024/1024
+                )
+
         if err:
             f = None
             if self.stream_have_file_info:
@@ -3244,7 +3270,6 @@ class P4Clone(P4Sync):
             optparse.make_option("--bare", dest="cloneBare",
                                  action="store_true", default=False),
         ]
-        self.cloneDestination = None
         self.needsGit = False
         self.cloneBare = False
 
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v7 6/7] git-p4: add support for large file systems
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
                   ` (4 preceding siblings ...)
  2015-09-21 22:41 ` [PATCH v7 5/7] git-p4: check free space during streaming larsxschneider
@ 2015-09-21 22:41 ` larsxschneider
  2015-09-25  9:09   ` Luke Diamand
  2015-09-21 22:41 ` [PATCH v7 7/7] git-p4: add Git LFS backend for large file system larsxschneider
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

Perforce repositories can contain large (binary) files. Migrating these
repositories to Git generates very large local clones. External storage
systems such as Git LFS [1], Git Fat [2], Git Media [3], git-annex [4]
try to address this problem.

Add a generic mechanism to detect large files based on extension,
uncompressed size, and/or compressed size.

[1] https://git-lfs.github.com/
[2] https://github.com/jedbrown/git-fat
[3] https://github.com/alebedev/git-media
[4] https://git-annex.branchable.com/

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 Documentation/git-p4.txt   |  32 +++++++++
 git-p4.py                  | 138 +++++++++++++++++++++++++++++++++---
 t/t9823-git-p4-mock-lfs.sh | 170 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 330 insertions(+), 10 deletions(-)
 create mode 100755 t/t9823-git-p4-mock-lfs.sh

diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt
index 12a57d4..19833e6 100644
--- a/Documentation/git-p4.txt
+++ b/Documentation/git-p4.txt
@@ -517,6 +517,38 @@ git-p4.pathEncoding::
 	to transcode the paths to UTF-8. As an example, Perforce on Windows
 	often uses “cp1252” to encode path names.
 
+git-p4.largeFileSystem::
+	Specify the system that is used for large (binary) files. Please note
+	that large file systems do not support the 'git p4 submit' command.
+	Only Git LFS [1] is implemented right now. Download
+	and install the Git LFS command line extension to use this option
+	and configure it like this:
++
+-------------
+git config       git-p4.largeFileSystem GitLFS
+-------------
++
+	[1] https://git-lfs.github.com/
+
+git-p4.largeFileExtensions::
+	All files matching a file extension in the list will be processed
+	by the large file system. Do not prefix the extensions with '.'.
+
+git-p4.largeFileThreshold::
+	All files with an uncompressed size exceeding the threshold will be
+	processed by the large file system. By default the threshold is
+	defined in bytes. Add the suffix k, m, or g to change the unit.
+
+git-p4.largeFileCompressedThreshold::
+	All files with a compressed size exceeding the threshold will be
+	processed by the large file system. This option might slow down
+	your clone/sync process. By default the threshold is defined in
+	bytes. Add the suffix k, m, or g to change the unit.
+
+git-p4.pushLargeFiles::
+	Boolean variable which defines if large files are automatically
+	pushed to a server.
+
 Submit variables
 ~~~~~~~~~~~~~~~~
 git-p4.detectRenames::
diff --git a/git-p4.py b/git-p4.py
index 3931989..7a80ebd 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -22,6 +22,8 @@ import platform
 import re
 import shutil
 import stat
+import zipfile
+import zlib
 
 try:
     from subprocess import CalledProcessError
@@ -932,6 +934,110 @@ def wildcard_present(path):
     m = re.search("[*#@%]", path)
     return m is not None
 
+class LargeFileSystem(object):
+    """Base class for large file system support."""
+
+    def __init__(self, writeToGitStream):
+        self.largeFiles = set()
+        self.writeToGitStream = writeToGitStream
+
+    def generatePointer(self, cloneDestination, contentFile):
+        """Return the content of a pointer file that is stored in Git instead of
+           the actual content."""
+        assert False, "Method 'generatePointer' required in " + self.__class__.__name__
+
+    def pushFile(self, localLargeFile):
+        """Push the actual content which is not stored in the Git repository to
+           a server."""
+        assert False, "Method 'pushFile' required in " + self.__class__.__name__
+
+    def hasLargeFileExtension(self, relPath):
+        return reduce(
+            lambda a, b: a or b,
+            [relPath.endswith('.' + e) for e in gitConfigList('git-p4.largeFileExtensions')],
+            False
+        )
+
+    def generateTempFile(self, contents):
+        contentFile = tempfile.NamedTemporaryFile(prefix='git-p4-large-file', delete=False)
+        for d in contents:
+            contentFile.write(d)
+        contentFile.close()
+        return contentFile.name
+
+    def exceedsLargeFileThreshold(self, relPath, contents):
+        if gitConfigInt('git-p4.largeFileThreshold'):
+            contentsSize = sum(len(d) for d in contents)
+            if contentsSize > gitConfigInt('git-p4.largeFileThreshold'):
+                return True
+        if gitConfigInt('git-p4.largeFileCompressedThreshold'):
+            contentsSize = sum(len(d) for d in contents)
+            if contentsSize <= gitConfigInt('git-p4.largeFileCompressedThreshold'):
+                return False
+            contentTempFile = self.generateTempFile(contents)
+            compressedContentFile = tempfile.NamedTemporaryFile(prefix='git-p4-large-file', delete=False)
+            zf = zipfile.ZipFile(compressedContentFile.name, mode='w')
+            zf.write(contentTempFile, compress_type=zipfile.ZIP_DEFLATED)
+            zf.close()
+            compressedContentsSize = zf.infolist()[0].compress_size
+            os.remove(contentTempFile)
+            os.remove(compressedContentFile.name)
+            if compressedContentsSize > gitConfigInt('git-p4.largeFileCompressedThreshold'):
+                return True
+        return False
+
+    def addLargeFile(self, relPath):
+        self.largeFiles.add(relPath)
+
+    def removeLargeFile(self, relPath):
+        self.largeFiles.remove(relPath)
+
+    def isLargeFile(self, relPath):
+        return relPath in self.largeFiles
+
+    def processContent(self, cloneDestination, git_mode, relPath, contents):
+        """Processes the content of git fast import. This method decides if a
+           file is stored in the large file system and handles all necessary
+           steps."""
+        if self.exceedsLargeFileThreshold(relPath, contents) or self.hasLargeFileExtension(relPath):
+            contentTempFile = self.generateTempFile(contents)
+            (git_mode, contents, localLargeFile) = self.generatePointer(cloneDestination, contentTempFile)
+
+            # Move temp file to final location in large file system
+            largeFileDir = os.path.dirname(localLargeFile)
+            if not os.path.isdir(largeFileDir):
+                os.makedirs(largeFileDir)
+            shutil.move(contentTempFile, localLargeFile)
+            self.addLargeFile(relPath)
+            if gitConfigBool('git-p4.pushLargeFiles'):
+                self.pushFile(localLargeFile)
+            if verbose:
+                sys.stderr.write("%s moved to large file system (%s)\n" % (relPath, localLargeFile))
+        return (git_mode, contents)
+
+class MockLFS(LargeFileSystem):
+    """Mock large file system for testing."""
+
+    def generatePointer(self, cloneDestination, contentFile):
+        """The pointer content is the original content prefixed with "pointer-".
+           The local filename of the large file storage is derived from the file content.
+           """
+        with open(contentFile, 'r') as f:
+            content = next(f)
+            gitMode = '100644'
+            pointerContents = 'pointer-' + content
+            localLargeFile = os.path.join(cloneDestination, '.git', 'mock-storage', 'local', content[:-1])
+            return (gitMode, pointerContents, localLargeFile)
+
+    def pushFile(self, localLargeFile):
+        """The remote filename of the large file storage is the same as the local
+           one but in a different directory.
+           """
+        remotePath = os.path.join(os.path.dirname(localLargeFile), '..', 'remote')
+        if not os.path.exists(remotePath):
+            os.makedirs(remotePath)
+        shutil.copyfile(localLargeFile, os.path.join(remotePath, os.path.basename(localLargeFile)))
+
 class Command:
     def __init__(self):
         self.usage = "usage: %prog [options]"
@@ -1105,6 +1211,9 @@ class P4Submit(Command, P4UserMap):
         self.p4HasMoveCommand = p4_has_move_command()
         self.branch = None
 
+        if gitConfig('git-p4.largeFileSystem'):
+            die("Large file system not supported for git-p4 submit command. Please remove it from config.")
+
     def check(self):
         if len(p4CmdList("opened ...")) > 0:
             die("You have files opened with perforce! Close them before starting the sync.")
@@ -2064,6 +2173,12 @@ class P4Sync(Command, P4UserMap):
                 lambda git_mode, relPath, contents: self.writeToGitStream(git_mode, relPath, contents)
             )
 
+        if gitConfig('git-p4.largeFileSystem'):
+            largeFileSystemConstructor = globals()[gitConfig('git-p4.largeFileSystem')]
+            self.largeFileSystem = largeFileSystemConstructor(
+                lambda git_mode, relPath, contents: self.writeToGitStream(git_mode, relPath, contents)
+            )
+
         if gitConfig("git-p4.syncFromOrigin") == "false":
             self.syncWithOrigin = False
 
@@ -2183,6 +2298,13 @@ class P4Sync(Command, P4UserMap):
 
         return branches
 
+    def writeToGitStream(self, gitMode, relPath, contents):
+        self.gitStream.write('M %s inline %s\n' % (gitMode, relPath))
+        self.gitStream.write('data %d\n' % sum(len(d) for d in contents))
+        for d in contents:
+            self.gitStream.write(d)
+        self.gitStream.write('\n')
+
     # output one file from the P4 stream
     # - helper for streamP4Files
 
@@ -2263,17 +2385,10 @@ class P4Sync(Command, P4UserMap):
             if self.verbose:
                 print 'Path with non-ASCII characters detected. Used %s to encode: %s ' % (encoding, relPath)
 
-        self.gitStream.write("M %s inline %s\n" % (git_mode, relPath))
+        if self.largeFileSystem:
+            (git_mode, contents) = self.largeFileSystem.processContent(self.cloneDestination, git_mode, relPath, contents)
 
-        # total length...
-        length = 0
-        for d in contents:
-            length = length + len(d)
-
-        self.gitStream.write("data %d\n" % length)
-        for d in contents:
-            self.gitStream.write(d)
-        self.gitStream.write("\n")
+        self.writeToGitStream(git_mode, relPath, contents)
 
     def streamOneP4Deletion(self, file):
         relPath = self.stripRepoPath(file['path'], self.branchPrefixes)
@@ -2282,6 +2397,9 @@ class P4Sync(Command, P4UserMap):
             sys.stdout.flush()
         self.gitStream.write("D %s\n" % relPath)
 
+        if self.largeFileSystem and self.largeFileSystem.isLargeFile(relPath):
+            self.largeFileSystem.removeLargeFile(relPath)
+
     # handle another chunk of streaming data
     def streamP4FilesCb(self, marshalled):
 
diff --git a/t/t9823-git-p4-mock-lfs.sh b/t/t9823-git-p4-mock-lfs.sh
new file mode 100755
index 0000000..5684ee3
--- /dev/null
+++ b/t/t9823-git-p4-mock-lfs.sh
@@ -0,0 +1,170 @@
+#!/bin/sh
+
+test_description='Clone repositories and store files in Mock LFS'
+
+. ./lib-git-p4.sh
+
+test_file_is_not_in_mock_lfs () {
+	FILE="$1" &&
+	CONTENT="$2" &&
+	echo "$CONTENT" >expect_content &&
+	test_path_is_file "$FILE" &&
+	test_cmp expect_content "$FILE"
+}
+
+test_file_is_in_mock_lfs () {
+	FILE="$1" &&
+	CONTENT="$2" &&
+	LOCAL_STORAGE=".git/mock-storage/local/$CONTENT" &&
+	SERVER_STORAGE=".git/mock-storage/remote/$CONTENT" &&
+	echo "pointer-$CONTENT" >expect_pointer &&
+	echo "$CONTENT" >expect_content &&
+	test_path_is_file "$FILE" &&
+	test_path_is_file "$LOCAL_STORAGE" &&
+	test_path_is_file "$SERVER_STORAGE" &&
+	test_cmp expect_pointer "$FILE" &&
+	test_cmp expect_content "$LOCAL_STORAGE" &&
+	test_cmp expect_content "$SERVER_STORAGE"
+}
+
+test_file_is_deleted_in_mock_lfs () {
+	FILE="$1" &&
+	CONTENT="$2" &&
+	LOCAL_STORAGE=".git/mock-storage/local/$CONTENT" &&
+	SERVER_STORAGE=".git/mock-storage/remote/$CONTENT" &&
+	echo "pointer-$CONTENT" >expect_pointer &&
+	echo "$CONTENT" >expect_content &&
+	! test_path_is_file "$FILE" &&
+	test_path_is_file "$LOCAL_STORAGE" &&
+	test_path_is_file "$SERVER_STORAGE" &&
+	test_cmp expect_content "$LOCAL_STORAGE" &&
+	test_cmp expect_content "$SERVER_STORAGE"
+}
+
+test_file_count_in_dir () {
+	DIR="$1" &&
+	EXPECTED_COUNT="$2" &&
+	find "$DIR" -type f >actual &&
+	test_line_count = $EXPECTED_COUNT actual
+}
+
+test_expect_success 'start p4d' '
+	start_p4d
+'
+
+test_expect_success 'Create repo with binary files' '
+	client_view "//depot/... //client/..." &&
+	(
+		cd "$cli" &&
+
+		echo "content 1 txt 23 bytes" >file1.txt &&
+		p4 add file1.txt &&
+		echo "content 2-3 bin 25 bytes" >file2.dat &&
+		p4 add file2.dat &&
+		p4 submit -d "Add text and binary file" &&
+
+		mkdir "path with spaces" &&
+		echo "content 2-3 bin 25 bytes" >"path with spaces/file3.bin" &&
+		p4 add "path with spaces/file3.bin" &&
+		p4 submit -d "Add another binary file with same content and spaces in path" &&
+
+		echo "content 4 bin 26 bytes XX" >file4.bin &&
+		p4 add file4.bin &&
+		p4 submit -d "Add another binary file with different content"
+	)
+'
+
+test_expect_success 'Store files in Mock LFS based on size (>24 bytes)' '
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem MockLFS &&
+		git config git-p4.largeFileThreshold 24 &&
+		git config git-p4.pushLargeFiles True &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" &&
+		test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" &&
+		test_file_is_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" &&
+		test_file_is_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" &&
+
+		test_file_count_in_dir ".git/mock-storage/local" 2 &&
+		test_file_count_in_dir ".git/mock-storage/remote" 2
+	)
+'
+
+test_expect_success 'Store files in Mock LFS based on extension (dat)' '
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem MockLFS &&
+		git config git-p4.largeFileExtensions dat &&
+		git config git-p4.pushLargeFiles True &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" &&
+		test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" &&
+		test_file_is_not_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" &&
+		test_file_is_not_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" &&
+
+		test_file_count_in_dir ".git/mock-storage/local" 1 &&
+		test_file_count_in_dir ".git/mock-storage/remote" 1
+	)
+'
+
+test_expect_success 'Remove file from repo and store files in Mock LFS based on size (>24 bytes)' '
+	client_view "//depot/... //client/..." &&
+	(
+		cd "$cli" &&
+		p4 delete file4.bin &&
+		p4 submit -d "Remove file"
+	) &&
+
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem MockLFS &&
+		git config git-p4.largeFileThreshold 24 &&
+		git config git-p4.pushLargeFiles True &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" &&
+		test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" &&
+		test_file_is_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" &&
+		test_file_is_deleted_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" &&
+
+		test_file_count_in_dir ".git/mock-storage/local" 2 &&
+		test_file_count_in_dir ".git/mock-storage/remote" 2
+	)
+'
+
+test_expect_success 'Run git p4 submit in repo configured with large file system' '
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem MockLFS &&
+		git config git-p4.largeFileThreshold 24 &&
+		git config git-p4.pushLargeFiles True &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_must_fail git p4 submit
+	)
+'
+
+test_expect_success 'kill p4d' '
+	kill_p4d
+'
+
+test_done
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v7 7/7] git-p4: add Git LFS backend for large file system
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
                   ` (5 preceding siblings ...)
  2015-09-21 22:41 ` [PATCH v7 6/7] git-p4: add support for large file systems larsxschneider
@ 2015-09-21 22:41 ` larsxschneider
  2015-09-22 22:03 ` [PATCH v7 0/7] git-p4: add support for large file systems Junio C Hamano
  2015-09-23  7:58 ` Luke Diamand
  8 siblings, 0 replies; 21+ messages in thread
From: larsxschneider @ 2015-09-21 22:41 UTC (permalink / raw)
  To: git; +Cc: luke, gitster, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

Add example implementation including test cases for the large file
system using Git LFS.

Pushing files to the Git LFS server is not tested.

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 git-p4.py                 |  72 ++++++++++++
 t/t9824-git-p4-git-lfs.sh | 288 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 360 insertions(+)
 create mode 100755 t/t9824-git-p4-git-lfs.sh

diff --git a/git-p4.py b/git-p4.py
index 7a80ebd..fce1d65 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -1038,6 +1038,78 @@ class MockLFS(LargeFileSystem):
             os.makedirs(remotePath)
         shutil.copyfile(localLargeFile, os.path.join(remotePath, os.path.basename(localLargeFile)))
 
+class GitLFS(LargeFileSystem):
+    """Git LFS as backend for the git-p4 large file system.
+       See https://git-lfs.github.com/ for details."""
+
+    def __init__(self, *args):
+        LargeFileSystem.__init__(self, *args)
+        self.baseGitAttributes = []
+
+    def generatePointer(self, cloneDestination, contentFile):
+        """Generate a Git LFS pointer for the content. Return LFS Pointer file
+           mode and content which is stored in the Git repository instead of
+           the actual content. Return also the new location of the actual
+           content.
+           """
+        pointerProcess = subprocess.Popen(
+            ['git', 'lfs', 'pointer', '--file=' + contentFile],
+            stdout=subprocess.PIPE
+        )
+        pointerFile = pointerProcess.stdout.read()
+        if pointerProcess.wait():
+            os.remove(contentFile)
+            die('git-lfs pointer command failed. Did you install the extension?')
+        pointerContents = [i+'\n' for i in pointerFile.split('\n')[2:][:-1]]
+        oid = pointerContents[1].split(' ')[1].split(':')[1][:-1]
+        localLargeFile = os.path.join(
+            cloneDestination,
+            '.git', 'lfs', 'objects', oid[:2], oid[2:4],
+            oid,
+        )
+        # LFS Spec states that pointer files should not have the executable bit set.
+        gitMode = '100644'
+        return (gitMode, pointerContents, localLargeFile)
+
+    def pushFile(self, localLargeFile):
+        uploadProcess = subprocess.Popen(
+            ['git', 'lfs', 'push', '--object-id', 'origin', os.path.basename(localLargeFile)]
+        )
+        if uploadProcess.wait():
+            die('git-lfs push command failed. Did you define a remote?')
+
+    def generateGitAttributes(self):
+        return (
+            self.baseGitAttributes +
+            [
+                '\n',
+                '#\n',
+                '# Git LFS (see https://git-lfs.github.com/)\n',
+                '#\n',
+            ] +
+            ['*.' + f.replace(' ', '[[:space:]]') + ' filter=lfs -text\n'
+                for f in sorted(gitConfigList('git-p4.largeFileExtensions'))
+            ] +
+            ['/' + f.replace(' ', '[[:space:]]') + ' filter=lfs -text\n'
+                for f in sorted(self.largeFiles) if not self.hasLargeFileExtension(f)
+            ]
+        )
+
+    def addLargeFile(self, relPath):
+        LargeFileSystem.addLargeFile(self, relPath)
+        self.writeToGitStream('100644', '.gitattributes', self.generateGitAttributes())
+
+    def removeLargeFile(self, relPath):
+        LargeFileSystem.removeLargeFile(self, relPath)
+        self.writeToGitStream('100644', '.gitattributes', self.generateGitAttributes())
+
+    def processContent(self, cloneDestination, git_mode, relPath, contents):
+        if relPath == '.gitattributes':
+            self.baseGitAttributes = contents
+            return (git_mode, self.generateGitAttributes())
+        else:
+            return LargeFileSystem.processContent(self, cloneDestination, git_mode, relPath, contents)
+
 class Command:
     def __init__(self):
         self.usage = "usage: %prog [options]"
diff --git a/t/t9824-git-p4-git-lfs.sh b/t/t9824-git-p4-git-lfs.sh
new file mode 100755
index 0000000..7385a2b
--- /dev/null
+++ b/t/t9824-git-p4-git-lfs.sh
@@ -0,0 +1,288 @@
+#!/bin/sh
+
+test_description='Clone repositories and store files in Git LFS'
+
+. ./lib-git-p4.sh
+
+git lfs help >/dev/null 2>&1 || {
+	skip_all='skipping git p4 Git LFS tests; Git LFS not found'
+	test_done
+}
+
+test_file_in_lfs () {
+	FILE="$1" &&
+	SIZE="$2" &&
+	EXPECTED_CONTENT="$3" &&
+	cat "$FILE" | grep "size $SIZE" &&
+	HASH=$(cat "$FILE" | grep "oid sha256:" | sed -e "s/oid sha256://g") &&
+	LFS_FILE=".git/lfs/objects/$(echo "$HASH" | cut -c1-2)/$(echo "$HASH" | cut -c3-4)/$HASH" &&
+	echo $EXPECTED_CONTENT >expect &&
+	test_path_is_file "$FILE" &&
+	test_path_is_file "$LFS_FILE" &&
+	test_cmp expect "$LFS_FILE"
+}
+
+test_file_count_in_dir () {
+	DIR="$1" &&
+	EXPECTED_COUNT="$2" &&
+	find "$DIR" -type f >actual &&
+	test_line_count = $EXPECTED_COUNT actual
+}
+
+test_expect_success 'start p4d' '
+	start_p4d
+'
+
+test_expect_success 'Create repo with binary files' '
+	client_view "//depot/... //client/..." &&
+	(
+		cd "$cli" &&
+
+		echo "content 1 txt 23 bytes" >file1.txt &&
+		p4 add file1.txt &&
+		echo "content 2-3 bin 25 bytes" >file2.dat &&
+		p4 add file2.dat &&
+		p4 submit -d "Add text and binary file" &&
+
+		mkdir "path with spaces" &&
+		echo "content 2-3 bin 25 bytes" >"path with spaces/file3.bin" &&
+		p4 add "path with spaces/file3.bin" &&
+		p4 submit -d "Add another binary file with same content and spaces in path" &&
+
+		echo "content 4 bin 26 bytes XX" >file4.bin &&
+		p4 add file4.bin &&
+		p4 submit -d "Add another binary file with different content"
+	)
+'
+
+test_expect_success 'Store files in LFS based on size (>24 bytes)' '
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem GitLFS &&
+		git config git-p4.largeFileThreshold 24 &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&
+		test_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" &&
+		test_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" &&
+
+		test_file_count_in_dir ".git/lfs/objects" 2 &&
+
+		cat >expect <<-\EOF &&
+
+		#
+		# Git LFS (see https://git-lfs.github.com/)
+		#
+		/file2.dat filter=lfs -text
+		/file4.bin filter=lfs -text
+		/path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text
+		EOF
+		test_path_is_file .gitattributes &&
+		test_cmp expect .gitattributes
+	)
+'
+
+test_expect_success 'Store files in LFS based on size (>25 bytes)' '
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem GitLFS &&
+		git config git-p4.largeFileThreshold 25 &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" &&
+		test_file_count_in_dir ".git/lfs/objects" 1 &&
+
+		cat >expect <<-\EOF &&
+
+		#
+		# Git LFS (see https://git-lfs.github.com/)
+		#
+		/file4.bin filter=lfs -text
+		EOF
+		test_path_is_file .gitattributes &&
+		test_cmp expect .gitattributes
+	)
+'
+
+test_expect_success 'Store files in LFS based on extension (dat)' '
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem GitLFS &&
+		git config git-p4.largeFileExtensions dat &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&
+		test_file_count_in_dir ".git/lfs/objects" 1 &&
+
+		cat >expect <<-\EOF &&
+
+		#
+		# Git LFS (see https://git-lfs.github.com/)
+		#
+		*.dat filter=lfs -text
+		EOF
+		test_path_is_file .gitattributes &&
+		test_cmp expect .gitattributes
+	)
+'
+
+test_expect_success 'Store files in LFS based on size (>25 bytes) and extension (dat)' '
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem GitLFS &&
+		git config git-p4.largeFileExtensions dat &&
+		git config git-p4.largeFileThreshold 25 &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&
+		test_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" &&
+		test_file_count_in_dir ".git/lfs/objects" 2 &&
+
+		cat >expect <<-\EOF &&
+
+		#
+		# Git LFS (see https://git-lfs.github.com/)
+		#
+		*.dat filter=lfs -text
+		/file4.bin filter=lfs -text
+		EOF
+		test_path_is_file .gitattributes &&
+		test_cmp expect .gitattributes
+	)
+'
+
+test_expect_success 'Remove file from repo and store files in LFS based on size (>24 bytes)' '
+	client_view "//depot/... //client/..." &&
+	(
+		cd "$cli" &&
+		p4 delete file4.bin &&
+		p4 submit -d "Remove file"
+	) &&
+
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem GitLFS &&
+		git config git-p4.largeFileThreshold 24 &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&
+		test_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" &&
+		! test_path_is_file file4.bin &&
+		test_file_count_in_dir ".git/lfs/objects" 2 &&
+
+		cat >expect <<-\EOF &&
+
+		#
+		# Git LFS (see https://git-lfs.github.com/)
+		#
+		/file2.dat filter=lfs -text
+		/path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text
+		EOF
+		test_path_is_file .gitattributes &&
+		test_cmp expect .gitattributes
+	)
+'
+
+test_expect_success 'Add .gitattributes and store files in LFS based on size (>24 bytes)' '
+	client_view "//depot/... //client/..." &&
+	(
+		cd "$cli" &&
+		echo "*.txt text" >.gitattributes &&
+		p4 add .gitattributes &&
+		p4 submit -d "Add .gitattributes"
+	) &&
+
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem GitLFS &&
+		git config git-p4.largeFileThreshold 24 &&
+		git p4 clone --destination="$git" //depot@all &&
+
+		test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&
+		test_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" &&
+		! test_path_is_file file4.bin &&
+		test_file_count_in_dir ".git/lfs/objects" 2 &&
+
+		cat >expect <<-\EOF &&
+		*.txt text
+
+		#
+		# Git LFS (see https://git-lfs.github.com/)
+		#
+		/file2.dat filter=lfs -text
+		/path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text
+		EOF
+		test_path_is_file .gitattributes &&
+		test_cmp expect .gitattributes
+	)
+'
+
+test_expect_success 'Add big files to repo and store files in LFS based on compressed size (>28 bytes)' '
+	client_view "//depot/... //client/..." &&
+	(
+		cd "$cli" &&
+		echo "content 5 bin 40 bytes XXXXXXXXXXXXXXXX" >file5.bin &&
+		p4 add file5.bin &&
+		p4 submit -d "Add file with small footprint after compression" &&
+
+		echo "content 6 bin 39 bytes XXXXXYYYYYZZZZZ" >file6.bin &&
+		p4 add file6.bin &&
+		p4 submit -d "Add file with large footprint after compression"
+	) &&
+
+	client_view "//depot/... //client/..." &&
+	test_when_finished cleanup_git &&
+	(
+		cd "$git" &&
+		git init . &&
+		git config git-p4.useClientSpec true &&
+		git config git-p4.largeFileSystem GitLFS &&
+		git config git-p4.largeFileCompressedThreshold 28 &&
+		# We only import HEAD here ("@all" is missing!)
+		git p4 clone --destination="$git" //depot &&
+
+		test_file_in_lfs file6.bin 13 "content 6 bin 39 bytes XXXXXYYYYYZZZZZ"
+		test_file_count_in_dir ".git/lfs/objects" 1 &&
+
+		cat >expect <<-\EOF &&
+		*.txt text
+
+		#
+		# Git LFS (see https://git-lfs.github.com/)
+		#
+		/file6.bin filter=lfs -text
+		EOF
+		test_path_is_file .gitattributes &&
+		test_cmp expect .gitattributes
+	)
+'
+
+test_expect_success 'kill p4d' '
+	kill_p4d
+'
+
+test_done
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader
  2015-09-21 22:41 ` [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader larsxschneider
@ 2015-09-22 21:49   ` Junio C Hamano
  2015-09-23  7:38     ` Lars Schneider
  0 siblings, 1 reply; 21+ messages in thread
From: Junio C Hamano @ 2015-09-22 21:49 UTC (permalink / raw)
  To: larsxschneider; +Cc: git, luke

larsxschneider@gmail.com writes:

> From: Lars Schneider <larsxschneider@gmail.com>
>
> The functions “gitConfig” and “gitConfigBool” are almost identical. Make “gitConfig” more generic by adding an optional type specifier. Use the type specifier “—bool” with “gitConfig” to implement “gitConfigBool. This prepares the implementation of other type specifiers such as “—int”.

What is this overlong single line paragraph?  Is this a MUA artifact
on my end?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
                   ` (6 preceding siblings ...)
  2015-09-21 22:41 ` [PATCH v7 7/7] git-p4: add Git LFS backend for large file system larsxschneider
@ 2015-09-22 22:03 ` Junio C Hamano
  2015-09-23  7:41   ` Lars Schneider
  2015-09-23  7:58 ` Luke Diamand
  8 siblings, 1 reply; 21+ messages in thread
From: Junio C Hamano @ 2015-09-22 22:03 UTC (permalink / raw)
  To: larsxschneider; +Cc: git, luke

larsxschneider@gmail.com writes:

> From: Lars Schneider <larsxschneider@gmail.com>
>
> diff to v6:
> * fix spaces in .gitattributes for Git-LFS files (old "[:space:]", new "[[:space:]]")
> * generated patch on top of next (95c4325) to resolve merge conflicts
>
> I am sorry about the "[:space:]" bug this late. I had the fix in my development
> branch but missed to apply it in this patch series.
>
> @Junio:
> Your conflict resolution in pu looks good. Nevertheless, I made this patch on
> top of next to ease the integration. I hope this is ok.

Please don't rebase without a good reason, especially after you
checked the conflict resolution is OK and your reroll does not
affect the way the conflicts are resolved.  If you based your
v6 patch on v2.6.0-rc0 and then your v7 patch needs to use something
that did not exist v2.6.0-rc3, you cannot avoid rebasing on top of
that newer codebase to use that new feature, but otherwise, no.

This is because I prefer to apply the new series to the same base
version so that each step can be compared with the corresponding
step in the previous round.

I even try hard to keep the commits from the older round if the
patch text and log message are unchanged.  This time, I had to
backport [v7 6/7] to apply to the same base before noticing and
verifying that [v7 7/7] is the only thing that was changed in this
round.  All the other ones turned out to be identical.

Hence, the end result for me was

    $ git checkout ls/p4-lfs
    $ git reset --hard HEAD^
    $ git am -s git-p4-lfs-7-of-7.mbox

but it took me a lot longer than necessary because of the rebase.

Thanks.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader
  2015-09-22 21:49   ` Junio C Hamano
@ 2015-09-23  7:38     ` Lars Schneider
  0 siblings, 0 replies; 21+ messages in thread
From: Lars Schneider @ 2015-09-23  7:38 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, luke


On 22 Sep 2015, at 23:49, Junio C Hamano <gitster@pobox.com> wrote:

> larsxschneider@gmail.com writes:
> 
>> From: Lars Schneider <larsxschneider@gmail.com>
>> 
>> The functions “gitConfig” and “gitConfigBool” are almost identical. Make “gitConfig” more generic by adding an optional type specifier. Use the type specifier “—bool” with “gitConfig” to implement “gitConfigBool. This prepares the implementation of other type specifiers such as “—int”.
> 
> What is this overlong single line paragraph?  Is this a MUA artifact
> on my end?
> 
No. It looks like I messed that up. Same is true for the commit “git-p4: add gitConfigInt reader”. I’ll be more careful in the future.

Sorry,
Lars

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-22 22:03 ` [PATCH v7 0/7] git-p4: add support for large file systems Junio C Hamano
@ 2015-09-23  7:41   ` Lars Schneider
  0 siblings, 0 replies; 21+ messages in thread
From: Lars Schneider @ 2015-09-23  7:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, luke


On 23 Sep 2015, at 00:03, Junio C Hamano <gitster@pobox.com> wrote:

> larsxschneider@gmail.com writes:
> 
>> From: Lars Schneider <larsxschneider@gmail.com>
>> 
>> diff to v6:
>> * fix spaces in .gitattributes for Git-LFS files (old "[:space:]", new "[[:space:]]")
>> * generated patch on top of next (95c4325) to resolve merge conflicts
>> 
>> I am sorry about the "[:space:]" bug this late. I had the fix in my development
>> branch but missed to apply it in this patch series.
>> 
>> @Junio:
>> Your conflict resolution in pu looks good. Nevertheless, I made this patch on
>> top of next to ease the integration. I hope this is ok.
> 
> Please don't rebase without a good reason, especially after you
> checked the conflict resolution is OK and your reroll does not
> affect the way the conflicts are resolved.  If you based your
> v6 patch on v2.6.0-rc0 and then your v7 patch needs to use something
> that did not exist v2.6.0-rc3, you cannot avoid rebasing on top of
> that newer codebase to use that new feature, but otherwise, no.
> 
> This is because I prefer to apply the new series to the same base
> version so that each step can be compared with the corresponding
> step in the previous round.
> 
> I even try hard to keep the commits from the older round if the
> patch text and log message are unchanged.  This time, I had to
> backport [v7 6/7] to apply to the same base before noticing and
> verifying that [v7 7/7] is the only thing that was changed in this
> round.  All the other ones turned out to be identical.
> 
> Hence, the end result for me was
> 
>    $ git checkout ls/p4-lfs
>    $ git reset --hard HEAD^
>    $ git am -s git-p4-lfs-7-of-7.mbox
> 
> but it took me a lot longer than necessary because of the rebase.
> 
Understood. Thanks for taking the time and explaining me your workflow. That helps a lot as my intention was to save your time, not waste it.

Sorry,
Lars

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
                   ` (7 preceding siblings ...)
  2015-09-22 22:03 ` [PATCH v7 0/7] git-p4: add support for large file systems Junio C Hamano
@ 2015-09-23  7:58 ` Luke Diamand
  2015-09-23  8:18   ` Lars Schneider
  8 siblings, 1 reply; 21+ messages in thread
From: Luke Diamand @ 2015-09-23  7:58 UTC (permalink / raw)
  To: Lars Schneider; +Cc: Git Users, Junio C Hamano

On 21 September 2015 at 23:41,  <larsxschneider@gmail.com> wrote:
> From: Lars Schneider <larsxschneider@gmail.com>
>
> diff to v6:
> * fix spaces in .gitattributes for Git-LFS files (old "[:space:]", new "[[:space:]]")
> * generated patch on top of next (95c4325) to resolve merge conflicts

Trying this out by hand (rather than using the test cases) it crashes
for me. Am I doing something wrong?

- I've got the version of git-p4.py from
ef93b8df71f6d8a7936786c989714868c2d3540c in Junio's ls/p4-lfs branch.
- I have git-lfs v0.60 (just downloaded the binary distribution).

Then I created a p4 repo, and added two files in Perforce, small.txt
and bigfile. bigfile is 400k.

Doing a regular git clone works fine:

$ mkdir depot
$ cd depot
$ git init .
$ git p4 sync //depot
$ git checkout p4/master

(I'm using git init + git sync rather than git clone so that I can
setup the git config variables I need in the next step).

Doing a clone with LFS support though doesn't work:

$ mkdir depot2
$ cd depot2
$ git init
$ git config git-p4.largeFileSystem GitLFS
$ git config git-p4.largeFileThreshold 100k
$ git p4 sync //depot
Doing initial import of //depot/ from revision #head into refs/remotes/p4/master
Traceback (most recent call last):
  File "/home/ldiamand/git/git/git-p4.py", line 3624, in <module>
    main()
  File "/home/ldiamand/git/git/git-p4.py", line 3618, in main
    if not cmd.run(args):
  File "/home/ldiamand/git/git/git-p4.py", line 3298, in run
    self.importHeadRevision(revision)
  File "/home/ldiamand/git/git/git-p4.py", line 3085, in importHeadRevision
    self.commit(details, self.extractFilesFromCommit(details), self.branch)
  File "/home/ldiamand/git/git/git-p4.py", line 2651, in commit
    self.streamP4Files(new_files)
  File "/home/ldiamand/git/git/git-p4.py", line 2565, in streamP4Files
    cb=streamP4FilesCbSelf)
  File "/home/ldiamand/git/git/git-p4.py", line 501, in p4CmdList
    cb(entry)
  File "/home/ldiamand/git/git/git-p4.py", line 2559, in streamP4FilesCbSelf
    self.streamP4FilesCb(entry)
  File "/home/ldiamand/git/git/git-p4.py", line 2501, in streamP4FilesCb
    self.streamOneP4File(self.stream_file, self.stream_contents)
  File "/home/ldiamand/git/git/git-p4.py", line 2451, in streamOneP4File
    (git_mode, contents) =
self.largeFileSystem.processContent(self.cloneDestination, git_mode,
relPath, contents)
  File "/home/ldiamand/git/git/git-p4.py", line 1111, in processContent
    return LargeFileSystem.processContent(self, cloneDestination,
git_mode, relPath, contents)
  File "/home/ldiamand/git/git/git-p4.py", line 1004, in processContent
    (git_mode, contents, localLargeFile) =
self.generatePointer(cloneDestination, contentTempFile)
  File "/home/ldiamand/git/git/git-p4.py", line 1068, in generatePointer
    oid,
  File "/usr/lib/python2.7/posixpath.py", line 70, in join
    elif path == '' or path.endswith('/'):
AttributeError: 'NoneType' object has no attribute 'endswith'


The test cases work fine, t9823 and t9824.

Thanks
Luke

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-23  7:58 ` Luke Diamand
@ 2015-09-23  8:18   ` Lars Schneider
  2015-09-23  8:50     ` Lars Schneider
  0 siblings, 1 reply; 21+ messages in thread
From: Lars Schneider @ 2015-09-23  8:18 UTC (permalink / raw)
  To: Luke Diamand; +Cc: Git Users, Junio C Hamano


On 23 Sep 2015, at 09:58, Luke Diamand <luke@diamand.org> wrote:

> On 21 September 2015 at 23:41,  <larsxschneider@gmail.com> wrote:
>> From: Lars Schneider <larsxschneider@gmail.com>
>> 
>> diff to v6:
>> * fix spaces in .gitattributes for Git-LFS files (old "[:space:]", new "[[:space:]]")
>> * generated patch on top of next (95c4325) to resolve merge conflicts
> 
> Trying this out by hand (rather than using the test cases) it crashes
> for me. Am I doing something wrong?
> 
> - I've got the version of git-p4.py from
> ef93b8df71f6d8a7936786c989714868c2d3540c in Junio's ls/p4-lfs branch.
> - I have git-lfs v0.60 (just downloaded the binary distribution).
> 
> Then I created a p4 repo, and added two files in Perforce, small.txt
> and bigfile. bigfile is 400k.
> 
> Doing a regular git clone works fine:
> 
> $ mkdir depot
> $ cd depot
> $ git init .
> $ git p4 sync //depot
> $ git checkout p4/master
> 
> (I'm using git init + git sync rather than git clone so that I can
> setup the git config variables I need in the next step).
> 
> Doing a clone with LFS support though doesn't work:
> 
> $ mkdir depot2
> $ cd depot2
> $ git init
> $ git config git-p4.largeFileSystem GitLFS
> $ git config git-p4.largeFileThreshold 100k
> $ git p4 sync //depot
> Doing initial import of //depot/ from revision #head into refs/remotes/p4/master
> Traceback (most recent call last):
>  File "/home/ldiamand/git/git/git-p4.py", line 3624, in <module>
>    main()
>  File "/home/ldiamand/git/git/git-p4.py", line 3618, in main
>    if not cmd.run(args):
>  File "/home/ldiamand/git/git/git-p4.py", line 3298, in run
>    self.importHeadRevision(revision)
>  File "/home/ldiamand/git/git/git-p4.py", line 3085, in importHeadRevision
>    self.commit(details, self.extractFilesFromCommit(details), self.branch)
>  File "/home/ldiamand/git/git/git-p4.py", line 2651, in commit
>    self.streamP4Files(new_files)
>  File "/home/ldiamand/git/git/git-p4.py", line 2565, in streamP4Files
>    cb=streamP4FilesCbSelf)
>  File "/home/ldiamand/git/git/git-p4.py", line 501, in p4CmdList
>    cb(entry)
>  File "/home/ldiamand/git/git/git-p4.py", line 2559, in streamP4FilesCbSelf
>    self.streamP4FilesCb(entry)
>  File "/home/ldiamand/git/git/git-p4.py", line 2501, in streamP4FilesCb
>    self.streamOneP4File(self.stream_file, self.stream_contents)
>  File "/home/ldiamand/git/git/git-p4.py", line 2451, in streamOneP4File
>    (git_mode, contents) =
> self.largeFileSystem.processContent(self.cloneDestination, git_mode,
> relPath, contents)
>  File "/home/ldiamand/git/git/git-p4.py", line 1111, in processContent
>    return LargeFileSystem.processContent(self, cloneDestination,
> git_mode, relPath, contents)
>  File "/home/ldiamand/git/git/git-p4.py", line 1004, in processContent
>    (git_mode, contents, localLargeFile) =
> self.generatePointer(cloneDestination, contentTempFile)
>  File "/home/ldiamand/git/git/git-p4.py", line 1068, in generatePointer
>    oid,
>  File "/usr/lib/python2.7/posixpath.py", line 70, in join
>    elif path == '' or path.endswith('/'):
> AttributeError: 'NoneType' object has no attribute 'endswith'
> 
Confirmed. This is a bug!

Can you try the following sequence of commands?

$ mkdir depot2
$ cd depot2
$ git init
$ git config git-p4.largeFileSystem GitLFS
$ git config git-p4.largeFileThreshold 100k
$ git p4 clone --destination=. //depot

I’ve always used “clone” and all test cases uses “clone”. I will fix it for “sync”.

Thanks for reporting,
Lars

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-23  8:18   ` Lars Schneider
@ 2015-09-23  8:50     ` Lars Schneider
       [not found]       ` <CAE5ih7-NqSd+zSqTungDt5oWzy4QT--vjYaShd=YDzGxHosz3A@mail.gmail.com>
  0 siblings, 1 reply; 21+ messages in thread
From: Lars Schneider @ 2015-09-23  8:50 UTC (permalink / raw)
  To: Luke Diamand; +Cc: Git Users, Junio C Hamano


On 23 Sep 2015, at 10:18, Lars Schneider <larsxschneider@gmail.com> wrote:

> 
> On 23 Sep 2015, at 09:58, Luke Diamand <luke@diamand.org> wrote:
> 
>> On 21 September 2015 at 23:41,  <larsxschneider@gmail.com> wrote:
>>> From: Lars Schneider <larsxschneider@gmail.com>
>>> 
>>> diff to v6:
>>> * fix spaces in .gitattributes for Git-LFS files (old "[:space:]", new "[[:space:]]")
>>> * generated patch on top of next (95c4325) to resolve merge conflicts
>> 
>> Trying this out by hand (rather than using the test cases) it crashes
>> for me. Am I doing something wrong?
>> 
>> - I've got the version of git-p4.py from
>> ef93b8df71f6d8a7936786c989714868c2d3540c in Junio's ls/p4-lfs branch.
>> - I have git-lfs v0.60 (just downloaded the binary distribution).
>> 
>> Then I created a p4 repo, and added two files in Perforce, small.txt
>> and bigfile. bigfile is 400k.
>> 
>> Doing a regular git clone works fine:
>> 
>> $ mkdir depot
>> $ cd depot
>> $ git init .
>> $ git p4 sync //depot
>> $ git checkout p4/master
>> 
>> (I'm using git init + git sync rather than git clone so that I can
>> setup the git config variables I need in the next step).
>> 
>> Doing a clone with LFS support though doesn't work:
>> 
>> $ mkdir depot2
>> $ cd depot2
>> $ git init
>> $ git config git-p4.largeFileSystem GitLFS
>> $ git config git-p4.largeFileThreshold 100k
>> $ git p4 sync //depot
>> Doing initial import of //depot/ from revision #head into refs/remotes/p4/master
>> Traceback (most recent call last):
>> File "/home/ldiamand/git/git/git-p4.py", line 3624, in <module>
>>   main()
>> File "/home/ldiamand/git/git/git-p4.py", line 3618, in main
>>   if not cmd.run(args):
>> File "/home/ldiamand/git/git/git-p4.py", line 3298, in run
>>   self.importHeadRevision(revision)
>> File "/home/ldiamand/git/git/git-p4.py", line 3085, in importHeadRevision
>>   self.commit(details, self.extractFilesFromCommit(details), self.branch)
>> File "/home/ldiamand/git/git/git-p4.py", line 2651, in commit
>>   self.streamP4Files(new_files)
>> File "/home/ldiamand/git/git/git-p4.py", line 2565, in streamP4Files
>>   cb=streamP4FilesCbSelf)
>> File "/home/ldiamand/git/git/git-p4.py", line 501, in p4CmdList
>>   cb(entry)
>> File "/home/ldiamand/git/git/git-p4.py", line 2559, in streamP4FilesCbSelf
>>   self.streamP4FilesCb(entry)
>> File "/home/ldiamand/git/git/git-p4.py", line 2501, in streamP4FilesCb
>>   self.streamOneP4File(self.stream_file, self.stream_contents)
>> File "/home/ldiamand/git/git/git-p4.py", line 2451, in streamOneP4File
>>   (git_mode, contents) =
>> self.largeFileSystem.processContent(self.cloneDestination, git_mode,
>> relPath, contents)
>> File "/home/ldiamand/git/git/git-p4.py", line 1111, in processContent
>>   return LargeFileSystem.processContent(self, cloneDestination,
>> git_mode, relPath, contents)
>> File "/home/ldiamand/git/git/git-p4.py", line 1004, in processContent
>>   (git_mode, contents, localLargeFile) =
>> self.generatePointer(cloneDestination, contentTempFile)
>> File "/home/ldiamand/git/git/git-p4.py", line 1068, in generatePointer
>>   oid,
>> File "/usr/lib/python2.7/posixpath.py", line 70, in join
>>   elif path == '' or path.endswith('/'):
>> AttributeError: 'NoneType' object has no attribute 'endswith'
>> 
> Confirmed. This is a bug!
> 
> Can you try the following sequence of commands?
> 
> $ mkdir depot2
> $ cd depot2
> $ git init
> $ git config git-p4.largeFileSystem GitLFS
> $ git config git-p4.largeFileThreshold 100k
> $ git p4 clone --destination=. //depot
> 
> I’ve always used “clone” and all test cases uses “clone”. I will fix it for “sync”.
> 
> Thanks for reporting,
> Lars

I think I found an easy fix. Can you try it?

(in case my mail app messes something up: I changed line 2240 in git-p4.py to 'self.cloneDestination = os.getcwd()’)

Thanks,
Lars


diff --git a/git-p4.py b/git-p4.py
index 8c7496d..1d1bb87 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -2237,7 +2237,7 @@ class P4Sync(Command, P4UserMap):
         self.tempBranches = []
         self.tempBranchLocation = "git-p4-tmp"
         self.largeFileSystem = None
-        self.cloneDestination = None
+        self.cloneDestination = os.getcwd()

         if gitConfig('git-p4.largeFileSystem'):
             largeFileSystemConstructor = globals()[gitConfig('git-p4.largeFileSystem')]
diff --git a/t/t9824-git-p4-git-lfs.sh b/t/t9824-git-p4-git-lfs.sh
index 7385a2b..6d374c0 100755
--- a/t/t9824-git-p4-git-lfs.sh
+++ b/t/t9824-git-p4-git-lfs.sh
@@ -86,6 +86,35 @@ test_expect_success 'Store files in LFS based on size (>24 bytes)' '
        )
 '

+test_expect_success 'Store files in LFS based on size (>24 bytes) and use git p4 sync and no client spec' '
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               git init . &&
+               git config git-p4.largeFileSystem GitLFS &&
+               git config git-p4.largeFileThreshold 24 &&
+               git p4 sync //depot &&
+               git checkout p4/master
+               test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&
+               test_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" &&
+               test_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" &&
+
+               test_file_count_in_dir ".git/lfs/objects" 2 &&
+
+               cat >expect <<-\EOF &&
+
+               #
+               # Git LFS (see https://git-lfs.github.com/)
+               #
+               /file2.dat filter=lfs -text
+               /file4.bin filter=lfs -text
+               /path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text
+               EOF
+               test_path_is_file .gitattributes &&
+               test_cmp expect .gitattributes
+       )
+'
+
 test_expect_success 'Store files in LFS based on size (>25 bytes)' '
        client_view "//depot/... //client/..." &&
        test_when_finished cleanup_git &&

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
       [not found]           ` <CAE5ih7_StiXA-c5yER9jhc941vsKfvEUONLXQ4E7JANOhCxMxQ@mail.gmail.com>
@ 2015-09-23 11:25             ` Luke Diamand
  2015-09-23 11:42               ` Lars Schneider
  0 siblings, 1 reply; 21+ messages in thread
From: Luke Diamand @ 2015-09-23 11:25 UTC (permalink / raw)
  To: Lars Schneider; +Cc: Git Users, Junio C Hamano

Adding back git@vger.kernel.org, which I inadvertently dropped off the thread.

On 23 September 2015 at 12:22, Luke Diamand <luke@diamand.org> wrote:
> On 23 September 2015 at 11:09, Lars Schneider <larsxschneider@gmail.com> wrote:
>>
>> On 23 Sep 2015, at 11:22, Luke Diamand <luke@diamand.org> wrote:
>>
>>> On 23 September 2015 at 09:50, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>
>>>> On 23 Sep 2015, at 10:18, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>
>>> <snip>
>>>
>>>>
>>>> I think I found an easy fix. Can you try it?
>>>>
>>>> (in case my mail app messes something up: I changed line 2240 in git-p4.py to 'self.cloneDestination = os.getcwd()’)
>>>
>>> It fixes the problem, but in re-running the tests, I'm seeing t9808
>>> fail which doesn't happen on next.
>> Confirmed. I fixed it.
>> Do you think it makes sense to create a new roll v8 for Junio?
>
> How about we leave it a day or two in case anything else crawls out of
> the woodwork?
>
> Thanks!
> Luke

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-23 11:25             ` Luke Diamand
@ 2015-09-23 11:42               ` Lars Schneider
  2015-09-24 20:44                 ` Luke Diamand
  0 siblings, 1 reply; 21+ messages in thread
From: Lars Schneider @ 2015-09-23 11:42 UTC (permalink / raw)
  To: Luke Diamand; +Cc: Git Users, Junio C Hamano


On 23 Sep 2015, at 13:25, Luke Diamand <luke@diamand.org> wrote:

> Adding back git@vger.kernel.org, which I inadvertently dropped off the thread.
> 
> On 23 September 2015 at 12:22, Luke Diamand <luke@diamand.org> wrote:
>> On 23 September 2015 at 11:09, Lars Schneider <larsxschneider@gmail.com> wrote:
>>> 
>>> On 23 Sep 2015, at 11:22, Luke Diamand <luke@diamand.org> wrote:
>>> 
>>>> On 23 September 2015 at 09:50, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>> 
>>>>> On 23 Sep 2015, at 10:18, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>> 
>>>> <snip>
>>>> 
>>>>> 
>>>>> I think I found an easy fix. Can you try it?
>>>>> 
>>>>> (in case my mail app messes something up: I changed line 2240 in git-p4.py to 'self.cloneDestination = os.getcwd()’)
>>>> 
>>>> It fixes the problem, but in re-running the tests, I'm seeing t9808
>>>> fail which doesn't happen on next.
>>> Confirmed. I fixed it.
>>> Do you think it makes sense to create a new roll v8 for Junio?
>> 
>> How about we leave it a day or two in case anything else crawls out of
>> the woodwork?
>> 
>> Thanks!
>> Luke
sounds good to me!

Thanks,
Lars

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-23 11:42               ` Lars Schneider
@ 2015-09-24 20:44                 ` Luke Diamand
  2015-09-25  8:35                   ` Lars Schneider
  0 siblings, 1 reply; 21+ messages in thread
From: Luke Diamand @ 2015-09-24 20:44 UTC (permalink / raw)
  To: Lars Schneider; +Cc: Git Users, Junio C Hamano

On 23 September 2015 at 12:42, Lars Schneider <larsxschneider@gmail.com> wrote:
>
> On 23 Sep 2015, at 13:25, Luke Diamand <luke@diamand.org> wrote:
>
>> Adding back git@vger.kernel.org, which I inadvertently dropped off the thread.
>>
>> On 23 September 2015 at 12:22, Luke Diamand <luke@diamand.org> wrote:
>>> On 23 September 2015 at 11:09, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>
>>>> On 23 Sep 2015, at 11:22, Luke Diamand <luke@diamand.org> wrote:
>>>>
>>>>> On 23 September 2015 at 09:50, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>>>
>>>>>> On 23 Sep 2015, at 10:18, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>>
>>>>> <snip>
>>>>>
>>>>>>
>>>>>> I think I found an easy fix. Can you try it?
>>>>>>
>>>>>> (in case my mail app messes something up: I changed line 2240 in git-p4.py to 'self.cloneDestination = os.getcwd()’)
>>>>>
>>>>> It fixes the problem, but in re-running the tests, I'm seeing t9808
>>>>> fail which doesn't happen on next.
>>>> Confirmed. I fixed it.
>>>> Do you think it makes sense to create a new roll v8 for Junio?
>>>
>>> How about we leave it a day or two in case anything else crawls out of
>>> the woodwork?
>>>
>>> Thanks!
>>> Luke
> sounds good to me!

OK, not sure if I'm just doing something daft here....but it seems to
be ignoring the size limit!

I've got the version from the branch:

   8fee565 git-p4: add Git LFS backend for large file system

Plus the couple of oneliner fixes for cloneDestination.

I've created a repo with a file called foo, size 16MB, and another
file called foo.mp4, which is just a symlink to foo.

I then do:

$ mkdir a
$ cd a
$ git init .
$ git config git-p4.largeFileSystem GitLFS
$ git config git-p4.largeFileExtensions mp4
$ git config git-p4.largeFileThreshold 100k
$ git-p4.py sync -v //depot

That reports that both foo and foo.mp4 have been pushed into LFS:

  //depot/foo --> foo (16 MB)
  Reading pipe: ['git', 'config', '--bool', 'git-p4.pushLargeFiles']
  foo moved to large file system
(/home/lgd/git/git/x/git/a/.git/lfs/objects/08/0a/080acf35a507ac9849cfcba47dc2ad83e01b75663a516279c8b9d243b719643e)
  //depot/foo.mp4 --> foo.mp4 (0 MB)
  foo.mp4 moved to large file system
(/home/lgd/git/git/x/git/a/.git/lfs/objects/2c/26/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae)

But the file system says otherwise:

$ ls -l
-rw-r--r-- 1 lgd lgd 16777216 Sep 24 21:38 foo
-rw-r--r-- 1 lgd lgd        3 Sep 24 21:38 foo.mp4

As does git:

git ls-files --debug
.gitattributes
  ctime: 1443127106:535552029
  mtime: 1443127106:535552029
  dev: 65025    ino: 13638459
  uid: 1000     gid: 1000
  size: 94      flags: 0
foo
  ctime: 1443127106:579552030
  mtime: 1443127106:579552030
  dev: 65025    ino: 13638462
  uid: 1000     gid: 1000
  size: 16777216        flags: 0    <<<<<<<<<<<<< Quite large!
foo.mp4
  ctime: 1443127106:599552030
  mtime: 1443127106:599552030
  dev: 65025    ino: 13638463
  uid: 1000     gid: 1000
  size: 3       flags: 0

What's going on?

Thanks!
Luke

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-24 20:44                 ` Luke Diamand
@ 2015-09-25  8:35                   ` Lars Schneider
  2015-09-25  9:00                     ` Luke Diamand
  0 siblings, 1 reply; 21+ messages in thread
From: Lars Schneider @ 2015-09-25  8:35 UTC (permalink / raw)
  To: Luke Diamand; +Cc: Git Users, Junio C Hamano


On 24 Sep 2015, at 22:44, Luke Diamand <luke@diamand.org> wrote:

> On 23 September 2015 at 12:42, Lars Schneider <larsxschneider@gmail.com> wrote:
>> 
>> On 23 Sep 2015, at 13:25, Luke Diamand <luke@diamand.org> wrote:
>> 
>>> Adding back git@vger.kernel.org, which I inadvertently dropped off the thread.
>>> 
>>> On 23 September 2015 at 12:22, Luke Diamand <luke@diamand.org> wrote:
>>>> On 23 September 2015 at 11:09, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>> 
>>>>> On 23 Sep 2015, at 11:22, Luke Diamand <luke@diamand.org> wrote:
>>>>> 
>>>>>> On 23 September 2015 at 09:50, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>>>> 
>>>>>>> On 23 Sep 2015, at 10:18, Lars Schneider <larsxschneider@gmail.com> wrote:
>>>>>> 
>>>>>> <snip>
>>>>>> 
>>>>>>> 
>>>>>>> I think I found an easy fix. Can you try it?
>>>>>>> 
>>>>>>> (in case my mail app messes something up: I changed line 2240 in git-p4.py to 'self.cloneDestination = os.getcwd()’)
>>>>>> 
>>>>>> It fixes the problem, but in re-running the tests, I'm seeing t9808
>>>>>> fail which doesn't happen on next.
>>>>> Confirmed. I fixed it.
>>>>> Do you think it makes sense to create a new roll v8 for Junio?
>>>> 
>>>> How about we leave it a day or two in case anything else crawls out of
>>>> the woodwork?
>>>> 
>>>> Thanks!
>>>> Luke
>> sounds good to me!
> 
> OK, not sure if I'm just doing something daft here....but it seems to
> be ignoring the size limit!
> 
> I've got the version from the branch:
> 
>   8fee565 git-p4: add Git LFS backend for large file system
> 
> Plus the couple of oneliner fixes for cloneDestination.
> 
> I've created a repo with a file called foo, size 16MB, and another
> file called foo.mp4, which is just a symlink to foo.
> 
> I then do:
> 
> $ mkdir a
> $ cd a
> $ git init .
> $ git config git-p4.largeFileSystem GitLFS
> $ git config git-p4.largeFileExtensions mp4
> $ git config git-p4.largeFileThreshold 100k
> $ git-p4.py sync -v //depot
> 
> That reports that both foo and foo.mp4 have been pushed into LFS:
> 
>  //depot/foo --> foo (16 MB)
>  Reading pipe: ['git', 'config', '--bool', 'git-p4.pushLargeFiles']
>  foo moved to large file system
> (/home/lgd/git/git/x/git/a/.git/lfs/objects/08/0a/080acf35a507ac9849cfcba47dc2ad83e01b75663a516279c8b9d243b719643e)
>  //depot/foo.mp4 --> foo.mp4 (0 MB)
>  foo.mp4 moved to large file system
> (/home/lgd/git/git/x/git/a/.git/lfs/objects/2c/26/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae)
> 
> But the file system says otherwise:
> 
> $ ls -l
> -rw-r--r-- 1 lgd lgd 16777216 Sep 24 21:38 foo
> -rw-r--r-- 1 lgd lgd        3 Sep 24 21:38 foo.mp4
> 
> As does git:
> 
> git ls-files --debug
> .gitattributes
>  ctime: 1443127106:535552029
>  mtime: 1443127106:535552029
>  dev: 65025    ino: 13638459
>  uid: 1000     gid: 1000
>  size: 94      flags: 0
> foo
>  ctime: 1443127106:579552030
>  mtime: 1443127106:579552030
>  dev: 65025    ino: 13638462
>  uid: 1000     gid: 1000
>  size: 16777216        flags: 0    <<<<<<<<<<<<< Quite large!
> foo.mp4
>  ctime: 1443127106:599552030
>  mtime: 1443127106:599552030
>  dev: 65025    ino: 13638463
>  uid: 1000     gid: 1000
>  size: 3       flags: 0
> 
> What's going on?
I believe this is correct. Git-LFS uses the clean/smudge filter to replace the LFS pointer with the actual file on checkout. Therefore you see the actual file!
You can find details here: https://github.com/github/git-lfs/blob/master/docs/spec.md#intercepting-git

Can you run `du -hs .git/objects` in your Git repository? This should report a value well below 16 MB.

Cheers,
Lars

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 0/7] git-p4: add support for large file systems
  2015-09-25  8:35                   ` Lars Schneider
@ 2015-09-25  9:00                     ` Luke Diamand
  0 siblings, 0 replies; 21+ messages in thread
From: Luke Diamand @ 2015-09-25  9:00 UTC (permalink / raw)
  To: Lars Schneider; +Cc: Git Users, Junio C Hamano

On 25/09/15 09:35, Lars Schneider wrote:
>
>>   size: 3       flags: 0
>>
>> What's going on?
> I believe this is correct. Git-LFS uses the clean/smudge filter to replace the LFS pointer with the actual file on checkout. Therefore you see the actual file!
> You can find details here: https://github.com/github/git-lfs/blob/master/docs/spec.md#intercepting-git
>
> Can you run `du -hs .git/objects` in your Git repository? This should report a value well below 16 MB.

It does, thanks!

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v7 6/7] git-p4: add support for large file systems
  2015-09-21 22:41 ` [PATCH v7 6/7] git-p4: add support for large file systems larsxschneider
@ 2015-09-25  9:09   ` Luke Diamand
  0 siblings, 0 replies; 21+ messages in thread
From: Luke Diamand @ 2015-09-25  9:09 UTC (permalink / raw)
  To: Lars Schneider; +Cc: Git Users, Junio C Hamano

One tiny comment, otherwise this looks good to me.

Can we use test_path_is_missing in place of !test_path_is_file ?



On 21 September 2015 at 23:41,  <larsxschneider@gmail.com> wrote:
> From: Lars Schneider <larsxschneider@gmail.com>
>
> Perforce repositories can contain large (binary) files. Migrating these
> repositories to Git generates very large local clones. External storage
> systems such as Git LFS [1], Git Fat [2], Git Media [3], git-annex [4]
> try to address this problem.
>
> Add a generic mechanism to detect large files based on extension,
> uncompressed size, and/or compressed size.
>
> [1] https://git-lfs.github.com/
> [2] https://github.com/jedbrown/git-fat
> [3] https://github.com/alebedev/git-media
> [4] https://git-annex.branchable.com/
>
>
> diff --git a/t/t9823-git-p4-mock-lfs.sh b/t/t9823-git-p4-mock-lfs.sh
> new file mode 100755
> index 0000000..5684ee3
> --- /dev/null
> +++ b/t/t9823-git-p4-mock-lfs.sh
> @@ -0,0 +1,170 @@
> +#!/bin/sh
> +
> +test_description='Clone repositories and store files in Mock LFS'
> +
> +. ./lib-git-p4.sh
> +
> +test_file_is_not_in_mock_lfs () {
> +       FILE="$1" &&
> +       CONTENT="$2" &&
> +       echo "$CONTENT" >expect_content &&
> +       test_path_is_file "$FILE" &&
> +       test_cmp expect_content "$FILE"
> +}
> +
> +test_file_is_in_mock_lfs () {
> +       FILE="$1" &&
> +       CONTENT="$2" &&
> +       LOCAL_STORAGE=".git/mock-storage/local/$CONTENT" &&
> +       SERVER_STORAGE=".git/mock-storage/remote/$CONTENT" &&
> +       echo "pointer-$CONTENT" >expect_pointer &&
> +       echo "$CONTENT" >expect_content &&
> +       test_path_is_file "$FILE" &&
> +       test_path_is_file "$LOCAL_STORAGE" &&
> +       test_path_is_file "$SERVER_STORAGE" &&
> +       test_cmp expect_pointer "$FILE" &&
> +       test_cmp expect_content "$LOCAL_STORAGE" &&
> +       test_cmp expect_content "$SERVER_STORAGE"
> +}
> +
> +test_file_is_deleted_in_mock_lfs () {
> +       FILE="$1" &&
> +       CONTENT="$2" &&
> +       LOCAL_STORAGE=".git/mock-storage/local/$CONTENT" &&
> +       SERVER_STORAGE=".git/mock-storage/remote/$CONTENT" &&
> +       echo "pointer-$CONTENT" >expect_pointer &&
> +       echo "$CONTENT" >expect_content &&
> +       ! test_path_is_file "$FILE" &&

Perhaps use test_path_is_missing instead here?

> +       test_path_is_file "$LOCAL_STORAGE" &&
> +       test_path_is_file "$SERVER_STORAGE" &&
> +       test_cmp expect_content "$LOCAL_STORAGE" &&
> +       test_cmp expect_content "$SERVER_STORAGE"
> +}
> +
> +test_file_count_in_dir () {
> +       DIR="$1" &&
> +       EXPECTED_COUNT="$2" &&
> +       find "$DIR" -type f >actual &&
> +       test_line_count = $EXPECTED_COUNT actual
> +}
> +
> +test_expect_success 'start p4d' '
> +       start_p4d
> +'
> +
> +test_expect_success 'Create repo with binary files' '
> +       client_view "//depot/... //client/..." &&
> +       (
> +               cd "$cli" &&
> +
> +               echo "content 1 txt 23 bytes" >file1.txt &&
> +               p4 add file1.txt &&
> +               echo "content 2-3 bin 25 bytes" >file2.dat &&
> +               p4 add file2.dat &&
> +               p4 submit -d "Add text and binary file" &&
> +
> +               mkdir "path with spaces" &&
> +               echo "content 2-3 bin 25 bytes" >"path with spaces/file3.bin" &&
> +               p4 add "path with spaces/file3.bin" &&
> +               p4 submit -d "Add another binary file with same content and spaces in path" &&
> +
> +               echo "content 4 bin 26 bytes XX" >file4.bin &&
> +               p4 add file4.bin &&
> +               p4 submit -d "Add another binary file with different content"
> +       )
> +'
> +
> +test_expect_success 'Store files in Mock LFS based on size (>24 bytes)' '
> +       client_view "//depot/... //client/..." &&
> +       test_when_finished cleanup_git &&
> +       (
> +               cd "$git" &&
> +               git init . &&
> +               git config git-p4.useClientSpec true &&
> +               git config git-p4.largeFileSystem MockLFS &&
> +               git config git-p4.largeFileThreshold 24 &&
> +               git config git-p4.pushLargeFiles True &&
> +               git p4 clone --destination="$git" //depot@all &&
> +
> +               test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" &&
> +               test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" &&
> +               test_file_is_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" &&
> +               test_file_is_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" &&
> +
> +               test_file_count_in_dir ".git/mock-storage/local" 2 &&
> +               test_file_count_in_dir ".git/mock-storage/remote" 2
> +       )
> +'
> +
> +test_expect_success 'Store files in Mock LFS based on extension (dat)' '
> +       client_view "//depot/... //client/..." &&
> +       test_when_finished cleanup_git &&
> +       (
> +               cd "$git" &&
> +               git init . &&
> +               git config git-p4.useClientSpec true &&
> +               git config git-p4.largeFileSystem MockLFS &&
> +               git config git-p4.largeFileExtensions dat &&
> +               git config git-p4.pushLargeFiles True &&
> +               git p4 clone --destination="$git" //depot@all &&
> +
> +               test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" &&
> +               test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" &&
> +               test_file_is_not_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" &&
> +               test_file_is_not_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" &&
> +
> +               test_file_count_in_dir ".git/mock-storage/local" 1 &&
> +               test_file_count_in_dir ".git/mock-storage/remote" 1
> +       )
> +'
> +
> +test_expect_success 'Remove file from repo and store files in Mock LFS based on size (>24 bytes)' '
> +       client_view "//depot/... //client/..." &&
> +       (
> +               cd "$cli" &&
> +               p4 delete file4.bin &&
> +               p4 submit -d "Remove file"
> +       ) &&
> +
> +       client_view "//depot/... //client/..." &&
> +       test_when_finished cleanup_git &&
> +       (
> +               cd "$git" &&
> +               git init . &&
> +               git config git-p4.useClientSpec true &&
> +               git config git-p4.largeFileSystem MockLFS &&
> +               git config git-p4.largeFileThreshold 24 &&
> +               git config git-p4.pushLargeFiles True &&
> +               git p4 clone --destination="$git" //depot@all &&
> +
> +               test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" &&
> +               test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" &&
> +               test_file_is_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" &&
> +               test_file_is_deleted_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" &&
> +
> +               test_file_count_in_dir ".git/mock-storage/local" 2 &&
> +               test_file_count_in_dir ".git/mock-storage/remote" 2
> +       )
> +'
> +
> +test_expect_success 'Run git p4 submit in repo configured with large file system' '
> +       client_view "//depot/... //client/..." &&
> +       test_when_finished cleanup_git &&
> +       (
> +               cd "$git" &&
> +               git init . &&
> +               git config git-p4.useClientSpec true &&
> +               git config git-p4.largeFileSystem MockLFS &&
> +               git config git-p4.largeFileThreshold 24 &&
> +               git config git-p4.pushLargeFiles True &&
> +               git p4 clone --destination="$git" //depot@all &&
> +
> +               test_must_fail git p4 submit
> +       )
> +'
> +
> +test_expect_success 'kill p4d' '
> +       kill_p4d
> +'
> +
> +test_done
> --
> 2.5.1
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2015-09-25  9:09 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-21 22:41 [PATCH v7 0/7] git-p4: add support for large file systems larsxschneider
2015-09-21 22:41 ` [PATCH v7 1/7] git-p4: add optional type specifier to gitConfig reader larsxschneider
2015-09-22 21:49   ` Junio C Hamano
2015-09-23  7:38     ` Lars Schneider
2015-09-21 22:41 ` [PATCH v7 2/7] git-p4: add gitConfigInt reader larsxschneider
2015-09-21 22:41 ` [PATCH v7 3/7] git-p4: return an empty list if a list config has no values larsxschneider
2015-09-21 22:41 ` [PATCH v7 4/7] git-p4: add file streaming progress in verbose mode larsxschneider
2015-09-21 22:41 ` [PATCH v7 5/7] git-p4: check free space during streaming larsxschneider
2015-09-21 22:41 ` [PATCH v7 6/7] git-p4: add support for large file systems larsxschneider
2015-09-25  9:09   ` Luke Diamand
2015-09-21 22:41 ` [PATCH v7 7/7] git-p4: add Git LFS backend for large file system larsxschneider
2015-09-22 22:03 ` [PATCH v7 0/7] git-p4: add support for large file systems Junio C Hamano
2015-09-23  7:41   ` Lars Schneider
2015-09-23  7:58 ` Luke Diamand
2015-09-23  8:18   ` Lars Schneider
2015-09-23  8:50     ` Lars Schneider
     [not found]       ` <CAE5ih7-NqSd+zSqTungDt5oWzy4QT--vjYaShd=YDzGxHosz3A@mail.gmail.com>
     [not found]         ` <ECBECF84-28A9-4E10-907C-8E670F864A25@gmail.com>
     [not found]           ` <CAE5ih7_StiXA-c5yER9jhc941vsKfvEUONLXQ4E7JANOhCxMxQ@mail.gmail.com>
2015-09-23 11:25             ` Luke Diamand
2015-09-23 11:42               ` Lars Schneider
2015-09-24 20:44                 ` Luke Diamand
2015-09-25  8:35                   ` Lars Schneider
2015-09-25  9:00                     ` Luke Diamand

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).