rugged 0.17.0.b7 → 0.18.0.b1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.md +88 -32
- data/ext/rugged/extconf.rb +4 -2
- data/ext/rugged/rugged.c +72 -10
- data/ext/rugged/rugged.h +14 -10
- data/ext/rugged/rugged_blob.c +8 -10
- data/ext/rugged/rugged_branch.c +11 -14
- data/ext/rugged/rugged_commit.c +31 -24
- data/ext/rugged/rugged_config.c +2 -2
- data/ext/rugged/rugged_index.c +133 -198
- data/ext/rugged/rugged_note.c +372 -0
- data/ext/rugged/rugged_object.c +50 -22
- data/ext/rugged/rugged_reference.c +122 -130
- data/ext/rugged/rugged_remote.c +72 -29
- data/ext/rugged/rugged_repo.c +402 -20
- data/ext/rugged/rugged_revwalk.c +7 -3
- data/ext/rugged/rugged_settings.c +110 -0
- data/ext/rugged/rugged_signature.c +23 -7
- data/ext/rugged/rugged_tag.c +32 -16
- data/ext/rugged/rugged_tree.c +44 -15
- data/lib/rugged.rb +1 -0
- data/lib/rugged/index.rb +8 -0
- data/lib/rugged/remote.rb +13 -0
- data/lib/rugged/repository.rb +3 -3
- data/lib/rugged/version.rb +1 -1
- data/test/blob_test.rb +13 -15
- data/test/branch_test.rb +32 -67
- data/test/commit_test.rb +50 -12
- data/test/config_test.rb +12 -11
- data/test/coverage/HEAD.json +1 -1
- data/test/coverage/cover.rb +40 -21
- data/test/errors_test.rb +34 -0
- data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
- data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
- data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
- data/test/fixtures/testrepo.git/logs/refs/notes/commits +1 -0
- data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +1 -0
- data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
- data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +1 -0
- data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
- data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
- data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +3 -0
- data/test/fixtures/testrepo.git/refs/notes/commits +1 -0
- data/test/index_test.rb +65 -69
- data/test/lib_test.rb +76 -11
- data/test/note_test.rb +158 -0
- data/test/object_test.rb +8 -11
- data/test/reference_test.rb +77 -85
- data/test/remote_test.rb +86 -8
- data/test/repo_pack_test.rb +9 -7
- data/test/repo_reset_test.rb +80 -0
- data/test/repo_test.rb +176 -53
- data/test/tag_test.rb +44 -7
- data/test/test_helper.rb +63 -35
- data/test/tree_test.rb +34 -13
- data/test/walker_test.rb +14 -14
- data/vendor/libgit2/Makefile.embed +1 -1
- data/vendor/libgit2/deps/http-parser/http_parser.c +974 -578
- data/vendor/libgit2/deps/http-parser/http_parser.h +106 -70
- data/vendor/libgit2/deps/regex/regcomp.c +7 -6
- data/vendor/libgit2/deps/regex/regex_internal.c +1 -1
- data/vendor/libgit2/deps/regex/regex_internal.h +12 -3
- data/vendor/libgit2/deps/regex/regexec.c +5 -5
- data/vendor/libgit2/include/git2.h +5 -1
- data/vendor/libgit2/include/git2/attr.h +4 -2
- data/vendor/libgit2/include/git2/blob.h +39 -12
- data/vendor/libgit2/include/git2/branch.h +123 -35
- data/vendor/libgit2/include/git2/checkout.h +206 -48
- data/vendor/libgit2/include/git2/clone.h +72 -27
- data/vendor/libgit2/include/git2/commit.h +20 -17
- data/vendor/libgit2/include/git2/common.h +67 -1
- data/vendor/libgit2/include/git2/config.h +81 -60
- data/vendor/libgit2/include/git2/cred_helpers.h +53 -0
- data/vendor/libgit2/include/git2/diff.h +459 -150
- data/vendor/libgit2/include/git2/errors.h +9 -1
- data/vendor/libgit2/include/git2/graph.h +41 -0
- data/vendor/libgit2/include/git2/ignore.h +7 -6
- data/vendor/libgit2/include/git2/index.h +323 -97
- data/vendor/libgit2/include/git2/indexer.h +27 -59
- data/vendor/libgit2/include/git2/inttypes.h +4 -0
- data/vendor/libgit2/include/git2/merge.h +13 -3
- data/vendor/libgit2/include/git2/message.h +14 -8
- data/vendor/libgit2/include/git2/net.h +9 -7
- data/vendor/libgit2/include/git2/notes.h +88 -29
- data/vendor/libgit2/include/git2/object.h +16 -6
- data/vendor/libgit2/include/git2/odb.h +80 -17
- data/vendor/libgit2/include/git2/odb_backend.h +47 -11
- data/vendor/libgit2/include/git2/oid.h +26 -17
- data/vendor/libgit2/include/git2/pack.h +62 -8
- data/vendor/libgit2/include/git2/push.h +131 -0
- data/vendor/libgit2/include/git2/refdb.h +103 -0
- data/vendor/libgit2/include/git2/refdb_backend.h +109 -0
- data/vendor/libgit2/include/git2/reflog.h +30 -21
- data/vendor/libgit2/include/git2/refs.h +215 -193
- data/vendor/libgit2/include/git2/refspec.h +22 -2
- data/vendor/libgit2/include/git2/remote.h +158 -37
- data/vendor/libgit2/include/git2/repository.h +150 -31
- data/vendor/libgit2/include/git2/reset.h +43 -9
- data/vendor/libgit2/include/git2/revparse.h +48 -4
- data/vendor/libgit2/include/git2/revwalk.h +25 -10
- data/vendor/libgit2/include/git2/signature.h +20 -12
- data/vendor/libgit2/include/git2/stash.h +121 -0
- data/vendor/libgit2/include/git2/status.h +122 -53
- data/vendor/libgit2/include/git2/strarray.h +17 -11
- data/vendor/libgit2/include/git2/submodule.h +42 -7
- data/vendor/libgit2/include/git2/tag.h +72 -59
- data/vendor/libgit2/include/git2/threads.h +4 -2
- data/vendor/libgit2/include/git2/trace.h +68 -0
- data/vendor/libgit2/include/git2/transport.h +328 -0
- data/vendor/libgit2/include/git2/tree.h +149 -120
- data/vendor/libgit2/include/git2/types.h +13 -12
- data/vendor/libgit2/include/git2/version.h +3 -3
- data/vendor/libgit2/src/amiga/map.c +2 -2
- data/vendor/libgit2/src/attr.c +58 -48
- data/vendor/libgit2/src/attr.h +4 -18
- data/vendor/libgit2/src/attr_file.c +30 -6
- data/vendor/libgit2/src/attr_file.h +6 -8
- data/vendor/libgit2/src/attrcache.h +24 -0
- data/vendor/libgit2/src/blob.c +30 -7
- data/vendor/libgit2/src/blob.h +1 -1
- data/vendor/libgit2/src/branch.c +361 -68
- data/vendor/libgit2/src/branch.h +17 -0
- data/vendor/libgit2/src/bswap.h +1 -1
- data/vendor/libgit2/src/buf_text.c +291 -0
- data/vendor/libgit2/src/buf_text.h +122 -0
- data/vendor/libgit2/src/buffer.c +27 -101
- data/vendor/libgit2/src/buffer.h +54 -39
- data/vendor/libgit2/src/cache.c +15 -6
- data/vendor/libgit2/src/cache.h +1 -1
- data/vendor/libgit2/src/cc-compat.h +3 -1
- data/vendor/libgit2/src/checkout.c +1165 -222
- data/vendor/libgit2/src/checkout.h +24 -0
- data/vendor/libgit2/src/clone.c +171 -86
- data/vendor/libgit2/src/commit.c +44 -45
- data/vendor/libgit2/src/commit.h +3 -3
- data/vendor/libgit2/src/commit_list.c +194 -0
- data/vendor/libgit2/src/commit_list.h +49 -0
- data/vendor/libgit2/src/common.h +44 -10
- data/vendor/libgit2/src/compress.c +1 -1
- data/vendor/libgit2/src/compress.h +1 -1
- data/vendor/libgit2/src/config.c +211 -124
- data/vendor/libgit2/src/config.h +23 -4
- data/vendor/libgit2/src/config_cache.c +2 -2
- data/vendor/libgit2/src/config_file.c +129 -53
- data/vendor/libgit2/src/config_file.h +10 -8
- data/vendor/libgit2/src/crlf.c +66 -67
- data/vendor/libgit2/src/date.c +12 -12
- data/vendor/libgit2/src/delta-apply.c +14 -1
- data/vendor/libgit2/src/delta-apply.h +18 -1
- data/vendor/libgit2/src/delta.c +40 -107
- data/vendor/libgit2/src/delta.h +19 -17
- data/vendor/libgit2/src/diff.c +347 -496
- data/vendor/libgit2/src/diff.h +27 -1
- data/vendor/libgit2/src/diff_output.c +564 -249
- data/vendor/libgit2/src/diff_output.h +15 -8
- data/vendor/libgit2/src/diff_tform.c +687 -0
- data/vendor/libgit2/src/errors.c +27 -36
- data/vendor/libgit2/src/fetch.c +13 -351
- data/vendor/libgit2/src/fetch.h +13 -3
- data/vendor/libgit2/src/fetchhead.c +295 -0
- data/vendor/libgit2/src/fetchhead.h +34 -0
- data/vendor/libgit2/src/filebuf.c +42 -15
- data/vendor/libgit2/src/filebuf.h +4 -2
- data/vendor/libgit2/src/fileops.c +466 -113
- data/vendor/libgit2/src/fileops.h +154 -28
- data/vendor/libgit2/src/filter.c +3 -75
- data/vendor/libgit2/src/filter.h +1 -29
- data/vendor/libgit2/src/fnmatch.c +1 -1
- data/vendor/libgit2/src/fnmatch.h +1 -1
- data/vendor/libgit2/src/global.c +54 -10
- data/vendor/libgit2/src/global.h +10 -1
- data/vendor/libgit2/src/graph.c +178 -0
- data/vendor/libgit2/src/hash.c +25 -52
- data/vendor/libgit2/src/hash.h +21 -9
- data/vendor/libgit2/src/{sha1/sha1.c → hash/hash_generic.c} +20 -12
- data/vendor/libgit2/src/hash/hash_generic.h +24 -0
- data/vendor/libgit2/src/hash/hash_openssl.h +45 -0
- data/vendor/libgit2/src/hash/hash_win32.c +291 -0
- data/vendor/libgit2/src/hash/hash_win32.h +140 -0
- data/vendor/libgit2/src/hashsig.c +368 -0
- data/vendor/libgit2/src/hashsig.h +72 -0
- data/vendor/libgit2/src/ignore.c +22 -15
- data/vendor/libgit2/src/ignore.h +6 -1
- data/vendor/libgit2/src/index.c +770 -171
- data/vendor/libgit2/src/index.h +13 -5
- data/vendor/libgit2/src/indexer.c +286 -431
- data/vendor/libgit2/src/iterator.c +854 -466
- data/vendor/libgit2/src/iterator.h +134 -109
- data/vendor/libgit2/src/map.h +1 -1
- data/vendor/libgit2/src/merge.c +296 -0
- data/vendor/libgit2/src/merge.h +22 -0
- data/vendor/libgit2/src/message.c +1 -1
- data/vendor/libgit2/src/message.h +1 -1
- data/vendor/libgit2/src/mwindow.c +35 -30
- data/vendor/libgit2/src/mwindow.h +2 -2
- data/vendor/libgit2/src/netops.c +162 -98
- data/vendor/libgit2/src/netops.h +50 -15
- data/vendor/libgit2/src/notes.c +109 -58
- data/vendor/libgit2/src/notes.h +2 -1
- data/vendor/libgit2/src/object.c +46 -57
- data/vendor/libgit2/src/object.h +1 -8
- data/vendor/libgit2/src/odb.c +151 -40
- data/vendor/libgit2/src/odb.h +5 -1
- data/vendor/libgit2/src/odb_loose.c +4 -5
- data/vendor/libgit2/src/odb_pack.c +122 -80
- data/vendor/libgit2/src/offmap.h +65 -0
- data/vendor/libgit2/src/oid.c +12 -4
- data/vendor/libgit2/src/oidmap.h +1 -1
- data/vendor/libgit2/src/pack-objects.c +88 -61
- data/vendor/libgit2/src/pack-objects.h +8 -8
- data/vendor/libgit2/src/pack.c +293 -28
- data/vendor/libgit2/src/pack.h +49 -4
- data/vendor/libgit2/src/path.c +103 -14
- data/vendor/libgit2/src/path.h +23 -7
- data/vendor/libgit2/src/pathspec.c +168 -0
- data/vendor/libgit2/src/pathspec.h +40 -0
- data/vendor/libgit2/src/pool.c +29 -4
- data/vendor/libgit2/src/pool.h +8 -1
- data/vendor/libgit2/src/posix.c +26 -27
- data/vendor/libgit2/src/posix.h +2 -3
- data/vendor/libgit2/src/pqueue.c +23 -1
- data/vendor/libgit2/src/pqueue.h +23 -1
- data/vendor/libgit2/src/push.c +653 -0
- data/vendor/libgit2/src/push.h +51 -0
- data/vendor/libgit2/src/refdb.c +185 -0
- data/vendor/libgit2/src/refdb.h +46 -0
- data/vendor/libgit2/src/refdb_fs.c +1024 -0
- data/vendor/libgit2/src/refdb_fs.h +15 -0
- data/vendor/libgit2/src/reflog.c +77 -45
- data/vendor/libgit2/src/reflog.h +1 -3
- data/vendor/libgit2/src/refs.c +366 -1326
- data/vendor/libgit2/src/refs.h +22 -13
- data/vendor/libgit2/src/refspec.c +46 -7
- data/vendor/libgit2/src/refspec.h +11 -1
- data/vendor/libgit2/src/remote.c +758 -120
- data/vendor/libgit2/src/remote.h +10 -5
- data/vendor/libgit2/src/repo_template.h +6 -6
- data/vendor/libgit2/src/repository.c +315 -96
- data/vendor/libgit2/src/repository.h +5 -3
- data/vendor/libgit2/src/reset.c +99 -81
- data/vendor/libgit2/src/revparse.c +157 -84
- data/vendor/libgit2/src/revwalk.c +68 -470
- data/vendor/libgit2/src/revwalk.h +44 -0
- data/vendor/libgit2/src/sha1_lookup.c +1 -1
- data/vendor/libgit2/src/sha1_lookup.h +1 -1
- data/vendor/libgit2/src/signature.c +68 -200
- data/vendor/libgit2/src/signature.h +1 -1
- data/vendor/libgit2/src/stash.c +663 -0
- data/vendor/libgit2/src/status.c +101 -79
- data/vendor/libgit2/src/strmap.h +1 -1
- data/vendor/libgit2/src/submodule.c +67 -51
- data/vendor/libgit2/src/submodule.h +1 -1
- data/vendor/libgit2/src/tag.c +35 -29
- data/vendor/libgit2/src/tag.h +1 -1
- data/vendor/libgit2/src/thread-utils.c +1 -1
- data/vendor/libgit2/src/thread-utils.h +2 -2
- data/vendor/libgit2/src/trace.c +39 -0
- data/vendor/libgit2/src/trace.h +56 -0
- data/vendor/libgit2/src/transport.c +81 -34
- data/vendor/libgit2/src/transports/cred.c +60 -0
- data/vendor/libgit2/src/transports/cred_helpers.c +49 -0
- data/vendor/libgit2/src/transports/git.c +234 -127
- data/vendor/libgit2/src/transports/http.c +761 -433
- data/vendor/libgit2/src/transports/local.c +460 -64
- data/vendor/libgit2/src/transports/smart.c +345 -0
- data/vendor/libgit2/src/transports/smart.h +179 -0
- data/vendor/libgit2/src/{pkt.c → transports/smart_pkt.c} +131 -12
- data/vendor/libgit2/src/transports/smart_protocol.c +856 -0
- data/vendor/libgit2/src/transports/winhttp.c +1136 -0
- data/vendor/libgit2/src/tree-cache.c +2 -2
- data/vendor/libgit2/src/tree-cache.h +1 -1
- data/vendor/libgit2/src/tree.c +239 -166
- data/vendor/libgit2/src/tree.h +11 -2
- data/vendor/libgit2/src/tsort.c +39 -23
- data/vendor/libgit2/src/unix/map.c +1 -1
- data/vendor/libgit2/src/unix/posix.h +12 -2
- data/vendor/libgit2/src/unix/realpath.c +30 -0
- data/vendor/libgit2/src/util.c +250 -13
- data/vendor/libgit2/src/util.h +71 -14
- data/vendor/libgit2/src/vector.c +123 -60
- data/vendor/libgit2/src/vector.h +24 -22
- data/vendor/libgit2/src/win32/dir.c +1 -1
- data/vendor/libgit2/src/win32/dir.h +1 -1
- data/vendor/libgit2/src/win32/error.c +77 -0
- data/vendor/libgit2/src/win32/error.h +13 -0
- data/vendor/libgit2/src/win32/findfile.c +143 -54
- data/vendor/libgit2/src/win32/findfile.h +10 -6
- data/vendor/libgit2/src/win32/map.c +1 -1
- data/vendor/libgit2/src/win32/mingw-compat.h +1 -1
- data/vendor/libgit2/src/win32/msvc-compat.h +10 -1
- data/vendor/libgit2/src/win32/posix.h +10 -1
- data/vendor/libgit2/src/win32/posix_w32.c +132 -63
- data/vendor/libgit2/src/win32/precompiled.c +1 -1
- data/vendor/libgit2/src/win32/pthread.c +1 -1
- data/vendor/libgit2/src/win32/pthread.h +1 -1
- data/vendor/libgit2/src/win32/utf-conv.c +5 -5
- data/vendor/libgit2/src/win32/utf-conv.h +3 -3
- data/vendor/libgit2/src/win32/version.h +20 -0
- metadata +308 -252
- data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
- data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
- data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
- data/test/index_test.rb~ +0 -218
- data/vendor/libgit2/src/pkt.h +0 -91
- data/vendor/libgit2/src/ppc/sha1.c +0 -70
- data/vendor/libgit2/src/ppc/sha1.h +0 -26
- data/vendor/libgit2/src/protocol.c +0 -110
- data/vendor/libgit2/src/protocol.h +0 -21
- data/vendor/libgit2/src/sha1.h +0 -33
- data/vendor/libgit2/src/transport.h +0 -148
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (C)
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
3
|
*
|
4
4
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
5
|
* a Linking Exception. For full terms see the included COPYING file.
|
@@ -10,299 +10,565 @@
|
|
10
10
|
#include "ignore.h"
|
11
11
|
#include "buffer.h"
|
12
12
|
#include "git2/submodule.h"
|
13
|
+
#include <ctype.h>
|
14
|
+
|
15
|
+
#define ITERATOR_SET_CB(P,NAME_LC) do { \
|
16
|
+
(P)->cb.current = NAME_LC ## _iterator__current; \
|
17
|
+
(P)->cb.advance = NAME_LC ## _iterator__advance; \
|
18
|
+
(P)->cb.advance_into = NAME_LC ## _iterator__advance_into; \
|
19
|
+
(P)->cb.seek = NAME_LC ## _iterator__seek; \
|
20
|
+
(P)->cb.reset = NAME_LC ## _iterator__reset; \
|
21
|
+
(P)->cb.at_end = NAME_LC ## _iterator__at_end; \
|
22
|
+
(P)->cb.free = NAME_LC ## _iterator__free; \
|
23
|
+
} while (0)
|
24
|
+
|
25
|
+
#define ITERATOR_CASE_FLAGS \
|
26
|
+
(GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_DONT_IGNORE_CASE)
|
13
27
|
|
14
|
-
#define ITERATOR_BASE_INIT(P,NAME_LC,NAME_UC) do { \
|
28
|
+
#define ITERATOR_BASE_INIT(P,NAME_LC,NAME_UC,REPO) do { \
|
15
29
|
(P) = git__calloc(1, sizeof(NAME_LC ## _iterator)); \
|
16
30
|
GITERR_CHECK_ALLOC(P); \
|
17
|
-
(P)->base.type =
|
31
|
+
(P)->base.type = GIT_ITERATOR_TYPE_ ## NAME_UC; \
|
32
|
+
(P)->base.cb = &(P)->cb; \
|
33
|
+
ITERATOR_SET_CB(P,NAME_LC); \
|
34
|
+
(P)->base.repo = (REPO); \
|
18
35
|
(P)->base.start = start ? git__strdup(start) : NULL; \
|
19
36
|
(P)->base.end = end ? git__strdup(end) : NULL; \
|
20
|
-
(P)->base.
|
21
|
-
|
22
|
-
(P)->base.
|
23
|
-
(P)->base.
|
24
|
-
(P)->base.
|
25
|
-
|
26
|
-
(P)->base.free = NAME_LC ## _iterator__free; \
|
27
|
-
if ((start && !(P)->base.start) || (end && !(P)->base.end)) \
|
28
|
-
return -1; \
|
37
|
+
if ((start && !(P)->base.start) || (end && !(P)->base.end)) { \
|
38
|
+
git__free(P); return -1; } \
|
39
|
+
(P)->base.prefixcomp = git__prefixcmp; \
|
40
|
+
(P)->base.flags = flags & ~ITERATOR_CASE_FLAGS; \
|
41
|
+
if ((P)->base.flags & GIT_ITERATOR_DONT_AUTOEXPAND) \
|
42
|
+
(P)->base.flags |= GIT_ITERATOR_INCLUDE_TREES; \
|
29
43
|
} while (0)
|
30
44
|
|
45
|
+
#define iterator__flag(I,F) ((((git_iterator *)(I))->flags & GIT_ITERATOR_ ## F) != 0)
|
46
|
+
#define iterator__ignore_case(I) iterator__flag(I,IGNORE_CASE)
|
47
|
+
#define iterator__include_trees(I) iterator__flag(I,INCLUDE_TREES)
|
48
|
+
#define iterator__dont_autoexpand(I) iterator__flag(I,DONT_AUTOEXPAND)
|
49
|
+
#define iterator__do_autoexpand(I) !iterator__flag(I,DONT_AUTOEXPAND)
|
50
|
+
|
51
|
+
#define iterator__end(I) ((git_iterator *)(I))->end
|
52
|
+
#define iterator__past_end(I,PATH) \
|
53
|
+
(iterator__end(I) && ((git_iterator *)(I))->prefixcomp((PATH),iterator__end(I)) > 0)
|
54
|
+
|
31
55
|
|
32
|
-
static int
|
33
|
-
git_iterator *iter, const
|
56
|
+
static int iterator__reset_range(
|
57
|
+
git_iterator *iter, const char *start, const char *end)
|
34
58
|
{
|
35
|
-
|
36
|
-
|
59
|
+
if (start) {
|
60
|
+
if (iter->start)
|
61
|
+
git__free(iter->start);
|
62
|
+
iter->start = git__strdup(start);
|
63
|
+
GITERR_CHECK_ALLOC(iter->start);
|
64
|
+
}
|
65
|
+
|
66
|
+
if (end) {
|
67
|
+
if (iter->end)
|
68
|
+
git__free(iter->end);
|
69
|
+
iter->end = git__strdup(end);
|
70
|
+
GITERR_CHECK_ALLOC(iter->end);
|
71
|
+
}
|
72
|
+
|
37
73
|
return 0;
|
38
74
|
}
|
39
75
|
|
40
|
-
static int
|
76
|
+
static int iterator__update_ignore_case(
|
77
|
+
git_iterator *iter,
|
78
|
+
git_iterator_flag_t flags)
|
41
79
|
{
|
42
|
-
|
43
|
-
|
80
|
+
int error = 0, ignore_case = -1;
|
81
|
+
|
82
|
+
if ((flags & GIT_ITERATOR_IGNORE_CASE) != 0)
|
83
|
+
ignore_case = true;
|
84
|
+
else if ((flags & GIT_ITERATOR_DONT_IGNORE_CASE) != 0)
|
85
|
+
ignore_case = false;
|
86
|
+
else {
|
87
|
+
git_index *index;
|
88
|
+
|
89
|
+
if (!(error = git_repository_index__weakptr(&index, iter->repo)))
|
90
|
+
ignore_case = (index->ignore_case != false);
|
91
|
+
}
|
92
|
+
|
93
|
+
if (ignore_case > 0)
|
94
|
+
iter->flags = (iter->flags | GIT_ITERATOR_IGNORE_CASE);
|
95
|
+
else if (ignore_case == 0)
|
96
|
+
iter->flags = (iter->flags & ~GIT_ITERATOR_IGNORE_CASE);
|
97
|
+
|
98
|
+
iter->prefixcomp = iterator__ignore_case(iter) ?
|
99
|
+
git__prefixcmp_icase : git__prefixcmp;
|
100
|
+
|
101
|
+
return error;
|
44
102
|
}
|
45
103
|
|
46
|
-
|
104
|
+
GIT_INLINE(void) iterator__clear_entry(const git_index_entry **entry)
|
47
105
|
{
|
48
|
-
|
106
|
+
if (entry) *entry = NULL;
|
107
|
+
}
|
108
|
+
|
109
|
+
|
110
|
+
static int empty_iterator__noop(const git_index_entry **e, git_iterator *i)
|
111
|
+
{
|
112
|
+
GIT_UNUSED(i);
|
113
|
+
iterator__clear_entry(e);
|
49
114
|
return 0;
|
50
115
|
}
|
51
116
|
|
52
|
-
static int empty_iterator__seek(git_iterator *
|
117
|
+
static int empty_iterator__seek(git_iterator *i, const char *p)
|
53
118
|
{
|
54
|
-
GIT_UNUSED(
|
55
|
-
GIT_UNUSED(prefix);
|
119
|
+
GIT_UNUSED(i); GIT_UNUSED(p);
|
56
120
|
return -1;
|
57
121
|
}
|
58
122
|
|
59
|
-
static
|
123
|
+
static int empty_iterator__reset(git_iterator *i, const char *s, const char *e)
|
60
124
|
{
|
61
|
-
GIT_UNUSED(
|
125
|
+
GIT_UNUSED(i); GIT_UNUSED(s); GIT_UNUSED(e);
|
126
|
+
return 0;
|
62
127
|
}
|
63
128
|
|
64
|
-
int
|
129
|
+
static int empty_iterator__at_end(git_iterator *i)
|
65
130
|
{
|
66
|
-
|
67
|
-
|
131
|
+
GIT_UNUSED(i);
|
132
|
+
return 1;
|
133
|
+
}
|
68
134
|
|
69
|
-
|
70
|
-
|
71
|
-
i
|
72
|
-
|
73
|
-
i->seek = empty_iterator__seek;
|
74
|
-
i->reset = empty_iterator__noop;
|
75
|
-
i->free = empty_iterator__free;
|
135
|
+
static void empty_iterator__free(git_iterator *i)
|
136
|
+
{
|
137
|
+
GIT_UNUSED(i);
|
138
|
+
}
|
76
139
|
|
77
|
-
|
140
|
+
typedef struct {
|
141
|
+
git_iterator base;
|
142
|
+
git_iterator_callbacks cb;
|
143
|
+
} empty_iterator;
|
78
144
|
|
145
|
+
int git_iterator_for_nothing(
|
146
|
+
git_iterator **iter,
|
147
|
+
git_iterator_flag_t flags,
|
148
|
+
const char *start,
|
149
|
+
const char *end)
|
150
|
+
{
|
151
|
+
empty_iterator *i;
|
152
|
+
|
153
|
+
#define empty_iterator__current empty_iterator__noop
|
154
|
+
#define empty_iterator__advance empty_iterator__noop
|
155
|
+
#define empty_iterator__advance_into empty_iterator__noop
|
156
|
+
|
157
|
+
ITERATOR_BASE_INIT(i, empty, EMPTY, NULL);
|
158
|
+
|
159
|
+
if ((flags & GIT_ITERATOR_IGNORE_CASE) != 0)
|
160
|
+
i->base.flags |= GIT_ITERATOR_IGNORE_CASE;
|
161
|
+
|
162
|
+
*iter = (git_iterator *)i;
|
79
163
|
return 0;
|
80
164
|
}
|
81
165
|
|
82
166
|
|
167
|
+
typedef struct tree_iterator_entry tree_iterator_entry;
|
168
|
+
struct tree_iterator_entry {
|
169
|
+
tree_iterator_entry *parent;
|
170
|
+
const git_tree_entry *te;
|
171
|
+
git_tree *tree;
|
172
|
+
};
|
173
|
+
|
83
174
|
typedef struct tree_iterator_frame tree_iterator_frame;
|
84
175
|
struct tree_iterator_frame {
|
85
|
-
tree_iterator_frame *
|
86
|
-
|
87
|
-
|
88
|
-
|
176
|
+
tree_iterator_frame *up, *down;
|
177
|
+
|
178
|
+
size_t n_entries; /* items in this frame */
|
179
|
+
size_t current; /* start of currently active range in frame */
|
180
|
+
size_t next; /* start of next range in frame */
|
181
|
+
|
182
|
+
const char *start;
|
183
|
+
size_t startlen;
|
184
|
+
|
185
|
+
tree_iterator_entry *entries[GIT_FLEX_ARRAY];
|
89
186
|
};
|
90
187
|
|
91
188
|
typedef struct {
|
92
189
|
git_iterator base;
|
93
|
-
|
94
|
-
tree_iterator_frame *
|
190
|
+
git_iterator_callbacks cb;
|
191
|
+
tree_iterator_frame *head, *root;
|
192
|
+
git_pool pool;
|
95
193
|
git_index_entry entry;
|
96
194
|
git_buf path;
|
195
|
+
int path_ambiguities;
|
97
196
|
bool path_has_filename;
|
197
|
+
int (*strncomp)(const char *a, const char *b, size_t sz);
|
98
198
|
} tree_iterator;
|
99
199
|
|
100
|
-
static const git_tree_entry *tree_iterator__tree_entry(tree_iterator *ti)
|
101
|
-
{
|
102
|
-
return (ti->stack == NULL) ? NULL :
|
103
|
-
git_tree_entry_byindex(ti->stack->tree, ti->stack->index);
|
104
|
-
}
|
105
|
-
|
106
200
|
static char *tree_iterator__current_filename(
|
107
201
|
tree_iterator *ti, const git_tree_entry *te)
|
108
202
|
{
|
109
203
|
if (!ti->path_has_filename) {
|
110
204
|
if (git_buf_joinpath(&ti->path, ti->path.ptr, te->filename) < 0)
|
111
205
|
return NULL;
|
206
|
+
|
207
|
+
if (git_tree_entry__is_tree(te) && git_buf_putc(&ti->path, '/') < 0)
|
208
|
+
return NULL;
|
209
|
+
|
112
210
|
ti->path_has_filename = true;
|
113
211
|
}
|
114
212
|
|
115
213
|
return ti->path.ptr;
|
116
214
|
}
|
117
215
|
|
118
|
-
static void
|
216
|
+
static void tree_iterator__rewrite_filename(tree_iterator *ti)
|
119
217
|
{
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
218
|
+
tree_iterator_entry *scan = ti->head->entries[ti->head->current];
|
219
|
+
ssize_t strpos = ti->path.size;
|
220
|
+
const git_tree_entry *te;
|
221
|
+
|
222
|
+
if (strpos && ti->path.ptr[strpos - 1] == '/')
|
223
|
+
strpos--;
|
224
|
+
|
225
|
+
for (; scan && (te = scan->te); scan = scan->parent) {
|
226
|
+
strpos -= te->filename_len;
|
227
|
+
memcpy(&ti->path.ptr[strpos], te->filename, te->filename_len);
|
228
|
+
strpos -= 1; /* separator */
|
125
229
|
}
|
126
|
-
git__free(tf);
|
127
230
|
}
|
128
231
|
|
129
|
-
static int
|
232
|
+
static int tree_iterator__te_cmp(
|
233
|
+
const git_tree_entry *a,
|
234
|
+
const git_tree_entry *b,
|
235
|
+
int (*compare)(const char *, const char *, size_t))
|
236
|
+
{
|
237
|
+
return git_path_cmp(
|
238
|
+
a->filename, a->filename_len, a->attr == GIT_FILEMODE_TREE,
|
239
|
+
b->filename, b->filename_len, b->attr == GIT_FILEMODE_TREE,
|
240
|
+
compare);
|
241
|
+
}
|
242
|
+
|
243
|
+
static int tree_iterator__ci_cmp(const void *a, const void *b, void *p)
|
244
|
+
{
|
245
|
+
const tree_iterator_entry *ae = a, *be = b;
|
246
|
+
int cmp = tree_iterator__te_cmp(ae->te, be->te, git__strncasecmp);
|
247
|
+
|
248
|
+
if (!cmp) {
|
249
|
+
/* stabilize sort order among equivalent names */
|
250
|
+
if (!ae->parent->te || !be->parent->te)
|
251
|
+
cmp = tree_iterator__te_cmp(ae->te, be->te, git__strncmp);
|
252
|
+
else
|
253
|
+
cmp = tree_iterator__ci_cmp(ae->parent, be->parent, p);
|
254
|
+
}
|
255
|
+
|
256
|
+
return cmp;
|
257
|
+
}
|
258
|
+
|
259
|
+
static int tree_iterator__search_cmp(const void *key, const void *val, void *p)
|
260
|
+
{
|
261
|
+
const tree_iterator_frame *tf = key;
|
262
|
+
const git_tree_entry *te = ((tree_iterator_entry *)val)->te;
|
263
|
+
|
264
|
+
return git_path_cmp(
|
265
|
+
tf->start, tf->startlen, false,
|
266
|
+
te->filename, te->filename_len, te->attr == GIT_FILEMODE_TREE,
|
267
|
+
((tree_iterator *)p)->strncomp);
|
268
|
+
}
|
269
|
+
|
270
|
+
static int tree_iterator__set_next(tree_iterator *ti, tree_iterator_frame *tf)
|
130
271
|
{
|
131
|
-
|
132
|
-
|
272
|
+
int error;
|
273
|
+
const git_tree_entry *te, *last = NULL;
|
274
|
+
|
275
|
+
tf->next = tf->current;
|
133
276
|
|
134
|
-
|
135
|
-
|
277
|
+
for (; tf->next < tf->n_entries; tf->next++, last = te) {
|
278
|
+
te = tf->entries[tf->next]->te;
|
279
|
+
|
280
|
+
if (last && tree_iterator__te_cmp(last, te, ti->strncomp))
|
281
|
+
break;
|
282
|
+
|
283
|
+
/* load trees for items in [current,next) range */
|
284
|
+
if (git_tree_entry__is_tree(te) &&
|
285
|
+
(error = git_tree_lookup(
|
286
|
+
&tf->entries[tf->next]->tree, ti->base.repo, &te->oid)) < 0)
|
287
|
+
return error;
|
288
|
+
}
|
289
|
+
|
290
|
+
if (tf->next > tf->current + 1)
|
291
|
+
ti->path_ambiguities++;
|
292
|
+
|
293
|
+
if (last && !tree_iterator__current_filename(ti, last))
|
294
|
+
return -1;
|
136
295
|
|
137
296
|
return 0;
|
138
297
|
}
|
139
298
|
|
140
|
-
|
141
|
-
git_iterator *self, const git_index_entry **entry)
|
299
|
+
GIT_INLINE(bool) tree_iterator__at_tree(tree_iterator *ti)
|
142
300
|
{
|
143
|
-
|
144
|
-
|
301
|
+
return (ti->head->current < ti->head->n_entries &&
|
302
|
+
ti->head->entries[ti->head->current]->tree != NULL);
|
303
|
+
}
|
145
304
|
|
146
|
-
|
147
|
-
|
305
|
+
static int tree_iterator__push_frame(tree_iterator *ti)
|
306
|
+
{
|
307
|
+
int error = 0;
|
308
|
+
tree_iterator_frame *head = ti->head, *tf = NULL;
|
309
|
+
size_t i, n_entries = 0;
|
148
310
|
|
149
|
-
if (
|
311
|
+
if (head->current >= head->n_entries || !head->entries[head->current]->tree)
|
150
312
|
return 0;
|
151
313
|
|
152
|
-
|
153
|
-
|
314
|
+
for (i = head->current; i < head->next; ++i)
|
315
|
+
n_entries += git_tree_entrycount(head->entries[i]->tree);
|
154
316
|
|
155
|
-
|
156
|
-
|
157
|
-
|
317
|
+
tf = git__calloc(sizeof(tree_iterator_frame) +
|
318
|
+
n_entries * sizeof(tree_iterator_entry *), 1);
|
319
|
+
GITERR_CHECK_ALLOC(tf);
|
158
320
|
|
159
|
-
|
160
|
-
return tree_iterator__to_end(ti);
|
321
|
+
tf->n_entries = n_entries;
|
161
322
|
|
162
|
-
|
163
|
-
|
323
|
+
tf->up = head;
|
324
|
+
head->down = tf;
|
325
|
+
ti->head = tf;
|
326
|
+
|
327
|
+
for (i = head->current, n_entries = 0; i < head->next; ++i) {
|
328
|
+
git_tree *tree = head->entries[i]->tree;
|
329
|
+
size_t j, max_j = git_tree_entrycount(tree);
|
330
|
+
|
331
|
+
for (j = 0; j < max_j; ++j) {
|
332
|
+
tree_iterator_entry *entry = git_pool_malloc(&ti->pool, 1);
|
333
|
+
GITERR_CHECK_ALLOC(entry);
|
334
|
+
|
335
|
+
entry->parent = head->entries[i];
|
336
|
+
entry->te = git_tree_entry_byindex(tree, j);
|
337
|
+
entry->tree = NULL;
|
338
|
+
|
339
|
+
tf->entries[n_entries++] = entry;
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
/* if ignore_case, sort entries case insensitively */
|
344
|
+
if (iterator__ignore_case(ti))
|
345
|
+
git__tsort_r(
|
346
|
+
(void **)tf->entries, tf->n_entries, tree_iterator__ci_cmp, tf);
|
347
|
+
|
348
|
+
/* pick tf->current based on "start" (or start at zero) */
|
349
|
+
if (head->startlen > 0) {
|
350
|
+
git__bsearch_r((void **)tf->entries, tf->n_entries, head,
|
351
|
+
tree_iterator__search_cmp, ti, &tf->current);
|
352
|
+
|
353
|
+
while (tf->current &&
|
354
|
+
!tree_iterator__search_cmp(head, tf->entries[tf->current-1], ti))
|
355
|
+
tf->current--;
|
356
|
+
|
357
|
+
if ((tf->start = strchr(head->start, '/')) != NULL) {
|
358
|
+
tf->start++;
|
359
|
+
tf->startlen = strlen(tf->start);
|
360
|
+
}
|
361
|
+
}
|
362
|
+
|
363
|
+
ti->path_has_filename = false;
|
364
|
+
|
365
|
+
if ((error = tree_iterator__set_next(ti, tf)) < 0)
|
366
|
+
return error;
|
367
|
+
|
368
|
+
/* autoexpand as needed */
|
369
|
+
if (!iterator__include_trees(ti) && tree_iterator__at_tree(ti))
|
370
|
+
return tree_iterator__push_frame(ti);
|
164
371
|
|
165
372
|
return 0;
|
166
373
|
}
|
167
374
|
|
168
|
-
static
|
375
|
+
static bool tree_iterator__move_to_next(
|
376
|
+
tree_iterator *ti, tree_iterator_frame *tf)
|
169
377
|
{
|
170
|
-
|
378
|
+
if (tf->next > tf->current + 1)
|
379
|
+
ti->path_ambiguities--;
|
380
|
+
|
381
|
+
if (!tf->up) { /* at root */
|
382
|
+
tf->current = tf->next;
|
383
|
+
return false;
|
384
|
+
}
|
385
|
+
|
386
|
+
for (; tf->current < tf->next; tf->current++) {
|
387
|
+
git_tree_free(tf->entries[tf->current]->tree);
|
388
|
+
tf->entries[tf->current]->tree = NULL;
|
389
|
+
}
|
390
|
+
|
391
|
+
return (tf->current < tf->n_entries);
|
171
392
|
}
|
172
393
|
|
173
|
-
static
|
174
|
-
git_tree *tree, char *start)
|
394
|
+
static bool tree_iterator__pop_frame(tree_iterator *ti, bool final)
|
175
395
|
{
|
176
|
-
tree_iterator_frame *tf =
|
177
|
-
if (!tf)
|
178
|
-
return NULL;
|
396
|
+
tree_iterator_frame *tf = ti->head;
|
179
397
|
|
180
|
-
tf->
|
398
|
+
if (!tf->up)
|
399
|
+
return false;
|
181
400
|
|
182
|
-
|
183
|
-
|
184
|
-
|
401
|
+
ti->head = tf->up;
|
402
|
+
ti->head->down = NULL;
|
403
|
+
|
404
|
+
tree_iterator__move_to_next(ti, tf);
|
405
|
+
|
406
|
+
if (!final) { /* if final, don't bother to clean up */
|
407
|
+
git_pool_free_array(&ti->pool, tf->n_entries, (void **)tf->entries);
|
408
|
+
git_buf_rtruncate_at_char(&ti->path, '/');
|
185
409
|
}
|
186
410
|
|
187
|
-
|
411
|
+
git__free(tf);
|
412
|
+
|
413
|
+
return true;
|
188
414
|
}
|
189
415
|
|
190
|
-
static int
|
416
|
+
static int tree_iterator__pop_all(tree_iterator *ti, bool to_end, bool final)
|
191
417
|
{
|
192
|
-
|
193
|
-
git_tree *subtree;
|
194
|
-
const git_tree_entry *te = tree_iterator__tree_entry(ti);
|
195
|
-
tree_iterator_frame *tf;
|
196
|
-
char *relpath;
|
418
|
+
while (tree_iterator__pop_frame(ti, final)) /* pop to root */;
|
197
419
|
|
198
|
-
|
199
|
-
|
200
|
-
|
420
|
+
if (!final) {
|
421
|
+
ti->head->current = to_end ? ti->head->n_entries : 0;
|
422
|
+
ti->path_ambiguities = 0;
|
423
|
+
git_buf_clear(&ti->path);
|
424
|
+
}
|
201
425
|
|
202
|
-
|
203
|
-
|
204
|
-
git__prefixcmp(ti->path.ptr, ti->base.end) > 0)
|
205
|
-
return tree_iterator__to_end(ti);
|
426
|
+
return 0;
|
427
|
+
}
|
206
428
|
|
207
|
-
|
208
|
-
|
429
|
+
static int tree_iterator__current(
|
430
|
+
const git_index_entry **entry, git_iterator *self)
|
431
|
+
{
|
432
|
+
tree_iterator *ti = (tree_iterator *)self;
|
433
|
+
tree_iterator_frame *tf = ti->head;
|
434
|
+
const git_tree_entry *te;
|
209
435
|
|
210
|
-
|
436
|
+
iterator__clear_entry(entry);
|
211
437
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
{
|
216
|
-
size_t namelen = strlen(te->filename);
|
217
|
-
if (ti->stack->start[namelen] == '/')
|
218
|
-
relpath = ti->stack->start + namelen + 1;
|
219
|
-
}
|
438
|
+
if (tf->current >= tf->n_entries)
|
439
|
+
return 0;
|
440
|
+
te = tf->entries[tf->current]->te;
|
220
441
|
|
221
|
-
|
222
|
-
|
442
|
+
ti->entry.mode = te->attr;
|
443
|
+
git_oid_cpy(&ti->entry.oid, &te->oid);
|
223
444
|
|
224
|
-
|
225
|
-
|
226
|
-
tf->next->prev = tf;
|
445
|
+
ti->entry.path = tree_iterator__current_filename(ti, te);
|
446
|
+
GITERR_CHECK_ALLOC(ti->entry.path);
|
227
447
|
|
228
|
-
|
229
|
-
|
448
|
+
if (ti->path_ambiguities > 0)
|
449
|
+
tree_iterator__rewrite_filename(ti);
|
450
|
+
|
451
|
+
if (iterator__past_end(ti, ti->entry.path))
|
452
|
+
return tree_iterator__pop_all(ti, true, false);
|
453
|
+
|
454
|
+
if (entry)
|
455
|
+
*entry = &ti->entry;
|
230
456
|
|
231
457
|
return 0;
|
232
458
|
}
|
233
459
|
|
234
|
-
static int
|
235
|
-
|
460
|
+
static int tree_iterator__advance_into(
|
461
|
+
const git_index_entry **entry, git_iterator *self)
|
236
462
|
{
|
237
463
|
int error = 0;
|
238
464
|
tree_iterator *ti = (tree_iterator *)self;
|
239
|
-
const git_tree_entry *te = NULL;
|
240
465
|
|
241
|
-
|
242
|
-
*entry = NULL;
|
466
|
+
iterator__clear_entry(entry);
|
243
467
|
|
244
|
-
if (ti
|
245
|
-
|
246
|
-
|
247
|
-
}
|
468
|
+
if (tree_iterator__at_tree(ti) &&
|
469
|
+
!(error = tree_iterator__push_frame(ti)))
|
470
|
+
error = tree_iterator__current(entry, self);
|
248
471
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
472
|
+
return error;
|
473
|
+
}
|
474
|
+
|
475
|
+
static int tree_iterator__advance(
|
476
|
+
const git_index_entry **entry, git_iterator *self)
|
477
|
+
{
|
478
|
+
int error;
|
479
|
+
tree_iterator *ti = (tree_iterator *)self;
|
480
|
+
tree_iterator_frame *tf = ti->head;
|
481
|
+
|
482
|
+
iterator__clear_entry(entry);
|
483
|
+
|
484
|
+
if (tf->current > tf->n_entries)
|
485
|
+
return 0;
|
253
486
|
|
254
|
-
|
487
|
+
if (iterator__do_autoexpand(ti) && iterator__include_trees(ti) &&
|
488
|
+
tree_iterator__at_tree(ti))
|
489
|
+
return tree_iterator__advance_into(entry, self);
|
255
490
|
|
491
|
+
if (ti->path_has_filename) {
|
256
492
|
git_buf_rtruncate_at_char(&ti->path, '/');
|
493
|
+
ti->path_has_filename = false;
|
257
494
|
}
|
258
495
|
|
259
|
-
|
260
|
-
|
496
|
+
/* scan forward and up, advancing in frame or popping frame when done */
|
497
|
+
while (!tree_iterator__move_to_next(ti, tf) &&
|
498
|
+
tree_iterator__pop_frame(ti, false))
|
499
|
+
tf = ti->head;
|
261
500
|
|
262
|
-
|
263
|
-
|
501
|
+
/* find next and load trees */
|
502
|
+
if ((error = tree_iterator__set_next(ti, tf)) < 0)
|
503
|
+
return error;
|
264
504
|
|
265
|
-
|
505
|
+
/* deal with include_trees / auto_expand as needed */
|
506
|
+
if (!iterator__include_trees(ti) && tree_iterator__at_tree(ti))
|
507
|
+
return tree_iterator__advance_into(entry, self);
|
508
|
+
|
509
|
+
return tree_iterator__current(entry, self);
|
266
510
|
}
|
267
511
|
|
268
512
|
static int tree_iterator__seek(git_iterator *self, const char *prefix)
|
269
513
|
{
|
270
|
-
GIT_UNUSED(self);
|
271
|
-
GIT_UNUSED(prefix);
|
272
|
-
/* pop stack until matches prefix */
|
273
|
-
/* seek item in current frame matching prefix */
|
274
|
-
/* push stack which matches prefix */
|
514
|
+
GIT_UNUSED(self); GIT_UNUSED(prefix);
|
275
515
|
return -1;
|
276
516
|
}
|
277
517
|
|
278
|
-
static
|
518
|
+
static int tree_iterator__reset(
|
519
|
+
git_iterator *self, const char *start, const char *end)
|
279
520
|
{
|
280
521
|
tree_iterator *ti = (tree_iterator *)self;
|
281
|
-
|
282
|
-
|
283
|
-
|
522
|
+
|
523
|
+
tree_iterator__pop_all(ti, false, false);
|
524
|
+
|
525
|
+
if (iterator__reset_range(self, start, end) < 0)
|
526
|
+
return -1;
|
527
|
+
|
528
|
+
return tree_iterator__push_frame(ti); /* re-expand root tree */
|
284
529
|
}
|
285
530
|
|
286
|
-
static int
|
531
|
+
static int tree_iterator__at_end(git_iterator *self)
|
287
532
|
{
|
288
533
|
tree_iterator *ti = (tree_iterator *)self;
|
534
|
+
return (ti->head->current >= ti->head->n_entries);
|
535
|
+
}
|
289
536
|
|
290
|
-
|
291
|
-
|
537
|
+
static void tree_iterator__free(git_iterator *self)
|
538
|
+
{
|
539
|
+
tree_iterator *ti = (tree_iterator *)self;
|
292
540
|
|
293
|
-
|
294
|
-
ti->stack->index =
|
295
|
-
git_tree__prefix_position(ti->stack->tree, ti->base.start);
|
541
|
+
tree_iterator__pop_all(ti, true, false);
|
296
542
|
|
297
|
-
|
543
|
+
git_tree_free(ti->head->entries[0]->tree);
|
544
|
+
git__free(ti->head);
|
545
|
+
git_pool_clear(&ti->pool);
|
546
|
+
git_buf_free(&ti->path);
|
547
|
+
}
|
298
548
|
|
299
|
-
|
549
|
+
static int tree_iterator__create_root_frame(tree_iterator *ti, git_tree *tree)
|
550
|
+
{
|
551
|
+
size_t sz = sizeof(tree_iterator_frame) + sizeof(tree_iterator_entry);
|
552
|
+
tree_iterator_frame *root = git__calloc(sz, sizeof(char));
|
553
|
+
GITERR_CHECK_ALLOC(root);
|
554
|
+
|
555
|
+
root->n_entries = 1;
|
556
|
+
root->next = 1;
|
557
|
+
root->start = ti->base.start;
|
558
|
+
root->startlen = root->start ? strlen(root->start) : 0;
|
559
|
+
root->entries[0] = git_pool_mallocz(&ti->pool, 1);
|
560
|
+
GITERR_CHECK_ALLOC(root->entries[0]);
|
561
|
+
root->entries[0]->tree = tree;
|
562
|
+
|
563
|
+
ti->head = ti->root = root;
|
564
|
+
|
565
|
+
return 0;
|
300
566
|
}
|
301
567
|
|
302
|
-
int
|
568
|
+
int git_iterator_for_tree(
|
303
569
|
git_iterator **iter,
|
304
|
-
git_repository *repo,
|
305
570
|
git_tree *tree,
|
571
|
+
git_iterator_flag_t flags,
|
306
572
|
const char *start,
|
307
573
|
const char *end)
|
308
574
|
{
|
@@ -310,42 +576,124 @@ int git_iterator_for_tree_range(
|
|
310
576
|
tree_iterator *ti;
|
311
577
|
|
312
578
|
if (tree == NULL)
|
313
|
-
return git_iterator_for_nothing(iter);
|
579
|
+
return git_iterator_for_nothing(iter, flags, start, end);
|
314
580
|
|
315
|
-
|
581
|
+
if ((error = git_object_dup((git_object **)&tree, (git_object *)tree)) < 0)
|
582
|
+
return error;
|
316
583
|
|
317
|
-
ti
|
318
|
-
ti->stack = ti->tail = tree_iterator__alloc_frame(tree, ti->base.start);
|
584
|
+
ITERATOR_BASE_INIT(ti, tree, TREE, git_tree_owner(tree));
|
319
585
|
|
320
|
-
if ((error =
|
321
|
-
|
322
|
-
|
323
|
-
*iter = (git_iterator *)ti;
|
586
|
+
if ((error = iterator__update_ignore_case((git_iterator *)ti, flags)) < 0)
|
587
|
+
goto fail;
|
588
|
+
ti->strncomp = iterator__ignore_case(ti) ? git__strncasecmp : git__strncmp;
|
324
589
|
|
590
|
+
if ((error = git_pool_init(&ti->pool, sizeof(tree_iterator_entry),0)) < 0 ||
|
591
|
+
(error = tree_iterator__create_root_frame(ti, tree)) < 0 ||
|
592
|
+
(error = tree_iterator__push_frame(ti)) < 0) /* expand root now */
|
593
|
+
goto fail;
|
594
|
+
|
595
|
+
*iter = (git_iterator *)ti;
|
596
|
+
return 0;
|
597
|
+
|
598
|
+
fail:
|
599
|
+
git_iterator_free((git_iterator *)ti);
|
325
600
|
return error;
|
326
601
|
}
|
327
602
|
|
328
603
|
|
329
604
|
typedef struct {
|
330
605
|
git_iterator base;
|
606
|
+
git_iterator_callbacks cb;
|
331
607
|
git_index *index;
|
332
|
-
|
608
|
+
size_t current;
|
609
|
+
/* when not in autoexpand mode, use these to represent "tree" state */
|
610
|
+
git_buf partial;
|
611
|
+
size_t partial_pos;
|
612
|
+
char restore_terminator;
|
613
|
+
git_index_entry tree_entry;
|
333
614
|
} index_iterator;
|
334
615
|
|
335
|
-
static
|
336
|
-
git_iterator *self, const git_index_entry **entry)
|
616
|
+
static const git_index_entry *index_iterator__index_entry(index_iterator *ii)
|
337
617
|
{
|
338
|
-
|
339
|
-
git_index_entry *ie = git_index_get(ii->index, ii->current);
|
618
|
+
const git_index_entry *ie = git_index_get_byindex(ii->index, ii->current);
|
340
619
|
|
341
|
-
if (ie != NULL &&
|
342
|
-
ii->base.end != NULL &&
|
343
|
-
ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0)
|
344
|
-
{
|
620
|
+
if (ie != NULL && iterator__past_end(ii, ie->path)) {
|
345
621
|
ii->current = git_index_entrycount(ii->index);
|
346
622
|
ie = NULL;
|
347
623
|
}
|
348
624
|
|
625
|
+
return ie;
|
626
|
+
}
|
627
|
+
|
628
|
+
static const git_index_entry *index_iterator__skip_conflicts(index_iterator *ii)
|
629
|
+
{
|
630
|
+
const git_index_entry *ie;
|
631
|
+
|
632
|
+
while ((ie = index_iterator__index_entry(ii)) != NULL &&
|
633
|
+
git_index_entry_stage(ie) != 0)
|
634
|
+
ii->current++;
|
635
|
+
|
636
|
+
return ie;
|
637
|
+
}
|
638
|
+
|
639
|
+
static void index_iterator__next_prefix_tree(index_iterator *ii)
|
640
|
+
{
|
641
|
+
const char *slash;
|
642
|
+
|
643
|
+
if (!iterator__include_trees(ii))
|
644
|
+
return;
|
645
|
+
|
646
|
+
slash = strchr(&ii->partial.ptr[ii->partial_pos], '/');
|
647
|
+
|
648
|
+
if (slash != NULL) {
|
649
|
+
ii->partial_pos = (slash - ii->partial.ptr) + 1;
|
650
|
+
ii->restore_terminator = ii->partial.ptr[ii->partial_pos];
|
651
|
+
ii->partial.ptr[ii->partial_pos] = '\0';
|
652
|
+
} else {
|
653
|
+
ii->partial_pos = ii->partial.size;
|
654
|
+
}
|
655
|
+
|
656
|
+
if (index_iterator__index_entry(ii) == NULL)
|
657
|
+
ii->partial_pos = ii->partial.size;
|
658
|
+
}
|
659
|
+
|
660
|
+
static int index_iterator__first_prefix_tree(index_iterator *ii)
|
661
|
+
{
|
662
|
+
const git_index_entry *ie = index_iterator__skip_conflicts(ii);
|
663
|
+
const char *scan, *prior, *slash;
|
664
|
+
|
665
|
+
if (!ie || !iterator__include_trees(ii))
|
666
|
+
return 0;
|
667
|
+
|
668
|
+
/* find longest common prefix with prior index entry */
|
669
|
+
for (scan = slash = ie->path, prior = ii->partial.ptr;
|
670
|
+
*scan && *scan == *prior; ++scan, ++prior)
|
671
|
+
if (*scan == '/')
|
672
|
+
slash = scan;
|
673
|
+
|
674
|
+
if (git_buf_sets(&ii->partial, ie->path) < 0)
|
675
|
+
return -1;
|
676
|
+
|
677
|
+
ii->partial_pos = (slash - ie->path) + 1;
|
678
|
+
index_iterator__next_prefix_tree(ii);
|
679
|
+
|
680
|
+
return 0;
|
681
|
+
}
|
682
|
+
|
683
|
+
#define index_iterator__at_tree(I) \
|
684
|
+
(iterator__include_trees(I) && (I)->partial_pos < (I)->partial.size)
|
685
|
+
|
686
|
+
static int index_iterator__current(
|
687
|
+
const git_index_entry **entry, git_iterator *self)
|
688
|
+
{
|
689
|
+
index_iterator *ii = (index_iterator *)self;
|
690
|
+
const git_index_entry *ie = git_index_get_byindex(ii->index, ii->current);
|
691
|
+
|
692
|
+
if (ie != NULL && index_iterator__at_tree(ii)) {
|
693
|
+
ii->tree_entry.path = ii->partial.ptr;
|
694
|
+
ie = &ii->tree_entry;
|
695
|
+
}
|
696
|
+
|
349
697
|
if (entry)
|
350
698
|
*entry = ie;
|
351
699
|
|
@@ -359,28 +707,90 @@ static int index_iterator__at_end(git_iterator *self)
|
|
359
707
|
}
|
360
708
|
|
361
709
|
static int index_iterator__advance(
|
362
|
-
|
710
|
+
const git_index_entry **entry, git_iterator *self)
|
363
711
|
{
|
364
712
|
index_iterator *ii = (index_iterator *)self;
|
713
|
+
size_t entrycount = git_index_entrycount(ii->index);
|
714
|
+
const git_index_entry *ie;
|
715
|
+
|
716
|
+
if (index_iterator__at_tree(ii)) {
|
717
|
+
if (iterator__do_autoexpand(ii)) {
|
718
|
+
ii->partial.ptr[ii->partial_pos] = ii->restore_terminator;
|
719
|
+
index_iterator__next_prefix_tree(ii);
|
720
|
+
} else {
|
721
|
+
/* advance to sibling tree (i.e. find entry with new prefix) */
|
722
|
+
while (ii->current < entrycount) {
|
723
|
+
ii->current++;
|
724
|
+
|
725
|
+
if (!(ie = git_index_get_byindex(ii->index, ii->current)) ||
|
726
|
+
ii->base.prefixcomp(ie->path, ii->partial.ptr) != 0)
|
727
|
+
break;
|
728
|
+
}
|
729
|
+
|
730
|
+
if (index_iterator__first_prefix_tree(ii) < 0)
|
731
|
+
return -1;
|
732
|
+
}
|
733
|
+
} else {
|
734
|
+
if (ii->current < entrycount)
|
735
|
+
ii->current++;
|
365
736
|
|
366
|
-
|
367
|
-
|
737
|
+
if (index_iterator__first_prefix_tree(ii) < 0)
|
738
|
+
return -1;
|
739
|
+
}
|
740
|
+
|
741
|
+
return index_iterator__current(entry, self);
|
742
|
+
}
|
743
|
+
|
744
|
+
static int index_iterator__advance_into(
|
745
|
+
const git_index_entry **entry, git_iterator *self)
|
746
|
+
{
|
747
|
+
index_iterator *ii = (index_iterator *)self;
|
748
|
+
const git_index_entry *ie = git_index_get_byindex(ii->index, ii->current);
|
749
|
+
|
750
|
+
if (ie != NULL && index_iterator__at_tree(ii)) {
|
751
|
+
if (ii->restore_terminator)
|
752
|
+
ii->partial.ptr[ii->partial_pos] = ii->restore_terminator;
|
753
|
+
index_iterator__next_prefix_tree(ii);
|
754
|
+
}
|
368
755
|
|
369
|
-
return index_iterator__current(
|
756
|
+
return index_iterator__current(entry, self);
|
370
757
|
}
|
371
758
|
|
372
759
|
static int index_iterator__seek(git_iterator *self, const char *prefix)
|
373
760
|
{
|
374
|
-
GIT_UNUSED(self);
|
375
|
-
GIT_UNUSED(prefix);
|
376
|
-
/* find last item before prefix */
|
761
|
+
GIT_UNUSED(self); GIT_UNUSED(prefix);
|
377
762
|
return -1;
|
378
763
|
}
|
379
764
|
|
380
|
-
static int index_iterator__reset(
|
765
|
+
static int index_iterator__reset(
|
766
|
+
git_iterator *self, const char *start, const char *end)
|
381
767
|
{
|
382
768
|
index_iterator *ii = (index_iterator *)self;
|
383
|
-
|
769
|
+
const git_index_entry *ie;
|
770
|
+
|
771
|
+
if (iterator__reset_range(self, start, end) < 0)
|
772
|
+
return -1;
|
773
|
+
|
774
|
+
ii->current = ii->base.start ?
|
775
|
+
git_index__prefix_position(ii->index, ii->base.start) : 0;
|
776
|
+
|
777
|
+
if ((ie = index_iterator__skip_conflicts(ii)) == NULL)
|
778
|
+
return 0;
|
779
|
+
|
780
|
+
if (git_buf_sets(&ii->partial, ie->path) < 0)
|
781
|
+
return -1;
|
782
|
+
|
783
|
+
ii->partial_pos = 0;
|
784
|
+
|
785
|
+
if (ii->base.start) {
|
786
|
+
size_t startlen = strlen(ii->base.start);
|
787
|
+
|
788
|
+
ii->partial_pos = (startlen > ii->partial.size) ?
|
789
|
+
ii->partial.size : startlen;
|
790
|
+
}
|
791
|
+
|
792
|
+
index_iterator__next_prefix_tree(ii);
|
793
|
+
|
384
794
|
return 0;
|
385
795
|
}
|
386
796
|
|
@@ -389,77 +799,98 @@ static void index_iterator__free(git_iterator *self)
|
|
389
799
|
index_iterator *ii = (index_iterator *)self;
|
390
800
|
git_index_free(ii->index);
|
391
801
|
ii->index = NULL;
|
802
|
+
|
803
|
+
git_buf_free(&ii->partial);
|
392
804
|
}
|
393
805
|
|
394
|
-
int
|
806
|
+
int git_iterator_for_index(
|
395
807
|
git_iterator **iter,
|
396
|
-
|
808
|
+
git_index *index,
|
809
|
+
git_iterator_flag_t flags,
|
397
810
|
const char *start,
|
398
811
|
const char *end)
|
399
812
|
{
|
400
|
-
int error;
|
401
813
|
index_iterator *ii;
|
402
814
|
|
403
|
-
ITERATOR_BASE_INIT(ii, index, INDEX);
|
815
|
+
ITERATOR_BASE_INIT(ii, index, INDEX, git_index_owner(index));
|
404
816
|
|
405
|
-
if (
|
406
|
-
|
407
|
-
|
408
|
-
ii->base.ignore_case = ii->index->ignore_case;
|
409
|
-
ii->current = start ? git_index__prefix_position(ii->index, start) : 0;
|
410
|
-
*iter = (git_iterator *)ii;
|
817
|
+
if (index->ignore_case) {
|
818
|
+
ii->base.flags |= GIT_ITERATOR_IGNORE_CASE;
|
819
|
+
ii->base.prefixcomp = git__prefixcmp_icase;
|
411
820
|
}
|
412
821
|
|
413
|
-
|
822
|
+
ii->index = index;
|
823
|
+
GIT_REFCOUNT_INC(index);
|
824
|
+
|
825
|
+
git_buf_init(&ii->partial, 0);
|
826
|
+
ii->tree_entry.mode = GIT_FILEMODE_TREE;
|
827
|
+
|
828
|
+
index_iterator__reset((git_iterator *)ii, NULL, NULL);
|
829
|
+
|
830
|
+
*iter = (git_iterator *)ii;
|
831
|
+
|
832
|
+
return 0;
|
414
833
|
}
|
415
834
|
|
416
835
|
|
836
|
+
#define WORKDIR_MAX_DEPTH 100
|
837
|
+
|
417
838
|
typedef struct workdir_iterator_frame workdir_iterator_frame;
|
418
839
|
struct workdir_iterator_frame {
|
419
840
|
workdir_iterator_frame *next;
|
420
841
|
git_vector entries;
|
421
|
-
|
422
|
-
char *start;
|
842
|
+
size_t index;
|
423
843
|
};
|
424
844
|
|
425
845
|
typedef struct {
|
426
846
|
git_iterator base;
|
427
|
-
|
428
|
-
size_t root_len;
|
847
|
+
git_iterator_callbacks cb;
|
429
848
|
workdir_iterator_frame *stack;
|
430
849
|
git_ignores ignores;
|
431
850
|
git_index_entry entry;
|
432
851
|
git_buf path;
|
852
|
+
size_t root_len;
|
433
853
|
int is_ignored;
|
854
|
+
int depth;
|
434
855
|
} workdir_iterator;
|
435
856
|
|
436
|
-
|
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)
|
857
|
+
GIT_INLINE(bool) path_is_dotgit(const git_path_with_stat *ps)
|
445
858
|
{
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
859
|
+
if (!ps)
|
860
|
+
return false;
|
861
|
+
else {
|
862
|
+
const char *path = ps->path;
|
863
|
+
size_t len = ps->path_len;
|
864
|
+
|
865
|
+
if (len < 4)
|
866
|
+
return false;
|
867
|
+
if (path[len - 1] == '/')
|
868
|
+
len--;
|
869
|
+
if (tolower(path[len - 1]) != 't' ||
|
870
|
+
tolower(path[len - 2]) != 'i' ||
|
871
|
+
tolower(path[len - 3]) != 'g' ||
|
872
|
+
tolower(path[len - 4]) != '.')
|
873
|
+
return false;
|
874
|
+
return (len == 4 || path[len - 5] == '/');
|
875
|
+
}
|
450
876
|
}
|
451
877
|
|
452
|
-
static workdir_iterator_frame *workdir_iterator__alloc_frame(
|
878
|
+
static workdir_iterator_frame *workdir_iterator__alloc_frame(
|
879
|
+
workdir_iterator *wi)
|
453
880
|
{
|
454
881
|
workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
|
455
|
-
git_vector_cmp entry_compare = CASESELECT(
|
882
|
+
git_vector_cmp entry_compare = CASESELECT(
|
883
|
+
iterator__ignore_case(wi),
|
884
|
+
git_path_with_stat_cmp_icase, git_path_with_stat_cmp);
|
456
885
|
|
457
886
|
if (wf == NULL)
|
458
887
|
return NULL;
|
888
|
+
|
459
889
|
if (git_vector_init(&wf->entries, 0, entry_compare) != 0) {
|
460
890
|
git__free(wf);
|
461
891
|
return NULL;
|
462
892
|
}
|
893
|
+
|
463
894
|
return wf;
|
464
895
|
}
|
465
896
|
|
@@ -476,62 +907,73 @@ static void workdir_iterator__free_frame(workdir_iterator_frame *wf)
|
|
476
907
|
|
477
908
|
static int workdir_iterator__update_entry(workdir_iterator *wi);
|
478
909
|
|
479
|
-
static int
|
910
|
+
static int workdir_iterator__entry_cmp(const void *i, const void *item)
|
480
911
|
{
|
912
|
+
const workdir_iterator *wi = (const workdir_iterator *)i;
|
481
913
|
const git_path_with_stat *ps = item;
|
482
|
-
return
|
914
|
+
return wi->base.prefixcomp(wi->base.start, ps->path);
|
483
915
|
}
|
484
916
|
|
485
|
-
static
|
917
|
+
static void workdir_iterator__seek_frame_start(
|
918
|
+
workdir_iterator *wi, workdir_iterator_frame *wf)
|
486
919
|
{
|
487
|
-
|
488
|
-
|
920
|
+
if (!wf)
|
921
|
+
return;
|
922
|
+
|
923
|
+
if (wi->base.start)
|
924
|
+
git_vector_bsearch2(
|
925
|
+
&wf->index, &wf->entries, workdir_iterator__entry_cmp, wi);
|
926
|
+
else
|
927
|
+
wf->index = 0;
|
928
|
+
|
929
|
+
if (path_is_dotgit(git_vector_get(&wf->entries, wf->index)))
|
930
|
+
wf->index++;
|
489
931
|
}
|
490
932
|
|
491
933
|
static int workdir_iterator__expand_dir(workdir_iterator *wi)
|
492
934
|
{
|
493
935
|
int error;
|
494
|
-
workdir_iterator_frame *wf
|
936
|
+
workdir_iterator_frame *wf;
|
937
|
+
|
938
|
+
wf = workdir_iterator__alloc_frame(wi);
|
495
939
|
GITERR_CHECK_ALLOC(wf);
|
496
940
|
|
497
|
-
error = git_path_dirload_with_stat(
|
941
|
+
error = git_path_dirload_with_stat(
|
942
|
+
wi->path.ptr, wi->root_len, iterator__ignore_case(wi),
|
943
|
+
wi->base.start, wi->base.end, &wf->entries);
|
944
|
+
|
498
945
|
if (error < 0 || wf->entries.length == 0) {
|
499
946
|
workdir_iterator__free_frame(wf);
|
500
947
|
return GIT_ENOTFOUND;
|
501
948
|
}
|
502
949
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
wf
|
507
|
-
|
508
|
-
|
509
|
-
wf->start = wi->stack->start;
|
510
|
-
|
511
|
-
if (wf->start)
|
512
|
-
git_vector_bsearch3(
|
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);
|
950
|
+
if (++(wi->depth) > WORKDIR_MAX_DEPTH) {
|
951
|
+
giterr_set(GITERR_REPOSITORY,
|
952
|
+
"Working directory is too deep (%d)", wi->depth);
|
953
|
+
workdir_iterator__free_frame(wf);
|
954
|
+
return -1;
|
955
|
+
}
|
517
956
|
|
518
|
-
wf
|
519
|
-
wi->stack = wf;
|
957
|
+
workdir_iterator__seek_frame_start(wi, wf);
|
520
958
|
|
521
959
|
/* only push new ignores if this is not top level directory */
|
522
|
-
if (wi->stack
|
960
|
+
if (wi->stack != NULL) {
|
523
961
|
ssize_t slash_pos = git_buf_rfind_next(&wi->path, '/');
|
524
962
|
(void)git_ignore__push_dir(&wi->ignores, &wi->path.ptr[slash_pos + 1]);
|
525
963
|
}
|
526
964
|
|
965
|
+
wf->next = wi->stack;
|
966
|
+
wi->stack = wf;
|
967
|
+
|
527
968
|
return workdir_iterator__update_entry(wi);
|
528
969
|
}
|
529
970
|
|
530
971
|
static int workdir_iterator__current(
|
531
|
-
|
972
|
+
const git_index_entry **entry, git_iterator *self)
|
532
973
|
{
|
533
974
|
workdir_iterator *wi = (workdir_iterator *)self;
|
534
|
-
|
975
|
+
if (entry)
|
976
|
+
*entry = (wi->entry.path == NULL) ? NULL : &wi->entry;
|
535
977
|
return 0;
|
536
978
|
}
|
537
979
|
|
@@ -540,46 +982,83 @@ static int workdir_iterator__at_end(git_iterator *self)
|
|
540
982
|
return (((workdir_iterator *)self)->entry.path == NULL);
|
541
983
|
}
|
542
984
|
|
985
|
+
static int workdir_iterator__advance_into(
|
986
|
+
const git_index_entry **entry, git_iterator *iter)
|
987
|
+
{
|
988
|
+
int error = 0;
|
989
|
+
workdir_iterator *wi = (workdir_iterator *)iter;
|
990
|
+
|
991
|
+
iterator__clear_entry(entry);
|
992
|
+
|
993
|
+
/* workdir iterator will allow you to explicitly advance into a
|
994
|
+
* commit/submodule (as well as a tree) to avoid some cases where an
|
995
|
+
* entry is mislabeled as a submodule in the working directory
|
996
|
+
*/
|
997
|
+
if (wi->entry.path != NULL &&
|
998
|
+
(wi->entry.mode == GIT_FILEMODE_TREE ||
|
999
|
+
wi->entry.mode == GIT_FILEMODE_COMMIT))
|
1000
|
+
/* returns GIT_ENOTFOUND if the directory is empty */
|
1001
|
+
error = workdir_iterator__expand_dir(wi);
|
1002
|
+
|
1003
|
+
if (!error && entry)
|
1004
|
+
error = workdir_iterator__current(entry, iter);
|
1005
|
+
|
1006
|
+
return error;
|
1007
|
+
}
|
1008
|
+
|
543
1009
|
static int workdir_iterator__advance(
|
544
|
-
|
1010
|
+
const git_index_entry **entry, git_iterator *self)
|
545
1011
|
{
|
546
|
-
int error;
|
1012
|
+
int error = 0;
|
547
1013
|
workdir_iterator *wi = (workdir_iterator *)self;
|
548
1014
|
workdir_iterator_frame *wf;
|
549
1015
|
git_path_with_stat *next;
|
550
1016
|
|
1017
|
+
/* given include_trees & autoexpand, we might have to go into a tree */
|
1018
|
+
if (iterator__do_autoexpand(wi) &&
|
1019
|
+
wi->entry.path != NULL &&
|
1020
|
+
wi->entry.mode == GIT_FILEMODE_TREE)
|
1021
|
+
{
|
1022
|
+
error = workdir_iterator__advance_into(entry, self);
|
1023
|
+
|
1024
|
+
/* continue silently past empty directories if autoexpanding */
|
1025
|
+
if (error != GIT_ENOTFOUND)
|
1026
|
+
return error;
|
1027
|
+
giterr_clear();
|
1028
|
+
error = 0;
|
1029
|
+
}
|
1030
|
+
|
551
1031
|
if (entry != NULL)
|
552
1032
|
*entry = NULL;
|
553
1033
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
while ((wf = wi->stack) != NULL) {
|
1034
|
+
while (wi->entry.path != NULL) {
|
1035
|
+
wf = wi->stack;
|
558
1036
|
next = git_vector_get(&wf->entries, ++wf->index);
|
1037
|
+
|
559
1038
|
if (next != NULL) {
|
560
1039
|
/* match git's behavior of ignoring anything named ".git" */
|
561
|
-
if (
|
562
|
-
STRCMP_CASESELECT(wi->base.ignore_case, next->path, DOT_GIT) == 0)
|
1040
|
+
if (path_is_dotgit(next))
|
563
1041
|
continue;
|
564
1042
|
/* else found a good entry */
|
565
1043
|
break;
|
566
1044
|
}
|
567
1045
|
|
568
|
-
/* pop
|
569
|
-
|
570
|
-
workdir_iterator__free_frame(wf);
|
571
|
-
git_ignore__pop_dir(&wi->ignores);
|
572
|
-
|
573
|
-
if (wi->stack == NULL) {
|
1046
|
+
/* pop stack if anything is left to pop */
|
1047
|
+
if (!wf->next) {
|
574
1048
|
memset(&wi->entry, 0, sizeof(wi->entry));
|
575
1049
|
return 0;
|
576
1050
|
}
|
1051
|
+
|
1052
|
+
wi->stack = wf->next;
|
1053
|
+
wi->depth--;
|
1054
|
+
workdir_iterator__free_frame(wf);
|
1055
|
+
git_ignore__pop_dir(&wi->ignores);
|
577
1056
|
}
|
578
1057
|
|
579
1058
|
error = workdir_iterator__update_entry(wi);
|
580
1059
|
|
581
1060
|
if (!error && entry != NULL)
|
582
|
-
error = workdir_iterator__current(
|
1061
|
+
error = workdir_iterator__current(entry, self);
|
583
1062
|
|
584
1063
|
return error;
|
585
1064
|
}
|
@@ -594,18 +1073,25 @@ static int workdir_iterator__seek(git_iterator *self, const char *prefix)
|
|
594
1073
|
return 0;
|
595
1074
|
}
|
596
1075
|
|
597
|
-
static int workdir_iterator__reset(
|
1076
|
+
static int workdir_iterator__reset(
|
1077
|
+
git_iterator *self, const char *start, const char *end)
|
598
1078
|
{
|
599
1079
|
workdir_iterator *wi = (workdir_iterator *)self;
|
1080
|
+
|
600
1081
|
while (wi->stack != NULL && wi->stack->next != NULL) {
|
601
1082
|
workdir_iterator_frame *wf = wi->stack;
|
602
1083
|
wi->stack = wf->next;
|
603
1084
|
workdir_iterator__free_frame(wf);
|
604
1085
|
git_ignore__pop_dir(&wi->ignores);
|
605
1086
|
}
|
606
|
-
|
607
|
-
|
608
|
-
|
1087
|
+
wi->depth = 0;
|
1088
|
+
|
1089
|
+
if (iterator__reset_range(self, start, end) < 0)
|
1090
|
+
return -1;
|
1091
|
+
|
1092
|
+
workdir_iterator__seek_frame_start(wi, wi->stack);
|
1093
|
+
|
1094
|
+
return workdir_iterator__update_entry(wi);
|
609
1095
|
}
|
610
1096
|
|
611
1097
|
static void workdir_iterator__free(git_iterator *self)
|
@@ -624,7 +1110,9 @@ static void workdir_iterator__free(git_iterator *self)
|
|
624
1110
|
|
625
1111
|
static int workdir_iterator__update_entry(workdir_iterator *wi)
|
626
1112
|
{
|
627
|
-
|
1113
|
+
int error = 0;
|
1114
|
+
git_path_with_stat *ps =
|
1115
|
+
git_vector_get(&wi->stack->entries, wi->stack->index);
|
628
1116
|
|
629
1117
|
git_buf_truncate(&wi->path, wi->root_len);
|
630
1118
|
memset(&wi->entry, 0, sizeof(wi->entry));
|
@@ -632,84 +1120,78 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
|
|
632
1120
|
if (!ps)
|
633
1121
|
return 0;
|
634
1122
|
|
1123
|
+
/* skip over .git entries */
|
1124
|
+
if (path_is_dotgit(ps))
|
1125
|
+
return workdir_iterator__advance(NULL, (git_iterator *)wi);
|
1126
|
+
|
635
1127
|
if (git_buf_put(&wi->path, ps->path, ps->path_len) < 0)
|
636
1128
|
return -1;
|
637
1129
|
|
638
|
-
if (wi->
|
639
|
-
ITERATOR_PREFIXCMP(wi->base, wi->path.ptr + wi->root_len, wi->base.end) > 0)
|
1130
|
+
if (iterator__past_end(wi, wi->path.ptr + wi->root_len))
|
640
1131
|
return 0;
|
641
1132
|
|
642
1133
|
wi->entry.path = ps->path;
|
643
1134
|
|
644
|
-
|
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)
|
647
|
-
return workdir_iterator__advance((git_iterator *)wi, NULL);
|
648
|
-
|
649
|
-
/* if there is an error processing the entry, treat as ignored */
|
650
|
-
wi->is_ignored = 1;
|
1135
|
+
wi->is_ignored = -1;
|
651
1136
|
|
652
|
-
|
1137
|
+
git_index_entry__init_from_stat(&wi->entry, &ps->st);
|
653
1138
|
|
654
1139
|
/* need different mode here to keep directories during iteration */
|
655
1140
|
wi->entry.mode = git_futils_canonical_mode(ps->st.st_mode);
|
656
1141
|
|
657
1142
|
/* if this is a file type we don't handle, treat as ignored */
|
658
|
-
if (wi->entry.mode == 0)
|
1143
|
+
if (wi->entry.mode == 0) {
|
1144
|
+
wi->is_ignored = 1;
|
659
1145
|
return 0;
|
1146
|
+
}
|
660
1147
|
|
661
|
-
/*
|
662
|
-
if (
|
663
|
-
return 0;
|
1148
|
+
/* if this isn't a tree, then we're done */
|
1149
|
+
if (wi->entry.mode != GIT_FILEMODE_TREE)
|
1150
|
+
return 0;
|
664
1151
|
|
665
1152
|
/* detect submodules */
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
1153
|
+
error = git_submodule_lookup(NULL, wi->base.repo, wi->entry.path);
|
1154
|
+
if (error == GIT_ENOTFOUND)
|
1155
|
+
giterr_clear();
|
1156
|
+
|
1157
|
+
if (error == GIT_EEXISTS) /* if contains .git, treat as untracked submod */
|
1158
|
+
error = 0;
|
1159
|
+
|
1160
|
+
/* if submodule, mark as GITLINK and remove trailing slash */
|
1161
|
+
if (!error) {
|
1162
|
+
size_t len = strlen(wi->entry.path);
|
1163
|
+
assert(wi->entry.path[len - 1] == '/');
|
1164
|
+
wi->entry.path[len - 1] = '\0';
|
1165
|
+
wi->entry.mode = S_IFGITLINK;
|
1166
|
+
return 0;
|
679
1167
|
}
|
680
1168
|
|
681
|
-
|
1169
|
+
if (iterator__include_trees(wi))
|
1170
|
+
return 0;
|
1171
|
+
|
1172
|
+
return workdir_iterator__advance(NULL, (git_iterator *)wi);
|
682
1173
|
}
|
683
1174
|
|
684
|
-
int
|
1175
|
+
int git_iterator_for_workdir(
|
685
1176
|
git_iterator **iter,
|
686
1177
|
git_repository *repo,
|
1178
|
+
git_iterator_flag_t flags,
|
687
1179
|
const char *start,
|
688
1180
|
const char *end)
|
689
1181
|
{
|
690
1182
|
int error;
|
691
1183
|
workdir_iterator *wi;
|
692
|
-
git_index *index;
|
693
1184
|
|
694
1185
|
assert(iter && repo);
|
695
1186
|
|
696
|
-
if ((error = git_repository__ensure_not_bare(
|
1187
|
+
if ((error = git_repository__ensure_not_bare(
|
1188
|
+
repo, "scan working directory")) < 0)
|
697
1189
|
return error;
|
698
1190
|
|
699
|
-
ITERATOR_BASE_INIT(wi, workdir, WORKDIR);
|
1191
|
+
ITERATOR_BASE_INIT(wi, workdir, WORKDIR, repo);
|
700
1192
|
|
701
|
-
|
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);
|
1193
|
+
if ((error = iterator__update_ignore_case((git_iterator *)wi, flags)) < 0)
|
1194
|
+
goto fail;
|
713
1195
|
|
714
1196
|
if (git_buf_sets(&wi->path, git_repository_workdir(repo)) < 0 ||
|
715
1197
|
git_path_to_dir(&wi->path) < 0 ||
|
@@ -718,244 +1200,150 @@ int git_iterator_for_workdir_range(
|
|
718
1200
|
git__free(wi);
|
719
1201
|
return -1;
|
720
1202
|
}
|
721
|
-
|
722
1203
|
wi->root_len = wi->path.size;
|
723
1204
|
|
724
1205
|
if ((error = workdir_iterator__expand_dir(wi)) < 0) {
|
725
|
-
if (error
|
726
|
-
|
727
|
-
|
728
|
-
git_iterator_free((git_iterator *)wi);
|
729
|
-
wi = NULL;
|
730
|
-
}
|
1206
|
+
if (error != GIT_ENOTFOUND)
|
1207
|
+
goto fail;
|
1208
|
+
giterr_clear();
|
731
1209
|
}
|
732
1210
|
|
733
1211
|
*iter = (git_iterator *)wi;
|
1212
|
+
return 0;
|
734
1213
|
|
1214
|
+
fail:
|
1215
|
+
git_iterator_free((git_iterator *)wi);
|
735
1216
|
return error;
|
736
1217
|
}
|
737
1218
|
|
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
1219
|
|
761
|
-
|
1220
|
+
void git_iterator_free(git_iterator *iter)
|
762
1221
|
{
|
763
|
-
|
1222
|
+
if (iter == NULL)
|
1223
|
+
return;
|
764
1224
|
|
765
|
-
|
766
|
-
}
|
1225
|
+
iter->cb->free(iter);
|
767
1226
|
|
768
|
-
|
769
|
-
|
770
|
-
{
|
771
|
-
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
1227
|
+
git__free(iter->start);
|
1228
|
+
git__free(iter->end);
|
772
1229
|
|
773
|
-
|
774
|
-
*entry = (const git_index_entry *)git_vector_get_const(&si->entries, ++si->position);
|
775
|
-
else
|
776
|
-
*entry = NULL;
|
1230
|
+
memset(iter, 0, sizeof(*iter));
|
777
1231
|
|
778
|
-
|
1232
|
+
git__free(iter);
|
779
1233
|
}
|
780
1234
|
|
781
|
-
|
1235
|
+
int git_iterator_set_ignore_case(git_iterator *iter, bool ignore_case)
|
782
1236
|
{
|
783
|
-
|
784
|
-
GIT_UNUSED(prefix);
|
785
|
-
|
786
|
-
return -1;
|
787
|
-
}
|
1237
|
+
bool desire_ignore_case = (ignore_case != 0);
|
788
1238
|
|
789
|
-
|
790
|
-
|
791
|
-
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
1239
|
+
if (iterator__ignore_case(iter) == desire_ignore_case)
|
1240
|
+
return 0;
|
792
1241
|
|
793
|
-
|
1242
|
+
if (iter->type == GIT_ITERATOR_TYPE_EMPTY) {
|
1243
|
+
if (desire_ignore_case)
|
1244
|
+
iter->flags |= GIT_ITERATOR_IGNORE_CASE;
|
1245
|
+
else
|
1246
|
+
iter->flags &= ~GIT_ITERATOR_IGNORE_CASE;
|
1247
|
+
} else {
|
1248
|
+
giterr_set(GITERR_INVALID,
|
1249
|
+
"Cannot currently set ignore case on non-empty iterators");
|
1250
|
+
return -1;
|
1251
|
+
}
|
794
1252
|
|
795
1253
|
return 0;
|
796
1254
|
}
|
797
1255
|
|
798
|
-
|
1256
|
+
git_index *git_iterator_get_index(git_iterator *iter)
|
799
1257
|
{
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
git_pool_clear(&si->entry_pool);
|
804
|
-
git_vector_free(&si->entries);
|
805
|
-
git_iterator_free(si->wrapped);
|
1258
|
+
if (iter->type == GIT_ITERATOR_TYPE_INDEX)
|
1259
|
+
return ((index_iterator *)iter)->index;
|
1260
|
+
return NULL;
|
806
1261
|
}
|
807
1262
|
|
808
|
-
int
|
809
|
-
git_iterator
|
810
|
-
git_iterator *towrap,
|
811
|
-
git_vector_cmp comparer,
|
812
|
-
bool ignore_case,
|
813
|
-
const char *start,
|
814
|
-
const char *end)
|
1263
|
+
int git_iterator_current_tree_entry(
|
1264
|
+
const git_tree_entry **tree_entry, git_iterator *iter)
|
815
1265
|
{
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
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
|
-
}
|
1266
|
+
if (iter->type != GIT_ITERATOR_TYPE_TREE)
|
1267
|
+
*tree_entry = NULL;
|
1268
|
+
else {
|
1269
|
+
tree_iterator_frame *tf = ((tree_iterator *)iter)->head;
|
1270
|
+
*tree_entry = (tf->current < tf->n_entries) ?
|
1271
|
+
tf->entries[tf->current]->te : NULL;
|
853
1272
|
}
|
854
1273
|
|
855
|
-
git_vector_sort(&si->entries);
|
856
|
-
|
857
|
-
*iter = (git_iterator *)si;
|
858
|
-
|
859
|
-
return 0;
|
860
|
-
}
|
861
|
-
|
862
|
-
int git_iterator_current_tree_entry(
|
863
|
-
git_iterator *iter, const git_tree_entry **tree_entry)
|
864
|
-
{
|
865
|
-
*tree_entry = (iter->type != GIT_ITERATOR_TREE) ? NULL :
|
866
|
-
tree_iterator__tree_entry((tree_iterator *)iter);
|
867
1274
|
return 0;
|
868
1275
|
}
|
869
1276
|
|
870
1277
|
int git_iterator_current_parent_tree(
|
1278
|
+
const git_tree **tree_ptr,
|
871
1279
|
git_iterator *iter,
|
872
|
-
const char *parent_path
|
873
|
-
const git_tree **tree_ptr)
|
1280
|
+
const char *parent_path)
|
874
1281
|
{
|
875
1282
|
tree_iterator *ti = (tree_iterator *)iter;
|
876
1283
|
tree_iterator_frame *tf;
|
877
1284
|
const char *scan = parent_path;
|
1285
|
+
const git_tree_entry *te;
|
878
1286
|
|
879
|
-
|
880
|
-
goto notfound;
|
1287
|
+
*tree_ptr = NULL;
|
881
1288
|
|
882
|
-
|
883
|
-
|
1289
|
+
if (iter->type != GIT_ITERATOR_TYPE_TREE)
|
1290
|
+
return 0;
|
884
1291
|
|
885
|
-
|
886
|
-
|
1292
|
+
for (tf = ti->root; *scan; ) {
|
1293
|
+
if (!(tf = tf->down) ||
|
1294
|
+
tf->current >= tf->n_entries ||
|
1295
|
+
!(te = tf->entries[tf->current]->te) ||
|
1296
|
+
ti->strncomp(scan, te->filename, te->filename_len) != 0)
|
887
1297
|
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
1298
|
|
895
1299
|
scan += te->filename_len;
|
896
|
-
|
897
|
-
if (*scan) {
|
898
|
-
if (*scan != '/')
|
899
|
-
goto notfound;
|
1300
|
+
if (*scan == '/')
|
900
1301
|
scan++;
|
901
|
-
}
|
902
1302
|
}
|
903
1303
|
|
904
|
-
|
905
|
-
*tree_ptr = NULL;
|
1304
|
+
*tree_ptr = tf->entries[tf->current]->tree;
|
906
1305
|
return 0;
|
907
1306
|
}
|
908
1307
|
|
909
|
-
|
910
|
-
{
|
911
|
-
return (iter->type != GIT_ITERATOR_WORKDIR) ? 0 :
|
912
|
-
((workdir_iterator *)iter)->is_ignored;
|
913
|
-
}
|
914
|
-
|
915
|
-
int git_iterator_advance_into_directory(
|
916
|
-
git_iterator *iter, const git_index_entry **entry)
|
1308
|
+
bool git_iterator_current_is_ignored(git_iterator *iter)
|
917
1309
|
{
|
918
1310
|
workdir_iterator *wi = (workdir_iterator *)iter;
|
919
1311
|
|
920
|
-
if (iter->type
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
if (workdir_iterator__expand_dir(wi) < 0)
|
926
|
-
/* if error loading or if empty, skip the directory. */
|
927
|
-
return workdir_iterator__advance(iter, entry);
|
928
|
-
}
|
1312
|
+
if (iter->type != GIT_ITERATOR_TYPE_WORKDIR)
|
1313
|
+
return false;
|
1314
|
+
|
1315
|
+
if (wi->is_ignored != -1)
|
1316
|
+
return (bool)(wi->is_ignored != 0);
|
929
1317
|
|
930
|
-
|
1318
|
+
if (git_ignore__lookup(&wi->ignores, wi->entry.path, &wi->is_ignored) < 0)
|
1319
|
+
wi->is_ignored = true;
|
1320
|
+
|
1321
|
+
return (bool)wi->is_ignored;
|
931
1322
|
}
|
932
1323
|
|
933
|
-
int git_iterator_cmp(
|
934
|
-
git_iterator *iter, const char *path_prefix)
|
1324
|
+
int git_iterator_cmp(git_iterator *iter, const char *path_prefix)
|
935
1325
|
{
|
936
1326
|
const git_index_entry *entry;
|
937
1327
|
|
938
1328
|
/* a "done" iterator is after every prefix */
|
939
|
-
if (git_iterator_current(
|
940
|
-
entry == NULL)
|
1329
|
+
if (git_iterator_current(&entry, iter) < 0 || entry == NULL)
|
941
1330
|
return 1;
|
942
1331
|
|
943
1332
|
/* a NULL prefix is after any valid iterator */
|
944
1333
|
if (!path_prefix)
|
945
1334
|
return -1;
|
946
1335
|
|
947
|
-
return
|
1336
|
+
return iter->prefixcomp(entry->path, path_prefix);
|
948
1337
|
}
|
949
1338
|
|
950
|
-
int git_iterator_current_workdir_path(git_iterator *iter
|
1339
|
+
int git_iterator_current_workdir_path(git_buf **path, git_iterator *iter)
|
951
1340
|
{
|
952
1341
|
workdir_iterator *wi = (workdir_iterator *)iter;
|
953
1342
|
|
954
|
-
if (iter->type !=
|
1343
|
+
if (iter->type != GIT_ITERATOR_TYPE_WORKDIR || !wi->entry.path)
|
955
1344
|
*path = NULL;
|
956
1345
|
else
|
957
1346
|
*path = &wi->path;
|
958
1347
|
|
959
1348
|
return 0;
|
960
1349
|
}
|
961
|
-
|