Re: [RFC PATCH 09/10] submodule: support reading .gitmodules even when it's not checked out

2018-05-14 Thread Stefan Beller
On Mon, May 14, 2018 at 3:58 AM, Antonio Ospite  wrote:
> When the .gitmodules file is not available in the working directory, try
> using HEAD:.gitmodules from the index.

I think HEAD:.gitmodules is different than the index (the former is
part of the latest commit, whereas the index could have changed via
git-add, that is not committed yet).

> This covers the case when the
> file is part of the repository but for some reason it is not checked
> out, for example because of a sparse checkout.
>
> This makes it possible to use at least the 'git submodule' commands
> which *read* the gitmodules configuration file without fully populating
> the work dir.

Instead of checking for an explicit sparse "hidden" could we just rely on
the file missing? Then I could continue using submodules if I just
"rm .gitmodules".

>
> Writing to .gitmodules wills still require that the file is checked out,
> so check for that in config_gitmodules_set.

That makes sense!

>
> Signed-off-by: Antonio Ospite 
> ---
>
> I am doing the is_gitmodules_hidden() check in the open for now, I am not sure
> whether it is approprate to do that inside stage_updated_gitmodules.

Why do we need that check at all?

In your use case, you want to checkout *a* .gitmodules file, not necessarily
the .gitmodules file of that repo you're currently working on. So it
sort of makes
sense to prevent cross-repo changes (i.e. committing the .gitmodules
accidentally
into the wrong repo)

Stefan


[RFC PATCH 09/10] submodule: support reading .gitmodules even when it's not checked out

2018-05-14 Thread Antonio Ospite
When the .gitmodules file is not available in the working directory, try
using HEAD:.gitmodules from the index. This covers the case when the
file is part of the repository but for some reason it is not checked
out, for example because of a sparse checkout.

This makes it possible to use at least the 'git submodule' commands
which *read* the gitmodules configuration file without fully populating
the work dir.

Writing to .gitmodules wills still require that the file is checked out,
so check for that in config_gitmodules_set.

Signed-off-by: Antonio Ospite 
---

I am doing the is_gitmodules_hidden() check in the open for now, I am not sure
whether it is approprate to do that inside stage_updated_gitmodules.

 builtin/mv.c|  2 ++
 builtin/rm.c|  7 +--
 builtin/submodule--helper.c | 21 -
 cache.h |  1 +
 config.c| 15 +--
 submodule.c | 15 +++
 submodule.h |  1 +
 7 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/builtin/mv.c b/builtin/mv.c
index 7a63667d6..41fd9b7be 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -83,6 +83,8 @@ static void prepare_move_submodule(const char *src, int first,
die(_("Directory %s is in index and no submodule?"), src);
if (!is_staging_gitmodules_ok(_index))
die(_("Please stage your changes to .gitmodules or stash them 
to proceed"));
+   if (is_gitmodules_hidden(_index))
+   die(_("cannot work with hidden submodule config"));
strbuf_addf(_dotgit, "%s/.git", src);
*submodule_gitfile = read_gitfile(submodule_dotgit.buf);
if (*submodule_gitfile)
diff --git a/builtin/rm.c b/builtin/rm.c
index 5b6fc7ee8..e3526a342 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -284,9 +284,12 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
list.entry[list.nr].name = xstrdup(ce->name);
list.entry[list.nr].is_submodule = S_ISGITLINK(ce->ce_mode);
-   if (list.entry[list.nr++].is_submodule &&
-   !is_staging_gitmodules_ok(_index))
+   if (list.entry[list.nr++].is_submodule) {
+   if (!is_staging_gitmodules_ok(_index))
die (_("Please stage your changes to .gitmodules or 
stash them to proceed"));
+   if (is_gitmodules_hidden(_index))
+   die(_("cannot work with hidden submodule config"));
+   }
}
 
if (pathspec.nr) {
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index de5caa776..b3bdb4b66 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1873,6 +1873,9 @@ static int module_config(int argc, const char **argv, 
const char *prefix)
if (read_cache() < 0)
die(_("index file corrupt"));
 
+   if (is_gitmodules_hidden(_index))
+   die(_("cannot stage changes to hidden submodule 
config"));
+
stage_updated_gitmodules(_index);
 
if (write_locked_index(_index, _file,
@@ -1897,8 +1900,24 @@ static int module_config(int argc, const char **argv, 
const char *prefix)
}
 
/* Equivalent to ACTION_SET in builtin/config.c */
-   if (argc == 3)
+   if (argc == 3) {
+   struct object_id oid;
+
+   /* 
+* If the .gitmodules file is not in the work tree but it is
+* in the index, stop, as writing new values and staging them
+* would blindly overwrite ALL the old content.
+*
+* Do not use is_gitmodules_hidden() here, to gracefully
+* handle the case when .gitmodules is neither in the work
+* tree nor in the index, i.e.: a new GITMODULES_FILE is going
+* to be created.
+*/
+   if (!file_exists(GITMODULES_FILE) && get_oid(GITMODULES_BLOB, 
) >= 0)
+   die(_("cannot change unchecked out .gitmodules, check 
it out first"));
+
return config_gitmodules_set(argv[1], argv[2]);
+   }
 
return 0;
 }
diff --git a/cache.h b/cache.h
index 0c1fb9fbc..6d45b0cbb 100644
--- a/cache.h
+++ b/cache.h
@@ -417,6 +417,7 @@ static inline enum object_type object_type(unsigned int 
mode)
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
 #define GITMODULES_FILE ".gitmodules"
+#define GITMODULES_BLOB "HEAD:.gitmodules"
 #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
 #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
 #define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
diff --git a/config.c b/config.c
index 8ffe29330..7d9744622 100644
--- a/config.c
+++ b/config.c
@@ -2184,8 +2184,19 @@ int