static FILE *pack_edges;
static unsigned int show_stats = 1;
static unsigned int quiet;
-static int global_argc;
-static const char **global_argv;
-static const char *global_prefix;
-
static enum sign_mode signed_tag_mode = SIGN_VERBATIM;
static enum sign_mode signed_commit_mode = SIGN_VERBATIM;
static const char *signed_commit_keyid;
/* Where to write output of cat-blob commands */
static int cat_blob_fd = STDOUT_FILENO;
-static void parse_argv(void);
-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);
+/* Command state */
+struct fast_import_state {
+ int argc;
+ const char **argv;
+ const char *prefix;
+};
+
+static void fast_import_state_init(struct fast_import_state *state,
+ int argc, const char **argv,
+ const char *prefix)
+{
+ memset(state, 0, sizeof(*state));
+ state->argc = argc;
+ state->argv = argv;
+ state->prefix = prefix;
+}
+
+static void parse_argv(struct fast_import_state *state);
+static void parse_get_mark(struct fast_import_state *state, const char *p);
+static void parse_cat_blob(struct fast_import_state *state, const char *p);
+static void parse_ls(struct fast_import_state *state, const char *p, struct branch *b);
static void for_each_mark(struct mark_set *m, uintmax_t base, each_mark_fn_t callback, void *p)
{
}
-static int read_next_command(void)
+static int read_next_command(struct fast_import_state *state)
{
static int stdin_eof = 0;
if (!seen_data_command
&& !starts_with(command_buf.buf, "feature ")
&& !starts_with(command_buf.buf, "option ")) {
- parse_argv();
+ parse_argv(state);
}
rc = rc_free;
ungetc(term_char, stdin);
}
-static void parse_mark(void)
+static void parse_mark(struct fast_import_state *state)
{
const char *v;
if (skip_prefix(command_buf.buf, "mark :", &v)) {
next_mark = strtoumax(v, NULL, 10);
- read_next_command();
+ read_next_command(state);
}
else
next_mark = 0;
}
-static void parse_original_identifier(void)
+static void parse_original_identifier(struct fast_import_state *state)
{
const char *v;
if (skip_prefix(command_buf.buf, "original-oid ", &v))
- read_next_command();
+ read_next_command(state);
}
static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
}
}
-static void parse_new_blob(void)
+static void parse_new_blob(struct fast_import_state *state)
{
- read_next_command();
- parse_mark();
- parse_original_identifier();
+ read_next_command(state);
+ parse_mark(state);
+ parse_original_identifier(state);
parse_and_store_blob(&last_blob, NULL, next_mark);
}
(*endp)++;
}
-static void file_change_m(const char *p, struct branch *b)
+static void file_change_m(struct fast_import_state *state, const char *p, struct branch *b)
{
static struct strbuf path = STRBUF_INIT;
struct object_entry *oe;
if (S_ISDIR(mode))
die(_("directories cannot be specified 'inline': %s"),
command_buf.buf);
- while (read_next_command() != EOF) {
+ while (read_next_command(state) != EOF) {
const char *v;
if (skip_prefix(command_buf.buf, "cat-blob ", &v))
- parse_cat_blob(v);
+ parse_cat_blob(state, v);
else {
parse_and_store_blob(&last_blob, &oid, 0);
break;
leaf.tree);
}
-static void note_change_n(const char *p, struct branch *b, unsigned char *old_fanout)
+static void note_change_n(struct fast_import_state *state, const char *p, struct branch *b, unsigned char *old_fanout)
{
struct object_entry *oe;
struct branch *s;
die(_("invalid ref name or SHA1 expression: %s"), p);
if (inline_data) {
- read_next_command();
+ read_next_command(state);
parse_and_store_blob(&last_blob, &oid, 0);
} else if (oe) {
if (oe->type != OBJ_BLOB)
}
}
-static int parse_objectish(struct branch *b, const char *objectish)
+static int parse_objectish(struct fast_import_state *state, struct branch *b, const char *objectish)
{
struct branch *s;
struct object_id oid;
b->branch_tree.tree = NULL;
}
- read_next_command();
+ read_next_command(state);
return 1;
}
-static int parse_from(struct branch *b)
+static int parse_from(struct fast_import_state *state, struct branch *b)
{
const char *from;
if (!skip_prefix(command_buf.buf, "from ", &from))
return 0;
- return parse_objectish(b, from);
+ return parse_objectish(state, b, from);
}
-static int parse_objectish_with_prefix(struct branch *b, const char *prefix)
+static int parse_objectish_with_prefix(struct fast_import_state *state, struct branch *b, const char *prefix)
{
const char *base;
if (!skip_prefix(command_buf.buf, prefix, &base))
return 0;
- return parse_objectish(b, base);
+ return parse_objectish(state, b, base);
}
-static struct hash_list *parse_merge(unsigned int *count)
+static struct hash_list *parse_merge(struct fast_import_state *state, unsigned int *count)
{
struct hash_list *list = NULL, **tail = &list, *n;
const char *from;
tail = &n->next;
(*count)++;
- read_next_command();
+ read_next_command(state);
}
return list;
}
struct strbuf data; /* The actual signature data */
};
-static void parse_one_signature(struct signature_data *sig, const char *v)
+static void parse_one_signature(struct fast_import_state *state, struct signature_data *sig, const char *v)
{
char *args = xstrdup(v); /* Will be freed when sig->hash_algo is freed */
char *space = strchr(args, ' ');
warning(_("'unknown' signature format in gpgsig"));
/* Read signature data */
- read_next_command();
+ read_next_command(state);
parse_data(&sig->data, 0, NULL);
}
-static void discard_one_signature(void)
+static void discard_one_signature(struct fast_import_state *state)
{
struct strbuf data = STRBUF_INIT;
- read_next_command();
+ read_next_command(state);
parse_data(&data, 0, NULL);
strbuf_release(&data);
}
}
}
-static void import_one_signature(struct signature_data *sig_sha1,
+static void import_one_signature(struct fast_import_state *state,
+ struct signature_data *sig_sha1,
struct signature_data *sig_sha256,
const char *v)
{
struct signature_data sig = { NULL, NULL, STRBUF_INIT };
- parse_one_signature(&sig, v);
+ parse_one_signature(state, &sig, v);
if (!strcmp(sig.hash_algo, "sha1"))
store_signature(sig_sha1, &sig, "SHA-1");
strbuf_release(&tmp_buf);
}
-static void parse_new_commit(const char *arg)
+static void parse_new_commit(struct fast_import_state *state, const char *arg)
{
static struct strbuf msg = STRBUF_INIT;
struct signature_data sig_sha1 = { NULL, NULL, STRBUF_INIT };
if (!b)
b = new_branch(arg);
- read_next_command();
- parse_mark();
- parse_original_identifier();
+ read_next_command(state);
+ parse_mark(state);
+ parse_original_identifier(state);
if (skip_prefix(command_buf.buf, "author ", &v)) {
author = parse_ident(v);
- read_next_command();
+ read_next_command(state);
}
if (skip_prefix(command_buf.buf, "committer ", &v)) {
committer = parse_ident(v);
- read_next_command();
+ read_next_command(state);
}
if (!committer)
die(_("expected committer but didn't get one"));
warning(_("stripping a commit signature"));
/* fallthru */
case SIGN_STRIP:
- discard_one_signature();
+ discard_one_signature(state);
break;
/* Second, modes that parse the signature */
case SIGN_STRIP_IF_INVALID:
case SIGN_SIGN_IF_INVALID:
case SIGN_ABORT_IF_INVALID:
- import_one_signature(&sig_sha1, &sig_sha256, v);
+ import_one_signature(state, &sig_sha1, &sig_sha256, v);
break;
/* Third, BUG */
default:
BUG("invalid signed_commit_mode value %d", signed_commit_mode);
}
- read_next_command();
+ read_next_command(state);
}
if (skip_prefix(command_buf.buf, "encoding ", &v)) {
encoding = xstrdup(v);
- read_next_command();
+ read_next_command(state);
}
parse_data(&msg, 0, NULL);
- read_next_command();
- parse_from(b);
- merge_list = parse_merge(&merge_count);
+ read_next_command(state);
+ parse_from(state, b);
+ merge_list = parse_merge(state, &merge_count);
/* ensure the branch is active/loaded */
if (!b->branch_tree.tree || !max_active_branches) {
/* file_change* */
while (command_buf.len > 0) {
if (skip_prefix(command_buf.buf, "M ", &v))
- file_change_m(v, b);
+ file_change_m(state, 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))
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);
+ note_change_n(state, v, b, &prev_fanout);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
else if (skip_prefix(command_buf.buf, "ls ", &v))
- parse_ls(v, b);
+ parse_ls(state, v, b);
else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
- parse_cat_blob(v);
+ parse_cat_blob(state, v);
else {
unread_command_buf = 1;
break;
}
- if (read_next_command() == EOF)
+ if (read_next_command(state) == EOF)
break;
}
}
}
-static void parse_new_tag(const char *arg)
+static void parse_new_tag(struct fast_import_state *state, const char *arg)
{
static struct strbuf msg = STRBUF_INIT;
const char *from;
else
first_tag = t;
last_tag = t;
- read_next_command();
- parse_mark();
+ read_next_command(state);
+ parse_mark(state);
/* from ... */
if (!skip_prefix(command_buf.buf, "from ", &from))
type = oe->type;
} else
die(_("invalid ref name or SHA1 expression: %s"), from);
- read_next_command();
+ read_next_command(state);
/* original-oid ... */
- parse_original_identifier();
+ parse_original_identifier(state);
/* tagger ... */
if (skip_prefix(command_buf.buf, "tagger ", &v)) {
tagger = parse_ident(v);
- read_next_command();
+ read_next_command(state);
} else
tagger = NULL;
t->pack_id = pack_id;
}
-static void parse_reset_branch(const char *arg)
+static void parse_reset_branch(struct fast_import_state *state, const char *arg)
{
struct branch *b;
const char *tag_name;
}
else
b = new_branch(arg);
- read_next_command();
- parse_from(b);
+ read_next_command(state);
+ parse_from(state, b);
if (b->delete && skip_prefix(b->name, "refs/tags/", &tag_name)) {
/*
* Elsewhere, we call dump_branches() before dump_tags(),
free(buf);
}
-static void parse_get_mark(const char *p)
+static void parse_get_mark(struct fast_import_state *state UNUSED, const char *p)
{
struct object_entry *oe;
char output[GIT_MAX_HEXSZ + 2];
cat_blob_write(output, the_hash_algo->hexsz + 1);
}
-static void parse_cat_blob(const char *p)
+static void parse_cat_blob(struct fast_import_state *state UNUSED, const char *p)
{
struct object_entry *oe;
struct object_id oid;
cat_blob_write(line.buf, line.len);
}
-static void parse_ls(const char *p, struct branch *b)
+static void parse_ls(struct fast_import_state *state UNUSED, const char *p, struct branch *b)
{
static struct strbuf path = STRBUF_INIT;
struct tree_entry *root = NULL;
dump_marks();
}
-static void parse_checkpoint(void)
+static void parse_checkpoint(struct fast_import_state *state UNUSED)
{
checkpoint_requested = 1;
skip_optional_lf();
}
-static void parse_progress(void)
+static void parse_progress(struct fast_import_state *state UNUSED)
{
fwrite(command_buf.buf, 1, command_buf.len, stdout);
fputc('\n', stdout);
skip_optional_lf();
}
-static void parse_alias(void)
+static void parse_alias(struct fast_import_state *state)
{
struct object_entry *e;
struct branch b;
skip_optional_lf();
- read_next_command();
+ read_next_command(state);
/* mark ... */
- parse_mark();
+ parse_mark(state);
if (!next_mark)
die(_("expected 'mark' command, got %s"), command_buf.buf);
/* to ... */
memset(&b, 0, sizeof(b));
- if (!parse_objectish_with_prefix(&b, "to "))
+ if (!parse_objectish_with_prefix(state, &b, "to "))
die(_("expected 'to' command, got %s"), command_buf.buf);
e = find_object(&b.oid);
assert(e);
insert_mark(&marks, next_mark, e);
}
-static char* make_fast_import_path(const char *path)
+static char* make_fast_import_path(struct fast_import_state *state, const char *path)
{
if (!relative_marks_paths || is_absolute_path(path))
- return prefix_filename(global_prefix, path);
+ return prefix_filename(state->prefix, path);
return repo_git_path(the_repository, "info/fast-import/%s", path);
}
-static void option_import_marks(const char *marks,
+static void option_import_marks(struct fast_import_state *state, const char *marks,
int from_stream, int ignore_missing)
{
if (import_marks_file) {
}
free(import_marks_file);
- import_marks_file = make_fast_import_path(marks);
+ import_marks_file = make_fast_import_path(state, marks);
import_marks_file_from_stream = from_stream;
import_marks_file_ignore_missing = ignore_missing;
}
max_active_branches = ulong_arg("--active-branches", branches);
}
-static void option_export_marks(const char *marks)
+static void option_export_marks(struct fast_import_state *state, const char *marks)
{
free(export_marks_file);
- export_marks_file = make_fast_import_path(marks);
+ export_marks_file = make_fast_import_path(state, marks);
}
-static void option_cat_blob_fd(const char *fd)
+static void option_cat_blob_fd(struct fast_import_state *state UNUSED, const char *fd)
{
unsigned long n = ulong_arg("--cat-blob-fd", fd);
if (n > (unsigned long) INT_MAX)
cat_blob_fd = (int) n;
}
-static void option_export_pack_edges(const char *edges)
+static void option_export_pack_edges(struct fast_import_state *state, const char *edges)
{
- char *fn = prefix_filename(global_prefix, edges);
+ char *fn = prefix_filename(state->prefix, edges);
if (pack_edges)
fclose(pack_edges);
pack_edges = xfopen(fn, "a");
free(fn);
}
-static void option_rewrite_submodules(const char *arg, struct string_list *list)
+static void option_rewrite_submodules(struct fast_import_state *state, const char *arg, struct string_list *list)
{
struct mark_set *ms;
FILE *fp;
f++;
CALLOC_ARRAY(ms, 1);
- f = prefix_filename(global_prefix, f);
+ f = prefix_filename(state->prefix, f);
fp = fopen(f, "r");
if (!fp)
die_errno(_("cannot read '%s'"), f);
free(s);
}
-static int parse_one_option(const char *option)
+static int parse_one_option(struct fast_import_state *state, const char *option)
{
if (skip_prefix(option, "max-pack-size=", &option)) {
unsigned long v;
} 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);
+ option_export_pack_edges(state, option);
} else if (skip_prefix(option, "signed-commits=", &option)) {
if (parse_sign_mode(option, &signed_commit_mode, &signed_commit_keyid))
usagef(_("unknown --signed-commits mode '%s'"), option);
return 1;
}
-static void check_unsafe_feature(const char *feature, int from_stream)
+static void check_unsafe_feature(struct fast_import_state *state UNUSED, const char *feature, int from_stream)
{
if (from_stream && !allow_unsafe_features)
die(_("feature '%s' forbidden in input without --allow-unsafe-features"),
feature);
}
-static int parse_one_feature(const char *feature, int from_stream)
+static int parse_one_feature(struct fast_import_state *state, const char *feature, int from_stream)
{
const char *arg;
if (skip_prefix(feature, "date-format=", &arg)) {
option_date_format(arg);
} else if (skip_prefix(feature, "import-marks=", &arg)) {
- check_unsafe_feature("import-marks", from_stream);
- option_import_marks(arg, from_stream, 0);
+ check_unsafe_feature(state, "import-marks", from_stream);
+ option_import_marks(state, arg, from_stream, 0);
} else if (skip_prefix(feature, "import-marks-if-exists=", &arg)) {
- check_unsafe_feature("import-marks-if-exists", from_stream);
- option_import_marks(arg, from_stream, 1);
+ check_unsafe_feature(state, "import-marks-if-exists", from_stream);
+ option_import_marks(state, arg, from_stream, 1);
} else if (skip_prefix(feature, "export-marks=", &arg)) {
- check_unsafe_feature(feature, from_stream);
- option_export_marks(arg);
+ check_unsafe_feature(state, feature, from_stream);
+ option_export_marks(state, arg);
} else if (!strcmp(feature, "alias")) {
; /* Don't die - this feature is supported */
} else if (skip_prefix(feature, "rewrite-submodules-to=", &arg)) {
- option_rewrite_submodules(arg, &sub_marks_to);
+ option_rewrite_submodules(state, arg, &sub_marks_to);
} else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
- option_rewrite_submodules(arg, &sub_marks_from);
+ option_rewrite_submodules(state, arg, &sub_marks_from);
} else if (!strcmp(feature, "get-mark")) {
; /* Don't die - this feature is supported */
} else if (!strcmp(feature, "cat-blob")) {
return 1;
}
-static void parse_feature(const char *feature)
+static void parse_feature(struct fast_import_state *state, const char *feature)
{
if (seen_data_command)
die(_("got feature command '%s' after data command"), feature);
- if (parse_one_feature(feature, 1))
+ if (parse_one_feature(state, feature, 1))
return;
die(_("this version of fast-import does not support feature %s."), feature);
}
-static void parse_option(const char *option)
+static void parse_option(struct fast_import_state *state, const char *option)
{
if (seen_data_command)
die(_("got option command '%s' after data command"), option);
- if (parse_one_option(option))
+ if (parse_one_option(state, option))
return;
die(_("this version of fast-import does not support option: %s"), option);
static const char fast_import_usage[] =
"git fast-import [--date-format=<f>] [--max-pack-size=<n>] [--big-file-threshold=<n>] [--depth=<n>] [--active-branches=<n>] [--export-marks=<marks.file>]";
-static void parse_argv(void)
+static void parse_argv(struct fast_import_state *state)
{
unsigned int i;
- for (i = 1; i < global_argc; i++) {
- const char *a = global_argv[i];
+ for (i = 1; i < state->argc; i++) {
+ const char *a = state->argv[i];
if (*a != '-' || !strcmp(a, "--"))
break;
if (!skip_prefix(a, "--", &a))
die(_("unknown option %s"), a);
- if (parse_one_option(a))
+ if (parse_one_option(state, a))
continue;
- if (parse_one_feature(a, 0))
+ if (parse_one_feature(state, a, 0))
continue;
if (skip_prefix(a, "cat-blob-fd=", &a)) {
- option_cat_blob_fd(a);
+ option_cat_blob_fd(state, a);
continue;
}
die(_("unknown option --%s"), a);
}
- if (i != global_argc)
+ if (i != state->argc)
usage(fast_import_usage);
seen_data_command = 1;
const char *prefix,
struct repository *repo)
{
+ struct fast_import_state state;
+
show_usage_if_asked(argc, argv, fast_import_usage);
reset_pack_idx_option(&pack_idx_opts);
allow_unsafe_features = 1;
}
- global_argc = argc;
- global_argv = argv;
- global_prefix = prefix;
+ fast_import_state_init(&state, argc, argv, prefix);
rc_free = mem_pool_alloc(&fi_mem_pool, cmd_save * sizeof(*rc_free));
for (unsigned int i = 0; i < (cmd_save - 1); i++)
start_packfile();
set_die_routine(die_nicely);
set_checkpoint_signal();
- while (read_next_command() != EOF) {
+ while (read_next_command(&state) != EOF) {
const char *v;
if (!strcmp("blob", command_buf.buf))
- parse_new_blob();
+ parse_new_blob(&state);
else if (skip_prefix(command_buf.buf, "commit ", &v))
- parse_new_commit(v);
+ parse_new_commit(&state, v);
else if (skip_prefix(command_buf.buf, "tag ", &v))
- parse_new_tag(v);
+ parse_new_tag(&state, v);
else if (skip_prefix(command_buf.buf, "reset ", &v))
- parse_reset_branch(v);
+ parse_reset_branch(&state, v);
else if (skip_prefix(command_buf.buf, "ls ", &v))
- parse_ls(v, NULL);
+ parse_ls(&state, v, NULL);
else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
- parse_cat_blob(v);
+ parse_cat_blob(&state, v);
else if (skip_prefix(command_buf.buf, "get-mark ", &v))
- parse_get_mark(v);
+ parse_get_mark(&state, v);
else if (!strcmp("checkpoint", command_buf.buf))
- parse_checkpoint();
+ parse_checkpoint(&state);
else if (!strcmp("done", command_buf.buf))
break;
else if (!strcmp("alias", command_buf.buf))
- parse_alias();
+ parse_alias(&state);
else if (starts_with(command_buf.buf, "progress "))
- parse_progress();
+ parse_progress(&state);
else if (skip_prefix(command_buf.buf, "feature ", &v))
- parse_feature(v);
+ parse_feature(&state, v);
else if (skip_prefix(command_buf.buf, "option git ", &v))
- parse_option(v);
+ parse_option(&state, v);
else if (starts_with(command_buf.buf, "option "))
/* ignore non-git options*/;
else
/* argv hasn't been parsed yet, do so */
if (!seen_data_command)
- parse_argv();
+ parse_argv(&state);
if (require_explicit_termination && feof(stdin))
die(_("stream ends early"));