git: make super-prefix option
authorBrandon Williams <bmwill@google.com>
Fri, 7 Oct 2016 18:18:48 +0000 (11:18 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Oct 2016 19:14:58 +0000 (12:14 -0700)
Add a super-prefix environment variable 'GIT_INTERNAL_SUPER_PREFIX'
which can be used to specify a path from above a repository down to its
root. When such a super-prefix is specified, the paths reported by Git
are prefixed with it to make them relative to that directory "above".
The paths given by the user on the command line
(e.g. "git subcmd --output-file=path/to/a/file" and pathspecs) are taken
relative to the directory "above" to match.

The immediate use of this option is by commands which have a
--recurse-submodule option in order to give context to submodules about
how they were invoked. This option is currently only allowed for
builtins which support a super-prefix.

Signed-off-by: Brandon Williams <bmwill@google.com>
Reviewed-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git.txt
cache.h
environment.c
git.c
index 7913fc2513234ddf6f3f2f7e9e9543a2b698aa00..2188ae605668492fe607720ada4a732350e0f4f0 100644 (file)
@@ -13,6 +13,7 @@ SYNOPSIS
     [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
     [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
     [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
+    [--super-prefix=<path>]
     <command> [<args>]
 
 DESCRIPTION
@@ -601,6 +602,11 @@ foo.bar= ...`) sets `foo.bar` to the empty string.
        details.  Equivalent to setting the `GIT_NAMESPACE` environment
        variable.
 
+--super-prefix=<path>::
+       Currently for internal use only.  Set a prefix which gives a path from
+       above a repository down to its root.  One use is to give submodules
+       context about the superproject that invoked it.
+
 --bare::
        Treat the repository as a bare repository.  If GIT_DIR
        environment is not set, it is set to the current working
diff --git a/cache.h b/cache.h
index 35563266bf54c49cb9e2ae1efbed7a26fbca3519..8cf495db75914f68666fe7efcc0135b8788efcdd 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -408,6 +408,7 @@ static inline enum object_type object_type(unsigned int mode)
 #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
 #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
 #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
+#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX"
 #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
 #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
 #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
@@ -468,6 +469,7 @@ extern int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
 extern int get_common_dir(struct strbuf *sb, const char *gitdir);
 extern const char *get_git_namespace(void);
 extern const char *strip_namespace(const char *namespaced_ref);
+extern const char *get_super_prefix(void);
 extern const char *get_git_work_tree(void);
 
 /*
index ca72464a985021e58b898bb0b1f9af6c4a5282ac..d12d7db20a555251d5789dc4f1067c267b6ebea7 100644 (file)
@@ -100,6 +100,8 @@ static char *work_tree;
 static const char *namespace;
 static size_t namespace_len;
 
+static const char *super_prefix;
+
 static const char *git_dir, *git_common_dir;
 static char *git_object_dir, *git_index_file, *git_graft_file;
 int git_db_env, git_index_env, git_graft_env, git_common_dir_env;
@@ -120,6 +122,7 @@ const char * const local_repo_env[] = {
        NO_REPLACE_OBJECTS_ENVIRONMENT,
        GIT_REPLACE_REF_BASE_ENVIRONMENT,
        GIT_PREFIX_ENVIRONMENT,
+       GIT_SUPER_PREFIX_ENVIRONMENT,
        GIT_SHALLOW_FILE_ENVIRONMENT,
        GIT_COMMON_DIR_ENVIRONMENT,
        NULL
@@ -222,6 +225,16 @@ const char *strip_namespace(const char *namespaced_ref)
        return namespaced_ref + namespace_len;
 }
 
+const char *get_super_prefix(void)
+{
+       static int initialized;
+       if (!initialized) {
+               super_prefix = getenv(GIT_SUPER_PREFIX_ENVIRONMENT);
+               initialized = 1;
+       }
+       return super_prefix;
+}
+
 static int git_work_tree_initialized;
 
 /*
diff --git a/git.c b/git.c
index 1c61151758531889e2a2e60e66799283240dc89a..469a83f2b42ce74dba640c8ceef93a1b6f4c76c9 100644 (file)
--- a/git.c
+++ b/git.c
@@ -164,6 +164,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
                        setenv(GIT_WORK_TREE_ENVIRONMENT, cmd, 1);
                        if (envchanged)
                                *envchanged = 1;
+               } else if (!strcmp(cmd, "--super-prefix")) {
+                       if (*argc < 2) {
+                               fprintf(stderr, "No prefix given for --super-prefix.\n" );
+                               usage(git_usage_string);
+                       }
+                       setenv(GIT_SUPER_PREFIX_ENVIRONMENT, (*argv)[1], 1);
+                       if (envchanged)
+                               *envchanged = 1;
+                       (*argv)++;
+                       (*argc)--;
+               } else if (skip_prefix(cmd, "--super-prefix=", &cmd)) {
+                       setenv(GIT_SUPER_PREFIX_ENVIRONMENT, cmd, 1);
+                       if (envchanged)
+                               *envchanged = 1;
                } else if (!strcmp(cmd, "--bare")) {
                        char *cwd = xgetcwd();
                        is_bare_repository_cfg = 1;
@@ -310,6 +324,7 @@ static int handle_alias(int *argcp, const char ***argv)
  * RUN_SETUP for reading from the configuration file.
  */
 #define NEED_WORK_TREE         (1<<3)
+#define SUPPORT_SUPER_PREFIX   (1<<4)
 
 struct cmd_struct {
        const char *cmd;
@@ -344,6 +359,13 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
        }
        commit_pager_choice();
 
+       if (!help && get_super_prefix()) {
+               if (!(p->option & SUPPORT_SUPER_PREFIX))
+                       die("%s doesn't support --super-prefix", p->cmd);
+               if (prefix)
+                       die("can't use --super-prefix from a subdirectory");
+       }
+
        if (!help && p->option & NEED_WORK_TREE)
                setup_work_tree();
 
@@ -558,6 +580,9 @@ static void execv_dashed_external(const char **argv)
        const char *tmp;
        int status;
 
+       if (get_super_prefix())
+               die("%s doesn't support --super-prefix", argv[0]);
+
        if (use_pager == -1)
                use_pager = check_pager_config(argv[0]);
        commit_pager_choice();