Merge branch 'sb/doc-config-submodule-update'
[git] / t / t6501-freshen-objects.sh
1 #!/bin/sh
2 #
3 # This test covers the handling of objects which might have old
4 # mtimes in the filesystem (because they were used previously)
5 # and are just now becoming referenced again.
6 #
7 # We're going to do two things that are a little bit "fake" to
8 # help make our simulation easier:
9 #
10 #   1. We'll turn off reflogs. You can still run into
11 #      problems with reflogs on, but your objects
12 #      don't get pruned until both the reflog expiration
13 #      has passed on their references, _and_ they are out
14 #      of prune's expiration period. Dropping reflogs
15 #      means we only have to deal with one variable in our tests,
16 #      but the results generalize.
17 #
18 #   2. We'll use a temporary index file to create our
19 #      works-in-progress. Most workflows would mention
20 #      referenced objects in the index, which prune takes
21 #      into account. However, many operations don't. For
22 #      example, a partial commit with "git commit foo"
23 #      will use a temporary index. Or they may not need
24 #      an index at all (e.g., creating a new commit
25 #      to refer to an existing tree).
26
27 test_description='check pruning of dependent objects'
28 . ./test-lib.sh
29
30 # We care about reachability, so we do not want to use
31 # the normal test_commit, which creates extra tags.
32 add () {
33         echo "$1" >"$1" &&
34         git add "$1"
35 }
36 commit () {
37         test_tick &&
38         add "$1" &&
39         git commit -m "$1"
40 }
41
42 maybe_repack () {
43         if test -n "$repack"; then
44                 git repack -ad
45         fi
46 }
47
48 for repack in '' true; do
49         title=${repack:+repack}
50         title=${title:-loose}
51
52         test_expect_success "make repo completely empty ($title)" '
53                 rm -rf .git &&
54                 git init
55         '
56
57         test_expect_success "disable reflogs ($title)" '
58                 git config core.logallrefupdates false &&
59                 git reflog expire --expire=all --all
60         '
61
62         test_expect_success "setup basic history ($title)" '
63                 commit base
64         '
65
66         test_expect_success "create and abandon some objects ($title)" '
67                 git checkout -b experiment &&
68                 commit abandon &&
69                 maybe_repack &&
70                 git checkout master &&
71                 git branch -D experiment
72         '
73
74         test_expect_success "simulate time passing ($title)" '
75                 find .git/objects -type f |
76                 xargs test-chmtime -v -86400
77         '
78
79         test_expect_success "start writing new commit with old blob ($title)" '
80                 tree=$(
81                         GIT_INDEX_FILE=index.tmp &&
82                         export GIT_INDEX_FILE &&
83                         git read-tree HEAD &&
84                         add unrelated &&
85                         add abandon &&
86                         git write-tree
87                 )
88         '
89
90         test_expect_success "simultaneous gc ($title)" '
91                 git gc --prune=12.hours.ago
92         '
93
94         test_expect_success "finish writing out commit ($title)" '
95                 commit=$(echo foo | git commit-tree -p HEAD $tree) &&
96                 git update-ref HEAD $commit
97         '
98
99         # "abandon" blob should have been rescued by reference from new tree
100         test_expect_success "repository passes fsck ($title)" '
101                 git fsck
102         '
103
104         test_expect_success "abandon objects again ($title)" '
105                 git reset --hard HEAD^ &&
106                 find .git/objects -type f |
107                 xargs test-chmtime -v -86400
108         '
109
110         test_expect_success "start writing new commit with same tree ($title)" '
111                 tree=$(
112                         GIT_INDEX_FILE=index.tmp &&
113                         export GIT_INDEX_FILE &&
114                         git read-tree HEAD &&
115                         add abandon &&
116                         add unrelated &&
117                         git write-tree
118                 )
119         '
120
121         test_expect_success "simultaneous gc ($title)" '
122                 git gc --prune=12.hours.ago
123         '
124
125         # tree should have been refreshed by write-tree
126         test_expect_success "finish writing out commit ($title)" '
127                 commit=$(echo foo | git commit-tree -p HEAD $tree) &&
128                 git update-ref HEAD $commit
129         '
130 done
131
132 test_expect_success 'do not complain about existing broken links (commit)' '
133         cat >broken-commit <<-\EOF &&
134         tree 0000000000000000000000000000000000000001
135         parent 0000000000000000000000000000000000000002
136         author whatever <whatever@example.com> 1234 -0000
137         committer whatever <whatever@example.com> 1234 -0000
138
139         some message
140         EOF
141         commit=$(git hash-object -t commit -w broken-commit) &&
142         git gc 2>stderr &&
143         verbose git cat-file -e $commit &&
144         test_must_be_empty stderr
145 '
146
147 test_expect_success 'do not complain about existing broken links (tree)' '
148         cat >broken-tree <<-\EOF &&
149         100644 blob 0000000000000000000000000000000000000003    foo
150         EOF
151         tree=$(git mktree --missing <broken-tree) &&
152         git gc 2>stderr &&
153         git cat-file -e $tree &&
154         test_must_be_empty stderr
155 '
156
157 test_expect_success 'do not complain about existing broken links (tag)' '
158         cat >broken-tag <<-\EOF &&
159         object 0000000000000000000000000000000000000004
160         type commit
161         tag broken
162         tagger whatever <whatever@example.com> 1234 -0000
163
164         this is a broken tag
165         EOF
166         tag=$(git hash-object -t tag -w broken-tag) &&
167         git gc 2>stderr &&
168         git cat-file -e $tag &&
169         test_must_be_empty stderr
170 '
171
172 test_done