Add several uses of get_object_hash.
[git/git.git] / walker.c
CommitLineData
4250a5e5 1#include "cache.h"
30ae764b 2#include "walker.h"
4250a5e5
DB
3#include "commit.h"
4#include "tree.h"
1bc995a3 5#include "tree-walk.h"
3173bd49
DB
6#include "tag.h"
7#include "blob.h"
cd541a68
DB
8#include "refs.h"
9
b2d62f16 10static unsigned char current_commit_sha1[20];
4250a5e5 11
30ae764b 12void walker_say(struct walker *walker, const char *fmt, const char *hex)
1e8be59d 13{
30ae764b 14 if (walker->get_verbosely)
e78d9772
JH
15 fprintf(stderr, fmt, hex);
16}
17
0d7a6e4e 18static void report_missing(const struct object *obj)
b2d62f16 19{
0d7a6e4e 20 fprintf(stderr, "Cannot obtain needed %s %s\n",
2b87d3a8
JK
21 obj->type ? typename(obj->type): "object",
22 sha1_to_hex(obj->sha1));
0d7a6e4e
AR
23 if (!is_null_sha1(current_commit_sha1))
24 fprintf(stderr, "while processing commit %s.\n",
25 sha1_to_hex(current_commit_sha1));
b2d62f16
JH
26}
27
30ae764b 28static int process(struct walker *walker, struct object *obj);
3173bd49 29
30ae764b 30static int process_tree(struct walker *walker, struct tree *tree)
4250a5e5 31{
1bc995a3 32 struct tree_desc desc;
4c068a98 33 struct name_entry entry;
4250a5e5
DB
34
35 if (parse_tree(tree))
36 return -1;
37
6fda5e51 38 init_tree_desc(&desc, tree->buffer, tree->size);
4c068a98 39 while (tree_entry(&desc, &entry)) {
6f9012b6
JH
40 struct object *obj = NULL;
41
582c7393 42 /* submodule commits are not stored in the superproject */
68fb4650 43 if (S_ISGITLINK(entry.mode))
582c7393 44 continue;
4c068a98
LT
45 if (S_ISDIR(entry.mode)) {
46 struct tree *tree = lookup_tree(entry.sha1);
6f9012b6
JH
47 if (tree)
48 obj = &tree->object;
49 }
50 else {
4c068a98 51 struct blob *blob = lookup_blob(entry.sha1);
6f9012b6
JH
52 if (blob)
53 obj = &blob->object;
2d9c58c6 54 }
30ae764b 55 if (!obj || process(walker, obj))
4250a5e5 56 return -1;
4250a5e5 57 }
6e454b9a 58 free_tree_buffer(tree);
4250a5e5
DB
59 return 0;
60}
61
208acbfb 62/* Remember to update object flag allocation in object.h */
24451c31
SV
63#define COMPLETE (1U << 0)
64#define SEEN (1U << 1)
65#define TO_SCAN (1U << 2)
85d106c2 66
d0ac30f2 67static struct commit_list *complete = NULL;
22c6e1d0 68
30ae764b 69static int process_commit(struct walker *walker, struct commit *commit)
4250a5e5 70{
1e8be59d 71 if (parse_commit(commit))
4250a5e5
DB
72 return -1;
73
22c6e1d0 74 while (complete && complete->item->date >= commit->date) {
d0ac30f2 75 pop_most_recent_commit(&complete, COMPLETE);
22c6e1d0 76 }
22c6e1d0 77
d0ac30f2 78 if (commit->object.flags & COMPLETE)
22c6e1d0
DB
79 return 0;
80
7999b2cf 81 hashcpy(current_commit_sha1, get_object_hash(commit->object));
4250a5e5 82
30ae764b 83 walker_say(walker, "walk %s\n", sha1_to_hex(commit->object.sha1));
85d106c2 84
30ae764b
DB
85 if (walker->get_tree) {
86 if (process(walker, &commit->tree->object))
4250a5e5 87 return -1;
30ae764b
DB
88 if (!walker->get_all)
89 walker->get_tree = 0;
4250a5e5 90 }
30ae764b 91 if (walker->get_history) {
1e8be59d 92 struct commit_list *parents = commit->parents;
4250a5e5 93 for (; parents; parents = parents->next) {
30ae764b 94 if (process(walker, &parents->item->object))
4250a5e5
DB
95 return -1;
96 }
97 }
98 return 0;
99}
100
30ae764b 101static int process_tag(struct walker *walker, struct tag *tag)
3173bd49 102{
1e8be59d 103 if (parse_tag(tag))
3173bd49 104 return -1;
30ae764b 105 return process(walker, tag->tagged);
3173bd49
DB
106}
107
1e8be59d
DB
108static struct object_list *process_queue = NULL;
109static struct object_list **process_queue_end = &process_queue;
110
30ae764b 111static int process_object(struct walker *walker, struct object *obj)
3173bd49 112{
1974632c 113 if (obj->type == OBJ_COMMIT) {
30ae764b 114 if (process_commit(walker, (struct commit *)obj))
f88fcf8b
DB
115 return -1;
116 return 0;
117 }
1974632c 118 if (obj->type == OBJ_TREE) {
30ae764b 119 if (process_tree(walker, (struct tree *)obj))
f88fcf8b
DB
120 return -1;
121 return 0;
122 }
1974632c 123 if (obj->type == OBJ_BLOB) {
f88fcf8b
DB
124 return 0;
125 }
1974632c 126 if (obj->type == OBJ_TAG) {
30ae764b 127 if (process_tag(walker, (struct tag *)obj))
f88fcf8b 128 return -1;
3173bd49 129 return 0;
f88fcf8b
DB
130 }
131 return error("Unable to determine requirements "
132 "of type %s for %s",
885a86ab 133 typename(obj->type), sha1_to_hex(obj->sha1));
f88fcf8b
DB
134}
135
30ae764b 136static int process(struct walker *walker, struct object *obj)
f88fcf8b 137{
a82d07e5
SV
138 if (obj->flags & SEEN)
139 return 0;
140 obj->flags |= SEEN;
141
80077f07 142 if (has_sha1_file(obj->sha1)) {
f88fcf8b 143 /* We already have it, so we should scan it now. */
85d106c2 144 obj->flags |= TO_SCAN;
e5f38ec3
JH
145 }
146 else {
7b64d06b
SV
147 if (obj->flags & COMPLETE)
148 return 0;
7999b2cf 149 walker->prefetch(walker, get_object_hash(*obj));
f88fcf8b 150 }
a6080a0a 151
1e8be59d
DB
152 object_list_insert(obj, process_queue_end);
153 process_queue_end = &(*process_queue_end)->next;
1e8be59d
DB
154 return 0;
155}
156
30ae764b 157static int loop(struct walker *walker)
1e8be59d 158{
85d106c2
JH
159 struct object_list *elem;
160
1e8be59d
DB
161 while (process_queue) {
162 struct object *obj = process_queue->item;
85d106c2
JH
163 elem = process_queue;
164 process_queue = elem->next;
165 free(elem);
1e8be59d
DB
166 if (!process_queue)
167 process_queue_end = &process_queue;
168
85d106c2
JH
169 /* If we are not scanning this object, we placed it in
170 * the queue because we needed to fetch it first.
171 */
172 if (! (obj->flags & TO_SCAN)) {
7999b2cf 173 if (walker->fetch(walker, get_object_hash(*obj))) {
0d7a6e4e 174 report_missing(obj);
85d106c2
JH
175 return -1;
176 }
177 }
1e8be59d 178 if (!obj->type)
7999b2cf 179 parse_object(get_object_hash(*obj));
30ae764b 180 if (process_object(walker, obj))
f88fcf8b 181 return -1;
1e8be59d
DB
182 }
183 return 0;
3173bd49
DB
184}
185
30ae764b 186static int interpret_target(struct walker *walker, char *target, unsigned char *sha1)
cd541a68
DB
187{
188 if (!get_sha1_hex(target, sha1))
189 return 0;
8d9c5010 190 if (!check_refname_format(target, 0)) {
59c69c0c 191 struct ref *ref = alloc_ref(target);
c13b2633 192 if (!walker->fetch_ref(walker, ref)) {
f4e54d02 193 hashcpy(sha1, ref->old_oid.hash);
c13b2633 194 free(ref);
cd541a68
DB
195 return 0;
196 }
c13b2633 197 free(ref);
cd541a68
DB
198 }
199 return -1;
200}
201
b4ebaf9e
MH
202static int mark_complete(const char *path, const struct object_id *oid,
203 int flag, void *cb_data)
22c6e1d0 204{
b4ebaf9e
MH
205 struct commit *commit = lookup_commit_reference_gently(oid->hash, 1);
206
d0ac30f2
JH
207 if (commit) {
208 commit->object.flags |= COMPLETE;
3bc7a05b 209 commit_list_insert(commit, &complete);
22c6e1d0
DB
210 }
211 return 0;
212}
cd541a68 213
30ae764b 214int walker_targets_stdin(char ***target, const char ***write_ref)
8e87ca66
PB
215{
216 int targets = 0, targets_alloc = 0;
f285a2d7 217 struct strbuf buf = STRBUF_INIT;
8e87ca66 218 *target = NULL; *write_ref = NULL;
8e87ca66
PB
219 while (1) {
220 char *rf_one = NULL;
221 char *tg_one;
222
e6c019d0 223 if (strbuf_getline(&buf, stdin, '\n') == EOF)
8e87ca66
PB
224 break;
225 tg_one = buf.buf;
226 rf_one = strchr(tg_one, '\t');
227 if (rf_one)
228 *rf_one++ = 0;
229
230 if (targets >= targets_alloc) {
231 targets_alloc = targets_alloc ? targets_alloc * 2 : 64;
2756ca43
RS
232 REALLOC_ARRAY(*target, targets_alloc);
233 REALLOC_ARRAY(*write_ref, targets_alloc);
8e87ca66 234 }
9befac47 235 (*target)[targets] = xstrdup(tg_one);
8c53f071 236 (*write_ref)[targets] = xstrdup_or_null(rf_one);
8e87ca66
PB
237 targets++;
238 }
e6c019d0 239 strbuf_release(&buf);
8e87ca66
PB
240 return targets;
241}
242
30ae764b 243void walker_targets_free(int targets, char **target, const char **write_ref)
8e87ca66
PB
244{
245 while (targets--) {
246 free(target[targets]);
24deea52 247 if (write_ref)
8e87ca66
PB
248 free((char *) write_ref[targets]);
249 }
250}
251
30ae764b
DB
252int walker_fetch(struct walker *walker, int targets, char **target,
253 const char **write_ref, const char *write_ref_log_details)
4250a5e5 254{
b6b10bb4
RS
255 struct strbuf refname = STRBUF_INIT;
256 struct strbuf err = STRBUF_INIT;
257 struct ref_transaction *transaction = NULL;
4211e4d1 258 unsigned char *sha1 = xmalloc(targets * 20);
b6b10bb4
RS
259 char *msg = NULL;
260 int i, ret = -1;
cd541a68 261
98533b90 262 save_commit_buffer = 0;
4211e4d1 263
b6b10bb4
RS
264 if (write_ref) {
265 transaction = ref_transaction_begin(&err);
266 if (!transaction) {
267 error("%s", err.buf);
268 goto done;
d0740d92 269 }
cd541a68
DB
270 }
271
3bc7a05b 272 if (!walker->get_recover) {
b4ebaf9e 273 for_each_ref(mark_complete, NULL);
3bc7a05b
RS
274 commit_list_sort_by_date(&complete);
275 }
22c6e1d0 276
4211e4d1 277 for (i = 0; i < targets; i++) {
30ae764b 278 if (interpret_target(walker, target[i], &sha1[20 * i])) {
5f48741a 279 error("Could not interpret response from server '%s' as something to pull", target[i]);
b6b10bb4 280 goto done;
4211e4d1 281 }
30ae764b 282 if (process(walker, lookup_unknown_object(&sha1[20 * i])))
b6b10bb4 283 goto done;
4bd18c43 284 }
4211e4d1 285
30ae764b 286 if (loop(walker))
b6b10bb4
RS
287 goto done;
288 if (!write_ref) {
289 ret = 0;
290 goto done;
291 }
4211e4d1 292 if (write_ref_log_details) {
01d678a2 293 msg = xstrfmt("fetch from %s", write_ref_log_details);
4211e4d1
PB
294 } else {
295 msg = NULL;
4bd18c43 296 }
4211e4d1 297 for (i = 0; i < targets; i++) {
b6b10bb4 298 if (!write_ref[i])
4211e4d1 299 continue;
b6b10bb4
RS
300 strbuf_reset(&refname);
301 strbuf_addf(&refname, "refs/%s", write_ref[i]);
302 if (ref_transaction_update(transaction, refname.buf,
1d147bdf 303 &sha1[20 * i], NULL, 0,
db7516ab 304 msg ? msg : "fetch (unknown)",
b6b10bb4
RS
305 &err)) {
306 error("%s", err.buf);
307 goto done;
308 }
309 }
db7516ab 310 if (ref_transaction_commit(transaction, &err)) {
b6b10bb4
RS
311 error("%s", err.buf);
312 goto done;
4bd18c43 313 }
4211e4d1 314
b6b10bb4 315 ret = 0;
30ae764b 316
b6b10bb4
RS
317done:
318 ref_transaction_free(transaction);
319 free(msg);
320 free(sha1);
321 strbuf_release(&err);
322 strbuf_release(&refname);
323 return ret;
4250a5e5 324}
30ae764b
DB
325
326void walker_free(struct walker *walker)
327{
328 walker->cleanup(walker);
329 free(walker);
330}