]> git.proxmox.com Git - libgit2.git/blob - src/checkout.c
Merge pull request #3097 from libgit2/cmn/submodule-config-state
[libgit2.git] / src / checkout.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include <assert.h>
9
10 #include "checkout.h"
11
12 #include "git2/repository.h"
13 #include "git2/refs.h"
14 #include "git2/tree.h"
15 #include "git2/blob.h"
16 #include "git2/config.h"
17 #include "git2/diff.h"
18 #include "git2/submodule.h"
19 #include "git2/sys/index.h"
20 #include "git2/sys/filter.h"
21
22 #include "refs.h"
23 #include "repository.h"
24 #include "index.h"
25 #include "filter.h"
26 #include "blob.h"
27 #include "diff.h"
28 #include "pathspec.h"
29 #include "buf_text.h"
30 #include "merge_file.h"
31 #include "path.h"
32 #include "attr.h"
33 #include "pool.h"
34 #include "strmap.h"
35
36 GIT__USE_STRMAP
37
38 /* See docs/checkout-internals.md for more information */
39
40 enum {
41 CHECKOUT_ACTION__NONE = 0,
42 CHECKOUT_ACTION__REMOVE = 1,
43 CHECKOUT_ACTION__UPDATE_BLOB = 2,
44 CHECKOUT_ACTION__UPDATE_SUBMODULE = 4,
45 CHECKOUT_ACTION__CONFLICT = 8,
46 CHECKOUT_ACTION__REMOVE_CONFLICT = 16,
47 CHECKOUT_ACTION__UPDATE_CONFLICT = 32,
48 CHECKOUT_ACTION__MAX = 32,
49 CHECKOUT_ACTION__DEFER_REMOVE = 64,
50 CHECKOUT_ACTION__REMOVE_AND_UPDATE =
51 (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE),
52 };
53
54 typedef struct {
55 git_repository *repo;
56 git_iterator *target;
57 git_diff *diff;
58 git_checkout_options opts;
59 bool opts_free_baseline;
60 char *pfx;
61 git_index *index;
62 git_pool pool;
63 git_vector removes;
64 git_vector remove_conflicts;
65 git_vector update_conflicts;
66 git_vector *update_reuc;
67 git_vector *update_names;
68 git_buf path;
69 size_t workdir_len;
70 git_buf tmp;
71 unsigned int strategy;
72 int can_symlink;
73 bool reload_submodules;
74 size_t total_steps;
75 size_t completed_steps;
76 git_checkout_perfdata perfdata;
77 git_strmap *mkdir_map;
78 git_attr_session attr_session;
79 } checkout_data;
80
81 typedef struct {
82 const git_index_entry *ancestor;
83 const git_index_entry *ours;
84 const git_index_entry *theirs;
85
86 int name_collision:1,
87 directoryfile:1,
88 one_to_two:1,
89 binary:1,
90 submodule:1;
91 } checkout_conflictdata;
92
93 static int checkout_notify(
94 checkout_data *data,
95 git_checkout_notify_t why,
96 const git_diff_delta *delta,
97 const git_index_entry *wditem)
98 {
99 git_diff_file wdfile;
100 const git_diff_file *baseline = NULL, *target = NULL, *workdir = NULL;
101 const char *path = NULL;
102
103 if (!data->opts.notify_cb ||
104 (why & data->opts.notify_flags) == 0)
105 return 0;
106
107 if (wditem) {
108 memset(&wdfile, 0, sizeof(wdfile));
109
110 git_oid_cpy(&wdfile.id, &wditem->id);
111 wdfile.path = wditem->path;
112 wdfile.size = wditem->file_size;
113 wdfile.flags = GIT_DIFF_FLAG_VALID_ID;
114 wdfile.mode = wditem->mode;
115
116 workdir = &wdfile;
117
118 path = wditem->path;
119 }
120
121 if (delta) {
122 switch (delta->status) {
123 case GIT_DELTA_UNMODIFIED:
124 case GIT_DELTA_MODIFIED:
125 case GIT_DELTA_TYPECHANGE:
126 default:
127 baseline = &delta->old_file;
128 target = &delta->new_file;
129 break;
130 case GIT_DELTA_ADDED:
131 case GIT_DELTA_IGNORED:
132 case GIT_DELTA_UNTRACKED:
133 case GIT_DELTA_UNREADABLE:
134 target = &delta->new_file;
135 break;
136 case GIT_DELTA_DELETED:
137 baseline = &delta->old_file;
138 break;
139 }
140
141 path = delta->old_file.path;
142 }
143
144 {
145 int error = data->opts.notify_cb(
146 why, path, baseline, target, workdir, data->opts.notify_payload);
147
148 return giterr_set_after_callback_function(
149 error, "git_checkout notification");
150 }
151 }
152
153 GIT_INLINE(bool) is_workdir_base_or_new(
154 const git_oid *workdir_id,
155 const git_diff_file *baseitem,
156 const git_diff_file *newitem)
157 {
158 return (git_oid__cmp(&baseitem->id, workdir_id) == 0 ||
159 git_oid__cmp(&newitem->id, workdir_id) == 0);
160 }
161
162 static bool checkout_is_workdir_modified(
163 checkout_data *data,
164 const git_diff_file *baseitem,
165 const git_diff_file *newitem,
166 const git_index_entry *wditem)
167 {
168 git_oid oid;
169 const git_index_entry *ie;
170
171 /* handle "modified" submodule */
172 if (wditem->mode == GIT_FILEMODE_COMMIT) {
173 git_submodule *sm;
174 unsigned int sm_status = 0;
175 const git_oid *sm_oid = NULL;
176 bool rval = false;
177
178 if (git_submodule_lookup(&sm, data->repo, wditem->path) < 0) {
179 giterr_clear();
180 return true;
181 }
182
183 if (git_submodule_status(&sm_status, data->repo, wditem->path, GIT_SUBMODULE_IGNORE_FALLBACK) < 0 ||
184 GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status))
185 rval = true;
186 else if ((sm_oid = git_submodule_wd_id(sm)) == NULL)
187 rval = false;
188 else
189 rval = (git_oid__cmp(&baseitem->id, sm_oid) != 0);
190
191 git_submodule_free(sm);
192 return rval;
193 }
194
195 /* Look at the cache to decide if the workdir is modified. If not,
196 * we can simply compare the oid in the cache to the baseitem instead
197 * of hashing the file. If so, we allow the checkout to proceed if the
198 * oid is identical (ie, the staged item is what we're trying to check
199 * out.)
200 */
201 if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) {
202 if (wditem->mtime.seconds == ie->mtime.seconds &&
203 wditem->mtime.nanoseconds == ie->mtime.nanoseconds &&
204 wditem->file_size == ie->file_size)
205 return !is_workdir_base_or_new(&ie->id, baseitem, newitem);
206 }
207
208 /* depending on where base is coming from, we may or may not know
209 * the actual size of the data, so we can't rely on this shortcut.
210 */
211 if (baseitem->size && wditem->file_size != baseitem->size)
212 return true;
213
214 if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0)
215 return false;
216
217 /* Allow the checkout if the workdir is not modified *or* if the checkout
218 * target's contents are already in the working directory.
219 */
220 return !is_workdir_base_or_new(&oid, baseitem, newitem);
221 }
222
223 #define CHECKOUT_ACTION_IF(FLAG,YES,NO) \
224 ((data->strategy & GIT_CHECKOUT_##FLAG) ? CHECKOUT_ACTION__##YES : CHECKOUT_ACTION__##NO)
225
226 static int checkout_action_common(
227 int *action,
228 checkout_data *data,
229 const git_diff_delta *delta,
230 const git_index_entry *wd)
231 {
232 git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE;
233
234 if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0)
235 *action = (*action & ~CHECKOUT_ACTION__REMOVE);
236
237 if ((*action & CHECKOUT_ACTION__UPDATE_BLOB) != 0) {
238 if (S_ISGITLINK(delta->new_file.mode))
239 *action = (*action & ~CHECKOUT_ACTION__UPDATE_BLOB) |
240 CHECKOUT_ACTION__UPDATE_SUBMODULE;
241
242 /* to "update" a symlink, we must remove the old one first */
243 if (delta->new_file.mode == GIT_FILEMODE_LINK && wd != NULL)
244 *action |= CHECKOUT_ACTION__REMOVE;
245
246 notify = GIT_CHECKOUT_NOTIFY_UPDATED;
247 }
248
249 if ((*action & CHECKOUT_ACTION__CONFLICT) != 0)
250 notify = GIT_CHECKOUT_NOTIFY_CONFLICT;
251
252 return checkout_notify(data, notify, delta, wd);
253 }
254
255 static int checkout_action_no_wd(
256 int *action,
257 checkout_data *data,
258 const git_diff_delta *delta)
259 {
260 int error = 0;
261
262 *action = CHECKOUT_ACTION__NONE;
263
264 switch (delta->status) {
265 case GIT_DELTA_UNMODIFIED: /* case 12 */
266 error = checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL);
267 if (error)
268 return error;
269 *action = CHECKOUT_ACTION_IF(RECREATE_MISSING, UPDATE_BLOB, NONE);
270 break;
271 case GIT_DELTA_ADDED: /* case 2 or 28 (and 5 but not really) */
272 *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
273 break;
274 case GIT_DELTA_MODIFIED: /* case 13 (and 35 but not really) */
275 *action = CHECKOUT_ACTION_IF(RECREATE_MISSING, UPDATE_BLOB, CONFLICT);
276 break;
277 case GIT_DELTA_TYPECHANGE: /* case 21 (B->T) and 28 (T->B)*/
278 if (delta->new_file.mode == GIT_FILEMODE_TREE)
279 *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
280 break;
281 case GIT_DELTA_DELETED: /* case 8 or 25 */
282 *action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE);
283 break;
284 default: /* impossible */
285 break;
286 }
287
288 return checkout_action_common(action, data, delta, NULL);
289 }
290
291 static bool wd_item_is_removable(git_iterator *iter, const git_index_entry *wd)
292 {
293 git_buf *full = NULL;
294
295 if (wd->mode != GIT_FILEMODE_TREE)
296 return true;
297 if (git_iterator_current_workdir_path(&full, iter) < 0)
298 return true;
299 return !full || !git_path_contains(full, DOT_GIT);
300 }
301
302 static int checkout_queue_remove(checkout_data *data, const char *path)
303 {
304 char *copy = git_pool_strdup(&data->pool, path);
305 GITERR_CHECK_ALLOC(copy);
306 return git_vector_insert(&data->removes, copy);
307 }
308
309 /* note that this advances the iterator over the wd item */
310 static int checkout_action_wd_only(
311 checkout_data *data,
312 git_iterator *workdir,
313 const git_index_entry **wditem,
314 git_vector *pathspec)
315 {
316 int error = 0;
317 bool remove = false;
318 git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE;
319 const git_index_entry *wd = *wditem;
320
321 if (!git_pathspec__match(
322 pathspec, wd->path,
323 (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0,
324 git_iterator_ignore_case(workdir), NULL, NULL))
325 return git_iterator_advance(wditem, workdir);
326
327 /* check if item is tracked in the index but not in the checkout diff */
328 if (data->index != NULL) {
329 size_t pos;
330
331 error = git_index__find_pos(
332 &pos, data->index, wd->path, 0, GIT_INDEX_STAGE_ANY);
333
334 if (wd->mode != GIT_FILEMODE_TREE) {
335 if (!error) { /* found by git_index__find_pos call */
336 notify = GIT_CHECKOUT_NOTIFY_DIRTY;
337 remove = ((data->strategy & GIT_CHECKOUT_FORCE) != 0);
338 } else if (error != GIT_ENOTFOUND)
339 return error;
340 else
341 error = 0; /* git_index__find_pos does not set error msg */
342 } else {
343 /* for tree entries, we have to see if there are any index
344 * entries that are contained inside that tree
345 */
346 const git_index_entry *e = git_index_get_byindex(data->index, pos);
347
348 if (e != NULL && data->diff->pfxcomp(e->path, wd->path) == 0) {
349 notify = GIT_CHECKOUT_NOTIFY_DIRTY;
350 remove = ((data->strategy & GIT_CHECKOUT_FORCE) != 0);
351 }
352 }
353 }
354
355 if (notify != GIT_CHECKOUT_NOTIFY_NONE) {
356 /* if we found something in the index, notify and advance */
357 if ((error = checkout_notify(data, notify, NULL, wd)) != 0)
358 return error;
359
360 if (remove && wd_item_is_removable(workdir, wd))
361 error = checkout_queue_remove(data, wd->path);
362
363 if (!error)
364 error = git_iterator_advance(wditem, workdir);
365 } else {
366 /* untracked or ignored - can't know which until we advance through */
367 bool over = false, removable = wd_item_is_removable(workdir, wd);
368 git_iterator_status_t untracked_state;
369
370 /* copy the entry for issuing notification callback later */
371 git_index_entry saved_wd = *wd;
372 git_buf_sets(&data->tmp, wd->path);
373 saved_wd.path = data->tmp.ptr;
374
375 error = git_iterator_advance_over_with_status(
376 wditem, &untracked_state, workdir);
377 if (error == GIT_ITEROVER)
378 over = true;
379 else if (error < 0)
380 return error;
381
382 if (untracked_state == GIT_ITERATOR_STATUS_IGNORED) {
383 notify = GIT_CHECKOUT_NOTIFY_IGNORED;
384 remove = ((data->strategy & GIT_CHECKOUT_REMOVE_IGNORED) != 0);
385 } else {
386 notify = GIT_CHECKOUT_NOTIFY_UNTRACKED;
387 remove = ((data->strategy & GIT_CHECKOUT_REMOVE_UNTRACKED) != 0);
388 }
389
390 if ((error = checkout_notify(data, notify, NULL, &saved_wd)) != 0)
391 return error;
392
393 if (remove && removable)
394 error = checkout_queue_remove(data, saved_wd.path);
395
396 if (!error && over) /* restore ITEROVER if needed */
397 error = GIT_ITEROVER;
398 }
399
400 return error;
401 }
402
403 static bool submodule_is_config_only(
404 checkout_data *data,
405 const char *path)
406 {
407 git_submodule *sm = NULL;
408 unsigned int sm_loc = 0;
409 bool rval = false;
410
411 if (git_submodule_lookup(&sm, data->repo, path) < 0)
412 return true;
413
414 if (git_submodule_location(&sm_loc, sm) < 0 ||
415 sm_loc == GIT_SUBMODULE_STATUS_IN_CONFIG)
416 rval = true;
417
418 git_submodule_free(sm);
419
420 return rval;
421 }
422
423 static bool checkout_is_empty_dir(checkout_data *data, const char *path)
424 {
425 git_buf_truncate(&data->path, data->workdir_len);
426 if (git_buf_puts(&data->path, path) < 0)
427 return false;
428 return git_path_is_empty_dir(data->path.ptr);
429 }
430
431 static int checkout_action_with_wd(
432 int *action,
433 checkout_data *data,
434 const git_diff_delta *delta,
435 git_iterator *workdir,
436 const git_index_entry *wd)
437 {
438 *action = CHECKOUT_ACTION__NONE;
439
440 switch (delta->status) {
441 case GIT_DELTA_UNMODIFIED: /* case 14/15 or 33 */
442 if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd)) {
443 GITERR_CHECK_ERROR(
444 checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) );
445 *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, NONE);
446 }
447 break;
448 case GIT_DELTA_ADDED: /* case 3, 4 or 6 */
449 if (git_iterator_current_is_ignored(workdir))
450 *action = CHECKOUT_ACTION_IF(DONT_OVERWRITE_IGNORED, CONFLICT, UPDATE_BLOB);
451 else
452 *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
453 break;
454 case GIT_DELTA_DELETED: /* case 9 or 10 (or 26 but not really) */
455 if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
456 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
457 else
458 *action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE);
459 break;
460 case GIT_DELTA_MODIFIED: /* case 16, 17, 18 (or 36 but not really) */
461 if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
462 *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
463 else
464 *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
465 break;
466 case GIT_DELTA_TYPECHANGE: /* case 22, 23, 29, 30 */
467 if (delta->old_file.mode == GIT_FILEMODE_TREE) {
468 if (wd->mode == GIT_FILEMODE_TREE)
469 /* either deleting items in old tree will delete the wd dir,
470 * or we'll get a conflict when we attempt blob update...
471 */
472 *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
473 else if (wd->mode == GIT_FILEMODE_COMMIT) {
474 /* workdir is possibly a "phantom" submodule - treat as a
475 * tree if the only submodule info came from the config
476 */
477 if (submodule_is_config_only(data, wd->path))
478 *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
479 else
480 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
481 } else
482 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
483 }
484 else if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
485 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
486 else
487 *action = CHECKOUT_ACTION_IF(SAFE, REMOVE_AND_UPDATE, NONE);
488
489 /* don't update if the typechange is to a tree */
490 if (delta->new_file.mode == GIT_FILEMODE_TREE)
491 *action = (*action & ~CHECKOUT_ACTION__UPDATE_BLOB);
492 break;
493 default: /* impossible */
494 break;
495 }
496
497 return checkout_action_common(action, data, delta, wd);
498 }
499
500 static int checkout_action_with_wd_blocker(
501 int *action,
502 checkout_data *data,
503 const git_diff_delta *delta,
504 const git_index_entry *wd)
505 {
506 *action = CHECKOUT_ACTION__NONE;
507
508 switch (delta->status) {
509 case GIT_DELTA_UNMODIFIED:
510 /* should show delta as dirty / deleted */
511 GITERR_CHECK_ERROR(
512 checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) );
513 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE);
514 break;
515 case GIT_DELTA_ADDED:
516 case GIT_DELTA_MODIFIED:
517 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
518 break;
519 case GIT_DELTA_DELETED:
520 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
521 break;
522 case GIT_DELTA_TYPECHANGE:
523 /* not 100% certain about this... */
524 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
525 break;
526 default: /* impossible */
527 break;
528 }
529
530 return checkout_action_common(action, data, delta, wd);
531 }
532
533 static int checkout_action_with_wd_dir(
534 int *action,
535 checkout_data *data,
536 const git_diff_delta *delta,
537 git_iterator *workdir,
538 const git_index_entry *wd)
539 {
540 *action = CHECKOUT_ACTION__NONE;
541
542 switch (delta->status) {
543 case GIT_DELTA_UNMODIFIED: /* case 19 or 24 (or 34 but not really) */
544 GITERR_CHECK_ERROR(
545 checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL));
546 GITERR_CHECK_ERROR(
547 checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd));
548 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE);
549 break;
550 case GIT_DELTA_ADDED:/* case 4 (and 7 for dir) */
551 case GIT_DELTA_MODIFIED: /* case 20 (or 37 but not really) */
552 if (delta->old_file.mode == GIT_FILEMODE_COMMIT)
553 /* expected submodule (and maybe found one) */;
554 else if (delta->new_file.mode != GIT_FILEMODE_TREE)
555 *action = git_iterator_current_is_ignored(workdir) ?
556 CHECKOUT_ACTION_IF(DONT_OVERWRITE_IGNORED, CONFLICT, REMOVE_AND_UPDATE) :
557 CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
558 break;
559 case GIT_DELTA_DELETED: /* case 11 (and 27 for dir) */
560 if (delta->old_file.mode != GIT_FILEMODE_TREE)
561 GITERR_CHECK_ERROR(
562 checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd));
563 break;
564 case GIT_DELTA_TYPECHANGE: /* case 24 or 31 */
565 if (delta->old_file.mode == GIT_FILEMODE_TREE) {
566 /* For typechange from dir, remove dir and add blob, but it is
567 * not safe to remove dir if it contains modified files.
568 * However, safely removing child files will remove the parent
569 * directory if is it left empty, so we can defer removing the
570 * dir and it will succeed if no children are left.
571 */
572 *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
573 }
574 else if (delta->new_file.mode != GIT_FILEMODE_TREE)
575 /* For typechange to dir, dir is already created so no action */
576 *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
577 break;
578 default: /* impossible */
579 break;
580 }
581
582 return checkout_action_common(action, data, delta, wd);
583 }
584
585 static int checkout_action_with_wd_dir_empty(
586 int *action,
587 checkout_data *data,
588 const git_diff_delta *delta)
589 {
590 int error = checkout_action_no_wd(action, data, delta);
591
592 /* We can always safely remove an empty directory. */
593 if (error == 0 && *action != CHECKOUT_ACTION__NONE)
594 *action |= CHECKOUT_ACTION__REMOVE;
595
596 return error;
597 }
598
599 static int checkout_action(
600 int *action,
601 checkout_data *data,
602 git_diff_delta *delta,
603 git_iterator *workdir,
604 const git_index_entry **wditem,
605 git_vector *pathspec)
606 {
607 int cmp = -1, error;
608 int (*strcomp)(const char *, const char *) = data->diff->strcomp;
609 int (*pfxcomp)(const char *str, const char *pfx) = data->diff->pfxcomp;
610 int (*advance)(const git_index_entry **, git_iterator *) = NULL;
611
612 /* move workdir iterator to follow along with deltas */
613
614 while (1) {
615 const git_index_entry *wd = *wditem;
616
617 if (!wd)
618 return checkout_action_no_wd(action, data, delta);
619
620 cmp = strcomp(wd->path, delta->old_file.path);
621
622 /* 1. wd before delta ("a/a" before "a/b")
623 * 2. wd prefixes delta & should expand ("a/" before "a/b")
624 * 3. wd prefixes delta & cannot expand ("a/b" before "a/b/c")
625 * 4. wd equals delta ("a/b" and "a/b")
626 * 5. wd after delta & delta prefixes wd ("a/b/c" after "a/b/" or "a/b")
627 * 6. wd after delta ("a/c" after "a/b")
628 */
629
630 if (cmp < 0) {
631 cmp = pfxcomp(delta->old_file.path, wd->path);
632
633 if (cmp == 0) {
634 if (wd->mode == GIT_FILEMODE_TREE) {
635 /* case 2 - entry prefixed by workdir tree */
636 error = git_iterator_advance_into_or_over(wditem, workdir);
637 if (error < 0 && error != GIT_ITEROVER)
638 goto done;
639 continue;
640 }
641
642 /* case 3 maybe - wd contains non-dir where dir expected */
643 if (delta->old_file.path[strlen(wd->path)] == '/') {
644 error = checkout_action_with_wd_blocker(
645 action, data, delta, wd);
646 advance = git_iterator_advance;
647 goto done;
648 }
649 }
650
651 /* case 1 - handle wd item (if it matches pathspec) */
652 error = checkout_action_wd_only(data, workdir, wditem, pathspec);
653 if (error && error != GIT_ITEROVER)
654 goto done;
655 continue;
656 }
657
658 if (cmp == 0) {
659 /* case 4 */
660 error = checkout_action_with_wd(action, data, delta, workdir, wd);
661 advance = git_iterator_advance;
662 goto done;
663 }
664
665 cmp = pfxcomp(wd->path, delta->old_file.path);
666
667 if (cmp == 0) { /* case 5 */
668 if (wd->path[strlen(delta->old_file.path)] != '/')
669 return checkout_action_no_wd(action, data, delta);
670
671 if (delta->status == GIT_DELTA_TYPECHANGE) {
672 if (delta->old_file.mode == GIT_FILEMODE_TREE) {
673 error = checkout_action_with_wd(action, data, delta, workdir, wd);
674 advance = git_iterator_advance_into;
675 goto done;
676 }
677
678 if (delta->new_file.mode == GIT_FILEMODE_TREE ||
679 delta->new_file.mode == GIT_FILEMODE_COMMIT ||
680 delta->old_file.mode == GIT_FILEMODE_COMMIT)
681 {
682 error = checkout_action_with_wd(action, data, delta, workdir, wd);
683 advance = git_iterator_advance;
684 goto done;
685 }
686 }
687
688 return checkout_is_empty_dir(data, wd->path) ?
689 checkout_action_with_wd_dir_empty(action, data, delta) :
690 checkout_action_with_wd_dir(action, data, delta, workdir, wd);
691 }
692
693 /* case 6 - wd is after delta */
694 return checkout_action_no_wd(action, data, delta);
695 }
696
697 done:
698 if (!error && advance != NULL &&
699 (error = advance(wditem, workdir)) < 0) {
700 *wditem = NULL;
701 if (error == GIT_ITEROVER)
702 error = 0;
703 }
704
705 return error;
706 }
707
708 static int checkout_remaining_wd_items(
709 checkout_data *data,
710 git_iterator *workdir,
711 const git_index_entry *wd,
712 git_vector *spec)
713 {
714 int error = 0;
715
716 while (wd && !error)
717 error = checkout_action_wd_only(data, workdir, &wd, spec);
718
719 if (error == GIT_ITEROVER)
720 error = 0;
721
722 return error;
723 }
724
725 GIT_INLINE(int) checkout_idxentry_cmp(
726 const git_index_entry *a,
727 const git_index_entry *b)
728 {
729 if (!a && !b)
730 return 0;
731 else if (!a && b)
732 return -1;
733 else if(a && !b)
734 return 1;
735 else
736 return strcmp(a->path, b->path);
737 }
738
739 static int checkout_conflictdata_cmp(const void *a, const void *b)
740 {
741 const checkout_conflictdata *ca = a;
742 const checkout_conflictdata *cb = b;
743 int diff;
744
745 if ((diff = checkout_idxentry_cmp(ca->ancestor, cb->ancestor)) == 0 &&
746 (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0)
747 diff = checkout_idxentry_cmp(ca->theirs, cb->theirs);
748
749 return diff;
750 }
751
752 int checkout_conflictdata_empty(
753 const git_vector *conflicts, size_t idx, void *payload)
754 {
755 checkout_conflictdata *conflict;
756
757 GIT_UNUSED(payload);
758
759 if ((conflict = git_vector_get(conflicts, idx)) == NULL)
760 return -1;
761
762 if (conflict->ancestor || conflict->ours || conflict->theirs)
763 return 0;
764
765 git__free(conflict);
766 return 1;
767 }
768
769 GIT_INLINE(bool) conflict_pathspec_match(
770 checkout_data *data,
771 git_iterator *workdir,
772 git_vector *pathspec,
773 const git_index_entry *ancestor,
774 const git_index_entry *ours,
775 const git_index_entry *theirs)
776 {
777 /* if the pathspec matches ours *or* theirs, proceed */
778 if (ours && git_pathspec__match(pathspec, ours->path,
779 (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0,
780 git_iterator_ignore_case(workdir), NULL, NULL))
781 return true;
782
783 if (theirs && git_pathspec__match(pathspec, theirs->path,
784 (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0,
785 git_iterator_ignore_case(workdir), NULL, NULL))
786 return true;
787
788 if (ancestor && git_pathspec__match(pathspec, ancestor->path,
789 (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0,
790 git_iterator_ignore_case(workdir), NULL, NULL))
791 return true;
792
793 return false;
794 }
795
796 GIT_INLINE(int) checkout_conflict_detect_submodule(checkout_conflictdata *conflict)
797 {
798 conflict->submodule = ((conflict->ancestor && S_ISGITLINK(conflict->ancestor->mode)) ||
799 (conflict->ours && S_ISGITLINK(conflict->ours->mode)) ||
800 (conflict->theirs && S_ISGITLINK(conflict->theirs->mode)));
801 return 0;
802 }
803
804 GIT_INLINE(int) checkout_conflict_detect_binary(git_repository *repo, checkout_conflictdata *conflict)
805 {
806 git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
807 int error = 0;
808
809 if (conflict->submodule)
810 return 0;
811
812 if (conflict->ancestor) {
813 if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor->id)) < 0)
814 goto done;
815
816 conflict->binary = git_blob_is_binary(ancestor_blob);
817 }
818
819 if (!conflict->binary && conflict->ours) {
820 if ((error = git_blob_lookup(&our_blob, repo, &conflict->ours->id)) < 0)
821 goto done;
822
823 conflict->binary = git_blob_is_binary(our_blob);
824 }
825
826 if (!conflict->binary && conflict->theirs) {
827 if ((error = git_blob_lookup(&their_blob, repo, &conflict->theirs->id)) < 0)
828 goto done;
829
830 conflict->binary = git_blob_is_binary(their_blob);
831 }
832
833 done:
834 git_blob_free(ancestor_blob);
835 git_blob_free(our_blob);
836 git_blob_free(their_blob);
837
838 return error;
839 }
840
841 static int checkout_conflict_append_update(
842 const git_index_entry *ancestor,
843 const git_index_entry *ours,
844 const git_index_entry *theirs,
845 void *payload)
846 {
847 checkout_data *data = payload;
848 checkout_conflictdata *conflict;
849 int error;
850
851 conflict = git__calloc(1, sizeof(checkout_conflictdata));
852 GITERR_CHECK_ALLOC(conflict);
853
854 conflict->ancestor = ancestor;
855 conflict->ours = ours;
856 conflict->theirs = theirs;
857
858 if ((error = checkout_conflict_detect_submodule(conflict)) < 0 ||
859 (error = checkout_conflict_detect_binary(data->repo, conflict)) < 0)
860 {
861 git__free(conflict);
862 return error;
863 }
864
865 if (git_vector_insert(&data->update_conflicts, conflict))
866 return -1;
867
868 return 0;
869 }
870
871 static int checkout_conflicts_foreach(
872 checkout_data *data,
873 git_index *index,
874 git_iterator *workdir,
875 git_vector *pathspec,
876 int (*cb)(const git_index_entry *, const git_index_entry *, const git_index_entry *, void *),
877 void *payload)
878 {
879 git_index_conflict_iterator *iterator = NULL;
880 const git_index_entry *ancestor, *ours, *theirs;
881 int error = 0;
882
883 if ((error = git_index_conflict_iterator_new(&iterator, index)) < 0)
884 goto done;
885
886 /* Collect the conflicts */
887 while ((error = git_index_conflict_next(&ancestor, &ours, &theirs, iterator)) == 0) {
888 if (!conflict_pathspec_match(data, workdir, pathspec, ancestor, ours, theirs))
889 continue;
890
891 if ((error = cb(ancestor, ours, theirs, payload)) < 0)
892 goto done;
893 }
894
895 if (error == GIT_ITEROVER)
896 error = 0;
897
898 done:
899 git_index_conflict_iterator_free(iterator);
900
901 return error;
902 }
903
904 static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec)
905 {
906 git_index *index;
907
908 /* Only write conficts from sources that have them: indexes. */
909 if ((index = git_iterator_get_index(data->target)) == NULL)
910 return 0;
911
912 data->update_conflicts._cmp = checkout_conflictdata_cmp;
913
914 if (checkout_conflicts_foreach(data, index, workdir, pathspec, checkout_conflict_append_update, data) < 0)
915 return -1;
916
917 /* Collect the REUC and NAME entries */
918 data->update_reuc = &index->reuc;
919 data->update_names = &index->names;
920
921 return 0;
922 }
923
924 GIT_INLINE(int) checkout_conflicts_cmp_entry(
925 const char *path,
926 const git_index_entry *entry)
927 {
928 return strcmp((const char *)path, entry->path);
929 }
930
931 static int checkout_conflicts_cmp_ancestor(const void *p, const void *c)
932 {
933 const char *path = p;
934 const checkout_conflictdata *conflict = c;
935
936 if (!conflict->ancestor)
937 return 1;
938
939 return checkout_conflicts_cmp_entry(path, conflict->ancestor);
940 }
941
942 static checkout_conflictdata *checkout_conflicts_search_ancestor(
943 checkout_data *data,
944 const char *path)
945 {
946 size_t pos;
947
948 if (git_vector_bsearch2(&pos, &data->update_conflicts, checkout_conflicts_cmp_ancestor, path) < 0)
949 return NULL;
950
951 return git_vector_get(&data->update_conflicts, pos);
952 }
953
954 static checkout_conflictdata *checkout_conflicts_search_branch(
955 checkout_data *data,
956 const char *path)
957 {
958 checkout_conflictdata *conflict;
959 size_t i;
960
961 git_vector_foreach(&data->update_conflicts, i, conflict) {
962 int cmp = -1;
963
964 if (conflict->ancestor)
965 break;
966
967 if (conflict->ours)
968 cmp = checkout_conflicts_cmp_entry(path, conflict->ours);
969 else if (conflict->theirs)
970 cmp = checkout_conflicts_cmp_entry(path, conflict->theirs);
971
972 if (cmp == 0)
973 return conflict;
974 }
975
976 return NULL;
977 }
978
979 static int checkout_conflicts_load_byname_entry(
980 checkout_conflictdata **ancestor_out,
981 checkout_conflictdata **ours_out,
982 checkout_conflictdata **theirs_out,
983 checkout_data *data,
984 const git_index_name_entry *name_entry)
985 {
986 checkout_conflictdata *ancestor, *ours = NULL, *theirs = NULL;
987 int error = 0;
988
989 *ancestor_out = NULL;
990 *ours_out = NULL;
991 *theirs_out = NULL;
992
993 if (!name_entry->ancestor) {
994 giterr_set(GITERR_INDEX, "A NAME entry exists without an ancestor");
995 error = -1;
996 goto done;
997 }
998
999 if (!name_entry->ours && !name_entry->theirs) {
1000 giterr_set(GITERR_INDEX, "A NAME entry exists without an ours or theirs");
1001 error = -1;
1002 goto done;
1003 }
1004
1005 if ((ancestor = checkout_conflicts_search_ancestor(data,
1006 name_entry->ancestor)) == NULL) {
1007 giterr_set(GITERR_INDEX,
1008 "A NAME entry referenced ancestor entry '%s' which does not exist in the main index",
1009 name_entry->ancestor);
1010 error = -1;
1011 goto done;
1012 }
1013
1014 if (name_entry->ours) {
1015 if (strcmp(name_entry->ancestor, name_entry->ours) == 0)
1016 ours = ancestor;
1017 else if ((ours = checkout_conflicts_search_branch(data, name_entry->ours)) == NULL ||
1018 ours->ours == NULL) {
1019 giterr_set(GITERR_INDEX,
1020 "A NAME entry referenced our entry '%s' which does not exist in the main index",
1021 name_entry->ours);
1022 error = -1;
1023 goto done;
1024 }
1025 }
1026
1027 if (name_entry->theirs) {
1028 if (strcmp(name_entry->ancestor, name_entry->theirs) == 0)
1029 theirs = ancestor;
1030 else if (name_entry->ours && strcmp(name_entry->ours, name_entry->theirs) == 0)
1031 theirs = ours;
1032 else if ((theirs = checkout_conflicts_search_branch(data, name_entry->theirs)) == NULL ||
1033 theirs->theirs == NULL) {
1034 giterr_set(GITERR_INDEX,
1035 "A NAME entry referenced their entry '%s' which does not exist in the main index",
1036 name_entry->theirs);
1037 error = -1;
1038 goto done;
1039 }
1040 }
1041
1042 *ancestor_out = ancestor;
1043 *ours_out = ours;
1044 *theirs_out = theirs;
1045
1046 done:
1047 return error;
1048 }
1049
1050 static int checkout_conflicts_coalesce_renames(
1051 checkout_data *data)
1052 {
1053 git_index *index;
1054 const git_index_name_entry *name_entry;
1055 checkout_conflictdata *ancestor_conflict, *our_conflict, *their_conflict;
1056 size_t i, names;
1057 int error = 0;
1058
1059 if ((index = git_iterator_get_index(data->target)) == NULL)
1060 return 0;
1061
1062 /* Juggle entries based on renames */
1063 names = git_index_name_entrycount(index);
1064
1065 for (i = 0; i < names; i++) {
1066 name_entry = git_index_name_get_byindex(index, i);
1067
1068 if ((error = checkout_conflicts_load_byname_entry(
1069 &ancestor_conflict, &our_conflict, &their_conflict,
1070 data, name_entry)) < 0)
1071 goto done;
1072
1073 if (our_conflict && our_conflict != ancestor_conflict) {
1074 ancestor_conflict->ours = our_conflict->ours;
1075 our_conflict->ours = NULL;
1076
1077 if (our_conflict->theirs)
1078 our_conflict->name_collision = 1;
1079
1080 if (our_conflict->name_collision)
1081 ancestor_conflict->name_collision = 1;
1082 }
1083
1084 if (their_conflict && their_conflict != ancestor_conflict) {
1085 ancestor_conflict->theirs = their_conflict->theirs;
1086 their_conflict->theirs = NULL;
1087
1088 if (their_conflict->ours)
1089 their_conflict->name_collision = 1;
1090
1091 if (their_conflict->name_collision)
1092 ancestor_conflict->name_collision = 1;
1093 }
1094
1095 if (our_conflict && our_conflict != ancestor_conflict &&
1096 their_conflict && their_conflict != ancestor_conflict)
1097 ancestor_conflict->one_to_two = 1;
1098 }
1099
1100 git_vector_remove_matching(
1101 &data->update_conflicts, checkout_conflictdata_empty, NULL);
1102
1103 done:
1104 return error;
1105 }
1106
1107 static int checkout_conflicts_mark_directoryfile(
1108 checkout_data *data)
1109 {
1110 git_index *index;
1111 checkout_conflictdata *conflict;
1112 const git_index_entry *entry;
1113 size_t i, j, len;
1114 const char *path;
1115 int prefixed, error = 0;
1116
1117 if ((index = git_iterator_get_index(data->target)) == NULL)
1118 return 0;
1119
1120 len = git_index_entrycount(index);
1121
1122 /* Find d/f conflicts */
1123 git_vector_foreach(&data->update_conflicts, i, conflict) {
1124 if ((conflict->ours && conflict->theirs) ||
1125 (!conflict->ours && !conflict->theirs))
1126 continue;
1127
1128 path = conflict->ours ?
1129 conflict->ours->path : conflict->theirs->path;
1130
1131 if ((error = git_index_find(&j, index, path)) < 0) {
1132 if (error == GIT_ENOTFOUND)
1133 giterr_set(GITERR_INDEX,
1134 "Index inconsistency, could not find entry for expected conflict '%s'", path);
1135
1136 goto done;
1137 }
1138
1139 for (; j < len; j++) {
1140 if ((entry = git_index_get_byindex(index, j)) == NULL) {
1141 giterr_set(GITERR_INDEX,
1142 "Index inconsistency, truncated index while loading expected conflict '%s'", path);
1143 error = -1;
1144 goto done;
1145 }
1146
1147 prefixed = git_path_equal_or_prefixed(path, entry->path, NULL);
1148
1149 if (prefixed == GIT_PATH_EQUAL)
1150 continue;
1151
1152 if (prefixed == GIT_PATH_PREFIX)
1153 conflict->directoryfile = 1;
1154
1155 break;
1156 }
1157 }
1158
1159 done:
1160 return error;
1161 }
1162
1163 static int checkout_get_update_conflicts(
1164 checkout_data *data,
1165 git_iterator *workdir,
1166 git_vector *pathspec)
1167 {
1168 int error = 0;
1169
1170 if (data->strategy & GIT_CHECKOUT_SKIP_UNMERGED)
1171 return 0;
1172
1173 if ((error = checkout_conflicts_load(data, workdir, pathspec)) < 0 ||
1174 (error = checkout_conflicts_coalesce_renames(data)) < 0 ||
1175 (error = checkout_conflicts_mark_directoryfile(data)) < 0)
1176 goto done;
1177
1178 done:
1179 return error;
1180 }
1181
1182 static int checkout_conflict_append_remove(
1183 const git_index_entry *ancestor,
1184 const git_index_entry *ours,
1185 const git_index_entry *theirs,
1186 void *payload)
1187 {
1188 checkout_data *data = payload;
1189 const char *name;
1190
1191 assert(ancestor || ours || theirs);
1192
1193 if (ancestor)
1194 name = git__strdup(ancestor->path);
1195 else if (ours)
1196 name = git__strdup(ours->path);
1197 else if (theirs)
1198 name = git__strdup(theirs->path);
1199 else
1200 abort();
1201
1202 GITERR_CHECK_ALLOC(name);
1203
1204 return git_vector_insert(&data->remove_conflicts, (char *)name);
1205 }
1206
1207 static int checkout_get_remove_conflicts(
1208 checkout_data *data,
1209 git_iterator *workdir,
1210 git_vector *pathspec)
1211 {
1212 if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) != 0)
1213 return 0;
1214
1215 return checkout_conflicts_foreach(data, data->index, workdir, pathspec, checkout_conflict_append_remove, data);
1216 }
1217
1218 static int checkout_verify_paths(
1219 git_repository *repo,
1220 int action,
1221 git_diff_delta *delta)
1222 {
1223 unsigned int flags = GIT_PATH_REJECT_DEFAULTS | GIT_PATH_REJECT_DOT_GIT;
1224
1225 if (action & CHECKOUT_ACTION__REMOVE) {
1226 if (!git_path_isvalid(repo, delta->old_file.path, flags)) {
1227 giterr_set(GITERR_CHECKOUT, "Cannot remove invalid path '%s'", delta->old_file.path);
1228 return -1;
1229 }
1230 }
1231
1232 if (action & ~CHECKOUT_ACTION__REMOVE) {
1233 if (!git_path_isvalid(repo, delta->new_file.path, flags)) {
1234 giterr_set(GITERR_CHECKOUT, "Cannot checkout to invalid path '%s'", delta->new_file.path);
1235 return -1;
1236 }
1237 }
1238
1239 return 0;
1240 }
1241
1242 static int checkout_get_actions(
1243 uint32_t **actions_ptr,
1244 size_t **counts_ptr,
1245 checkout_data *data,
1246 git_iterator *workdir)
1247 {
1248 int error = 0, act;
1249 const git_index_entry *wditem;
1250 git_vector pathspec = GIT_VECTOR_INIT, *deltas;
1251 git_pool pathpool = GIT_POOL_INIT_STRINGPOOL;
1252 git_diff_delta *delta;
1253 size_t i, *counts = NULL;
1254 uint32_t *actions = NULL;
1255
1256 if (data->opts.paths.count > 0 &&
1257 git_pathspec__vinit(&pathspec, &data->opts.paths, &pathpool) < 0)
1258 return -1;
1259
1260 if ((error = git_iterator_current(&wditem, workdir)) < 0 &&
1261 error != GIT_ITEROVER)
1262 goto fail;
1263
1264 deltas = &data->diff->deltas;
1265
1266 *counts_ptr = counts = git__calloc(CHECKOUT_ACTION__MAX+1, sizeof(size_t));
1267 *actions_ptr = actions = git__calloc(
1268 deltas->length ? deltas->length : 1, sizeof(uint32_t));
1269 if (!counts || !actions) {
1270 error = -1;
1271 goto fail;
1272 }
1273
1274 git_vector_foreach(deltas, i, delta) {
1275 if ((error = checkout_action(&act, data, delta, workdir, &wditem, &pathspec)) == 0)
1276 error = checkout_verify_paths(data->repo, act, delta);
1277
1278 if (error != 0)
1279 goto fail;
1280
1281 actions[i] = act;
1282
1283 if (act & CHECKOUT_ACTION__REMOVE)
1284 counts[CHECKOUT_ACTION__REMOVE]++;
1285 if (act & CHECKOUT_ACTION__UPDATE_BLOB)
1286 counts[CHECKOUT_ACTION__UPDATE_BLOB]++;
1287 if (act & CHECKOUT_ACTION__UPDATE_SUBMODULE)
1288 counts[CHECKOUT_ACTION__UPDATE_SUBMODULE]++;
1289 if (act & CHECKOUT_ACTION__CONFLICT)
1290 counts[CHECKOUT_ACTION__CONFLICT]++;
1291 }
1292
1293 error = checkout_remaining_wd_items(data, workdir, wditem, &pathspec);
1294 if (error)
1295 goto fail;
1296
1297 counts[CHECKOUT_ACTION__REMOVE] += data->removes.length;
1298
1299 if (counts[CHECKOUT_ACTION__CONFLICT] > 0 &&
1300 (data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0)
1301 {
1302 giterr_set(GITERR_CHECKOUT, "%d %s checkout",
1303 (int)counts[CHECKOUT_ACTION__CONFLICT],
1304 counts[CHECKOUT_ACTION__CONFLICT] == 1 ?
1305 "conflict prevents" : "conflicts prevent");
1306 error = GIT_ECONFLICT;
1307 goto fail;
1308 }
1309
1310
1311 if ((error = checkout_get_remove_conflicts(data, workdir, &pathspec)) < 0 ||
1312 (error = checkout_get_update_conflicts(data, workdir, &pathspec)) < 0)
1313 goto fail;
1314
1315 counts[CHECKOUT_ACTION__REMOVE_CONFLICT] = git_vector_length(&data->remove_conflicts);
1316 counts[CHECKOUT_ACTION__UPDATE_CONFLICT] = git_vector_length(&data->update_conflicts);
1317
1318 git_pathspec__vfree(&pathspec);
1319 git_pool_clear(&pathpool);
1320
1321 return 0;
1322
1323 fail:
1324 *counts_ptr = NULL;
1325 git__free(counts);
1326 *actions_ptr = NULL;
1327 git__free(actions);
1328
1329 git_pathspec__vfree(&pathspec);
1330 git_pool_clear(&pathpool);
1331
1332 return error;
1333 }
1334
1335 static bool should_remove_existing(checkout_data *data)
1336 {
1337 int ignorecase = 0;
1338
1339 git_repository__cvar(&ignorecase, data->repo, GIT_CVAR_IGNORECASE);
1340
1341 return (ignorecase &&
1342 (data->strategy & GIT_CHECKOUT_DONT_REMOVE_EXISTING) == 0);
1343 }
1344
1345 #define MKDIR_NORMAL \
1346 GIT_MKDIR_PATH | GIT_MKDIR_VERIFY_DIR
1347 #define MKDIR_REMOVE_EXISTING \
1348 MKDIR_NORMAL | GIT_MKDIR_REMOVE_FILES | GIT_MKDIR_REMOVE_SYMLINKS
1349
1350 static int checkout_mkdir(
1351 checkout_data *data,
1352 const char *path,
1353 const char *base,
1354 mode_t mode,
1355 unsigned int flags)
1356 {
1357 struct git_futils_mkdir_options mkdir_opts = {0};
1358 int error;
1359
1360 mkdir_opts.dir_map = data->mkdir_map;
1361 mkdir_opts.pool = &data->pool;
1362
1363 error = git_futils_mkdir_ext(
1364 path, base, mode, flags, &mkdir_opts);
1365
1366 data->perfdata.mkdir_calls += mkdir_opts.perfdata.mkdir_calls;
1367 data->perfdata.stat_calls += mkdir_opts.perfdata.stat_calls;
1368 data->perfdata.chmod_calls += mkdir_opts.perfdata.chmod_calls;
1369
1370 return error;
1371 }
1372
1373 static int mkpath2file(
1374 checkout_data *data, const char *path, unsigned int mode)
1375 {
1376 struct stat st;
1377 bool remove_existing = should_remove_existing(data);
1378 unsigned int flags =
1379 (remove_existing ? MKDIR_REMOVE_EXISTING : MKDIR_NORMAL) |
1380 GIT_MKDIR_SKIP_LAST;
1381 int error;
1382
1383 if ((error = checkout_mkdir(
1384 data, path, data->opts.target_directory, mode, flags)) < 0)
1385 return error;
1386
1387 if (remove_existing) {
1388 data->perfdata.stat_calls++;
1389
1390 if (p_lstat(path, &st) == 0) {
1391
1392 /* Some file, symlink or folder already exists at this name.
1393 * We would have removed it in remove_the_old unless we're on
1394 * a case inensitive filesystem (or the user has asked us not
1395 * to). Remove the similarly named file to write the new.
1396 */
1397 error = git_futils_rmdir_r(path, NULL, GIT_RMDIR_REMOVE_FILES);
1398 } else if (errno != ENOENT) {
1399 giterr_set(GITERR_OS, "Failed to stat file '%s'", path);
1400 return GIT_EEXISTS;
1401 } else {
1402 giterr_clear();
1403 }
1404 }
1405
1406 return error;
1407 }
1408
1409 struct checkout_stream {
1410 git_writestream base;
1411 const char *path;
1412 int fd;
1413 int open;
1414 };
1415
1416 static int checkout_stream_write(
1417 git_writestream *s, const char *buffer, size_t len)
1418 {
1419 struct checkout_stream *stream = (struct checkout_stream *)s;
1420 int ret;
1421
1422 if ((ret = p_write(stream->fd, buffer, len)) < 0)
1423 giterr_set(GITERR_OS, "Could not write to '%s'", stream->path);
1424
1425 return ret;
1426 }
1427
1428 static int checkout_stream_close(git_writestream *s)
1429 {
1430 struct checkout_stream *stream = (struct checkout_stream *)s;
1431 assert(stream && stream->open);
1432
1433 stream->open = 0;
1434 return p_close(stream->fd);
1435 }
1436
1437 static void checkout_stream_free(git_writestream *s)
1438 {
1439 GIT_UNUSED(s);
1440 }
1441
1442 static int blob_content_to_file(
1443 checkout_data *data,
1444 struct stat *st,
1445 git_blob *blob,
1446 const char *path,
1447 const char *hint_path,
1448 mode_t entry_filemode)
1449 {
1450 int flags = data->opts.file_open_flags;
1451 mode_t file_mode = data->opts.file_mode ?
1452 data->opts.file_mode : entry_filemode;
1453 git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
1454 struct checkout_stream writer;
1455 mode_t mode;
1456 git_filter_list *fl = NULL;
1457 int fd;
1458 int error = 0;
1459
1460 if (hint_path == NULL)
1461 hint_path = path;
1462
1463 if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0)
1464 return error;
1465
1466 if (flags <= 0)
1467 flags = O_CREAT | O_TRUNC | O_WRONLY;
1468 if (!(mode = file_mode))
1469 mode = GIT_FILEMODE_BLOB;
1470
1471 if ((fd = p_open(path, flags, mode)) < 0) {
1472 giterr_set(GITERR_OS, "Could not open '%s' for writing", path);
1473 return fd;
1474 }
1475
1476 filter_opts.attr_session = &data->attr_session;
1477 filter_opts.temp_buf = &data->tmp;
1478
1479 if (!data->opts.disable_filters &&
1480 (error = git_filter_list__load_ext(
1481 &fl, data->repo, blob, hint_path,
1482 GIT_FILTER_TO_WORKTREE, &filter_opts)))
1483 return error;
1484
1485 /* setup the writer */
1486 memset(&writer, 0, sizeof(struct checkout_stream));
1487 writer.base.write = checkout_stream_write;
1488 writer.base.close = checkout_stream_close;
1489 writer.base.free = checkout_stream_free;
1490 writer.path = path;
1491 writer.fd = fd;
1492 writer.open = 1;
1493
1494 error = git_filter_list_stream_blob(fl, blob, &writer.base);
1495
1496 assert(writer.open == 0);
1497
1498 git_filter_list_free(fl);
1499
1500 if (error < 0)
1501 return error;
1502
1503 if (GIT_PERMS_IS_EXEC(mode)) {
1504 data->perfdata.chmod_calls++;
1505
1506 if ((error = p_chmod(path, mode)) < 0) {
1507 giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path);
1508 return error;
1509 }
1510 }
1511
1512 if (st) {
1513 data->perfdata.stat_calls++;
1514
1515 if ((error = p_stat(path, st)) < 0) {
1516 giterr_set(GITERR_OS, "Error statting '%s'", path);
1517 return error;
1518 }
1519
1520 st->st_mode = entry_filemode;
1521 }
1522
1523 return 0;
1524 }
1525
1526 static int blob_content_to_link(
1527 checkout_data *data,
1528 struct stat *st,
1529 git_blob *blob,
1530 const char *path)
1531 {
1532 git_buf linktarget = GIT_BUF_INIT;
1533 int error;
1534
1535 if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0)
1536 return error;
1537
1538 if ((error = git_blob__getbuf(&linktarget, blob)) < 0)
1539 return error;
1540
1541 if (data->can_symlink) {
1542 if ((error = p_symlink(git_buf_cstr(&linktarget), path)) < 0)
1543 giterr_set(GITERR_OS, "Could not create symlink %s", path);
1544 } else {
1545 error = git_futils_fake_symlink(git_buf_cstr(&linktarget), path);
1546 }
1547
1548 if (!error) {
1549 data->perfdata.stat_calls++;
1550
1551 if ((error = p_lstat(path, st)) < 0)
1552 giterr_set(GITERR_CHECKOUT, "Could not stat symlink %s", path);
1553
1554 st->st_mode = GIT_FILEMODE_LINK;
1555 }
1556
1557 git_buf_free(&linktarget);
1558
1559 return error;
1560 }
1561
1562 static int checkout_update_index(
1563 checkout_data *data,
1564 const git_diff_file *file,
1565 struct stat *st)
1566 {
1567 git_index_entry entry;
1568
1569 if (!data->index)
1570 return 0;
1571
1572 memset(&entry, 0, sizeof(entry));
1573 entry.path = (char *)file->path; /* cast to prevent warning */
1574 git_index_entry__init_from_stat(&entry, st, true);
1575 git_oid_cpy(&entry.id, &file->id);
1576
1577 return git_index_add(data->index, &entry);
1578 }
1579
1580 static int checkout_submodule_update_index(
1581 checkout_data *data,
1582 const git_diff_file *file)
1583 {
1584 struct stat st;
1585
1586 /* update the index unless prevented */
1587 if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) != 0)
1588 return 0;
1589
1590 git_buf_truncate(&data->path, data->workdir_len);
1591 if (git_buf_puts(&data->path, file->path) < 0)
1592 return -1;
1593
1594 data->perfdata.stat_calls++;
1595 if (p_stat(git_buf_cstr(&data->path), &st) < 0) {
1596 giterr_set(
1597 GITERR_CHECKOUT, "Could not stat submodule %s\n", file->path);
1598 return GIT_ENOTFOUND;
1599 }
1600
1601 st.st_mode = GIT_FILEMODE_COMMIT;
1602
1603 return checkout_update_index(data, file, &st);
1604 }
1605
1606 static int checkout_submodule(
1607 checkout_data *data,
1608 const git_diff_file *file)
1609 {
1610 bool remove_existing = should_remove_existing(data);
1611 int error = 0;
1612
1613 /* Until submodules are supported, UPDATE_ONLY means do nothing here */
1614 if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0)
1615 return 0;
1616
1617 if ((error = checkout_mkdir(
1618 data,
1619 file->path, data->opts.target_directory, data->opts.dir_mode,
1620 remove_existing ? MKDIR_REMOVE_EXISTING : MKDIR_NORMAL)) < 0)
1621 return error;
1622
1623 if ((error = git_submodule_lookup(NULL, data->repo, file->path)) < 0) {
1624 /* I've observed repos with submodules in the tree that do not
1625 * have a .gitmodules - core Git just makes an empty directory
1626 */
1627 if (error == GIT_ENOTFOUND) {
1628 giterr_clear();
1629 return checkout_submodule_update_index(data, file);
1630 }
1631
1632 return error;
1633 }
1634
1635 /* TODO: Support checkout_strategy options. Two circumstances:
1636 * 1 - submodule already checked out, but we need to move the HEAD
1637 * to the new OID, or
1638 * 2 - submodule not checked out and we should recursively check it out
1639 *
1640 * Checkout will not execute a pull on the submodule, but a clone
1641 * command should probably be able to. Do we need a submodule callback?
1642 */
1643
1644 return checkout_submodule_update_index(data, file);
1645 }
1646
1647 static void report_progress(
1648 checkout_data *data,
1649 const char *path)
1650 {
1651 if (data->opts.progress_cb)
1652 data->opts.progress_cb(
1653 path, data->completed_steps, data->total_steps,
1654 data->opts.progress_payload);
1655 }
1656
1657 static int checkout_safe_for_update_only(
1658 checkout_data *data, const char *path, mode_t expected_mode)
1659 {
1660 struct stat st;
1661
1662 data->perfdata.stat_calls++;
1663
1664 if (p_lstat(path, &st) < 0) {
1665 /* if doesn't exist, then no error and no update */
1666 if (errno == ENOENT || errno == ENOTDIR)
1667 return 0;
1668
1669 /* otherwise, stat error and no update */
1670 giterr_set(GITERR_OS, "Failed to stat file '%s'", path);
1671 return -1;
1672 }
1673
1674 /* only safe for update if this is the same type of file */
1675 if ((st.st_mode & ~0777) == (expected_mode & ~0777))
1676 return 1;
1677
1678 return 0;
1679 }
1680
1681 static int checkout_write_content(
1682 checkout_data *data,
1683 const git_oid *oid,
1684 const char *full_path,
1685 const char *hint_path,
1686 unsigned int mode,
1687 struct stat *st)
1688 {
1689 int error = 0;
1690 git_blob *blob;
1691
1692 if ((error = git_blob_lookup(&blob, data->repo, oid)) < 0)
1693 return error;
1694
1695 if (S_ISLNK(mode))
1696 error = blob_content_to_link(data, st, blob, full_path);
1697 else
1698 error = blob_content_to_file(data, st, blob, full_path, hint_path, mode);
1699
1700 git_blob_free(blob);
1701
1702 /* if we try to create the blob and an existing directory blocks it from
1703 * being written, then there must have been a typechange conflict in a
1704 * parent directory - suppress the error and try to continue.
1705 */
1706 if ((data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) != 0 &&
1707 (error == GIT_ENOTFOUND || error == GIT_EEXISTS))
1708 {
1709 giterr_clear();
1710 error = 0;
1711 }
1712
1713 return error;
1714 }
1715
1716 static int checkout_blob(
1717 checkout_data *data,
1718 const git_diff_file *file)
1719 {
1720 int error = 0;
1721 struct stat st;
1722
1723 git_buf_truncate(&data->path, data->workdir_len);
1724 if (git_buf_puts(&data->path, file->path) < 0)
1725 return -1;
1726
1727 if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) {
1728 int rval = checkout_safe_for_update_only(
1729 data, git_buf_cstr(&data->path), file->mode);
1730 if (rval <= 0)
1731 return rval;
1732 }
1733
1734 error = checkout_write_content(
1735 data, &file->id, git_buf_cstr(&data->path), NULL, file->mode, &st);
1736
1737 /* update the index unless prevented */
1738 if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
1739 error = checkout_update_index(data, file, &st);
1740
1741 /* update the submodule data if this was a new .gitmodules file */
1742 if (!error && strcmp(file->path, ".gitmodules") == 0)
1743 data->reload_submodules = true;
1744
1745 return error;
1746 }
1747
1748 static int checkout_remove_the_old(
1749 unsigned int *actions,
1750 checkout_data *data)
1751 {
1752 int error = 0;
1753 git_diff_delta *delta;
1754 const char *str;
1755 size_t i;
1756 const char *workdir = git_buf_cstr(&data->path);
1757 uint32_t flg = GIT_RMDIR_EMPTY_PARENTS |
1758 GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS;
1759
1760 if (data->opts.checkout_strategy & GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES)
1761 flg |= GIT_RMDIR_SKIP_NONEMPTY;
1762
1763 git_buf_truncate(&data->path, data->workdir_len);
1764
1765 git_vector_foreach(&data->diff->deltas, i, delta) {
1766 if (actions[i] & CHECKOUT_ACTION__REMOVE) {
1767 error = git_futils_rmdir_r(delta->old_file.path, workdir, flg);
1768 if (error < 0)
1769 return error;
1770
1771 data->completed_steps++;
1772 report_progress(data, delta->old_file.path);
1773
1774 if ((actions[i] & CHECKOUT_ACTION__UPDATE_BLOB) == 0 &&
1775 (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0 &&
1776 data->index != NULL)
1777 {
1778 (void)git_index_remove(data->index, delta->old_file.path, 0);
1779 }
1780 }
1781 }
1782
1783 git_vector_foreach(&data->removes, i, str) {
1784 error = git_futils_rmdir_r(str, workdir, flg);
1785 if (error < 0)
1786 return error;
1787
1788 data->completed_steps++;
1789 report_progress(data, str);
1790
1791 if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0 &&
1792 data->index != NULL)
1793 {
1794 if (str[strlen(str) - 1] == '/')
1795 (void)git_index_remove_directory(data->index, str, 0);
1796 else
1797 (void)git_index_remove(data->index, str, 0);
1798 }
1799 }
1800
1801 return 0;
1802 }
1803
1804 static int checkout_deferred_remove(git_repository *repo, const char *path)
1805 {
1806 #if 0
1807 int error = git_futils_rmdir_r(
1808 path, data->opts.target_directory, GIT_RMDIR_EMPTY_PARENTS);
1809
1810 if (error == GIT_ENOTFOUND) {
1811 error = 0;
1812 giterr_clear();
1813 }
1814
1815 return error;
1816 #else
1817 GIT_UNUSED(repo);
1818 GIT_UNUSED(path);
1819 assert(false);
1820 return 0;
1821 #endif
1822 }
1823
1824 static int checkout_create_the_new(
1825 unsigned int *actions,
1826 checkout_data *data)
1827 {
1828 int error = 0;
1829 git_diff_delta *delta;
1830 size_t i;
1831
1832 git_vector_foreach(&data->diff->deltas, i, delta) {
1833 if (actions[i] & CHECKOUT_ACTION__DEFER_REMOVE) {
1834 /* this had a blocker directory that should only be removed iff
1835 * all of the contents of the directory were safely removed
1836 */
1837 if ((error = checkout_deferred_remove(
1838 data->repo, delta->old_file.path)) < 0)
1839 return error;
1840 }
1841
1842 if (actions[i] & CHECKOUT_ACTION__UPDATE_BLOB) {
1843 error = checkout_blob(data, &delta->new_file);
1844 if (error < 0)
1845 return error;
1846
1847 data->completed_steps++;
1848 report_progress(data, delta->new_file.path);
1849 }
1850 }
1851
1852 return 0;
1853 }
1854
1855 static int checkout_create_submodules(
1856 unsigned int *actions,
1857 checkout_data *data)
1858 {
1859 int error = 0;
1860 git_diff_delta *delta;
1861 size_t i;
1862
1863 git_vector_foreach(&data->diff->deltas, i, delta) {
1864 if (actions[i] & CHECKOUT_ACTION__DEFER_REMOVE) {
1865 /* this has a blocker directory that should only be removed iff
1866 * all of the contents of the directory were safely removed
1867 */
1868 if ((error = checkout_deferred_remove(
1869 data->repo, delta->old_file.path)) < 0)
1870 return error;
1871 }
1872
1873 if (actions[i] & CHECKOUT_ACTION__UPDATE_SUBMODULE) {
1874 int error = checkout_submodule(data, &delta->new_file);
1875 if (error < 0)
1876 return error;
1877
1878 data->completed_steps++;
1879 report_progress(data, delta->new_file.path);
1880 }
1881 }
1882
1883 return 0;
1884 }
1885
1886 static int checkout_lookup_head_tree(git_tree **out, git_repository *repo)
1887 {
1888 int error = 0;
1889 git_reference *ref = NULL;
1890 git_object *head;
1891
1892 if (!(error = git_repository_head(&ref, repo)) &&
1893 !(error = git_reference_peel(&head, ref, GIT_OBJ_TREE)))
1894 *out = (git_tree *)head;
1895
1896 git_reference_free(ref);
1897
1898 return error;
1899 }
1900
1901
1902 static int conflict_entry_name(
1903 git_buf *out,
1904 const char *side_name,
1905 const char *filename)
1906 {
1907 if (git_buf_puts(out, side_name) < 0 ||
1908 git_buf_putc(out, ':') < 0 ||
1909 git_buf_puts(out, filename) < 0)
1910 return -1;
1911
1912 return 0;
1913 }
1914
1915 static int checkout_path_suffixed(git_buf *path, const char *suffix)
1916 {
1917 size_t path_len;
1918 int i = 0, error = 0;
1919
1920 if ((error = git_buf_putc(path, '~')) < 0 || (error = git_buf_puts(path, suffix)) < 0)
1921 return -1;
1922
1923 path_len = git_buf_len(path);
1924
1925 while (git_path_exists(git_buf_cstr(path)) && i < INT_MAX) {
1926 git_buf_truncate(path, path_len);
1927
1928 if ((error = git_buf_putc(path, '_')) < 0 ||
1929 (error = git_buf_printf(path, "%d", i)) < 0)
1930 return error;
1931
1932 i++;
1933 }
1934
1935 if (i == INT_MAX) {
1936 git_buf_truncate(path, path_len);
1937
1938 giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path);
1939 return GIT_EEXISTS;
1940 }
1941
1942 return 0;
1943 }
1944
1945 static int checkout_write_entry(
1946 checkout_data *data,
1947 checkout_conflictdata *conflict,
1948 const git_index_entry *side)
1949 {
1950 const char *hint_path = NULL, *suffix;
1951 struct stat st;
1952 int error;
1953
1954 assert (side == conflict->ours || side == conflict->theirs);
1955
1956 git_buf_truncate(&data->path, data->workdir_len);
1957 if (git_buf_puts(&data->path, side->path) < 0)
1958 return -1;
1959
1960 if ((conflict->name_collision || conflict->directoryfile) &&
1961 (data->strategy & GIT_CHECKOUT_USE_OURS) == 0 &&
1962 (data->strategy & GIT_CHECKOUT_USE_THEIRS) == 0) {
1963
1964 if (side == conflict->ours)
1965 suffix = data->opts.our_label ? data->opts.our_label :
1966 "ours";
1967 else
1968 suffix = data->opts.their_label ? data->opts.their_label :
1969 "theirs";
1970
1971 if (checkout_path_suffixed(&data->path, suffix) < 0)
1972 return -1;
1973
1974 hint_path = side->path;
1975 }
1976
1977 if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 &&
1978 (error = checkout_safe_for_update_only(data, git_buf_cstr(&data->path), side->mode)) <= 0)
1979 return error;
1980
1981 return checkout_write_content(data,
1982 &side->id, git_buf_cstr(&data->path), hint_path, side->mode, &st);
1983 }
1984
1985 static int checkout_write_entries(
1986 checkout_data *data,
1987 checkout_conflictdata *conflict)
1988 {
1989 int error = 0;
1990
1991 if ((error = checkout_write_entry(data, conflict, conflict->ours)) >= 0)
1992 error = checkout_write_entry(data, conflict, conflict->theirs);
1993
1994 return error;
1995 }
1996
1997 static int checkout_merge_path(
1998 git_buf *out,
1999 checkout_data *data,
2000 checkout_conflictdata *conflict,
2001 git_merge_file_result *result)
2002 {
2003 const char *our_label_raw, *their_label_raw, *suffix;
2004 int error = 0;
2005
2006 if ((error = git_buf_joinpath(out, git_repository_workdir(data->repo), result->path)) < 0)
2007 return error;
2008
2009 /* Most conflicts simply use the filename in the index */
2010 if (!conflict->name_collision)
2011 return 0;
2012
2013 /* Rename 2->1 conflicts need the branch name appended */
2014 our_label_raw = data->opts.our_label ? data->opts.our_label : "ours";
2015 their_label_raw = data->opts.their_label ? data->opts.their_label : "theirs";
2016 suffix = strcmp(result->path, conflict->ours->path) == 0 ? our_label_raw : their_label_raw;
2017
2018 if ((error = checkout_path_suffixed(out, suffix)) < 0)
2019 return error;
2020
2021 return 0;
2022 }
2023
2024 static int checkout_write_merge(
2025 checkout_data *data,
2026 checkout_conflictdata *conflict)
2027 {
2028 git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
2029 path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT,
2030 in_data = GIT_BUF_INIT, out_data = GIT_BUF_INIT;
2031 git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
2032 git_merge_file_result result = {0};
2033 git_filebuf output = GIT_FILEBUF_INIT;
2034 git_filter_list *fl = NULL;
2035 git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
2036 int error = 0;
2037
2038 if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
2039 opts.flags |= GIT_MERGE_FILE_STYLE_DIFF3;
2040
2041 opts.ancestor_label = data->opts.ancestor_label ?
2042 data->opts.ancestor_label : "ancestor";
2043 opts.our_label = data->opts.our_label ?
2044 data->opts.our_label : "ours";
2045 opts.their_label = data->opts.their_label ?
2046 data->opts.their_label : "theirs";
2047
2048 /* If all the paths are identical, decorate the diff3 file with the branch
2049 * names. Otherwise, append branch_name:path.
2050 */
2051 if (conflict->ours && conflict->theirs &&
2052 strcmp(conflict->ours->path, conflict->theirs->path) != 0) {
2053
2054 if ((error = conflict_entry_name(
2055 &our_label, opts.our_label, conflict->ours->path)) < 0 ||
2056 (error = conflict_entry_name(
2057 &their_label, opts.their_label, conflict->theirs->path)) < 0)
2058 goto done;
2059
2060 opts.our_label = git_buf_cstr(&our_label);
2061 opts.their_label = git_buf_cstr(&their_label);
2062 }
2063
2064 if ((error = git_merge_file_from_index(&result, data->repo,
2065 conflict->ancestor, conflict->ours, conflict->theirs, &opts)) < 0)
2066 goto done;
2067
2068 if (result.path == NULL || result.mode == 0) {
2069 giterr_set(GITERR_CHECKOUT, "Could not merge contents of file");
2070 error = GIT_ECONFLICT;
2071 goto done;
2072 }
2073
2074 if ((error = checkout_merge_path(&path_workdir, data, conflict, &result)) < 0)
2075 goto done;
2076
2077 if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 &&
2078 (error = checkout_safe_for_update_only(data, git_buf_cstr(&path_workdir), result.mode)) <= 0)
2079 goto done;
2080
2081 if (!data->opts.disable_filters) {
2082 in_data.ptr = (char *)result.ptr;
2083 in_data.size = result.len;
2084
2085 filter_opts.attr_session = &data->attr_session;
2086 filter_opts.temp_buf = &data->tmp;
2087
2088 if ((error = git_filter_list__load_ext(
2089 &fl, data->repo, NULL, git_buf_cstr(&path_workdir),
2090 GIT_FILTER_TO_WORKTREE, &filter_opts)) < 0 ||
2091 (error = git_filter_list_apply_to_data(&out_data, fl, &in_data)) < 0)
2092 goto done;
2093 } else {
2094 out_data.ptr = (char *)result.ptr;
2095 out_data.size = result.len;
2096 }
2097
2098 if ((error = mkpath2file(data, path_workdir.ptr, data->opts.dir_mode)) < 0 ||
2099 (error = git_filebuf_open(&output, git_buf_cstr(&path_workdir), GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
2100 (error = git_filebuf_write(&output, out_data.ptr, out_data.size)) < 0 ||
2101 (error = git_filebuf_commit(&output)) < 0)
2102 goto done;
2103
2104 done:
2105 git_filter_list_free(fl);
2106
2107 git_buf_free(&out_data);
2108 git_buf_free(&our_label);
2109 git_buf_free(&their_label);
2110
2111 git_merge_file_result_free(&result);
2112 git_buf_free(&path_workdir);
2113 git_buf_free(&path_suffixed);
2114
2115 return error;
2116 }
2117
2118 static int checkout_conflict_add(
2119 checkout_data *data,
2120 const git_index_entry *conflict)
2121 {
2122 int error = git_index_remove(data->index, conflict->path, 0);
2123
2124 if (error == GIT_ENOTFOUND)
2125 giterr_clear();
2126 else if (error < 0)
2127 return error;
2128
2129 return git_index_add(data->index, conflict);
2130 }
2131
2132 static int checkout_conflict_update_index(
2133 checkout_data *data,
2134 checkout_conflictdata *conflict)
2135 {
2136 int error = 0;
2137
2138 if (conflict->ancestor)
2139 error = checkout_conflict_add(data, conflict->ancestor);
2140
2141 if (!error && conflict->ours)
2142 error = checkout_conflict_add(data, conflict->ours);
2143
2144 if (!error && conflict->theirs)
2145 error = checkout_conflict_add(data, conflict->theirs);
2146
2147 return error;
2148 }
2149
2150 static int checkout_create_conflicts(checkout_data *data)
2151 {
2152 checkout_conflictdata *conflict;
2153 size_t i;
2154 int error = 0;
2155
2156 git_vector_foreach(&data->update_conflicts, i, conflict) {
2157
2158 /* Both deleted: nothing to do */
2159 if (conflict->ours == NULL && conflict->theirs == NULL)
2160 error = 0;
2161
2162 else if ((data->strategy & GIT_CHECKOUT_USE_OURS) &&
2163 conflict->ours)
2164 error = checkout_write_entry(data, conflict, conflict->ours);
2165 else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) &&
2166 conflict->theirs)
2167 error = checkout_write_entry(data, conflict, conflict->theirs);
2168
2169 /* Ignore the other side of name collisions. */
2170 else if ((data->strategy & GIT_CHECKOUT_USE_OURS) &&
2171 !conflict->ours && conflict->name_collision)
2172 error = 0;
2173 else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) &&
2174 !conflict->theirs && conflict->name_collision)
2175 error = 0;
2176
2177 /* For modify/delete, name collisions and d/f conflicts, write
2178 * the file (potentially with the name mangled.
2179 */
2180 else if (conflict->ours != NULL && conflict->theirs == NULL)
2181 error = checkout_write_entry(data, conflict, conflict->ours);
2182 else if (conflict->ours == NULL && conflict->theirs != NULL)
2183 error = checkout_write_entry(data, conflict, conflict->theirs);
2184
2185 /* Add/add conflicts and rename 1->2 conflicts, write the
2186 * ours/theirs sides (potentially name mangled).
2187 */
2188 else if (conflict->one_to_two)
2189 error = checkout_write_entries(data, conflict);
2190
2191 /* If all sides are links, write the ours side */
2192 else if (S_ISLNK(conflict->ours->mode) &&
2193 S_ISLNK(conflict->theirs->mode))
2194 error = checkout_write_entry(data, conflict, conflict->ours);
2195 /* Link/file conflicts, write the file side */
2196 else if (S_ISLNK(conflict->ours->mode))
2197 error = checkout_write_entry(data, conflict, conflict->theirs);
2198 else if (S_ISLNK(conflict->theirs->mode))
2199 error = checkout_write_entry(data, conflict, conflict->ours);
2200
2201 /* If any side is a gitlink, do nothing. */
2202 else if (conflict->submodule)
2203 error = 0;
2204
2205 /* If any side is binary, write the ours side */
2206 else if (conflict->binary)
2207 error = checkout_write_entry(data, conflict, conflict->ours);
2208
2209 else if (!error)
2210 error = checkout_write_merge(data, conflict);
2211
2212 /* Update the index extensions (REUC and NAME) if we're checking
2213 * out a different index. (Otherwise just leave them there.)
2214 */
2215 if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
2216 error = checkout_conflict_update_index(data, conflict);
2217
2218 if (error)
2219 break;
2220
2221 data->completed_steps++;
2222 report_progress(data,
2223 conflict->ours ? conflict->ours->path :
2224 (conflict->theirs ? conflict->theirs->path : conflict->ancestor->path));
2225 }
2226
2227 return error;
2228 }
2229
2230 static int checkout_remove_conflicts(checkout_data *data)
2231 {
2232 const char *conflict;
2233 size_t i;
2234
2235 git_vector_foreach(&data->remove_conflicts, i, conflict) {
2236 if (git_index_conflict_remove(data->index, conflict) < 0)
2237 return -1;
2238
2239 data->completed_steps++;
2240 }
2241
2242 return 0;
2243 }
2244
2245 static int checkout_extensions_update_index(checkout_data *data)
2246 {
2247 const git_index_reuc_entry *reuc_entry;
2248 const git_index_name_entry *name_entry;
2249 size_t i;
2250 int error = 0;
2251
2252 if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0)
2253 return 0;
2254
2255 if (data->update_reuc) {
2256 git_vector_foreach(data->update_reuc, i, reuc_entry) {
2257 if ((error = git_index_reuc_add(data->index, reuc_entry->path,
2258 reuc_entry->mode[0], &reuc_entry->oid[0],
2259 reuc_entry->mode[1], &reuc_entry->oid[1],
2260 reuc_entry->mode[2], &reuc_entry->oid[2])) < 0)
2261 goto done;
2262 }
2263 }
2264
2265 if (data->update_names) {
2266 git_vector_foreach(data->update_names, i, name_entry) {
2267 if ((error = git_index_name_add(data->index, name_entry->ancestor,
2268 name_entry->ours, name_entry->theirs)) < 0)
2269 goto done;
2270 }
2271 }
2272
2273 done:
2274 return error;
2275 }
2276
2277 static void checkout_data_clear(checkout_data *data)
2278 {
2279 if (data->opts_free_baseline) {
2280 git_tree_free(data->opts.baseline);
2281 data->opts.baseline = NULL;
2282 }
2283
2284 git_vector_free(&data->removes);
2285 git_pool_clear(&data->pool);
2286
2287 git_vector_free_deep(&data->remove_conflicts);
2288 git_vector_free_deep(&data->update_conflicts);
2289
2290 git__free(data->pfx);
2291 data->pfx = NULL;
2292
2293 git_strmap_free(data->mkdir_map);
2294
2295 git_buf_free(&data->path);
2296 git_buf_free(&data->tmp);
2297
2298 git_index_free(data->index);
2299 data->index = NULL;
2300
2301 git_strmap_free(data->mkdir_map);
2302
2303 git_attr_session__free(&data->attr_session);
2304 }
2305
2306 static int checkout_data_init(
2307 checkout_data *data,
2308 git_iterator *target,
2309 const git_checkout_options *proposed)
2310 {
2311 int error = 0;
2312 git_repository *repo = git_iterator_owner(target);
2313
2314 memset(data, 0, sizeof(*data));
2315
2316 if (!repo) {
2317 giterr_set(GITERR_CHECKOUT, "Cannot checkout nothing");
2318 return -1;
2319 }
2320
2321 if ((!proposed || !proposed->target_directory) &&
2322 (error = git_repository__ensure_not_bare(repo, "checkout")) < 0)
2323 return error;
2324
2325 data->repo = repo;
2326 data->target = target;
2327
2328 GITERR_CHECK_VERSION(
2329 proposed, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options");
2330
2331 if (!proposed)
2332 GIT_INIT_STRUCTURE(&data->opts, GIT_CHECKOUT_OPTIONS_VERSION);
2333 else
2334 memmove(&data->opts, proposed, sizeof(git_checkout_options));
2335
2336 if (!data->opts.target_directory)
2337 data->opts.target_directory = git_repository_workdir(repo);
2338 else if (!git_path_isdir(data->opts.target_directory) &&
2339 (error = checkout_mkdir(data,
2340 data->opts.target_directory, NULL,
2341 GIT_DIR_MODE, GIT_MKDIR_VERIFY_DIR)) < 0)
2342 goto cleanup;
2343
2344 /* refresh config and index content unless NO_REFRESH is given */
2345 if ((data->opts.checkout_strategy & GIT_CHECKOUT_NO_REFRESH) == 0) {
2346 git_config *cfg;
2347
2348 if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
2349 goto cleanup;
2350
2351 /* Get the repository index and reload it (unless we're checking
2352 * out the index; then it has the changes we're trying to check
2353 * out and those should not be overwritten.)
2354 */
2355 if ((error = git_repository_index(&data->index, data->repo)) < 0)
2356 goto cleanup;
2357
2358 if (data->index != git_iterator_get_index(target)) {
2359 if ((error = git_index_read(data->index, true)) < 0)
2360 goto cleanup;
2361
2362 /* cannot checkout if unresolved conflicts exist */
2363 if ((data->opts.checkout_strategy & GIT_CHECKOUT_FORCE) == 0 &&
2364 git_index_has_conflicts(data->index)) {
2365 error = GIT_ECONFLICT;
2366 giterr_set(GITERR_CHECKOUT,
2367 "unresolved conflicts exist in the index");
2368 goto cleanup;
2369 }
2370
2371 /* clean conflict data in the current index */
2372 git_index_name_clear(data->index);
2373 git_index_reuc_clear(data->index);
2374 }
2375 }
2376
2377 /* if you are forcing, allow all safe updates, plus recreate missing */
2378 if ((data->opts.checkout_strategy & GIT_CHECKOUT_FORCE) != 0)
2379 data->opts.checkout_strategy |= GIT_CHECKOUT_SAFE |
2380 GIT_CHECKOUT_RECREATE_MISSING;
2381
2382 /* if the repository does not actually have an index file, then this
2383 * is an initial checkout (perhaps from clone), so we allow safe updates
2384 */
2385 if (!data->index->on_disk &&
2386 (data->opts.checkout_strategy & GIT_CHECKOUT_SAFE) != 0)
2387 data->opts.checkout_strategy |= GIT_CHECKOUT_RECREATE_MISSING;
2388
2389 data->strategy = data->opts.checkout_strategy;
2390
2391 /* opts->disable_filters is false by default */
2392
2393 if (!data->opts.dir_mode)
2394 data->opts.dir_mode = GIT_DIR_MODE;
2395
2396 if (!data->opts.file_open_flags)
2397 data->opts.file_open_flags = O_CREAT | O_TRUNC | O_WRONLY;
2398
2399 data->pfx = git_pathspec_prefix(&data->opts.paths);
2400
2401 if ((error = git_repository__cvar(
2402 &data->can_symlink, repo, GIT_CVAR_SYMLINKS)) < 0)
2403 goto cleanup;
2404
2405 if (!data->opts.baseline && !data->opts.baseline_index) {
2406 data->opts_free_baseline = true;
2407
2408 error = checkout_lookup_head_tree(&data->opts.baseline, repo);
2409
2410 if (error == GIT_EUNBORNBRANCH) {
2411 error = 0;
2412 giterr_clear();
2413 }
2414
2415 if (error < 0)
2416 goto cleanup;
2417 }
2418
2419 if ((data->opts.checkout_strategy &
2420 (GIT_CHECKOUT_CONFLICT_STYLE_MERGE | GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)) == 0) {
2421 git_config_entry *conflict_style = NULL;
2422 git_config *cfg = NULL;
2423
2424 if ((error = git_repository_config__weakptr(&cfg, repo)) < 0 ||
2425 (error = git_config_get_entry(&conflict_style, cfg, "merge.conflictstyle")) < 0 ||
2426 error == GIT_ENOTFOUND)
2427 ;
2428 else if (error)
2429 goto cleanup;
2430 else if (strcmp(conflict_style->value, "merge") == 0)
2431 data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_MERGE;
2432 else if (strcmp(conflict_style->value, "diff3") == 0)
2433 data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
2434 else {
2435 giterr_set(GITERR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'",
2436 conflict_style);
2437 error = -1;
2438 git_config_entry_free(conflict_style);
2439 goto cleanup;
2440 }
2441 git_config_entry_free(conflict_style);
2442 }
2443
2444 if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 ||
2445 (error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 ||
2446 (error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 ||
2447 (error = git_pool_init(&data->pool, 1, 0)) < 0 ||
2448 (error = git_buf_puts(&data->path, data->opts.target_directory)) < 0 ||
2449 (error = git_path_to_dir(&data->path)) < 0 ||
2450 (error = git_strmap_alloc(&data->mkdir_map)) < 0)
2451 goto cleanup;
2452
2453 data->workdir_len = git_buf_len(&data->path);
2454
2455 git_attr_session__init(&data->attr_session, data->repo);
2456
2457 cleanup:
2458 if (error < 0)
2459 checkout_data_clear(data);
2460
2461 return error;
2462 }
2463
2464 #define CHECKOUT_INDEX_DONT_WRITE_MASK \
2465 (GIT_CHECKOUT_DONT_UPDATE_INDEX | GIT_CHECKOUT_DONT_WRITE_INDEX)
2466
2467 int git_checkout_iterator(
2468 git_iterator *target,
2469 git_index *index,
2470 const git_checkout_options *opts)
2471 {
2472 int error = 0;
2473 git_iterator *baseline = NULL, *workdir = NULL;
2474 checkout_data data = {0};
2475 git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
2476 uint32_t *actions = NULL;
2477 size_t *counts = NULL;
2478 git_iterator_flag_t iterflags = 0;
2479
2480 /* initialize structures and options */
2481 error = checkout_data_init(&data, target, opts);
2482 if (error < 0)
2483 return error;
2484
2485 diff_opts.flags =
2486 GIT_DIFF_INCLUDE_UNMODIFIED |
2487 GIT_DIFF_INCLUDE_UNREADABLE |
2488 GIT_DIFF_INCLUDE_UNTRACKED |
2489 GIT_DIFF_RECURSE_UNTRACKED_DIRS | /* needed to match baseline */
2490 GIT_DIFF_INCLUDE_IGNORED |
2491 GIT_DIFF_INCLUDE_TYPECHANGE |
2492 GIT_DIFF_INCLUDE_TYPECHANGE_TREES |
2493 GIT_DIFF_SKIP_BINARY_CHECK |
2494 GIT_DIFF_INCLUDE_CASECHANGE;
2495 if (data.opts.checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)
2496 diff_opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
2497 if (data.opts.paths.count > 0)
2498 diff_opts.pathspec = data.opts.paths;
2499
2500 /* set up iterators */
2501
2502 iterflags = git_iterator_ignore_case(target) ?
2503 GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE;
2504
2505 if ((error = git_iterator_reset(target, data.pfx, data.pfx)) < 0 ||
2506 (error = git_iterator_for_workdir_ext(
2507 &workdir, data.repo, data.opts.target_directory, index, NULL,
2508 iterflags | GIT_ITERATOR_DONT_AUTOEXPAND,
2509 data.pfx, data.pfx)) < 0)
2510 goto cleanup;
2511
2512 if (data.opts.baseline_index) {
2513 if ((error = git_iterator_for_index(
2514 &baseline, data.opts.baseline_index,
2515 iterflags, data.pfx, data.pfx)) < 0)
2516 goto cleanup;
2517 } else {
2518 if ((error = git_iterator_for_tree(
2519 &baseline, data.opts.baseline,
2520 iterflags, data.pfx, data.pfx)) < 0)
2521 goto cleanup;
2522 }
2523
2524 /* Should not have case insensitivity mismatch */
2525 assert(git_iterator_ignore_case(workdir) == git_iterator_ignore_case(baseline));
2526
2527 /* Generate baseline-to-target diff which will include an entry for
2528 * every possible update that might need to be made.
2529 */
2530 if ((error = git_diff__from_iterators(
2531 &data.diff, data.repo, baseline, target, &diff_opts)) < 0)
2532 goto cleanup;
2533
2534 /* Loop through diff (and working directory iterator) building a list of
2535 * actions to be taken, plus look for conflicts and send notifications,
2536 * then loop through conflicts.
2537 */
2538 if ((error = checkout_get_actions(&actions, &counts, &data, workdir)) != 0)
2539 goto cleanup;
2540
2541 data.total_steps = counts[CHECKOUT_ACTION__REMOVE] +
2542 counts[CHECKOUT_ACTION__REMOVE_CONFLICT] +
2543 counts[CHECKOUT_ACTION__UPDATE_BLOB] +
2544 counts[CHECKOUT_ACTION__UPDATE_SUBMODULE] +
2545 counts[CHECKOUT_ACTION__UPDATE_CONFLICT];
2546
2547 report_progress(&data, NULL); /* establish 0 baseline */
2548
2549 /* To deal with some order dependencies, perform remaining checkout
2550 * in three passes: removes, then update blobs, then update submodules.
2551 */
2552 if (counts[CHECKOUT_ACTION__REMOVE] > 0 &&
2553 (error = checkout_remove_the_old(actions, &data)) < 0)
2554 goto cleanup;
2555
2556 if (counts[CHECKOUT_ACTION__REMOVE_CONFLICT] > 0 &&
2557 (error = checkout_remove_conflicts(&data)) < 0)
2558 goto cleanup;
2559
2560 if (counts[CHECKOUT_ACTION__UPDATE_BLOB] > 0 &&
2561 (error = checkout_create_the_new(actions, &data)) < 0)
2562 goto cleanup;
2563
2564 if (counts[CHECKOUT_ACTION__UPDATE_SUBMODULE] > 0 &&
2565 (error = checkout_create_submodules(actions, &data)) < 0)
2566 goto cleanup;
2567
2568 if (counts[CHECKOUT_ACTION__UPDATE_CONFLICT] > 0 &&
2569 (error = checkout_create_conflicts(&data)) < 0)
2570 goto cleanup;
2571
2572 if (data.index != git_iterator_get_index(target) &&
2573 (error = checkout_extensions_update_index(&data)) < 0)
2574 goto cleanup;
2575
2576 assert(data.completed_steps == data.total_steps);
2577
2578 if (data.opts.perfdata_cb)
2579 data.opts.perfdata_cb(&data.perfdata, data.opts.perfdata_payload);
2580
2581 cleanup:
2582 if (!error && data.index != NULL &&
2583 (data.strategy & CHECKOUT_INDEX_DONT_WRITE_MASK) == 0)
2584 error = git_index_write(data.index);
2585
2586 git_diff_free(data.diff);
2587 git_iterator_free(workdir);
2588 git_iterator_free(baseline);
2589 git__free(actions);
2590 git__free(counts);
2591 checkout_data_clear(&data);
2592
2593 return error;
2594 }
2595
2596 int git_checkout_index(
2597 git_repository *repo,
2598 git_index *index,
2599 const git_checkout_options *opts)
2600 {
2601 int error, owned = 0;
2602 git_iterator *index_i;
2603
2604 if (!index && !repo) {
2605 giterr_set(GITERR_CHECKOUT,
2606 "Must provide either repository or index to checkout");
2607 return -1;
2608 }
2609
2610 if (index && repo &&
2611 git_index_owner(index) &&
2612 git_index_owner(index) != repo) {
2613 giterr_set(GITERR_CHECKOUT,
2614 "Index to checkout does not match repository");
2615 return -1;
2616 } else if(index && repo && !git_index_owner(index)) {
2617 GIT_REFCOUNT_OWN(index, repo);
2618 owned = 1;
2619 }
2620
2621 if (!repo)
2622 repo = git_index_owner(index);
2623
2624 if (!index && (error = git_repository_index__weakptr(&index, repo)) < 0)
2625 return error;
2626 GIT_REFCOUNT_INC(index);
2627
2628 if (!(error = git_iterator_for_index(&index_i, index, 0, NULL, NULL)))
2629 error = git_checkout_iterator(index_i, index, opts);
2630
2631 if (owned)
2632 GIT_REFCOUNT_OWN(index, NULL);
2633
2634 git_iterator_free(index_i);
2635 git_index_free(index);
2636
2637 return error;
2638 }
2639
2640 int git_checkout_tree(
2641 git_repository *repo,
2642 const git_object *treeish,
2643 const git_checkout_options *opts)
2644 {
2645 int error;
2646 git_index *index;
2647 git_tree *tree = NULL;
2648 git_iterator *tree_i = NULL;
2649
2650 if (!treeish && !repo) {
2651 giterr_set(GITERR_CHECKOUT,
2652 "Must provide either repository or tree to checkout");
2653 return -1;
2654 }
2655 if (treeish && repo && git_object_owner(treeish) != repo) {
2656 giterr_set(GITERR_CHECKOUT,
2657 "Object to checkout does not match repository");
2658 return -1;
2659 }
2660
2661 if (!repo)
2662 repo = git_object_owner(treeish);
2663
2664 if (treeish) {
2665 if (git_object_peel((git_object **)&tree, treeish, GIT_OBJ_TREE) < 0) {
2666 giterr_set(
2667 GITERR_CHECKOUT, "Provided object cannot be peeled to a tree");
2668 return -1;
2669 }
2670 }
2671 else {
2672 if ((error = checkout_lookup_head_tree(&tree, repo)) < 0) {
2673 if (error != GIT_EUNBORNBRANCH)
2674 giterr_set(
2675 GITERR_CHECKOUT,
2676 "HEAD could not be peeled to a tree and no treeish given");
2677 return error;
2678 }
2679 }
2680
2681 if ((error = git_repository_index(&index, repo)) < 0)
2682 return error;
2683
2684 if (!(error = git_iterator_for_tree(&tree_i, tree, 0, NULL, NULL)))
2685 error = git_checkout_iterator(tree_i, index, opts);
2686
2687 git_iterator_free(tree_i);
2688 git_index_free(index);
2689 git_tree_free(tree);
2690
2691 return error;
2692 }
2693
2694 int git_checkout_head(
2695 git_repository *repo,
2696 const git_checkout_options *opts)
2697 {
2698 assert(repo);
2699 return git_checkout_tree(repo, NULL, opts);
2700 }
2701
2702 int git_checkout_init_options(git_checkout_options *opts, unsigned int version)
2703 {
2704 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
2705 opts, version, git_checkout_options, GIT_CHECKOUT_OPTIONS_INIT);
2706 return 0;
2707 }