{"thread":{"id":"29744","subject":"[PATCH] git-p4: submit files with wildcards","startedAt":"2012-02-26T14:55:00Z","lastAt":"2012-02-26T14:55:00Z","messageCount":1,"participants":["Pete Wyckoff"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"185456","messageId":"1330268100-29630-1-git-send-email-pw@padd.com","threadId":"29744","inReplyTo":null,"subject":"[PATCH] git-p4: submit files with wildcards","fromName":"Pete Wyckoff","fromEmail":"pw@padd.com","sentAt":"2012-02-26T14:55:00Z","receivedAt":"2012-02-26T14:55:00Z","isPatch":true,"sender":{"key":"pw@padd.com","avatar":null},"body":"There are four wildcard characters in p4.  Files with these\ncharacters can be added to p4 repos using the \"-f\" option.  They\nare stored in %xx notation, and when checked out, p4 converts\nthem back to normal.\n\nWhen adding files with wildcards in git, the submit path must\nbe careful to use the encoded names in some places, and it\nmust use \"-f\" to add them.\n\nSupport for wildcards in the clone/sync path was added in\n084f630 (git-p4: decode p4 wildcard characters, 2011-02-19),\nbut that change did not handle the submit path.\n\nReported-by: Luke Diamand <luke@diamand.org>\nSigned-off-by: Pete Wyckoff <pw@padd.com>\n---\n contrib/fast-import/git-p4 |   64 ++++++++++++++++++++++++++++---------------\n t/t9800-git-p4-basic.sh    |   23 ++++++++++++++++\n 2 files changed, 65 insertions(+), 22 deletions(-)\n\ndiff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4\nindex 0539553..bd89402 100755\n--- a/contrib/fast-import/git-p4\n+++ b/contrib/fast-import/git-p4\n@@ -136,8 +136,8 @@ def p4_integrate(src, dest):\n def p4_sync(path):\n     p4_system([\"sync\", path])\n \n-def p4_add(f):\n-    p4_system([\"add\", f])\n+def p4_add(path, *options):\n+    p4_system([\"add\"] + list(options) + [path])\n \n def p4_delete(f):\n     p4_system([\"delete\", f])\n@@ -232,8 +232,12 @@ def setP4ExecBit(file, mode):\n     # Reopens an already open file and changes the execute bit to match\n     # the execute bit setting in the passed in mode.\n \n-    p4Type = \"+x\"\n+    # Since this is working on already opened files, any with wildcards\n+    # in the name have been encoded already, and must be referred to\n+    # with the encoded name.\n+    file = wildcard_encode(file)\n \n+    p4Type = \"+x\"\n     if not isModeExec(mode):\n         p4Type = getP4OpenedType(file)\n         p4Type = re.sub('^([cku]?)x(.*)', '\\\\1\\\\2', p4Type)\n@@ -596,6 +600,34 @@ def p4PathStartsWith(path, prefix):\n         return path.lower().startswith(prefix.lower())\n     return path.startswith(prefix)\n \n+#\n+# P4 wildcards are not allowed in filenames.  P4 complains\n+# if you simply add them, but you can force it with \"-f\", in\n+# which case it translates them into %xx encoding internally.\n+#\n+def wildcard_decode(path):\n+    # Search for and fix just these four characters.  Do % last so\n+    # that fixing it does not inadvertently create new %-escapes.\n+    # Cannot have * in a filename in windows; untested as to\n+    # what p4 would do in such a case.\n+    if not platform.system() == \"Windows\":\n+        path = path.replace(\"%2A\", \"*\")\n+    path = path.replace(\"%23\", \"#\") \\\n+               .replace(\"%40\", \"@\") \\\n+               .replace(\"%25\", \"%\")\n+    return path\n+\n+def wildcard_encode(path):\n+    # do % first to avoid double-encoding the %s introduced here\n+    path = path.replace(\"%\", \"%25\") \\\n+               .replace(\"*\", \"%2A\") \\\n+               .replace(\"#\", \"%23\") \\\n+               .replace(\"@\", \"%40\")\n+    return path\n+\n+def wildcard_present(path):\n+    return path.translate(None, \"*#@%\") != path\n+\n class Command:\n     def __init__(self):\n         self.usage = \"usage: %prog [options]\"\n@@ -1099,7 +1131,12 @@ class P4Submit(Command, P4UserMap):\n         system(applyPatchCmd)\n \n         for f in filesToAdd:\n-            p4_add(f)\n+            # forcibly add file names with wildcards; see also\n+            # wildcard_decode() in the sync path\n+            if wildcard_present(f):\n+                p4_add(f, \"-f\")\n+            else:\n+                p4_add(f)\n         for f in filesToDelete:\n             p4_revert(f)\n             p4_delete(f)\n@@ -1537,23 +1574,6 @@ class P4Sync(Command, P4UserMap):\n         if gitConfig(\"git-p4.syncFromOrigin\") == \"false\":\n             self.syncWithOrigin = False\n \n-    #\n-    # P4 wildcards are not allowed in filenames.  P4 complains\n-    # if you simply add them, but you can force it with \"-f\", in\n-    # which case it translates them into %xx encoding internally.\n-    # Search for and fix just these four characters.  Do % last so\n-    # that fixing it does not inadvertently create new %-escapes.\n-    #\n-    def wildcard_decode(self, path):\n-        # Cannot have * in a filename in windows; untested as to\n-        # what p4 would do in such a case.\n-        if not self.isWindows:\n-            path = path.replace(\"%2A\", \"*\")\n-        path = path.replace(\"%23\", \"#\") \\\n-                   .replace(\"%40\", \"@\") \\\n-                   .replace(\"%25\", \"%\")\n-        return path\n-\n     # Force a checkpoint in fast-import and wait for it to finish\n     def checkpoint(self):\n         self.gitStream.write(\"checkpoint\\n\\n\")\n@@ -1638,7 +1658,7 @@ class P4Sync(Command, P4UserMap):\n \n     def streamOneP4File(self, file, contents):\n         relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes)\n-        relPath = self.wildcard_decode(relPath)\n+        relPath = wildcard_decode(relPath)\n         if verbose:\n             sys.stderr.write(\"%s\\n\" % relPath)\n \ndiff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh\nindex 04ee20e..22669df 100755\n--- a/t/t9800-git-p4-basic.sh\n+++ b/t/t9800-git-p4-basic.sh\n@@ -163,6 +163,29 @@ test_expect_success 'wildcard files git-p4 clone' '\n \t)\n '\n \n+test_expect_success 'wildcard files submit back to p4' '\n+\t\"$GITP4\" clone --dest=\"$git\" //depot &&\n+\ttest_when_finished cleanup_git &&\n+\t(\n+\t\tcd \"$git\" &&\n+\t\techo git-wild-hash >git-wild#hash &&\n+\t\techo git-wild-star >git-wild\\*star &&\n+\t\techo git-wild-at >git-wild@at &&\n+\t\techo git-wild-percent >git-wild%percent &&\n+\t\tgit add git-wild* &&\n+\t\tgit commit -m \"add some wildcard filenames\" &&\n+\t\tgit config git-p4.skipSubmitEditCheck true &&\n+\t\t\"$GITP4\" submit\n+\t) &&\n+\t(\n+\t\tcd \"$cli\" &&\n+\t\ttest_path_is_file git-wild#hash &&\n+\t\ttest_path_is_file git-wild\\*star &&\n+\t\ttest_path_is_file git-wild@at &&\n+\t\ttest_path_is_file git-wild%percent\n+\t)\n+'\n+\n test_expect_success 'clone bare' '\n \t\"$GITP4\" clone --dest=\"$git\" --bare //depot &&\n \ttest_when_finished cleanup_git &&\n-- \n1.7.9.220.g4b839\n"}]}