diff options
Diffstat (limited to 'src/reader.c')
| -rw-r--r-- | src/reader.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/src/reader.c b/src/reader.c new file mode 100644 index 000000000..754b90a3b --- /dev/null +++ b/src/reader.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "reader.h" + +#include "fileops.h" +#include "blob.h" + +#include "git2/tree.h" +#include "git2/blob.h" +#include "git2/index.h" +#include "git2/repository.h" + +/* tree reader */ + +typedef struct { + git_reader reader; + git_tree *tree; +} tree_reader; + +static int tree_reader_read( + git_buf *out, + git_reader *_reader, + const char *filename) +{ + tree_reader *reader = (tree_reader *)_reader; + git_tree_entry *tree_entry = NULL; + git_blob *blob = NULL; + int error; + + if ((error = git_tree_entry_bypath(&tree_entry, reader->tree, filename)) < 0 || + (error = git_blob_lookup(&blob, git_tree_owner(reader->tree), git_tree_entry_id(tree_entry))) < 0 || + (error = git_buf_set(out, git_blob_rawcontent(blob), git_blob_rawsize(blob))) < 0) + goto done; + +done: + git_blob_free(blob); + git_tree_entry_free(tree_entry); + return error; +} + +static void tree_reader_free(git_reader *_reader) +{ + GIT_UNUSED(_reader); +} + +int git_reader_for_tree(git_reader **out, git_tree *tree) +{ + tree_reader *reader; + + assert(out && tree); + + reader = git__calloc(1, sizeof(tree_reader)); + GITERR_CHECK_ALLOC(reader); + + reader->reader.read = tree_reader_read; + reader->reader.free = tree_reader_free; + reader->tree = tree; + + *out = (git_reader *)reader; + return 0; +} + +/* workdir reader */ + +typedef struct { + git_reader reader; + git_repository *repo; +} workdir_reader; + +static int workdir_reader_read( + git_buf *out, + git_reader *_reader, + const char *filename) +{ + workdir_reader *reader = (workdir_reader *)_reader; + git_buf path = GIT_BUF_INIT; + int error; + + if ((error = git_buf_joinpath(&path, + git_repository_workdir(reader->repo), filename)) < 0) + goto done; + + /* TODO: should we read the filtered data? */ + error = git_futils_readbuffer(out, path.ptr); + +done: + git_buf_dispose(&path); + return error; +} + +static void workdir_reader_free(git_reader *_reader) +{ + GIT_UNUSED(_reader); +} + +int git_reader_for_workdir(git_reader **out, git_repository *repo) +{ + workdir_reader *reader; + + assert(out && repo); + + reader = git__calloc(1, sizeof(workdir_reader)); + GITERR_CHECK_ALLOC(reader); + + reader->reader.read = workdir_reader_read; + reader->reader.free = workdir_reader_free; + reader->repo = repo; + + *out = (git_reader *)reader; + return 0; +} + +/* index reader */ + +typedef struct { + git_reader reader; + git_repository *repo; + git_index *index; +} index_reader; + +static int index_reader_read( + git_buf *out, + git_reader *_reader, + const char *filename) +{ + index_reader *reader = (index_reader *)_reader; + const git_index_entry *entry; + git_blob *blob; + int error; + + if ((entry = git_index_get_bypath(reader->index, filename, 0)) == NULL) + return GIT_ENOTFOUND; + + if ((error = git_blob_lookup(&blob, reader->repo, &entry->id)) < 0) + goto done; + + error = git_blob__getbuf(out, blob); + +done: + git_blob_free(blob); + return error; +} + +static void index_reader_free(git_reader *_reader) +{ + GIT_UNUSED(_reader); +} + +int git_reader_for_index( + git_reader **out, + git_repository *repo, + git_index *index) +{ + index_reader *reader; + int error; + + assert(out && repo); + + reader = git__calloc(1, sizeof(index_reader)); + GITERR_CHECK_ALLOC(reader); + + reader->reader.read = index_reader_read; + reader->reader.free = index_reader_free; + reader->repo = repo; + + if (index) { + reader->index = index; + } else { + error = git_repository_index__weakptr(&reader->index, repo); + + if (error < 0) { + git__free(reader); + return error; + } + } + + *out = (git_reader *)reader; + return 0; +} + +/* generic */ + +int git_reader_read(git_buf *out, git_reader *reader, const char *filename) +{ + assert(out && reader && filename); + + return reader->read(out, reader, filename); +} + +void git_reader_free(git_reader *reader) +{ + if (!reader) + return; + + reader->free(reader); + git__free(reader); +} |
