submodule: support reading .gitmodules when it's not in the working tree
[gitweb.git] / submodule.c
index 293efc2a2f5130bd86b5546398d3a22630b6f311..2b7082b2dbba735d81998dd4a31b1dbe9ab6b14f 100644 (file)
@@ -50,6 +50,24 @@ int is_gitmodules_unmerged(const struct index_state *istate)
        return 0;
 }
 
+/*
+ * Check if the .gitmodules file is safe to write.
+ *
+ * Writing to the .gitmodules file requires that the file exists in the
+ * working tree or, if it doesn't, that a brand new .gitmodules file is going
+ * to be created (i.e. it's neither in the index nor in the current branch).
+ *
+ * It is not safe to write to .gitmodules if it's not in the working tree but
+ * it is in the index or in the current branch, because writing new values
+ * (and staging them) would blindly overwrite ALL the old content.
+ */
+int is_writing_gitmodules_ok(void)
+{
+       struct object_id oid;
+       return file_exists(GITMODULES_FILE) ||
+               (get_oid(GITMODULES_INDEX, &oid) < 0 && get_oid(GITMODULES_HEAD, &oid) < 0);
+}
+
 /*
  * Check if the .gitmodules file has unstaged modifications.  This must be
  * checked before allowing modifications to the .gitmodules file with the
@@ -89,11 +107,12 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
 {
        struct strbuf entry = STRBUF_INIT;
        const struct submodule *submodule;
+       int ret;
 
        if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
                return -1;
 
-       if (is_gitmodules_unmerged(&the_index))
+       if (is_gitmodules_unmerged(the_repository->index))
                die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
 
        submodule = submodule_from_path(the_repository, &null_oid, oldpath);
@@ -104,14 +123,9 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
        strbuf_addstr(&entry, "submodule.");
        strbuf_addstr(&entry, submodule->name);
        strbuf_addstr(&entry, ".path");
-       if (git_config_set_in_file_gently(GITMODULES_FILE, entry.buf, newpath) < 0) {
-               /* Maybe the user already did that, don't error out here */
-               warning(_("Could not update .gitmodules entry %s"), entry.buf);
-               strbuf_release(&entry);
-               return -1;
-       }
+       ret = config_set_in_gitmodules_file_gently(entry.buf, newpath);
        strbuf_release(&entry);
-       return 0;
+       return ret;
 }
 
 /*
@@ -127,7 +141,7 @@ int remove_path_from_gitmodules(const char *path)
        if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
                return -1;
 
-       if (is_gitmodules_unmerged(&the_index))
+       if (is_gitmodules_unmerged(the_repository->index))
                die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
 
        submodule = submodule_from_path(the_repository, &null_oid, path);
@@ -188,7 +202,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 
                if (ignore)
                        handle_ignore_submodules_arg(diffopt, ignore);
-               else if (is_gitmodules_unmerged(&the_index))
+               else if (is_gitmodules_unmerged(the_repository->index))
                        diffopt->flags.ignore_submodules = 1;
        }
 }
@@ -258,7 +272,7 @@ int is_submodule_active(struct repository *repo, const char *path)
                }
 
                parse_pathspec(&ps, 0, 0, NULL, args.argv);
-               ret = match_pathspec(&the_index, &ps, path, strlen(path), 0, NULL, 1);
+               ret = match_pathspec(repo->index, &ps, path, strlen(path), 0, NULL, 1);
 
                argv_array_clear(&args);
                clear_pathspec(&ps);
@@ -1534,18 +1548,6 @@ int bad_to_remove_submodule(const char *path, unsigned flags)
        return ret;
 }
 
-void submodule_unset_core_worktree(const struct submodule *sub)
-{
-       char *config_path = xstrfmt("%s/modules/%s/config",
-                                   get_git_common_dir(), sub->name);
-
-       if (git_config_set_in_file_gently(config_path, "core.worktree", NULL))
-               warning(_("Could not unset core.worktree setting in submodule '%s'"),
-                         sub->path);
-
-       free(config_path);
-}
-
 static const char *get_super_prefix_or_empty(void)
 {
        const char *s = get_super_prefix();
@@ -1711,8 +1713,6 @@ int submodule_move_head(const char *path,
 
                        if (is_empty_dir(path))
                                rmdir_or_warn(path);
-
-                       submodule_unset_core_worktree(sub);
                }
        }
 out: