Merge branch 'ls/p4-lfs'
authorJunio C Hamano <gitster@pobox.com>
Tue, 10 May 2016 20:40:29 +0000 (13:40 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 10 May 2016 20:40:29 +0000 (13:40 -0700)
Recent update to Git LFS broke "git p4" by changing the output from
its "lfs pointer" subcommand.

* ls/p4-lfs:
git-p4: fix Git LFS pointer parsing
travis-ci: express Linux/OS X dependency versions more clearly
travis-ci: update Git-LFS and P4 to the latest version

1  2 
git-p4.py
t/t9824-git-p4-git-lfs.sh
diff --combined git-p4.py
index 8f869d74a11da62c618a37bed45a3f0ecbe16513,e752153f6f16247c23ff390e20ae18cf51158a30..b6593cf9a19144650cc476fae0243140f4c0a8bb
+++ b/git-p4.py
@@@ -1064,8 -1064,15 +1064,15 @@@ class GitLFS(LargeFileSystem)
          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]
+         # Git LFS removed the preamble in the output of the 'pointer' command
+         # starting from version 1.2.0. Check for the preamble here to support
+         # earlier versions.
+         # c.f. https://github.com/github/git-lfs/commit/da2935d9a739592bc775c98d8ef4df9c72ea3b43
+         if pointerFile.startswith('Git LFS pointer for'):
+             pointerFile = re.sub(r'Git LFS pointer for.*\n\n', '', pointerFile)
+         oid = re.search(r'^oid \w+:(\w+)', pointerFile, re.MULTILINE).group(1)
          localLargeFile = os.path.join(
              os.getcwd(),
              '.git', 'lfs', 'objects', oid[:2], oid[2:4],
          )
          # LFS Spec states that pointer files should not have the executable bit set.
          gitMode = '100644'
-         return (gitMode, pointerContents, localLargeFile)
+         return (gitMode, pointerFile, localLargeFile)
  
      def pushFile(self, localLargeFile):
          uploadProcess = subprocess.Popen(
@@@ -1160,15 -1167,6 +1167,15 @@@ class P4UserMap
              self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">"
              self.emails[output["Email"]] = output["User"]
  
 +        mapUserConfigRegex = re.compile(r"^\s*(\S+)\s*=\s*(.+)\s*<(\S+)>\s*$", re.VERBOSE)
 +        for mapUserConfig in gitConfigList("git-p4.mapUser"):
 +            mapUser = mapUserConfigRegex.findall(mapUserConfig)
 +            if mapUser and len(mapUser[0]) == 3:
 +                user = mapUser[0][0]
 +                fullname = mapUser[0][1]
 +                email = mapUser[0][2]
 +                self.users[user] = fullname + " <" + email + ">"
 +                self.emails[email] = user
  
          s = ''
          for (key, val) in self.users.items():
@@@ -2320,15 -2318,6 +2327,15 @@@ class P4Sync(Command, P4UserMap)
              fnum = fnum + 1
          return files
  
 +    def extractJobsFromCommit(self, commit):
 +        jobs = []
 +        jnum = 0
 +        while commit.has_key("job%s" % jnum):
 +            job = commit["job%s" % jnum]
 +            jobs.append(job)
 +            jnum = jnum + 1
 +        return jobs
 +
      def stripRepoPath(self, path, prefixes):
          """When streaming files, this is called to map a p4 depot path
             to where it should go in git.  The prefixes are either
      def commit(self, details, files, branch, parent = ""):
          epoch = details["time"]
          author = details["user"]
 +        jobs = self.extractJobsFromCommit(details)
  
          if self.verbose:
              print('commit into {0}'.format(branch))
  
          self.gitStream.write("data <<EOT\n")
          self.gitStream.write(details["desc"])
 +        if len(jobs) > 0:
 +            self.gitStream.write("\nJobs: %s" % (' '.join(jobs)))
          self.gitStream.write("\n[git-p4: depot-paths = \"%s\": change = %s" %
                               (','.join(self.branchPrefixes), details["change"]))
          if len(details['options']) > 0:
index 3fc6790b0744f40fab91be76768cdf71f9d71789,ca93ac8813c6bcf2a479492cffb13beaf452ebc1..110a7e792475fcf19ef782fae1d265ae81653853
@@@ -13,6 -13,10 +13,10 @@@ test_file_in_lfs () 
        FILE="$1" &&
        SIZE="$2" &&
        EXPECTED_CONTENT="$3" &&
+       sed -n '1,1 p' "$FILE" | grep "^version " &&
+       sed -n '2,2 p' "$FILE" | grep "^oid " &&
+       sed -n '3,3 p' "$FILE" | grep "^size " &&
+       test_line_count = 3 "$FILE" &&
        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" &&
@@@ -265,7 -269,7 +269,7 @@@ test_expect_success 'Add big files to r
                # 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_in_lfs file6.bin 39 "content 6 bin 39 bytes XXXXXYYYYYZZZZZ" &&
                test_file_count_in_dir ".git/lfs/objects" 1 &&
  
                cat >expect <<-\EOF &&