Commit dc1b0909 by Ben Straub

Create filtered_blob_contents out of parts on hand.

parent 280c7bbf
...@@ -27,63 +27,70 @@ typedef struct tree_walk_data ...@@ -27,63 +27,70 @@ typedef struct tree_walk_data
{ {
git_indexer_stats *stats; git_indexer_stats *stats;
git_repository *repo; git_repository *repo;
git_odb *odb;
} tree_walk_data; } tree_walk_data;
static int apply_filters(git_buf *out, static int unfiltered_blob_contents(git_buf *out, git_repository *repo, const git_oid *blob_id)
git_vector *filters,
const void *data,
size_t len)
{ {
int retcode = GIT_ERROR; int retcode = GIT_ERROR;
git_buf origblob = GIT_BUF_INIT;
git_buf_clear(out); git_blob *blob;
if (!git_blob_lookup(&blob, repo, blob_id)) {
if (!filters->length) { const void *contents = git_blob_rawcontent(blob);
/* No filters to apply; just copy the result */ size_t len = git_blob_rawsize(blob);
git_buf_put(out, (const char *)data, len); git_buf_clear(out);
return 0; git_buf_set(out, (const char*)contents, len);
git_blob_free(blob);
retcode = 0;
} }
git_buf_attach(&origblob, (char*)data, len);
retcode = git_filters_apply(out, &origblob, filters);
git_buf_detach(&origblob);
return retcode; return retcode;
} }
static int blob_contents_to_file(git_repository *repo, git_buf *fnbuf, const git_oid *id, int mode) static int filtered_blob_contents(git_buf *out, git_repository *repo, const git_oid *oid, const char *path)
{ {
int retcode = GIT_ERROR; int retcode = GIT_ERROR;
git_blob *blob; git_buf unfiltered = GIT_BUF_INIT;
if (!git_blob_lookup(&blob, repo, id)) { if (!unfiltered_blob_contents(&unfiltered, repo, oid)) {
const void *contents = git_blob_rawcontent(blob);
size_t len = git_blob_rawsize(blob);
git_vector filters = GIT_VECTOR_INIT; git_vector filters = GIT_VECTOR_INIT;
int filter_count; int filter_count = git_filters_load(&filters, repo,
path, GIT_FILTER_TO_WORKTREE);
/* TODO: line-ending smudging */
filter_count = git_filters_load(&filters, repo,
git_buf_cstr(fnbuf),
GIT_FILTER_TO_WORKTREE);
if (filter_count >= 0) { if (filter_count >= 0) {
git_buf filteredblob = GIT_BUF_INIT; git_buf_clear(out);
if (!apply_filters(&filteredblob, &filters, contents, len)) { if (!filter_count) {
int fd = git_futils_creat_withpath(git_buf_cstr(fnbuf), git_buf_put(out, git_buf_cstr(&unfiltered), git_buf_len(&unfiltered));
GIT_DIR_MODE, mode); retcode = 0;
if (fd >= 0) { } else {
retcode = (!p_write(fd, contents, len)) ? 0 : GIT_ERROR; retcode = git_filters_apply(out, &unfiltered, &filters);
p_close(fd);
}
} }
git_buf_free(&filteredblob);
git_filters_free(&filters);
} }
git_blob_free(blob); git_filters_free(&filters);
}
git_buf_free(&unfiltered);
return retcode;
}
static int blob_contents_to_file(git_repository *repo, git_buf *fnbuf, const git_oid *id, int mode)
{
int retcode = GIT_ERROR;
git_buf filteredcontents = GIT_BUF_INIT;
if (!filtered_blob_contents(&filteredcontents, repo, id, git_buf_cstr(fnbuf))) {
int fd = git_futils_creat_withpath(git_buf_cstr(fnbuf),
GIT_DIR_MODE, mode);
if (fd >= 0) {
if (!p_write(fd, git_buf_cstr(&filteredcontents),
git_buf_len(&filteredcontents)))
retcode = 0;
else
retcode = GIT_ERROR;
p_close(fd);
}
} }
git_buf_free(&filteredcontents);
return retcode; return retcode;
} }
...@@ -94,26 +101,32 @@ static int checkout_walker(const char *path, git_tree_entry *entry, void *payloa ...@@ -94,26 +101,32 @@ static int checkout_walker(const char *path, git_tree_entry *entry, void *payloa
tree_walk_data *data = (tree_walk_data*)payload; tree_walk_data *data = (tree_walk_data*)payload;
int attr = git_tree_entry_attributes(entry); int attr = git_tree_entry_attributes(entry);
switch(git_tree_entry_type(entry)) { /* TODO: handle submodules */
case GIT_OBJ_TREE:
/* TODO: mkdir? */ if (S_ISLNK(attr)) {
break; printf("It's a link!\n'");
} else {
case GIT_OBJ_BLOB: switch(git_tree_entry_type(entry)) {
{ case GIT_OBJ_TREE:
git_buf fnbuf = GIT_BUF_INIT; /* Nothing to do; the blob handling creates necessary directories. */
git_buf_join_n(&fnbuf, '/', 3, break;
git_repository_workdir(data->repo),
path, case GIT_OBJ_BLOB:
git_tree_entry_name(entry)); {
retcode = blob_contents_to_file(data->repo, &fnbuf, git_tree_entry_id(entry), attr); git_buf fnbuf = GIT_BUF_INIT;
git_buf_free(&fnbuf); git_buf_join_n(&fnbuf, '/', 3,
} git_repository_workdir(data->repo),
break; path,
git_tree_entry_name(entry));
retcode = blob_contents_to_file(data->repo, &fnbuf, git_tree_entry_id(entry), attr);
git_buf_free(&fnbuf);
}
break;
default: default:
retcode = -1; retcode = -1;
break; break;
}
} }
data->stats->processed++; data->stats->processed++;
...@@ -131,9 +144,15 @@ int git_checkout_force(git_repository *repo, git_indexer_stats *stats) ...@@ -131,9 +144,15 @@ int git_checkout_force(git_repository *repo, git_indexer_stats *stats)
assert(repo); assert(repo);
if (!stats) stats = &dummy_stats; if (!stats) stats = &dummy_stats;
if (git_repository_is_bare(repo)) {
giterr_set(GITERR_INVALID, "Checkout is not allowed for bare repositories");
return GIT_ERROR;
}
stats->total = stats->processed = 0; stats->total = stats->processed = 0;
payload.stats = stats; payload.stats = stats;
payload.repo = repo; payload.repo = repo;
if (git_repository_odb(&payload.odb, repo) < 0) return GIT_ERROR;
/* TODO: stats->total is never calculated. */ /* TODO: stats->total is never calculated. */
...@@ -145,6 +164,7 @@ int git_checkout_force(git_repository *repo, git_indexer_stats *stats) ...@@ -145,6 +164,7 @@ int git_checkout_force(git_repository *repo, git_indexer_stats *stats)
git_tree_free(tree); git_tree_free(tree);
} }
git_odb_free(payload.odb);
return retcode; return retcode;
} }
......
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