summaryrefslogtreecommitdiff
path: root/pack-write.c
diff options
context:
space:
mode:
Diffstat (limited to 'pack-write.c')
-rw-r--r--pack-write.c144
1 files changed, 142 insertions, 2 deletions
diff --git a/pack-write.c b/pack-write.c
index 3513665e1e..2ca85a9d16 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "pack.h"
#include "csum-file.h"
+#include "remote.h"
void reset_pack_idx_option(struct pack_idx_option *opts)
{
@@ -166,6 +167,113 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec
return index_name;
}
+static int pack_order_cmp(const void *va, const void *vb, void *ctx)
+{
+ struct pack_idx_entry **objects = ctx;
+
+ off_t oa = objects[*(uint32_t*)va]->offset;
+ off_t ob = objects[*(uint32_t*)vb]->offset;
+
+ if (oa < ob)
+ return -1;
+ if (oa > ob)
+ return 1;
+ return 0;
+}
+
+static void write_rev_header(struct hashfile *f)
+{
+ uint32_t oid_version;
+ switch (hash_algo_by_ptr(the_hash_algo)) {
+ case GIT_HASH_SHA1:
+ oid_version = 1;
+ break;
+ case GIT_HASH_SHA256:
+ oid_version = 2;
+ break;
+ default:
+ die("write_rev_header: unknown hash version");
+ }
+
+ hashwrite_be32(f, RIDX_SIGNATURE);
+ hashwrite_be32(f, RIDX_VERSION);
+ hashwrite_be32(f, oid_version);
+}
+
+static void write_rev_index_positions(struct hashfile *f,
+ struct pack_idx_entry **objects,
+ uint32_t nr_objects)
+{
+ uint32_t *pack_order;
+ uint32_t i;
+
+ ALLOC_ARRAY(pack_order, nr_objects);
+ for (i = 0; i < nr_objects; i++)
+ pack_order[i] = i;
+ QSORT_S(pack_order, nr_objects, pack_order_cmp, objects);
+
+ for (i = 0; i < nr_objects; i++)
+ hashwrite_be32(f, pack_order[i]);
+
+ free(pack_order);
+}
+
+static void write_rev_trailer(struct hashfile *f, const unsigned char *hash)
+{
+ hashwrite(f, hash, the_hash_algo->rawsz);
+}
+
+const char *write_rev_file(const char *rev_name,
+ struct pack_idx_entry **objects,
+ uint32_t nr_objects,
+ const unsigned char *hash,
+ unsigned flags)
+{
+ struct hashfile *f;
+ int fd;
+
+ if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY))
+ die(_("cannot both write and verify reverse index"));
+
+ if (flags & WRITE_REV) {
+ if (!rev_name) {
+ struct strbuf tmp_file = STRBUF_INIT;
+ fd = odb_mkstemp(&tmp_file, "pack/tmp_rev_XXXXXX");
+ rev_name = strbuf_detach(&tmp_file, NULL);
+ } else {
+ unlink(rev_name);
+ fd = open(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
+ if (fd < 0)
+ die_errno("unable to create '%s'", rev_name);
+ }
+ f = hashfd(fd, rev_name);
+ } else if (flags & WRITE_REV_VERIFY) {
+ struct stat statbuf;
+ if (stat(rev_name, &statbuf)) {
+ if (errno == ENOENT) {
+ /* .rev files are optional */
+ return NULL;
+ } else
+ die_errno(_("could not stat: %s"), rev_name);
+ }
+ f = hashfd_check(rev_name);
+ } else
+ return NULL;
+
+ write_rev_header(f);
+
+ write_rev_index_positions(f, objects, nr_objects);
+ write_rev_trailer(f, hash);
+
+ if (rev_name && adjust_shared_perm(rev_name) < 0)
+ die(_("failed to make %s readable"), rev_name);
+
+ finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_CLOSE |
+ ((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));
+
+ return rev_name;
+}
+
off_t write_pack_header(struct hashfile *f, uint32_t nr_entries)
{
struct pack_header hdr;
@@ -272,7 +380,7 @@ void fixup_pack_header_footer(int pack_fd,
fsync_or_die(pack_fd, pack_name);
}
-char *index_pack_lockfile(int ip_out)
+char *index_pack_lockfile(int ip_out, int *is_well_formed)
{
char packname[GIT_MAX_HEXSZ + 6];
const int len = the_hash_algo->hexsz + 6;
@@ -286,11 +394,17 @@ char *index_pack_lockfile(int ip_out)
*/
if (read_in_full(ip_out, packname, len) == len && packname[len-1] == '\n') {
const char *name;
+
+ if (is_well_formed)
+ *is_well_formed = 1;
packname[len-1] = 0;
if (skip_prefix(packname, "keep\t", &name))
return xstrfmt("%s/pack/pack-%s.keep",
get_object_directory(), name);
+ return NULL;
}
+ if (is_well_formed)
+ *is_well_formed = 0;
return NULL;
}
@@ -341,7 +455,7 @@ void finish_tmp_packfile(struct strbuf *name_buffer,
struct pack_idx_option *pack_idx_opts,
unsigned char hash[])
{
- const char *idx_tmp_name;
+ const char *idx_tmp_name, *rev_tmp_name = NULL;
int basename_len = name_buffer->len;
if (adjust_shared_perm(pack_tmp_name))
@@ -352,6 +466,9 @@ void finish_tmp_packfile(struct strbuf *name_buffer,
if (adjust_shared_perm(idx_tmp_name))
die_errno("unable to make temporary index file readable");
+ rev_tmp_name = write_rev_file(NULL, written_list, nr_written, hash,
+ pack_idx_opts->flags);
+
strbuf_addf(name_buffer, "%s.pack", hash_to_hex(hash));
if (rename(pack_tmp_name, name_buffer->buf))
@@ -365,5 +482,28 @@ void finish_tmp_packfile(struct strbuf *name_buffer,
strbuf_setlen(name_buffer, basename_len);
+ if (rev_tmp_name) {
+ strbuf_addf(name_buffer, "%s.rev", hash_to_hex(hash));
+ if (rename(rev_tmp_name, name_buffer->buf))
+ die_errno("unable to rename temporary reverse-index file");
+ }
+
+ strbuf_setlen(name_buffer, basename_len);
+
free((void *)idx_tmp_name);
}
+
+void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought)
+{
+ int i, err;
+ FILE *output = xfopen(promisor_name, "w");
+
+ for (i = 0; i < nr_sought; i++)
+ fprintf(output, "%s %s\n", oid_to_hex(&sought[i]->old_oid),
+ sought[i]->name);
+
+ err = ferror(output);
+ err |= fclose(output);
+ if (err)
+ die(_("could not write '%s' promisor file"), promisor_name);
+}