]> git.ipfire.org Git - thirdparty/git.git/blobdiff - fast-import.c
is_ntfs_dotgit(): only verify the leading segment
[thirdparty/git.git] / fast-import.c
index a5b7685e845e7438a9c4d8c55ba09598b054e606..93c3838254931901109d6722feb844bf98e3b7b2 100644 (file)
@@ -366,6 +366,7 @@ static uintmax_t next_mark;
 static struct strbuf new_data = STRBUF_INIT;
 static int seen_data_command;
 static int require_explicit_termination;
+static int allow_unsafe_features;
 
 /* Signal handling */
 static volatile sig_atomic_t checkpoint_requested;
@@ -1861,6 +1862,12 @@ static void dump_marks(void)
        if (!export_marks_file || (import_marks_file && !import_marks_file_done))
                return;
 
+       if (safe_create_leading_directories_const(export_marks_file)) {
+               failure |= error_errno("unable to create leading directories of %s",
+                                      export_marks_file);
+               return;
+       }
+
        if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) {
                failure |= error_errno("Unable to write marks file %s",
                                       export_marks_file);
@@ -3268,7 +3275,6 @@ static void option_active_branches(const char *branches)
 static void option_export_marks(const char *marks)
 {
        export_marks_file = make_fast_import_path(marks);
-       safe_create_leading_directories_const(export_marks_file);
 }
 
 static void option_cat_blob_fd(const char *fd)
@@ -3315,6 +3321,8 @@ static int parse_one_option(const char *option)
                show_stats = 0;
        } else if (!strcmp(option, "stats")) {
                show_stats = 1;
+       } else if (!strcmp(option, "allow-unsafe-features")) {
+               ; /* already handled during early option parsing */
        } else {
                return 0;
        }
@@ -3322,6 +3330,13 @@ static int parse_one_option(const char *option)
        return 1;
 }
 
+static void check_unsafe_feature(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)
 {
        const char *arg;
@@ -3329,10 +3344,13 @@ static int parse_one_feature(const char *feature, int from_stream)
        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);
        } 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);
        } else if (skip_prefix(feature, "export-marks=", &arg)) {
+               check_unsafe_feature(feature, from_stream);
                option_export_marks(arg);
        } else if (!strcmp(feature, "get-mark")) {
                ; /* Don't die - this feature is supported */
@@ -3459,6 +3477,20 @@ int cmd_main(int argc, const char **argv)
        avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
        marks = pool_calloc(1, sizeof(struct mark_set));
 
+       /*
+        * We don't parse most options until after we've seen the set of
+        * "feature" lines at the start of the stream (which allows the command
+        * line to override stream data). But we must do an early parse of any
+        * command-line options that impact how we interpret the feature lines.
+        */
+       for (i = 1; i < argc; i++) {
+               const char *arg = argv[i];
+               if (*arg != '-' || !strcmp(arg, "--"))
+                       break;
+               if (!strcmp(arg, "--allow-unsafe-features"))
+                       allow_unsafe_features = 1;
+       }
+
        global_argc = argc;
        global_argv = argv;