Merge branch 'bw/push-submodule-only'
authorJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:14:56 +0000 (13:14 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:14:56 +0000 (13:14 -0800)
"git submodule push" learned "--recurse-submodules=only option to
push submodules out without pushing the top-level superproject.

* bw/push-submodule-only:
push: add option to push only submodules
submodules: add RECURSE_SUBMODULES_ONLY value
transport: reformat flag #defines to be more readable

1  2 
builtin/push.c
submodule-config.c
submodule.h
transport.c
transport.h
diff --combined builtin/push.c
index 9307ad56a9fb91455eaf06371382b1431d115598,9433797539c4fe09375dbee0906263a58e3c28cf..5c22e9f2e56b7d8049890e44f4c6fb63b16f8357
@@@ -194,18 -194,15 +194,18 @@@ static void setup_push_upstream(struct 
                        die_push_simple(branch, remote);
        }
  
 -      strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
 +      strbuf_addf(&refspec, "%s:%s", branch->refname, branch->merge[0]->src);
        add_refspec(refspec.buf);
  }
  
  static void setup_push_current(struct remote *remote, struct branch *branch)
  {
 +      struct strbuf refspec = STRBUF_INIT;
 +
        if (!branch)
                die(_(message_detached_head_die), remote->name);
 -      add_refspec(branch->name);
 +      strbuf_addf(&refspec, "%s:%s", branch->refname, branch->refname);
 +      add_refspec(refspec.buf);
  }
  
  static int is_workflow_triangular(struct remote *remote)
@@@ -568,6 -565,8 +568,8 @@@ int cmd_push(int argc, const char **arg
                flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
        else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
                flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;
+       else if (recurse_submodules == RECURSE_SUBMODULES_ONLY)
+               flags |= TRANSPORT_RECURSE_SUBMODULES_ONLY;
  
        if (tags)
                add_refspec("refs/tags/*");
diff --combined submodule-config.c
index 4bf50f398a5bd705531e32f9329c0e3b7e630506,33eb62d31aa2364d417bd386beb913192e6dc002..93453909cf3225e2b4b9630d4013f76987ca8be8
@@@ -251,6 -251,8 +251,8 @@@ static int parse_push_recurse(const cha
                        return RECURSE_SUBMODULES_ON_DEMAND;
                else if (!strcmp(arg, "check"))
                        return RECURSE_SUBMODULES_CHECK;
+               else if (!strcmp(arg, "only"))
+                       return RECURSE_SUBMODULES_ONLY;
                else if (die_on_error)
                        die("bad %s argument: %s", opt, arg);
                else
@@@ -263,12 -265,12 +265,12 @@@ int parse_push_recurse_submodules_arg(c
        return parse_push_recurse(opt, arg, 1);
  }
  
 -static void warn_multiple_config(const unsigned char *commit_sha1,
 +static void warn_multiple_config(const unsigned char *treeish_name,
                                 const char *name, const char *option)
  {
        const char *commit_string = "WORKTREE";
 -      if (commit_sha1)
 -              commit_string = sha1_to_hex(commit_sha1);
 +      if (treeish_name)
 +              commit_string = sha1_to_hex(treeish_name);
        warning("%s:.gitmodules, multiple configurations found for "
                        "'submodule.%s.%s'. Skipping second one!",
                        commit_string, name, option);
  
  struct parse_config_parameter {
        struct submodule_cache *cache;
 -      const unsigned char *commit_sha1;
 +      const unsigned char *treeish_name;
        const unsigned char *gitmodules_sha1;
        int overwrite;
  };
@@@ -300,7 -302,7 +302,7 @@@ static int parse_config(const char *var
                if (!value)
                        ret = config_error_nonbool(var);
                else if (!me->overwrite && submodule->path)
 -                      warn_multiple_config(me->commit_sha1, submodule->name,
 +                      warn_multiple_config(me->treeish_name, submodule->name,
                                        "path");
                else {
                        if (submodule->path)
                int die_on_error = is_null_sha1(me->gitmodules_sha1);
                if (!me->overwrite &&
                    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)
 -                      warn_multiple_config(me->commit_sha1, submodule->name,
 +                      warn_multiple_config(me->treeish_name, submodule->name,
                                        "fetchrecursesubmodules");
                else
                        submodule->fetch_recurse = parse_fetch_recurse(
                if (!value)
                        ret = config_error_nonbool(var);
                else if (!me->overwrite && submodule->ignore)
 -                      warn_multiple_config(me->commit_sha1, submodule->name,
 +                      warn_multiple_config(me->treeish_name, submodule->name,
                                        "ignore");
                else if (strcmp(value, "untracked") &&
                         strcmp(value, "dirty") &&
                if (!value) {
                        ret = config_error_nonbool(var);
                } else if (!me->overwrite && submodule->url) {
 -                      warn_multiple_config(me->commit_sha1, submodule->name,
 +                      warn_multiple_config(me->treeish_name, submodule->name,
                                        "url");
                } else {
                        free((void *) submodule->url);
                        ret = config_error_nonbool(var);
                else if (!me->overwrite &&
                         submodule->update_strategy.type != SM_UPDATE_UNSPECIFIED)
 -                      warn_multiple_config(me->commit_sha1, submodule->name,
 +                      warn_multiple_config(me->treeish_name, submodule->name,
                                             "update");
                else if (parse_submodule_update_strategy(value,
                         &submodule->update_strategy) < 0)
                                die(_("invalid value for %s"), var);
        } else if (!strcmp(item.buf, "shallow")) {
                if (!me->overwrite && submodule->recommend_shallow != -1)
 -                      warn_multiple_config(me->commit_sha1, submodule->name,
 +                      warn_multiple_config(me->treeish_name, submodule->name,
                                             "shallow");
                else
                        submodule->recommend_shallow =
                                git_config_bool(var, value);
        } else if (!strcmp(item.buf, "branch")) {
                if (!me->overwrite && submodule->branch)
 -                      warn_multiple_config(me->commit_sha1, submodule->name,
 +                      warn_multiple_config(me->treeish_name, submodule->name,
                                             "branch");
                else {
                        free((void *)submodule->branch);
        return ret;
  }
  
 -static int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
 +int gitmodule_sha1_from_commit(const unsigned char *treeish_name,
                                      unsigned char *gitmodules_sha1,
                                      struct strbuf *rev)
  {
        int ret = 0;
  
 -      if (is_null_sha1(commit_sha1)) {
 +      if (is_null_sha1(treeish_name)) {
                hashclr(gitmodules_sha1);
                return 1;
        }
  
 -      strbuf_addf(rev, "%s:.gitmodules", sha1_to_hex(commit_sha1));
 +      strbuf_addf(rev, "%s:.gitmodules", sha1_to_hex(treeish_name));
        if (get_sha1(rev->buf, gitmodules_sha1) >= 0)
                ret = 1;
  
   * revisions.
   */
  static const struct submodule *config_from(struct submodule_cache *cache,
 -              const unsigned char *commit_sha1, const char *key,
 +              const unsigned char *treeish_name, const char *key,
                enum lookup_type lookup_type)
  {
        struct strbuf rev = STRBUF_INIT;
         * return the first submodule. Can be used to check whether
         * there are any submodules parsed.
         */
 -      if (!commit_sha1 || !key) {
 +      if (!treeish_name || !key) {
                struct hashmap_iter iter;
                struct submodule_entry *entry;
  
                return entry->config;
        }
  
 -      if (!gitmodule_sha1_from_commit(commit_sha1, sha1, &rev))
 +      if (!gitmodule_sha1_from_commit(treeish_name, sha1, &rev))
                goto out;
  
        switch (lookup_type) {
  
        /* fill the submodule config into the cache */
        parameter.cache = cache;
 -      parameter.commit_sha1 = commit_sha1;
 +      parameter.treeish_name = treeish_name;
        parameter.gitmodules_sha1 = sha1;
        parameter.overwrite = 0;
        git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
@@@ -471,6 -473,18 +473,6 @@@ out
        return submodule;
  }
  
 -static const struct submodule *config_from_path(struct submodule_cache *cache,
 -              const unsigned char *commit_sha1, const char *path)
 -{
 -      return config_from(cache, commit_sha1, path, lookup_path);
 -}
 -
 -static const struct submodule *config_from_name(struct submodule_cache *cache,
 -              const unsigned char *commit_sha1, const char *name)
 -{
 -      return config_from(cache, commit_sha1, name, lookup_name);
 -}
 -
  static void ensure_cache_init(void)
  {
        if (is_cache_init)
@@@ -484,7 -498,7 +486,7 @@@ int parse_submodule_config_option(cons
  {
        struct parse_config_parameter parameter;
        parameter.cache = &the_submodule_cache;
 -      parameter.commit_sha1 = NULL;
 +      parameter.treeish_name = NULL;
        parameter.gitmodules_sha1 = null_sha1;
        parameter.overwrite = 1;
  
        return parse_config(var, value, &parameter);
  }
  
 -const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
 +const struct submodule *submodule_from_name(const unsigned char *treeish_name,
                const char *name)
  {
        ensure_cache_init();
 -      return config_from_name(&the_submodule_cache, commit_sha1, name);
 +      return config_from(&the_submodule_cache, treeish_name, name, lookup_name);
  }
  
 -const struct submodule *submodule_from_path(const unsigned char *commit_sha1,
 +const struct submodule *submodule_from_path(const unsigned char *treeish_name,
                const char *path)
  {
        ensure_cache_init();
 -      return config_from_path(&the_submodule_cache, commit_sha1, path);
 +      return config_from(&the_submodule_cache, treeish_name, path, lookup_path);
  }
  
  void submodule_free(void)
diff --combined submodule.h
index b7fe4d20279dfe165338dc412595fe1ccf6ad73c,4a83a4c8dffcb9e6c2348425fb7b62d6018cccd2..05ab674f069282b3d5b20ca69d9a1fe8f295879b
@@@ -6,6 -6,7 +6,7 @@@ struct argv_array
  struct sha1_array;
  
  enum {
+       RECURSE_SUBMODULES_ONLY = -5,
        RECURSE_SUBMODULES_CHECK = -4,
        RECURSE_SUBMODULES_ERROR = -3,
        RECURSE_SUBMODULES_NONE = -2,
@@@ -30,66 -31,52 +31,66 @@@ struct submodule_update_strategy 
  };
  #define SUBMODULE_UPDATE_STRATEGY_INIT {SM_UPDATE_UNSPECIFIED, NULL}
  
 -int is_staging_gitmodules_ok(void);
 -int update_path_in_gitmodules(const char *oldpath, const char *newpath);
 -int remove_path_from_gitmodules(const char *path);
 -void stage_updated_gitmodules(void);
 -void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 +extern int is_staging_gitmodules_ok(void);
 +extern int update_path_in_gitmodules(const char *oldpath, const char *newpath);
 +extern int remove_path_from_gitmodules(const char *path);
 +extern void stage_updated_gitmodules(void);
 +extern void set_diffopt_flags_from_submodule_config(struct diff_options *,
                const char *path);
 -int submodule_config(const char *var, const char *value, void *cb);
 -void gitmodules_config(void);
 -int parse_submodule_update_strategy(const char *value,
 +extern int submodule_config(const char *var, const char *value, void *cb);
 +extern void gitmodules_config(void);
 +extern void gitmodules_config_sha1(const unsigned char *commit_sha1);
 +extern int is_submodule_initialized(const char *path);
 +extern int is_submodule_populated(const char *path);
 +extern int parse_submodule_update_strategy(const char *value,
                struct submodule_update_strategy *dst);
 -const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
 -void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
 -void show_submodule_summary(FILE *f, const char *path,
 +extern const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
 +extern void handle_ignore_submodules_arg(struct diff_options *, const char *);
 +extern void show_submodule_summary(FILE *f, const char *path,
                const char *line_prefix,
                struct object_id *one, struct object_id *two,
                unsigned dirty_submodule, const char *meta,
                const char *del, const char *add, const char *reset);
 -void show_submodule_inline_diff(FILE *f, const char *path,
 +extern void show_submodule_inline_diff(FILE *f, const char *path,
                const char *line_prefix,
                struct object_id *one, struct object_id *two,
                unsigned dirty_submodule, const char *meta,
                const char *del, const char *add, const char *reset,
                const struct diff_options *opt);
 -void set_config_fetch_recurse_submodules(int value);
 -void check_for_new_submodule_commits(unsigned char new_sha1[20]);
 -int fetch_populated_submodules(const struct argv_array *options,
 +extern void set_config_fetch_recurse_submodules(int value);
 +extern void check_for_new_submodule_commits(unsigned char new_sha1[20]);
 +extern int fetch_populated_submodules(const struct argv_array *options,
                               const char *prefix, int command_line_option,
                               int quiet, int max_parallel_jobs);
 -unsigned is_submodule_modified(const char *path, int ignore_untracked);
 -int submodule_uses_gitfile(const char *path);
 -int ok_to_remove_submodule(const char *path);
 -int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
 -                  const unsigned char a[20], const unsigned char b[20], int search);
 -int find_unpushed_submodules(struct sha1_array *commits, const char *remotes_name,
 -              struct string_list *needs_pushing);
 +extern unsigned is_submodule_modified(const char *path, int ignore_untracked);
 +extern int submodule_uses_gitfile(const char *path);
 +
 +#define SUBMODULE_REMOVAL_DIE_ON_ERROR (1<<0)
 +#define SUBMODULE_REMOVAL_IGNORE_UNTRACKED (1<<1)
 +#define SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED (1<<2)
 +extern int bad_to_remove_submodule(const char *path, unsigned flags);
 +extern int merge_submodule(unsigned char result[20], const char *path,
 +                         const unsigned char base[20],
 +                         const unsigned char a[20],
 +                         const unsigned char b[20], int search);
 +extern int find_unpushed_submodules(struct sha1_array *commits,
 +                                  const char *remotes_name,
 +                                  struct string_list *needs_pushing);
  extern int push_unpushed_submodules(struct sha1_array *commits,
                                    const char *remotes_name,
                                    int dry_run);
 -void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
 -int parallel_submodules(void);
 +extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
 +extern int parallel_submodules(void);
  
  /*
   * Prepare the "env_array" parameter of a "struct child_process" for executing
   * a submodule by clearing any repo-specific envirionment variables, but
   * retaining any config in the environment.
   */
 -void prepare_submodule_repo_env(struct argv_array *out);
 +extern void prepare_submodule_repo_env(struct argv_array *out);
  
 +#define ABSORB_GITDIR_RECURSE_SUBMODULES (1<<0)
 +extern void absorb_git_dir_into_superproject(const char *prefix,
 +                                           const char *path,
 +                                           unsigned flags);
  #endif
diff --combined transport.c
index c86ba2eb897f4ee2e45dadd418587ee4cb76401e,20ebee84c34009873506a523b2a49d4d03daa8bc..d72e0894840fc384d67339b549a9a6bce7ba03ec
@@@ -664,89 -664,21 +664,89 @@@ static const struct string_list *protoc
        return enabled ? &allowed : NULL;
  }
  
 -int is_transport_allowed(const char *type)
 +enum protocol_allow_config {
 +      PROTOCOL_ALLOW_NEVER = 0,
 +      PROTOCOL_ALLOW_USER_ONLY,
 +      PROTOCOL_ALLOW_ALWAYS
 +};
 +
 +static enum protocol_allow_config parse_protocol_config(const char *key,
 +                                                      const char *value)
  {
 -      const struct string_list *allowed = protocol_whitelist();
 -      return !allowed || string_list_has_string(allowed, type);
 +      if (!strcasecmp(value, "always"))
 +              return PROTOCOL_ALLOW_ALWAYS;
 +      else if (!strcasecmp(value, "never"))
 +              return PROTOCOL_ALLOW_NEVER;
 +      else if (!strcasecmp(value, "user"))
 +              return PROTOCOL_ALLOW_USER_ONLY;
 +
 +      die("unknown value for config '%s': %s", key, value);
  }
  
 -void transport_check_allowed(const char *type)
 +static enum protocol_allow_config get_protocol_config(const char *type)
  {
 -      if (!is_transport_allowed(type))
 -              die("transport '%s' not allowed", type);
 +      char *key = xstrfmt("protocol.%s.allow", type);
 +      char *value;
 +
 +      /* first check the per-protocol config */
 +      if (!git_config_get_string(key, &value)) {
 +              enum protocol_allow_config ret =
 +                      parse_protocol_config(key, value);
 +              free(key);
 +              free(value);
 +              return ret;
 +      }
 +      free(key);
 +
 +      /* if defined, fallback to user-defined default for unknown protocols */
 +      if (!git_config_get_string("protocol.allow", &value)) {
 +              enum protocol_allow_config ret =
 +                      parse_protocol_config("protocol.allow", value);
 +              free(value);
 +              return ret;
 +      }
 +
 +      /* fallback to built-in defaults */
 +      /* known safe */
 +      if (!strcmp(type, "http") ||
 +          !strcmp(type, "https") ||
 +          !strcmp(type, "git") ||
 +          !strcmp(type, "ssh") ||
 +          !strcmp(type, "file"))
 +              return PROTOCOL_ALLOW_ALWAYS;
 +
 +      /* known scary; err on the side of caution */
 +      if (!strcmp(type, "ext"))
 +              return PROTOCOL_ALLOW_NEVER;
 +
 +      /* unknown; by default let them be used only directly by the user */
 +      return PROTOCOL_ALLOW_USER_ONLY;
  }
  
 -int transport_restrict_protocols(void)
 +int is_transport_allowed(const char *type, int from_user)
  {
 -      return !!protocol_whitelist();
 +      const struct string_list *whitelist = protocol_whitelist();
 +      if (whitelist)
 +              return string_list_has_string(whitelist, type);
 +
 +      switch (get_protocol_config(type)) {
 +      case PROTOCOL_ALLOW_ALWAYS:
 +              return 1;
 +      case PROTOCOL_ALLOW_NEVER:
 +              return 0;
 +      case PROTOCOL_ALLOW_USER_ONLY:
 +              if (from_user < 0)
 +                      from_user = git_env_bool("GIT_PROTOCOL_FROM_USER", 1);
 +              return from_user;
 +      }
 +
 +      die("BUG: invalid protocol_allow_config type");
 +}
 +
 +void transport_check_allowed(const char *type)
 +{
 +      if (!is_transport_allowed(type, -1))
 +              die("transport '%s' not allowed", type);
  }
  
  struct transport *transport_get(struct remote *remote, const char *url)
@@@ -1015,7 -947,9 +1015,9 @@@ int transport_push(struct transport *tr
                        if (run_pre_push_hook(transport, remote_refs))
                                return -1;
  
-               if ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) && !is_bare_repository()) {
+               if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
+                             TRANSPORT_RECURSE_SUBMODULES_ONLY)) &&
+                   !is_bare_repository()) {
                        struct ref *ref = remote_refs;
                        struct sha1_array commits = SHA1_ARRAY_INIT;
  
                }
  
                if (((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) ||
-                    ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) &&
+                    ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
+                               TRANSPORT_RECURSE_SUBMODULES_ONLY)) &&
                      !pretend)) && !is_bare_repository()) {
                        struct ref *ref = remote_refs;
                        struct string_list needs_pushing = STRING_LIST_INIT_DUP;
                        sha1_array_clear(&commits);
                }
  
-               push_ret = transport->push_refs(transport, remote_refs, flags);
+               if (!(flags & TRANSPORT_RECURSE_SUBMODULES_ONLY))
+                       push_ret = transport->push_refs(transport, remote_refs, flags);
+               else
+                       push_ret = 0;
                err = push_had_errors(remote_refs);
                ret = push_ret | err;
  
                if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
                        set_upstreams(transport, remote_refs, pretend);
  
-               if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
+               if (!(flags & (TRANSPORT_PUSH_DRY_RUN |
+                              TRANSPORT_RECURSE_SUBMODULES_ONLY))) {
                        struct ref *ref;
                        for (ref = remote_refs; ref; ref = ref->next)
                                transport_update_tracking_ref(transport->remote, ref, verbose);
@@@ -1214,7 -1153,7 +1221,7 @@@ static int refs_from_alternate_cb(struc
        const struct ref *extra;
        struct alternate_refs_data *cb = data;
  
 -      other = xstrdup(real_path(e->path));
 +      other = real_pathdup(e->path);
        len = strlen(other);
  
        while (other[len-1] == '/')
diff --combined transport.h
index 9820f10b8e41c6aa6ff6131e5660866d30bf541a,efd5fb668c678c70a2a87c9550a218a92f3379fe..e597b31b38d9d7bb374af203b80e4b6e83abbc3d
@@@ -131,21 -131,22 +131,22 @@@ struct transport 
        enum transport_family family;
  };
  
- #define TRANSPORT_PUSH_ALL 1
- #define TRANSPORT_PUSH_FORCE 2
- #define TRANSPORT_PUSH_DRY_RUN 4
- #define TRANSPORT_PUSH_MIRROR 8
- #define TRANSPORT_PUSH_PORCELAIN 16
- #define TRANSPORT_PUSH_SET_UPSTREAM 32
- #define TRANSPORT_RECURSE_SUBMODULES_CHECK 64
- #define TRANSPORT_PUSH_PRUNE 128
- #define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256
- #define TRANSPORT_PUSH_NO_HOOK 512
- #define TRANSPORT_PUSH_FOLLOW_TAGS 1024
- #define TRANSPORT_PUSH_CERT_ALWAYS 2048
- #define TRANSPORT_PUSH_CERT_IF_ASKED 4096
- #define TRANSPORT_PUSH_ATOMIC 8192
- #define TRANSPORT_PUSH_OPTIONS 16384
+ #define TRANSPORT_PUSH_ALL                    (1<<0)
+ #define TRANSPORT_PUSH_FORCE                  (1<<1)
+ #define TRANSPORT_PUSH_DRY_RUN                        (1<<2)
+ #define TRANSPORT_PUSH_MIRROR                 (1<<3)
+ #define TRANSPORT_PUSH_PORCELAIN              (1<<4)
+ #define TRANSPORT_PUSH_SET_UPSTREAM           (1<<5)
+ #define TRANSPORT_RECURSE_SUBMODULES_CHECK    (1<<6)
+ #define TRANSPORT_PUSH_PRUNE                  (1<<7)
+ #define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND        (1<<8)
+ #define TRANSPORT_PUSH_NO_HOOK                        (1<<9)
+ #define TRANSPORT_PUSH_FOLLOW_TAGS            (1<<10)
+ #define TRANSPORT_PUSH_CERT_ALWAYS            (1<<11)
+ #define TRANSPORT_PUSH_CERT_IF_ASKED          (1<<12)
+ #define TRANSPORT_PUSH_ATOMIC                 (1<<13)
+ #define TRANSPORT_PUSH_OPTIONS                        (1<<14)
+ #define TRANSPORT_RECURSE_SUBMODULES_ONLY     (1<<15)
  
  extern int transport_summary_width(const struct ref *refs);
  
  struct transport *transport_get(struct remote *, const char *);
  
  /*
 - * Check whether a transport is allowed by the environment. Type should
 - * generally be the URL scheme, as described in Documentation/git.txt
 + * Check whether a transport is allowed by the environment.
 + *
 + * Type should generally be the URL scheme, as described in
 + * Documentation/git.txt
 + *
 + * from_user specifies if the transport was given by the user.  If unknown pass
 + * a -1 to read from the environment to determine if the transport was given by
 + * the user.
 + *
   */
 -int is_transport_allowed(const char *type);
 +int is_transport_allowed(const char *type, int from_user);
  
  /*
   * Check whether a transport is allowed by the environment,
   */
  void transport_check_allowed(const char *type);
  
 -/*
 - * Returns true if the user has attempted to turn on protocol
 - * restrictions at all.
 - */
 -int transport_restrict_protocols(void);
 -
  /* Transport options which apply to git:// and scp-style URLs */
  
  /* The program to use on the remote side to send a pack */