Browse Source

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>
maint
Vitor Antunes 13 years ago committed by Junio C Hamano
parent
commit
fed23693ba
  1. 46
      contrib/fast-import/git-p4

46
contrib/fast-import/git-p4

@ -1429,6 +1429,8 @@ class P4Sync(Command, P4UserMap): @@ -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): @@ -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): @@ -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): @@ -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): @@ -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…
Cancel
Save