Merge branch 'rr/misc-fixes'
[git] / t / t9800-git-p4.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 'exit when p4 fails to produce marshaled output' '
69         badp4dir="$TRASH_DIRECTORY/badp4dir" &&
70         mkdir "$badp4dir" &&
71         test_when_finished "rm \"$badp4dir/p4\" && rmdir \"$badp4dir\"" &&
72         cat >"$badp4dir"/p4 <<-EOF &&
73         #!$SHELL_PATH
74         exit 1
75         EOF
76         chmod 755 "$badp4dir"/p4 &&
77         PATH="$badp4dir:$PATH" "$GITP4" clone --dest="$git" //depot >errs 2>&1 ; retval=$? &&
78         test $retval -eq 1 &&
79         test_must_fail grep -q Traceback errs
80 '
81
82 test_expect_success 'add p4 files with wildcards in the names' '
83         (
84                 cd "$cli" &&
85                 echo file-wild-hash >file-wild#hash &&
86                 echo file-wild-star >file-wild\*star &&
87                 echo file-wild-at >file-wild@at &&
88                 echo file-wild-percent >file-wild%percent &&
89                 p4 add -f file-wild* &&
90                 p4 submit -d "file wildcards"
91         )
92 '
93
94 test_expect_success 'wildcard files git-p4 clone' '
95         "$GITP4" clone --dest="$git" //depot &&
96         test_when_finished cleanup_git &&
97         (
98                 cd "$git" &&
99                 test -f file-wild#hash &&
100                 test -f file-wild\*star &&
101                 test -f file-wild@at &&
102                 test -f file-wild%percent
103         )
104 '
105
106 test_expect_success 'clone bare' '
107         "$GITP4" clone --dest="$git" --bare //depot &&
108         test_when_finished cleanup_git &&
109         (
110                 cd "$git" &&
111                 test ! -d .git &&
112                 bare=`git config --get core.bare` &&
113                 test "$bare" = true
114         )
115 '
116
117 p4_add_user() {
118         name=$1 fullname=$2 &&
119         p4 user -f -i <<-EOF &&
120         User: $name
121         Email: $name@localhost
122         FullName: $fullname
123         EOF
124         p4 passwd -P secret $name
125 }
126
127 p4_grant_admin() {
128         name=$1 &&
129         {
130                 p4 protect -o &&
131                 echo "    admin user $name * //depot/..."
132         } | p4 protect -i
133 }
134
135 p4_check_commit_author() {
136         file=$1 user=$2 &&
137         p4 changes -m 1 //depot/$file | grep -q $user
138 }
139
140 make_change_by_user() {
141         file=$1 name=$2 email=$3 &&
142         echo "username: a change by $name" >>"$file" &&
143         git add "$file" &&
144         git commit --author "$name <$email>" -m "a change by $name"
145 }
146
147 # Test username support, submitting as user 'alice'
148 test_expect_success 'preserve users' '
149         p4_add_user alice Alice &&
150         p4_add_user bob Bob &&
151         p4_grant_admin alice &&
152         "$GITP4" clone --dest="$git" //depot &&
153         test_when_finished cleanup_git &&
154         (
155                 cd "$git" &&
156                 echo "username: a change by alice" >>file1 &&
157                 echo "username: a change by bob" >>file2 &&
158                 git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 &&
159                 git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 &&
160                 git config git-p4.skipSubmitEditCheck true &&
161                 P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user &&
162                 p4_check_commit_author file1 alice &&
163                 p4_check_commit_author file2 bob
164         )
165 '
166
167 # Test username support, submitting as bob, who lacks admin rights. Should
168 # not submit change to p4 (git diff should show deltas).
169 test_expect_success 'refuse to preserve users without perms' '
170         "$GITP4" clone --dest="$git" //depot &&
171         test_when_finished cleanup_git &&
172         (
173                 cd "$git" &&
174                 git config git-p4.skipSubmitEditCheck true &&
175                 echo "username-noperms: a change by alice" >>file1 &&
176                 git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
177                 P4EDITOR=touch P4USER=bob P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user &&
178                 test_must_fail git diff --exit-code HEAD..p4/master
179         )
180 '
181
182 # What happens with unknown author? Without allowMissingP4Users it should fail.
183 test_expect_success 'preserve user where author is unknown to p4' '
184         "$GITP4" clone --dest="$git" //depot &&
185         test_when_finished cleanup_git &&
186         (
187                 cd "$git" &&
188                 git config git-p4.skipSubmitEditCheck true &&
189                 echo "username-bob: a change by bob" >>file1 &&
190                 git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 &&
191                 echo "username-unknown: a change by charlie" >>file1 &&
192                 git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 &&
193                 P4EDITOR=touch P4USER=alice P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user &&
194                 test_must_fail git diff --exit-code HEAD..p4/master &&
195
196                 echo "$0: repeat with allowMissingP4Users enabled" &&
197                 git config git-p4.allowMissingP4Users true &&
198                 git config git-p4.preserveUser true &&
199                 P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit &&
200                 git diff --exit-code HEAD..p4/master &&
201                 p4_check_commit_author file1 alice
202         )
203 '
204
205 # If we're *not* using --preserve-user, git-p4 should warn if we're submitting
206 # changes that are not all ours.
207 # Test: user in p4 and user unknown to p4.
208 # Test: warning disabled and user is the same.
209 test_expect_success 'not preserving user with mixed authorship' '
210         "$GITP4" clone --dest="$git" //depot &&
211         test_when_finished cleanup_git &&
212         (
213                 cd "$git" &&
214                 git config git-p4.skipSubmitEditCheck true &&
215                 p4_add_user derek Derek &&
216
217                 make_change_by_user usernamefile3 Derek derek@localhost &&
218                 P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\
219                 grep "git author derek@localhost does not match" &&
220
221                 make_change_by_user usernamefile3 Charlie charlie@localhost &&
222                 P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\
223                 grep "git author charlie@localhost does not match" &&
224
225                 make_change_by_user usernamefile3 alice alice@localhost &&
226                 P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" |\
227                 test_must_fail grep "git author.*does not match" &&
228
229                 git config git-p4.skipUserNameCheck true &&
230                 make_change_by_user usernamefile3 Charlie charlie@localhost &&
231                 P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\
232                 test_must_fail grep "git author.*does not match" &&
233
234                 p4_check_commit_author usernamefile3 alice
235         )
236 '
237
238 marshal_dump() {
239         what=$1
240         "$PYTHON_PATH" -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]'
241 }
242
243 # Sleep a bit so that the top-most p4 change did not happen "now".  Then
244 # import the repo and make sure that the initial import has the same time
245 # as the top-most change.
246 test_expect_success 'initial import time from top change time' '
247         p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) &&
248         p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) &&
249         sleep 3 &&
250         "$GITP4" clone --dest="$git" //depot &&
251         test_when_finished cleanup_git &&
252         (
253                 cd "$git" &&
254                 gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
255                 echo $p4time $gittime &&
256                 test $p4time = $gittime
257         )
258 '
259
260 # Rename a file and confirm that rename is not detected in P4.
261 # Rename the new file again with detectRenames option enabled and confirm that
262 # this is detected in P4.
263 # Rename the new file again adding an extra line, configure a big threshold in
264 # detectRenames and confirm that rename is not detected in P4.
265 # Repeat, this time with a smaller threshold and confirm that the rename is
266 # detected in P4.
267 test_expect_success 'detect renames' '
268         "$GITP4" clone --dest="$git" //depot@all &&
269         test_when_finished cleanup_git &&
270         (
271                 cd "$git" &&
272                 git config git-p4.skipSubmitEditCheck true &&
273
274                 git mv file1 file4 &&
275                 git commit -a -m "Rename file1 to file4" &&
276                 git diff-tree -r -M HEAD &&
277                 "$GITP4" submit &&
278                 p4 filelog //depot/file4 &&
279                 p4 filelog //depot/file4 | test_must_fail grep -q "branch from" &&
280
281                 git mv file4 file5 &&
282                 git commit -a -m "Rename file4 to file5" &&
283                 git diff-tree -r -M HEAD &&
284                 git config git-p4.detectRenames true &&
285                 "$GITP4" submit &&
286                 p4 filelog //depot/file5 &&
287                 p4 filelog //depot/file5 | grep -q "branch from //depot/file4" &&
288
289                 git mv file5 file6 &&
290                 echo update >>file6 &&
291                 git add file6 &&
292                 git commit -a -m "Rename file5 to file6 with changes" &&
293                 git diff-tree -r -M HEAD &&
294                 level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
295                 test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
296                 git config git-p4.detectRenames $(($level + 2)) &&
297                 "$GITP4" submit &&
298                 p4 filelog //depot/file6 &&
299                 p4 filelog //depot/file6 | test_must_fail grep -q "branch from" &&
300
301                 git mv file6 file7 &&
302                 echo update >>file7 &&
303                 git add file7 &&
304                 git commit -a -m "Rename file6 to file7 with changes" &&
305                 git diff-tree -r -M HEAD &&
306                 level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
307                 test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
308                 git config git-p4.detectRenames $(($level - 2)) &&
309                 "$GITP4" submit &&
310                 p4 filelog //depot/file7 &&
311                 p4 filelog //depot/file7 | grep -q "branch from //depot/file6"
312         )
313 '
314
315 # Copy a file and confirm that copy is not detected in P4.
316 # Copy a file with detectCopies option enabled and confirm that copy is not
317 # detected in P4.
318 # Modify and copy a file with detectCopies option enabled and confirm that copy
319 # is detected in P4.
320 # Copy a file with detectCopies and detectCopiesHarder options enabled and
321 # confirm that copy is detected in P4.
322 # Modify and copy a file, configure a bigger threshold in detectCopies and
323 # confirm that copy is not detected in P4.
324 # Modify and copy a file, configure a smaller threshold in detectCopies and
325 # confirm that copy is detected in P4.
326 test_expect_success 'detect copies' '
327         "$GITP4" clone --dest="$git" //depot@all &&
328         test_when_finished cleanup_git &&
329         (
330                 cd "$git" &&
331                 git config git-p4.skipSubmitEditCheck true &&
332
333                 cp file2 file8 &&
334                 git add file8 &&
335                 git commit -a -m "Copy file2 to file8" &&
336                 git diff-tree -r -C HEAD &&
337                 "$GITP4" submit &&
338                 p4 filelog //depot/file8 &&
339                 p4 filelog //depot/file8 | test_must_fail grep -q "branch from" &&
340
341                 cp file2 file9 &&
342                 git add file9 &&
343                 git commit -a -m "Copy file2 to file9" &&
344                 git diff-tree -r -C HEAD &&
345                 git config git-p4.detectCopies true &&
346                 "$GITP4" submit &&
347                 p4 filelog //depot/file9 &&
348                 p4 filelog //depot/file9 | test_must_fail grep -q "branch from" &&
349
350                 echo "file2" >>file2 &&
351                 cp file2 file10 &&
352                 git add file2 file10 &&
353                 git commit -a -m "Modify and copy file2 to file10" &&
354                 git diff-tree -r -C HEAD &&
355                 "$GITP4" submit &&
356                 p4 filelog //depot/file10 &&
357                 p4 filelog //depot/file10 | grep -q "branch from //depot/file" &&
358
359                 cp file2 file11 &&
360                 git add file11 &&
361                 git commit -a -m "Copy file2 to file11" &&
362                 git diff-tree -r -C --find-copies-harder HEAD &&
363                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
364                 test "$src" = file10 &&
365                 git config git-p4.detectCopiesHarder true &&
366                 "$GITP4" submit &&
367                 p4 filelog //depot/file11 &&
368                 p4 filelog //depot/file11 | grep -q "branch from //depot/file" &&
369
370                 cp file2 file12 &&
371                 echo "some text" >>file12 &&
372                 git add file12 &&
373                 git commit -a -m "Copy file2 to file12 with changes" &&
374                 git diff-tree -r -C --find-copies-harder HEAD &&
375                 level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
376                 test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
377                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
378                 test "$src" = file10 &&
379                 git config git-p4.detectCopies $(($level + 2)) &&
380                 "$GITP4" submit &&
381                 p4 filelog //depot/file12 &&
382                 p4 filelog //depot/file12 | test_must_fail grep -q "branch from" &&
383
384                 cp file2 file13 &&
385                 echo "different text" >>file13 &&
386                 git add file13 &&
387                 git commit -a -m "Copy file2 to file13 with changes" &&
388                 git diff-tree -r -C --find-copies-harder HEAD &&
389                 level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
390                 test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
391                 src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
392                 test "$src" = file10 &&
393                 git config git-p4.detectCopies $(($level - 2)) &&
394                 "$GITP4" submit &&
395                 p4 filelog //depot/file13 &&
396                 p4 filelog //depot/file13 | grep -q "branch from //depot/file"
397         )
398 '
399
400 test_expect_success 'kill p4d' '
401         kill_p4d
402 '
403
404 test_done