rugged 0.24.0b8 → 0.24.0b9
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_tree.c +7 -3
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +27 -1
- data/vendor/libgit2/include/git2/common.h +12 -7
- data/vendor/libgit2/include/git2/diff.h +24 -5
- data/vendor/libgit2/include/git2/merge.h +31 -13
- data/vendor/libgit2/include/git2/repository.h +2 -0
- data/vendor/libgit2/include/git2/submodule.h +12 -1
- data/vendor/libgit2/include/git2/sys/stream.h +13 -0
- data/vendor/libgit2/include/git2/sys/transport.h +1 -0
- data/vendor/libgit2/src/annotated_commit.c +71 -18
- data/vendor/libgit2/src/annotated_commit.h +26 -1
- data/vendor/libgit2/src/checkout.c +1 -2
- data/vendor/libgit2/src/commit.c +25 -10
- data/vendor/libgit2/src/common.h +1 -0
- data/vendor/libgit2/src/config_file.c +5 -10
- data/vendor/libgit2/src/diff.c +18 -21
- data/vendor/libgit2/src/diff.h +0 -1
- data/vendor/libgit2/src/diff_file.c +25 -0
- data/vendor/libgit2/src/filebuf.c +6 -0
- data/vendor/libgit2/src/fileops.c +54 -29
- data/vendor/libgit2/src/fileops.h +3 -2
- data/vendor/libgit2/src/global.c +5 -0
- data/vendor/libgit2/src/global.h +2 -0
- data/vendor/libgit2/src/index.c +105 -58
- data/vendor/libgit2/src/index.h +39 -0
- data/vendor/libgit2/src/merge.c +303 -104
- data/vendor/libgit2/src/merge.h +2 -2
- data/vendor/libgit2/src/object.c +0 -2
- data/vendor/libgit2/src/pool.c +16 -8
- data/vendor/libgit2/src/refdb_fs.c +15 -5
- data/vendor/libgit2/src/refs.h +5 -0
- data/vendor/libgit2/src/repository.c +10 -3
- data/vendor/libgit2/src/reset.c +6 -6
- data/vendor/libgit2/src/settings.c +31 -3
- data/vendor/libgit2/src/stream.h +3 -0
- data/vendor/libgit2/src/submodule.c +19 -25
- data/vendor/libgit2/src/tls_stream.c +13 -0
- data/vendor/libgit2/src/transports/http.c +12 -1
- data/vendor/libgit2/src/transports/winhttp.c +34 -2
- data/vendor/libgit2/src/tree.c +75 -21
- data/vendor/libgit2/src/tree.h +5 -2
- data/vendor/libgit2/src/win32/mingw-compat.h +0 -6
- data/vendor/libgit2/src/win32/msvc-compat.h +0 -3
- data/vendor/libgit2/src/win32/w32_util.h +14 -8
- data/vendor/libgit2/src/win32/win32-compat.h +42 -0
- metadata +3 -2
@@ -13,6 +13,7 @@
|
|
13
13
|
#include "path.h"
|
14
14
|
#include "pool.h"
|
15
15
|
#include "strmap.h"
|
16
|
+
#include "oid.h"
|
16
17
|
|
17
18
|
/**
|
18
19
|
* Filebuffer methods
|
@@ -21,7 +22,7 @@
|
|
21
22
|
*/
|
22
23
|
extern int git_futils_readbuffer(git_buf *obj, const char *path);
|
23
24
|
extern int git_futils_readbuffer_updated(
|
24
|
-
git_buf *obj, const char *path,
|
25
|
+
git_buf *obj, const char *path, git_oid *checksum, int *updated);
|
25
26
|
extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
|
26
27
|
|
27
28
|
extern int git_futils_writebuffer(
|
@@ -309,7 +310,7 @@ extern int git_futils_fake_symlink(const char *new, const char *old);
|
|
309
310
|
* versions could be implemented in the future.
|
310
311
|
*/
|
311
312
|
typedef struct {
|
312
|
-
|
313
|
+
struct timespec mtime;
|
313
314
|
git_off_t size;
|
314
315
|
unsigned int ino;
|
315
316
|
} git_futils_filestamp;
|
data/vendor/libgit2/src/global.c
CHANGED
@@ -31,6 +31,7 @@ static git_mutex *openssl_locks;
|
|
31
31
|
static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
|
32
32
|
static git_atomic git__n_shutdown_callbacks;
|
33
33
|
static git_atomic git__n_inits;
|
34
|
+
char *git__user_agent;
|
34
35
|
|
35
36
|
void git__on_shutdown(git_global_shutdown_fn callback)
|
36
37
|
{
|
@@ -269,6 +270,8 @@ int git_libgit2_shutdown(void)
|
|
269
270
|
git_win32__crtdbg_stacktrace_cleanup();
|
270
271
|
git_win32__stack_cleanup();
|
271
272
|
#endif
|
273
|
+
|
274
|
+
git__free(git__user_agent);
|
272
275
|
}
|
273
276
|
|
274
277
|
/* Exit the lock */
|
@@ -369,6 +372,7 @@ int git_libgit2_shutdown(void)
|
|
369
372
|
|
370
373
|
git__global_state_cleanup(ptr);
|
371
374
|
git__free(ptr);
|
375
|
+
git__free(git__user_agent);
|
372
376
|
|
373
377
|
pthread_key_delete(_tls_key);
|
374
378
|
git_mutex_free(&git__mwindow_mutex);
|
@@ -423,6 +427,7 @@ int git_libgit2_shutdown(void)
|
|
423
427
|
git__shutdown();
|
424
428
|
git__global_state_cleanup(&__state);
|
425
429
|
uninit_ssl();
|
430
|
+
git__free(git__user_agent);
|
426
431
|
|
427
432
|
return 0;
|
428
433
|
}
|
data/vendor/libgit2/src/global.h
CHANGED
data/vendor/libgit2/src/index.c
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
#include "ignore.h"
|
19
19
|
#include "blob.h"
|
20
20
|
#include "idxmap.h"
|
21
|
+
#include "diff.h"
|
21
22
|
|
22
23
|
#include "git2/odb.h"
|
23
24
|
#include "git2/oid.h"
|
@@ -719,18 +720,13 @@ int git_index__changed_relative_to(
|
|
719
720
|
return !!git_oid_cmp(&index->checksum, checksum);
|
720
721
|
}
|
721
722
|
|
722
|
-
static bool
|
723
|
+
static bool is_racy_entry(git_index *index, const git_index_entry *entry)
|
723
724
|
{
|
724
725
|
/* Git special-cases submodules in the check */
|
725
726
|
if (S_ISGITLINK(entry->mode))
|
726
727
|
return false;
|
727
728
|
|
728
|
-
|
729
|
-
if (stamp == 0)
|
730
|
-
return false;
|
731
|
-
|
732
|
-
/* If the timestamp is the same or newer than the index, it's racy */
|
733
|
-
return ((int32_t) stamp) <= entry->mtime.seconds;
|
729
|
+
return git_index_entry_newer_than_index(entry, index);
|
734
730
|
}
|
735
731
|
|
736
732
|
/*
|
@@ -742,9 +738,10 @@ static int truncate_racily_clean(git_index *index)
|
|
742
738
|
size_t i;
|
743
739
|
int error;
|
744
740
|
git_index_entry *entry;
|
745
|
-
git_time_t ts = index->stamp.mtime;
|
746
741
|
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
|
747
|
-
git_diff *diff;
|
742
|
+
git_diff *diff = NULL;
|
743
|
+
git_vector paths = GIT_VECTOR_INIT;
|
744
|
+
git_diff_delta *delta;
|
748
745
|
|
749
746
|
/* Nothing to do if there's no repo to talk about */
|
750
747
|
if (!INDEX_OWNER(index))
|
@@ -756,22 +753,33 @@ static int truncate_racily_clean(git_index *index)
|
|
756
753
|
|
757
754
|
diff_opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE | GIT_DIFF_IGNORE_SUBMODULES | GIT_DIFF_DISABLE_PATHSPEC_MATCH;
|
758
755
|
git_vector_foreach(&index->entries, i, entry) {
|
759
|
-
if (
|
760
|
-
|
756
|
+
if ((entry->flags_extended & GIT_IDXENTRY_UPTODATE) == 0 &&
|
757
|
+
is_racy_entry(index, entry))
|
758
|
+
git_vector_insert(&paths, (char *)entry->path);
|
759
|
+
}
|
761
760
|
|
762
|
-
|
763
|
-
|
764
|
-
diff_opts.pathspec.strings = (char **) &entry->path;
|
761
|
+
if (paths.length == 0)
|
762
|
+
goto done;
|
765
763
|
|
766
|
-
|
767
|
-
|
764
|
+
diff_opts.pathspec.count = paths.length;
|
765
|
+
diff_opts.pathspec.strings = (char **)paths.contents;
|
768
766
|
|
769
|
-
|
770
|
-
|
767
|
+
if ((error = git_diff_index_to_workdir(&diff, INDEX_OWNER(index), index, &diff_opts)) < 0)
|
768
|
+
return error;
|
771
769
|
|
772
|
-
|
770
|
+
git_vector_foreach(&diff->deltas, i, delta) {
|
771
|
+
entry = (git_index_entry *)git_index_get_bypath(index, delta->old_file.path, 0);
|
772
|
+
|
773
|
+
/* Ensure that we have a stage 0 for this file (ie, it's not a
|
774
|
+
* conflict), otherwise smudging it is quite pointless.
|
775
|
+
*/
|
776
|
+
if (entry)
|
777
|
+
entry->file_size = 0;
|
773
778
|
}
|
774
779
|
|
780
|
+
done:
|
781
|
+
git_diff_free(diff);
|
782
|
+
git_vector_free(&paths);
|
775
783
|
return 0;
|
776
784
|
}
|
777
785
|
|
@@ -858,8 +866,10 @@ void git_index_entry__init_from_stat(
|
|
858
866
|
{
|
859
867
|
entry->ctime.seconds = (git_time_t)st->st_ctime;
|
860
868
|
entry->mtime.seconds = (git_time_t)st->st_mtime;
|
861
|
-
|
862
|
-
|
869
|
+
#if defined(GIT_USE_NSEC)
|
870
|
+
entry->mtime.nanoseconds = st->st_mtim.tv_nsec;
|
871
|
+
entry->ctime.nanoseconds = st->st_ctim.tv_nsec;
|
872
|
+
#endif
|
863
873
|
entry->dev = st->st_rdev;
|
864
874
|
entry->ino = st->st_ino;
|
865
875
|
entry->mode = (!trust_mode && S_ISREG(st->st_mode)) ?
|
@@ -979,20 +989,11 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
|
|
979
989
|
|
980
990
|
static void index_entry_cpy(
|
981
991
|
git_index_entry *tgt,
|
982
|
-
|
983
|
-
const git_index_entry *src,
|
984
|
-
bool update_path)
|
992
|
+
const git_index_entry *src)
|
985
993
|
{
|
986
994
|
const char *tgt_path = tgt->path;
|
987
995
|
memcpy(tgt, src, sizeof(*tgt));
|
988
|
-
|
989
|
-
/* keep the existing path buffer, but update the path to the one
|
990
|
-
* given by the caller, if we trust it.
|
991
|
-
*/
|
992
996
|
tgt->path = tgt_path;
|
993
|
-
|
994
|
-
if (index->ignore_case && update_path)
|
995
|
-
memcpy((char *)tgt->path, src->path, strlen(tgt->path));
|
996
997
|
}
|
997
998
|
|
998
999
|
static int index_entry_dup(
|
@@ -1000,18 +1001,32 @@ static int index_entry_dup(
|
|
1000
1001
|
git_index *index,
|
1001
1002
|
const git_index_entry *src)
|
1002
1003
|
{
|
1003
|
-
|
1004
|
+
if (index_entry_create(out, INDEX_OWNER(index), src->path) < 0)
|
1005
|
+
return -1;
|
1004
1006
|
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
}
|
1007
|
+
index_entry_cpy(*out, src);
|
1008
|
+
return 0;
|
1009
|
+
}
|
1009
1010
|
|
1010
|
-
|
1011
|
+
static void index_entry_cpy_nocache(
|
1012
|
+
git_index_entry *tgt,
|
1013
|
+
const git_index_entry *src)
|
1014
|
+
{
|
1015
|
+
git_oid_cpy(&tgt->id, &src->id);
|
1016
|
+
tgt->mode = src->mode;
|
1017
|
+
tgt->flags = src->flags;
|
1018
|
+
tgt->flags_extended = (src->flags_extended & GIT_IDXENTRY_EXTENDED_FLAGS);
|
1019
|
+
}
|
1020
|
+
|
1021
|
+
static int index_entry_dup_nocache(
|
1022
|
+
git_index_entry **out,
|
1023
|
+
git_index *index,
|
1024
|
+
const git_index_entry *src)
|
1025
|
+
{
|
1026
|
+
if (index_entry_create(out, INDEX_OWNER(index), src->path) < 0)
|
1011
1027
|
return -1;
|
1012
1028
|
|
1013
|
-
|
1014
|
-
*out = entry;
|
1029
|
+
index_entry_cpy_nocache(*out, src);
|
1015
1030
|
return 0;
|
1016
1031
|
}
|
1017
1032
|
|
@@ -1152,7 +1167,7 @@ static int canonicalize_directory_path(
|
|
1152
1167
|
while ((match = git_vector_get(&index->entries, pos))) {
|
1153
1168
|
if (GIT_IDXENTRY_STAGE(match) != 0) {
|
1154
1169
|
/* conflicts do not contribute to canonical paths */
|
1155
|
-
} else if (
|
1170
|
+
} else if (strncmp(search, match->path, search_len) == 0) {
|
1156
1171
|
/* prefer an exact match to the input filename */
|
1157
1172
|
best = match;
|
1158
1173
|
best_len = search_len;
|
@@ -1272,6 +1287,9 @@ static int index_insert(
|
|
1272
1287
|
else
|
1273
1288
|
entry->flags |= GIT_IDXENTRY_NAMEMASK;
|
1274
1289
|
|
1290
|
+
/* this entry is now up-to-date and should not be checked for raciness */
|
1291
|
+
entry->flags_extended |= GIT_IDXENTRY_UPTODATE;
|
1292
|
+
|
1275
1293
|
if (git_mutex_lock(&index->lock) < 0) {
|
1276
1294
|
giterr_set(GITERR_OS, "Unable to acquire index lock");
|
1277
1295
|
return -1;
|
@@ -1304,8 +1322,13 @@ static int index_insert(
|
|
1304
1322
|
* and return it in place of the passed in one.
|
1305
1323
|
*/
|
1306
1324
|
else if (existing) {
|
1307
|
-
if (replace)
|
1308
|
-
index_entry_cpy(existing,
|
1325
|
+
if (replace) {
|
1326
|
+
index_entry_cpy(existing, entry);
|
1327
|
+
|
1328
|
+
if (trust_path)
|
1329
|
+
memcpy((char *)existing->path, entry->path, strlen(entry->path));
|
1330
|
+
}
|
1331
|
+
|
1309
1332
|
index_entry_free(entry);
|
1310
1333
|
*entry_ptr = entry = existing;
|
1311
1334
|
}
|
@@ -1682,16 +1705,19 @@ int git_index_conflict_add(git_index *index,
|
|
1682
1705
|
|
1683
1706
|
assert (index);
|
1684
1707
|
|
1685
|
-
if ((
|
1686
|
-
|
1687
|
-
(
|
1708
|
+
if ((ancestor_entry &&
|
1709
|
+
(ret = index_entry_dup(&entries[0], index, ancestor_entry)) < 0) ||
|
1710
|
+
(our_entry &&
|
1711
|
+
(ret = index_entry_dup(&entries[1], index, our_entry)) < 0) ||
|
1712
|
+
(their_entry &&
|
1713
|
+
(ret = index_entry_dup(&entries[2], index, their_entry)) < 0))
|
1688
1714
|
goto on_error;
|
1689
1715
|
|
1690
1716
|
/* Validate entries */
|
1691
1717
|
for (i = 0; i < 3; i++) {
|
1692
1718
|
if (entries[i] && !valid_filemode(entries[i]->mode)) {
|
1693
1719
|
giterr_set(GITERR_INDEX, "invalid filemode for stage %d entry",
|
1694
|
-
i);
|
1720
|
+
i + 1);
|
1695
1721
|
return -1;
|
1696
1722
|
}
|
1697
1723
|
}
|
@@ -1718,7 +1744,7 @@ int git_index_conflict_add(git_index *index,
|
|
1718
1744
|
/* Make sure stage is correct */
|
1719
1745
|
GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
|
1720
1746
|
|
1721
|
-
if ((ret = index_insert(index, &entries[i],
|
1747
|
+
if ((ret = index_insert(index, &entries[i], 1, true, true)) < 0)
|
1722
1748
|
goto on_error;
|
1723
1749
|
|
1724
1750
|
entries[i] = NULL; /* don't free if later entry fails */
|
@@ -2535,7 +2561,8 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
|
|
2535
2561
|
if (entry->flags & GIT_IDXENTRY_EXTENDED) {
|
2536
2562
|
struct entry_long *ondisk_ext;
|
2537
2563
|
ondisk_ext = (struct entry_long *)ondisk;
|
2538
|
-
ondisk_ext->flags_extended = htons(entry->flags_extended
|
2564
|
+
ondisk_ext->flags_extended = htons(entry->flags_extended &
|
2565
|
+
GIT_IDXENTRY_EXTENDED_FLAGS);
|
2539
2566
|
path = ondisk_ext->path;
|
2540
2567
|
}
|
2541
2568
|
else
|
@@ -2718,6 +2745,15 @@ static int write_tree_extension(git_index *index, git_filebuf *file)
|
|
2718
2745
|
return error;
|
2719
2746
|
}
|
2720
2747
|
|
2748
|
+
static void clear_uptodate(git_index *index)
|
2749
|
+
{
|
2750
|
+
git_index_entry *entry;
|
2751
|
+
size_t i;
|
2752
|
+
|
2753
|
+
git_vector_foreach(&index->entries, i, entry)
|
2754
|
+
entry->flags_extended &= ~GIT_IDXENTRY_UPTODATE;
|
2755
|
+
}
|
2756
|
+
|
2721
2757
|
static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
|
2722
2758
|
{
|
2723
2759
|
git_oid hash_final;
|
@@ -2757,7 +2793,13 @@ static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
|
|
2757
2793
|
git_oid_cpy(checksum, &hash_final);
|
2758
2794
|
|
2759
2795
|
/* write it at the end of the file */
|
2760
|
-
|
2796
|
+
if (git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ) < 0)
|
2797
|
+
return -1;
|
2798
|
+
|
2799
|
+
/* file entries are no longer up to date */
|
2800
|
+
clear_uptodate(index);
|
2801
|
+
|
2802
|
+
return 0;
|
2761
2803
|
}
|
2762
2804
|
|
2763
2805
|
int git_index_entry_stage(const git_index_entry *entry)
|
@@ -2806,7 +2848,7 @@ static int read_tree_cb(
|
|
2806
2848
|
entry->mode == old_entry->mode &&
|
2807
2849
|
git_oid_equal(&entry->id, &old_entry->id))
|
2808
2850
|
{
|
2809
|
-
index_entry_cpy(entry,
|
2851
|
+
index_entry_cpy(entry, old_entry);
|
2810
2852
|
entry->flags_extended = 0;
|
2811
2853
|
}
|
2812
2854
|
|
@@ -2924,14 +2966,17 @@ int git_index_read_index(
|
|
2924
2966
|
(error = git_iterator_for_index(&new_iterator, (git_index *)new_index, &opts)) < 0)
|
2925
2967
|
goto done;
|
2926
2968
|
|
2927
|
-
if (((error = git_iterator_current(&old_entry, index_iterator)) < 0 &&
|
2969
|
+
if (((error = git_iterator_current(&old_entry, index_iterator)) < 0 &&
|
2928
2970
|
error != GIT_ITEROVER) ||
|
2929
|
-
((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
|
2971
|
+
((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
|
2930
2972
|
error != GIT_ITEROVER))
|
2931
2973
|
goto done;
|
2932
2974
|
|
2933
2975
|
while (true) {
|
2934
|
-
git_index_entry
|
2976
|
+
git_index_entry
|
2977
|
+
*dup_entry = NULL,
|
2978
|
+
*add_entry = NULL,
|
2979
|
+
*remove_entry = NULL;
|
2935
2980
|
int diff;
|
2936
2981
|
|
2937
2982
|
if (old_entry && new_entry)
|
@@ -2946,8 +2991,7 @@ int git_index_read_index(
|
|
2946
2991
|
if (diff < 0) {
|
2947
2992
|
remove_entry = (git_index_entry *)old_entry;
|
2948
2993
|
} else if (diff > 0) {
|
2949
|
-
|
2950
|
-
goto done;
|
2994
|
+
dup_entry = (git_index_entry *)new_entry;
|
2951
2995
|
} else {
|
2952
2996
|
/* Path and stage are equal, if the OID is equal, keep it to
|
2953
2997
|
* keep the stat cache data.
|
@@ -2955,13 +2999,16 @@ int git_index_read_index(
|
|
2955
2999
|
if (git_oid_equal(&old_entry->id, &new_entry->id)) {
|
2956
3000
|
add_entry = (git_index_entry *)old_entry;
|
2957
3001
|
} else {
|
2958
|
-
|
2959
|
-
goto done;
|
2960
|
-
|
3002
|
+
dup_entry = (git_index_entry *)new_entry;
|
2961
3003
|
remove_entry = (git_index_entry *)old_entry;
|
2962
3004
|
}
|
2963
3005
|
}
|
2964
3006
|
|
3007
|
+
if (dup_entry) {
|
3008
|
+
if ((error = index_entry_dup_nocache(&add_entry, index, dup_entry)) < 0)
|
3009
|
+
goto done;
|
3010
|
+
}
|
3011
|
+
|
2965
3012
|
if (add_entry) {
|
2966
3013
|
if ((error = git_vector_insert(&new_entries, add_entry)) == 0)
|
2967
3014
|
INSERT_IN_MAP_EX(index, new_entries_map, add_entry, error);
|
data/vendor/libgit2/src/index.h
CHANGED
@@ -65,6 +65,45 @@ extern int git_index_entry_icmp(const void *a, const void *b);
|
|
65
65
|
extern int git_index_entry_srch(const void *a, const void *b);
|
66
66
|
extern int git_index_entry_isrch(const void *a, const void *b);
|
67
67
|
|
68
|
+
/* Index time handling functions */
|
69
|
+
GIT_INLINE(bool) git_index_time_eq(const git_index_time *one, const git_index_time *two)
|
70
|
+
{
|
71
|
+
if (one->seconds != two->seconds)
|
72
|
+
return false;
|
73
|
+
|
74
|
+
#ifdef GIT_USE_NSEC
|
75
|
+
if (one->nanoseconds != two->nanoseconds)
|
76
|
+
return false;
|
77
|
+
#endif
|
78
|
+
|
79
|
+
return true;
|
80
|
+
}
|
81
|
+
|
82
|
+
/*
|
83
|
+
* Test if the given index time is newer than the given existing index entry.
|
84
|
+
* If the timestamps are exactly equivalent, then the given index time is
|
85
|
+
* considered "racily newer" than the existing index entry.
|
86
|
+
*/
|
87
|
+
GIT_INLINE(bool) git_index_entry_newer_than_index(
|
88
|
+
const git_index_entry *entry, git_index *index)
|
89
|
+
{
|
90
|
+
/* If we never read the index, we can't have this race either */
|
91
|
+
if (!index || index->stamp.mtime.tv_sec == 0)
|
92
|
+
return false;
|
93
|
+
|
94
|
+
/* If the timestamp is the same or newer than the index, it's racy */
|
95
|
+
#if defined(GIT_USE_NSEC)
|
96
|
+
if ((int32_t)index->stamp.tv_sec < entry->mtime.seconds)
|
97
|
+
return true;
|
98
|
+
else if ((int32_t)index->stamp.mtime.tv_sec > entry->mtime.seconds)
|
99
|
+
return false;
|
100
|
+
else
|
101
|
+
return (uint32_t)index->stamp.mtime.tv_nsec <= entry->mtime.nanoseconds;
|
102
|
+
#else
|
103
|
+
return ((int32_t)index->stamp.mtime.tv_sec) <= entry->mtime.seconds;
|
104
|
+
#endif
|
105
|
+
}
|
106
|
+
|
68
107
|
/* Search index for `path`, returning GIT_ENOTFOUND if it does not exist
|
69
108
|
* (but not setting an error message).
|
70
109
|
*
|
data/vendor/libgit2/src/merge.c
CHANGED
@@ -27,6 +27,8 @@
|
|
27
27
|
#include "config.h"
|
28
28
|
#include "oidarray.h"
|
29
29
|
#include "annotated_commit.h"
|
30
|
+
#include "commit.h"
|
31
|
+
#include "oidarray.h"
|
30
32
|
|
31
33
|
#include "git2/types.h"
|
32
34
|
#include "git2/repository.h"
|
@@ -47,6 +49,19 @@
|
|
47
49
|
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
|
48
50
|
#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
|
49
51
|
|
52
|
+
|
53
|
+
/** Internal merge flags. */
|
54
|
+
enum {
|
55
|
+
/** The merge is for a virtual base in a recursive merge. */
|
56
|
+
GIT_MERGE__VIRTUAL_BASE = (1 << 31),
|
57
|
+
};
|
58
|
+
|
59
|
+
enum {
|
60
|
+
/** Accept the conflict file, staging it as the merge result. */
|
61
|
+
GIT_MERGE_FILE_FAVOR__CONFLICTED = 4,
|
62
|
+
};
|
63
|
+
|
64
|
+
|
50
65
|
typedef enum {
|
51
66
|
TREE_IDX_ANCESTOR = 0,
|
52
67
|
TREE_IDX_OURS = 1,
|
@@ -799,11 +814,9 @@ static int merge_conflict_resolve_automerge(
|
|
799
814
|
int *resolved,
|
800
815
|
git_merge_diff_list *diff_list,
|
801
816
|
const git_merge_diff *conflict,
|
802
|
-
|
803
|
-
unsigned int file_flags)
|
817
|
+
const git_merge_file_options *file_opts)
|
804
818
|
{
|
805
819
|
const git_index_entry *ancestor = NULL, *ours = NULL, *theirs = NULL;
|
806
|
-
git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
|
807
820
|
git_merge_file_result result = {0};
|
808
821
|
git_index_entry *index_entry;
|
809
822
|
git_odb *odb = NULL;
|
@@ -850,12 +863,9 @@ static int merge_conflict_resolve_automerge(
|
|
850
863
|
theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
|
851
864
|
&conflict->their_entry : NULL;
|
852
865
|
|
853
|
-
opts.favor = merge_file_favor;
|
854
|
-
opts.flags = file_flags;
|
855
|
-
|
856
866
|
if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
|
857
|
-
(error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs,
|
858
|
-
!result.automergeable ||
|
867
|
+
(error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, file_opts)) < 0 ||
|
868
|
+
(!result.automergeable && !(file_opts->flags & GIT_MERGE_FILE_FAVOR__CONFLICTED)) ||
|
859
869
|
(error = git_odb_write(&automerge_oid, odb, result.ptr, result.len, GIT_OBJ_BLOB)) < 0)
|
860
870
|
goto done;
|
861
871
|
|
@@ -885,8 +895,7 @@ static int merge_conflict_resolve(
|
|
885
895
|
int *out,
|
886
896
|
git_merge_diff_list *diff_list,
|
887
897
|
const git_merge_diff *conflict,
|
888
|
-
|
889
|
-
unsigned int file_flags)
|
898
|
+
const git_merge_file_options *file_opts)
|
890
899
|
{
|
891
900
|
int resolved = 0;
|
892
901
|
int error = 0;
|
@@ -902,8 +911,7 @@ static int merge_conflict_resolve(
|
|
902
911
|
if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
|
903
912
|
goto done;
|
904
913
|
|
905
|
-
if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict,
|
906
|
-
merge_file_favor, file_flags)) < 0)
|
914
|
+
if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, file_opts)) < 0)
|
907
915
|
goto done;
|
908
916
|
|
909
917
|
*out = resolved;
|
@@ -1296,7 +1304,7 @@ int git_merge_diff_list__find_renames(
|
|
1296
1304
|
|
1297
1305
|
assert(diff_list && opts);
|
1298
1306
|
|
1299
|
-
if ((opts->
|
1307
|
+
if ((opts->flags & GIT_MERGE_FIND_RENAMES) == 0)
|
1300
1308
|
return 0;
|
1301
1309
|
|
1302
1310
|
similarity_ours = git__calloc(diff_list->conflicts.length,
|
@@ -1632,8 +1640,8 @@ static int merge_normalize_opts(
|
|
1632
1640
|
git_merge_options init = GIT_MERGE_OPTIONS_INIT;
|
1633
1641
|
memcpy(opts, &init, sizeof(init));
|
1634
1642
|
|
1635
|
-
opts->
|
1636
|
-
opts->rename_threshold =
|
1643
|
+
opts->flags = GIT_MERGE_FIND_RENAMES;
|
1644
|
+
opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD;
|
1637
1645
|
}
|
1638
1646
|
|
1639
1647
|
if (!opts->target_limit) {
|
@@ -1643,7 +1651,7 @@ static int merge_normalize_opts(
|
|
1643
1651
|
limit = git_config__get_int_force(cfg, "diff.renamelimit", 0);
|
1644
1652
|
|
1645
1653
|
opts->target_limit = (limit <= 0) ?
|
1646
|
-
|
1654
|
+
GIT_MERGE_DEFAULT_TARGET_LIMIT : (unsigned int)limit;
|
1647
1655
|
}
|
1648
1656
|
|
1649
1657
|
/* assign the internal metric with whitespace flag as payload */
|
@@ -1827,6 +1835,7 @@ int git_merge__iterators(
|
|
1827
1835
|
*empty_theirs = NULL;
|
1828
1836
|
git_merge_diff_list *diff_list;
|
1829
1837
|
git_merge_options opts;
|
1838
|
+
git_merge_file_options file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
|
1830
1839
|
git_merge_diff *conflict;
|
1831
1840
|
git_vector changes;
|
1832
1841
|
size_t i;
|
@@ -1842,6 +1851,17 @@ int git_merge__iterators(
|
|
1842
1851
|
if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0)
|
1843
1852
|
return error;
|
1844
1853
|
|
1854
|
+
file_opts.favor = opts.file_favor;
|
1855
|
+
file_opts.flags = opts.file_flags;
|
1856
|
+
|
1857
|
+
/* use the git-inspired labels when virtual base building */
|
1858
|
+
if (opts.flags & GIT_MERGE__VIRTUAL_BASE) {
|
1859
|
+
file_opts.ancestor_label = "merged common ancestors";
|
1860
|
+
file_opts.our_label = "Temporary merge branch 1";
|
1861
|
+
file_opts.their_label = "Temporary merge branch 2";
|
1862
|
+
file_opts.flags |= GIT_MERGE_FILE_FAVOR__CONFLICTED;
|
1863
|
+
}
|
1864
|
+
|
1845
1865
|
diff_list = git_merge_diff_list__alloc(repo);
|
1846
1866
|
GITERR_CHECK_ALLOC(diff_list);
|
1847
1867
|
|
@@ -1860,11 +1880,12 @@ int git_merge__iterators(
|
|
1860
1880
|
git_vector_foreach(&changes, i, conflict) {
|
1861
1881
|
int resolved = 0;
|
1862
1882
|
|
1863
|
-
if ((error = merge_conflict_resolve(
|
1883
|
+
if ((error = merge_conflict_resolve(
|
1884
|
+
&resolved, diff_list, conflict, &file_opts)) < 0)
|
1864
1885
|
goto done;
|
1865
1886
|
|
1866
1887
|
if (!resolved) {
|
1867
|
-
if ((opts.
|
1888
|
+
if ((opts.flags & GIT_MERGE_FAIL_ON_CONFLICT)) {
|
1868
1889
|
giterr_set(GITERR_MERGE, "merge conflicts exist");
|
1869
1890
|
error = GIT_EMERGECONFLICT;
|
1870
1891
|
goto done;
|
@@ -1875,7 +1896,7 @@ int git_merge__iterators(
|
|
1875
1896
|
}
|
1876
1897
|
|
1877
1898
|
error = index_from_diff_list(out, diff_list,
|
1878
|
-
(opts.
|
1899
|
+
(opts.flags & GIT_MERGE_SKIP_REUC));
|
1879
1900
|
|
1880
1901
|
done:
|
1881
1902
|
if (!given_opts || !given_opts->metric)
|
@@ -1922,6 +1943,207 @@ done:
|
|
1922
1943
|
return error;
|
1923
1944
|
}
|
1924
1945
|
|
1946
|
+
static int merge_annotated_commits(
|
1947
|
+
git_index **index_out,
|
1948
|
+
git_annotated_commit **base_out,
|
1949
|
+
git_repository *repo,
|
1950
|
+
git_annotated_commit *our_commit,
|
1951
|
+
git_annotated_commit *their_commit,
|
1952
|
+
size_t recursion_level,
|
1953
|
+
const git_merge_options *opts);
|
1954
|
+
|
1955
|
+
GIT_INLINE(int) insert_head_ids(
|
1956
|
+
git_array_oid_t *ids,
|
1957
|
+
const git_annotated_commit *annotated_commit)
|
1958
|
+
{
|
1959
|
+
git_oid *id;
|
1960
|
+
size_t i;
|
1961
|
+
|
1962
|
+
if (annotated_commit->type == GIT_ANNOTATED_COMMIT_REAL) {
|
1963
|
+
id = git_array_alloc(*ids);
|
1964
|
+
GITERR_CHECK_ALLOC(id);
|
1965
|
+
|
1966
|
+
git_oid_cpy(id, git_commit_id(annotated_commit->commit));
|
1967
|
+
} else {
|
1968
|
+
for (i = 0; i < annotated_commit->parents.size; i++) {
|
1969
|
+
id = git_array_alloc(*ids);
|
1970
|
+
GITERR_CHECK_ALLOC(id);
|
1971
|
+
|
1972
|
+
git_oid_cpy(id, &annotated_commit->parents.ptr[i]);
|
1973
|
+
}
|
1974
|
+
}
|
1975
|
+
|
1976
|
+
return 0;
|
1977
|
+
}
|
1978
|
+
|
1979
|
+
static int create_virtual_base(
|
1980
|
+
git_annotated_commit **out,
|
1981
|
+
git_repository *repo,
|
1982
|
+
git_annotated_commit *one,
|
1983
|
+
git_annotated_commit *two,
|
1984
|
+
const git_merge_options *opts,
|
1985
|
+
size_t recursion_level)
|
1986
|
+
{
|
1987
|
+
git_annotated_commit *result = NULL;
|
1988
|
+
git_index *index = NULL;
|
1989
|
+
git_merge_options virtual_opts = GIT_MERGE_OPTIONS_INIT;
|
1990
|
+
|
1991
|
+
result = git__calloc(1, sizeof(git_annotated_commit));
|
1992
|
+
GITERR_CHECK_ALLOC(result);
|
1993
|
+
|
1994
|
+
/* Conflicts in the merge base creation do not propagate to conflicts
|
1995
|
+
* in the result; the conflicted base will act as the common ancestor.
|
1996
|
+
*/
|
1997
|
+
if (opts)
|
1998
|
+
memcpy(&virtual_opts, opts, sizeof(git_merge_options));
|
1999
|
+
|
2000
|
+
virtual_opts.flags &= ~GIT_MERGE_FAIL_ON_CONFLICT;
|
2001
|
+
virtual_opts.flags |= GIT_MERGE__VIRTUAL_BASE;
|
2002
|
+
|
2003
|
+
if ((merge_annotated_commits(&index, NULL, repo, one, two,
|
2004
|
+
recursion_level + 1, &virtual_opts)) < 0)
|
2005
|
+
return -1;
|
2006
|
+
|
2007
|
+
result->type = GIT_ANNOTATED_COMMIT_VIRTUAL;
|
2008
|
+
result->index = index;
|
2009
|
+
|
2010
|
+
insert_head_ids(&result->parents, one);
|
2011
|
+
insert_head_ids(&result->parents, two);
|
2012
|
+
|
2013
|
+
*out = result;
|
2014
|
+
return 0;
|
2015
|
+
}
|
2016
|
+
|
2017
|
+
static int compute_base(
|
2018
|
+
git_annotated_commit **out,
|
2019
|
+
git_repository *repo,
|
2020
|
+
const git_annotated_commit *one,
|
2021
|
+
const git_annotated_commit *two,
|
2022
|
+
const git_merge_options *given_opts,
|
2023
|
+
size_t recursion_level)
|
2024
|
+
{
|
2025
|
+
git_array_oid_t head_ids = GIT_ARRAY_INIT;
|
2026
|
+
git_oidarray bases = {0};
|
2027
|
+
git_annotated_commit *base = NULL, *other = NULL, *new_base = NULL;
|
2028
|
+
git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
|
2029
|
+
size_t i;
|
2030
|
+
int error;
|
2031
|
+
|
2032
|
+
*out = NULL;
|
2033
|
+
|
2034
|
+
if (given_opts)
|
2035
|
+
memcpy(&opts, given_opts, sizeof(git_merge_options));
|
2036
|
+
|
2037
|
+
if ((error = insert_head_ids(&head_ids, one)) < 0 ||
|
2038
|
+
(error = insert_head_ids(&head_ids, two)) < 0)
|
2039
|
+
goto done;
|
2040
|
+
|
2041
|
+
if ((error = git_merge_bases_many(&bases, repo,
|
2042
|
+
head_ids.size, head_ids.ptr)) < 0 ||
|
2043
|
+
(error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0 ||
|
2044
|
+
(opts.flags & GIT_MERGE_NO_RECURSIVE))
|
2045
|
+
goto done;
|
2046
|
+
|
2047
|
+
for (i = 1; i < bases.count; i++) {
|
2048
|
+
recursion_level++;
|
2049
|
+
|
2050
|
+
if (opts.recursion_limit && recursion_level > opts.recursion_limit)
|
2051
|
+
break;
|
2052
|
+
|
2053
|
+
if ((error = git_annotated_commit_lookup(&other, repo,
|
2054
|
+
&bases.ids[i])) < 0 ||
|
2055
|
+
(error = create_virtual_base(&new_base, repo, base, other, &opts,
|
2056
|
+
recursion_level)) < 0)
|
2057
|
+
goto done;
|
2058
|
+
|
2059
|
+
git_annotated_commit_free(base);
|
2060
|
+
git_annotated_commit_free(other);
|
2061
|
+
|
2062
|
+
base = new_base;
|
2063
|
+
new_base = NULL;
|
2064
|
+
other = NULL;
|
2065
|
+
}
|
2066
|
+
|
2067
|
+
done:
|
2068
|
+
if (error == 0)
|
2069
|
+
*out = base;
|
2070
|
+
else
|
2071
|
+
git_annotated_commit_free(base);
|
2072
|
+
|
2073
|
+
git_annotated_commit_free(other);
|
2074
|
+
git_annotated_commit_free(new_base);
|
2075
|
+
git_oidarray_free(&bases);
|
2076
|
+
git_array_clear(head_ids);
|
2077
|
+
return error;
|
2078
|
+
}
|
2079
|
+
|
2080
|
+
static int iterator_for_annotated_commit(
|
2081
|
+
git_iterator **out,
|
2082
|
+
git_annotated_commit *commit)
|
2083
|
+
{
|
2084
|
+
git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
|
2085
|
+
int error;
|
2086
|
+
|
2087
|
+
opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
|
2088
|
+
|
2089
|
+
if (commit == NULL) {
|
2090
|
+
error = git_iterator_for_nothing(out, &opts);
|
2091
|
+
} else if (commit->type == GIT_ANNOTATED_COMMIT_VIRTUAL) {
|
2092
|
+
error = git_iterator_for_index(out, commit->index, &opts);
|
2093
|
+
} else {
|
2094
|
+
if (!commit->tree &&
|
2095
|
+
(error = git_commit_tree(&commit->tree, commit->commit)) < 0)
|
2096
|
+
goto done;
|
2097
|
+
|
2098
|
+
error = git_iterator_for_tree(out, commit->tree, &opts);
|
2099
|
+
}
|
2100
|
+
|
2101
|
+
done:
|
2102
|
+
return error;
|
2103
|
+
}
|
2104
|
+
|
2105
|
+
static int merge_annotated_commits(
|
2106
|
+
git_index **index_out,
|
2107
|
+
git_annotated_commit **base_out,
|
2108
|
+
git_repository *repo,
|
2109
|
+
git_annotated_commit *ours,
|
2110
|
+
git_annotated_commit *theirs,
|
2111
|
+
size_t recursion_level,
|
2112
|
+
const git_merge_options *opts)
|
2113
|
+
{
|
2114
|
+
git_annotated_commit *base = NULL;
|
2115
|
+
git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL;
|
2116
|
+
int error;
|
2117
|
+
|
2118
|
+
if ((error = compute_base(&base, repo, ours, theirs, opts,
|
2119
|
+
recursion_level)) < 0) {
|
2120
|
+
|
2121
|
+
if (error != GIT_ENOTFOUND)
|
2122
|
+
goto done;
|
2123
|
+
|
2124
|
+
giterr_clear();
|
2125
|
+
}
|
2126
|
+
|
2127
|
+
if ((error = iterator_for_annotated_commit(&base_iter, base)) < 0 ||
|
2128
|
+
(error = iterator_for_annotated_commit(&our_iter, ours)) < 0 ||
|
2129
|
+
(error = iterator_for_annotated_commit(&their_iter, theirs)) < 0 ||
|
2130
|
+
(error = git_merge__iterators(index_out, repo, base_iter, our_iter,
|
2131
|
+
their_iter, opts)) < 0)
|
2132
|
+
goto done;
|
2133
|
+
|
2134
|
+
if (base_out) {
|
2135
|
+
*base_out = base;
|
2136
|
+
base = NULL;
|
2137
|
+
}
|
2138
|
+
|
2139
|
+
done:
|
2140
|
+
git_annotated_commit_free(base);
|
2141
|
+
git_iterator_free(base_iter);
|
2142
|
+
git_iterator_free(our_iter);
|
2143
|
+
git_iterator_free(their_iter);
|
2144
|
+
return error;
|
2145
|
+
}
|
2146
|
+
|
1925
2147
|
|
1926
2148
|
int git_merge_commits(
|
1927
2149
|
git_index **out,
|
@@ -1930,30 +2152,19 @@ int git_merge_commits(
|
|
1930
2152
|
const git_commit *their_commit,
|
1931
2153
|
const git_merge_options *opts)
|
1932
2154
|
{
|
1933
|
-
|
1934
|
-
git_commit *ancestor_commit = NULL;
|
1935
|
-
git_tree *our_tree = NULL, *their_tree = NULL, *ancestor_tree = NULL;
|
2155
|
+
git_annotated_commit *ours = NULL, *theirs = NULL, *base = NULL;
|
1936
2156
|
int error = 0;
|
1937
2157
|
|
1938
|
-
if ((error =
|
1939
|
-
error
|
1940
|
-
giterr_clear();
|
1941
|
-
else if (error < 0 ||
|
1942
|
-
(error = git_commit_lookup(&ancestor_commit, repo, &ancestor_oid)) < 0 ||
|
1943
|
-
(error = git_commit_tree(&ancestor_tree, ancestor_commit)) < 0)
|
2158
|
+
if ((error = git_annotated_commit_from_commit(&ours, (git_commit *)our_commit)) < 0 ||
|
2159
|
+
(error = git_annotated_commit_from_commit(&theirs, (git_commit *)their_commit)) < 0)
|
1944
2160
|
goto done;
|
1945
2161
|
|
1946
|
-
|
1947
|
-
(error = git_commit_tree(&their_tree, their_commit)) < 0 ||
|
1948
|
-
(error = git_merge_trees(out, repo, ancestor_tree, our_tree, their_tree, opts)) < 0)
|
1949
|
-
goto done;
|
2162
|
+
error = merge_annotated_commits(out, &base, repo, ours, theirs, 0, opts);
|
1950
2163
|
|
1951
2164
|
done:
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
git_tree_free(ancestor_tree);
|
1956
|
-
|
2165
|
+
git_annotated_commit_free(ours);
|
2166
|
+
git_annotated_commit_free(theirs);
|
2167
|
+
git_annotated_commit_free(base);
|
1957
2168
|
return error;
|
1958
2169
|
}
|
1959
2170
|
|
@@ -2387,49 +2598,50 @@ const char *merge_their_label(const char *branchname)
|
|
2387
2598
|
}
|
2388
2599
|
|
2389
2600
|
static int merge_normalize_checkout_opts(
|
2601
|
+
git_checkout_options *out,
|
2390
2602
|
git_repository *repo,
|
2391
|
-
git_checkout_options *checkout_opts,
|
2392
2603
|
const git_checkout_options *given_checkout_opts,
|
2393
|
-
|
2604
|
+
unsigned int checkout_strategy,
|
2605
|
+
git_annotated_commit *ancestor,
|
2394
2606
|
const git_annotated_commit *our_head,
|
2395
|
-
|
2396
|
-
|
2607
|
+
const git_annotated_commit **their_heads,
|
2608
|
+
size_t their_heads_len)
|
2397
2609
|
{
|
2610
|
+
git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
|
2398
2611
|
int error = 0;
|
2399
2612
|
|
2400
2613
|
GIT_UNUSED(repo);
|
2401
2614
|
|
2402
2615
|
if (given_checkout_opts != NULL)
|
2403
|
-
memcpy(
|
2404
|
-
else
|
2405
|
-
|
2406
|
-
default_checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
2616
|
+
memcpy(out, given_checkout_opts, sizeof(git_checkout_options));
|
2617
|
+
else
|
2618
|
+
memcpy(out, &default_checkout_opts, sizeof(git_checkout_options));
|
2407
2619
|
|
2408
|
-
|
2409
|
-
}
|
2620
|
+
out->checkout_strategy = checkout_strategy;
|
2410
2621
|
|
2411
|
-
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2622
|
+
if (!out->ancestor_label) {
|
2623
|
+
if (ancestor && ancestor->type == GIT_ANNOTATED_COMMIT_REAL)
|
2624
|
+
out->ancestor_label = git_commit_summary(ancestor->commit);
|
2625
|
+
else if (ancestor)
|
2626
|
+
out->ancestor_label = "merged common ancestors";
|
2415
2627
|
else
|
2416
|
-
|
2628
|
+
out->ancestor_label = "empty base";
|
2417
2629
|
}
|
2418
2630
|
|
2419
|
-
if (!
|
2631
|
+
if (!out->our_label) {
|
2420
2632
|
if (our_head && our_head->ref_name)
|
2421
|
-
|
2633
|
+
out->our_label = our_head->ref_name;
|
2422
2634
|
else
|
2423
|
-
|
2635
|
+
out->our_label = "ours";
|
2424
2636
|
}
|
2425
2637
|
|
2426
|
-
if (!
|
2638
|
+
if (!out->their_label) {
|
2427
2639
|
if (their_heads_len == 1 && their_heads[0]->ref_name)
|
2428
|
-
|
2640
|
+
out->their_label = merge_their_label(their_heads[0]->ref_name);
|
2429
2641
|
else if (their_heads_len == 1)
|
2430
|
-
|
2642
|
+
out->their_label = their_heads[0]->id_str;
|
2431
2643
|
else
|
2432
|
-
|
2644
|
+
out->their_label = "theirs";
|
2433
2645
|
}
|
2434
2646
|
|
2435
2647
|
return error;
|
@@ -2782,11 +2994,10 @@ int git_merge(
|
|
2782
2994
|
{
|
2783
2995
|
git_reference *our_ref = NULL;
|
2784
2996
|
git_checkout_options checkout_opts;
|
2785
|
-
git_annotated_commit *
|
2786
|
-
git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL;
|
2997
|
+
git_annotated_commit *our_head = NULL, *base = NULL;
|
2787
2998
|
git_index *index = NULL;
|
2788
2999
|
git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
|
2789
|
-
|
3000
|
+
unsigned int checkout_strategy;
|
2790
3001
|
int error = 0;
|
2791
3002
|
|
2792
3003
|
assert(repo && their_heads);
|
@@ -2796,61 +3007,49 @@ int git_merge(
|
|
2796
3007
|
return -1;
|
2797
3008
|
}
|
2798
3009
|
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2802
|
-
if ((error = merge_heads(&ancestor_head, &our_head, repo, their_heads, their_heads_len)) < 0 ||
|
2803
|
-
(error = merge_normalize_checkout_opts(repo, &checkout_opts, given_checkout_opts,
|
2804
|
-
ancestor_head, our_head, their_heads_len, their_heads)) < 0 ||
|
2805
|
-
(error = git_indexwriter_init_for_operation(&indexwriter, repo, &checkout_opts.checkout_strategy)) < 0)
|
2806
|
-
goto on_error;
|
2807
|
-
|
2808
|
-
/* Write the merge files to the repository. */
|
2809
|
-
if ((error = git_merge__setup(repo, our_head, their_heads, their_heads_len)) < 0)
|
2810
|
-
goto on_error;
|
3010
|
+
if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
|
3011
|
+
goto done;
|
2811
3012
|
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
3013
|
+
checkout_strategy = given_checkout_opts ?
|
3014
|
+
given_checkout_opts->checkout_strategy :
|
3015
|
+
GIT_CHECKOUT_SAFE;
|
2815
3016
|
|
2816
|
-
if ((error =
|
2817
|
-
|
3017
|
+
if ((error = git_indexwriter_init_for_operation(&indexwriter, repo,
|
3018
|
+
&checkout_strategy)) < 0)
|
3019
|
+
goto done;
|
2818
3020
|
|
2819
|
-
|
2820
|
-
|
2821
|
-
|
2822
|
-
|
3021
|
+
/* Write the merge setup files to the repository. */
|
3022
|
+
if ((error = git_annotated_commit_from_head(&our_head, repo)) < 0 ||
|
3023
|
+
(error = git_merge__setup(repo, our_head, their_heads,
|
3024
|
+
their_heads_len)) < 0)
|
3025
|
+
goto done;
|
2823
3026
|
|
2824
|
-
/* TODO:
|
3027
|
+
/* TODO: octopus */
|
2825
3028
|
|
2826
|
-
if ((error =
|
3029
|
+
if ((error = merge_annotated_commits(&index, &base, repo, our_head,
|
3030
|
+
(git_annotated_commit *)their_heads[0], 0, merge_opts)) < 0 ||
|
2827
3031
|
(error = git_merge__check_result(repo, index)) < 0 ||
|
2828
|
-
(error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0
|
2829
|
-
|
2830
|
-
(error = git_indexwriter_commit(&indexwriter)) < 0)
|
2831
|
-
goto on_error;
|
3032
|
+
(error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0)
|
3033
|
+
goto done;
|
2832
3034
|
|
2833
|
-
|
3035
|
+
/* check out the merge results */
|
2834
3036
|
|
2835
|
-
|
2836
|
-
|
3037
|
+
if ((error = merge_normalize_checkout_opts(&checkout_opts, repo,
|
3038
|
+
given_checkout_opts, checkout_strategy,
|
3039
|
+
base, our_head, their_heads, their_heads_len)) < 0 ||
|
3040
|
+
(error = git_checkout_index(repo, index, &checkout_opts)) < 0)
|
3041
|
+
goto done;
|
3042
|
+
|
3043
|
+
error = git_indexwriter_commit(&indexwriter);
|
2837
3044
|
|
2838
3045
|
done:
|
2839
|
-
|
3046
|
+
if (error < 0)
|
3047
|
+
merge_state_cleanup(repo);
|
2840
3048
|
|
3049
|
+
git_indexwriter_cleanup(&indexwriter);
|
2841
3050
|
git_index_free(index);
|
2842
|
-
|
2843
|
-
git_tree_free(ancestor_tree);
|
2844
|
-
git_tree_free(our_tree);
|
2845
|
-
|
2846
|
-
for (i = 0; i < their_heads_len; i++)
|
2847
|
-
git_tree_free(their_trees[i]);
|
2848
|
-
|
2849
|
-
git__free(their_trees);
|
2850
|
-
|
2851
3051
|
git_annotated_commit_free(our_head);
|
2852
|
-
git_annotated_commit_free(
|
2853
|
-
|
3052
|
+
git_annotated_commit_free(base);
|
2854
3053
|
git_reference_free(our_ref);
|
2855
3054
|
|
2856
3055
|
return error;
|