Skip to content

Commit 543987b

Browse files
Pete Wyckoffgitster
authored andcommitted
git-p4: fix submit regression with clientSpec and subdir clone
When the --use-client-spec is given to clone, and the clone path is a subset of the full tree as specified in the client, future submits will go to the wrong place. Factor out getClientSpec() so both clone/sync and submit can use it. Introduce getClientRoot() that is needed for the client spec case, and use it instead of p4Where(). Test the five possible submit behaviors (add, modify, rename, copy, delete). Reported-by: Laurent Charrière <[email protected]> Signed-off-by: Pete Wyckoff <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a93d33e commit 543987b

File tree

2 files changed

+185
-43
lines changed

2 files changed

+185
-43
lines changed

contrib/fast-import/git-p4

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,46 @@ def p4PathStartsWith(path, prefix):
555555
return path.lower().startswith(prefix.lower())
556556
return path.startswith(prefix)
557557

558+
def getClientSpec():
559+
"""Look at the p4 client spec, create a View() object that contains
560+
all the mappings, and return it."""
561+
562+
specList = p4CmdList("client -o")
563+
if len(specList) != 1:
564+
die('Output from "client -o" is %d lines, expecting 1' %
565+
len(specList))
566+
567+
# dictionary of all client parameters
568+
entry = specList[0]
569+
570+
# just the keys that start with "View"
571+
view_keys = [ k for k in entry.keys() if k.startswith("View") ]
572+
573+
# hold this new View
574+
view = View()
575+
576+
# append the lines, in order, to the view
577+
for view_num in range(len(view_keys)):
578+
k = "View%d" % view_num
579+
if k not in view_keys:
580+
die("Expected view key %s missing" % k)
581+
view.append(entry[k])
582+
583+
return view
584+
585+
def getClientRoot():
586+
"""Grab the client directory."""
587+
588+
output = p4CmdList("client -o")
589+
if len(output) != 1:
590+
die('Output from "client -o" is %d lines, expecting 1' % len(output))
591+
592+
entry = output[0]
593+
if "Root" not in entry:
594+
die('Client has no "Root"')
595+
596+
return entry["Root"]
597+
558598
class Command:
559599
def __init__(self):
560600
self.usage = "usage: %prog [options]"
@@ -1119,11 +1159,20 @@ class P4Submit(Command, P4UserMap):
11191159
print "Internal error: cannot locate perforce depot path from existing branches"
11201160
sys.exit(128)
11211161

1122-
self.clientPath = p4Where(self.depotPath)
1162+
self.useClientSpec = False
1163+
if gitConfig("git-p4.useclientspec", "--bool") == "true":
1164+
self.useClientSpec = True
1165+
if self.useClientSpec:
1166+
self.clientSpecDirs = getClientSpec()
1167+
1168+
if self.useClientSpec:
1169+
# all files are relative to the client spec
1170+
self.clientPath = getClientRoot()
1171+
else:
1172+
self.clientPath = p4Where(self.depotPath)
11231173

1124-
if len(self.clientPath) == 0:
1125-
print "Error: Cannot locate perforce checkout of %s in client view" % self.depotPath
1126-
sys.exit(128)
1174+
if self.clientPath == "":
1175+
die("Error: Cannot locate perforce checkout of %s in client view" % self.depotPath)
11271176

11281177
print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath)
11291178
self.oldWorkingDirectory = os.getcwd()
@@ -2078,33 +2127,6 @@ class P4Sync(Command, P4UserMap):
20782127
print self.gitError.read()
20792128

20802129

2081-
def getClientSpec(self):
2082-
specList = p4CmdList("client -o")
2083-
if len(specList) != 1:
2084-
die('Output from "client -o" is %d lines, expecting 1' %
2085-
len(specList))
2086-
2087-
# dictionary of all client parameters
2088-
entry = specList[0]
2089-
2090-
# just the keys that start with "View"
2091-
view_keys = [ k for k in entry.keys() if k.startswith("View") ]
2092-
2093-
# hold this new View
2094-
view = View()
2095-
2096-
# append the lines, in order, to the view
2097-
for view_num in range(len(view_keys)):
2098-
k = "View%d" % view_num
2099-
if k not in view_keys:
2100-
die("Expected view key %s missing" % k)
2101-
view.append(entry[k])
2102-
2103-
self.clientSpecDirs = view
2104-
if self.verbose:
2105-
for i, m in enumerate(self.clientSpecDirs.mappings):
2106-
print "clientSpecDirs %d: %s" % (i, str(m))
2107-
21082130
def run(self, args):
21092131
self.depotPaths = []
21102132
self.changeRange = ""
@@ -2145,7 +2167,7 @@ class P4Sync(Command, P4UserMap):
21452167
if gitConfig("git-p4.useclientspec", "--bool") == "true":
21462168
self.useClientSpec = True
21472169
if self.useClientSpec:
2148-
self.getClientSpec()
2170+
self.clientSpecDirs = getClientSpec()
21492171

21502172
# TODO: should always look at previous commits,
21512173
# merge with previous imports, if possible.

t/t9809-git-p4-client-view.sh

Lines changed: 131 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,24 @@ git_verify() {
7171
# - dir2
7272
# - file21
7373
# - file22
74+
init_depot() {
75+
for d in 1 2 ; do
76+
mkdir -p dir$d &&
77+
for f in 1 2 ; do
78+
echo dir$d/file$d$f >dir$d/file$d$f &&
79+
p4 add dir$d/file$d$f &&
80+
p4 submit -d "dir$d/file$d$f"
81+
done
82+
done &&
83+
find . -type f ! -name files >files &&
84+
check_files_exist dir1/file11 dir1/file12 \
85+
dir2/file21 dir2/file22
86+
}
87+
7488
test_expect_success 'init depot' '
7589
(
7690
cd "$cli" &&
77-
for d in 1 2 ; do
78-
mkdir -p dir$d &&
79-
for f in 1 2 ; do
80-
echo dir$d/file$d$f >dir$d/file$d$f &&
81-
p4 add dir$d/file$d$f &&
82-
p4 submit -d "dir$d/file$d$f"
83-
done
84-
done &&
85-
find . -type f ! -name files >files &&
86-
check_files_exist dir1/file11 dir1/file12 \
87-
dir2/file21 dir2/file22
91+
init_depot
8892
)
8993
'
9094

@@ -257,6 +261,122 @@ test_expect_success 'clone --use-client-spec sets useClientSpec' '
257261
)
258262
'
259263

264+
# clone just a subdir of the client spec
265+
test_expect_success 'subdir clone' '
266+
client_view "//depot/... //client/..." &&
267+
files="dir1/file11 dir1/file12 dir2/file21 dir2/file22" &&
268+
client_verify $files &&
269+
test_when_finished cleanup_git &&
270+
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
271+
git_verify dir1/file11 dir1/file12
272+
'
273+
274+
#
275+
# submit back, see what happens: five cases
276+
#
277+
test_expect_success 'subdir clone, submit modify' '
278+
client_view "//depot/... //client/..." &&
279+
test_when_finished cleanup_git &&
280+
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
281+
(
282+
cd "$git" &&
283+
git config git-p4.skipSubmitEdit true &&
284+
echo line >>dir1/file12 &&
285+
git add dir1/file12 &&
286+
git commit -m dir1/file12 &&
287+
"$GITP4" submit
288+
) &&
289+
(
290+
cd "$cli" &&
291+
test_path_is_file dir1/file12 &&
292+
test_line_count = 2 dir1/file12
293+
)
294+
'
295+
296+
test_expect_success 'subdir clone, submit add' '
297+
client_view "//depot/... //client/..." &&
298+
test_when_finished cleanup_git &&
299+
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
300+
(
301+
cd "$git" &&
302+
git config git-p4.skipSubmitEdit true &&
303+
echo file13 >dir1/file13 &&
304+
git add dir1/file13 &&
305+
git commit -m dir1/file13 &&
306+
"$GITP4" submit
307+
) &&
308+
(
309+
cd "$cli" &&
310+
test_path_is_file dir1/file13
311+
)
312+
'
313+
314+
test_expect_success 'subdir clone, submit delete' '
315+
client_view "//depot/... //client/..." &&
316+
test_when_finished cleanup_git &&
317+
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
318+
(
319+
cd "$git" &&
320+
git config git-p4.skipSubmitEdit true &&
321+
git rm dir1/file12 &&
322+
git commit -m "delete dir1/file12" &&
323+
"$GITP4" submit
324+
) &&
325+
(
326+
cd "$cli" &&
327+
test_path_is_missing dir1/file12
328+
)
329+
'
330+
331+
test_expect_success 'subdir clone, submit copy' '
332+
client_view "//depot/... //client/..." &&
333+
test_when_finished cleanup_git &&
334+
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
335+
(
336+
cd "$git" &&
337+
git config git-p4.skipSubmitEdit true &&
338+
git config git-p4.detectCopies true &&
339+
cp dir1/file11 dir1/file11a &&
340+
git add dir1/file11a &&
341+
git commit -m "copy to dir1/file11a" &&
342+
"$GITP4" submit
343+
) &&
344+
(
345+
cd "$cli" &&
346+
test_path_is_file dir1/file11a
347+
)
348+
'
349+
350+
test_expect_success 'subdir clone, submit rename' '
351+
client_view "//depot/... //client/..." &&
352+
test_when_finished cleanup_git &&
353+
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
354+
(
355+
cd "$git" &&
356+
git config git-p4.skipSubmitEdit true &&
357+
git config git-p4.detectRenames true &&
358+
git mv dir1/file13 dir1/file13a &&
359+
git commit -m "rename dir1/file13 to dir1/file13a" &&
360+
"$GITP4" submit
361+
) &&
362+
(
363+
cd "$cli" &&
364+
test_path_is_missing dir1/file13 &&
365+
test_path_is_file dir1/file13a
366+
)
367+
'
368+
369+
test_expect_success 'reinit depot' '
370+
(
371+
cd "$cli" &&
372+
p4 sync -f &&
373+
rm files &&
374+
p4 delete */* &&
375+
p4 submit -d "delete all files" &&
376+
init_depot
377+
)
378+
'
379+
260380
#
261381
# Rename directories to test quoting in depot-side mappings
262382
# //depot

0 commit comments

Comments
 (0)