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
@@ -22,6 +22,9 @@ extern int git_futils_readbuffer_updated(
|
|
22
22
|
git_buf *obj, const char *path, time_t *mtime, size_t *size, int *updated);
|
23
23
|
extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
|
24
24
|
|
25
|
+
extern int git_futils_writebuffer(
|
26
|
+
const git_buf *buf, const char *path, int open_flags, mode_t mode);
|
27
|
+
|
25
28
|
/**
|
26
29
|
* File utils
|
27
30
|
*
|
@@ -223,6 +226,7 @@ extern git_off_t git_futils_filesize(git_file fd);
|
|
223
226
|
#define GIT_MODE_PERMS_MASK 0777
|
224
227
|
#define GIT_CANONICAL_PERMS(MODE) (((MODE) & 0100) ? 0755 : 0644)
|
225
228
|
#define GIT_MODE_TYPE(MODE) ((MODE) & ~GIT_MODE_PERMS_MASK)
|
229
|
+
#define GIT_MODE_ISBLOB(MODE) (GIT_MODE_TYPE(MODE) == GIT_MODE_TYPE(GIT_FILEMODE_BLOB))
|
226
230
|
|
227
231
|
/**
|
228
232
|
* Convert a mode_t from the OS to a legal git mode_t value.
|
data/vendor/libgit2/src/global.c
CHANGED
@@ -61,7 +61,8 @@ int git_threads_init(void)
|
|
61
61
|
return 0;
|
62
62
|
|
63
63
|
_tls_index = TlsAlloc();
|
64
|
-
git_mutex_init(&git__mwindow_mutex)
|
64
|
+
if (git_mutex_init(&git__mwindow_mutex))
|
65
|
+
return -1;
|
65
66
|
|
66
67
|
/* Initialize any other subsystems that have global state */
|
67
68
|
if ((error = git_hash_global_init()) >= 0)
|
@@ -121,7 +122,8 @@ int git_threads_init(void)
|
|
121
122
|
if (_tls_init)
|
122
123
|
return 0;
|
123
124
|
|
124
|
-
git_mutex_init(&git__mwindow_mutex)
|
125
|
+
if (git_mutex_init(&git__mwindow_mutex))
|
126
|
+
return -1;
|
125
127
|
pthread_key_create(&_tls_key, &cb__free_status);
|
126
128
|
|
127
129
|
/* Initialize any other subsystems that have global state */
|
@@ -135,6 +137,12 @@ int git_threads_init(void)
|
|
135
137
|
|
136
138
|
void git_threads_shutdown(void)
|
137
139
|
{
|
140
|
+
if (_tls_init) {
|
141
|
+
void *ptr = pthread_getspecific(_tls_key);
|
142
|
+
pthread_setspecific(_tls_key, NULL);
|
143
|
+
git__free(ptr);
|
144
|
+
}
|
145
|
+
|
138
146
|
pthread_key_delete(_tls_key);
|
139
147
|
_tls_init = 0;
|
140
148
|
git_mutex_free(&git__mwindow_mutex);
|
data/vendor/libgit2/src/global.h
CHANGED
@@ -10,14 +10,6 @@
|
|
10
10
|
#include "mwindow.h"
|
11
11
|
#include "hash.h"
|
12
12
|
|
13
|
-
#if defined(GIT_THREADS) && defined(_MSC_VER)
|
14
|
-
# define GIT_MEMORY_BARRIER MemoryBarrier()
|
15
|
-
#elif defined(GIT_THREADS)
|
16
|
-
# define GIT_MEMORY_BARRIER __sync_synchronize()
|
17
|
-
#else
|
18
|
-
# define GIT_MEMORY_BARRIER /* noop */
|
19
|
-
#endif
|
20
|
-
|
21
13
|
typedef struct {
|
22
14
|
git_error *last_error;
|
23
15
|
git_error error_t;
|
@@ -48,10 +48,10 @@ struct hash_cryptoapi_prov {
|
|
48
48
|
|
49
49
|
/* Function declarations for CNG */
|
50
50
|
typedef NTSTATUS (WINAPI *hash_win32_cng_open_algorithm_provider_fn)(
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
HANDLE /* BCRYPT_ALG_HANDLE */ *phAlgorithm,
|
52
|
+
LPCWSTR pszAlgId,
|
53
|
+
LPCWSTR pszImplementation,
|
54
|
+
DWORD dwFlags);
|
55
55
|
|
56
56
|
typedef NTSTATUS (WINAPI *hash_win32_cng_get_property_fn)(
|
57
57
|
HANDLE /* BCRYPT_HANDLE */ hObject,
|
data/vendor/libgit2/src/ignore.c
CHANGED
@@ -15,24 +15,14 @@ static int parse_ignore_file(
|
|
15
15
|
git_attr_fnmatch *match = NULL;
|
16
16
|
const char *scan = NULL;
|
17
17
|
char *context = NULL;
|
18
|
-
|
19
|
-
git_config *cfg = NULL;
|
20
|
-
int val;
|
21
|
-
|
22
|
-
/* Prefer to have the caller pass in a git_ignores as the parsedata object.
|
23
|
-
* If they did not, then we can (much more slowly) find the value of
|
24
|
-
* ignore_case by using the repository object. */
|
25
|
-
if (parsedata != NULL) {
|
26
|
-
ignore_case = ((git_ignores *)parsedata)->ignore_case;
|
27
|
-
} else {
|
28
|
-
if ((error = git_repository_config(&cfg, repo)) < 0)
|
29
|
-
return error;
|
30
|
-
|
31
|
-
if (git_config_get_bool(&val, cfg, "core.ignorecase") == 0)
|
32
|
-
ignore_case = (val != 0);
|
18
|
+
int ignore_case = false;
|
33
19
|
|
34
|
-
|
35
|
-
|
20
|
+
/* Prefer to have the caller pass in a git_ignores as the parsedata
|
21
|
+
* object. If they did not, then look up the value of ignore_case */
|
22
|
+
if (parsedata != NULL)
|
23
|
+
ignore_case = ((git_ignores *)parsedata)->ignore_case;
|
24
|
+
else if (git_repository__cvar(&ignore_case, repo, GIT_CVAR_IGNORECASE) < 0)
|
25
|
+
return error;
|
36
26
|
|
37
27
|
if (ignores->key && git__suffixcmp(ignores->key, "/" GIT_IGNORE_FILE) == 0) {
|
38
28
|
context = ignores->key + 2;
|
@@ -109,8 +99,6 @@ int git_ignore__for_path(
|
|
109
99
|
{
|
110
100
|
int error = 0;
|
111
101
|
const char *workdir = git_repository_workdir(repo);
|
112
|
-
git_config *cfg = NULL;
|
113
|
-
int val;
|
114
102
|
|
115
103
|
assert(ignores);
|
116
104
|
|
@@ -118,17 +106,11 @@ int git_ignore__for_path(
|
|
118
106
|
git_buf_init(&ignores->dir, 0);
|
119
107
|
ignores->ign_internal = NULL;
|
120
108
|
|
121
|
-
/*
|
122
|
-
if ((error =
|
109
|
+
/* Read the ignore_case flag */
|
110
|
+
if ((error = git_repository__cvar(
|
111
|
+
&ignores->ignore_case, repo, GIT_CVAR_IGNORECASE)) < 0)
|
123
112
|
goto cleanup;
|
124
113
|
|
125
|
-
if (git_config_get_bool(&val, cfg, "core.ignorecase") == 0)
|
126
|
-
ignores->ignore_case = (val != 0);
|
127
|
-
else
|
128
|
-
ignores->ignore_case = 0;
|
129
|
-
|
130
|
-
git_config_free(cfg);
|
131
|
-
|
132
114
|
if ((error = git_vector_init(&ignores->ign_path, 8, NULL)) < 0 ||
|
133
115
|
(error = git_vector_init(&ignores->ign_global, 2, NULL)) < 0 ||
|
134
116
|
(error = git_attr_cache__init(repo)) < 0)
|
@@ -358,3 +340,61 @@ cleanup:
|
|
358
340
|
return error;
|
359
341
|
}
|
360
342
|
|
343
|
+
|
344
|
+
int git_ignore__check_pathspec_for_exact_ignores(
|
345
|
+
git_repository *repo,
|
346
|
+
git_vector *vspec,
|
347
|
+
bool no_fnmatch)
|
348
|
+
{
|
349
|
+
int error = 0;
|
350
|
+
size_t i;
|
351
|
+
git_attr_fnmatch *match;
|
352
|
+
int ignored;
|
353
|
+
git_buf path = GIT_BUF_INIT;
|
354
|
+
const char *wd, *filename;
|
355
|
+
git_index *idx;
|
356
|
+
|
357
|
+
if ((error = git_repository__ensure_not_bare(
|
358
|
+
repo, "validate pathspec")) < 0 ||
|
359
|
+
(error = git_repository_index(&idx, repo)) < 0)
|
360
|
+
return error;
|
361
|
+
|
362
|
+
wd = git_repository_workdir(repo);
|
363
|
+
|
364
|
+
git_vector_foreach(vspec, i, match) {
|
365
|
+
/* skip wildcard matches (if they are being used) */
|
366
|
+
if ((match->flags & GIT_ATTR_FNMATCH_HASWILD) != 0 &&
|
367
|
+
!no_fnmatch)
|
368
|
+
continue;
|
369
|
+
|
370
|
+
filename = match->pattern;
|
371
|
+
|
372
|
+
/* if file is already in the index, it's fine */
|
373
|
+
if (git_index_get_bypath(idx, filename, 0) != NULL)
|
374
|
+
continue;
|
375
|
+
|
376
|
+
if ((error = git_buf_joinpath(&path, wd, filename)) < 0)
|
377
|
+
break;
|
378
|
+
|
379
|
+
/* is there a file on disk that matches this exactly? */
|
380
|
+
if (!git_path_isfile(path.ptr))
|
381
|
+
continue;
|
382
|
+
|
383
|
+
/* is that file ignored? */
|
384
|
+
if ((error = git_ignore_path_is_ignored(&ignored, repo, filename)) < 0)
|
385
|
+
break;
|
386
|
+
|
387
|
+
if (ignored) {
|
388
|
+
giterr_set(GITERR_INVALID, "pathspec contains ignored file '%s'",
|
389
|
+
filename);
|
390
|
+
error = GIT_EINVALIDSPEC;
|
391
|
+
break;
|
392
|
+
}
|
393
|
+
}
|
394
|
+
|
395
|
+
git_index_free(idx);
|
396
|
+
git_buf_free(&path);
|
397
|
+
|
398
|
+
return error;
|
399
|
+
}
|
400
|
+
|
data/vendor/libgit2/src/ignore.h
CHANGED
@@ -28,7 +28,7 @@ typedef struct {
|
|
28
28
|
git_attr_file *ign_internal;
|
29
29
|
git_vector ign_path;
|
30
30
|
git_vector ign_global;
|
31
|
-
|
31
|
+
int ignore_case;
|
32
32
|
} git_ignores;
|
33
33
|
|
34
34
|
extern int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ign);
|
@@ -41,4 +41,13 @@ extern void git_ignore__free(git_ignores *ign);
|
|
41
41
|
|
42
42
|
extern int git_ignore__lookup(git_ignores *ign, const char *path, int *ignored);
|
43
43
|
|
44
|
+
/* command line Git sometimes generates an error message if given a
|
45
|
+
* pathspec that contains an exact match to an ignored file (provided
|
46
|
+
* --force isn't also given). This makes it easy to check it that has
|
47
|
+
* happened. Returns GIT_EINVALIDSPEC if the pathspec contains ignored
|
48
|
+
* exact matches (that are not already present in the index).
|
49
|
+
*/
|
50
|
+
extern int git_ignore__check_pathspec_for_exact_ignores(
|
51
|
+
git_repository *repo, git_vector *pathspec, bool no_fnmatch);
|
52
|
+
|
44
53
|
#endif
|
data/vendor/libgit2/src/index.c
CHANGED
@@ -15,10 +15,13 @@
|
|
15
15
|
#include "hash.h"
|
16
16
|
#include "iterator.h"
|
17
17
|
#include "pathspec.h"
|
18
|
+
#include "ignore.h"
|
19
|
+
|
18
20
|
#include "git2/odb.h"
|
19
21
|
#include "git2/oid.h"
|
20
22
|
#include "git2/blob.h"
|
21
23
|
#include "git2/config.h"
|
24
|
+
#include "git2/sys/index.h"
|
22
25
|
|
23
26
|
#define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
|
24
27
|
#define short_entry_size(len) entry_size(struct entry_short, len)
|
@@ -35,6 +38,7 @@ static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
|
|
35
38
|
static const unsigned int INDEX_HEADER_SIG = 0x44495243;
|
36
39
|
static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
|
37
40
|
static const char INDEX_EXT_UNMERGED_SIG[] = {'R', 'E', 'U', 'C'};
|
41
|
+
static const char INDEX_EXT_CONFLICT_NAME_SIG[] = {'N', 'A', 'M', 'E'};
|
38
42
|
|
39
43
|
#define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
|
40
44
|
|
@@ -102,11 +106,6 @@ static int index_find(size_t *at_pos, git_index *index, const char *path, int st
|
|
102
106
|
static void index_entry_free(git_index_entry *entry);
|
103
107
|
static void index_entry_reuc_free(git_index_reuc_entry *reuc);
|
104
108
|
|
105
|
-
GIT_INLINE(int) index_entry_stage(const git_index_entry *entry)
|
106
|
-
{
|
107
|
-
return (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT;
|
108
|
-
}
|
109
|
-
|
110
109
|
static int index_srch(const void *key, const void *array_member)
|
111
110
|
{
|
112
111
|
const struct entry_srch_key *srch_key = key;
|
@@ -116,7 +115,7 @@ static int index_srch(const void *key, const void *array_member)
|
|
116
115
|
ret = strcmp(srch_key->path, entry->path);
|
117
116
|
|
118
117
|
if (ret == 0)
|
119
|
-
ret = srch_key->stage -
|
118
|
+
ret = srch_key->stage - GIT_IDXENTRY_STAGE(entry);
|
120
119
|
|
121
120
|
return ret;
|
122
121
|
}
|
@@ -130,7 +129,7 @@ static int index_isrch(const void *key, const void *array_member)
|
|
130
129
|
ret = strcasecmp(srch_key->path, entry->path);
|
131
130
|
|
132
131
|
if (ret == 0)
|
133
|
-
ret = srch_key->stage -
|
132
|
+
ret = srch_key->stage - GIT_IDXENTRY_STAGE(entry);
|
134
133
|
|
135
134
|
return ret;
|
136
135
|
}
|
@@ -168,7 +167,7 @@ static int index_cmp(const void *a, const void *b)
|
|
168
167
|
diff = strcmp(entry_a->path, entry_b->path);
|
169
168
|
|
170
169
|
if (diff == 0)
|
171
|
-
diff = (
|
170
|
+
diff = (GIT_IDXENTRY_STAGE(entry_a) - GIT_IDXENTRY_STAGE(entry_b));
|
172
171
|
|
173
172
|
return diff;
|
174
173
|
}
|
@@ -182,11 +181,56 @@ static int index_icmp(const void *a, const void *b)
|
|
182
181
|
diff = strcasecmp(entry_a->path, entry_b->path);
|
183
182
|
|
184
183
|
if (diff == 0)
|
185
|
-
diff = (
|
184
|
+
diff = (GIT_IDXENTRY_STAGE(entry_a) - GIT_IDXENTRY_STAGE(entry_b));
|
186
185
|
|
187
186
|
return diff;
|
188
187
|
}
|
189
188
|
|
189
|
+
static int conflict_name_cmp(const void *a, const void *b)
|
190
|
+
{
|
191
|
+
const git_index_name_entry *name_a = a;
|
192
|
+
const git_index_name_entry *name_b = b;
|
193
|
+
|
194
|
+
if (name_a->ancestor && !name_b->ancestor)
|
195
|
+
return 1;
|
196
|
+
|
197
|
+
if (!name_a->ancestor && name_b->ancestor)
|
198
|
+
return -1;
|
199
|
+
|
200
|
+
if (name_a->ancestor)
|
201
|
+
return strcmp(name_a->ancestor, name_b->ancestor);
|
202
|
+
|
203
|
+
if (!name_a->ours || !name_b->ours)
|
204
|
+
return 0;
|
205
|
+
|
206
|
+
return strcmp(name_a->ours, name_b->ours);
|
207
|
+
}
|
208
|
+
|
209
|
+
/**
|
210
|
+
* TODO: enable this when resolving case insensitive conflicts
|
211
|
+
*/
|
212
|
+
#if 0
|
213
|
+
static int conflict_name_icmp(const void *a, const void *b)
|
214
|
+
{
|
215
|
+
const git_index_name_entry *name_a = a;
|
216
|
+
const git_index_name_entry *name_b = b;
|
217
|
+
|
218
|
+
if (name_a->ancestor && !name_b->ancestor)
|
219
|
+
return 1;
|
220
|
+
|
221
|
+
if (!name_a->ancestor && name_b->ancestor)
|
222
|
+
return -1;
|
223
|
+
|
224
|
+
if (name_a->ancestor)
|
225
|
+
return strcasecmp(name_a->ancestor, name_b->ancestor);
|
226
|
+
|
227
|
+
if (!name_a->ours || !name_b->ours)
|
228
|
+
return 0;
|
229
|
+
|
230
|
+
return strcasecmp(name_a->ours, name_b->ours);
|
231
|
+
}
|
232
|
+
#endif
|
233
|
+
|
190
234
|
static int reuc_srch(const void *key, const void *array_member)
|
191
235
|
{
|
192
236
|
const git_index_reuc_entry *reuc = array_member;
|
@@ -246,16 +290,16 @@ void git_index__set_ignore_case(git_index *index, bool ignore_case)
|
|
246
290
|
{
|
247
291
|
index->ignore_case = ignore_case;
|
248
292
|
|
249
|
-
index->entries._cmp = ignore_case ? index_icmp : index_cmp;
|
250
293
|
index->entries_cmp_path = ignore_case ? index_icmp_path : index_cmp_path;
|
251
294
|
index->entries_search = ignore_case ? index_isrch : index_srch;
|
252
295
|
index->entries_search_path = ignore_case ? index_isrch_path : index_srch_path;
|
253
|
-
|
296
|
+
|
297
|
+
git_vector_set_cmp(&index->entries, ignore_case ? index_icmp : index_cmp);
|
254
298
|
git_vector_sort(&index->entries);
|
255
299
|
|
256
|
-
index->reuc._cmp = ignore_case ? reuc_icmp : reuc_cmp;
|
257
300
|
index->reuc_search = ignore_case ? reuc_isrch : reuc_srch;
|
258
|
-
|
301
|
+
|
302
|
+
git_vector_set_cmp(&index->reuc, ignore_case ? reuc_icmp : reuc_cmp);
|
259
303
|
git_vector_sort(&index->reuc);
|
260
304
|
}
|
261
305
|
|
@@ -278,6 +322,7 @@ int git_index_open(git_index **index_out, const char *index_path)
|
|
278
322
|
}
|
279
323
|
|
280
324
|
if (git_vector_init(&index->entries, 32, index_cmp) < 0 ||
|
325
|
+
git_vector_init(&index->names, 32, conflict_name_cmp) < 0 ||
|
281
326
|
git_vector_init(&index->reuc, 32, reuc_cmp) < 0)
|
282
327
|
return -1;
|
283
328
|
|
@@ -301,9 +346,12 @@ static void index_free(git_index *index)
|
|
301
346
|
{
|
302
347
|
git_index_clear(index);
|
303
348
|
git_vector_free(&index->entries);
|
349
|
+
git_vector_free(&index->names);
|
304
350
|
git_vector_free(&index->reuc);
|
305
351
|
|
306
352
|
git__free(index->index_file_path);
|
353
|
+
|
354
|
+
git__memzero(index, sizeof(*index));
|
307
355
|
git__free(index);
|
308
356
|
}
|
309
357
|
|
@@ -315,22 +363,27 @@ void git_index_free(git_index *index)
|
|
315
363
|
GIT_REFCOUNT_DEC(index, index_free);
|
316
364
|
}
|
317
365
|
|
318
|
-
void
|
366
|
+
static void index_entries_free(git_vector *entries)
|
319
367
|
{
|
320
368
|
size_t i;
|
321
369
|
|
322
|
-
|
323
|
-
|
324
|
-
for (i = 0; i < index->entries.length; ++i) {
|
325
|
-
git_index_entry *e;
|
326
|
-
e = git_vector_get(&index->entries, i);
|
370
|
+
for (i = 0; i < entries->length; ++i) {
|
371
|
+
git_index_entry *e = git_vector_get(entries, i);
|
327
372
|
git__free(e->path);
|
328
373
|
git__free(e);
|
329
374
|
}
|
330
|
-
git_vector_clear(&index->entries);
|
331
375
|
|
376
|
+
git_vector_clear(entries);
|
377
|
+
}
|
378
|
+
|
379
|
+
void git_index_clear(git_index *index)
|
380
|
+
{
|
381
|
+
assert(index);
|
382
|
+
|
383
|
+
index_entries_free(&index->entries);
|
332
384
|
git_index_reuc_clear(index);
|
333
|
-
|
385
|
+
git_index_name_clear(index);
|
386
|
+
|
334
387
|
git_futils_filestamp_set(&index->stamp, NULL);
|
335
388
|
|
336
389
|
git_tree_cache_free(index->tree);
|
@@ -352,19 +405,18 @@ int git_index_set_caps(git_index *index, unsigned int caps)
|
|
352
405
|
old_ignore_case = index->ignore_case;
|
353
406
|
|
354
407
|
if (caps == GIT_INDEXCAP_FROM_OWNER) {
|
355
|
-
|
408
|
+
git_repository *repo = INDEX_OWNER(index);
|
356
409
|
int val;
|
357
410
|
|
358
|
-
if (
|
359
|
-
|
360
|
-
|
361
|
-
"Cannot get repository config to set index caps");
|
411
|
+
if (!repo)
|
412
|
+
return create_index_error(
|
413
|
+
-1, "Cannot access repository to set index caps");
|
362
414
|
|
363
|
-
if (
|
415
|
+
if (!git_repository__cvar(&val, repo, GIT_CVAR_IGNORECASE))
|
364
416
|
index->ignore_case = (val != 0);
|
365
|
-
if (
|
417
|
+
if (!git_repository__cvar(&val, repo, GIT_CVAR_FILEMODE))
|
366
418
|
index->distrust_filemode = (val == 0);
|
367
|
-
if (
|
419
|
+
if (!git_repository__cvar(&val, repo, GIT_CVAR_SYMLINKS))
|
368
420
|
index->no_symlinks = (val == 0);
|
369
421
|
}
|
370
422
|
else {
|
@@ -497,8 +549,10 @@ const git_index_entry *git_index_get_bypath(
|
|
497
549
|
|
498
550
|
git_vector_sort(&index->entries);
|
499
551
|
|
500
|
-
if (index_find(&pos, index, path, stage) < 0)
|
552
|
+
if (index_find(&pos, index, path, stage) < 0) {
|
553
|
+
giterr_set(GITERR_INDEX, "Index does not contain %s", path);
|
501
554
|
return NULL;
|
555
|
+
}
|
502
556
|
|
503
557
|
return git_index_get_byindex(index, pos);
|
504
558
|
}
|
@@ -586,8 +640,9 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const
|
|
586
640
|
|
587
641
|
static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
|
588
642
|
const char *path,
|
589
|
-
int ancestor_mode, git_oid *ancestor_oid,
|
590
|
-
int our_mode, git_oid *our_oid,
|
643
|
+
int ancestor_mode, const git_oid *ancestor_oid,
|
644
|
+
int our_mode, const git_oid *our_oid,
|
645
|
+
int their_mode, const git_oid *their_oid)
|
591
646
|
{
|
592
647
|
git_index_reuc_entry *reuc = NULL;
|
593
648
|
|
@@ -668,7 +723,7 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace)
|
|
668
723
|
entry->flags |= GIT_IDXENTRY_NAMEMASK;
|
669
724
|
|
670
725
|
/* look if an entry with this path already exists */
|
671
|
-
if (!index_find(&position, index, entry->path,
|
726
|
+
if (!index_find(&position, index, entry->path, GIT_IDXENTRY_STAGE(entry))) {
|
672
727
|
existing = (git_index_entry **)&index->entries.contents[position];
|
673
728
|
|
674
729
|
/* update filemode to existing values if stat is not trusted */
|
@@ -681,8 +736,9 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace)
|
|
681
736
|
if (!replace || !existing)
|
682
737
|
return git_vector_insert(&index->entries, entry);
|
683
738
|
|
684
|
-
/* exists, replace it */
|
685
|
-
git__free(
|
739
|
+
/* exists, replace it (preserving name from existing entry) */
|
740
|
+
git__free(entry->path);
|
741
|
+
entry->path = (*existing)->path;
|
686
742
|
git__free(*existing);
|
687
743
|
*existing = entry;
|
688
744
|
|
@@ -691,9 +747,9 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace)
|
|
691
747
|
|
692
748
|
static int index_conflict_to_reuc(git_index *index, const char *path)
|
693
749
|
{
|
694
|
-
git_index_entry *conflict_entries[3];
|
750
|
+
const git_index_entry *conflict_entries[3];
|
695
751
|
int ancestor_mode, our_mode, their_mode;
|
696
|
-
git_oid *ancestor_oid, *our_oid, *their_oid;
|
752
|
+
git_oid const *ancestor_oid, *our_oid, *their_oid;
|
697
753
|
int ret;
|
698
754
|
|
699
755
|
if ((ret = git_index_conflict_get(&conflict_entries[0],
|
@@ -779,8 +835,11 @@ int git_index_remove(git_index *index, const char *path, int stage)
|
|
779
835
|
|
780
836
|
git_vector_sort(&index->entries);
|
781
837
|
|
782
|
-
if (index_find(&position, index, path, stage) < 0)
|
838
|
+
if (index_find(&position, index, path, stage) < 0) {
|
839
|
+
giterr_set(GITERR_INDEX, "Index does not contain %s at stage %d",
|
840
|
+
path, stage);
|
783
841
|
return GIT_ENOTFOUND;
|
842
|
+
}
|
784
843
|
|
785
844
|
entry = git_vector_get(&index->entries, position);
|
786
845
|
if (entry != NULL)
|
@@ -813,7 +872,7 @@ int git_index_remove_directory(git_index *index, const char *dir, int stage)
|
|
813
872
|
if (!entry || git__prefixcmp(entry->path, pfx.ptr) != 0)
|
814
873
|
break;
|
815
874
|
|
816
|
-
if (
|
875
|
+
if (GIT_IDXENTRY_STAGE(entry) != stage) {
|
817
876
|
++pos;
|
818
877
|
continue;
|
819
878
|
}
|
@@ -927,53 +986,80 @@ on_error:
|
|
927
986
|
return ret;
|
928
987
|
}
|
929
988
|
|
930
|
-
int
|
931
|
-
git_index_entry **
|
932
|
-
git_index_entry **
|
933
|
-
|
989
|
+
static int index_conflict__get_byindex(
|
990
|
+
const git_index_entry **ancestor_out,
|
991
|
+
const git_index_entry **our_out,
|
992
|
+
const git_index_entry **their_out,
|
993
|
+
git_index *index,
|
994
|
+
size_t n)
|
934
995
|
{
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
int
|
996
|
+
const git_index_entry *conflict_entry;
|
997
|
+
const char *path = NULL;
|
998
|
+
size_t count;
|
999
|
+
int stage, len = 0;
|
939
1000
|
|
940
|
-
assert(ancestor_out && our_out && their_out && index
|
1001
|
+
assert(ancestor_out && our_out && their_out && index);
|
941
1002
|
|
942
1003
|
*ancestor_out = NULL;
|
943
1004
|
*our_out = NULL;
|
944
1005
|
*their_out = NULL;
|
945
1006
|
|
946
|
-
|
947
|
-
|
1007
|
+
for (count = git_index_entrycount(index); n < count; ++n) {
|
1008
|
+
conflict_entry = git_vector_get(&index->entries, n);
|
948
1009
|
|
949
|
-
|
950
|
-
|
951
|
-
conflict_entry = git_vector_get(&index->entries, pos);
|
952
|
-
|
953
|
-
if (index->entries_cmp_path(conflict_entry->path, path) != 0)
|
1010
|
+
if (path && index->entries_cmp_path(conflict_entry->path, path) != 0)
|
954
1011
|
break;
|
955
1012
|
|
956
|
-
stage =
|
1013
|
+
stage = GIT_IDXENTRY_STAGE(conflict_entry);
|
1014
|
+
path = conflict_entry->path;
|
957
1015
|
|
958
1016
|
switch (stage) {
|
959
1017
|
case 3:
|
960
1018
|
*their_out = conflict_entry;
|
961
|
-
|
1019
|
+
len++;
|
962
1020
|
break;
|
963
1021
|
case 2:
|
964
1022
|
*our_out = conflict_entry;
|
965
|
-
|
1023
|
+
len++;
|
966
1024
|
break;
|
967
1025
|
case 1:
|
968
1026
|
*ancestor_out = conflict_entry;
|
969
|
-
|
1027
|
+
len++;
|
970
1028
|
break;
|
971
1029
|
default:
|
972
1030
|
break;
|
973
1031
|
};
|
974
1032
|
}
|
975
1033
|
|
976
|
-
return
|
1034
|
+
return len;
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
int git_index_conflict_get(
|
1038
|
+
const git_index_entry **ancestor_out,
|
1039
|
+
const git_index_entry **our_out,
|
1040
|
+
const git_index_entry **their_out,
|
1041
|
+
git_index *index,
|
1042
|
+
const char *path)
|
1043
|
+
{
|
1044
|
+
size_t pos;
|
1045
|
+
int len = 0;
|
1046
|
+
|
1047
|
+
assert(ancestor_out && our_out && their_out && index && path);
|
1048
|
+
|
1049
|
+
*ancestor_out = NULL;
|
1050
|
+
*our_out = NULL;
|
1051
|
+
*their_out = NULL;
|
1052
|
+
|
1053
|
+
if (git_index_find(&pos, index, path) < 0)
|
1054
|
+
return GIT_ENOTFOUND;
|
1055
|
+
|
1056
|
+
if ((len = index_conflict__get_byindex(
|
1057
|
+
ancestor_out, our_out, their_out, index, pos)) < 0)
|
1058
|
+
return len;
|
1059
|
+
else if (len == 0)
|
1060
|
+
return GIT_ENOTFOUND;
|
1061
|
+
|
1062
|
+
return 0;
|
977
1063
|
}
|
978
1064
|
|
979
1065
|
int git_index_conflict_remove(git_index *index, const char *path)
|
@@ -995,7 +1081,7 @@ int git_index_conflict_remove(git_index *index, const char *path)
|
|
995
1081
|
if (index->entries_cmp_path(conflict_entry->path, path) != 0)
|
996
1082
|
break;
|
997
1083
|
|
998
|
-
if (
|
1084
|
+
if (GIT_IDXENTRY_STAGE(conflict_entry) == 0) {
|
999
1085
|
pos++;
|
1000
1086
|
continue;
|
1001
1087
|
}
|
@@ -1014,7 +1100,7 @@ static int index_conflicts_match(const git_vector *v, size_t idx)
|
|
1014
1100
|
{
|
1015
1101
|
git_index_entry *entry = git_vector_get(v, idx);
|
1016
1102
|
|
1017
|
-
if (
|
1103
|
+
if (GIT_IDXENTRY_STAGE(entry) > 0) {
|
1018
1104
|
index_entry_free(entry);
|
1019
1105
|
return 1;
|
1020
1106
|
}
|
@@ -1036,20 +1122,151 @@ int git_index_has_conflicts(const git_index *index)
|
|
1036
1122
|
assert(index);
|
1037
1123
|
|
1038
1124
|
git_vector_foreach(&index->entries, i, entry) {
|
1039
|
-
if (
|
1125
|
+
if (GIT_IDXENTRY_STAGE(entry) > 0)
|
1040
1126
|
return 1;
|
1041
1127
|
}
|
1042
1128
|
|
1043
1129
|
return 0;
|
1044
1130
|
}
|
1045
1131
|
|
1132
|
+
int git_index_conflict_iterator_new(
|
1133
|
+
git_index_conflict_iterator **iterator_out,
|
1134
|
+
git_index *index)
|
1135
|
+
{
|
1136
|
+
git_index_conflict_iterator *it = NULL;
|
1137
|
+
|
1138
|
+
assert(iterator_out && index);
|
1139
|
+
|
1140
|
+
it = git__calloc(1, sizeof(git_index_conflict_iterator));
|
1141
|
+
GITERR_CHECK_ALLOC(it);
|
1142
|
+
|
1143
|
+
it->index = index;
|
1144
|
+
|
1145
|
+
*iterator_out = it;
|
1146
|
+
return 0;
|
1147
|
+
}
|
1148
|
+
|
1149
|
+
int git_index_conflict_next(
|
1150
|
+
const git_index_entry **ancestor_out,
|
1151
|
+
const git_index_entry **our_out,
|
1152
|
+
const git_index_entry **their_out,
|
1153
|
+
git_index_conflict_iterator *iterator)
|
1154
|
+
{
|
1155
|
+
const git_index_entry *entry;
|
1156
|
+
int len;
|
1157
|
+
|
1158
|
+
assert(ancestor_out && our_out && their_out && iterator);
|
1159
|
+
|
1160
|
+
*ancestor_out = NULL;
|
1161
|
+
*our_out = NULL;
|
1162
|
+
*their_out = NULL;
|
1163
|
+
|
1164
|
+
while (iterator->cur < iterator->index->entries.length) {
|
1165
|
+
entry = git_index_get_byindex(iterator->index, iterator->cur);
|
1166
|
+
|
1167
|
+
if (git_index_entry_stage(entry) > 0) {
|
1168
|
+
if ((len = index_conflict__get_byindex(
|
1169
|
+
ancestor_out,
|
1170
|
+
our_out,
|
1171
|
+
their_out,
|
1172
|
+
iterator->index,
|
1173
|
+
iterator->cur)) < 0)
|
1174
|
+
return len;
|
1175
|
+
|
1176
|
+
iterator->cur += len;
|
1177
|
+
return 0;
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
iterator->cur++;
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
return GIT_ITEROVER;
|
1184
|
+
}
|
1185
|
+
|
1186
|
+
void git_index_conflict_iterator_free(git_index_conflict_iterator *iterator)
|
1187
|
+
{
|
1188
|
+
if (iterator == NULL)
|
1189
|
+
return;
|
1190
|
+
|
1191
|
+
git__free(iterator);
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
unsigned int git_index_name_entrycount(git_index *index)
|
1195
|
+
{
|
1196
|
+
assert(index);
|
1197
|
+
return (unsigned int)index->names.length;
|
1198
|
+
}
|
1199
|
+
|
1200
|
+
const git_index_name_entry *git_index_name_get_byindex(
|
1201
|
+
git_index *index, size_t n)
|
1202
|
+
{
|
1203
|
+
assert(index);
|
1204
|
+
|
1205
|
+
git_vector_sort(&index->names);
|
1206
|
+
return git_vector_get(&index->names, n);
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
int git_index_name_add(git_index *index,
|
1210
|
+
const char *ancestor, const char *ours, const char *theirs)
|
1211
|
+
{
|
1212
|
+
git_index_name_entry *conflict_name;
|
1213
|
+
|
1214
|
+
assert ((ancestor && ours) || (ancestor && theirs) || (ours && theirs));
|
1215
|
+
|
1216
|
+
conflict_name = git__calloc(1, sizeof(git_index_name_entry));
|
1217
|
+
GITERR_CHECK_ALLOC(conflict_name);
|
1218
|
+
|
1219
|
+
if (ancestor) {
|
1220
|
+
conflict_name->ancestor = git__strdup(ancestor);
|
1221
|
+
GITERR_CHECK_ALLOC(conflict_name->ancestor);
|
1222
|
+
}
|
1223
|
+
|
1224
|
+
if (ours) {
|
1225
|
+
conflict_name->ours = git__strdup(ours);
|
1226
|
+
GITERR_CHECK_ALLOC(conflict_name->ours);
|
1227
|
+
}
|
1228
|
+
|
1229
|
+
if (theirs) {
|
1230
|
+
conflict_name->theirs = git__strdup(theirs);
|
1231
|
+
GITERR_CHECK_ALLOC(conflict_name->theirs);
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
return git_vector_insert(&index->names, conflict_name);
|
1235
|
+
}
|
1236
|
+
|
1237
|
+
void git_index_name_clear(git_index *index)
|
1238
|
+
{
|
1239
|
+
size_t i;
|
1240
|
+
git_index_name_entry *conflict_name;
|
1241
|
+
|
1242
|
+
assert(index);
|
1243
|
+
|
1244
|
+
git_vector_foreach(&index->names, i, conflict_name) {
|
1245
|
+
if (conflict_name->ancestor)
|
1246
|
+
git__free(conflict_name->ancestor);
|
1247
|
+
|
1248
|
+
if (conflict_name->ours)
|
1249
|
+
git__free(conflict_name->ours);
|
1250
|
+
|
1251
|
+
if (conflict_name->theirs)
|
1252
|
+
git__free(conflict_name->theirs);
|
1253
|
+
|
1254
|
+
git__free(conflict_name);
|
1255
|
+
}
|
1256
|
+
|
1257
|
+
git_vector_clear(&index->names);
|
1258
|
+
}
|
1259
|
+
|
1046
1260
|
unsigned int git_index_reuc_entrycount(git_index *index)
|
1047
1261
|
{
|
1048
1262
|
assert(index);
|
1049
1263
|
return (unsigned int)index->reuc.length;
|
1050
1264
|
}
|
1051
1265
|
|
1052
|
-
static int index_reuc_insert(
|
1266
|
+
static int index_reuc_insert(
|
1267
|
+
git_index *index,
|
1268
|
+
git_index_reuc_entry *reuc,
|
1269
|
+
int replace)
|
1053
1270
|
{
|
1054
1271
|
git_index_reuc_entry **existing = NULL;
|
1055
1272
|
size_t position;
|
@@ -1071,9 +1288,9 @@ static int index_reuc_insert(git_index *index, git_index_reuc_entry *reuc, int r
|
|
1071
1288
|
}
|
1072
1289
|
|
1073
1290
|
int git_index_reuc_add(git_index *index, const char *path,
|
1074
|
-
int ancestor_mode, git_oid *ancestor_oid,
|
1075
|
-
int our_mode, git_oid *our_oid,
|
1076
|
-
int their_mode, git_oid *their_oid)
|
1291
|
+
int ancestor_mode, const git_oid *ancestor_oid,
|
1292
|
+
int our_mode, const git_oid *our_oid,
|
1293
|
+
int their_mode, const git_oid *their_oid)
|
1077
1294
|
{
|
1078
1295
|
git_index_reuc_entry *reuc = NULL;
|
1079
1296
|
int error = 0;
|
@@ -1164,8 +1381,9 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|
1164
1381
|
size_t len;
|
1165
1382
|
int i;
|
1166
1383
|
|
1167
|
-
/*
|
1168
|
-
if (index->reuc._alloc_size == 0 &&
|
1384
|
+
/* If called multiple times, the vector might already be initialized */
|
1385
|
+
if (index->reuc._alloc_size == 0 &&
|
1386
|
+
git_vector_init(&index->reuc, 16, reuc_cmp) < 0)
|
1169
1387
|
return -1;
|
1170
1388
|
|
1171
1389
|
while (size) {
|
@@ -1175,12 +1393,9 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|
1175
1393
|
if (size <= len)
|
1176
1394
|
return index_error_invalid("reading reuc entries");
|
1177
1395
|
|
1178
|
-
lost =
|
1396
|
+
lost = git__calloc(1, sizeof(git_index_reuc_entry));
|
1179
1397
|
GITERR_CHECK_ALLOC(lost);
|
1180
1398
|
|
1181
|
-
if (git_vector_insert(&index->reuc, lost) < 0)
|
1182
|
-
return -1;
|
1183
|
-
|
1184
1399
|
/* read NUL-terminated pathname for entry */
|
1185
1400
|
lost->path = git__strdup(buffer);
|
1186
1401
|
GITERR_CHECK_ALLOC(lost->path);
|
@@ -1218,6 +1433,10 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|
1218
1433
|
size -= 20;
|
1219
1434
|
buffer += 20;
|
1220
1435
|
}
|
1436
|
+
|
1437
|
+
/* entry was read successfully - insert into reuc vector */
|
1438
|
+
if (git_vector_insert(&index->reuc, lost) < 0)
|
1439
|
+
return -1;
|
1221
1440
|
}
|
1222
1441
|
|
1223
1442
|
/* entries are guaranteed to be sorted on-disk */
|
@@ -1226,6 +1445,52 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|
1226
1445
|
return 0;
|
1227
1446
|
}
|
1228
1447
|
|
1448
|
+
|
1449
|
+
static int read_conflict_names(git_index *index, const char *buffer, size_t size)
|
1450
|
+
{
|
1451
|
+
size_t len;
|
1452
|
+
|
1453
|
+
/* This gets called multiple times, the vector might already be initialized */
|
1454
|
+
if (index->names._alloc_size == 0 &&
|
1455
|
+
git_vector_init(&index->names, 16, conflict_name_cmp) < 0)
|
1456
|
+
return -1;
|
1457
|
+
|
1458
|
+
#define read_conflict_name(ptr) \
|
1459
|
+
len = strlen(buffer) + 1; \
|
1460
|
+
if (size < len) \
|
1461
|
+
return index_error_invalid("reading conflict name entries"); \
|
1462
|
+
\
|
1463
|
+
if (len == 1) \
|
1464
|
+
ptr = NULL; \
|
1465
|
+
else { \
|
1466
|
+
ptr = git__malloc(len); \
|
1467
|
+
GITERR_CHECK_ALLOC(ptr); \
|
1468
|
+
memcpy(ptr, buffer, len); \
|
1469
|
+
} \
|
1470
|
+
\
|
1471
|
+
buffer += len; \
|
1472
|
+
size -= len;
|
1473
|
+
|
1474
|
+
while (size) {
|
1475
|
+
git_index_name_entry *conflict_name = git__calloc(1, sizeof(git_index_name_entry));
|
1476
|
+
GITERR_CHECK_ALLOC(conflict_name);
|
1477
|
+
|
1478
|
+
read_conflict_name(conflict_name->ancestor);
|
1479
|
+
read_conflict_name(conflict_name->ours);
|
1480
|
+
read_conflict_name(conflict_name->theirs);
|
1481
|
+
|
1482
|
+
if (git_vector_insert(&index->names, conflict_name) < 0)
|
1483
|
+
return -1;
|
1484
|
+
}
|
1485
|
+
|
1486
|
+
#undef read_conflict_name
|
1487
|
+
|
1488
|
+
/* entries are guaranteed to be sorted on-disk */
|
1489
|
+
index->names.sorted = 1;
|
1490
|
+
|
1491
|
+
return 0;
|
1492
|
+
}
|
1493
|
+
|
1229
1494
|
static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size)
|
1230
1495
|
{
|
1231
1496
|
size_t path_length, entry_size;
|
@@ -1318,7 +1583,8 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
|
|
1318
1583
|
|
1319
1584
|
total_size = dest.extension_size + sizeof(struct index_extension);
|
1320
1585
|
|
1321
|
-
if (buffer_size
|
1586
|
+
if (buffer_size < total_size ||
|
1587
|
+
buffer_size - total_size < INDEX_FOOTER_SIZE)
|
1322
1588
|
return 0;
|
1323
1589
|
|
1324
1590
|
/* optional extension */
|
@@ -1330,6 +1596,9 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
|
|
1330
1596
|
} else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) {
|
1331
1597
|
if (read_reuc(index, buffer + 8, dest.extension_size) < 0)
|
1332
1598
|
return 0;
|
1599
|
+
} else if (memcmp(dest.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4) == 0) {
|
1600
|
+
if (read_conflict_names(index, buffer + 8, dest.extension_size) < 0)
|
1601
|
+
return 0;
|
1333
1602
|
}
|
1334
1603
|
/* else, unsupported extension. We cannot parse this, but we can skip
|
1335
1604
|
* it by returning `total_size */
|
@@ -1345,7 +1614,7 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
|
|
1345
1614
|
static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
|
1346
1615
|
{
|
1347
1616
|
unsigned int i;
|
1348
|
-
struct index_header header;
|
1617
|
+
struct index_header header = { 0 };
|
1349
1618
|
git_oid checksum_calculated, checksum_expected;
|
1350
1619
|
|
1351
1620
|
#define seek_forward(_increase) { \
|
@@ -1401,7 +1670,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
|
|
1401
1670
|
|
1402
1671
|
/* see if we have read any bytes from the extension */
|
1403
1672
|
if (extension_size == 0)
|
1404
|
-
return index_error_invalid("extension
|
1673
|
+
return index_error_invalid("extension is truncated");
|
1405
1674
|
|
1406
1675
|
seek_forward(extension_size);
|
1407
1676
|
}
|
@@ -1412,7 +1681,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
|
|
1412
1681
|
/* 160-bit SHA-1 over the content of the index file before this checksum. */
|
1413
1682
|
git_oid_fromraw(&checksum_expected, (const unsigned char *)buffer);
|
1414
1683
|
|
1415
|
-
if (
|
1684
|
+
if (git_oid__cmp(&checksum_calculated, &checksum_expected) != 0)
|
1416
1685
|
return index_error_invalid("calculated checksum does not match expected");
|
1417
1686
|
|
1418
1687
|
#undef seek_forward
|
@@ -1543,6 +1812,61 @@ static int write_extension(git_filebuf *file, struct index_extension *header, gi
|
|
1543
1812
|
return error;
|
1544
1813
|
}
|
1545
1814
|
|
1815
|
+
static int create_name_extension_data(git_buf *name_buf, git_index_name_entry *conflict_name)
|
1816
|
+
{
|
1817
|
+
int error = 0;
|
1818
|
+
|
1819
|
+
if (conflict_name->ancestor == NULL)
|
1820
|
+
error = git_buf_put(name_buf, "\0", 1);
|
1821
|
+
else
|
1822
|
+
error = git_buf_put(name_buf, conflict_name->ancestor, strlen(conflict_name->ancestor) + 1);
|
1823
|
+
|
1824
|
+
if (error != 0)
|
1825
|
+
goto on_error;
|
1826
|
+
|
1827
|
+
if (conflict_name->ours == NULL)
|
1828
|
+
error = git_buf_put(name_buf, "\0", 1);
|
1829
|
+
else
|
1830
|
+
error = git_buf_put(name_buf, conflict_name->ours, strlen(conflict_name->ours) + 1);
|
1831
|
+
|
1832
|
+
if (error != 0)
|
1833
|
+
goto on_error;
|
1834
|
+
|
1835
|
+
if (conflict_name->theirs == NULL)
|
1836
|
+
error = git_buf_put(name_buf, "\0", 1);
|
1837
|
+
else
|
1838
|
+
error = git_buf_put(name_buf, conflict_name->theirs, strlen(conflict_name->theirs) + 1);
|
1839
|
+
|
1840
|
+
on_error:
|
1841
|
+
return error;
|
1842
|
+
}
|
1843
|
+
|
1844
|
+
static int write_name_extension(git_index *index, git_filebuf *file)
|
1845
|
+
{
|
1846
|
+
git_buf name_buf = GIT_BUF_INIT;
|
1847
|
+
git_vector *out = &index->names;
|
1848
|
+
git_index_name_entry *conflict_name;
|
1849
|
+
struct index_extension extension;
|
1850
|
+
size_t i;
|
1851
|
+
int error = 0;
|
1852
|
+
|
1853
|
+
git_vector_foreach(out, i, conflict_name) {
|
1854
|
+
if ((error = create_name_extension_data(&name_buf, conflict_name)) < 0)
|
1855
|
+
goto done;
|
1856
|
+
}
|
1857
|
+
|
1858
|
+
memset(&extension, 0x0, sizeof(struct index_extension));
|
1859
|
+
memcpy(&extension.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4);
|
1860
|
+
extension.extension_size = (uint32_t)name_buf.size;
|
1861
|
+
|
1862
|
+
error = write_extension(file, &extension, &name_buf);
|
1863
|
+
|
1864
|
+
git_buf_free(&name_buf);
|
1865
|
+
|
1866
|
+
done:
|
1867
|
+
return error;
|
1868
|
+
}
|
1869
|
+
|
1546
1870
|
static int create_reuc_extension_data(git_buf *reuc_buf, git_index_reuc_entry *reuc)
|
1547
1871
|
{
|
1548
1872
|
int i;
|
@@ -1613,6 +1937,10 @@ static int write_index(git_index *index, git_filebuf *file)
|
|
1613
1937
|
|
1614
1938
|
/* TODO: write tree cache extension */
|
1615
1939
|
|
1940
|
+
/* write the rename conflict extension */
|
1941
|
+
if (index->names.length > 0 && write_name_extension(index, file) < 0)
|
1942
|
+
return -1;
|
1943
|
+
|
1616
1944
|
/* write the reuc extension */
|
1617
1945
|
if (index->reuc.length > 0 && write_reuc_extension(index, file) < 0)
|
1618
1946
|
return -1;
|
@@ -1626,18 +1954,19 @@ static int write_index(git_index *index, git_filebuf *file)
|
|
1626
1954
|
|
1627
1955
|
int git_index_entry_stage(const git_index_entry *entry)
|
1628
1956
|
{
|
1629
|
-
return
|
1957
|
+
return GIT_IDXENTRY_STAGE(entry);
|
1630
1958
|
}
|
1631
1959
|
|
1632
1960
|
typedef struct read_tree_data {
|
1633
1961
|
git_index *index;
|
1634
|
-
|
1962
|
+
git_vector *old_entries;
|
1635
1963
|
} read_tree_data;
|
1636
1964
|
|
1637
|
-
static int read_tree_cb(
|
1965
|
+
static int read_tree_cb(
|
1966
|
+
const char *root, const git_tree_entry *tentry, void *payload)
|
1638
1967
|
{
|
1639
|
-
|
1640
|
-
git_index_entry *entry = NULL;
|
1968
|
+
read_tree_data *data = payload;
|
1969
|
+
git_index_entry *entry = NULL, *old_entry;
|
1641
1970
|
git_buf path = GIT_BUF_INIT;
|
1642
1971
|
|
1643
1972
|
if (git_tree_entry__is_tree(tentry))
|
@@ -1652,6 +1981,25 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
|
|
1652
1981
|
entry->mode = tentry->attr;
|
1653
1982
|
entry->oid = tentry->oid;
|
1654
1983
|
|
1984
|
+
/* look for corresponding old entry and copy data to new entry */
|
1985
|
+
if (data->old_entries) {
|
1986
|
+
size_t pos;
|
1987
|
+
struct entry_srch_key skey;
|
1988
|
+
|
1989
|
+
skey.path = path.ptr;
|
1990
|
+
skey.stage = 0;
|
1991
|
+
|
1992
|
+
if (!git_vector_bsearch2(
|
1993
|
+
&pos, data->old_entries, data->index->entries_search, &skey) &&
|
1994
|
+
(old_entry = git_vector_get(data->old_entries, pos)) != NULL &&
|
1995
|
+
entry->mode == old_entry->mode &&
|
1996
|
+
git_oid_equal(&entry->oid, &old_entry->oid))
|
1997
|
+
{
|
1998
|
+
memcpy(entry, old_entry, sizeof(*entry));
|
1999
|
+
entry->flags_extended = 0;
|
2000
|
+
}
|
2001
|
+
}
|
2002
|
+
|
1655
2003
|
if (path.size < GIT_IDXENTRY_NAMEMASK)
|
1656
2004
|
entry->flags = path.size & GIT_IDXENTRY_NAMEMASK;
|
1657
2005
|
else
|
@@ -1660,7 +2008,7 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
|
|
1660
2008
|
entry->path = git_buf_detach(&path);
|
1661
2009
|
git_buf_free(&path);
|
1662
2010
|
|
1663
|
-
if (git_vector_insert(&index->entries, entry) < 0) {
|
2011
|
+
if (git_vector_insert(&data->index->entries, entry) < 0) {
|
1664
2012
|
index_entry_free(entry);
|
1665
2013
|
return -1;
|
1666
2014
|
}
|
@@ -1670,12 +2018,246 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
|
|
1670
2018
|
|
1671
2019
|
int git_index_read_tree(git_index *index, const git_tree *tree)
|
1672
2020
|
{
|
2021
|
+
int error = 0;
|
2022
|
+
git_vector entries = GIT_VECTOR_INIT;
|
2023
|
+
read_tree_data data;
|
2024
|
+
|
2025
|
+
git_vector_sort(&index->entries);
|
2026
|
+
|
2027
|
+
git_vector_set_cmp(&entries, index->entries._cmp);
|
2028
|
+
git_vector_swap(&entries, &index->entries);
|
2029
|
+
|
1673
2030
|
git_index_clear(index);
|
1674
2031
|
|
1675
|
-
|
2032
|
+
data.index = index;
|
2033
|
+
data.old_entries = &entries;
|
2034
|
+
|
2035
|
+
error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data);
|
2036
|
+
|
2037
|
+
index_entries_free(&entries);
|
2038
|
+
git_vector_free(&entries);
|
2039
|
+
|
2040
|
+
git_vector_sort(&index->entries);
|
2041
|
+
|
2042
|
+
return error;
|
1676
2043
|
}
|
1677
2044
|
|
1678
2045
|
git_repository *git_index_owner(const git_index *index)
|
1679
2046
|
{
|
1680
2047
|
return INDEX_OWNER(index);
|
1681
2048
|
}
|
2049
|
+
|
2050
|
+
int git_index_add_all(
|
2051
|
+
git_index *index,
|
2052
|
+
const git_strarray *paths,
|
2053
|
+
unsigned int flags,
|
2054
|
+
git_index_matched_path_cb cb,
|
2055
|
+
void *payload)
|
2056
|
+
{
|
2057
|
+
int error;
|
2058
|
+
git_repository *repo;
|
2059
|
+
git_iterator *wditer = NULL;
|
2060
|
+
const git_index_entry *wd = NULL;
|
2061
|
+
git_index_entry *entry;
|
2062
|
+
git_pathspec_context ps;
|
2063
|
+
const char *match;
|
2064
|
+
size_t existing;
|
2065
|
+
bool no_fnmatch = (flags & GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH) != 0;
|
2066
|
+
int ignorecase;
|
2067
|
+
git_oid blobid;
|
2068
|
+
|
2069
|
+
assert(index);
|
2070
|
+
|
2071
|
+
if (INDEX_OWNER(index) == NULL)
|
2072
|
+
return create_index_error(-1,
|
2073
|
+
"Could not add paths to index. "
|
2074
|
+
"Index is not backed up by an existing repository.");
|
2075
|
+
|
2076
|
+
repo = INDEX_OWNER(index);
|
2077
|
+
if ((error = git_repository__ensure_not_bare(repo, "index add all")) < 0)
|
2078
|
+
return error;
|
2079
|
+
|
2080
|
+
if (git_repository__cvar(&ignorecase, repo, GIT_CVAR_IGNORECASE) < 0)
|
2081
|
+
return -1;
|
2082
|
+
|
2083
|
+
if ((error = git_pathspec_context_init(&ps, paths)) < 0)
|
2084
|
+
return error;
|
2085
|
+
|
2086
|
+
/* optionally check that pathspec doesn't mention any ignored files */
|
2087
|
+
if ((flags & GIT_INDEX_ADD_CHECK_PATHSPEC) != 0 &&
|
2088
|
+
(flags & GIT_INDEX_ADD_FORCE) == 0 &&
|
2089
|
+
(error = git_ignore__check_pathspec_for_exact_ignores(
|
2090
|
+
repo, &ps.pathspec, no_fnmatch)) < 0)
|
2091
|
+
goto cleanup;
|
2092
|
+
|
2093
|
+
if ((error = git_iterator_for_workdir(
|
2094
|
+
&wditer, repo, 0, ps.prefix, ps.prefix)) < 0)
|
2095
|
+
goto cleanup;
|
2096
|
+
|
2097
|
+
while (!(error = git_iterator_advance(&wd, wditer))) {
|
2098
|
+
|
2099
|
+
/* check if path actually matches */
|
2100
|
+
if (!git_pathspec_match_path(
|
2101
|
+
&ps.pathspec, wd->path, no_fnmatch, ignorecase, &match))
|
2102
|
+
continue;
|
2103
|
+
|
2104
|
+
/* skip ignored items that are not already in the index */
|
2105
|
+
if ((flags & GIT_INDEX_ADD_FORCE) == 0 &&
|
2106
|
+
git_iterator_current_is_ignored(wditer) &&
|
2107
|
+
index_find(&existing, index, wd->path, 0) < 0)
|
2108
|
+
continue;
|
2109
|
+
|
2110
|
+
/* issue notification callback if requested */
|
2111
|
+
if (cb && (error = cb(wd->path, match, payload)) != 0) {
|
2112
|
+
if (error > 0) /* return > 0 means skip this one */
|
2113
|
+
continue;
|
2114
|
+
if (error < 0) { /* return < 0 means abort */
|
2115
|
+
giterr_clear();
|
2116
|
+
error = GIT_EUSER;
|
2117
|
+
break;
|
2118
|
+
}
|
2119
|
+
}
|
2120
|
+
|
2121
|
+
/* TODO: Should we check if the file on disk is already an exact
|
2122
|
+
* match to the file in the index and skip this work if it is?
|
2123
|
+
*/
|
2124
|
+
|
2125
|
+
/* write the blob to disk and get the oid */
|
2126
|
+
if ((error = git_blob_create_fromworkdir(&blobid, repo, wd->path)) < 0)
|
2127
|
+
break;
|
2128
|
+
|
2129
|
+
/* make the new entry to insert */
|
2130
|
+
if ((entry = index_entry_dup(wd)) == NULL) {
|
2131
|
+
error = -1;
|
2132
|
+
break;
|
2133
|
+
}
|
2134
|
+
entry->oid = blobid;
|
2135
|
+
|
2136
|
+
/* add working directory item to index */
|
2137
|
+
if ((error = index_insert(index, entry, 1)) < 0) {
|
2138
|
+
index_entry_free(entry);
|
2139
|
+
break;
|
2140
|
+
}
|
2141
|
+
|
2142
|
+
git_tree_cache_invalidate_path(index->tree, wd->path);
|
2143
|
+
|
2144
|
+
/* add implies conflict resolved, move conflict entries to REUC */
|
2145
|
+
if ((error = index_conflict_to_reuc(index, wd->path)) < 0) {
|
2146
|
+
if (error != GIT_ENOTFOUND)
|
2147
|
+
break;
|
2148
|
+
giterr_clear();
|
2149
|
+
}
|
2150
|
+
}
|
2151
|
+
|
2152
|
+
if (error == GIT_ITEROVER)
|
2153
|
+
error = 0;
|
2154
|
+
|
2155
|
+
cleanup:
|
2156
|
+
git_iterator_free(wditer);
|
2157
|
+
git_pathspec_context_free(&ps);
|
2158
|
+
|
2159
|
+
return error;
|
2160
|
+
}
|
2161
|
+
|
2162
|
+
enum {
|
2163
|
+
INDEX_ACTION_NONE = 0,
|
2164
|
+
INDEX_ACTION_UPDATE = 1,
|
2165
|
+
INDEX_ACTION_REMOVE = 2,
|
2166
|
+
};
|
2167
|
+
|
2168
|
+
static int index_apply_to_all(
|
2169
|
+
git_index *index,
|
2170
|
+
int action,
|
2171
|
+
const git_strarray *paths,
|
2172
|
+
git_index_matched_path_cb cb,
|
2173
|
+
void *payload)
|
2174
|
+
{
|
2175
|
+
int error = 0;
|
2176
|
+
size_t i;
|
2177
|
+
git_pathspec_context ps;
|
2178
|
+
const char *match;
|
2179
|
+
git_buf path = GIT_BUF_INIT;
|
2180
|
+
|
2181
|
+
assert(index);
|
2182
|
+
|
2183
|
+
if ((error = git_pathspec_context_init(&ps, paths)) < 0)
|
2184
|
+
return error;
|
2185
|
+
|
2186
|
+
git_vector_sort(&index->entries);
|
2187
|
+
|
2188
|
+
for (i = 0; !error && i < index->entries.length; ++i) {
|
2189
|
+
git_index_entry *entry = git_vector_get(&index->entries, i);
|
2190
|
+
|
2191
|
+
/* check if path actually matches */
|
2192
|
+
if (!git_pathspec_match_path(
|
2193
|
+
&ps.pathspec, entry->path, false, index->ignore_case, &match))
|
2194
|
+
continue;
|
2195
|
+
|
2196
|
+
/* issue notification callback if requested */
|
2197
|
+
if (cb && (error = cb(entry->path, match, payload)) != 0) {
|
2198
|
+
if (error > 0) { /* return > 0 means skip this one */
|
2199
|
+
error = 0;
|
2200
|
+
continue;
|
2201
|
+
}
|
2202
|
+
if (error < 0) { /* return < 0 means abort */
|
2203
|
+
giterr_clear();
|
2204
|
+
error = GIT_EUSER;
|
2205
|
+
break;
|
2206
|
+
}
|
2207
|
+
}
|
2208
|
+
|
2209
|
+
/* index manipulation may alter entry, so don't depend on it */
|
2210
|
+
if ((error = git_buf_sets(&path, entry->path)) < 0)
|
2211
|
+
break;
|
2212
|
+
|
2213
|
+
switch (action) {
|
2214
|
+
case INDEX_ACTION_NONE:
|
2215
|
+
break;
|
2216
|
+
case INDEX_ACTION_UPDATE:
|
2217
|
+
error = git_index_add_bypath(index, path.ptr);
|
2218
|
+
|
2219
|
+
if (error == GIT_ENOTFOUND) {
|
2220
|
+
giterr_clear();
|
2221
|
+
|
2222
|
+
error = git_index_remove_bypath(index, path.ptr);
|
2223
|
+
|
2224
|
+
if (!error) /* back up foreach if we removed this */
|
2225
|
+
i--;
|
2226
|
+
}
|
2227
|
+
break;
|
2228
|
+
case INDEX_ACTION_REMOVE:
|
2229
|
+
if (!(error = git_index_remove_bypath(index, path.ptr)))
|
2230
|
+
i--; /* back up foreach if we removed this */
|
2231
|
+
break;
|
2232
|
+
default:
|
2233
|
+
giterr_set(GITERR_INVALID, "Unknown index action %d", action);
|
2234
|
+
error = -1;
|
2235
|
+
break;
|
2236
|
+
}
|
2237
|
+
}
|
2238
|
+
|
2239
|
+
git_buf_free(&path);
|
2240
|
+
git_pathspec_context_free(&ps);
|
2241
|
+
|
2242
|
+
return error;
|
2243
|
+
}
|
2244
|
+
|
2245
|
+
int git_index_remove_all(
|
2246
|
+
git_index *index,
|
2247
|
+
const git_strarray *pathspec,
|
2248
|
+
git_index_matched_path_cb cb,
|
2249
|
+
void *payload)
|
2250
|
+
{
|
2251
|
+
return index_apply_to_all(
|
2252
|
+
index, INDEX_ACTION_REMOVE, pathspec, cb, payload);
|
2253
|
+
}
|
2254
|
+
|
2255
|
+
int git_index_update_all(
|
2256
|
+
git_index *index,
|
2257
|
+
const git_strarray *pathspec,
|
2258
|
+
git_index_matched_path_cb cb,
|
2259
|
+
void *payload)
|
2260
|
+
{
|
2261
|
+
return index_apply_to_all(
|
2262
|
+
index, INDEX_ACTION_UPDATE, pathspec, cb, payload);
|
2263
|
+
}
|