diff --git a/src/checkout.c b/src/checkout.c index cd4bc5a62..ff4a8f82e 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -12,10 +12,12 @@ #include "git2/refs.h" #include "git2/tree.h" #include "git2/commit.h" +#include "git2/blob.h" #include "common.h" #include "refs.h" #include "buffer.h" +#include "repository.h" GIT_BEGIN_DECL @@ -46,6 +48,7 @@ static int get_head_tree(git_tree **out, git_repository *repo) typedef struct tree_walk_data { git_indexer_stats *stats; + git_repository *repo; } tree_walk_data; @@ -57,18 +60,51 @@ static int count_walker(const char *path, git_tree_entry *entry, void *payload) return 0; } +static int blob_contents_to_file(git_repository *repo, git_buf *fnbuf, const git_oid *id, int mode) +{ + int retcode = GIT_ERROR; + + git_blob *blob; + if (!git_blob_lookup(&blob, repo, id)) { + const void *contents = git_blob_rawcontent(blob); + size_t len = git_blob_rawsize(blob); + + /* TODO: line-ending smudging */ + + int fd = git_futils_creat_withpath(git_buf_cstr(fnbuf), + GIT_DIR_MODE, mode); + if (fd >= 0) { + retcode = (!p_write(fd, contents, len)) ? 0 : GIT_ERROR; + p_close(fd); + } + + git_blob_free(blob); + } + + return retcode; +} + static int checkout_walker(const char *path, git_tree_entry *entry, void *payload) { int retcode = 0; tree_walk_data *data = (tree_walk_data*)payload; + int attr = git_tree_entry_attributes(entry); switch(git_tree_entry_type(entry)) { case GIT_OBJ_TREE: - /* TODO: mkdir */ + /* TODO: mkdir? */ break; case GIT_OBJ_BLOB: - /* TODO: create/populate file */ + { + git_buf fnbuf = GIT_BUF_INIT; + git_buf_join_n(&fnbuf, '/', 3, + git_repository_workdir(data->repo), + 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: @@ -95,6 +131,7 @@ int git_checkout_force(git_repository *repo, git_indexer_stats *stats) stats->total = stats->processed = 0; payload.stats = stats; + payload.repo = repo; if (!get_head_tree(&tree, repo)) { /* Count all the tree nodes for progress information */