Sync with maint
[git] / t / t9800-git-p4-basic.sh
1 #!/bin/sh
2
3 test_description='git p4 tests'
4
5 . ./lib-git-p4.sh
6
7 test_expect_success 'start p4d' '
8         start_p4d
9 '
10
11 test_expect_success 'add p4 files' '
12         (
13                 cd "$cli" &&
14                 echo file1 >file1 &&
15                 p4 add file1 &&
16                 p4 submit -d "file1" &&
17                 echo file2 >file2 &&
18                 p4 add file2 &&
19                 p4 submit -d "file2"
20         )
21 '
22
23 test_expect_success 'basic git p4 clone' '
24         git p4 clone --dest="$git" //depot &&
25         test_when_finished cleanup_git &&
26         (
27                 cd "$git" &&
28                 git log --oneline >lines &&
29                 test_line_count = 1 lines
30         )
31 '
32
33 test_expect_success 'git p4 clone @all' '
34         git p4 clone --dest="$git" //depot@all &&
35         test_when_finished cleanup_git &&
36         (
37                 cd "$git" &&
38                 git log --oneline >lines &&
39                 test_line_count = 2 lines
40         )
41 '
42
43 test_expect_success 'git p4 sync uninitialized repo' '
44         test_create_repo "$git" &&
45         test_when_finished cleanup_git &&
46         (
47                 cd "$git" &&
48                 test_must_fail git p4 sync
49         )
50 '
51
52 #
53 # Create a git repo by hand.  Add a commit so that HEAD is valid.
54 # Test imports a new p4 repository into a new git branch.
55 #
56 test_expect_success 'git p4 sync new branch' '
57         test_create_repo "$git" &&
58         test_when_finished cleanup_git &&
59         (
60                 cd "$git" &&
61                 test_commit head &&
62                 git p4 sync --branch=refs/remotes/p4/depot //depot@all &&
63                 git log --oneline p4/depot >lines &&
64                 test_line_count = 2 lines
65         )
66 '
67
68 test_expect_success 'clone two dirs' '
69         (
70                 cd "$cli" &&
71                 mkdir sub1 sub2 &&
72                 echo sub1/f1 >sub1/f1 &&
73                 echo sub2/f2 >sub2/f2 &&
74                 p4 add sub1/f1 &&
75                 p4 submit -d "sub1/f1" &&
76                 p4 add sub2/f2 &&
77                 p4 submit -d "sub2/f2"
78         ) &&
79         git p4 clone --dest="$git" //depot/sub1 //depot/sub2 &&
80         test_when_finished cleanup_git &&
81         (
82                 cd "$git" &&
83                 git ls-files >lines &&
84                 test_line_count = 2 lines &&
85                 git log --oneline p4/master >lines &&
86                 test_line_count = 1 lines
87         )
88 '
89
90 test_expect_success 'clone two dirs, @all' '
91         (
92                 cd "$cli" &&
93                 echo sub1/f3 >sub1/f3 &&
94                 p4 add sub1/f3 &&
95                 p4 submit -d "sub1/f3"
96         ) &&
97         git p4 clone --dest="$git" //depot/sub1@all //depot/sub2@all &&
98         test_when_finished cleanup_git &&
99         (
100                 cd "$git" &&
101                 git ls-files >lines &&
102                 test_line_count = 3 lines &&
103                 git log --oneline p4/master >lines &&
104                 test_line_count = 3 lines
105         )
106 '
107
108 test_expect_success 'clone two dirs, @all, conflicting files' '
109         (
110                 cd "$cli" &&
111                 echo sub2/f3 >sub2/f3 &&
112                 p4 add sub2/f3 &&
113                 p4 submit -d "sub2/f3"
114         ) &&
115         git p4 clone --dest="$git" //depot/sub1@all //depot/sub2@all &&
116         test_when_finished cleanup_git &&
117         (
118                 cd "$git" &&
119                 git ls-files >lines &&
120                 test_line_count = 3 lines &&
121                 git log --oneline p4/master >lines &&
122                 test_line_count = 4 lines &&
123                 echo sub2/f3 >expected &&
124                 test_cmp expected f3
125         )
126 '
127
128 test_expect_success 'exit when p4 fails to produce marshaled output' '
129         badp4dir="$TRASH_DIRECTORY/badp4dir" &&
130         mkdir "$badp4dir" &&
131         test_when_finished "rm \"$badp4dir/p4\" && rmdir \"$badp4dir\"" &&
132         cat >"$badp4dir"/p4 <<-EOF &&
133         #!$SHELL_PATH
134         exit 1
135         EOF
136         chmod 755 "$badp4dir"/p4 &&
137         PATH="$badp4dir:$PATH" git p4 clone --dest="$git" //depot >errs 2>&1 ; retval=$? &&
138         test $retval -eq 1 &&
139         test_must_fail grep -q Traceback errs
140 '
141
142 test_expect_success 'add p4 files with wildcards in the names' '
143         (
144                 cd "$cli" &&
145                 echo file-wild-hash >file-wild#hash &&
146                 echo file-wild-star >file-wild\*star &&
147                 echo file-wild-at >file-wild@at &&
148                 echo file-wild-percent >file-wild%percent &&
149                 p4 add -f file-wild* &&
150                 p4 submit -d "file wildcards"
151         )
152 '
153
154 test_expect_success 'wildcard files git p4 clone' '
155         git p4 clone --dest="$git" //depot &&
156         test_when_finished cleanup_git &&
157         (
158                 cd "$git" &&
159                 test -f file-wild#hash &&
160                 test -f file-wild\*star &&
161                 test -f file-wild@at &&
162                 test -f file-wild%percent
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 &&
275         (
276                 cd "$git" &&
277                 test ! -d .git &&
278                 bare=`git config --get core.bare` &&
279                 test "$bare" = true
280         )
281 '
282
283 p4_add_user() {
284         name=$1 fullname=$2 &&
285         p4 user -f -i <<-EOF &&
286         User: $name
287         Email: $name@localhost
288         FullName: $fullname
289         EOF
290         p4 passwd -P secret $name
291 }
292
293 p4_grant_admin() {
294         name=$1 &&
295         {
296                 p4 protect -o &&
297                 echo "    admin user $name * //depot/..."
298         } | p4 protect -i
299 }
300
301 p4_check_commit_author() {
302         file=$1 user=$2 &&
303         p4 changes -m 1 //depot/$file | grep -q $user
304 }
305
306 make_change_by_user() {
307         file=$1 name=$2 email=$3 &&
308         echo "username: a change by $name" >>"$file" &&
309         git add "$file" &&
310         git commit --author "$name <$email>" -m "a change by $name"
311 }
312
313 # Test username support, submitting as user 'alice'
314 test_expect_success 'preserve users' '
315         p4_add_user alice Alice &&
316         p4_add_user bob Bob &&
317         p4_grant_admin alice &&
318         git p4 clone --dest="$git" //depot &&
319         test_when_finished cleanup_git &&
320         (
321                 cd "$git" &&
322                 echo "username: a change by alice" >>file1 &&
323                 echo "username: a change by bob" >>file2 &&
324                 git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 &&
325                 git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 &&
326                 git config git-p4.skipSubmitEditCheck true &&
327                 P4EDITOR=touch P4USER=alice P4PASSWD=secret git p4 commit --preserve-user &&
328                 p4_check_commit_author file1 alice &&
329                 p4_check_commit_author file2 bob
330         )
331 '
332
333 # Test username support, submitting as bob, who lacks admin rights. Should
334 # not submit change to p4 (git diff should show deltas).
335 test_expect_success 'refuse to preserve users without perms' '
336         git p4 clone --dest="$git" //depot &&
337         test_when_finished cleanup_git &&
338         (
339                 cd "$git" &&
340                 git config git-p4.skipSubmitEditCheck true &&
341                 echo "username-noperms: a change by alice" >>file1 &&
342                 git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
343                 P4EDITOR=touch P4USER=bob P4PASSWD=secret &&
344                 export P4EDITOR P4USER P4PASSWD &&
345                 test_must_fail git p4 commit --preserve-user &&
346                 ! git diff --exit-code HEAD..p4/master
347         )
348 '
349
350 # What happens with unknown author? Without allowMissingP4Users it should fail.
351 test_expect_success 'preserve user where author is unknown to p4' '
352         git p4 clone --dest="$git" //depot &&
353         test_when_finished cleanup_git &&
354         (
355                 cd "$git" &&
356                 git config git-p4.skipSubmitEditCheck true &&
357                 echo "username-bob: a change by bob" >>file1 &&
358                 git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 &&
359                 echo "username-unknown: a change by charlie" >>file1 &&
360                 git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 &&
361                 P4EDITOR=touch P4USER=alice P4PASSWD=secret &&
362                 export P4EDITOR P4USER P4PASSWD &&
363                 test_must_fail git p4 commit --preserve-user &&
364                 ! git diff --exit-code HEAD..p4/master &&
365
366                 echo "$0: repeat with allowMissingP4Users enabled" &&
367                 git config git-p4.allowMissingP4Users true &&
368                 git config git-p4.preserveUser true &&
369                 git p4 commit &&
370                 git diff --exit-code HEAD..p4/master &&
371                 p4_check_commit_author file1 alice
372         )
373 '
374
375 # If we're *not* using --preserve-user, git p4 should warn if we're submitting
376 # changes that are not all ours.
377 # Test: user in p4 and user unknown to p4.
378 # Test: warning disabled and user is the same.
379 test_expect_success 'not preserving user with mixed authorship' '
380         git p4 clone --dest="$git" //depot &&
381         test_when_finished cleanup_git &&
382         (
383                 cd "$git" &&
384                 git config git-p4.skipSubmitEditCheck true &&
385                 p4_add_user derek Derek &&
386
387                 make_change_by_user usernamefile3 Derek derek@localhost &&
388                 P4EDITOR=cat P4USER=alice P4PASSWD=secret &&
389                 export P4EDITOR P4USER P4PASSWD &&
390                 git p4 commit |\
391                 grep "git author derek@localhost does not match" &&
392
393                 make_change_by_user usernamefile3 Charlie charlie@localhost &&
394                 git p4 commit |\
395                 grep "git author charlie@localhost does not match" &&
396
397                 make_change_by_user usernamefile3 alice alice@localhost &&
398                 git p4 commit |\
399                 test_must_fail grep "git author.*does not match" &&
400
401                 git config git-p4.skipUserNameCheck true &&
402                 make_change_by_user usernamefile3 Charlie charlie@localhost &&
403                 git p4 commit |\
404                 test_must_fail grep "git author.*does not match" &&
405
406                 p4_check_commit_author usernamefile3 alice
407         )
408 '
409
410 marshal_dump() {
411         what=$1
412         "$PYTHON_PATH" -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]'
413 }
414
415 # Sleep a bit so that the top-most p4 change did not happen "now".  Then
416 # import the repo and make sure that the initial import has the same time
417 # as the top-most change.
418 test_expect_success 'initial import time from top change time' '
419         p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) &&
420         p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) &&
421         sleep 3 &&
422         git p4 clone --dest="$git" //depot &&
423         test_when_finished cleanup_git &&
424         (
425                 cd "$git" &&
426                 gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
427                 echo $p4time $gittime &&
428                 test $p4time = $gittime
429         )
430 '
431
432 # Rename a file and confirm that rename is not detected in P4.
433 # Rename the new file again with detectRenames option enabled and confirm that
434 # this is detected in P4.
435 # Rename the new file again adding an extra line, configure a big threshold in
436 # detectRenames and confirm that rename is not detected in P4.
437 # Repeat, this time with a smaller threshold and confirm that the rename is
438 # detected in P4.
439 test_expect_success 'detect renames' '
440         git p4 clone --dest="$git" //depot@all &&
441         test_when_finished cleanup_git &&
442         (
443                 cd "$git" &&
444                 git config git-p4.skipSubmitEdit true &&
445
446                 git mv file1 file4 &&
447                 git commit -a -m "Rename file1 to file4" &&
448                 git diff-tree -r -M HEAD &&
449                 git p4 submit &&
450                 p4 filelog //depot/file4 &&
451                 p4 filelog //depot/file4 | test_must_fail grep -q "branch from" &&
452
453                 git mv file4 file5 &&
454                 git commit -a -m "Rename file4 to file5" &&
455                 git diff-tree -r -M HEAD &&
456                 git config git-p4.detectRenames true &&
457                 git p4 submit &&
458                 p4 filelog //depot/file5 &&
459                 p4 filelog //depot/file5 | grep -q "branch from //depot/file4" &&
460
461                 git mv file5 file6 &&
462                 echo update >>file6 &&
463                 git add file6 &&
464                 git commit -a -m "Rename file5 to file6 with changes" &&
465                 git diff-tree -r -M HEAD &&
466                 level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
467                 test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
468                 git config git-p4.detectRenames $(($level + 2)) &&
469                 git p4 submit &&
470                 p4 filelog //depot/file6 &&
471                 p4 filelog //depot/file6 | test_must_fail grep -q "branch from" &&
472
473                 git mv file6 file7 &&
474                 echo update >>file7 &&
475                 git add file7 &&
476                 git commit -a -m "Rename file6 to file7 with changes" &&
477                 git diff-tree -r -M HEAD &&
478                 level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
479                 test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
480                 git config git-p4.detectRenames $(($level - 2)) &&
481                 git p4 submit &&
482                 p4 filelog //depot/file7 &&
483                 p4 filelog //depot/file7 | grep -q "branch from //depot/file6"
484         )
485 '
486
487 # Copy a file and confirm that copy is not detected in P4.
488 # Copy a file with detectCopies option enabled and confirm that copy is not
489 # detected in P4.
490 # Modify and copy a file with detectCopies option enabled and confirm that copy
491 # is detected in P4.
492 # Copy a file with detectCopies and detectCopiesHarder options enabled and
493 # confirm that copy is detected in P4.
494 # Modify and copy a file, configure a bigger threshold in detectCopies and
495 # confirm that copy is not detected in P4.
496 # Modify and copy a file, configure a smaller threshold in detectCopies and
497 # confirm that copy is detected in P4.
498 test_expect_success 'detect copies' '
499         git p4 clone --dest="$git" //depot@all &&
500         test_when_finished cleanup_git &&
501         (
502                 cd "$git" &&
503                 git config git-p4.skipSubmitEdit true &&
504
505                 cp file2 file8 &&
506                 git add file8 &&
507                 git commit -a -m "Copy file2 to file8" &&
508                 git diff-tree -r -C HEAD &&
509                 git p4 submit &&
510                 p4 filelog //depot/file8 &&
511                 p4 filelog //depot/file8 | test_must_fail grep -q "branch from" &&
512
513                 cp file2 file9 &&
514                 git add file9 &&
515                 git commit -a -m "Copy file2 to file9" &&
516                 git diff-tree -r -C HEAD &&
517                 git config git-p4.detectCopies true &&
518                 git p4 submit &&
519                 p4 filelog //depot/file9 &&
520                 p4 filelog //depot/file9 | test_must_fail grep -q "branch from" &&
521
522                 echo "file2" >>file2 &&
523                 cp file2 file10 &&
524                 git add file2 file10 &&
525                 git commit -a -m "Modify and copy file2 to file10" &&
526                 git diff-tree -r -C HEAD &&
527                 git p4 submit &&
528                 p4 filelog //depot/file10 &&
529                 p4 filelog //depot/file10 | grep -q "branch from //depot/file" &&
530
531                 cp file2 file11 &&
532                 git add file11 &&
533                 git commit -a -m "Copy file2 to file11" &&
534                 git diff-tree -r -C --find-copies-harder HEAD &&
535                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
536                 test "$src" = file10 &&
537                 git config git-p4.detectCopiesHarder true &&
538                 git p4 submit &&
539                 p4 filelog //depot/file11 &&
540                 p4 filelog //depot/file11 | grep -q "branch from //depot/file" &&
541
542                 cp file2 file12 &&
543                 echo "some text" >>file12 &&
544                 git add file12 &&
545                 git commit -a -m "Copy file2 to file12 with changes" &&
546                 git diff-tree -r -C --find-copies-harder HEAD &&
547                 level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
548                 test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
549                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
550                 test "$src" = file10 &&
551                 git config git-p4.detectCopies $(($level + 2)) &&
552                 git p4 submit &&
553                 p4 filelog //depot/file12 &&
554                 p4 filelog //depot/file12 | test_must_fail grep -q "branch from" &&
555
556                 cp file2 file13 &&
557                 echo "different text" >>file13 &&
558                 git add file13 &&
559                 git commit -a -m "Copy file2 to file13 with changes" &&
560                 git diff-tree -r -C --find-copies-harder HEAD &&
561                 level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
562                 test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
563                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
564                 test "$src" = file10 &&
565                 git config git-p4.detectCopies $(($level - 2)) &&
566                 git p4 submit &&
567                 p4 filelog //depot/file13 &&
568                 p4 filelog //depot/file13 | grep -q "branch from //depot/file"
569         )
570 '
571
572 test_expect_success 'kill p4d' '
573         kill_p4d
574 '
575
576 test_done