#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;
const char *name;
struct tree_entry branch_tree;
uintmax_t last_commit;
- unsigned int pack_id;
+ unsigned active : 1;
+ unsigned pack_id : PACK_ID_BITS;
unsigned char sha1[20];
};
/* 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 */
b->table_next_branch = branch_table[hc];
b->branch_tree.versions[0].mode = S_IFDIR;
b->branch_tree.versions[1].mode = S_IFDIR;
+ b->active = 0;
b->pack_id = MAX_PACK_ID;
branch_table[hc] = b;
branch_count++;
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));
buf = xmalloc(buf_sz);
for (;;) {
- size_t n = xread(pack_fd, buf, buf_sz);
+ ssize_t n = xread(pack_fd, buf, buf_sz);
if (!n)
break;
if (n < 0)
}
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);
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) {
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);
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 (!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) {
e = active_branches;
active_branches = e->active_next_branch;
}
+ e->active = 0;
e->active_next_branch = NULL;
if (e->branch_tree.tree) {
release_tree_content_recursive(e->branch_tree.tree);
static void load_branch(struct branch *b)
{
load_tree(&b->branch_tree);
- b->active_next_branch = active_branches;
- active_branches = b;
- cur_active_branches++;
- branch_load_count++;
+ if (!b->active) {
+ b->active = 1;
+ b->active_next_branch = active_branches;
+ active_branches = b;
+ cur_active_branches++;
+ branch_load_count++;
+ }
}
static void file_change_m(struct branch *b)
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", idnum);
hashcpy(n->sha1, oe->sha1);
- } else if (get_sha1(from, n->sha1))
+ } else if (!get_sha1(from, n->sha1)) {
+ unsigned long size;
+ char *buf = read_object_with_reference(n->sha1,
+ commit_type, &size, n->sha1);
+ if (!buf || size < 46)
+ die("Not a valid commit: %s", from);
+ free(buf);
+ } else
die("Invalid ref name or SHA1 expression: %s", from);
n->next = NULL;
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();