source src/reader.c
| Line | Flow | Count | Block(s) | Source | 
|---|---|---|---|---|
| 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 |  | ##### | 2 | static 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 | ##### | 2 | tree_reader *reader = (tree_reader *)_reader; | |
| 33 | ##### | 2 | git_tree_entry *tree_entry = NULL; | |
| 34 | ##### | 2 | git_blob *blob = NULL; | |
| 35 | - | git_object_size_t blobsize; | ||
| 36 | - | int error; | ||
| 37 | - | |||
| 38 | ##### | 2,3,6,7 | if ((error = git_tree_entry_bypath(&tree_entry, reader->tree, filename)) < 0 || | |
| 39 | ##### | 4,5 | (error = git_blob_lookup(&blob, git_tree_owner(reader->tree), git_tree_entry_id(tree_entry))) < 0) | |
| 40 | - | goto done; | ||
| 41 | - | |||
| 42 | ##### | 8 | blobsize = git_blob_rawsize(blob); | |
| 43 | ##### | 9-12 | GIT_ERROR_CHECK_BLOBSIZE(blobsize); | |
| 44 | - | |||
| 45 | ##### | 13-15 | if ((error = git_buf_set(out, git_blob_rawcontent(blob), (size_t)blobsize)) < 0) | |
| 46 | ##### | 16 | goto done; | |
| 47 | - | |||
| 48 | ##### | 17 | if (out_id) | |
| 49 | ##### | 18,19 | git_oid_cpy(out_id, git_tree_entry_id(tree_entry)); | |
| 50 | - | |||
| 51 | ##### | 20 | if (out_filemode) | |
| 52 | ##### | 21,22 | *out_filemode = git_tree_entry_filemode(tree_entry); | |
| 53 | - | |||
| 54 | - | done: | ||
| 55 | ##### | 23 | git_blob_free(blob); | |
| 56 | ##### | 24 | git_tree_entry_free(tree_entry); | |
| 57 | ##### | 25 | return error; | |
| 58 | - | } | ||
| 59 | - | |||
| 60 |  | 2 | 2 | int git_reader_for_tree(git_reader **out, git_tree *tree) | 
| 61 | - | { | ||
| 62 | - | tree_reader *reader; | ||
| 63 | - | |||
| 64 | 2 | 2-4 | assert(out && tree); | |
| 65 | - | |||
| 66 | 2 | 5 | reader = git__calloc(1, sizeof(tree_reader)); | |
| 67 | 2 | 6,7 | GIT_ERROR_CHECK_ALLOC(reader); | |
| 68 | - | |||
| 69 | 2 | 8 | reader->reader.read = tree_reader_read; | |
| 70 | 2 | 8 | reader->tree = tree; | |
| 71 | - | |||
| 72 | 2 | 8 | *out = (git_reader *)reader; | |
| 73 | 2 | 8 | return 0; | |
| 74 | - | } | ||
| 75 | - | |||
| 76 | - | /* workdir reader */ | ||
| 77 | - | |||
| 78 | - | typedef struct { | ||
| 79 | - | git_reader reader; | ||
| 80 | - | git_repository *repo; | ||
| 81 | - | git_index *index; | ||
| 82 | - | } workdir_reader; | ||
| 83 | - | |||
| 84 |  | 57 | 2 | static 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 | 57 | 2 | workdir_reader *reader = (workdir_reader *)_reader; | |
| 92 | 57 | 2 | git_buf path = GIT_BUF_INIT; | |
| 93 | - | struct stat st; | ||
| 94 | - | git_filemode_t filemode; | ||
| 95 | 57 | 2 | git_filter_list *filters = NULL; | |
| 96 | - | const git_index_entry *idx_entry; | ||
| 97 | - | git_oid id; | ||
| 98 | - | int error; | ||
| 99 | - | |||
| 100 | 57 | 2-4 | if ((error = git_buf_joinpath(&path, | |
| 101 | 57 | 2 | git_repository_workdir(reader->repo), filename)) < 0) | |
| 102 | ##### | 5 | goto done; | |
| 103 | - | |||
| 104 | 57 | 6,7 | if ((error = p_lstat(path.ptr, &st)) < 0) { | |
| 105 | ##### | 8-10 | if (error == -1 && errno == ENOENT) | |
| 106 | ##### | 11 | error = GIT_ENOTFOUND; | |
| 107 | - | |||
| 108 | ##### | 12 | git_error_set(GIT_ERROR_OS, "could not stat '%s'", path.ptr); | |
| 109 | ##### | 13 | goto done; | |
| 110 | - | } | ||
| 111 | - | |||
| 112 | 57 | 14 | 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 | 57 | 15,16 | if ((error = git_filter_list_load(&filters, reader->repo, NULL, filename, | |
| 120 | - | GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT)) < 0) | ||
| 121 | ##### | 17 | goto done; | |
| 122 | - | |||
| 123 | 57 | 18,19 | if ((error = git_filter_list_apply_to_file(out, | |
| 124 | 57 | 18 | filters, reader->repo, path.ptr)) < 0) | |
| 125 | ##### | 20 | goto done; | |
| 126 | - | |||
| 127 | 57 | 21,22 | if (out_id || reader->index) { | |
| 128 | 57 | 23,24 | if ((error = git_odb_hash(&id, out->ptr, out->size, GIT_OBJECT_BLOB)) < 0) | |
| 129 | ##### | 25 | goto done; | |
| 130 | - | } | ||
| 131 | - | |||
| 132 | 57 | 26 | if (reader->index) { | |
| 133 | 39 | 27-29 | if (!(idx_entry = git_index_get_bypath(reader->index, filename, 0)) || | |
| 134 | 38 | 29,31 | filemode != idx_entry->mode || | |
| 135 | 37 | 30 | !git_oid_equal(&id, &idx_entry->id)) { | |
| 136 | 3 | 32 | error = GIT_READER_MISMATCH; | |
| 137 | 3 | 32 | goto done; | |
| 138 | - | } | ||
| 139 | - | } | ||
| 140 | - | |||
| 141 | 54 | 33 | if (out_id) | |
| 142 | 54 | 34 | git_oid_cpy(out_id, &id); | |
| 143 | - | |||
| 144 | 54 | 35 | if (out_filemode) | |
| 145 | 54 | 36 | *out_filemode = filemode; | |
| 146 | - | |||
| 147 | - | done: | ||
| 148 | 57 | 37 | git_filter_list_free(filters); | |
| 149 | 57 | 38 | git_buf_dispose(&path); | |
| 150 | 57 | 39 | return error; | |
| 151 | - | } | ||
| 152 | - | |||
| 153 |  | 40 | 2 | 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 | 40 | 2-4 | assert(out && repo); | |
| 162 | - | |||
| 163 | 40 | 5 | reader = git__calloc(1, sizeof(workdir_reader)); | |
| 164 | 40 | 6,7 | GIT_ERROR_CHECK_ALLOC(reader); | |
| 165 | - | |||
| 166 | 40 | 8 | reader->reader.read = workdir_reader_read; | |
| 167 | 40 | 8 | reader->repo = repo; | |
| 168 | - | |||
| 169 | 40 | 8-10 | if (validate_index && | |
| 170 | 27 | 9 | (error = git_repository_index__weakptr(&reader->index, repo)) < 0) { | |
| 171 | ##### | 11 | git__free(reader); | |
| 172 | ##### | 12 | return error; | |
| 173 | - | } | ||
| 174 | - | |||
| 175 | 40 | 13 | *out = (git_reader *)reader; | |
| 176 | 40 | 13 | return 0; | |
| 177 | - | } | ||
| 178 | - | |||
| 179 | - | /* index reader */ | ||
| 180 | - | |||
| 181 | - | typedef struct { | ||
| 182 | - | git_reader reader; | ||
| 183 | - | git_repository *repo; | ||
| 184 | - | git_index *index; | ||
| 185 | - | } index_reader; | ||
| 186 | - | |||
| 187 |  | 98 | 2 | static 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 | 98 | 2 | index_reader *reader = (index_reader *)_reader; | |
| 195 | - | const git_index_entry *entry; | ||
| 196 | - | git_blob *blob; | ||
| 197 | - | int error; | ||
| 198 | - | |||
| 199 | 98 | 2,3 | if ((entry = git_index_get_bypath(reader->index, filename, 0)) == NULL) | |
| 200 | 74 | 4 | return GIT_ENOTFOUND; | |
| 201 | - | |||
| 202 | 24 | 5,6 | if ((error = git_blob_lookup(&blob, reader->repo, &entry->id)) < 0) | |
| 203 | ##### | 7 | goto done; | |
| 204 | - | |||
| 205 | 24 | 8 | if (out_id) | |
| 206 | 24 | 9 | git_oid_cpy(out_id, &entry->id); | |
| 207 | - | |||
| 208 | 24 | 10 | if (out_filemode) | |
| 209 | 24 | 11 | *out_filemode = entry->mode; | |
| 210 | - | |||
| 211 | 24 | 12 | error = git_blob__getbuf(out, blob); | |
| 212 | - | |||
| 213 | - | done: | ||
| 214 | 24 | 13 | git_blob_free(blob); | |
| 215 | 24 | 14 | return error; | |
| 216 | - | } | ||
| 217 | - | |||
| 218 |  | 68 | 2 | int 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 | 68 | 2-4 | assert(out && repo); | |
| 227 | - | |||
| 228 | 68 | 5 | reader = git__calloc(1, sizeof(index_reader)); | |
| 229 | 68 | 6,7 | GIT_ERROR_CHECK_ALLOC(reader); | |
| 230 | - | |||
| 231 | 68 | 8 | reader->reader.read = index_reader_read; | |
| 232 | 68 | 8 | reader->repo = repo; | |
| 233 | - | |||
| 234 | 68 | 8 | if (index) { | |
| 235 | 55 | 9 | reader->index = index; | |
| 236 | 13 | 10,11 | } else if ((error = git_repository_index__weakptr(&reader->index, repo)) < 0) { | |
| 237 | ##### | 12 | git__free(reader); | |
| 238 | ##### | 13 | return error; | |
| 239 | - | } | ||
| 240 | - | |||
| 241 | 68 | 14 | *out = (git_reader *)reader; | |
| 242 | 68 | 14 | return 0; | |
| 243 | - | } | ||
| 244 | - | |||
| 245 | - | /* generic */ | ||
| 246 | - | |||
| 247 |  | 155 | 2 | int 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 | 155 | 2-5 | assert(out && reader && filename); | |
| 255 | - | |||
| 256 | 155 | 6 | return reader->read(out, out_id, out_filemode, reader, filename); | |
| 257 | - | } | ||
| 258 | - | |||
| 259 |  | 110 | 2 | void git_reader_free(git_reader *reader) | 
| 260 | - | { | ||
| 261 | 110 | 2 | if (!reader) | |
| 262 | 110 | 3,5 | return; | |
| 263 | - | |||
| 264 | 110 | 4 | git__free(reader); | |
| 265 | - | } |