[PATCH] git-fsck-cache: Gracefully handle non-commit IDs
[git.git] / rpull.c
1 #include <fcntl.h>
2 #include <unistd.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "cache.h"
6 #include "commit.h"
7 #include <errno.h>
8 #include <stdio.h>
9 #include "rsh.h"
10
11 static int tree = 0;
12 static int commits = 0;
13 static int all = 0;
14
15 static int fd_in;
16 static int fd_out;
17
18 static int fetch(unsigned char *sha1)
19 {
20         if (has_sha1_file(sha1))
21                 return 0;
22         write(fd_out, sha1, 20);
23         return write_sha1_from_fd(sha1, fd_in);
24 }
25
26 static int process_tree(unsigned char *sha1)
27 {
28         struct tree *tree = lookup_tree(sha1);
29         struct tree_entry_list *entries;
30
31         if (parse_tree(tree))
32                 return -1;
33
34         for (entries = tree->entries; entries; entries = entries->next) {
35                 /*
36                   fprintf(stderr, "Tree %s ", sha1_to_hex(sha1));
37                   fprintf(stderr, "needs %s\n", 
38                   sha1_to_hex(entries->item.tree->object.sha1));
39                 */
40                 if (fetch(entries->item.tree->object.sha1)) {
41                         return error("Missing item %s",
42                                      sha1_to_hex(entries->item.tree->object.sha1));
43                 }
44                 if (entries->directory) {
45                         if (process_tree(entries->item.tree->object.sha1))
46                                 return -1;
47                 }
48         }
49         return 0;
50 }
51
52 static int process_commit(unsigned char *sha1)
53 {
54         struct commit *obj = lookup_commit(sha1);
55
56         if (fetch(sha1)) {
57                 return error("Fetching %s", sha1_to_hex(sha1));
58         }
59
60         if (parse_commit(obj))
61                 return -1;
62
63         if (tree) {
64                 if (fetch(obj->tree->object.sha1))
65                         return -1;
66                 if (process_tree(obj->tree->object.sha1))
67                         return -1;
68                 if (!all)
69                         tree = 0;
70         }
71         if (commits) {
72                 struct commit_list *parents = obj->parents;
73                 for (; parents; parents = parents->next) {
74                         if (has_sha1_file(parents->item->object.sha1))
75                                 continue;
76                         if (fetch(parents->item->object.sha1)) {
77                                 /* The server might not have it, and
78                                  * we don't mind. 
79                                  */
80                                 error("Missing tree %s; continuing", 
81                                       sha1_to_hex(parents->item->object.sha1));
82                                 continue;
83                         }
84                         if (process_commit(parents->item->object.sha1))
85                                 return -1;
86                 }
87         }
88         return 0;
89 }
90
91 int main(int argc, char **argv)
92 {
93         char *commit_id;
94         char *url;
95         int arg = 1;
96         unsigned char sha1[20];
97
98         while (arg < argc && argv[arg][0] == '-') {
99                 if (argv[arg][1] == 't') {
100                         tree = 1;
101                 } else if (argv[arg][1] == 'c') {
102                         commits = 1;
103                 } else if (argv[arg][1] == 'a') {
104                         all = 1;
105                         tree = 1;
106                         commits = 1;
107                 }
108                 arg++;
109         }
110         if (argc < arg + 2) {
111                 usage("rpull [-c] [-t] [-a] commit-id url");
112                 return 1;
113         }
114         commit_id = argv[arg];
115         url = argv[arg + 1];
116
117         if (setup_connection(&fd_in, &fd_out, "rpush", url, arg, argv + 1))
118                 return 1;
119
120         get_sha1_hex(commit_id, sha1);
121
122         if (fetch(sha1))
123                 return 1;
124         if (process_commit(sha1))
125                 return 1;
126
127         return 0;
128 }