rugged 0.18.0.gh.de28323 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -4
- data/Rakefile +1 -1
- data/ext/rugged/extconf.rb +10 -0
- data/ext/rugged/rugged.c +153 -86
- data/ext/rugged/rugged.h +44 -33
- data/ext/rugged/rugged_blob.c +288 -60
- data/ext/rugged/rugged_branch.c +82 -57
- data/ext/rugged/rugged_commit.c +83 -86
- data/ext/rugged/rugged_config.c +68 -68
- data/ext/rugged/rugged_diff.c +509 -0
- data/ext/rugged/rugged_diff_delta.c +94 -0
- data/ext/rugged/rugged_diff_hunk.c +100 -0
- data/ext/rugged/rugged_diff_line.c +79 -0
- data/ext/rugged/rugged_diff_patch.c +169 -0
- data/ext/rugged/rugged_index.c +539 -8
- data/ext/rugged/rugged_note.c +74 -80
- data/ext/rugged/rugged_object.c +63 -8
- data/ext/rugged/rugged_reference.c +231 -145
- data/ext/rugged/rugged_remote.c +509 -53
- data/ext/rugged/rugged_repo.c +572 -236
- data/ext/rugged/rugged_revwalk.c +59 -36
- data/ext/rugged/rugged_settings.c +7 -9
- data/ext/rugged/rugged_signature.c +7 -11
- data/ext/rugged/rugged_tag.c +93 -39
- data/ext/rugged/rugged_tree.c +321 -58
- data/lib/rugged.rb +1 -0
- data/lib/rugged/commit.rb +16 -1
- data/lib/rugged/console.rb +9 -0
- data/lib/rugged/diff.rb +19 -0
- data/lib/rugged/diff/delta.rb +54 -0
- data/lib/rugged/diff/hunk.rb +23 -0
- data/lib/rugged/diff/line.rb +29 -0
- data/lib/rugged/diff/patch.rb +28 -0
- data/lib/rugged/repository.rb +36 -39
- data/lib/rugged/version.rb +1 -1
- data/test/blob_test.rb +308 -1
- data/test/branch_test.rb +7 -0
- data/test/commit_test.rb +7 -10
- data/test/coverage/cover.rb +9 -1
- data/test/diff_test.rb +777 -0
- data/test/fixtures/archive.tar.gz +0 -0
- data/test/fixtures/attr/attr0 +1 -0
- data/test/fixtures/attr/attr1 +29 -0
- data/test/fixtures/attr/attr2 +21 -0
- data/test/fixtures/attr/attr3 +4 -0
- data/test/fixtures/attr/binfile +1 -0
- data/test/fixtures/attr/dir/file +0 -0
- data/test/fixtures/attr/file +1 -0
- data/test/fixtures/attr/gitattributes +29 -0
- data/test/fixtures/attr/gitignore +2 -0
- data/test/fixtures/attr/ign +1 -0
- data/test/fixtures/attr/macro_bad +1 -0
- data/test/fixtures/attr/macro_test +1 -0
- data/test/fixtures/attr/root_test1 +1 -0
- data/test/fixtures/attr/root_test2 +6 -0
- data/test/fixtures/attr/root_test3 +19 -0
- data/test/fixtures/attr/root_test4.txt +14 -0
- data/test/fixtures/attr/sub/abc +37 -0
- data/test/fixtures/attr/sub/dir/file +0 -0
- data/test/fixtures/attr/sub/file +1 -0
- data/test/fixtures/attr/sub/ign/file +1 -0
- data/test/fixtures/attr/sub/ign/sub/file +1 -0
- data/test/fixtures/attr/sub/sub/dir +0 -0
- data/test/fixtures/attr/sub/sub/file +1 -0
- data/test/fixtures/attr/sub/sub/subsub.txt +1 -0
- data/test/fixtures/attr/sub/subdir_test1 +2 -0
- data/test/fixtures/attr/sub/subdir_test2.txt +1 -0
- data/test/fixtures/diff/another.txt +38 -0
- data/test/fixtures/diff/readme.txt +36 -0
- data/test/fixtures/mergedrepo/conflicts-one.txt +5 -0
- data/test/fixtures/mergedrepo/conflicts-two.txt +5 -0
- data/test/fixtures/mergedrepo/one.txt +10 -0
- data/test/fixtures/mergedrepo/two.txt +12 -0
- data/test/fixtures/status/current_file +1 -0
- data/test/fixtures/status/ignored_file +1 -0
- data/test/fixtures/status/modified_file +2 -0
- data/test/fixtures/status/new_file +1 -0
- data/test/fixtures/status/staged_changes +2 -0
- data/test/fixtures/status/staged_changes_modified_file +3 -0
- data/test/fixtures/status/staged_delete_modified_file +1 -0
- data/test/fixtures/status/staged_new_file +1 -0
- data/test/fixtures/status/staged_new_file_modified_file +2 -0
- data/test/fixtures/status/subdir.txt +2 -0
- data/test/fixtures/status/subdir/current_file +1 -0
- data/test/fixtures/status/subdir/modified_file +2 -0
- data/test/fixtures/status/subdir/new_file +1 -0
- data/test/fixtures/status//350/277/231 +1 -0
- data/test/fixtures/testrepo.git/config +5 -0
- data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
- data/test/fixtures/text_file.md +464 -0
- data/test/fixtures/unsymlinked.git/HEAD +1 -0
- data/test/fixtures/unsymlinked.git/config +6 -0
- data/test/fixtures/unsymlinked.git/description +1 -0
- data/test/fixtures/unsymlinked.git/info/exclude +2 -0
- data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
- data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
- data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
- data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
- data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
- data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
- data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
- data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
- data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
- data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +2 -0
- data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
- data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
- data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
- data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
- data/test/fixtures/unsymlinked.git/refs/heads/exe-file +1 -0
- data/test/fixtures/unsymlinked.git/refs/heads/master +1 -0
- data/test/fixtures/unsymlinked.git/refs/heads/reg-file +1 -0
- data/test/index_test.rb +120 -0
- data/test/reference_test.rb +38 -3
- data/test/remote_test.rb +224 -3
- data/test/repo_reset_test.rb +2 -0
- data/test/repo_test.rb +147 -10
- data/test/test_helper.rb +5 -2
- data/vendor/libgit2/include/git2/attr.h +3 -3
- data/vendor/libgit2/include/git2/blob.h +11 -17
- data/vendor/libgit2/include/git2/branch.h +3 -2
- data/vendor/libgit2/include/git2/checkout.h +7 -0
- data/vendor/libgit2/include/git2/clone.h +3 -0
- data/vendor/libgit2/include/git2/commit.h +61 -66
- data/vendor/libgit2/include/git2/common.h +73 -42
- data/vendor/libgit2/include/git2/config.h +57 -71
- data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
- data/vendor/libgit2/include/git2/diff.h +179 -30
- data/vendor/libgit2/include/git2/errors.h +3 -3
- data/vendor/libgit2/include/git2/index.h +225 -146
- data/vendor/libgit2/include/git2/indexer.h +2 -22
- data/vendor/libgit2/include/git2/inttypes.h +9 -9
- data/vendor/libgit2/include/git2/merge.h +123 -5
- data/vendor/libgit2/include/git2/odb.h +59 -38
- data/vendor/libgit2/include/git2/odb_backend.h +45 -104
- data/vendor/libgit2/include/git2/oid.h +30 -19
- data/vendor/libgit2/include/git2/pack.h +21 -3
- data/vendor/libgit2/include/git2/refdb.h +0 -35
- data/vendor/libgit2/include/git2/refs.h +93 -31
- data/vendor/libgit2/include/git2/refspec.h +17 -0
- data/vendor/libgit2/include/git2/remote.h +60 -20
- data/vendor/libgit2/include/git2/repository.h +48 -70
- data/vendor/libgit2/include/git2/reset.h +3 -3
- data/vendor/libgit2/include/git2/revparse.h +22 -0
- data/vendor/libgit2/include/git2/stash.h +1 -1
- data/vendor/libgit2/include/git2/status.h +131 -56
- data/vendor/libgit2/include/git2/strarray.h +2 -2
- data/vendor/libgit2/include/git2/submodule.h +16 -16
- data/vendor/libgit2/include/git2/sys/commit.h +46 -0
- data/vendor/libgit2/include/git2/sys/config.h +71 -0
- data/vendor/libgit2/include/git2/sys/index.h +179 -0
- data/vendor/libgit2/include/git2/sys/odb_backend.h +86 -0
- data/vendor/libgit2/include/git2/sys/refdb_backend.h +158 -0
- data/vendor/libgit2/include/git2/sys/refs.h +38 -0
- data/vendor/libgit2/include/git2/sys/repository.h +106 -0
- data/vendor/libgit2/include/git2/tag.h +44 -18
- data/vendor/libgit2/include/git2/trace.h +1 -2
- data/vendor/libgit2/include/git2/transport.h +74 -0
- data/vendor/libgit2/include/git2/tree.h +12 -22
- data/vendor/libgit2/include/git2/types.h +33 -0
- data/vendor/libgit2/include/git2/version.h +2 -2
- data/vendor/libgit2/src/array.h +66 -0
- data/vendor/libgit2/src/attr.c +26 -13
- data/vendor/libgit2/src/attr_file.c +3 -2
- data/vendor/libgit2/src/attr_file.h +3 -3
- data/vendor/libgit2/src/attrcache.h +4 -4
- data/vendor/libgit2/src/blob.c +13 -9
- data/vendor/libgit2/src/blob.h +2 -2
- data/vendor/libgit2/src/branch.c +67 -49
- data/vendor/libgit2/src/cache.c +224 -54
- data/vendor/libgit2/src/cache.h +33 -20
- data/vendor/libgit2/src/checkout.c +145 -85
- data/vendor/libgit2/src/clone.c +62 -50
- data/vendor/libgit2/src/commit.c +74 -40
- data/vendor/libgit2/src/commit.h +2 -3
- data/vendor/libgit2/src/commit_list.c +14 -8
- data/vendor/libgit2/src/config.c +119 -36
- data/vendor/libgit2/src/config.h +3 -0
- data/vendor/libgit2/src/config_cache.c +24 -7
- data/vendor/libgit2/src/config_file.c +9 -6
- data/vendor/libgit2/src/crlf.c +4 -2
- data/vendor/libgit2/src/date.c +3 -3
- data/vendor/libgit2/src/delta.c +1 -1
- data/vendor/libgit2/src/diff.c +681 -303
- data/vendor/libgit2/src/diff.h +34 -2
- data/vendor/libgit2/src/diff_driver.c +405 -0
- data/vendor/libgit2/src/diff_driver.h +49 -0
- data/vendor/libgit2/src/diff_file.c +447 -0
- data/vendor/libgit2/src/diff_file.h +58 -0
- data/vendor/libgit2/src/diff_patch.c +995 -0
- data/vendor/libgit2/src/diff_patch.h +46 -0
- data/vendor/libgit2/src/diff_print.c +430 -0
- data/vendor/libgit2/src/diff_tform.c +464 -203
- data/vendor/libgit2/src/diff_xdiff.c +166 -0
- data/vendor/libgit2/src/diff_xdiff.h +28 -0
- data/vendor/libgit2/src/fetch.c +11 -4
- data/vendor/libgit2/src/fileops.c +85 -61
- data/vendor/libgit2/src/fileops.h +4 -0
- data/vendor/libgit2/src/global.c +10 -2
- data/vendor/libgit2/src/global.h +0 -8
- data/vendor/libgit2/src/hash/hash_generic.h +3 -3
- data/vendor/libgit2/src/hash/hash_win32.h +4 -4
- data/vendor/libgit2/src/hashsig.c +0 -1
- data/vendor/libgit2/src/ignore.c +68 -28
- data/vendor/libgit2/src/ignore.h +10 -1
- data/vendor/libgit2/src/index.c +666 -84
- data/vendor/libgit2/src/index.h +6 -0
- data/vendor/libgit2/src/indexer.c +10 -28
- data/vendor/libgit2/src/iterator.c +427 -283
- data/vendor/libgit2/src/iterator.h +58 -4
- data/vendor/libgit2/src/merge.c +1892 -32
- data/vendor/libgit2/src/merge.h +132 -5
- data/vendor/libgit2/src/merge_file.c +174 -0
- data/vendor/libgit2/src/merge_file.h +71 -0
- data/vendor/libgit2/src/mwindow.c +1 -1
- data/vendor/libgit2/src/notes.c +45 -48
- data/vendor/libgit2/src/object.c +89 -127
- data/vendor/libgit2/src/object.h +0 -1
- data/vendor/libgit2/src/object_api.c +129 -0
- data/vendor/libgit2/src/odb.c +156 -59
- data/vendor/libgit2/src/odb.h +5 -2
- data/vendor/libgit2/src/odb_loose.c +31 -17
- data/vendor/libgit2/src/odb_pack.c +39 -43
- data/vendor/libgit2/src/oid.c +62 -27
- data/vendor/libgit2/src/oid.h +33 -0
- data/vendor/libgit2/src/oidmap.h +4 -6
- data/vendor/libgit2/src/pack-objects.c +54 -22
- data/vendor/libgit2/src/pack.c +98 -56
- data/vendor/libgit2/src/pack.h +3 -1
- data/vendor/libgit2/src/pathspec.c +26 -1
- data/vendor/libgit2/src/pathspec.h +14 -0
- data/vendor/libgit2/src/pool.c +5 -0
- data/vendor/libgit2/src/posix.c +2 -2
- data/vendor/libgit2/src/posix.h +3 -0
- data/vendor/libgit2/src/push.c +13 -10
- data/vendor/libgit2/src/refdb.c +82 -62
- data/vendor/libgit2/src/refdb.h +16 -16
- data/vendor/libgit2/src/refdb_fs.c +386 -133
- data/vendor/libgit2/src/reflog.c +3 -1
- data/vendor/libgit2/src/refs.c +247 -221
- data/vendor/libgit2/src/refs.h +2 -1
- data/vendor/libgit2/src/refspec.c +18 -1
- data/vendor/libgit2/src/refspec.h +3 -1
- data/vendor/libgit2/src/remote.c +434 -253
- data/vendor/libgit2/src/remote.h +5 -3
- data/vendor/libgit2/src/repository.c +197 -111
- data/vendor/libgit2/src/repository.h +26 -5
- data/vendor/libgit2/src/reset.c +1 -1
- data/vendor/libgit2/src/revparse.c +84 -79
- data/vendor/libgit2/src/revwalk.c +1 -1
- data/vendor/libgit2/src/signature.c +22 -10
- data/vendor/libgit2/src/stash.c +5 -2
- data/vendor/libgit2/src/status.c +311 -107
- data/vendor/libgit2/src/status.h +23 -0
- data/vendor/libgit2/src/submodule.c +21 -13
- data/vendor/libgit2/src/tag.c +42 -31
- data/vendor/libgit2/src/tag.h +2 -3
- data/vendor/libgit2/src/thread-utils.h +105 -3
- data/vendor/libgit2/src/trace.c +1 -2
- data/vendor/libgit2/src/trace.h +3 -3
- data/vendor/libgit2/src/transport.c +18 -6
- data/vendor/libgit2/src/transports/cred.c +103 -1
- data/vendor/libgit2/src/transports/local.c +19 -9
- data/vendor/libgit2/src/transports/smart_protocol.c +32 -12
- data/vendor/libgit2/src/transports/ssh.c +519 -0
- data/vendor/libgit2/src/transports/winhttp.c +3 -1
- data/vendor/libgit2/src/tree.c +26 -28
- data/vendor/libgit2/src/tree.h +3 -3
- data/vendor/libgit2/src/unix/posix.h +2 -0
- data/vendor/libgit2/src/util.c +43 -6
- data/vendor/libgit2/src/util.h +40 -12
- data/vendor/libgit2/src/vector.c +3 -5
- data/vendor/libgit2/src/vector.h +9 -0
- data/vendor/libgit2/src/win32/dir.c +1 -1
- data/vendor/libgit2/src/win32/error.c +2 -0
- data/vendor/libgit2/src/win32/findfile.c +3 -6
- data/vendor/libgit2/src/win32/posix_w32.c +85 -59
- data/vendor/libgit2/src/win32/pthread.c +16 -8
- data/vendor/libgit2/src/win32/pthread.h +7 -4
- metadata +407 -306
- data/test/coverage/HEAD.json +0 -1
- data/vendor/libgit2/include/git2/refdb_backend.h +0 -109
- data/vendor/libgit2/src/diff_output.c +0 -1819
- data/vendor/libgit2/src/diff_output.h +0 -93
data/vendor/libgit2/src/index.h
CHANGED
@@ -33,6 +33,7 @@ struct git_index {
|
|
33
33
|
|
34
34
|
git_tree_cache *tree;
|
35
35
|
|
36
|
+
git_vector names;
|
36
37
|
git_vector reuc;
|
37
38
|
|
38
39
|
git_vector_cmp entries_cmp_path;
|
@@ -41,6 +42,11 @@ struct git_index {
|
|
41
42
|
git_vector_cmp reuc_search;
|
42
43
|
};
|
43
44
|
|
45
|
+
struct git_index_conflict_iterator {
|
46
|
+
git_index *index;
|
47
|
+
size_t cur;
|
48
|
+
};
|
49
|
+
|
44
50
|
extern void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st);
|
45
51
|
|
46
52
|
extern size_t git_index__prefix_position(git_index *index, const char *path);
|
@@ -9,7 +9,6 @@
|
|
9
9
|
|
10
10
|
#include "git2/indexer.h"
|
11
11
|
#include "git2/object.h"
|
12
|
-
#include "git2/oid.h"
|
13
12
|
|
14
13
|
#include "common.h"
|
15
14
|
#include "pack.h"
|
@@ -17,6 +16,7 @@
|
|
17
16
|
#include "posix.h"
|
18
17
|
#include "pack.h"
|
19
18
|
#include "filebuf.h"
|
19
|
+
#include "oid.h"
|
20
20
|
#include "oidmap.h"
|
21
21
|
|
22
22
|
#define UINT31_MAX (0x7FFFFFFF)
|
@@ -60,36 +60,19 @@ const git_oid *git_indexer_stream_hash(const git_indexer_stream *idx)
|
|
60
60
|
|
61
61
|
static int open_pack(struct git_pack_file **out, const char *filename)
|
62
62
|
{
|
63
|
-
size_t namelen;
|
64
63
|
struct git_pack_file *pack;
|
65
|
-
struct stat st;
|
66
|
-
int fd;
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
GITERR_CHECK_ALLOC(pack);
|
71
|
-
|
72
|
-
memcpy(pack->pack_name, filename, namelen + 1);
|
73
|
-
|
74
|
-
if (p_stat(filename, &st) < 0) {
|
75
|
-
giterr_set(GITERR_OS, "Failed to stat packfile.");
|
76
|
-
goto cleanup;
|
77
|
-
}
|
65
|
+
if (git_packfile_alloc(&pack, filename) < 0)
|
66
|
+
return -1;
|
78
67
|
|
79
|
-
if ((fd = p_open(pack->pack_name, O_RDONLY)) < 0) {
|
68
|
+
if ((pack->mwf.fd = p_open(pack->pack_name, O_RDONLY)) < 0) {
|
80
69
|
giterr_set(GITERR_OS, "Failed to open packfile.");
|
81
|
-
|
70
|
+
git_packfile_free(pack);
|
71
|
+
return -1;
|
82
72
|
}
|
83
73
|
|
84
|
-
pack->mwf.fd = fd;
|
85
|
-
pack->mwf.size = (git_off_t)st.st_size;
|
86
|
-
|
87
74
|
*out = pack;
|
88
75
|
return 0;
|
89
|
-
|
90
|
-
cleanup:
|
91
|
-
git__free(pack);
|
92
|
-
return -1;
|
93
76
|
}
|
94
77
|
|
95
78
|
static int parse_header(struct git_pack_header *hdr, struct git_pack_file *pack)
|
@@ -120,7 +103,7 @@ static int objects_cmp(const void *a, const void *b)
|
|
120
103
|
const struct entry *entrya = a;
|
121
104
|
const struct entry *entryb = b;
|
122
105
|
|
123
|
-
return
|
106
|
+
return git_oid__cmp(&entrya->oid, &entryb->oid);
|
124
107
|
}
|
125
108
|
|
126
109
|
int git_indexer_stream_new(
|
@@ -276,7 +259,7 @@ static int store_object(git_indexer_stream *idx)
|
|
276
259
|
entry = git__calloc(1, sizeof(*entry));
|
277
260
|
GITERR_CHECK_ALLOC(entry);
|
278
261
|
|
279
|
-
pentry =
|
262
|
+
pentry = git__calloc(1, sizeof(struct git_pack_entry));
|
280
263
|
GITERR_CHECK_ALLOC(pentry);
|
281
264
|
|
282
265
|
git_hash_final(&oid, ctx);
|
@@ -345,7 +328,7 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent
|
|
345
328
|
return -1;
|
346
329
|
}
|
347
330
|
|
348
|
-
pentry =
|
331
|
+
pentry = git__calloc(1, sizeof(struct git_pack_entry));
|
349
332
|
GITERR_CHECK_ALLOC(pentry);
|
350
333
|
|
351
334
|
git_oid_cpy(&pentry->sha1, &oid);
|
@@ -391,7 +374,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
|
|
391
374
|
{
|
392
375
|
int error = -1;
|
393
376
|
struct git_pack_header hdr;
|
394
|
-
size_t processed;
|
377
|
+
size_t processed;
|
395
378
|
git_mwindow_file *mwf = &idx->pack->mwf;
|
396
379
|
|
397
380
|
assert(idx && data && stats);
|
@@ -404,7 +387,6 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
|
|
404
387
|
/* Make sure we set the new size of the pack */
|
405
388
|
if (idx->opened_pack) {
|
406
389
|
idx->pack->mwf.size += size;
|
407
|
-
//printf("\nadding %zu for %zu\n", size, idx->pack->mwf.size);
|
408
390
|
} else {
|
409
391
|
if (open_pack(&idx->pack, idx->pack_file.path_lock) < 0)
|
410
392
|
return -1;
|
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
#include "iterator.h"
|
9
9
|
#include "tree.h"
|
10
|
+
#include "index.h"
|
10
11
|
#include "ignore.h"
|
11
12
|
#include "buffer.h"
|
12
13
|
#include "git2/submodule.h"
|
@@ -26,8 +27,6 @@
|
|
26
27
|
(GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_DONT_IGNORE_CASE)
|
27
28
|
|
28
29
|
#define ITERATOR_BASE_INIT(P,NAME_LC,NAME_UC,REPO) do { \
|
29
|
-
(P) = git__calloc(1, sizeof(NAME_LC ## _iterator)); \
|
30
|
-
GITERR_CHECK_ALLOC(P); \
|
31
30
|
(P)->base.type = GIT_ITERATOR_TYPE_ ## NAME_UC; \
|
32
31
|
(P)->base.cb = &(P)->cb; \
|
33
32
|
ITERATOR_SET_CB(P,NAME_LC); \
|
@@ -48,6 +47,9 @@
|
|
48
47
|
#define iterator__dont_autoexpand(I) iterator__flag(I,DONT_AUTOEXPAND)
|
49
48
|
#define iterator__do_autoexpand(I) !iterator__flag(I,DONT_AUTOEXPAND)
|
50
49
|
|
50
|
+
#define GIT_ITERATOR_FIRST_ACCESS (1 << 15)
|
51
|
+
#define iterator__has_been_accessed(I) iterator__flag(I,FIRST_ACCESS)
|
52
|
+
|
51
53
|
#define iterator__end(I) ((git_iterator *)(I))->end
|
52
54
|
#define iterator__past_end(I,PATH) \
|
53
55
|
(iterator__end(I) && ((git_iterator *)(I))->prefixcomp((PATH),iterator__end(I)) > 0)
|
@@ -70,6 +72,8 @@ static int iterator__reset_range(
|
|
70
72
|
GITERR_CHECK_ALLOC(iter->end);
|
71
73
|
}
|
72
74
|
|
75
|
+
iter->flags &= ~GIT_ITERATOR_FIRST_ACCESS;
|
76
|
+
|
73
77
|
return 0;
|
74
78
|
}
|
75
79
|
|
@@ -111,7 +115,7 @@ static int empty_iterator__noop(const git_index_entry **e, git_iterator *i)
|
|
111
115
|
{
|
112
116
|
GIT_UNUSED(i);
|
113
117
|
iterator__clear_entry(e);
|
114
|
-
return
|
118
|
+
return GIT_ITEROVER;
|
115
119
|
}
|
116
120
|
|
117
121
|
static int empty_iterator__seek(git_iterator *i, const char *p)
|
@@ -148,7 +152,8 @@ int git_iterator_for_nothing(
|
|
148
152
|
const char *start,
|
149
153
|
const char *end)
|
150
154
|
{
|
151
|
-
empty_iterator *i;
|
155
|
+
empty_iterator *i = git__calloc(1, sizeof(empty_iterator));
|
156
|
+
GITERR_CHECK_ALLOC(i);
|
152
157
|
|
153
158
|
#define empty_iterator__current empty_iterator__noop
|
154
159
|
#define empty_iterator__advance empty_iterator__noop
|
@@ -194,6 +199,7 @@ typedef struct {
|
|
194
199
|
git_buf path;
|
195
200
|
int path_ambiguities;
|
196
201
|
bool path_has_filename;
|
202
|
+
bool entry_is_current;
|
197
203
|
int (*strncomp)(const char *a, const char *b, size_t sz);
|
198
204
|
} tree_iterator;
|
199
205
|
|
@@ -267,9 +273,28 @@ static int tree_iterator__search_cmp(const void *key, const void *val, void *p)
|
|
267
273
|
((tree_iterator *)p)->strncomp);
|
268
274
|
}
|
269
275
|
|
276
|
+
static bool tree_iterator__move_to_next(
|
277
|
+
tree_iterator *ti, tree_iterator_frame *tf)
|
278
|
+
{
|
279
|
+
if (tf->next > tf->current + 1)
|
280
|
+
ti->path_ambiguities--;
|
281
|
+
|
282
|
+
if (!tf->up) { /* at root */
|
283
|
+
tf->current = tf->next;
|
284
|
+
return false;
|
285
|
+
}
|
286
|
+
|
287
|
+
for (; tf->current < tf->next; tf->current++) {
|
288
|
+
git_tree_free(tf->entries[tf->current]->tree);
|
289
|
+
tf->entries[tf->current]->tree = NULL;
|
290
|
+
}
|
291
|
+
|
292
|
+
return (tf->current < tf->n_entries);
|
293
|
+
}
|
294
|
+
|
270
295
|
static int tree_iterator__set_next(tree_iterator *ti, tree_iterator_frame *tf)
|
271
296
|
{
|
272
|
-
int error;
|
297
|
+
int error = 0;
|
273
298
|
const git_tree_entry *te, *last = NULL;
|
274
299
|
|
275
300
|
tf->next = tf->current;
|
@@ -280,18 +305,23 @@ static int tree_iterator__set_next(tree_iterator *ti, tree_iterator_frame *tf)
|
|
280
305
|
if (last && tree_iterator__te_cmp(last, te, ti->strncomp))
|
281
306
|
break;
|
282
307
|
|
283
|
-
/* load trees for items in [current,next) range */
|
284
|
-
if (git_tree_entry__is_tree(te)
|
285
|
-
|
286
|
-
&tf->entries[tf->next]->tree, ti->base.repo, &te->oid)
|
287
|
-
return error;
|
308
|
+
/* try to load trees for items in [current,next) range */
|
309
|
+
if (!error && git_tree_entry__is_tree(te))
|
310
|
+
error = git_tree_lookup(
|
311
|
+
&tf->entries[tf->next]->tree, ti->base.repo, &te->oid);
|
288
312
|
}
|
289
313
|
|
290
314
|
if (tf->next > tf->current + 1)
|
291
315
|
ti->path_ambiguities++;
|
292
316
|
|
317
|
+
/* if a tree lookup failed, advance over this span and return failure */
|
318
|
+
if (error < 0) {
|
319
|
+
tree_iterator__move_to_next(ti, tf);
|
320
|
+
return error;
|
321
|
+
}
|
322
|
+
|
293
323
|
if (last && !tree_iterator__current_filename(ti, last))
|
294
|
-
return -1;
|
324
|
+
return -1; /* must have been allocation failure */
|
295
325
|
|
296
326
|
return 0;
|
297
327
|
}
|
@@ -309,7 +339,7 @@ static int tree_iterator__push_frame(tree_iterator *ti)
|
|
309
339
|
size_t i, n_entries = 0;
|
310
340
|
|
311
341
|
if (head->current >= head->n_entries || !head->entries[head->current]->tree)
|
312
|
-
return
|
342
|
+
return GIT_ITEROVER;
|
313
343
|
|
314
344
|
for (i = head->current; i < head->next; ++i)
|
315
345
|
n_entries += git_tree_entrycount(head->entries[i]->tree);
|
@@ -360,7 +390,7 @@ static int tree_iterator__push_frame(tree_iterator *ti)
|
|
360
390
|
}
|
361
391
|
}
|
362
392
|
|
363
|
-
ti->path_has_filename = false;
|
393
|
+
ti->path_has_filename = ti->entry_is_current = false;
|
364
394
|
|
365
395
|
if ((error = tree_iterator__set_next(ti, tf)) < 0)
|
366
396
|
return error;
|
@@ -372,25 +402,6 @@ static int tree_iterator__push_frame(tree_iterator *ti)
|
|
372
402
|
return 0;
|
373
403
|
}
|
374
404
|
|
375
|
-
static bool tree_iterator__move_to_next(
|
376
|
-
tree_iterator *ti, tree_iterator_frame *tf)
|
377
|
-
{
|
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);
|
392
|
-
}
|
393
|
-
|
394
405
|
static bool tree_iterator__pop_frame(tree_iterator *ti, bool final)
|
395
406
|
{
|
396
407
|
tree_iterator_frame *tf = ti->head;
|
@@ -413,7 +424,7 @@ static bool tree_iterator__pop_frame(tree_iterator *ti, bool final)
|
|
413
424
|
return true;
|
414
425
|
}
|
415
426
|
|
416
|
-
static
|
427
|
+
static void tree_iterator__pop_all(tree_iterator *ti, bool to_end, bool final)
|
417
428
|
{
|
418
429
|
while (tree_iterator__pop_frame(ti, final)) /* pop to root */;
|
419
430
|
|
@@ -422,22 +433,18 @@ static int tree_iterator__pop_all(tree_iterator *ti, bool to_end, bool final)
|
|
422
433
|
ti->path_ambiguities = 0;
|
423
434
|
git_buf_clear(&ti->path);
|
424
435
|
}
|
425
|
-
|
426
|
-
return 0;
|
427
436
|
}
|
428
437
|
|
429
|
-
static int
|
430
|
-
const git_index_entry **entry, git_iterator *self)
|
438
|
+
static int tree_iterator__update_entry(tree_iterator *ti)
|
431
439
|
{
|
432
|
-
|
433
|
-
|
434
|
-
const git_tree_entry *te;
|
440
|
+
tree_iterator_frame *tf;
|
441
|
+
const git_tree_entry *te;
|
435
442
|
|
436
|
-
|
443
|
+
if (ti->entry_is_current)
|
444
|
+
return 0;
|
437
445
|
|
438
|
-
|
439
|
-
|
440
|
-
te = tf->entries[tf->current]->te;
|
446
|
+
tf = ti->head;
|
447
|
+
te = tf->entries[tf->current]->te;
|
441
448
|
|
442
449
|
ti->entry.mode = te->attr;
|
443
450
|
git_oid_cpy(&ti->entry.oid, &te->oid);
|
@@ -448,12 +455,36 @@ static int tree_iterator__current(
|
|
448
455
|
if (ti->path_ambiguities > 0)
|
449
456
|
tree_iterator__rewrite_filename(ti);
|
450
457
|
|
451
|
-
if (iterator__past_end(ti, ti->entry.path))
|
452
|
-
|
458
|
+
if (iterator__past_end(ti, ti->entry.path)) {
|
459
|
+
tree_iterator__pop_all(ti, true, false);
|
460
|
+
return GIT_ITEROVER;
|
461
|
+
}
|
462
|
+
|
463
|
+
ti->entry_is_current = true;
|
464
|
+
|
465
|
+
return 0;
|
466
|
+
}
|
467
|
+
|
468
|
+
static int tree_iterator__current(
|
469
|
+
const git_index_entry **entry, git_iterator *self)
|
470
|
+
{
|
471
|
+
int error;
|
472
|
+
tree_iterator *ti = (tree_iterator *)self;
|
473
|
+
tree_iterator_frame *tf = ti->head;
|
474
|
+
|
475
|
+
iterator__clear_entry(entry);
|
476
|
+
|
477
|
+
if (tf->current >= tf->n_entries)
|
478
|
+
return GIT_ITEROVER;
|
479
|
+
|
480
|
+
if ((error = tree_iterator__update_entry(ti)) < 0)
|
481
|
+
return error;
|
453
482
|
|
454
483
|
if (entry)
|
455
484
|
*entry = &ti->entry;
|
456
485
|
|
486
|
+
ti->base.flags |= GIT_ITERATOR_FIRST_ACCESS;
|
487
|
+
|
457
488
|
return 0;
|
458
489
|
}
|
459
490
|
|
@@ -465,8 +496,10 @@ static int tree_iterator__advance_into(
|
|
465
496
|
|
466
497
|
iterator__clear_entry(entry);
|
467
498
|
|
468
|
-
if (tree_iterator__at_tree(ti)
|
469
|
-
|
499
|
+
if (tree_iterator__at_tree(ti))
|
500
|
+
error = tree_iterator__push_frame(ti);
|
501
|
+
|
502
|
+
if (!error && entry)
|
470
503
|
error = tree_iterator__current(entry, self);
|
471
504
|
|
472
505
|
return error;
|
@@ -481,8 +514,11 @@ static int tree_iterator__advance(
|
|
481
514
|
|
482
515
|
iterator__clear_entry(entry);
|
483
516
|
|
484
|
-
if (tf->current
|
485
|
-
return
|
517
|
+
if (tf->current >= tf->n_entries)
|
518
|
+
return GIT_ITEROVER;
|
519
|
+
|
520
|
+
if (!iterator__has_been_accessed(ti))
|
521
|
+
return tree_iterator__current(entry, self);
|
486
522
|
|
487
523
|
if (iterator__do_autoexpand(ti) && iterator__include_trees(ti) &&
|
488
524
|
tree_iterator__at_tree(ti))
|
@@ -490,7 +526,7 @@ static int tree_iterator__advance(
|
|
490
526
|
|
491
527
|
if (ti->path_has_filename) {
|
492
528
|
git_buf_rtruncate_at_char(&ti->path, '/');
|
493
|
-
ti->path_has_filename = false;
|
529
|
+
ti->path_has_filename = ti->entry_is_current = false;
|
494
530
|
}
|
495
531
|
|
496
532
|
/* scan forward and up, advancing in frame or popping frame when done */
|
@@ -581,6 +617,9 @@ int git_iterator_for_tree(
|
|
581
617
|
if ((error = git_object_dup((git_object **)&tree, (git_object *)tree)) < 0)
|
582
618
|
return error;
|
583
619
|
|
620
|
+
ti = git__calloc(1, sizeof(tree_iterator));
|
621
|
+
GITERR_CHECK_ALLOC(ti);
|
622
|
+
|
584
623
|
ITERATOR_BASE_INIT(ti, tree, TREE, git_tree_owner(tree));
|
585
624
|
|
586
625
|
if ((error = iterator__update_ignore_case((git_iterator *)ti, flags)) < 0)
|
@@ -697,7 +736,9 @@ static int index_iterator__current(
|
|
697
736
|
if (entry)
|
698
737
|
*entry = ie;
|
699
738
|
|
700
|
-
|
739
|
+
ii->base.flags |= GIT_ITERATOR_FIRST_ACCESS;
|
740
|
+
|
741
|
+
return (ie != NULL) ? 0 : GIT_ITEROVER;
|
701
742
|
}
|
702
743
|
|
703
744
|
static int index_iterator__at_end(git_iterator *self)
|
@@ -713,6 +754,9 @@ static int index_iterator__advance(
|
|
713
754
|
size_t entrycount = git_index_entrycount(ii->index);
|
714
755
|
const git_index_entry *ie;
|
715
756
|
|
757
|
+
if (!iterator__has_been_accessed(ii))
|
758
|
+
return index_iterator__current(entry, self);
|
759
|
+
|
716
760
|
if (index_iterator__at_tree(ii)) {
|
717
761
|
if (iterator__do_autoexpand(ii)) {
|
718
762
|
ii->partial.ptr[ii->partial_pos] = ii->restore_terminator;
|
@@ -810,7 +854,8 @@ int git_iterator_for_index(
|
|
810
854
|
const char *start,
|
811
855
|
const char *end)
|
812
856
|
{
|
813
|
-
index_iterator *ii;
|
857
|
+
index_iterator *ii = git__calloc(1, sizeof(index_iterator));
|
858
|
+
GITERR_CHECK_ALLOC(ii);
|
814
859
|
|
815
860
|
ITERATOR_BASE_INIT(ii, index, INDEX, git_index_owner(index));
|
816
861
|
|
@@ -833,237 +878,240 @@ int git_iterator_for_index(
|
|
833
878
|
}
|
834
879
|
|
835
880
|
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
struct workdir_iterator_frame {
|
840
|
-
workdir_iterator_frame *next;
|
881
|
+
typedef struct fs_iterator_frame fs_iterator_frame;
|
882
|
+
struct fs_iterator_frame {
|
883
|
+
fs_iterator_frame *next;
|
841
884
|
git_vector entries;
|
842
885
|
size_t index;
|
843
886
|
};
|
844
887
|
|
845
|
-
typedef struct
|
888
|
+
typedef struct fs_iterator fs_iterator;
|
889
|
+
struct fs_iterator {
|
846
890
|
git_iterator base;
|
847
891
|
git_iterator_callbacks cb;
|
848
|
-
|
849
|
-
git_ignores ignores;
|
892
|
+
fs_iterator_frame *stack;
|
850
893
|
git_index_entry entry;
|
851
894
|
git_buf path;
|
852
895
|
size_t root_len;
|
853
|
-
int is_ignored;
|
854
896
|
int depth;
|
855
|
-
} workdir_iterator;
|
856
897
|
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
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
|
-
}
|
876
|
-
}
|
898
|
+
int (*enter_dir_cb)(fs_iterator *self);
|
899
|
+
int (*leave_dir_cb)(fs_iterator *self);
|
900
|
+
int (*update_entry_cb)(fs_iterator *self);
|
901
|
+
};
|
902
|
+
|
903
|
+
#define FS_MAX_DEPTH 100
|
877
904
|
|
878
|
-
static
|
879
|
-
workdir_iterator *wi)
|
905
|
+
static fs_iterator_frame *fs_iterator__alloc_frame(fs_iterator *fi)
|
880
906
|
{
|
881
|
-
|
907
|
+
fs_iterator_frame *ff = git__calloc(1, sizeof(fs_iterator_frame));
|
882
908
|
git_vector_cmp entry_compare = CASESELECT(
|
883
|
-
iterator__ignore_case(
|
909
|
+
iterator__ignore_case(fi),
|
884
910
|
git_path_with_stat_cmp_icase, git_path_with_stat_cmp);
|
885
911
|
|
886
|
-
if (
|
887
|
-
|
888
|
-
|
889
|
-
if (git_vector_init(&wf->entries, 0, entry_compare) != 0) {
|
890
|
-
git__free(wf);
|
891
|
-
return NULL;
|
912
|
+
if (ff && git_vector_init(&ff->entries, 0, entry_compare) < 0) {
|
913
|
+
git__free(ff);
|
914
|
+
ff = NULL;
|
892
915
|
}
|
893
916
|
|
894
|
-
return
|
917
|
+
return ff;
|
895
918
|
}
|
896
919
|
|
897
|
-
static void
|
920
|
+
static void fs_iterator__free_frame(fs_iterator_frame *ff)
|
898
921
|
{
|
899
|
-
|
922
|
+
size_t i;
|
900
923
|
git_path_with_stat *path;
|
901
924
|
|
902
|
-
git_vector_foreach(&
|
925
|
+
git_vector_foreach(&ff->entries, i, path)
|
903
926
|
git__free(path);
|
904
|
-
git_vector_free(&
|
905
|
-
git__free(
|
927
|
+
git_vector_free(&ff->entries);
|
928
|
+
git__free(ff);
|
929
|
+
}
|
930
|
+
|
931
|
+
static void fs_iterator__pop_frame(
|
932
|
+
fs_iterator *fi, fs_iterator_frame *ff, bool pop_last)
|
933
|
+
{
|
934
|
+
if (fi && fi->stack == ff) {
|
935
|
+
if (!ff->next && !pop_last) {
|
936
|
+
memset(&fi->entry, 0, sizeof(fi->entry));
|
937
|
+
return;
|
938
|
+
}
|
939
|
+
|
940
|
+
if (fi->leave_dir_cb)
|
941
|
+
(void)fi->leave_dir_cb(fi);
|
942
|
+
|
943
|
+
fi->stack = ff->next;
|
944
|
+
fi->depth--;
|
945
|
+
}
|
946
|
+
|
947
|
+
fs_iterator__free_frame(ff);
|
906
948
|
}
|
907
949
|
|
908
|
-
static int
|
950
|
+
static int fs_iterator__update_entry(fs_iterator *fi);
|
951
|
+
static int fs_iterator__advance_over(
|
952
|
+
const git_index_entry **entry, git_iterator *self);
|
909
953
|
|
910
|
-
static int
|
954
|
+
static int fs_iterator__entry_cmp(const void *i, const void *item)
|
911
955
|
{
|
912
|
-
const
|
956
|
+
const fs_iterator *fi = (const fs_iterator *)i;
|
913
957
|
const git_path_with_stat *ps = item;
|
914
|
-
return
|
958
|
+
return fi->base.prefixcomp(fi->base.start, ps->path);
|
915
959
|
}
|
916
960
|
|
917
|
-
static void
|
918
|
-
|
961
|
+
static void fs_iterator__seek_frame_start(
|
962
|
+
fs_iterator *fi, fs_iterator_frame *ff)
|
919
963
|
{
|
920
|
-
if (!
|
964
|
+
if (!ff)
|
921
965
|
return;
|
922
966
|
|
923
|
-
if (
|
967
|
+
if (fi->base.start)
|
924
968
|
git_vector_bsearch2(
|
925
|
-
&
|
969
|
+
&ff->index, &ff->entries, fs_iterator__entry_cmp, fi);
|
926
970
|
else
|
927
|
-
|
928
|
-
|
929
|
-
if (path_is_dotgit(git_vector_get(&wf->entries, wf->index)))
|
930
|
-
wf->index++;
|
971
|
+
ff->index = 0;
|
931
972
|
}
|
932
973
|
|
933
|
-
static int
|
974
|
+
static int fs_iterator__expand_dir(fs_iterator *fi)
|
934
975
|
{
|
935
976
|
int error;
|
936
|
-
|
977
|
+
fs_iterator_frame *ff;
|
978
|
+
|
979
|
+
if (fi->depth > FS_MAX_DEPTH) {
|
980
|
+
giterr_set(GITERR_REPOSITORY,
|
981
|
+
"Directory nesting is too deep (%d)", fi->depth);
|
982
|
+
return -1;
|
983
|
+
}
|
937
984
|
|
938
|
-
|
939
|
-
GITERR_CHECK_ALLOC(
|
985
|
+
ff = fs_iterator__alloc_frame(fi);
|
986
|
+
GITERR_CHECK_ALLOC(ff);
|
940
987
|
|
941
988
|
error = git_path_dirload_with_stat(
|
942
|
-
|
943
|
-
|
989
|
+
fi->path.ptr, fi->root_len, iterator__ignore_case(fi),
|
990
|
+
fi->base.start, fi->base.end, &ff->entries);
|
944
991
|
|
945
|
-
if (error < 0
|
946
|
-
|
947
|
-
|
992
|
+
if (error < 0) {
|
993
|
+
fs_iterator__free_frame(ff);
|
994
|
+
fs_iterator__advance_over(NULL, (git_iterator *)fi);
|
995
|
+
return error;
|
948
996
|
}
|
949
997
|
|
950
|
-
if (
|
951
|
-
|
952
|
-
|
953
|
-
workdir_iterator__free_frame(wf);
|
954
|
-
return -1;
|
998
|
+
if (ff->entries.length == 0) {
|
999
|
+
fs_iterator__free_frame(ff);
|
1000
|
+
return GIT_ENOTFOUND;
|
955
1001
|
}
|
956
1002
|
|
957
|
-
|
1003
|
+
fs_iterator__seek_frame_start(fi, ff);
|
958
1004
|
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
(void)git_ignore__push_dir(&wi->ignores, &wi->path.ptr[slash_pos + 1]);
|
963
|
-
}
|
1005
|
+
ff->next = fi->stack;
|
1006
|
+
fi->stack = ff;
|
1007
|
+
fi->depth++;
|
964
1008
|
|
965
|
-
|
966
|
-
|
1009
|
+
if (fi->enter_dir_cb && (error = fi->enter_dir_cb(fi)) < 0)
|
1010
|
+
return error;
|
967
1011
|
|
968
|
-
return
|
1012
|
+
return fs_iterator__update_entry(fi);
|
969
1013
|
}
|
970
1014
|
|
971
|
-
static int
|
1015
|
+
static int fs_iterator__current(
|
972
1016
|
const git_index_entry **entry, git_iterator *self)
|
973
1017
|
{
|
974
|
-
|
1018
|
+
fs_iterator *fi = (fs_iterator *)self;
|
1019
|
+
const git_index_entry *fe = (fi->entry.path == NULL) ? NULL : &fi->entry;
|
1020
|
+
|
975
1021
|
if (entry)
|
976
|
-
*entry =
|
977
|
-
|
1022
|
+
*entry = fe;
|
1023
|
+
|
1024
|
+
fi->base.flags |= GIT_ITERATOR_FIRST_ACCESS;
|
1025
|
+
|
1026
|
+
return (fe != NULL) ? 0 : GIT_ITEROVER;
|
978
1027
|
}
|
979
1028
|
|
980
|
-
static int
|
1029
|
+
static int fs_iterator__at_end(git_iterator *self)
|
981
1030
|
{
|
982
|
-
return (((
|
1031
|
+
return (((fs_iterator *)self)->entry.path == NULL);
|
983
1032
|
}
|
984
1033
|
|
985
|
-
static int
|
1034
|
+
static int fs_iterator__advance_into(
|
986
1035
|
const git_index_entry **entry, git_iterator *iter)
|
987
1036
|
{
|
988
1037
|
int error = 0;
|
989
|
-
|
1038
|
+
fs_iterator *fi = (fs_iterator *)iter;
|
990
1039
|
|
991
1040
|
iterator__clear_entry(entry);
|
992
1041
|
|
993
|
-
/*
|
994
|
-
*
|
995
|
-
*
|
1042
|
+
/* Allow you to explicitly advance into a commit/submodule (as well as a
|
1043
|
+
* tree) to avoid cases where an entry is mislabeled as a submodule in
|
1044
|
+
* the working directory. The fs iterator will never have COMMMIT
|
1045
|
+
* entries on it's own, but a wrapper might add them.
|
996
1046
|
*/
|
997
|
-
if (
|
998
|
-
(
|
999
|
-
|
1047
|
+
if (fi->entry.path != NULL &&
|
1048
|
+
(fi->entry.mode == GIT_FILEMODE_TREE ||
|
1049
|
+
fi->entry.mode == GIT_FILEMODE_COMMIT))
|
1000
1050
|
/* returns GIT_ENOTFOUND if the directory is empty */
|
1001
|
-
error =
|
1051
|
+
error = fs_iterator__expand_dir(fi);
|
1002
1052
|
|
1003
1053
|
if (!error && entry)
|
1004
|
-
error =
|
1054
|
+
error = fs_iterator__current(entry, iter);
|
1055
|
+
|
1056
|
+
if (!error && !fi->entry.path)
|
1057
|
+
error = GIT_ITEROVER;
|
1005
1058
|
|
1006
1059
|
return error;
|
1007
1060
|
}
|
1008
1061
|
|
1009
|
-
static int
|
1062
|
+
static int fs_iterator__advance_over(
|
1010
1063
|
const git_index_entry **entry, git_iterator *self)
|
1011
1064
|
{
|
1012
1065
|
int error = 0;
|
1013
|
-
|
1014
|
-
|
1066
|
+
fs_iterator *fi = (fs_iterator *)self;
|
1067
|
+
fs_iterator_frame *ff;
|
1015
1068
|
git_path_with_stat *next;
|
1016
1069
|
|
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
|
-
|
1031
1070
|
if (entry != NULL)
|
1032
1071
|
*entry = NULL;
|
1033
1072
|
|
1034
|
-
while (
|
1035
|
-
|
1036
|
-
next = git_vector_get(&
|
1073
|
+
while (fi->entry.path != NULL) {
|
1074
|
+
ff = fi->stack;
|
1075
|
+
next = git_vector_get(&ff->entries, ++ff->index);
|
1037
1076
|
|
1038
|
-
if (next != NULL)
|
1039
|
-
/* match git's behavior of ignoring anything named ".git" */
|
1040
|
-
if (path_is_dotgit(next))
|
1041
|
-
continue;
|
1042
|
-
/* else found a good entry */
|
1077
|
+
if (next != NULL)
|
1043
1078
|
break;
|
1044
|
-
}
|
1045
1079
|
|
1046
|
-
|
1047
|
-
if (!wf->next) {
|
1048
|
-
memset(&wi->entry, 0, sizeof(wi->entry));
|
1049
|
-
return 0;
|
1050
|
-
}
|
1051
|
-
|
1052
|
-
wi->stack = wf->next;
|
1053
|
-
wi->depth--;
|
1054
|
-
workdir_iterator__free_frame(wf);
|
1055
|
-
git_ignore__pop_dir(&wi->ignores);
|
1080
|
+
fs_iterator__pop_frame(fi, ff, false);
|
1056
1081
|
}
|
1057
1082
|
|
1058
|
-
error =
|
1083
|
+
error = fs_iterator__update_entry(fi);
|
1059
1084
|
|
1060
1085
|
if (!error && entry != NULL)
|
1061
|
-
error =
|
1086
|
+
error = fs_iterator__current(entry, self);
|
1062
1087
|
|
1063
1088
|
return error;
|
1064
1089
|
}
|
1065
1090
|
|
1066
|
-
static int
|
1091
|
+
static int fs_iterator__advance(
|
1092
|
+
const git_index_entry **entry, git_iterator *self)
|
1093
|
+
{
|
1094
|
+
fs_iterator *fi = (fs_iterator *)self;
|
1095
|
+
|
1096
|
+
if (!iterator__has_been_accessed(fi))
|
1097
|
+
return fs_iterator__current(entry, self);
|
1098
|
+
|
1099
|
+
/* given include_trees & autoexpand, we might have to go into a tree */
|
1100
|
+
if (iterator__do_autoexpand(fi) &&
|
1101
|
+
fi->entry.path != NULL &&
|
1102
|
+
fi->entry.mode == GIT_FILEMODE_TREE)
|
1103
|
+
{
|
1104
|
+
int error = fs_iterator__advance_into(entry, self);
|
1105
|
+
if (error != GIT_ENOTFOUND)
|
1106
|
+
return error;
|
1107
|
+
/* continue silently past empty directories if autoexpanding */
|
1108
|
+
giterr_clear();
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
return fs_iterator__advance_over(entry, self);
|
1112
|
+
}
|
1113
|
+
|
1114
|
+
static int fs_iterator__seek(git_iterator *self, const char *prefix)
|
1067
1115
|
{
|
1068
1116
|
GIT_UNUSED(self);
|
1069
1117
|
GIT_UNUSED(prefix);
|
@@ -1073,108 +1121,210 @@ static int workdir_iterator__seek(git_iterator *self, const char *prefix)
|
|
1073
1121
|
return 0;
|
1074
1122
|
}
|
1075
1123
|
|
1076
|
-
static int
|
1124
|
+
static int fs_iterator__reset(
|
1077
1125
|
git_iterator *self, const char *start, const char *end)
|
1078
1126
|
{
|
1079
|
-
|
1127
|
+
int error;
|
1128
|
+
fs_iterator *fi = (fs_iterator *)self;
|
1080
1129
|
|
1081
|
-
while (
|
1082
|
-
|
1083
|
-
|
1084
|
-
workdir_iterator__free_frame(wf);
|
1085
|
-
git_ignore__pop_dir(&wi->ignores);
|
1086
|
-
}
|
1087
|
-
wi->depth = 0;
|
1130
|
+
while (fi->stack != NULL && fi->stack->next != NULL)
|
1131
|
+
fs_iterator__pop_frame(fi, fi->stack, false);
|
1132
|
+
fi->depth = 0;
|
1088
1133
|
|
1089
|
-
if (iterator__reset_range(self, start, end) < 0)
|
1090
|
-
return
|
1134
|
+
if ((error = iterator__reset_range(self, start, end)) < 0)
|
1135
|
+
return error;
|
1136
|
+
|
1137
|
+
fs_iterator__seek_frame_start(fi, fi->stack);
|
1091
1138
|
|
1092
|
-
|
1139
|
+
error = fs_iterator__update_entry(fi);
|
1140
|
+
if (error == GIT_ITEROVER)
|
1141
|
+
error = 0;
|
1093
1142
|
|
1094
|
-
return
|
1143
|
+
return error;
|
1095
1144
|
}
|
1096
1145
|
|
1097
|
-
static void
|
1146
|
+
static void fs_iterator__free(git_iterator *self)
|
1098
1147
|
{
|
1099
|
-
|
1148
|
+
fs_iterator *fi = (fs_iterator *)self;
|
1100
1149
|
|
1101
|
-
while (
|
1102
|
-
|
1103
|
-
wi->stack = wf->next;
|
1104
|
-
workdir_iterator__free_frame(wf);
|
1105
|
-
}
|
1150
|
+
while (fi->stack != NULL)
|
1151
|
+
fs_iterator__pop_frame(fi, fi->stack, true);
|
1106
1152
|
|
1107
|
-
|
1108
|
-
git_buf_free(&wi->path);
|
1153
|
+
git_buf_free(&fi->path);
|
1109
1154
|
}
|
1110
1155
|
|
1111
|
-
static int
|
1156
|
+
static int fs_iterator__update_entry(fs_iterator *fi)
|
1112
1157
|
{
|
1113
|
-
|
1114
|
-
git_path_with_stat *ps =
|
1115
|
-
git_vector_get(&wi->stack->entries, wi->stack->index);
|
1158
|
+
git_path_with_stat *ps;
|
1116
1159
|
|
1117
|
-
|
1118
|
-
memset(&wi->entry, 0, sizeof(wi->entry));
|
1160
|
+
memset(&fi->entry, 0, sizeof(fi->entry));
|
1119
1161
|
|
1162
|
+
if (!fi->stack)
|
1163
|
+
return GIT_ITEROVER;
|
1164
|
+
|
1165
|
+
ps = git_vector_get(&fi->stack->entries, fi->stack->index);
|
1120
1166
|
if (!ps)
|
1121
|
-
return
|
1167
|
+
return GIT_ITEROVER;
|
1122
1168
|
|
1123
|
-
|
1124
|
-
if (
|
1125
|
-
return
|
1169
|
+
git_buf_truncate(&fi->path, fi->root_len);
|
1170
|
+
if (git_buf_put(&fi->path, ps->path, ps->path_len) < 0)
|
1171
|
+
return -1;
|
1126
1172
|
|
1127
|
-
if (
|
1173
|
+
if (iterator__past_end(fi, fi->path.ptr + fi->root_len))
|
1174
|
+
return GIT_ITEROVER;
|
1175
|
+
|
1176
|
+
fi->entry.path = ps->path;
|
1177
|
+
git_index_entry__init_from_stat(&fi->entry, &ps->st);
|
1178
|
+
|
1179
|
+
/* need different mode here to keep directories during iteration */
|
1180
|
+
fi->entry.mode = git_futils_canonical_mode(ps->st.st_mode);
|
1181
|
+
|
1182
|
+
/* allow wrapper to check/update the entry (can force skip) */
|
1183
|
+
if (fi->update_entry_cb &&
|
1184
|
+
fi->update_entry_cb(fi) == GIT_ENOTFOUND)
|
1185
|
+
return fs_iterator__advance_over(NULL, (git_iterator *)fi);
|
1186
|
+
|
1187
|
+
/* if this is a tree and trees aren't included, then skip */
|
1188
|
+
if (fi->entry.mode == GIT_FILEMODE_TREE && !iterator__include_trees(fi)) {
|
1189
|
+
int error = fs_iterator__advance_into(NULL, (git_iterator *)fi);
|
1190
|
+
if (error != GIT_ENOTFOUND)
|
1191
|
+
return error;
|
1192
|
+
giterr_clear();
|
1193
|
+
return fs_iterator__advance_over(NULL, (git_iterator *)fi);
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
return 0;
|
1197
|
+
}
|
1198
|
+
|
1199
|
+
static int fs_iterator__initialize(
|
1200
|
+
git_iterator **out, fs_iterator *fi, const char *root)
|
1201
|
+
{
|
1202
|
+
int error;
|
1203
|
+
|
1204
|
+
if (git_buf_sets(&fi->path, root) < 0 || git_path_to_dir(&fi->path) < 0) {
|
1205
|
+
git__free(fi);
|
1128
1206
|
return -1;
|
1207
|
+
}
|
1208
|
+
fi->root_len = fi->path.size;
|
1129
1209
|
|
1130
|
-
if (
|
1131
|
-
|
1210
|
+
if ((error = fs_iterator__expand_dir(fi)) < 0) {
|
1211
|
+
if (error == GIT_ENOTFOUND || error == GIT_ITEROVER) {
|
1212
|
+
giterr_clear();
|
1213
|
+
error = 0;
|
1214
|
+
} else {
|
1215
|
+
git_iterator_free((git_iterator *)fi);
|
1216
|
+
fi = NULL;
|
1217
|
+
}
|
1218
|
+
}
|
1132
1219
|
|
1133
|
-
|
1220
|
+
*out = (git_iterator *)fi;
|
1221
|
+
return error;
|
1222
|
+
}
|
1134
1223
|
|
1135
|
-
|
1224
|
+
int git_iterator_for_filesystem(
|
1225
|
+
git_iterator **out,
|
1226
|
+
const char *root,
|
1227
|
+
git_iterator_flag_t flags,
|
1228
|
+
const char *start,
|
1229
|
+
const char *end)
|
1230
|
+
{
|
1231
|
+
fs_iterator *fi = git__calloc(1, sizeof(fs_iterator));
|
1232
|
+
GITERR_CHECK_ALLOC(fi);
|
1136
1233
|
|
1137
|
-
|
1234
|
+
ITERATOR_BASE_INIT(fi, fs, FS, NULL);
|
1138
1235
|
|
1139
|
-
|
1140
|
-
|
1236
|
+
if ((flags & GIT_ITERATOR_IGNORE_CASE) != 0)
|
1237
|
+
fi->base.flags |= GIT_ITERATOR_IGNORE_CASE;
|
1141
1238
|
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1239
|
+
return fs_iterator__initialize(out, fi, root);
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
|
1243
|
+
typedef struct {
|
1244
|
+
fs_iterator fi;
|
1245
|
+
git_ignores ignores;
|
1246
|
+
int is_ignored;
|
1247
|
+
} workdir_iterator;
|
1248
|
+
|
1249
|
+
GIT_INLINE(bool) workdir_path_is_dotgit(const git_buf *path)
|
1250
|
+
{
|
1251
|
+
size_t len;
|
1252
|
+
|
1253
|
+
if (!path || (len = path->size) < 4)
|
1254
|
+
return false;
|
1255
|
+
|
1256
|
+
if (path->ptr[len - 1] == '/')
|
1257
|
+
len--;
|
1258
|
+
|
1259
|
+
if (tolower(path->ptr[len - 1]) != 't' ||
|
1260
|
+
tolower(path->ptr[len - 2]) != 'i' ||
|
1261
|
+
tolower(path->ptr[len - 3]) != 'g' ||
|
1262
|
+
tolower(path->ptr[len - 4]) != '.')
|
1263
|
+
return false;
|
1264
|
+
|
1265
|
+
return (len == 4 || path->ptr[len - 5] == '/');
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
static int workdir_iterator__enter_dir(fs_iterator *fi)
|
1269
|
+
{
|
1270
|
+
/* only push new ignores if this is not top level directory */
|
1271
|
+
if (fi->stack->next != NULL) {
|
1272
|
+
workdir_iterator *wi = (workdir_iterator *)fi;
|
1273
|
+
ssize_t slash_pos = git_buf_rfind_next(&fi->path, '/');
|
1274
|
+
|
1275
|
+
(void)git_ignore__push_dir(&wi->ignores, &fi->path.ptr[slash_pos + 1]);
|
1146
1276
|
}
|
1147
1277
|
|
1148
|
-
|
1149
|
-
|
1150
|
-
return 0;
|
1278
|
+
return 0;
|
1279
|
+
}
|
1151
1280
|
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1281
|
+
static int workdir_iterator__leave_dir(fs_iterator *fi)
|
1282
|
+
{
|
1283
|
+
workdir_iterator *wi = (workdir_iterator *)fi;
|
1284
|
+
git_ignore__pop_dir(&wi->ignores);
|
1285
|
+
return 0;
|
1286
|
+
}
|
1156
1287
|
|
1157
|
-
|
1158
|
-
|
1288
|
+
static int workdir_iterator__update_entry(fs_iterator *fi)
|
1289
|
+
{
|
1290
|
+
int error = 0;
|
1291
|
+
workdir_iterator *wi = (workdir_iterator *)fi;
|
1159
1292
|
|
1160
|
-
/*
|
1161
|
-
if (
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1293
|
+
/* skip over .git entries */
|
1294
|
+
if (workdir_path_is_dotgit(&fi->path))
|
1295
|
+
return GIT_ENOTFOUND;
|
1296
|
+
|
1297
|
+
/* reset is_ignored since we haven't checked yet */
|
1298
|
+
wi->is_ignored = -1;
|
1299
|
+
|
1300
|
+
/* check if apparent tree entries are actually submodules */
|
1301
|
+
if (fi->entry.mode != GIT_FILEMODE_TREE)
|
1166
1302
|
return 0;
|
1303
|
+
|
1304
|
+
error = git_submodule_lookup(NULL, fi->base.repo, fi->entry.path);
|
1305
|
+
if (error < 0)
|
1306
|
+
giterr_clear();
|
1307
|
+
|
1308
|
+
/* mark submodule (or any dir with .git) as GITLINK and remove slash */
|
1309
|
+
if (!error || error == GIT_EEXISTS) {
|
1310
|
+
fi->entry.mode = S_IFGITLINK;
|
1311
|
+
fi->entry.path[strlen(fi->entry.path) - 1] = '\0';
|
1167
1312
|
}
|
1168
1313
|
|
1169
|
-
|
1170
|
-
|
1314
|
+
return 0;
|
1315
|
+
}
|
1171
1316
|
|
1172
|
-
|
1317
|
+
static void workdir_iterator__free(git_iterator *self)
|
1318
|
+
{
|
1319
|
+
workdir_iterator *wi = (workdir_iterator *)self;
|
1320
|
+
fs_iterator__free(self);
|
1321
|
+
git_ignore__free(&wi->ignores);
|
1173
1322
|
}
|
1174
1323
|
|
1175
|
-
int
|
1176
|
-
git_iterator **
|
1324
|
+
int git_iterator_for_workdir_ext(
|
1325
|
+
git_iterator **out,
|
1177
1326
|
git_repository *repo,
|
1327
|
+
const char *repo_workdir,
|
1178
1328
|
git_iterator_flag_t flags,
|
1179
1329
|
const char *start,
|
1180
1330
|
const char *end)
|
@@ -1182,38 +1332,31 @@ int git_iterator_for_workdir(
|
|
1182
1332
|
int error;
|
1183
1333
|
workdir_iterator *wi;
|
1184
1334
|
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1335
|
+
if (!repo_workdir) {
|
1336
|
+
if (git_repository__ensure_not_bare(repo, "scan working directory") < 0)
|
1337
|
+
return GIT_EBAREREPO;
|
1338
|
+
repo_workdir = git_repository_workdir(repo);
|
1339
|
+
}
|
1190
1340
|
|
1191
|
-
|
1341
|
+
/* initialize as an fs iterator then do overrides */
|
1342
|
+
wi = git__calloc(1, sizeof(workdir_iterator));
|
1343
|
+
GITERR_CHECK_ALLOC(wi);
|
1344
|
+
ITERATOR_BASE_INIT((&wi->fi), fs, FS, repo);
|
1192
1345
|
|
1193
|
-
|
1194
|
-
|
1346
|
+
wi->fi.base.type = GIT_ITERATOR_TYPE_WORKDIR;
|
1347
|
+
wi->fi.cb.free = workdir_iterator__free;
|
1348
|
+
wi->fi.enter_dir_cb = workdir_iterator__enter_dir;
|
1349
|
+
wi->fi.leave_dir_cb = workdir_iterator__leave_dir;
|
1350
|
+
wi->fi.update_entry_cb = workdir_iterator__update_entry;
|
1195
1351
|
|
1196
|
-
if (
|
1197
|
-
|
1198
|
-
git_ignore__for_path(repo, "", &wi->ignores) < 0)
|
1352
|
+
if ((error = iterator__update_ignore_case((git_iterator *)wi, flags)) < 0 ||
|
1353
|
+
(error = git_ignore__for_path(repo, "", &wi->ignores)) < 0)
|
1199
1354
|
{
|
1200
|
-
|
1201
|
-
return
|
1202
|
-
}
|
1203
|
-
wi->root_len = wi->path.size;
|
1204
|
-
|
1205
|
-
if ((error = workdir_iterator__expand_dir(wi)) < 0) {
|
1206
|
-
if (error != GIT_ENOTFOUND)
|
1207
|
-
goto fail;
|
1208
|
-
giterr_clear();
|
1355
|
+
git_iterator_free((git_iterator *)wi);
|
1356
|
+
return error;
|
1209
1357
|
}
|
1210
1358
|
|
1211
|
-
|
1212
|
-
return 0;
|
1213
|
-
|
1214
|
-
fail:
|
1215
|
-
git_iterator_free((git_iterator *)wi);
|
1216
|
-
return error;
|
1359
|
+
return fs_iterator__initialize(out, &wi->fi, repo_workdir);
|
1217
1360
|
}
|
1218
1361
|
|
1219
1362
|
|
@@ -1315,7 +1458,8 @@ bool git_iterator_current_is_ignored(git_iterator *iter)
|
|
1315
1458
|
if (wi->is_ignored != -1)
|
1316
1459
|
return (bool)(wi->is_ignored != 0);
|
1317
1460
|
|
1318
|
-
if (git_ignore__lookup(
|
1461
|
+
if (git_ignore__lookup(
|
1462
|
+
&wi->ignores, wi->fi.entry.path, &wi->is_ignored) < 0)
|
1319
1463
|
wi->is_ignored = true;
|
1320
1464
|
|
1321
1465
|
return (bool)wi->is_ignored;
|
@@ -1340,10 +1484,10 @@ int git_iterator_current_workdir_path(git_buf **path, git_iterator *iter)
|
|
1340
1484
|
{
|
1341
1485
|
workdir_iterator *wi = (workdir_iterator *)iter;
|
1342
1486
|
|
1343
|
-
if (iter->type != GIT_ITERATOR_TYPE_WORKDIR || !wi->entry.path)
|
1487
|
+
if (iter->type != GIT_ITERATOR_TYPE_WORKDIR || !wi->fi.entry.path)
|
1344
1488
|
*path = NULL;
|
1345
1489
|
else
|
1346
|
-
*path = &wi->path;
|
1490
|
+
*path = &wi->fi.path;
|
1347
1491
|
|
1348
1492
|
return 0;
|
1349
1493
|
}
|