Merge branch 'jk/ui-color-always-to-auto'
authorJunio C Hamano <gitster@pobox.com>
Sat, 7 Oct 2017 07:27:55 +0000 (16:27 +0900)
committerJunio C Hamano <gitster@pobox.com>
Sat, 7 Oct 2017 07:27:55 +0000 (16:27 +0900)
Fix regression of "git add -p" for users with "color.ui = always"
in their configuration, by merging the topic below and adjusting it
for the 'master' front.

* jk/ui-color-always-to-auto:
t7301: use test_terminal to check color
t4015: use --color with --color-moved
color: make "always" the same as "auto" in config
provide --color option for all ref-filter users
t3205: use --color instead of color.branch=always
t3203: drop "always" color test
t6006: drop "always" color config tests
t7502: use diff.noprefix for --verbose test
t7508: use test_terminal for color output
t3701: use test-terminal to collect color output
t4015: prefer --color to -c color.diff=always
test-terminal: set TERM=vt100

34 files changed:
.clang-format
Documentation/RelNotes/2.15.0.txt
GIT-VERSION-GEN
builtin/branch.c
builtin/checkout.c
builtin/diff-index.c
builtin/diff.c
builtin/name-rev.c
builtin/receive-pack.c
builtin/tag.c
compat/poll/poll.c
contrib/coccinelle/array.cocci
fast-import.c
git-request-pull.sh
graph.c
http-push.c
path.c
pretty.c
ref-filter.c
reflog-walk.c
refs/files-backend.c
refs/packed-backend.c
repository.c
run-command.c
sequencer.c
strbuf.h
sub-process.c
t/helper/test-string-list.c
t/t4205-log-pretty-formats.sh
t/t5150-request-pull.sh
t/t9300-fast-import.sh
tag.c
transport.c
wt-status.c
index 56822c116b13c6782d4488fed6d3e21d01c18f35..611ab4750bd21e77d0fec41c8b2e115574c692ff 100644 (file)
@@ -1,4 +1,8 @@
-# Defaults
+# This file is an example configuration for clang-format 5.0.
+#
+# Note that this style definition should only be understood as a hint
+# for writing new code. The rules are still work-in-progress and does
+# not yet exactly match the style we have in the existing code.
 
 # Use tabs whenever we need to fill whitespace that spans at least from one tab
 # stop to the next one.
index face5e0b0236c6f28ffecee61f92693ddc11d7a4..1be62c9e27566e5cbd1581f90569a7cf9c7d923a 100644 (file)
@@ -219,6 +219,9 @@ Performance, Internal Implementation, Development Support etc.
    pre-parse everything, and an access to a single ref in the
    packed-refs does not touch majority of irrelevant refs, either.
 
+ * Add comment to clarify that the style file is meant to be used with
+   clang-5 and the rules are still work in progress.
+
 Also contains various documentation updates and code clean-ups.
 
 
@@ -442,6 +445,16 @@ Fixes since v2.14
    correctly, which has been corrected.
    (merge a6304fa4c2 bc/rev-parse-parseopt-fix later to maint).
 
+ * The checkpoint command "git fast-import" did not flush updates to
+   refs and marks unless at least one object was created since the
+   last checkpoint, which has been corrected, as these things can
+   happen without any new object getting created.
+   (merge 30e215a65c er/fast-import-dump-refs-on-checkpoint later to maint).
+
+ * Spell the name of our system as "Git" in the output from
+   request-pull script.
+   (merge e66d7c37a5 ar/request-pull-phrasofix later to maint).
+
  * Other minor doc, test and build updates and code cleanups.
    (merge f094b89a4d ma/parse-maybe-bool later to maint).
    (merge 39b00fa4d4 jk/drop-sha1-entry-pos later to maint).
@@ -465,3 +478,6 @@ Fixes since v2.14
    (merge 0bca165fdb jk/validate-headref-fix later to maint).
    (merge 93dbefb389 mr/doc-negative-pathspec later to maint).
    (merge 5e633326e4 ad/doc-markup-fix later to maint).
+   (merge 9ca356fa8b rs/cocci-de-paren-call-params later to maint).
+   (merge 7099153e8d rs/tag-null-pointer-arith-fix later to maint).
+   (merge 0e187d758c rs/run-command-use-alloc-array later to maint).
index 75beb2e7750f82db233c8365f0ba2223ca4e2486..ab04c977be0cfdb6f282b7911d3fe630d5f70c65 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.14.GIT
+DEF_VER=v2.15.0-rc0
 
 LF='
 '
index b998e16d0c24b300ce1469749e290c7879af14a7..d7a876cca3157f58dfd88936e53f5f52076ab702 100644 (file)
@@ -217,7 +217,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                if (!head_rev)
                        die(_("Couldn't look up commit object for HEAD"));
        }
-       for (i = 0; i < argc; i++, strbuf_release(&bname)) {
+       for (i = 0; i < argc; i++, strbuf_reset(&bname)) {
                char *target = NULL;
                int flags = 0;
 
@@ -282,8 +282,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
        }
 
        free(name);
+       strbuf_release(&bname);
 
-       return(ret);
+       return ret;
 }
 
 static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
@@ -353,7 +354,7 @@ static char *build_format(struct ref_filter *filter, int maxwidth, const char *r
                        strbuf_addf(&obname, "%%(objectname:short=%d)", filter->abbrev);
 
                strbuf_addf(&local, "%%(align:%d,left)%%(refname:lstrip=2)%%(end)", maxwidth);
-               strbuf_addf(&local, "%s", branch_get_color(BRANCH_COLOR_RESET));
+               strbuf_addstr(&local, branch_get_color(BRANCH_COLOR_RESET));
                strbuf_addf(&local, " %s ", obname.buf);
 
                if (filter->verbose > 1)
index 3345a0d16f21c38fe5fe6f32fa5b0a139e21c4a3..fc4f8fd2ea29c7c23d3b1c7ca0ba78824c255a91 100644 (file)
@@ -1124,9 +1124,8 @@ static int checkout_branch(struct checkout_opts *opts,
 
        if (new->path && !opts->force_detach && !opts->new_branch &&
            !opts->ignore_other_worktrees) {
-               struct object_id oid;
                int flag;
-               char *head_ref = resolve_refdup("HEAD", 0, oid.hash, &flag);
+               char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag);
                if (head_ref &&
                    (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)))
                        die_if_checked_out(new->path, 1);
@@ -1298,6 +1297,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                strbuf_release(&buf);
        }
 
+       UNLEAK(opts);
        if (opts.patch_mode || opts.pathspec.nr)
                return checkout_paths(&opts, new.name);
        else
index 9d772f8f27fe722921c00ea57af1087f988856da..522f4fdffd064de2e50232934cb7d616246c92e4 100644 (file)
@@ -56,5 +56,6 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
                return -1;
        }
        result = run_diff_index(&rev, cached);
+       UNLEAK(rev);
        return diff_result_code(&rev.diffopt, result);
 }
index 7e3ebcea38f1485f4c7fb5f5af6494ceb81f5cbb..f5bbd4d757e12e6e34a86fac006298acb771909f 100644 (file)
@@ -464,5 +464,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        result = diff_result_code(&rev.diffopt, result);
        if (1 < rev.diffopt.skip_stat_unmatch)
                refresh_index_quietly();
+       UNLEAK(rev);
+       UNLEAK(ent);
+       UNLEAK(blob);
        return result;
 }
index 598da6c8bc75e9de50f85eac78d3051f27f96a6c..9e088ebd11dced248640df9e17adbbd8b9a73ffb 100644 (file)
@@ -494,5 +494,6 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
                                  always, allow_undefined, data.name_only);
        }
 
+       UNLEAK(revs);
        return 0;
 }
index 29a0f3b75fb02dfa2a02c325816453e36baaa55a..cc4876740569c6e495b7cb32161d019619171d79 100644 (file)
@@ -1458,7 +1458,6 @@ static void execute_commands(struct command *commands,
 {
        struct check_connected_options opt = CHECK_CONNECTED_INIT;
        struct command *cmd;
-       struct object_id oid;
        struct iterate_data data;
        struct async muxer;
        int err_fd = 0;
@@ -1515,7 +1514,7 @@ static void execute_commands(struct command *commands,
        check_aliased_updates(commands);
 
        free(head_name_to_free);
-       head_name = head_name_to_free = resolve_refdup("HEAD", 0, oid.hash, NULL);
+       head_name = head_name_to_free = resolve_refdup("HEAD", 0, NULL, NULL);
 
        if (use_atomic)
                execute_commands_atomic(commands, si);
index 12dbbc56d93f296f09a0f640127311bdeb8c8800..695cb0778e2cad52d829030b00f91a4b230224e1 100644 (file)
@@ -553,9 +553,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        if (force && !is_null_oid(&prev) && oidcmp(&prev, &object))
                printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev.hash, DEFAULT_ABBREV));
 
-       strbuf_release(&err);
-       strbuf_release(&buf);
-       strbuf_release(&ref);
-       strbuf_release(&reflog_msg);
+       UNLEAK(buf);
+       UNLEAK(ref);
+       UNLEAK(reflog_msg);
+       UNLEAK(msg);
+       UNLEAK(err);
        return 0;
 }
index b10adc780fc334383f2684d21fa1c5a8d92771b9..ae03b74a6f4e9c8ff6d519d9a784ab6b84179872 100644 (file)
@@ -438,6 +438,10 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
            pfd[i].revents = happened;
            rc++;
          }
+       else
+         {
+           pfd[i].revents = 0;
+         }
       }
 
   return rc;
index c61d1ca8dc49f1da8dd70cf0c00ce97b1f18fcd2..01586821dc7c15be2a94c30bfbf4f3b4c94ac5f3 100644 (file)
@@ -4,7 +4,7 @@ T *dst;
 T *src;
 expression n;
 @@
-- memcpy(dst, src, n * sizeof(*dst));
+- memcpy(dst, src, (n) * sizeof(*dst));
 + COPY_ARRAY(dst, src, n);
 
 @@
@@ -13,7 +13,7 @@ T *dst;
 T *src;
 expression n;
 @@
-- memcpy(dst, src, n * sizeof(*src));
+- memcpy(dst, src, (n) * sizeof(*src));
 + COPY_ARRAY(dst, src, n);
 
 @@
@@ -22,7 +22,7 @@ T *dst;
 T *src;
 expression n;
 @@
-- memcpy(dst, src, n * sizeof(T));
+- memcpy(dst, src, (n) * sizeof(T));
 + COPY_ARRAY(dst, src, n);
 
 @@
@@ -47,7 +47,7 @@ type T;
 T *ptr;
 expression n;
 @@
-- ptr = xmalloc(n * sizeof(*ptr));
+- ptr = xmalloc((n) * sizeof(*ptr));
 + ALLOC_ARRAY(ptr, n);
 
 @@
@@ -55,5 +55,5 @@ type T;
 T *ptr;
 expression n;
 @@
-- ptr = xmalloc(n * sizeof(T));
+- ptr = xmalloc((n) * sizeof(T));
 + ALLOC_ARRAY(ptr, n);
index 35bf671f12c41ce5a2a9f9224babee792bf71209..d5e4cf0bad411dad859dbe421ab7583cfb0f1561 100644 (file)
@@ -3189,10 +3189,10 @@ static void checkpoint(void)
        checkpoint_requested = 0;
        if (object_count) {
                cycle_packfile();
-               dump_branches();
-               dump_tags();
-               dump_marks();
        }
+       dump_branches();
+       dump_tags();
+       dump_marks();
 }
 
 static void parse_checkpoint(void)
index eebd33276da9028afa1f2ed3b03e60f037d7e646..13c172bd94fc5d4a9658b27fae9733f73a272376 100755 (executable)
@@ -128,7 +128,7 @@ git show -s --format='The following changes since commit %H:
 
   %s (%ci)
 
-are available in the git repository at:
+are available in the Git repository at:
 ' $merge_base &&
 echo "  $url $pretty_remote" &&
 git show -s --format='
diff --git a/graph.c b/graph.c
index e7e20650da6983ada7c94c22aea7ecaec41c5c17..e1f6d3bddb38aadd4e439aea30f542d286ecb98e 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -696,12 +696,8 @@ static void graph_pad_horizontally(struct git_graph *graph, struct strbuf *sb,
         * This way, fields printed to the right of the graph will remain
         * aligned for the entire commit.
         */
-       int extra;
-       if (chars_written >= graph->width)
-               return;
-
-       extra = graph->width - chars_written;
-       strbuf_addf(sb, "%*s", (int) extra, "");
+       if (chars_written < graph->width)
+               strbuf_addchars(sb, ' ', graph->width - chars_written);
 }
 
 static void graph_output_padding_line(struct git_graph *graph,
@@ -787,7 +783,7 @@ static void graph_output_pre_commit_line(struct git_graph *graph,
                if (col->commit == graph->commit) {
                        seen_this = 1;
                        strbuf_write_column(sb, col, '|');
-                       strbuf_addf(sb, "%*s", graph->expansion_row, "");
+                       strbuf_addchars(sb, ' ', graph->expansion_row);
                        chars_written += 1 + graph->expansion_row;
                } else if (seen_this && (graph->expansion_row == 0)) {
                        /*
index d860c477c60e7baec79220d9f06330a139d0e035..493ee7d719d488f25cd6c45bb4c7ce1d5a75977b 100644 (file)
@@ -1018,7 +1018,7 @@ static int get_oid_hex_from_objpath(const char *path, struct object_id *oid)
        memcpy(hex, path, 2);
        path += 2;
        path++; /* skip '/' */
-       memcpy(hex, path, GIT_SHA1_HEXSZ - 2);
+       memcpy(hex + 2, path, GIT_SHA1_HEXSZ - 2);
 
        return get_oid_hex(hex, oid);
 }
diff --git a/path.c b/path.c
index 5aa9244eb24d95717f2b20e207266c289c925757..2e09a7bce0688acccaca8b980c2c337a71885966 100644 (file)
--- a/path.c
+++ b/path.c
@@ -34,11 +34,10 @@ static struct strbuf *get_pathname(void)
        return sb;
 }
 
-static char *cleanup_path(char *path)
+static const char *cleanup_path(const char *path)
 {
        /* Clean it up */
-       if (!memcmp(path, "./", 2)) {
-               path += 2;
+       if (skip_prefix(path, "./", &path)) {
                while (*path == '/')
                        path++;
        }
@@ -47,7 +46,7 @@ static char *cleanup_path(char *path)
 
 static void strbuf_cleanup_path(struct strbuf *sb)
 {
-       char *path = cleanup_path(sb->buf);
+       const char *path = cleanup_path(sb->buf);
        if (path > sb->buf)
                strbuf_remove(sb, 0, path - sb->buf);
 }
@@ -64,7 +63,7 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
                strlcpy(buf, bad_path, n);
                return buf;
        }
-       return cleanup_path(buf);
+       return (char *)cleanup_path(buf);
 }
 
 static int dir_prefix(const char *buf, const char *dir)
@@ -718,7 +717,7 @@ char *expand_user_path(const char *path, int real_home)
                        if (!home)
                                goto return_null;
                        if (real_home)
-                               strbuf_addstr(&user_path, real_path(home));
+                               strbuf_add_real_path(&user_path, home);
                        else
                                strbuf_addstr(&user_path, home);
 #ifdef GIT_WINDOWS_NATIVE
index 94eab5c89ee1a1fa696b9fc491a5846008a2a255..2f6b0ae6c1486660bb37442b991cb1140a9f2bb6 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -1056,6 +1056,24 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
        return 0;
 }
 
+static int match_placeholder_arg(const char *to_parse, const char *candidate,
+                                const char **end)
+{
+       const char *p;
+
+       if (!(skip_prefix(to_parse, candidate, &p)))
+               return 0;
+       if (*p == ',') {
+               *end = p + 1;
+               return 1;
+       }
+       if (*p == ')') {
+               *end = p;
+               return 1;
+       }
+       return 0;
+}
+
 static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                                const char *placeholder,
                                void *context)
@@ -1285,11 +1303,16 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 
        if (skip_prefix(placeholder, "(trailers", &arg)) {
                struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
-               while (*arg == ':') {
-                       if (skip_prefix(arg, ":only", &arg))
-                               opts.only_trailers = 1;
-                       else if (skip_prefix(arg, ":unfold", &arg))
-                               opts.unfold = 1;
+               if (*arg == ':') {
+                       arg++;
+                       for (;;) {
+                               if (match_placeholder_arg(arg, "only", &arg))
+                                       opts.only_trailers = 1;
+                               else if (match_placeholder_arg(arg, "unfold", &arg))
+                                       opts.unfold = 1;
+                               else
+                                       break;
+                       }
                }
                if (*arg == ')') {
                        format_trailers_from_commit(sb, msg + c->subject_off, &opts);
index bc591f4f3de0c07b0cfe3813d5d9daaf1ad44b63..55323620ab2aedc443989a876b4f4c43df6115cf 100644 (file)
@@ -295,9 +295,7 @@ static void if_atom_parser(const struct ref_format *format, struct used_atom *at
 
 static void head_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)
 {
-       struct object_id unused;
-
-       atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, unused.hash, NULL);
+       atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
 }
 
 static struct {
@@ -1317,9 +1315,8 @@ static void populate_value(struct ref_array_item *ref)
        ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
 
        if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
-               struct object_id unused1;
                ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,
-                                            unused1.hash, NULL);
+                                            NULL, NULL);
                if (!ref->symref)
                        ref->symref = "";
        }
index 74ebe5148f6623f0bffd612262519266a8ab2cc4..842b2f77dc3e40a2eb296bfade00d9d2104ff9e1 100644 (file)
@@ -61,11 +61,10 @@ static struct complete_reflogs *read_complete_reflog(const char *ref)
        reflogs->ref = xstrdup(ref);
        for_each_reflog_ent(ref, read_one_reflog, reflogs);
        if (reflogs->nr == 0) {
-               struct object_id oid;
                const char *name;
                void *name_to_free;
                name = name_to_free = resolve_refdup(ref, RESOLVE_REF_READING,
-                                                    oid.hash, NULL);
+                                                    NULL, NULL);
                if (name) {
                        for_each_reflog_ent(name, read_one_reflog, reflogs);
                        free(name_to_free);
@@ -151,9 +150,8 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
                reflogs = item->util;
        else {
                if (*branch == '\0') {
-                       struct object_id oid;
                        free(branch);
-                       branch = resolve_refdup("HEAD", 0, oid.hash, NULL);
+                       branch = resolve_refdup("HEAD", 0, NULL, NULL);
                        if (!branch)
                                die ("No current branch");
 
index 1b6141e718a5c449226c22fdeefb80b591ca3f7e..014dabb0bf3647b9392d6087ebf6c40e1bc68108 100644 (file)
@@ -2494,7 +2494,6 @@ static int files_transaction_prepare(struct ref_store *ref_store,
        struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
        char *head_ref = NULL;
        int head_type;
-       struct object_id head_oid;
        struct files_transaction_backend_data *backend_data;
        struct ref_transaction *packed_transaction = NULL;
 
@@ -2551,7 +2550,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
         */
        head_ref = refs_resolve_refdup(ref_store, "HEAD",
                                       RESOLVE_REF_NO_RECURSE,
-                                      head_oid.hash, &head_type);
+                                      NULL, &head_type);
 
        if (head_ref && !(head_type & REF_ISSYMREF)) {
                FREE_AND_NULL(head_ref);
index 6e85b0bf0bd5efad7617698a4c2f740a9a28fb05..3279d42c5a696434bbcdb85d6244cded1ddbc758 100644 (file)
@@ -1233,8 +1233,8 @@ static int write_with_updates(struct packed_ref_store *refs,
        }
 
        if (ok != ITER_DONE) {
-               strbuf_addf(err, "unable to write packed-refs file: "
-                           "error iterating over old contents");
+               strbuf_addstr(err, "unable to write packed-refs file: "
+                             "error iterating over old contents");
                goto error;
        }
 
index 97c732bd48ca8776203ae0936fe8ee61bb330ad9..bb2fae5446b7ea8d2bfac87faa30c165f714d121 100644 (file)
@@ -200,25 +200,17 @@ int repo_submodule_init(struct repository *submodule,
 
 void repo_clear(struct repository *repo)
 {
-       free(repo->gitdir);
-       repo->gitdir = NULL;
-       free(repo->commondir);
-       repo->commondir = NULL;
-       free(repo->objectdir);
-       repo->objectdir = NULL;
-       free(repo->graft_file);
-       repo->graft_file = NULL;
-       free(repo->index_file);
-       repo->index_file = NULL;
-       free(repo->worktree);
-       repo->worktree = NULL;
-       free(repo->submodule_prefix);
-       repo->submodule_prefix = NULL;
+       FREE_AND_NULL(repo->gitdir);
+       FREE_AND_NULL(repo->commondir);
+       FREE_AND_NULL(repo->objectdir);
+       FREE_AND_NULL(repo->graft_file);
+       FREE_AND_NULL(repo->index_file);
+       FREE_AND_NULL(repo->worktree);
+       FREE_AND_NULL(repo->submodule_prefix);
 
        if (repo->config) {
                git_configset_clear(repo->config);
-               free(repo->config);
-               repo->config = NULL;
+               FREE_AND_NULL(repo->config);
        }
 
        if (repo->submodule_cache) {
@@ -228,8 +220,7 @@ void repo_clear(struct repository *repo)
 
        if (repo->index) {
                discard_index(repo->index);
-               free(repo->index);
-               repo->index = NULL;
+               FREE_AND_NULL(repo->index);
        }
 }
 
index b5e6eb37c0eb3d6ed0cbd4fc35e879bf9fbd3db6..014b2165b5a2f92ff18869effafd4c6df01b33eb 100644 (file)
@@ -452,7 +452,7 @@ static char **prep_childenv(const char *const *deltaenv)
        }
 
        /* Create an array of 'char *' to be used as the childenv */
-       childenv = xmalloc((env.nr + 1) * sizeof(char *));
+       ALLOC_ARRAY(childenv, env.nr + 1);
        for (i = 0; i < env.nr; i++)
                childenv[i] = env.items[i].util;
        childenv[env.nr] = NULL;
index b8c1e876fa7b57986e6ae93873e23f87c45b9e49..7886e2269eb7813cdf9f908002ec70a9561a153c 100644 (file)
@@ -204,7 +204,7 @@ int sequencer_remove_state(struct replay_opts *opts)
                free(opts->xopts[i]);
        free(opts->xopts);
 
-       strbuf_addf(&dir, "%s", get_dir(opts));
+       strbuf_addstr(&dir, get_dir(opts));
        remove_dir_recursively(&dir, 0);
        strbuf_release(&dir);
 
index 7496cb8ec5a1f8baeda90f8653b2fcbbe2527390..0a74acb2369ac26cb56b05a953171330c3abe652 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -82,8 +82,12 @@ extern char strbuf_slopbuf[];
 extern void strbuf_init(struct strbuf *, size_t);
 
 /**
- * Release a string buffer and the memory it used. You should not use the
- * string buffer after using this function, unless you initialize it again.
+ * Release a string buffer and the memory it used. After this call, the
+ * strbuf points to an empty string that does not need to be free()ed, as
+ * if it had been set to `STRBUF_INIT` and never modified.
+ *
+ * To clear a strbuf in preparation for further use without the overhead
+ * of free()ing and malloc()ing again, use strbuf_reset() instead.
  */
 extern void strbuf_release(struct strbuf *);
 
@@ -91,6 +95,9 @@ extern void strbuf_release(struct strbuf *);
  * Detach the string from the strbuf and returns it; you now own the
  * storage the string occupies and it is your responsibility from then on
  * to release it with `free(3)` when you are done with it.
+ *
+ * The strbuf that previously held the string is reset to `STRBUF_INIT` so
+ * it can be reused after calling this function.
  */
 extern char *strbuf_detach(struct strbuf *, size_t *);
 
index 6dde5062bef388fcdd3db10d9af19f8ffc7f7d6f..8d2a1707cfe1a7d0fb6b589f0857a6389a8a3d70 100644 (file)
@@ -77,13 +77,12 @@ int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, co
 {
        int err;
        struct child_process *process;
-       const char *argv[] = { cmd, NULL };
 
        entry->cmd = cmd;
        process = &entry->process;
 
        child_process_init(process);
-       process->argv = argv;
+       argv_array_push(&process->args, cmd);
        process->use_shell = 1;
        process->in = -1;
        process->out = -1;
index c502fa16d307957b6fe23cbd5481fc35f49c00da..829ec3d7d2f58b9538bb3bbab47213eddb9e62ec 100644 (file)
@@ -108,7 +108,7 @@ int cmd_main(int argc, const char **argv)
                 * Split by newline, but don't create a string_list item
                 * for the empty string after the last separator.
                 */
-               if (sb.buf[sb.len - 1] == '\n')
+               if (sb.len && sb.buf[sb.len - 1] == '\n')
                        strbuf_setlen(&sb, sb.len - 1);
                string_list_split_in_place(&list, sb.buf, '\n', -1);
 
index ec5f530102c04080b9d199269583cac9ab924c7e..977472f5390fbe6d1a19c52dd70692ca55dff505 100755 (executable)
@@ -588,8 +588,8 @@ test_expect_success '%(trailers:unfold) unfolds trailers' '
 '
 
 test_expect_success ':only and :unfold work together' '
-       git log --no-walk --pretty="%(trailers:only:unfold)" >actual &&
-       git log --no-walk --pretty="%(trailers:unfold:only)" >reverse &&
+       git log --no-walk --pretty="%(trailers:only,unfold)" >actual &&
+       git log --no-walk --pretty="%(trailers:unfold,only)" >reverse &&
        test_cmp actual reverse &&
        {
                grep -v patch.description <trailers | unfold &&
index 82c33b88e710b5fb6163a7bdcd9ecb783633aa83..08c210f03586ab8cd26d69cb0761180ef5588f58 100755 (executable)
@@ -68,7 +68,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '
        cat <<-\EOT >read-request.sed &&
        #!/bin/sed -nf
        # Note that a request could ask for "tag $tagname"
-       / in the git repository at:$/!d
+       / in the Git repository at:$/!d
        n
        /^$/ n
        s/ tag \([^ ]*\)$/ tag--\1/
@@ -192,7 +192,7 @@ test_expect_success 'pull request format' '
 
          SUBJECT (DATE)
 
-       are available in the git repository at:
+       are available in the Git repository at:
 
          URL BRANCH
 
index 67b8c50a5ab431345de2909209811fc8e4f12548..d47560b6343db7006461259e4808837f3d35eecb 100755 (executable)
@@ -3120,4 +3120,146 @@ test_expect_success 'U: validate root delete result' '
        compare_diff_raw expect actual
 '
 
+###
+### series V (checkpoint)
+###
+
+# The commands in input_file should not produce any output on the file
+# descriptor set with --cat-blob-fd (or stdout if unspecified).
+#
+# To make sure you're observing the side effects of checkpoint *before*
+# fast-import terminates (and thus writes out its state), check that the
+# fast-import process is still running using background_import_still_running
+# *after* evaluating the test conditions.
+background_import_then_checkpoint () {
+       options=$1
+       input_file=$2
+
+       mkfifo V.input
+       exec 8<>V.input
+       rm V.input
+
+       mkfifo V.output
+       exec 9<>V.output
+       rm V.output
+
+       git fast-import $options <&8 >&9 &
+       echo $! >V.pid
+       # We don't mind if fast-import has already died by the time the test
+       # ends.
+       test_when_finished "exec 8>&-; exec 9>&-; kill $(cat V.pid) || true"
+
+       # Start in the background to ensure we adhere strictly to (blocking)
+       # pipes writing sequence. We want to assume that the write below could
+       # block, e.g. if fast-import blocks writing its own output to &9
+       # because there is no reader on &9 yet.
+       (
+               cat "$input_file"
+               echo "checkpoint"
+               echo "progress checkpoint"
+       ) >&8 &
+
+       error=1 ;# assume the worst
+       while read output <&9
+       do
+               if test "$output" = "progress checkpoint"
+               then
+                       error=0
+                       break
+               fi
+               # otherwise ignore cruft
+               echo >&2 "cruft: $output"
+       done
+
+       if test $error -eq 1
+       then
+               false
+       fi
+}
+
+background_import_still_running () {
+       if ! kill -0 "$(cat V.pid)"
+       then
+               echo >&2 "background fast-import terminated too early"
+               false
+       fi
+}
+
+test_expect_success PIPE 'V: checkpoint helper does not get stuck with extra output' '
+       cat >input <<-INPUT_END &&
+       progress foo
+       progress bar
+
+       INPUT_END
+
+       background_import_then_checkpoint "" input &&
+       background_import_still_running
+'
+
+test_expect_success PIPE 'V: checkpoint updates refs after reset' '
+       cat >input <<-\INPUT_END &&
+       reset refs/heads/V
+       from refs/heads/U
+
+       INPUT_END
+
+       background_import_then_checkpoint "" input &&
+       test "$(git rev-parse --verify V)" = "$(git rev-parse --verify U)" &&
+       background_import_still_running
+'
+
+test_expect_success PIPE 'V: checkpoint updates refs and marks after commit' '
+       cat >input <<-INPUT_END &&
+       commit refs/heads/V
+       mark :1
+       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data 0
+       from refs/heads/U
+
+       INPUT_END
+
+       background_import_then_checkpoint "--export-marks=marks.actual" input &&
+
+       echo ":1 $(git rev-parse --verify V)" >marks.expected &&
+
+       test "$(git rev-parse --verify V^)" = "$(git rev-parse --verify U)" &&
+       test_cmp marks.expected marks.actual &&
+       background_import_still_running
+'
+
+# Re-create the exact same commit, but on a different branch: no new object is
+# created in the database, but the refs and marks still need to be updated.
+test_expect_success PIPE 'V: checkpoint updates refs and marks after commit (no new objects)' '
+       cat >input <<-INPUT_END &&
+       commit refs/heads/V2
+       mark :2
+       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data 0
+       from refs/heads/U
+
+       INPUT_END
+
+       background_import_then_checkpoint "--export-marks=marks.actual" input &&
+
+       echo ":2 $(git rev-parse --verify V2)" >marks.expected &&
+
+       test "$(git rev-parse --verify V2)" = "$(git rev-parse --verify V)" &&
+       test_cmp marks.expected marks.actual &&
+       background_import_still_running
+'
+
+test_expect_success PIPE 'V: checkpoint updates tags after tag' '
+       cat >input <<-INPUT_END &&
+       tag Vtag
+       from refs/heads/V
+       tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data 0
+
+       INPUT_END
+
+       background_import_then_checkpoint "" input &&
+       git show-ref -d Vtag &&
+       background_import_still_running
+'
+
 test_done
diff --git a/tag.c b/tag.c
index 7e10acfb6ef1673e783e0a42e1b8810a6e2eff06..fcbe012f7a2203e198dac9eac03aa9dab999f334 100644 (file)
--- a/tag.c
+++ b/tag.c
@@ -142,13 +142,13 @@ int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
        bufptr = nl + 1;
 
        if (!strcmp(type, blob_type)) {
-               item->tagged = &lookup_blob(&oid)->object;
+               item->tagged = (struct object *)lookup_blob(&oid);
        } else if (!strcmp(type, tree_type)) {
-               item->tagged = &lookup_tree(&oid)->object;
+               item->tagged = (struct object *)lookup_tree(&oid);
        } else if (!strcmp(type, commit_type)) {
-               item->tagged = &lookup_commit(&oid)->object;
+               item->tagged = (struct object *)lookup_commit(&oid);
        } else if (!strcmp(type, tag_type)) {
-               item->tagged = &lookup_tag(&oid)->object;
+               item->tagged = (struct object *)lookup_tag(&oid);
        } else {
                error("Unknown type %s", type);
                item->tagged = NULL;
index fb8c01e57a99f35f63690c536e3f623d3695b1de..f1e2f61991424f3314158676754f6b8d305a31f2 100644 (file)
@@ -471,11 +471,10 @@ void transport_print_push_status(const char *dest, struct ref *refs,
 {
        struct ref *ref;
        int n = 0;
-       struct object_id head_oid;
        char *head;
        int summary_width = transport_summary_width(refs);
 
-       head = resolve_refdup("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL);
+       head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
 
        if (verbose) {
                for (ref = refs; ref; ref = ref->next)
index 6f730ee8f22b958c7502656d2e1d01ea1f932396..29bc64cc0280675065142bac257930904216d415 100644 (file)
@@ -121,15 +121,13 @@ static void status_printf_more(struct wt_status *s, const char *color,
 
 void wt_status_prepare(struct wt_status *s)
 {
-       struct object_id oid;
-
        memset(s, 0, sizeof(*s));
        memcpy(s->color_palette, default_wt_status_colors,
               sizeof(default_wt_status_colors));
        s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
        s->use_color = -1;
        s->relative_paths = 1;
-       s->branch = resolve_refdup("HEAD", 0, oid.hash, NULL);
+       s->branch = resolve_refdup("HEAD", 0, NULL, NULL);
        s->reference = "HEAD";
        s->fp = stdout;
        s->index_file = get_index_file();