rugged 0.17.0.b6 → 0.17.0.b7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/README.md +3 -3
  2. data/Rakefile +3 -1
  3. data/ext/rugged/rugged.c +30 -0
  4. data/ext/rugged/rugged.h +9 -0
  5. data/ext/rugged/rugged_branch.c +306 -0
  6. data/ext/rugged/rugged_config.c +16 -13
  7. data/ext/rugged/rugged_index.c +25 -0
  8. data/ext/rugged/rugged_object.c +6 -2
  9. data/ext/rugged/rugged_reference.c +11 -18
  10. data/ext/rugged/rugged_revwalk.c +1 -1
  11. data/lib/rugged.rb +1 -0
  12. data/lib/rugged/branch.rb +28 -0
  13. data/lib/rugged/commit.rb +5 -5
  14. data/lib/rugged/repository.rb +32 -7
  15. data/lib/rugged/tag.rb +5 -1
  16. data/lib/rugged/version.rb +1 -1
  17. data/test/branch_test.rb +227 -0
  18. data/test/config_test.rb +1 -1
  19. data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  20. data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
  21. data/test/index_test.rb +31 -0
  22. data/test/index_test.rb~ +218 -0
  23. data/test/lib_test.rb +22 -0
  24. data/test/reference_test.rb +5 -3
  25. data/vendor/libgit2/Makefile.embed +1 -1
  26. data/vendor/libgit2/include/git2.h +1 -0
  27. data/vendor/libgit2/include/git2/branch.h +17 -13
  28. data/vendor/libgit2/include/git2/checkout.h +83 -22
  29. data/vendor/libgit2/include/git2/clone.h +6 -3
  30. data/vendor/libgit2/include/git2/common.h +1 -8
  31. data/vendor/libgit2/include/git2/config.h +185 -26
  32. data/vendor/libgit2/include/git2/diff.h +229 -17
  33. data/vendor/libgit2/include/git2/errors.h +39 -1
  34. data/vendor/libgit2/include/git2/ignore.h +6 -3
  35. data/vendor/libgit2/include/git2/indexer.h +1 -0
  36. data/vendor/libgit2/include/git2/merge.h +1 -1
  37. data/vendor/libgit2/include/git2/object.h +7 -4
  38. data/vendor/libgit2/include/git2/odb.h +4 -2
  39. data/vendor/libgit2/include/git2/odb_backend.h +6 -0
  40. data/vendor/libgit2/include/git2/oid.h +2 -0
  41. data/vendor/libgit2/include/git2/pack.h +89 -0
  42. data/vendor/libgit2/include/git2/refs.h +88 -0
  43. data/vendor/libgit2/include/git2/refspec.h +0 -8
  44. data/vendor/libgit2/include/git2/remote.h +34 -1
  45. data/vendor/libgit2/include/git2/repository.h +238 -6
  46. data/vendor/libgit2/include/git2/reset.h +4 -1
  47. data/vendor/libgit2/include/git2/revwalk.h +1 -1
  48. data/vendor/libgit2/include/git2/status.h +19 -14
  49. data/vendor/libgit2/include/git2/strarray.h +54 -0
  50. data/vendor/libgit2/include/git2/submodule.h +451 -45
  51. data/vendor/libgit2/include/git2/tag.h +16 -0
  52. data/vendor/libgit2/include/git2/tree.h +2 -2
  53. data/vendor/libgit2/include/git2/types.h +4 -0
  54. data/vendor/libgit2/src/amiga/map.c +4 -7
  55. data/vendor/libgit2/src/attr.c +21 -13
  56. data/vendor/libgit2/src/attr.h +3 -1
  57. data/vendor/libgit2/src/attr_file.c +14 -14
  58. data/vendor/libgit2/src/attr_file.h +6 -5
  59. data/vendor/libgit2/src/blob.c +22 -12
  60. data/vendor/libgit2/src/branch.c +62 -66
  61. data/vendor/libgit2/src/buffer.c +63 -14
  62. data/vendor/libgit2/src/buffer.h +4 -0
  63. data/vendor/libgit2/src/cache.c +5 -4
  64. data/vendor/libgit2/src/checkout.c +381 -159
  65. data/vendor/libgit2/src/clone.c +221 -94
  66. data/vendor/libgit2/src/common.h +13 -3
  67. data/vendor/libgit2/src/compress.c +53 -0
  68. data/vendor/libgit2/src/compress.h +16 -0
  69. data/vendor/libgit2/src/config.c +380 -175
  70. data/vendor/libgit2/src/config.h +2 -5
  71. data/vendor/libgit2/src/config_file.c +63 -46
  72. data/vendor/libgit2/src/config_file.h +16 -4
  73. data/vendor/libgit2/src/crlf.c +4 -3
  74. data/vendor/libgit2/src/delta.c +491 -0
  75. data/vendor/libgit2/src/delta.h +112 -0
  76. data/vendor/libgit2/src/diff.c +310 -67
  77. data/vendor/libgit2/src/diff.h +10 -1
  78. data/vendor/libgit2/src/diff_output.c +1030 -337
  79. data/vendor/libgit2/src/diff_output.h +86 -0
  80. data/vendor/libgit2/src/errors.c +10 -1
  81. data/vendor/libgit2/src/fetch.c +108 -24
  82. data/vendor/libgit2/src/filebuf.c +8 -2
  83. data/vendor/libgit2/src/fileops.c +342 -177
  84. data/vendor/libgit2/src/fileops.h +84 -7
  85. data/vendor/libgit2/src/filter.c +0 -35
  86. data/vendor/libgit2/src/filter.h +0 -12
  87. data/vendor/libgit2/src/{compat/fnmatch.c → fnmatch.c} +16 -4
  88. data/vendor/libgit2/src/{compat/fnmatch.h → fnmatch.h} +4 -3
  89. data/vendor/libgit2/src/global.c +4 -0
  90. data/vendor/libgit2/src/ignore.c +122 -23
  91. data/vendor/libgit2/src/ignore.h +1 -0
  92. data/vendor/libgit2/src/index.c +56 -10
  93. data/vendor/libgit2/src/index.h +2 -0
  94. data/vendor/libgit2/src/indexer.c +8 -9
  95. data/vendor/libgit2/src/iterator.c +244 -31
  96. data/vendor/libgit2/src/iterator.h +30 -1
  97. data/vendor/libgit2/src/message.c +1 -1
  98. data/vendor/libgit2/src/netops.c +44 -4
  99. data/vendor/libgit2/src/object.c +80 -69
  100. data/vendor/libgit2/src/object.h +39 -0
  101. data/vendor/libgit2/src/odb.c +79 -15
  102. data/vendor/libgit2/src/odb.h +20 -5
  103. data/vendor/libgit2/src/odb_pack.c +65 -33
  104. data/vendor/libgit2/src/oid.c +0 -3
  105. data/vendor/libgit2/src/pack-objects.c +1315 -0
  106. data/vendor/libgit2/src/pack-objects.h +87 -0
  107. data/vendor/libgit2/src/pack.c +36 -12
  108. data/vendor/libgit2/src/pack.h +1 -0
  109. data/vendor/libgit2/src/path.c +42 -9
  110. data/vendor/libgit2/src/path.h +14 -0
  111. data/vendor/libgit2/src/pkt.c +52 -2
  112. data/vendor/libgit2/src/pkt.h +10 -0
  113. data/vendor/libgit2/src/pool.h +11 -0
  114. data/vendor/libgit2/src/posix.h +8 -0
  115. data/vendor/libgit2/src/protocol.c +24 -2
  116. data/vendor/libgit2/src/protocol.h +4 -0
  117. data/vendor/libgit2/src/reflog.c +1 -1
  118. data/vendor/libgit2/src/refs.c +292 -124
  119. data/vendor/libgit2/src/refs.h +4 -2
  120. data/vendor/libgit2/src/refspec.c +117 -19
  121. data/vendor/libgit2/src/refspec.h +19 -0
  122. data/vendor/libgit2/src/remote.c +152 -48
  123. data/vendor/libgit2/src/remote.h +4 -1
  124. data/vendor/libgit2/src/repo_template.h +58 -0
  125. data/vendor/libgit2/src/repository.c +594 -179
  126. data/vendor/libgit2/src/repository.h +23 -22
  127. data/vendor/libgit2/src/reset.c +71 -29
  128. data/vendor/libgit2/src/revparse.c +26 -17
  129. data/vendor/libgit2/src/revwalk.c +36 -19
  130. data/vendor/libgit2/src/sha1.h +7 -0
  131. data/vendor/libgit2/src/{sha1.c → sha1/sha1.c} +0 -0
  132. data/vendor/libgit2/src/signature.c +12 -10
  133. data/vendor/libgit2/src/status.c +52 -6
  134. data/vendor/libgit2/src/submodule.c +1363 -255
  135. data/vendor/libgit2/src/submodule.h +102 -0
  136. data/vendor/libgit2/src/tag.c +42 -26
  137. data/vendor/libgit2/src/thread-utils.h +7 -7
  138. data/vendor/libgit2/src/transport.h +15 -1
  139. data/vendor/libgit2/src/transports/git.c +1 -1
  140. data/vendor/libgit2/src/transports/http.c +197 -36
  141. data/vendor/libgit2/src/tree.c +3 -3
  142. data/vendor/libgit2/src/unix/map.c +2 -0
  143. data/vendor/libgit2/src/unix/posix.h +1 -8
  144. data/vendor/libgit2/src/util.c +6 -1
  145. data/vendor/libgit2/src/util.h +7 -0
  146. data/vendor/libgit2/src/vector.c +16 -0
  147. data/vendor/libgit2/src/vector.h +1 -0
  148. data/vendor/libgit2/src/win32/dir.c +8 -21
  149. data/vendor/libgit2/src/win32/findfile.c +149 -0
  150. data/vendor/libgit2/src/win32/findfile.h +23 -0
  151. data/vendor/libgit2/src/win32/posix.h +3 -7
  152. data/vendor/libgit2/src/win32/posix_w32.c +44 -102
  153. data/vendor/libgit2/src/win32/pthread.c +68 -0
  154. data/vendor/libgit2/src/win32/pthread.h +7 -0
  155. data/vendor/libgit2/src/win32/utf-conv.c +60 -71
  156. data/vendor/libgit2/src/win32/utf-conv.h +4 -3
  157. metadata +70 -71
  158. data/vendor/libgit2/include/git2/windows.h +0 -59
@@ -19,6 +19,7 @@
19
19
  */
20
20
  extern int git_futils_readbuffer(git_buf *obj, const char *path);
21
21
  extern int git_futils_readbuffer_updated(git_buf *obj, const char *path, time_t *mtime, int *updated);
22
+ extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
22
23
 
23
24
  /**
24
25
  * File utils
@@ -50,11 +51,46 @@ extern int git_futils_creat_locked_withpath(const char *path, const mode_t dirmo
50
51
  /**
51
52
  * Create a path recursively
52
53
  *
53
- * If a base parameter is being passed, it's expected to be valued with a path pointing to an already
54
- * exisiting directory.
54
+ * If a base parameter is being passed, it's expected to be valued with a
55
+ * path pointing to an already existing directory.
55
56
  */
56
57
  extern int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode);
57
58
 
59
+ /**
60
+ * Flags to pass to `git_futils_mkdir`.
61
+ *
62
+ * * GIT_MKDIR_EXCL is "exclusive" - i.e. generate an error if dir exists.
63
+ * * GIT_MKDIR_PATH says to make all components in the path.
64
+ * * GIT_MKDIR_CHMOD says to chmod the final directory entry after creation
65
+ * * GIT_MKDIR_CHMOD_PATH says to chmod each directory component in the path
66
+ * * GIT_MKDIR_SKIP_LAST says to leave off the last element of the path
67
+ *
68
+ * Note that the chmod options will be executed even if the directory already
69
+ * exists, unless GIT_MKDIR_EXCL is given.
70
+ */
71
+ typedef enum {
72
+ GIT_MKDIR_EXCL = 1,
73
+ GIT_MKDIR_PATH = 2,
74
+ GIT_MKDIR_CHMOD = 4,
75
+ GIT_MKDIR_CHMOD_PATH = 8,
76
+ GIT_MKDIR_SKIP_LAST = 16
77
+ } git_futils_mkdir_flags;
78
+
79
+ /**
80
+ * Create a directory or entire path.
81
+ *
82
+ * This makes a directory (and the entire path leading up to it if requested),
83
+ * and optionally chmods the directory immediately after (or each part of the
84
+ * path if requested).
85
+ *
86
+ * @param path The path to create.
87
+ * @param base Root for relative path. These directories will never be made.
88
+ * @param mode The mode to use for created directories.
89
+ * @param flags Combination of the mkdir flags above.
90
+ * @return 0 on success, else error code
91
+ */
92
+ extern int git_futils_mkdir(const char *path, const char *base, mode_t mode, uint32_t flags);
93
+
58
94
  /**
59
95
  * Create all the folders required to contain
60
96
  * the full path of a file
@@ -71,15 +107,17 @@ typedef enum {
71
107
  * Remove path and any files and directories beneath it.
72
108
  *
73
109
  * @param path Path to to top level directory to process.
74
- *
110
+ * @param base Root for relative path.
75
111
  * @param removal_type GIT_DIRREMOVAL_EMPTY_HIERARCHY to remove a hierarchy
76
- * of empty directories (will fail if any file is found), GIT_DIRREMOVAL_FILES_AND_DIRS
77
- * to remove a hierarchy of files and folders, GIT_DIRREMOVAL_ONLY_EMPTY_DIRS to only remove
78
- * empty directories (no failure on file encounter).
112
+ * of empty directories (will fail if any file is found),
113
+ * GIT_DIRREMOVAL_FILES_AND_DIRS to remove a hierarchy of
114
+ * files and folders,
115
+ * GIT_DIRREMOVAL_ONLY_EMPTY_DIRS to only remove empty
116
+ * directories (no failure on file encounter).
79
117
  *
80
118
  * @return 0 on success; -1 on error.
81
119
  */
82
- extern int git_futils_rmdir_r(const char *path, git_directory_removal_type removal_type);
120
+ extern int git_futils_rmdir_r(const char *path, const char *base, git_directory_removal_type removal_type);
83
121
 
84
122
  /**
85
123
  * Create and open a temporary file with a `_git2_` suffix.
@@ -94,6 +132,45 @@ extern int git_futils_mktmp(git_buf *path_out, const char *filename);
94
132
  */
95
133
  extern int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode);
96
134
 
135
+ /**
136
+ * Copy a file
137
+ *
138
+ * The filemode will be used for the newly created file.
139
+ */
140
+ extern int git_futils_cp(
141
+ const char *from,
142
+ const char *to,
143
+ mode_t filemode);
144
+
145
+ /**
146
+ * Flags that can be passed to `git_futils_cp_r`.
147
+ */
148
+ typedef enum {
149
+ GIT_CPDIR_CREATE_EMPTY_DIRS = 1,
150
+ GIT_CPDIR_COPY_SYMLINKS = 2,
151
+ GIT_CPDIR_COPY_DOTFILES = 4,
152
+ GIT_CPDIR_OVERWRITE = 8,
153
+ GIT_CPDIR_CHMOD = 16
154
+ } git_futils_cpdir_flags;
155
+
156
+ /**
157
+ * Copy a directory tree.
158
+ *
159
+ * This copies directories and files from one root to another. You can
160
+ * pass a combinationof GIT_CPDIR flags as defined above.
161
+ *
162
+ * If you pass the CHMOD flag, then the dirmode will be applied to all
163
+ * directories that are created during the copy, overiding the natural
164
+ * permissions. If you do not pass the CHMOD flag, then the dirmode
165
+ * will actually be copied from the source files and the `dirmode` arg
166
+ * will be ignored.
167
+ */
168
+ extern int git_futils_cp_r(
169
+ const char *from,
170
+ const char *to,
171
+ uint32_t flags,
172
+ mode_t dirmode);
173
+
97
174
  /**
98
175
  * Open a file readonly and set error if needed.
99
176
  */
@@ -164,38 +164,3 @@ int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters)
164
164
 
165
165
  return 0;
166
166
  }
167
-
168
- static int unfiltered_blob_contents(git_buf *out, git_repository *repo, const git_oid *blob_id)
169
- {
170
- int retcode = GIT_ERROR;
171
- git_blob *blob;
172
-
173
- if (!(retcode = git_blob_lookup(&blob, repo, blob_id)))
174
- {
175
- retcode = git_blob__getbuf(out, blob);
176
- git_blob_free(blob);
177
- }
178
-
179
- return retcode;
180
- }
181
-
182
- int git_filter_blob_contents(git_buf *out, git_repository *repo, const git_oid *oid, const char *path)
183
- {
184
- int retcode = GIT_ERROR;
185
-
186
- git_buf unfiltered = GIT_BUF_INIT;
187
- if (!unfiltered_blob_contents(&unfiltered, repo, oid)) {
188
- git_vector filters = GIT_VECTOR_INIT;
189
- if (git_filters_load(&filters,
190
- repo, path, GIT_FILTER_TO_WORKTREE) >= 0) {
191
- git_buf_clear(out);
192
- retcode = git_filters_apply(out, &unfiltered, &filters);
193
- }
194
-
195
- git_filters_free(&filters);
196
- }
197
-
198
- git_buf_free(&unfiltered);
199
- return retcode;
200
- }
201
-
@@ -119,16 +119,4 @@ extern void git_text_gather_stats(git_text_stats *stats, const git_buf *text);
119
119
  */
120
120
  extern int git_text_is_binary(git_text_stats *stats);
121
121
 
122
-
123
- /**
124
- * Get the content of a blob after all filters have been run.
125
- *
126
- * @param out buffer to receive the contents
127
- * @param repo repository containing the blob
128
- * @param oid object id for the blob
129
- * @param path path to the blob's output file, relative to the workdir root
130
- * @return 0 on success, an error code otherwise
131
- */
132
- extern int git_filter_blob_contents(git_buf *out, git_repository *repo, const git_oid *oid, const char *path);
133
-
134
122
  #endif
@@ -24,13 +24,16 @@
24
24
 
25
25
  static int rangematch(const char *, char, int, char **);
26
26
 
27
- int
28
- p_fnmatch(const char *pattern, const char *string, int flags)
27
+ static int
28
+ p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs)
29
29
  {
30
30
  const char *stringstart;
31
31
  char *newp;
32
32
  char c, test;
33
33
 
34
+ if (recurs-- == 0)
35
+ return FNM_NORES;
36
+
34
37
  for (stringstart = string;;)
35
38
  switch (c = *pattern++) {
36
39
  case EOS:
@@ -75,8 +78,11 @@ p_fnmatch(const char *pattern, const char *string, int flags)
75
78
 
76
79
  /* General case, use recursion. */
77
80
  while ((test = *string) != EOS) {
78
- if (!p_fnmatch(pattern, string, flags & ~FNM_PERIOD))
79
- return (0);
81
+ int e;
82
+
83
+ e = p_fnmatchx(pattern, string, flags & ~FNM_PERIOD, recurs);
84
+ if (e != FNM_NOMATCH)
85
+ return e;
80
86
  if (test == '/' && (flags & FNM_PATHNAME))
81
87
  break;
82
88
  ++string;
@@ -178,3 +184,9 @@ rangematch(const char *pattern, char test, int flags, char **newp)
178
184
  return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
179
185
  }
180
186
 
187
+ int
188
+ p_fnmatch(const char *pattern, const char *string, int flags)
189
+ {
190
+ return p_fnmatchx(pattern, string, flags, 64);
191
+ }
192
+
@@ -11,12 +11,13 @@
11
11
 
12
12
  #define FNM_NOMATCH 1 /* Match failed. */
13
13
  #define FNM_NOSYS 2 /* Function not supported (unused). */
14
+ #define FNM_NORES 3 /* Out of resources */
14
15
 
15
- #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
16
- #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
16
+ #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
17
+ #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
17
18
  #define FNM_PERIOD 0x04 /* Period must be matched by period. */
18
19
  #define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
19
- #define FNM_CASEFOLD 0x10 /* Case insensitive search. */
20
+ #define FNM_CASEFOLD 0x10 /* Case insensitive search. */
20
21
 
21
22
  #define FNM_IGNORECASE FNM_CASEFOLD
22
23
  #define FNM_FILE_NAME FNM_PATHNAME
@@ -64,6 +64,8 @@ git_global_st *git__global_state(void)
64
64
  {
65
65
  void *ptr;
66
66
 
67
+ assert(_tls_init);
68
+
67
69
  if ((ptr = TlsGetValue(_tls_index)) != NULL)
68
70
  return ptr;
69
71
 
@@ -105,6 +107,8 @@ git_global_st *git__global_state(void)
105
107
  {
106
108
  void *ptr;
107
109
 
110
+ assert(_tls_init);
111
+
108
112
  if ((ptr = pthread_getspecific(_tls_key)) != NULL)
109
113
  return ptr;
110
114
 
@@ -1,20 +1,37 @@
1
1
  #include "git2/ignore.h"
2
2
  #include "ignore.h"
3
3
  #include "path.h"
4
+ #include "config.h"
4
5
 
5
6
  #define GIT_IGNORE_INTERNAL "[internal]exclude"
6
7
  #define GIT_IGNORE_FILE_INREPO "info/exclude"
7
8
  #define GIT_IGNORE_FILE ".gitignore"
8
9
 
9
10
  static int parse_ignore_file(
10
- git_repository *repo, const char *buffer, git_attr_file *ignores)
11
+ git_repository *repo, void *parsedata, const char *buffer, git_attr_file *ignores)
11
12
  {
12
13
  int error = 0;
13
14
  git_attr_fnmatch *match = NULL;
14
15
  const char *scan = NULL;
15
16
  char *context = NULL;
16
-
17
- GIT_UNUSED(repo);
17
+ bool ignore_case = false;
18
+ git_config *cfg = NULL;
19
+ int val;
20
+
21
+ /* Prefer to have the caller pass in a git_ignores as the parsedata object.
22
+ * If they did not, then we can (much more slowly) find the value of
23
+ * ignore_case by using the repository object. */
24
+ if (parsedata != NULL) {
25
+ ignore_case = ((git_ignores *)parsedata)->ignore_case;
26
+ } else {
27
+ if ((error = git_repository_config(&cfg, repo)) < 0)
28
+ return error;
29
+
30
+ if (git_config_get_bool(&val, cfg, "core.ignorecase") == 0)
31
+ ignore_case = (val != 0);
32
+
33
+ git_config_free(cfg);
34
+ }
18
35
 
19
36
  if (ignores->key && git__suffixcmp(ignores->key, "/" GIT_IGNORE_FILE) == 0) {
20
37
  context = ignores->key + 2;
@@ -34,7 +51,11 @@ static int parse_ignore_file(
34
51
  if (!(error = git_attr_fnmatch__parse(
35
52
  match, ignores->pool, context, &scan)))
36
53
  {
37
- match->flags = match->flags | GIT_ATTR_FNMATCH_IGNORE;
54
+ match->flags |= GIT_ATTR_FNMATCH_IGNORE;
55
+
56
+ if (ignore_case)
57
+ match->flags |= GIT_ATTR_FNMATCH_ICASE;
58
+
38
59
  scan = git__next_line(scan);
39
60
  error = git_vector_insert(&ignores->rules, match);
40
61
  }
@@ -58,13 +79,13 @@ static int parse_ignore_file(
58
79
  return error;
59
80
  }
60
81
 
61
- #define push_ignore_file(R,S,B,F) \
62
- git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,parse_ignore_file,(S))
82
+ #define push_ignore_file(R,IGN,S,B,F) \
83
+ git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,parse_ignore_file,(IGN),(S))
63
84
 
64
85
  static int push_one_ignore(void *ref, git_buf *path)
65
86
  {
66
87
  git_ignores *ign = (git_ignores *)ref;
67
- return push_ignore_file(ign->repo, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
88
+ return push_ignore_file(ign->repo, ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
68
89
  }
69
90
 
70
91
  int git_ignore__for_path(
@@ -74,6 +95,8 @@ int git_ignore__for_path(
74
95
  {
75
96
  int error = 0;
76
97
  const char *workdir = git_repository_workdir(repo);
98
+ git_config *cfg = NULL;
99
+ int val;
77
100
 
78
101
  assert(ignores);
79
102
 
@@ -81,6 +104,17 @@ int git_ignore__for_path(
81
104
  git_buf_init(&ignores->dir, 0);
82
105
  ignores->ign_internal = NULL;
83
106
 
107
+ /* Set the ignore_case flag appropriately */
108
+ if ((error = git_repository_config(&cfg, repo)) < 0)
109
+ goto cleanup;
110
+
111
+ if (git_config_get_bool(&val, cfg, "core.ignorecase") == 0)
112
+ ignores->ignore_case = (val != 0);
113
+ else
114
+ ignores->ignore_case = 0;
115
+
116
+ git_config_free(cfg);
117
+
84
118
  if ((error = git_vector_init(&ignores->ign_path, 8, NULL)) < 0 ||
85
119
  (error = git_vector_init(&ignores->ign_global, 2, NULL)) < 0 ||
86
120
  (error = git_attr_cache__init(repo)) < 0)
@@ -109,14 +143,14 @@ int git_ignore__for_path(
109
143
  }
110
144
 
111
145
  /* load .git/info/exclude */
112
- error = push_ignore_file(repo, &ignores->ign_global,
146
+ error = push_ignore_file(repo, ignores, &ignores->ign_global,
113
147
  git_repository_path(repo), GIT_IGNORE_FILE_INREPO);
114
148
  if (error < 0)
115
149
  goto cleanup;
116
150
 
117
151
  /* load core.excludesfile */
118
152
  if (git_repository_attr_cache(repo)->cfg_excl_file != NULL)
119
- error = push_ignore_file(repo, &ignores->ign_global, NULL,
153
+ error = push_ignore_file(repo, ignores, &ignores->ign_global, NULL,
120
154
  git_repository_attr_cache(repo)->cfg_excl_file);
121
155
 
122
156
  cleanup:
@@ -132,7 +166,7 @@ int git_ignore__push_dir(git_ignores *ign, const char *dir)
132
166
  return -1;
133
167
  else
134
168
  return push_ignore_file(
135
- ign->repo, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE);
169
+ ign->repo, ign, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE);
136
170
  }
137
171
 
138
172
  int git_ignore__pop_dir(git_ignores *ign)
@@ -205,6 +239,16 @@ cleanup:
205
239
  return 0;
206
240
  }
207
241
 
242
+ static int get_internal_ignores(git_attr_file **ign, git_repository *repo)
243
+ {
244
+ int error;
245
+
246
+ if (!(error = git_attr_cache__init(repo)))
247
+ error = git_attr_cache__internal_file(repo, GIT_IGNORE_INTERNAL, ign);
248
+
249
+ return error;
250
+ }
251
+
208
252
  int git_ignore_add_rule(
209
253
  git_repository *repo,
210
254
  const char *rules)
@@ -212,11 +256,8 @@ int git_ignore_add_rule(
212
256
  int error;
213
257
  git_attr_file *ign_internal;
214
258
 
215
- error = git_attr_cache__internal_file(
216
- repo, GIT_IGNORE_INTERNAL, &ign_internal);
217
-
218
- if (!error && ign_internal != NULL)
219
- error = parse_ignore_file(repo, rules, ign_internal);
259
+ if (!(error = get_internal_ignores(&ign_internal, repo)))
260
+ error = parse_ignore_file(repo, NULL, rules, ign_internal);
220
261
 
221
262
  return error;
222
263
  }
@@ -227,10 +268,7 @@ int git_ignore_clear_internal_rules(
227
268
  int error;
228
269
  git_attr_file *ign_internal;
229
270
 
230
- error = git_attr_cache__internal_file(
231
- repo, GIT_IGNORE_INTERNAL, &ign_internal);
232
-
233
- if (!error && ign_internal != NULL)
271
+ if (!(error = get_internal_ignores(&ign_internal, repo)))
234
272
  git_attr_file__clear_rules(ign_internal);
235
273
 
236
274
  return error;
@@ -239,15 +277,76 @@ int git_ignore_clear_internal_rules(
239
277
  int git_ignore_path_is_ignored(
240
278
  int *ignored,
241
279
  git_repository *repo,
242
- const char *path)
280
+ const char *pathname)
243
281
  {
244
282
  int error;
283
+ const char *workdir;
284
+ git_attr_path path;
285
+ char *tail, *end;
286
+ bool full_is_dir;
245
287
  git_ignores ignores;
288
+ unsigned int i;
289
+ git_attr_file *file;
246
290
 
247
- if (git_ignore__for_path(repo, path, &ignores) < 0)
248
- return -1;
291
+ assert(ignored && pathname);
292
+
293
+ workdir = repo ? git_repository_workdir(repo) : NULL;
294
+
295
+ if ((error = git_attr_path__init(&path, pathname, workdir)) < 0)
296
+ return error;
297
+
298
+ tail = path.path;
299
+ end = &path.full.ptr[path.full.size];
300
+ full_is_dir = path.is_dir;
301
+
302
+ while (1) {
303
+ /* advance to next component of path */
304
+ path.basename = tail;
305
+
306
+ while (tail < end && *tail != '/') tail++;
307
+ *tail = '\0';
308
+
309
+ path.full.size = (tail - path.full.ptr);
310
+ path.is_dir = (tail == end) ? full_is_dir : true;
311
+
312
+ /* update ignores for new path fragment */
313
+ if (path.basename == path.path)
314
+ error = git_ignore__for_path(repo, path.path, &ignores);
315
+ else
316
+ error = git_ignore__push_dir(&ignores, path.basename);
317
+ if (error < 0)
318
+ break;
319
+
320
+ /* first process builtins - success means path was found */
321
+ if (ignore_lookup_in_rules(
322
+ &ignores.ign_internal->rules, &path, ignored))
323
+ goto cleanup;
249
324
 
250
- error = git_ignore__lookup(&ignores, path, ignored);
325
+ /* next process files in the path */
326
+ git_vector_foreach(&ignores.ign_path, i, file) {
327
+ if (ignore_lookup_in_rules(&file->rules, &path, ignored))
328
+ goto cleanup;
329
+ }
330
+
331
+ /* last process global ignores */
332
+ git_vector_foreach(&ignores.ign_global, i, file) {
333
+ if (ignore_lookup_in_rules(&file->rules, &path, ignored))
334
+ goto cleanup;
335
+ }
336
+
337
+ /* if we found no rules before reaching the end, we're done */
338
+ if (tail == end)
339
+ break;
340
+
341
+ /* reinstate divider in path */
342
+ *tail = '/';
343
+ while (*tail == '/') tail++;
344
+ }
345
+
346
+ *ignored = 0;
347
+
348
+ cleanup:
349
+ git_attr_path__free(&path);
251
350
  git_ignore__free(&ignores);
252
351
  return error;
253
352
  }