| 244 | } |
| 245 | |
| 246 | char *write_rev_file_order(struct repository *repo, |
| 247 | const char *rev_name, |
| 248 | uint32_t *pack_order, |
| 249 | uint32_t nr_objects, |
| 250 | const unsigned char *hash, |
| 251 | unsigned flags) |
| 252 | { |
| 253 | struct hashfile *f; |
| 254 | char *path; |
| 255 | int fd; |
| 256 | |
| 257 | if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY)) |
| 258 | die(_("cannot both write and verify reverse index")); |
| 259 | |
| 260 | if (flags & WRITE_REV) { |
| 261 | if (!rev_name) { |
| 262 | struct strbuf tmp_file = STRBUF_INIT; |
| 263 | fd = odb_mkstemp(repo->objects, &tmp_file, |
| 264 | "pack/tmp_rev_XXXXXX"); |
| 265 | path = strbuf_detach(&tmp_file, NULL); |
| 266 | } else { |
| 267 | unlink(rev_name); |
| 268 | fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600); |
| 269 | path = xstrdup(rev_name); |
| 270 | } |
| 271 | f = hashfd(repo->hash_algo, fd, path); |
| 272 | } else if (flags & WRITE_REV_VERIFY) { |
| 273 | struct stat statbuf; |
| 274 | if (stat(rev_name, &statbuf)) { |
| 275 | if (errno == ENOENT) { |
| 276 | /* .rev files are optional */ |
| 277 | return NULL; |
| 278 | } else |
| 279 | die_errno(_("could not stat: %s"), rev_name); |
| 280 | } |
| 281 | f = hashfd_check(repo->hash_algo, rev_name); |
| 282 | path = xstrdup(rev_name); |
| 283 | } else { |
| 284 | return NULL; |
| 285 | } |
| 286 | |
| 287 | write_rev_header(repo->hash_algo, f); |
| 288 | |
| 289 | write_rev_index_positions(f, pack_order, nr_objects); |
| 290 | write_rev_trailer(repo->hash_algo, f, hash); |
| 291 | |
| 292 | if (adjust_shared_perm(repo, path) < 0) |
| 293 | die(_("failed to make %s readable"), path); |
| 294 | |
| 295 | finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, |
| 296 | CSUM_HASH_IN_STREAM | CSUM_CLOSE | |
| 297 | ((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC)); |
| 298 | |
| 299 | return path; |
| 300 | } |
| 301 | |
| 302 | static void write_mtimes_header(const struct git_hash_algo *hash_algo, |
| 303 | struct hashfile *f) |
no test coverage detected