Skip to contentSkip to conversation

git-p4: support explicit sync of arbitrary existing git-p4 refs

PATCH New Tao Klerks via GitGitGadget 1 participant 1 message Apr 4, 2022

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 git-p4: support explicit sync of arbitrary existing git-p4 refs

From: Tao Klerks <[email protected]>

With the --branch argument of the "sync" subcommand, git-p4 enables you to import a perforce branch/path to an arbitrary git ref, using a full ref path, or to refs/remotes/p4/* or refs/heads/p4/*, depending on --import-local, using a short ref name.

However, when you later want to explicitly sync such a given ref to pick up subsequent p4 changes, it only works if the ref was placed in the p4 path *and* has only one path component (no "/").

This limitation results from a bad assumption in the existing-branch sync logic, and also means you cannot individually sync branches detected by --detect-branches, as these also get a "/" in their names.

Fix "git p4 sync --branch", when called with an existing ref, so that it works correctly regardless of whether the ref is in the p4 path or not, and (in the case of refs in the p4 path) regardless of whether it has a "/" in its short name or not.

Also add tests to validate that these branch-specific syncs work as expected.

---
git-p4: support explicit sync of arbitrary existing git-p4 refs

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1202%2FTaoK%2Fgit-p4-structured-paths-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1202/TaoK/git-p4-structured-paths-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1202

 git-p4.py                | 52 +++++++++++++++++-------
 t/t9800-git-p4-basic.sh  | 85 ++++++++++++++++++++++++++++++++++++++++
 t/t9801-git-p4-branch.sh | 10 +++++
 3 files changed, 133 insertions(+), 14 deletions(-)
git-p4.py +38 -14
index a9b1f904410..48d5805ee41 100755
@@ -893,6 +893,36 @@ def gitConfigList(key):
             _gitConfig[key] = []
     return _gitConfig[key]
 
+def fullP4Ref(incomingRef, importIntoRemotes=True):
+    """Standardize a given provided p4 ref value to a full git ref:
+         refs/foo/bar/branch -> use it exactly
+         p4/branch -> prepend refs/remotes/ or refs/heads/
+         branch -> prepend refs/remotes/p4/ or refs/heads/p4/"""
+    if incomingRef.startswith("refs/"):
+        return incomingRef
+    if importIntoRemotes:
+        prepend = "refs/remotes/"
+    else:
+        prepend = "refs/heads/"
+    if not incomingRef.startswith("p4/"):
+        prepend += "p4/"
+    return prepend + incomingRef
+
+def shortP4Ref(incomingRef, importIntoRemotes=True):
+    """Standardize to a "short ref" if possible:
+         refs/foo/bar/branch -> ignore
+         refs/remotes/p4/branch or refs/heads/p4/branch -> shorten
+         p4/branch -> shorten"""
+    if importIntoRemotes:
+        longprefix = "refs/remotes/p4/"
+    else:
+        longprefix = "refs/heads/p4/"
+    if incomingRef.startswith(longprefix):
+        return incomingRef[len(longprefix):]
+    if incomingRef.startswith("p4/"):
+        return incomingRef[3:]
+    return incomingRef
+
 def p4BranchesInGit(branchesAreInRemotes=True):
     """Find all the branches whose names start with "p4/", looking
        in remotes or heads as specified by the argument.  Return
@@ -3750,9 +3780,13 @@ class P4Sync(Command, P4UserMap):
 
             # restrict to just this one, disabling detect-branches
             if branch_arg_given:
-                short = self.branch.split("/")[-1]
+                short = shortP4Ref(self.branch, self.importIntoRemotes)
                 if short in branches:
                     self.p4BranchesInGit = [ short ]
+                elif self.branch.startswith('refs/') and \
+                        branchExists(self.branch) and \
+                        '[git-p4:' in extractLogMessageFromGitCommit(self.branch):
+                    self.p4BranchesInGit = [ self.branch ]
             else:
                 self.p4BranchesInGit = branches.keys()
 
@@ -3769,7 +3803,8 @@ class P4Sync(Command, P4UserMap):
 
             p4Change = 0
             for branch in self.p4BranchesInGit:
-                logMsg =  extractLogMessageFromGitCommit(self.refPrefix + branch)
+                logMsg = extractLogMessageFromGitCommit(fullP4Ref(branch,
+                                                        self.importIntoRemotes))
 
                 settings = extractSettingsGitLog(logMsg)
 
@@ -3802,18 +3837,7 @@ class P4Sync(Command, P4UserMap):
                 if not self.silent and not self.detectBranches:
                     print("Performing incremental import into %s git branch" % self.branch)
 
-        # accept multiple ref name abbreviations:
-        #    refs/foo/bar/branch -> use it exactly
-        #    p4/branch -> prepend refs/remotes/ or refs/heads/
-        #    branch -> prepend refs/remotes/p4/ or refs/heads/p4/
-        if not self.branch.startswith("refs/"):
-            if self.importIntoRemotes:
-                prepend = "refs/remotes/"
-            else:
-                prepend = "refs/heads/"
-            if not self.branch.startswith("p4/"):
-                prepend += "p4/"
-            self.branch = prepend + self.branch
+        self.branch = fullP4Ref(self.branch, self.importIntoRemotes)
 
         if len(args) == 0 and self.depotPaths:
             if not self.silent:
t/t9800-git-p4-basic.sh +85 -0

91 lines not on this page · raw message

t/t9801-git-p4-branch.sh +10 -0
index 50a6f8bad5c..759a14fa87c 100755
@@ -129,6 +129,16 @@ test_expect_success 'import depot, branch detection' '
 	)
 '
 
+test_expect_success 'sync specific detected branch' '
+	test_when_finished cleanup_git &&
+	git p4 clone --dest="$git" --detect-branches //depot@all &&
+	(
+		cd "$git" &&
+		git p4 sync --branch=depot/branch2 >out &&
+		test_i18ngrep "No changes to import!" out
+	)
+'
+
 test_expect_success 'import depot, branch detection, branchList branch definition' '
 	test_when_finished cleanup_git &&
 	test_create_repo "$git" &&

base-commit: 805e0a68082a217f0112db9ee86a022227a9c81b

Signature · 1 line
gitgitgadget