Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit a5f9ba9

Browse files
committed
Merge branch 'pw/p4-various'
Miscellaneous updates to "git p4". By Pete Wyckoff * pw/p4-various: git p4: submit files with wildcards git p4: fix writable file after rename or copy git p4: test submit git p4: bring back files in deleted client directory
2 parents 7b871c5 + 9d7d446 commit a5f9ba9

File tree

4 files changed

+308
-35
lines changed

4 files changed

+308
-35
lines changed

git-p4.py

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -133,25 +133,29 @@ def p4_system(cmd):
133133
subprocess.check_call(real_cmd, shell=expand)
134134

135135
def p4_integrate(src, dest):
136-
p4_system(["integrate", "-Dt", src, dest])
136+
p4_system(["integrate", "-Dt", wildcard_encode(src), wildcard_encode(dest)])
137137

138-
def p4_sync(path):
139-
p4_system(["sync", path])
138+
def p4_sync(f, *options):
139+
p4_system(["sync"] + list(options) + [wildcard_encode(f)])
140140

141141
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])
143147

144148
def p4_delete(f):
145-
p4_system(["delete", f])
149+
p4_system(["delete", wildcard_encode(f)])
146150

147151
def p4_edit(f):
148-
p4_system(["edit", f])
152+
p4_system(["edit", wildcard_encode(f)])
149153

150154
def p4_revert(f):
151-
p4_system(["revert", f])
155+
p4_system(["revert", wildcard_encode(f)])
152156

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)])
155159

156160
#
157161
# Canonicalize the p4 type and return a tuple of the
@@ -248,7 +252,7 @@ def setP4ExecBit(file, mode):
248252
def getP4OpenedType(file):
249253
# Returns the perforce file type for the given file.
250254

251-
result = p4_read_pipe(["opened", file])
255+
result = p4_read_pipe(["opened", wildcard_encode(file)])
252256
match = re.match(".*\((.+)\)\r?$", result)
253257
if match:
254258
return match.group(1)
@@ -658,6 +662,34 @@ def getClientRoot():
658662

659663
return entry["Root"]
660664

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+
661693
class Command:
662694
def __init__(self):
663695
self.usage = "usage: %prog [options]"
@@ -1038,6 +1070,7 @@ def applyCommit(self, id):
10381070
filesToAdd = set()
10391071
filesToDelete = set()
10401072
editedFiles = set()
1073+
pureRenameCopy = set()
10411074
filesToChangeExecBit = {}
10421075

10431076
for line in diff:
@@ -1061,10 +1094,13 @@ def applyCommit(self, id):
10611094
elif modifier == "C":
10621095
src, dest = diff['src'], diff['dst']
10631096
p4_integrate(src, dest)
1097+
pureRenameCopy.add(dest)
10641098
if diff['src_sha1'] != diff['dst_sha1']:
10651099
p4_edit(dest)
1100+
pureRenameCopy.discard(dest)
10661101
if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
10671102
p4_edit(dest)
1103+
pureRenameCopy.discard(dest)
10681104
filesToChangeExecBit[dest] = diff['dst_mode']
10691105
os.unlink(dest)
10701106
editedFiles.add(dest)
@@ -1073,6 +1109,8 @@ def applyCommit(self, id):
10731109
p4_integrate(src, dest)
10741110
if diff['src_sha1'] != diff['dst_sha1']:
10751111
p4_edit(dest)
1112+
else:
1113+
pureRenameCopy.add(dest)
10761114
if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
10771115
p4_edit(dest)
10781116
filesToChangeExecBit[dest] = diff['dst_mode']
@@ -1181,7 +1219,8 @@ def applyCommit(self, id):
11811219
del(os.environ["P4DIFF"])
11821220
diff = ""
11831221
for editedFile in editedFiles:
1184-
diff += p4_read_pipe(['diff', '-du', editedFile])
1222+
diff += p4_read_pipe(['diff', '-du',
1223+
wildcard_encode(editedFile)])
11851224

11861225
newdiff = ""
11871226
for newFile in filesToAdd:
@@ -1226,6 +1265,12 @@ def applyCommit(self, id):
12261265
# unmarshalled.
12271266
changelist = self.lastP4Changelist()
12281267
self.modifyChangelistUser(changelist, p4User)
1268+
1269+
# The rename/copy happened by applying a patch that created a
1270+
# new file. This leaves it writable, which confuses p4.
1271+
for f in pureRenameCopy:
1272+
p4_sync(f, "-f")
1273+
12291274
else:
12301275
# skip this patch
12311276
print "Submission cancelled, undoing p4 changes."
@@ -1361,12 +1406,18 @@ def run(self, args):
13611406
self.oldWorkingDirectory = os.getcwd()
13621407

13631408
# ensure the clientPath exists
1409+
new_client_dir = False
13641410
if not os.path.exists(self.clientPath):
1411+
new_client_dir = True
13651412
os.makedirs(self.clientPath)
13661413

13671414
chdir(self.clientPath)
13681415
print "Synchronizing p4 checkout..."
1369-
p4_sync("...")
1416+
if new_client_dir:
1417+
# old one was destroyed, and maybe nobody told p4
1418+
p4_sync("...", "-f")
1419+
else:
1420+
p4_sync("...")
13701421
self.check()
13711422

13721423
commits = []
@@ -1679,23 +1730,6 @@ def __init__(self):
16791730
if gitConfig("git-p4.syncFromOrigin") == "false":
16801731
self.syncWithOrigin = False
16811732

1682-
#
1683-
# P4 wildcards are not allowed in filenames. P4 complains
1684-
# if you simply add them, but you can force it with "-f", in
1685-
# which case it translates them into %xx encoding internally.
1686-
# Search for and fix just these four characters. Do % last so
1687-
# that fixing it does not inadvertently create new %-escapes.
1688-
#
1689-
def wildcard_decode(self, path):
1690-
# Cannot have * in a filename in windows; untested as to
1691-
# what p4 would do in such a case.
1692-
if not self.isWindows:
1693-
path = path.replace("%2A", "*")
1694-
path = path.replace("%23", "#") \
1695-
.replace("%40", "@") \
1696-
.replace("%25", "%")
1697-
return path
1698-
16991733
# Force a checkpoint in fast-import and wait for it to finish
17001734
def checkpoint(self):
17011735
self.gitStream.write("checkpoint\n\n")
@@ -1763,6 +1797,7 @@ def splitFilesIntoBranches(self, commit):
17631797
fnum = fnum + 1
17641798

17651799
relPath = self.stripRepoPath(path, self.depotPaths)
1800+
relPath = wildcard_decode(relPath)
17661801

17671802
for branch in self.knownBranches.keys():
17681803

@@ -1780,7 +1815,7 @@ def splitFilesIntoBranches(self, commit):
17801815

17811816
def streamOneP4File(self, file, contents):
17821817
relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes)
1783-
relPath = self.wildcard_decode(relPath)
1818+
relPath = wildcard_decode(relPath)
17841819
if verbose:
17851820
sys.stderr.write("%s\n" % relPath)
17861821

@@ -1849,6 +1884,7 @@ def streamOneP4File(self, file, contents):
18491884

18501885
def streamOneP4Deletion(self, file):
18511886
relPath = self.stripRepoPath(file['path'], self.branchPrefixes)
1887+
relPath = wildcard_decode(relPath)
18521888
if verbose:
18531889
sys.stderr.write("delete %s\n" % relPath)
18541890
self.gitStream.write("D %s\n" % relPath)

t/t9800-git-p4-basic.sh

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,112 @@ test_expect_success 'wildcard files git p4 clone' '
163163
)
164164
'
165165

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+
166272
test_expect_success 'clone bare' '
167273
git p4 clone --dest="$git" --bare //depot &&
168274
test_when_finished cleanup_git &&

0 commit comments

Comments
 (0)