Merge tag 'v2.7.6' into maint-2.8
authorJunio C Hamano <gitster@pobox.com>
Sun, 30 Jul 2017 21:46:43 +0000 (14:46 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 30 Jul 2017 21:46:43 +0000 (14:46 -0700)
Git 2.7.6

1  2 
cache.h
connect.c
path.c
t/t5532-fetch-proxy.sh
diff --combined cache.h
index 4ff196c25926cb1a6662f7582969ed665bae5ee3,b9fc3a8e33f657db8869ca512da177f6fc6859c9..924354f664f6004ee7b3760136937704ca0ffef2
+++ b/cache.h
@@@ -9,7 -9,6 +9,7 @@@
  #include "convert.h"
  #include "trace.h"
  #include "string-list.h"
 +#include "pack-revindex.h"
  
  #include SHA1_HEADER
  #ifndef platform_SHA_CTX
@@@ -651,6 -650,7 +651,6 @@@ extern int prefer_symlink_refs
  extern int log_all_ref_updates;
  extern int warn_ambiguous_refs;
  extern int warn_on_object_refname_ambiguity;
 -extern int shared_repository;
  extern const char *apply_default_whitespace;
  extern const char *apply_default_ignorewhitespace;
  extern const char *git_attributes_file;
@@@ -663,9 -663,6 +663,9 @@@ extern size_t delta_base_cache_limit
  extern unsigned long big_file_threshold;
  extern unsigned long pack_size_limit_cfg;
  
 +void set_shared_repository(int value);
 +int get_shared_repository(void);
 +
  /*
   * Do replace refs need to be checked this run?  This variable is
   * initialized to true unless --no-replace-object is used or
@@@ -700,14 -697,6 +700,14 @@@ extern int ref_paranoia
  extern char comment_line_char;
  extern int auto_comment_line_char;
  
 +/* Windows only */
 +enum hide_dotfiles_type {
 +      HIDE_DOTFILES_FALSE = 0,
 +      HIDE_DOTFILES_TRUE,
 +      HIDE_DOTFILES_DOTGITONLY
 +};
 +extern enum hide_dotfiles_type hide_dotfiles;
 +
  enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
@@@ -755,39 -744,9 +755,39 @@@ extern int grafts_replace_parents
   */
  #define GIT_REPO_VERSION 0
  #define GIT_REPO_VERSION_READ 1
 -extern int repository_format_version;
  extern int repository_format_precious_objects;
 -extern int check_repository_format(void);
 +
 +struct repository_format {
 +      int version;
 +      int precious_objects;
 +      int is_bare;
 +      char *work_tree;
 +      struct string_list unknown_extensions;
 +};
 +
 +/*
 + * Read the repository format characteristics from the config file "path" into
 + * "format" struct. Returns the numeric version. On error, -1 is returned,
 + * format->version is set to -1, and all other fields in the struct are
 + * undefined.
 + */
 +int read_repository_format(struct repository_format *format, const char *path);
 +
 +/*
 + * Verify that the repository described by repository_format is something we
 + * can read. If it is, return 0. Otherwise, return -1, and "err" will describe
 + * any errors encountered.
 + */
 +int verify_repository_format(const struct repository_format *format,
 +                           struct strbuf *err);
 +
 +/*
 + * Check the repository format version in the path found in get_git_dir(),
 + * and die if it is a version we don't understand. Generally one would
 + * set_git_dir() before calling this, and use it only for "are we in a valid
 + * repo?".
 + */
 +extern void check_repository_format(void);
  
  #define MTIME_CHANGED 0x0001
  #define CTIME_CHANGED 0x0002
@@@ -966,6 -925,8 +966,6 @@@ static inline int is_empty_blob_sha1(co
  
  int git_mkstemp(char *path, size_t n, const char *template);
  
 -int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
 -
  /* set default permissions by passing mode arguments to open(2) */
  int git_mkstemps_mode(char *pattern, int suffix_len, int mode);
  int git_mkstemp_mode(char *pattern, int mode);
@@@ -1030,6 -991,14 +1030,14 @@@ char *strip_path_suffix(const char *pat
  int daemon_avoid_alias(const char *path);
  extern int is_ntfs_dotgit(const char *name);
  
+ /*
+  * Returns true iff "str" could be confused as a command-line option when
+  * passed to a sub-program like "ssh". Note that this has nothing to do with
+  * shell-quoting, which should be handled separately; we're assuming here that
+  * the string makes it verbatim to the sub-program.
+  */
+ int looks_like_command_line_option(const char *str);
  /**
   * Return a newly allocated string with the evaluation of
   * "$XDG_CONFIG_HOME/git/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise
@@@ -1359,7 -1328,6 +1367,7 @@@ extern struct packed_git 
                 freshened:1,
                 do_not_close:1;
        unsigned char sha1[20];
 +      struct revindex_entry *revindex;
        /* something like ".git/objects/pack/xxxxx.pack" */
        char pack_name[FLEX_ARRAY]; /* more */
  } *packed_git;
@@@ -1556,14 -1524,15 +1564,14 @@@ struct git_config_source 
  typedef int (*config_fn_t)(const char *, const char *, void *);
  extern int git_default_config(const char *, const char *, void *);
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
 -extern int git_config_from_buf(config_fn_t fn, const char *name,
 -                             const char *buf, size_t len, void *data);
 +extern int git_config_from_mem(config_fn_t fn, const char *origin_type,
 +                                      const char *name, const char *buf, size_t len, void *data);
  extern void git_config_push_parameter(const char *text);
  extern int git_config_from_parameters(config_fn_t fn, void *data);
  extern void git_config(config_fn_t fn, void *);
  extern int git_config_with_options(config_fn_t fn, void *,
                                   struct git_config_source *config_source,
                                   int respect_includes);
 -extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
  extern int git_parse_ulong(const char *, unsigned long *);
  extern int git_parse_maybe_bool(const char *);
  extern int git_config_int(const char *, const char *);
@@@ -1587,6 -1556,7 +1595,6 @@@ extern void git_config_set_multivar_in_
  extern int git_config_rename_section(const char *, const char *);
  extern int git_config_rename_section_in_file(const char *, const char *, const char *);
  extern const char *git_etc_gitconfig(void);
 -extern int check_repository_format_version(const char *var, const char *value, void *cb);
  extern int git_env_bool(const char *, int);
  extern unsigned long git_env_ulong(const char *, unsigned long);
  extern int git_config_system(void);
@@@ -1598,8 -1568,6 +1606,8 @@@ extern const char *get_log_output_encod
  extern const char *get_commit_output_encoding(void);
  
  extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 +extern const char *current_config_origin_type(void);
 +extern const char *current_config_name(void);
  
  struct config_include_data {
        int depth;
@@@ -1678,14 -1646,6 +1686,14 @@@ extern int git_config_get_bool(const ch
  extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
  extern int git_config_get_maybe_bool(const char *key, int *dest);
  extern int git_config_get_pathname(const char *key, const char **dest);
 +extern int git_config_get_untracked_cache(void);
 +
 +/*
 + * This is a hack for test programs like test-dump-untracked-cache to
 + * ensure that they do not modify the untracked cache when reading it.
 + * Do not use it otherwise!
 + */
 +extern int ignore_untracked_cache_config;
  
  struct key_value_info {
        const char *filename;
@@@ -1807,7 -1767,7 +1815,7 @@@ int split_cmdline(char *cmdline, const 
  /* Takes a negative value returned by split_cmdline */
  const char *split_cmdline_strerror(int cmdline_errno);
  
 -/* git.c */
 +/* setup.c */
  struct startup_info {
        int have_repository;
        const char *prefix;
diff --combined connect.c
index c53f3f1c55243feae8affbb268af689b35b9169f,d77d39771b6c5101abe14df1e078af2a02ce8ace..c75bf52ee29040626f89bc1daf85aab742915e91
+++ b/connect.c
@@@ -267,9 -267,9 +267,9 @@@ static enum protocol get_protocol(cons
                return PROTO_SSH;
        if (!strcmp(name, "git"))
                return PROTO_GIT;
 -      if (!strcmp(name, "git+ssh"))
 +      if (!strcmp(name, "git+ssh")) /* deprecated - do not use */
                return PROTO_SSH;
 -      if (!strcmp(name, "ssh+git"))
 +      if (!strcmp(name, "ssh+git")) /* deprecated - do not use */
                return PROTO_SSH;
        if (!strcmp(name, "file"))
                return PROTO_FILE;
@@@ -357,10 -357,6 +357,10 @@@ static int git_tcp_connect_sock(char *h
                port = "<none>";
  
        memset(&hints, 0, sizeof(hints));
 +      if (flags & CONNECT_IPV4)
 +              hints.ai_family = AF_INET;
 +      else if (flags & CONNECT_IPV6)
 +              hints.ai_family = AF_INET6;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
  
@@@ -557,6 -553,11 +557,11 @@@ static struct child_process *git_proxy_
  
        get_host_and_port(&host, &port);
  
+       if (looks_like_command_line_option(host))
+               die("strange hostname '%s' blocked", host);
+       if (looks_like_command_line_option(port))
+               die("strange port '%s' blocked", port);
        proxy = xmalloc(sizeof(*proxy));
        child_process_init(proxy);
        argv_array_push(&proxy->args, git_proxy_command);
@@@ -726,6 -727,9 +731,9 @@@ struct child_process *git_connect(int f
                conn = xmalloc(sizeof(*conn));
                child_process_init(conn);
  
+               if (looks_like_command_line_option(path))
+                       die("strange pathname '%s' blocked", path);
                strbuf_addstr(&cmd, prog);
                strbuf_addch(&cmd, ' ');
                sq_quote_buf(&cmd, path);
                                return NULL;
                        }
  
+                       if (looks_like_command_line_option(ssh_host))
+                               die("strange hostname '%s' blocked", ssh_host);
                        ssh = getenv("GIT_SSH_COMMAND");
                        if (!ssh) {
                                const char *base;
                        }
  
                        argv_array_push(&conn->args, ssh);
 +                      if (flags & CONNECT_IPV4)
 +                              argv_array_push(&conn->args, "-4");
 +                      else if (flags & CONNECT_IPV6)
 +                              argv_array_push(&conn->args, "-6");
                        if (tortoiseplink)
                                argv_array_push(&conn->args, "-batch");
                        if (port) {
diff --combined path.c
index 503766784c4c0c1be71edacbaae6ec4bd698ee8d,b214ac3fe63d4aa7cd134f4e819f48c54936977a..6fbc4c38cc03ee4fba7a7026cb9520fd81ce25f4
--- 1/path.c
--- 2/path.c
+++ b/path.c
@@@ -134,7 -134,7 +134,7 @@@ static struct common_dir common_list[] 
   * definite
   * definition
   *
 - * The trie would look look like:
 + * The trie would look like:
   * root: len = 0, children a and d non-NULL, value = NULL.
   *    a: len = 2, contents = bc, value = (data for "abc")
   *    d: len = 2, contents = ef, children i non-NULL, value = (data for "def")
@@@ -584,9 -584,6 +584,9 @@@ char *expand_user_path(const char *path
                        if (!home)
                                goto return_null;
                        strbuf_addstr(&user_path, home);
 +#ifdef GIT_WINDOWS_NATIVE
 +                      convert_slashes(user_path.buf);
 +#endif
                } else {
                        struct passwd *pw = getpw_str(username, username_len);
                        if (!pw)
@@@ -702,17 -699,17 +702,17 @@@ static int calc_shared_perm(int mode
  {
        int tweak;
  
 -      if (shared_repository < 0)
 -              tweak = -shared_repository;
 +      if (get_shared_repository() < 0)
 +              tweak = -get_shared_repository();
        else
 -              tweak = shared_repository;
 +              tweak = get_shared_repository();
  
        if (!(mode & S_IWUSR))
                tweak &= ~0222;
        if (mode & S_IXUSR)
                /* Copy read bits to execute bits */
                tweak |= (tweak & 0444) >> 2;
 -      if (shared_repository < 0)
 +      if (get_shared_repository() < 0)
                mode = (mode & ~0777) | tweak;
        else
                mode |= tweak;
@@@ -725,7 -722,7 +725,7 @@@ int adjust_shared_perm(const char *path
  {
        int old_mode, new_mode;
  
 -      if (!shared_repository)
 +      if (!get_shared_repository())
                return 0;
        if (get_st_mode_bits(path, &old_mode) < 0)
                return -1;
@@@ -1181,6 -1178,11 +1181,11 @@@ int is_ntfs_dotgit(const char *name
                }
  }
  
+ int looks_like_command_line_option(const char *str)
+ {
+       return str && str[0] == '-';
+ }
  char *xdg_config_home(const char *filename)
  {
        const char *home, *config_home;
diff --combined t/t5532-fetch-proxy.sh
index 51c9669398a01bab0b59174ec6ec1be92c3f21fe,d3b2651b6114e6db50464d25d2b6dc6fa700c903..9c2798603b4d7b4a3db135febedc71e8cea23635
@@@ -12,8 -12,10 +12,8 @@@ test_expect_success 'setup remote repo
        )
  '
  
 -cat >proxy <<'EOF'
 -#!/bin/sh
 -echo >&2 "proxying for $*"
 -cmd=`"$PERL_PATH" -e '
 +test_expect_success 'setup proxy script' '
 +      write_script proxy-get-cmd "$PERL_PATH" <<-\EOF &&
        read(STDIN, $buf, 4);
        my $n = hex($buf) - 4;
        read(STDIN, $buf, $n);
        # drop absolute-path on repo name
        $cmd =~ s{ /}{ };
        print $cmd;
 -'`
 -echo >&2 "Running '$cmd'"
 -exec $cmd
 -EOF
 -chmod +x proxy
 +      EOF
 +
 +      write_script proxy <<-\EOF
 +      echo >&2 "proxying for $*"
 +      cmd=$(./proxy-get-cmd)
 +      echo >&2 "Running $cmd"
 +      exec $cmd
 +      EOF
 +'
 +
  test_expect_success 'setup local repo' '
        git remote add fake git://example.com/remote &&
        git config core.gitproxy ./proxy
@@@ -43,4 -40,9 +43,9 @@@ test_expect_success 'fetch through prox
        test_cmp expect actual
  '
  
+ test_expect_success 'funny hostnames are rejected before running proxy' '
+       test_must_fail git fetch git://-remote/repo.git 2>stderr &&
+       ! grep "proxying for" stderr
+ '
  test_done