git-p4: Search for parent commit on branch creation
To find out which is its parent the commit of the new branch is compared sequentially to each blob of the parent branch from the newest to the oldest. The first blob which results in a zero diff is considered the parent commit. If none is found, then the commit is applied to the top of the parent branch. A fast-import "checkpoint" call is required because diff-tree is only able to work with blobs on disk. But most of these commits will not be part of the final imported tree, making fast-import fail. To avoid this, the temporary branches are tracked and then removed at the end of the import process. Signed-off-by: Vitor Antunes <vitor.hda@gmail.com> Acked-by: Pete Wyckoff <pw@padd.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
a080558ed7
commit
fed23693ba
@ -1429,6 +1429,8 @@ class P4Sync(Command, P4UserMap):
|
||||
self.cloneExclude = []
|
||||
self.useClientSpec = False
|
||||
self.clientSpecDirs = None
|
||||
self.tempBranches = []
|
||||
self.tempBranchLocation = "git-p4-tmp"
|
||||
|
||||
if gitConfig("git-p4.syncFromOrigin") == "false":
|
||||
self.syncWithOrigin = False
|
||||
@ -1450,6 +1452,14 @@ class P4Sync(Command, P4UserMap):
|
||||
.replace("%25", "%")
|
||||
return path
|
||||
|
||||
# Force a checkpoint in fast-import and wait for it to finish
|
||||
def checkpoint(self):
|
||||
self.gitStream.write("checkpoint\n\n")
|
||||
self.gitStream.write("progress checkpoint\n\n")
|
||||
out = self.gitOutput.readline()
|
||||
if self.verbose:
|
||||
print "checkpoint finished: " + out
|
||||
|
||||
def extractFilesFromCommit(self, commit):
|
||||
self.cloneExclude = [re.sub(r"\.\.\.$", "", path)
|
||||
for path in self.cloneExclude]
|
||||
@ -1957,6 +1967,20 @@ class P4Sync(Command, P4UserMap):
|
||||
self.importChanges(changes)
|
||||
return True
|
||||
|
||||
def searchParent(self, parent, branch, target):
|
||||
parentFound = False
|
||||
for blob in read_pipe_lines(["git", "rev-list", "--reverse", "--no-merges", parent]):
|
||||
blob = blob.strip()
|
||||
if len(read_pipe(["git", "diff-tree", blob, target])) == 0:
|
||||
parentFound = True
|
||||
if self.verbose:
|
||||
print "Found parent of %s in commit %s" % (branch, blob)
|
||||
break
|
||||
if parentFound:
|
||||
return blob
|
||||
else:
|
||||
return None
|
||||
|
||||
def importChanges(self, changes):
|
||||
cnt = 1
|
||||
for change in changes:
|
||||
@ -2013,7 +2037,21 @@ class P4Sync(Command, P4UserMap):
|
||||
parent = self.initialParents[branch]
|
||||
del self.initialParents[branch]
|
||||
|
||||
self.commit(description, filesForCommit, branch, [branchPrefix], parent)
|
||||
blob = None
|
||||
if len(parent) > 0:
|
||||
tempBranch = os.path.join(self.tempBranchLocation, "%d" % (change))
|
||||
if self.verbose:
|
||||
print "Creating temporary branch: " + tempBranch
|
||||
self.commit(description, filesForCommit, tempBranch, [branchPrefix])
|
||||
self.tempBranches.append(tempBranch)
|
||||
self.checkpoint()
|
||||
blob = self.searchParent(parent, branch, tempBranch)
|
||||
if blob:
|
||||
self.commit(description, filesForCommit, branch, [branchPrefix], blob)
|
||||
else:
|
||||
if self.verbose:
|
||||
print "Parent of %s not found. Committing into head of %s" % (branch, parent)
|
||||
self.commit(description, filesForCommit, branch, [branchPrefix], parent)
|
||||
else:
|
||||
files = self.extractFilesFromCommit(description)
|
||||
self.commit(description, files, self.branch, self.depotPaths,
|
||||
@ -2348,6 +2386,12 @@ class P4Sync(Command, P4UserMap):
|
||||
self.gitOutput.close()
|
||||
self.gitError.close()
|
||||
|
||||
# Cleanup temporary branches created during import
|
||||
if self.tempBranches != []:
|
||||
for branch in self.tempBranches:
|
||||
read_pipe("git update-ref -d %s" % branch)
|
||||
os.rmdir(os.path.join(os.environ.get("GIT_DIR", ".git"), self.tempBranchLocation))
|
||||
|
||||
return True
|
||||
|
||||
class P4Rebase(Command):
|
||||
|
Loading…
Reference in New Issue
Block a user