Merge branch 'jc/apply-trailing-blank-removal' into maint
[git] / builtin / fetch-pack.c
1 #include "builtin.h"
2 #include "pkt-line.h"
3 #include "fetch-pack.h"
4
5 static const char fetch_pack_usage[] =
6 "git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] "
7 "[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
8 "[--no-progress] [-v] [<host>:]<directory> [<refs>...]";
9
10 int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
11 {
12         int i, ret;
13         struct ref *ref = NULL;
14         const char *dest = NULL;
15         struct string_list sought = STRING_LIST_INIT_DUP;
16         int fd[2];
17         char *pack_lockfile = NULL;
18         char **pack_lockfile_ptr = NULL;
19         struct child_process *conn;
20         struct fetch_pack_args args;
21
22         packet_trace_identity("fetch-pack");
23
24         memset(&args, 0, sizeof(args));
25         args.uploadpack = "git-upload-pack";
26
27         for (i = 1; i < argc && *argv[i] == '-'; i++) {
28                 const char *arg = argv[i];
29
30                 if (!prefixcmp(arg, "--upload-pack=")) {
31                         args.uploadpack = arg + 14;
32                         continue;
33                 }
34                 if (!prefixcmp(arg, "--exec=")) {
35                         args.uploadpack = arg + 7;
36                         continue;
37                 }
38                 if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
39                         args.quiet = 1;
40                         continue;
41                 }
42                 if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
43                         args.lock_pack = args.keep_pack;
44                         args.keep_pack = 1;
45                         continue;
46                 }
47                 if (!strcmp("--thin", arg)) {
48                         args.use_thin_pack = 1;
49                         continue;
50                 }
51                 if (!strcmp("--include-tag", arg)) {
52                         args.include_tag = 1;
53                         continue;
54                 }
55                 if (!strcmp("--all", arg)) {
56                         args.fetch_all = 1;
57                         continue;
58                 }
59                 if (!strcmp("--stdin", arg)) {
60                         args.stdin_refs = 1;
61                         continue;
62                 }
63                 if (!strcmp("-v", arg)) {
64                         args.verbose = 1;
65                         continue;
66                 }
67                 if (!prefixcmp(arg, "--depth=")) {
68                         args.depth = strtol(arg + 8, NULL, 0);
69                         continue;
70                 }
71                 if (!strcmp("--no-progress", arg)) {
72                         args.no_progress = 1;
73                         continue;
74                 }
75                 if (!strcmp("--stateless-rpc", arg)) {
76                         args.stateless_rpc = 1;
77                         continue;
78                 }
79                 if (!strcmp("--lock-pack", arg)) {
80                         args.lock_pack = 1;
81                         pack_lockfile_ptr = &pack_lockfile;
82                         continue;
83                 }
84                 usage(fetch_pack_usage);
85         }
86
87         if (i < argc)
88                 dest = argv[i++];
89         else
90                 usage(fetch_pack_usage);
91
92         /*
93          * Copy refs from cmdline to growable list, then append any
94          * refs from the standard input:
95          */
96         for (; i < argc; i++)
97                 string_list_append(&sought, xstrdup(argv[i]));
98         if (args.stdin_refs) {
99                 if (args.stateless_rpc) {
100                         /* in stateless RPC mode we use pkt-line to read
101                          * from stdin, until we get a flush packet
102                          */
103                         static char line[1000];
104                         for (;;) {
105                                 int n = packet_read_line(0, line, sizeof(line));
106                                 if (!n)
107                                         break;
108                                 if (line[n-1] == '\n')
109                                         n--;
110                                 string_list_append(&sought, xmemdupz(line, n));
111                         }
112                 }
113                 else {
114                         /* read from stdin one ref per line, until EOF */
115                         struct strbuf line = STRBUF_INIT;
116                         while (strbuf_getline(&line, stdin, '\n') != EOF)
117                                 string_list_append(&sought, strbuf_detach(&line, NULL));
118                         strbuf_release(&line);
119                 }
120         }
121
122         if (args.stateless_rpc) {
123                 conn = NULL;
124                 fd[0] = 0;
125                 fd[1] = 1;
126         } else {
127                 conn = git_connect(fd, dest, args.uploadpack,
128                                    args.verbose ? CONNECT_VERBOSE : 0);
129         }
130
131         get_remote_heads(fd[0], &ref, 0, NULL);
132
133         ref = fetch_pack(&args, fd, conn, ref, dest,
134                          &sought, pack_lockfile_ptr);
135         if (pack_lockfile) {
136                 printf("lock %s\n", pack_lockfile);
137                 fflush(stdout);
138         }
139         close(fd[0]);
140         close(fd[1]);
141         if (finish_connect(conn))
142                 return 1;
143
144         ret = !ref || sought.nr;
145
146         /*
147          * If the heads to pull were given, we should have consumed
148          * all of them by matching the remote.  Otherwise, 'git fetch
149          * remote no-such-ref' would silently succeed without issuing
150          * an error.
151          */
152         for (i = 0; i < sought.nr; i++)
153                 error("no such remote ref %s", sought.items[i].string);
154         while (ref) {
155                 printf("%s %s\n",
156                        sha1_to_hex(ref->old_sha1), ref->name);
157                 ref = ref->next;
158         }
159
160         return ret;
161 }