Imported Upstream version 2.5.1
[scm/test.git] / t / t-migrate-export.sh
1 #!/usr/bin/env bash
2
3 . "$(dirname "$0")/fixtures/migrate.sh"
4 . "$(dirname "$0")/testlib.sh"
5
6 begin_test "migrate export (default branch)"
7 (
8   set -e
9
10   setup_multiple_local_branches_tracked
11
12   # Add b.md, a pointer existing only on master
13   base64 < /dev/urandom | head -c 160 > b.md
14   git add b.md
15   git commit -m "add b.md"
16
17   md_oid="$(calc_oid "$(cat a.md)")"
18   txt_oid="$(calc_oid "$(cat a.txt)")"
19   b_md_oid="$(calc_oid "$(cat b.md)")"
20
21   git checkout my-feature
22   md_feature_oid="$(calc_oid "$(cat a.md)")"
23   git checkout master
24
25   assert_pointer "refs/heads/master" "a.md" "$md_oid" "140"
26   assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "120"
27   assert_pointer "refs/heads/master" "b.md" "$b_md_oid" "160"
28   assert_pointer "refs/heads/my-feature" "a.md" "$md_feature_oid" "30"
29
30   git lfs migrate export --include="*.md, *.txt"
31
32   refute_pointer "refs/heads/master" "a.md"
33   refute_pointer "refs/heads/master" "a.txt"
34   refute_pointer "refs/heads/master" "b.md"
35   assert_pointer "refs/heads/my-feature" "a.md" "$md_feature_oid" "30"
36
37   # b.md should be pruned as no pointer exists to reference it
38   refute_local_object "$b_md_oid" "160"
39
40   # Other objects should not be pruned as they're still referenced in `feature`
41   # by pointers
42   assert_local_object "$md_oid" "140"
43   assert_local_object "$txt_oid" "120"
44   assert_local_object "$md_feature_oid" "30"
45
46   master="$(git rev-parse refs/heads/master)"
47   feature="$(git rev-parse refs/heads/my-feature)"
48
49   master_attrs="$(git cat-file -p "$master:.gitattributes")"
50   feature_attrs="$(git cat-file -p "$feature:.gitattributes")"
51
52   echo "$master_attrs" | grep -q "*.md text !filter !merge !diff"
53   echo "$master_attrs" | grep -q "*.txt text !filter !merge !diff"
54
55   [ ! $(echo "$feature_attrs" | grep -q "*.md text !filter !merge !diff") ]
56   [ ! $(echo "$feature_attrs" | grep -q "*.txt text !filter !merge !diff") ]
57 )
58 end_test
59
60 begin_test "migrate export (with remote)"
61 (
62   set -e
63
64   setup_single_remote_branch_tracked
65
66   git push origin master
67
68   md_oid="$(calc_oid "$(cat a.md)")"
69   txt_oid="$(calc_oid "$(cat a.txt)")"
70
71   assert_pointer "refs/heads/master" "a.md" "$md_oid" "50"
72   assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "30"
73
74   assert_pointer "refs/remotes/origin/master" "a.md" "$md_oid" "50"
75   assert_pointer "refs/remotes/origin/master" "a.txt" "$txt_oid" "30"
76
77   # Flush the cache to ensure all objects have to be downloaded
78   rm -rf .git/lfs/objects
79
80   git lfs migrate export --everything --include="*.md, *.txt"
81
82   refute_pointer "refs/heads/master" "a.md"
83   refute_pointer "refs/heads/master" "a.txt"
84
85   # All pointers have been exported, so all objects should be pruned
86   refute_local_object "$md_oid" "50"
87   refute_local_object "$txt_oid" "30"
88
89   master="$(git rev-parse refs/heads/master)"
90   master_attrs="$(git cat-file -p "$master:.gitattributes")"
91
92   echo "$master_attrs" | grep -q "*.md text !filter !merge !diff"
93   echo "$master_attrs" | grep -q "*.txt text !filter !merge !diff"
94 )
95 end_test
96
97 begin_test "migrate export (include/exclude args)"
98 (
99   set -e
100
101   setup_single_local_branch_tracked
102
103   md_oid="$(calc_oid "$(cat a.md)")"
104   txt_oid="$(calc_oid "$(cat a.txt)")"
105
106   assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "120"
107   assert_pointer "refs/heads/master" "a.md" "$md_oid" "140"
108
109   git lfs migrate export --include="*" --exclude="a.md"
110
111   refute_pointer "refs/heads/master" "a.txt"
112   assert_pointer "refs/heads/master" "a.md" "$md_oid" "140"
113
114   refute_local_object "$txt_oid" "120"
115   assert_local_object "$md_oid" "140"
116
117   master="$(git rev-parse refs/heads/master)"
118
119   master_attrs="$(git cat-file -p "$master:.gitattributes")"
120
121   echo "$master_attrs" | grep -q "* text !filter !merge !diff"
122   echo "$master_attrs" | grep -q "a.md filter=lfs diff=lfs merge=lfs"
123 )
124 end_test
125
126 begin_test "migrate export (bare repository)"
127 (
128   set -e
129
130   setup_single_remote_branch_tracked
131   git push origin master
132
133   md_oid="$(calc_oid "$(cat a.md)")"
134   txt_oid="$(calc_oid "$(cat a.txt)")"
135
136   make_bare
137
138   assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "30"
139   assert_pointer "refs/heads/master" "a.md" "$md_oid" "50"
140
141   git lfs migrate export --everything --include="*"
142
143   refute_pointer "refs/heads/master" "a.md"
144   refute_pointer "refs/heads/master" "a.txt"
145
146   # All pointers have been exported, so all objects should be pruned
147   refute_local_object "$md_oid" "50"
148   refute_local_object "$txt_oid" "30"
149 )
150 end_test
151
152 begin_test "migrate export (given branch)"
153 (
154   set -e
155
156   setup_multiple_local_branches_tracked
157
158   md_oid="$(calc_oid "$(cat a.md)")"
159   txt_oid="$(calc_oid "$(cat a.txt)")"
160
161   git checkout my-feature
162   md_feature_oid="$(calc_oid "$(cat a.md)")"
163   git checkout master
164
165   assert_pointer "refs/heads/my-feature" "a.md" "$md_feature_oid" "30"
166   assert_pointer "refs/heads/my-feature" "a.txt" "$txt_oid" "120"
167   assert_pointer "refs/heads/master" "a.md" "$md_oid" "140"
168   assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "120"
169
170   git lfs migrate export --include="*.md,*.txt" my-feature
171
172   refute_pointer "refs/heads/my-feature" "a.md"
173   refute_pointer "refs/heads/my-feature" "a.txt"
174   refute_pointer "refs/heads/master" "a.md"
175   refute_pointer "refs/heads/master" "a.txt"
176
177   # No pointers left, so all objects should be pruned
178   refute_local_object "$md_feature_oid" "30"
179   refute_local_object "$txt_oid" "120"
180   refute_local_object "$md_oid" "140"
181
182   master="$(git rev-parse refs/heads/master)"
183   feature="$(git rev-parse refs/heads/my-feature)"
184
185   master_attrs="$(git cat-file -p "$master:.gitattributes")"
186   feature_attrs="$(git cat-file -p "$feature:.gitattributes")"
187
188   echo "$master_attrs" | grep -q "*.md text !filter !merge !diff"
189   echo "$master_attrs" | grep -q "*.txt text !filter !merge !diff"
190   echo "$feature_attrs" | grep -q "*.md text !filter !merge !diff"
191   echo "$feature_attrs" | grep -q "*.txt text !filter !merge !diff"
192 )
193 end_test
194
195 begin_test "migrate export (no filter)"
196 (
197   set -e
198
199   setup_multiple_local_branches_tracked
200
201   git lfs migrate export --yes 2>&1 | tee migrate.log
202   if [ ${PIPESTATUS[0]} -eq 0 ]; then
203     echo >&2 "fatal: expected git lfs migrate export to fail, didn't"
204     exit 1
205   fi
206
207   grep "fatal: one or more files must be specified with --include" migrate.log
208 )
209 end_test
210
211 begin_test "migrate export (exclude remote refs)"
212 (
213   set -e
214
215   setup_single_remote_branch_tracked
216
217   md_oid="$(calc_oid "$(cat a.md)")"
218   txt_oid="$(calc_oid "$(cat a.txt)")"
219
220   git checkout refs/remotes/origin/master
221   md_remote_oid="$(calc_oid "$(cat a.md)")"
222   txt_remote_oid="$(calc_oid "$(cat a.txt)")"
223   git checkout master
224
225   assert_pointer "refs/heads/master" "a.md" "$md_oid" "50"
226   assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "30"
227
228   assert_pointer "refs/remotes/origin/master" "a.md" "$md_remote_oid" "140"
229   assert_pointer "refs/remotes/origin/master" "a.txt" "$txt_remote_oid" "120"
230
231   git lfs migrate export --include="*.md,*.txt"
232
233   refute_pointer "refs/heads/master" "a.md"
234   refute_pointer "refs/heads/master" "a.txt"
235
236   refute_local_object "$md_oid" "50"
237   refute_local_object "$txt_oid" "30"
238
239   assert_pointer "refs/remotes/origin/master" "a.md" "$md_remote_oid" "140"
240   assert_pointer "refs/remotes/origin/master" "a.txt" "$txt_remote_oid" "120"
241
242   # Since these two objects exist on the remote, they should be removed with
243   # our prune operation
244   refute_local_object "$md_remote_oid" "140"
245   refute_local_object "$txt_remote_oid" "120"
246
247   master="$(git rev-parse refs/heads/master)"
248   remote="$(git rev-parse refs/remotes/origin/master)"
249
250   master_attrs="$(git cat-file -p "$master:.gitattributes")"
251   remote_attrs="$(git cat-file -p "$remote:.gitattributes")"
252
253   echo "$master_attrs" | grep -q "*.md text !filter !merge !diff"
254   echo "$master_attrs" | grep -q "*.txt text !filter !merge !diff"
255
256   [ ! $(echo "$remote_attrs" | grep -q "*.md text !filter !merge !diff") ]
257   [ ! $(echo "$remote_attrs" | grep -q "*.txt text !filter !merge !diff") ]
258 )
259 end_test
260
261 begin_test "migrate export (--skip-fetch)"
262 (
263   set -e
264
265   setup_single_remote_branch_tracked
266
267   md_master_oid="$(calc_oid "$(cat a.md)")"
268   txt_master_oid="$(calc_oid "$(cat a.txt)")"
269
270   git checkout refs/remotes/origin/master
271   md_remote_oid="$(calc_oid "$(cat a.md)")"
272   txt_remote_oid="$(calc_oid "$(cat a.txt)")"
273   git checkout master
274
275   git tag pseudo-remote "$(git rev-parse refs/remotes/origin/master)"
276   # Remove the refs/remotes/origin/master ref, and instruct 'git lfs migrate' to
277   # not fetch it.
278   git update-ref -d refs/remotes/origin/master
279
280   assert_pointer "refs/heads/master" "a.md" "$md_master_oid" "50"
281   assert_pointer "pseudo-remote" "a.md" "$md_remote_oid" "140"
282   assert_pointer "refs/heads/master" "a.txt" "$txt_master_oid" "30"
283   assert_pointer "pseudo-remote" "a.txt" "$txt_remote_oid" "120"
284
285   git lfs migrate export --skip-fetch --include="*.md,*.txt"
286
287   refute_pointer "refs/heads/master" "a.md"
288   refute_pointer "pseudo-remote" "a.md"
289   refute_pointer "refs/heads/master" "a.txt"
290   refute_pointer "pseudo-remote" "a.txt"
291
292   refute_local_object "$md_master_oid" "50"
293   refute_local_object "$md_remote_oid" "140"
294   refute_local_object "$txt_master_oid" "30"
295   refute_local_object "$txt_remote_oid" "120"
296
297   master="$(git rev-parse refs/heads/master)"
298   remote="$(git rev-parse pseudo-remote)"
299
300   master_attrs="$(git cat-file -p "$master:.gitattributes")"
301   remote_attrs="$(git cat-file -p "$remote:.gitattributes")"
302
303   echo "$master_attrs" | grep -q "*.md text !filter !merge !diff"
304   echo "$master_attrs" | grep -q "*.txt text !filter !merge !diff"
305   echo "$remote_attrs" | grep -q "*.md text !filter !merge !diff"
306   echo "$remote_attrs" | grep -q "*.txt text !filter !merge !diff"
307 )
308 end_test
309
310 begin_test "migrate export (include/exclude ref)"
311 (
312   set -e
313
314   setup_multiple_remote_branches_gitattrs
315
316   md_master_oid="$(calc_oid "$(cat a.md)")"
317   txt_master_oid="$(calc_oid "$(cat a.txt)")"
318
319   git checkout refs/remotes/origin/master
320   md_remote_oid="$(calc_oid "$(cat a.md)")"
321   txt_remote_oid="$(calc_oid "$(cat a.txt)")"
322
323   git checkout my-feature
324   md_feature_oid="$(calc_oid "$(cat a.md)")"
325   txt_feature_oid="$(calc_oid "$(cat a.txt)")"
326
327   git checkout master
328
329   git lfs migrate export \
330     --include="*.txt" \
331     --include-ref=refs/heads/my-feature \
332     --exclude-ref=refs/heads/master
333
334   assert_pointer "refs/heads/master" "a.md" "$md_master_oid" "21"
335   assert_pointer "refs/heads/master" "a.txt" "$txt_master_oid" "20"
336
337   assert_pointer "refs/remotes/origin/master" "a.md" "$md_remote_oid" "11"
338   assert_pointer "refs/remotes/origin/master" "a.txt" "$txt_remote_oid" "10"
339
340   assert_pointer "refs/heads/my-feature" "a.md" "$md_feature_oid" "31"
341   refute_pointer "refs/heads/my-feature" "a.txt"
342
343   # Master objects should not be pruned as they exist in unpushed commits
344   assert_local_object "$md_master_oid" "21"
345   assert_local_object "$txt_master_oid" "20"
346
347   # Remote master objects should be pruned as they exist in the remote
348   refute_local_object "$md_remote_oid" "11"
349   refute_local_object "$txt_remote_oid" "10"
350
351   # txt_feature_oid should be pruned as it's no longer a pointer, but
352   # md_feature_oid should remain as it's still a pointer in unpushed commits
353   assert_local_object "$md_feature_oid" "31"
354   refute_local_object "$txt_feature_oid" "30"
355
356   master="$(git rev-parse refs/heads/master)"
357   feature="$(git rev-parse refs/heads/my-feature)"
358   remote="$(git rev-parse refs/remotes/origin/master)"
359
360   master_attrs="$(git cat-file -p "$master:.gitattributes")"
361   remote_attrs="$(git cat-file -p "$remote:.gitattributes")"
362   feature_attrs="$(git cat-file -p "$feature:.gitattributes")"
363
364   [ ! $(echo "$master_attrs" | grep -q "*.txt text !filter !merge !diff") ]
365   [ ! $(echo "$remote_attrs" | grep -q "*.txt text !filter !merge !diff") ]
366   echo "$feature_attrs" | grep -q "*.txt text !filter !merge !diff"
367 )
368 end_test
369
370 begin_test "migrate export (--object-map)"
371 (
372   set -e
373
374   setup_multiple_local_branches_tracked
375
376   output_dir=$(mktemp -d)
377
378   git log --all --pretty='format:%H' > "${output_dir}/old_sha.txt"
379   git lfs migrate export --everything --include="*" --object-map "${output_dir}/object-map.txt"
380   git log --all --pretty='format:%H' > "${output_dir}/new_sha.txt"
381   paste -d',' "${output_dir}/old_sha.txt" "${output_dir}/new_sha.txt" > "${output_dir}/expected-map.txt"
382
383   diff -u <(sort "${output_dir}/expected-map.txt") <(sort "${output_dir}/object-map.txt")
384 )
385 end_test
386
387 begin_test "migrate export (--verbose)"
388 (
389   set -e
390
391   setup_multiple_local_branches_tracked
392
393   git lfs migrate export --everything --include="*" --verbose 2>&1 | grep -q "migrate: commit "
394 )
395 end_test
396
397 begin_test "migrate export (--remote)"
398 (
399   set -e
400
401   setup_single_remote_branch_tracked
402
403   git push origin master
404
405   md_oid="$(calc_oid "$(cat a.md)")"
406   txt_oid="$(calc_oid "$(cat a.txt)")"
407
408   assert_pointer "refs/heads/master" "a.md" "$md_oid" "50"
409   assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "30"
410
411   # Flush the cache to ensure all objects have to be downloaded
412   rm -rf .git/lfs/objects
413
414   # Setup a new remote and invalidate the default
415   remote_url="$(git config --get remote.origin.url)"
416   git remote add zeta "$remote_url"
417   git remote set-url origin ""
418
419   git lfs migrate export --everything --remote="zeta" --include="*.md, *.txt"
420
421   refute_pointer "refs/heads/master" "a.md"
422   refute_pointer "refs/heads/master" "a.txt"
423
424   refute_local_object "$md_oid" "50"
425   refute_local_object "$txt_oid" "30"
426 )
427 end_test
428
429 begin_test "migrate export (invalid --remote)"
430 (
431   set -e
432
433   setup_single_remote_branch_tracked
434
435   git lfs migrate export --include="*" --remote="zz" --yes 2>&1 \
436     | tee migrate.log
437   if [ ${PIPESTATUS[0]} -eq 0 ]; then
438     echo >&2 "fatal: expected git lfs migrate export to fail, didn't"
439     exit 1
440   fi
441
442   grep "fatal: invalid remote zz provided" migrate.log
443 )
444 end_test