Merge branch 'maint-2.4' into maint-2.5
authorJunio C Hamano <gitster@pobox.com>
Thu, 17 Mar 2016 18:24:14 +0000 (11:24 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 17 Mar 2016 18:24:14 +0000 (11:24 -0700)
* maint-2.4:
Git 2.4.11
list-objects: pass full pathname to callbacks
list-objects: drop name_path entirely
list-objects: convert name_path to a strbuf
show_object_with_name: simplify by using path_name()
http-push: stop using name_path
tree-diff: catch integer overflow in combine_diff_path allocation
add helpers for detecting size_t overflow

1  2 
Documentation/git.txt
builtin/pack-objects.c
builtin/rev-list.c
diff.h
git-compat-util.h
reachable.c
revision.c
tree-diff.c
diff --combined Documentation/git.txt
index 1a262757dc9f73f39cadef45613046d09d824c9a,889fa51f909bf369c5d37eb2c8d3ad5c56fa31d8..5449d7b35cc2c9212979ce80cf7d0e8015970b15
@@@ -43,18 -43,10 +43,19 @@@ unreleased) version of Git, that is ava
  branch of the `git.git` repository.
  Documentation for older releases are available here:
  
- * link:v2.4.10/git.html[documentation for release 2.4.10]
 +* link:v2.5.4/git.html[documentation for release 2.5.4]
 +
 +* release notes for
 +  link:RelNotes/2.5.4.txt[2.5.4],
 +  link:RelNotes/2.5.3.txt[2.5.3],
 +  link:RelNotes/2.5.2.txt[2.5.2],
 +  link:RelNotes/2.5.1.txt[2.5.1],
 +  link:RelNotes/2.5.0.txt[2.5].
 +
+ * link:v2.4.11/git.html[documentation for release 2.4.11]
  
  * release notes for
+   link:RelNotes/2.4.11.txt[2.4.11],
    link:RelNotes/2.4.10.txt[2.4.10],
    link:RelNotes/2.4.9.txt[2.4.9],
    link:RelNotes/2.4.8.txt[2.4.8],
@@@ -790,7 -782,7 +791,7 @@@ The Git Repositor
  ~~~~~~~~~~~~~~~~~~
  These environment variables apply to 'all' core Git commands. Nb: it
  is worth noting that they may be used/overridden by SCMS sitting above
 -Git so take care if using Cogito etc.
 +Git so take care if using a foreign front-end.
  
  'GIT_INDEX_FILE'::
        This environment allows the specification of an alternate
        an explicit repository directory set via 'GIT_DIR' or on the
        command line.
  
 +'GIT_COMMON_DIR'::
 +      If this variable is set to a path, non-worktree files that are
 +      normally in $GIT_DIR will be taken from this path
 +      instead. Worktree-specific files such as HEAD or index are
 +      taken from $GIT_DIR. See linkgit:gitrepository-layout[5] and
 +      linkgit:git-worktree[1] for
 +      details. This variable has lower precedence than other path
 +      variables such as GIT_INDEX_FILE, GIT_OBJECT_DIRECTORY...
 +
  Git Commits
  ~~~~~~~~~~~
  'GIT_AUTHOR_NAME'::
diff --combined builtin/pack-objects.c
index 80fe8c7dc1da9b78d2ba39ba0a70de69372c35ab,4af92f113c8423aa4749d2ddb19be95e68d43c13..53307d53b00812a40b2958aa01bff3ccca6f6298
@@@ -540,11 -540,11 +540,11 @@@ static enum write_one_status write_one(
        return WRITE_ONE_WRITTEN;
  }
  
 -static int mark_tagged(const char *path, const unsigned char *sha1, int flag,
 +static int mark_tagged(const char *path, const struct object_id *oid, int flag,
                       void *cb_data)
  {
        unsigned char peeled[20];
 -      struct object_entry *entry = packlist_find(&to_pack, sha1, NULL);
 +      struct object_entry *entry = packlist_find(&to_pack, oid->hash, NULL);
  
        if (entry)
                entry->tagged = 1;
@@@ -2097,14 -2097,14 +2097,14 @@@ static void ll_find_deltas(struct objec
  #define ll_find_deltas(l, s, w, d, p) find_deltas(l, &s, w, d, p)
  #endif
  
 -static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 +static int add_ref_tag(const char *path, const struct object_id *oid, int flag, void *cb_data)
  {
 -      unsigned char peeled[20];
 +      struct object_id peeled;
  
        if (starts_with(path, "refs/tags/") && /* is a tag? */
 -          !peel_ref(path, peeled)        && /* peelable? */
 -          packlist_find(&to_pack, peeled, NULL))      /* object packed? */
 -              add_object_entry(sha1, OBJ_TAG, NULL, 0);
 +          !peel_ref(path, peeled.hash)    && /* peelable? */
 +          packlist_find(&to_pack, peeled.hash, NULL))      /* object packed? */
 +              add_object_entry(oid->hash, OBJ_TAG, NULL, 0);
        return 0;
  }
  
@@@ -2284,21 -2284,11 +2284,11 @@@ static void show_commit(struct commit *
                index_commit_for_bitmap(commit);
  }
  
- static void show_object(struct object *obj,
-                       const struct name_path *path, const char *last,
-                       void *data)
+ static void show_object(struct object *obj, const char *name, void *data)
  {
-       char *name = path_name(path, last);
        add_preferred_base_object(name);
        add_object_entry(obj->sha1, obj->type, name, 0);
        obj->flags |= OBJECT_ADDED;
-       /*
-        * We will have generated the hash from the name,
-        * but not saved a pointer to it - we can free it
-        */
-       free((char *)name);
  }
  
  static void show_edge(struct commit *commit)
@@@ -2480,8 -2470,7 +2470,7 @@@ static int get_object_list_from_bitmap(
  }
  
  static void record_recent_object(struct object *obj,
-                                const struct name_path *path,
-                                const char *last,
+                                const char *name,
                                 void *data)
  {
        sha1_array_append(&recent_objects, obj->sha1);
diff --combined builtin/rev-list.c
index d80d1ed35944144aa0aeeeb1b0e08c9efdec6523,7ae255862aaa43fb20969b75d9e434902ec2cba1..4c46341749ae4a2a8eb90af81b7b1fc4bfcf2c90
@@@ -177,9 -177,7 +177,7 @@@ static void finish_commit(struct commi
        free_commit_buffer(commit);
  }
  
- static void finish_object(struct object *obj,
-                         const struct name_path *path, const char *name,
-                         void *cb_data)
+ static void finish_object(struct object *obj, const char *name, void *cb_data)
  {
        struct rev_list_info *info = cb_data;
        if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1))
                parse_object(obj->sha1);
  }
  
- static void show_object(struct object *obj,
-                       const struct name_path *path, const char *component,
-                       void *cb_data)
+ static void show_object(struct object *obj, const char *name, void *cb_data)
  {
        struct rev_list_info *info = cb_data;
-       finish_object(obj, path, component, cb_data);
+       finish_object(obj, name, cb_data);
        if (info->flags & REV_LIST_QUIET)
                return;
-       show_object_with_name(stdout, obj, path, component);
+       show_object_with_name(stdout, obj, name);
  }
  
  static void show_edge(struct commit *commit)
@@@ -350,9 -346,6 +346,9 @@@ int cmd_rev_list(int argc, const char *
            revs.diff)
                usage(rev_list_usage);
  
 +      if (revs.show_notes)
 +              die(_("rev-list does not support display of notes"));
 +
        save_commit_buffer = (revs.verbose_header ||
                              revs.grep_filter.pattern_list ||
                              revs.grep_filter.header_list);
diff --combined diff.h
index c7ad42addf8e4cd91b423d96526a5557473e5688,561635b2b9be13c19874152a2185ad2b6d867834..37e43bc537fac4044d528a64f2dd7fd26a7353af
--- 1/diff.h
--- 2/diff.h
+++ b/diff.h
@@@ -6,7 -6,6 +6,7 @@@
  
  #include "tree-walk.h"
  #include "pathspec.h"
 +#include "object.h"
  
  struct rev_info;
  struct diff_options;
@@@ -138,11 -137,6 +138,11 @@@ struct diff_options 
        int dirstat_permille;
        int setup;
        int abbrev;
 +/* white-space error highlighting */
 +#define WSEH_NEW 1
 +#define WSEH_CONTEXT 2
 +#define WSEH_OLD 4
 +      unsigned ws_error_highlight;
        const char *prefix;
        int prefix_length;
        const char *stat_sep;
@@@ -213,16 -207,16 +213,16 @@@ struct combine_diff_path 
        struct combine_diff_path *next;
        char *path;
        unsigned int mode;
 -      unsigned char sha1[20];
 +      struct object_id oid;
        struct combine_diff_parent {
                char status;
                unsigned int mode;
 -              unsigned char sha1[20];
 +              struct object_id oid;
        } parent[FLEX_ARRAY];
  };
  #define combine_diff_path_size(n, l) \
-       (sizeof(struct combine_diff_path) + \
-        sizeof(struct combine_diff_parent) * (n) + (l) + 1)
+       st_add4(sizeof(struct combine_diff_path), (l), 1, \
+               st_mult(sizeof(struct combine_diff_parent), (n)))
  
  extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
                              int dense, struct rev_info *);
diff --combined git-compat-util.h
index 076461e8c8d3cd2051e84060c2ca405c3a3577ac,061e33c7749dc496e1f5e78aabdfd4c6f1e82736..d20fa89d5f32e0c76c7a9e6f77d91be6cb0d9f09
  #define unsigned_add_overflows(a, b) \
      ((b) > maximum_unsigned_value_of_type(a) - (a))
  
+ /*
+  * Returns true if the multiplication of "a" and "b" will
+  * overflow. The types of "a" and "b" must match and must be unsigned.
+  * Note that this macro evaluates "a" twice!
+  */
+ #define unsigned_mult_overflows(a, b) \
+     ((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
  #ifdef __GNUC__
  #define TYPEOF(x) (__typeof__(x))
  #else
  #elif defined(_MSC_VER)
  #include "compat/msvc.h"
  #else
 +#include <sys/utsname.h>
  #include <sys/wait.h>
  #include <sys/resource.h>
  #include <sys/socket.h>
@@@ -389,6 -396,7 +397,6 @@@ struct strbuf
  
  /* General helper functions */
  extern void vreportf(const char *prefix, const char *err, va_list params);
 -extern void vwritef(int fd, const char *prefix, const char *err, va_list params);
  extern NORETURN void usage(const char *err);
  extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
@@@ -424,7 -432,6 +432,7 @@@ static inline int const_error(void
  extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
  extern void set_error_routine(void (*routine)(const char *err, va_list params));
  extern void set_die_is_recursing_routine(int (*routine)(void));
 +extern void set_error_handle(FILE *);
  
  extern int starts_with(const char *str, const char *prefix);
  
@@@ -699,6 -706,32 +707,32 @@@ extern void release_pack_memory(size_t)
  typedef void (*try_to_free_t)(size_t);
  extern try_to_free_t set_try_to_free_routine(try_to_free_t);
  
+ static inline size_t st_add(size_t a, size_t b)
+ {
+       if (unsigned_add_overflows(a, b))
+               die("size_t overflow: %"PRIuMAX" + %"PRIuMAX,
+                   (uintmax_t)a, (uintmax_t)b);
+       return a + b;
+ }
+ #define st_add3(a,b,c)   st_add((a),st_add((b),(c)))
+ #define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d)))
+ static inline size_t st_mult(size_t a, size_t b)
+ {
+       if (unsigned_mult_overflows(a, b))
+               die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
+                   (uintmax_t)a, (uintmax_t)b);
+       return a * b;
+ }
+ static inline size_t st_sub(size_t a, size_t b)
+ {
+       if (a < b)
+               die("size_t underflow: %"PRIuMAX" - %"PRIuMAX,
+                   (uintmax_t)a, (uintmax_t)b);
+       return a - b;
+ }
  #ifdef HAVE_ALLOCA_H
  # include <alloca.h>
  # define xalloca(size)      (alloca(size))
@@@ -935,10 -968,4 +969,10 @@@ struct tm *git_gmtime_r(const time_t *
  # define SHELL_PATH "/bin/sh"
  #endif
  
 +#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
 +#define flockfile(fh)
 +#define funlockfile(fh)
 +#define getc_unlocked(fh) getc(fh)
 +#endif
 +
  #endif
diff --combined reachable.c
index 9cff25b490f7ec7c5535647afe017326a6984520,9b0295469f562998ecffb8c8608d887c973bbce5..59196253a60c03a622276279788e642fe36f076b
@@@ -22,10 -22,9 +22,10 @@@ static void update_progress(struct conn
                display_progress(cp->progress, cp->count);
  }
  
 -static int add_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 +static int add_one_ref(const char *path, const struct object_id *oid,
 +                     int flag, void *cb_data)
  {
 -      struct object *object = parse_object_or_die(sha1, path);
 +      struct object *object = parse_object_or_die(oid->hash, path);
        struct rev_info *revs = (struct rev_info *)cb_data;
  
        add_pending_object(revs, object, "");
   * The traversal will have already marked us as SEEN, so we
   * only need to handle any progress reporting here.
   */
- static void mark_object(struct object *obj, const struct name_path *path,
-                       const char *name, void *data)
+ static void mark_object(struct object *obj, const char *name, void *data)
  {
        update_progress(data);
  }
  
  static void mark_commit(struct commit *c, void *data)
  {
-       mark_object(&c->object, NULL, NULL, data);
+       mark_object(&c->object, NULL, data);
  }
  
  struct recent_data {
diff --combined revision.c
index 9b9d77dc439d6a6c8e25c58454833804116db14a,871812db2a34d584662f9032c207695e82aae14a..8f30ab1e46b4a07148b7dfe0e8f7950fd241c325
  
  volatile show_early_output_fn_t show_early_output;
  
char *path_name(const struct name_path *path, const char *name)
void show_object_with_name(FILE *out, struct object *obj, const char *name)
  {
-       const struct name_path *p;
-       char *n, *m;
-       int nlen = strlen(name);
-       int len = nlen + 1;
-       for (p = path; p; p = p->up) {
-               if (p->elem_len)
-                       len += p->elem_len + 1;
-       }
-       n = xmalloc(len);
-       m = n + len - (nlen + 1);
-       strcpy(m, name);
-       for (p = path; p; p = p->up) {
-               if (p->elem_len) {
-                       m -= p->elem_len + 1;
-                       memcpy(m, p->elem, p->elem_len);
-                       m[p->elem_len] = '/';
-               }
-       }
-       return n;
- }
- static int show_path_component_truncated(FILE *out, const char *name, int len)
- {
-       int cnt;
-       for (cnt = 0; cnt < len; cnt++) {
-               int ch = name[cnt];
-               if (!ch || ch == '\n')
-                       return -1;
-               fputc(ch, out);
-       }
-       return len;
- }
- static int show_path_truncated(FILE *out, const struct name_path *path)
- {
-       int emitted, ours;
-       if (!path)
-               return 0;
-       emitted = show_path_truncated(out, path->up);
-       if (emitted < 0)
-               return emitted;
-       if (emitted)
-               fputc('/', out);
-       ours = show_path_component_truncated(out, path->elem, path->elem_len);
-       if (ours < 0)
-               return ours;
-       return ours || emitted;
- }
- void show_object_with_name(FILE *out, struct object *obj,
-                          const struct name_path *path, const char *component)
- {
-       struct name_path leaf;
-       leaf.up = (struct name_path *)path;
-       leaf.elem = component;
-       leaf.elem_len = strlen(component);
+       const char *p;
  
        fprintf(out, "%s ", sha1_to_hex(obj->sha1));
-       show_path_truncated(out, &leaf);
+       for (p = name; *p && *p != '\n'; p++)
+               fputc(*p, out);
        fputc('\n', out);
  }
  
@@@ -361,8 -305,8 +305,8 @@@ static int everybody_uninteresting(stru
                list = list->next;
                if (commit->object.flags & UNINTERESTING)
                        continue;
 -              if (interesting_cache)
 -                      *interesting_cache = commit;
 +
 +              *interesting_cache = commit;
                return 0;
        }
        return 1;
@@@ -1218,8 -1162,7 +1162,8 @@@ int ref_excluded(struct string_list *re
        return 0;
  }
  
 -static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 +static int handle_one_ref(const char *path, const struct object_id *oid,
 +                        int flag, void *cb_data)
  {
        struct all_refs_cb *cb = cb_data;
        struct object *object;
        if (ref_excluded(cb->all_revs->ref_excludes, path))
            return 0;
  
 -      object = get_reference(cb->all_revs, path, sha1, cb->all_flags);
 +      object = get_reference(cb->all_revs, path, oid->hash, cb->all_flags);
        add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
 -      add_pending_sha1(cb->all_revs, path, sha1, cb->all_flags);
 +      add_pending_sha1(cb->all_revs, path, oid->hash, cb->all_flags);
        return 0;
  }
  
@@@ -1293,8 -1236,7 +1237,8 @@@ static int handle_one_reflog_ent(unsign
        return 0;
  }
  
 -static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 +static int handle_one_reflog(const char *path, const struct object_id *oid,
 +                           int flag, void *cb_data)
  {
        struct all_refs_cb *cb = cb_data;
        cb->warned_bad_reflog = 0;
  void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
  {
        struct all_refs_cb cb;
 +
        cb.all_revs = revs;
        cb.all_flags = flags;
        for_each_reflog(handle_one_reflog, &cb);
@@@ -2173,21 -2114,6 +2117,21 @@@ static int handle_revision_pseudo_opt(c
        return 1;
  }
  
 +static void NORETURN diagnose_missing_default(const char *def)
 +{
 +      unsigned char sha1[20];
 +      int flags;
 +      const char *refname;
 +
 +      refname = resolve_ref_unsafe(def, 0, sha1, &flags);
 +      if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN))
 +              die(_("your current branch appears to be broken"));
 +
 +      skip_prefix(refname, "refs/heads/", &refname);
 +      die(_("your current branch '%s' does not have any commits yet"),
 +          refname);
 +}
 +
  /*
   * Parse revision information, filling in the "rev_info" structure,
   * and removing the used arguments from the argument list.
@@@ -2317,7 -2243,7 +2261,7 @@@ int setup_revisions(int argc, const cha
                struct object *object;
                struct object_context oc;
                if (get_sha1_with_context(revs->def, 0, sha1, &oc))
 -                      die("bad default revision '%s'", revs->def);
 +                      diagnose_missing_default(revs->def);
                object = get_reference(revs, revs->def, sha1, 0);
                add_pending_object_with_mode(revs, object, revs->def, oc.mode);
        }
diff --combined tree-diff.c
index 290a1da4ce5c3504dd75e584030a4a00fbdbe9a2,4b32d40677da2821fca8d9b15300229800117e07..4dda9a14abacbf38ba19fcf89b2ef54576a26538
@@@ -64,7 -64,7 +64,7 @@@ static int emit_diff_first_parent_only(
  {
        struct combine_diff_parent *p0 = &p->parent[0];
        if (p->mode && p0->mode) {
 -              opt->change(opt, p0->mode, p->mode, p0->sha1, p->sha1,
 +              opt->change(opt, p0->mode, p->mode, p0->oid.hash, p->oid.hash,
                        1, 1, p->path, 0, 0);
        }
        else {
  
                if (p->mode) {
                        addremove = '+';
 -                      sha1 = p->sha1;
 +                      sha1 = p->oid.hash;
                        mode = p->mode;
                } else {
                        addremove = '-';
 -                      sha1 = p0->sha1;
 +                      sha1 = p0->oid.hash;
                        mode = p0->mode;
                }
  
@@@ -124,8 -124,8 +124,8 @@@ static struct combine_diff_path *path_a
        unsigned mode, const unsigned char *sha1)
  {
        struct combine_diff_path *p;
-       int len = base->len + pathlen;
-       int alloclen = combine_diff_path_size(nparent, len);
+       size_t len = st_add(base->len, pathlen);
+       size_t alloclen = combine_diff_path_size(nparent, len);
  
        /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */
        p = last->next;
        memcpy(p->path + base->len, path, pathlen);
        p->path[len] = 0;
        p->mode = mode;
 -      hashcpy(p->sha1, sha1 ? sha1 : null_sha1);
 +      hashcpy(p->oid.hash, sha1 ? sha1 : null_sha1);
  
        return p;
  }
@@@ -238,7 -238,7 +238,7 @@@ static struct combine_diff_path *emit_p
                        }
  
                        p->parent[i].mode = mode_i;
 -                      hashcpy(p->parent[i].sha1, sha1_i ? sha1_i : null_sha1);
 +                      hashcpy(p->parent[i].oid.hash, sha1_i ? sha1_i : null_sha1);
                }
  
                keep = 1;