Skip to content

Commit da3b5f5

Browse files
author
Scott Guest
committed
git-p4: preserve executable bit in LFS pointers
git-p4.py currently marks all Git LFS pointers non-executable, when it should instead match the executable bit of the stored file. The LFS spec made this change nearly a decade ago, see git-lfs/git-lfs@8d075a8 Signed-off-by: Scott Guest <sguest@nvidia.com>
1 parent 6c0bd1f commit da3b5f5

File tree

1 file changed

+13
-21
lines changed

1 file changed

+13
-21
lines changed

git-p4.py

+13-21
Original file line numberDiff line numberDiff line change
@@ -1463,7 +1463,7 @@ def __init__(self, writeToGitStream):
14631463
self.largeFiles = set()
14641464
self.writeToGitStream = writeToGitStream
14651465

1466-
def generatePointer(self, cloneDestination, contentFile):
1466+
def generatePointer(self, contentFile):
14671467
"""Return the content of a pointer file that is stored in Git instead
14681468
of the actual content.
14691469
"""
@@ -1517,20 +1517,14 @@ def removeLargeFile(self, relPath):
15171517
def isLargeFile(self, relPath):
15181518
return relPath in self.largeFiles
15191519

1520-
def processContent(self, git_mode, relPath, contents):
1520+
def processContent(self, relPath, contents):
15211521
"""Processes the content of git fast import. This method decides if a
15221522
file is stored in the large file system and handles all necessary
15231523
steps.
15241524
"""
1525-
# symlinks aren't processed by smudge/clean filters
1526-
if git_mode == "120000":
1527-
return (git_mode, contents)
1528-
15291525
if self.exceedsLargeFileThreshold(relPath, contents) or self.hasLargeFileExtension(relPath):
15301526
contentTempFile = self.generateTempFile(contents)
1531-
pointer_git_mode, contents, localLargeFile = self.generatePointer(contentTempFile)
1532-
if pointer_git_mode:
1533-
git_mode = pointer_git_mode
1527+
contents, localLargeFile = self.generatePointer(contentTempFile)
15341528
if localLargeFile:
15351529
# Move temp file to final location in large file system
15361530
largeFileDir = os.path.dirname(localLargeFile)
@@ -1542,7 +1536,7 @@ def processContent(self, git_mode, relPath, contents):
15421536
self.pushFile(localLargeFile)
15431537
if verbose:
15441538
sys.stderr.write("%s moved to large file system (%s)\n" % (relPath, localLargeFile))
1545-
return (git_mode, contents)
1539+
return contents
15461540

15471541

15481542
class MockLFS(LargeFileSystem):
@@ -1555,10 +1549,9 @@ def generatePointer(self, contentFile):
15551549
"""
15561550
with open(contentFile, 'r') as f:
15571551
content = next(f)
1558-
gitMode = '100644'
15591552
pointerContents = 'pointer-' + content
15601553
localLargeFile = os.path.join(os.getcwd(), '.git', 'mock-storage', 'local', content[:-1])
1561-
return (gitMode, pointerContents, localLargeFile)
1554+
return (pointerContents, localLargeFile)
15621555

15631556
def pushFile(self, localLargeFile):
15641557
"""The remote filename of the large file storage is the same as the
@@ -1586,7 +1579,7 @@ def generatePointer(self, contentFile):
15861579
content.
15871580
"""
15881581
if os.path.getsize(contentFile) == 0:
1589-
return (None, '', None)
1582+
return ('', None)
15901583

15911584
pointerProcess = subprocess.Popen(
15921585
['git', 'lfs', 'pointer', '--file=' + contentFile],
@@ -1616,9 +1609,7 @@ def generatePointer(self, contentFile):
16161609
'objects', oid[:2], oid[2:4],
16171610
oid,
16181611
)
1619-
# LFS Spec states that pointer files should not have the executable bit set.
1620-
gitMode = '100644'
1621-
return (gitMode, pointerFile, localLargeFile)
1612+
return (pointerFile, localLargeFile)
16221613

16231614
def pushFile(self, localLargeFile):
16241615
uploadProcess = subprocess.Popen(
@@ -1652,12 +1643,12 @@ def removeLargeFile(self, relPath):
16521643
LargeFileSystem.removeLargeFile(self, relPath)
16531644
self.writeToGitStream('100644', '.gitattributes', self.generateGitAttributes())
16541645

1655-
def processContent(self, git_mode, relPath, contents):
1646+
def processContent(self, relPath, contents):
16561647
if relPath == '.gitattributes':
16571648
self.baseGitAttributes = contents
1658-
return (git_mode, self.generateGitAttributes())
1649+
return self.generateGitAttributes()
16591650
else:
1660-
return LargeFileSystem.processContent(self, git_mode, relPath, contents)
1651+
return LargeFileSystem.processContent(self, relPath, contents)
16611652

16621653

16631654
class Command:
@@ -3217,8 +3208,9 @@ def streamOneP4File(self, file, contents):
32173208
if regexp:
32183209
contents = [regexp.sub(br'$\1$', c) for c in contents]
32193210

3220-
if self.largeFileSystem:
3221-
git_mode, contents = self.largeFileSystem.processContent(git_mode, relPath, contents)
3211+
# symlinks aren't processed by smudge/clean filters
3212+
if git_mode != '120000' and self.largeFileSystem:
3213+
contents = self.largeFileSystem.processContent(relPath, contents)
32223214

32233215
self.writeToGitStream(git_mode, relPath, contents)
32243216

0 commit comments

Comments
 (0)