[PATCH] git-ssh-pull: commit-id consistency
[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 /* 1 means "get delta", 2 means "really check delta harder */
17 int get_delta = 1;
18 int get_all = 0;
19 int get_verbosely = 0;
20 static unsigned char current_commit_sha1[20];
21
22 static const char commitS[] = "commit";
23 static const char treeS[] = "tree";
24 static const char blobS[] = "blob";
25
26 void pull_say(const char *fmt, const char *hex) {
27         if (get_verbosely)
28                 fprintf(stderr, fmt, hex);
29 }
30
31 static void report_missing(const char *what, const unsigned char *missing)
32 {
33         char missing_hex[41];
34
35         strcpy(missing_hex, sha1_to_hex(missing));;
36         fprintf(stderr,
37                 "Cannot obtain needed %s %s\nwhile processing commit %s.\n",
38                 what, missing_hex, sha1_to_hex(current_commit_sha1));
39 }
40
41 static int make_sure_we_have_it(const char *what, unsigned char *sha1)
42 {
43         int status = 0;
44
45         if (!has_sha1_file(sha1)) {
46                 status = fetch(sha1);
47                 if (status && what)
48                         report_missing(what, sha1);
49         }
50         else if (get_delta < 2)
51                 return 0;
52
53         if (get_delta) {
54                 unsigned char delta_sha1[20];
55                 status = sha1_delta_base(sha1, delta_sha1);
56                 if (0 < status)
57                         status = make_sure_we_have_it(what, delta_sha1);
58         }
59         return status;
60 }
61
62 static int process_unknown(unsigned char *sha1);
63
64 static int process_tree(unsigned char *sha1)
65 {
66         struct tree *tree = lookup_tree(sha1);
67         struct tree_entry_list *entries;
68
69         if (parse_tree(tree))
70                 return -1;
71
72         for (entries = tree->entries; entries; entries = entries->next) {
73                 const char *what = entries->directory ? treeS : blobS;
74                 if (make_sure_we_have_it(what, entries->item.tree->object.sha1))
75                         return -1;
76                 if (entries->directory) {
77                         if (process_tree(entries->item.tree->object.sha1))
78                                 return -1;
79                 }
80         }
81         return 0;
82 }
83
84 static int process_commit(unsigned char *sha1)
85 {
86         struct commit *obj = lookup_commit(sha1);
87
88         if (make_sure_we_have_it(commitS, sha1))
89                 return -1;
90
91         if (parse_commit(obj))
92                 return -1;
93
94         if (get_tree) {
95                 if (make_sure_we_have_it(treeS, obj->tree->object.sha1))
96                         return -1;
97                 if (process_tree(obj->tree->object.sha1))
98                         return -1;
99                 if (!get_all)
100                         get_tree = 0;
101         }
102         if (get_history) {
103                 struct commit_list *parents = obj->parents;
104                 for (; parents; parents = parents->next) {
105                         if (has_sha1_file(parents->item->object.sha1))
106                                 continue;
107                         if (make_sure_we_have_it(NULL,
108                                                  parents->item->object.sha1)) {
109                                 /* The server might not have it, and
110                                  * we don't mind. 
111                                  */
112                                 continue;
113                         }
114                         if (process_commit(parents->item->object.sha1))
115                                 return -1;
116                         memcpy(current_commit_sha1, sha1, 20);
117                 }
118         }
119         return 0;
120 }
121
122 static int process_tag(unsigned char *sha1)
123 {
124         struct tag *obj = lookup_tag(sha1);
125
126         if (parse_tag(obj))
127                 return -1;
128         return process_unknown(obj->tagged->sha1);
129 }
130
131 static int process_unknown(unsigned char *sha1)
132 {
133         struct object *obj;
134         if (make_sure_we_have_it("object", sha1))
135                 return -1;
136         obj = parse_object(sha1);
137         if (!obj)
138                 return error("Unable to parse object %s", sha1_to_hex(sha1));
139         if (obj->type == commit_type)
140                 return process_commit(sha1);
141         if (obj->type == tree_type)
142                 return process_tree(sha1);
143         if (obj->type == blob_type)
144                 return 0;
145         if (obj->type == tag_type)
146                 return process_tag(sha1);
147         return error("Unable to determine requirement of type %s for %s",
148                      obj->type, sha1_to_hex(sha1));
149 }
150
151 static int interpret_target(char *target, unsigned char *sha1)
152 {
153         if (!get_sha1_hex(target, sha1))
154                 return 0;
155         if (!check_ref_format(target)) {
156                 if (!fetch_ref(target, sha1)) {
157                         return 0;
158                 }
159         }
160         return -1;
161 }
162
163
164 int pull(char *target)
165 {
166         unsigned char sha1[20];
167         int fd = -1;
168
169         if (write_ref && current_ref) {
170                 fd = lock_ref_sha1(write_ref, current_ref);
171                 if (fd < 0)
172                         return -1;
173         }
174
175         if (interpret_target(target, sha1))
176                 return error("Could not interpret %s as something to pull",
177                              target);
178         if (process_unknown(sha1))
179                 return -1;
180         
181         if (write_ref) {
182                 if (current_ref) {
183                         write_ref_sha1(write_ref, fd, sha1);
184                 } else {
185                         write_ref_sha1_unlocked(write_ref, sha1);
186                 }
187         }
188         return 0;
189 }