File Coverage

deps/libgit2/src/libgit2/reader.c
Criterion Covered Total %
statement 0 108 0.0
branch 0 84 0.0
condition n/a
subroutine n/a
pod n/a
total 0 192 0.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
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.
6             */
7              
8             #include "reader.h"
9              
10             #include "futils.h"
11             #include "blob.h"
12              
13             #include "git2/tree.h"
14             #include "git2/blob.h"
15             #include "git2/index.h"
16             #include "git2/repository.h"
17              
18             /* tree reader */
19              
20             typedef struct {
21             git_reader reader;
22             git_tree *tree;
23             } tree_reader;
24              
25 0           static int tree_reader_read(
26             git_str *out,
27             git_oid *out_id,
28             git_filemode_t *out_filemode,
29             git_reader *_reader,
30             const char *filename)
31             {
32 0           tree_reader *reader = (tree_reader *)_reader;
33 0           git_tree_entry *tree_entry = NULL;
34 0           git_blob *blob = NULL;
35             git_object_size_t blobsize;
36             int error;
37              
38 0 0         if ((error = git_tree_entry_bypath(&tree_entry, reader->tree, filename)) < 0 ||
    0          
39 0           (error = git_blob_lookup(&blob, git_tree_owner(reader->tree), git_tree_entry_id(tree_entry))) < 0)
40             goto done;
41              
42 0           blobsize = git_blob_rawsize(blob);
43 0 0         GIT_ERROR_CHECK_BLOBSIZE(blobsize);
44              
45 0 0         if ((error = git_str_set(out, git_blob_rawcontent(blob), (size_t)blobsize)) < 0)
46 0           goto done;
47              
48 0 0         if (out_id)
49 0           git_oid_cpy(out_id, git_tree_entry_id(tree_entry));
50              
51 0 0         if (out_filemode)
52 0           *out_filemode = git_tree_entry_filemode(tree_entry);
53              
54             done:
55 0           git_blob_free(blob);
56 0           git_tree_entry_free(tree_entry);
57 0           return error;
58             }
59              
60 0           int git_reader_for_tree(git_reader **out, git_tree *tree)
61             {
62             tree_reader *reader;
63              
64 0 0         GIT_ASSERT_ARG(out);
65 0 0         GIT_ASSERT_ARG(tree);
66              
67 0           reader = git__calloc(1, sizeof(tree_reader));
68 0 0         GIT_ERROR_CHECK_ALLOC(reader);
69              
70 0           reader->reader.read = tree_reader_read;
71 0           reader->tree = tree;
72              
73 0           *out = (git_reader *)reader;
74 0           return 0;
75             }
76              
77             /* workdir reader */
78              
79             typedef struct {
80             git_reader reader;
81             git_repository *repo;
82             git_index *index;
83             } workdir_reader;
84              
85 0           static int workdir_reader_read(
86             git_str *out,
87             git_oid *out_id,
88             git_filemode_t *out_filemode,
89             git_reader *_reader,
90             const char *filename)
91             {
92 0           workdir_reader *reader = (workdir_reader *)_reader;
93 0           git_str path = GIT_STR_INIT;
94             struct stat st;
95             git_filemode_t filemode;
96 0           git_filter_list *filters = NULL;
97             const git_index_entry *idx_entry;
98             git_oid id;
99             int error;
100              
101 0 0         if ((error = git_repository_workdir_path(&path, reader->repo, filename)) < 0)
102 0           goto done;
103              
104 0 0         if ((error = p_lstat(path.ptr, &st)) < 0) {
105 0 0         if (error == -1 && errno == ENOENT)
    0          
106 0           error = GIT_ENOTFOUND;
107              
108 0           git_error_set(GIT_ERROR_OS, "could not stat '%s'", path.ptr);
109 0           goto done;
110             }
111              
112 0           filemode = git_futils_canonical_mode(st.st_mode);
113              
114             /*
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.
118             */
119 0 0         if ((error = git_filter_list_load(&filters, reader->repo, NULL, filename,
120             GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT)) < 0)
121 0           goto done;
122              
123 0 0         if ((error = git_filter_list__apply_to_file(out,
124 0           filters, reader->repo, path.ptr)) < 0)
125 0           goto done;
126              
127 0 0         if (out_id || reader->index) {
    0          
128 0 0         if ((error = git_odb_hash(&id, out->ptr, out->size, GIT_OBJECT_BLOB)) < 0)
129 0           goto done;
130             }
131              
132 0 0         if (reader->index) {
133 0 0         if (!(idx_entry = git_index_get_bypath(reader->index, filename, 0)) ||
    0          
134 0 0         filemode != idx_entry->mode ||
135 0           !git_oid_equal(&id, &idx_entry->id)) {
136 0           error = GIT_READER_MISMATCH;
137 0           goto done;
138             }
139             }
140              
141 0 0         if (out_id)
142 0           git_oid_cpy(out_id, &id);
143              
144 0 0         if (out_filemode)
145 0           *out_filemode = filemode;
146              
147             done:
148 0           git_filter_list_free(filters);
149 0           git_str_dispose(&path);
150 0           return error;
151             }
152              
153 0           int git_reader_for_workdir(
154             git_reader **out,
155             git_repository *repo,
156             bool validate_index)
157             {
158             workdir_reader *reader;
159             int error;
160              
161 0 0         GIT_ASSERT_ARG(out);
162 0 0         GIT_ASSERT_ARG(repo);
163              
164 0           reader = git__calloc(1, sizeof(workdir_reader));
165 0 0         GIT_ERROR_CHECK_ALLOC(reader);
166              
167 0           reader->reader.read = workdir_reader_read;
168 0           reader->repo = repo;
169              
170 0 0         if (validate_index &&
    0          
171 0           (error = git_repository_index__weakptr(&reader->index, repo)) < 0) {
172 0           git__free(reader);
173 0           return error;
174             }
175              
176 0           *out = (git_reader *)reader;
177 0           return 0;
178             }
179              
180             /* index reader */
181              
182             typedef struct {
183             git_reader reader;
184             git_repository *repo;
185             git_index *index;
186             } index_reader;
187              
188 0           static int index_reader_read(
189             git_str *out,
190             git_oid *out_id,
191             git_filemode_t *out_filemode,
192             git_reader *_reader,
193             const char *filename)
194             {
195 0           index_reader *reader = (index_reader *)_reader;
196             const git_index_entry *entry;
197             git_blob *blob;
198             int error;
199              
200 0 0         if ((entry = git_index_get_bypath(reader->index, filename, 0)) == NULL)
201 0           return GIT_ENOTFOUND;
202              
203 0 0         if ((error = git_blob_lookup(&blob, reader->repo, &entry->id)) < 0)
204 0           goto done;
205              
206 0 0         if (out_id)
207 0           git_oid_cpy(out_id, &entry->id);
208              
209 0 0         if (out_filemode)
210 0           *out_filemode = entry->mode;
211              
212 0           error = git_blob__getbuf(out, blob);
213              
214             done:
215 0           git_blob_free(blob);
216 0           return error;
217             }
218              
219 0           int git_reader_for_index(
220             git_reader **out,
221             git_repository *repo,
222             git_index *index)
223             {
224             index_reader *reader;
225             int error;
226              
227 0 0         GIT_ASSERT_ARG(out);
228 0 0         GIT_ASSERT_ARG(repo);
229              
230 0           reader = git__calloc(1, sizeof(index_reader));
231 0 0         GIT_ERROR_CHECK_ALLOC(reader);
232              
233 0           reader->reader.read = index_reader_read;
234 0           reader->repo = repo;
235              
236 0 0         if (index) {
237 0           reader->index = index;
238 0 0         } else if ((error = git_repository_index__weakptr(&reader->index, repo)) < 0) {
239 0           git__free(reader);
240 0           return error;
241             }
242              
243 0           *out = (git_reader *)reader;
244 0           return 0;
245             }
246              
247             /* generic */
248              
249 0           int git_reader_read(
250             git_str *out,
251             git_oid *out_id,
252             git_filemode_t *out_filemode,
253             git_reader *reader,
254             const char *filename)
255             {
256 0 0         GIT_ASSERT_ARG(out);
257 0 0         GIT_ASSERT_ARG(reader);
258 0 0         GIT_ASSERT_ARG(filename);
259              
260 0           return reader->read(out, out_id, out_filemode, reader, filename);
261             }
262              
263 0           void git_reader_free(git_reader *reader)
264             {
265 0 0         if (!reader)
266 0           return;
267              
268 0           git__free(reader);
269             }