git p4: submit files with wildcards

There are four wildcard characters in p4. Files with these characters can be added to p4 repos using the "-f" option. They are stored in %xx notation, and when checked out, p4 converts them back to normal. When adding files with wildcards in git, the submit path must be careful to use the encoded names in some places, and it must use "-f" to add them. All other p4 commands that operate on the client directory expect encoded filenames as arguments. Support for wildcards in the clone/sync path was added in 084f630 (git-p4: decode p4 wildcard characters, 2011-02-19), but that change did not handle the submit path. There was a problem with wildcards in the sync path too. Commit 084f630 (git-p4: decode p4 wildcard characters, 2011-02-19) handled files with p4 wildcards that were added or modified in p4. Do this for deleted files, and also in branch detection checks, too. Reported-by: Luke Diamand <luke@diamand.org> Signed-off-by: Pete Wyckoff <pw@padd.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Pete Wyckoff committed Apr 29, 2012 at 20:57 UTC 9d7d446ae94d03ff3b7b32e7341198d9b2c5b222
3 files changed +185 -28
git-p4.py
+46 -28
@@ -133,25 +133,29 @@ def p4_system(cmd):
133 subprocess.check_call(real_cmd, shell=expand)
134
135 def p4_integrate(src, dest):
136 - p4_system(["integrate", "-Dt", src, dest])
136 + p4_system(["integrate", "-Dt", wildcard_encode(src), wildcard_encode(dest)])
137
138 def p4_sync(f, *options):
139 - p4_system(["sync"] + list(options) + [f])
139 + p4_system(["sync"] + list(options) + [wildcard_encode(f)])
140
141 def p4_add(f):
142 - p4_system(["add", f])
142 + # forcibly add file names with wildcards
143 + if wildcard_present(f):
144 + p4_system(["add", "-f", f])
145 + else:
146 + p4_system(["add", f])
147
148 def p4_delete(f):
145 - p4_system(["delete", f])
149 + p4_system(["delete", wildcard_encode(f)])
150
151 def p4_edit(f):
148 - p4_system(["edit", f])
152 + p4_system(["edit", wildcard_encode(f)])
153
154 def p4_revert(f):
151 - p4_system(["revert", f])
155 + p4_system(["revert", wildcard_encode(f)])
156
153 -def p4_reopen(type, file):
154 - p4_system(["reopen", "-t", type, file])
157 +def p4_reopen(type, f):
158 + p4_system(["reopen", "-t", type, wildcard_encode(f)])
159
160 #
161 # Canonicalize the p4 type and return a tuple of the
@@ -248,7 +252,7 @@ def setP4ExecBit(file, mode):
252 def getP4OpenedType(file):
253 # Returns the perforce file type for the given file.
254
251 - result = p4_read_pipe(["opened", file])
255 + result = p4_read_pipe(["opened", wildcard_encode(file)])
256 match = re.match(".*\((.+)\)\r?$", result)
257 if match:
258 return match.group(1)
@@ -658,6 +662,34 @@ def getClientRoot():
662
663 return entry["Root"]
664
665 +#
666 +# P4 wildcards are not allowed in filenames. P4 complains
667 +# if you simply add them, but you can force it with "-f", in
668 +# which case it translates them into %xx encoding internally.
669 +#
670 +def wildcard_decode(path):
671 + # Search for and fix just these four characters. Do % last so
672 + # that fixing it does not inadvertently create new %-escapes.
673 + # Cannot have * in a filename in windows; untested as to
674 + # what p4 would do in such a case.
675 + if not platform.system() == "Windows":
676 + path = path.replace("%2A", "*")
677 + path = path.replace("%23", "#") \
678 + .replace("%40", "@") \
679 + .replace("%25", "%")
680 + return path
681 +
682 +def wildcard_encode(path):
683 + # do % first to avoid double-encoding the %s introduced here
684 + path = path.replace("%", "%25") \
685 + .replace("*", "%2A") \
686 + .replace("#", "%23") \
687 + .replace("@", "%40")
688 + return path
689 +
690 +def wildcard_present(path):
691 + return path.translate(None, "*#@%") != path
692 +
693 class Command:
694 def __init__(self):
695 self.usage = "usage: %prog [options]"
@@ -1187,7 +1219,8 @@ class P4Submit(Command, P4UserMap):
1219 del(os.environ["P4DIFF"])
1220 diff = ""
1221 for editedFile in editedFiles:
1190 - diff += p4_read_pipe(['diff', '-du', editedFile])
1222 + diff += p4_read_pipe(['diff', '-du',
1223 + wildcard_encode(editedFile)])
1224
1225 newdiff = ""
1226 for newFile in filesToAdd:
@@ -1697,23 +1730,6 @@ class P4Sync(Command, P4UserMap):
1730 if gitConfig("git-p4.syncFromOrigin") == "false":
1731 self.syncWithOrigin = False
1732
1700 - #
1701 - # P4 wildcards are not allowed in filenames. P4 complains
1702 - # if you simply add them, but you can force it with "-f", in
1703 - # which case it translates them into %xx encoding internally.
1704 - # Search for and fix just these four characters. Do % last so
1705 - # that fixing it does not inadvertently create new %-escapes.
1706 - #
1707 - def wildcard_decode(self, path):
1708 - # Cannot have * in a filename in windows; untested as to
1709 - # what p4 would do in such a case.
1710 - if not self.isWindows:
1711 - path = path.replace("%2A", "*")
1712 - path = path.replace("%23", "#") \
1713 - .replace("%40", "@") \
1714 - .replace("%25", "%")
1715 - return path
1716 -
1733 # Force a checkpoint in fast-import and wait for it to finish
1734 def checkpoint(self):
1735 self.gitStream.write("checkpoint\n\n")
@@ -1781,6 +1797,7 @@ class P4Sync(Command, P4UserMap):
1797 fnum = fnum + 1
1798
1799 relPath = self.stripRepoPath(path, self.depotPaths)
1800 + relPath = wildcard_decode(relPath)
1801
1802 for branch in self.knownBranches.keys():
1803
@@ -1798,7 +1815,7 @@ class P4Sync(Command, P4UserMap):
1815
1816 def streamOneP4File(self, file, contents):
1817 relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes)
1801 - relPath = self.wildcard_decode(relPath)
1818 + relPath = wildcard_decode(relPath)
1819 if verbose:
1820 sys.stderr.write("%s\n" % relPath)
1821
@@ -1867,6 +1884,7 @@ class P4Sync(Command, P4UserMap):
1884
1885 def streamOneP4Deletion(self, file):
1886 relPath = self.stripRepoPath(file['path'], self.branchPrefixes)
1887 + relPath = wildcard_decode(relPath)
1888 if verbose:
1889 sys.stderr.write("delete %s\n" % relPath)
1890 self.gitStream.write("D %s\n" % relPath)
t/t9800-git-p4-basic.sh
+106
@@ -163,6 +163,112 @@ test_expect_success 'wildcard files git p4 clone' '
163 )
164 '
165
166 +test_expect_success 'wildcard files submit back to p4, add' '
167 + test_when_finished cleanup_git &&
168 + git p4 clone --dest="$git" //depot &&
169 + (
170 + cd "$git" &&
171 + echo git-wild-hash >git-wild#hash &&
172 + echo git-wild-star >git-wild\*star &&
173 + echo git-wild-at >git-wild@at &&
174 + echo git-wild-percent >git-wild%percent &&
175 + git add git-wild* &&
176 + git commit -m "add some wildcard filenames" &&
177 + git config git-p4.skipSubmitEdit true &&
178 + git p4 submit
179 + ) &&
180 + (
181 + cd "$cli" &&
182 + test_path_is_file git-wild#hash &&
183 + test_path_is_file git-wild\*star &&
184 + test_path_is_file git-wild@at &&
185 + test_path_is_file git-wild%percent
186 + )
187 +'
188 +
189 +test_expect_success 'wildcard files submit back to p4, modify' '
190 + test_when_finished cleanup_git &&
191 + git p4 clone --dest="$git" //depot &&
192 + (
193 + cd "$git" &&
194 + echo new-line >>git-wild#hash &&
195 + echo new-line >>git-wild\*star &&
196 + echo new-line >>git-wild@at &&
197 + echo new-line >>git-wild%percent &&
198 + git add git-wild* &&
199 + git commit -m "modify the wildcard files" &&
200 + git config git-p4.skipSubmitEdit true &&
201 + git p4 submit
202 + ) &&
203 + (
204 + cd "$cli" &&
205 + test_line_count = 2 git-wild#hash &&
206 + test_line_count = 2 git-wild\*star &&
207 + test_line_count = 2 git-wild@at &&
208 + test_line_count = 2 git-wild%percent
209 + )
210 +'
211 +
212 +test_expect_success 'wildcard files submit back to p4, copy' '
213 + test_when_finished cleanup_git &&
214 + git p4 clone --dest="$git" //depot &&
215 + (
216 + cd "$git" &&
217 + cp file2 git-wild-cp#hash &&
218 + git add git-wild-cp#hash &&
219 + cp git-wild\*star file-wild-3 &&
220 + git add file-wild-3 &&
221 + git commit -m "wildcard copies" &&
222 + git config git-p4.detectCopies true &&
223 + git config git-p4.detectCopiesHarder true &&
224 + git config git-p4.skipSubmitEdit true &&
225 + git p4 submit
226 + ) &&
227 + (
228 + cd "$cli" &&
229 + test_path_is_file git-wild-cp#hash &&
230 + test_path_is_file file-wild-3
231 + )
232 +'
233 +
234 +test_expect_success 'wildcard files submit back to p4, rename' '
235 + test_when_finished cleanup_git &&
236 + git p4 clone --dest="$git" //depot &&
237 + (
238 + cd "$git" &&
239 + git mv git-wild@at file-wild-4 &&
240 + git mv file-wild-3 git-wild-cp%percent &&
241 + git commit -m "wildcard renames" &&
242 + git config git-p4.detectRenames true &&
243 + git config git-p4.skipSubmitEdit true &&
244 + git p4 submit
245 + ) &&
246 + (
247 + cd "$cli" &&
248 + test_path_is_missing git-wild@at &&
249 + test_path_is_file git-wild-cp%percent
250 + )
251 +'
252 +
253 +test_expect_success 'wildcard files submit back to p4, delete' '
254 + test_when_finished cleanup_git &&
255 + git p4 clone --dest="$git" //depot &&
256 + (
257 + cd "$git" &&
258 + git rm git-wild* &&
259 + git commit -m "delete the wildcard files" &&
260 + git config git-p4.skipSubmitEdit true &&
261 + git p4 submit
262 + ) &&
263 + (
264 + cd "$cli" &&
265 + test_path_is_missing git-wild#hash &&
266 + test_path_is_missing git-wild\*star &&
267 + test_path_is_missing git-wild@at &&
268 + test_path_is_missing git-wild%percent
269 + )
270 +'
271 +
272 test_expect_success 'clone bare' '
273 git p4 clone --dest="$git" --bare //depot &&
274 test_when_finished cleanup_git &&
t/t9809-git-p4-client-view.sh
+33
@@ -374,6 +374,39 @@ test_expect_success 'subdir clone, submit rename' '
374 )
375 '
376
377 +# see t9800 for the non-client-spec case, and the rest of the wildcard tests
378 +test_expect_success 'wildcard files submit back to p4, client-spec case' '
379 + client_view "//depot/... //client/..." &&
380 + test_when_finished cleanup_git &&
381 + git p4 clone --use-client-spec --dest="$git" //depot/dir1 &&
382 + (
383 + cd "$git" &&
384 + echo git-wild-hash >dir1/git-wild#hash &&
385 + echo git-wild-star >dir1/git-wild\*star &&
386 + echo git-wild-at >dir1/git-wild@at &&
387 + echo git-wild-percent >dir1/git-wild%percent &&
388 + git add dir1/git-wild* &&
389 + git commit -m "add some wildcard filenames" &&
390 + git config git-p4.skipSubmitEditCheck true &&
391 + git p4 submit
392 + ) &&
393 + (
394 + cd "$cli" &&
395 + test_path_is_file dir1/git-wild#hash &&
396 + test_path_is_file dir1/git-wild\*star &&
397 + test_path_is_file dir1/git-wild@at &&
398 + test_path_is_file dir1/git-wild%percent
399 + ) &&
400 + (
401 + # delete these carefully, cannot just do "p4 delete"
402 + # on files with wildcards; but git-p4 knows how
403 + cd "$git" &&
404 + git rm dir1/git-wild* &&
405 + git commit -m "clean up the wildcards" &&
406 + git p4 submit
407 + )
408 +'
409 +
410 test_expect_success 'reinit depot' '
411 (
412 cd "$cli" &&