diff options
author | Edward Thomson <ethomson@microsoft.com> | 2015-01-22 16:11:36 -0600 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2015-02-17 15:57:10 -0500 |
commit | e78f5c9f4282319cf8e1afc8631e6259e91653a6 (patch) | |
tree | cb1dac68dc96eb8554efb67104944c12d1b3eab7 | |
parent | 5555696f8a48d2319a7ca0918726711e6a81a924 (diff) | |
download | libgit2-e78f5c9f4282319cf8e1afc8631e6259e91653a6.tar.gz |
checkout: stream the blob into the filters
Use the new streaming filter API during checkout.
-rw-r--r-- | src/checkout.c | 121 | ||||
-rw-r--r-- | src/filter.c | 2 |
2 files changed, 84 insertions, 39 deletions
diff --git a/src/checkout.c b/src/checkout.c index 880af3dff..623ac92a1 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -17,6 +17,7 @@ #include "git2/diff.h" #include "git2/submodule.h" #include "git2/sys/index.h" +#include "git2/sys/filter.h" #include "refs.h" #include "repository.h" @@ -1371,39 +1372,37 @@ static int mkpath2file( return error; } -static int buffer_to_file( - checkout_data *data, - struct stat *st, - git_buf *buf, - const char *path, - mode_t file_mode) -{ - int error; - - if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0) - return error; +struct checkout_stream { + git_filter_stream base; + const char *path; + int fd; + int open; +}; - if ((error = git_futils_writebuffer( - buf, path, data->opts.file_open_flags, file_mode)) < 0) - return error; +static int checkout_stream_write( + git_filter_stream *s, const char *buffer, size_t len) +{ + struct checkout_stream *stream = (struct checkout_stream *)s; + int ret; - if (st) { - data->perfdata.stat_calls++; + if ((ret = p_write(stream->fd, buffer, len)) < 0) + giterr_set(GITERR_OS, "Could not write to '%s'", stream->path); - if ((error = p_stat(path, st)) < 0) { - giterr_set(GITERR_OS, "Error statting '%s'", path); - return error; - } - } + return ret; +} - if (GIT_PERMS_IS_EXEC(file_mode)) { - data->perfdata.chmod_calls++; +static int checkout_stream_close(git_filter_stream *s) +{ + struct checkout_stream *stream = (struct checkout_stream *)s; + assert(stream && stream->open); - if ((error = p_chmod(path, file_mode)) < 0) - giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path); - } + stream->open = 0; + return 0; +} - return error; +static void checkout_stream_free(git_filter_stream *s) +{ + GIT_UNUSED(s); } static int blob_content_to_file( @@ -1411,36 +1410,80 @@ static int blob_content_to_file( struct stat *st, git_blob *blob, const char *path, - const char * hint_path, + const char *hint_path, mode_t entry_filemode) { + int flags = data->opts.file_open_flags; mode_t file_mode = data->opts.file_mode ? data->opts.file_mode : entry_filemode; - git_buf out = GIT_BUF_INIT; + struct checkout_stream writer; + mode_t mode; git_filter_list *fl = NULL; + int fd; int error = 0; if (hint_path == NULL) hint_path = path; - if (!data->opts.disable_filters) - error = git_filter_list__load_with_attr_session( + if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0) + return error; + + if (flags <= 0) + flags = O_CREAT | O_TRUNC | O_WRONLY; + if (!(mode = file_mode)) + mode = GIT_FILEMODE_BLOB; + + if ((fd = p_open(path, flags, mode)) < 0) { + giterr_set(GITERR_OS, "Could not open '%s' for writing", path); + return fd; + } + + if (!data->opts.disable_filters && + (error = git_filter_list__load_with_attr_session( &fl, data->repo, &data->attr_session, blob, hint_path, - GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT); + GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT))) + return error; + + /* setup the writer */ + memset(&writer, 0, sizeof(struct checkout_stream)); + writer.base.write = checkout_stream_write; + writer.base.close = checkout_stream_close; + writer.base.free = checkout_stream_free; + writer.path = path; + writer.fd = fd; + writer.open = 1; + + error = git_filter_list_stream_blob(fl, blob, (git_filter_stream *)&writer); - if (!error) - error = git_filter_list_apply_to_blob(&out, fl, blob); + assert(writer.open == 0); git_filter_list_free(fl); + p_close(fd); - if (!error) { - error = buffer_to_file(data, st, &out, path, file_mode); - st->st_mode = entry_filemode; + if (error < 0) + return error; + + if (GIT_PERMS_IS_EXEC(mode)) { + data->perfdata.chmod_calls++; + + if ((error = p_chmod(path, mode)) < 0) { + giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path); + return error; + } + } - git_buf_free(&out); + if (st) { + data->perfdata.stat_calls++; + + if ((error = p_stat(path, st)) < 0) { + giterr_set(GITERR_OS, "Error statting '%s'", path); + return error; + } + + st->st_mode = entry_filemode; } - return error; + return 0; } static int blob_content_to_link( diff --git a/src/filter.c b/src/filter.c index 700afbac3..d930b2399 100644 --- a/src/filter.c +++ b/src/filter.c @@ -522,6 +522,7 @@ int git_filter_list__load_with_attr_session( fe = git_array_alloc(fl->filters); GITERR_CHECK_ALLOC(fe); fe->filter = fdef->filter; + fe->stream = NULL; fe->payload = payload; } } @@ -590,6 +591,7 @@ int git_filter_list_push( fe = git_array_alloc(fl->filters); GITERR_CHECK_ALLOC(fe); fe->filter = filter; + fe->stream = NULL; fe->payload = payload; return 0; |