summaryrefslogtreecommitdiff
path: root/fast-import.c
diff options
context:
space:
mode:
Diffstat (limited to 'fast-import.c')
-rw-r--r--fast-import.c504
1 files changed, 266 insertions, 238 deletions
diff --git a/fast-import.c b/fast-import.c
index fb4738d373..3c65edb5c4 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -134,16 +134,17 @@ Format of STDIN stream:
ts ::= # time since the epoch in seconds, ascii base10 notation;
tz ::= # GIT style timezone;
- # note: comments, ls and cat requests may appear anywhere
- # in the input, except within a data command. Any form
- # of the data command always escapes the related input
- # from comment processing.
+ # note: comments, get-mark, ls-tree, and cat-blob requests may
+ # appear anywhere in the input, except within a data command. Any
+ # form of the data command always escapes the related input from
+ # comment processing.
#
# In case it is not clear, the '#' that starts the comment
# must be the first character on that line (an lf
# preceded it).
#
+ get_mark ::= 'get-mark' sp idnum lf;
cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;
ls_tree ::= 'ls' sp (hexsha1 | idnum) sp path_str lf;
@@ -153,6 +154,7 @@ Format of STDIN stream:
#include "builtin.h"
#include "cache.h"
+#include "lockfile.h"
#include "object.h"
#include "blob.h"
#include "tree.h"
@@ -248,6 +250,7 @@ struct branch {
uintmax_t last_commit;
uintmax_t num_notes;
unsigned active : 1;
+ unsigned delete : 1;
unsigned pack_id : PACK_ID_BITS;
unsigned char sha1[20];
};
@@ -370,8 +373,9 @@ static volatile sig_atomic_t checkpoint_requested;
static int cat_blob_fd = STDOUT_FILENO;
static void parse_argv(void);
-static void parse_cat_blob(void);
-static void parse_ls(struct branch *b);
+static void parse_get_mark(const char *p);
+static void parse_cat_blob(const char *p);
+static void parse_ls(const char *p, struct branch *b);
static void write_branch_report(FILE *rpt, struct branch *b)
{
@@ -403,7 +407,7 @@ static void dump_marks_helper(FILE *, uintmax_t, struct mark_set *);
static void write_crash_report(const char *err)
{
- char *loc = git_path("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid());
+ char *loc = git_pathdup("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid());
FILE *rpt = fopen(loc, "w");
struct branch *b;
unsigned long lu;
@@ -411,6 +415,7 @@ static void write_crash_report(const char *err)
if (!rpt) {
error("can't write crash report %s: %s", loc, strerror(errno));
+ free(loc);
return;
}
@@ -419,7 +424,7 @@ static void write_crash_report(const char *err)
fprintf(rpt, "fast-import crash report:\n");
fprintf(rpt, " fast-import process: %"PRIuMAX"\n", (uintmax_t) getpid());
fprintf(rpt, " parent process : %"PRIuMAX"\n", (uintmax_t) getppid());
- fprintf(rpt, " at %s\n", show_date(time(NULL), 0, DATE_LOCAL));
+ fprintf(rpt, " at %s\n", show_date(time(NULL), 0, DATE_MODE(ISO8601)));
fputc('\n', rpt);
fputs("fatal: ", rpt);
@@ -484,6 +489,7 @@ static void write_crash_report(const char *err)
fputs("-------------------\n", rpt);
fputs("END OF CRASH REPORT\n", rpt);
fclose(rpt);
+ free(loc);
}
static void end_packfile(void);
@@ -638,8 +644,9 @@ static void *pool_calloc(size_t count, size_t size)
static char *pool_strdup(const char *s)
{
- char *r = pool_alloc(strlen(s) + 1);
- strcpy(r, s);
+ size_t len = strlen(s) + 1;
+ char *r = pool_alloc(len);
+ memcpy(r, s, len);
return r;
}
@@ -696,7 +703,7 @@ static struct atom_str *to_atom(const char *s, unsigned short len)
c = pool_alloc(sizeof(struct atom_str) + len + 1);
c->str_len = len;
- strncpy(c->str_dat, s, len);
+ memcpy(c->str_dat, s, len);
c->str_dat[len] = 0;
c->next_atom = atom_table[hc];
atom_table[hc] = c;
@@ -857,13 +864,15 @@ static void start_packfile(void)
{
static char tmp_file[PATH_MAX];
struct packed_git *p;
+ int namelen;
struct pack_header hdr;
int pack_fd;
pack_fd = odb_mkstemp(tmp_file, sizeof(tmp_file),
"pack/tmp_pack_XXXXXX");
- p = xcalloc(1, sizeof(*p) + strlen(tmp_file) + 2);
- strcpy(p->pack_name, tmp_file);
+ namelen = strlen(tmp_file) + 2;
+ p = xcalloc(1, sizeof(*p) + namelen);
+ xsnprintf(p->pack_name, namelen, "%s", tmp_file);
p->pack_fd = pack_fd;
p->do_not_close = 1;
pack_file = sha1fd(pack_fd, p->pack_name);
@@ -877,7 +886,7 @@ static void start_packfile(void)
pack_size = sizeof(hdr);
object_count = 0;
- all_packs = xrealloc(all_packs, sizeof(*all_packs) * (pack_id + 1));
+ REALLOC_ARRAY(all_packs, pack_id + 1);
all_packs[pack_id] = p;
}
@@ -919,12 +928,12 @@ static char *keep_pack(const char *curr_index_name)
snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
get_object_directory(), sha1_to_hex(pack_data->sha1));
- if (move_temp_to_file(pack_data->pack_name, name))
+ if (finalize_object_file(pack_data->pack_name, name))
die("cannot store pack file");
snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
get_object_directory(), sha1_to_hex(pack_data->sha1));
- if (move_temp_to_file(curr_index_name, name))
+ if (finalize_object_file(curr_index_name, name))
die("cannot store index file");
free((void *)curr_index_name);
return name;
@@ -945,10 +954,15 @@ static void unkeep_all_packs(void)
static void end_packfile(void)
{
- struct packed_git *old_p = pack_data, *new_p;
+ static int running;
+ if (running || !pack_data)
+ return;
+
+ running = 1;
clear_delta_base_cache();
if (object_count) {
+ struct packed_git *new_p;
unsigned char cur_pack_sha1[20];
char *idx_name;
int i;
@@ -990,10 +1004,12 @@ static void end_packfile(void)
pack_id++;
}
else {
- close(old_p->pack_fd);
- unlink_or_warn(old_p->pack_name);
+ close(pack_data->pack_fd);
+ unlink_or_warn(pack_data->pack_name);
}
- free(old_p);
+ free(pack_data);
+ pack_data = NULL;
+ running = 0;
/* We can't carry a delta across packfiles. */
strbuf_release(&last_blob.data);
@@ -1022,8 +1038,8 @@ static int store_object(
git_SHA_CTX c;
git_zstream s;
- hdrlen = sprintf((char *)hdr,"%s %lu", typename(type),
- (unsigned long)dat->len) + 1;
+ hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu",
+ typename(type), (unsigned long)dat->len) + 1;
git_SHA1_Init(&c);
git_SHA1_Update(&c, hdr, hdrlen);
git_SHA1_Update(&c, dat->buf, dat->len);
@@ -1053,7 +1069,6 @@ static int store_object(
} else
delta = NULL;
- memset(&s, 0, sizeof(s));
git_deflate_init(&s, pack_compression_level);
if (delta) {
s.next_in = delta;
@@ -1081,7 +1096,6 @@ static int store_object(
free(delta);
delta = NULL;
- memset(&s, 0, sizeof(s));
git_deflate_init(&s, pack_compression_level);
s.next_in = (void *)dat->buf;
s.avail_in = dat->len;
@@ -1181,7 +1195,6 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
crc32_begin(pack_file);
- memset(&s, 0, sizeof(s));
git_deflate_init(&s, pack_compression_level);
hdrlen = encode_in_pack_object_header(OBJ_BLOB, len, out_buf);
@@ -1418,7 +1431,7 @@ static void mktree(struct tree_content *t, int v, struct strbuf *b)
static void store_tree(struct tree_entry *root)
{
- struct tree_content *t = root->tree;
+ struct tree_content *t;
unsigned int i, j, del;
struct last_object lo = { STRBUF_INIT, 0, 0, /* no_swap */ 1 };
struct object_entry *le = NULL;
@@ -1426,6 +1439,10 @@ static void store_tree(struct tree_entry *root)
if (!is_null_sha1(root->versions[1].sha1))
return;
+ if (!root->tree)
+ load_tree(root);
+ t = root->tree;
+
for (i = 0; i < t->entry_count; i++) {
if (t->entries[i]->tree)
store_tree(t->entries[i]);
@@ -1678,36 +1695,44 @@ found_entry:
static int update_branch(struct branch *b)
{
static const char *msg = "fast-import";
- struct ref_lock *lock;
+ struct ref_transaction *transaction;
unsigned char old_sha1[20];
+ struct strbuf err = STRBUF_INIT;
- if (is_null_sha1(b->sha1))
+ if (is_null_sha1(b->sha1)) {
+ if (b->delete)
+ delete_ref(b->name, NULL, 0);
return 0;
+ }
if (read_ref(b->name, old_sha1))
hashclr(old_sha1);
- lock = lock_any_ref_for_update(b->name, old_sha1, 0, NULL);
- if (!lock)
- return error("Unable to lock %s", b->name);
if (!force_update && !is_null_sha1(old_sha1)) {
struct commit *old_cmit, *new_cmit;
old_cmit = lookup_commit_reference_gently(old_sha1, 0);
new_cmit = lookup_commit_reference_gently(b->sha1, 0);
- if (!old_cmit || !new_cmit) {
- unlock_ref(lock);
+ if (!old_cmit || !new_cmit)
return error("Branch %s is missing commits.", b->name);
- }
if (!in_merge_bases(old_cmit, new_cmit)) {
- unlock_ref(lock);
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;
}
}
- if (write_ref_sha1(lock, b->sha1, msg) < 0)
- return error("Unable to update %s", b->name);
+ transaction = ref_transaction_begin(&err);
+ if (!transaction ||
+ ref_transaction_update(transaction, b->name, b->sha1, old_sha1,
+ 0, msg, &err) ||
+ ref_transaction_commit(transaction, &err)) {
+ ref_transaction_free(transaction);
+ error("%s", err.buf);
+ strbuf_release(&err);
+ return -1;
+ }
+ ref_transaction_free(transaction);
+ strbuf_release(&err);
return 0;
}
@@ -1726,15 +1751,32 @@ static void dump_tags(void)
{
static const char *msg = "fast-import";
struct tag *t;
- struct ref_lock *lock;
- char ref_name[PATH_MAX];
+ struct strbuf ref_name = STRBUF_INIT;
+ struct strbuf err = STRBUF_INIT;
+ struct ref_transaction *transaction;
+ transaction = ref_transaction_begin(&err);
+ if (!transaction) {
+ failure |= error("%s", err.buf);
+ goto cleanup;
+ }
for (t = first_tag; t; t = t->next_tag) {
- sprintf(ref_name, "tags/%s", t->name);
- lock = lock_ref_sha1(ref_name, NULL);
- if (!lock || write_ref_sha1(lock, t->sha1, msg) < 0)
- failure |= error("Unable to update %s", ref_name);
+ strbuf_reset(&ref_name);
+ strbuf_addf(&ref_name, "refs/tags/%s", t->name);
+
+ if (ref_transaction_update(transaction, ref_name.buf,
+ t->sha1, NULL, 0, msg, &err)) {
+ failure |= error("%s", err.buf);
+ goto cleanup;
+ }
}
+ if (ref_transaction_commit(transaction, &err))
+ failure |= error("%s", err.buf);
+
+ cleanup:
+ ref_transaction_free(transaction);
+ strbuf_release(&ref_name);
+ strbuf_release(&err);
}
static void dump_marks_helper(FILE *f,
@@ -1760,20 +1802,18 @@ static void dump_marks_helper(FILE *f,
static void dump_marks(void)
{
static struct lock_file mark_lock;
- int mark_fd;
FILE *f;
if (!export_marks_file)
return;
- mark_fd = hold_lock_file_for_update(&mark_lock, export_marks_file, 0);
- if (mark_fd < 0) {
+ if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) {
failure |= error("Unable to write marks file %s: %s",
export_marks_file, strerror(errno));
return;
}
- f = fdopen(mark_fd, "w");
+ f = fdopen_lock_file(&mark_lock, "w");
if (!f) {
int saved_errno = errno;
rollback_lock_file(&mark_lock);
@@ -1782,27 +1822,10 @@ static void dump_marks(void)
return;
}
- /*
- * Since the lock file was fdopen()'ed, it should not be close()'ed.
- * Assign -1 to the lock file descriptor so that commit_lock_file()
- * won't try to close() it.
- */
- mark_lock.fd = -1;
-
dump_marks_helper(f, 0, marks);
- if (ferror(f) || fclose(f)) {
- int saved_errno = errno;
- rollback_lock_file(&mark_lock);
- failure |= error("Unable to write marks file %s: %s",
- export_marks_file, strerror(saved_errno));
- return;
- }
-
if (commit_lock_file(&mark_lock)) {
- int saved_errno = errno;
- rollback_lock_file(&mark_lock);
- failure |= error("Unable to commit marks file %s: %s",
- export_marks_file, strerror(saved_errno));
+ failure |= error("Unable to write file %s: %s",
+ export_marks_file, strerror(errno));
return;
}
}
@@ -1857,6 +1880,8 @@ static int read_next_command(void)
}
for (;;) {
+ const char *p;
+
if (unread_command_buf) {
unread_command_buf = 0;
} else {
@@ -1889,8 +1914,12 @@ static int read_next_command(void)
rc->prev->next = rc;
cmd_tail = rc;
}
- if (starts_with(command_buf.buf, "cat-blob ")) {
- parse_cat_blob();
+ if (skip_prefix(command_buf.buf, "get-mark ", &p)) {
+ parse_get_mark(p);
+ continue;
+ }
+ if (skip_prefix(command_buf.buf, "cat-blob ", &p)) {
+ parse_cat_blob(p);
continue;
}
if (command_buf.buf[0] == '#')
@@ -1908,8 +1937,9 @@ static void skip_optional_lf(void)
static void parse_mark(void)
{
- if (starts_with(command_buf.buf, "mark :")) {
- next_mark = strtoumax(command_buf.buf + 6, NULL, 10);
+ const char *v;
+ if (skip_prefix(command_buf.buf, "mark :", &v)) {
+ next_mark = strtoumax(v, NULL, 10);
read_next_command();
}
else
@@ -1918,14 +1948,15 @@ static void parse_mark(void)
static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
{
+ const char *data;
strbuf_reset(sb);
- if (!starts_with(command_buf.buf, "data "))
+ if (!skip_prefix(command_buf.buf, "data ", &data))
die("Expected 'data n' command, found: %s", command_buf.buf);
- if (starts_with(command_buf.buf + 5, "<<")) {
- char *term = xstrdup(command_buf.buf + 5 + 2);
- size_t term_len = command_buf.len - 5 - 2;
+ if (skip_prefix(data, "<<", &data)) {
+ char *term = xstrdup(data);
+ size_t term_len = command_buf.len - (data - command_buf.buf);
strbuf_detach(&command_buf, NULL);
for (;;) {
@@ -1940,7 +1971,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
free(term);
}
else {
- uintmax_t len = strtoumax(command_buf.buf + 5, NULL, 10);
+ uintmax_t len = strtoumax(data, NULL, 10);
size_t n = 0, length = (size_t)len;
if (limit && limit < len) {
@@ -1963,7 +1994,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
return 1;
}
-static int validate_raw_date(const char *src, char *result, int maxlen)
+static int validate_raw_date(const char *src, struct strbuf *result)
{
const char *orig_src = src;
char *endp;
@@ -1981,11 +2012,10 @@ static int validate_raw_date(const char *src, char *result, int maxlen)
return -1;
num = strtoul(src + 1, &endp, 10);
- if (errno || endp == src + 1 || *endp || (endp - orig_src) >= maxlen ||
- 1400 < num)
+ if (errno || endp == src + 1 || *endp || 1400 < num)
return -1;
- strcpy(result, orig_src);
+ strbuf_addstr(result, orig_src);
return 0;
}
@@ -1993,7 +2023,7 @@ static char *parse_ident(const char *buf)
{
const char *ltgt;
size_t name_len;
- char *ident;
+ struct strbuf ident = STRBUF_INIT;
/* ensure there is a space delimiter even if there is no name */
if (*buf == '<')
@@ -2012,26 +2042,25 @@ static char *parse_ident(const char *buf)
die("Missing space after > in ident string: %s", buf);
ltgt++;
name_len = ltgt - buf;
- ident = xmalloc(name_len + 24);
- strncpy(ident, buf, name_len);
+ strbuf_add(&ident, buf, name_len);
switch (whenspec) {
case WHENSPEC_RAW:
- if (validate_raw_date(ltgt, ident + name_len, 24) < 0)
+ if (validate_raw_date(ltgt, &ident) < 0)
die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
break;
case WHENSPEC_RFC2822:
- if (parse_date(ltgt, ident + name_len, 24) < 0)
+ if (parse_date(ltgt, &ident) < 0)
die("Invalid rfc2822 date \"%s\" in ident: %s", ltgt, buf);
break;
case WHENSPEC_NOW:
if (strcmp("now", ltgt))
die("Date in ident must be 'now': %s", buf);
- datestamp(ident + name_len, 24);
+ datestamp(&ident);
break;
}
- return ident;
+ return strbuf_detach(&ident, NULL);
}
static void parse_and_store_blob(
@@ -2261,15 +2290,14 @@ static uintmax_t parse_mark_ref_space(const char **p)
char *end;
mark = parse_mark_ref(*p, &end);
- if (*end != ' ')
+ if (*end++ != ' ')
die("Missing space after mark: %s", command_buf.buf);
*p = end;
return mark;
}
-static void file_change_m(struct branch *b)
+static void file_change_m(const char *p, struct branch *b)
{
- const char *p = command_buf.buf + 2;
static struct strbuf uq = STRBUF_INIT;
const char *endp;
struct object_entry *oe;
@@ -2297,20 +2325,17 @@ static void file_change_m(struct branch *b)
if (*p == ':') {
oe = find_mark(parse_mark_ref_space(&p));
hashcpy(sha1, oe->idx.sha1);
- } else if (starts_with(p, "inline ")) {
+ } else if (skip_prefix(p, "inline ", &p)) {
inline_data = 1;
oe = NULL; /* not used with inline_data, but makes gcc happy */
- p += strlen("inline"); /* advance to space */
} else {
if (get_sha1_hex(p, sha1))
die("Invalid dataref: %s", command_buf.buf);
oe = find_object(sha1);
p += 40;
- if (*p != ' ')
+ if (*p++ != ' ')
die("Missing space after SHA1: %s", command_buf.buf);
}
- assert(*p == ' ');
- p++; /* skip space */
strbuf_reset(&uq);
if (!unquote_c_style(&uq, p, &endp)) {
@@ -2320,7 +2345,7 @@ static void file_change_m(struct branch *b)
}
/* Git does not track empty, non-toplevel directories. */
- if (S_ISDIR(mode) && !memcmp(sha1, EMPTY_TREE_SHA1_BIN, 20) && *p) {
+ if (S_ISDIR(mode) && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN) && *p) {
tree_content_remove(&b->branch_tree, p, NULL, 0);
return;
}
@@ -2370,9 +2395,8 @@ static void file_change_m(struct branch *b)
tree_content_set(&b->branch_tree, p, sha1, mode, NULL);
}
-static void file_change_d(struct branch *b)
+static void file_change_d(const char *p, struct branch *b)
{
- const char *p = command_buf.buf + 2;
static struct strbuf uq = STRBUF_INIT;
const char *endp;
@@ -2385,15 +2409,14 @@ static void file_change_d(struct branch *b)
tree_content_remove(&b->branch_tree, p, NULL, 1);
}
-static void file_change_cr(struct branch *b, int rename)
+static void file_change_cr(const char *s, struct branch *b, int rename)
{
- const char *s, *d;
+ const char *d;
static struct strbuf s_uq = STRBUF_INIT;
static struct strbuf d_uq = STRBUF_INIT;
const char *endp;
struct tree_entry leaf;
- s = command_buf.buf + 2;
strbuf_reset(&s_uq);
if (!unquote_c_style(&s_uq, s, &endp)) {
if (*endp != ' ')
@@ -2438,9 +2461,8 @@ static void file_change_cr(struct branch *b, int rename)
leaf.tree);
}
-static void note_change_n(struct branch *b, unsigned char *old_fanout)
+static void note_change_n(const char *p, struct branch *b, unsigned char *old_fanout)
{
- const char *p = command_buf.buf + 2;
static struct strbuf uq = STRBUF_INIT;
struct object_entry *oe;
struct branch *s;
@@ -2470,20 +2492,17 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout)
if (*p == ':') {
oe = find_mark(parse_mark_ref_space(&p));
hashcpy(sha1, oe->idx.sha1);
- } else if (starts_with(p, "inline ")) {
+ } else if (skip_prefix(p, "inline ", &p)) {
inline_data = 1;
oe = NULL; /* not used with inline_data, but makes gcc happy */
- p += strlen("inline"); /* advance to space */
} else {
if (get_sha1_hex(p, sha1))
die("Invalid dataref: %s", command_buf.buf);
oe = find_object(sha1);
p += 40;
- if (*p != ' ')
+ if (*p++ != ' ')
die("Missing space after SHA1: %s", command_buf.buf);
}
- assert(*p == ' ');
- p++; /* skip space */
/* <commit-ish> */
s = lookup_branch(p);
@@ -2580,16 +2599,13 @@ static int parse_from(struct branch *b)
{
const char *from;
struct branch *s;
+ unsigned char sha1[20];
- if (!starts_with(command_buf.buf, "from "))
+ if (!skip_prefix(command_buf.buf, "from ", &from))
return 0;
- if (b->branch_tree.tree) {
- release_tree_content_recursive(b->branch_tree.tree);
- b->branch_tree.tree = NULL;
- }
+ hashcpy(sha1, b->branch_tree.versions[1].sha1);
- from = strchr(command_buf.buf, ' ') + 1;
s = lookup_branch(from);
if (b == s)
die("Can't create a branch from itself: %s", b->name);
@@ -2603,19 +2619,29 @@ static int parse_from(struct branch *b)
struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", idnum);
- hashcpy(b->sha1, oe->idx.sha1);
- if (oe->pack_id != MAX_PACK_ID) {
- unsigned long size;
- char *buf = gfi_unpack_entry(oe, &size);
- parse_from_commit(b, buf, size);
- free(buf);
- } else
- parse_from_existing(b);
- } else if (!get_sha1(from, b->sha1))
+ if (hashcmp(b->sha1, oe->idx.sha1)) {
+ hashcpy(b->sha1, oe->idx.sha1);
+ if (oe->pack_id != MAX_PACK_ID) {
+ unsigned long size;
+ char *buf = gfi_unpack_entry(oe, &size);
+ parse_from_commit(b, buf, size);
+ free(buf);
+ } else
+ parse_from_existing(b);
+ }
+ } else if (!get_sha1(from, b->sha1)) {
parse_from_existing(b);
+ if (is_null_sha1(b->sha1))
+ b->delete = 1;
+ }
else
die("Invalid ref name or SHA1 expression: %s", from);
+ if (b->branch_tree.tree && hashcmp(sha1, b->branch_tree.versions[1].sha1)) {
+ release_tree_content_recursive(b->branch_tree.tree);
+ b->branch_tree.tree = NULL;
+ }
+
read_next_command();
return 1;
}
@@ -2627,8 +2653,7 @@ static struct hash_list *parse_merge(unsigned int *count)
struct branch *s;
*count = 0;
- while (starts_with(command_buf.buf, "merge ")) {
- from = strchr(command_buf.buf, ' ') + 1;
+ while (skip_prefix(command_buf.buf, "merge ", &from)) {
n = xmalloc(sizeof(*n));
s = lookup_branch(from);
if (s)
@@ -2659,31 +2684,29 @@ static struct hash_list *parse_merge(unsigned int *count)
return list;
}
-static void parse_new_commit(void)
+static void parse_new_commit(const char *arg)
{
static struct strbuf msg = STRBUF_INIT;
struct branch *b;
- char *sp;
char *author = NULL;
char *committer = NULL;
struct hash_list *merge_list = NULL;
unsigned int merge_count;
unsigned char prev_fanout, new_fanout;
+ const char *v;
- /* Obtain the branch name from the rest of our command */
- sp = strchr(command_buf.buf, ' ') + 1;
- b = lookup_branch(sp);
+ b = lookup_branch(arg);
if (!b)
- b = new_branch(sp);
+ b = new_branch(arg);
read_next_command();
parse_mark();
- if (starts_with(command_buf.buf, "author ")) {
- author = parse_ident(command_buf.buf + 7);
+ if (skip_prefix(command_buf.buf, "author ", &v)) {
+ author = parse_ident(v);
read_next_command();
}
- if (starts_with(command_buf.buf, "committer ")) {
- committer = parse_ident(command_buf.buf + 10);
+ if (skip_prefix(command_buf.buf, "committer ", &v)) {
+ committer = parse_ident(v);
read_next_command();
}
if (!committer)
@@ -2703,20 +2726,20 @@ static void parse_new_commit(void)
/* file_change* */
while (command_buf.len > 0) {
- if (starts_with(command_buf.buf, "M "))
- file_change_m(b);
- else if (starts_with(command_buf.buf, "D "))
- file_change_d(b);
- else if (starts_with(command_buf.buf, "R "))
- file_change_cr(b, 1);
- else if (starts_with(command_buf.buf, "C "))
- file_change_cr(b, 0);
- else if (starts_with(command_buf.buf, "N "))
- note_change_n(b, &prev_fanout);
+ if (skip_prefix(command_buf.buf, "M ", &v))
+ file_change_m(v, b);
+ else if (skip_prefix(command_buf.buf, "D ", &v))
+ file_change_d(v, b);
+ else if (skip_prefix(command_buf.buf, "R ", &v))
+ file_change_cr(v, b, 1);
+ else if (skip_prefix(command_buf.buf, "C ", &v))
+ file_change_cr(v, b, 0);
+ else if (skip_prefix(command_buf.buf, "N ", &v))
+ note_change_n(v, b, &prev_fanout);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
- else if (starts_with(command_buf.buf, "ls "))
- parse_ls(b);
+ else if (skip_prefix(command_buf.buf, "ls ", &v))
+ parse_ls(v, b);
else {
unread_command_buf = 1;
break;
@@ -2759,10 +2782,9 @@ static void parse_new_commit(void)
b->last_commit = object_count_by_type[OBJ_COMMIT];
}
-static void parse_new_tag(void)
+static void parse_new_tag(const char *arg)
{
static struct strbuf msg = STRBUF_INIT;
- char *sp;
const char *from;
char *tagger;
struct branch *s;
@@ -2770,12 +2792,11 @@ static void parse_new_tag(void)
uintmax_t from_mark = 0;
unsigned char sha1[20];
enum object_type type;
+ const char *v;
- /* Obtain the new tag name from the rest of our command */
- sp = strchr(command_buf.buf, ' ') + 1;
t = pool_alloc(sizeof(struct tag));
memset(t, 0, sizeof(struct tag));
- t->name = pool_strdup(sp);
+ t->name = pool_strdup(arg);
if (last_tag)
last_tag->next_tag = t;
else
@@ -2784,9 +2805,8 @@ static void parse_new_tag(void)
read_next_command();
/* from ... */
- if (!starts_with(command_buf.buf, "from "))
+ if (!skip_prefix(command_buf.buf, "from ", &from))
die("Expected from command, got %s", command_buf.buf);
- from = strchr(command_buf.buf, ' ') + 1;
s = lookup_branch(from);
if (s) {
if (is_null_sha1(s->sha1))
@@ -2812,8 +2832,8 @@ static void parse_new_tag(void)
read_next_command();
/* tagger ... */
- if (starts_with(command_buf.buf, "tagger ")) {
- tagger = parse_ident(command_buf.buf + 7);
+ if (skip_prefix(command_buf.buf, "tagger ", &v)) {
+ tagger = parse_ident(v);
read_next_command();
} else
tagger = NULL;
@@ -2842,14 +2862,11 @@ static void parse_new_tag(void)
t->pack_id = pack_id;
}
-static void parse_reset_branch(void)
+static void parse_reset_branch(const char *arg)
{
struct branch *b;
- char *sp;
- /* Obtain the branch name from the rest of our command */
- sp = strchr(command_buf.buf, ' ') + 1;
- b = lookup_branch(sp);
+ b = lookup_branch(arg);
if (b) {
hashclr(b->sha1);
hashclr(b->branch_tree.versions[0].sha1);
@@ -2860,7 +2877,7 @@ static void parse_reset_branch(void)
}
}
else
- b = new_branch(sp);
+ b = new_branch(arg);
read_next_command();
parse_from(b);
if (command_buf.len > 0)
@@ -2918,14 +2935,29 @@ static void cat_blob(struct object_entry *oe, unsigned char sha1[20])
free(buf);
}
-static void parse_cat_blob(void)
+static void parse_get_mark(const char *p)
+{
+ struct object_entry *oe = oe;
+ char output[42];
+
+ /* get-mark SP <object> LF */
+ if (*p != ':')
+ die("Not a mark: %s", p);
+
+ oe = find_mark(parse_mark_ref_eol(p));
+ if (!oe)
+ die("Unknown mark: %s", command_buf.buf);
+
+ snprintf(output, sizeof(output), "%s\n", sha1_to_hex(oe->idx.sha1));
+ cat_blob_write(output, 41);
+}
+
+static void parse_cat_blob(const char *p)
{
- const char *p;
struct object_entry *oe = oe;
unsigned char sha1[20];
/* cat-blob SP <object> LF */
- p = command_buf.buf + strlen("cat-blob ");
if (*p == ':') {
oe = find_mark(parse_mark_ref_eol(p));
if (!oe)
@@ -3008,6 +3040,8 @@ static struct object_entry *parse_treeish_dataref(const char **p)
die("Invalid dataref: %s", command_buf.buf);
e = find_object(sha1);
*p += 40;
+ if (*(*p)++ != ' ')
+ die("Missing space after tree-ish: %s", command_buf.buf);
}
while (!e || e->type != OBJ_TREE)
@@ -3042,14 +3076,12 @@ static void print_ls(int mode, const unsigned char *sha1, const char *path)
cat_blob_write(line.buf, line.len);
}
-static void parse_ls(struct branch *b)
+static void parse_ls(const char *p, struct branch *b)
{
- const char *p;
struct tree_entry *root = NULL;
struct tree_entry leaf = {NULL};
/* ls SP (<tree-ish> SP)? <path> */
- p = command_buf.buf + strlen("ls ");
if (*p == '"') {
if (!b)
die("Not in a commit: %s", command_buf.buf);
@@ -3061,8 +3093,6 @@ static void parse_ls(struct branch *b)
if (!is_null_sha1(root->versions[1].sha1))
root->versions[1].mode = S_IFDIR;
load_tree(root);
- if (*p++ != ' ')
- die("Missing space after tree-ish: %s", command_buf.buf);
}
if (*p == '"') {
static struct strbuf uq = STRBUF_INIT;
@@ -3116,12 +3146,9 @@ static void parse_progress(void)
static char* make_fast_import_path(const char *path)
{
- struct strbuf abs_path = STRBUF_INIT;
-
if (!relative_marks_paths || is_absolute_path(path))
return xstrdup(path);
- strbuf_addf(&abs_path, "%s/info/fast-import/%s", get_git_dir(), path);
- return strbuf_detach(&abs_path, NULL);
+ return xstrdup(git_path("info/fast-import/%s", path));
}
static void option_import_marks(const char *marks,
@@ -3200,9 +3227,9 @@ static void option_export_pack_edges(const char *edges)
static int parse_one_option(const char *option)
{
- if (starts_with(option, "max-pack-size=")) {
+ if (skip_prefix(option, "max-pack-size=", &option)) {
unsigned long v;
- if (!git_parse_ulong(option + 14, &v))
+ if (!git_parse_ulong(option, &v))
return 0;
if (v < 8192) {
warning("max-pack-size is now in bytes, assuming --max-pack-size=%lum", v);
@@ -3212,17 +3239,17 @@ static int parse_one_option(const char *option)
v = 1024 * 1024;
}
max_packsize = v;
- } else if (starts_with(option, "big-file-threshold=")) {
+ } else if (skip_prefix(option, "big-file-threshold=", &option)) {
unsigned long v;
- if (!git_parse_ulong(option + 19, &v))
+ if (!git_parse_ulong(option, &v))
return 0;
big_file_threshold = v;
- } else if (starts_with(option, "depth=")) {
- option_depth(option + 6);
- } else if (starts_with(option, "active-branches=")) {
- option_active_branches(option + 16);
- } else if (starts_with(option, "export-pack-edges=")) {
- option_export_pack_edges(option + 18);
+ } else if (skip_prefix(option, "depth=", &option)) {
+ option_depth(option);
+ } else if (skip_prefix(option, "active-branches=", &option)) {
+ option_active_branches(option);
+ } else if (skip_prefix(option, "export-pack-edges=", &option)) {
+ option_export_pack_edges(option);
} else if (starts_with(option, "quiet")) {
show_stats = 0;
} else if (starts_with(option, "stats")) {
@@ -3236,15 +3263,18 @@ static int parse_one_option(const char *option)
static int parse_one_feature(const char *feature, int from_stream)
{
- if (starts_with(feature, "date-format=")) {
- option_date_format(feature + 12);
- } else if (starts_with(feature, "import-marks=")) {
- option_import_marks(feature + 13, from_stream, 0);
- } else if (starts_with(feature, "import-marks-if-exists=")) {
- option_import_marks(feature + strlen("import-marks-if-exists="),
- from_stream, 1);
- } else if (starts_with(feature, "export-marks=")) {
- option_export_marks(feature + 13);
+ const char *arg;
+
+ if (skip_prefix(feature, "date-format=", &arg)) {
+ option_date_format(arg);
+ } else if (skip_prefix(feature, "import-marks=", &arg)) {
+ option_import_marks(arg, from_stream, 0);
+ } else if (skip_prefix(feature, "import-marks-if-exists=", &arg)) {
+ option_import_marks(arg, from_stream, 1);
+ } else if (skip_prefix(feature, "export-marks=", &arg)) {
+ option_export_marks(arg);
+ } else if (!strcmp(feature, "get-mark")) {
+ ; /* Don't die - this feature is supported */
} else if (!strcmp(feature, "cat-blob")) {
; /* Don't die - this feature is supported */
} else if (!strcmp(feature, "relative-marks")) {
@@ -3264,10 +3294,8 @@ static int parse_one_feature(const char *feature, int from_stream)
return 1;
}
-static void parse_feature(void)
+static void parse_feature(const char *feature)
{
- char *feature = command_buf.buf + 8;
-
if (seen_data_command)
die("Got feature command '%s' after data command", feature);
@@ -3277,10 +3305,8 @@ static void parse_feature(void)
die("This version of fast-import does not support feature %s.", feature);
}
-static void parse_option(void)
+static void parse_option(const char *option)
{
- char *option = command_buf.buf + 11;
-
if (seen_data_command)
die("Got option command '%s' after data command", option);
@@ -3290,36 +3316,34 @@ static void parse_option(void)
die("This version of fast-import does not support option: %s", option);
}
-static int git_pack_config(const char *k, const char *v, void *cb)
+static void git_pack_config(void)
{
- if (!strcmp(k, "pack.depth")) {
- max_depth = git_config_int(k, v);
+ int indexversion_value;
+ unsigned long packsizelimit_value;
+
+ if (!git_config_get_ulong("pack.depth", &max_depth)) {
if (max_depth > MAX_DEPTH)
max_depth = MAX_DEPTH;
- return 0;
}
- if (!strcmp(k, "pack.compression")) {
- int level = git_config_int(k, v);
- if (level == -1)
- level = Z_DEFAULT_COMPRESSION;
- else if (level < 0 || level > Z_BEST_COMPRESSION)
- die("bad pack compression level %d", level);
- pack_compression_level = level;
+ if (!git_config_get_int("pack.compression", &pack_compression_level)) {
+ if (pack_compression_level == -1)
+ pack_compression_level = Z_DEFAULT_COMPRESSION;
+ else if (pack_compression_level < 0 ||
+ pack_compression_level > Z_BEST_COMPRESSION)
+ git_die_config("pack.compression",
+ "bad pack compression level %d", pack_compression_level);
pack_compression_seen = 1;
- return 0;
}
- if (!strcmp(k, "pack.indexversion")) {
- pack_idx_opts.version = git_config_int(k, v);
+ if (!git_config_get_int("pack.indexversion", &indexversion_value)) {
+ pack_idx_opts.version = indexversion_value;
if (pack_idx_opts.version > 2)
- die("bad pack.indexversion=%"PRIu32,
- pack_idx_opts.version);
- return 0;
+ git_die_config("pack.indexversion",
+ "bad pack.indexversion=%"PRIu32, pack_idx_opts.version);
}
- if (!strcmp(k, "pack.packsizelimit")) {
- max_packsize = git_config_ulong(k, v);
- return 0;
- }
- return git_default_config(k, v, cb);
+ if (!git_config_get_ulong("pack.packsizelimit", &packsizelimit_value))
+ max_packsize = packsizelimit_value;
+
+ git_config(git_default_config, NULL);
}
static const char fast_import_usage[] =
@@ -3335,18 +3359,21 @@ static void parse_argv(void)
if (*a != '-' || !strcmp(a, "--"))
break;
- if (parse_one_option(a + 2))
+ if (!skip_prefix(a, "--", &a))
+ die("unknown option %s", a);
+
+ if (parse_one_option(a))
continue;
- if (parse_one_feature(a + 2, 0))
+ if (parse_one_feature(a, 0))
continue;
- if (starts_with(a + 2, "cat-blob-fd=")) {
- option_cat_blob_fd(a + 2 + strlen("cat-blob-fd="));
+ if (skip_prefix(a, "cat-blob-fd=", &a)) {
+ option_cat_blob_fd(a);
continue;
}
- die("unknown option %s", a);
+ die("unknown option --%s", a);
}
if (i != global_argc)
usage(fast_import_usage);
@@ -3369,7 +3396,7 @@ int main(int argc, char **argv)
setup_git_directory();
reset_pack_idx_option(&pack_idx_opts);
- git_config(git_pack_config, NULL);
+ git_pack_config();
if (!pack_compression_seen && core_compression_seen)
pack_compression_level = core_compression_level;
@@ -3393,26 +3420,27 @@ int main(int argc, char **argv)
set_die_routine(die_nicely);
set_checkpoint_signal();
while (read_next_command() != EOF) {
+ const char *v;
if (!strcmp("blob", command_buf.buf))
parse_new_blob();
- else if (starts_with(command_buf.buf, "ls "))
- parse_ls(NULL);
- else if (starts_with(command_buf.buf, "commit "))
- parse_new_commit();
- else if (starts_with(command_buf.buf, "tag "))
- parse_new_tag();
- else if (starts_with(command_buf.buf, "reset "))
- parse_reset_branch();
+ else if (skip_prefix(command_buf.buf, "ls ", &v))
+ parse_ls(v, NULL);
+ else if (skip_prefix(command_buf.buf, "commit ", &v))
+ parse_new_commit(v);
+ else if (skip_prefix(command_buf.buf, "tag ", &v))
+ parse_new_tag(v);
+ else if (skip_prefix(command_buf.buf, "reset ", &v))
+ parse_reset_branch(v);
else if (!strcmp("checkpoint", command_buf.buf))
parse_checkpoint();
else if (!strcmp("done", command_buf.buf))
break;
else if (starts_with(command_buf.buf, "progress "))
parse_progress();
- else if (starts_with(command_buf.buf, "feature "))
- parse_feature();
- else if (starts_with(command_buf.buf, "option git "))
- parse_option();
+ else if (skip_prefix(command_buf.buf, "feature ", &v))
+ parse_feature(v);
+ else if (skip_prefix(command_buf.buf, "option git ", &v))
+ parse_option(v);
else if (starts_with(command_buf.buf, "option "))
/* ignore non-git options*/;
else