[PATCH] New git-apply test cases for scanning forwards and backwards.
[git.git] / pull.c
1 #include "pull.h"
2
3 #include "cache.h"
4 #include "commit.h"
5 #include "tree.h"
6 #include "tag.h"
7 #include "blob.h"
8 #include "refs.h"
9
10 const char *write_ref = NULL;
11
12 const unsigned char *current_ref = NULL;
13
14 int get_tree = 0;
15 int get_history = 0;
16 int get_all = 0;
17 int get_verbosely = 0;
18 static unsigned char current_commit_sha1[20];
19
20 void pull_say(const char *fmt, const char *hex) 
21 {
22         if (get_verbosely)
23                 fprintf(stderr, fmt, hex);
24 }
25
26 static void report_missing(const char *what, const unsigned char *missing)
27 {
28         char missing_hex[41];
29
30         strcpy(missing_hex, sha1_to_hex(missing));;
31         fprintf(stderr,
32                 "Cannot obtain needed %s %s\nwhile processing commit %s.\n",
33                 what, missing_hex, sha1_to_hex(current_commit_sha1));
34 }
35
36 static int make_sure_we_have_it(const char *what, unsigned char *sha1)
37 {
38         int status = 0;
39
40         if (!has_sha1_file(sha1)) {
41                 status = fetch(sha1);
42                 if (status && what)
43                         report_missing(what, sha1);
44         }
45         return status;
46 }
47
48 static int process(unsigned char *sha1, const char *type);
49
50 static int process_tree(struct tree *tree)
51 {
52         struct tree_entry_list *entries;
53
54         if (parse_tree(tree))
55                 return -1;
56
57         for (entries = tree->entries; entries; entries = entries->next) {
58                 if (process(entries->item.any->sha1,
59                             entries->directory ? tree_type : blob_type))
60                         return -1;
61         }
62         return 0;
63 }
64
65 static int process_commit(struct commit *commit)
66 {
67         if (parse_commit(commit))
68                 return -1;
69
70         memcpy(current_commit_sha1, commit->object.sha1, 20);
71
72         if (get_tree) {
73                 if (process(commit->tree->object.sha1, tree_type))
74                         return -1;
75                 if (!get_all)
76                         get_tree = 0;
77         }
78         if (get_history) {
79                 struct commit_list *parents = commit->parents;
80                 for (; parents; parents = parents->next) {
81                         if (has_sha1_file(parents->item->object.sha1))
82                                 continue;
83                         if (process(parents->item->object.sha1,
84                                     commit_type))
85                                 return -1;
86                 }
87         }
88         return 0;
89 }
90
91 static int process_tag(struct tag *tag)
92 {
93         if (parse_tag(tag))
94                 return -1;
95         return process(tag->tagged->sha1, NULL);
96 }
97
98 static struct object_list *process_queue = NULL;
99 static struct object_list **process_queue_end = &process_queue;
100
101 static int process_object(struct object *obj)
102 {
103         if (obj->type == commit_type) {
104                 if (process_commit((struct commit *)obj))
105                         return -1;
106                 return 0;
107         }
108         if (obj->type == tree_type) {
109                 if (process_tree((struct tree *)obj))
110                         return -1;
111                 return 0;
112         }
113         if (obj->type == blob_type) {
114                 return 0;
115         }
116         if (obj->type == tag_type) {
117                 if (process_tag((struct tag *)obj))
118                         return -1;
119                 return 0;
120         }
121         return error("Unable to determine requirements "
122                      "of type %s for %s",
123                      obj->type, sha1_to_hex(obj->sha1));
124 }
125
126 static int process(unsigned char *sha1, const char *type)
127 {
128         struct object *obj = lookup_object_type(sha1, type);
129         if (has_sha1_file(sha1)) {
130                 parse_object(sha1);
131                 /* We already have it, so we should scan it now. */
132                 return process_object(obj);
133         }
134         if (object_list_contains(process_queue, obj))
135                 return 0;
136         object_list_insert(obj, process_queue_end);
137         process_queue_end = &(*process_queue_end)->next;
138
139         //fprintf(stderr, "prefetch %s\n", sha1_to_hex(sha1));
140         prefetch(sha1);
141                 
142         return 0;
143 }
144
145 static int loop(void)
146 {
147         while (process_queue) {
148                 struct object *obj = process_queue->item;
149                 /*
150                 fprintf(stderr, "%d objects to pull\n", 
151                         object_list_length(process_queue));
152                 */
153                 process_queue = process_queue->next;
154                 if (!process_queue)
155                         process_queue_end = &process_queue;
156
157                 //fprintf(stderr, "fetch %s\n", sha1_to_hex(obj->sha1));
158                 
159                 if (make_sure_we_have_it(obj->type ?: "object", 
160                                          obj->sha1))
161                         return -1;
162                 if (!obj->type)
163                         parse_object(obj->sha1);
164                 if (process_object(obj))
165                         return -1;
166         }
167         return 0;
168 }
169
170 static int interpret_target(char *target, unsigned char *sha1)
171 {
172         if (!get_sha1_hex(target, sha1))
173                 return 0;
174         if (!check_ref_format(target)) {
175                 if (!fetch_ref(target, sha1)) {
176                         return 0;
177                 }
178         }
179         return -1;
180 }
181
182
183 int pull(char *target)
184 {
185         unsigned char sha1[20];
186         int fd = -1;
187
188         if (write_ref && current_ref) {
189                 fd = lock_ref_sha1(write_ref, current_ref);
190                 if (fd < 0)
191                         return -1;
192         }
193
194         if (interpret_target(target, sha1))
195                 return error("Could not interpret %s as something to pull",
196                              target);
197         if (process(sha1, NULL))
198                 return -1;
199         if (loop())
200                 return -1;
201         
202         if (write_ref) {
203                 if (current_ref) {
204                         write_ref_sha1(write_ref, fd, sha1);
205                 } else {
206                         write_ref_sha1_unlocked(write_ref, sha1);
207                 }
208         }
209         return 0;
210 }