rugged 0.22.2 → 0.23.0b1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/rugged/rugged.c +1 -2
- data/ext/rugged/rugged_branch_collection.c +6 -44
- data/ext/rugged/rugged_config.c +7 -3
- data/ext/rugged/rugged_diff_delta.c +1 -1
- data/ext/rugged/rugged_diff_line.c +1 -1
- data/ext/rugged/rugged_object.c +2 -2
- data/ext/rugged/rugged_reference_collection.c +12 -56
- data/ext/rugged/rugged_remote.c +4 -33
- data/ext/rugged/rugged_remote_collection.c +1 -1
- data/ext/rugged/rugged_repo.c +10 -36
- data/ext/rugged/rugged_settings.c +3 -3
- data/ext/rugged/rugged_tree.c +1 -1
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +10 -3
- data/vendor/libgit2/COPYING +15 -21
- data/vendor/libgit2/include/git2/annotated_commit.h +20 -3
- data/vendor/libgit2/include/git2/branch.h +20 -16
- data/vendor/libgit2/include/git2/checkout.h +32 -18
- data/vendor/libgit2/include/git2/cherrypick.h +2 -2
- data/vendor/libgit2/include/git2/clone.h +4 -10
- data/vendor/libgit2/include/git2/config.h +66 -12
- data/vendor/libgit2/include/git2/describe.h +3 -2
- data/vendor/libgit2/include/git2/diff.h +3 -3
- data/vendor/libgit2/include/git2/errors.h +1 -0
- data/vendor/libgit2/include/git2/filter.h +21 -5
- data/vendor/libgit2/include/git2/index.h +32 -0
- data/vendor/libgit2/include/git2/merge.h +20 -3
- data/vendor/libgit2/include/git2/oid.h +1 -1
- data/vendor/libgit2/include/git2/pack.h +13 -0
- data/vendor/libgit2/include/git2/patch.h +3 -6
- data/vendor/libgit2/include/git2/rebase.h +8 -12
- data/vendor/libgit2/include/git2/refs.h +19 -29
- data/vendor/libgit2/include/git2/remote.h +5 -11
- data/vendor/libgit2/include/git2/repository.h +44 -15
- data/vendor/libgit2/include/git2/reset.h +19 -10
- data/vendor/libgit2/include/git2/revert.h +2 -2
- data/vendor/libgit2/include/git2/submodule.h +3 -9
- data/vendor/libgit2/include/git2/sys/config.h +3 -1
- data/vendor/libgit2/include/git2/sys/filter.h +10 -2
- data/vendor/libgit2/include/git2/sys/hashsig.h +49 -22
- data/vendor/libgit2/include/git2/transport.h +1 -1
- data/vendor/libgit2/include/git2/types.h +10 -3
- data/vendor/libgit2/include/git2/version.h +3 -2
- data/vendor/libgit2/src/annotated_commit.c +28 -0
- data/vendor/libgit2/src/array.h +19 -8
- data/vendor/libgit2/src/attr.c +95 -35
- data/vendor/libgit2/src/attr_file.c +51 -17
- data/vendor/libgit2/src/attr_file.h +37 -10
- data/vendor/libgit2/src/attrcache.c +13 -7
- data/vendor/libgit2/src/attrcache.h +1 -0
- data/vendor/libgit2/src/blame.c +26 -2
- data/vendor/libgit2/src/blame_git.c +6 -2
- data/vendor/libgit2/src/blob.c +6 -8
- data/vendor/libgit2/src/branch.c +55 -43
- data/vendor/libgit2/src/buf_text.c +13 -6
- data/vendor/libgit2/src/buffer.c +110 -25
- data/vendor/libgit2/src/buffer.h +18 -0
- data/vendor/libgit2/src/checkout.c +164 -92
- data/vendor/libgit2/src/checkout.h +0 -7
- data/vendor/libgit2/src/cherrypick.c +13 -7
- data/vendor/libgit2/src/clone.c +23 -25
- data/vendor/libgit2/src/commit.c +3 -3
- data/vendor/libgit2/src/common.h +23 -1
- data/vendor/libgit2/src/config.c +137 -19
- data/vendor/libgit2/src/config.h +2 -2
- data/vendor/libgit2/src/config_cache.c +2 -1
- data/vendor/libgit2/src/config_file.c +39 -18
- data/vendor/libgit2/src/config_file.h +1 -1
- data/vendor/libgit2/src/crlf.c +1 -1
- data/vendor/libgit2/src/delta-apply.c +3 -2
- data/vendor/libgit2/src/delta.c +25 -6
- data/vendor/libgit2/src/describe.c +2 -0
- data/vendor/libgit2/src/diff.c +8 -5
- data/vendor/libgit2/src/diff_driver.c +39 -18
- data/vendor/libgit2/src/diff_file.c +1 -1
- data/vendor/libgit2/src/diff_patch.c +12 -6
- data/vendor/libgit2/src/diff_tform.c +21 -24
- data/vendor/libgit2/src/filebuf.c +14 -12
- data/vendor/libgit2/src/fileops.c +61 -18
- data/vendor/libgit2/src/fileops.h +11 -2
- data/vendor/libgit2/src/filter.c +351 -99
- data/vendor/libgit2/src/filter.h +17 -0
- data/vendor/libgit2/src/global.c +38 -9
- data/vendor/libgit2/src/hash/hash_generic.c +1 -1
- data/vendor/libgit2/src/hashsig.c +28 -16
- data/vendor/libgit2/src/ignore.c +2 -2
- data/vendor/libgit2/src/index.c +159 -42
- data/vendor/libgit2/src/index.h +29 -0
- data/vendor/libgit2/src/indexer.c +11 -2
- data/vendor/libgit2/src/integer.h +96 -0
- data/vendor/libgit2/src/iterator.c +5 -3
- data/vendor/libgit2/src/khash.h +41 -29
- data/vendor/libgit2/src/merge.c +48 -35
- data/vendor/libgit2/src/merge.h +0 -1
- data/vendor/libgit2/src/merge_file.c +13 -0
- data/vendor/libgit2/src/mwindow.c +1 -1
- data/vendor/libgit2/src/notes.c +1 -1
- data/vendor/libgit2/src/odb.c +13 -11
- data/vendor/libgit2/src/odb_loose.c +22 -10
- data/vendor/libgit2/src/odb_mempack.c +4 -2
- data/vendor/libgit2/src/offmap.h +3 -2
- data/vendor/libgit2/src/oid.c +1 -1
- data/vendor/libgit2/src/oidmap.h +2 -1
- data/vendor/libgit2/src/openssl_stream.c +6 -3
- data/vendor/libgit2/src/pack-objects.c +273 -12
- data/vendor/libgit2/src/pack-objects.h +10 -0
- data/vendor/libgit2/src/pack.c +17 -6
- data/vendor/libgit2/src/pack.h +1 -3
- data/vendor/libgit2/src/path.c +68 -38
- data/vendor/libgit2/src/pathspec.c +3 -0
- data/vendor/libgit2/src/pool.c +9 -8
- data/vendor/libgit2/src/posix.c +11 -1
- data/vendor/libgit2/src/push.c +15 -17
- data/vendor/libgit2/src/push.h +1 -6
- data/vendor/libgit2/src/rebase.c +77 -35
- data/vendor/libgit2/src/refdb_fs.c +2 -2
- data/vendor/libgit2/src/refs.c +107 -81
- data/vendor/libgit2/src/refs.h +2 -2
- data/vendor/libgit2/src/refspec.c +3 -0
- data/vendor/libgit2/src/remote.c +19 -21
- data/vendor/libgit2/src/repository.c +258 -67
- data/vendor/libgit2/src/repository.h +31 -16
- data/vendor/libgit2/src/reset.c +28 -12
- data/vendor/libgit2/src/revert.c +12 -7
- data/vendor/libgit2/src/revwalk.c +3 -5
- data/vendor/libgit2/src/revwalk.h +1 -1
- data/vendor/libgit2/src/sortedcache.c +5 -3
- data/vendor/libgit2/src/stash.c +3 -5
- data/vendor/libgit2/src/strmap.h +2 -1
- data/vendor/libgit2/src/submodule.c +5 -6
- data/vendor/libgit2/src/tag.c +7 -5
- data/vendor/libgit2/src/transaction.c +1 -1
- data/vendor/libgit2/src/transports/cred.c +5 -2
- data/vendor/libgit2/src/transports/git.c +2 -3
- data/vendor/libgit2/src/transports/local.c +15 -34
- data/vendor/libgit2/src/transports/smart.c +1 -1
- data/vendor/libgit2/src/transports/smart_pkt.c +58 -18
- data/vendor/libgit2/src/transports/smart_protocol.c +2 -2
- data/vendor/libgit2/src/transports/winhttp.c +2 -2
- data/vendor/libgit2/src/tree.c +7 -5
- data/vendor/libgit2/src/tsort.c +3 -1
- data/vendor/libgit2/src/util.c +25 -0
- data/vendor/libgit2/src/util.h +31 -27
- data/vendor/libgit2/src/vector.c +2 -7
- data/vendor/libgit2/src/win32/dir.c +5 -3
- data/vendor/libgit2/src/win32/git2.rc +8 -4
- data/vendor/libgit2/src/win32/mingw-compat.h +7 -0
- data/vendor/libgit2/src/win32/msvc-compat.h +3 -0
- data/vendor/libgit2/src/win32/posix.h +1 -3
- data/vendor/libgit2/src/win32/posix_w32.c +31 -7
- data/vendor/libgit2/src/win32/utf-conv.c +1 -3
- data/vendor/libgit2/src/zstream.c +1 -1
- metadata +5 -5
- data/vendor/libgit2/src/bswap.h +0 -97
@@ -302,7 +302,7 @@ static int diff_file_content_load_workdir_file(
|
|
302
302
|
|
303
303
|
if ((error = git_filter_list_load(
|
304
304
|
&fl, fc->repo, NULL, fc->file->path,
|
305
|
-
GIT_FILTER_TO_ODB,
|
305
|
+
GIT_FILTER_TO_ODB, GIT_FILTER_ALLOW_UNSAFE)) < 0)
|
306
306
|
goto cleanup;
|
307
307
|
|
308
308
|
/* if there are no filters, try to mmap the file */
|
@@ -284,11 +284,12 @@ int git_diff_foreach(
|
|
284
284
|
if (git_diff_delta__should_skip(&diff->opts, patch.delta))
|
285
285
|
continue;
|
286
286
|
|
287
|
-
if ((error =
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
287
|
+
if ((error = diff_patch_invoke_file_callback(&patch, &xo.output)) == 0) {
|
288
|
+
if (hunk_cb || data_cb) {
|
289
|
+
if ((error = diff_patch_init_from_diff(&patch, diff, idx)) == 0)
|
290
|
+
error = diff_patch_generate(&patch, &xo.output);
|
291
|
+
}
|
292
|
+
}
|
292
293
|
|
293
294
|
git_patch_free(&patch);
|
294
295
|
|
@@ -387,8 +388,13 @@ static int diff_patch_with_delta_alloc(
|
|
387
388
|
diff_patch_with_delta *pd;
|
388
389
|
size_t old_len = *old_path ? strlen(*old_path) : 0;
|
389
390
|
size_t new_len = *new_path ? strlen(*new_path) : 0;
|
391
|
+
size_t alloc_len;
|
392
|
+
|
393
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*pd), old_len);
|
394
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, new_len);
|
395
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
|
390
396
|
|
391
|
-
*out = pd = git__calloc(1,
|
397
|
+
*out = pd = git__calloc(1, alloc_len);
|
392
398
|
GITERR_CHECK_ALLOC(pd);
|
393
399
|
|
394
400
|
pd->patch.flags = GIT_DIFF_PATCH_ALLOCATED;
|
@@ -219,34 +219,18 @@ int git_diff_find_similar__hashsig_for_file(
|
|
219
219
|
void **out, const git_diff_file *f, const char *path, void *p)
|
220
220
|
{
|
221
221
|
git_hashsig_option_t opt = (git_hashsig_option_t)(intptr_t)p;
|
222
|
-
int error = 0;
|
223
222
|
|
224
223
|
GIT_UNUSED(f);
|
225
|
-
|
226
|
-
|
227
|
-
if (error == GIT_EBUFS) {
|
228
|
-
error = 0;
|
229
|
-
giterr_clear();
|
230
|
-
}
|
231
|
-
|
232
|
-
return error;
|
224
|
+
return git_hashsig_create_fromfile((git_hashsig **)out, path, opt);
|
233
225
|
}
|
234
226
|
|
235
227
|
int git_diff_find_similar__hashsig_for_buf(
|
236
228
|
void **out, const git_diff_file *f, const char *buf, size_t len, void *p)
|
237
229
|
{
|
238
230
|
git_hashsig_option_t opt = (git_hashsig_option_t)(intptr_t)p;
|
239
|
-
int error = 0;
|
240
231
|
|
241
232
|
GIT_UNUSED(f);
|
242
|
-
|
243
|
-
|
244
|
-
if (error == GIT_EBUFS) {
|
245
|
-
error = 0;
|
246
|
-
giterr_clear();
|
247
|
-
}
|
248
|
-
|
249
|
-
return error;
|
233
|
+
return git_hashsig_create((git_hashsig **)out, buf, len, opt);
|
250
234
|
}
|
251
235
|
|
252
236
|
void git_diff_find_similar__hashsig_free(void *sig, void *payload)
|
@@ -258,8 +242,14 @@ void git_diff_find_similar__hashsig_free(void *sig, void *payload)
|
|
258
242
|
int git_diff_find_similar__calc_similarity(
|
259
243
|
int *score, void *siga, void *sigb, void *payload)
|
260
244
|
{
|
245
|
+
int error;
|
246
|
+
|
261
247
|
GIT_UNUSED(payload);
|
262
|
-
|
248
|
+
error = git_hashsig_compare(siga, sigb);
|
249
|
+
if (error < 0)
|
250
|
+
return error;
|
251
|
+
|
252
|
+
*score = error;
|
263
253
|
return 0;
|
264
254
|
}
|
265
255
|
|
@@ -273,6 +263,7 @@ static int normalize_find_opts(
|
|
273
263
|
const git_diff_find_options *given)
|
274
264
|
{
|
275
265
|
git_config *cfg = NULL;
|
266
|
+
git_hashsig_option_t hashsig_opts;
|
276
267
|
|
277
268
|
GITERR_CHECK_VERSION(given, GIT_DIFF_FIND_OPTIONS_VERSION, "git_diff_find_options");
|
278
269
|
|
@@ -286,7 +277,7 @@ static int normalize_find_opts(
|
|
286
277
|
if (!given ||
|
287
278
|
(given->flags & GIT_DIFF_FIND_ALL) == GIT_DIFF_FIND_BY_CONFIG)
|
288
279
|
{
|
289
|
-
|
280
|
+
char *rule =
|
290
281
|
git_config__get_string_force(cfg, "diff.renames", "true");
|
291
282
|
int boolval;
|
292
283
|
|
@@ -296,6 +287,8 @@ static int normalize_find_opts(
|
|
296
287
|
opts->flags |= GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES;
|
297
288
|
else
|
298
289
|
opts->flags |= GIT_DIFF_FIND_RENAMES;
|
290
|
+
|
291
|
+
git__free(rule);
|
299
292
|
}
|
300
293
|
|
301
294
|
/* some flags imply others */
|
@@ -354,11 +347,13 @@ static int normalize_find_opts(
|
|
354
347
|
opts->metric->similarity = git_diff_find_similar__calc_similarity;
|
355
348
|
|
356
349
|
if (opts->flags & GIT_DIFF_FIND_IGNORE_WHITESPACE)
|
357
|
-
|
350
|
+
hashsig_opts = GIT_HASHSIG_IGNORE_WHITESPACE;
|
358
351
|
else if (opts->flags & GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE)
|
359
|
-
|
352
|
+
hashsig_opts = GIT_HASHSIG_NORMAL;
|
360
353
|
else
|
361
|
-
|
354
|
+
hashsig_opts = GIT_HASHSIG_SMART_WHITESPACE;
|
355
|
+
hashsig_opts |= GIT_HASHSIG_ALLOW_SMALL_FILES;
|
356
|
+
opts->metric->payload = (void *)hashsig_opts;
|
362
357
|
}
|
363
358
|
|
364
359
|
return 0;
|
@@ -818,6 +813,7 @@ int git_diff_find_similar(
|
|
818
813
|
size_t num_deltas, num_srcs = 0, num_tgts = 0;
|
819
814
|
size_t tried_srcs = 0, tried_tgts = 0;
|
820
815
|
size_t num_rewrites = 0, num_updates = 0, num_bumped = 0;
|
816
|
+
size_t sigcache_size;
|
821
817
|
void **sigcache = NULL; /* cache of similarity metric file signatures */
|
822
818
|
diff_find_match *tgt2src = NULL;
|
823
819
|
diff_find_match *src2tgt = NULL;
|
@@ -838,7 +834,8 @@ int git_diff_find_similar(
|
|
838
834
|
if ((opts.flags & GIT_DIFF_FIND_ALL) == 0)
|
839
835
|
goto cleanup;
|
840
836
|
|
841
|
-
|
837
|
+
GITERR_CHECK_ALLOC_MULTIPLY(&sigcache_size, num_deltas, 2);
|
838
|
+
sigcache = git__calloc(sigcache_size, sizeof(void *));
|
842
839
|
GITERR_CHECK_ALLOC(sigcache);
|
843
840
|
|
844
841
|
/* Label rename sources and targets
|
@@ -194,7 +194,7 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)
|
|
194
194
|
int git_filebuf_open(git_filebuf *file, const char *path, int flags, mode_t mode)
|
195
195
|
{
|
196
196
|
int compression, error = -1;
|
197
|
-
size_t path_len;
|
197
|
+
size_t path_len, alloc_len;
|
198
198
|
|
199
199
|
/* opening an already open buffer is a programming error;
|
200
200
|
* assert that this never happens instead of returning
|
@@ -271,7 +271,8 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags, mode_t mode
|
|
271
271
|
GITERR_CHECK_ALLOC(file->path_original);
|
272
272
|
|
273
273
|
/* create the locking path by appending ".lock" to the original */
|
274
|
-
|
274
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_len, path_len, GIT_FILELOCK_EXTLENGTH);
|
275
|
+
file->path_lock = git__malloc(alloc_len);
|
275
276
|
GITERR_CHECK_ALLOC(file->path_lock);
|
276
277
|
|
277
278
|
memcpy(file->path_lock, file->path_original, path_len);
|
@@ -407,8 +408,8 @@ int git_filebuf_reserve(git_filebuf *file, void **buffer, size_t len)
|
|
407
408
|
int git_filebuf_printf(git_filebuf *file, const char *format, ...)
|
408
409
|
{
|
409
410
|
va_list arglist;
|
410
|
-
size_t space_left;
|
411
|
-
int
|
411
|
+
size_t space_left, len, alloclen;
|
412
|
+
int written, res;
|
412
413
|
char *tmp_buffer;
|
413
414
|
|
414
415
|
ENSURE_BUF_OK(file);
|
@@ -417,15 +418,16 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
|
|
417
418
|
|
418
419
|
do {
|
419
420
|
va_start(arglist, format);
|
420
|
-
|
421
|
+
written = p_vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
|
421
422
|
va_end(arglist);
|
422
423
|
|
423
|
-
if (
|
424
|
+
if (written < 0) {
|
424
425
|
file->last_error = BUFERR_MEM;
|
425
426
|
return -1;
|
426
427
|
}
|
427
428
|
|
428
|
-
|
429
|
+
len = written;
|
430
|
+
if (len + 1 <= space_left) {
|
429
431
|
file->buf_pos += len;
|
430
432
|
return 0;
|
431
433
|
}
|
@@ -435,19 +437,19 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
|
|
435
437
|
|
436
438
|
space_left = file->buf_size - file->buf_pos;
|
437
439
|
|
438
|
-
} while (
|
440
|
+
} while (len + 1 <= space_left);
|
439
441
|
|
440
|
-
|
441
|
-
|
442
|
+
if (GIT_ADD_SIZET_OVERFLOW(&alloclen, len, 1) ||
|
443
|
+
!(tmp_buffer = git__malloc(alloclen))) {
|
442
444
|
file->last_error = BUFERR_MEM;
|
443
445
|
return -1;
|
444
446
|
}
|
445
447
|
|
446
448
|
va_start(arglist, format);
|
447
|
-
|
449
|
+
written = p_vsnprintf(tmp_buffer, len + 1, format, arglist);
|
448
450
|
va_end(arglist);
|
449
451
|
|
450
|
-
if (
|
452
|
+
if (written < 0) {
|
451
453
|
git__free(tmp_buffer);
|
452
454
|
file->last_error = BUFERR_MEM;
|
453
455
|
return -1;
|
@@ -7,11 +7,14 @@
|
|
7
7
|
#include "common.h"
|
8
8
|
#include "fileops.h"
|
9
9
|
#include "global.h"
|
10
|
+
#include "strmap.h"
|
10
11
|
#include <ctype.h>
|
11
12
|
#if GIT_WIN32
|
12
13
|
#include "win32/findfile.h"
|
13
14
|
#endif
|
14
15
|
|
16
|
+
GIT__USE_STRMAP
|
17
|
+
|
15
18
|
int git_futils_mkpath2file(const char *file_path, const mode_t mode)
|
16
19
|
{
|
17
20
|
return git_futils_mkdir(
|
@@ -121,10 +124,17 @@ mode_t git_futils_canonical_mode(mode_t raw_mode)
|
|
121
124
|
int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
|
122
125
|
{
|
123
126
|
ssize_t read_size = 0;
|
127
|
+
size_t alloc_len;
|
124
128
|
|
125
129
|
git_buf_clear(buf);
|
126
130
|
|
127
|
-
if (
|
131
|
+
if (!git__is_ssizet(len)) {
|
132
|
+
giterr_set(GITERR_INVALID, "Read too large.");
|
133
|
+
return -1;
|
134
|
+
}
|
135
|
+
|
136
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
|
137
|
+
if (git_buf_grow(buf, alloc_len) < 0)
|
128
138
|
return -1;
|
129
139
|
|
130
140
|
/* p_read loops internally to read len bytes */
|
@@ -174,7 +184,7 @@ int git_futils_readbuffer_updated(
|
|
174
184
|
*/
|
175
185
|
if (size && *size != (size_t)st.st_size)
|
176
186
|
changed = true;
|
177
|
-
if (mtime && *mtime != st.st_mtime)
|
187
|
+
if (mtime && *mtime != (time_t)st.st_mtime)
|
178
188
|
changed = true;
|
179
189
|
if (!size && !mtime)
|
180
190
|
changed = true;
|
@@ -313,7 +323,7 @@ GIT_INLINE(int) validate_existing(
|
|
313
323
|
}
|
314
324
|
|
315
325
|
else if (!S_ISDIR(st->st_mode)) {
|
316
|
-
giterr_set(
|
326
|
+
giterr_set(GITERR_FILESYSTEM,
|
317
327
|
"Failed to make directory '%s': directory exists", make_path);
|
318
328
|
return GIT_EEXISTS;
|
319
329
|
}
|
@@ -321,12 +331,12 @@ GIT_INLINE(int) validate_existing(
|
|
321
331
|
return 0;
|
322
332
|
}
|
323
333
|
|
324
|
-
int
|
334
|
+
int git_futils_mkdir_ext(
|
325
335
|
const char *path,
|
326
336
|
const char *base,
|
327
337
|
mode_t mode,
|
328
338
|
uint32_t flags,
|
329
|
-
struct
|
339
|
+
struct git_futils_mkdir_options *opts)
|
330
340
|
{
|
331
341
|
int error = -1;
|
332
342
|
git_buf make_path = GIT_BUF_INIT;
|
@@ -389,6 +399,7 @@ int git_futils_mkdir_withperf(
|
|
389
399
|
|
390
400
|
/* walk down tail of path making each directory */
|
391
401
|
for (tail = &make_path.ptr[root]; *tail; *tail = lastch) {
|
402
|
+
bool mkdir_attempted = false;
|
392
403
|
|
393
404
|
/* advance tail to include next path component */
|
394
405
|
while (*tail == '/')
|
@@ -401,29 +412,40 @@ int git_futils_mkdir_withperf(
|
|
401
412
|
*tail = '\0';
|
402
413
|
st.st_mode = 0;
|
403
414
|
|
415
|
+
if (opts->dir_map && git_strmap_exists(opts->dir_map, make_path.ptr))
|
416
|
+
continue;
|
417
|
+
|
404
418
|
/* See what's going on with this path component */
|
405
|
-
perfdata
|
419
|
+
opts->perfdata.stat_calls++;
|
406
420
|
|
421
|
+
retry_lstat:
|
407
422
|
if (p_lstat(make_path.ptr, &st) < 0) {
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
|
412
|
-
error = GIT_EEXISTS;
|
423
|
+
if (mkdir_attempted || errno != ENOENT) {
|
424
|
+
giterr_set(GITERR_OS, "Cannot access component in path '%s'", make_path.ptr);
|
425
|
+
error = -1;
|
413
426
|
goto done;
|
414
427
|
}
|
415
428
|
|
416
429
|
giterr_clear();
|
430
|
+
opts->perfdata.mkdir_calls++;
|
431
|
+
mkdir_attempted = true;
|
432
|
+
if (p_mkdir(make_path.ptr, mode) < 0) {
|
433
|
+
if (errno == EEXIST)
|
434
|
+
goto retry_lstat;
|
435
|
+
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
|
436
|
+
error = -1;
|
437
|
+
goto done;
|
438
|
+
}
|
417
439
|
} else {
|
418
440
|
/* with exclusive create, existing dir is an error */
|
419
441
|
if ((flags & GIT_MKDIR_EXCL) != 0) {
|
420
|
-
giterr_set(
|
442
|
+
giterr_set(GITERR_FILESYSTEM, "Failed to make directory '%s': directory exists", make_path.ptr);
|
421
443
|
error = GIT_EEXISTS;
|
422
444
|
goto done;
|
423
445
|
}
|
424
446
|
|
425
447
|
if ((error = validate_existing(
|
426
|
-
make_path.ptr, &st, mode, flags, perfdata)) < 0)
|
448
|
+
make_path.ptr, &st, mode, flags, &opts->perfdata)) < 0)
|
427
449
|
goto done;
|
428
450
|
}
|
429
451
|
|
@@ -432,7 +454,7 @@ int git_futils_mkdir_withperf(
|
|
432
454
|
(lastch == '\0' && (flags & GIT_MKDIR_CHMOD) != 0)) &&
|
433
455
|
st.st_mode != mode) {
|
434
456
|
|
435
|
-
perfdata
|
457
|
+
opts->perfdata.chmod_calls++;
|
436
458
|
|
437
459
|
if ((error = p_chmod(make_path.ptr, mode)) < 0 &&
|
438
460
|
lastch == '\0') {
|
@@ -441,6 +463,23 @@ int git_futils_mkdir_withperf(
|
|
441
463
|
goto done;
|
442
464
|
}
|
443
465
|
}
|
466
|
+
|
467
|
+
if (opts->dir_map && opts->pool) {
|
468
|
+
char *cache_path;
|
469
|
+
size_t alloc_size;
|
470
|
+
|
471
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_size, make_path.size, 1);
|
472
|
+
if (!git__is_uint32(alloc_size))
|
473
|
+
return -1;
|
474
|
+
cache_path = git_pool_malloc(opts->pool, (uint32_t)alloc_size);
|
475
|
+
GITERR_CHECK_ALLOC(cache_path);
|
476
|
+
|
477
|
+
memcpy(cache_path, make_path.ptr, make_path.size + 1);
|
478
|
+
|
479
|
+
git_strmap_insert(opts->dir_map, cache_path, cache_path, error);
|
480
|
+
if (error < 0)
|
481
|
+
goto done;
|
482
|
+
}
|
444
483
|
}
|
445
484
|
|
446
485
|
error = 0;
|
@@ -448,7 +487,7 @@ int git_futils_mkdir_withperf(
|
|
448
487
|
/* check that full path really is a directory if requested & needed */
|
449
488
|
if ((flags & GIT_MKDIR_VERIFY_DIR) != 0 &&
|
450
489
|
lastch != '\0') {
|
451
|
-
perfdata
|
490
|
+
opts->perfdata.stat_calls++;
|
452
491
|
|
453
492
|
if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) {
|
454
493
|
giterr_set(GITERR_OS, "Path is not a directory '%s'",
|
@@ -468,8 +507,8 @@ int git_futils_mkdir(
|
|
468
507
|
mode_t mode,
|
469
508
|
uint32_t flags)
|
470
509
|
{
|
471
|
-
struct
|
472
|
-
return
|
510
|
+
struct git_futils_mkdir_options options = {0};
|
511
|
+
return git_futils_mkdir_ext(path, base, mode, flags, &options);
|
473
512
|
}
|
474
513
|
|
475
514
|
int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
|
@@ -691,7 +730,11 @@ static int cp_link(const char *from, const char *to, size_t link_size)
|
|
691
730
|
{
|
692
731
|
int error = 0;
|
693
732
|
ssize_t read_len;
|
694
|
-
char *link_data
|
733
|
+
char *link_data;
|
734
|
+
size_t alloc_size;
|
735
|
+
|
736
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_size, link_size, 1);
|
737
|
+
link_data = git__malloc(alloc_size);
|
695
738
|
GITERR_CHECK_ALLOC(link_data);
|
696
739
|
|
697
740
|
read_len = p_readlink(from, link_data, link_size);
|
@@ -11,6 +11,8 @@
|
|
11
11
|
#include "map.h"
|
12
12
|
#include "posix.h"
|
13
13
|
#include "path.h"
|
14
|
+
#include "pool.h"
|
15
|
+
#include "strmap.h"
|
14
16
|
|
15
17
|
/**
|
16
18
|
* Filebuffer methods
|
@@ -95,6 +97,13 @@ struct git_futils_mkdir_perfdata
|
|
95
97
|
size_t chmod_calls;
|
96
98
|
};
|
97
99
|
|
100
|
+
struct git_futils_mkdir_options
|
101
|
+
{
|
102
|
+
git_strmap *dir_map;
|
103
|
+
git_pool *pool;
|
104
|
+
struct git_futils_mkdir_perfdata perfdata;
|
105
|
+
};
|
106
|
+
|
98
107
|
/**
|
99
108
|
* Create a directory or entire path.
|
100
109
|
*
|
@@ -106,10 +115,10 @@ struct git_futils_mkdir_perfdata
|
|
106
115
|
* @param base Root for relative path. These directories will never be made.
|
107
116
|
* @param mode The mode to use for created directories.
|
108
117
|
* @param flags Combination of the mkdir flags above.
|
109
|
-
* @param
|
118
|
+
* @param opts Extended options, use `git_futils_mkdir` if you are not interested.
|
110
119
|
* @return 0 on success, else error code
|
111
120
|
*/
|
112
|
-
extern int
|
121
|
+
extern int git_futils_mkdir_ext(const char *path, const char *base, mode_t mode, uint32_t flags, struct git_futils_mkdir_options *opts);
|
113
122
|
|
114
123
|
/**
|
115
124
|
* Create a directory or entire path. Similar to `git_futils_mkdir_withperf`
|
data/vendor/libgit2/src/filter.c
CHANGED
@@ -23,7 +23,7 @@ struct git_filter_source {
|
|
23
23
|
git_oid oid; /* zero if unknown (which is likely) */
|
24
24
|
uint16_t filemode; /* zero if unknown */
|
25
25
|
git_filter_mode_t mode;
|
26
|
-
uint32_t
|
26
|
+
uint32_t flags;
|
27
27
|
};
|
28
28
|
|
29
29
|
typedef struct {
|
@@ -34,6 +34,7 @@ typedef struct {
|
|
34
34
|
struct git_filter_list {
|
35
35
|
git_array_t(git_filter_entry) filters;
|
36
36
|
git_filter_source source;
|
37
|
+
git_buf *temp_buf;
|
37
38
|
char path[GIT_FLEX_ARRAY];
|
38
39
|
};
|
39
40
|
|
@@ -228,7 +229,7 @@ int git_filter_register(
|
|
228
229
|
const char *name, git_filter *filter, int priority)
|
229
230
|
{
|
230
231
|
git_filter_def *fdef;
|
231
|
-
size_t nattr = 0, nmatch = 0;
|
232
|
+
size_t nattr = 0, nmatch = 0, alloc_len;
|
232
233
|
git_buf attrs = GIT_BUF_INIT;
|
233
234
|
|
234
235
|
assert(name && filter);
|
@@ -245,8 +246,11 @@ int git_filter_register(
|
|
245
246
|
if (filter_def_scan_attrs(&attrs, &nattr, &nmatch, filter->attributes) < 0)
|
246
247
|
return -1;
|
247
248
|
|
248
|
-
|
249
|
-
|
249
|
+
GITERR_CHECK_ALLOC_MULTIPLY(&alloc_len, nattr, 2);
|
250
|
+
GITERR_CHECK_ALLOC_MULTIPLY(&alloc_len, alloc_len, sizeof(char *));
|
251
|
+
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, sizeof(git_filter_def));
|
252
|
+
|
253
|
+
fdef = git__calloc(1, alloc_len);
|
250
254
|
GITERR_CHECK_ALLOC(fdef);
|
251
255
|
|
252
256
|
fdef->filter_name = git__strdup(name);
|
@@ -368,18 +372,21 @@ git_filter_mode_t git_filter_source_mode(const git_filter_source *src)
|
|
368
372
|
return src->mode;
|
369
373
|
}
|
370
374
|
|
371
|
-
uint32_t
|
375
|
+
uint32_t git_filter_source_flags(const git_filter_source *src)
|
372
376
|
{
|
373
|
-
return src->
|
377
|
+
return src->flags;
|
374
378
|
}
|
375
379
|
|
376
380
|
static int filter_list_new(
|
377
381
|
git_filter_list **out, const git_filter_source *src)
|
378
382
|
{
|
379
383
|
git_filter_list *fl = NULL;
|
380
|
-
size_t pathlen = src->path ? strlen(src->path) : 0;
|
384
|
+
size_t pathlen = src->path ? strlen(src->path) : 0, alloclen;
|
385
|
+
|
386
|
+
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_filter_list), pathlen);
|
387
|
+
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
|
381
388
|
|
382
|
-
fl = git__calloc(1,
|
389
|
+
fl = git__calloc(1, alloclen);
|
383
390
|
GITERR_CHECK_ALLOC(fl);
|
384
391
|
|
385
392
|
if (src->path)
|
@@ -387,22 +394,26 @@ static int filter_list_new(
|
|
387
394
|
fl->source.repo = src->repo;
|
388
395
|
fl->source.path = fl->path;
|
389
396
|
fl->source.mode = src->mode;
|
390
|
-
fl->source.
|
397
|
+
fl->source.flags = src->flags;
|
391
398
|
|
392
399
|
*out = fl;
|
393
400
|
return 0;
|
394
401
|
}
|
395
402
|
|
396
403
|
static int filter_list_check_attributes(
|
397
|
-
const char ***out,
|
404
|
+
const char ***out,
|
405
|
+
git_repository *repo,
|
406
|
+
git_attr_session *attr_session,
|
407
|
+
git_filter_def *fdef,
|
408
|
+
const git_filter_source *src)
|
398
409
|
{
|
399
410
|
int error;
|
400
411
|
size_t i;
|
401
412
|
const char **strs = git__calloc(fdef->nattrs, sizeof(const char *));
|
402
413
|
GITERR_CHECK_ALLOC(strs);
|
403
414
|
|
404
|
-
error =
|
405
|
-
strs,
|
415
|
+
error = git_attr_get_many_with_session(
|
416
|
+
strs, repo, attr_session, 0, src->path, fdef->nattrs, fdef->attrs);
|
406
417
|
|
407
418
|
/* if no values were found but no matches are needed, it's okay! */
|
408
419
|
if (error == GIT_ENOTFOUND && !fdef->nmatches) {
|
@@ -438,23 +449,23 @@ int git_filter_list_new(
|
|
438
449
|
git_filter_list **out,
|
439
450
|
git_repository *repo,
|
440
451
|
git_filter_mode_t mode,
|
441
|
-
uint32_t
|
452
|
+
uint32_t flags)
|
442
453
|
{
|
443
454
|
git_filter_source src = { 0 };
|
444
455
|
src.repo = repo;
|
445
456
|
src.path = NULL;
|
446
457
|
src.mode = mode;
|
447
|
-
src.
|
458
|
+
src.flags = flags;
|
448
459
|
return filter_list_new(out, &src);
|
449
460
|
}
|
450
461
|
|
451
|
-
int
|
462
|
+
int git_filter_list__load_ext(
|
452
463
|
git_filter_list **filters,
|
453
464
|
git_repository *repo,
|
454
465
|
git_blob *blob, /* can be NULL */
|
455
466
|
const char *path,
|
456
467
|
git_filter_mode_t mode,
|
457
|
-
|
468
|
+
git_filter_options *filter_opts)
|
458
469
|
{
|
459
470
|
int error = 0;
|
460
471
|
git_filter_list *fl = NULL;
|
@@ -469,7 +480,8 @@ int git_filter_list_load(
|
|
469
480
|
src.repo = repo;
|
470
481
|
src.path = path;
|
471
482
|
src.mode = mode;
|
472
|
-
src.
|
483
|
+
src.flags = filter_opts->flags;
|
484
|
+
|
473
485
|
if (blob)
|
474
486
|
git_oid_cpy(&src.oid, git_blob_id(blob));
|
475
487
|
|
@@ -481,7 +493,9 @@ int git_filter_list_load(
|
|
481
493
|
continue;
|
482
494
|
|
483
495
|
if (fdef->nattrs > 0) {
|
484
|
-
error = filter_list_check_attributes(
|
496
|
+
error = filter_list_check_attributes(
|
497
|
+
&values, repo, filter_opts->attr_session, fdef, &src);
|
498
|
+
|
485
499
|
if (error == GIT_ENOTFOUND) {
|
486
500
|
error = 0;
|
487
501
|
continue;
|
@@ -503,8 +517,12 @@ int git_filter_list_load(
|
|
503
517
|
else if (error < 0)
|
504
518
|
break;
|
505
519
|
else {
|
506
|
-
if (!fl
|
507
|
-
|
520
|
+
if (!fl) {
|
521
|
+
if ((error = filter_list_new(&fl, &src)) < 0)
|
522
|
+
return error;
|
523
|
+
|
524
|
+
fl->temp_buf = filter_opts->temp_buf;
|
525
|
+
}
|
508
526
|
|
509
527
|
fe = git_array_alloc(fl->filters);
|
510
528
|
GITERR_CHECK_ALLOC(fe);
|
@@ -523,6 +541,22 @@ int git_filter_list_load(
|
|
523
541
|
return error;
|
524
542
|
}
|
525
543
|
|
544
|
+
int git_filter_list_load(
|
545
|
+
git_filter_list **filters,
|
546
|
+
git_repository *repo,
|
547
|
+
git_blob *blob, /* can be NULL */
|
548
|
+
const char *path,
|
549
|
+
git_filter_mode_t mode,
|
550
|
+
uint32_t flags)
|
551
|
+
{
|
552
|
+
git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
|
553
|
+
|
554
|
+
filter_opts.flags = flags;
|
555
|
+
|
556
|
+
return git_filter_list__load_ext(
|
557
|
+
filters, repo, blob, path, mode, &filter_opts);
|
558
|
+
}
|
559
|
+
|
526
560
|
void git_filter_list_free(git_filter_list *fl)
|
527
561
|
{
|
528
562
|
uint32_t i;
|
@@ -575,84 +609,72 @@ size_t git_filter_list_length(const git_filter_list *fl)
|
|
575
609
|
return fl ? git_array_size(fl->filters) : 0;
|
576
610
|
}
|
577
611
|
|
578
|
-
|
579
|
-
|
612
|
+
struct buf_stream {
|
613
|
+
git_writestream parent;
|
614
|
+
git_buf *target;
|
615
|
+
bool complete;
|
616
|
+
};
|
617
|
+
|
618
|
+
static int buf_stream_write(
|
619
|
+
git_writestream *s, const char *buffer, size_t len)
|
580
620
|
{
|
581
|
-
|
582
|
-
|
621
|
+
struct buf_stream *buf_stream = (struct buf_stream *)s;
|
622
|
+
assert(buf_stream);
|
583
623
|
|
584
|
-
|
585
|
-
git_buf_init(out, 0);
|
586
|
-
} else {
|
587
|
-
out->ptr = (char *)ptr;
|
588
|
-
out->asize = 0;
|
589
|
-
out->size = size;
|
590
|
-
}
|
624
|
+
assert(buf_stream->complete == 0);
|
591
625
|
|
592
|
-
return
|
626
|
+
return git_buf_put(buf_stream->target, buffer, len);
|
593
627
|
}
|
594
628
|
|
595
|
-
int
|
596
|
-
git_buf *tgt, git_filter_list *fl, git_buf *src)
|
629
|
+
static int buf_stream_close(git_writestream *s)
|
597
630
|
{
|
598
|
-
|
599
|
-
|
600
|
-
git_buf *dbuffer[2], local = GIT_BUF_INIT;
|
601
|
-
unsigned int si = 0;
|
631
|
+
struct buf_stream *buf_stream = (struct buf_stream *)s;
|
632
|
+
assert(buf_stream);
|
602
633
|
|
603
|
-
|
604
|
-
|
634
|
+
assert(buf_stream->complete == 0);
|
635
|
+
buf_stream->complete = 1;
|
605
636
|
|
606
|
-
|
607
|
-
|
637
|
+
return 0;
|
638
|
+
}
|
608
639
|
|
609
|
-
|
610
|
-
|
640
|
+
static void buf_stream_free(git_writestream *s)
|
641
|
+
{
|
642
|
+
GIT_UNUSED(s);
|
643
|
+
}
|
611
644
|
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
return -1;
|
616
|
-
dbuffer[0] = &local;
|
617
|
-
}
|
645
|
+
static void buf_stream_init(struct buf_stream *writer, git_buf *target)
|
646
|
+
{
|
647
|
+
memset(writer, 0, sizeof(struct buf_stream));
|
618
648
|
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
git_filter_entry *fe = git_array_get(fl->filters, fidx);
|
624
|
-
|
625
|
-
dbuffer[di]->size = 0;
|
626
|
-
|
627
|
-
/* Apply the filter from dbuffer[src] to the other buffer;
|
628
|
-
* if the filtering is canceled by the user mid-filter,
|
629
|
-
* we skip to the next filter without changing the source
|
630
|
-
* of the double buffering (so that the text goes through
|
631
|
-
* cleanly).
|
632
|
-
*/
|
649
|
+
writer->parent.write = buf_stream_write;
|
650
|
+
writer->parent.close = buf_stream_close;
|
651
|
+
writer->parent.free = buf_stream_free;
|
652
|
+
writer->target = target;
|
633
653
|
|
634
|
-
|
635
|
-
|
654
|
+
git_buf_clear(target);
|
655
|
+
}
|
636
656
|
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
657
|
+
int git_filter_list_apply_to_data(
|
658
|
+
git_buf *tgt, git_filter_list *filters, git_buf *src)
|
659
|
+
{
|
660
|
+
struct buf_stream writer;
|
661
|
+
int error;
|
662
|
+
|
663
|
+
git_buf_sanitize(tgt);
|
664
|
+
git_buf_sanitize(src);
|
665
|
+
|
666
|
+
if (!filters) {
|
667
|
+
git_buf_attach_notowned(tgt, src->ptr, src->size);
|
668
|
+
return 0;
|
647
669
|
}
|
648
670
|
|
649
|
-
|
650
|
-
if (si != 1)
|
651
|
-
git_buf_swap(dbuffer[0], dbuffer[1]);
|
671
|
+
buf_stream_init(&writer, tgt);
|
652
672
|
|
653
|
-
|
654
|
-
|
673
|
+
if ((error = git_filter_list_stream_data(filters, src,
|
674
|
+
(git_writestream *)&writer)) < 0)
|
675
|
+
return error;
|
655
676
|
|
677
|
+
assert(writer.complete);
|
656
678
|
return error;
|
657
679
|
}
|
658
680
|
|
@@ -662,28 +684,21 @@ int git_filter_list_apply_to_file(
|
|
662
684
|
git_repository *repo,
|
663
685
|
const char *path)
|
664
686
|
{
|
687
|
+
struct buf_stream writer;
|
665
688
|
int error;
|
666
|
-
const char *base = repo ? git_repository_workdir(repo) : NULL;
|
667
|
-
git_buf abspath = GIT_BUF_INIT, raw = GIT_BUF_INIT;
|
668
689
|
|
669
|
-
|
670
|
-
!(error = git_futils_readbuffer(&raw, abspath.ptr)))
|
671
|
-
{
|
672
|
-
error = git_filter_list_apply_to_data(out, filters, &raw);
|
690
|
+
buf_stream_init(&writer, out);
|
673
691
|
|
674
|
-
|
675
|
-
|
692
|
+
if ((error = git_filter_list_stream_file(
|
693
|
+
filters, repo, path, (git_writestream *)&writer)) < 0)
|
694
|
+
return error;
|
676
695
|
|
677
|
-
|
696
|
+
assert(writer.complete);
|
678
697
|
return error;
|
679
698
|
}
|
680
699
|
|
681
|
-
int
|
682
|
-
git_buf *out,
|
683
|
-
git_filter_list *filters,
|
684
|
-
git_blob *blob)
|
700
|
+
static int buf_from_blob(git_buf *out, git_blob *blob)
|
685
701
|
{
|
686
|
-
git_buf in = GIT_BUF_INIT;
|
687
702
|
git_off_t rawsize = git_blob_rawsize(blob);
|
688
703
|
|
689
704
|
if (!git__is_sizet(rawsize)) {
|
@@ -691,12 +706,249 @@ int git_filter_list_apply_to_blob(
|
|
691
706
|
return -1;
|
692
707
|
}
|
693
708
|
|
694
|
-
|
695
|
-
|
696
|
-
|
709
|
+
git_buf_attach_notowned(out, git_blob_rawcontent(blob), (size_t)rawsize);
|
710
|
+
return 0;
|
711
|
+
}
|
712
|
+
|
713
|
+
int git_filter_list_apply_to_blob(
|
714
|
+
git_buf *out,
|
715
|
+
git_filter_list *filters,
|
716
|
+
git_blob *blob)
|
717
|
+
{
|
718
|
+
struct buf_stream writer;
|
719
|
+
int error;
|
720
|
+
|
721
|
+
buf_stream_init(&writer, out);
|
722
|
+
|
723
|
+
if ((error = git_filter_list_stream_blob(
|
724
|
+
filters, blob, (git_writestream *)&writer)) < 0)
|
725
|
+
return error;
|
726
|
+
|
727
|
+
assert(writer.complete);
|
728
|
+
return error;
|
729
|
+
}
|
730
|
+
|
731
|
+
struct proxy_stream {
|
732
|
+
git_writestream parent;
|
733
|
+
git_filter *filter;
|
734
|
+
const git_filter_source *source;
|
735
|
+
void **payload;
|
736
|
+
git_buf input;
|
737
|
+
git_buf temp_buf;
|
738
|
+
git_buf *output;
|
739
|
+
git_writestream *target;
|
740
|
+
};
|
741
|
+
|
742
|
+
static int proxy_stream_write(
|
743
|
+
git_writestream *s, const char *buffer, size_t len)
|
744
|
+
{
|
745
|
+
struct proxy_stream *proxy_stream = (struct proxy_stream *)s;
|
746
|
+
assert(proxy_stream);
|
747
|
+
|
748
|
+
return git_buf_put(&proxy_stream->input, buffer, len);
|
749
|
+
}
|
750
|
+
|
751
|
+
static int proxy_stream_close(git_writestream *s)
|
752
|
+
{
|
753
|
+
struct proxy_stream *proxy_stream = (struct proxy_stream *)s;
|
754
|
+
git_buf *writebuf;
|
755
|
+
int error;
|
756
|
+
|
757
|
+
assert(proxy_stream);
|
758
|
+
|
759
|
+
error = proxy_stream->filter->apply(
|
760
|
+
proxy_stream->filter,
|
761
|
+
proxy_stream->payload,
|
762
|
+
proxy_stream->output,
|
763
|
+
&proxy_stream->input,
|
764
|
+
proxy_stream->source);
|
765
|
+
|
766
|
+
if (error == GIT_PASSTHROUGH) {
|
767
|
+
writebuf = &proxy_stream->input;
|
768
|
+
} else if (error == 0) {
|
769
|
+
git_buf_sanitize(proxy_stream->output);
|
770
|
+
writebuf = proxy_stream->output;
|
771
|
+
} else {
|
772
|
+
return error;
|
773
|
+
}
|
774
|
+
|
775
|
+
if ((error = proxy_stream->target->write(
|
776
|
+
proxy_stream->target, writebuf->ptr, writebuf->size)) == 0)
|
777
|
+
error = proxy_stream->target->close(proxy_stream->target);
|
778
|
+
|
779
|
+
return error;
|
780
|
+
}
|
781
|
+
|
782
|
+
static void proxy_stream_free(git_writestream *s)
|
783
|
+
{
|
784
|
+
struct proxy_stream *proxy_stream = (struct proxy_stream *)s;
|
785
|
+
assert(proxy_stream);
|
786
|
+
|
787
|
+
git_buf_free(&proxy_stream->input);
|
788
|
+
git_buf_free(&proxy_stream->temp_buf);
|
789
|
+
git__free(proxy_stream);
|
790
|
+
}
|
791
|
+
|
792
|
+
static int proxy_stream_init(
|
793
|
+
git_writestream **out,
|
794
|
+
git_filter *filter,
|
795
|
+
git_buf *temp_buf,
|
796
|
+
void **payload,
|
797
|
+
const git_filter_source *source,
|
798
|
+
git_writestream *target)
|
799
|
+
{
|
800
|
+
struct proxy_stream *proxy_stream = git__calloc(1, sizeof(struct proxy_stream));
|
801
|
+
GITERR_CHECK_ALLOC(proxy_stream);
|
802
|
+
|
803
|
+
proxy_stream->parent.write = proxy_stream_write;
|
804
|
+
proxy_stream->parent.close = proxy_stream_close;
|
805
|
+
proxy_stream->parent.free = proxy_stream_free;
|
806
|
+
proxy_stream->filter = filter;
|
807
|
+
proxy_stream->payload = payload;
|
808
|
+
proxy_stream->source = source;
|
809
|
+
proxy_stream->target = target;
|
810
|
+
proxy_stream->output = temp_buf ? temp_buf : &proxy_stream->temp_buf;
|
811
|
+
|
812
|
+
*out = (git_writestream *)proxy_stream;
|
813
|
+
return 0;
|
814
|
+
}
|
815
|
+
|
816
|
+
static int stream_list_init(
|
817
|
+
git_writestream **out,
|
818
|
+
git_vector *streams,
|
819
|
+
git_filter_list *filters,
|
820
|
+
git_writestream *target)
|
821
|
+
{
|
822
|
+
git_writestream *last_stream = target;
|
823
|
+
size_t i;
|
824
|
+
int error = 0;
|
825
|
+
|
826
|
+
*out = NULL;
|
827
|
+
|
828
|
+
if (!filters) {
|
829
|
+
*out = target;
|
830
|
+
return 0;
|
831
|
+
}
|
832
|
+
|
833
|
+
/* Create filters last to first to get the chaining direction */
|
834
|
+
for (i = 0; i < git_array_size(filters->filters); ++i) {
|
835
|
+
size_t filter_idx = (filters->source.mode == GIT_FILTER_TO_WORKTREE) ?
|
836
|
+
git_array_size(filters->filters) - 1 - i : i;
|
837
|
+
git_filter_entry *fe = git_array_get(filters->filters, filter_idx);
|
838
|
+
git_writestream *filter_stream;
|
839
|
+
|
840
|
+
assert(fe->filter->stream || fe->filter->apply);
|
841
|
+
|
842
|
+
/* If necessary, create a stream that proxies the traditional
|
843
|
+
* application.
|
844
|
+
*/
|
845
|
+
if (fe->filter->stream)
|
846
|
+
error = fe->filter->stream(&filter_stream, fe->filter,
|
847
|
+
&fe->payload, &filters->source, last_stream);
|
848
|
+
else
|
849
|
+
/* Create a stream that proxies the one-shot apply */
|
850
|
+
error = proxy_stream_init(&filter_stream, fe->filter,
|
851
|
+
filters->temp_buf, &fe->payload, &filters->source,
|
852
|
+
last_stream);
|
853
|
+
|
854
|
+
if (error < 0)
|
855
|
+
return error;
|
856
|
+
|
857
|
+
git_vector_insert(streams, filter_stream);
|
858
|
+
last_stream = filter_stream;
|
859
|
+
}
|
860
|
+
|
861
|
+
*out = last_stream;
|
862
|
+
return 0;
|
863
|
+
}
|
864
|
+
|
865
|
+
void stream_list_free(git_vector *streams)
|
866
|
+
{
|
867
|
+
git_writestream *stream;
|
868
|
+
size_t i;
|
869
|
+
|
870
|
+
git_vector_foreach(streams, i, stream)
|
871
|
+
stream->free(stream);
|
872
|
+
git_vector_free(streams);
|
873
|
+
}
|
874
|
+
|
875
|
+
#define STREAM_BUFSIZE 10240
|
876
|
+
|
877
|
+
int git_filter_list_stream_file(
|
878
|
+
git_filter_list *filters,
|
879
|
+
git_repository *repo,
|
880
|
+
const char *path,
|
881
|
+
git_writestream *target)
|
882
|
+
{
|
883
|
+
char buf[STREAM_BUFSIZE];
|
884
|
+
git_buf abspath = GIT_BUF_INIT;
|
885
|
+
const char *base = repo ? git_repository_workdir(repo) : NULL;
|
886
|
+
git_vector filter_streams = GIT_VECTOR_INIT;
|
887
|
+
git_writestream *stream_start;
|
888
|
+
ssize_t readlen;
|
889
|
+
int fd, error;
|
890
|
+
|
891
|
+
if ((error = stream_list_init(
|
892
|
+
&stream_start, &filter_streams, filters, target)) < 0 ||
|
893
|
+
(error = git_path_join_unrooted(&abspath, path, base, NULL)) < 0)
|
894
|
+
goto done;
|
895
|
+
|
896
|
+
if ((fd = git_futils_open_ro(abspath.ptr)) < 0) {
|
897
|
+
error = fd;
|
898
|
+
goto done;
|
899
|
+
}
|
900
|
+
|
901
|
+
while ((readlen = p_read(fd, buf, STREAM_BUFSIZE)) > 0) {
|
902
|
+
if ((error = stream_start->write(stream_start, buf, readlen)) < 0)
|
903
|
+
goto done;
|
904
|
+
}
|
905
|
+
|
906
|
+
if (!readlen)
|
907
|
+
error = stream_start->close(stream_start);
|
908
|
+
else if (readlen < 0)
|
909
|
+
error = readlen;
|
910
|
+
|
911
|
+
p_close(fd);
|
912
|
+
|
913
|
+
done:
|
914
|
+
stream_list_free(&filter_streams);
|
915
|
+
git_buf_free(&abspath);
|
916
|
+
return error;
|
917
|
+
}
|
918
|
+
|
919
|
+
int git_filter_list_stream_data(
|
920
|
+
git_filter_list *filters,
|
921
|
+
git_buf *data,
|
922
|
+
git_writestream *target)
|
923
|
+
{
|
924
|
+
git_vector filter_streams = GIT_VECTOR_INIT;
|
925
|
+
git_writestream *stream_start;
|
926
|
+
int error = 0;
|
927
|
+
|
928
|
+
git_buf_sanitize(data);
|
929
|
+
|
930
|
+
if ((error = stream_list_init(
|
931
|
+
&stream_start, &filter_streams, filters, target)) == 0 &&
|
932
|
+
(error =
|
933
|
+
stream_start->write(stream_start, data->ptr, data->size)) == 0)
|
934
|
+
error = stream_start->close(stream_start);
|
935
|
+
|
936
|
+
stream_list_free(&filter_streams);
|
937
|
+
return error;
|
938
|
+
}
|
939
|
+
|
940
|
+
int git_filter_list_stream_blob(
|
941
|
+
git_filter_list *filters,
|
942
|
+
git_blob *blob,
|
943
|
+
git_writestream *target)
|
944
|
+
{
|
945
|
+
git_buf in = GIT_BUF_INIT;
|
946
|
+
|
947
|
+
if (buf_from_blob(&in, blob) < 0)
|
948
|
+
return -1;
|
697
949
|
|
698
950
|
if (filters)
|
699
951
|
git_oid_cpy(&filters->source.oid, git_blob_id(blob));
|
700
952
|
|
701
|
-
return
|
953
|
+
return git_filter_list_stream_data(filters, &in, target);
|
702
954
|
}
|