rugged 0.23.0b2 → 0.23.0b4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_blob.c +39 -0
  3. data/ext/rugged/rugged_diff.c +7 -3
  4. data/ext/rugged/rugged_index.c +2 -2
  5. data/ext/rugged/rugged_remote.c +27 -148
  6. data/ext/rugged/rugged_remote_collection.c +134 -12
  7. data/ext/rugged/rugged_repo.c +74 -5
  8. data/ext/rugged/rugged_submodule.c +18 -208
  9. data/ext/rugged/rugged_submodule_collection.c +148 -0
  10. data/lib/rugged/version.rb +1 -1
  11. data/vendor/libgit2/AUTHORS +1 -0
  12. data/vendor/libgit2/CMakeLists.txt +33 -25
  13. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -29
  14. data/vendor/libgit2/include/git2.h +1 -1
  15. data/vendor/libgit2/include/git2/blob.h +4 -6
  16. data/vendor/libgit2/include/git2/checkout.h +10 -1
  17. data/vendor/libgit2/include/git2/clone.h +6 -7
  18. data/vendor/libgit2/include/git2/commit.h +11 -0
  19. data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
  20. data/vendor/libgit2/include/git2/describe.h +1 -1
  21. data/vendor/libgit2/include/git2/diff.h +68 -11
  22. data/vendor/libgit2/include/git2/errors.h +4 -1
  23. data/vendor/libgit2/include/git2/filter.h +16 -0
  24. data/vendor/libgit2/include/git2/index.h +38 -11
  25. data/vendor/libgit2/include/git2/odb.h +1 -1
  26. data/vendor/libgit2/include/git2/odb_backend.h +2 -2
  27. data/vendor/libgit2/include/git2/remote.h +300 -207
  28. data/vendor/libgit2/include/git2/reset.h +1 -0
  29. data/vendor/libgit2/include/git2/stash.h +135 -4
  30. data/vendor/libgit2/include/git2/status.h +1 -0
  31. data/vendor/libgit2/include/git2/submodule.h +46 -75
  32. data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
  33. data/vendor/libgit2/include/git2/sys/stream.h +2 -0
  34. data/vendor/libgit2/include/git2/sys/transport.h +1 -21
  35. data/vendor/libgit2/include/git2/transport.h +27 -0
  36. data/vendor/libgit2/include/git2/types.h +20 -10
  37. data/vendor/libgit2/include/git2/version.h +3 -3
  38. data/vendor/libgit2/libgit2.pc.in +4 -2
  39. data/vendor/libgit2/src/attr.c +2 -1
  40. data/vendor/libgit2/src/attr_file.c +18 -37
  41. data/vendor/libgit2/src/blame.c +2 -2
  42. data/vendor/libgit2/src/blob.c +4 -3
  43. data/vendor/libgit2/src/branch.c +6 -3
  44. data/vendor/libgit2/src/buf_text.c +4 -6
  45. data/vendor/libgit2/src/buf_text.h +1 -2
  46. data/vendor/libgit2/src/buffer.c +8 -6
  47. data/vendor/libgit2/src/buffer.h +1 -1
  48. data/vendor/libgit2/src/cache.c +1 -0
  49. data/vendor/libgit2/src/checkout.c +34 -20
  50. data/vendor/libgit2/src/clone.c +29 -29
  51. data/vendor/libgit2/src/commit.c +65 -0
  52. data/vendor/libgit2/src/common.h +5 -0
  53. data/vendor/libgit2/src/config.c +20 -0
  54. data/vendor/libgit2/src/config.h +6 -0
  55. data/vendor/libgit2/src/config_file.c +2 -2
  56. data/vendor/libgit2/src/crlf.c +39 -17
  57. data/vendor/libgit2/src/curl_stream.c +257 -0
  58. data/vendor/libgit2/src/curl_stream.h +14 -0
  59. data/vendor/libgit2/src/diff.c +223 -88
  60. data/vendor/libgit2/src/diff.h +21 -1
  61. data/vendor/libgit2/src/diff_file.c +23 -13
  62. data/vendor/libgit2/src/diff_file.h +4 -2
  63. data/vendor/libgit2/src/diff_patch.c +266 -71
  64. data/vendor/libgit2/src/diff_patch.h +36 -0
  65. data/vendor/libgit2/src/diff_print.c +156 -126
  66. data/vendor/libgit2/src/diff_tform.c +32 -54
  67. data/vendor/libgit2/src/fetch.c +27 -10
  68. data/vendor/libgit2/src/fetch.h +2 -2
  69. data/vendor/libgit2/src/filebuf.c +1 -1
  70. data/vendor/libgit2/src/fileops.c +6 -2
  71. data/vendor/libgit2/src/filter.c +28 -7
  72. data/vendor/libgit2/src/fnmatch.c +5 -5
  73. data/vendor/libgit2/src/global.c +16 -0
  74. data/vendor/libgit2/src/ident.c +2 -2
  75. data/vendor/libgit2/src/ignore.c +1 -0
  76. data/vendor/libgit2/src/index.c +338 -80
  77. data/vendor/libgit2/src/index.h +4 -1
  78. data/vendor/libgit2/src/indexer.c +19 -5
  79. data/vendor/libgit2/src/iterator.c +118 -11
  80. data/vendor/libgit2/src/iterator.h +25 -0
  81. data/vendor/libgit2/src/merge.c +96 -106
  82. data/vendor/libgit2/src/merge.h +14 -4
  83. data/vendor/libgit2/src/netops.c +3 -3
  84. data/vendor/libgit2/src/odb.c +17 -9
  85. data/vendor/libgit2/src/odb.h +1 -1
  86. data/vendor/libgit2/src/odb_loose.c +2 -2
  87. data/vendor/libgit2/src/odb_pack.c +1 -1
  88. data/vendor/libgit2/src/openssl_stream.c +118 -27
  89. data/vendor/libgit2/src/pack-objects.c +28 -0
  90. data/vendor/libgit2/src/pack-objects.h +1 -0
  91. data/vendor/libgit2/src/pack.c +18 -10
  92. data/vendor/libgit2/src/path.c +16 -11
  93. data/vendor/libgit2/src/path.h +1 -1
  94. data/vendor/libgit2/src/push.c +26 -42
  95. data/vendor/libgit2/src/push.h +2 -34
  96. data/vendor/libgit2/src/rebase.c +1 -1
  97. data/vendor/libgit2/src/refs.c +1 -1
  98. data/vendor/libgit2/src/refspec.c +6 -0
  99. data/vendor/libgit2/src/remote.c +381 -274
  100. data/vendor/libgit2/src/remote.h +0 -4
  101. data/vendor/libgit2/src/repository.c +33 -12
  102. data/vendor/libgit2/src/repository.h +0 -1
  103. data/vendor/libgit2/src/reset.c +1 -0
  104. data/vendor/libgit2/src/stash.c +439 -17
  105. data/vendor/libgit2/src/status.c +6 -0
  106. data/vendor/libgit2/src/stransport_stream.c +58 -21
  107. data/vendor/libgit2/src/stream.h +15 -0
  108. data/vendor/libgit2/src/submodule.c +410 -664
  109. data/vendor/libgit2/src/submodule.h +0 -24
  110. data/vendor/libgit2/src/transaction.c +1 -0
  111. data/vendor/libgit2/src/transports/cred.c +55 -1
  112. data/vendor/libgit2/src/transports/http.c +18 -2
  113. data/vendor/libgit2/src/transports/local.c +60 -59
  114. data/vendor/libgit2/src/transports/smart.h +1 -1
  115. data/vendor/libgit2/src/transports/smart_protocol.c +11 -11
  116. data/vendor/libgit2/src/transports/ssh.c +46 -7
  117. data/vendor/libgit2/src/unix/posix.h +4 -0
  118. data/vendor/libgit2/src/util.c +9 -9
  119. data/vendor/libgit2/src/util.h +9 -0
  120. data/vendor/libgit2/src/win32/posix.h +3 -0
  121. data/vendor/libgit2/src/win32/posix_w32.c +38 -0
  122. data/vendor/libgit2/src/win32/w32_util.h +10 -0
  123. metadata +4 -3
  124. data/vendor/libgit2/include/git2/push.h +0 -94
@@ -22,6 +22,7 @@ struct git_index {
22
22
 
23
23
  char *index_file_path;
24
24
  git_futils_filestamp stamp;
25
+ git_oid checksum; /* checksum at the end of the file */
25
26
 
26
27
  git_vector entries;
27
28
 
@@ -80,7 +81,7 @@ GIT_INLINE(const git_futils_filestamp *) git_index__filestamp(git_index *index)
80
81
  return &index->stamp;
81
82
  }
82
83
 
83
- extern int git_index__changed_relative_to(git_index *index, const git_futils_filestamp *fs);
84
+ extern int git_index__changed_relative_to(git_index *index, const git_oid *checksum);
84
85
 
85
86
  /* Copy the current entries vector *and* increment the index refcount.
86
87
  * Call `git_index__release_snapshot` when done.
@@ -93,6 +94,8 @@ extern int git_index_snapshot_find(
93
94
  size_t *at_pos, git_vector *snap, git_vector_cmp entry_srch,
94
95
  const char *path, size_t path_len, int stage);
95
96
 
97
+ /* Replace an index with a new index */
98
+ int git_index_read_index(git_index *index, const git_index *new_index);
96
99
 
97
100
  typedef struct {
98
101
  git_index *index;
@@ -325,6 +325,13 @@ on_error:
325
325
  return -1;
326
326
  }
327
327
 
328
+ GIT_INLINE(bool) has_entry(git_indexer *idx, git_oid *id)
329
+ {
330
+ khiter_t k;
331
+ k = kh_get(oid, idx->pack->idx_cache, id);
332
+ return (k != kh_end(idx->pack->idx_cache));
333
+ }
334
+
328
335
  static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start)
329
336
  {
330
337
  int i, error;
@@ -339,8 +346,11 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent
339
346
 
340
347
  pentry->offset = entry_start;
341
348
  k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
342
- if (!error)
349
+
350
+ if (error <= 0) {
351
+ giterr_set(GITERR_INDEXER, "cannot insert object into pack");
343
352
  return -1;
353
+ }
344
354
 
345
355
  kh_value(idx->pack->idx_cache, k) = pentry;
346
356
 
@@ -468,13 +478,14 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
468
478
  static int append_to_pack(git_indexer *idx, const void *data, size_t size)
469
479
  {
470
480
  git_off_t current_size = idx->pack->mwf.size;
481
+ int fd = idx->pack->mwf.fd;
471
482
 
472
483
  if (!size)
473
484
  return 0;
474
485
 
475
- /* add the extra space we need at the end */
476
- if (p_ftruncate(idx->pack->mwf.fd, current_size + size) < 0) {
477
- giterr_set(GITERR_OS, "Failed to increase size of pack file '%s'", idx->pack->pack_name);
486
+ if (p_lseek(fd, current_size + size - 1, SEEK_SET) < 0 ||
487
+ p_write(idx->pack->mwf.fd, data, 1) < 0) {
488
+ giterr_set(GITERR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
478
489
  return -1;
479
490
  }
480
491
 
@@ -791,6 +802,9 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
791
802
  git_oid_fromraw(&base, base_info);
792
803
  git_mwindow_close(&w);
793
804
 
805
+ if (has_entry(idx, &base))
806
+ return 0;
807
+
794
808
  if (inject_object(idx, &base) < 0)
795
809
  return -1;
796
810
 
@@ -809,7 +823,7 @@ static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats)
809
823
  progressed = 0;
810
824
  non_null = 0;
811
825
  git_vector_foreach(&idx->deltas, i, delta) {
812
- git_rawobj obj;
826
+ git_rawobj obj = {NULL};
813
827
 
814
828
  if (!delta)
815
829
  continue;
@@ -46,6 +46,7 @@
46
46
  #define iterator__include_trees(I) iterator__flag(I,INCLUDE_TREES)
47
47
  #define iterator__dont_autoexpand(I) iterator__flag(I,DONT_AUTOEXPAND)
48
48
  #define iterator__do_autoexpand(I) !iterator__flag(I,DONT_AUTOEXPAND)
49
+ #define iterator__include_conflicts(I) iterator__flag(I, INCLUDE_CONFLICTS)
49
50
 
50
51
  #define GIT_ITERATOR_FIRST_ACCESS (1 << 15)
51
52
  #define iterator__has_been_accessed(I) iterator__flag(I,FIRST_ACCESS)
@@ -668,13 +669,16 @@ static const git_index_entry *index_iterator__index_entry(index_iterator *ii)
668
669
  return ie;
669
670
  }
670
671
 
671
- static const git_index_entry *index_iterator__skip_conflicts(index_iterator *ii)
672
+ static const git_index_entry *index_iterator__advance_over_conflicts(index_iterator *ii)
672
673
  {
673
- const git_index_entry *ie;
674
+ const git_index_entry *ie = index_iterator__index_entry(ii);
674
675
 
675
- while ((ie = index_iterator__index_entry(ii)) != NULL &&
676
- git_index_entry_stage(ie) != 0)
677
- ii->current++;
676
+ if (!iterator__include_conflicts(ii)) {
677
+ while (ie && git_index_entry_is_conflict(ie)) {
678
+ ii->current++;
679
+ ie = index_iterator__index_entry(ii);
680
+ }
681
+ }
678
682
 
679
683
  return ie;
680
684
  }
@@ -702,7 +706,7 @@ static void index_iterator__next_prefix_tree(index_iterator *ii)
702
706
 
703
707
  static int index_iterator__first_prefix_tree(index_iterator *ii)
704
708
  {
705
- const git_index_entry *ie = index_iterator__skip_conflicts(ii);
709
+ const git_index_entry *ie = index_iterator__advance_over_conflicts(ii);
706
710
  const char *scan, *prior, *slash;
707
711
 
708
712
  if (!ie || !iterator__include_trees(ii))
@@ -825,7 +829,7 @@ static int index_iterator__reset(
825
829
  git_index_snapshot_find(
826
830
  &ii->current, &ii->entries, ii->entry_srch, ii->base.start, 0, 0);
827
831
 
828
- if ((ie = index_iterator__skip_conflicts(ii)) == NULL)
832
+ if ((ie = index_iterator__advance_over_conflicts(ii)) == NULL)
829
833
  return 0;
830
834
 
831
835
  if (git_buf_sets(&ii->partial, ie->path) < 0)
@@ -1401,10 +1405,10 @@ GIT_INLINE(bool) workdir_path_is_dotgit(const git_buf *path)
1401
1405
  if (path->ptr[len - 1] == '/')
1402
1406
  len--;
1403
1407
 
1404
- if (tolower(path->ptr[len - 1]) != 't' ||
1405
- tolower(path->ptr[len - 2]) != 'i' ||
1406
- tolower(path->ptr[len - 3]) != 'g' ||
1407
- tolower(path->ptr[len - 4]) != '.')
1408
+ if (git__tolower(path->ptr[len - 1]) != 't' ||
1409
+ git__tolower(path->ptr[len - 2]) != 'i' ||
1410
+ git__tolower(path->ptr[len - 3]) != 'g' ||
1411
+ git__tolower(path->ptr[len - 4]) != '.')
1408
1412
  return false;
1409
1413
 
1410
1414
  return (len == 4 || path->ptr[len - 5] == '/');
@@ -1758,6 +1762,18 @@ int git_iterator_current_workdir_path(git_buf **path, git_iterator *iter)
1758
1762
  return 0;
1759
1763
  }
1760
1764
 
1765
+ int git_iterator_index(git_index **out, git_iterator *iter)
1766
+ {
1767
+ workdir_iterator *wi = (workdir_iterator *)iter;
1768
+
1769
+ if (iter->type != GIT_ITERATOR_TYPE_WORKDIR)
1770
+ *out = NULL;
1771
+
1772
+ *out = wi->index;
1773
+
1774
+ return 0;
1775
+ }
1776
+
1761
1777
  int git_iterator_advance_over_with_status(
1762
1778
  const git_index_entry **entryptr,
1763
1779
  git_iterator_status_t *status,
@@ -1827,3 +1843,94 @@ int git_iterator_advance_over_with_status(
1827
1843
  return error;
1828
1844
  }
1829
1845
 
1846
+ int git_iterator_walk(
1847
+ git_iterator **iterators,
1848
+ size_t cnt,
1849
+ git_iterator_walk_cb cb,
1850
+ void *data)
1851
+ {
1852
+ const git_index_entry **iterator_item; /* next in each iterator */
1853
+ const git_index_entry **cur_items; /* current path in each iter */
1854
+ const git_index_entry *first_match;
1855
+ int cur_item_modified;
1856
+ size_t i, j;
1857
+ int error = 0;
1858
+
1859
+ iterator_item = git__calloc(cnt, sizeof(git_index_entry *));
1860
+ cur_items = git__calloc(cnt, sizeof(git_index_entry *));
1861
+
1862
+ GITERR_CHECK_ALLOC(iterator_item);
1863
+ GITERR_CHECK_ALLOC(cur_items);
1864
+
1865
+ /* Set up the iterators */
1866
+ for (i = 0; i < cnt; i++) {
1867
+ error = git_iterator_current(&iterator_item[i], iterators[i]);
1868
+
1869
+ if (error < 0 && error != GIT_ITEROVER)
1870
+ goto done;
1871
+ }
1872
+
1873
+ while (true) {
1874
+ for (i = 0; i < cnt; i++)
1875
+ cur_items[i] = NULL;
1876
+
1877
+ first_match = NULL;
1878
+ cur_item_modified = 0;
1879
+
1880
+ /* Find the next path(s) to consume from each iterator */
1881
+ for (i = 0; i < cnt; i++) {
1882
+ if (iterator_item[i] == NULL)
1883
+ continue;
1884
+
1885
+ if (first_match == NULL) {
1886
+ first_match = iterator_item[i];
1887
+ cur_items[i] = iterator_item[i];
1888
+ } else {
1889
+ int path_diff = git_index_entry_cmp(iterator_item[i], first_match);
1890
+
1891
+ if (path_diff < 0) {
1892
+ /* Found an index entry that sorts before the one we're
1893
+ * looking at. Forget that we've seen the other and
1894
+ * look at the other iterators for this path.
1895
+ */
1896
+ for (j = 0; j < i; j++)
1897
+ cur_items[j] = NULL;
1898
+
1899
+ first_match = iterator_item[i];
1900
+ cur_items[i] = iterator_item[i];
1901
+ } else if (path_diff > 0) {
1902
+ /* No entry for the current item, this is modified */
1903
+ cur_item_modified = 1;
1904
+ } else if (path_diff == 0) {
1905
+ cur_items[i] = iterator_item[i];
1906
+ }
1907
+ }
1908
+ }
1909
+
1910
+ if (first_match == NULL)
1911
+ break;
1912
+
1913
+ if ((error = cb(cur_items, data)) != 0)
1914
+ goto done;
1915
+
1916
+ /* Advance each iterator that participated */
1917
+ for (i = 0; i < cnt; i++) {
1918
+ if (cur_items[i] == NULL)
1919
+ continue;
1920
+
1921
+ error = git_iterator_advance(&iterator_item[i], iterators[i]);
1922
+
1923
+ if (error < 0 && error != GIT_ITEROVER)
1924
+ goto done;
1925
+ }
1926
+ }
1927
+
1928
+ done:
1929
+ git__free(iterator_item);
1930
+ git__free(cur_items);
1931
+
1932
+ if (error == GIT_ITEROVER)
1933
+ error = 0;
1934
+
1935
+ return error;
1936
+ }
@@ -11,6 +11,7 @@
11
11
  #include "git2/index.h"
12
12
  #include "vector.h"
13
13
  #include "buffer.h"
14
+ #include "ignore.h"
14
15
 
15
16
  typedef struct git_iterator git_iterator;
16
17
 
@@ -33,6 +34,8 @@ typedef enum {
33
34
  GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
34
35
  /** convert precomposed unicode to decomposed unicode */
35
36
  GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
37
+ /** include conflicts */
38
+ GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 5),
36
39
  } git_iterator_flag_t;
37
40
 
38
41
  typedef struct {
@@ -284,4 +287,26 @@ typedef enum {
284
287
  extern int git_iterator_advance_over_with_status(
285
288
  const git_index_entry **entry, git_iterator_status_t *status, git_iterator *iter);
286
289
 
290
+ /**
291
+ * Retrieve the index stored in the iterator.
292
+ *
293
+ * Only implemented for the workdir iterator
294
+ */
295
+ extern int git_iterator_index(git_index **out, git_iterator *iter);
296
+
297
+ typedef int (*git_iterator_walk_cb)(
298
+ const git_index_entry **entries,
299
+ void *data);
300
+
301
+ /**
302
+ * Walk the given iterators in lock-step. The given callback will be
303
+ * called for each unique path, with the index entry in each iterator
304
+ * (or NULL if the given iterator does not contain that path).
305
+ */
306
+ extern int git_iterator_walk(
307
+ git_iterator **iterators,
308
+ size_t cnt,
309
+ git_iterator_walk_cb cb,
310
+ void *data);
311
+
287
312
  #endif
@@ -1143,9 +1143,9 @@ static void merge_diff_list_count_candidates(
1143
1143
  if (GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry) &&
1144
1144
  (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->our_entry) ||
1145
1145
  !GIT_MERGE_INDEX_ENTRY_EXISTS(entry->their_entry)))
1146
- src_count++;
1146
+ (*src_count)++;
1147
1147
  else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry))
1148
- tgt_count++;
1148
+ (*tgt_count)++;
1149
1149
  }
1150
1150
  }
1151
1151
 
@@ -1449,108 +1449,44 @@ static int merge_diff_list_insert_unmodified(
1449
1449
  return error;
1450
1450
  }
1451
1451
 
1452
- int git_merge_diff_list__find_differences(
1453
- git_merge_diff_list *diff_list,
1454
- const git_tree *ancestor_tree,
1455
- const git_tree *our_tree,
1456
- const git_tree *their_tree)
1457
- {
1458
- git_iterator *iterators[3] = {0};
1459
- const git_index_entry *items[3] = {0}, *best_cur_item, *cur_items[3];
1460
- git_vector_cmp entry_compare = git_index_entry_cmp;
1461
- struct merge_diff_df_data df_data = {0};
1462
- int cur_item_modified;
1463
- size_t i, j;
1464
- int error = 0;
1465
-
1466
- assert(diff_list && (our_tree || their_tree));
1467
-
1468
- if ((error = git_iterator_for_tree(&iterators[TREE_IDX_ANCESTOR], (git_tree *)ancestor_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
1469
- (error = git_iterator_for_tree(&iterators[TREE_IDX_OURS], (git_tree *)our_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
1470
- (error = git_iterator_for_tree(&iterators[TREE_IDX_THEIRS], (git_tree *)their_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0)
1471
- goto done;
1472
-
1473
- /* Set up the iterators */
1474
- for (i = 0; i < 3; i++) {
1475
- error = git_iterator_current(&items[i], iterators[i]);
1476
-
1477
- if (error < 0 && error != GIT_ITEROVER)
1478
- goto done;
1479
- }
1480
-
1481
- while (true) {
1482
- for (i = 0; i < 3; i++)
1483
- cur_items[i] = NULL;
1484
-
1485
- best_cur_item = NULL;
1486
- cur_item_modified = 0;
1452
+ struct merge_diff_find_data {
1453
+ git_merge_diff_list *diff_list;
1454
+ struct merge_diff_df_data df_data;
1455
+ };
1487
1456
 
1488
- /* Find the next path(s) to consume from each iterator */
1489
- for (i = 0; i < 3; i++) {
1490
- if (items[i] == NULL) {
1491
- cur_item_modified = 1;
1492
- continue;
1493
- }
1457
+ static int queue_difference(const git_index_entry **entries, void *data)
1458
+ {
1459
+ struct merge_diff_find_data *find_data = data;
1460
+ bool item_modified = false;
1461
+ size_t i;
1494
1462
 
1495
- if (best_cur_item == NULL) {
1496
- best_cur_item = items[i];
1497
- cur_items[i] = items[i];
1498
- } else {
1499
- int path_diff = entry_compare(items[i], best_cur_item);
1500
-
1501
- if (path_diff < 0) {
1502
- /*
1503
- * Found an item that sorts before our current item, make
1504
- * our current item this one.
1505
- */
1506
- for (j = 0; j < i; j++)
1507
- cur_items[j] = NULL;
1508
-
1509
- cur_item_modified = 1;
1510
- best_cur_item = items[i];
1511
- cur_items[i] = items[i];
1512
- } else if (path_diff > 0) {
1513
- /* No entry for the current item, this is modified */
1514
- cur_item_modified = 1;
1515
- } else if (path_diff == 0) {
1516
- cur_items[i] = items[i];
1517
-
1518
- if (!cur_item_modified)
1519
- cur_item_modified = index_entry_cmp(best_cur_item, items[i]);
1520
- }
1463
+ if (!entries[0] || !entries[1] || !entries[2]) {
1464
+ item_modified = true;
1465
+ } else {
1466
+ for (i = 1; i < 3; i++) {
1467
+ if (index_entry_cmp(entries[0], entries[i]) != 0) {
1468
+ item_modified = true;
1469
+ break;
1521
1470
  }
1522
1471
  }
1523
-
1524
- if (best_cur_item == NULL)
1525
- break;
1526
-
1527
- if (cur_item_modified)
1528
- error = merge_diff_list_insert_conflict(diff_list, &df_data, cur_items);
1529
- else
1530
- error = merge_diff_list_insert_unmodified(diff_list, cur_items);
1531
- if (error < 0)
1532
- goto done;
1533
-
1534
- /* Advance each iterator that participated */
1535
- for (i = 0; i < 3; i++) {
1536
- if (cur_items[i] == NULL)
1537
- continue;
1538
-
1539
- error = git_iterator_advance(&items[i], iterators[i]);
1540
-
1541
- if (error < 0 && error != GIT_ITEROVER)
1542
- goto done;
1543
- }
1544
1472
  }
1545
1473
 
1546
- done:
1547
- for (i = 0; i < 3; i++)
1548
- git_iterator_free(iterators[i]);
1474
+ return item_modified ?
1475
+ merge_diff_list_insert_conflict(
1476
+ find_data->diff_list, &find_data->df_data, entries) :
1477
+ merge_diff_list_insert_unmodified(find_data->diff_list, entries);
1478
+ }
1549
1479
 
1550
- if (error == GIT_ITEROVER)
1551
- error = 0;
1480
+ int git_merge_diff_list__find_differences(
1481
+ git_merge_diff_list *diff_list,
1482
+ git_iterator *ancestor_iter,
1483
+ git_iterator *our_iter,
1484
+ git_iterator *their_iter)
1485
+ {
1486
+ git_iterator *iterators[3] = { ancestor_iter, our_iter, their_iter };
1487
+ struct merge_diff_find_data find_data = { diff_list };
1552
1488
 
1553
- return error;
1489
+ return git_iterator_walk(iterators, 3, queue_difference, &find_data);
1554
1490
  }
1555
1491
 
1556
1492
  git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
@@ -1757,14 +1693,28 @@ on_error:
1757
1693
  return error;
1758
1694
  }
1759
1695
 
1760
- int git_merge_trees(
1696
+ static git_iterator *iterator_given_or_empty(git_iterator **empty, git_iterator *given)
1697
+ {
1698
+ if (given)
1699
+ return given;
1700
+
1701
+ if (git_iterator_for_nothing(empty, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL) < 0)
1702
+ return NULL;
1703
+
1704
+ return *empty;
1705
+ }
1706
+
1707
+ int git_merge__iterators(
1761
1708
  git_index **out,
1762
1709
  git_repository *repo,
1763
- const git_tree *ancestor_tree,
1764
- const git_tree *our_tree,
1765
- const git_tree *their_tree,
1710
+ git_iterator *ancestor_iter,
1711
+ git_iterator *our_iter,
1712
+ git_iterator *theirs_iter,
1766
1713
  const git_merge_options *given_opts)
1767
1714
  {
1715
+ git_iterator *empty_ancestor = NULL,
1716
+ *empty_ours = NULL,
1717
+ *empty_theirs = NULL;
1768
1718
  git_merge_diff_list *diff_list;
1769
1719
  git_merge_options opts;
1770
1720
  git_merge_diff *conflict;
@@ -1772,11 +1722,12 @@ int git_merge_trees(
1772
1722
  size_t i;
1773
1723
  int error = 0;
1774
1724
 
1775
- assert(out && repo && (our_tree || their_tree));
1725
+ assert(out && repo);
1776
1726
 
1777
1727
  *out = NULL;
1778
1728
 
1779
- GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
1729
+ GITERR_CHECK_VERSION(
1730
+ given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
1780
1731
 
1781
1732
  if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0)
1782
1733
  return error;
@@ -1784,7 +1735,12 @@ int git_merge_trees(
1784
1735
  diff_list = git_merge_diff_list__alloc(repo);
1785
1736
  GITERR_CHECK_ALLOC(diff_list);
1786
1737
 
1787
- if ((error = git_merge_diff_list__find_differences(diff_list, ancestor_tree, our_tree, their_tree)) < 0 ||
1738
+ ancestor_iter = iterator_given_or_empty(&empty_ancestor, ancestor_iter);
1739
+ our_iter = iterator_given_or_empty(&empty_ours, our_iter);
1740
+ theirs_iter = iterator_given_or_empty(&empty_theirs, theirs_iter);
1741
+
1742
+ if ((error = git_merge_diff_list__find_differences(
1743
+ diff_list, ancestor_iter, our_iter, theirs_iter)) < 0 ||
1788
1744
  (error = git_merge_diff_list__find_renames(repo, diff_list, &opts)) < 0)
1789
1745
  goto done;
1790
1746
 
@@ -1808,10 +1764,44 @@ int git_merge_trees(
1808
1764
 
1809
1765
  done:
1810
1766
  git_merge_diff_list__free(diff_list);
1767
+ git_iterator_free(empty_ancestor);
1768
+ git_iterator_free(empty_ours);
1769
+ git_iterator_free(empty_theirs);
1811
1770
 
1812
1771
  return error;
1813
1772
  }
1814
1773
 
1774
+ int git_merge_trees(
1775
+ git_index **out,
1776
+ git_repository *repo,
1777
+ const git_tree *ancestor_tree,
1778
+ const git_tree *our_tree,
1779
+ const git_tree *their_tree,
1780
+ const git_merge_options *merge_opts)
1781
+ {
1782
+ git_iterator *ancestor_iter = NULL, *our_iter = NULL, *their_iter = NULL;
1783
+ int error;
1784
+
1785
+ if ((error = git_iterator_for_tree(&ancestor_iter, (git_tree *)ancestor_tree,
1786
+ GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
1787
+ (error = git_iterator_for_tree(&our_iter, (git_tree *)our_tree,
1788
+ GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
1789
+ (error = git_iterator_for_tree(&their_iter, (git_tree *)their_tree,
1790
+ GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0)
1791
+ goto done;
1792
+
1793
+ error = git_merge__iterators(
1794
+ out, repo, ancestor_iter, our_iter, their_iter, merge_opts);
1795
+
1796
+ done:
1797
+ git_iterator_free(ancestor_iter);
1798
+ git_iterator_free(our_iter);
1799
+ git_iterator_free(their_iter);
1800
+
1801
+ return error;
1802
+ }
1803
+
1804
+
1815
1805
  int git_merge_commits(
1816
1806
  git_index **out,
1817
1807
  git_repository *repo,
@@ -2446,7 +2436,7 @@ int git_merge__check_result(git_repository *repo, git_index *index_new)
2446
2436
  for (i = 0; i < git_index_entrycount(index_new); i++) {
2447
2437
  e = git_index_get_byindex(index_new, i);
2448
2438
 
2449
- if (git_index_entry_stage(e) != 0 &&
2439
+ if (git_index_entry_is_conflict(e) &&
2450
2440
  (git_vector_last(&paths) == NULL ||
2451
2441
  strcmp(git_vector_last(&paths), e->path) != 0)) {
2452
2442
 
@@ -2463,7 +2453,7 @@ int git_merge__check_result(git_repository *repo, git_index *index_new)
2463
2453
  if ((conflicts = index_conflicts + wd_conflicts) > 0) {
2464
2454
  giterr_set(GITERR_MERGE, "%d uncommitted change%s would be overwritten by merge",
2465
2455
  conflicts, (conflicts != 1) ? "s" : "");
2466
- error = GIT_EMERGECONFLICT;
2456
+ error = GIT_ECONFLICT;
2467
2457
  }
2468
2458
 
2469
2459
  done:
@@ -2498,7 +2488,7 @@ int git_merge__append_conflicts_to_merge_msg(
2498
2488
  for (i = 0; i < git_index_entrycount(index); i++) {
2499
2489
  const git_index_entry *e = git_index_get_byindex(index, i);
2500
2490
 
2501
- if (git_index_entry_stage(e) == 0)
2491
+ if (!git_index_entry_is_conflict(e))
2502
2492
  continue;
2503
2493
 
2504
2494
  if (last == NULL || strcmp(e->path, last) != 0)