Merge branch 'sr/gfi-options'
* sr/gfi-options: fast-import: add (non-)relative-marks feature fast-import: allow for multiple --import-marks= arguments fast-import: test the new option command fast-import: add option command fast-import: add feature command fast-import: put marks reading in its own function fast-import: put option parsing code in separate functions
This commit is contained in:
commit
fa232d457e
@ -75,6 +75,20 @@ OPTIONS
|
|||||||
set of marks. If a mark is defined to different values,
|
set of marks. If a mark is defined to different values,
|
||||||
the last file wins.
|
the last file wins.
|
||||||
|
|
||||||
|
--relative-marks::
|
||||||
|
After specifying --relative-marks= the paths specified
|
||||||
|
with --import-marks= and --export-marks= are relative
|
||||||
|
to an internal directory in the current repository.
|
||||||
|
In git-fast-import this means that the paths are relative
|
||||||
|
to the .git/info/fast-import directory. However, other
|
||||||
|
importers may use a different location.
|
||||||
|
|
||||||
|
--no-relative-marks::
|
||||||
|
Negates a previous --relative-marks. Allows for combining
|
||||||
|
relative and non-relative marks by interweaving
|
||||||
|
--(no-)-relative-marks= with the --(import|export)-marks=
|
||||||
|
options.
|
||||||
|
|
||||||
--export-pack-edges=<file>::
|
--export-pack-edges=<file>::
|
||||||
After creating a packfile, print a line of data to
|
After creating a packfile, print a line of data to
|
||||||
<file> listing the filename of the packfile and the last
|
<file> listing the filename of the packfile and the last
|
||||||
@ -303,6 +317,15 @@ and control the current import process. More detailed discussion
|
|||||||
standard output. This command is optional and is not needed
|
standard output. This command is optional and is not needed
|
||||||
to perform an import.
|
to perform an import.
|
||||||
|
|
||||||
|
`feature`::
|
||||||
|
Require that fast-import supports the specified feature, or
|
||||||
|
abort if it does not.
|
||||||
|
|
||||||
|
`option`::
|
||||||
|
Specify any of the options listed under OPTIONS that do not
|
||||||
|
change stream semantic to suit the frontend's needs. This
|
||||||
|
command is optional and is not needed to perform an import.
|
||||||
|
|
||||||
`commit`
|
`commit`
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
Create or update a branch with a new commit, recording one logical
|
Create or update a branch with a new commit, recording one logical
|
||||||
@ -846,6 +869,62 @@ Placing a `progress` command immediately after a `checkpoint` will
|
|||||||
inform the reader when the `checkpoint` has been completed and it
|
inform the reader when the `checkpoint` has been completed and it
|
||||||
can safely access the refs that fast-import updated.
|
can safely access the refs that fast-import updated.
|
||||||
|
|
||||||
|
`feature`
|
||||||
|
~~~~~~~~~
|
||||||
|
Require that fast-import supports the specified feature, or abort if
|
||||||
|
it does not.
|
||||||
|
|
||||||
|
....
|
||||||
|
'feature' SP <feature> LF
|
||||||
|
....
|
||||||
|
|
||||||
|
The <feature> part of the command may be any string matching
|
||||||
|
^[a-zA-Z][a-zA-Z-]*$ and should be understood by fast-import.
|
||||||
|
|
||||||
|
Feature work identical as their option counterparts with the
|
||||||
|
exception of the import-marks feature, see below.
|
||||||
|
|
||||||
|
The following features are currently supported:
|
||||||
|
|
||||||
|
* date-format
|
||||||
|
* import-marks
|
||||||
|
* export-marks
|
||||||
|
* relative-marks
|
||||||
|
* no-relative-marks
|
||||||
|
* force
|
||||||
|
|
||||||
|
The import-marks behaves differently from when it is specified as
|
||||||
|
commandline option in that only one "feature import-marks" is allowed
|
||||||
|
per stream. Also, any --import-marks= specified on the commandline
|
||||||
|
will override those from the stream (if any).
|
||||||
|
|
||||||
|
`option`
|
||||||
|
~~~~~~~~
|
||||||
|
Processes the specified option so that git fast-import behaves in a
|
||||||
|
way that suits the frontend's needs.
|
||||||
|
Note that options specified by the frontend are overridden by any
|
||||||
|
options the user may specify to git fast-import itself.
|
||||||
|
|
||||||
|
....
|
||||||
|
'option' SP <option> LF
|
||||||
|
....
|
||||||
|
|
||||||
|
The `<option>` part of the command may contain any of the options
|
||||||
|
listed in the OPTIONS section that do not change import semantics,
|
||||||
|
without the leading '--' and is treated in the same way.
|
||||||
|
|
||||||
|
Option commands must be the first commands on the input (not counting
|
||||||
|
feature commands), to give an option command after any non-option
|
||||||
|
command is an error.
|
||||||
|
|
||||||
|
The following commandline options change import semantics and may therefore
|
||||||
|
not be passed as option:
|
||||||
|
|
||||||
|
* date-format
|
||||||
|
* import-marks
|
||||||
|
* export-marks
|
||||||
|
* force
|
||||||
|
|
||||||
Crash Reports
|
Crash Reports
|
||||||
-------------
|
-------------
|
||||||
If fast-import is supplied invalid input it will terminate with a
|
If fast-import is supplied invalid input it will terminate with a
|
||||||
|
317
fast-import.c
317
fast-import.c
@ -295,6 +295,9 @@ static unsigned long branch_count;
|
|||||||
static unsigned long branch_load_count;
|
static unsigned long branch_load_count;
|
||||||
static int failure;
|
static int failure;
|
||||||
static FILE *pack_edges;
|
static FILE *pack_edges;
|
||||||
|
static unsigned int show_stats = 1;
|
||||||
|
static int global_argc;
|
||||||
|
static const char **global_argv;
|
||||||
|
|
||||||
/* Memory pools */
|
/* Memory pools */
|
||||||
static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
|
static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
|
||||||
@ -317,7 +320,10 @@ static unsigned int object_entry_alloc = 5000;
|
|||||||
static struct object_entry_pool *blocks;
|
static struct object_entry_pool *blocks;
|
||||||
static struct object_entry *object_table[1 << 16];
|
static struct object_entry *object_table[1 << 16];
|
||||||
static struct mark_set *marks;
|
static struct mark_set *marks;
|
||||||
static const char *mark_file;
|
static const char *export_marks_file;
|
||||||
|
static const char *import_marks_file;
|
||||||
|
static int import_marks_file_from_stream;
|
||||||
|
static int relative_marks_paths;
|
||||||
|
|
||||||
/* Our last blob */
|
/* Our last blob */
|
||||||
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
|
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
|
||||||
@ -351,6 +357,9 @@ static struct recent_command *rc_free;
|
|||||||
static unsigned int cmd_save = 100;
|
static unsigned int cmd_save = 100;
|
||||||
static uintmax_t next_mark;
|
static uintmax_t next_mark;
|
||||||
static struct strbuf new_data = STRBUF_INIT;
|
static struct strbuf new_data = STRBUF_INIT;
|
||||||
|
static int seen_data_command;
|
||||||
|
|
||||||
|
static void parse_argv(void);
|
||||||
|
|
||||||
static void write_branch_report(FILE *rpt, struct branch *b)
|
static void write_branch_report(FILE *rpt, struct branch *b)
|
||||||
{
|
{
|
||||||
@ -454,8 +463,8 @@ static void write_crash_report(const char *err)
|
|||||||
fputc('\n', rpt);
|
fputc('\n', rpt);
|
||||||
fputs("Marks\n", rpt);
|
fputs("Marks\n", rpt);
|
||||||
fputs("-----\n", rpt);
|
fputs("-----\n", rpt);
|
||||||
if (mark_file)
|
if (export_marks_file)
|
||||||
fprintf(rpt, " exported to %s\n", mark_file);
|
fprintf(rpt, " exported to %s\n", export_marks_file);
|
||||||
else
|
else
|
||||||
dump_marks_helper(rpt, 0, marks);
|
dump_marks_helper(rpt, 0, marks);
|
||||||
|
|
||||||
@ -1602,13 +1611,13 @@ static void dump_marks(void)
|
|||||||
int mark_fd;
|
int mark_fd;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
if (!mark_file)
|
if (!export_marks_file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mark_fd = hold_lock_file_for_update(&mark_lock, mark_file, 0);
|
mark_fd = hold_lock_file_for_update(&mark_lock, export_marks_file, 0);
|
||||||
if (mark_fd < 0) {
|
if (mark_fd < 0) {
|
||||||
failure |= error("Unable to write marks file %s: %s",
|
failure |= error("Unable to write marks file %s: %s",
|
||||||
mark_file, strerror(errno));
|
export_marks_file, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1617,7 +1626,7 @@ static void dump_marks(void)
|
|||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
rollback_lock_file(&mark_lock);
|
rollback_lock_file(&mark_lock);
|
||||||
failure |= error("Unable to write marks file %s: %s",
|
failure |= error("Unable to write marks file %s: %s",
|
||||||
mark_file, strerror(saved_errno));
|
export_marks_file, strerror(saved_errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1633,7 +1642,7 @@ static void dump_marks(void)
|
|||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
rollback_lock_file(&mark_lock);
|
rollback_lock_file(&mark_lock);
|
||||||
failure |= error("Unable to write marks file %s: %s",
|
failure |= error("Unable to write marks file %s: %s",
|
||||||
mark_file, strerror(saved_errno));
|
export_marks_file, strerror(saved_errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1641,11 +1650,47 @@ static void dump_marks(void)
|
|||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
rollback_lock_file(&mark_lock);
|
rollback_lock_file(&mark_lock);
|
||||||
failure |= error("Unable to commit marks file %s: %s",
|
failure |= error("Unable to commit marks file %s: %s",
|
||||||
mark_file, strerror(saved_errno));
|
export_marks_file, strerror(saved_errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void read_marks(void)
|
||||||
|
{
|
||||||
|
char line[512];
|
||||||
|
FILE *f = fopen(import_marks_file, "r");
|
||||||
|
if (!f)
|
||||||
|
die_errno("cannot read '%s'", import_marks_file);
|
||||||
|
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 int read_next_command(void)
|
static int read_next_command(void)
|
||||||
{
|
{
|
||||||
static int stdin_eof = 0;
|
static int stdin_eof = 0;
|
||||||
@ -1666,6 +1711,12 @@ static int read_next_command(void)
|
|||||||
if (stdin_eof)
|
if (stdin_eof)
|
||||||
return EOF;
|
return EOF;
|
||||||
|
|
||||||
|
if (!seen_data_command
|
||||||
|
&& prefixcmp(command_buf.buf, "feature ")
|
||||||
|
&& prefixcmp(command_buf.buf, "option ")) {
|
||||||
|
parse_argv();
|
||||||
|
}
|
||||||
|
|
||||||
rc = rc_free;
|
rc = rc_free;
|
||||||
if (rc)
|
if (rc)
|
||||||
rc_free = rc->next;
|
rc_free = rc->next;
|
||||||
@ -2420,39 +2471,140 @@ static void parse_progress(void)
|
|||||||
skip_optional_lf();
|
skip_optional_lf();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void import_marks(const char *input_file)
|
static char* make_fast_import_path(const char *path)
|
||||||
{
|
{
|
||||||
char line[512];
|
struct strbuf abs_path = STRBUF_INIT;
|
||||||
FILE *f = fopen(input_file, "r");
|
|
||||||
if (!f)
|
|
||||||
die_errno("cannot read '%s'", input_file);
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
|
||||||
uintmax_t mark;
|
|
||||||
char *end;
|
|
||||||
unsigned char sha1[20];
|
|
||||||
struct object_entry *e;
|
|
||||||
|
|
||||||
end = strchr(line, '\n');
|
if (!relative_marks_paths || is_absolute_path(path))
|
||||||
if (line[0] != ':' || !end)
|
return xstrdup(path);
|
||||||
die("corrupt mark line: %s", line);
|
strbuf_addf(&abs_path, "%s/info/fast-import/%s", get_git_dir(), path);
|
||||||
*end = 0;
|
return strbuf_detach(&abs_path, NULL);
|
||||||
mark = strtoumax(line + 1, &end, 10);
|
}
|
||||||
if (!mark || end == line + 1
|
|
||||||
|| *end != ' ' || get_sha1(end + 1, sha1))
|
static void option_import_marks(const char *marks, int from_stream)
|
||||||
die("corrupt mark line: %s", line);
|
{
|
||||||
e = find_object(sha1);
|
if (import_marks_file) {
|
||||||
if (!e) {
|
if (from_stream)
|
||||||
enum object_type type = sha1_object_info(sha1, NULL);
|
die("Only one import-marks command allowed per stream");
|
||||||
if (type < 0)
|
|
||||||
die("object not found: %s", sha1_to_hex(sha1));
|
/* read previous mark file */
|
||||||
e = insert_object(sha1);
|
if(!import_marks_file_from_stream)
|
||||||
e->type = type;
|
read_marks();
|
||||||
e->pack_id = MAX_PACK_ID;
|
|
||||||
e->offset = 1; /* just not zero! */
|
|
||||||
}
|
|
||||||
insert_mark(mark, e);
|
|
||||||
}
|
}
|
||||||
fclose(f);
|
|
||||||
|
import_marks_file = make_fast_import_path(marks);
|
||||||
|
import_marks_file_from_stream = from_stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void option_date_format(const char *fmt)
|
||||||
|
{
|
||||||
|
if (!strcmp(fmt, "raw"))
|
||||||
|
whenspec = WHENSPEC_RAW;
|
||||||
|
else if (!strcmp(fmt, "rfc2822"))
|
||||||
|
whenspec = WHENSPEC_RFC2822;
|
||||||
|
else if (!strcmp(fmt, "now"))
|
||||||
|
whenspec = WHENSPEC_NOW;
|
||||||
|
else
|
||||||
|
die("unknown --date-format argument %s", fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void option_max_pack_size(const char *packsize)
|
||||||
|
{
|
||||||
|
max_packsize = strtoumax(packsize, NULL, 0) * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void option_depth(const char *depth)
|
||||||
|
{
|
||||||
|
max_depth = strtoul(depth, NULL, 0);
|
||||||
|
if (max_depth > MAX_DEPTH)
|
||||||
|
die("--depth cannot exceed %u", MAX_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void option_active_branches(const char *branches)
|
||||||
|
{
|
||||||
|
max_active_branches = strtoul(branches, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void option_export_marks(const char *marks)
|
||||||
|
{
|
||||||
|
export_marks_file = make_fast_import_path(marks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void option_export_pack_edges(const char *edges)
|
||||||
|
{
|
||||||
|
if (pack_edges)
|
||||||
|
fclose(pack_edges);
|
||||||
|
pack_edges = fopen(edges, "a");
|
||||||
|
if (!pack_edges)
|
||||||
|
die_errno("Cannot open '%s'", edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_one_option(const char *option)
|
||||||
|
{
|
||||||
|
if (!prefixcmp(option, "max-pack-size=")) {
|
||||||
|
option_max_pack_size(option + 14);
|
||||||
|
} else if (!prefixcmp(option, "depth=")) {
|
||||||
|
option_depth(option + 6);
|
||||||
|
} else if (!prefixcmp(option, "active-branches=")) {
|
||||||
|
option_active_branches(option + 16);
|
||||||
|
} else if (!prefixcmp(option, "export-pack-edges=")) {
|
||||||
|
option_export_pack_edges(option + 18);
|
||||||
|
} else if (!prefixcmp(option, "quiet")) {
|
||||||
|
show_stats = 0;
|
||||||
|
} else if (!prefixcmp(option, "stats")) {
|
||||||
|
show_stats = 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_one_feature(const char *feature, int from_stream)
|
||||||
|
{
|
||||||
|
if (!prefixcmp(feature, "date-format=")) {
|
||||||
|
option_date_format(feature + 12);
|
||||||
|
} else if (!prefixcmp(feature, "import-marks=")) {
|
||||||
|
option_import_marks(feature + 13, from_stream);
|
||||||
|
} else if (!prefixcmp(feature, "export-marks=")) {
|
||||||
|
option_export_marks(feature + 13);
|
||||||
|
} else if (!prefixcmp(feature, "relative-marks")) {
|
||||||
|
relative_marks_paths = 1;
|
||||||
|
} else if (!prefixcmp(feature, "no-relative-marks")) {
|
||||||
|
relative_marks_paths = 0;
|
||||||
|
} else if (!prefixcmp(feature, "force")) {
|
||||||
|
force_update = 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_feature(void)
|
||||||
|
{
|
||||||
|
char *feature = command_buf.buf + 8;
|
||||||
|
|
||||||
|
if (seen_data_command)
|
||||||
|
die("Got feature command '%s' after data command", feature);
|
||||||
|
|
||||||
|
if (parse_one_feature(feature, 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
die("This version of fast-import does not support feature %s.", feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_option(void)
|
||||||
|
{
|
||||||
|
char *option = command_buf.buf + 11;
|
||||||
|
|
||||||
|
if (seen_data_command)
|
||||||
|
die("Got option command '%s' after data command", option);
|
||||||
|
|
||||||
|
if (parse_one_option(option))
|
||||||
|
return;
|
||||||
|
|
||||||
|
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 int git_pack_config(const char *k, const char *v, void *cb)
|
||||||
@ -2479,9 +2631,35 @@ static int git_pack_config(const char *k, const char *v, void *cb)
|
|||||||
static const char fast_import_usage[] =
|
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]";
|
"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
|
||||||
|
|
||||||
|
static void parse_argv(void)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 1; i < global_argc; i++) {
|
||||||
|
const char *a = global_argv[i];
|
||||||
|
|
||||||
|
if (*a != '-' || !strcmp(a, "--"))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (parse_one_option(a + 2))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (parse_one_feature(a + 2, 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
die("unknown option %s", a);
|
||||||
|
}
|
||||||
|
if (i != global_argc)
|
||||||
|
usage(fast_import_usage);
|
||||||
|
|
||||||
|
seen_data_command = 1;
|
||||||
|
if (import_marks_file)
|
||||||
|
read_marks();
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
unsigned int i, show_stats = 1;
|
unsigned int i;
|
||||||
|
|
||||||
git_extract_argv0_path(argv[0]);
|
git_extract_argv0_path(argv[0]);
|
||||||
|
|
||||||
@ -2500,52 +2678,8 @@ int main(int argc, const char **argv)
|
|||||||
avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
|
avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
|
||||||
marks = pool_calloc(1, sizeof(struct mark_set));
|
marks = pool_calloc(1, sizeof(struct mark_set));
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
global_argc = argc;
|
||||||
const char *a = argv[i];
|
global_argv = argv;
|
||||||
|
|
||||||
if (*a != '-' || !strcmp(a, "--"))
|
|
||||||
break;
|
|
||||||
else if (!prefixcmp(a, "--date-format=")) {
|
|
||||||
const char *fmt = a + 14;
|
|
||||||
if (!strcmp(fmt, "raw"))
|
|
||||||
whenspec = WHENSPEC_RAW;
|
|
||||||
else if (!strcmp(fmt, "rfc2822"))
|
|
||||||
whenspec = WHENSPEC_RFC2822;
|
|
||||||
else if (!strcmp(fmt, "now"))
|
|
||||||
whenspec = WHENSPEC_NOW;
|
|
||||||
else
|
|
||||||
die("unknown --date-format argument %s", fmt);
|
|
||||||
}
|
|
||||||
else if (!prefixcmp(a, "--max-pack-size="))
|
|
||||||
max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024;
|
|
||||||
else if (!prefixcmp(a, "--depth=")) {
|
|
||||||
max_depth = strtoul(a + 8, NULL, 0);
|
|
||||||
if (max_depth > MAX_DEPTH)
|
|
||||||
die("--depth cannot exceed %u", MAX_DEPTH);
|
|
||||||
}
|
|
||||||
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 (pack_edges)
|
|
||||||
fclose(pack_edges);
|
|
||||||
pack_edges = fopen(a + 20, "a");
|
|
||||||
if (!pack_edges)
|
|
||||||
die_errno("Cannot open '%s'", a + 20);
|
|
||||||
} else if (!strcmp(a, "--force"))
|
|
||||||
force_update = 1;
|
|
||||||
else if (!strcmp(a, "--quiet"))
|
|
||||||
show_stats = 0;
|
|
||||||
else if (!strcmp(a, "--stats"))
|
|
||||||
show_stats = 1;
|
|
||||||
else
|
|
||||||
die("unknown option %s", a);
|
|
||||||
}
|
|
||||||
if (i != argc)
|
|
||||||
usage(fast_import_usage);
|
|
||||||
|
|
||||||
rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
|
rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
|
||||||
for (i = 0; i < (cmd_save - 1); i++)
|
for (i = 0; i < (cmd_save - 1); i++)
|
||||||
@ -2568,9 +2702,20 @@ int main(int argc, const char **argv)
|
|||||||
parse_checkpoint();
|
parse_checkpoint();
|
||||||
else if (!prefixcmp(command_buf.buf, "progress "))
|
else if (!prefixcmp(command_buf.buf, "progress "))
|
||||||
parse_progress();
|
parse_progress();
|
||||||
|
else if (!prefixcmp(command_buf.buf, "feature "))
|
||||||
|
parse_feature();
|
||||||
|
else if (!prefixcmp(command_buf.buf, "option git "))
|
||||||
|
parse_option();
|
||||||
|
else if (!prefixcmp(command_buf.buf, "option "))
|
||||||
|
/* ignore non-git options*/;
|
||||||
else
|
else
|
||||||
die("Unsupported command: %s", command_buf.buf);
|
die("Unsupported command: %s", command_buf.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* argv hasn't been parsed yet, do so */
|
||||||
|
if (!seen_data_command)
|
||||||
|
parse_argv();
|
||||||
|
|
||||||
end_packfile();
|
end_packfile();
|
||||||
|
|
||||||
dump_branches();
|
dump_branches();
|
||||||
|
@ -1254,4 +1254,156 @@ test_expect_success \
|
|||||||
'Q: verify note for third commit' \
|
'Q: verify note for third commit' \
|
||||||
'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
|
'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
|
||||||
|
|
||||||
|
###
|
||||||
|
### series R (feature and option)
|
||||||
|
###
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
feature no-such-feature-exists
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: abort on unsupported feature' '
|
||||||
|
test_must_fail git fast-import <input
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
feature date-format=now
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: supported feature is accepted' '
|
||||||
|
git fast-import <input
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input << EOF
|
||||||
|
blob
|
||||||
|
data 3
|
||||||
|
hi
|
||||||
|
feature date-format=now
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: abort on receiving feature after data command' '
|
||||||
|
test_must_fail git fast-import <input
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input << EOF
|
||||||
|
feature import-marks=git.marks
|
||||||
|
feature import-marks=git2.marks
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: only one import-marks feature allowed per stream' '
|
||||||
|
test_must_fail git fast-import <input
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input << EOF
|
||||||
|
feature export-marks=git.marks
|
||||||
|
blob
|
||||||
|
mark :1
|
||||||
|
data 3
|
||||||
|
hi
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'R: export-marks feature results in a marks file being created' \
|
||||||
|
'cat input | git fast-import &&
|
||||||
|
grep :1 git.marks'
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'R: export-marks options can be overriden by commandline options' \
|
||||||
|
'cat input | git fast-import --export-marks=other.marks &&
|
||||||
|
grep :1 other.marks'
|
||||||
|
|
||||||
|
cat >input << EOF
|
||||||
|
feature import-marks=marks.out
|
||||||
|
feature export-marks=marks.new
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'R: import to output marks works without any content' \
|
||||||
|
'cat input | git fast-import &&
|
||||||
|
test_cmp marks.out marks.new'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
feature import-marks=nonexistant.marks
|
||||||
|
feature export-marks=marks.new
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'R: import marks prefers commandline marks file over the stream' \
|
||||||
|
'cat input | git fast-import --import-marks=marks.out &&
|
||||||
|
test_cmp marks.out marks.new'
|
||||||
|
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
feature import-marks=nonexistant.marks
|
||||||
|
feature export-marks=combined.marks
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: multiple --import-marks= should be honoured' '
|
||||||
|
head -n2 marks.out > one.marks &&
|
||||||
|
tail -n +3 marks.out > two.marks &&
|
||||||
|
git fast-import --import-marks=one.marks --import-marks=two.marks <input &&
|
||||||
|
test_cmp marks.out combined.marks
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
feature relative-marks
|
||||||
|
feature import-marks=relative.in
|
||||||
|
feature export-marks=relative.out
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: feature relative-marks should be honoured' '
|
||||||
|
mkdir -p .git/info/fast-import/ &&
|
||||||
|
cp marks.new .git/info/fast-import/relative.in &&
|
||||||
|
git fast-import <input &&
|
||||||
|
test_cmp marks.new .git/info/fast-import/relative.out
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
feature relative-marks
|
||||||
|
feature import-marks=relative.in
|
||||||
|
feature no-relative-marks
|
||||||
|
feature export-marks=non-relative.out
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: feature no-relative-marks should be honoured' '
|
||||||
|
git fast-import <input &&
|
||||||
|
test_cmp marks.new non-relative.out
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input << EOF
|
||||||
|
option git quiet
|
||||||
|
blob
|
||||||
|
data 3
|
||||||
|
hi
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
touch empty
|
||||||
|
|
||||||
|
test_expect_success 'R: quiet option results in no stats being output' '
|
||||||
|
cat input | git fast-import 2> output &&
|
||||||
|
test_cmp empty output
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
option git non-existing-option
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: die on unknown option' '
|
||||||
|
test_must_fail git fast-import <input
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'R: unknown commandline options are rejected' '\
|
||||||
|
test_must_fail git fast-import --non-existing-option < /dev/null
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
option non-existing-vcs non-existing-option
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'R: ignore non-git options' '
|
||||||
|
git fast-import <input
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user