push: error out when the "upstream" semantics does not make sense
[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         "$GITP4" 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         "$GITP4" 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 "$GITP4" 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                 "$GITP4" 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         "$GITP4" 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         "$GITP4" 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         "$GITP4" 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" "$GITP4" 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         "$GITP4" 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 'clone bare' '
167         "$GITP4" clone --dest="$git" --bare //depot &&
168         test_when_finished cleanup_git &&
169         (
170                 cd "$git" &&
171                 test ! -d .git &&
172                 bare=`git config --get core.bare` &&
173                 test "$bare" = true
174         )
175 '
176
177 p4_add_user() {
178         name=$1 fullname=$2 &&
179         p4 user -f -i <<-EOF &&
180         User: $name
181         Email: $name@localhost
182         FullName: $fullname
183         EOF
184         p4 passwd -P secret $name
185 }
186
187 p4_grant_admin() {
188         name=$1 &&
189         {
190                 p4 protect -o &&
191                 echo "    admin user $name * //depot/..."
192         } | p4 protect -i
193 }
194
195 p4_check_commit_author() {
196         file=$1 user=$2 &&
197         p4 changes -m 1 //depot/$file | grep -q $user
198 }
199
200 make_change_by_user() {
201         file=$1 name=$2 email=$3 &&
202         echo "username: a change by $name" >>"$file" &&
203         git add "$file" &&
204         git commit --author "$name <$email>" -m "a change by $name"
205 }
206
207 # Test username support, submitting as user 'alice'
208 test_expect_success 'preserve users' '
209         p4_add_user alice Alice &&
210         p4_add_user bob Bob &&
211         p4_grant_admin alice &&
212         "$GITP4" clone --dest="$git" //depot &&
213         test_when_finished cleanup_git &&
214         (
215                 cd "$git" &&
216                 echo "username: a change by alice" >>file1 &&
217                 echo "username: a change by bob" >>file2 &&
218                 git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 &&
219                 git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 &&
220                 git config git-p4.skipSubmitEditCheck true &&
221                 P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user &&
222                 p4_check_commit_author file1 alice &&
223                 p4_check_commit_author file2 bob
224         )
225 '
226
227 # Test username support, submitting as bob, who lacks admin rights. Should
228 # not submit change to p4 (git diff should show deltas).
229 test_expect_success 'refuse to preserve users without perms' '
230         "$GITP4" clone --dest="$git" //depot &&
231         test_when_finished cleanup_git &&
232         (
233                 cd "$git" &&
234                 git config git-p4.skipSubmitEditCheck true &&
235                 echo "username-noperms: a change by alice" >>file1 &&
236                 git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
237                 P4EDITOR=touch P4USER=bob P4PASSWD=secret &&
238                 export P4EDITOR P4USER P4PASSWD &&
239                 test_must_fail "$GITP4" commit --preserve-user &&
240                 ! git diff --exit-code HEAD..p4/master
241         )
242 '
243
244 # What happens with unknown author? Without allowMissingP4Users it should fail.
245 test_expect_success 'preserve user where author is unknown to p4' '
246         "$GITP4" clone --dest="$git" //depot &&
247         test_when_finished cleanup_git &&
248         (
249                 cd "$git" &&
250                 git config git-p4.skipSubmitEditCheck true &&
251                 echo "username-bob: a change by bob" >>file1 &&
252                 git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 &&
253                 echo "username-unknown: a change by charlie" >>file1 &&
254                 git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 &&
255                 P4EDITOR=touch P4USER=alice P4PASSWD=secret &&
256                 export P4EDITOR P4USER P4PASSWD &&
257                 test_must_fail "$GITP4" commit --preserve-user &&
258                 ! git diff --exit-code HEAD..p4/master &&
259
260                 echo "$0: repeat with allowMissingP4Users enabled" &&
261                 git config git-p4.allowMissingP4Users true &&
262                 git config git-p4.preserveUser true &&
263                 "$GITP4" commit &&
264                 git diff --exit-code HEAD..p4/master &&
265                 p4_check_commit_author file1 alice
266         )
267 '
268
269 # If we're *not* using --preserve-user, git-p4 should warn if we're submitting
270 # changes that are not all ours.
271 # Test: user in p4 and user unknown to p4.
272 # Test: warning disabled and user is the same.
273 test_expect_success 'not preserving user with mixed authorship' '
274         "$GITP4" clone --dest="$git" //depot &&
275         test_when_finished cleanup_git &&
276         (
277                 cd "$git" &&
278                 git config git-p4.skipSubmitEditCheck true &&
279                 p4_add_user derek Derek &&
280
281                 make_change_by_user usernamefile3 Derek derek@localhost &&
282                 P4EDITOR=cat P4USER=alice P4PASSWD=secret &&
283                 export P4EDITOR P4USER P4PASSWD &&
284                 "$GITP4" commit |\
285                 grep "git author derek@localhost does not match" &&
286
287                 make_change_by_user usernamefile3 Charlie charlie@localhost &&
288                 "$GITP4" commit |\
289                 grep "git author charlie@localhost does not match" &&
290
291                 make_change_by_user usernamefile3 alice alice@localhost &&
292                 "$GITP4" commit |\
293                 test_must_fail grep "git author.*does not match" &&
294
295                 git config git-p4.skipUserNameCheck true &&
296                 make_change_by_user usernamefile3 Charlie charlie@localhost &&
297                 "$GITP4" commit |\
298                 test_must_fail grep "git author.*does not match" &&
299
300                 p4_check_commit_author usernamefile3 alice
301         )
302 '
303
304 marshal_dump() {
305         what=$1
306         "$PYTHON_PATH" -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]'
307 }
308
309 # Sleep a bit so that the top-most p4 change did not happen "now".  Then
310 # import the repo and make sure that the initial import has the same time
311 # as the top-most change.
312 test_expect_success 'initial import time from top change time' '
313         p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) &&
314         p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) &&
315         sleep 3 &&
316         "$GITP4" clone --dest="$git" //depot &&
317         test_when_finished cleanup_git &&
318         (
319                 cd "$git" &&
320                 gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
321                 echo $p4time $gittime &&
322                 test $p4time = $gittime
323         )
324 '
325
326 # Rename a file and confirm that rename is not detected in P4.
327 # Rename the new file again with detectRenames option enabled and confirm that
328 # this is detected in P4.
329 # Rename the new file again adding an extra line, configure a big threshold in
330 # detectRenames and confirm that rename is not detected in P4.
331 # Repeat, this time with a smaller threshold and confirm that the rename is
332 # detected in P4.
333 test_expect_success 'detect renames' '
334         "$GITP4" clone --dest="$git" //depot@all &&
335         test_when_finished cleanup_git &&
336         (
337                 cd "$git" &&
338                 git config git-p4.skipSubmitEditCheck true &&
339
340                 git mv file1 file4 &&
341                 git commit -a -m "Rename file1 to file4" &&
342                 git diff-tree -r -M HEAD &&
343                 "$GITP4" submit &&
344                 p4 filelog //depot/file4 &&
345                 p4 filelog //depot/file4 | test_must_fail grep -q "branch from" &&
346
347                 git mv file4 file5 &&
348                 git commit -a -m "Rename file4 to file5" &&
349                 git diff-tree -r -M HEAD &&
350                 git config git-p4.detectRenames true &&
351                 "$GITP4" submit &&
352                 p4 filelog //depot/file5 &&
353                 p4 filelog //depot/file5 | grep -q "branch from //depot/file4" &&
354
355                 git mv file5 file6 &&
356                 echo update >>file6 &&
357                 git add file6 &&
358                 git commit -a -m "Rename file5 to file6 with changes" &&
359                 git diff-tree -r -M HEAD &&
360                 level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
361                 test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
362                 git config git-p4.detectRenames $(($level + 2)) &&
363                 "$GITP4" submit &&
364                 p4 filelog //depot/file6 &&
365                 p4 filelog //depot/file6 | test_must_fail grep -q "branch from" &&
366
367                 git mv file6 file7 &&
368                 echo update >>file7 &&
369                 git add file7 &&
370                 git commit -a -m "Rename file6 to file7 with changes" &&
371                 git diff-tree -r -M HEAD &&
372                 level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
373                 test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
374                 git config git-p4.detectRenames $(($level - 2)) &&
375                 "$GITP4" submit &&
376                 p4 filelog //depot/file7 &&
377                 p4 filelog //depot/file7 | grep -q "branch from //depot/file6"
378         )
379 '
380
381 # Copy a file and confirm that copy is not detected in P4.
382 # Copy a file with detectCopies option enabled and confirm that copy is not
383 # detected in P4.
384 # Modify and copy a file with detectCopies option enabled and confirm that copy
385 # is detected in P4.
386 # Copy a file with detectCopies and detectCopiesHarder options enabled and
387 # confirm that copy is detected in P4.
388 # Modify and copy a file, configure a bigger threshold in detectCopies and
389 # confirm that copy is not detected in P4.
390 # Modify and copy a file, configure a smaller threshold in detectCopies and
391 # confirm that copy is detected in P4.
392 test_expect_success 'detect copies' '
393         "$GITP4" clone --dest="$git" //depot@all &&
394         test_when_finished cleanup_git &&
395         (
396                 cd "$git" &&
397                 git config git-p4.skipSubmitEditCheck true &&
398
399                 cp file2 file8 &&
400                 git add file8 &&
401                 git commit -a -m "Copy file2 to file8" &&
402                 git diff-tree -r -C HEAD &&
403                 "$GITP4" submit &&
404                 p4 filelog //depot/file8 &&
405                 p4 filelog //depot/file8 | test_must_fail grep -q "branch from" &&
406
407                 cp file2 file9 &&
408                 git add file9 &&
409                 git commit -a -m "Copy file2 to file9" &&
410                 git diff-tree -r -C HEAD &&
411                 git config git-p4.detectCopies true &&
412                 "$GITP4" submit &&
413                 p4 filelog //depot/file9 &&
414                 p4 filelog //depot/file9 | test_must_fail grep -q "branch from" &&
415
416                 echo "file2" >>file2 &&
417                 cp file2 file10 &&
418                 git add file2 file10 &&
419                 git commit -a -m "Modify and copy file2 to file10" &&
420                 git diff-tree -r -C HEAD &&
421                 "$GITP4" submit &&
422                 p4 filelog //depot/file10 &&
423                 p4 filelog //depot/file10 | grep -q "branch from //depot/file" &&
424
425                 cp file2 file11 &&
426                 git add file11 &&
427                 git commit -a -m "Copy file2 to file11" &&
428                 git diff-tree -r -C --find-copies-harder HEAD &&
429                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
430                 test "$src" = file10 &&
431                 git config git-p4.detectCopiesHarder true &&
432                 "$GITP4" submit &&
433                 p4 filelog //depot/file11 &&
434                 p4 filelog //depot/file11 | grep -q "branch from //depot/file" &&
435
436                 cp file2 file12 &&
437                 echo "some text" >>file12 &&
438                 git add file12 &&
439                 git commit -a -m "Copy file2 to file12 with changes" &&
440                 git diff-tree -r -C --find-copies-harder HEAD &&
441                 level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
442                 test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
443                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
444                 test "$src" = file10 &&
445                 git config git-p4.detectCopies $(($level + 2)) &&
446                 "$GITP4" submit &&
447                 p4 filelog //depot/file12 &&
448                 p4 filelog //depot/file12 | test_must_fail grep -q "branch from" &&
449
450                 cp file2 file13 &&
451                 echo "different text" >>file13 &&
452                 git add file13 &&
453                 git commit -a -m "Copy file2 to file13 with changes" &&
454                 git diff-tree -r -C --find-copies-harder HEAD &&
455                 level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
456                 test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
457                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
458                 test "$src" = file10 &&
459                 git config git-p4.detectCopies $(($level - 2)) &&
460                 "$GITP4" submit &&
461                 p4 filelog //depot/file13 &&
462                 p4 filelog //depot/file13 | grep -q "branch from //depot/file"
463         )
464 '
465
466 test_expect_success 'kill p4d' '
467         kill_p4d
468 '
469
470 test_done