stash.c 22.4 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"
nulltoken committed
25 26 27 28 29 30 31 32 33 34 35

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);

36
	if (error == GIT_EUNBORNBRANCH)
nulltoken committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
		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)
{
57 58
	const char *summary = git_commit_summary(commit);
	GITERR_CHECK_ALLOC(summary);
nulltoken committed
59 60 61 62 63

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

	git_buf_putc(out, ' ');
64
	git_buf_puts(out, summary);
nulltoken committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
	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)
82
		error = git_buf_puts(stash_message, "(no branch): ");
nulltoken committed
83
	else
84
		error = git_buf_printf(
nulltoken committed
85 86 87
			stash_message,
			"%s: ",
			git_reference_name(head) + strlen(GIT_REFS_HEADS_DIR));
88
	if (error < 0)
nulltoken committed
89 90
		goto cleanup;

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

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

cleanup:
	git_reference_free(head);
	return error;
}

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

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

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

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

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

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

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

	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
153
struct stash_update_rules {
nulltoken committed
154 155 156 157 158
	bool include_changed;
	bool include_untracked;
	bool include_ignored;
};

Russell Belfer committed
159 160 161 162
static int stash_update_index_from_diff(
	git_index *index,
	const git_diff *diff,
	struct stash_update_rules *data)
nulltoken committed
163
{
Russell Belfer committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177
	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:
178 179
			if (data->include_untracked &&
				delta->new_file.mode != GIT_FILEMODE_TREE)
Russell Belfer committed
180
				add_path = delta->new_file.path;
nulltoken committed
181 182
			break;

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

Russell Belfer committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
		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
209 210 211 212 213 214 215 216 217
}

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

	git_index_clear(index);

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

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

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

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

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

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

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

static int commit_untracked(
	git_commit **u_commit,
	git_index *index,
258
	const git_signature *stasher,
nulltoken committed
259 260 261 262 263 264 265
	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;
266
	int error;
nulltoken committed
267

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

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

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

	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;
}

static int build_workdir_tree(
	git_tree **tree_out,
	git_index *index,
	git_commit *b_commit)
{
300
	git_repository *repo = git_index_owner(index);
nulltoken committed
301
	git_tree *b_tree = NULL;
Russell Belfer committed
302
	git_diff *diff = NULL;
303
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Russell Belfer committed
304
	struct stash_update_rules data = {0};
305
	int error;
nulltoken committed
306

307 308
	opts.flags = GIT_DIFF_IGNORE_SUBMODULES;

309
	if ((error = git_commit_tree(&b_tree, b_commit)) < 0)
nulltoken committed
310 311
		goto cleanup;

312
	if ((error = git_diff_tree_to_workdir(&diff, repo, b_tree, &opts)) < 0)
nulltoken committed
313 314 315 316
		goto cleanup;

	data.include_changed = true;

Russell Belfer committed
317
	if ((error = stash_update_index_from_diff(index, diff, &data)) < 0)
nulltoken committed
318 319
		goto cleanup;

Russell Belfer committed
320
	error = build_tree_from_index(tree_out, index);
nulltoken committed
321 322

cleanup:
323
	git_diff_free(diff);
nulltoken committed
324
	git_tree_free(b_tree);
325

nulltoken committed
326 327 328 329 330 331
	return error;
}

static int commit_worktree(
	git_oid *w_commit_oid,
	git_index *index,
332
	const git_signature *stasher,
nulltoken committed
333 334 335 336 337
	const char *message,
	git_commit *i_commit,
	git_commit *b_commit,
	git_commit *u_commit)
{
338
	int error = 0;
nulltoken committed
339 340 341 342 343 344 345
	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;

346 347
	if ((error = git_commit_tree(&i_tree, i_commit)) < 0)
		goto cleanup;
nulltoken committed
348

349
	if ((error = git_index_read_tree(index, i_tree)) < 0)
nulltoken committed
350 351
		goto cleanup;

352
	if ((error = build_workdir_tree(&w_tree, index, b_commit)) < 0)
nulltoken committed
353 354
		goto cleanup;

355
	error = git_commit_create(
nulltoken committed
356 357 358 359 360 361 362 363
		w_commit_oid,
		git_index_owner(index),
		NULL,
		stasher,
		stasher,
		NULL,
		message,
		w_tree,
364 365
		u_commit ? 3 : 2,
		parents);
nulltoken committed
366 367 368 369 370 371 372 373 374 375 376 377

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;
378 379
	int error;

380 381
	if ((error = git_buf_set(&buf, git_buf_cstr(msg), git_buf_len(msg))) < 0)
		return error;
nulltoken committed
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397

	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);
	}

398
	error = (git_buf_oom(msg) || git_buf_oom(&buf)) ? -1 : 0;
nulltoken committed
399 400 401

cleanup:
	git_buf_free(&buf);
402

nulltoken committed
403 404 405 406 407 408 409 410
	return error;
}

static int update_reflog(
	git_oid *w_commit_oid,
	git_repository *repo,
	const char *message)
{
411
	git_reference *stash;
nulltoken committed
412 413
	int error;

414 415
	if ((error = git_reference_ensure_log(repo, GIT_REFS_STASH_FILE)) < 0)
		return error;
nulltoken committed
416

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

419
	git_reference_free(stash);
nulltoken committed
420 421 422 423 424 425 426 427 428 429

	return error;
}

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

430
	return GIT_PASSTHROUGH;
nulltoken committed
431 432 433 434 435 436 437 438
}

static int ensure_there_are_changes_to_stash(
	git_repository *repo,
	bool include_untracked_files,
	bool include_ignored_files)
{
	int error;
439
	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
nulltoken committed
440 441

	opts.show  = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
442 443
	opts.flags = GIT_STATUS_OPT_EXCLUDE_SUBMODULES;

nulltoken committed
444
	if (include_untracked_files)
445
		opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED |
446
			GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
nulltoken committed
447 448

	if (include_ignored_files)
449 450
		opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED |
			GIT_STATUS_OPT_RECURSE_IGNORED_DIRS;
nulltoken committed
451 452 453

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

454
	if (error == GIT_PASSTHROUGH)
nulltoken committed
455 456 457 458 459 460 461 462 463 464 465
		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,
466 467
	bool remove_untracked,
	bool remove_ignored)
nulltoken committed
468
{
469
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
nulltoken committed
470

471
	opts.checkout_strategy = GIT_CHECKOUT_FORCE;
nulltoken committed
472 473 474 475

	if (remove_untracked)
		opts.checkout_strategy |= GIT_CHECKOUT_REMOVE_UNTRACKED;

476 477 478
	if (remove_ignored)
		opts.checkout_strategy |= GIT_CHECKOUT_REMOVE_IGNORED;

nulltoken committed
479 480 481 482 483 484
	return git_checkout_tree(repo, (git_object *)commit, &opts);
}

int git_stash_save(
	git_oid *out,
	git_repository *repo,
485
	const git_signature *stasher,
nulltoken committed
486 487 488 489 490 491 492 493 494 495
	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);

496
	if ((error = git_repository__ensure_not_bare(repo, "stash save")) < 0)
nulltoken committed
497 498 499 500 501 502 503
		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,
504 505
		(flags & GIT_STASH_INCLUDE_UNTRACKED) != 0,
		(flags & GIT_STASH_INCLUDE_IGNORED) != 0)) < 0)
nulltoken committed
506 507
		goto cleanup;

508
	if ((error = git_repository_index(&index, repo)) < 0)
nulltoken committed
509 510
		goto cleanup;

511 512
	if ((error = commit_index(
			&i_commit, index, stasher, git_buf_cstr(&msg), b_commit)) < 0)
nulltoken committed
513 514
		goto cleanup;

515 516 517 518
	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
519 520
		goto cleanup;

521
	if ((error = prepare_worktree_commit_message(&msg, message)) < 0)
nulltoken committed
522 523
		goto cleanup;

524 525 526
	if ((error = commit_worktree(
			out, index, stasher, git_buf_cstr(&msg),
			i_commit, b_commit, u_commit)) < 0)
nulltoken committed
527 528 529
		goto cleanup;

	git_buf_rtrim(&msg);
530

531
	if ((error = update_reflog(out, repo, git_buf_cstr(&msg))) < 0)
nulltoken committed
532 533
		goto cleanup;

534
	if ((error = reset_index_and_workdir(
nulltoken committed
535
		repo,
536
		((flags & GIT_STASH_KEEP_INDEX) != 0) ? i_commit : b_commit,
537 538
		(flags & GIT_STASH_INCLUDE_UNTRACKED) != 0,
		(flags & GIT_STASH_INCLUDE_IGNORED) != 0)) < 0)
nulltoken committed
539 540 541
		goto cleanup;

cleanup:
542

nulltoken committed
543 544 545 546 547
	git_buf_free(&msg);
	git_commit_free(i_commit);
	git_commit_free(b_commit);
	git_commit_free(u_commit);
	git_index_free(index);
548

nulltoken committed
549 550
	return error;
}
551

552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
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);
570
	if (!max || index > max - 1) {
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 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
		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;
}

651 652
static int merge_index_and_tree(
	git_index **out,
653
	git_repository *repo,
654 655 656
	git_tree *ancestor_tree,
	git_index *ours_index,
	git_tree *theirs_tree)
657
{
658 659
	git_iterator *ancestor = NULL, *ours = NULL, *theirs = NULL;
	const git_iterator_flag_t flags = GIT_ITERATOR_DONT_IGNORE_CASE;
660 661
	int error;

662 663 664 665
	if ((error = git_iterator_for_tree(&ancestor, ancestor_tree, flags, NULL, NULL)) < 0 ||
		(error = git_iterator_for_index(&ours, ours_index, flags, NULL, NULL)) < 0 ||
		(error = git_iterator_for_tree(&theirs, theirs_tree, flags, NULL, NULL)) < 0)
		goto done;
666

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

669 670 671 672
done:
	git_iterator_free(ancestor);
	git_iterator_free(ours);
	git_iterator_free(theirs);
673 674 675
	return error;
}

676 677 678
static void normalize_apply_options(
	git_stash_apply_options *opts,
	const git_stash_apply_options *given_apply_opts)
679
{	
680 681
	if (given_apply_opts != NULL) {
		memcpy(opts, given_apply_opts, sizeof(git_stash_apply_options));
682
	} else {
683 684
		git_stash_apply_options default_apply_opts = GIT_STASH_APPLY_OPTIONS_INIT;
		memcpy(opts, &default_apply_opts, sizeof(git_stash_apply_options));
685 686
	}

687 688
	if ((opts->checkout_options.checkout_strategy & (GIT_CHECKOUT_SAFE | GIT_CHECKOUT_FORCE)) == 0)
		opts->checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE;
689

690 691
	if (!opts->checkout_options.our_label)
		opts->checkout_options.our_label = "Updated upstream";
692

693 694 695 696 697 698 699 700 701
	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;
702 703
}

Carlos Martín Nieto committed
704 705 706 707 708 709 710 711
#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);
712

713 714 715
int git_stash_apply(
	git_repository *repo,
	size_t index,
716
	const git_stash_apply_options *given_opts)
717
{
718
	git_stash_apply_options opts;
719
	unsigned int checkout_strategy;
720 721
	git_commit *stash_commit = NULL;
	git_tree *stash_tree = NULL;
722
	git_tree *stash_parent_tree = NULL;
723 724 725 726
	git_tree *index_tree = NULL;
	git_tree *index_parent_tree = NULL;
	git_tree *untracked_tree = NULL;
	git_index *repo_index = NULL;
727 728 729
	git_index *unstashed_index = NULL;
	git_index *modified_index = NULL;
	git_index *untracked_index = NULL;
730 731
	int error;

732 733 734 735
	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;
736

737 738
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_LOADING_STASH);

739 740 741 742 743 744
	/* 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(
745
			&stash_tree, &stash_parent_tree, &index_tree,
746 747 748 749 750 751 752
			&index_parent_tree, &untracked_tree, stash_commit)) < 0)
		goto cleanup;

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

753 754
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX);

755
	/* Restore index if required */
756
	if ((opts.flags & GIT_STASH_APPLY_REINSTATE_INDEX) &&
757
		git_oid_cmp(git_tree_id(stash_parent_tree), git_tree_id(index_tree))) {
758

759 760
		if ((error = merge_index_and_tree(
				&unstashed_index, repo, index_parent_tree, repo_index, index_tree)) < 0)
761 762
			goto cleanup;

763
		if (git_index_has_conflicts(unstashed_index)) {
764
			error = GIT_EMERGECONFLICT;
765
			goto cleanup;
766
		}
767 768
	}

769 770
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED);

771
	/* Restore modified files in workdir */
772 773
	if ((error = merge_index_and_tree(
			&modified_index, repo, stash_parent_tree, repo_index, stash_tree)) < 0)
774 775
		goto cleanup;

776
	/* If applicable, restore untracked / ignored files in workdir */
777 778 779 780 781 782
	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;
	}
783

784
	if (untracked_index) {
785
		opts.checkout_options.checkout_strategy |= GIT_CHECKOUT_DONT_UPDATE_INDEX;
786

787 788
		NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED);

789
		if ((error = git_checkout_index(repo, untracked_index, &opts.checkout_options)) < 0)
790 791
			goto cleanup;

792
		opts.checkout_options.checkout_strategy = checkout_strategy;
793 794 795 796 797 798 799 800 801
	}


	/* 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))
802
		opts.checkout_options.checkout_strategy |= GIT_CHECKOUT_DONT_UPDATE_INDEX;
803 804 805 806 807

	/* 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.
	 */
808
	opts.checkout_options.baseline_index = repo_index;
809

810 811
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED);

812
	if ((error = git_checkout_index(repo, modified_index, &opts.checkout_options)) < 0)
813 814
		goto cleanup;

815 816 817 818 819
	if (unstashed_index && !git_index_has_conflicts(modified_index)) {
		if ((error = git_index_read_index(repo_index, unstashed_index)) < 0)
			goto cleanup;
	}

820 821
	NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_DONE);

822
cleanup:
823 824 825
	git_index_free(untracked_index);
	git_index_free(modified_index);
	git_index_free(unstashed_index);
826 827 828 829
	git_index_free(repo_index);
	git_tree_free(untracked_tree);
	git_tree_free(index_parent_tree);
	git_tree_free(index_tree);
830
	git_tree_free(stash_parent_tree);
831 832 833 834 835
	git_tree_free(stash_tree);
	git_commit_free(stash_commit);
	return error;
}

836 837
int git_stash_foreach(
	git_repository *repo,
Ben Straub committed
838
	git_stash_cb callback,
839 840 841 842 843 844 845 846 847
	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);
848 849
	if (error == GIT_ENOTFOUND) {
		giterr_clear();
850
		return 0;
851
	}
852 853 854
	if (error < 0)
		goto cleanup;

855
	if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0)
856 857 858 859
		goto cleanup;

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

862 863 864 865 866 867
		error = callback(i,
			git_reflog_entry_message(entry),
			git_reflog_entry_id_new(entry),
			payload);

		if (error) {
868
			giterr_set_after_callback(error);
869
			break;
870
		}
871 872 873 874 875 876 877
	}

cleanup:
	git_reference_free(stash);
	git_reflog_free(reflog);
	return error;
}
nulltoken committed
878 879 880 881 882

int git_stash_drop(
	git_repository *repo,
	size_t index)
{
883 884
	git_transaction *tx;
	git_reference *stash = NULL;
nulltoken committed
885 886 887 888
	git_reflog *reflog = NULL;
	size_t max;
	int error;

889
	if ((error = git_transaction_new(&tx, repo)) < 0)
nulltoken committed
890 891
		return error;

892
	if ((error = git_transaction_lock_ref(tx, GIT_REFS_STASH_FILE)) < 0)
893 894 895 896 897
		goto cleanup;

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

898
	if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0)
nulltoken committed
899 900 901 902
		goto cleanup;

	max = git_reflog_entrycount(reflog);

903
	if (!max || index > max - 1) {
nulltoken committed
904 905 906 907 908
		error = GIT_ENOTFOUND;
		giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index);
		goto cleanup;
	}

909
	if ((error = git_reflog_drop(reflog, index, true)) < 0)
nulltoken committed
910 911
		goto cleanup;

912
	if ((error = git_transaction_set_reflog(tx, GIT_REFS_STASH_FILE, reflog)) < 0)
nulltoken committed
913 914 915
		goto cleanup;

	if (max == 1) {
916 917
		if ((error = git_transaction_remove(tx, GIT_REFS_STASH_FILE)) < 0)
			goto cleanup;
918 919 920 921
	} else if (index == 0) {
		const git_reflog_entry *entry;

		entry = git_reflog_entry_byindex(reflog, 0);
922
		if ((error = git_transaction_set_target(tx, GIT_REFS_STASH_FILE, &entry->oid_cur, NULL, NULL)) < 0)
923
			goto cleanup;
nulltoken committed
924 925
	}

926 927
	error = git_transaction_commit(tx);

nulltoken committed
928 929
cleanup:
	git_reference_free(stash);
930
	git_transaction_free(tx);
nulltoken committed
931 932 933
	git_reflog_free(reflog);
	return error;
}
934 935 936 937

int git_stash_pop(
	git_repository *repo,
	size_t index,
938
	const git_stash_apply_options *options)
939 940 941
{
	int error;

942
	if ((error = git_stash_apply(repo, index, options)) < 0)
943 944 945 946
		return error;

	return git_stash_drop(repo, index);
}