Commit e78f5c9f by Edward Thomson

checkout: stream the blob into the filters

Use the new streaming filter API during checkout.
parent 5555696f
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "git2/diff.h" #include "git2/diff.h"
#include "git2/submodule.h" #include "git2/submodule.h"
#include "git2/sys/index.h" #include "git2/sys/index.h"
#include "git2/sys/filter.h"
#include "refs.h" #include "refs.h"
#include "repository.h" #include "repository.h"
...@@ -1371,39 +1372,37 @@ static int mkpath2file( ...@@ -1371,39 +1372,37 @@ static int mkpath2file(
return error; return error;
} }
static int buffer_to_file( struct checkout_stream {
checkout_data *data, git_filter_stream base;
struct stat *st, const char *path;
git_buf *buf, int fd;
const char *path, int open;
mode_t file_mode) };
{
int error;
if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0)
return error;
if ((error = git_futils_writebuffer( static int checkout_stream_write(
buf, path, data->opts.file_open_flags, file_mode)) < 0) git_filter_stream *s, const char *buffer, size_t len)
return error; {
struct checkout_stream *stream = (struct checkout_stream *)s;
int ret;
if (st) { if ((ret = p_write(stream->fd, buffer, len)) < 0)
data->perfdata.stat_calls++; giterr_set(GITERR_OS, "Could not write to '%s'", stream->path);
if ((error = p_stat(path, st)) < 0) { return ret;
giterr_set(GITERR_OS, "Error statting '%s'", path); }
return error;
}
}
if (GIT_PERMS_IS_EXEC(file_mode)) { static int checkout_stream_close(git_filter_stream *s)
data->perfdata.chmod_calls++; {
struct checkout_stream *stream = (struct checkout_stream *)s;
assert(stream && stream->open);
if ((error = p_chmod(path, file_mode)) < 0) stream->open = 0;
giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path); return 0;
} }
return error; static void checkout_stream_free(git_filter_stream *s)
{
GIT_UNUSED(s);
} }
static int blob_content_to_file( static int blob_content_to_file(
...@@ -1411,36 +1410,80 @@ static int blob_content_to_file( ...@@ -1411,36 +1410,80 @@ static int blob_content_to_file(
struct stat *st, struct stat *st,
git_blob *blob, git_blob *blob,
const char *path, const char *path,
const char * hint_path, const char *hint_path,
mode_t entry_filemode) mode_t entry_filemode)
{ {
int flags = data->opts.file_open_flags;
mode_t file_mode = data->opts.file_mode ? mode_t file_mode = data->opts.file_mode ?
data->opts.file_mode : entry_filemode; data->opts.file_mode : entry_filemode;
git_buf out = GIT_BUF_INIT; struct checkout_stream writer;
mode_t mode;
git_filter_list *fl = NULL; git_filter_list *fl = NULL;
int fd;
int error = 0; int error = 0;
if (hint_path == NULL) if (hint_path == NULL)
hint_path = path; hint_path = path;
if (!data->opts.disable_filters) if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0)
error = git_filter_list__load_with_attr_session( 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, &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;
if (!error) /* setup the writer */
error = git_filter_list_apply_to_blob(&out, fl, blob); 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);
assert(writer.open == 0);
git_filter_list_free(fl); git_filter_list_free(fl);
p_close(fd);
if (!error) { if (error < 0)
error = buffer_to_file(data, st, &out, path, file_mode); return error;
st->st_mode = entry_filemode;
if (GIT_PERMS_IS_EXEC(mode)) {
data->perfdata.chmod_calls++;
git_buf_free(&out); if ((error = p_chmod(path, mode)) < 0) {
giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path);
return error;
}
} }
if (st) {
data->perfdata.stat_calls++;
if ((error = p_stat(path, st)) < 0) {
giterr_set(GITERR_OS, "Error statting '%s'", path);
return error; return error;
}
st->st_mode = entry_filemode;
}
return 0;
} }
static int blob_content_to_link( static int blob_content_to_link(
......
...@@ -522,6 +522,7 @@ int git_filter_list__load_with_attr_session( ...@@ -522,6 +522,7 @@ int git_filter_list__load_with_attr_session(
fe = git_array_alloc(fl->filters); fe = git_array_alloc(fl->filters);
GITERR_CHECK_ALLOC(fe); GITERR_CHECK_ALLOC(fe);
fe->filter = fdef->filter; fe->filter = fdef->filter;
fe->stream = NULL;
fe->payload = payload; fe->payload = payload;
} }
} }
...@@ -590,6 +591,7 @@ int git_filter_list_push( ...@@ -590,6 +591,7 @@ int git_filter_list_push(
fe = git_array_alloc(fl->filters); fe = git_array_alloc(fl->filters);
GITERR_CHECK_ALLOC(fe); GITERR_CHECK_ALLOC(fe);
fe->filter = filter; fe->filter = filter;
fe->stream = NULL;
fe->payload = payload; fe->payload = payload;
return 0; return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment