rugged 0.17.0.b7 → 0.18.0.b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
|