pkt-line: provide a LARGE_PACKET_MAX static buffer
[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                         for (;;) {
104                                 char *line = packet_read_line(0, NULL);
105                                 if (!line)
106                                         break;
107                                 string_list_append(&sought, xstrdup(line));
108                         }
109                 }
110                 else {
111                         /* read from stdin one ref per line, until EOF */
112                         struct strbuf line = STRBUF_INIT;
113                         while (strbuf_getline(&line, stdin, '\n') != EOF)
114                                 string_list_append(&sought, strbuf_detach(&line, NULL));
115                         strbuf_release(&line);
116                 }
117         }
118
119         if (args.stateless_rpc) {
120                 conn = NULL;
121                 fd[0] = 0;
122                 fd[1] = 1;
123         } else {
124                 conn = git_connect(fd, dest, args.uploadpack,
125                                    args.verbose ? CONNECT_VERBOSE : 0);
126         }
127
128         get_remote_heads(fd[0], &ref, 0, NULL);
129
130         ref = fetch_pack(&args, fd, conn, ref, dest,
131                          &sought, pack_lockfile_ptr);
132         if (pack_lockfile) {
133                 printf("lock %s\n", pack_lockfile);
134                 fflush(stdout);
135         }
136         close(fd[0]);
137         close(fd[1]);
138         if (finish_connect(conn))
139                 return 1;
140
141         ret = !ref || sought.nr;
142
143         /*
144          * If the heads to pull were given, we should have consumed
145          * all of them by matching the remote.  Otherwise, 'git fetch
146          * remote no-such-ref' would silently succeed without issuing
147          * an error.
148          */
149         for (i = 0; i < sought.nr; i++)
150                 error("no such remote ref %s", sought.items[i].string);
151         while (ref) {
152                 printf("%s %s\n",
153                        sha1_to_hex(ref->old_sha1), ref->name);
154                 ref = ref->next;
155         }
156
157         return ret;
158 }