rugged 0.23.0b2 → 0.23.0b4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/rugged/rugged_blob.c +39 -0
- data/ext/rugged/rugged_diff.c +7 -3
- data/ext/rugged/rugged_index.c +2 -2
- data/ext/rugged/rugged_remote.c +27 -148
- data/ext/rugged/rugged_remote_collection.c +134 -12
- data/ext/rugged/rugged_repo.c +74 -5
- data/ext/rugged/rugged_submodule.c +18 -208
- data/ext/rugged/rugged_submodule_collection.c +148 -0
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/AUTHORS +1 -0
- data/vendor/libgit2/CMakeLists.txt +33 -25
- data/vendor/libgit2/deps/winhttp/winhttp.def +29 -29
- data/vendor/libgit2/include/git2.h +1 -1
- data/vendor/libgit2/include/git2/blob.h +4 -6
- data/vendor/libgit2/include/git2/checkout.h +10 -1
- data/vendor/libgit2/include/git2/clone.h +6 -7
- data/vendor/libgit2/include/git2/commit.h +11 -0
- data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
- data/vendor/libgit2/include/git2/describe.h +1 -1
- data/vendor/libgit2/include/git2/diff.h +68 -11
- data/vendor/libgit2/include/git2/errors.h +4 -1
- data/vendor/libgit2/include/git2/filter.h +16 -0
- data/vendor/libgit2/include/git2/index.h +38 -11
- data/vendor/libgit2/include/git2/odb.h +1 -1
- data/vendor/libgit2/include/git2/odb_backend.h +2 -2
- data/vendor/libgit2/include/git2/remote.h +300 -207
- data/vendor/libgit2/include/git2/reset.h +1 -0
- data/vendor/libgit2/include/git2/stash.h +135 -4
- data/vendor/libgit2/include/git2/status.h +1 -0
- data/vendor/libgit2/include/git2/submodule.h +46 -75
- data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
- data/vendor/libgit2/include/git2/sys/stream.h +2 -0
- data/vendor/libgit2/include/git2/sys/transport.h +1 -21
- data/vendor/libgit2/include/git2/transport.h +27 -0
- data/vendor/libgit2/include/git2/types.h +20 -10
- data/vendor/libgit2/include/git2/version.h +3 -3
- data/vendor/libgit2/libgit2.pc.in +4 -2
- data/vendor/libgit2/src/attr.c +2 -1
- data/vendor/libgit2/src/attr_file.c +18 -37
- data/vendor/libgit2/src/blame.c +2 -2
- data/vendor/libgit2/src/blob.c +4 -3
- data/vendor/libgit2/src/branch.c +6 -3
- data/vendor/libgit2/src/buf_text.c +4 -6
- data/vendor/libgit2/src/buf_text.h +1 -2
- data/vendor/libgit2/src/buffer.c +8 -6
- data/vendor/libgit2/src/buffer.h +1 -1
- data/vendor/libgit2/src/cache.c +1 -0
- data/vendor/libgit2/src/checkout.c +34 -20
- data/vendor/libgit2/src/clone.c +29 -29
- data/vendor/libgit2/src/commit.c +65 -0
- data/vendor/libgit2/src/common.h +5 -0
- data/vendor/libgit2/src/config.c +20 -0
- data/vendor/libgit2/src/config.h +6 -0
- data/vendor/libgit2/src/config_file.c +2 -2
- data/vendor/libgit2/src/crlf.c +39 -17
- data/vendor/libgit2/src/curl_stream.c +257 -0
- data/vendor/libgit2/src/curl_stream.h +14 -0
- data/vendor/libgit2/src/diff.c +223 -88
- data/vendor/libgit2/src/diff.h +21 -1
- data/vendor/libgit2/src/diff_file.c +23 -13
- data/vendor/libgit2/src/diff_file.h +4 -2
- data/vendor/libgit2/src/diff_patch.c +266 -71
- data/vendor/libgit2/src/diff_patch.h +36 -0
- data/vendor/libgit2/src/diff_print.c +156 -126
- data/vendor/libgit2/src/diff_tform.c +32 -54
- data/vendor/libgit2/src/fetch.c +27 -10
- data/vendor/libgit2/src/fetch.h +2 -2
- data/vendor/libgit2/src/filebuf.c +1 -1
- data/vendor/libgit2/src/fileops.c +6 -2
- data/vendor/libgit2/src/filter.c +28 -7
- data/vendor/libgit2/src/fnmatch.c +5 -5
- data/vendor/libgit2/src/global.c +16 -0
- data/vendor/libgit2/src/ident.c +2 -2
- data/vendor/libgit2/src/ignore.c +1 -0
- data/vendor/libgit2/src/index.c +338 -80
- data/vendor/libgit2/src/index.h +4 -1
- data/vendor/libgit2/src/indexer.c +19 -5
- data/vendor/libgit2/src/iterator.c +118 -11
- data/vendor/libgit2/src/iterator.h +25 -0
- data/vendor/libgit2/src/merge.c +96 -106
- data/vendor/libgit2/src/merge.h +14 -4
- data/vendor/libgit2/src/netops.c +3 -3
- data/vendor/libgit2/src/odb.c +17 -9
- data/vendor/libgit2/src/odb.h +1 -1
- data/vendor/libgit2/src/odb_loose.c +2 -2
- data/vendor/libgit2/src/odb_pack.c +1 -1
- data/vendor/libgit2/src/openssl_stream.c +118 -27
- data/vendor/libgit2/src/pack-objects.c +28 -0
- data/vendor/libgit2/src/pack-objects.h +1 -0
- data/vendor/libgit2/src/pack.c +18 -10
- data/vendor/libgit2/src/path.c +16 -11
- data/vendor/libgit2/src/path.h +1 -1
- data/vendor/libgit2/src/push.c +26 -42
- data/vendor/libgit2/src/push.h +2 -34
- data/vendor/libgit2/src/rebase.c +1 -1
- data/vendor/libgit2/src/refs.c +1 -1
- data/vendor/libgit2/src/refspec.c +6 -0
- data/vendor/libgit2/src/remote.c +381 -274
- data/vendor/libgit2/src/remote.h +0 -4
- data/vendor/libgit2/src/repository.c +33 -12
- data/vendor/libgit2/src/repository.h +0 -1
- data/vendor/libgit2/src/reset.c +1 -0
- data/vendor/libgit2/src/stash.c +439 -17
- data/vendor/libgit2/src/status.c +6 -0
- data/vendor/libgit2/src/stransport_stream.c +58 -21
- data/vendor/libgit2/src/stream.h +15 -0
- data/vendor/libgit2/src/submodule.c +410 -664
- data/vendor/libgit2/src/submodule.h +0 -24
- data/vendor/libgit2/src/transaction.c +1 -0
- data/vendor/libgit2/src/transports/cred.c +55 -1
- data/vendor/libgit2/src/transports/http.c +18 -2
- data/vendor/libgit2/src/transports/local.c +60 -59
- data/vendor/libgit2/src/transports/smart.h +1 -1
- data/vendor/libgit2/src/transports/smart_protocol.c +11 -11
- data/vendor/libgit2/src/transports/ssh.c +46 -7
- data/vendor/libgit2/src/unix/posix.h +4 -0
- data/vendor/libgit2/src/util.c +9 -9
- data/vendor/libgit2/src/util.h +9 -0
- data/vendor/libgit2/src/win32/posix.h +3 -0
- data/vendor/libgit2/src/win32/posix_w32.c +38 -0
- data/vendor/libgit2/src/win32/w32_util.h +10 -0
- metadata +4 -3
- data/vendor/libgit2/include/git2/push.h +0 -94
data/vendor/libgit2/src/remote.h
CHANGED
|
@@ -24,16 +24,12 @@ struct git_remote {
|
|
|
24
24
|
git_vector refspecs;
|
|
25
25
|
git_vector active_refspecs;
|
|
26
26
|
git_vector passive_refspecs;
|
|
27
|
-
git_transport_cb transport_cb;
|
|
28
|
-
void *transport_cb_payload;
|
|
29
27
|
git_transport *transport;
|
|
30
28
|
git_repository *repo;
|
|
31
29
|
git_push *push;
|
|
32
|
-
git_remote_callbacks callbacks;
|
|
33
30
|
git_transfer_progress stats;
|
|
34
31
|
unsigned int need_pack;
|
|
35
32
|
git_remote_autotag_option_t download_tags;
|
|
36
|
-
int update_fetchhead;
|
|
37
33
|
int prune_refs;
|
|
38
34
|
int passed_refspecs;
|
|
39
35
|
};
|
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
# include "win32/w32_util.h"
|
|
33
33
|
#endif
|
|
34
34
|
|
|
35
|
+
static int check_repositoryformatversion(git_config *config);
|
|
36
|
+
|
|
35
37
|
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
|
|
36
38
|
|
|
37
39
|
#define GIT_BRANCH_MASTER "master"
|
|
@@ -109,7 +111,6 @@ void git_repository__cleanup(git_repository *repo)
|
|
|
109
111
|
|
|
110
112
|
git_cache_clear(&repo->objects);
|
|
111
113
|
git_attr_cache_flush(repo);
|
|
112
|
-
git_submodule_cache_free(repo);
|
|
113
114
|
|
|
114
115
|
set_config(repo, NULL);
|
|
115
116
|
set_index(repo, NULL);
|
|
@@ -489,6 +490,7 @@ int git_repository_open_ext(
|
|
|
489
490
|
git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT,
|
|
490
491
|
link_path = GIT_BUF_INIT;
|
|
491
492
|
git_repository *repo;
|
|
493
|
+
git_config *config = NULL;
|
|
492
494
|
|
|
493
495
|
if (repo_ptr)
|
|
494
496
|
*repo_ptr = NULL;
|
|
@@ -510,22 +512,36 @@ int git_repository_open_ext(
|
|
|
510
512
|
GITERR_CHECK_ALLOC(repo->path_gitlink);
|
|
511
513
|
}
|
|
512
514
|
|
|
515
|
+
/*
|
|
516
|
+
* We'd like to have the config, but git doesn't particularly
|
|
517
|
+
* care if it's not there, so we need to deal with that.
|
|
518
|
+
*/
|
|
519
|
+
|
|
520
|
+
error = git_repository_config_snapshot(&config, repo);
|
|
521
|
+
if (error < 0 && error != GIT_ENOTFOUND)
|
|
522
|
+
goto cleanup;
|
|
523
|
+
|
|
524
|
+
if (config && (error = check_repositoryformatversion(config)) < 0)
|
|
525
|
+
goto cleanup;
|
|
526
|
+
|
|
513
527
|
if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
|
|
514
528
|
repo->is_bare = 1;
|
|
515
529
|
else {
|
|
516
|
-
git_config *config = NULL;
|
|
517
530
|
|
|
518
|
-
if (
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
git_config_free(config);
|
|
531
|
+
if (config &&
|
|
532
|
+
((error = load_config_data(repo, config)) < 0 ||
|
|
533
|
+
(error = load_workdir(repo, config, &parent)) < 0))
|
|
534
|
+
goto cleanup;
|
|
524
535
|
}
|
|
525
536
|
|
|
526
|
-
|
|
527
|
-
*repo_ptr = repo;
|
|
537
|
+
cleanup:
|
|
528
538
|
git_buf_free(&parent);
|
|
539
|
+
git_config_free(config);
|
|
540
|
+
|
|
541
|
+
if (error < 0)
|
|
542
|
+
git_repository_free(repo);
|
|
543
|
+
else
|
|
544
|
+
*repo_ptr = repo;
|
|
529
545
|
|
|
530
546
|
return error;
|
|
531
547
|
}
|
|
@@ -931,9 +947,14 @@ bool git_repository__reserved_names(
|
|
|
931
947
|
|
|
932
948
|
static int check_repositoryformatversion(git_config *config)
|
|
933
949
|
{
|
|
934
|
-
int version;
|
|
950
|
+
int version, error;
|
|
935
951
|
|
|
936
|
-
|
|
952
|
+
error = git_config_get_int32(&version, config, "core.repositoryformatversion");
|
|
953
|
+
/* git ignores this if the config variable isn't there */
|
|
954
|
+
if (error == GIT_ENOTFOUND)
|
|
955
|
+
return 0;
|
|
956
|
+
|
|
957
|
+
if (error < 0)
|
|
937
958
|
return -1;
|
|
938
959
|
|
|
939
960
|
if (GIT_REPO_VERSION < version) {
|
data/vendor/libgit2/src/reset.c
CHANGED
|
@@ -63,6 +63,7 @@ int git_reset_default(
|
|
|
63
63
|
|
|
64
64
|
assert(delta->status == GIT_DELTA_ADDED ||
|
|
65
65
|
delta->status == GIT_DELTA_MODIFIED ||
|
|
66
|
+
delta->status == GIT_DELTA_CONFLICTED ||
|
|
66
67
|
delta->status == GIT_DELTA_DELETED);
|
|
67
68
|
|
|
68
69
|
error = git_index_conflict_remove(index, delta->old_file.path);
|
data/vendor/libgit2/src/stash.c
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include "common.h"
|
|
9
9
|
#include "repository.h"
|
|
10
10
|
#include "commit.h"
|
|
11
|
+
#include "message.h"
|
|
11
12
|
#include "tree.h"
|
|
12
13
|
#include "reflog.h"
|
|
13
14
|
#include "git2/diff.h"
|
|
@@ -16,7 +17,12 @@
|
|
|
16
17
|
#include "git2/checkout.h"
|
|
17
18
|
#include "git2/index.h"
|
|
18
19
|
#include "git2/transaction.h"
|
|
20
|
+
#include "git2/merge.h"
|
|
21
|
+
#include "index.h"
|
|
19
22
|
#include "signature.h"
|
|
23
|
+
#include "iterator.h"
|
|
24
|
+
#include "merge.h"
|
|
25
|
+
#include "diff.h"
|
|
20
26
|
|
|
21
27
|
static int create_error(int error, const char *msg)
|
|
22
28
|
{
|
|
@@ -49,23 +55,14 @@ static int append_abbreviated_oid(git_buf *out, const git_oid *b_commit)
|
|
|
49
55
|
|
|
50
56
|
static int append_commit_description(git_buf *out, git_commit* commit)
|
|
51
57
|
{
|
|
52
|
-
const char *
|
|
53
|
-
|
|
58
|
+
const char *summary = git_commit_summary(commit);
|
|
59
|
+
GITERR_CHECK_ALLOC(summary);
|
|
54
60
|
|
|
55
61
|
if (append_abbreviated_oid(out, git_commit_id(commit)) < 0)
|
|
56
62
|
return -1;
|
|
57
63
|
|
|
58
|
-
message = git_commit_message(commit);
|
|
59
|
-
len = strlen(message);
|
|
60
|
-
|
|
61
|
-
/* TODO: Replace with proper commit short message
|
|
62
|
-
* when git_commit_message_short() is implemented.
|
|
63
|
-
*/
|
|
64
|
-
while (pos < len && message[pos] != '\n')
|
|
65
|
-
pos++;
|
|
66
|
-
|
|
67
64
|
git_buf_putc(out, ' ');
|
|
68
|
-
|
|
65
|
+
git_buf_puts(out, summary);
|
|
69
66
|
git_buf_putc(out, '\n');
|
|
70
67
|
|
|
71
68
|
return git_buf_oom(out) ? -1 : 0;
|
|
@@ -110,7 +107,7 @@ static int build_tree_from_index(git_tree **out, git_index *index)
|
|
|
110
107
|
git_oid i_tree_oid;
|
|
111
108
|
|
|
112
109
|
if ((error = git_index_write_tree(&i_tree_oid, index)) < 0)
|
|
113
|
-
return
|
|
110
|
+
return error;
|
|
114
111
|
|
|
115
112
|
return git_tree_lookup(out, git_index_owner(index), &i_tree_oid);
|
|
116
113
|
}
|
|
@@ -296,6 +293,25 @@ cleanup:
|
|
|
296
293
|
return error;
|
|
297
294
|
}
|
|
298
295
|
|
|
296
|
+
static git_diff_delta *stash_delta_merge(
|
|
297
|
+
const git_diff_delta *a,
|
|
298
|
+
const git_diff_delta *b,
|
|
299
|
+
git_pool *pool)
|
|
300
|
+
{
|
|
301
|
+
/* Special case for stash: if a file is deleted in the index, but exists
|
|
302
|
+
* in the working tree, we need to stash the workdir copy for the workdir.
|
|
303
|
+
*/
|
|
304
|
+
if (a->status == GIT_DELTA_DELETED && b->status == GIT_DELTA_UNTRACKED) {
|
|
305
|
+
git_diff_delta *dup = git_diff__delta_dup(b, pool);
|
|
306
|
+
|
|
307
|
+
if (dup)
|
|
308
|
+
dup->status = GIT_DELTA_MODIFIED;
|
|
309
|
+
return dup;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return git_diff__merge_like_cgit(a, b, pool);
|
|
313
|
+
}
|
|
314
|
+
|
|
299
315
|
static int build_workdir_tree(
|
|
300
316
|
git_tree **tree_out,
|
|
301
317
|
git_index *index,
|
|
@@ -303,17 +319,19 @@ static int build_workdir_tree(
|
|
|
303
319
|
{
|
|
304
320
|
git_repository *repo = git_index_owner(index);
|
|
305
321
|
git_tree *b_tree = NULL;
|
|
306
|
-
git_diff *diff = NULL;
|
|
322
|
+
git_diff *diff = NULL, *idx_to_wd = NULL;
|
|
307
323
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
|
308
324
|
struct stash_update_rules data = {0};
|
|
309
325
|
int error;
|
|
310
326
|
|
|
311
|
-
opts.flags = GIT_DIFF_IGNORE_SUBMODULES;
|
|
327
|
+
opts.flags = GIT_DIFF_IGNORE_SUBMODULES | GIT_DIFF_INCLUDE_UNTRACKED;
|
|
312
328
|
|
|
313
329
|
if ((error = git_commit_tree(&b_tree, b_commit)) < 0)
|
|
314
330
|
goto cleanup;
|
|
315
331
|
|
|
316
|
-
if ((error =
|
|
332
|
+
if ((error = git_diff_tree_to_index(&diff, repo, b_tree, index, &opts)) < 0 ||
|
|
333
|
+
(error = git_diff_index_to_workdir(&idx_to_wd, repo, index, &opts)) < 0 ||
|
|
334
|
+
(error = git_diff__merge(diff, idx_to_wd, stash_delta_merge)) < 0)
|
|
317
335
|
goto cleanup;
|
|
318
336
|
|
|
319
337
|
data.include_changed = true;
|
|
@@ -324,6 +342,7 @@ static int build_workdir_tree(
|
|
|
324
342
|
error = build_tree_from_index(tree_out, index);
|
|
325
343
|
|
|
326
344
|
cleanup:
|
|
345
|
+
git_diff_free(idx_to_wd);
|
|
327
346
|
git_diff_free(diff);
|
|
328
347
|
git_tree_free(b_tree);
|
|
329
348
|
|
|
@@ -553,6 +572,396 @@ cleanup:
|
|
|
553
572
|
return error;
|
|
554
573
|
}
|
|
555
574
|
|
|
575
|
+
static int retrieve_stash_commit(
|
|
576
|
+
git_commit **commit,
|
|
577
|
+
git_repository *repo,
|
|
578
|
+
size_t index)
|
|
579
|
+
{
|
|
580
|
+
git_reference *stash = NULL;
|
|
581
|
+
git_reflog *reflog = NULL;
|
|
582
|
+
int error;
|
|
583
|
+
size_t max;
|
|
584
|
+
const git_reflog_entry *entry;
|
|
585
|
+
|
|
586
|
+
if ((error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)) < 0)
|
|
587
|
+
goto cleanup;
|
|
588
|
+
|
|
589
|
+
if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0)
|
|
590
|
+
goto cleanup;
|
|
591
|
+
|
|
592
|
+
max = git_reflog_entrycount(reflog);
|
|
593
|
+
if (!max || index > max - 1) {
|
|
594
|
+
error = GIT_ENOTFOUND;
|
|
595
|
+
giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index);
|
|
596
|
+
goto cleanup;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
entry = git_reflog_entry_byindex(reflog, index);
|
|
600
|
+
if ((error = git_commit_lookup(commit, repo, git_reflog_entry_id_new(entry))) < 0)
|
|
601
|
+
goto cleanup;
|
|
602
|
+
|
|
603
|
+
cleanup:
|
|
604
|
+
git_reference_free(stash);
|
|
605
|
+
git_reflog_free(reflog);
|
|
606
|
+
return error;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
static int retrieve_stash_trees(
|
|
610
|
+
git_tree **out_stash_tree,
|
|
611
|
+
git_tree **out_base_tree,
|
|
612
|
+
git_tree **out_index_tree,
|
|
613
|
+
git_tree **out_index_parent_tree,
|
|
614
|
+
git_tree **out_untracked_tree,
|
|
615
|
+
git_commit *stash_commit)
|
|
616
|
+
{
|
|
617
|
+
git_tree *stash_tree = NULL;
|
|
618
|
+
git_commit *base_commit = NULL;
|
|
619
|
+
git_tree *base_tree = NULL;
|
|
620
|
+
git_commit *index_commit = NULL;
|
|
621
|
+
git_tree *index_tree = NULL;
|
|
622
|
+
git_commit *index_parent_commit = NULL;
|
|
623
|
+
git_tree *index_parent_tree = NULL;
|
|
624
|
+
git_commit *untracked_commit = NULL;
|
|
625
|
+
git_tree *untracked_tree = NULL;
|
|
626
|
+
int error;
|
|
627
|
+
|
|
628
|
+
if ((error = git_commit_tree(&stash_tree, stash_commit)) < 0)
|
|
629
|
+
goto cleanup;
|
|
630
|
+
|
|
631
|
+
if ((error = git_commit_parent(&base_commit, stash_commit, 0)) < 0)
|
|
632
|
+
goto cleanup;
|
|
633
|
+
if ((error = git_commit_tree(&base_tree, base_commit)) < 0)
|
|
634
|
+
goto cleanup;
|
|
635
|
+
|
|
636
|
+
if ((error = git_commit_parent(&index_commit, stash_commit, 1)) < 0)
|
|
637
|
+
goto cleanup;
|
|
638
|
+
if ((error = git_commit_tree(&index_tree, index_commit)) < 0)
|
|
639
|
+
goto cleanup;
|
|
640
|
+
|
|
641
|
+
if ((error = git_commit_parent(&index_parent_commit, index_commit, 0)) < 0)
|
|
642
|
+
goto cleanup;
|
|
643
|
+
if ((error = git_commit_tree(&index_parent_tree, index_parent_commit)) < 0)
|
|
644
|
+
goto cleanup;
|
|
645
|
+
|
|
646
|
+
if (git_commit_parentcount(stash_commit) == 3) {
|
|
647
|
+
if ((error = git_commit_parent(&untracked_commit, stash_commit, 2)) < 0)
|
|
648
|
+
goto cleanup;
|
|
649
|
+
if ((error = git_commit_tree(&untracked_tree, untracked_commit)) < 0)
|
|
650
|
+
goto cleanup;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
*out_stash_tree = stash_tree;
|
|
654
|
+
*out_base_tree = base_tree;
|
|
655
|
+
*out_index_tree = index_tree;
|
|
656
|
+
*out_index_parent_tree = index_parent_tree;
|
|
657
|
+
*out_untracked_tree = untracked_tree;
|
|
658
|
+
|
|
659
|
+
cleanup:
|
|
660
|
+
git_commit_free(untracked_commit);
|
|
661
|
+
git_commit_free(index_parent_commit);
|
|
662
|
+
git_commit_free(index_commit);
|
|
663
|
+
git_commit_free(base_commit);
|
|
664
|
+
if (error < 0) {
|
|
665
|
+
git_tree_free(stash_tree);
|
|
666
|
+
git_tree_free(base_tree);
|
|
667
|
+
git_tree_free(index_tree);
|
|
668
|
+
git_tree_free(index_parent_tree);
|
|
669
|
+
git_tree_free(untracked_tree);
|
|
670
|
+
}
|
|
671
|
+
return error;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
static int merge_indexes(
|
|
675
|
+
git_index **out,
|
|
676
|
+
git_repository *repo,
|
|
677
|
+
git_tree *ancestor_tree,
|
|
678
|
+
git_index *ours_index,
|
|
679
|
+
git_index *theirs_index)
|
|
680
|
+
{
|
|
681
|
+
git_iterator *ancestor = NULL, *ours = NULL, *theirs = NULL;
|
|
682
|
+
const git_iterator_flag_t flags = GIT_ITERATOR_DONT_IGNORE_CASE;
|
|
683
|
+
int error;
|
|
684
|
+
|
|
685
|
+
if ((error = git_iterator_for_tree(&ancestor, ancestor_tree, flags, NULL, NULL)) < 0 ||
|
|
686
|
+
(error = git_iterator_for_index(&ours, ours_index, flags, NULL, NULL)) < 0 ||
|
|
687
|
+
(error = git_iterator_for_index(&theirs, theirs_index, flags, NULL, NULL)) < 0)
|
|
688
|
+
goto done;
|
|
689
|
+
|
|
690
|
+
error = git_merge__iterators(out, repo, ancestor, ours, theirs, NULL);
|
|
691
|
+
|
|
692
|
+
done:
|
|
693
|
+
git_iterator_free(ancestor);
|
|
694
|
+
git_iterator_free(ours);
|
|
695
|
+
git_iterator_free(theirs);
|
|
696
|
+
return error;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
static int merge_index_and_tree(
|
|
700
|
+
git_index **out,
|
|
701
|
+
git_repository *repo,
|
|
702
|
+
git_tree *ancestor_tree,
|
|
703
|
+
git_index *ours_index,
|
|
704
|
+
git_tree *theirs_tree)
|
|
705
|
+
{
|
|
706
|
+
git_iterator *ancestor = NULL, *ours = NULL, *theirs = NULL;
|
|
707
|
+
const git_iterator_flag_t flags = GIT_ITERATOR_DONT_IGNORE_CASE;
|
|
708
|
+
int error;
|
|
709
|
+
|
|
710
|
+
if ((error = git_iterator_for_tree(&ancestor, ancestor_tree, flags, NULL, NULL)) < 0 ||
|
|
711
|
+
(error = git_iterator_for_index(&ours, ours_index, flags, NULL, NULL)) < 0 ||
|
|
712
|
+
(error = git_iterator_for_tree(&theirs, theirs_tree, flags, NULL, NULL)) < 0)
|
|
713
|
+
goto done;
|
|
714
|
+
|
|
715
|
+
error = git_merge__iterators(out, repo, ancestor, ours, theirs, NULL);
|
|
716
|
+
|
|
717
|
+
done:
|
|
718
|
+
git_iterator_free(ancestor);
|
|
719
|
+
git_iterator_free(ours);
|
|
720
|
+
git_iterator_free(theirs);
|
|
721
|
+
return error;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
static void normalize_apply_options(
|
|
725
|
+
git_stash_apply_options *opts,
|
|
726
|
+
const git_stash_apply_options *given_apply_opts)
|
|
727
|
+
{
|
|
728
|
+
if (given_apply_opts != NULL) {
|
|
729
|
+
memcpy(opts, given_apply_opts, sizeof(git_stash_apply_options));
|
|
730
|
+
} else {
|
|
731
|
+
git_stash_apply_options default_apply_opts = GIT_STASH_APPLY_OPTIONS_INIT;
|
|
732
|
+
memcpy(opts, &default_apply_opts, sizeof(git_stash_apply_options));
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
if ((opts->checkout_options.checkout_strategy & (GIT_CHECKOUT_SAFE | GIT_CHECKOUT_FORCE)) == 0)
|
|
736
|
+
opts->checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE;
|
|
737
|
+
|
|
738
|
+
if (!opts->checkout_options.our_label)
|
|
739
|
+
opts->checkout_options.our_label = "Updated upstream";
|
|
740
|
+
|
|
741
|
+
if (!opts->checkout_options.their_label)
|
|
742
|
+
opts->checkout_options.their_label = "Stashed changes";
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int version)
|
|
746
|
+
{
|
|
747
|
+
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
|
|
748
|
+
opts, version, git_stash_apply_options, GIT_STASH_APPLY_OPTIONS_INIT);
|
|
749
|
+
return 0;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
#define NOTIFY_PROGRESS(opts, progress_type) \
|
|
753
|
+
do { \
|
|
754
|
+
if ((opts).progress_cb && \
|
|
755
|
+
(error = (opts).progress_cb((progress_type), (opts).progress_payload))) { \
|
|
756
|
+
error = (error < 0) ? error : -1; \
|
|
757
|
+
goto cleanup; \
|
|
758
|
+
} \
|
|
759
|
+
} while(false);
|
|
760
|
+
|
|
761
|
+
static int ensure_clean_index(git_repository *repo, git_index *index)
|
|
762
|
+
{
|
|
763
|
+
git_tree *head_tree = NULL;
|
|
764
|
+
git_diff *index_diff = NULL;
|
|
765
|
+
int error = 0;
|
|
766
|
+
|
|
767
|
+
if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
|
|
768
|
+
(error = git_diff_tree_to_index(
|
|
769
|
+
&index_diff, repo, head_tree, index, NULL)) < 0)
|
|
770
|
+
goto done;
|
|
771
|
+
|
|
772
|
+
if (git_diff_num_deltas(index_diff) > 0) {
|
|
773
|
+
giterr_set(GITERR_STASH, "%d uncommitted changes exist in the index",
|
|
774
|
+
git_diff_num_deltas(index_diff));
|
|
775
|
+
error = GIT_EUNCOMMITTED;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
done:
|
|
779
|
+
git_diff_free(index_diff);
|
|
780
|
+
git_tree_free(head_tree);
|
|
781
|
+
return error;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
static int stage_new_file(const git_index_entry **entries, void *data)
|
|
785
|
+
{
|
|
786
|
+
git_index *index = data;
|
|
787
|
+
|
|
788
|
+
if(entries[0] == NULL)
|
|
789
|
+
return git_index_add(index, entries[1]);
|
|
790
|
+
else
|
|
791
|
+
return git_index_add(index, entries[0]);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
static int stage_new_files(
|
|
795
|
+
git_index **out,
|
|
796
|
+
git_repository *repo,
|
|
797
|
+
git_tree *parent_tree,
|
|
798
|
+
git_tree *tree)
|
|
799
|
+
{
|
|
800
|
+
git_iterator *iterators[2] = { NULL, NULL };
|
|
801
|
+
git_index *index = NULL;
|
|
802
|
+
int error;
|
|
803
|
+
|
|
804
|
+
if ((error = git_index_new(&index)) < 0 ||
|
|
805
|
+
(error = git_iterator_for_tree(&iterators[0], parent_tree,
|
|
806
|
+
GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
|
|
807
|
+
(error = git_iterator_for_tree(&iterators[1], tree,
|
|
808
|
+
GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0)
|
|
809
|
+
goto done;
|
|
810
|
+
|
|
811
|
+
error = git_iterator_walk(iterators, 2, stage_new_file, index);
|
|
812
|
+
|
|
813
|
+
done:
|
|
814
|
+
if (error < 0)
|
|
815
|
+
git_index_free(index);
|
|
816
|
+
else
|
|
817
|
+
*out = index;
|
|
818
|
+
|
|
819
|
+
git_iterator_free(iterators[0]);
|
|
820
|
+
git_iterator_free(iterators[1]);
|
|
821
|
+
|
|
822
|
+
return error;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
int git_stash_apply(
|
|
826
|
+
git_repository *repo,
|
|
827
|
+
size_t index,
|
|
828
|
+
const git_stash_apply_options *given_opts)
|
|
829
|
+
{
|
|
830
|
+
git_stash_apply_options opts;
|
|
831
|
+
unsigned int checkout_strategy;
|
|
832
|
+
git_commit *stash_commit = NULL;
|
|
833
|
+
git_tree *stash_tree = NULL;
|
|
834
|
+
git_tree *stash_parent_tree = NULL;
|
|
835
|
+
git_tree *index_tree = NULL;
|
|
836
|
+
git_tree *index_parent_tree = NULL;
|
|
837
|
+
git_tree *untracked_tree = NULL;
|
|
838
|
+
git_index *stash_adds = NULL;
|
|
839
|
+
git_index *repo_index = NULL;
|
|
840
|
+
git_index *unstashed_index = NULL;
|
|
841
|
+
git_index *modified_index = NULL;
|
|
842
|
+
git_index *untracked_index = NULL;
|
|
843
|
+
int error;
|
|
844
|
+
|
|
845
|
+
GITERR_CHECK_VERSION(given_opts, GIT_STASH_APPLY_OPTIONS_VERSION, "git_stash_apply_options");
|
|
846
|
+
|
|
847
|
+
normalize_apply_options(&opts, given_opts);
|
|
848
|
+
checkout_strategy = opts.checkout_options.checkout_strategy;
|
|
849
|
+
|
|
850
|
+
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_LOADING_STASH);
|
|
851
|
+
|
|
852
|
+
/* Retrieve commit corresponding to the given stash */
|
|
853
|
+
if ((error = retrieve_stash_commit(&stash_commit, repo, index)) < 0)
|
|
854
|
+
goto cleanup;
|
|
855
|
+
|
|
856
|
+
/* Retrieve all trees in the stash */
|
|
857
|
+
if ((error = retrieve_stash_trees(
|
|
858
|
+
&stash_tree, &stash_parent_tree, &index_tree,
|
|
859
|
+
&index_parent_tree, &untracked_tree, stash_commit)) < 0)
|
|
860
|
+
goto cleanup;
|
|
861
|
+
|
|
862
|
+
/* Load repo index */
|
|
863
|
+
if ((error = git_repository_index(&repo_index, repo)) < 0)
|
|
864
|
+
goto cleanup;
|
|
865
|
+
|
|
866
|
+
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX);
|
|
867
|
+
|
|
868
|
+
if ((error = ensure_clean_index(repo, repo_index)) < 0)
|
|
869
|
+
goto cleanup;
|
|
870
|
+
|
|
871
|
+
/* Restore index if required */
|
|
872
|
+
if ((opts.flags & GIT_STASH_APPLY_REINSTATE_INDEX) &&
|
|
873
|
+
git_oid_cmp(git_tree_id(stash_parent_tree), git_tree_id(index_tree))) {
|
|
874
|
+
|
|
875
|
+
if ((error = merge_index_and_tree(
|
|
876
|
+
&unstashed_index, repo, index_parent_tree, repo_index, index_tree)) < 0)
|
|
877
|
+
goto cleanup;
|
|
878
|
+
|
|
879
|
+
if (git_index_has_conflicts(unstashed_index)) {
|
|
880
|
+
error = GIT_ECONFLICT;
|
|
881
|
+
goto cleanup;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/* Otherwise, stage any new files in the stash tree. (Note: their
|
|
885
|
+
* previously unstaged contents are staged, not the previously staged.)
|
|
886
|
+
*/
|
|
887
|
+
} else if ((opts.flags & GIT_STASH_APPLY_REINSTATE_INDEX) == 0) {
|
|
888
|
+
if ((error = stage_new_files(
|
|
889
|
+
&stash_adds, repo, stash_parent_tree, stash_tree)) < 0 ||
|
|
890
|
+
(error = merge_indexes(
|
|
891
|
+
&unstashed_index, repo, stash_parent_tree, repo_index, stash_adds)) < 0)
|
|
892
|
+
goto cleanup;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED);
|
|
896
|
+
|
|
897
|
+
/* Restore modified files in workdir */
|
|
898
|
+
if ((error = merge_index_and_tree(
|
|
899
|
+
&modified_index, repo, stash_parent_tree, repo_index, stash_tree)) < 0)
|
|
900
|
+
goto cleanup;
|
|
901
|
+
|
|
902
|
+
/* If applicable, restore untracked / ignored files in workdir */
|
|
903
|
+
if (untracked_tree) {
|
|
904
|
+
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED);
|
|
905
|
+
|
|
906
|
+
if ((error = merge_index_and_tree(&untracked_index, repo, NULL, repo_index, untracked_tree)) < 0)
|
|
907
|
+
goto cleanup;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
if (untracked_index) {
|
|
911
|
+
opts.checkout_options.checkout_strategy |= GIT_CHECKOUT_DONT_UPDATE_INDEX;
|
|
912
|
+
|
|
913
|
+
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED);
|
|
914
|
+
|
|
915
|
+
if ((error = git_checkout_index(repo, untracked_index, &opts.checkout_options)) < 0)
|
|
916
|
+
goto cleanup;
|
|
917
|
+
|
|
918
|
+
opts.checkout_options.checkout_strategy = checkout_strategy;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
/* If there are conflicts in the modified index, then we need to actually
|
|
923
|
+
* check that out as the repo's index. Otherwise, we don't update the
|
|
924
|
+
* index.
|
|
925
|
+
*/
|
|
926
|
+
|
|
927
|
+
if (!git_index_has_conflicts(modified_index))
|
|
928
|
+
opts.checkout_options.checkout_strategy |= GIT_CHECKOUT_DONT_UPDATE_INDEX;
|
|
929
|
+
|
|
930
|
+
/* Check out the modified index using the existing repo index as baseline,
|
|
931
|
+
* so that existing modifications in the index can be rewritten even when
|
|
932
|
+
* checking out safely.
|
|
933
|
+
*/
|
|
934
|
+
opts.checkout_options.baseline_index = repo_index;
|
|
935
|
+
|
|
936
|
+
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED);
|
|
937
|
+
|
|
938
|
+
if ((error = git_checkout_index(repo, modified_index, &opts.checkout_options)) < 0)
|
|
939
|
+
goto cleanup;
|
|
940
|
+
|
|
941
|
+
if (unstashed_index && !git_index_has_conflicts(modified_index)) {
|
|
942
|
+
if ((error = git_index_read_index(repo_index, unstashed_index)) < 0)
|
|
943
|
+
goto cleanup;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
NOTIFY_PROGRESS(opts, GIT_STASH_APPLY_PROGRESS_DONE);
|
|
947
|
+
|
|
948
|
+
error = git_index_write(repo_index);
|
|
949
|
+
|
|
950
|
+
cleanup:
|
|
951
|
+
git_index_free(untracked_index);
|
|
952
|
+
git_index_free(modified_index);
|
|
953
|
+
git_index_free(unstashed_index);
|
|
954
|
+
git_index_free(stash_adds);
|
|
955
|
+
git_index_free(repo_index);
|
|
956
|
+
git_tree_free(untracked_tree);
|
|
957
|
+
git_tree_free(index_parent_tree);
|
|
958
|
+
git_tree_free(index_tree);
|
|
959
|
+
git_tree_free(stash_parent_tree);
|
|
960
|
+
git_tree_free(stash_tree);
|
|
961
|
+
git_commit_free(stash_commit);
|
|
962
|
+
return error;
|
|
963
|
+
}
|
|
964
|
+
|
|
556
965
|
int git_stash_foreach(
|
|
557
966
|
git_repository *repo,
|
|
558
967
|
git_stash_cb callback,
|
|
@@ -620,7 +1029,7 @@ int git_stash_drop(
|
|
|
620
1029
|
|
|
621
1030
|
max = git_reflog_entrycount(reflog);
|
|
622
1031
|
|
|
623
|
-
if (index > max - 1) {
|
|
1032
|
+
if (!max || index > max - 1) {
|
|
624
1033
|
error = GIT_ENOTFOUND;
|
|
625
1034
|
giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index);
|
|
626
1035
|
goto cleanup;
|
|
@@ -651,3 +1060,16 @@ cleanup:
|
|
|
651
1060
|
git_reflog_free(reflog);
|
|
652
1061
|
return error;
|
|
653
1062
|
}
|
|
1063
|
+
|
|
1064
|
+
int git_stash_pop(
|
|
1065
|
+
git_repository *repo,
|
|
1066
|
+
size_t index,
|
|
1067
|
+
const git_stash_apply_options *options)
|
|
1068
|
+
{
|
|
1069
|
+
int error;
|
|
1070
|
+
|
|
1071
|
+
if ((error = git_stash_apply(repo, index, options)) < 0)
|
|
1072
|
+
return error;
|
|
1073
|
+
|
|
1074
|
+
return git_stash_drop(repo, index);
|
|
1075
|
+
}
|