Merge tag 'v2.9.5' into maint-2.10
authorJunio C Hamano <gitster@pobox.com>
Sun, 30 Jul 2017 21:57:33 +0000 (14:57 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 30 Jul 2017 21:57:33 +0000 (14:57 -0700)
Git 2.9.5

1  2 
cache.h
connect.c
path.c
diff --combined cache.h
index 1ec9021a70083ea40ee21add8ba766ea9b9c5e25,84148cf9ea060dc98214b5684670e9df0df370c0..2125eb50d0c7628779dd8fa3506bfa8d64fc4622
+++ b/cache.h
@@@ -367,9 -367,8 +367,9 @@@ extern void free_name_hash(struct index
  #define rename_cache_entry_at(pos, new_name) rename_index_entry_at(&the_index, (pos), (new_name))
  #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))
  #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))
 -#define add_to_cache(path, st, flags) add_to_index(&the_index, (path), (st), (flags), 0)
 -#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags), 0)
 +#define add_to_cache(path, st, flags) add_to_index(&the_index, (path), (st), (flags))
 +#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))
 +#define chmod_cache_entry(ce, flip) chmod_index_entry(&the_index, (ce), (flip))
  #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL, NULL)
  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
@@@ -582,10 -581,9 +582,10 @@@ extern int remove_file_from_index(struc
  #define ADD_CACHE_IGNORE_ERRORS       4
  #define ADD_CACHE_IGNORE_REMOVAL 8
  #define ADD_CACHE_INTENT 16
 -extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags, int force_mode);
 -extern int add_file_to_index(struct index_state *, const char *path, int flags, int force_mode);
 +extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
 +extern int add_file_to_index(struct index_state *, const char *path, int flags);
  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, unsigned int refresh_options);
 +extern int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
  extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
  extern void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
  extern int index_name_is_other(const struct index_state *, const char *, int);
@@@ -1006,11 -1004,6 +1006,11 @@@ int adjust_shared_perm(const char *path
   * directory while we were working.  To be robust against this kind of
   * race, callers might want to try invoking the function again when it
   * returns SCLD_VANISHED.
 + *
 + * safe_create_leading_directories() temporarily changes path while it
 + * is working but restores it before returning.
 + * safe_create_leading_directories_const() doesn't modify path, even
 + * temporarily.
   */
  enum scld_error {
        SCLD_OK = 0,
@@@ -1042,6 -1035,14 +1042,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
@@@ -1123,7 -1124,6 +1131,7 @@@ static inline int has_sha1_file(const u
  
  /* Same as the above, except for struct object_id. */
  extern int has_object_file(const struct object_id *oid);
 +extern int has_object_file_with_flags(const struct object_id *oid, int flags);
  
  /*
   * Return true iff an alternate object database has a loose object
@@@ -1142,16 -1142,6 +1150,16 @@@ static inline unsigned int hexval(unsig
        return hexval_table[c];
  }
  
 +/*
 + * Convert two consecutive hexadecimal digits into a char.  Return a
 + * negative value on error.  Don't run over the end of short strings.
 + */
 +static inline int hex2chr(const char *s)
 +{
 +      int val = hexval(s[0]);
 +      return (val < 0) ? val : (val << 4) | hexval(s[1]);
 +}
 +
  /* Convert to/from hex/sha1 representation */
  #define MINIMUM_ABBREV minimum_abbrev
  #define DEFAULT_ABBREV default_abbrev
@@@ -1212,7 -1202,6 +1220,7 @@@ extern int get_oid_hex(const char *hex
   *   printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two));
   */
  extern char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 +extern char *oid_to_hex_r(char *out, const struct object_id *oid);
  extern char *sha1_to_hex(const unsigned char *sha1);  /* static buffer result! */
  extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */
  
@@@ -1392,13 -1381,6 +1400,13 @@@ extern struct packed_git 
        char pack_name[FLEX_ARRAY]; /* more */
  } *packed_git;
  
 +/*
 + * A most-recently-used ordered version of the packed_git list, which can
 + * be iterated instead of packed_git (and marked via mru_mark).
 + */
 +struct mru;
 +extern struct mru *packed_git_mru;
 +
  struct pack_entry {
        off_t offset;
        unsigned char sha1[20];
@@@ -1438,6 -1420,7 +1446,6 @@@ extern unsigned char *use_pack(struct p
  extern void close_pack_windows(struct packed_git *);
  extern void close_all_packs(void);
  extern void unuse_pack(struct pack_window **);
 -extern void free_pack_by_name(const char *);
  extern void clear_delta_base_cache(void);
  extern struct packed_git *add_packed_git(const char *path, size_t path_len, int local);
  
@@@ -1587,18 -1570,10 +1595,18 @@@ struct git_config_source 
        const char *blob;
  };
  
 +enum config_origin_type {
 +      CONFIG_ORIGIN_BLOB,
 +      CONFIG_ORIGIN_FILE,
 +      CONFIG_ORIGIN_STDIN,
 +      CONFIG_ORIGIN_SUBMODULE_BLOB,
 +      CONFIG_ORIGIN_CMDLINE
 +};
 +
  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_mem(config_fn_t fn, const char *origin_type,
 +extern int git_config_from_mem(config_fn_t fn, const enum config_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);
@@@ -1640,16 -1615,6 +1648,16 @@@ 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);
 +
 +enum config_scope {
 +      CONFIG_SCOPE_UNKNOWN = 0,
 +      CONFIG_SCOPE_SYSTEM,
 +      CONFIG_SCOPE_GLOBAL,
 +      CONFIG_SCOPE_REPO,
 +      CONFIG_SCOPE_CMDLINE,
 +};
 +
 +extern enum config_scope current_config_scope(void);
  extern const char *current_config_origin_type(void);
  extern const char *current_config_name(void);
  
@@@ -1742,8 -1707,6 +1750,8 @@@ extern int ignore_untracked_cache_confi
  struct key_value_info {
        const char *filename;
        int linenr;
 +      enum config_origin_type origin_type;
 +      enum config_scope scope;
  };
  
  extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
@@@ -1769,6 -1732,7 +1777,6 @@@ extern int copy_file(const char *dst, c
  extern int copy_file_with_time(const char *dst, const char *src, int mode);
  
  extern void write_or_die(int fd, const void *buf, size_t count);
 -extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
  extern void fsync_or_die(int fd, const char *);
  
  extern ssize_t read_in_full(int fd, void *buf, size_t count);
@@@ -1780,21 -1744,8 +1788,21 @@@ static inline ssize_t write_str_in_full
        return write_in_full(fd, str, strlen(str));
  }
  
 -extern int write_file(const char *path, const char *fmt, ...);
 -extern int write_file_gently(const char *path, const char *fmt, ...);
 +/**
 + * Open (and truncate) the file at path, write the contents of buf to it,
 + * and close it. Dies if any errors are encountered.
 + */
 +extern void write_file_buf(const char *path, const char *buf, size_t len);
 +
 +/**
 + * Like write_file_buf(), but format the contents into a buffer first.
 + * Additionally, write_file() will append a newline if one is not already
 + * present, making it convenient to write text files:
 + *
 + *   write_file(path, "counter: %d", ctr);
 + */
 +__attribute__((format (printf, 2, 3)))
 +extern void write_file(const char *path, const char *fmt, ...);
  
  /* pager.c */
  extern void setup_pager(void);
@@@ -1831,7 -1782,7 +1839,7 @@@ void packet_trace_identity(const char *
   * return 0 if success, 1 - if addition of a file failed and
   * ADD_FILES_IGNORE_ERRORS was specified in flags
   */
 -int add_files_to_cache(const char *prefix, const struct pathspec *pathspec, int flags, int force_mode);
 +int add_files_to_cache(const char *prefix, const struct pathspec *pathspec, int flags);
  
  /* diff.c */
  extern int diff_auto_refresh_index;
diff --combined connect.c
index 722dc3fc546056be199f5d6a59c556833be58286,c75bf52ee29040626f89bc1daf85aab742915e91..048fa049170c8f6912ac96b7b547f2f28a74995e
+++ b/connect.c
@@@ -557,6 -557,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);
@@@ -658,19 -663,6 +663,19 @@@ static enum protocol parse_connect_url(
  
  static struct child_process no_fork = CHILD_PROCESS_INIT;
  
 +static const char *get_ssh_command(void)
 +{
 +      const char *ssh;
 +
 +      if ((ssh = getenv("GIT_SSH_COMMAND")))
 +              return ssh;
 +
 +      if (!git_config_get_string_const("core.sshcommand", &ssh))
 +              return ssh;
 +
 +      return NULL;
 +}
 +
  /*
   * This returns a dummy child_process if the transport protocol does not
   * need fork(2), or a struct child_process object if it does.  Once done,
@@@ -739,6 -731,9 +744,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;
                        }
  
 -                      ssh = getenv("GIT_SSH_COMMAND");
+                       if (looks_like_command_line_option(ssh_host))
+                               die("strange hostname '%s' blocked", ssh_host);
 +                      ssh = get_ssh_command();
                        if (!ssh) {
                                const char *base;
                                char *ssh_dup;
diff --combined path.c
index 9bfaeda2071636ec8a5a5ee32491494f5f83211c,0778ff03f9d86275eac43e217f3da3e7d0dbb3f6..6d4b007f4a9e7fad19cb8b87d8cde1bfc5f85b9e
--- 1/path.c
--- 2/path.c
+++ b/path.c
@@@ -24,8 -24,7 +24,8 @@@ static struct strbuf *get_pathname(void
                STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
        };
        static int index;
 -      struct strbuf *sb = &pathname_array[3 & ++index];
 +      struct strbuf *sb = &pathname_array[index];
 +      index = (index + 1) % ARRAY_SIZE(pathname_array);
        strbuf_reset(sb);
        return sb;
  }
@@@ -381,8 -380,6 +381,8 @@@ static void adjust_git_path(struct strb
                              get_index_file(), strlen(get_index_file()));
        else if (git_db_env && dir_prefix(base, "objects"))
                replace_dir(buf, git_dir_len + 7, get_object_directory());
 +      else if (git_hooks_path && dir_prefix(base, "hooks"))
 +              replace_dir(buf, git_dir_len + 5, git_hooks_path);
        else if (git_common_dir_env)
                update_common_dir(buf, git_dir_len, NULL);
  }
@@@ -1225,6 -1222,11 +1225,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;