2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
13 #include "git2/tree.h"
14 #include "git2/blob.h"
15 #include "git2/index.h"
16 #include "git2/repository.h"
25 static int tree_reader_read(
28 git_filemode_t
*out_filemode
,
32 tree_reader
*reader
= (tree_reader
*)_reader
;
33 git_tree_entry
*tree_entry
= NULL
;
34 git_blob
*blob
= NULL
;
35 git_object_size_t blobsize
;
38 if ((error
= git_tree_entry_bypath(&tree_entry
, reader
->tree
, filename
)) < 0 ||
39 (error
= git_blob_lookup(&blob
, git_tree_owner(reader
->tree
), git_tree_entry_id(tree_entry
))) < 0)
42 blobsize
= git_blob_rawsize(blob
);
43 GIT_ERROR_CHECK_BLOBSIZE(blobsize
);
45 if ((error
= git_str_set(out
, git_blob_rawcontent(blob
), (size_t)blobsize
)) < 0)
49 git_oid_cpy(out_id
, git_tree_entry_id(tree_entry
));
52 *out_filemode
= git_tree_entry_filemode(tree_entry
);
56 git_tree_entry_free(tree_entry
);
60 int git_reader_for_tree(git_reader
**out
, git_tree
*tree
)
67 reader
= git__calloc(1, sizeof(tree_reader
));
68 GIT_ERROR_CHECK_ALLOC(reader
);
70 reader
->reader
.read
= tree_reader_read
;
73 *out
= (git_reader
*)reader
;
85 static int workdir_reader_read(
88 git_filemode_t
*out_filemode
,
92 workdir_reader
*reader
= (workdir_reader
*)_reader
;
93 git_str path
= GIT_STR_INIT
;
95 git_filemode_t filemode
;
96 git_filter_list
*filters
= NULL
;
97 const git_index_entry
*idx_entry
;
101 if ((error
= git_repository_workdir_path(&path
, reader
->repo
, filename
)) < 0)
104 if ((error
= p_lstat(path
.ptr
, &st
)) < 0) {
105 if (error
== -1 && errno
== ENOENT
)
106 error
= GIT_ENOTFOUND
;
108 git_error_set(GIT_ERROR_OS
, "could not stat '%s'", path
.ptr
);
112 filemode
= git_futils_canonical_mode(st
.st_mode
);
115 * Patch application - for example - uses the filtered version of
116 * the working directory data to match git. So we will run the
117 * workdir -> ODB filter on the contents in this workdir reader.
119 if ((error
= git_filter_list_load(&filters
, reader
->repo
, NULL
, filename
,
120 GIT_FILTER_TO_ODB
, GIT_FILTER_DEFAULT
)) < 0)
123 if ((error
= git_filter_list__apply_to_file(out
,
124 filters
, reader
->repo
, path
.ptr
)) < 0)
127 if (out_id
|| reader
->index
) {
128 if ((error
= git_odb_hash(&id
, out
->ptr
, out
->size
, GIT_OBJECT_BLOB
)) < 0)
133 if (!(idx_entry
= git_index_get_bypath(reader
->index
, filename
, 0)) ||
134 filemode
!= idx_entry
->mode
||
135 !git_oid_equal(&id
, &idx_entry
->id
)) {
136 error
= GIT_READER_MISMATCH
;
142 git_oid_cpy(out_id
, &id
);
145 *out_filemode
= filemode
;
148 git_filter_list_free(filters
);
149 git_str_dispose(&path
);
153 int git_reader_for_workdir(
155 git_repository
*repo
,
158 workdir_reader
*reader
;
162 GIT_ASSERT_ARG(repo
);
164 reader
= git__calloc(1, sizeof(workdir_reader
));
165 GIT_ERROR_CHECK_ALLOC(reader
);
167 reader
->reader
.read
= workdir_reader_read
;
170 if (validate_index
&&
171 (error
= git_repository_index__weakptr(&reader
->index
, repo
)) < 0) {
176 *out
= (git_reader
*)reader
;
184 git_repository
*repo
;
188 static int index_reader_read(
191 git_filemode_t
*out_filemode
,
193 const char *filename
)
195 index_reader
*reader
= (index_reader
*)_reader
;
196 const git_index_entry
*entry
;
200 if ((entry
= git_index_get_bypath(reader
->index
, filename
, 0)) == NULL
)
201 return GIT_ENOTFOUND
;
203 if ((error
= git_blob_lookup(&blob
, reader
->repo
, &entry
->id
)) < 0)
207 git_oid_cpy(out_id
, &entry
->id
);
210 *out_filemode
= entry
->mode
;
212 error
= git_blob__getbuf(out
, blob
);
219 int git_reader_for_index(
221 git_repository
*repo
,
224 index_reader
*reader
;
228 GIT_ASSERT_ARG(repo
);
230 reader
= git__calloc(1, sizeof(index_reader
));
231 GIT_ERROR_CHECK_ALLOC(reader
);
233 reader
->reader
.read
= index_reader_read
;
237 reader
->index
= index
;
238 } else if ((error
= git_repository_index__weakptr(&reader
->index
, repo
)) < 0) {
243 *out
= (git_reader
*)reader
;
252 git_filemode_t
*out_filemode
,
254 const char *filename
)
257 GIT_ASSERT_ARG(reader
);
258 GIT_ASSERT_ARG(filename
);
260 return reader
->read(out
, out_id
, out_filemode
, reader
, filename
);
263 void git_reader_free(git_reader
*reader
)