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