stash.c 26 KB
Newer Older
nulltoken committed
1
/*
Edward Thomson committed
2
 * Copyright (C) the libgit2 contributors. All rights reserved.
nulltoken committed
3 4 5 6 7 8 9 10
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#include "common.h"
#include "repository.h"
#include "commit.h"
11
#include "message.h"
nulltoken committed
12 13 14 15 16 17
#include "tree.h"
#include "reflog.h"
#include "git2/diff.h"
#include "git2/stash.h"
#include "git2/status.h"
#include "git2/checkout.h"
18
#include "git2/index.h"
19
#include "git2/transaction.h"
20
#include "git2/merge.h"
21
#include "index.h"
Ben Straub committed
22
#include "signature.h"
23 24
#include "iterator.h"
#include "merge.h"
25
#include "diff.h"
nulltoken committed
26 27 28 29 30 31 32 33 34 35 36

static int create_error(int error, const char *msg)
{
	giterr_set(GITERR_STASH, "Cannot stash changes - %s", msg);
	return error;
}

static int retrieve_head(git_reference **out, git_repository *repo)
{
	int error = git_repository_head(out, repo);

37
	if (error == GIT_EUNBORNBRANCH)
nulltoken committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
		return create_error(error, "You do not have the initial commit yet.");

	return error;
}

static int append_abbreviated_oid(git_buf *out, const git_oid *b_commit)
{
	char *formatted_oid;

	formatted_oid = git_oid_allocfmt(b_commit);
	GITERR_CHECK_ALLOC(formatted_oid);

	git_buf_put(out, formatted_oid, 7);
	git__free(formatted_oid);

	return git_buf_oom(out) ? -1 : 0;
}

static int append_commit_description(git_buf *out, git_commit* commit)
{
58 59
	const char *summary = git_commit_summary(commit);
	GITERR_CHECK_ALLOC(summary);
nulltoken committed
60 61 62 63 64

	if (append_abbreviated_oid(out, git_commit_id(commit)) < 0)
		return -1;

	git_buf_putc(out, ' ');
65
	git_buf_puts(out, summary);
nulltoken committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
	git_buf_putc(out, '\n');

	return git_buf_oom(out) ? -1 : 0;
}

static int retrieve_base_commit_and_message(
	git_commit **b_commit,
	git_buf *stash_message,
	git_repository *repo)
{
	git_reference *head = NULL;
	int error;

	if ((error = retrieve_head(&head, repo)) < 0)
		return error;

	if (strcmp("HEAD", git_reference_name(head)) == 0)
83
		error = git_buf_puts(stash_message, "(no branch): ");
nulltoken committed
84
	else
85
		error = git_buf_printf(
nulltoken committed
86 87 88
			stash_message,
			"%s: ",
			git_reference_name(head) + strlen(GIT_REFS_HEADS_DIR));
89
	if (error < 0)
nulltoken committed
90 91
		goto cleanup;

92 93
	if ((error = git_commit_lookup(
			 b_commit, repo, git_reference_target(head))) < 0)
nulltoken committed
94 95
		goto cleanup;

96 97
	if ((error = append_commit_description(stash_message, *b_commit)) < 0)
		goto cleanup;
nulltoken committed
98 99 100 101 102 103 104 105

cleanup:
	git_reference_free(head);
	return error;
}

static int build_tree_from_index(git_tree **out, git_index *index)
{
106
	int error;
nulltoken committed
107 108
	git_oid i_tree_oid;

109
	if ((error = git_index_write_tree(&i_tree_oid, index)) < 0)
110
		return error;
nulltoken committed
111 112 113 114 115 116 117

	return git_tree_lookup(out, git_index_owner(index), &i_tree_oid);
}

static int commit_index(
	git_commit **i_commit,
	git_index *index,
118
	const git_signature *stasher,
nulltoken committed
119 120 121 122 123 124
	const char *message,
	const git_commit *parent)
{
	git_tree *i_tree = NULL;
	git_oid i_commit_oid;
	git_buf msg = GIT_BUF_INIT;
125
	int error;
nulltoken committed
126

127
	if ((error = build_tree_from_index(&i_tree, index)) < 0)
nulltoken committed
128 129
		goto cleanup;

130
	if ((error = git_buf_printf(&msg, "index on %s\n", message)) < 0)
nulltoken committed
131 132
		goto cleanup;

133
	if ((error = git_commit_create(
nulltoken committed
134 135 136 137 138 139 140 141 142
		&i_commit_oid,
		git_index_owner(index),
		NULL,
		stasher,
		stasher,
		NULL,
		git_buf_cstr(&msg),
		i_tree,
		1,
143 144
		&parent)) < 0)
		goto cleanup;
nulltoken committed
145 146 147 148 149 150 151 152 153

	error = git_commit_lookup(i_commit, git_index_owner(index), &i_commit_oid);

cleanup:
	git_tree_free(i_tree);
	git_buf_free(&msg);
	return error;
}

Russell Belfer committed
154
struct stash_update_rules {
nulltoken committed
155 156 157 158 159
	bool include_changed;
	bool include_untracked;
	bool include_ignored;
};

Russell Belfer committed
160 161 162 163
static int stash_update_index_from_diff(
	git_index *index,
	const git_diff *diff,
	struct stash_update_rules *data)
nulltoken committed
164
{
Russell Belfer committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178
	int error = 0;
	size_t d, max_d = git_diff_num_deltas(diff);

	for (d = 0; !error && d < max_d; ++d) {
		const char *add_path = NULL;
		const git_diff_delta *delta = git_diff_get_delta(diff, d);

		switch (delta->status) {
		case GIT_DELTA_IGNORED:
			if (data->include_ignored)
				add_path = delta->new_file.path;
			break;

		case GIT_DELTA_UNTRACKED:
179 180
			if (data->include_untracked &&
				delta->new_file.mode != GIT_FILEMODE_TREE)
Russell Belfer committed
181
				add_path = delta->new_file.path;
nulltoken committed
182 183
			break;

Russell Belfer committed
184 185 186 187 188
		case GIT_DELTA_ADDED:
		case GIT_DELTA_MODIFIED:
			if (data->include_changed)
				add_path = delta->new_file.path;
			break;
189

Russell Belfer committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
		case GIT_DELTA_DELETED:
			if (data->include_changed &&
				!git_index_find(NULL, index, delta->old_file.path))
				error = git_index_remove(index, delta->old_file.path, 0);
			break;

		default:
			/* Unimplemented */
			giterr_set(
				GITERR_INVALID,
				"Cannot update index. Unimplemented status (%d)",
				delta->status);
			return -1;
		}

		if (add_path != NULL)
			error = git_index_add_bypath(index, add_path);
	}

	return error;
nulltoken committed
210 211 212 213 214 215 216 217 218
}

static int build_untracked_tree(
	git_tree **tree_out,
	git_index *index,
	git_commit *i_commit,
	uint32_t flags)
{
	git_tree *i_tree = NULL;
219
	git_diff *diff = NULL;
220
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Russell Belfer committed
221
	struct stash_update_rules data = {0};
222
	int error;
nulltoken committed
223 224 225 226

	git_index_clear(index);

	if (flags & GIT_STASH_INCLUDE_UNTRACKED) {
227 228
		opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED |
			GIT_DIFF_RECURSE_UNTRACKED_DIRS;
nulltoken committed
229 230 231 232
		data.include_untracked = true;
	}

	if (flags & GIT_STASH_INCLUDE_IGNORED) {
233 234
		opts.flags |= GIT_DIFF_INCLUDE_IGNORED |
			GIT_DIFF_RECURSE_IGNORED_DIRS;
nulltoken committed
235 236 237
		data.include_ignored = true;
	}

238
	if ((error = git_commit_tree(&i_tree, i_commit)) < 0)
nulltoken committed
239 240
		goto cleanup;

241 242
	if ((error = git_diff_tree_to_workdir(
			&diff, git_index_owner(index), i_tree, &opts)) < 0)
nulltoken committed
243 244
		goto cleanup;

Russell Belfer committed
245
	if ((error = stash_update_index_from_diff(index, diff, &data)) < 0)
nulltoken committed
246 247
		goto cleanup;

248
	error = build_tree_from_index(tree_out, index);
nulltoken committed
249 250

cleanup:
251
	git_diff_free(diff);
nulltoken committed
252 253 254 255 256 257 258
	git_tree_free(i_tree);
	return error;
}

static int commit_untracked(
	git_commit **u_commit,
	git_index *index,
259
	const git_signature *stasher,
nulltoken committed
260 261 262 263 264 265 266
	const char *message,
	git_commit *i_commit,
	uint32_t flags)
{
	git_tree *u_tree = NULL;
	git_oid u_commit_oid;
	git_buf msg = GIT_BUF_INIT;
267
	int error;
nulltoken committed
268

269
	if ((error = build_untracked_tree(&u_tree, index, i_commit, flags)) < 0)
nulltoken committed
270 271
		goto cleanup;

272
	if ((error = git_buf_printf(&msg, "untracked files on %s\n", message)) < 0)
nulltoken committed
273 274
		goto cleanup;

275
	if ((error = git_commit_create(
nulltoken committed
276 277 278 279 280 281 282 283 284
		&u_commit_oid,
		git_index_owner(index),
		NULL,
		stasher,
		stasher,
		NULL,
		git_buf_cstr(&msg),
		u_tree,
		0,
285 286
		NULL)) < 0)
		goto cleanup;
nulltoken committed
287 288 289 290 291 292 293 294 295

	error = git_commit_lookup(u_commit, git_index_owner(index), &u_commit_oid);

cleanup:
	git_tree_free(u_tree);
	git_buf_free(&msg);
	return error;
}

296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
static git_diff_delta *stash_delta_merge(
	const git_diff_delta *a,
	const git_diff_delta *b,
	git_pool *pool)
{
	/* Special case for stash: if a file is deleted in the index, but exists
	 * in the working tree, we need to stash the workdir copy for the workdir.
	 */
	if (a->status == GIT_DELTA_DELETED && b->status == GIT_DELTA_UNTRACKED) {
		git_diff_delta *dup = git_diff__delta_dup(b, pool);

		if (dup)
			dup->status = GIT_DELTA_MODIFIED;
		return dup;
	}

	return git_diff__merge_like_cgit(a, b, pool);
}

nulltoken committed
315 316 317 318 319
static int build_workdir_tree(
	git_tree **tree_out,
	git_index *index,
	git_commit *b_commit)
{
320
	git_repository *repo = git_index_owner(index);
nulltoken committed
321
	git_tree *b_tree = NULL;
322
	git_diff *diff = NULL, *idx_to_wd = NULL;
323
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Russell Belfer committed
324
	struct stash_update_rules data = {0};
325
	int error;
nulltoken committed
326

327
	opts.flags = GIT_DIFF_IGNORE_SUBMODULES | GIT_DIFF_INCLUDE_UNTRACKED;
328

329
	if ((error = git_commit_tree(&b_tree, b_commit)) < 0)
nulltoken committed
330 331
		goto cleanup;

332 333 334
	if ((error = git_diff_tree_to_index(&diff, repo, b_tree, index, &opts)) < 0 ||
		(error = git_diff_index_to_workdir(&idx_to_wd, repo, index, &opts)) < 0 ||
		(error = git_diff__merge(diff, idx_to_wd, stash_delta_merge)) < 0)
nulltoken committed
335 336 337 338
		goto cleanup;

	data.include_changed = true;

Russell Belfer committed
339
	if ((error = stash_update_index_from_diff(index, diff, &data)) < 0)
nulltoken committed
340 341
		goto cleanup;

Russell Belfer committed
342
	error = build_tree_from_index(tree_out, index);
nulltoken committed
343 344

cleanup:
345
	git_diff_free(idx_to_wd);
346
	git_diff_free(diff);
nulltoken committed
347
	git_tree_free(b_tree);
348

nulltoken committed
349 350 351 352 353 354
	return error;
}

static int commit_worktree(
	git_oid *w_commit_oid,
	git_index *index,
355
	const git_signature *stasher,
nulltoken committed
356 357 358 359 360
	const char *message,
	git_commit *i_commit,
	git_commit *b_commit,
	git_commit *u_commit)
{
361
	int error = 0;
nulltoken committed
362 363 364 365 366 367 368
	git_tree *w_tree = NULL, *i_tree = NULL;
	const git_commit *parents[] = {	NULL, NULL,	NULL };

	parents[0] = b_commit;
	parents[1] = i_commit;
	parents[2] = u_commit;

369 370
	if ((error = git_commit_tree(&i_tree, i_commit)) < 0)
		goto cleanup;
nulltoken committed
371

372
	if ((error = git_index_read_tree(index, i_tree)) < 0)
nulltoken committed
373 374
		goto cleanup;

375
	if ((error = build_workdir_tree(&w_tree, index, b_commit)) < 0)
nulltoken committed
376 377
		goto cleanup;

378
	error = git_commit_create(
nulltoken committed
379 380 381 382 383 384 385 386
		w_commit_oid,
		git_index_owner(index),
		NULL,
		stasher,
		stasher,
		NULL,
		message,
		w_tree,
387 388
		u_commit ? 3 : 2,
		parents);
nulltoken committed
389 390 391 392 393 394 395 396 397 398 399 400

cleanup:
	git_tree_free(i_tree);
	git_tree_free(w_tree);
	return error;
}

static int prepare_worktree_commit_message(
	git_buf* msg,
	const char *user_message)
{
	git_buf buf = GIT_BUF_INIT;
401 402
	int error;

403 404
	if ((error = git_buf_set(&buf, git_buf_cstr(msg), git_buf_len(msg))) < 0)
		return error;
nulltoken committed
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420

	git_buf_clear(msg);

	if (!user_message)
		git_buf_printf(msg, "WIP on %s", git_buf_cstr(&buf));
	else {
		const char *colon;

		if ((colon = strchr(git_buf_cstr(&buf), ':')) == NULL)
			goto cleanup;

		git_buf_puts(msg, "On ");
		git_buf_put(msg, git_buf_cstr(&buf), colon - buf.ptr);
		git_buf_printf(msg, ": %s\n", user_message);
	}

421
	error = (git_buf_oom(msg) || git_buf_oom(&buf)) ? -1 : 0;
nulltoken committed
422 423 424

cleanup:
	git_buf_free(&buf);
425

nulltoken committed
426 427 428 429 430 431 432 433
	return error;
}

static int update_reflog(
	git_oid *w_commit_oid,
	git_repository *repo,
	const char *message)
{
434
	git_reference *stash;
nulltoken committed
435 436
	int error;

437 438
	if ((error = git_reference_ensure_log(repo, GIT_REFS_STASH_FILE)) < 0)
		return error;
nulltoken committed
439

440
	error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, w_commit_oid, 1, message);
nulltoken committed
441

442
	git_reference_free(stash);
nulltoken committed
443 444 445 446 447 448 449 450 451 452

	return error;
}

static int is_dirty_cb(const char *path, unsigned int status, void *payload)
{
	GIT_UNUSED(path);
	GIT_UNUSED(status);
	GIT_UNUSED(payload);

453
	return GIT_PASSTHROUGH;
nulltoken committed
454 455 456 457 458 459 460 461
}

static int ensure_there_are_changes_to_stash(
	git_repository *repo,
	bool include_untracked_files,
	bool include_ignored_files)
{
	int error;
462
	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
nulltoken committed
463 464

	opts.show  = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
465 466
	opts.flags = GIT_STATUS_OPT_EXCLUDE_SUBMODULES;

nulltoken committed
467
	if (include_untracked_files)
468
		opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED |
469
			GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
nulltoken committed
470 471

	if (include_ignored_files)
472 473
		opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED |
			GIT_STATUS_OPT_RECURSE_IGNORED_DIRS;
nulltoken committed
474 475 476

	error = git_status_foreach_ext(repo, &opts, is_dirty_cb, NULL);

477
	if (error == GIT_PASSTHROUGH)
nulltoken committed
478 479 480 481 482 483 484 485 486 487 488
		return 0;

	if (!error)
		return create_error(GIT_ENOTFOUND, "There is nothing to stash.");

	return error;
}

static int reset_index_and_workdir(
	git_repository *repo,
	git_commit *commit,
489 490
	bool remove_untracked,
	bool remove_ignored)
nulltoken committed
491
{
492
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
nulltoken committed
493

494
	opts.checkout_strategy = GIT_CHECKOUT_FORCE;
nulltoken committed
495 496 497 498

	if (remove_untracked)
		opts.checkout_strategy |= GIT_CHECKOUT_REMOVE_UNTRACKED;

499 500 501
	if (remove_ignored)
		opts.checkout_strategy |= GIT_CHECKOUT_REMOVE_IGNORED;

nulltoken committed
502 503 504 505 506 507
	return git_checkout_tree(repo, (git_object *)commit, &opts);
}

int git_stash_save(
	git_oid *out,
	git_repository *repo,
508
	const git_signature *stasher,
nulltoken committed
509 510 511 512 513 514 515 516 517 518
	const char *message,
	uint32_t flags)
{
	git_index *index = NULL;
	git_commit *b_commit = NULL, *i_commit = NULL, *u_commit = NULL;
	git_buf msg = GIT_BUF_INIT;
	int error;

	assert(out && repo && stasher);

519
	if ((error = git_repository__ensure_not_bare(repo, "stash save")) < 0)
nulltoken committed
520 521 522 523 524 525 526
		return error;

	if ((error = retrieve_base_commit_and_message(&b_commit, &msg, repo)) < 0)
		goto cleanup;

	if ((error = ensure_there_are_changes_to_stash(
		repo,
527 528
		(flags & GIT_STASH_INCLUDE_UNTRACKED) != 0,
		(flags & GIT_STASH_INCLUDE_IGNORED) != 0)) < 0)
nulltoken committed
529 530
		goto cleanup;

531
	if ((error = git_repository_index(&index, repo)) < 0)
nulltoken committed
532 533
		goto cleanup;

534 535
	if ((error = commit_index(
			&i_commit, index, stasher, git_buf_cstr(&msg), b_commit)) < 0)
nulltoken committed
536 537
		goto cleanup;

538 539 540 541
	if ((flags & (GIT_STASH_INCLUDE_UNTRACKED | GIT_STASH_INCLUDE_IGNORED)) &&
		(error = commit_untracked(
			&u_commit, index, stasher, git_buf_cstr(&msg),
			i_commit, flags)) < 0)
nulltoken committed
542 543
		goto cleanup;

544
	if ((error = prepare_worktree_commit_message(&msg, message)) < 0)
nulltoken committed
545 546
		goto cleanup;

547 548 549
	if ((error = commit_worktree(
			out, index, stasher, git_buf_cstr(&msg),
			i_commit, b_commit, u_commit)) < 0)
nulltoken committed
550 551 552
		goto cleanup;

	git_buf_rtrim(&msg);
553

554
	if ((error = update_reflog(out, repo, git_buf_cstr(&msg))) < 0)
nulltoken committed
555 556
		goto cleanup;

557
	if ((error = reset_index_and_workdir(
nulltoken committed
558
		repo,
559
		((flags & GIT_STASH_KEEP_INDEX) != 0) ? i_commit : b_commit,
560 561
		(flags & GIT_STASH_INCLUDE_UNTRACKED) != 0,
		(flags & GIT_STASH_INCLUDE_IGNORED) != 0)) < 0)
nulltoken committed
562 563 564
		goto cleanup;

cleanup:
565

nulltoken committed
566 567 568 569 570
	git_buf_free(&msg);
	git_commit_free(i_commit);
	git_commit_free(b_commit);
	git_commit_free(u_commit);
	git_index_free(index);
571

nulltoken committed
572 573
	return error;
}
574

575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
static int retrieve_stash_commit(
	git_commit **commit,
	git_repository *repo,
	size_t index)
{
	git_reference *stash = NULL;
	git_reflog *reflog = NULL;
	int error;
	size_t max;
	const git_reflog_entry *entry;

	if ((error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)) < 0)
		goto cleanup;

	if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0)
		goto cleanup;

	max = git_reflog_entrycount(reflog);
593
	if (!max || index > max - 1) {
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
		error = GIT_ENOTFOUND;
		giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index);
		goto cleanup;
	}

	entry = git_reflog_entry_byindex(reflog, index);
	if ((error = git_commit_lookup(commit, repo, git_reflog_entry_id_new(entry))) < 0)
		goto cleanup;

cleanup:
	git_reference_free(stash);
	git_reflog_free(reflog);
	return error;
}

static int retrieve_stash_trees(
	git_tree **out_stash_tree,
	git_tree **out_base_tree,
	git_tree **out_index_tree,
	git_tree **out_index_parent_tree,
	git_tree **out_untracked_tree,
	git_commit *stash_commit)
{
	git_tree *stash_tree = NULL;
	git_commit *base_commit = NULL;
	git_tree *base_tree = NULL;
	git_commit *index_commit = NULL;
	git_tree *index_tree = NULL;
	git_commit *index_parent_commit = NULL;
	git_tree *index_parent_tree = NULL;
	git_commit *untracked_commit = NULL;
	git_tree *untracked_tree = NULL;
	int error;

	if ((error = git_commit_tree(&stash_tree, stash_commit)) < 0)
		goto cleanup;

	if ((error = git_commit_parent(&base_commit, stash_commit, 0)) < 0)
		goto cleanup;
	if ((error = git_commit_tree(&base_tree, base_commit)) < 0)
		goto cleanup;

	if ((error = git_commit_parent(&index_commit, stash_commit, 1)) < 0)
		goto cleanup;
	if ((error = git_commit_tree(&index_tree, index_commit)) < 0)
		goto cleanup;

	if ((error = git_commit_parent(&index_parent_commit, index_commit, 0)) < 0)
		goto cleanup;
	if ((error = git_commit_tree(&index_parent_tree, index_parent_commit)) < 0)
		goto cleanup;

	if (git_commit_parentcount(stash_commit) == 3) {
		if ((error = git_commit_parent(&untracked_commit, stash_commit, 2)) < 0)
			goto cleanup;
		if ((error = git_commit_tree(&untracked_tree, untracked_commit)) < 0)
			goto cleanup;
	}

	*out_stash_tree = stash_tree;
	*out_base_tree = base_tree;
	*out_index_tree = index_tree;
	*out_index_parent_tree = index_parent_tree;
	*out_untracked_tree = untracked_tree;

cleanup:
	git_commit_free(untracked_commit);
	git_commit_free(index_parent_commit);
	git_commit_free(index_commit);
	git_commit_free(base_commit);
	if (error < 0) {
		git_tree_free(stash_tree);
		git_tree_free(base_tree);
		git_tree_free(index_tree);
		git_tree_free(index_parent_tree);
		git_tree_free(untracked_tree);
	}
	return error;
}

674 675 676 677 678 679 680 681
static int merge_indexes(
	git_index **out,
	git_repository *repo,
	git_tree *ancestor_tree,
	git_index *ours_index,
	git_index *theirs_index)
{
	git_iterator *ancestor = NULL, *ours = NULL, *theirs = NULL;
682
	git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
683 684
	int error;

685 686 687
	iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;

	if ((error = git_iterator_for_tree(&ancestor, ancestor_tree, &iter_opts)) < 0 ||
688 689
		(error = git_iterator_for_index(&ours, repo, ours_index, &iter_opts)) < 0 ||
		(error = git_iterator_for_index(&theirs, repo, theirs_index, &iter_opts)) < 0)
690 691 692 693 694 695 696 697 698 699 700
		goto done;

	error = git_merge__iterators(out, repo, ancestor, ours, theirs, NULL);

done:
	git_iterator_free(ancestor);
	git_iterator_free(ours);
	git_iterator_free(theirs);
	return error;
}

701 702
static int merge_index_and_tree(
	git_index **out,
703
	git_repository *repo,
704 705 706
	git_tree *ancestor_tree,
	git_index *ours_index,
	git_tree *theirs_tree)
707
{
708
	git_iterator *ancestor = NULL, *ours = NULL, *theirs = NULL;
709
	git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
710 711
	int error;

712 713 714
	iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;

	if ((error = git_iterator_for_tree(&ancestor, ancestor_tree, &iter_opts)) < 0 ||
715
		(error = git_iterator_for_index(&ours, repo, ours_index, &iter_opts)) < 0 ||
716
		(error = git_iterator_for_tree(&theirs, theirs_tree, &iter_opts)) < 0)
717
		goto done;
718

719
	error = git_merge__iterators(out, repo, ancestor, ours, theirs, NULL);
720

721 722 723 724
done:
	git_iterator_free(ancestor);
	git_iterator_free(ours);
	git_iterator_free(theirs);
725 726 727
	return error;
}

728 729 730
static void normalize_apply_options(
	git_stash_apply_options *opts,
	const git_stash_apply_options *given_apply_opts)
731
{
732 733
	if (given_apply_opts != NULL) {
		memcpy(opts, given_apply_opts, sizeof(git_stash_apply_options));
734
	} else {
735 736
		git_stash_apply_options default_apply_opts = GIT_STASH_APPLY_OPTIONS_INIT;
		memcpy(opts, &default_apply_opts, sizeof(git_stash_apply_options));
737 738
	}

739 740
	if ((opts->checkout_options.checkout_strategy & (GIT_CHECKOUT_SAFE | GIT_CHECKOUT_FORCE)) == 0)
		opts->checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE;
741

742 743
	if (!opts->checkout_options.our_label)
		opts->checkout_options.our_label = "Updated upstream";
744

745 746 747 748 749 750 751 752 753
	if (!opts->checkout_options.their_label)
		opts->checkout_options.their_label = "Stashed changes";
}

int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int version)
{
	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
		opts, version, git_stash_apply_options, GIT_STASH_APPLY_OPTIONS_INIT);
	return 0;
754 755
}

Carlos Martín Nieto committed
756 757 758 759 760 761 762 763
#define NOTIFY_PROGRESS(opts, progress_type)				\
	do {								\
		if ((opts).progress_cb &&				\
		    (error = (opts).progress_cb((progress_type), (opts).progress_payload))) { \
			error = (error < 0) ? error : -1;		\
			goto cleanup;					\
		}							\
	} while(false);
764

765 766 767 768 769 770 771 772 773 774 775 776
static int ensure_clean_index(git_repository *repo, git_index *index)
{
	git_tree *head_tree = NULL;
	git_diff *index_diff = NULL;
	int error = 0;

	if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
		(error = git_diff_tree_to_index(
			&index_diff, repo, head_tree, index, NULL)) < 0)
		goto done;

	if (git_diff_num_deltas(index_diff) > 0) {
777
		giterr_set(GITERR_STASH, "%" PRIuZ " uncommitted changes exist in the index",
778 779 780 781 782 783 784 785 786 787
			git_diff_num_deltas(index_diff));
		error = GIT_EUNCOMMITTED;
	}

done:
	git_diff_free(index_diff);
	git_tree_free(head_tree);
	return error;
}

788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
static int stage_new_file(const git_index_entry **entries, void *data)
{
	git_index *index = data;

	if(entries[0] == NULL)
		return git_index_add(index, entries[1]);
	else
		return git_index_add(index, entries[0]);
}

static int stage_new_files(
	git_index **out,
	git_tree *parent_tree,
	git_tree *tree)
{
	git_iterator *iterators[2] = { NULL, NULL };
804
	git_iterator_options iterator_options = GIT_ITERATOR_OPTIONS_INIT;
805 806 807 808
	git_index *index = NULL;
	int error;

	if ((error = git_index_new(&index)) < 0 ||
809 810 811 812
		(error = git_iterator_for_tree(
			&iterators[0], parent_tree, &iterator_options)) < 0 ||
		(error = git_iterator_for_tree(
			&iterators[1], tree, &iterator_options)) < 0)
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
		goto done;

	error = git_iterator_walk(iterators, 2, stage_new_file, index);

done:
	if (error < 0)
		git_index_free(index);
	else
		*out = index;

	git_iterator_free(iterators[0]);
	git_iterator_free(iterators[1]);

	return error;
}

829 830 831
int git_stash_apply(
	git_repository *repo,
	size_t index,
832
	const git_stash_apply_options *given_opts)
833
{
834
	git_stash_apply_options opts;
835
	unsigned int checkout_strategy;
836 837
	git_commit *stash_commit = NULL;
	git_tree *stash_tree = NULL;
838
	git_tree *stash_parent_tree = NULL;
839 840 841
	git_tree *index_tree = NULL;
	git_tree *index_parent_tree = NULL;
	git_tree *untracked_tree = NULL;
842
	git_index *stash_adds = NULL;
843
	git_index *repo_index = NULL;
844 845 846
	git_index *unstashed_index = NULL;
	git_index *modified_index = NULL;
	git_index *untracked_index = NULL;
847 848
	int error;

849 850 851 852
	GITERR_CHECK_VERSION(given_opts, GIT_STASH_APPLY_OPTIONS_VERSION, "git_stash_apply_options");

	normalize_apply_options(&opts, given_opts);
	checkout_strategy = opts.checkout_options.checkout_strategy;
853

854 855
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_LOADING_STASH);

856 857 858 859 860 861
	/* Retrieve commit corresponding to the given stash */
	if ((error = retrieve_stash_commit(&stash_commit, repo, index)) < 0)
		goto cleanup;

	/* Retrieve all trees in the stash */
	if ((error = retrieve_stash_trees(
862
			&stash_tree, &stash_parent_tree, &index_tree,
863 864 865 866 867 868 869
			&index_parent_tree, &untracked_tree, stash_commit)) < 0)
		goto cleanup;

	/* Load repo index */
	if ((error = git_repository_index(&repo_index, repo)) < 0)
		goto cleanup;

870 871
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX);

872 873 874
	if ((error = ensure_clean_index(repo, repo_index)) < 0)
		goto cleanup;

875
	/* Restore index if required */
876
	if ((opts.flags & GIT_STASH_APPLY_REINSTATE_INDEX) &&
877
		git_oid_cmp(git_tree_id(stash_parent_tree), git_tree_id(index_tree))) {
878

879 880
		if ((error = merge_index_and_tree(
				&unstashed_index, repo, index_parent_tree, repo_index, index_tree)) < 0)
881 882
			goto cleanup;

883
		if (git_index_has_conflicts(unstashed_index)) {
884
			error = GIT_ECONFLICT;
885
			goto cleanup;
886
		}
887 888 889 890 891 892

	/* Otherwise, stage any new files in the stash tree.  (Note: their
	 * previously unstaged contents are staged, not the previously staged.)
	 */
	} else if ((opts.flags & GIT_STASH_APPLY_REINSTATE_INDEX) == 0) {
		if ((error = stage_new_files(
893
				&stash_adds, stash_parent_tree, stash_tree)) < 0 ||
894 895 896
			(error = merge_indexes(
				&unstashed_index, repo, stash_parent_tree, repo_index, stash_adds)) < 0)
			goto cleanup;
897 898
	}

899 900
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED);

901
	/* Restore modified files in workdir */
902 903
	if ((error = merge_index_and_tree(
			&modified_index, repo, stash_parent_tree, repo_index, stash_tree)) < 0)
904 905
		goto cleanup;

906
	/* If applicable, restore untracked / ignored files in workdir */
907 908 909 910 911 912
	if (untracked_tree) {
		NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED);

		if ((error = merge_index_and_tree(&untracked_index, repo, NULL, repo_index, untracked_tree)) < 0)
			goto cleanup;
	}
913

914
	if (untracked_index) {
915
		opts.checkout_options.checkout_strategy |= GIT_CHECKOUT_DONT_UPDATE_INDEX;
916

917 918
		NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED);

919
		if ((error = git_checkout_index(repo, untracked_index, &opts.checkout_options)) < 0)
920 921
			goto cleanup;

922
		opts.checkout_options.checkout_strategy = checkout_strategy;
923 924 925 926 927 928 929 930 931
	}


	/* If there are conflicts in the modified index, then we need to actually
	 * check that out as the repo's index.  Otherwise, we don't update the
	 * index.
	 */

	if (!git_index_has_conflicts(modified_index))
932
		opts.checkout_options.checkout_strategy |= GIT_CHECKOUT_DONT_UPDATE_INDEX;
933 934 935 936 937

	/* Check out the modified index using the existing repo index as baseline,
	 * so that existing modifications in the index can be rewritten even when
	 * checking out safely.
	 */
938
	opts.checkout_options.baseline_index = repo_index;
939

940 941
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED);

942
	if ((error = git_checkout_index(repo, modified_index, &opts.checkout_options)) < 0)
943 944
		goto cleanup;

945 946 947 948 949
	if (unstashed_index && !git_index_has_conflicts(modified_index)) {
		if ((error = git_index_read_index(repo_index, unstashed_index)) < 0)
			goto cleanup;
	}

950 951
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_DONE);

952 953
	error = git_index_write(repo_index);

954
cleanup:
955 956 957
	git_index_free(untracked_index);
	git_index_free(modified_index);
	git_index_free(unstashed_index);
958
	git_index_free(stash_adds);
959 960 961 962
	git_index_free(repo_index);
	git_tree_free(untracked_tree);
	git_tree_free(index_parent_tree);
	git_tree_free(index_tree);
963
	git_tree_free(stash_parent_tree);
964 965 966 967 968
	git_tree_free(stash_tree);
	git_commit_free(stash_commit);
	return error;
}

969 970
int git_stash_foreach(
	git_repository *repo,
Ben Straub committed
971
	git_stash_cb callback,
972 973 974 975 976 977 978 979 980
	void *payload)
{
	git_reference *stash;
	git_reflog *reflog = NULL;
	int error;
	size_t i, max;
	const git_reflog_entry *entry;

	error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE);
981 982
	if (error == GIT_ENOTFOUND) {
		giterr_clear();
983
		return 0;
984
	}
985 986 987
	if (error < 0)
		goto cleanup;

988
	if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0)
989 990 991 992
		goto cleanup;

	max = git_reflog_entrycount(reflog);
	for (i = 0; i < max; i++) {
993
		entry = git_reflog_entry_byindex(reflog, i);
994

995 996 997 998 999 1000
		error = callback(i,
			git_reflog_entry_message(entry),
			git_reflog_entry_id_new(entry),
			payload);

		if (error) {
1001
			giterr_set_after_callback(error);
1002
			break;
1003
		}
1004 1005 1006 1007 1008 1009 1010
	}

cleanup:
	git_reference_free(stash);
	git_reflog_free(reflog);
	return error;
}
nulltoken committed
1011 1012 1013 1014 1015

int git_stash_drop(
	git_repository *repo,
	size_t index)
{
1016 1017
	git_transaction *tx;
	git_reference *stash = NULL;
nulltoken committed
1018 1019 1020 1021
	git_reflog *reflog = NULL;
	size_t max;
	int error;

1022
	if ((error = git_transaction_new(&tx, repo)) < 0)
nulltoken committed
1023 1024
		return error;

1025
	if ((error = git_transaction_lock_ref(tx, GIT_REFS_STASH_FILE)) < 0)
1026 1027 1028 1029 1030
		goto cleanup;

	if ((error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)) < 0)
		goto cleanup;

1031
	if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0)
nulltoken committed
1032 1033 1034 1035
		goto cleanup;

	max = git_reflog_entrycount(reflog);

1036
	if (!max || index > max - 1) {
nulltoken committed
1037 1038 1039 1040 1041
		error = GIT_ENOTFOUND;
		giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index);
		goto cleanup;
	}

1042
	if ((error = git_reflog_drop(reflog, index, true)) < 0)
nulltoken committed
1043 1044
		goto cleanup;

1045
	if ((error = git_transaction_set_reflog(tx, GIT_REFS_STASH_FILE, reflog)) < 0)
nulltoken committed
1046 1047 1048
		goto cleanup;

	if (max == 1) {
1049 1050
		if ((error = git_transaction_remove(tx, GIT_REFS_STASH_FILE)) < 0)
			goto cleanup;
1051 1052 1053 1054
	} else if (index == 0) {
		const git_reflog_entry *entry;

		entry = git_reflog_entry_byindex(reflog, 0);
1055
		if ((error = git_transaction_set_target(tx, GIT_REFS_STASH_FILE, &entry->oid_cur, NULL, NULL)) < 0)
1056
			goto cleanup;
nulltoken committed
1057 1058
	}

1059 1060
	error = git_transaction_commit(tx);

nulltoken committed
1061 1062
cleanup:
	git_reference_free(stash);
1063
	git_transaction_free(tx);
nulltoken committed
1064 1065 1066
	git_reflog_free(reflog);
	return error;
}
1067 1068 1069 1070

int git_stash_pop(
	git_repository *repo,
	size_t index,
1071
	const git_stash_apply_options *options)
1072 1073 1074
{
	int error;

1075
	if ((error = git_stash_apply(repo, index, options)) < 0)
1076 1077 1078 1079
		return error;

	return git_stash_drop(repo, index);
}