diff options
| -rwxr-xr-x | contrib/fast-import/git-p4 | 55 | ||||
| -rw-r--r-- | contrib/fast-import/git-p4.txt | 38 | ||||
| -rwxr-xr-x | t/t9800-git-p4.sh | 200 | 
3 files changed, 284 insertions, 9 deletions
| diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6b9de9e7e0..2f7b270566 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -342,6 +342,11 @@ def gitConfig(key, args = None): # set args to "--bool", for instance          _gitConfig[key] = read_pipe(cmd, ignore_error=True).strip()      return _gitConfig[key] +def gitConfigList(key): +    if not _gitConfig.has_key(key): +        _gitConfig[key] = read_pipe("git config --get-all %s" % key, ignore_error=True).strip().split(os.linesep) +    return _gitConfig[key] +  def p4BranchesInGit(branchesAreInRemotes = True):      branches = {} @@ -774,17 +779,22 @@ class P4Submit(Command, P4UserMap):          if not self.detectRenames:              # If not explicitly set check the config variable -            self.detectRenames = gitConfig("git-p4.detectRenames").lower() == "true" +            self.detectRenames = gitConfig("git-p4.detectRenames") -        if self.detectRenames: +        if self.detectRenames.lower() == "false" or self.detectRenames == "": +            diffOpts = "" +        elif self.detectRenames.lower() == "true":              diffOpts = "-M"          else: -            diffOpts = "" +            diffOpts = "-M%s" % self.detectRenames -        if gitConfig("git-p4.detectCopies").lower() == "true": +        detectCopies = gitConfig("git-p4.detectCopies") +        if detectCopies.lower() == "true":              diffOpts += " -C" +        elif detectCopies != "" and detectCopies.lower() != "false": +            diffOpts += " -C%s" % detectCopies -        if gitConfig("git-p4.detectCopiesHarder").lower() == "true": +        if gitConfig("git-p4.detectCopiesHarder", "--bool") == "true":              diffOpts += " --find-copies-harder"          diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (diffOpts, id, id)) @@ -1450,7 +1460,13 @@ class P4Sync(Command, P4UserMap):      def getBranchMapping(self):          lostAndFoundBranches = set() -        for info in p4CmdList("branches"): +        user = gitConfig("git-p4.branchUser") +        if len(user) > 0: +            command = "branches -u %s" % user +        else: +            command = "branches" + +        for info in p4CmdList(command):              details = p4Cmd("branch -o %s" % info["branch"])              viewIdx = 0              while details.has_key("View%s" % viewIdx): @@ -1479,6 +1495,25 @@ class P4Sync(Command, P4UserMap):                      if source not in self.knownBranches:                          lostAndFoundBranches.add(source) +        # Perforce does not strictly require branches to be defined, so we also +        # check git config for a branch list. +        # +        # Example of branch definition in git config file: +        # [git-p4] +        #   branchList=main:branchA +        #   branchList=main:branchB +        #   branchList=branchA:branchC +        configBranches = gitConfigList("git-p4.branchList") +        for branch in configBranches: +            if branch: +                (source, destination) = branch.split(":") +                self.knownBranches[destination] = source + +                lostAndFoundBranches.discard(destination) + +                if source not in self.knownBranches: +                    lostAndFoundBranches.add(source) +          for branch in lostAndFoundBranches:              self.knownBranches[branch] = branch @@ -1824,12 +1859,14 @@ class P4Sync(Command, P4UserMap):                      else:                          paths = []                          for (prev, cur) in zip(self.previousDepotPaths, depotPaths): -                            for i in range(0, min(len(cur), len(prev))): -                                if cur[i] <> prev[i]: +                            prev_list = prev.split("/") +                            cur_list = cur.split("/") +                            for i in range(0, min(len(cur_list), len(prev_list))): +                                if cur_list[i] <> prev_list[i]:                                      i = i - 1                                      break -                            paths.append (cur[:i + 1]) +                            paths.append ("/".join(cur_list[:i + 1]))                          self.previousDepotPaths = paths diff --git a/contrib/fast-import/git-p4.txt b/contrib/fast-import/git-p4.txt index caa4bb3e30..52003ae904 100644 --- a/contrib/fast-import/git-p4.txt +++ b/contrib/fast-import/git-p4.txt @@ -232,6 +232,44 @@ git-p4.skipUserNameCheck  When submitting, git-p4 checks that the git commits are authored by the current  p4 user, and warns if they are not. This disables the check. +git-p4.detectRenames + +Detect renames when submitting changes to Perforce server. Will enable -M git +argument. Can be optionally set to a number representing the threshold +percentage value of the rename detection. + +  git config [--global] git-p4.detectRenames true +  git config [--global] git-p4.detectRenames 50 + +git-p4.detectCopies + +Detect copies when submitting changes to Perforce server. Will enable -C git +argument. Can be optionally set to a number representing the threshold +percentage value of the copy detection. + +  git config [--global] git-p4.detectCopies true +  git config [--global] git-p4.detectCopies 80 + +git-p4.detectCopiesHarder + +Detect copies even between files that did not change when submitting changes to +Perforce server. Will enable --find-copies-harder git argument. + +  git config [--global] git-p4.detectCopies true + +git-p4.branchUser + +Only use branch specifications defined by the selected username. + +  git config [--global] git-p4.branchUser username + +git-p4.branchList + +List of branches to be imported when branch detection is enabled. + +  git config [--global] git-p4.branchList main:branchA +  git config [--global] --add git-p4.branchList main:branchB +  Implementation Details...  ========================= diff --git a/t/t9800-git-p4.sh b/t/t9800-git-p4.sh index 97ec9753b4..39e7f78e28 100755 --- a/t/t9800-git-p4.sh +++ b/t/t9800-git-p4.sh @@ -269,6 +269,206 @@ test_expect_success 'initial import time from top change time' '  	test $p4time = $gittime  ' +# Rename a file and confirm that rename is not detected in P4. +# Rename the new file again with detectRenames option enabled and confirm that +# this is detected in P4. +# Rename the new file again adding an extra line, configure a big threshold in +# detectRenames and confirm that rename is not detected in P4. +# Repeat, this time with a smaller threshold and confirm that the rename is +# detected in P4. +test_expect_success 'detect renames' ' +	"$GITP4" clone --dest="$git" //depot@all && +	test_when_finished cleanup_git && +	cd "$git" && +	git config git-p4.skipSubmitEditCheck true && + +	git mv file1 file4 && +	git commit -a -m "Rename file1 to file4" && +	git diff-tree -r -M HEAD && +	"$GITP4" submit && +	p4 filelog //depot/file4 && +	! p4 filelog //depot/file4 | grep -q "branch from" && + +	git mv file4 file5 && +	git commit -a -m "Rename file4 to file5" && +	git diff-tree -r -M HEAD && +	git config git-p4.detectRenames true && +	"$GITP4" submit && +	p4 filelog //depot/file5 && +	p4 filelog //depot/file5 | grep -q "branch from //depot/file4" && + +	git mv file5 file6 && +	echo update >>file6 && +	git add file6 && +	git commit -a -m "Rename file5 to file6 with changes" && +	git diff-tree -r -M HEAD && +	level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && +	test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && +	git config git-p4.detectRenames $((level + 2)) && +	"$GITP4" submit && +	p4 filelog //depot/file6 && +	! p4 filelog //depot/file6 | grep -q "branch from" && + +	git mv file6 file7 && +	echo update >>file7 && +	git add file7 && +	git commit -a -m "Rename file6 to file7 with changes" && +	git diff-tree -r -M HEAD && +	level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && +	test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && +	git config git-p4.detectRenames $((level - 2)) && +	"$GITP4" submit && +	p4 filelog //depot/file7 && +	p4 filelog //depot/file7 | grep -q "branch from //depot/file6" +' + +# Copy a file and confirm that copy is not detected in P4. +# Copy a file with detectCopies option enabled and confirm that copy is not +# detected in P4. +# Modify and copy a file with detectCopies option enabled and confirm that copy +# is detected in P4. +# Copy a file with detectCopies and detectCopiesHarder options enabled and +# confirm that copy is detected in P4. +# Modify and copy a file, configure a bigger threshold in detectCopies and +# confirm that copy is not detected in P4. +# Modify and copy a file, configure a smaller threshold in detectCopies and +# confirm that copy is detected in P4. +test_expect_success 'detect copies' ' +	"$GITP4" clone --dest="$git" //depot@all && +	test_when_finished cleanup_git && +	cd "$git" && +	git config git-p4.skipSubmitEditCheck true && + +	cp file2 file8 && +	git add file8 && +	git commit -a -m "Copy file2 to file8" && +	git diff-tree -r -C HEAD && +	"$GITP4" submit && +	p4 filelog //depot/file8 && +	! p4 filelog //depot/file8 | grep -q "branch from" && + +	cp file2 file9 && +	git add file9 && +	git commit -a -m "Copy file2 to file9" && +	git diff-tree -r -C HEAD && +	git config git-p4.detectCopies true && +	"$GITP4" submit && +	p4 filelog //depot/file9 && +	! p4 filelog //depot/file9 | grep -q "branch from" && + +	echo "file2" >>file2 && +	cp file2 file10 && +	git add file2 file10 && +	git commit -a -m "Modify and copy file2 to file10" && +	git diff-tree -r -C HEAD && +	"$GITP4" submit && +	p4 filelog //depot/file10 && +	p4 filelog //depot/file10 | grep -q "branch from //depot/file" && + +	cp file2 file11 && +	git add file11 && +	git commit -a -m "Copy file2 to file11" && +	git diff-tree -r -C --find-copies-harder HEAD && +	src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && +	test "$src" = file10 && +	git config git-p4.detectCopiesHarder true && +	"$GITP4" submit && +	p4 filelog //depot/file11 && +	p4 filelog //depot/file11 | grep -q "branch from //depot/file" && + +	cp file2 file12 && +	echo "some text" >>file12 && +	git add file12 && +	git commit -a -m "Copy file2 to file12 with changes" && +	git diff-tree -r -C --find-copies-harder HEAD && +	level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && +	test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && +	src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && +	test "$src" = file10 && +	git config git-p4.detectCopies $((level + 2)) && +	"$GITP4" submit && +	p4 filelog //depot/file12 && +	! p4 filelog //depot/file12 | grep -q "branch from" && + +	cp file2 file13 && +	echo "different text" >>file13 && +	git add file13 && +	git commit -a -m "Copy file2 to file13 with changes" && +	git diff-tree -r -C --find-copies-harder HEAD && +	level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && +	test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && +	src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && +	test "$src" = file10 && +	git config git-p4.detectCopies $((level - 2)) && +	"$GITP4" submit && +	p4 filelog //depot/file13 && +	p4 filelog //depot/file13 | grep -q "branch from //depot/file" +' + +# Create a simple branch structure in P4 depot to check if it is correctly +# cloned. +test_expect_success 'add simple p4 branches' ' +	cd "$cli" && +	mkdir branch1 && +	cd branch1 && +	echo file1 >file1 && +	echo file2 >file2 && +	p4 add file* && +	p4 submit -d "branch1" && +	p4 integrate //depot/branch1/... //depot/branch2/... && +	p4 submit -d "branch2" && +	echo file3 >file3 && +	p4 add file3 && +	p4 submit -d "add file3 in branch1" && +	p4 open file2 && +	echo update >>file2 && +	p4 submit -d "update file2 in branch1" && +	p4 integrate //depot/branch1/... //depot/branch3/... && +	p4 submit -d "branch3" && +	cd "$TRASH_DIRECTORY" +' + +# Configure branches through git-config and clone them. +# All files are tested to make sure branches were cloned correctly. +# Finally, make an update to branch1 on P4 side to check if it is imported +# correctly by git-p4. +test_expect_success 'git-p4 clone simple branches' ' +	git init "$git" && +	cd "$git" && +	git config git-p4.branchList branch1:branch2 && +	git config --add git-p4.branchList branch1:branch3 && +	cd "$TRASH_DIRECTORY" && +	"$GITP4" clone --dest="$git" --detect-branches //depot@all && +	cd "$git" && +	git log --all --graph --decorate --stat && +	git reset --hard p4/depot/branch1 && +	test -f file1 && +	test -f file2 && +	test -f file3 && +	grep -q update file2 && +	git reset --hard p4/depot/branch2 && +	test -f file1 && +	test -f file2 && +	test \! -z file3 && +	! grep -q update file2 && +	git reset --hard p4/depot/branch3 && +	test -f file1 && +	test -f file2 && +	test -f file3 && +	grep -q update file2 && +	cd "$cli" && +	cd branch1 && +	p4 edit file2 && +	echo file2_ >> file2 && +	p4 submit -d "update file2 in branch3" && +	cd "$git" && +	git reset --hard p4/depot/branch1 && +	"$GITP4" rebase && +	grep -q file2_ file2 && +	cd "$TRASH_DIRECTORY" && +	rm -rf "$git" && mkdir "$git" +' +  test_expect_success 'shutdown' '  	pid=`pgrep -f p4d` &&  	test -n "$pid" && | 
