1#include "pull.h"
2
3#include "cache.h"
4#include "commit.h"
5#include "tree.h"
6#include "refs.h"
7
8const char *write_ref = NULL;
9
10const unsigned char *current_ref = NULL;
11
12int get_tree = 0;
13int get_history = 0;
14/* 1 means "get delta", 2 means "really check delta harder */
15int get_delta = 1;
16int get_all = 0;
17int get_verbosely = 0;
18static unsigned char current_commit_sha1[20];
19
20static const char commitS[] = "commit";
21static const char treeS[] = "tree";
22static const char blobS[] = "blob";
23
24void pull_say(const char *fmt, const char *hex) {
25 if (get_verbosely)
26 fprintf(stderr, fmt, hex);
27}
28
29static void report_missing(const char *what, const unsigned char *missing)
30{
31 char missing_hex[41];
32
33 strcpy(missing_hex, sha1_to_hex(missing));;
34 fprintf(stderr,
35 "Cannot obtain needed %s %s\nwhile processing commit %s.\n",
36 what, missing_hex, sha1_to_hex(current_commit_sha1));
37}
38
39static int make_sure_we_have_it(const char *what, unsigned char *sha1)
40{
41 int status = 0;
42
43 if (!has_sha1_file(sha1)) {
44 status = fetch(sha1);
45 if (status && what)
46 report_missing(what, sha1);
47 }
48 else if (get_delta < 2)
49 return 0;
50
51 if (get_delta) {
52 char delta_sha1[20];
53 status = sha1_delta_base(sha1, delta_sha1);
54 if (0 < status)
55 status = make_sure_we_have_it(what, delta_sha1);
56 }
57 return status;
58}
59
60static int process_tree(unsigned char *sha1)
61{
62 struct tree *tree = lookup_tree(sha1);
63 struct tree_entry_list *entries;
64
65 if (parse_tree(tree))
66 return -1;
67
68 for (entries = tree->entries; entries; entries = entries->next) {
69 const char *what = entries->directory ? treeS : blobS;
70 if (make_sure_we_have_it(what, entries->item.tree->object.sha1))
71 return -1;
72 if (entries->directory) {
73 if (process_tree(entries->item.tree->object.sha1))
74 return -1;
75 }
76 }
77 return 0;
78}
79
80static int process_commit(unsigned char *sha1)
81{
82 struct commit *obj = lookup_commit(sha1);
83
84 if (make_sure_we_have_it(commitS, sha1))
85 return -1;
86
87 if (parse_commit(obj))
88 return -1;
89
90 if (get_tree) {
91 if (make_sure_we_have_it(treeS, obj->tree->object.sha1))
92 return -1;
93 if (process_tree(obj->tree->object.sha1))
94 return -1;
95 if (!get_all)
96 get_tree = 0;
97 }
98 if (get_history) {
99 struct commit_list *parents = obj->parents;
100 for (; parents; parents = parents->next) {
101 if (has_sha1_file(parents->item->object.sha1))
102 continue;
103 if (make_sure_we_have_it(NULL,
104 parents->item->object.sha1)) {
105 /* The server might not have it, and
106 * we don't mind.
107 */
108 continue;
109 }
110 if (process_commit(parents->item->object.sha1))
111 return -1;
112 memcpy(current_commit_sha1, sha1, 20);
113 }
114 }
115 return 0;
116}
117
118static int interpret_target(char *target, unsigned char *sha1)
119{
120 if (!get_sha1_hex(target, sha1))
121 return 0;
122 if (!check_ref_format(target)) {
123 if (!fetch_ref(target, sha1)) {
124 return 0;
125 }
126 }
127 return -1;
128}
129
130
131int pull(char *target)
132{
133 unsigned char sha1[20];
134 int fd = -1;
135
136 if (write_ref && current_ref) {
137 fd = lock_ref_sha1(write_ref, current_ref);
138 if (fd < 0)
139 return -1;
140 }
141
142 if (interpret_target(target, sha1))
143 return error("Could not interpret %s as something to pull",
144 target);
145 if (process_commit(sha1))
146 return -1;
147
148 if (write_ref) {
149 if (current_ref) {
150 write_ref_sha1(write_ref, fd, sha1);
151 } else {
152 write_ref_sha1_unlocked(write_ref, sha1);
153 }
154 }
155 return 0;
156}