#define PACK_ID_BITS 16
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
-#ifndef PRIuMAX
-#define PRIuMAX "llu"
-#endif
-
struct object_entry
{
struct object_entry *next;
/* Configured limits on output */
static unsigned long max_depth = 10;
-static unsigned long max_packsize = (1LL << 32) - 1;
+static off_t max_packsize = (1LL << 32) - 1;
static int force_update;
/* Stats and misc. counters */
int pack_fd;
snprintf(tmpfile, sizeof(tmpfile),
- "%s/pack_XXXXXX", get_object_directory());
+ "%s/tmp_pack_XXXXXX", get_object_directory());
pack_fd = mkstemp(tmpfile);
if (pack_fd < 0)
die("Can't create %s: %s", tmpfile, strerror(errno));
all_packs[pack_id] = p;
}
-static void fixup_header_footer(void)
-{
- static const int buf_sz = 128 * 1024;
- int pack_fd = pack_data->pack_fd;
- SHA_CTX c;
- struct pack_header hdr;
- char *buf;
-
- if (lseek(pack_fd, 0, SEEK_SET) != 0)
- die("Failed seeking to start: %s", strerror(errno));
- if (read_in_full(pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
- die("Unable to reread header of %s", pack_data->pack_name);
- if (lseek(pack_fd, 0, SEEK_SET) != 0)
- die("Failed seeking to start: %s", strerror(errno));
- hdr.hdr_entries = htonl(object_count);
- write_or_die(pack_fd, &hdr, sizeof(hdr));
-
- SHA1_Init(&c);
- SHA1_Update(&c, &hdr, sizeof(hdr));
-
- buf = xmalloc(buf_sz);
- for (;;) {
- size_t n = xread(pack_fd, buf, buf_sz);
- if (!n)
- break;
- if (n < 0)
- die("Failed to checksum %s", pack_data->pack_name);
- SHA1_Update(&c, buf, n);
- }
- free(buf);
-
- SHA1_Final(pack_data->sha1, &c);
- write_or_die(pack_fd, pack_data->sha1, sizeof(pack_data->sha1));
- close(pack_fd);
-}
-
static int oecmp (const void *a_, const void *b_)
{
struct object_entry *a = *((struct object_entry**)a_);
}
snprintf(tmpfile, sizeof(tmpfile),
- "%s/index_XXXXXX", get_object_directory());
+ "%s/tmp_idx_XXXXXX", get_object_directory());
idx_fd = mkstemp(tmpfile);
if (idx_fd < 0)
die("Can't create %s: %s", tmpfile, strerror(errno));
static char *keep_pack(char *curr_index_name)
{
static char name[PATH_MAX];
- static char *keep_msg = "fast-import";
+ static const char *keep_msg = "fast-import";
int keep_fd;
chmod(pack_data->pack_name, 0444);
struct branch *b;
struct tag *t;
- fixup_header_footer();
+ fixup_pack_header_footer(pack_data->pack_fd, pack_data->sha1,
+ pack_data->pack_name, object_count);
+ close(pack_data->pack_fd);
idx_name = keep_pack(create_index());
/* Register the packfile with core git's machinary. */
if (e->offset) {
duplicate_count_by_type[type]++;
return 1;
+ } else if (find_sha1_pack(sha1, packed_git)) {
+ e->type = type;
+ e->pack_id = MAX_PACK_ID;
+ e->offset = 1; /* just not zero! */
+ duplicate_count_by_type[type]++;
+ return 1;
}
if (last && last->data && last->depth < max_depth) {
return;
myoe = find_object(sha1);
- if (myoe) {
+ if (myoe && myoe->pack_id != MAX_PACK_ID) {
if (myoe->type != OBJ_TREE)
die("Not a tree: %s", sha1_to_hex(sha1));
t->delta_depth = 0;
struct tree_entry *e = new_tree_entry();
if (t->entry_count == t->entry_capacity)
- root->tree = t = grow_tree_content(t, 8);
+ root->tree = t = grow_tree_content(t, t->entry_count);
t->entries[t->entry_count++] = e;
e->tree = NULL;
if (!c)
die("Corrupt mode in %s", sha1_to_hex(sha1));
e->versions[0].mode = e->versions[1].mode;
- e->name = to_atom(c, (unsigned short)strlen(c));
+ e->name = to_atom(c, strlen(c));
c += e->name->str_len + 1;
hashcpy(e->versions[0].sha1, (unsigned char*)c);
hashcpy(e->versions[1].sha1, (unsigned char*)c);
|| le->pack_id != pack_id) {
lo.data = NULL;
lo.depth = 0;
+ lo.no_free = 0;
} else {
mktree(t, 0, &lo.len, &old_tree);
lo.data = old_tree.buffer;
n = slash1 - p;
else
n = strlen(p);
+ if (!n)
+ die("Empty path component found in input");
for (i = 0; i < t->entry_count; i++) {
e = t->entries[i];
}
if (t->entry_count == t->entry_capacity)
- root->tree = t = grow_tree_content(t, 8);
+ root->tree = t = grow_tree_content(t, t->entry_count);
e = new_tree_entry();
- e->name = to_atom(p, (unsigned short)n);
+ e->name = to_atom(p, n);
e->versions[0].mode = 0;
hashclr(e->versions[0].sha1);
t->entries[t->entry_count++] = e;
if (read_ref(b->name, old_sha1))
hashclr(old_sha1);
- lock = lock_any_ref_for_update(b->name, old_sha1);
+ lock = lock_any_ref_for_update(b->name, old_sha1, 0);
if (!lock)
return error("Unable to lock %s", b->name);
if (!force_update && !is_null_sha1(old_sha1)) {
if (!in_merge_bases(old_cmit, &new_cmit, 1)) {
unlock_ref(lock);
- warn("Not updating %s"
+ warning("Not updating %s"
" (new tip %s does not contain %s)",
b->name, sha1_to_hex(b->sha1), sha1_to_hex(old_sha1));
return -1;
static void dump_marks(void)
{
- if (mark_file)
- {
- FILE *f = fopen(mark_file, "w");
- if (f) {
- dump_marks_helper(f, 0, marks);
- fclose(f);
- } else
- failure |= error("Unable to write marks file %s: %s",
- mark_file, strerror(errno));
+ static struct lock_file mark_lock;
+ int mark_fd;
+ FILE *f;
+
+ if (!mark_file)
+ return;
+
+ mark_fd = hold_lock_file_for_update(&mark_lock, mark_file, 0);
+ if (mark_fd < 0) {
+ failure |= error("Unable to write marks file %s: %s",
+ mark_file, strerror(errno));
+ return;
+ }
+
+ f = fdopen(mark_fd, "w");
+ if (!f) {
+ rollback_lock_file(&mark_lock);
+ failure |= error("Unable to write marks file %s: %s",
+ mark_file, strerror(errno));
+ return;
}
+
+ dump_marks_helper(f, 0, marks);
+ fclose(f);
+ if (commit_lock_file(&mark_lock))
+ failure |= error("Unable to write marks file %s: %s",
+ mark_file, strerror(errno));
}
static void read_next_command(void)
{
while (cur_active_branches
&& cur_active_branches >= max_active_branches) {
- unsigned long min_commit = ULONG_MAX;
+ uintmax_t min_commit = ULONG_MAX;
struct branch *e, *l = NULL, *p = NULL;
for (e = active_branches; e; e = e->active_next_branch) {
load_tree(&b->branch_tree);
}
+static void cmd_from_commit(struct branch *b, char *buf, unsigned long size)
+{
+ if (!buf || size < 46)
+ die("Not a valid commit: %s", sha1_to_hex(b->sha1));
+ if (memcmp("tree ", buf, 5)
+ || get_sha1_hex(buf + 5, b->branch_tree.versions[1].sha1))
+ die("The commit %s is corrupt", sha1_to_hex(b->sha1));
+ hashcpy(b->branch_tree.versions[0].sha1,
+ b->branch_tree.versions[1].sha1);
+}
+
+static void cmd_from_existing(struct branch *b)
+{
+ if (is_null_sha1(b->sha1)) {
+ hashclr(b->branch_tree.versions[0].sha1);
+ hashclr(b->branch_tree.versions[1].sha1);
+ } else {
+ unsigned long size;
+ char *buf;
+
+ buf = read_object_with_reference(b->sha1,
+ commit_type, &size, b->sha1);
+ cmd_from_commit(b, buf, size);
+ free(buf);
+ }
+}
+
static void cmd_from(struct branch *b)
{
const char *from;
} else if (*from == ':') {
uintmax_t idnum = strtoumax(from + 1, NULL, 10);
struct object_entry *oe = find_mark(idnum);
- unsigned long size;
- char *buf;
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", idnum);
hashcpy(b->sha1, oe->sha1);
- buf = gfi_unpack_entry(oe, &size);
- if (!buf || size < 46)
- die("Not a valid commit: %s", from);
- if (memcmp("tree ", buf, 5)
- || get_sha1_hex(buf + 5, b->branch_tree.versions[1].sha1))
- die("The commit %s is corrupt", sha1_to_hex(b->sha1));
- free(buf);
- hashcpy(b->branch_tree.versions[0].sha1,
- b->branch_tree.versions[1].sha1);
- } else if (!get_sha1(from, b->sha1)) {
- if (is_null_sha1(b->sha1)) {
- hashclr(b->branch_tree.versions[0].sha1);
- hashclr(b->branch_tree.versions[1].sha1);
- } else {
+ if (oe->pack_id != MAX_PACK_ID) {
unsigned long size;
- char *buf;
-
- buf = read_object_with_reference(b->sha1,
- commit_type, &size, b->sha1);
- if (!buf || size < 46)
- die("Not a valid commit: %s", from);
- if (memcmp("tree ", buf, 5)
- || get_sha1_hex(buf + 5, b->branch_tree.versions[1].sha1))
- die("The commit %s is corrupt", sha1_to_hex(b->sha1));
+ char *buf = gfi_unpack_entry(oe, &size);
+ cmd_from_commit(b, buf, size);
free(buf);
- hashcpy(b->branch_tree.versions[0].sha1,
- b->branch_tree.versions[1].sha1);
- }
- } else
+ } else
+ cmd_from_existing(b);
+ } else if (!get_sha1(from, b->sha1))
+ cmd_from_existing(b);
+ else
die("Invalid ref name or SHA1 expression: %s", from);
read_next_command();
read_next_command();
}
+static void import_marks(const char *input_file)
+{
+ char line[512];
+ FILE *f = fopen(input_file, "r");
+ if (!f)
+ die("cannot read %s: %s", input_file, strerror(errno));
+ while (fgets(line, sizeof(line), f)) {
+ uintmax_t mark;
+ char *end;
+ unsigned char sha1[20];
+ struct object_entry *e;
+
+ end = strchr(line, '\n');
+ if (line[0] != ':' || !end)
+ die("corrupt mark line: %s", line);
+ *end = 0;
+ mark = strtoumax(line + 1, &end, 10);
+ if (!mark || end == line + 1
+ || *end != ' ' || get_sha1(end + 1, sha1))
+ die("corrupt mark line: %s", line);
+ e = find_object(sha1);
+ if (!e) {
+ enum object_type type = sha1_object_info(sha1, NULL);
+ if (type < 0)
+ die("object not found: %s", sha1_to_hex(sha1));
+ e = insert_object(sha1);
+ e->type = type;
+ e->pack_id = MAX_PACK_ID;
+ e->offset = 1; /* just not zero! */
+ }
+ insert_mark(mark, e);
+ }
+ fclose(f);
+}
+
static const char fast_import_usage[] =
"git-fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
int i, show_stats = 1;
git_config(git_default_config);
+ alloc_objects(object_entry_alloc);
+ strbuf_init(&command_buf);
+ atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*));
+ branch_table = xcalloc(branch_table_sz, sizeof(struct branch*));
+ avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
+ marks = pool_calloc(1, sizeof(struct mark_set));
for (i = 1; i < argc; i++) {
const char *a = argv[i];
max_depth = strtoul(a + 8, NULL, 0);
else if (!prefixcmp(a, "--active-branches="))
max_active_branches = strtoul(a + 18, NULL, 0);
+ else if (!prefixcmp(a, "--import-marks="))
+ import_marks(a + 15);
else if (!prefixcmp(a, "--export-marks="))
mark_file = a + 15;
else if (!prefixcmp(a, "--export-pack-edges=")) {
if (i != argc)
usage(fast_import_usage);
- alloc_objects(object_entry_alloc);
- strbuf_init(&command_buf);
-
- atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*));
- branch_table = xcalloc(branch_table_sz, sizeof(struct branch*));
- avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
- marks = pool_calloc(1, sizeof(struct mark_set));
-
+ prepare_packed_git();
start_packfile();
for (;;) {
read_next_command();