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
data/vendor/libgit2/src/delta.h
CHANGED
|
@@ -46,11 +46,12 @@ extern unsigned long git_delta_sizeof_index(struct git_delta_index *index);
|
|
|
46
46
|
* returned and *delta_size is updated with its size. The returned buffer
|
|
47
47
|
* must be freed by the caller.
|
|
48
48
|
*/
|
|
49
|
-
extern void *
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
extern void *git_delta_create(
|
|
50
|
+
const struct git_delta_index *index,
|
|
51
|
+
const void *buf,
|
|
52
|
+
unsigned long bufsize,
|
|
53
|
+
unsigned long *delta_size,
|
|
54
|
+
unsigned long max_delta_size);
|
|
54
55
|
|
|
55
56
|
/*
|
|
56
57
|
* diff_delta: create a delta from source buffer to target buffer
|
|
@@ -60,15 +61,16 @@ git_delta_create(const struct git_delta_index *index,
|
|
|
60
61
|
* pointer to the buffer with the delta data is returned and *delta_size is
|
|
61
62
|
* updated with its size. The returned buffer must be freed by the caller.
|
|
62
63
|
*/
|
|
63
|
-
GIT_INLINE(void *)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
GIT_INLINE(void *) git_delta(
|
|
65
|
+
const void *src_buf, unsigned long src_bufsize,
|
|
66
|
+
const void *trg_buf, unsigned long trg_bufsize,
|
|
67
|
+
unsigned long *delta_size,
|
|
68
|
+
unsigned long max_delta_size)
|
|
67
69
|
{
|
|
68
70
|
struct git_delta_index *index = git_delta_create_index(src_buf, src_bufsize);
|
|
69
71
|
if (index) {
|
|
70
|
-
void *delta = git_delta_create(
|
|
71
|
-
|
|
72
|
+
void *delta = git_delta_create(
|
|
73
|
+
index, trg_buf, trg_bufsize, delta_size, max_delta_size);
|
|
72
74
|
git_delta_free_index(index);
|
|
73
75
|
return delta;
|
|
74
76
|
}
|
|
@@ -82,9 +84,10 @@ git_delta(const void *src_buf, unsigned long src_bufsize,
|
|
|
82
84
|
* *trg_bufsize is updated with its size. On failure a NULL pointer is
|
|
83
85
|
* returned. The returned buffer must be freed by the caller.
|
|
84
86
|
*/
|
|
85
|
-
extern void *git_delta_patch(
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
extern void *git_delta_patch(
|
|
88
|
+
const void *src_buf, unsigned long src_size,
|
|
89
|
+
const void *delta_buf, unsigned long delta_size,
|
|
90
|
+
unsigned long *dst_size);
|
|
88
91
|
|
|
89
92
|
/* the smallest possible delta size is 4 bytes */
|
|
90
93
|
#define GIT_DELTA_SIZE_MIN 4
|
|
@@ -93,9 +96,8 @@ extern void *git_delta_patch(const void *src_buf, unsigned long src_size,
|
|
|
93
96
|
* This must be called twice on the delta data buffer, first to get the
|
|
94
97
|
* expected source buffer size, and again to get the target buffer size.
|
|
95
98
|
*/
|
|
96
|
-
GIT_INLINE(unsigned long)
|
|
97
|
-
|
|
98
|
-
const unsigned char *top)
|
|
99
|
+
GIT_INLINE(unsigned long) git_delta_get_hdr_size(
|
|
100
|
+
const unsigned char **datap, const unsigned char *top)
|
|
99
101
|
{
|
|
100
102
|
const unsigned char *data = *datap;
|
|
101
103
|
unsigned long cmd, size = 0;
|
data/vendor/libgit2/src/diff.c
CHANGED
|
@@ -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,76 +10,10 @@
|
|
|
10
10
|
#include "config.h"
|
|
11
11
|
#include "attr_file.h"
|
|
12
12
|
#include "filter.h"
|
|
13
|
+
#include "pathspec.h"
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
git_buf prefix = GIT_BUF_INIT;
|
|
17
|
-
const char *scan;
|
|
18
|
-
|
|
19
|
-
if (git_buf_common_prefix(&prefix, pathspec) < 0)
|
|
20
|
-
return NULL;
|
|
21
|
-
|
|
22
|
-
/* diff prefix will only be leading non-wildcards */
|
|
23
|
-
for (scan = prefix.ptr; *scan; ++scan) {
|
|
24
|
-
if (git__iswildcard(*scan) &&
|
|
25
|
-
(scan == prefix.ptr || (*(scan - 1) != '\\')))
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
git_buf_truncate(&prefix, scan - prefix.ptr);
|
|
29
|
-
|
|
30
|
-
if (prefix.size <= 0) {
|
|
31
|
-
git_buf_free(&prefix);
|
|
32
|
-
return NULL;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
git_buf_unescape(&prefix);
|
|
36
|
-
|
|
37
|
-
return git_buf_detach(&prefix);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
static bool diff_pathspec_is_interesting(const git_strarray *pathspec)
|
|
41
|
-
{
|
|
42
|
-
const char *str;
|
|
43
|
-
|
|
44
|
-
if (pathspec == NULL || pathspec->count == 0)
|
|
45
|
-
return false;
|
|
46
|
-
if (pathspec->count > 1)
|
|
47
|
-
return true;
|
|
48
|
-
|
|
49
|
-
str = pathspec->strings[0];
|
|
50
|
-
if (!str || !str[0] || (!str[1] && (str[0] == '*' || str[0] == '.')))
|
|
51
|
-
return false;
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static bool diff_path_matches_pathspec(git_diff_list *diff, const char *path)
|
|
56
|
-
{
|
|
57
|
-
unsigned int i;
|
|
58
|
-
git_attr_fnmatch *match;
|
|
59
|
-
|
|
60
|
-
if (!diff->pathspec.length)
|
|
61
|
-
return true;
|
|
62
|
-
|
|
63
|
-
git_vector_foreach(&diff->pathspec, i, match) {
|
|
64
|
-
int result = strcmp(match->pattern, path) ? FNM_NOMATCH : 0;
|
|
65
|
-
|
|
66
|
-
if (((diff->opts.flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH) == 0) &&
|
|
67
|
-
result == FNM_NOMATCH)
|
|
68
|
-
result = p_fnmatch(match->pattern, path, 0);
|
|
69
|
-
|
|
70
|
-
/* if we didn't match, look for exact dirname prefix match */
|
|
71
|
-
if (result == FNM_NOMATCH &&
|
|
72
|
-
(match->flags & GIT_ATTR_FNMATCH_HASWILD) == 0 &&
|
|
73
|
-
strncmp(path, match->pattern, match->length) == 0 &&
|
|
74
|
-
path[match->length] == '/')
|
|
75
|
-
result = 0;
|
|
76
|
-
|
|
77
|
-
if (result == 0)
|
|
78
|
-
return (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) ? false : true;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
15
|
+
#define DIFF_FLAG_IS_SET(DIFF,FLAG) (((DIFF)->opts.flags & (FLAG)) != 0)
|
|
16
|
+
#define DIFF_FLAG_ISNT_SET(DIFF,FLAG) (((DIFF)->opts.flags & (FLAG)) == 0)
|
|
83
17
|
|
|
84
18
|
static git_diff_delta *diff_delta__alloc(
|
|
85
19
|
git_diff_list *diff,
|
|
@@ -98,7 +32,7 @@ static git_diff_delta *diff_delta__alloc(
|
|
|
98
32
|
|
|
99
33
|
delta->new_file.path = delta->old_file.path;
|
|
100
34
|
|
|
101
|
-
if (diff
|
|
35
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) {
|
|
102
36
|
switch (status) {
|
|
103
37
|
case GIT_DELTA_ADDED: status = GIT_DELTA_DELETED; break;
|
|
104
38
|
case GIT_DELTA_DELETED: status = GIT_DELTA_ADDED; break;
|
|
@@ -110,83 +44,16 @@ static git_diff_delta *diff_delta__alloc(
|
|
|
110
44
|
return delta;
|
|
111
45
|
}
|
|
112
46
|
|
|
113
|
-
static
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!delta)
|
|
118
|
-
return NULL;
|
|
119
|
-
|
|
120
|
-
memcpy(delta, d, sizeof(git_diff_delta));
|
|
121
|
-
|
|
122
|
-
delta->old_file.path = git_pool_strdup(pool, d->old_file.path);
|
|
123
|
-
if (delta->old_file.path == NULL)
|
|
124
|
-
goto fail;
|
|
125
|
-
|
|
126
|
-
if (d->new_file.path != d->old_file.path) {
|
|
127
|
-
delta->new_file.path = git_pool_strdup(pool, d->new_file.path);
|
|
128
|
-
if (delta->new_file.path == NULL)
|
|
129
|
-
goto fail;
|
|
130
|
-
} else {
|
|
131
|
-
delta->new_file.path = delta->old_file.path;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return delta;
|
|
135
|
-
|
|
136
|
-
fail:
|
|
137
|
-
git__free(delta);
|
|
138
|
-
return NULL;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
static git_diff_delta *diff_delta__merge_like_cgit(
|
|
142
|
-
const git_diff_delta *a, const git_diff_delta *b, git_pool *pool)
|
|
47
|
+
static int diff_notify(
|
|
48
|
+
const git_diff_list *diff,
|
|
49
|
+
const git_diff_delta *delta,
|
|
50
|
+
const char *matched_pathspec)
|
|
143
51
|
{
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
/* Emulate C git for merging two diffs (a la 'git diff <sha>').
|
|
147
|
-
*
|
|
148
|
-
* When C git does a diff between the work dir and a tree, it actually
|
|
149
|
-
* diffs with the index but uses the workdir contents. This emulates
|
|
150
|
-
* those choices so we can emulate the type of diff.
|
|
151
|
-
*
|
|
152
|
-
* We have three file descriptions here, let's call them:
|
|
153
|
-
* f1 = a->old_file
|
|
154
|
-
* f2 = a->new_file AND b->old_file
|
|
155
|
-
* f3 = b->new_file
|
|
156
|
-
*/
|
|
157
|
-
|
|
158
|
-
/* if f2 == f3 or f2 is deleted, then just dup the 'a' diff */
|
|
159
|
-
if (b->status == GIT_DELTA_UNMODIFIED || a->status == GIT_DELTA_DELETED)
|
|
160
|
-
return diff_delta__dup(a, pool);
|
|
161
|
-
|
|
162
|
-
/* otherwise, base this diff on the 'b' diff */
|
|
163
|
-
if ((dup = diff_delta__dup(b, pool)) == NULL)
|
|
164
|
-
return NULL;
|
|
165
|
-
|
|
166
|
-
/* If 'a' status is uninteresting, then we're done */
|
|
167
|
-
if (a->status == GIT_DELTA_UNMODIFIED)
|
|
168
|
-
return dup;
|
|
169
|
-
|
|
170
|
-
assert(a->status != GIT_DELTA_UNMODIFIED);
|
|
171
|
-
assert(b->status != GIT_DELTA_UNMODIFIED);
|
|
172
|
-
|
|
173
|
-
/* A cgit exception is that the diff of a file that is only in the
|
|
174
|
-
* index (i.e. not in HEAD nor workdir) is given as empty.
|
|
175
|
-
*/
|
|
176
|
-
if (dup->status == GIT_DELTA_DELETED) {
|
|
177
|
-
if (a->status == GIT_DELTA_ADDED)
|
|
178
|
-
dup->status = GIT_DELTA_UNMODIFIED;
|
|
179
|
-
/* else don't overwrite DELETE status */
|
|
180
|
-
} else {
|
|
181
|
-
dup->status = a->status;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
git_oid_cpy(&dup->old_file.oid, &a->old_file.oid);
|
|
185
|
-
dup->old_file.mode = a->old_file.mode;
|
|
186
|
-
dup->old_file.size = a->old_file.size;
|
|
187
|
-
dup->old_file.flags = a->old_file.flags;
|
|
52
|
+
if (!diff->opts.notify_cb)
|
|
53
|
+
return 0;
|
|
188
54
|
|
|
189
|
-
return
|
|
55
|
+
return diff->opts.notify_cb(
|
|
56
|
+
diff, delta, matched_pathspec, diff->opts.notify_payload);
|
|
190
57
|
}
|
|
191
58
|
|
|
192
59
|
static int diff_delta__from_one(
|
|
@@ -195,16 +62,26 @@ static int diff_delta__from_one(
|
|
|
195
62
|
const git_index_entry *entry)
|
|
196
63
|
{
|
|
197
64
|
git_diff_delta *delta;
|
|
65
|
+
const char *matched_pathspec;
|
|
66
|
+
int notify_res;
|
|
198
67
|
|
|
199
68
|
if (status == GIT_DELTA_IGNORED &&
|
|
200
|
-
(diff
|
|
69
|
+
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_IGNORED))
|
|
201
70
|
return 0;
|
|
202
71
|
|
|
203
72
|
if (status == GIT_DELTA_UNTRACKED &&
|
|
204
|
-
(diff
|
|
73
|
+
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED))
|
|
74
|
+
return 0;
|
|
75
|
+
|
|
76
|
+
if (entry->mode == GIT_FILEMODE_COMMIT &&
|
|
77
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES))
|
|
205
78
|
return 0;
|
|
206
79
|
|
|
207
|
-
if (!
|
|
80
|
+
if (!git_pathspec_match_path(
|
|
81
|
+
&diff->pathspec, entry->path,
|
|
82
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH),
|
|
83
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE),
|
|
84
|
+
&matched_pathspec))
|
|
208
85
|
return 0;
|
|
209
86
|
|
|
210
87
|
delta = diff_delta__alloc(diff, status, entry->path);
|
|
@@ -223,18 +100,22 @@ static int diff_delta__from_one(
|
|
|
223
100
|
git_oid_cpy(&delta->new_file.oid, &entry->oid);
|
|
224
101
|
}
|
|
225
102
|
|
|
226
|
-
delta->old_file.flags |=
|
|
103
|
+
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
|
|
227
104
|
|
|
228
105
|
if (delta->status == GIT_DELTA_DELETED ||
|
|
229
106
|
!git_oid_iszero(&delta->new_file.oid))
|
|
230
|
-
delta->new_file.flags |=
|
|
107
|
+
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
|
|
231
108
|
|
|
232
|
-
|
|
109
|
+
notify_res = diff_notify(diff, delta, matched_pathspec);
|
|
110
|
+
|
|
111
|
+
if (notify_res)
|
|
112
|
+
git__free(delta);
|
|
113
|
+
else if (git_vector_insert(&diff->deltas, delta) < 0) {
|
|
233
114
|
git__free(delta);
|
|
234
115
|
return -1;
|
|
235
116
|
}
|
|
236
117
|
|
|
237
|
-
return 0;
|
|
118
|
+
return notify_res < 0 ? GIT_EUSER : 0;
|
|
238
119
|
}
|
|
239
120
|
|
|
240
121
|
static int diff_delta__from_two(
|
|
@@ -244,15 +125,22 @@ static int diff_delta__from_two(
|
|
|
244
125
|
uint32_t old_mode,
|
|
245
126
|
const git_index_entry *new_entry,
|
|
246
127
|
uint32_t new_mode,
|
|
247
|
-
git_oid *new_oid
|
|
128
|
+
git_oid *new_oid,
|
|
129
|
+
const char *matched_pathspec)
|
|
248
130
|
{
|
|
249
131
|
git_diff_delta *delta;
|
|
132
|
+
int notify_res;
|
|
250
133
|
|
|
251
134
|
if (status == GIT_DELTA_UNMODIFIED &&
|
|
252
|
-
(diff
|
|
135
|
+
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNMODIFIED))
|
|
136
|
+
return 0;
|
|
137
|
+
|
|
138
|
+
if (old_entry->mode == GIT_FILEMODE_COMMIT &&
|
|
139
|
+
new_entry->mode == GIT_FILEMODE_COMMIT &&
|
|
140
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES))
|
|
253
141
|
return 0;
|
|
254
142
|
|
|
255
|
-
if ((diff
|
|
143
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) {
|
|
256
144
|
uint32_t temp_mode = old_mode;
|
|
257
145
|
const git_index_entry *temp_entry = old_entry;
|
|
258
146
|
old_entry = new_entry;
|
|
@@ -267,28 +155,32 @@ static int diff_delta__from_two(
|
|
|
267
155
|
git_oid_cpy(&delta->old_file.oid, &old_entry->oid);
|
|
268
156
|
delta->old_file.size = old_entry->file_size;
|
|
269
157
|
delta->old_file.mode = old_mode;
|
|
270
|
-
delta->old_file.flags |=
|
|
158
|
+
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
|
|
271
159
|
|
|
272
160
|
git_oid_cpy(&delta->new_file.oid, &new_entry->oid);
|
|
273
161
|
delta->new_file.size = new_entry->file_size;
|
|
274
162
|
delta->new_file.mode = new_mode;
|
|
275
163
|
|
|
276
164
|
if (new_oid) {
|
|
277
|
-
if ((diff
|
|
165
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE))
|
|
278
166
|
git_oid_cpy(&delta->old_file.oid, new_oid);
|
|
279
167
|
else
|
|
280
168
|
git_oid_cpy(&delta->new_file.oid, new_oid);
|
|
281
169
|
}
|
|
282
170
|
|
|
283
171
|
if (new_oid || !git_oid_iszero(&new_entry->oid))
|
|
284
|
-
delta->new_file.flags |=
|
|
172
|
+
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
|
|
285
173
|
|
|
286
|
-
|
|
174
|
+
notify_res = diff_notify(diff, delta, matched_pathspec);
|
|
175
|
+
|
|
176
|
+
if (notify_res)
|
|
177
|
+
git__free(delta);
|
|
178
|
+
else if (git_vector_insert(&diff->deltas, delta) < 0) {
|
|
287
179
|
git__free(delta);
|
|
288
180
|
return -1;
|
|
289
181
|
}
|
|
290
182
|
|
|
291
|
-
return 0;
|
|
183
|
+
return notify_res < 0 ? GIT_EUSER : 0;
|
|
292
184
|
}
|
|
293
185
|
|
|
294
186
|
static git_diff_delta *diff_delta__last_for_item(
|
|
@@ -309,6 +201,11 @@ static git_diff_delta *diff_delta__last_for_item(
|
|
|
309
201
|
if (git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
|
310
202
|
return delta;
|
|
311
203
|
break;
|
|
204
|
+
case GIT_DELTA_UNTRACKED:
|
|
205
|
+
if (diff->strcomp(delta->new_file.path, item->path) == 0 &&
|
|
206
|
+
git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
|
207
|
+
return delta;
|
|
208
|
+
break;
|
|
312
209
|
case GIT_DELTA_MODIFIED:
|
|
313
210
|
if (git_oid_cmp(&delta->old_file.oid, &item->oid) == 0 ||
|
|
314
211
|
git_oid_cmp(&delta->new_file.oid, &item->oid) == 0)
|
|
@@ -332,13 +229,34 @@ static char *diff_strdup_prefix(git_pool *pool, const char *prefix)
|
|
|
332
229
|
return git_pool_strndup(pool, prefix, len + 1);
|
|
333
230
|
}
|
|
334
231
|
|
|
335
|
-
|
|
232
|
+
int git_diff_delta__cmp(const void *a, const void *b)
|
|
336
233
|
{
|
|
337
234
|
const git_diff_delta *da = a, *db = b;
|
|
338
235
|
int val = strcmp(da->old_file.path, db->old_file.path);
|
|
339
236
|
return val ? val : ((int)da->status - (int)db->status);
|
|
340
237
|
}
|
|
341
238
|
|
|
239
|
+
bool git_diff_delta__should_skip(
|
|
240
|
+
const git_diff_options *opts, const git_diff_delta *delta)
|
|
241
|
+
{
|
|
242
|
+
uint32_t flags = opts ? opts->flags : 0;
|
|
243
|
+
|
|
244
|
+
if (delta->status == GIT_DELTA_UNMODIFIED &&
|
|
245
|
+
(flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
|
|
246
|
+
return true;
|
|
247
|
+
|
|
248
|
+
if (delta->status == GIT_DELTA_IGNORED &&
|
|
249
|
+
(flags & GIT_DIFF_INCLUDE_IGNORED) == 0)
|
|
250
|
+
return true;
|
|
251
|
+
|
|
252
|
+
if (delta->status == GIT_DELTA_UNTRACKED &&
|
|
253
|
+
(flags & GIT_DIFF_INCLUDE_UNTRACKED) == 0)
|
|
254
|
+
return true;
|
|
255
|
+
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
342
260
|
static int config_bool(git_config *cfg, const char *name, int defvalue)
|
|
343
261
|
{
|
|
344
262
|
int val = defvalue;
|
|
@@ -353,7 +271,6 @@ static git_diff_list *git_diff_list_alloc(
|
|
|
353
271
|
git_repository *repo, const git_diff_options *opts)
|
|
354
272
|
{
|
|
355
273
|
git_config *cfg;
|
|
356
|
-
size_t i;
|
|
357
274
|
git_diff_list *diff = git__calloc(1, sizeof(git_diff_list));
|
|
358
275
|
if (diff == NULL)
|
|
359
276
|
return NULL;
|
|
@@ -361,7 +278,7 @@ static git_diff_list *git_diff_list_alloc(
|
|
|
361
278
|
GIT_REFCOUNT_INC(diff);
|
|
362
279
|
diff->repo = repo;
|
|
363
280
|
|
|
364
|
-
if (git_vector_init(&diff->deltas, 0,
|
|
281
|
+
if (git_vector_init(&diff->deltas, 0, git_diff_delta__cmp) < 0 ||
|
|
365
282
|
git_pool_init(&diff->pool, 1, 0) < 0)
|
|
366
283
|
goto fail;
|
|
367
284
|
|
|
@@ -378,11 +295,31 @@ static git_diff_list *git_diff_list_alloc(
|
|
|
378
295
|
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_CTIME;
|
|
379
296
|
/* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */
|
|
380
297
|
|
|
381
|
-
if
|
|
298
|
+
/* TODO: there are certain config settings where even if we were
|
|
299
|
+
* not given an options structure, we need the diff list to have one
|
|
300
|
+
* so that we can store the altered default values.
|
|
301
|
+
*
|
|
302
|
+
* - diff.ignoreSubmodules
|
|
303
|
+
* - diff.mnemonicprefix
|
|
304
|
+
* - diff.noprefix
|
|
305
|
+
*/
|
|
306
|
+
|
|
307
|
+
if (opts == NULL) {
|
|
308
|
+
/* Make sure we default to 3 lines */
|
|
309
|
+
diff->opts.context_lines = 3;
|
|
382
310
|
return diff;
|
|
311
|
+
}
|
|
383
312
|
|
|
384
313
|
memcpy(&diff->opts, opts, sizeof(git_diff_options));
|
|
385
|
-
|
|
314
|
+
|
|
315
|
+
if(opts->flags & GIT_DIFF_IGNORE_FILEMODE)
|
|
316
|
+
diff->diffcaps = diff->diffcaps & ~GIT_DIFFCAPS_TRUST_MODE_BITS;
|
|
317
|
+
|
|
318
|
+
/* pathspec init will do nothing for empty pathspec */
|
|
319
|
+
if (git_pathspec_init(&diff->pathspec, &opts->pathspec, &diff->pool) < 0)
|
|
320
|
+
goto fail;
|
|
321
|
+
|
|
322
|
+
/* TODO: handle config diff.mnemonicprefix, diff.noprefix */
|
|
386
323
|
|
|
387
324
|
diff->opts.old_prefix = diff_strdup_prefix(&diff->pool,
|
|
388
325
|
opts->old_prefix ? opts->old_prefix : DIFF_OLD_PREFIX_DEFAULT);
|
|
@@ -392,45 +329,16 @@ static git_diff_list *git_diff_list_alloc(
|
|
|
392
329
|
if (!diff->opts.old_prefix || !diff->opts.new_prefix)
|
|
393
330
|
goto fail;
|
|
394
331
|
|
|
395
|
-
if (diff
|
|
396
|
-
char *swap = diff->opts.old_prefix;
|
|
332
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) {
|
|
333
|
+
const char *swap = diff->opts.old_prefix;
|
|
397
334
|
diff->opts.old_prefix = diff->opts.new_prefix;
|
|
398
335
|
diff->opts.new_prefix = swap;
|
|
399
336
|
}
|
|
400
337
|
|
|
401
338
|
/* INCLUDE_TYPECHANGE_TREES implies INCLUDE_TYPECHANGE */
|
|
402
|
-
if (diff
|
|
339
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE_TREES))
|
|
403
340
|
diff->opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE;
|
|
404
341
|
|
|
405
|
-
/* only copy pathspec if it is "interesting" so we can test
|
|
406
|
-
* diff->pathspec.length > 0 to know if it is worth calling
|
|
407
|
-
* fnmatch as we iterate.
|
|
408
|
-
*/
|
|
409
|
-
if (!diff_pathspec_is_interesting(&opts->pathspec))
|
|
410
|
-
return diff;
|
|
411
|
-
|
|
412
|
-
if (git_vector_init(
|
|
413
|
-
&diff->pathspec, (unsigned int)opts->pathspec.count, NULL) < 0)
|
|
414
|
-
goto fail;
|
|
415
|
-
|
|
416
|
-
for (i = 0; i < opts->pathspec.count; ++i) {
|
|
417
|
-
int ret;
|
|
418
|
-
const char *pattern = opts->pathspec.strings[i];
|
|
419
|
-
git_attr_fnmatch *match = git__calloc(1, sizeof(git_attr_fnmatch));
|
|
420
|
-
if (!match)
|
|
421
|
-
goto fail;
|
|
422
|
-
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE;
|
|
423
|
-
ret = git_attr_fnmatch__parse(match, &diff->pool, NULL, &pattern);
|
|
424
|
-
if (ret == GIT_ENOTFOUND) {
|
|
425
|
-
git__free(match);
|
|
426
|
-
continue;
|
|
427
|
-
} else if (ret < 0)
|
|
428
|
-
goto fail;
|
|
429
|
-
|
|
430
|
-
if (git_vector_insert(&diff->pathspec, match) < 0)
|
|
431
|
-
goto fail;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
342
|
return diff;
|
|
435
343
|
|
|
436
344
|
fail:
|
|
@@ -441,7 +349,6 @@ fail:
|
|
|
441
349
|
static void diff_list_free(git_diff_list *diff)
|
|
442
350
|
{
|
|
443
351
|
git_diff_delta *delta;
|
|
444
|
-
git_attr_fnmatch *match;
|
|
445
352
|
unsigned int i;
|
|
446
353
|
|
|
447
354
|
git_vector_foreach(&diff->deltas, i, delta) {
|
|
@@ -450,12 +357,7 @@ static void diff_list_free(git_diff_list *diff)
|
|
|
450
357
|
}
|
|
451
358
|
git_vector_free(&diff->deltas);
|
|
452
359
|
|
|
453
|
-
|
|
454
|
-
git__free(match);
|
|
455
|
-
diff->pathspec.contents[i] = NULL;
|
|
456
|
-
}
|
|
457
|
-
git_vector_free(&diff->pathspec);
|
|
458
|
-
|
|
360
|
+
git_pathspec_free(&diff->pathspec);
|
|
459
361
|
git_pool_clear(&diff->pool);
|
|
460
362
|
git__free(diff);
|
|
461
363
|
}
|
|
@@ -473,25 +375,40 @@ void git_diff_list_addref(git_diff_list *diff)
|
|
|
473
375
|
GIT_REFCOUNT_INC(diff);
|
|
474
376
|
}
|
|
475
377
|
|
|
476
|
-
|
|
378
|
+
int git_diff__oid_for_file(
|
|
477
379
|
git_repository *repo,
|
|
478
|
-
const
|
|
380
|
+
const char *path,
|
|
381
|
+
uint16_t mode,
|
|
382
|
+
git_off_t size,
|
|
479
383
|
git_oid *oid)
|
|
480
384
|
{
|
|
481
385
|
int result = 0;
|
|
482
386
|
git_buf full_path = GIT_BUF_INIT;
|
|
483
387
|
|
|
484
388
|
if (git_buf_joinpath(
|
|
485
|
-
&full_path, git_repository_workdir(repo),
|
|
389
|
+
&full_path, git_repository_workdir(repo), path) < 0)
|
|
486
390
|
return -1;
|
|
487
391
|
|
|
392
|
+
if (!mode) {
|
|
393
|
+
struct stat st;
|
|
394
|
+
|
|
395
|
+
if (p_stat(path, &st) < 0) {
|
|
396
|
+
giterr_set(GITERR_OS, "Could not stat '%s'", path);
|
|
397
|
+
result = -1;
|
|
398
|
+
goto cleanup;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
mode = st.st_mode;
|
|
402
|
+
size = st.st_size;
|
|
403
|
+
}
|
|
404
|
+
|
|
488
405
|
/* calculate OID for file if possible */
|
|
489
|
-
if (S_ISGITLINK(
|
|
406
|
+
if (S_ISGITLINK(mode)) {
|
|
490
407
|
git_submodule *sm;
|
|
491
408
|
const git_oid *sm_oid;
|
|
492
409
|
|
|
493
|
-
if (!git_submodule_lookup(&sm, repo,
|
|
494
|
-
(sm_oid =
|
|
410
|
+
if (!git_submodule_lookup(&sm, repo, path) &&
|
|
411
|
+
(sm_oid = git_submodule_wd_id(sm)) != NULL)
|
|
495
412
|
git_oid_cpy(oid, sm_oid);
|
|
496
413
|
else {
|
|
497
414
|
/* if submodule lookup failed probably just in an intermediate
|
|
@@ -500,23 +417,22 @@ static int oid_for_workdir_item(
|
|
|
500
417
|
giterr_clear();
|
|
501
418
|
memset(oid, 0, sizeof(*oid));
|
|
502
419
|
}
|
|
503
|
-
} else if (S_ISLNK(
|
|
420
|
+
} else if (S_ISLNK(mode)) {
|
|
504
421
|
result = git_odb__hashlink(oid, full_path.ptr);
|
|
505
|
-
else if (!git__is_sizet(
|
|
506
|
-
giterr_set(GITERR_OS, "File size overflow for 32-
|
|
422
|
+
} else if (!git__is_sizet(size)) {
|
|
423
|
+
giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", path);
|
|
507
424
|
result = -1;
|
|
508
425
|
} else {
|
|
509
426
|
git_vector filters = GIT_VECTOR_INIT;
|
|
510
427
|
|
|
511
|
-
result = git_filters_load(
|
|
512
|
-
&filters, repo, item->path, GIT_FILTER_TO_ODB);
|
|
428
|
+
result = git_filters_load(&filters, repo, path, GIT_FILTER_TO_ODB);
|
|
513
429
|
if (result >= 0) {
|
|
514
430
|
int fd = git_futils_open_ro(full_path.ptr);
|
|
515
431
|
if (fd < 0)
|
|
516
432
|
result = fd;
|
|
517
433
|
else {
|
|
518
434
|
result = git_odb__hashfd_filtered(
|
|
519
|
-
oid, fd, (size_t)
|
|
435
|
+
oid, fd, (size_t)size, GIT_OBJ_BLOB, &filters);
|
|
520
436
|
p_close(fd);
|
|
521
437
|
}
|
|
522
438
|
}
|
|
@@ -524,8 +440,8 @@ static int oid_for_workdir_item(
|
|
|
524
440
|
git_filters_free(&filters);
|
|
525
441
|
}
|
|
526
442
|
|
|
443
|
+
cleanup:
|
|
527
444
|
git_buf_free(&full_path);
|
|
528
|
-
|
|
529
445
|
return result;
|
|
530
446
|
}
|
|
531
447
|
|
|
@@ -542,11 +458,16 @@ static int maybe_modified(
|
|
|
542
458
|
git_delta_t status = GIT_DELTA_MODIFIED;
|
|
543
459
|
unsigned int omode = oitem->mode;
|
|
544
460
|
unsigned int nmode = nitem->mode;
|
|
545
|
-
bool new_is_workdir = (new_iter->type ==
|
|
461
|
+
bool new_is_workdir = (new_iter->type == GIT_ITERATOR_TYPE_WORKDIR);
|
|
462
|
+
const char *matched_pathspec;
|
|
546
463
|
|
|
547
464
|
GIT_UNUSED(old_iter);
|
|
548
465
|
|
|
549
|
-
if (!
|
|
466
|
+
if (!git_pathspec_match_path(
|
|
467
|
+
&diff->pathspec, oitem->path,
|
|
468
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH),
|
|
469
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE),
|
|
470
|
+
&matched_pathspec))
|
|
550
471
|
return 0;
|
|
551
472
|
|
|
552
473
|
/* on platforms with no symlinks, preserve mode of existing symlinks */
|
|
@@ -571,7 +492,7 @@ static int maybe_modified(
|
|
|
571
492
|
|
|
572
493
|
/* if basic type of file changed, then split into delete and add */
|
|
573
494
|
else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) {
|
|
574
|
-
if ((diff
|
|
495
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE))
|
|
575
496
|
status = GIT_DELTA_TYPECHANGE;
|
|
576
497
|
else {
|
|
577
498
|
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
|
|
@@ -582,8 +503,7 @@ static int maybe_modified(
|
|
|
582
503
|
}
|
|
583
504
|
|
|
584
505
|
/* if oids and modes match, then file is unmodified */
|
|
585
|
-
else if (
|
|
586
|
-
omode == nmode)
|
|
506
|
+
else if (git_oid_equal(&oitem->oid, &nitem->oid) && omode == nmode)
|
|
587
507
|
status = GIT_DELTA_UNMODIFIED;
|
|
588
508
|
|
|
589
509
|
/* if we have an unknown OID and a workdir iterator, then check some
|
|
@@ -606,24 +526,32 @@ static int maybe_modified(
|
|
|
606
526
|
status = GIT_DELTA_UNMODIFIED;
|
|
607
527
|
|
|
608
528
|
else if (S_ISGITLINK(nmode)) {
|
|
529
|
+
int err;
|
|
609
530
|
git_submodule *sub;
|
|
610
531
|
|
|
611
|
-
if ((diff
|
|
532
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES))
|
|
612
533
|
status = GIT_DELTA_UNMODIFIED;
|
|
613
|
-
else if (git_submodule_lookup(&sub, diff->repo, nitem->path) < 0)
|
|
614
|
-
|
|
615
|
-
|
|
534
|
+
else if ((err = git_submodule_lookup(&sub, diff->repo, nitem->path)) < 0) {
|
|
535
|
+
if (err == GIT_EEXISTS)
|
|
536
|
+
status = GIT_DELTA_UNMODIFIED;
|
|
537
|
+
else
|
|
538
|
+
return err;
|
|
539
|
+
} else if (git_submodule_ignore(sub) == GIT_SUBMODULE_IGNORE_ALL)
|
|
616
540
|
status = GIT_DELTA_UNMODIFIED;
|
|
617
541
|
else {
|
|
618
542
|
unsigned int sm_status = 0;
|
|
619
543
|
if (git_submodule_status(&sm_status, sub) < 0)
|
|
620
544
|
return -1;
|
|
621
|
-
|
|
545
|
+
|
|
546
|
+
/* check IS_WD_UNMODIFIED because this case is only used
|
|
547
|
+
* when the new side of the diff is the working directory
|
|
548
|
+
*/
|
|
549
|
+
status = GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(sm_status)
|
|
622
550
|
? GIT_DELTA_UNMODIFIED : GIT_DELTA_MODIFIED;
|
|
623
551
|
|
|
624
552
|
/* grab OID while we are here */
|
|
625
553
|
if (git_oid_iszero(&nitem->oid)) {
|
|
626
|
-
const git_oid *sm_oid =
|
|
554
|
+
const git_oid *sm_oid = git_submodule_wd_id(sub);
|
|
627
555
|
if (sm_oid != NULL) {
|
|
628
556
|
git_oid_cpy(&noid, sm_oid);
|
|
629
557
|
use_noid = &noid;
|
|
@@ -633,114 +561,124 @@ static int maybe_modified(
|
|
|
633
561
|
}
|
|
634
562
|
}
|
|
635
563
|
|
|
564
|
+
/* if mode is GITLINK and submodules are ignored, then skip */
|
|
565
|
+
else if (S_ISGITLINK(nmode) &&
|
|
566
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES))
|
|
567
|
+
status = GIT_DELTA_UNMODIFIED;
|
|
568
|
+
|
|
636
569
|
/* if we got here and decided that the files are modified, but we
|
|
637
570
|
* haven't calculated the OID of the new item, then calculate it now
|
|
638
571
|
*/
|
|
639
572
|
if (status != GIT_DELTA_UNMODIFIED && git_oid_iszero(&nitem->oid)) {
|
|
640
|
-
if (
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
573
|
+
if (!use_noid) {
|
|
574
|
+
if (git_diff__oid_for_file(diff->repo,
|
|
575
|
+
nitem->path, nitem->mode, nitem->file_size, &noid) < 0)
|
|
576
|
+
return -1;
|
|
577
|
+
use_noid = &noid;
|
|
578
|
+
}
|
|
644
579
|
|
|
645
|
-
/*
|
|
646
|
-
|
|
580
|
+
/* if oid matches, then mark unmodified (except submodules, where
|
|
581
|
+
* the filesystem content may be modified even if the oid still
|
|
582
|
+
* matches between the index and the workdir HEAD)
|
|
583
|
+
*/
|
|
584
|
+
if (omode == nmode && !S_ISGITLINK(omode) &&
|
|
585
|
+
git_oid_equal(&oitem->oid, use_noid))
|
|
586
|
+
status = GIT_DELTA_UNMODIFIED;
|
|
647
587
|
}
|
|
648
588
|
|
|
649
589
|
return diff_delta__from_two(
|
|
650
|
-
diff, status, oitem, omode, nitem, nmode, use_noid);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
static int git_index_entry_cmp_case(const void *a, const void *b)
|
|
654
|
-
{
|
|
655
|
-
const git_index_entry *entry_a = a;
|
|
656
|
-
const git_index_entry *entry_b = b;
|
|
657
|
-
|
|
658
|
-
return strcmp(entry_a->path, entry_b->path);
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
static int git_index_entry_cmp_icase(const void *a, const void *b)
|
|
662
|
-
{
|
|
663
|
-
const git_index_entry *entry_a = a;
|
|
664
|
-
const git_index_entry *entry_b = b;
|
|
665
|
-
|
|
666
|
-
return strcasecmp(entry_a->path, entry_b->path);
|
|
590
|
+
diff, status, oitem, omode, nitem, nmode, use_noid, matched_pathspec);
|
|
667
591
|
}
|
|
668
592
|
|
|
669
593
|
static bool entry_is_prefixed(
|
|
594
|
+
git_diff_list *diff,
|
|
670
595
|
const git_index_entry *item,
|
|
671
|
-
git_iterator *prefix_iterator,
|
|
672
596
|
const git_index_entry *prefix_item)
|
|
673
597
|
{
|
|
674
598
|
size_t pathlen;
|
|
675
599
|
|
|
676
|
-
if (!prefix_item
|
|
677
|
-
ITERATOR_PREFIXCMP(*prefix_iterator, prefix_item->path, item->path))
|
|
600
|
+
if (!item || diff->pfxcomp(item->path, prefix_item->path) != 0)
|
|
678
601
|
return false;
|
|
679
602
|
|
|
680
|
-
pathlen = strlen(
|
|
603
|
+
pathlen = strlen(prefix_item->path);
|
|
681
604
|
|
|
682
|
-
return (
|
|
683
|
-
|
|
684
|
-
|
|
605
|
+
return (prefix_item->path[pathlen - 1] == '/' ||
|
|
606
|
+
item->path[pathlen] == '\0' ||
|
|
607
|
+
item->path[pathlen] == '/');
|
|
685
608
|
}
|
|
686
609
|
|
|
687
|
-
static int
|
|
688
|
-
|
|
689
|
-
const git_diff_options *opts, /**< can be NULL for defaults */
|
|
610
|
+
static int diff_list_init_from_iterators(
|
|
611
|
+
git_diff_list *diff,
|
|
690
612
|
git_iterator *old_iter,
|
|
691
|
-
git_iterator *new_iter
|
|
692
|
-
git_diff_list **diff_ptr)
|
|
613
|
+
git_iterator *new_iter)
|
|
693
614
|
{
|
|
694
|
-
const git_index_entry *oitem, *nitem;
|
|
695
|
-
git_buf ignore_prefix = GIT_BUF_INIT;
|
|
696
|
-
git_diff_list *diff = git_diff_list_alloc(repo, opts);
|
|
697
|
-
git_vector_cmp entry_compare;
|
|
698
|
-
|
|
699
|
-
if (!diff)
|
|
700
|
-
goto fail;
|
|
701
|
-
|
|
702
615
|
diff->old_src = old_iter->type;
|
|
703
616
|
diff->new_src = new_iter->type;
|
|
704
617
|
|
|
705
618
|
/* Use case-insensitive compare if either iterator has
|
|
706
619
|
* the ignore_case bit set */
|
|
707
|
-
if (!old_iter
|
|
708
|
-
|
|
620
|
+
if (!git_iterator_ignore_case(old_iter) &&
|
|
621
|
+
!git_iterator_ignore_case(new_iter))
|
|
622
|
+
{
|
|
709
623
|
diff->opts.flags &= ~GIT_DIFF_DELTAS_ARE_ICASE;
|
|
624
|
+
|
|
625
|
+
diff->strcomp = git__strcmp;
|
|
626
|
+
diff->strncomp = git__strncmp;
|
|
627
|
+
diff->pfxcomp = git__prefixcmp;
|
|
628
|
+
diff->entrycomp = git_index_entry__cmp;
|
|
710
629
|
} else {
|
|
711
|
-
entry_compare = git_index_entry_cmp_icase;
|
|
712
630
|
diff->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE;
|
|
713
631
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
632
|
+
diff->strcomp = git__strcasecmp;
|
|
633
|
+
diff->strncomp = git__strncasecmp;
|
|
634
|
+
diff->pfxcomp = git__prefixcmp_icase;
|
|
635
|
+
diff->entrycomp = git_index_entry__cmp_icase;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return 0;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
int git_diff__from_iterators(
|
|
642
|
+
git_diff_list **diff_ptr,
|
|
643
|
+
git_repository *repo,
|
|
644
|
+
git_iterator *old_iter,
|
|
645
|
+
git_iterator *new_iter,
|
|
646
|
+
const git_diff_options *opts)
|
|
647
|
+
{
|
|
648
|
+
int error = 0;
|
|
649
|
+
const git_index_entry *oitem, *nitem;
|
|
650
|
+
git_buf ignore_prefix = GIT_BUF_INIT;
|
|
651
|
+
git_diff_list *diff = git_diff_list_alloc(repo, opts);
|
|
652
|
+
|
|
653
|
+
*diff_ptr = NULL;
|
|
654
|
+
|
|
655
|
+
if (!diff || diff_list_init_from_iterators(diff, old_iter, new_iter) < 0)
|
|
656
|
+
goto fail;
|
|
657
|
+
|
|
658
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE)) {
|
|
659
|
+
if (git_iterator_set_ignore_case(old_iter, true) < 0 ||
|
|
660
|
+
git_iterator_set_ignore_case(new_iter, true) < 0)
|
|
661
|
+
goto fail;
|
|
725
662
|
}
|
|
726
663
|
|
|
727
|
-
if (git_iterator_current(
|
|
728
|
-
git_iterator_current(
|
|
664
|
+
if (git_iterator_current(&oitem, old_iter) < 0 ||
|
|
665
|
+
git_iterator_current(&nitem, new_iter) < 0)
|
|
729
666
|
goto fail;
|
|
730
667
|
|
|
731
668
|
/* run iterators building diffs */
|
|
732
669
|
while (oitem || nitem) {
|
|
670
|
+
int cmp = oitem ? (nitem ? diff->entrycomp(oitem, nitem) : -1) : 1;
|
|
733
671
|
|
|
734
672
|
/* create DELETED records for old items not matched in new */
|
|
735
|
-
if (
|
|
673
|
+
if (cmp < 0) {
|
|
736
674
|
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0)
|
|
737
675
|
goto fail;
|
|
738
676
|
|
|
739
677
|
/* if we are generating TYPECHANGE records then check for that
|
|
740
678
|
* instead of just generating a DELETE record
|
|
741
679
|
*/
|
|
742
|
-
if ((diff
|
|
743
|
-
entry_is_prefixed(
|
|
680
|
+
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE_TREES) &&
|
|
681
|
+
entry_is_prefixed(diff, nitem, oitem))
|
|
744
682
|
{
|
|
745
683
|
/* this entry has become a tree! convert to TYPECHANGE */
|
|
746
684
|
git_diff_delta *last = diff_delta__last_for_item(diff, oitem);
|
|
@@ -748,22 +686,33 @@ static int diff_from_iterators(
|
|
|
748
686
|
last->status = GIT_DELTA_TYPECHANGE;
|
|
749
687
|
last->new_file.mode = GIT_FILEMODE_TREE;
|
|
750
688
|
}
|
|
689
|
+
|
|
690
|
+
/* If new_iter is a workdir iterator, then this situation
|
|
691
|
+
* will certainly be followed by a series of untracked items.
|
|
692
|
+
* Unless RECURSE_UNTRACKED_DIRS is set, skip over them...
|
|
693
|
+
*/
|
|
694
|
+
if (S_ISDIR(nitem->mode) &&
|
|
695
|
+
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_RECURSE_UNTRACKED_DIRS))
|
|
696
|
+
{
|
|
697
|
+
if (git_iterator_advance(&nitem, new_iter) < 0)
|
|
698
|
+
goto fail;
|
|
699
|
+
}
|
|
751
700
|
}
|
|
752
701
|
|
|
753
|
-
if (git_iterator_advance(
|
|
702
|
+
if (git_iterator_advance(&oitem, old_iter) < 0)
|
|
754
703
|
goto fail;
|
|
755
704
|
}
|
|
756
705
|
|
|
757
706
|
/* create ADDED, TRACKED, or IGNORED records for new items not
|
|
758
707
|
* matched in old (and/or descend into directories as needed)
|
|
759
708
|
*/
|
|
760
|
-
else if (
|
|
709
|
+
else if (cmp > 0) {
|
|
761
710
|
git_delta_t delta_type = GIT_DELTA_UNTRACKED;
|
|
711
|
+
bool contains_oitem = entry_is_prefixed(diff, oitem, nitem);
|
|
762
712
|
|
|
763
713
|
/* check if contained in ignored parent directory */
|
|
764
714
|
if (git_buf_len(&ignore_prefix) &&
|
|
765
|
-
|
|
766
|
-
git_buf_cstr(&ignore_prefix)) == 0)
|
|
715
|
+
diff->pfxcomp(nitem->path, git_buf_cstr(&ignore_prefix)) == 0)
|
|
767
716
|
delta_type = GIT_DELTA_IGNORED;
|
|
768
717
|
|
|
769
718
|
if (S_ISDIR(nitem->mode)) {
|
|
@@ -771,32 +720,48 @@ static int diff_from_iterators(
|
|
|
771
720
|
* it or if the user requested the contents of untracked
|
|
772
721
|
* directories and it is not under an ignored directory.
|
|
773
722
|
*/
|
|
774
|
-
bool
|
|
775
|
-
entry_is_prefixed(nitem, old_iter, oitem);
|
|
776
|
-
bool recurse_untracked =
|
|
723
|
+
bool recurse_into_dir =
|
|
777
724
|
(delta_type == GIT_DELTA_UNTRACKED &&
|
|
778
|
-
(diff
|
|
725
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_RECURSE_UNTRACKED_DIRS)) ||
|
|
726
|
+
(delta_type == GIT_DELTA_IGNORED &&
|
|
727
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_RECURSE_IGNORED_DIRS));
|
|
779
728
|
|
|
780
729
|
/* do not advance into directories that contain a .git file */
|
|
781
|
-
if (!
|
|
730
|
+
if (!contains_oitem && recurse_into_dir) {
|
|
782
731
|
git_buf *full = NULL;
|
|
783
|
-
if (git_iterator_current_workdir_path(
|
|
732
|
+
if (git_iterator_current_workdir_path(&full, new_iter) < 0)
|
|
784
733
|
goto fail;
|
|
785
734
|
if (git_path_contains_dir(full, DOT_GIT))
|
|
786
|
-
|
|
735
|
+
recurse_into_dir = false;
|
|
787
736
|
}
|
|
788
737
|
|
|
789
|
-
if
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
738
|
+
/* if directory is ignored, remember ignore_prefix */
|
|
739
|
+
if ((contains_oitem || recurse_into_dir) &&
|
|
740
|
+
delta_type == GIT_DELTA_UNTRACKED &&
|
|
741
|
+
git_iterator_current_is_ignored(new_iter))
|
|
742
|
+
{
|
|
743
|
+
git_buf_sets(&ignore_prefix, nitem->path);
|
|
744
|
+
delta_type = GIT_DELTA_IGNORED;
|
|
745
|
+
|
|
746
|
+
/* skip recursion if we've just learned this is ignored */
|
|
747
|
+
if (DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_RECURSE_IGNORED_DIRS))
|
|
748
|
+
recurse_into_dir = false;
|
|
749
|
+
}
|
|
796
750
|
|
|
797
|
-
|
|
798
|
-
|
|
751
|
+
if (contains_oitem || recurse_into_dir) {
|
|
752
|
+
/* advance into directory */
|
|
753
|
+
error = git_iterator_advance_into(&nitem, new_iter);
|
|
799
754
|
|
|
755
|
+
/* if directory is empty, can't advance into it, so skip */
|
|
756
|
+
if (error == GIT_ENOTFOUND) {
|
|
757
|
+
giterr_clear();
|
|
758
|
+
error = git_iterator_advance(&nitem, new_iter);
|
|
759
|
+
|
|
760
|
+
git_buf_clear(&ignore_prefix);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
if (error < 0)
|
|
764
|
+
goto fail;
|
|
800
765
|
continue;
|
|
801
766
|
}
|
|
802
767
|
}
|
|
@@ -816,8 +781,9 @@ static int diff_from_iterators(
|
|
|
816
781
|
* checked before container directory exclusions are used to
|
|
817
782
|
* skip the file.
|
|
818
783
|
*/
|
|
819
|
-
else if (delta_type == GIT_DELTA_IGNORED
|
|
820
|
-
|
|
784
|
+
else if (delta_type == GIT_DELTA_IGNORED &&
|
|
785
|
+
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_RECURSE_IGNORED_DIRS)) {
|
|
786
|
+
if (git_iterator_advance(&nitem, new_iter) < 0)
|
|
821
787
|
goto fail;
|
|
822
788
|
continue; /* ignored parent directory, so skip completely */
|
|
823
789
|
}
|
|
@@ -825,28 +791,28 @@ static int diff_from_iterators(
|
|
|
825
791
|
else if (git_iterator_current_is_ignored(new_iter))
|
|
826
792
|
delta_type = GIT_DELTA_IGNORED;
|
|
827
793
|
|
|
828
|
-
else if (new_iter->type !=
|
|
794
|
+
else if (new_iter->type != GIT_ITERATOR_TYPE_WORKDIR)
|
|
829
795
|
delta_type = GIT_DELTA_ADDED;
|
|
830
796
|
|
|
831
797
|
if (diff_delta__from_one(diff, delta_type, nitem) < 0)
|
|
832
798
|
goto fail;
|
|
833
799
|
|
|
834
800
|
/* if we are generating TYPECHANGE records then check for that
|
|
835
|
-
* instead of just generating an
|
|
801
|
+
* instead of just generating an ADDED/UNTRACKED record
|
|
836
802
|
*/
|
|
837
803
|
if (delta_type != GIT_DELTA_IGNORED &&
|
|
838
|
-
(diff
|
|
839
|
-
|
|
804
|
+
DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE_TREES) &&
|
|
805
|
+
contains_oitem)
|
|
840
806
|
{
|
|
841
|
-
/* this entry was a tree
|
|
842
|
-
git_diff_delta *last = diff_delta__last_for_item(diff,
|
|
807
|
+
/* this entry was prefixed with a tree - make TYPECHANGE */
|
|
808
|
+
git_diff_delta *last = diff_delta__last_for_item(diff, nitem);
|
|
843
809
|
if (last) {
|
|
844
810
|
last->status = GIT_DELTA_TYPECHANGE;
|
|
845
811
|
last->old_file.mode = GIT_FILEMODE_TREE;
|
|
846
812
|
}
|
|
847
813
|
}
|
|
848
814
|
|
|
849
|
-
if (git_iterator_advance(
|
|
815
|
+
if (git_iterator_advance(&nitem, new_iter) < 0)
|
|
850
816
|
goto fail;
|
|
851
817
|
}
|
|
852
818
|
|
|
@@ -854,231 +820,116 @@ static int diff_from_iterators(
|
|
|
854
820
|
* (or ADDED and DELETED pair if type changed)
|
|
855
821
|
*/
|
|
856
822
|
else {
|
|
857
|
-
assert(oitem && nitem &&
|
|
823
|
+
assert(oitem && nitem && cmp == 0);
|
|
858
824
|
|
|
859
825
|
if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 ||
|
|
860
|
-
git_iterator_advance(
|
|
861
|
-
git_iterator_advance(
|
|
826
|
+
git_iterator_advance(&oitem, old_iter) < 0 ||
|
|
827
|
+
git_iterator_advance(&nitem, new_iter) < 0)
|
|
862
828
|
goto fail;
|
|
863
829
|
}
|
|
864
830
|
}
|
|
865
831
|
|
|
866
|
-
git_iterator_free(old_iter);
|
|
867
|
-
git_iterator_free(new_iter);
|
|
868
|
-
git_buf_free(&ignore_prefix);
|
|
869
|
-
|
|
870
832
|
*diff_ptr = diff;
|
|
871
|
-
return 0;
|
|
872
833
|
|
|
873
834
|
fail:
|
|
874
|
-
|
|
875
|
-
|
|
835
|
+
if (!*diff_ptr) {
|
|
836
|
+
git_diff_list_free(diff);
|
|
837
|
+
error = -1;
|
|
838
|
+
}
|
|
839
|
+
|
|
876
840
|
git_buf_free(&ignore_prefix);
|
|
877
841
|
|
|
878
|
-
|
|
879
|
-
*diff_ptr = NULL;
|
|
880
|
-
return -1;
|
|
842
|
+
return error;
|
|
881
843
|
}
|
|
882
844
|
|
|
845
|
+
#define DIFF_FROM_ITERATORS(MAKE_FIRST, MAKE_SECOND) do { \
|
|
846
|
+
git_iterator *a = NULL, *b = NULL; \
|
|
847
|
+
char *pfx = opts ? git_pathspec_prefix(&opts->pathspec) : NULL; \
|
|
848
|
+
GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); \
|
|
849
|
+
if (!(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \
|
|
850
|
+
error = git_diff__from_iterators(diff, repo, a, b, opts); \
|
|
851
|
+
git__free(pfx); git_iterator_free(a); git_iterator_free(b); \
|
|
852
|
+
} while (0)
|
|
883
853
|
|
|
884
854
|
int git_diff_tree_to_tree(
|
|
855
|
+
git_diff_list **diff,
|
|
885
856
|
git_repository *repo,
|
|
886
|
-
const git_diff_options *opts, /**< can be NULL for defaults */
|
|
887
857
|
git_tree *old_tree,
|
|
888
858
|
git_tree *new_tree,
|
|
889
|
-
|
|
859
|
+
const git_diff_options *opts)
|
|
890
860
|
{
|
|
891
|
-
|
|
892
|
-
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
|
861
|
+
int error = 0;
|
|
893
862
|
|
|
894
|
-
assert(
|
|
863
|
+
assert(diff && repo);
|
|
895
864
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
865
|
+
DIFF_FROM_ITERATORS(
|
|
866
|
+
git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
|
|
867
|
+
git_iterator_for_tree(&b, new_tree, 0, pfx, pfx)
|
|
868
|
+
);
|
|
899
869
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
return diff_from_iterators(repo, opts, a, b, diff);
|
|
870
|
+
return error;
|
|
903
871
|
}
|
|
904
872
|
|
|
905
|
-
int
|
|
873
|
+
int git_diff_tree_to_index(
|
|
874
|
+
git_diff_list **diff,
|
|
906
875
|
git_repository *repo,
|
|
907
|
-
const git_diff_options *opts,
|
|
908
876
|
git_tree *old_tree,
|
|
909
|
-
|
|
877
|
+
git_index *index,
|
|
878
|
+
const git_diff_options *opts)
|
|
910
879
|
{
|
|
911
|
-
|
|
912
|
-
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
|
913
|
-
|
|
914
|
-
assert(repo && diff);
|
|
880
|
+
int error = 0;
|
|
915
881
|
|
|
916
|
-
|
|
917
|
-
git_iterator_for_index_range(&b, repo, prefix, prefix) < 0)
|
|
918
|
-
goto on_error;
|
|
882
|
+
assert(diff && repo);
|
|
919
883
|
|
|
920
|
-
|
|
884
|
+
if (!index && (error = git_repository_index__weakptr(&index, repo)) < 0)
|
|
885
|
+
return error;
|
|
921
886
|
|
|
922
|
-
|
|
887
|
+
DIFF_FROM_ITERATORS(
|
|
888
|
+
git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
|
|
889
|
+
git_iterator_for_index(&b, index, 0, pfx, pfx)
|
|
890
|
+
);
|
|
923
891
|
|
|
924
|
-
|
|
925
|
-
git__free(prefix);
|
|
926
|
-
git_iterator_free(a);
|
|
927
|
-
return -1;
|
|
892
|
+
return error;
|
|
928
893
|
}
|
|
929
894
|
|
|
930
|
-
int
|
|
895
|
+
int git_diff_index_to_workdir(
|
|
896
|
+
git_diff_list **diff,
|
|
931
897
|
git_repository *repo,
|
|
932
|
-
|
|
933
|
-
|
|
898
|
+
git_index *index,
|
|
899
|
+
const git_diff_options *opts)
|
|
934
900
|
{
|
|
935
|
-
|
|
936
|
-
int error;
|
|
937
|
-
|
|
938
|
-
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
|
939
|
-
|
|
940
|
-
assert(repo && diff);
|
|
901
|
+
int error = 0;
|
|
941
902
|
|
|
942
|
-
|
|
943
|
-
(error = git_iterator_for_workdir_range(&b, repo, prefix, prefix)) < 0)
|
|
944
|
-
goto on_error;
|
|
903
|
+
assert(diff && repo);
|
|
945
904
|
|
|
946
|
-
|
|
905
|
+
if (!index && (error = git_repository_index__weakptr(&index, repo)) < 0)
|
|
906
|
+
return error;
|
|
947
907
|
|
|
948
|
-
|
|
908
|
+
DIFF_FROM_ITERATORS(
|
|
909
|
+
git_iterator_for_index(&a, index, 0, pfx, pfx),
|
|
910
|
+
git_iterator_for_workdir(
|
|
911
|
+
&b, repo, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx)
|
|
912
|
+
);
|
|
949
913
|
|
|
950
|
-
on_error:
|
|
951
|
-
git__free(prefix);
|
|
952
|
-
git_iterator_free(a);
|
|
953
914
|
return error;
|
|
954
915
|
}
|
|
955
916
|
|
|
956
917
|
|
|
957
|
-
int
|
|
918
|
+
int git_diff_tree_to_workdir(
|
|
919
|
+
git_diff_list **diff,
|
|
958
920
|
git_repository *repo,
|
|
959
|
-
const git_diff_options *opts,
|
|
960
921
|
git_tree *old_tree,
|
|
961
|
-
|
|
962
|
-
{
|
|
963
|
-
git_iterator *a = NULL, *b = NULL;
|
|
964
|
-
int error;
|
|
965
|
-
|
|
966
|
-
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
|
967
|
-
|
|
968
|
-
assert(repo && old_tree && diff);
|
|
969
|
-
|
|
970
|
-
if ((error = git_iterator_for_tree_range(&a, repo, old_tree, prefix, prefix)) < 0 ||
|
|
971
|
-
(error = git_iterator_for_workdir_range(&b, repo, prefix, prefix)) < 0)
|
|
972
|
-
goto on_error;
|
|
973
|
-
|
|
974
|
-
git__free(prefix);
|
|
975
|
-
|
|
976
|
-
return diff_from_iterators(repo, opts, a, b, diff);
|
|
977
|
-
|
|
978
|
-
on_error:
|
|
979
|
-
git__free(prefix);
|
|
980
|
-
git_iterator_free(a);
|
|
981
|
-
return error;
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
bool git_diff_delta__should_skip(
|
|
986
|
-
const git_diff_options *opts, const git_diff_delta *delta)
|
|
987
|
-
{
|
|
988
|
-
uint32_t flags = opts ? opts->flags : 0;
|
|
989
|
-
|
|
990
|
-
if (delta->status == GIT_DELTA_UNMODIFIED &&
|
|
991
|
-
(flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
|
|
992
|
-
return true;
|
|
993
|
-
|
|
994
|
-
if (delta->status == GIT_DELTA_IGNORED &&
|
|
995
|
-
(flags & GIT_DIFF_INCLUDE_IGNORED) == 0)
|
|
996
|
-
return true;
|
|
997
|
-
|
|
998
|
-
if (delta->status == GIT_DELTA_UNTRACKED &&
|
|
999
|
-
(flags & GIT_DIFF_INCLUDE_UNTRACKED) == 0)
|
|
1000
|
-
return true;
|
|
1001
|
-
|
|
1002
|
-
return false;
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
int git_diff_merge(
|
|
1007
|
-
git_diff_list *onto,
|
|
1008
|
-
const git_diff_list *from)
|
|
922
|
+
const git_diff_options *opts)
|
|
1009
923
|
{
|
|
1010
924
|
int error = 0;
|
|
1011
|
-
git_pool onto_pool;
|
|
1012
|
-
git_vector onto_new;
|
|
1013
|
-
git_diff_delta *delta;
|
|
1014
|
-
bool ignore_case = false;
|
|
1015
|
-
unsigned int i, j;
|
|
1016
|
-
|
|
1017
|
-
assert(onto && from);
|
|
1018
|
-
|
|
1019
|
-
if (!from->deltas.length)
|
|
1020
|
-
return 0;
|
|
1021
|
-
|
|
1022
|
-
if (git_vector_init(&onto_new, onto->deltas.length, diff_delta__cmp) < 0 ||
|
|
1023
|
-
git_pool_init(&onto_pool, 1, 0) < 0)
|
|
1024
|
-
return -1;
|
|
1025
925
|
|
|
1026
|
-
|
|
1027
|
-
(from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0)
|
|
1028
|
-
{
|
|
1029
|
-
ignore_case = true;
|
|
1030
|
-
|
|
1031
|
-
/* This function currently only supports merging diff lists that
|
|
1032
|
-
* are sorted identically. */
|
|
1033
|
-
assert((onto->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 &&
|
|
1034
|
-
(from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0);
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) {
|
|
1038
|
-
git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i);
|
|
1039
|
-
const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j);
|
|
1040
|
-
int cmp = !f ? -1 : !o ? 1 : STRCMP_CASESELECT(ignore_case, o->old_file.path, f->old_file.path);
|
|
1041
|
-
|
|
1042
|
-
if (cmp < 0) {
|
|
1043
|
-
delta = diff_delta__dup(o, &onto_pool);
|
|
1044
|
-
i++;
|
|
1045
|
-
} else if (cmp > 0) {
|
|
1046
|
-
delta = diff_delta__dup(f, &onto_pool);
|
|
1047
|
-
j++;
|
|
1048
|
-
} else {
|
|
1049
|
-
delta = diff_delta__merge_like_cgit(o, f, &onto_pool);
|
|
1050
|
-
i++;
|
|
1051
|
-
j++;
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
/* the ignore rules for the target may not match the source
|
|
1055
|
-
* or the result of a merged delta could be skippable...
|
|
1056
|
-
*/
|
|
1057
|
-
if (git_diff_delta__should_skip(&onto->opts, delta)) {
|
|
1058
|
-
git__free(delta);
|
|
1059
|
-
continue;
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
if ((error = !delta ? -1 : git_vector_insert(&onto_new, delta)) < 0)
|
|
1063
|
-
break;
|
|
1064
|
-
}
|
|
926
|
+
assert(diff && repo);
|
|
1065
927
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
/* prefix strings also come from old pool, so recreate those.*/
|
|
1072
|
-
onto->opts.old_prefix =
|
|
1073
|
-
git_pool_strdup_safe(&onto->pool, onto->opts.old_prefix);
|
|
1074
|
-
onto->opts.new_prefix =
|
|
1075
|
-
git_pool_strdup_safe(&onto->pool, onto->opts.new_prefix);
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
git_vector_foreach(&onto_new, i, delta)
|
|
1079
|
-
git__free(delta);
|
|
1080
|
-
git_vector_free(&onto_new);
|
|
1081
|
-
git_pool_clear(&onto_pool);
|
|
928
|
+
DIFF_FROM_ITERATORS(
|
|
929
|
+
git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
|
|
930
|
+
git_iterator_for_workdir(
|
|
931
|
+
&b, repo, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx)
|
|
932
|
+
);
|
|
1082
933
|
|
|
1083
934
|
return error;
|
|
1084
935
|
}
|