]> rtime.felk.cvut.cz Git - git.git/blob - builtin/checkout-index.c
Merge branch 'js/remote-add-with-insteadof'
[git.git] / builtin / checkout-index.c
1 /*
2  * Check-out files from the "current cache directory"
3  *
4  * Copyright (C) 2005 Linus Torvalds
5  *
6  */
7 #include "builtin.h"
8 #include "lockfile.h"
9 #include "quote.h"
10 #include "cache-tree.h"
11 #include "parse-options.h"
12
13 #define CHECKOUT_ALL 4
14 static int line_termination = '\n';
15 static int checkout_stage; /* default to checkout stage0 */
16 static int to_tempfile;
17 static char topath[4][TEMPORARY_FILENAME_LENGTH + 1];
18
19 static struct checkout state;
20
21 static void write_tempfile_record(const char *name, const char *prefix)
22 {
23         int i;
24
25         if (CHECKOUT_ALL == checkout_stage) {
26                 for (i = 1; i < 4; i++) {
27                         if (i > 1)
28                                 putchar(' ');
29                         if (topath[i][0])
30                                 fputs(topath[i], stdout);
31                         else
32                                 putchar('.');
33                 }
34         } else
35                 fputs(topath[checkout_stage], stdout);
36
37         putchar('\t');
38         write_name_quoted_relative(name, prefix, stdout, line_termination);
39
40         for (i = 0; i < 4; i++) {
41                 topath[i][0] = 0;
42         }
43 }
44
45 static int checkout_file(const char *name, const char *prefix)
46 {
47         int namelen = strlen(name);
48         int pos = cache_name_pos(name, namelen);
49         int has_same_name = 0;
50         int did_checkout = 0;
51         int errs = 0;
52
53         if (pos < 0)
54                 pos = -pos - 1;
55
56         while (pos < active_nr) {
57                 struct cache_entry *ce = active_cache[pos];
58                 if (ce_namelen(ce) != namelen ||
59                     memcmp(ce->name, name, namelen))
60                         break;
61                 has_same_name = 1;
62                 pos++;
63                 if (ce_stage(ce) != checkout_stage
64                     && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
65                         continue;
66                 did_checkout = 1;
67                 if (checkout_entry(ce, &state,
68                     to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
69                         errs++;
70         }
71
72         if (did_checkout) {
73                 if (to_tempfile)
74                         write_tempfile_record(name, prefix);
75                 return errs > 0 ? -1 : 0;
76         }
77
78         if (!state.quiet) {
79                 fprintf(stderr, "git checkout-index: %s ", name);
80                 if (!has_same_name)
81                         fprintf(stderr, "is not in the cache");
82                 else if (checkout_stage)
83                         fprintf(stderr, "does not exist at stage %d",
84                                 checkout_stage);
85                 else
86                         fprintf(stderr, "is unmerged");
87                 fputc('\n', stderr);
88         }
89         return -1;
90 }
91
92 static void checkout_all(const char *prefix, int prefix_length)
93 {
94         int i, errs = 0;
95         struct cache_entry *last_ce = NULL;
96
97         for (i = 0; i < active_nr ; i++) {
98                 struct cache_entry *ce = active_cache[i];
99                 if (ce_stage(ce) != checkout_stage
100                     && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
101                         continue;
102                 if (prefix && *prefix &&
103                     (ce_namelen(ce) <= prefix_length ||
104                      memcmp(prefix, ce->name, prefix_length)))
105                         continue;
106                 if (last_ce && to_tempfile) {
107                         if (ce_namelen(last_ce) != ce_namelen(ce)
108                             || memcmp(last_ce->name, ce->name, ce_namelen(ce)))
109                                 write_tempfile_record(last_ce->name, prefix);
110                 }
111                 if (checkout_entry(ce, &state,
112                     to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
113                         errs++;
114                 last_ce = ce;
115         }
116         if (last_ce && to_tempfile)
117                 write_tempfile_record(last_ce->name, prefix);
118         if (errs)
119                 /* we have already done our error reporting.
120                  * exit with the same code as die().
121                  */
122                 exit(128);
123 }
124
125 static const char * const builtin_checkout_index_usage[] = {
126         N_("git checkout-index [options] [--] [<file>...]"),
127         NULL
128 };
129
130 static struct lock_file lock_file;
131
132 static int option_parse_u(const struct option *opt,
133                               const char *arg, int unset)
134 {
135         int *newfd = opt->value;
136
137         state.refresh_cache = 1;
138         state.istate = &the_index;
139         if (*newfd < 0)
140                 *newfd = hold_locked_index(&lock_file, 1);
141         return 0;
142 }
143
144 static int option_parse_z(const struct option *opt,
145                           const char *arg, int unset)
146 {
147         if (unset)
148                 line_termination = '\n';
149         else
150                 line_termination = 0;
151         return 0;
152 }
153
154 static int option_parse_prefix(const struct option *opt,
155                                const char *arg, int unset)
156 {
157         state.base_dir = arg;
158         state.base_dir_len = strlen(arg);
159         return 0;
160 }
161
162 static int option_parse_stage(const struct option *opt,
163                               const char *arg, int unset)
164 {
165         if (!strcmp(arg, "all")) {
166                 to_tempfile = 1;
167                 checkout_stage = CHECKOUT_ALL;
168         } else {
169                 int ch = arg[0];
170                 if ('1' <= ch && ch <= '3')
171                         checkout_stage = arg[0] - '0';
172                 else
173                         die("stage should be between 1 and 3 or all");
174         }
175         return 0;
176 }
177
178 int cmd_checkout_index(int argc, const char **argv, const char *prefix)
179 {
180         int i;
181         int newfd = -1;
182         int all = 0;
183         int read_from_stdin = 0;
184         int prefix_length;
185         int force = 0, quiet = 0, not_new = 0;
186         struct option builtin_checkout_index_options[] = {
187                 OPT_BOOL('a', "all", &all,
188                         N_("check out all files in the index")),
189                 OPT__FORCE(&force, N_("force overwrite of existing files")),
190                 OPT__QUIET(&quiet,
191                         N_("no warning for existing files and files not in index")),
192                 OPT_BOOL('n', "no-create", &not_new,
193                         N_("don't checkout new files")),
194                 { OPTION_CALLBACK, 'u', "index", &newfd, NULL,
195                         N_("update stat information in the index file"),
196                         PARSE_OPT_NOARG, option_parse_u },
197                 { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
198                         N_("paths are separated with NUL character"),
199                         PARSE_OPT_NOARG, option_parse_z },
200                 OPT_BOOL(0, "stdin", &read_from_stdin,
201                         N_("read list of paths from the standard input")),
202                 OPT_BOOL(0, "temp", &to_tempfile,
203                         N_("write the content to temporary files")),
204                 OPT_CALLBACK(0, "prefix", NULL, N_("string"),
205                         N_("when creating files, prepend <string>"),
206                         option_parse_prefix),
207                 OPT_CALLBACK(0, "stage", NULL, NULL,
208                         N_("copy out the files from named stage"),
209                         option_parse_stage),
210                 OPT_END()
211         };
212
213         if (argc == 2 && !strcmp(argv[1], "-h"))
214                 usage_with_options(builtin_checkout_index_usage,
215                                    builtin_checkout_index_options);
216         git_config(git_default_config, NULL);
217         state.base_dir = "";
218         prefix_length = prefix ? strlen(prefix) : 0;
219
220         if (read_cache() < 0) {
221                 die("invalid cache");
222         }
223
224         argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
225                         builtin_checkout_index_usage, 0);
226         state.force = force;
227         state.quiet = quiet;
228         state.not_new = not_new;
229
230         if (state.base_dir_len || to_tempfile) {
231                 /* when --prefix is specified we do not
232                  * want to update cache.
233                  */
234                 if (state.refresh_cache) {
235                         rollback_lock_file(&lock_file);
236                         newfd = -1;
237                 }
238                 state.refresh_cache = 0;
239         }
240
241         /* Check out named files first */
242         for (i = 0; i < argc; i++) {
243                 const char *arg = argv[i];
244                 const char *p;
245
246                 if (all)
247                         die("git checkout-index: don't mix '--all' and explicit filenames");
248                 if (read_from_stdin)
249                         die("git checkout-index: don't mix '--stdin' and explicit filenames");
250                 p = prefix_path(prefix, prefix_length, arg);
251                 checkout_file(p, prefix);
252                 if (p < arg || p > arg + strlen(arg))
253                         free((char *)p);
254         }
255
256         if (read_from_stdin) {
257                 struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
258
259                 if (all)
260                         die("git checkout-index: don't mix '--all' and '--stdin'");
261
262                 while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
263                         const char *p;
264                         if (line_termination && buf.buf[0] == '"') {
265                                 strbuf_reset(&nbuf);
266                                 if (unquote_c_style(&nbuf, buf.buf, NULL))
267                                         die("line is badly quoted");
268                                 strbuf_swap(&buf, &nbuf);
269                         }
270                         p = prefix_path(prefix, prefix_length, buf.buf);
271                         checkout_file(p, prefix);
272                         if (p < buf.buf || p > buf.buf + buf.len)
273                                 free((char *)p);
274                 }
275                 strbuf_release(&nbuf);
276                 strbuf_release(&buf);
277         }
278
279         if (all)
280                 checkout_all(prefix, prefix_length);
281
282         if (0 <= newfd &&
283             write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
284                 die("Unable to write new index file");
285         return 0;
286 }