rugged 0.23.0b1 → 0.23.0b2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_note.c +7 -2
  3. data/ext/rugged/rugged_revwalk.c +321 -145
  4. data/lib/rugged/version.rb +1 -1
  5. data/vendor/libgit2/CMakeLists.txt +83 -8
  6. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +9 -0
  7. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +0 -3
  8. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +9 -0
  9. data/vendor/libgit2/deps/winhttp/urlmon.h +45 -0
  10. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -0
  11. data/vendor/libgit2/deps/winhttp/winhttp.h +592 -0
  12. data/vendor/libgit2/deps/winhttp/winhttp64.def +29 -0
  13. data/vendor/libgit2/include/git2/diff.h +6 -1
  14. data/vendor/libgit2/include/git2/index.h +1 -1
  15. data/vendor/libgit2/include/git2/merge.h +2 -1
  16. data/vendor/libgit2/include/git2/notes.h +2 -2
  17. data/vendor/libgit2/include/git2/pack.h +12 -0
  18. data/vendor/libgit2/include/git2/push.h +30 -0
  19. data/vendor/libgit2/include/git2/rebase.h +36 -16
  20. data/vendor/libgit2/include/git2/remote.h +6 -0
  21. data/vendor/libgit2/include/git2/reset.h +2 -2
  22. data/vendor/libgit2/include/git2/revwalk.h +10 -8
  23. data/vendor/libgit2/include/git2/submodule.h +16 -0
  24. data/vendor/libgit2/include/git2/sys/transport.h +12 -4
  25. data/vendor/libgit2/include/git2/types.h +1 -0
  26. data/vendor/libgit2/src/attr.c +3 -3
  27. data/vendor/libgit2/src/attr_file.c +24 -3
  28. data/vendor/libgit2/src/attr_file.h +3 -1
  29. data/vendor/libgit2/src/checkout.c +31 -7
  30. data/vendor/libgit2/src/config.c +5 -6
  31. data/vendor/libgit2/src/config_file.c +533 -469
  32. data/vendor/libgit2/src/describe.c +1 -1
  33. data/vendor/libgit2/src/diff.c +20 -10
  34. data/vendor/libgit2/src/diff_driver.c +1 -1
  35. data/vendor/libgit2/src/diff_tform.c +8 -2
  36. data/vendor/libgit2/src/filter.c +6 -3
  37. data/vendor/libgit2/src/global.c +17 -15
  38. data/vendor/libgit2/src/global.h +3 -1
  39. data/vendor/libgit2/src/ignore.c +48 -8
  40. data/vendor/libgit2/src/ignore.h +1 -1
  41. data/vendor/libgit2/src/index.c +12 -8
  42. data/vendor/libgit2/src/iterator.c +133 -12
  43. data/vendor/libgit2/src/netops.h +2 -2
  44. data/vendor/libgit2/src/notes.c +40 -21
  45. data/vendor/libgit2/src/openssl_stream.c +5 -1
  46. data/vendor/libgit2/src/pack-objects.c +36 -0
  47. data/vendor/libgit2/src/path.c +277 -140
  48. data/vendor/libgit2/src/path.h +132 -60
  49. data/vendor/libgit2/src/posix.h +0 -1
  50. data/vendor/libgit2/src/push.c +43 -4
  51. data/vendor/libgit2/src/push.h +8 -1
  52. data/vendor/libgit2/src/rebase.c +139 -119
  53. data/vendor/libgit2/src/reflog.c +1 -1
  54. data/vendor/libgit2/src/refs.c +3 -5
  55. data/vendor/libgit2/src/remote.c +6 -5
  56. data/vendor/libgit2/src/repository.c +7 -3
  57. data/vendor/libgit2/src/reset.c +3 -3
  58. data/vendor/libgit2/src/revwalk.c +26 -2
  59. data/vendor/libgit2/src/settings.c +3 -3
  60. data/vendor/libgit2/src/stransport_stream.c +249 -0
  61. data/vendor/libgit2/src/stransport_stream.h +14 -0
  62. data/vendor/libgit2/src/submodule.c +26 -2
  63. data/vendor/libgit2/src/tls_stream.c +28 -0
  64. data/vendor/libgit2/src/tls_stream.h +21 -0
  65. data/vendor/libgit2/src/transport.c +4 -4
  66. data/vendor/libgit2/src/transports/git.c +4 -1
  67. data/vendor/libgit2/src/transports/http.c +6 -4
  68. data/vendor/libgit2/src/transports/local.c +2 -1
  69. data/vendor/libgit2/src/transports/smart.c +1 -1
  70. data/vendor/libgit2/src/transports/ssh.c +5 -1
  71. data/vendor/libgit2/src/transports/winhttp.c +30 -23
  72. data/vendor/libgit2/src/tree.c +2 -2
  73. data/vendor/libgit2/src/unix/posix.h +1 -0
  74. data/vendor/libgit2/src/util.h +117 -0
  75. data/vendor/libgit2/src/win32/buffer.c +55 -0
  76. data/vendor/libgit2/src/win32/buffer.h +18 -0
  77. data/vendor/libgit2/src/win32/path_w32.c +75 -0
  78. data/vendor/libgit2/src/win32/path_w32.h +3 -0
  79. data/vendor/libgit2/src/win32/posix.h +2 -2
  80. data/vendor/libgit2/src/win32/posix_w32.c +2 -118
  81. data/vendor/libgit2/src/win32/pthread.c +2 -0
  82. data/vendor/libgit2/src/win32/utf-conv.c +0 -4
  83. data/vendor/libgit2/src/win32/utf-conv.h +4 -0
  84. data/vendor/libgit2/src/win32/w32_util.h +72 -0
  85. metadata +14 -2
@@ -693,7 +693,7 @@ int git_describe_commit(
693
693
  get_name, &data)) < 0)
694
694
  goto cleanup;
695
695
 
696
- if (git_oidmap_size(data.names) == 0) {
696
+ if (git_oidmap_size(data.names) == 0 && !opts->show_commit_oid_as_fallback) {
697
697
  giterr_set(GITERR_DESCRIBE, "Cannot describe - "
698
698
  "No reference found, cannot describe anything.");
699
699
  error = -1;
@@ -621,7 +621,7 @@ int git_diff__oid_for_entry(
621
621
  git_index *idx;
622
622
 
623
623
  if (!(error = git_repository_index__weakptr(&idx, diff->repo))) {
624
- memcpy(&entry.id, out, sizeof(entry.id));
624
+ git_oid_cpy(&entry.id, out);
625
625
  error = git_index_add(idx, &entry);
626
626
  }
627
627
  }
@@ -806,15 +806,12 @@ static int maybe_modified(
806
806
  * haven't calculated the OID of the new item, then calculate it now
807
807
  */
808
808
  if (modified_uncertain && git_oid_iszero(&nitem->id)) {
809
- if (git_oid_iszero(&noid)) {
810
- const git_oid *update_check =
811
- DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) ?
812
- &oitem->id : NULL;
813
-
814
- if ((error = git_diff__oid_for_entry(
815
- &noid, diff, nitem, update_check)) < 0)
816
- return error;
817
- }
809
+ const git_oid *update_check =
810
+ DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) && omode == nmode ?
811
+ &oitem->id : NULL;
812
+ if ((error = git_diff__oid_for_entry(
813
+ &noid, diff, nitem, update_check)) < 0)
814
+ return error;
818
815
 
819
816
  /* if oid matches, then mark unmodified (except submodules, where
820
817
  * the filesystem content may be modified even if the oid still
@@ -825,6 +822,19 @@ static int maybe_modified(
825
822
  status = GIT_DELTA_UNMODIFIED;
826
823
  }
827
824
 
825
+ /* If we want case changes, then break this into a delete of the old
826
+ * and an add of the new so that consumers can act accordingly (eg,
827
+ * checkout will update the case on disk.)
828
+ */
829
+ if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE) &&
830
+ DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_CASECHANGE) &&
831
+ strcmp(oitem->path, nitem->path) != 0) {
832
+
833
+ if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem)))
834
+ error = diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem);
835
+ return error;
836
+ }
837
+
828
838
  return diff_delta__from_two(
829
839
  diff, status, oitem, omode, nitem, nmode,
830
840
  git_oid_iszero(&noid) ? NULL : &noid, matched_pathspec);
@@ -116,7 +116,7 @@ static int diff_driver_add_patterns(
116
116
  if (error < 0)
117
117
  break;
118
118
 
119
- if ((error = regcomp(&pat->re, buf.ptr, regex_flags)) < 0) {
119
+ if ((error = regcomp(&pat->re, buf.ptr, regex_flags)) != 0) {
120
120
  /* if regex fails to compile, warn? fail? */
121
121
  error = giterr_set_regex(&pat->re, error);
122
122
  regfree(&pat->re);
@@ -84,11 +84,14 @@ static git_diff_delta *diff_delta__merge_like_cgit(
84
84
  * index (i.e. not in HEAD nor workdir) is given as empty.
85
85
  */
86
86
  if (dup->status == GIT_DELTA_DELETED) {
87
- if (a->status == GIT_DELTA_ADDED)
87
+ if (a->status == GIT_DELTA_ADDED) {
88
88
  dup->status = GIT_DELTA_UNMODIFIED;
89
+ dup->nfiles = 2;
90
+ }
89
91
  /* else don't overwrite DELETE status */
90
92
  } else {
91
93
  dup->status = a->status;
94
+ dup->nfiles = a->nfiles;
92
95
  }
93
96
 
94
97
  git_oid_cpy(&dup->old_file.id, &a->old_file.id);
@@ -118,10 +121,13 @@ static git_diff_delta *diff_delta__merge_like_cgit_reversed(
118
121
  return dup;
119
122
 
120
123
  if (dup->status == GIT_DELTA_DELETED) {
121
- if (b->status == GIT_DELTA_ADDED)
124
+ if (b->status == GIT_DELTA_ADDED) {
122
125
  dup->status = GIT_DELTA_UNMODIFIED;
126
+ dup->nfiles = 2;
127
+ }
123
128
  } else {
124
129
  dup->status = b->status;
130
+ dup->nfiles = b->nfiles;
125
131
  }
126
132
 
127
133
  git_oid_cpy(&dup->old_file.id, &b->old_file.id);
@@ -671,7 +671,7 @@ int git_filter_list_apply_to_data(
671
671
  buf_stream_init(&writer, tgt);
672
672
 
673
673
  if ((error = git_filter_list_stream_data(filters, src,
674
- (git_writestream *)&writer)) < 0)
674
+ &writer.parent)) < 0)
675
675
  return error;
676
676
 
677
677
  assert(writer.complete);
@@ -690,7 +690,7 @@ int git_filter_list_apply_to_file(
690
690
  buf_stream_init(&writer, out);
691
691
 
692
692
  if ((error = git_filter_list_stream_file(
693
- filters, repo, path, (git_writestream *)&writer)) < 0)
693
+ filters, repo, path, &writer.parent)) < 0)
694
694
  return error;
695
695
 
696
696
  assert(writer.complete);
@@ -721,7 +721,7 @@ int git_filter_list_apply_to_blob(
721
721
  buf_stream_init(&writer, out);
722
722
 
723
723
  if ((error = git_filter_list_stream_blob(
724
- filters, blob, (git_writestream *)&writer)) < 0)
724
+ filters, blob, &writer.parent)) < 0)
725
725
  return error;
726
726
 
727
727
  assert(writer.complete);
@@ -809,6 +809,9 @@ static int proxy_stream_init(
809
809
  proxy_stream->target = target;
810
810
  proxy_stream->output = temp_buf ? temp_buf : &proxy_stream->temp_buf;
811
811
 
812
+ if (temp_buf)
813
+ git_buf_clear(temp_buf);
814
+
812
815
  *out = (git_writestream *)proxy_stream;
813
816
  return 0;
814
817
  }
@@ -17,7 +17,7 @@ git_mutex git__mwindow_mutex;
17
17
 
18
18
  #define MAX_SHUTDOWN_CB 8
19
19
 
20
- #ifdef GIT_SSL
20
+ #ifdef GIT_OPENSSL
21
21
  # include <openssl/ssl.h>
22
22
  SSL_CTX *git__ssl_ctx;
23
23
  # ifdef GIT_THREADS
@@ -57,7 +57,7 @@ static void git__shutdown(void)
57
57
  }
58
58
  }
59
59
 
60
- #if defined(GIT_THREADS) && defined(GIT_SSL)
60
+ #if defined(GIT_THREADS) && defined(GIT_OPENSSL)
61
61
  void openssl_locking_function(int mode, int n, const char *file, int line)
62
62
  {
63
63
  int lock;
@@ -89,7 +89,7 @@ static void shutdown_ssl_locking(void)
89
89
 
90
90
  static void init_ssl(void)
91
91
  {
92
- #ifdef GIT_SSL
92
+ #ifdef GIT_OPENSSL
93
93
  long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
94
94
 
95
95
  /* Older OpenSSL and MacOS OpenSSL doesn't have this */
@@ -118,7 +118,7 @@ static void init_ssl(void)
118
118
 
119
119
  int git_openssl_set_locking(void)
120
120
  {
121
- #ifdef GIT_SSL
121
+ #ifdef GIT_OPENSSL
122
122
  # ifdef GIT_THREADS
123
123
  int num_locks, i;
124
124
 
@@ -223,13 +223,10 @@ int git_libgit2_init(void)
223
223
 
224
224
  static void synchronized_threads_shutdown(void)
225
225
  {
226
- void *ptr;
227
-
228
226
  /* Shut down any subsystems that have global state */
229
227
  git__shutdown();
230
228
 
231
- ptr = TlsGetValue(_tls_index);
232
- git__global_state_cleanup(ptr);
229
+ git__free_tls_data();
233
230
 
234
231
  TlsFree(_tls_index);
235
232
  git_mutex_free(&git__mwindow_mutex);
@@ -270,15 +267,20 @@ git_global_st *git__global_state(void)
270
267
  return ptr;
271
268
  }
272
269
 
273
- BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
270
+ /**
271
+ * Free the TLS data associated with this thread.
272
+ * This should only be used by the thread as it
273
+ * is exiting.
274
+ */
275
+ void git__free_tls_data(void)
274
276
  {
275
- if (reason == DLL_THREAD_DETACH) {
276
- void *ptr = TlsGetValue(_tls_index);
277
- git__global_state_cleanup(ptr);
278
- git__free(ptr);
279
- }
277
+ void *ptr = TlsGetValue(_tls_index);
278
+ if (!ptr)
279
+ return;
280
280
 
281
- return TRUE;
281
+ git__global_state_cleanup(ptr);
282
+ git__free(ptr);
283
+ TlsSetValue(_tls_index, NULL);
282
284
  }
283
285
 
284
286
  #elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
@@ -17,7 +17,7 @@ typedef struct {
17
17
  char oid_fmt[GIT_OID_HEXSZ+1];
18
18
  } git_global_st;
19
19
 
20
- #ifdef GIT_SSL
20
+ #ifdef GIT_OPENSSL
21
21
  # include <openssl/ssl.h>
22
22
  extern SSL_CTX *git__ssl_ctx;
23
23
  #endif
@@ -32,4 +32,6 @@ typedef void (*git_global_shutdown_fn)(void);
32
32
 
33
33
  extern void git__on_shutdown(git_global_shutdown_fn callback);
34
34
 
35
+ extern void git__free_tls_data(void);
36
+
35
37
  #endif
@@ -10,6 +10,41 @@
10
10
 
11
11
  #define GIT_IGNORE_DEFAULT_RULES ".\n..\n.git\n"
12
12
 
13
+ /**
14
+ * A negative ignore pattern can match a positive one without
15
+ * wildcards if its pattern equals the tail of the positive
16
+ * pattern. Thus
17
+ *
18
+ * foo/bar
19
+ * !bar
20
+ *
21
+ * would result in foo/bar being unignored again.
22
+ */
23
+ static int does_negate_pattern(git_attr_fnmatch *rule, git_attr_fnmatch *neg)
24
+ {
25
+ char *p;
26
+
27
+ if ((rule->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0
28
+ && (neg->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0) {
29
+ /*
30
+ * no chance of matching if rule is shorter than
31
+ * the negated one
32
+ */
33
+ if (rule->length < neg->length)
34
+ return false;
35
+
36
+ /*
37
+ * shift pattern so its tail aligns with the
38
+ * negated pattern
39
+ */
40
+ p = rule->pattern + rule->length - neg->length;
41
+ if (strcmp(p, neg->pattern) == 0)
42
+ return true;
43
+ }
44
+
45
+ return false;
46
+ }
47
+
13
48
  /**
14
49
  * A negative ignore can only unignore a file which is given explicitly before, thus
15
50
  *
@@ -31,6 +66,8 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
31
66
  char *path;
32
67
  git_buf buf = GIT_BUF_INIT;
33
68
 
69
+ *out = 0;
70
+
34
71
  /* path of the file relative to the workdir, so we match the rules in subdirs */
35
72
  if (match->containing_dir) {
36
73
  git_buf_puts(&buf, match->containing_dir);
@@ -41,9 +78,14 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
41
78
  path = git_buf_detach(&buf);
42
79
 
43
80
  git_vector_foreach(rules, i, rule) {
44
- /* no chance of matching w/o a wilcard */
45
- if (!(rule->flags & GIT_ATTR_FNMATCH_HASWILD))
46
- continue;
81
+ if (!(rule->flags & GIT_ATTR_FNMATCH_HASWILD)) {
82
+ if (does_negate_pattern(rule, match)) {
83
+ *out = 1;
84
+ goto out;
85
+ }
86
+ else
87
+ continue;
88
+ }
47
89
 
48
90
  /*
49
91
  * If we're dealing with a directory (which we know via the
@@ -62,7 +104,6 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
62
104
  if (error < 0)
63
105
  goto out;
64
106
 
65
-
66
107
  if ((error = p_fnmatch(git_buf_cstr(&buf), path, FNM_PATHNAME)) < 0) {
67
108
  giterr_set(GITERR_INVALID, "error matching pattern");
68
109
  goto out;
@@ -76,7 +117,6 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
76
117
  }
77
118
  }
78
119
 
79
- *out = 0;
80
120
  error = 0;
81
121
 
82
122
  out:
@@ -348,7 +388,7 @@ static bool ignore_lookup_in_rules(
348
388
  }
349
389
 
350
390
  int git_ignore__lookup(
351
- int *out, git_ignores *ignores, const char *pathname)
391
+ int *out, git_ignores *ignores, const char *pathname, git_dir_flag dir_flag)
352
392
  {
353
393
  unsigned int i;
354
394
  git_attr_file *file;
@@ -357,7 +397,7 @@ int git_ignore__lookup(
357
397
  *out = GIT_IGNORE_NOTFOUND;
358
398
 
359
399
  if (git_attr_path__init(
360
- &path, pathname, git_repository_workdir(ignores->repo)) < 0)
400
+ &path, pathname, git_repository_workdir(ignores->repo), dir_flag) < 0)
361
401
  return -1;
362
402
 
363
403
  /* first process builtins - success means path was found */
@@ -430,7 +470,7 @@ int git_ignore_path_is_ignored(
430
470
  memset(&path, 0, sizeof(path));
431
471
  memset(&ignores, 0, sizeof(ignores));
432
472
 
433
- if ((error = git_attr_path__init(&path, pathname, workdir)) < 0 ||
473
+ if ((error = git_attr_path__init(&path, pathname, workdir, GIT_DIR_FLAG_UNKNOWN)) < 0 ||
434
474
  (error = git_ignore__for_path(repo, path.path, &ignores)) < 0)
435
475
  goto cleanup;
436
476
 
@@ -49,7 +49,7 @@ enum {
49
49
  GIT_IGNORE_TRUE = 1,
50
50
  };
51
51
 
52
- extern int git_ignore__lookup(int *out, git_ignores *ign, const char *path);
52
+ extern int git_ignore__lookup(int *out, git_ignores *ign, const char *path, git_dir_flag dir_flag);
53
53
 
54
54
  /* command line Git sometimes generates an error message if given a
55
55
  * pathspec that contains an exact match to an ignored file (provided
@@ -987,9 +987,10 @@ static int index_no_dups(void **old, void *new)
987
987
  * it, then it will return an error **and also free the entry**. When
988
988
  * it replaces an existing entry, it will update the entry_ptr with the
989
989
  * actual entry in the index (and free the passed in one).
990
+ * trust_mode is whether we trust the mode in entry_ptr.
990
991
  */
991
992
  static int index_insert(
992
- git_index *index, git_index_entry **entry_ptr, int replace)
993
+ git_index *index, git_index_entry **entry_ptr, int replace, bool trust_mode)
993
994
  {
994
995
  int error = 0;
995
996
  size_t path_length, position;
@@ -1021,7 +1022,10 @@ static int index_insert(
1021
1022
  &position, index, entry->path, 0, GIT_IDXENTRY_STAGE(entry), false)) {
1022
1023
  existing = index->entries.contents[position];
1023
1024
  /* update filemode to existing values if stat is not trusted */
1024
- entry->mode = index_merge_mode(index, existing, entry->mode);
1025
+ if (trust_mode)
1026
+ entry->mode = git_index__create_mode(entry->mode);
1027
+ else
1028
+ entry->mode = index_merge_mode(index, existing, entry->mode);
1025
1029
  }
1026
1030
 
1027
1031
  /* look for tree / blob name collisions, removing conflicts if requested */
@@ -1091,7 +1095,7 @@ static bool valid_filemode(const int filemode)
1091
1095
  }
1092
1096
 
1093
1097
  int git_index_add_frombuffer(
1094
- git_index *index, git_index_entry *source_entry,
1098
+ git_index *index, const git_index_entry *source_entry,
1095
1099
  const void *buffer, size_t len)
1096
1100
  {
1097
1101
  git_index_entry *entry = NULL;
@@ -1122,7 +1126,7 @@ int git_index_add_frombuffer(
1122
1126
  git_oid_cpy(&entry->id, &id);
1123
1127
  entry->file_size = len;
1124
1128
 
1125
- if ((error = index_insert(index, &entry, 1)) < 0)
1129
+ if ((error = index_insert(index, &entry, 1, true)) < 0)
1126
1130
  return error;
1127
1131
 
1128
1132
  /* Adding implies conflict was resolved, move conflict entries to REUC */
@@ -1142,7 +1146,7 @@ int git_index_add_bypath(git_index *index, const char *path)
1142
1146
  assert(index && path);
1143
1147
 
1144
1148
  if ((ret = index_entry_init(&entry, index, path)) < 0 ||
1145
- (ret = index_insert(index, &entry, 1)) < 0)
1149
+ (ret = index_insert(index, &entry, 1, false)) < 0)
1146
1150
  return ret;
1147
1151
 
1148
1152
  /* Adding implies conflict was resolved, move conflict entries to REUC */
@@ -1182,7 +1186,7 @@ int git_index_add(git_index *index, const git_index_entry *source_entry)
1182
1186
  }
1183
1187
 
1184
1188
  if ((ret = index_entry_dup(&entry, INDEX_OWNER(index), source_entry)) < 0 ||
1185
- (ret = index_insert(index, &entry, 1)) < 0)
1189
+ (ret = index_insert(index, &entry, 1, true)) < 0)
1186
1190
  return ret;
1187
1191
 
1188
1192
  git_tree_cache_invalidate_path(index->tree, entry->path);
@@ -1313,7 +1317,7 @@ int git_index_conflict_add(git_index *index,
1313
1317
  /* Make sure stage is correct */
1314
1318
  GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
1315
1319
 
1316
- if ((ret = index_insert(index, &entries[i], 1)) < 0)
1320
+ if ((ret = index_insert(index, &entries[i], 1, true)) < 0)
1317
1321
  goto on_error;
1318
1322
 
1319
1323
  entries[i] = NULL; /* don't free if later entry fails */
@@ -2537,7 +2541,7 @@ int git_index_add_all(
2537
2541
  entry->id = blobid;
2538
2542
 
2539
2543
  /* add working directory item to index */
2540
- if ((error = index_insert(index, &entry, 1)) < 0)
2544
+ if ((error = index_insert(index, &entry, 1, false)) < 0)
2541
2545
  break;
2542
2546
 
2543
2547
  git_tree_cache_invalidate_path(index->tree, wd->path);
@@ -920,12 +920,31 @@ struct fs_iterator {
920
920
 
921
921
  #define FS_MAX_DEPTH 100
922
922
 
923
+ typedef struct {
924
+ struct stat st;
925
+ size_t path_len;
926
+ char path[GIT_FLEX_ARRAY];
927
+ } fs_iterator_path_with_stat;
928
+
929
+ static int fs_iterator_path_with_stat_cmp(const void *a, const void *b)
930
+ {
931
+ const fs_iterator_path_with_stat *psa = a, *psb = b;
932
+ return strcmp(psa->path, psb->path);
933
+ }
934
+
935
+ static int fs_iterator_path_with_stat_cmp_icase(const void *a, const void *b)
936
+ {
937
+ const fs_iterator_path_with_stat *psa = a, *psb = b;
938
+ return strcasecmp(psa->path, psb->path);
939
+ }
940
+
923
941
  static fs_iterator_frame *fs_iterator__alloc_frame(fs_iterator *fi)
924
942
  {
925
943
  fs_iterator_frame *ff = git__calloc(1, sizeof(fs_iterator_frame));
926
944
  git_vector_cmp entry_compare = CASESELECT(
927
945
  iterator__ignore_case(fi),
928
- git_path_with_stat_cmp_icase, git_path_with_stat_cmp);
946
+ fs_iterator_path_with_stat_cmp_icase,
947
+ fs_iterator_path_with_stat_cmp);
929
948
 
930
949
  if (ff && git_vector_init(&ff->entries, 0, entry_compare) < 0) {
931
950
  git__free(ff);
@@ -967,7 +986,7 @@ static int fs_iterator__advance_over(
967
986
  static int fs_iterator__entry_cmp(const void *i, const void *item)
968
987
  {
969
988
  const fs_iterator *fi = (const fs_iterator *)i;
970
- const git_path_with_stat *ps = item;
989
+ const fs_iterator_path_with_stat *ps = item;
971
990
  return fi->base.prefixcomp(fi->base.start, ps->path);
972
991
  }
973
992
 
@@ -984,6 +1003,96 @@ static void fs_iterator__seek_frame_start(
984
1003
  ff->index = 0;
985
1004
  }
986
1005
 
1006
+ static int dirload_with_stat(
1007
+ const char *dirpath,
1008
+ size_t prefix_len,
1009
+ unsigned int flags,
1010
+ const char *start_stat,
1011
+ const char *end_stat,
1012
+ git_vector *contents)
1013
+ {
1014
+ git_path_diriter diriter = GIT_PATH_DIRITER_INIT;
1015
+ const char *path;
1016
+ int (*strncomp)(const char *a, const char *b, size_t sz);
1017
+ size_t start_len = start_stat ? strlen(start_stat) : 0;
1018
+ size_t end_len = end_stat ? strlen(end_stat) : 0;
1019
+ fs_iterator_path_with_stat *ps;
1020
+ size_t path_len, cmp_len, ps_size;
1021
+ int error;
1022
+
1023
+ strncomp = (flags & GIT_PATH_DIR_IGNORE_CASE) != 0 ?
1024
+ git__strncasecmp : git__strncmp;
1025
+
1026
+ if ((error = git_path_diriter_init(&diriter, dirpath, flags)) < 0)
1027
+ goto done;
1028
+
1029
+ while ((error = git_path_diriter_next(&diriter)) == 0) {
1030
+ if ((error = git_path_diriter_fullpath(&path, &path_len, &diriter)) < 0)
1031
+ goto done;
1032
+
1033
+ assert(path_len > prefix_len);
1034
+
1035
+ /* remove the prefix if requested */
1036
+ path += prefix_len;
1037
+ path_len -= prefix_len;
1038
+
1039
+ /* skip if before start_stat or after end_stat */
1040
+ cmp_len = min(start_len, path_len);
1041
+ if (cmp_len && strncomp(path, start_stat, cmp_len) < 0)
1042
+ continue;
1043
+ cmp_len = min(end_len, path_len);
1044
+ if (cmp_len && strncomp(path, end_stat, cmp_len) > 0)
1045
+ continue;
1046
+
1047
+ /* Make sure to append two bytes, one for the path's null
1048
+ * termination, one for a possible trailing '/' for folders.
1049
+ */
1050
+ GITERR_CHECK_ALLOC_ADD(&ps_size, sizeof(fs_iterator_path_with_stat), path_len);
1051
+ GITERR_CHECK_ALLOC_ADD(&ps_size, ps_size, 2);
1052
+
1053
+ ps = git__calloc(1, ps_size);
1054
+ ps->path_len = path_len;
1055
+
1056
+ memcpy(ps->path, path, path_len);
1057
+
1058
+ if ((error = git_path_diriter_stat(&ps->st, &diriter)) < 0) {
1059
+ if (error == GIT_ENOTFOUND) {
1060
+ /* file was removed between readdir and lstat */
1061
+ git__free(ps);
1062
+ continue;
1063
+ }
1064
+
1065
+ /* Treat the file as unreadable if we get any other error */
1066
+ memset(&ps->st, 0, sizeof(ps->st));
1067
+ ps->st.st_mode = GIT_FILEMODE_UNREADABLE;
1068
+
1069
+ giterr_clear();
1070
+ error = 0;
1071
+ } else if (S_ISDIR(ps->st.st_mode)) {
1072
+ /* Suffix directory paths with a '/' */
1073
+ ps->path[ps->path_len++] = '/';
1074
+ ps->path[ps->path_len] = '\0';
1075
+ } else if(!S_ISREG(ps->st.st_mode) && !S_ISLNK(ps->st.st_mode)) {
1076
+ /* Ignore wacky things in the filesystem */
1077
+ git__free(ps);
1078
+ continue;
1079
+ }
1080
+
1081
+ git_vector_insert(contents, ps);
1082
+ }
1083
+
1084
+ if (error == GIT_ITEROVER)
1085
+ error = 0;
1086
+
1087
+ /* sort now that directory suffix is added */
1088
+ git_vector_sort(contents);
1089
+
1090
+ done:
1091
+ git_path_diriter_free(&diriter);
1092
+ return error;
1093
+ }
1094
+
1095
+
987
1096
  static int fs_iterator__expand_dir(fs_iterator *fi)
988
1097
  {
989
1098
  int error;
@@ -998,7 +1107,7 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
998
1107
  ff = fs_iterator__alloc_frame(fi);
999
1108
  GITERR_CHECK_ALLOC(ff);
1000
1109
 
1001
- error = git_path_dirload_with_stat(
1110
+ error = dirload_with_stat(
1002
1111
  fi->path.ptr, fi->root_len, fi->dirload_flags,
1003
1112
  fi->base.start, fi->base.end, &ff->entries);
1004
1113
 
@@ -1086,7 +1195,7 @@ static int fs_iterator__advance_over(
1086
1195
  int error = 0;
1087
1196
  fs_iterator *fi = (fs_iterator *)self;
1088
1197
  fs_iterator_frame *ff;
1089
- git_path_with_stat *next;
1198
+ fs_iterator_path_with_stat *next;
1090
1199
 
1091
1200
  if (entry != NULL)
1092
1201
  *entry = NULL;
@@ -1176,7 +1285,7 @@ static void fs_iterator__free(git_iterator *self)
1176
1285
 
1177
1286
  static int fs_iterator__update_entry(fs_iterator *fi)
1178
1287
  {
1179
- git_path_with_stat *ps;
1288
+ fs_iterator_path_with_stat *ps;
1180
1289
 
1181
1290
  memset(&fi->entry, 0, sizeof(fi->entry));
1182
1291
 
@@ -1307,7 +1416,7 @@ GIT_INLINE(bool) workdir_path_is_dotgit(const git_buf *path)
1307
1416
  * We consider it a submodule if the path is listed as a submodule in
1308
1417
  * either the tree or the index.
1309
1418
  */
1310
- static int is_submodule(workdir_iterator *wi, git_path_with_stat *ie)
1419
+ static int is_submodule(workdir_iterator *wi, fs_iterator_path_with_stat *ie)
1311
1420
  {
1312
1421
  int error, is_submodule = 0;
1313
1422
 
@@ -1344,17 +1453,29 @@ static int is_submodule(workdir_iterator *wi, git_path_with_stat *ie)
1344
1453
  return is_submodule;
1345
1454
  }
1346
1455
 
1456
+ GIT_INLINE(git_dir_flag) git_entry__dir_flag(git_index_entry *entry) {
1457
+ #if defined(GIT_WIN32) && !defined(__MINGW32__)
1458
+ return (entry && entry->mode)
1459
+ ? S_ISDIR(entry->mode) ? GIT_DIR_FLAG_TRUE : GIT_DIR_FLAG_FALSE
1460
+ : GIT_DIR_FLAG_UNKNOWN;
1461
+ #else
1462
+ GIT_UNUSED(entry);
1463
+ return GIT_DIR_FLAG_UNKNOWN;
1464
+ #endif
1465
+ }
1466
+
1347
1467
  static int workdir_iterator__enter_dir(fs_iterator *fi)
1348
1468
  {
1349
1469
  workdir_iterator *wi = (workdir_iterator *)fi;
1350
1470
  fs_iterator_frame *ff = fi->stack;
1351
1471
  size_t pos;
1352
- git_path_with_stat *entry;
1472
+ fs_iterator_path_with_stat *entry;
1353
1473
  bool found_submodules = false;
1354
1474
 
1475
+ git_dir_flag dir_flag = git_entry__dir_flag(&fi->entry);
1476
+
1355
1477
  /* check if this directory is ignored */
1356
- if (git_ignore__lookup(
1357
- &ff->is_ignored, &wi->ignores, fi->path.ptr + fi->root_len) < 0) {
1478
+ if (git_ignore__lookup(&ff->is_ignored, &wi->ignores, fi->path.ptr + fi->root_len, dir_flag) < 0) {
1358
1479
  giterr_clear();
1359
1480
  ff->is_ignored = GIT_IGNORE_NOTFOUND;
1360
1481
  }
@@ -1483,7 +1604,6 @@ int git_iterator_for_workdir_ext(
1483
1604
  return fs_iterator__initialize(out, &wi->fi, repo_workdir);
1484
1605
  }
1485
1606
 
1486
-
1487
1607
  void git_iterator_free(git_iterator *iter)
1488
1608
  {
1489
1609
  if (iter == NULL)
@@ -1574,8 +1694,9 @@ int git_iterator_current_parent_tree(
1574
1694
 
1575
1695
  static void workdir_iterator_update_is_ignored(workdir_iterator *wi)
1576
1696
  {
1577
- if (git_ignore__lookup(
1578
- &wi->is_ignored, &wi->ignores, wi->fi.entry.path) < 0) {
1697
+ git_dir_flag dir_flag = git_entry__dir_flag(&wi->fi.entry);
1698
+
1699
+ if (git_ignore__lookup(&wi->is_ignored, &wi->ignores, wi->fi.entry.path, dir_flag) < 0) {
1579
1700
  giterr_clear();
1580
1701
  wi->is_ignored = GIT_IGNORE_NOTFOUND;
1581
1702
  }
@@ -11,12 +11,12 @@
11
11
  #include "common.h"
12
12
  #include "stream.h"
13
13
 
14
- #ifdef GIT_SSL
14
+ #ifdef GIT_OPENSSL
15
15
  # include <openssl/ssl.h>
16
16
  #endif
17
17
 
18
18
  typedef struct gitno_ssl {
19
- #ifdef GIT_SSL
19
+ #ifdef GIT_OPENSSL
20
20
  SSL *ssl;
21
21
  #else
22
22
  size_t dummy;