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.
- data/README.md +3 -3
- data/Rakefile +3 -1
- data/ext/rugged/rugged.c +30 -0
- data/ext/rugged/rugged.h +9 -0
- data/ext/rugged/rugged_branch.c +306 -0
- data/ext/rugged/rugged_config.c +16 -13
- data/ext/rugged/rugged_index.c +25 -0
- data/ext/rugged/rugged_object.c +6 -2
- data/ext/rugged/rugged_reference.c +11 -18
- data/ext/rugged/rugged_revwalk.c +1 -1
- data/lib/rugged.rb +1 -0
- data/lib/rugged/branch.rb +28 -0
- data/lib/rugged/commit.rb +5 -5
- data/lib/rugged/repository.rb +32 -7
- data/lib/rugged/tag.rb +5 -1
- data/lib/rugged/version.rb +1 -1
- data/test/branch_test.rb +227 -0
- data/test/config_test.rb +1 -1
- data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
- data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
- data/test/index_test.rb +31 -0
- data/test/index_test.rb~ +218 -0
- data/test/lib_test.rb +22 -0
- data/test/reference_test.rb +5 -3
- data/vendor/libgit2/Makefile.embed +1 -1
- data/vendor/libgit2/include/git2.h +1 -0
- data/vendor/libgit2/include/git2/branch.h +17 -13
- data/vendor/libgit2/include/git2/checkout.h +83 -22
- data/vendor/libgit2/include/git2/clone.h +6 -3
- data/vendor/libgit2/include/git2/common.h +1 -8
- data/vendor/libgit2/include/git2/config.h +185 -26
- data/vendor/libgit2/include/git2/diff.h +229 -17
- data/vendor/libgit2/include/git2/errors.h +39 -1
- data/vendor/libgit2/include/git2/ignore.h +6 -3
- data/vendor/libgit2/include/git2/indexer.h +1 -0
- data/vendor/libgit2/include/git2/merge.h +1 -1
- data/vendor/libgit2/include/git2/object.h +7 -4
- data/vendor/libgit2/include/git2/odb.h +4 -2
- data/vendor/libgit2/include/git2/odb_backend.h +6 -0
- data/vendor/libgit2/include/git2/oid.h +2 -0
- data/vendor/libgit2/include/git2/pack.h +89 -0
- data/vendor/libgit2/include/git2/refs.h +88 -0
- data/vendor/libgit2/include/git2/refspec.h +0 -8
- data/vendor/libgit2/include/git2/remote.h +34 -1
- data/vendor/libgit2/include/git2/repository.h +238 -6
- data/vendor/libgit2/include/git2/reset.h +4 -1
- data/vendor/libgit2/include/git2/revwalk.h +1 -1
- data/vendor/libgit2/include/git2/status.h +19 -14
- data/vendor/libgit2/include/git2/strarray.h +54 -0
- data/vendor/libgit2/include/git2/submodule.h +451 -45
- data/vendor/libgit2/include/git2/tag.h +16 -0
- data/vendor/libgit2/include/git2/tree.h +2 -2
- data/vendor/libgit2/include/git2/types.h +4 -0
- data/vendor/libgit2/src/amiga/map.c +4 -7
- data/vendor/libgit2/src/attr.c +21 -13
- data/vendor/libgit2/src/attr.h +3 -1
- data/vendor/libgit2/src/attr_file.c +14 -14
- data/vendor/libgit2/src/attr_file.h +6 -5
- data/vendor/libgit2/src/blob.c +22 -12
- data/vendor/libgit2/src/branch.c +62 -66
- data/vendor/libgit2/src/buffer.c +63 -14
- data/vendor/libgit2/src/buffer.h +4 -0
- data/vendor/libgit2/src/cache.c +5 -4
- data/vendor/libgit2/src/checkout.c +381 -159
- data/vendor/libgit2/src/clone.c +221 -94
- data/vendor/libgit2/src/common.h +13 -3
- data/vendor/libgit2/src/compress.c +53 -0
- data/vendor/libgit2/src/compress.h +16 -0
- data/vendor/libgit2/src/config.c +380 -175
- data/vendor/libgit2/src/config.h +2 -5
- data/vendor/libgit2/src/config_file.c +63 -46
- data/vendor/libgit2/src/config_file.h +16 -4
- data/vendor/libgit2/src/crlf.c +4 -3
- data/vendor/libgit2/src/delta.c +491 -0
- data/vendor/libgit2/src/delta.h +112 -0
- data/vendor/libgit2/src/diff.c +310 -67
- data/vendor/libgit2/src/diff.h +10 -1
- data/vendor/libgit2/src/diff_output.c +1030 -337
- data/vendor/libgit2/src/diff_output.h +86 -0
- data/vendor/libgit2/src/errors.c +10 -1
- data/vendor/libgit2/src/fetch.c +108 -24
- data/vendor/libgit2/src/filebuf.c +8 -2
- data/vendor/libgit2/src/fileops.c +342 -177
- data/vendor/libgit2/src/fileops.h +84 -7
- data/vendor/libgit2/src/filter.c +0 -35
- data/vendor/libgit2/src/filter.h +0 -12
- data/vendor/libgit2/src/{compat/fnmatch.c → fnmatch.c} +16 -4
- data/vendor/libgit2/src/{compat/fnmatch.h → fnmatch.h} +4 -3
- data/vendor/libgit2/src/global.c +4 -0
- data/vendor/libgit2/src/ignore.c +122 -23
- data/vendor/libgit2/src/ignore.h +1 -0
- data/vendor/libgit2/src/index.c +56 -10
- data/vendor/libgit2/src/index.h +2 -0
- data/vendor/libgit2/src/indexer.c +8 -9
- data/vendor/libgit2/src/iterator.c +244 -31
- data/vendor/libgit2/src/iterator.h +30 -1
- data/vendor/libgit2/src/message.c +1 -1
- data/vendor/libgit2/src/netops.c +44 -4
- data/vendor/libgit2/src/object.c +80 -69
- data/vendor/libgit2/src/object.h +39 -0
- data/vendor/libgit2/src/odb.c +79 -15
- data/vendor/libgit2/src/odb.h +20 -5
- data/vendor/libgit2/src/odb_pack.c +65 -33
- data/vendor/libgit2/src/oid.c +0 -3
- data/vendor/libgit2/src/pack-objects.c +1315 -0
- data/vendor/libgit2/src/pack-objects.h +87 -0
- data/vendor/libgit2/src/pack.c +36 -12
- data/vendor/libgit2/src/pack.h +1 -0
- data/vendor/libgit2/src/path.c +42 -9
- data/vendor/libgit2/src/path.h +14 -0
- data/vendor/libgit2/src/pkt.c +52 -2
- data/vendor/libgit2/src/pkt.h +10 -0
- data/vendor/libgit2/src/pool.h +11 -0
- data/vendor/libgit2/src/posix.h +8 -0
- data/vendor/libgit2/src/protocol.c +24 -2
- data/vendor/libgit2/src/protocol.h +4 -0
- data/vendor/libgit2/src/reflog.c +1 -1
- data/vendor/libgit2/src/refs.c +292 -124
- data/vendor/libgit2/src/refs.h +4 -2
- data/vendor/libgit2/src/refspec.c +117 -19
- data/vendor/libgit2/src/refspec.h +19 -0
- data/vendor/libgit2/src/remote.c +152 -48
- data/vendor/libgit2/src/remote.h +4 -1
- data/vendor/libgit2/src/repo_template.h +58 -0
- data/vendor/libgit2/src/repository.c +594 -179
- data/vendor/libgit2/src/repository.h +23 -22
- data/vendor/libgit2/src/reset.c +71 -29
- data/vendor/libgit2/src/revparse.c +26 -17
- data/vendor/libgit2/src/revwalk.c +36 -19
- data/vendor/libgit2/src/sha1.h +7 -0
- data/vendor/libgit2/src/{sha1.c → sha1/sha1.c} +0 -0
- data/vendor/libgit2/src/signature.c +12 -10
- data/vendor/libgit2/src/status.c +52 -6
- data/vendor/libgit2/src/submodule.c +1363 -255
- data/vendor/libgit2/src/submodule.h +102 -0
- data/vendor/libgit2/src/tag.c +42 -26
- data/vendor/libgit2/src/thread-utils.h +7 -7
- data/vendor/libgit2/src/transport.h +15 -1
- data/vendor/libgit2/src/transports/git.c +1 -1
- data/vendor/libgit2/src/transports/http.c +197 -36
- data/vendor/libgit2/src/tree.c +3 -3
- data/vendor/libgit2/src/unix/map.c +2 -0
- data/vendor/libgit2/src/unix/posix.h +1 -8
- data/vendor/libgit2/src/util.c +6 -1
- data/vendor/libgit2/src/util.h +7 -0
- data/vendor/libgit2/src/vector.c +16 -0
- data/vendor/libgit2/src/vector.h +1 -0
- data/vendor/libgit2/src/win32/dir.c +8 -21
- data/vendor/libgit2/src/win32/findfile.c +149 -0
- data/vendor/libgit2/src/win32/findfile.h +23 -0
- data/vendor/libgit2/src/win32/posix.h +3 -7
- data/vendor/libgit2/src/win32/posix_w32.c +44 -102
- data/vendor/libgit2/src/win32/pthread.c +68 -0
- data/vendor/libgit2/src/win32/pthread.h +7 -0
- data/vendor/libgit2/src/win32/utf-conv.c +60 -71
- data/vendor/libgit2/src/win32/utf-conv.h +4 -3
- metadata +70 -71
- data/vendor/libgit2/include/git2/windows.h +0 -59
data/vendor/libgit2/src/ignore.h
CHANGED
data/vendor/libgit2/src/index.c
CHANGED
@@ -99,6 +99,13 @@ static int index_srch(const void *key, const void *array_member)
|
|
99
99
|
return strcmp(key, entry->path);
|
100
100
|
}
|
101
101
|
|
102
|
+
static int index_isrch(const void *key, const void *array_member)
|
103
|
+
{
|
104
|
+
const git_index_entry *entry = array_member;
|
105
|
+
|
106
|
+
return strcasecmp(key, entry->path);
|
107
|
+
}
|
108
|
+
|
102
109
|
static int index_cmp(const void *a, const void *b)
|
103
110
|
{
|
104
111
|
const git_index_entry *entry_a = a;
|
@@ -107,6 +114,14 @@ static int index_cmp(const void *a, const void *b)
|
|
107
114
|
return strcmp(entry_a->path, entry_b->path);
|
108
115
|
}
|
109
116
|
|
117
|
+
static int index_icmp(const void *a, const void *b)
|
118
|
+
{
|
119
|
+
const git_index_entry *entry_a = a;
|
120
|
+
const git_index_entry *entry_b = b;
|
121
|
+
|
122
|
+
return strcasecmp(entry_a->path, entry_b->path);
|
123
|
+
}
|
124
|
+
|
110
125
|
static int unmerged_srch(const void *key, const void *array_member)
|
111
126
|
{
|
112
127
|
const git_index_entry_unmerged *entry = array_member;
|
@@ -147,6 +162,14 @@ static unsigned int index_merge_mode(
|
|
147
162
|
return index_create_mode(mode);
|
148
163
|
}
|
149
164
|
|
165
|
+
static void index_set_ignore_case(git_index *index, bool ignore_case)
|
166
|
+
{
|
167
|
+
index->entries._cmp = ignore_case ? index_icmp : index_cmp;
|
168
|
+
index->entries_search = ignore_case ? index_isrch : index_srch;
|
169
|
+
index->entries.sorted = 0;
|
170
|
+
git_vector_sort(&index->entries);
|
171
|
+
}
|
172
|
+
|
150
173
|
int git_index_open(git_index **index_out, const char *index_path)
|
151
174
|
{
|
152
175
|
git_index *index;
|
@@ -162,6 +185,8 @@ int git_index_open(git_index **index_out, const char *index_path)
|
|
162
185
|
if (git_vector_init(&index->entries, 32, index_cmp) < 0)
|
163
186
|
return -1;
|
164
187
|
|
188
|
+
index->entries_search = index_srch;
|
189
|
+
|
165
190
|
/* Check if index file is stored on disk already */
|
166
191
|
if (git_path_exists(index->index_file_path) == true)
|
167
192
|
index->on_disk = 1;
|
@@ -228,8 +253,12 @@ void git_index_clear(git_index *index)
|
|
228
253
|
|
229
254
|
int git_index_set_caps(git_index *index, unsigned int caps)
|
230
255
|
{
|
256
|
+
int old_ignore_case;
|
257
|
+
|
231
258
|
assert(index);
|
232
259
|
|
260
|
+
old_ignore_case = index->ignore_case;
|
261
|
+
|
233
262
|
if (caps == GIT_INDEXCAP_FROM_OWNER) {
|
234
263
|
git_config *cfg;
|
235
264
|
int val;
|
@@ -247,7 +276,7 @@ int git_index_set_caps(git_index *index, unsigned int caps)
|
|
247
276
|
if (git_config_get_bool(&val, cfg, "core.filemode") == 0)
|
248
277
|
index->distrust_filemode = (val == 0);
|
249
278
|
if (git_config_get_bool(&val, cfg, "core.symlinks") == 0)
|
250
|
-
index->no_symlinks = (val
|
279
|
+
index->no_symlinks = (val == 0);
|
251
280
|
}
|
252
281
|
else {
|
253
282
|
index->ignore_case = ((caps & GIT_INDEXCAP_IGNORE_CASE) != 0);
|
@@ -255,6 +284,11 @@ int git_index_set_caps(git_index *index, unsigned int caps)
|
|
255
284
|
index->no_symlinks = ((caps & GIT_INDEXCAP_NO_SYMLINKS) != 0);
|
256
285
|
}
|
257
286
|
|
287
|
+
if (old_ignore_case != index->ignore_case)
|
288
|
+
{
|
289
|
+
index_set_ignore_case(index, index->ignore_case);
|
290
|
+
}
|
291
|
+
|
258
292
|
return 0;
|
259
293
|
}
|
260
294
|
|
@@ -552,14 +586,14 @@ int git_index_remove(git_index *index, int position)
|
|
552
586
|
|
553
587
|
int git_index_find(git_index *index, const char *path)
|
554
588
|
{
|
555
|
-
return git_vector_bsearch2(&index->entries,
|
589
|
+
return git_vector_bsearch2(&index->entries, index->entries_search, path);
|
556
590
|
}
|
557
591
|
|
558
592
|
unsigned int git_index__prefix_position(git_index *index, const char *path)
|
559
593
|
{
|
560
594
|
unsigned int pos;
|
561
595
|
|
562
|
-
git_vector_bsearch3(&pos, &index->entries,
|
596
|
+
git_vector_bsearch3(&pos, &index->entries, index->entries_search, path);
|
563
597
|
|
564
598
|
return pos;
|
565
599
|
}
|
@@ -938,16 +972,28 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
|
|
938
972
|
|
939
973
|
static int write_entries(git_index *index, git_filebuf *file)
|
940
974
|
{
|
975
|
+
int error = 0;
|
941
976
|
unsigned int i;
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
977
|
+
git_vector case_sorted;
|
978
|
+
git_index_entry *entry;
|
979
|
+
git_vector *out = &index->entries;
|
980
|
+
|
981
|
+
/* If index->entries is sorted case-insensitively, then we need
|
982
|
+
* to re-sort it case-sensitively before writing */
|
983
|
+
if (index->ignore_case) {
|
984
|
+
git_vector_dup(&case_sorted, &index->entries, index_cmp);
|
985
|
+
git_vector_sort(&case_sorted);
|
986
|
+
out = &case_sorted;
|
948
987
|
}
|
949
988
|
|
950
|
-
|
989
|
+
git_vector_foreach(out, i, entry)
|
990
|
+
if ((error = write_disk_entry(file, entry)) < 0)
|
991
|
+
break;
|
992
|
+
|
993
|
+
if (index->ignore_case)
|
994
|
+
git_vector_free(&case_sorted);
|
995
|
+
|
996
|
+
return error;
|
951
997
|
}
|
952
998
|
|
953
999
|
static int write_index(git_index *index, git_filebuf *file)
|
data/vendor/libgit2/src/index.h
CHANGED
@@ -324,8 +324,8 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
|
|
324
324
|
if (git_vector_init(&idx->deltas, (unsigned int)(idx->nr_objects / 2), NULL) < 0)
|
325
325
|
return -1;
|
326
326
|
|
327
|
+
memset(stats, 0, sizeof(git_indexer_stats));
|
327
328
|
stats->total = (unsigned int)idx->nr_objects;
|
328
|
-
stats->processed = 0;
|
329
329
|
}
|
330
330
|
|
331
331
|
/* Now that we have data in the pack, let's try to parse it */
|
@@ -361,6 +361,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
|
|
361
361
|
if (error < 0)
|
362
362
|
return error;
|
363
363
|
|
364
|
+
stats->received++;
|
364
365
|
continue;
|
365
366
|
}
|
366
367
|
|
@@ -379,6 +380,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
|
|
379
380
|
git__free(obj.data);
|
380
381
|
|
381
382
|
stats->processed = (unsigned int)++processed;
|
383
|
+
stats->received++;
|
382
384
|
}
|
383
385
|
|
384
386
|
return 0;
|
@@ -577,9 +579,11 @@ void git_indexer_stream_free(git_indexer_stream *idx)
|
|
577
579
|
git_vector_foreach(&idx->objects, i, e)
|
578
580
|
git__free(e);
|
579
581
|
git_vector_free(&idx->objects);
|
580
|
-
|
581
|
-
|
582
|
-
|
582
|
+
if (idx->pack) {
|
583
|
+
git_vector_foreach(&idx->pack->cache, i, pe)
|
584
|
+
git__free(pe);
|
585
|
+
git_vector_free(&idx->pack->cache);
|
586
|
+
}
|
583
587
|
git_vector_foreach(&idx->deltas, i, delta)
|
584
588
|
git__free(delta);
|
585
589
|
git_vector_free(&idx->deltas);
|
@@ -595,11 +599,6 @@ int git_indexer_new(git_indexer **out, const char *packname)
|
|
595
599
|
|
596
600
|
assert(out && packname);
|
597
601
|
|
598
|
-
if (git_path_root(packname) < 0) {
|
599
|
-
giterr_set(GITERR_INDEXER, "Path is not absolute");
|
600
|
-
return -1;
|
601
|
-
}
|
602
|
-
|
603
602
|
idx = git__calloc(1, sizeof(git_indexer));
|
604
603
|
GITERR_CHECK_ALLOC(idx);
|
605
604
|
|
@@ -17,6 +17,7 @@
|
|
17
17
|
(P)->base.type = GIT_ITERATOR_ ## NAME_UC; \
|
18
18
|
(P)->base.start = start ? git__strdup(start) : NULL; \
|
19
19
|
(P)->base.end = end ? git__strdup(end) : NULL; \
|
20
|
+
(P)->base.ignore_case = 0; \
|
20
21
|
(P)->base.current = NAME_LC ## _iterator__current; \
|
21
22
|
(P)->base.at_end = NAME_LC ## _iterator__at_end; \
|
22
23
|
(P)->base.advance = NAME_LC ## _iterator__advance; \
|
@@ -81,7 +82,7 @@ int git_iterator_for_nothing(git_iterator **iter)
|
|
81
82
|
|
82
83
|
typedef struct tree_iterator_frame tree_iterator_frame;
|
83
84
|
struct tree_iterator_frame {
|
84
|
-
tree_iterator_frame *next;
|
85
|
+
tree_iterator_frame *next, *prev;
|
85
86
|
git_tree *tree;
|
86
87
|
char *start;
|
87
88
|
unsigned int index;
|
@@ -90,7 +91,7 @@ struct tree_iterator_frame {
|
|
90
91
|
typedef struct {
|
91
92
|
git_iterator base;
|
92
93
|
git_repository *repo;
|
93
|
-
tree_iterator_frame *stack;
|
94
|
+
tree_iterator_frame *stack, *tail;
|
94
95
|
git_index_entry entry;
|
95
96
|
git_buf path;
|
96
97
|
bool path_has_filename;
|
@@ -118,8 +119,10 @@ static void tree_iterator__pop_frame(tree_iterator *ti)
|
|
118
119
|
{
|
119
120
|
tree_iterator_frame *tf = ti->stack;
|
120
121
|
ti->stack = tf->next;
|
121
|
-
if (ti->stack != NULL)
|
122
|
-
git_tree_free(tf->tree);
|
122
|
+
if (ti->stack != NULL) {
|
123
|
+
git_tree_free(tf->tree); /* don't free the initial tree */
|
124
|
+
ti->stack->prev = NULL; /* disconnect prev */
|
125
|
+
}
|
123
126
|
git__free(tf);
|
124
127
|
}
|
125
128
|
|
@@ -220,6 +223,7 @@ static int tree_iterator__expand_tree(tree_iterator *ti)
|
|
220
223
|
|
221
224
|
tf->next = ti->stack;
|
222
225
|
ti->stack = tf;
|
226
|
+
tf->next->prev = tf;
|
223
227
|
|
224
228
|
te = tree_iterator__tree_entry(ti);
|
225
229
|
}
|
@@ -311,7 +315,7 @@ int git_iterator_for_tree_range(
|
|
311
315
|
ITERATOR_BASE_INIT(ti, tree, TREE);
|
312
316
|
|
313
317
|
ti->repo = repo;
|
314
|
-
ti->stack = tree_iterator__alloc_frame(tree, ti->base.start);
|
318
|
+
ti->stack = ti->tail = tree_iterator__alloc_frame(tree, ti->base.start);
|
315
319
|
|
316
320
|
if ((error = tree_iterator__expand_tree(ti)) < 0)
|
317
321
|
git_iterator_free((git_iterator *)ti);
|
@@ -336,7 +340,7 @@ static int index_iterator__current(
|
|
336
340
|
|
337
341
|
if (ie != NULL &&
|
338
342
|
ii->base.end != NULL &&
|
339
|
-
|
343
|
+
ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0)
|
340
344
|
{
|
341
345
|
ii->current = git_index_entrycount(ii->index);
|
342
346
|
ie = NULL;
|
@@ -401,6 +405,7 @@ int git_iterator_for_index_range(
|
|
401
405
|
if ((error = git_repository_index(&ii->index, repo)) < 0)
|
402
406
|
git__free(ii);
|
403
407
|
else {
|
408
|
+
ii->base.ignore_case = ii->index->ignore_case;
|
404
409
|
ii->current = start ? git_index__prefix_position(ii->index, start) : 0;
|
405
410
|
*iter = (git_iterator *)ii;
|
406
411
|
}
|
@@ -428,12 +433,30 @@ typedef struct {
|
|
428
433
|
int is_ignored;
|
429
434
|
} workdir_iterator;
|
430
435
|
|
431
|
-
static
|
436
|
+
static int git_path_with_stat_cmp_case(const void *a, const void *b)
|
437
|
+
{
|
438
|
+
const git_path_with_stat *path_with_stat_a = a;
|
439
|
+
const git_path_with_stat *path_with_stat_b = b;
|
440
|
+
|
441
|
+
return strcmp(path_with_stat_a->path, path_with_stat_b->path);
|
442
|
+
}
|
443
|
+
|
444
|
+
static int git_path_with_stat_cmp_icase(const void *a, const void *b)
|
445
|
+
{
|
446
|
+
const git_path_with_stat *path_with_stat_a = a;
|
447
|
+
const git_path_with_stat *path_with_stat_b = b;
|
448
|
+
|
449
|
+
return strcasecmp(path_with_stat_a->path, path_with_stat_b->path);
|
450
|
+
}
|
451
|
+
|
452
|
+
static workdir_iterator_frame *workdir_iterator__alloc_frame(workdir_iterator *wi)
|
432
453
|
{
|
433
454
|
workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
|
455
|
+
git_vector_cmp entry_compare = CASESELECT(wi->base.ignore_case, git_path_with_stat_cmp_icase, git_path_with_stat_cmp_case);
|
456
|
+
|
434
457
|
if (wf == NULL)
|
435
458
|
return NULL;
|
436
|
-
if (git_vector_init(&wf->entries, 0,
|
459
|
+
if (git_vector_init(&wf->entries, 0, entry_compare) != 0) {
|
437
460
|
git__free(wf);
|
438
461
|
return NULL;
|
439
462
|
}
|
@@ -453,16 +476,22 @@ static void workdir_iterator__free_frame(workdir_iterator_frame *wf)
|
|
453
476
|
|
454
477
|
static int workdir_iterator__update_entry(workdir_iterator *wi);
|
455
478
|
|
456
|
-
static int
|
479
|
+
static int workdir_iterator__entry_cmp_case(const void *prefix, const void *item)
|
457
480
|
{
|
458
481
|
const git_path_with_stat *ps = item;
|
459
482
|
return git__prefixcmp((const char *)prefix, ps->path);
|
460
483
|
}
|
461
484
|
|
485
|
+
static int workdir_iterator__entry_cmp_icase(const void *prefix, const void *item)
|
486
|
+
{
|
487
|
+
const git_path_with_stat *ps = item;
|
488
|
+
return git__prefixcmp_icase((const char *)prefix, ps->path);
|
489
|
+
}
|
490
|
+
|
462
491
|
static int workdir_iterator__expand_dir(workdir_iterator *wi)
|
463
492
|
{
|
464
493
|
int error;
|
465
|
-
workdir_iterator_frame *wf = workdir_iterator__alloc_frame();
|
494
|
+
workdir_iterator_frame *wf = workdir_iterator__alloc_frame(wi);
|
466
495
|
GITERR_CHECK_ALLOC(wf);
|
467
496
|
|
468
497
|
error = git_path_dirload_with_stat(wi->path.ptr, wi->root_len, &wf->entries);
|
@@ -476,12 +505,15 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
|
|
476
505
|
if (!wi->stack)
|
477
506
|
wf->start = wi->base.start;
|
478
507
|
else if (wi->stack->start &&
|
479
|
-
|
508
|
+
ITERATOR_PREFIXCMP(wi->base, wi->stack->start, wi->path.ptr + wi->root_len) == 0)
|
480
509
|
wf->start = wi->stack->start;
|
481
510
|
|
482
511
|
if (wf->start)
|
483
512
|
git_vector_bsearch3(
|
484
|
-
&wf->index,
|
513
|
+
&wf->index,
|
514
|
+
&wf->entries,
|
515
|
+
CASESELECT(wi->base.ignore_case, workdir_iterator__entry_cmp_icase, workdir_iterator__entry_cmp_case),
|
516
|
+
wf->start);
|
485
517
|
|
486
518
|
wf->next = wi->stack;
|
487
519
|
wi->stack = wf;
|
@@ -525,7 +557,9 @@ static int workdir_iterator__advance(
|
|
525
557
|
while ((wf = wi->stack) != NULL) {
|
526
558
|
next = git_vector_get(&wf->entries, ++wf->index);
|
527
559
|
if (next != NULL) {
|
528
|
-
|
560
|
+
/* match git's behavior of ignoring anything named ".git" */
|
561
|
+
if (STRCMP_CASESELECT(wi->base.ignore_case, next->path, DOT_GIT "/") == 0 ||
|
562
|
+
STRCMP_CASESELECT(wi->base.ignore_case, next->path, DOT_GIT) == 0)
|
529
563
|
continue;
|
530
564
|
/* else found a good entry */
|
531
565
|
break;
|
@@ -602,13 +636,14 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
|
|
602
636
|
return -1;
|
603
637
|
|
604
638
|
if (wi->base.end &&
|
605
|
-
|
639
|
+
ITERATOR_PREFIXCMP(wi->base, wi->path.ptr + wi->root_len, wi->base.end) > 0)
|
606
640
|
return 0;
|
607
641
|
|
608
642
|
wi->entry.path = ps->path;
|
609
643
|
|
610
|
-
/* skip over .git
|
611
|
-
if (
|
644
|
+
/* skip over .git entry */
|
645
|
+
if (STRCMP_CASESELECT(wi->base.ignore_case, ps->path, DOT_GIT "/") == 0 ||
|
646
|
+
STRCMP_CASESELECT(wi->base.ignore_case, ps->path, DOT_GIT) == 0)
|
612
647
|
return workdir_iterator__advance((git_iterator *)wi, NULL);
|
613
648
|
|
614
649
|
/* if there is an error processing the entry, treat as ignored */
|
@@ -629,15 +664,10 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
|
|
629
664
|
|
630
665
|
/* detect submodules */
|
631
666
|
if (S_ISDIR(wi->entry.mode)) {
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
int res = git_submodule_lookup(NULL, wi->repo, wi->entry.path);
|
637
|
-
is_submodule = (res == 0);
|
638
|
-
if (res == GIT_ENOTFOUND)
|
639
|
-
giterr_clear();
|
640
|
-
}
|
667
|
+
int res = git_submodule_lookup(NULL, wi->repo, wi->entry.path);
|
668
|
+
bool is_submodule = (res == 0);
|
669
|
+
if (res == GIT_ENOTFOUND)
|
670
|
+
giterr_clear();
|
641
671
|
|
642
672
|
/* if submodule, mark as GITLINK and remove trailing slash */
|
643
673
|
if (is_submodule) {
|
@@ -659,19 +689,28 @@ int git_iterator_for_workdir_range(
|
|
659
689
|
{
|
660
690
|
int error;
|
661
691
|
workdir_iterator *wi;
|
692
|
+
git_index *index;
|
662
693
|
|
663
694
|
assert(iter && repo);
|
664
695
|
|
665
|
-
if (
|
666
|
-
|
667
|
-
"Cannot scan working directory for bare repo");
|
668
|
-
return -1;
|
669
|
-
}
|
696
|
+
if ((error = git_repository__ensure_not_bare(repo, "scan working directory")) < 0)
|
697
|
+
return error;
|
670
698
|
|
671
699
|
ITERATOR_BASE_INIT(wi, workdir, WORKDIR);
|
672
700
|
|
673
701
|
wi->repo = repo;
|
674
702
|
|
703
|
+
if ((error = git_repository_index(&index, repo)) < 0) {
|
704
|
+
git__free(wi);
|
705
|
+
return error;
|
706
|
+
}
|
707
|
+
|
708
|
+
/* Set the ignore_case flag for the workdir iterator to match
|
709
|
+
* that of the index. */
|
710
|
+
wi->base.ignore_case = index->ignore_case;
|
711
|
+
|
712
|
+
git_index_free(index);
|
713
|
+
|
675
714
|
if (git_buf_sets(&wi->path, git_repository_workdir(repo)) < 0 ||
|
676
715
|
git_path_to_dir(&wi->path) < 0 ||
|
677
716
|
git_ignore__for_path(repo, "", &wi->ignores) < 0)
|
@@ -696,6 +735,129 @@ int git_iterator_for_workdir_range(
|
|
696
735
|
return error;
|
697
736
|
}
|
698
737
|
|
738
|
+
typedef struct {
|
739
|
+
git_iterator base;
|
740
|
+
git_iterator *wrapped;
|
741
|
+
git_vector entries;
|
742
|
+
git_vector_cmp comparer;
|
743
|
+
git_pool entry_pool;
|
744
|
+
git_pool string_pool;
|
745
|
+
unsigned int position;
|
746
|
+
} spoolandsort_iterator;
|
747
|
+
|
748
|
+
static int spoolandsort_iterator__current(
|
749
|
+
git_iterator *self, const git_index_entry **entry)
|
750
|
+
{
|
751
|
+
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
752
|
+
|
753
|
+
if (si->position < si->entries.length)
|
754
|
+
*entry = (const git_index_entry *)git_vector_get_const(&si->entries, si->position);
|
755
|
+
else
|
756
|
+
*entry = NULL;
|
757
|
+
|
758
|
+
return 0;
|
759
|
+
}
|
760
|
+
|
761
|
+
static int spoolandsort_iterator__at_end(git_iterator *self)
|
762
|
+
{
|
763
|
+
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
764
|
+
|
765
|
+
return 0 == si->entries.length || si->entries.length - 1 <= si->position;
|
766
|
+
}
|
767
|
+
|
768
|
+
static int spoolandsort_iterator__advance(
|
769
|
+
git_iterator *self, const git_index_entry **entry)
|
770
|
+
{
|
771
|
+
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
772
|
+
|
773
|
+
if (si->position < si->entries.length)
|
774
|
+
*entry = (const git_index_entry *)git_vector_get_const(&si->entries, ++si->position);
|
775
|
+
else
|
776
|
+
*entry = NULL;
|
777
|
+
|
778
|
+
return 0;
|
779
|
+
}
|
780
|
+
|
781
|
+
static int spoolandsort_iterator__seek(git_iterator *self, const char *prefix)
|
782
|
+
{
|
783
|
+
GIT_UNUSED(self);
|
784
|
+
GIT_UNUSED(prefix);
|
785
|
+
|
786
|
+
return -1;
|
787
|
+
}
|
788
|
+
|
789
|
+
static int spoolandsort_iterator__reset(git_iterator *self)
|
790
|
+
{
|
791
|
+
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
792
|
+
|
793
|
+
si->position = 0;
|
794
|
+
|
795
|
+
return 0;
|
796
|
+
}
|
797
|
+
|
798
|
+
static void spoolandsort_iterator__free(git_iterator *self)
|
799
|
+
{
|
800
|
+
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
801
|
+
|
802
|
+
git_pool_clear(&si->string_pool);
|
803
|
+
git_pool_clear(&si->entry_pool);
|
804
|
+
git_vector_free(&si->entries);
|
805
|
+
git_iterator_free(si->wrapped);
|
806
|
+
}
|
807
|
+
|
808
|
+
int git_iterator_spoolandsort_range(
|
809
|
+
git_iterator **iter,
|
810
|
+
git_iterator *towrap,
|
811
|
+
git_vector_cmp comparer,
|
812
|
+
bool ignore_case,
|
813
|
+
const char *start,
|
814
|
+
const char *end)
|
815
|
+
{
|
816
|
+
spoolandsort_iterator *si;
|
817
|
+
const git_index_entry *item;
|
818
|
+
|
819
|
+
assert(iter && towrap && comparer);
|
820
|
+
|
821
|
+
ITERATOR_BASE_INIT(si, spoolandsort, SPOOLANDSORT);
|
822
|
+
si->base.ignore_case = ignore_case;
|
823
|
+
si->wrapped = towrap;
|
824
|
+
si->comparer = comparer;
|
825
|
+
si->position = 0;
|
826
|
+
|
827
|
+
if (git_vector_init(&si->entries, 16, si->comparer) < 0 ||
|
828
|
+
git_iterator_current(towrap, &item) < 0 ||
|
829
|
+
git_pool_init(&si->entry_pool, sizeof(git_index_entry), 0) ||
|
830
|
+
git_pool_init(&si->string_pool, 1, 0))
|
831
|
+
{
|
832
|
+
git__free(si);
|
833
|
+
return -1;
|
834
|
+
}
|
835
|
+
|
836
|
+
while (item)
|
837
|
+
{
|
838
|
+
git_index_entry *clone = git_pool_malloc(&si->entry_pool, 1);
|
839
|
+
memcpy(clone, item, sizeof(git_index_entry));
|
840
|
+
|
841
|
+
if (item->path)
|
842
|
+
{
|
843
|
+
clone->path = git_pool_strdup(&si->string_pool, item->path);
|
844
|
+
}
|
845
|
+
|
846
|
+
git_vector_insert(&si->entries, clone);
|
847
|
+
|
848
|
+
if (git_iterator_advance(towrap, &item) < 0)
|
849
|
+
{
|
850
|
+
git__free(si);
|
851
|
+
return -1;
|
852
|
+
}
|
853
|
+
}
|
854
|
+
|
855
|
+
git_vector_sort(&si->entries);
|
856
|
+
|
857
|
+
*iter = (git_iterator *)si;
|
858
|
+
|
859
|
+
return 0;
|
860
|
+
}
|
699
861
|
|
700
862
|
int git_iterator_current_tree_entry(
|
701
863
|
git_iterator *iter, const git_tree_entry **tree_entry)
|
@@ -705,6 +867,45 @@ int git_iterator_current_tree_entry(
|
|
705
867
|
return 0;
|
706
868
|
}
|
707
869
|
|
870
|
+
int git_iterator_current_parent_tree(
|
871
|
+
git_iterator *iter,
|
872
|
+
const char *parent_path,
|
873
|
+
const git_tree **tree_ptr)
|
874
|
+
{
|
875
|
+
tree_iterator *ti = (tree_iterator *)iter;
|
876
|
+
tree_iterator_frame *tf;
|
877
|
+
const char *scan = parent_path;
|
878
|
+
|
879
|
+
if (iter->type != GIT_ITERATOR_TREE || ti->stack == NULL)
|
880
|
+
goto notfound;
|
881
|
+
|
882
|
+
for (tf = ti->tail; tf != NULL; tf = tf->prev) {
|
883
|
+
const git_tree_entry *te;
|
884
|
+
|
885
|
+
if (!*scan) {
|
886
|
+
*tree_ptr = tf->tree;
|
887
|
+
return 0;
|
888
|
+
}
|
889
|
+
|
890
|
+
te = git_tree_entry_byindex(tf->tree, tf->index);
|
891
|
+
|
892
|
+
if (strncmp(scan, te->filename, te->filename_len) != 0)
|
893
|
+
goto notfound;
|
894
|
+
|
895
|
+
scan += te->filename_len;
|
896
|
+
|
897
|
+
if (*scan) {
|
898
|
+
if (*scan != '/')
|
899
|
+
goto notfound;
|
900
|
+
scan++;
|
901
|
+
}
|
902
|
+
}
|
903
|
+
|
904
|
+
notfound:
|
905
|
+
*tree_ptr = NULL;
|
906
|
+
return 0;
|
907
|
+
}
|
908
|
+
|
708
909
|
int git_iterator_current_is_ignored(git_iterator *iter)
|
709
910
|
{
|
710
911
|
return (iter->type != GIT_ITERATOR_WORKDIR) ? 0 :
|
@@ -743,6 +944,18 @@ int git_iterator_cmp(
|
|
743
944
|
if (!path_prefix)
|
744
945
|
return -1;
|
745
946
|
|
746
|
-
return
|
947
|
+
return ITERATOR_PREFIXCMP(*iter, entry->path, path_prefix);
|
948
|
+
}
|
949
|
+
|
950
|
+
int git_iterator_current_workdir_path(git_iterator *iter, git_buf **path)
|
951
|
+
{
|
952
|
+
workdir_iterator *wi = (workdir_iterator *)iter;
|
953
|
+
|
954
|
+
if (iter->type != GIT_ITERATOR_WORKDIR || !wi->entry.path)
|
955
|
+
*path = NULL;
|
956
|
+
else
|
957
|
+
*path = &wi->path;
|
958
|
+
|
959
|
+
return 0;
|
747
960
|
}
|
748
961
|
|