[PATCH] Parse tags for absent objects
[alt-git.git] / pull.c
blobe70fc02f3bf5b6c626a138d6d76d819fab76f0c8
1 #include "pull.h"
3 #include "cache.h"
4 #include "commit.h"
5 #include "tree.h"
6 #include "refs.h"
8 const char *write_ref = NULL;
10 const unsigned char *current_ref = NULL;
12 int get_tree = 0;
13 int get_history = 0;
14 /* 1 means "get delta", 2 means "really check delta harder */
15 int get_delta = 1;
16 int get_all = 0;
17 int get_verbosely = 0;
18 static unsigned char current_commit_sha1[20];
20 static const char commitS[] = "commit";
21 static const char treeS[] = "tree";
22 static const char blobS[] = "blob";
24 void pull_say(const char *fmt, const char *hex) {
25 if (get_verbosely)
26 fprintf(stderr, fmt, hex);
29 static void report_missing(const char *what, const unsigned char *missing)
31 char missing_hex[41];
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));
39 static int make_sure_we_have_it(const char *what, unsigned char *sha1)
41 int status = 0;
43 if (!has_sha1_file(sha1)) {
44 status = fetch(sha1);
45 if (status && what)
46 report_missing(what, sha1);
48 else if (get_delta < 2)
49 return 0;
51 if (get_delta) {
52 unsigned 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);
57 return status;
60 static int process_tree(unsigned char *sha1)
62 struct tree *tree = lookup_tree(sha1);
63 struct tree_entry_list *entries;
65 if (parse_tree(tree))
66 return -1;
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;
77 return 0;
80 static int process_commit(unsigned char *sha1)
82 struct commit *obj = lookup_commit(sha1);
84 if (make_sure_we_have_it(commitS, sha1))
85 return -1;
87 if (parse_commit(obj))
88 return -1;
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;
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.
108 continue;
110 if (process_commit(parents->item->object.sha1))
111 return -1;
112 memcpy(current_commit_sha1, sha1, 20);
115 return 0;
118 static int interpret_target(char *target, unsigned char *sha1)
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;
127 return -1;
131 int pull(char *target)
133 unsigned char sha1[20];
134 int fd = -1;
136 if (write_ref && current_ref) {
137 fd = lock_ref_sha1(write_ref, current_ref);
138 if (fd < 0)
139 return -1;
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;
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);
155 return 0;