]> git.proxmox.com Git - libgit2.git/blame - src/reader.c
Add BD on ca-certificates
[libgit2.git] / src / reader.c
CommitLineData
ac3d33df
JK
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 "fileops.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
20typedef struct {
21 git_reader reader;
22 git_tree *tree;
23} tree_reader;
24
25static int tree_reader_read(
26 git_buf *out,
27 git_oid *out_id,
28 git_filemode_t *out_filemode,
29 git_reader *_reader,
30 const char *filename)
31{
32 tree_reader *reader = (tree_reader *)_reader;
33 git_tree_entry *tree_entry = NULL;
34 git_blob *blob = NULL;
35 git_off_t blobsize;
36 int error;
37
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)
40 goto done;
41
42 blobsize = git_blob_rawsize(blob);
43 GIT_ERROR_CHECK_BLOBSIZE(blobsize);
44
45 if ((error = git_buf_set(out, git_blob_rawcontent(blob), (size_t)blobsize)) < 0)
46 goto done;
47
48 if (out_id)
49 git_oid_cpy(out_id, git_tree_entry_id(tree_entry));
50
51 if (out_filemode)
52 *out_filemode = git_tree_entry_filemode(tree_entry);
53
54done:
55 git_blob_free(blob);
56 git_tree_entry_free(tree_entry);
57 return error;
58}
59
60int git_reader_for_tree(git_reader **out, git_tree *tree)
61{
62 tree_reader *reader;
63
64 assert(out && tree);
65
66 reader = git__calloc(1, sizeof(tree_reader));
67 GIT_ERROR_CHECK_ALLOC(reader);
68
69 reader->reader.read = tree_reader_read;
70 reader->tree = tree;
71
72 *out = (git_reader *)reader;
73 return 0;
74}
75
76/* workdir reader */
77
78typedef struct {
79 git_reader reader;
80 git_repository *repo;
81 git_index *index;
82} workdir_reader;
83
84static int workdir_reader_read(
85 git_buf *out,
86 git_oid *out_id,
87 git_filemode_t *out_filemode,
88 git_reader *_reader,
89 const char *filename)
90{
91 workdir_reader *reader = (workdir_reader *)_reader;
92 git_buf path = GIT_BUF_INIT;
93 struct stat st;
94 git_filemode_t filemode;
95 git_filter_list *filters = NULL;
96 const git_index_entry *idx_entry;
97 git_oid id;
98 int error;
99
100 if ((error = git_buf_joinpath(&path,
101 git_repository_workdir(reader->repo), filename)) < 0)
102 goto done;
103
104 if ((error = p_lstat(path.ptr, &st)) < 0) {
105 if (error == -1 && errno == ENOENT)
106 error = GIT_ENOTFOUND;
107
108 git_error_set(GIT_ERROR_OS, "could not stat '%s'", path.ptr);
109 goto done;
110 }
111
112 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 if ((error = git_filter_list_load(&filters, reader->repo, NULL, filename,
120 GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT)) < 0)
121 goto done;
122
123 if ((error = git_filter_list_apply_to_file(out,
124 filters, reader->repo, path.ptr)) < 0)
125 goto done;
126
127 if (out_id || reader->index) {
128 if ((error = git_odb_hash(&id, out->ptr, out->size, GIT_OBJECT_BLOB)) < 0)
129 goto done;
130 }
131
132 if (reader->index) {
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;
137 goto done;
138 }
139 }
140
141 if (out_id)
142 git_oid_cpy(out_id, &id);
143
144 if (out_filemode)
145 *out_filemode = filemode;
146
147done:
148 git_filter_list_free(filters);
149 git_buf_dispose(&path);
150 return error;
151}
152
153int 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 assert(out && repo);
162
163 reader = git__calloc(1, sizeof(workdir_reader));
164 GIT_ERROR_CHECK_ALLOC(reader);
165
166 reader->reader.read = workdir_reader_read;
167 reader->repo = repo;
168
169 if (validate_index &&
170 (error = git_repository_index__weakptr(&reader->index, repo)) < 0) {
171 git__free(reader);
172 return error;
173 }
174
175 *out = (git_reader *)reader;
176 return 0;
177}
178
179/* index reader */
180
181typedef struct {
182 git_reader reader;
183 git_repository *repo;
184 git_index *index;
185} index_reader;
186
187static int index_reader_read(
188 git_buf *out,
189 git_oid *out_id,
190 git_filemode_t *out_filemode,
191 git_reader *_reader,
192 const char *filename)
193{
194 index_reader *reader = (index_reader *)_reader;
195 const git_index_entry *entry;
196 git_blob *blob;
197 int error;
198
199 if ((entry = git_index_get_bypath(reader->index, filename, 0)) == NULL)
200 return GIT_ENOTFOUND;
201
202 if ((error = git_blob_lookup(&blob, reader->repo, &entry->id)) < 0)
203 goto done;
204
205 if (out_id)
206 git_oid_cpy(out_id, &entry->id);
207
208 if (out_filemode)
209 *out_filemode = entry->mode;
210
211 error = git_blob__getbuf(out, blob);
212
213done:
214 git_blob_free(blob);
215 return error;
216}
217
218int git_reader_for_index(
219 git_reader **out,
220 git_repository *repo,
221 git_index *index)
222{
223 index_reader *reader;
224 int error;
225
226 assert(out && repo);
227
228 reader = git__calloc(1, sizeof(index_reader));
229 GIT_ERROR_CHECK_ALLOC(reader);
230
231 reader->reader.read = index_reader_read;
232 reader->repo = repo;
233
234 if (index) {
235 reader->index = index;
236 } else if ((error = git_repository_index__weakptr(&reader->index, repo)) < 0) {
237 git__free(reader);
238 return error;
239 }
240
241 *out = (git_reader *)reader;
242 return 0;
243}
244
245/* generic */
246
247int git_reader_read(
248 git_buf *out,
249 git_oid *out_id,
250 git_filemode_t *out_filemode,
251 git_reader *reader,
252 const char *filename)
253{
254 assert(out && reader && filename);
255
256 return reader->read(out, out_id, out_filemode, reader, filename);
257}
258
259void git_reader_free(git_reader *reader)
260{
261 if (!reader)
262 return;
263
264 git__free(reader);
265}