Merge branch 'js/mingw-create-hard-link'
authorJunio C Hamano <gitster@pobox.com>
Sun, 18 Nov 2018 09:23:58 +0000 (18:23 +0900)
committerJunio C Hamano <gitster@pobox.com>
Sun, 18 Nov 2018 09:23:58 +0000 (18:23 +0900)
Windows update.

* js/mingw-create-hard-link:
mingw: use `CreateHardLink()` directly

78 files changed:
.gitattributes
.mailmap
Documentation/git-range-diff.txt
Documentation/technical/api-parse-options.txt
Makefile
apply.c
attr.c
builtin/am.c
builtin/blame.c
builtin/cat-file.c
builtin/checkout-index.c
builtin/clean.c
builtin/commit.c
builtin/fetch.c
builtin/grep.c
builtin/index-pack.c
builtin/init-db.c
builtin/interpret-trailers.c
builtin/log.c
builtin/ls-files.c
builtin/merge-file.c
builtin/merge.c
builtin/notes.c
builtin/pack-objects.c
builtin/pull.c
builtin/read-tree.c
builtin/rebase.c
builtin/show-branch.c
builtin/show-ref.c
builtin/tag.c
builtin/update-index.c
commit.c
commit.h
compat/win32/pthread.c
compat/win32/pthread.h
config.c
config.mak.uname
configure.ac
grep.c
grep.h
midx.c
name-hash.c
object.h
pack-objects.h
parse-options-cb.c
parse-options.h
preload-index.c
prio-queue.c
prio-queue.h
range-diff.c
read-cache.c
ref-filter.c
refs.c
revision.c
revision.h
run-command.c
run-command.h
send-pack.c
sequencer.c
t/helper/test-parse-options.c
t/helper/test-prio-queue.c
t/lib-gpg/keyring.gpg
t/perf/p3400-rebase.sh
t/t0009-prio-queue.sh
t/t0040-parse-options.sh
t/t3206-range-diff.sh
t/t3420-rebase-autostash.sh
t/t3430-rebase-merges.sh
t/t4136-apply-check.sh
t/t5573-pull-verify-signatures.sh
t/t6012-rev-list-simplify.sh
t/t6018-rev-list-glob.sh
t/t6600-test-reach.sh
t/t7510-signed-commit.sh
t/t7612-merge-verify-signatures.sh
thread-utils.c
thread-utils.h
wt-status.c
index 49b30516419c8dfe8c039ef368a3af984439ebcc..acf853e0299463a12212e9ed5f35d7f4a9d289af 100644 (file)
@@ -5,7 +5,7 @@
 *.pl eof=lf diff=perl
 *.pm eol=lf diff=perl
 *.py eol=lf diff=python
-/Documentation/git-*.txt eol=lf
+/Documentation/**/*.txt eol=lf
 /command-list.txt eol=lf
 /GIT-VERSION-GEN eol=lf
 /mergetools/* eol=lf
index bef3352b0d3c6e84a33304b2fe44f6a68f6044a3..eb7b5fc7b97f33999eced124943728854bc2e983 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -21,6 +21,8 @@ Anders Kaseorg <andersk@MIT.EDU> <andersk@mit.edu>
 Aneesh Kumar K.V <aneesh.kumar@gmail.com>
 Amos Waterland <apw@debian.org> <apw@rossby.metr.ou.edu>
 Amos Waterland <apw@debian.org> <apw@us.ibm.com>
+Ben Peart <benpeart@microsoft.com> <Ben.Peart@microsoft.com>
+Ben Peart <benpeart@microsoft.com> <peartben@gmail.com>
 Ben Walton <bdwalton@gmail.com> <bwalton@artsci.utoronto.ca>
 Benoit Sigoure <tsunanet@gmail.com> <tsuna@lrde.epita.fr>
 Bernt Hansen <bernt@norang.ca> <bernt@alumni.uwaterloo.ca>
@@ -32,6 +34,7 @@ Bryan Larsen <bryan@larsen.st> <bryanlarsen@yahoo.com>
 Cheng Renquan <crquan@gmail.com>
 Chris Shoemaker <c.shoemaker@cox.net>
 Chris Wright <chrisw@sous-sol.org> <chrisw@osdl.org>
+Christian Ludwig <chrissicool@gmail.com> <chrissicool@googlemail.com>
 Cord Seele <cowose@gmail.com> <cowose@googlemail.com>
 Christian Couder <chriscool@tuxfamily.org> <christian.couder@gmail.com>
 Christian Stimming <stimming@tuhh.de> <chs@ckiste.goetheallee>
@@ -51,6 +54,7 @@ David Reiss <dreiss@facebook.com> <dreiss@dreiss-vmware.(none)>
 David S. Miller <davem@davemloft.net>
 David Turner <novalis@novalis.org> <dturner@twopensource.com>
 David Turner <novalis@novalis.org> <dturner@twosigma.com>
+Derrick Stolee <dstolee@microsoft.com> <stolee@gmail.com>
 Deskin Miller <deskinm@umich.edu>
 Dirk Süsserott <newsletter@dirk.my1.cc>
 Eric Blake <eblake@redhat.com> <ebb9@byu.net>
@@ -98,6 +102,7 @@ Jens Axboe <axboe@kernel.dk> <jens.axboe@oracle.com>
 Jens Lindström <jl@opera.com> Jens Lindstrom <jl@opera.com>
 Jim Meyering <jim@meyering.net> <meyering@redhat.com>
 Joachim Berdal Haga <cjhaga@fys.uio.no>
+Joachim Jablon <joachim.jablon@people-doc.com> <ewjoachim@gmail.com>
 Johannes Schindelin <Johannes.Schindelin@gmx.de> <johannes.schindelin@gmx.de>
 Johannes Sixt <j6t@kdbg.org> <J.Sixt@eudaptics.com>
 Johannes Sixt <j6t@kdbg.org> <j.sixt@viscovery.net>
@@ -150,6 +155,7 @@ Mark Levedahl <mdl123@verizon.net> <mlevedahl@gmail.com>
 Mark Rada <marada@uwaterloo.ca>
 Martin Langhoff <martin@laptop.org> <martin@catalyst.net.nz>
 Martin von Zweigbergk <martinvonz@gmail.com> <martin.von.zweigbergk@gmail.com>
+Masaya Suzuki <masayasuzuki@google.com> <draftcode@gmail.com>
 Matt Draisey <matt@draisey.ca> <mattdraisey@sympatico.ca>
 Matt Kraai <kraai@ftbfs.org> <matt.kraai@amo.abbott.com>
 Matt McCutchen <matt@mattmccutchen.net> <hashproduct@gmail.com>
@@ -157,6 +163,7 @@ Matthias Kestenholz <matthias@spinlock.ch> <mk@spinlock.ch>
 Matthias Rüster <matthias.ruester@gmail.com> Matthias Ruester
 Matthias Urlichs <matthias@urlichs.de> <smurf@kiste.(none)>
 Matthias Urlichs <matthias@urlichs.de> <smurf@smurf.noris.de>
+Matthieu Moy <git@matthieu-moy.fr> <Matthieu.Moy@imag.fr>
 Michael Coleman <tutufan@gmail.com>
 Michael J Gruber <git@grubix.eu> <michaeljgruber+gmane@fastmail.fm>
 Michael J Gruber <git@grubix.eu> <git@drmicha.warpmail.net>
@@ -180,7 +187,11 @@ Nick Stokoe <nick@noodlefactory.co.uk> Nick Woolley <nick@noodlefactory.co.uk>
 Nick Stokoe <nick@noodlefactory.co.uk> Nick Woolley <nickwoolley@yahoo.co.uk>
 Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> <nicolas.morey@free.fr>
 Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> <nmorey@kalray.eu>
+Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> <nicolas@morey-chaisemartin.com>
+Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> <NMoreyChaisemartin@suse.com>
+Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> <nmoreychaisemartin@suse.com>
 Nicolas Sebrecht <nicolas.s.dev@gmx.fr> <ni.s@laposte.net>
+Orgad Shaneh <orgads@gmail.com> <orgad.shaneh@audiocodes.com>
 Paolo Bonzini <bonzini@gnu.org> <paolo.bonzini@lu.unisi.ch>
 Pascal Obry <pascal@obry.net> <pascal.obry@gmail.com>
 Pascal Obry <pascal@obry.net> <pascal.obry@wanadoo.fr>
@@ -200,6 +211,7 @@ Philipp A. Hartmann <pah@qo.cx> <ph@sorgh.de>
 Philippe Bruhat <book@cpan.org>
 Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
 Ramsay Jones <ramsay@ramsayjones.plus.com> <ramsay@ramsay1.demon.co.uk>
+Randall S. Becker <randall.becker@nexbridge.ca> <rsbecker@nexbridge.com>
 René Scharfe <l.s.r@web.de> <rene.scharfe@lsrfire.ath.cx>
 René Scharfe <l.s.r@web.de> Rene Scharfe
 Richard Hansen <rhansen@rhansen.org> <hansenr@google.com>
@@ -238,6 +250,7 @@ Steven Walter <stevenrwalter@gmail.com> <swalter@lpdev.prtdev.lexmark.com>
 Sven Verdoolaege <skimo@kotnet.org> <Sven.Verdoolaege@cs.kuleuven.ac.be>
 Sven Verdoolaege <skimo@kotnet.org> <skimo@liacs.nl>
 SZEDER Gábor <szeder.dev@gmail.com> <szeder@ira.uka.de>
+Tao Qingyun <taoqy@ls-a.me> <845767657@qq.com>
 Tay Ray Chuan <rctay89@gmail.com>
 Ted Percival <ted@midg3t.net> <ted.percival@quest.com>
 Theodore Ts'o <tytso@mit.edu>
index f693930fdb502ac85cf99eae4d206c3d4962b247..8a6ea2c6c5c7a39a9f34d6b93388f3343c1e3026 100644 (file)
@@ -78,6 +78,23 @@ between patches", i.e. to compare the author, commit message and diff of
 corresponding old/new commits. There is currently no means to tweak the
 diff options passed to `git log` when generating those patches.
 
+OUTPUT STABILITY
+----------------
+
+The output of the `range-diff` command is subject to change. It is
+intended to be human-readable porcelain output, not something that can
+be used across versions of Git to get a textually stable `range-diff`
+(as opposed to something like the `--stable` option to
+linkgit:git-patch-id[1]). There's also no equivalent of
+linkgit:git-apply[1] for `range-diff`, the output is not intended to
+be machine-readable.
+
+This is particularly true when passing in diff options. Currently some
+options like `--stat` can, as an emergent effect, produce output
+that's quite useless in the context of `range-diff`. Future versions
+of `range-diff` may learn to interpret such options in a manner
+specific to `range-diff` (e.g. for `--stat` producing human-readable
+output which summarizes how the diffstat changed).
 
 CONFIGURATION
 -------------
index 829b5581105468d4d3b457e60b10cdbdf317fbbc..2b036d7838ef906153a29cf0e17d57a1dbe93109 100644 (file)
@@ -183,10 +183,6 @@ There are some macros to easily define options:
        scale the provided value by 1024, 1024^2 or 1024^3 respectively.
        The scaled value is put into `unsigned_long_var`.
 
-`OPT_DATE(short, long, &timestamp_t_var, description)`::
-       Introduce an option with date argument, see `approxidate()`.
-       The timestamp is put into `timestamp_t_var`.
-
 `OPT_EXPIRY_DATE(short, long, &timestamp_t_var, description)`::
        Introduce an option with expiry date argument, see `parse_expiry_date()`.
        The timestamp is put into `timestamp_t_var`.
index 016fdcdb817c00b2bced052a92c8a421bfef0e73..827e9633780c84a11f294a7005de5d1fe1d1580d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -59,6 +59,13 @@ all::
 # Define CURL_CONFIG to curl's configuration program that prints information
 # about the library (e.g., its version number).  The default is 'curl-config'.
 #
+# Define CURL_LDFLAGS to specify flags that you need to link when using libcurl,
+# if you do not want to rely on the libraries provided by CURL_CONFIG.  The
+# default value is a result of `curl-config --libs`.  An example value for
+# CURL_LDFLAGS is as follows:
+#
+#     CURL_LDFLAGS=-lcurl
+#
 # Define NO_EXPAT if you do not have expat installed.  git-http-push is
 # not built, and you cannot push using http:// and https:// transports (dumb).
 #
@@ -183,10 +190,6 @@ all::
 #
 # Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
 #
-# Define NEEDS_SSL_WITH_CURL if you need -lssl with -lcurl (Minix).
-#
-# Define NEEDS_IDN_WITH_CURL if you need -lidn when using -lcurl (Minix).
-#
 # Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
 #
 # Define NEEDS_LIBINTL_BEFORE_LIBICONV if you need libintl before libiconv.
@@ -993,6 +996,7 @@ LIB_OBJS += sub-process.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += tempfile.o
+LIB_OBJS += thread-utils.o
 LIB_OBJS += tmp-objdir.o
 LIB_OBJS += trace.o
 LIB_OBJS += trailer.o
@@ -1308,20 +1312,17 @@ else
        ifdef CURLDIR
                # Try "-Wl,-rpath=$(CURLDIR)/$(lib)" in such a case.
                BASIC_CFLAGS += -I$(CURLDIR)/include
-               CURL_LIBCURL = -L$(CURLDIR)/$(lib) $(CC_LD_DYNPATH)$(CURLDIR)/$(lib) -lcurl
+               CURL_LIBCURL = -L$(CURLDIR)/$(lib) $(CC_LD_DYNPATH)$(CURLDIR)/$(lib)
        else
-               CURL_LIBCURL = -lcurl
-       endif
-       ifdef NEEDS_SSL_WITH_CURL
-               CURL_LIBCURL += -lssl
-               ifdef NEEDS_CRYPTO_WITH_SSL
-                       CURL_LIBCURL += -lcrypto
-               endif
-       endif
-       ifdef NEEDS_IDN_WITH_CURL
-               CURL_LIBCURL += -lidn
+               CURL_LIBCURL =
        endif
 
+ifdef CURL_LDFLAGS
+       CURL_LIBCURL += $(CURL_LDFLAGS)
+else
+       CURL_LIBCURL += $(shell $(CURL_CONFIG) --libs)
+endif
+
        REMOTE_CURL_PRIMARY = git-remote-http$X
        REMOTE_CURL_ALIASES = git-remote-https$X git-remote-ftp$X git-remote-ftps$X
        REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
@@ -1677,7 +1678,6 @@ ifdef NO_PTHREADS
 else
        BASIC_CFLAGS += $(PTHREAD_CFLAGS)
        EXTLIBS += $(PTHREAD_LIBS)
-       LIB_OBJS += thread-utils.o
 endif
 
 ifdef HAVE_PATHS_H
@@ -2111,7 +2111,7 @@ $(SCRIPT_LIB) : % : %.sh GIT-SCRIPT-DEFINES
        $(QUIET_GEN)$(cmd_munge_script) && \
        mv $@+ $@
 
-git.res: git.rc GIT-VERSION-FILE
+git.res: git.rc GIT-VERSION-FILE GIT-PREFIX
        $(QUIET_RC)$(RC) \
          $(join -DMAJOR= -DMINOR= -DMICRO= -DPATCHLEVEL=, $(wordlist 1, 4, \
            $(shell echo $(GIT_VERSION) 0 0 0 0 | tr '.a-zA-Z-' ' '))) \
diff --git a/apply.c b/apply.c
index 073d5f04512ac6febc2949040f53ef273433f3c0..01793d612620246b14fa57f6ce3ed6c33df65d0f 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -1748,7 +1748,7 @@ static int parse_fragment(struct apply_state *state,
        }
        if (oldlines || newlines)
                return -1;
-       if (!deleted && !added)
+       if (!patch->recount && !deleted && !added)
                return -1;
 
        fragment->leading = leading;
@@ -4772,6 +4772,9 @@ static int apply_option_parse_exclude(const struct option *opt,
                                      const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+
        add_name_limit(state, arg, 1);
        return 0;
 }
@@ -4780,6 +4783,9 @@ static int apply_option_parse_include(const struct option *opt,
                                      const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+
        add_name_limit(state, arg, 0);
        state->has_include = 1;
        return 0;
@@ -4790,6 +4796,9 @@ static int apply_option_parse_p(const struct option *opt,
                                int unset)
 {
        struct apply_state *state = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+
        state->p_value = atoi(arg);
        state->p_value_known = 1;
        return 0;
@@ -4799,6 +4808,9 @@ static int apply_option_parse_space_change(const struct option *opt,
                                           const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
+
+       BUG_ON_OPT_ARG(arg);
+
        if (unset)
                state->ws_ignore_action = ignore_ws_none;
        else
@@ -4810,9 +4822,12 @@ static int apply_option_parse_whitespace(const struct option *opt,
                                         const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+
        state->whitespace_option = arg;
        if (parse_whitespace_option(state, arg))
-               exit(1);
+               return -1;
        return 0;
 }
 
@@ -4820,6 +4835,9 @@ static int apply_option_parse_directory(const struct option *opt,
                                        const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+
        strbuf_reset(&state->root);
        strbuf_addstr(&state->root, arg);
        strbuf_complete(&state->root, '/');
@@ -4939,10 +4957,10 @@ int apply_parse_options(int argc, const char **argv,
        struct option builtin_apply_options[] = {
                { OPTION_CALLBACK, 0, "exclude", state, N_("path"),
                        N_("don't apply changes matching the given path"),
-                       0, apply_option_parse_exclude },
+                       PARSE_OPT_NONEG, apply_option_parse_exclude },
                { OPTION_CALLBACK, 0, "include", state, N_("path"),
                        N_("apply changes matching the given path"),
-                       0, apply_option_parse_include },
+                       PARSE_OPT_NONEG, apply_option_parse_include },
                { OPTION_CALLBACK, 'p', NULL, state, N_("num"),
                        N_("remove <num> leading slashes from traditional diff paths"),
                        0, apply_option_parse_p },
diff --git a/attr.c b/attr.c
index 60d284796de728f59b839865eb035e1289a1a060..eaece6658d64b2129332ffab39e30485730f3306 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -41,23 +41,17 @@ const char *git_attr_name(const struct git_attr *attr)
 
 struct attr_hashmap {
        struct hashmap map;
-#ifndef NO_PTHREADS
        pthread_mutex_t mutex;
-#endif
 };
 
 static inline void hashmap_lock(struct attr_hashmap *map)
 {
-#ifndef NO_PTHREADS
        pthread_mutex_lock(&map->mutex);
-#endif
 }
 
 static inline void hashmap_unlock(struct attr_hashmap *map)
 {
-#ifndef NO_PTHREADS
        pthread_mutex_unlock(&map->mutex);
-#endif
 }
 
 /*
@@ -498,23 +492,17 @@ static struct check_vector {
        size_t nr;
        size_t alloc;
        struct attr_check **checks;
-#ifndef NO_PTHREADS
        pthread_mutex_t mutex;
-#endif
 } check_vector;
 
 static inline void vector_lock(void)
 {
-#ifndef NO_PTHREADS
        pthread_mutex_lock(&check_vector.mutex);
-#endif
 }
 
 static inline void vector_unlock(void)
 {
-#ifndef NO_PTHREADS
        pthread_mutex_unlock(&check_vector.mutex);
-#endif
 }
 
 static void check_vector_add(struct attr_check *c)
@@ -1181,8 +1169,6 @@ void git_all_attrs(const struct index_state *istate,
 
 void attr_start(void)
 {
-#ifndef NO_PTHREADS
        pthread_mutex_init(&g_attr_hashmap.mutex, NULL);
        pthread_mutex_init(&check_vector.mutex, NULL);
-#endif
 }
index dc576a33728f5c2264acf66fcbe3243284144781..8f27f3375b1e92f2ef026e0a1530ca8b6b3235bf 100644 (file)
@@ -2113,7 +2113,9 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
 {
        int *opt_value = opt->value;
 
-       if (!strcmp(arg, "mbox"))
+       if (unset)
+               *opt_value = PATCH_FORMAT_UNKNOWN;
+       else if (!strcmp(arg, "mbox"))
                *opt_value = PATCH_FORMAT_MBOX;
        else if (!strcmp(arg, "stgit"))
                *opt_value = PATCH_FORMAT_STGIT;
index a443af9ee9dad5ec20de7e75640947c221e7aa6a..06a7163ffe269cd43dc783c81ca6ac71b91b3614 100644 (file)
@@ -732,6 +732,8 @@ static int blame_copy_callback(const struct option *option, const char *arg, int
 {
        int *opt = option->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        /*
         * -C enables copy from removed files;
         * -C -C enables copy from existing files, but only
@@ -754,6 +756,8 @@ static int blame_move_callback(const struct option *option, const char *arg, int
 {
        int *opt = option->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        *opt |= PICKAXE_BLAME_MOVE;
 
        if (arg)
index 0d403eb77d37d3b409d7d8ef030c12b91fe63da6..657fe926e2ae884012a8987e7a5753f4277384d7 100644 (file)
@@ -603,8 +603,10 @@ static int batch_option_callback(const struct option *opt,
 {
        struct batch_options *bo = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (bo->enabled) {
-               return 1;
+               return error(_("only one batch option may be specified"));
        }
 
        bo->enabled = 1;
@@ -639,10 +641,12 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
                OPT_BOOL(0, "buffer", &batch.buffer_output, N_("buffer --batch output")),
                { OPTION_CALLBACK, 0, "batch", &batch, "format",
                        N_("show info and content of objects fed from the standard input"),
-                       PARSE_OPT_OPTARG, batch_option_callback },
+                       PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
+                       batch_option_callback },
                { OPTION_CALLBACK, 0, "batch-check", &batch, "format",
                        N_("show info about objects fed from the standard input"),
-                       PARSE_OPT_OPTARG, batch_option_callback },
+                       PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
+                       batch_option_callback },
                OPT_BOOL(0, "follow-symlinks", &batch.follow_symlinks,
                         N_("follow in-tree symlinks (used with --batch or --batch-check)")),
                OPT_BOOL(0, "batch-all-objects", &batch.all_objects,
index 88b86c8d9f5a0ea9c49b42e891082203b80a977f..eb74774cbc9d6bd6acf1b7fe2f31b8e80e461a12 100644 (file)
@@ -132,6 +132,8 @@ static const char * const builtin_checkout_index_usage[] = {
 static int option_parse_stage(const struct option *opt,
                              const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
+
        if (!strcmp(arg, "all")) {
                to_tempfile = 1;
                checkout_stage = CHECKOUT_ALL;
index 8d9a7dc20647079bc5f35b446bbbab5479abb32d..bbcdeb2d9e7f275309609a2a21a5dd4baf1cf1bd 100644 (file)
@@ -140,6 +140,7 @@ static void clean_print_color(enum color_clean ix)
 static int exclude_cb(const struct option *opt, const char *arg, int unset)
 {
        struct string_list *exclude_list = opt->value;
+       BUG_ON_OPT_NEG(unset);
        string_list_append(exclude_list, arg);
        return 0;
 }
index 96d336ec3d8044918fb260d6cf8c03296cf32ed1..c021b119bb9df106ab7a860e032ea5dd35529401 100644 (file)
@@ -161,6 +161,9 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 static int opt_parse_rename_score(const struct option *opt, const char *arg, int unset)
 {
        const char **value = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+
        if (arg != NULL && *arg == '=')
                arg = arg + 1;
 
@@ -1335,7 +1338,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
                OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")),
                { OPTION_CALLBACK, 'M', "find-renames", &rename_score_arg,
                  N_("n"), N_("detect renames, optionally set similarity index"),
-                 PARSE_OPT_OPTARG, opt_parse_rename_score },
+                 PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_rename_score },
                OPT_END(),
        };
 
index 6ec7c07d1dc111e6370dad498bf7453b5cd2c92e..e0140327aab23654c69e7388c23a07b98b8ff913 100644 (file)
@@ -98,6 +98,8 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
 
 static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
+
        /*
         * "git fetch --refmap='' origin foo"
         * can be used to tell the command not to store anywhere
index 56e4a110526379d1df69615a0ade611c2a82c17d..71df52a333cbc756b057e93bf3d2affca8157860 100644 (file)
@@ -34,7 +34,6 @@ static int recurse_submodules;
 #define GREP_NUM_THREADS_DEFAULT 8
 static int num_threads;
 
-#ifndef NO_PTHREADS
 static pthread_t *threads;
 
 /* We use one producer thread and THREADS consumer
@@ -70,13 +69,11 @@ static pthread_mutex_t grep_mutex;
 
 static inline void grep_lock(void)
 {
-       assert(num_threads);
        pthread_mutex_lock(&grep_mutex);
 }
 
 static inline void grep_unlock(void)
 {
-       assert(num_threads);
        pthread_mutex_unlock(&grep_mutex);
 }
 
@@ -234,6 +231,9 @@ static int wait_all(void)
        int hit = 0;
        int i;
 
+       if (!HAVE_THREADS)
+               BUG("Never call this function unless you have started threads");
+
        grep_lock();
        all_work_added = 1;
 
@@ -265,13 +265,6 @@ static int wait_all(void)
 
        return hit;
 }
-#else /* !NO_PTHREADS */
-
-static int wait_all(void)
-{
-       return 0;
-}
-#endif
 
 static int grep_cmd_config(const char *var, const char *value, void *cb)
 {
@@ -284,17 +277,15 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
                if (num_threads < 0)
                        die(_("invalid number of threads specified (%d) for %s"),
                            num_threads, var);
-#ifdef NO_PTHREADS
-               else if (num_threads && num_threads != 1) {
+               else if (!HAVE_THREADS && num_threads > 1) {
                        /*
                         * TRANSLATORS: %s is the configuration
                         * variable for tweaking threads, currently
                         * grep.threads
                         */
                        warning(_("no threads support, ignoring %s"), var);
-                       num_threads = 0;
+                       num_threads = 1;
                }
-#endif
        }
 
        if (!strcmp(var, "submodule.recurse"))
@@ -330,17 +321,14 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
        grep_source_init(&gs, GREP_SOURCE_OID, pathbuf.buf, path, oid);
        strbuf_release(&pathbuf);
 
-#ifndef NO_PTHREADS
-       if (num_threads) {
+       if (num_threads > 1) {
                /*
                 * add_work() copies gs and thus assumes ownership of
                 * its fields, so do not call grep_source_clear()
                 */
                add_work(opt, &gs);
                return 0;
-       } else
-#endif
-       {
+       } else {
                int hit;
 
                hit = grep_source(opt, &gs);
@@ -363,17 +351,14 @@ static int grep_file(struct grep_opt *opt, const char *filename)
        grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename, filename);
        strbuf_release(&buf);
 
-#ifndef NO_PTHREADS
-       if (num_threads) {
+       if (num_threads > 1) {
                /*
                 * add_work() copies gs and thus assumes ownership of
                 * its fields, so do not call grep_source_clear()
                 */
                add_work(opt, &gs);
                return 0;
-       } else
-#endif
-       {
+       } else {
                int hit;
 
                hit = grep_source(opt, &gs);
@@ -723,11 +708,14 @@ static int context_callback(const struct option *opt, const char *arg,
 static int file_callback(const struct option *opt, const char *arg, int unset)
 {
        struct grep_opt *grep_opt = opt->value;
-       int from_stdin = !strcmp(arg, "-");
+       int from_stdin;
        FILE *patterns;
        int lno = 0;
        struct strbuf sb = STRBUF_INIT;
 
+       BUG_ON_OPT_NEG(unset);
+
+       from_stdin = !strcmp(arg, "-");
        patterns = from_stdin ? stdin : fopen(arg, "r");
        if (!patterns)
                die_errno(_("cannot open '%s'"), arg);
@@ -748,6 +736,8 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
 static int not_callback(const struct option *opt, const char *arg, int unset)
 {
        struct grep_opt *grep_opt = opt->value;
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
        return 0;
 }
@@ -755,6 +745,8 @@ static int not_callback(const struct option *opt, const char *arg, int unset)
 static int and_callback(const struct option *opt, const char *arg, int unset)
 {
        struct grep_opt *grep_opt = opt->value;
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
        return 0;
 }
@@ -762,6 +754,8 @@ static int and_callback(const struct option *opt, const char *arg, int unset)
 static int open_callback(const struct option *opt, const char *arg, int unset)
 {
        struct grep_opt *grep_opt = opt->value;
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
        return 0;
 }
@@ -769,6 +763,8 @@ static int open_callback(const struct option *opt, const char *arg, int unset)
 static int close_callback(const struct option *opt, const char *arg, int unset)
 {
        struct grep_opt *grep_opt = opt->value;
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
        return 0;
 }
@@ -777,6 +773,7 @@ static int pattern_callback(const struct option *opt, const char *arg,
                            int unset)
 {
        struct grep_opt *grep_opt = opt->value;
+       BUG_ON_OPT_NEG(unset);
        append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
        return 0;
 }
@@ -1049,39 +1046,35 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        pathspec.recursive = 1;
        pathspec.recurse_submodules = !!recurse_submodules;
 
-#ifndef NO_PTHREADS
-       if (list.nr || cached || show_in_pager)
-               num_threads = 0;
-       else if (num_threads == 0)
-               num_threads = GREP_NUM_THREADS_DEFAULT;
-       else if (num_threads < 0)
-               die(_("invalid number of threads specified (%d)"), num_threads);
-       if (num_threads == 1)
-               num_threads = 0;
-#else
-       if (num_threads)
+       if (list.nr || cached || show_in_pager) {
+               if (num_threads > 1)
+                       warning(_("invalid option combination, ignoring --threads"));
+               num_threads = 1;
+       } else if (!HAVE_THREADS && num_threads > 1) {
                warning(_("no threads support, ignoring --threads"));
-       num_threads = 0;
-#endif
+               num_threads = 1;
+       } else if (num_threads < 0)
+               die(_("invalid number of threads specified (%d)"), num_threads);
+       else if (num_threads == 0)
+               num_threads = HAVE_THREADS ? GREP_NUM_THREADS_DEFAULT : 1;
 
-       if (!num_threads)
+       if (num_threads > 1) {
+               if (!HAVE_THREADS)
+                       BUG("Somebody got num_threads calculation wrong!");
+               if (!(opt.name_only || opt.unmatch_name_only || opt.count)
+                   && (opt.pre_context || opt.post_context ||
+                       opt.file_break || opt.funcbody))
+                       skip_first_line = 1;
+               start_threads(&opt);
+       } else {
                /*
                 * The compiled patterns on the main path are only
                 * used when not using threading. Otherwise
-                * start_threads() below calls compile_grep_patterns()
+                * start_threads() above calls compile_grep_patterns()
                 * for each thread.
                 */
                compile_grep_patterns(&opt);
-
-#ifndef NO_PTHREADS
-       if (num_threads) {
-               if (!(opt.name_only || opt.unmatch_name_only || opt.count)
-                   && (opt.pre_context || opt.post_context ||
-                       opt.file_break || opt.funcbody))
-                       skip_first_line = 1;
-               start_threads(&opt);
        }
-#endif
 
        if (show_in_pager && (cached || list.nr))
                die(_("--open-files-in-pager only works on the worktree"));
@@ -1132,7 +1125,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                hit = grep_objects(&opt, &pathspec, &list);
        }
 
-       if (num_threads)
+       if (num_threads > 1)
                hit |= wait_all();
        if (hit && show_in_pager)
                run_pager(&opt, prefix);
index 2004e25da230c7d9f0b1e951d8a59dca2d9d08b8..682042579b36828864cb74d41d84a7cff0516bab 100644 (file)
@@ -42,9 +42,7 @@ struct base_data {
 };
 
 struct thread_local {
-#ifndef NO_PTHREADS
        pthread_t thread;
-#endif
        struct base_data *base_cache;
        size_t base_cache_used;
        int pack_fd;
@@ -98,8 +96,6 @@ static uint32_t input_crc32;
 static int input_fd, output_fd;
 static const char *curr_pack;
 
-#ifndef NO_PTHREADS
-
 static struct thread_local *thread_data;
 static int nr_dispatched;
 static int threads_active;
@@ -179,26 +175,6 @@ static void cleanup_thread(void)
        free(thread_data);
 }
 
-#else
-
-#define read_lock()
-#define read_unlock()
-
-#define counter_lock()
-#define counter_unlock()
-
-#define work_lock()
-#define work_unlock()
-
-#define deepest_delta_lock()
-#define deepest_delta_unlock()
-
-#define type_cas_lock()
-#define type_cas_unlock()
-
-#endif
-
-
 static int mark_link(struct object *obj, int type, void *data, struct fsck_options *options)
 {
        if (!obj)
@@ -364,22 +340,20 @@ static NORETURN void bad_object(off_t offset, const char *format, ...)
 
 static inline struct thread_local *get_thread_data(void)
 {
-#ifndef NO_PTHREADS
-       if (threads_active)
-               return pthread_getspecific(key);
-       assert(!threads_active &&
-              "This should only be reached when all threads are gone");
-#endif
+       if (HAVE_THREADS) {
+               if (threads_active)
+                       return pthread_getspecific(key);
+               assert(!threads_active &&
+                      "This should only be reached when all threads are gone");
+       }
        return &nothread_data;
 }
 
-#ifndef NO_PTHREADS
 static void set_thread_data(struct thread_local *data)
 {
        if (threads_active)
                pthread_setspecific(key, data);
 }
-#endif
 
 static struct base_data *alloc_base_data(void)
 {
@@ -1092,7 +1066,6 @@ static void resolve_base(struct object_entry *obj)
        find_unresolved_deltas(base_obj);
 }
 
-#ifndef NO_PTHREADS
 static void *threaded_second_pass(void *data)
 {
        set_thread_data(data);
@@ -1116,7 +1089,6 @@ static void *threaded_second_pass(void *data)
        }
        return NULL;
 }
-#endif
 
 /*
  * First pass:
@@ -1213,7 +1185,6 @@ static void resolve_deltas(void)
                progress = start_progress(_("Resolving deltas"),
                                          nr_ref_deltas + nr_ofs_deltas);
 
-#ifndef NO_PTHREADS
        nr_dispatched = 0;
        if (nr_threads > 1 || getenv("GIT_FORCE_THREADS")) {
                init_thread();
@@ -1229,7 +1200,6 @@ static void resolve_deltas(void)
                cleanup_thread();
                return;
        }
-#endif
 
        for (i = 0; i < nr_objects; i++) {
                struct object_entry *obj = &objects[i];
@@ -1531,11 +1501,10 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
                if (nr_threads < 0)
                        die(_("invalid number of threads specified (%d)"),
                            nr_threads);
-#ifdef NO_PTHREADS
-               if (nr_threads != 1)
+               if (!HAVE_THREADS && nr_threads != 1) {
                        warning(_("no threads support, ignoring %s"), k);
-               nr_threads = 1;
-#endif
+                       nr_threads = 1;
+               }
                return 0;
        }
        return git_default_config(k, v, cb);
@@ -1723,12 +1692,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
                                nr_threads = strtoul(arg+10, &end, 0);
                                if (!arg[10] || *end || nr_threads < 0)
                                        usage(index_pack_usage);
-#ifdef NO_PTHREADS
-                               if (nr_threads != 1)
-                                       warning(_("no threads support, "
-                                                 "ignoring %s"), arg);
-                               nr_threads = 1;
-#endif
+                               if (!HAVE_THREADS && nr_threads != 1) {
+                                       warning(_("no threads support, ignoring %s"), arg);
+                                       nr_threads = 1;
+                               }
                        } else if (starts_with(arg, "--pack_header=")) {
                                struct pack_header *hdr;
                                char *c;
@@ -1791,14 +1758,12 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
        if (strict)
                opts.flags |= WRITE_IDX_STRICT;
 
-#ifndef NO_PTHREADS
-       if (!nr_threads) {
+       if (HAVE_THREADS && !nr_threads) {
                nr_threads = online_cpus();
                /* An experiment showed that more threads does not mean faster */
                if (nr_threads > 3)
                        nr_threads = 3;
        }
-#endif
 
        curr_pack = open_pack_file(pack_name);
        parse_pack_header();
index 12ddda7e7bac51f74b2f7ca8a2b64ffe90fd8683..41faffd28db8850fb97daa52c6d481375b380504 100644 (file)
@@ -451,6 +451,7 @@ static int guess_repository_type(const char *git_dir)
 
 static int shared_callback(const struct option *opt, const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
        *((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP;
        return 0;
 }
index 4b87e0dd2e8854bf940e92e3020c5e4f66e8a6bd..8ae40dec4746571cf80d2f76bbad067c33a972fa 100644 (file)
@@ -80,6 +80,8 @@ static int parse_opt_parse(const struct option *opt, const char *arg,
        v->only_trailers = 1;
        v->only_input = 1;
        v->unfold = 1;
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        return 0;
 }
 
index 061d4fd864f3fb479e2877e3bbf25928ad1fb9d3..9f2d9872946dfd7fe527a7f3822d9be23aa5ec83 100644 (file)
@@ -107,6 +107,8 @@ static int log_line_range_callback(const struct option *option, const char *arg,
 {
        struct line_opt_callback_data *data = option->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (!arg)
                return -1;
 
@@ -1151,6 +1153,8 @@ static int keep_subject = 0;
 
 static int keep_callback(const struct option *opt, const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        ((struct rev_info *)opt->value)->total = -1;
        keep_subject = 1;
        return 0;
@@ -1161,6 +1165,7 @@ static int subject_prefix = 0;
 static int subject_prefix_callback(const struct option *opt, const char *arg,
                            int unset)
 {
+       BUG_ON_OPT_NEG(unset);
        subject_prefix = 1;
        ((struct rev_info *)opt->value)->subject_prefix = arg;
        return 0;
@@ -1168,6 +1173,8 @@ static int subject_prefix_callback(const struct option *opt, const char *arg,
 
 static int rfc_callback(const struct option *opt, const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        return subject_prefix_callback(opt, "RFC PATCH", unset);
 }
 
@@ -1176,6 +1183,7 @@ static int numbered_cmdline_opt = 0;
 static int numbered_callback(const struct option *opt, const char *arg,
                             int unset)
 {
+       BUG_ON_OPT_ARG(arg);
        *(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
        if (unset)
                auto_number =  0;
@@ -1185,6 +1193,7 @@ static int numbered_callback(const struct option *opt, const char *arg,
 static int no_numbered_callback(const struct option *opt, const char *arg,
                                int unset)
 {
+       BUG_ON_OPT_NEG(unset);
        return numbered_callback(opt, arg, 1);
 }
 
@@ -1192,6 +1201,7 @@ static int output_directory_callback(const struct option *opt, const char *arg,
                              int unset)
 {
        const char **dir = (const char **)opt->value;
+       BUG_ON_OPT_NEG(unset);
        if (*dir)
                die(_("Two output directories?"));
        *dir = arg;
@@ -1508,7 +1518,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                            PARSE_OPT_NOARG, numbered_callback },
                { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
                            N_("use [PATCH] even with multiple patches"),
-                           PARSE_OPT_NOARG, no_numbered_callback },
+                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback },
                OPT_BOOL('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
                OPT_BOOL(0, "stdout", &use_stdout,
                            N_("print patches to standard out")),
index 7f9919a36234f603ffe76d7324fafc7f5872d404..c70a9c71588a76b2ef04689fc6cd805cee4ae0b8 100644 (file)
@@ -475,6 +475,8 @@ static int option_parse_exclude(const struct option *opt,
 {
        struct string_list *exclude_list = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        exc_given = 1;
        string_list_append(exclude_list, arg);
 
@@ -486,6 +488,8 @@ static int option_parse_exclude_from(const struct option *opt,
 {
        struct dir_struct *dir = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        exc_given = 1;
        add_excludes_from_file(dir, arg);
 
@@ -497,6 +501,9 @@ static int option_parse_exclude_standard(const struct option *opt,
 {
        struct dir_struct *dir = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
+
        exc_given = 1;
        setup_standard_excludes(dir);
 
@@ -548,15 +555,16 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                            N_("show resolve-undo information")),
                { OPTION_CALLBACK, 'x', "exclude", &exclude_list, N_("pattern"),
                        N_("skip files matching pattern"),
-                       0, option_parse_exclude },
+                       PARSE_OPT_NONEG, option_parse_exclude },
                { OPTION_CALLBACK, 'X', "exclude-from", &dir, N_("file"),
                        N_("exclude patterns are read from <file>"),
-                       0, option_parse_exclude_from },
+                       PARSE_OPT_NONEG, option_parse_exclude_from },
                OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, N_("file"),
                        N_("read additional per-directory exclude patterns in <file>")),
                { OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
                        N_("add the standard git exclusions"),
-                       PARSE_OPT_NOARG, option_parse_exclude_standard },
+                       PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+                       option_parse_exclude_standard },
                OPT_SET_INT_F(0, "full-name", &prefix_len,
                              N_("make the output relative to the project top directory"),
                              0, PARSE_OPT_NONEG),
index b08803e61119a569e2ca5a33402666d8978d9ff0..06a2f90c4875f2a8ff82a927071ac584ad929f8b 100644 (file)
@@ -15,6 +15,8 @@ static int label_cb(const struct option *opt, const char *arg, int unset)
        static int label_count = 0;
        const char **names = (const char **)opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (label_count >= 3)
                return error("too many labels on the command line");
        names[label_count++] = arg;
index 4aa60715980f2f226d752e9d7fe0df4ecdcc369d..c3c976d471ce78268e673a5135a4c37ebc6d0f6d 100644 (file)
@@ -224,6 +224,7 @@ static int option_parse_x(const struct option *opt,
 static int option_parse_n(const struct option *opt,
                          const char *arg, int unset)
 {
+       BUG_ON_OPT_ARG(arg);
        show_diffstat = unset;
        return 0;
 }
@@ -1336,6 +1337,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        die(_("%s - not something we can merge"), argv[0]);
                if (remoteheads->next)
                        die(_("Can merge only exactly one commit into empty head"));
+
+               if (verify_signatures)
+                       verify_merge_signature(remoteheads->item, verbosity);
+
                remote_head_oid = &remoteheads->item->object.oid;
                read_empty(remote_head_oid, 0);
                update_ref("initial pull", "HEAD", remote_head_oid, NULL, 0,
@@ -1357,31 +1362,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
        if (verify_signatures) {
                for (p = remoteheads; p; p = p->next) {
-                       struct commit *commit = p->item;
-                       char hex[GIT_MAX_HEXSZ + 1];
-                       struct signature_check signature_check;
-                       memset(&signature_check, 0, sizeof(signature_check));
-
-                       check_commit_signature(commit, &signature_check);
-
-                       find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
-                       switch (signature_check.result) {
-                       case 'G':
-                               break;
-                       case 'U':
-                               die(_("Commit %s has an untrusted GPG signature, "
-                                     "allegedly by %s."), hex, signature_check.signer);
-                       case 'B':
-                               die(_("Commit %s has a bad GPG signature "
-                                     "allegedly by %s."), hex, signature_check.signer);
-                       default: /* 'N' */
-                               die(_("Commit %s does not have a GPG signature."), hex);
-                       }
-                       if (verbosity >= 0 && signature_check.result == 'G')
-                               printf(_("Commit %s has a good GPG signature by %s\n"),
-                                      hex, signature_check.signer);
-
-                       signature_check_clear(&signature_check);
+                       verify_merge_signature(p->item, verbosity);
                }
        }
 
index c05cd004abcbdcd1e4c3d140f3cf4251c416df36..c78b7a0c5b7fbea81320ae9873553c437d82e73e 100644 (file)
@@ -215,6 +215,8 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
 {
        struct note_data *d = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        strbuf_grow(&d->buf, strlen(arg) + 2);
        if (d->buf.len)
                strbuf_addch(&d->buf, '\n');
@@ -229,6 +231,8 @@ static int parse_file_arg(const struct option *opt, const char *arg, int unset)
 {
        struct note_data *d = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (d->buf.len)
                strbuf_addch(&d->buf, '\n');
        if (!strcmp(arg, "-")) {
@@ -250,15 +254,15 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
        enum object_type type;
        unsigned long len;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (d->buf.len)
                strbuf_addch(&d->buf, '\n');
 
        if (get_oid(arg, &object))
                die(_("failed to resolve '%s' as a valid ref."), arg);
-       if (!(buf = read_object_file(&object, &type, &len))) {
-               free(buf);
+       if (!(buf = read_object_file(&object, &type, &len)))
                die(_("failed to read object '%s'."), arg);
-       }
        if (type != OBJ_BLOB) {
                free(buf);
                die(_("cannot read note data from non-blob object '%s'."), arg);
@@ -273,6 +277,7 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
 static int parse_reedit_arg(const struct option *opt, const char *arg, int unset)
 {
        struct note_data *d = opt->value;
+       BUG_ON_OPT_NEG(unset);
        d->use_editor = 1;
        return parse_reuse_arg(opt, arg, unset);
 }
index c99ee79c31a84a3f67735cb44e85c156f63ad966..794714e4f8703c0efed76fc37006fba05496f660 100644 (file)
@@ -1953,8 +1953,6 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
        return 0;
 }
 
-#ifndef NO_PTHREADS
-
 /* Protect access to object database */
 static pthread_mutex_t read_mutex;
 #define read_lock()            pthread_mutex_lock(&read_mutex)
@@ -1979,16 +1977,6 @@ static pthread_mutex_t progress_mutex;
  * ahead in the list because they can be stolen and would need
  * progress_mutex for protection.
  */
-#else
-
-#define read_lock()            (void)0
-#define read_unlock()          (void)0
-#define cache_lock()           (void)0
-#define cache_unlock()         (void)0
-#define progress_lock()                (void)0
-#define progress_unlock()      (void)0
-
-#endif
 
 /*
  * Return the size of the object without doing any delta
@@ -2347,8 +2335,6 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
        free(array);
 }
 
-#ifndef NO_PTHREADS
-
 static void try_to_free_from_threads(size_t size)
 {
        read_lock();
@@ -2577,10 +2563,6 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
        free(p);
 }
 
-#else
-#define ll_find_deltas(l, s, w, d, p)  find_deltas(l, &s, w, d, p)
-#endif
-
 static void add_tag_chain(const struct object_id *oid)
 {
        struct tag *tag;
@@ -2733,12 +2715,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
                if (delta_search_threads < 0)
                        die(_("invalid number of threads specified (%d)"),
                            delta_search_threads);
-#ifdef NO_PTHREADS
-               if (delta_search_threads != 1) {
+               if (!HAVE_THREADS && delta_search_threads != 1) {
                        warning(_("no threads support, ignoring %s"), k);
                        delta_search_threads = 0;
                }
-#endif
                return 0;
        }
        if (!strcmp(k, "pack.indexversion")) {
@@ -3207,6 +3187,9 @@ static int option_parse_index_version(const struct option *opt,
 {
        char *c;
        const char *val = arg;
+
+       BUG_ON_OPT_NEG(unset);
+
        pack_idx_opts.version = strtoul(val, &c, 10);
        if (pack_idx_opts.version > 2)
                die(_("unsupported index version %s"), val);
@@ -3253,7 +3236,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                         N_("similar to --all-progress when progress meter is shown")),
                { OPTION_CALLBACK, 0, "index-version", NULL, N_("<version>[,<offset>]"),
                  N_("write the pack index file in the specified idx format version"),
-                 0, option_parse_index_version },
+                 PARSE_OPT_NONEG, option_parse_index_version },
                OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit,
                              N_("maximum size of each output pack file")),
                OPT_BOOL(0, "local", &local,
@@ -3402,10 +3385,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        if (!delta_search_threads)      /* --threads=0 means autodetect */
                delta_search_threads = online_cpus();
 
-#ifdef NO_PTHREADS
-       if (delta_search_threads != 1)
+       if (!HAVE_THREADS && delta_search_threads != 1)
                warning(_("no threads support, ignoring --threads"));
-#endif
        if (!pack_to_stdout && !pack_size_limit)
                pack_size_limit = pack_size_limit_cfg;
        if (pack_to_stdout && pack_size_limit)
index c21aa276f1e93ef2593397d5304e72d59e6914b0..1b90622b1311187612ef8b33995c92a6802eb343 100644 (file)
@@ -557,6 +557,17 @@ static int run_fetch(const char *repo, const char **refspecs)
 static int pull_into_void(const struct object_id *merge_head,
                const struct object_id *curr_head)
 {
+       if (opt_verify_signatures) {
+               struct commit *commit;
+
+               commit = lookup_commit(the_repository, merge_head);
+               if (!commit)
+                       die(_("unable to access commit %s"),
+                           oid_to_hex(merge_head));
+
+               verify_merge_signature(commit, opt_verbosity);
+       }
+
        /*
         * Two-way merge: we treat the index as based on an empty tree,
         * and try to fast-forward to HEAD. This ensures we will not lose
index fbbc98e5161f011a25743a528e6bb3f85e415f51..183ee8c1e5d4de53d10e9ed00c624f615baf3fc9 100644 (file)
@@ -44,6 +44,7 @@ static const char * const read_tree_usage[] = {
 static int index_output_cb(const struct option *opt, const char *arg,
                                 int unset)
 {
+       BUG_ON_OPT_NEG(unset);
        set_alternate_index_output(arg);
        return 0;
 }
@@ -54,6 +55,8 @@ static int exclude_per_directory_cb(const struct option *opt, const char *arg,
        struct dir_struct *dir;
        struct unpack_trees_options *opts;
 
+       BUG_ON_OPT_NEG(unset);
+
        opts = (struct unpack_trees_options *)opt->value;
 
        if (opts->dir)
index 0ee06aa3631ee89761d570b433994cc77302742e..59e6f7852f5cd2ca77e0aef721f2875edd7a6794 100644 (file)
@@ -23,6 +23,7 @@
 #include "revision.h"
 #include "commit-reach.h"
 #include "rerere.h"
+#include "branch.h"
 
 static char const * const builtin_rebase_usage[] = {
        N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
@@ -522,12 +523,17 @@ static int run_specific_rebase(struct rebase_options *opts)
 
 #define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
 
+#define RESET_HEAD_DETACH (1<<0)
+#define RESET_HEAD_HARD (1<<1)
+
 static int reset_head(struct object_id *oid, const char *action,
-                     const char *switch_to_branch, int detach_head,
+                     const char *switch_to_branch, unsigned flags,
                      const char *reflog_orig_head, const char *reflog_head)
 {
+       unsigned detach_head = flags & RESET_HEAD_DETACH;
+       unsigned reset_hard = flags & RESET_HEAD_HARD;
        struct object_id head_oid;
-       struct tree_desc desc;
+       struct tree_desc desc[2] = { { NULL }, { NULL } };
        struct lock_file lock = LOCK_INIT;
        struct unpack_trees_options unpack_tree_opts;
        struct tree *tree;
@@ -536,60 +542,62 @@ static int reset_head(struct object_id *oid, const char *action,
        size_t prefix_len;
        struct object_id *orig = NULL, oid_orig,
                *old_orig = NULL, oid_old_orig;
-       int ret = 0;
+       int ret = 0, nr = 0;
 
        if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
                BUG("Not a fully qualified branch: '%s'", switch_to_branch);
 
-       if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0)
-               return -1;
+       if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) {
+               ret = -1;
+               goto leave_reset_head;
+       }
 
-       if (!oid) {
-               if (get_oid("HEAD", &head_oid)) {
-                       rollback_lock_file(&lock);
-                       return error(_("could not determine HEAD revision"));
-               }
-               oid = &head_oid;
+       if ((!oid || !reset_hard) && get_oid("HEAD", &head_oid)) {
+               ret = error(_("could not determine HEAD revision"));
+               goto leave_reset_head;
        }
 
+       if (!oid)
+               oid = &head_oid;
+
        memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
        setup_unpack_trees_porcelain(&unpack_tree_opts, action);
        unpack_tree_opts.head_idx = 1;
        unpack_tree_opts.src_index = the_repository->index;
        unpack_tree_opts.dst_index = the_repository->index;
-       unpack_tree_opts.fn = oneway_merge;
+       unpack_tree_opts.fn = reset_hard ? oneway_merge : twoway_merge;
        unpack_tree_opts.update = 1;
        unpack_tree_opts.merge = 1;
        if (!detach_head)
                unpack_tree_opts.reset = 1;
 
        if (read_index_unmerged(the_repository->index) < 0) {
-               rollback_lock_file(&lock);
-               return error(_("could not read index"));
+               ret = error(_("could not read index"));
+               goto leave_reset_head;
        }
 
-       if (!fill_tree_descriptor(&desc, oid)) {
-               error(_("failed to find tree of %s"), oid_to_hex(oid));
-               rollback_lock_file(&lock);
-               free((void *)desc.buffer);
-               return -1;
+       if (!reset_hard && !fill_tree_descriptor(&desc[nr++], &head_oid)) {
+               ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
+               goto leave_reset_head;
        }
 
-       if (unpack_trees(1, &desc, &unpack_tree_opts)) {
-               rollback_lock_file(&lock);
-               free((void *)desc.buffer);
-               return -1;
+       if (!fill_tree_descriptor(&desc[nr++], oid)) {
+               ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
+               goto leave_reset_head;
+       }
+
+       if (unpack_trees(nr, desc, &unpack_tree_opts)) {
+               ret = -1;
+               goto leave_reset_head;
        }
 
        tree = parse_tree_indirect(oid);
        prime_cache_tree(the_repository->index, tree);
 
-       if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0)
+       if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0) {
                ret = error(_("could not write index"));
-       free((void *)desc.buffer);
-
-       if (ret)
-               return ret;
+               goto leave_reset_head;
+       }
 
        reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
        strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase");
@@ -613,7 +621,8 @@ static int reset_head(struct object_id *oid, const char *action,
                reflog_head = msg.buf;
        }
        if (!switch_to_branch)
-               ret = update_ref(reflog_head, "HEAD", oid, orig, REF_NO_DEREF,
+               ret = update_ref(reflog_head, "HEAD", oid, orig,
+                                detach_head ? REF_NO_DEREF : 0,
                                 UPDATE_REFS_MSG_ON_ERR);
        else {
                ret = create_symref("HEAD", switch_to_branch, msg.buf);
@@ -622,7 +631,11 @@ static int reset_head(struct object_id *oid, const char *action,
                                         UPDATE_REFS_MSG_ON_ERR);
        }
 
+leave_reset_head:
        strbuf_release(&msg);
+       rollback_lock_file(&lock);
+       while (nr)
+               free((void *)desc[--nr].buffer);
        return ret;
 }
 
@@ -703,6 +716,9 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
 {
        struct rebase_options *opts = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
+
        if (!is_interactive(opts))
                opts->type = REBASE_MERGE;
 
@@ -715,6 +731,9 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
 {
        struct rebase_options *opts = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
+
        opts->type = REBASE_INTERACTIVE;
        opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
 
@@ -1000,8 +1019,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                rerere_clear(&merge_rr);
                string_list_clear(&merge_rr, 1);
 
-               if (reset_head(NULL, "reset", NULL, 0, NULL, NULL) < 0)
+               if (reset_head(NULL, "reset", NULL, RESET_HEAD_HARD,
+                              NULL, NULL) < 0)
                        die(_("could not discard worktree changes"));
+               remove_branch_state();
                if (read_basic_state(&options))
                        exit(1);
                goto run_rebase;
@@ -1016,9 +1037,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                if (read_basic_state(&options))
                        exit(1);
                if (reset_head(&options.orig_head, "reset",
-                              options.head_name, 0, NULL, NULL) < 0)
+                              options.head_name, RESET_HEAD_HARD,
+                              NULL, NULL) < 0)
                        die(_("could not move back to %s"),
                            oid_to_hex(&options.orig_head));
+               remove_branch_state();
                ret = finish_rebase(&options);
                goto cleanup;
        }
@@ -1380,7 +1403,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                        write_file(autostash, "%s", oid_to_hex(&oid));
                        printf(_("Created autostash: %s\n"), buf.buf);
                        if (reset_head(&head->object.oid, "reset --hard",
-                                      NULL, 0, NULL, NULL) < 0)
+                                      NULL, RESET_HEAD_HARD, NULL, NULL) < 0)
                                die(_("could not reset --hard"));
                        printf(_("HEAD is now at %s"),
                               find_unique_abbrev(&head->object.oid,
@@ -1500,8 +1523,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                         "it...\n"));
 
        strbuf_addf(&msg, "rebase: checkout %s", options.onto_name);
-       if (reset_head(&options.onto->object.oid, "checkout", NULL, 1,
-           NULL, msg.buf))
+       if (reset_head(&options.onto->object.oid, "checkout", NULL,
+                      RESET_HEAD_DETACH, NULL, msg.buf))
                die(_("Could not detach HEAD"));
        strbuf_release(&msg);
 
index 65f4a4c83c42ec33d5ffe3f1d83d7b5465c0796d..934e5149448783e32acc8b605f202384af7d96ee 100644 (file)
@@ -604,6 +604,7 @@ static int parse_reflog_param(const struct option *opt, const char *arg,
 {
        char *ep;
        const char **base = (const char **)opt->value;
+       BUG_ON_OPT_NEG(unset);
        if (!arg)
                arg = "";
        reflog = strtoul(arg, &ep, 10);
@@ -674,7 +675,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
                            N_("show <n> most recent ref-log entries starting at "
                               "base"),
-                           PARSE_OPT_OPTARG,
+                           PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
                            parse_reflog_param },
                OPT_END()
        };
index 2f13f1316fadc2fc860fac75a161b47f7d11e391..ed888ffa48ce1d5ef80859b8f5b3bf1720e49abd 100644 (file)
@@ -151,6 +151,7 @@ static int hash_callback(const struct option *opt, const char *arg, int unset)
 static int exclude_existing_callback(const struct option *opt, const char *arg,
                                     int unset)
 {
+       BUG_ON_OPT_NEG(unset);
        exclude_arg = 1;
        *(const char **)opt->value = arg;
        return 0;
index f6236321865773cb60907bfe8b56d96bbaf3e83a..02f6bd1279d9c360f97d04ebba0b1f88ff2f27e1 100644 (file)
@@ -338,6 +338,8 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
 {
        struct msg_arg *msg = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (!arg)
                return -1;
        if (msg->buf.len)
@@ -390,8 +392,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                OPT_GROUP(N_("Tag creation options")),
                OPT_BOOL('a', "annotate", &annotate,
                                        N_("annotated tag, needs a message")),
-               OPT_CALLBACK('m', "message", &msg, N_("message"),
-                            N_("tag message"), parse_msg_arg),
+               { OPTION_CALLBACK, 'm', "message", &msg, N_("message"),
+                 N_("tag message"), PARSE_OPT_NONEG, parse_msg_arg },
                OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
                OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")),
                OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
index 0e1dcf0438f7b2ec37b404d3f2acb7bd70650b67..31e7cce3013a3b3f358834f24848fc73b67f8e8b 100644 (file)
@@ -790,12 +790,16 @@ static int refresh(struct refresh_params *o, unsigned int flag)
 static int refresh_callback(const struct option *opt,
                                const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        return refresh(opt->value, 0);
 }
 
 static int really_refresh_callback(const struct option *opt,
                                const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        return refresh(opt->value, REFRESH_REALLY);
 }
 
@@ -803,6 +807,7 @@ static int chmod_callback(const struct option *opt,
                                const char *arg, int unset)
 {
        char *flip = opt->value;
+       BUG_ON_OPT_NEG(unset);
        if ((arg[0] != '-' && arg[0] != '+') || arg[1] != 'x' || arg[2])
                return error("option 'chmod' expects \"+x\" or \"-x\"");
        *flip = arg[0];
@@ -812,6 +817,8 @@ static int chmod_callback(const struct option *opt,
 static int resolve_undo_clear_callback(const struct option *opt,
                                const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
        resolve_undo_clear();
        return 0;
 }
@@ -847,6 +854,8 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
        unsigned int mode;
        const char *path;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) {
                if (add_cacheinfo(mode, &oid, path, 0))
                        die("git update-index: --cacheinfo cannot add %s", path);
@@ -869,6 +878,8 @@ static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx,
 {
        int *nul_term_line = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (ctx->argc != 1)
                return error("option '%s' must be the last argument", opt->long_name);
        allow_add = allow_replace = allow_remove = 1;
@@ -881,6 +892,8 @@ static int stdin_callback(struct parse_opt_ctx_t *ctx,
 {
        int *read_from_stdin = opt->value;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (ctx->argc != 1)
                return error("option '%s' must be the last argument", opt->long_name);
        *read_from_stdin = 1;
@@ -888,11 +901,13 @@ static int stdin_callback(struct parse_opt_ctx_t *ctx,
 }
 
 static int unresolve_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int flags)
+                               const struct option *opt, int unset)
 {
        int *has_errors = opt->value;
        const char *prefix = startup_info->prefix;
 
+       BUG_ON_OPT_NEG(unset);
+
        /* consume remaining arguments. */
        *has_errors = do_unresolve(ctx->argc, ctx->argv,
                                prefix, prefix ? strlen(prefix) : 0);
@@ -905,11 +920,13 @@ static int unresolve_callback(struct parse_opt_ctx_t *ctx,
 }
 
 static int reupdate_callback(struct parse_opt_ctx_t *ctx,
-                               const struct option *opt, int flags)
+                               const struct option *opt, int unset)
 {
        int *has_errors = opt->value;
        const char *prefix = startup_info->prefix;
 
+       BUG_ON_OPT_NEG(unset);
+
        /* consume remaining arguments. */
        setup_work_tree();
        *has_errors = do_reupdate(ctx->argc, ctx->argv,
index d566d7e45c17cfa53493f228dbe46f2f92713ac9..d13a7bc3746406bdaf0bda0975c25b40111afe47 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -657,11 +657,10 @@ struct commit *pop_commit(struct commit_list **stack)
 /* count number of children that have not been emitted */
 define_commit_slab(indegree_slab, int);
 
-/* record author-date for each commit object */
 define_commit_slab(author_date_slab, timestamp_t);
 
-static void record_author_date(struct author_date_slab *author_date,
-                              struct commit *commit)
+void record_author_date(struct author_date_slab *author_date,
+                       struct commit *commit)
 {
        const char *buffer = get_commit_buffer(commit, NULL);
        struct ident_split ident;
@@ -686,8 +685,8 @@ static void record_author_date(struct author_date_slab *author_date,
        unuse_commit_buffer(commit, buffer);
 }
 
-static int compare_commits_by_author_date(const void *a_, const void *b_,
-                                         void *cb_data)
+int compare_commits_by_author_date(const void *a_, const void *b_,
+                                  void *cb_data)
 {
        const struct commit *a = a_, *b = b_;
        struct author_date_slab *author_date = cb_data;
@@ -1100,7 +1099,33 @@ int check_commit_signature(const struct commit *commit, struct signature_check *
        return ret;
 }
 
+void verify_merge_signature(struct commit *commit, int verbosity)
+{
+       char hex[GIT_MAX_HEXSZ + 1];
+       struct signature_check signature_check;
+       memset(&signature_check, 0, sizeof(signature_check));
+
+       check_commit_signature(commit, &signature_check);
+
+       find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
+       switch (signature_check.result) {
+       case 'G':
+               break;
+       case 'U':
+               die(_("Commit %s has an untrusted GPG signature, "
+                     "allegedly by %s."), hex, signature_check.signer);
+       case 'B':
+               die(_("Commit %s has a bad GPG signature "
+                     "allegedly by %s."), hex, signature_check.signer);
+       default: /* 'N' */
+               die(_("Commit %s does not have a GPG signature."), hex);
+       }
+       if (verbosity >= 0 && signature_check.result == 'G')
+               printf(_("Commit %s has a good GPG signature by %s\n"),
+                      hex, signature_check.signer);
 
+       signature_check_clear(&signature_check);
+}
 
 void append_merge_tag_headers(struct commit_list *parents,
                              struct commit_extra_header ***tail)
index 8f15cfd43b602f0b85eda82fb9af90eef7996b6c..98664536cb82c65f04a1742c3e5c1e269afc9493 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -8,6 +8,7 @@
 #include "gpg-interface.h"
 #include "string-list.h"
 #include "pretty.h"
+#include "commit-slab.h"
 
 #define COMMIT_NOT_FROM_GRAPH 0xFFFFFFFF
 #define GENERATION_NUMBER_INFINITY 0xFFFFFFFF
@@ -333,6 +334,20 @@ extern int remove_signature(struct strbuf *buf);
  */
 extern int check_commit_signature(const struct commit *commit, struct signature_check *sigc);
 
+/* record author-date for each commit object */
+struct author_date_slab;
+void record_author_date(struct author_date_slab *author_date,
+                       struct commit *commit);
+
+int compare_commits_by_author_date(const void *a_, const void *b_, void *unused);
+
+/*
+ * Verify a single commit with check_commit_signature() and die() if it is not
+ * a good signature. This isn't really suitable for general use, but is a
+ * helper to implement consistent logic for pull/merge --verify-signatures.
+ */
+void verify_merge_signature(struct commit *commit, int verbose);
+
 int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
 int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused);
 
index e18f5c6e2e55a4b42f178e3042301cd77a654d80..2e7eead42cb008980c7a3b4de63050897c2996da 100644 (file)
@@ -56,141 +56,3 @@ pthread_t pthread_self(void)
        t.tid = GetCurrentThreadId();
        return t;
 }
-
-int pthread_cond_init(pthread_cond_t *cond, const void *unused)
-{
-       cond->waiters = 0;
-       cond->was_broadcast = 0;
-       InitializeCriticalSection(&cond->waiters_lock);
-
-       cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
-       if (!cond->sema)
-               die("CreateSemaphore() failed");
-
-       cond->continue_broadcast = CreateEvent(NULL,    /* security */
-                               FALSE,                  /* auto-reset */
-                               FALSE,                  /* not signaled */
-                               NULL);                  /* name */
-       if (!cond->continue_broadcast)
-               die("CreateEvent() failed");
-
-       return 0;
-}
-
-int pthread_cond_destroy(pthread_cond_t *cond)
-{
-       CloseHandle(cond->sema);
-       CloseHandle(cond->continue_broadcast);
-       DeleteCriticalSection(&cond->waiters_lock);
-       return 0;
-}
-
-int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
-{
-       int last_waiter;
-
-       EnterCriticalSection(&cond->waiters_lock);
-       cond->waiters++;
-       LeaveCriticalSection(&cond->waiters_lock);
-
-       /*
-        * Unlock external mutex and wait for signal.
-        * NOTE: we've held mutex locked long enough to increment
-        * waiters count above, so there's no problem with
-        * leaving mutex unlocked before we wait on semaphore.
-        */
-       LeaveCriticalSection(mutex);
-
-       /* let's wait - ignore return value */
-       WaitForSingleObject(cond->sema, INFINITE);
-
-       /*
-        * Decrease waiters count. If we are the last waiter, then we must
-        * notify the broadcasting thread that it can continue.
-        * But if we continued due to cond_signal, we do not have to do that
-        * because the signaling thread knows that only one waiter continued.
-        */
-       EnterCriticalSection(&cond->waiters_lock);
-       cond->waiters--;
-       last_waiter = cond->was_broadcast && cond->waiters == 0;
-       LeaveCriticalSection(&cond->waiters_lock);
-
-       if (last_waiter) {
-               /*
-                * cond_broadcast was issued while mutex was held. This means
-                * that all other waiters have continued, but are contending
-                * for the mutex at the end of this function because the
-                * broadcasting thread did not leave cond_broadcast, yet.
-                * (This is so that it can be sure that each waiter has
-                * consumed exactly one slice of the semaphor.)
-                * The last waiter must tell the broadcasting thread that it
-                * can go on.
-                */
-               SetEvent(cond->continue_broadcast);
-               /*
-                * Now we go on to contend with all other waiters for
-                * the mutex. Auf in den Kampf!
-                */
-       }
-       /* lock external mutex again */
-       EnterCriticalSection(mutex);
-
-       return 0;
-}
-
-/*
- * IMPORTANT: This implementation requires that pthread_cond_signal
- * is called while the mutex is held that is used in the corresponding
- * pthread_cond_wait calls!
- */
-int pthread_cond_signal(pthread_cond_t *cond)
-{
-       int have_waiters;
-
-       EnterCriticalSection(&cond->waiters_lock);
-       have_waiters = cond->waiters > 0;
-       LeaveCriticalSection(&cond->waiters_lock);
-
-       /*
-        * Signal only when there are waiters
-        */
-       if (have_waiters)
-               return ReleaseSemaphore(cond->sema, 1, NULL) ?
-                       0 : err_win_to_posix(GetLastError());
-       else
-               return 0;
-}
-
-/*
- * DOUBLY IMPORTANT: This implementation requires that pthread_cond_broadcast
- * is called while the mutex is held that is used in the corresponding
- * pthread_cond_wait calls!
- */
-int pthread_cond_broadcast(pthread_cond_t *cond)
-{
-       EnterCriticalSection(&cond->waiters_lock);
-
-       if ((cond->was_broadcast = cond->waiters > 0)) {
-               /* wake up all waiters */
-               ReleaseSemaphore(cond->sema, cond->waiters, NULL);
-               LeaveCriticalSection(&cond->waiters_lock);
-               /*
-                * At this point all waiters continue. Each one takes its
-                * slice of the semaphor. Now it's our turn to wait: Since
-                * the external mutex is held, no thread can leave cond_wait,
-                * yet. For this reason, we can be sure that no thread gets
-                * a chance to eat *more* than one slice. OTOH, it means
-                * that the last waiter must send us a wake-up.
-                */
-               WaitForSingleObject(cond->continue_broadcast, INFINITE);
-               /*
-                * Since the external mutex is held, no thread can enter
-                * cond_wait, and, hence, it is safe to reset this flag
-                * without cond->waiters_lock held.
-                */
-               cond->was_broadcast = 0;
-       } else {
-               LeaveCriticalSection(&cond->waiters_lock);
-       }
-       return 0;
-}
index 1c164088fbb64d2f0143f536f3186f481d876d28..c6cb8dd2190062b3c3db2ac93a996c859a2e1145 100644 (file)
@@ -32,27 +32,13 @@ typedef int pthread_mutexattr_t;
 #define pthread_mutexattr_settype(a, t) 0
 #define PTHREAD_MUTEX_RECURSIVE 0
 
-/*
- * Implement simple condition variable for Windows threads, based on ACE
- * implementation.
- *
- * See original implementation: http://bit.ly/1vkDjo
- * ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html
- * See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
- */
-typedef struct {
-       LONG waiters;
-       int was_broadcast;
-       CRITICAL_SECTION waiters_lock;
-       HANDLE sema;
-       HANDLE continue_broadcast;
-} pthread_cond_t;
-
-extern int pthread_cond_init(pthread_cond_t *cond, const void *unused);
-extern int pthread_cond_destroy(pthread_cond_t *cond);
-extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex);
-extern int pthread_cond_signal(pthread_cond_t *cond);
-extern int pthread_cond_broadcast(pthread_cond_t *cond);
+#define pthread_cond_t CONDITION_VARIABLE
+
+#define pthread_cond_init(a,b) InitializeConditionVariable((a))
+#define pthread_cond_destroy(a) do {} while (0)
+#define pthread_cond_wait(a,b) return_0(SleepConditionVariableCS((a), (b), INFINITE))
+#define pthread_cond_signal WakeConditionVariable
+#define pthread_cond_broadcast WakeAllConditionVariable
 
 /*
  * Simple thread creation implementation using pthread API
index 2ffd39c22006beaf8c4b0941d82183dd3b756955..04286f7717645c6812c7236a282c34f5ad353eb7 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1668,6 +1668,8 @@ static int do_git_config_sequence(const struct config_options *opts,
 
        if (opts->commondir)
                repo_config = mkpathdup("%s/config", opts->commondir);
+       else if (opts->git_dir)
+               BUG("git_dir without commondir");
        else
                repo_config = NULL;
 
index f179d7a1dc98d091f915dcca9ceb05dda5491549..3ee7da0e230c4c33e79ae2f3cf498a5cd7cc4881 100644 (file)
@@ -430,8 +430,6 @@ ifeq ($(uname_S),Minix)
        NO_NSEC = YesPlease
        NEEDS_LIBGEN =
        NEEDS_CRYPTO_WITH_SSL = YesPlease
-       NEEDS_IDN_WITH_CURL = YesPlease
-       NEEDS_SSL_WITH_CURL = YesPlease
        NEEDS_RESOLV =
        NO_HSTRERROR = YesPlease
        NO_MMAP = YesPlease
@@ -457,7 +455,6 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
        # Missdetected, hence commented out, see below.
        #NO_CURL = YesPlease
        # Added manually, see above.
-       NEEDS_SSL_WITH_CURL = YesPlease
        HAVE_LIBCHARSET_H = YesPlease
        HAVE_STRINGS_H = YesPlease
        NEEDS_LIBICONV = YesPlease
index e11b7976ab1c93d8ccec2e499d0093db42551059..44e8c036b6ec417e95ca4e5c2861785900d8634c 100644 (file)
@@ -600,17 +600,14 @@ AC_CHECK_PROG([CURL_CONFIG], [curl-config],
 
 if test $CURL_CONFIG != no; then
     GIT_CONF_SUBST([CURL_CONFIG])
-    if test -z "${NO_OPENSSL}"; then
-      AC_MSG_CHECKING([if Curl supports SSL])
-      if test $(curl-config --features|grep SSL) = SSL; then
-         NEEDS_SSL_WITH_CURL=YesPlease
-         AC_MSG_RESULT([yes])
-      else
-         NEEDS_SSL_WITH_CURL=
-         AC_MSG_RESULT([no])
-      fi
-      GIT_CONF_SUBST([NEEDS_SSL_WITH_CURL])
+
+    if test -z "$CURL_CONFIG_OPTS"; then
+        CURL_CONFIG_OPTS="--libs"
     fi
+
+    CURL_LDFLAGS=$($CURL_CONFIG $CURL_CONFIG_OPTS)
+    AC_MSG_NOTICE([Setting CURL_LDFLAGS to '$CURL_LDFLAGS'])
+    GIT_CONF_SUBST([CURL_LDFLAGS], [$CURL_LDFLAGS])
 fi
 
 fi
diff --git a/grep.c b/grep.c
index f6bd89e40b7f7a8442a6e0a302a1e6080df5afbd..4db1510d167c9fc3cc7b129c90aa874a4c7c2b0f 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -1513,7 +1513,6 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
        }
 }
 
-#ifndef NO_PTHREADS
 int grep_use_locks;
 
 /*
@@ -1539,11 +1538,6 @@ static inline void grep_attr_unlock(void)
  */
 pthread_mutex_t grep_read_mutex;
 
-#else
-#define grep_attr_lock()
-#define grep_attr_unlock()
-#endif
-
 static int match_funcname(struct grep_opt *opt, struct grep_source *gs, char *bol, char *eol)
 {
        xdemitconf_t *xecfg = opt->priv;
diff --git a/grep.h b/grep.h
index 1a57d12b906fb07a9041f52b109dcdb4c7478bfa..fb0489372169d7f1563a09e050c8715542ce5963 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -229,7 +229,6 @@ int grep_source(struct grep_opt *opt, struct grep_source *gs);
 extern struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
 extern int grep_threads_ok(const struct grep_opt *opt);
 
-#ifndef NO_PTHREADS
 /*
  * Mutex used around access to the attributes machinery if
  * opt->use_threads.  Must be initialized/destroyed by callers!
@@ -250,9 +249,4 @@ static inline void grep_read_unlock(void)
                pthread_mutex_unlock(&grep_read_mutex);
 }
 
-#else
-#define grep_read_lock()
-#define grep_read_unlock()
-#endif
-
 #endif
diff --git a/midx.c b/midx.c
index a50b117b777d2659a6d930997ced4f43fbbc3e46..730ff84dff6cb23e4ba2218e956629dc1465744b 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -721,12 +721,18 @@ static size_t write_midx_object_offsets(struct hashfile *f, int large_offset_nee
 static size_t write_midx_large_offsets(struct hashfile *f, uint32_t nr_large_offset,
                                       struct pack_midx_entry *objects, uint32_t nr_objects)
 {
-       struct pack_midx_entry *list = objects;
+       struct pack_midx_entry *list = objects, *end = objects + nr_objects;
        size_t written = 0;
 
        while (nr_large_offset) {
-               struct pack_midx_entry *obj = list++;
-               uint64_t offset = obj->offset;
+               struct pack_midx_entry *obj;
+               uint64_t offset;
+
+               if (list >= end)
+                       BUG("too many large-offset objects");
+
+               obj = list++;
+               offset = obj->offset;
 
                if (!(offset >> 31))
                        continue;
index 1fcda73cb396e305a75aa8dc5869aaf85011761e..623ca6923a9ec78b9bb7d7cc899af72057d101d3 100644 (file)
@@ -7,6 +7,7 @@
  */
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "thread-utils.h"
 
 struct dir_entry {
        struct hashmap_entry ent;
@@ -131,22 +132,6 @@ static int cache_entry_cmp(const void *unused_cmp_data,
 static int lazy_try_threaded = 1;
 static int lazy_nr_dir_threads;
 
-#ifdef NO_PTHREADS
-
-static inline int lookup_lazy_params(struct index_state *istate)
-{
-       return 0;
-}
-
-static inline void threaded_lazy_init_name_hash(
-       struct index_state *istate)
-{
-}
-
-#else
-
-#include "thread-utils.h"
-
 /*
  * Set a minimum number of cache_entries that we will handle per
  * thread and use that to decide how many threads to run (upto
@@ -509,6 +494,7 @@ static inline void lazy_update_dir_ref_counts(
 static void threaded_lazy_init_name_hash(
        struct index_state *istate)
 {
+       int err;
        int nr_each;
        int k_start;
        int t;
@@ -516,6 +502,9 @@ static void threaded_lazy_init_name_hash(
        struct lazy_dir_thread_data *td_dir;
        struct lazy_name_thread_data *td_name;
 
+       if (!HAVE_THREADS)
+               return;
+
        k_start = 0;
        nr_each = DIV_ROUND_UP(istate->cache_nr, lazy_nr_dir_threads);
 
@@ -538,8 +527,9 @@ static void threaded_lazy_init_name_hash(
                if (k_start > istate->cache_nr)
                        k_start = istate->cache_nr;
                td_dir_t->k_end = k_start;
-               if (pthread_create(&td_dir_t->pthread, NULL, lazy_dir_thread_proc, td_dir_t))
-                       die("unable to create lazy_dir_thread");
+               err = pthread_create(&td_dir_t->pthread, NULL, lazy_dir_thread_proc, td_dir_t);
+               if (err)
+                       die(_("unable to create lazy_dir thread: %s"), strerror(err));
        }
        for (t = 0; t < lazy_nr_dir_threads; t++) {
                struct lazy_dir_thread_data *td_dir_t = td_dir + t;
@@ -559,13 +549,15 @@ static void threaded_lazy_init_name_hash(
         */
        td_name->istate = istate;
        td_name->lazy_entries = lazy_entries;
-       if (pthread_create(&td_name->pthread, NULL, lazy_name_thread_proc, td_name))
-               die("unable to create lazy_name_thread");
+       err = pthread_create(&td_name->pthread, NULL, lazy_name_thread_proc, td_name);
+       if (err)
+               die(_("unable to create lazy_name thread: %s"), strerror(err));
 
        lazy_update_dir_ref_counts(istate, lazy_entries);
 
-       if (pthread_join(td_name->pthread, NULL))
-               die("unable to join lazy_name_thread");
+       err = pthread_join(td_name->pthread, NULL);
+       if (err)
+               die(_("unable to join lazy_name thread: %s"), strerror(err));
 
        cleanup_dir_mutex();
 
@@ -574,8 +566,6 @@ static void threaded_lazy_init_name_hash(
        free(lazy_entries);
 }
 
-#endif
-
 static void lazy_init_name_hash(struct index_state *istate)
 {
 
index 0feb90ae613be04d56ac091307c9b2be88724e42..796792cb32a7ae86b253df05671e1ed4736e4d15 100644 (file)
--- a/object.h
+++ b/object.h
@@ -59,7 +59,7 @@ struct object_array {
 
 /*
  * object flag allocation:
- * revision.h:               0---------10                              2526
+ * revision.h:               0---------10                              25----28
  * fetch-pack.c:             01
  * negotiator/default.c:       2--5
  * walker.c:                 0-2
@@ -78,7 +78,7 @@ struct object_array {
  * builtin/show-branch.c:    0-------------------------------------------26
  * builtin/unpack-objects.c:                                 2021
  */
-#define FLAG_BITS  27
+#define FLAG_BITS  29
 
 /*
  * The object type is stored in 3 bits.
index 86ee93feb4f7d14518ed1ffe9cac8d8a7cd817fe..feb6a6a05edba0772f4cfd8b4529bce9d3858751 100644 (file)
@@ -145,9 +145,7 @@ struct packing_data {
        struct packed_git **in_pack_by_idx;
        struct packed_git **in_pack;
 
-#ifndef NO_PTHREADS
        pthread_mutex_t lock;
-#endif
 
        /*
         * This list contains entries for bases which we know the other side
@@ -169,15 +167,11 @@ void prepare_packing_data(struct packing_data *pdata);
 
 static inline void packing_data_lock(struct packing_data *pdata)
 {
-#ifndef NO_PTHREADS
        pthread_mutex_lock(&pdata->lock);
-#endif
 }
 static inline void packing_data_unlock(struct packing_data *pdata)
 {
-#ifndef NO_PTHREADS
        pthread_mutex_unlock(&pdata->lock);
-#endif
 }
 
 struct object_entry *packlist_alloc(struct packing_data *pdata,
index e8236534ac8aa00fde2a5a9ae27e85c72d062f3a..8c9edce52f63bcb1085b119b3a2264a97b1fb374 100644 (file)
@@ -28,13 +28,6 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
        return 0;
 }
 
-int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
-                            int unset)
-{
-       *(timestamp_t *)(opt->value) = approxidate(arg);
-       return 0;
-}
-
 int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
                             int unset)
 {
@@ -65,6 +58,8 @@ int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
 {
        int *target = opt->value;
 
+       BUG_ON_OPT_ARG(arg);
+
        if (unset)
                /* --no-quiet, --no-verbose */
                *target = 0;
@@ -87,6 +82,8 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)
        struct object_id oid;
        struct commit *commit;
 
+       BUG_ON_OPT_NEG(unset);
+
        if (!arg)
                return -1;
        if (get_oid(arg, &oid))
@@ -117,6 +114,9 @@ int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
 int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
 {
        int *target = opt->value;
+
+       BUG_ON_OPT_ARG(arg);
+
        *target = unset ? 2 : 1;
        return 0;
 }
index dd14911a297a5b10705ecb31243c55a7dc2f193c..6c4fe2016d65f1093400f8f5080085eb244f0026 100644 (file)
@@ -150,9 +150,6 @@ struct option {
                                      (h), 0, &parse_opt_string_list }
 #define OPT_UYN(s, l, v, h)         { OPTION_CALLBACK, (s), (l), (v), NULL, \
                                      (h), PARSE_OPT_NOARG, &parse_opt_tertiary }
-#define OPT_DATE(s, l, v, h) \
-       { OPTION_CALLBACK, (s), (l), (v), N_("time"),(h), 0,    \
-         parse_opt_approxidate_cb }
 #define OPT_EXPIRY_DATE(s, l, v, h) \
        { OPTION_CALLBACK, (s), (l), (v), N_("expiry-date"),(h), 0,     \
          parse_opt_expiry_date_cb }
@@ -194,6 +191,20 @@ extern int opterror(const struct option *opt, const char *reason, int flags);
 #define opterror(o,r,f) (opterror((o),(r),(f)), const_error())
 #endif
 
+/*
+ * Use these assertions for callbacks that expect to be called with NONEG and
+ * NOARG respectively, and do not otherwise handle the "unset" and "arg"
+ * parameters.
+ */
+#define BUG_ON_OPT_NEG(unset) do { \
+       if ((unset)) \
+               BUG("option callback does not expect negation"); \
+} while (0)
+#define BUG_ON_OPT_ARG(arg) do { \
+       if ((arg)) \
+               BUG("option callback does not expect an argument"); \
+} while (0)
+
 /*----- incremental advanced APIs -----*/
 
 enum {
@@ -232,7 +243,6 @@ extern struct option *parse_options_concat(struct option *a, struct option *b);
 
 /*----- some often used options -----*/
 extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
-extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
 extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);
 extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
 extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
index 222792ccbc39b6166a75c702525c396b77c2299e..c7dc3f2b9f62a762efd7f590d6e8959fc1707479 100644 (file)
@@ -7,17 +7,7 @@
 #include "fsmonitor.h"
 #include "config.h"
 #include "progress.h"
-
-#ifdef NO_PTHREADS
-void preload_index(struct index_state *index,
-                         const struct pathspec *pathspec,
-                         unsigned int refresh_flags)
-{
-       ; /* nothing */
-}
-#else
-
-#include <pthread.h>
+#include "thread-utils.h"
 
 /*
  * Mostly randomly chosen maximum thread counts: we
@@ -108,7 +98,7 @@ void preload_index(struct index_state *index,
        struct thread_data data[MAX_PARALLEL];
        struct progress_data pd;
 
-       if (!core_preload_index)
+       if (!HAVE_THREADS || !core_preload_index)
                return;
 
        threads = index->cache_nr / THREAD_COST;
@@ -131,6 +121,8 @@ void preload_index(struct index_state *index,
 
        for (i = 0; i < threads; i++) {
                struct thread_data *p = data+i;
+               int err;
+
                p->index = index;
                if (pathspec)
                        copy_pathspec(&p->pathspec, pathspec);
@@ -139,8 +131,10 @@ void preload_index(struct index_state *index,
                if (pd.progress)
                        p->progress = &pd;
                offset += work;
-               if (pthread_create(&p->pthread, NULL, preload_thread, p))
-                       die("unable to create threaded lstat");
+               err = pthread_create(&p->pthread, NULL, preload_thread, p);
+
+               if (err)
+                       die(_("unable to create threaded lstat: %s"), strerror(err));
        }
        for (i = 0; i < threads; i++) {
                struct thread_data *p = data+i;
@@ -151,7 +145,6 @@ void preload_index(struct index_state *index,
 
        trace_performance_leave("preload index");
 }
-#endif
 
 int read_index_preload(struct index_state *index,
                       const struct pathspec *pathspec,
index a07845187233e429e00138cce7ade42e97a40d4b..d3f488cb05f29bc90e4e03810d9bf4b972d0834f 100644 (file)
@@ -85,3 +85,12 @@ void *prio_queue_get(struct prio_queue *queue)
        }
        return result;
 }
+
+void *prio_queue_peek(struct prio_queue *queue)
+{
+       if (!queue->nr)
+               return NULL;
+       if (!queue->compare)
+               return queue->array[queue->nr - 1].data;
+       return queue->array[0].data;
+}
index d030ec9dd6765447ad986a40945d1ed8bf9272a0..682e51867a3452bc1106bc63f44d6d6ba5f523b9 100644 (file)
@@ -46,6 +46,12 @@ extern void prio_queue_put(struct prio_queue *, void *thing);
  */
 extern void *prio_queue_get(struct prio_queue *);
 
+/*
+ * Gain access to the "thing" that would be returned by
+ * prio_queue_get, but do not remove it from the queue.
+ */
+extern void *prio_queue_peek(struct prio_queue *);
+
 extern void clear_prio_queue(struct prio_queue *);
 
 /* Reverse the LIFO elements */
index 3958720f004ebe9ba027cd6097a7cd3ce41e3d73..767af8c5bb5617016ba2c341334c05696fdcbcc1 100644 (file)
@@ -461,7 +461,8 @@ int show_range_diff(const char *range1, const char *range2,
                struct strbuf indent = STRBUF_INIT;
 
                memcpy(&opts, diffopt, sizeof(opts));
-               opts.output_format = DIFF_FORMAT_PATCH;
+               if (!opts.output_format)
+                       opts.output_format = DIFF_FORMAT_PATCH;
                opts.flags.suppress_diff_headers = 1;
                opts.flags.dual_color_diffed_diffs = dual_color;
                opts.output_prefix = output_prefix_cb;
index 8c924506dd96037c1d7c0fa93e4223f9274a851f..4ca81286c00c57484a3567a56fa4d441725708da 100644 (file)
@@ -1752,7 +1752,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
        size_t len;
        const char *name;
        unsigned int flags;
-       size_t copy_len;
+       size_t copy_len = 0;
        /*
         * Adjacent cache entries tend to share the leading paths, so it makes
         * sense to only store the differences in later entries.  In the v4
@@ -1792,8 +1792,6 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
                                die(_("malformed name field in the index, near path '%s'"),
                                        previous_ce->name);
                        copy_len = previous_len - strip_len;
-               } else {
-                       copy_len = 0;
                }
                name = (const char *)cp;
        }
@@ -1926,19 +1924,15 @@ struct index_entry_offset_table
        struct index_entry_offset entries[FLEX_ARRAY];
 };
 
-#ifndef NO_PTHREADS
 static struct index_entry_offset_table *read_ieot_extension(const char *mmap, size_t mmap_size, size_t offset);
 static void write_ieot_extension(struct strbuf *sb, struct index_entry_offset_table *ieot);
-#endif
 
 static size_t read_eoie_extension(const char *mmap, size_t mmap_size);
 static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context, size_t offset);
 
 struct load_index_extensions
 {
-#ifndef NO_PTHREADS
        pthread_t pthread;
-#endif
        struct index_state *istate;
        const char *mmap;
        size_t mmap_size;
@@ -2016,8 +2010,6 @@ static unsigned long load_all_cache_entries(struct index_state *istate,
        return consumed;
 }
 
-#ifndef NO_PTHREADS
-
 /*
  * Mostly randomly chosen maximum thread counts: we
  * cap the parallelism to online_cpus() threads, and we want
@@ -2128,7 +2120,6 @@ static unsigned long load_cache_entries_threaded(struct index_state *istate, con
 
        return consumed;
 }
-#endif
 
 /* remember to discard_cache() before reading a different cache! */
 int do_read_index(struct index_state *istate, const char *path, int must_exist)
@@ -2141,10 +2132,8 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
        size_t mmap_size;
        struct load_index_extensions p;
        size_t extension_offset = 0;
-#ifndef NO_PTHREADS
        int nr_threads, cpus;
        struct index_entry_offset_table *ieot = NULL;
-#endif
 
        if (istate->initialized)
                return istate->cache_nr;
@@ -2187,7 +2176,6 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
 
        src_offset = sizeof(*hdr);
 
-#ifndef NO_PTHREADS
        nr_threads = git_config_get_index_threads();
 
        /* TODO: does creating more threads than cores help? */
@@ -2198,6 +2186,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
                        nr_threads = cpus;
        }
 
+       if (!HAVE_THREADS)
+               nr_threads = 1;
+
        if (nr_threads > 1) {
                extension_offset = read_eoie_extension(mmap, mmap_size);
                if (extension_offset) {
@@ -2225,22 +2216,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
        } else {
                src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
        }
-#else
-       src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
-#endif
 
        istate->timestamp.sec = st.st_mtime;
        istate->timestamp.nsec = ST_MTIME_NSEC(st);
 
        /* if we created a thread, join it otherwise load the extensions on the primary thread */
-#ifndef NO_PTHREADS
        if (extension_offset) {
                int ret = pthread_join(p.pthread, NULL);
                if (ret)
                        die(_("unable to join load_index_extensions thread: %s"), strerror(ret));
-       }
-#endif
-       if (!extension_offset) {
+       } else {
                p.src_offset = src_offset;
                load_index_extensions(&p);
        }
@@ -2762,8 +2747,11 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
        if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
                return -1;
 
-#ifndef NO_PTHREADS
-       nr_threads = git_config_get_index_threads();
+       if (HAVE_THREADS)
+               nr_threads = git_config_get_index_threads();
+       else
+               nr_threads = 1;
+
        if (nr_threads != 1) {
                int ieot_blocks, cpus;
 
@@ -2793,7 +2781,6 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                        ieot_entries = DIV_ROUND_UP(entries, ieot_blocks);
                }
        }
-#endif
 
        offset = lseek(newfd, 0, SEEK_CUR);
        if (offset < 0) {
@@ -2877,7 +2864,6 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
         * strip_extensions parameter as we need it when loading the shared
         * index.
         */
-#ifndef NO_PTHREADS
        if (ieot) {
                struct strbuf sb = STRBUF_INIT;
 
@@ -2889,7 +2875,6 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                if (err)
                        return -1;
        }
-#endif
 
        if (!strip_extensions && istate->split_index) {
                struct strbuf sb = STRBUF_INIT;
@@ -3475,7 +3460,6 @@ static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context,
        strbuf_add(sb, hash, the_hash_algo->rawsz);
 }
 
-#ifndef NO_PTHREADS
 #define IEOT_VERSION   (1)
 
 static struct index_entry_offset_table *read_ieot_extension(const char *mmap, size_t mmap_size, size_t offset)
@@ -3548,4 +3532,3 @@ static void write_ieot_extension(struct strbuf *sb, struct index_entry_offset_ta
               strbuf_add(sb, &buffer, sizeof(uint32_t));
        }
 }
-#endif
index 0c45ed9d94a4bd4bfab6c9d441ca9bc7de7ebf31..7eca4362236cb6aee15999ee290a08c4ee06278d 100644 (file)
@@ -2316,6 +2316,8 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
        struct object_id oid;
        int no_merged = starts_with(opt->long_name, "no");
 
+       BUG_ON_OPT_NEG(unset);
+
        if (rf->merge) {
                if (no_merged) {
                        return opterror(opt, "is incompatible with --merged", 0);
diff --git a/refs.c b/refs.c
index 17e4307f3171697ddd8c1e49710c16218e6774a8..f9936355cda6a1515f3192151f7fc14d0c2d7522 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -217,6 +217,7 @@ char *resolve_refdup(const char *refname, int resolve_flags,
 /* The argument to filter_refs */
 struct ref_filter {
        const char *pattern;
+       const char *prefix;
        each_ref_fn *fn;
        void *cb_data;
 };
@@ -296,6 +297,8 @@ static int filter_refs(const char *refname, const struct object_id *oid,
 
        if (wildmatch(filter->pattern, refname, 0))
                return 0;
+       if (filter->prefix)
+               skip_prefix(refname, filter->prefix, &refname);
        return filter->fn(refname, oid, flags, filter->cb_data);
 }
 
@@ -458,6 +461,7 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
        }
 
        filter.pattern = real_pattern.buf;
+       filter.prefix = prefix;
        filter.fn = fn;
        filter.cb_data = cb_data;
        ret = for_each_ref(filter_refs, &filter);
index bdd3e7c9f193415d073b78c220366ac69afa5c20..13e0519c0241635c0c1fd14a7ff12e9478c70bd4 100644 (file)
@@ -25,6 +25,8 @@
 #include "worktree.h"
 #include "argv-array.h"
 #include "commit-reach.h"
+#include "commit-graph.h"
+#include "prio-queue.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -767,8 +769,8 @@ static void commit_list_insert_by_date_cached(struct commit *p, struct commit_li
                *cache = new_entry;
 }
 
-static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
-                   struct commit_list **list, struct commit_list **cache_ptr)
+static int process_parents(struct rev_info *revs, struct commit *commit,
+                          struct commit_list **list, struct commit_list **cache_ptr)
 {
        struct commit_list *parent = commit->parents;
        unsigned left_flag;
@@ -807,7 +809,8 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
                        if (p->object.flags & SEEN)
                                continue;
                        p->object.flags |= SEEN;
-                       commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
+                       if (list)
+                               commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
                }
                return 0;
        }
@@ -846,7 +849,8 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
                p->object.flags |= left_flag;
                if (!(p->object.flags & SEEN)) {
                        p->object.flags |= SEEN;
-                       commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
+                       if (list)
+                               commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
                }
                if (revs->first_parent_only)
                        break;
@@ -1090,7 +1094,7 @@ static int limit_list(struct rev_info *revs)
 
                if (revs->max_age != -1 && (commit->date < revs->max_age))
                        obj->flags |= UNINTERESTING;
-               if (add_parents_to_list(revs, commit, &list, NULL) < 0)
+               if (process_parents(revs, commit, &list, NULL) < 0)
                        return -1;
                if (obj->flags & UNINTERESTING) {
                        mark_parents_uninteresting(commit);
@@ -2468,7 +2472,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
        if (revs->diffopt.objfind)
                revs->simplify_history = 0;
 
-       if (revs->topo_order)
+       if (revs->topo_order && !generation_numbers_enabled(the_repository))
                revs->limited = 1;
 
        if (revs->prune_data.nr) {
@@ -2907,6 +2911,217 @@ static int mark_uninteresting(const struct object_id *oid,
        return 0;
 }
 
+define_commit_slab(indegree_slab, int);
+define_commit_slab(author_date_slab, timestamp_t);
+
+struct topo_walk_info {
+       uint32_t min_generation;
+       struct prio_queue explore_queue;
+       struct prio_queue indegree_queue;
+       struct prio_queue topo_queue;
+       struct indegree_slab indegree;
+       struct author_date_slab author_date;
+};
+
+static inline void test_flag_and_insert(struct prio_queue *q, struct commit *c, int flag)
+{
+       if (c->object.flags & flag)
+               return;
+
+       c->object.flags |= flag;
+       prio_queue_put(q, c);
+}
+
+static void explore_walk_step(struct rev_info *revs)
+{
+       struct topo_walk_info *info = revs->topo_walk_info;
+       struct commit_list *p;
+       struct commit *c = prio_queue_get(&info->explore_queue);
+
+       if (!c)
+               return;
+
+       if (parse_commit_gently(c, 1) < 0)
+               return;
+
+       if (revs->sort_order == REV_SORT_BY_AUTHOR_DATE)
+               record_author_date(&info->author_date, c);
+
+       if (revs->max_age != -1 && (c->date < revs->max_age))
+               c->object.flags |= UNINTERESTING;
+
+       if (process_parents(revs, c, NULL, NULL) < 0)
+               return;
+
+       if (c->object.flags & UNINTERESTING)
+               mark_parents_uninteresting(c);
+
+       for (p = c->parents; p; p = p->next)
+               test_flag_and_insert(&info->explore_queue, p->item, TOPO_WALK_EXPLORED);
+}
+
+static void explore_to_depth(struct rev_info *revs,
+                            uint32_t gen_cutoff)
+{
+       struct topo_walk_info *info = revs->topo_walk_info;
+       struct commit *c;
+       while ((c = prio_queue_peek(&info->explore_queue)) &&
+              c->generation >= gen_cutoff)
+               explore_walk_step(revs);
+}
+
+static void indegree_walk_step(struct rev_info *revs)
+{
+       struct commit_list *p;
+       struct topo_walk_info *info = revs->topo_walk_info;
+       struct commit *c = prio_queue_get(&info->indegree_queue);
+
+       if (!c)
+               return;
+
+       if (parse_commit_gently(c, 1) < 0)
+               return;
+
+       explore_to_depth(revs, c->generation);
+
+       for (p = c->parents; p; p = p->next) {
+               struct commit *parent = p->item;
+               int *pi = indegree_slab_at(&info->indegree, parent);
+
+               if (*pi)
+                       (*pi)++;
+               else
+                       *pi = 2;
+
+               test_flag_and_insert(&info->indegree_queue, parent, TOPO_WALK_INDEGREE);
+
+               if (revs->first_parent_only)
+                       return;
+       }
+}
+
+static void compute_indegrees_to_depth(struct rev_info *revs,
+                                      uint32_t gen_cutoff)
+{
+       struct topo_walk_info *info = revs->topo_walk_info;
+       struct commit *c;
+       while ((c = prio_queue_peek(&info->indegree_queue)) &&
+              c->generation >= gen_cutoff)
+               indegree_walk_step(revs);
+}
+
+static void init_topo_walk(struct rev_info *revs)
+{
+       struct topo_walk_info *info;
+       struct commit_list *list;
+       revs->topo_walk_info = xmalloc(sizeof(struct topo_walk_info));
+       info = revs->topo_walk_info;
+       memset(info, 0, sizeof(struct topo_walk_info));
+
+       init_indegree_slab(&info->indegree);
+       memset(&info->explore_queue, 0, sizeof(info->explore_queue));
+       memset(&info->indegree_queue, 0, sizeof(info->indegree_queue));
+       memset(&info->topo_queue, 0, sizeof(info->topo_queue));
+
+       switch (revs->sort_order) {
+       default: /* REV_SORT_IN_GRAPH_ORDER */
+               info->topo_queue.compare = NULL;
+               break;
+       case REV_SORT_BY_COMMIT_DATE:
+               info->topo_queue.compare = compare_commits_by_commit_date;
+               break;
+       case REV_SORT_BY_AUTHOR_DATE:
+               init_author_date_slab(&info->author_date);
+               info->topo_queue.compare = compare_commits_by_author_date;
+               info->topo_queue.cb_data = &info->author_date;
+               break;
+       }
+
+       info->explore_queue.compare = compare_commits_by_gen_then_commit_date;
+       info->indegree_queue.compare = compare_commits_by_gen_then_commit_date;
+
+       info->min_generation = GENERATION_NUMBER_INFINITY;
+       for (list = revs->commits; list; list = list->next) {
+               struct commit *c = list->item;
+
+               if (parse_commit_gently(c, 1))
+                       continue;
+
+               test_flag_and_insert(&info->explore_queue, c, TOPO_WALK_EXPLORED);
+               test_flag_and_insert(&info->indegree_queue, c, TOPO_WALK_INDEGREE);
+
+               if (c->generation < info->min_generation)
+                       info->min_generation = c->generation;
+
+               *(indegree_slab_at(&info->indegree, c)) = 1;
+
+               if (revs->sort_order == REV_SORT_BY_AUTHOR_DATE)
+                       record_author_date(&info->author_date, c);
+       }
+       compute_indegrees_to_depth(revs, info->min_generation);
+
+       for (list = revs->commits; list; list = list->next) {
+               struct commit *c = list->item;
+
+               if (*(indegree_slab_at(&info->indegree, c)) == 1)
+                       prio_queue_put(&info->topo_queue, c);
+       }
+
+       /*
+        * This is unfortunate; the initial tips need to be shown
+        * in the order given from the revision traversal machinery.
+        */
+       if (revs->sort_order == REV_SORT_IN_GRAPH_ORDER)
+               prio_queue_reverse(&info->topo_queue);
+}
+
+static struct commit *next_topo_commit(struct rev_info *revs)
+{
+       struct commit *c;
+       struct topo_walk_info *info = revs->topo_walk_info;
+
+       /* pop next off of topo_queue */
+       c = prio_queue_get(&info->topo_queue);
+
+       if (c)
+               *(indegree_slab_at(&info->indegree, c)) = 0;
+
+       return c;
+}
+
+static void expand_topo_walk(struct rev_info *revs, struct commit *commit)
+{
+       struct commit_list *p;
+       struct topo_walk_info *info = revs->topo_walk_info;
+       if (process_parents(revs, commit, NULL, NULL) < 0) {
+               if (!revs->ignore_missing_links)
+                       die("Failed to traverse parents of commit %s",
+                           oid_to_hex(&commit->object.oid));
+       }
+
+       for (p = commit->parents; p; p = p->next) {
+               struct commit *parent = p->item;
+               int *pi;
+
+               if (parse_commit_gently(parent, 1) < 0)
+                       continue;
+
+               if (parent->generation < info->min_generation) {
+                       info->min_generation = parent->generation;
+                       compute_indegrees_to_depth(revs, info->min_generation);
+               }
+
+               pi = indegree_slab_at(&info->indegree, parent);
+
+               (*pi)--;
+               if (*pi == 1)
+                       prio_queue_put(&info->topo_queue, parent);
+
+               if (revs->first_parent_only)
+                       return;
+       }
+}
+
 int prepare_revision_walk(struct rev_info *revs)
 {
        int i;
@@ -2943,11 +3158,13 @@ int prepare_revision_walk(struct rev_info *revs)
                commit_list_sort_by_date(&revs->commits);
        if (revs->no_walk)
                return 0;
-       if (revs->limited)
+       if (revs->limited) {
                if (limit_list(revs) < 0)
                        return -1;
-       if (revs->topo_order)
-               sort_in_topological_order(&revs->commits, revs->sort_order);
+               if (revs->topo_order)
+                       sort_in_topological_order(&revs->commits, revs->sort_order);
+       } else if (revs->topo_order)
+               init_topo_walk(revs);
        if (revs->line_level_traverse)
                line_log_filter(revs);
        if (revs->simplify_merges)
@@ -2964,7 +3181,7 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp
        for (;;) {
                struct commit *p = *pp;
                if (!revs->limited)
-                       if (add_parents_to_list(revs, p, &revs->commits, &cache) < 0)
+                       if (process_parents(revs, p, &revs->commits, &cache) < 0)
                                return rewrite_one_error;
                if (p->object.flags & UNINTERESTING)
                        return rewrite_one_ok;
@@ -3272,6 +3489,8 @@ static struct commit *get_revision_1(struct rev_info *revs)
 
                if (revs->reflog_info)
                        commit = next_reflog_entry(revs->reflog_info);
+               else if (revs->topo_walk_info)
+                       commit = next_topo_commit(revs);
                else
                        commit = pop_commit(&revs->commits);
 
@@ -3293,7 +3512,9 @@ static struct commit *get_revision_1(struct rev_info *revs)
 
                        if (revs->reflog_info)
                                try_to_simplify_commit(revs, commit);
-                       else if (add_parents_to_list(revs, commit, &revs->commits, NULL) < 0) {
+                       else if (revs->topo_walk_info)
+                               expand_topo_walk(revs, commit);
+                       else if (process_parents(revs, commit, &revs->commits, NULL) < 0) {
                                if (!revs->ignore_missing_links)
                                        die("Failed to traverse parents of commit %s",
                                                oid_to_hex(&commit->object.oid));
index 0d2abc2d36ec579c281135a2a3b866fb37911326..7987bfcd2e9bd6ee7bac4f1cbeb10af17ab40b50 100644 (file)
@@ -32,6 +32,9 @@
 #define TRACK_LINEAR   (1u<<26)
 #define ALL_REV_FLAGS  (((1u<<11)-1) | NOT_USER_GIVEN | TRACK_LINEAR)
 
+#define TOPO_WALK_EXPLORED     (1u<<27)
+#define TOPO_WALK_INDEGREE     (1u<<28)
+
 #define DECORATE_SHORT_REFS    1
 #define DECORATE_FULL_REFS     2
 
@@ -64,6 +67,8 @@ struct rev_cmdline_info {
 #define REVISION_WALK_NO_WALK_SORTED 1
 #define REVISION_WALK_NO_WALK_UNSORTED 2
 
+struct topo_walk_info;
+
 struct rev_info {
        /* Starting list */
        struct commit_list *commits;
@@ -270,6 +275,8 @@ struct rev_info {
        const char *break_bar;
 
        struct revision_sources *sources;
+
+       struct topo_walk_info *topo_walk_info;
 };
 
 int ref_excluded(struct string_list *, const char *path);
index d679cc267c39b9fb34f57078db5db12ed591b7e2..c11ff8067481f70c444198bcc7477ef744d99fd3 100644 (file)
@@ -1226,7 +1226,7 @@ int start_async(struct async *async)
        {
                int err = pthread_create(&async->tid, NULL, run_thread, async);
                if (err) {
-                       error_errno("cannot create thread");
+                       error(_("cannot create async thread: %s"), strerror(err));
                        goto error;
                }
        }
@@ -1259,6 +1259,15 @@ int finish_async(struct async *async)
 #endif
 }
 
+int async_with_fork(void)
+{
+#ifdef NO_PTHREADS
+       return 1;
+#else
+       return 0;
+#endif
+}
+
 const char *find_hook(const char *name)
 {
        static struct strbuf path = STRBUF_INIT;
index 3932420ec8a560479c9697e3626e9da15e952853..68f5369fc2d432e8b4b504e9625b541056814216 100644 (file)
@@ -1,9 +1,7 @@
 #ifndef RUN_COMMAND_H
 #define RUN_COMMAND_H
 
-#ifndef NO_PTHREADS
-#include <pthread.h>
-#endif
+#include "thread-utils.h"
 
 #include "argv-array.h"
 
@@ -143,6 +141,7 @@ struct async {
 int start_async(struct async *async);
 int finish_async(struct async *async);
 int in_async(void);
+int async_with_fork(void);
 void check_pipe(int err);
 
 /**
index e920ca57df4dd0b65d6694ed2532dead8ae83fb6..f692686770f69b49d44bf6dbabdb17886d85ea1a 100644 (file)
@@ -203,9 +203,8 @@ static int receive_status(int in, struct ref *refs)
 static int sideband_demux(int in, int out, void *data)
 {
        int *fd = data, ret;
-#ifdef NO_PTHREADS
-       close(fd[1]);
-#endif
+       if (async_with_fork())
+               close(fd[1]);
        ret = recv_sideband("send-pack", fd[0], out);
        close(out);
        return ret;
index 0d87b0739be5c5fdaf686063729aca02559638b8..e1a4dd15f1a826c7bd1bf4780c8f85c21117c43b 100644 (file)
@@ -3244,10 +3244,6 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
        }
 
        merge_commit = to_merge->item;
-       write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ,
-                     git_path_merge_head(the_repository), 0);
-       write_message("no-ff", 5, git_path_merge_mode(the_repository), 0);
-
        bases = get_merge_bases(head_commit, merge_commit);
        if (bases && oideq(&merge_commit->object.oid,
                           &bases->item->object.oid)) {
@@ -3256,6 +3252,10 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
                goto leave_merge;
        }
 
+       write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ,
+                     git_path_merge_head(the_repository), 0);
+       write_message("no-ff", 5, git_path_merge_mode(the_repository), 0);
+
        for (j = bases; j; j = j->next)
                commit_list_insert(j->item, &reversed);
        free_commit_list(bases);
@@ -3512,6 +3512,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
                        unlink(rebase_path_author_script());
                        unlink(rebase_path_stopped_sha());
                        unlink(rebase_path_amend());
+                       unlink(git_path_merge_head(the_repository));
                        delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
 
                        if (item->command == TODO_BREAK)
@@ -3882,6 +3883,7 @@ static int commit_staged_changes(struct replay_opts *opts,
                           opts, flags))
                return error(_("could not commit staged changes."));
        unlink(rebase_path_amend());
+       unlink(git_path_merge_head(the_repository));
        if (final_fixup) {
                unlink(rebase_path_fixup_msg());
                unlink(rebase_path_squash_msg());
index 9cb8a0ea0f8ae7b3da8525b2a354bfa542db93c3..47fee660b86a6e6977735e2c940de79d4330d519 100644 (file)
@@ -36,6 +36,7 @@ static int length_callback(const struct option *opt, const char *arg, int unset)
 
 static int number_callback(const struct option *opt, const char *arg, int unset)
 {
+       BUG_ON_OPT_NEG(unset);
        *(int *)opt->value = strtol(arg, NULL, 10);
        return 0;
 }
@@ -119,7 +120,6 @@ int cmd__parse_options(int argc, const char **argv)
                OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
                OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
                OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
-               OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
                OPT_CALLBACK('L', "length", &integer, "str",
                        "get length of <str>", length_callback),
                OPT_FILENAME('F', "file", &file, "set file to <file>"),
index 9807b649b14c0002bee6d10b200c27bb89a54812..5bc9c46ea5603e22e6fb5aaa5c0276a12d2a031f 100644 (file)
@@ -22,14 +22,24 @@ int cmd__prio_queue(int argc, const char **argv)
        struct prio_queue pq = { intcmp };
 
        while (*++argv) {
-               if (!strcmp(*argv, "get"))
-                       show(prio_queue_get(&pq));
-               else if (!strcmp(*argv, "dump")) {
-                       int *v;
-                       while ((v = prio_queue_get(&pq)))
-                              show(v);
-               }
-               else {
+               if (!strcmp(*argv, "get")) {
+                       void *peek = prio_queue_peek(&pq);
+                       void *get = prio_queue_get(&pq);
+                       if (peek != get)
+                               BUG("peek and get results do not match");
+                       show(get);
+               } else if (!strcmp(*argv, "dump")) {
+                       void *peek;
+                       void *get;
+                       while ((peek = prio_queue_peek(&pq))) {
+                               get = prio_queue_get(&pq);
+                               if (peek != get)
+                                       BUG("peek and get results do not match");
+                               show(get);
+                       }
+               } else if (!strcmp(*argv, "stack")) {
+                       pq.compare = NULL;
+               } else {
                        int *v = malloc(sizeof(*v));
                        *v = atoi(*argv);
                        prio_queue_put(&pq, v);
index d4754a1f19c7984b3286cfd9dfa9740a790800e0..918dfce332e183c9ab62ab2400f8a35598f1ad8c 100644 (file)
@@ -30,7 +30,6 @@ Cezx4Q2khACcCs+/LtE8Lb9hC+2cvr3uH5p82AI=
 =aEiU
 -----END PGP PRIVATE KEY BLOCK-----
 -----BEGIN PGP PRIVATE KEY BLOCK-----
-Version: GnuPG v1
 
 lQOYBFFMlkcBCADJi/xnAF8yI34PHilSCbM7VtOFO17oFMkpu4cgN2QpPuM5MVjy
 cvrzKSguZFvPCDLzeAFJW1uPxL4SHaHSkisCrFhijH7OJWcOPNPSFCwu+inAoAsv
@@ -83,11 +82,43 @@ fn1sY/IG5atoKK+ypmV/TlBlMZqFQzuPIJQT8VLbmxtLlDhJG04LbI6c8axIZxOO
 ZKLy5nTTSy16ztqEeS7eifHLPZg1UFFyEEIQ1XW0CNDAeuWKh90ERjyl4Cg7PnWS
 Z9Ei+zj6JD5Pcdi3BJhQo9WOLOVEJ0NHmewTYqk9QVXH/0v1Hdl4LMJtgcbdbDWk
 4UTkXbg9pn3umCgkNJ3Vs8fWnIWO9Izdr2/wrFY2JvUT7Yvl+wsNIWatvOEzGy7n
-BOW78WUxzhu0YJTLKy+iKCjg5HS5dx6OC+e4aEEgfhNPCMkbvDsJjtQ=
-=hieJ
+BOW78WUxzhu0YJTLKy+iKCjg5HS5dx6OC+e4aEEgfhNPCMkbvDsJjtSdA5gEW967
+3AEIAKjseT0sTQjyN39fOn0fzxWp89REMUUKgLigb01MKuuNI3cedBZsz3hpFOKV
+cii5rldw8uf3yS3Okht2DfHPSD4NrGzLGEzSTpQ10S8N2q0DUYwyLU6C0U8HnMZm
+/n+lCGBbUoxvnruohAvKAjpHO3rmJ8D4De9hlWg/fwdAxQQ0Sve0kN8Vwk2p1GuO
+OWQKV1SU9c+kBiou7dewQmbilPRanKmP5ZSU4emhpTOMlJFXF+kmYSODQk1cMvWW
+Ob3ttll2llX0Gul7Sjf+haq/FcRyRk7Tw5MHwZjr5aWiCny0/0+byvfF6SBIfzyE
+qlyWURQ2gHZUqSiG3QPMZiYr04cAEQEAAQAH/Am4rv/oQF6wodgz5y4zc6JJiTDA
+4+nKdIuR7OKqUxk1oo7eZjJML/xvMumygNyUvJ9nodl1SlMKilOhdAswfkKj9gJY
+BdDJLm1OufhW3pJwy6ahbjeqEgwJFVENtSPF0zkuyED9kElrpbD2ZTGfzwdM0e9D
+10ZDFWtODCw8rzOFcijujgI8oilLtxSNrkkTKW+25WJFRNPSHgIkMIm8UlPAG+rj
+3Yj9UqodeXTSvXwG2zceOxjFJadV77sOFJDgwWslN6J8El4+GcgwFVepJxoZEj7e
+cKkmVr0Dc9/Q04D5dWATc1FYcIhZbTu3oImCAh45ep4u9WYLUV5PGyeMviEEAMwo
+mJbYBxWuPjpNa722HQcbvMUiZWWDwHfLCib/SaP0AgfDahid8/PcZwxOPHPByBrm
+GDi0z7ibn/pgJr07kpp1Cic9ntfc2FvkI0QMzG0EuiekzQyPEnzjoDHF+V4nJIj2
+GWVjLYYqlZWEmhsfKt1CnlPXBunKoDJ30ABPcHJ/BADT0WxAIVKF4lO2HlrDVP44
+bufBEG9Ct7dl/G08Qve4Ag3VEZpT82vEFp0LzX0mTCDIUKJUYAYLxAIPhP7IvIfc
+EZXrwyDUxU7YSgKTHMKo9nFC6fIc1GeGPRalIF1gmTY32qlYJC6y5BTDhZNV5ydG
+u8QL2P/orP7XuRrJyeyK+QP/XTekr/DS6Jkct826MPA52ciIkWVgYLatH5fO4HCq
+ssDU8vz7FbbvGs0G1Xn7GA4m9dNYVOZtKwX++3nf2IEOpgPiZVTn/nP2u3HutpJb
+/HMLlcfZGiGdxS6n/vdz6wsEobJoi6STkHkA+VFNOSZmdsw6eKl3X911tpCTYfOG
+2U47/IkCbAQYAQgAIBYhBNS+IjEa0xMeXtoppGEJLoW3InGJBQJb3rvcAhsCAUAJ
+EGEJLoW3InGJwHQgBBkBCAAdFiEE+DZKWeB//p9NYwBaZaDuoC4wytcFAlveu9wA
+CgkQZaDuoC4wytcD9gf/WigtHl7lFyl8RaE/uqROFEelZyM00v1h55fd/IGRG88E
+tN0Lr4FaqBqPkMZjU/LN9UMBaTd+748vHlHaweZqljXJu99CO9Id7Y4w7WzF3C3Y
+yQsGZ92EGxthsPK0+rhHV0MbaINupI1oO9gATFglSxq17o83FJatGRjaXCZau8jr
+57/By1MGtjk+Iq1NkzGkrX778LdRQGLKDw2Qa7lsdHY8d3lUPAH8mbb97ELmIc9t
+PG2aM7ATJL7nBmFuTHo6hmEcIw32Ei9KK1zxM0ZylEYkjBjHAlklWmKb9MiayMC5
+uHW7Iyhjl+NbgbIEr2JTamW/9tL6UrIIxiDEdqaHNfCaB/9D+V31Upcohc9azwB4
+AF8diQwt5nfiVpnVeF/W8+eS1By2W6QrwLNthNRabYFnuSf9USHAY6atDWe+egId
+MLIv4ce0i3ykoczSu0oMoUCMxdl9kQrsNHZCqWX/OiDDLSb05u/P/3he900y6tSB
+15MbIPA6i5Bw/693nHguqxS1ASbBB/LiIu3vCXdFEs9RMvIJ+qkP3xQA96oImQiK
+R3U6OGv593eONKijUINNqHRq6+UxIyJ+OCAi+L2QTidAhJLRCp6EZD96u02cthYq
+8KA8j1+rx9BcbeacVVHepeG1JsgxsXX8BTJ7ZuS5VVndZOjag8URW/9nJMf01w/h
+el64
+=Iv7W
 -----END PGP PRIVATE KEY BLOCK-----
 -----BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1
 
 mQGiBEZnyykRBACzCPjIpTYNL7Y2tQqlEGTTDlvZcWNLjF5f7ZzuyOqNOidLUgFD
 36qch1LZLSZkShdR3Gae+bsolyjxrlFuFP0eXRPMtqK20aLw7WZvPFpEV1ThMne+
@@ -137,6 +168,25 @@ bGPyBuWraCivsqZlf05QZTGahUM7jyCUE/FS25sbS5Q4SRtOC2yOnPGsSGcTjmSi
 8uZ000stes7ahHku3onxyz2YNVBRchBCENV1tAjQwHrliofdBEY8peAoOz51kmfR
 Ivs4+iQ+T3HYtwSYUKPVjizlRCdDR5nsE2KpPUFVx/9L9R3ZeCzCbYHG3Ww1pOFE
 5F24PaZ97pgoJDSd1bPH1pyFjvSM3a9v8KxWNib1E+2L5fsLDSFmrbzhMxsu5wTl
-u/FlMc4btGCUyysvoigo4OR0uXcejgvnuGhBIH4TTwjJG7w7CY7U
-=iYv/
+u/FlMc4btGCUyysvoigo4OR0uXcejgvnuGhBIH4TTwjJG7w7CY7UuQENBFveu9wB
+CACo7Hk9LE0I8jd/Xzp9H88VqfPURDFFCoC4oG9NTCrrjSN3HnQWbM94aRTilXIo
+ua5XcPLn98ktzpIbdg3xz0g+DaxsyxhM0k6UNdEvDdqtA1GMMi1OgtFPB5zGZv5/
+pQhgW1KMb567qIQLygI6Rzt65ifA+A3vYZVoP38HQMUENEr3tJDfFcJNqdRrjjlk
+CldUlPXPpAYqLu3XsEJm4pT0Wpypj+WUlOHpoaUzjJSRVxfpJmEjg0JNXDL1ljm9
+7bZZdpZV9Brpe0o3/oWqvxXEckZO08OTB8GY6+Wlogp8tP9Pm8r3xekgSH88hKpc
+llEUNoB2VKkoht0DzGYmK9OHABEBAAGJAmwEGAEIACAWIQTUviIxGtMTHl7aKaRh
+CS6FtyJxiQUCW9673AIbAgFACRBhCS6FtyJxicB0IAQZAQgAHRYhBPg2Slngf/6f
+TWMAWmWg7qAuMMrXBQJb3rvcAAoJEGWg7qAuMMrXA/YH/1ooLR5e5RcpfEWhP7qk
+ThRHpWcjNNL9YeeX3fyBkRvPBLTdC6+BWqgaj5DGY1PyzfVDAWk3fu+PLx5R2sHm
+apY1ybvfQjvSHe2OMO1sxdwt2MkLBmfdhBsbYbDytPq4R1dDG2iDbqSNaDvYAExY
+JUsate6PNxSWrRkY2lwmWrvI6+e/wctTBrY5PiKtTZMxpK1++/C3UUBiyg8NkGu5
+bHR2PHd5VDwB/Jm2/exC5iHPbTxtmjOwEyS+5wZhbkx6OoZhHCMN9hIvSitc8TNG
+cpRGJIwYxwJZJVpim/TImsjAubh1uyMoY5fjW4GyBK9iU2plv/bS+lKyCMYgxHam
+hzXwmgf/Q/ld9VKXKIXPWs8AeABfHYkMLeZ34laZ1Xhf1vPnktQctlukK8CzbYTU
+Wm2BZ7kn/VEhwGOmrQ1nvnoCHTCyL+HHtIt8pKHM0rtKDKFAjMXZfZEK7DR2Qqll
+/zogwy0m9Obvz/94XvdNMurUgdeTGyDwOouQcP+vd5x4LqsUtQEmwQfy4iLt7wl3
+RRLPUTLyCfqpD98UAPeqCJkIikd1Ojhr+fd3jjSoo1CDTah0auvlMSMifjggIvi9
+kE4nQISS0QqehGQ/ertNnLYWKvCgPI9fq8fQXG3mnFVR3qXhtSbIMbF1/AUye2bk
+uVVZ3WTo2oPFEVv/ZyTH9NcP4XpeuA==
+=KRyT
 -----END PGP PUBLIC KEY BLOCK-----
index ce271ca4c1a07f620f25c5f4dd6febe020308c64..d202aaed06fc6cba62a1955e790bbe324d365235 100755 (executable)
@@ -6,9 +6,9 @@ test_description='Tests rebase performance'
 test_perf_default_repo
 
 test_expect_success 'setup rebasing on top of a lot of changes' '
-       git checkout -f -b base &&
-       git checkout -b to-rebase &&
-       git checkout -b upstream &&
+       git checkout -f -B base &&
+       git checkout -B to-rebase &&
+       git checkout -B upstream &&
        for i in $(seq 100)
        do
                # simulate huge diffs
@@ -35,8 +35,8 @@ test_perf 'rebase on top of a lot of unrelated changes' '
 
 test_expect_success 'setup rebasing many changes without split-index' '
        git config core.splitIndex false &&
-       git checkout -b upstream2 to-rebase &&
-       git checkout -b to-rebase2 upstream
+       git checkout -B upstream2 to-rebase &&
+       git checkout -B to-rebase2 upstream
 '
 
 test_perf 'rebase a lot of unrelated changes without split-index' '
index e56dfce6680298c133bc2b2de12d9492fda66b7a..3941ad25286562a57faa63d4ba37604d1fd708bd 100755 (executable)
@@ -47,4 +47,18 @@ test_expect_success 'notice empty queue' '
        test_cmp expect actual
 '
 
+cat >expect <<'EOF'
+3
+2
+6
+4
+5
+1
+8
+EOF
+test_expect_success 'stack order' '
+       test-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 17d0c18feb84e2c47167b9b54f71f192d78b0e9b..f5b10861c498e435155f6aec5dec6f27c82aa51b 100755 (executable)
@@ -23,7 +23,6 @@ usage: test-tool parse-options <options>
     -j <n>                get a integer, too
     -m, --magnitude <n>   get a magnitude
     --set23               set integer to 23
-    -t <time>             get timestamp of <time>
     -L, --length <str>    get length of <str>
     -F, --file <file>     set file to <file>
 
@@ -245,27 +244,6 @@ test_expect_success 'keep some options as arguments' '
        test-tool parse-options --expect="arg 00: --quux" --quux
 '
 
-cat >expect <<\EOF
-boolean: 0
-integer: 0
-magnitude: 0
-timestamp: 1
-string: (not set)
-abbrev: 7
-verbose: -1
-quiet: 1
-dry run: no
-file: (not set)
-arg 00: foo
-EOF
-
-test_expect_success 'OPT_DATE() works' '
-       test-tool parse-options -t "1970-01-01 00:00:01 +0000" \
-               foo -q >output 2>output.err &&
-       test_must_be_empty output.err &&
-       test_cmp expect output
-'
-
 cat >expect <<\EOF
 Callback: "four", 0
 boolean: 5
index 6aae36417122a8af5d010910fb2586aa9ec91815..e497c1358f8b2da6960d3d73db3cc75f9f7df85c 100755 (executable)
@@ -122,6 +122,36 @@ test_expect_success 'changed commit' '
        test_cmp expected actual
 '
 
+test_expect_success 'changed commit with --no-patch diff option' '
+       git range-diff --no-color --no-patch topic...changed >actual &&
+       cat >expected <<-EOF &&
+       1:  4de457d = 1:  a4b3333 s/5/A/
+       2:  fccce22 = 2:  f51d370 s/4/A/
+       3:  147e64e ! 3:  0559556 s/11/B/
+       4:  a63e992 ! 4:  d966c5c s/12/B/
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'changed commit with --stat diff option' '
+       git range-diff --no-color --stat topic...changed >actual &&
+       cat >expected <<-EOF &&
+       1:  4de457d = 1:  a4b3333 s/5/A/
+            a => b | 0
+            1 file changed, 0 insertions(+), 0 deletions(-)
+       2:  fccce22 = 2:  f51d370 s/4/A/
+            a => b | 0
+            1 file changed, 0 insertions(+), 0 deletions(-)
+       3:  147e64e ! 3:  0559556 s/11/B/
+            a => b | 0
+            1 file changed, 0 insertions(+), 0 deletions(-)
+       4:  a63e992 ! 4:  d966c5c s/12/B/
+            a => b | 0
+            1 file changed, 0 insertions(+), 0 deletions(-)
+       EOF
+       test_cmp expected actual
+'
+
 test_expect_success 'changed commit with sm config' '
        git range-diff --no-color --submodule=log topic...changed >actual &&
        cat >expected <<-EOF &&
index f355c6825a4a5ff6adef656c432a4e2fdaf0fea9..4c7494cc8f77a3ff92373cb130974825c4418ada 100755 (executable)
@@ -361,4 +361,12 @@ test_expect_success 'autostash with dirty submodules' '
        git rebase -i --autostash HEAD
 '
 
+test_expect_success 'branch is left alone when possible' '
+       git checkout -b unchanged-branch &&
+       echo changed >file0 &&
+       git rebase --autostash unchanged-branch &&
+       test changed = "$(cat file0)" &&
+       test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
+'
+
 test_done
index aa7bfc88ece9de7f542f354c78b7be9ec6d2bdf7..cc5646836fce1aaaa01556450a9b017c7a853088 100755 (executable)
@@ -396,4 +396,20 @@ test_expect_success 'with --autosquash and --exec' '
        grep "G: +G" actual
 '
 
+test_expect_success '--continue after resolving conflicts after a merge' '
+       git checkout -b already-has-g E &&
+       git cherry-pick E..G &&
+       test_commit H2 &&
+
+       git checkout -b conflicts-in-merge H &&
+       test_commit H2 H2.t conflicts H2-conflict &&
+       test_must_fail git rebase -r already-has-g &&
+       grep conflicts H2.t &&
+       echo resolved >H2.t &&
+       git add -u &&
+       git rebase --continue &&
+       test_must_fail git rev-parse --verify HEAD^2 &&
+       test_path_is_missing .git/MERGE_HEAD
+'
+
 test_done
index 6d9287231826ece18873b531186907cd75ef7461..4c3f264a633b770445e116edfac83872b47916bf 100755 (executable)
@@ -29,6 +29,18 @@ test_expect_success 'apply exits non-zero with no-op patch' '
        test_must_fail git apply --check input
 '
 
+test_expect_success '`apply --recount` allows no-op patch' '
+       echo 1 >1 &&
+       git apply --recount --check <<-\EOF
+       diff --get a/1 b/1
+       index 6696ea4..606eddd 100644
+       --- a/1
+       +++ b/1
+       @@ -1,1 +1,1 @@
+        1
+       EOF
+'
+
 test_expect_success 'invalid combination: create and copy' '
        test_must_fail git apply --check - <<-\EOF
        diff --git a/1 b/2
index 747775c147612f3b09a599661fe3dc7d3b1d34bd..3e9876e1971348daad7fd87f8aa107ea5fd6aaff 100755 (executable)
@@ -78,4 +78,11 @@ test_expect_success GPG 'pull commit with bad signature with --no-verify-signatu
        git pull --ff-only --no-verify-signatures bad 2>pullerror
 '
 
+test_expect_success GPG 'pull unsigned commit into unborn branch' '
+       git init empty-repo &&
+       test_must_fail \
+               git -C empty-repo pull --verify-signatures ..  2>pullerror &&
+       test_i18ngrep "does not have a GPG signature" pullerror
+'
+
 test_done
index b5a1190ffe63b53d8b637b39a15d3d94b3efa6cd..a10f0df02b0ec8acdcaf7c90d02da4a9c20ffb1b 100755 (executable)
@@ -12,6 +12,22 @@ unnote () {
        git name-rev --tags --stdin | sed -e "s|$OID_REGEX (tags/\([^)]*\)) |\1 |g"
 }
 
+#
+# Create a test repo with interesting commit graph:
+#
+# A--B----------G--H--I--K--L
+#  \  \           /     /
+#   \  \         /     /
+#    C------E---F     J
+#        \_/
+#
+# The commits are laid out from left-to-right starting with
+# the root commit A and terminating at the tip commit L.
+#
+# There are a few places where we adjust the commit date or
+# author date to make the --topo-order, --date-order, and
+# --author-date-order flags produce different output.
+
 test_expect_success setup '
        echo "Hi there" >file &&
        echo "initial" >lost &&
@@ -21,10 +37,18 @@ test_expect_success setup '
 
        git branch other-branch &&
 
+       git symbolic-ref HEAD refs/heads/unrelated &&
+       git rm -f "*" &&
+       echo "Unrelated branch" >side &&
+       git add side &&
+       test_tick && git commit -m "Side root" &&
+       note J &&
+       git checkout master &&
+
        echo "Hello" >file &&
        echo "second" >lost &&
        git add file lost &&
-       test_tick && git commit -m "Modified file and lost" &&
+       test_tick && GIT_AUTHOR_DATE=$(($test_tick + 120)) git commit -m "Modified file and lost" &&
        note B &&
 
        git checkout other-branch &&
@@ -63,13 +87,6 @@ test_expect_success setup '
        test_tick && git commit -a -m "Final change" &&
        note I &&
 
-       git symbolic-ref HEAD refs/heads/unrelated &&
-       git rm -f "*" &&
-       echo "Unrelated branch" >side &&
-       git add side &&
-       test_tick && git commit -m "Side root" &&
-       note J &&
-
        git checkout master &&
        test_tick && git merge --allow-unrelated-histories -m "Coolest" unrelated &&
        note K &&
@@ -103,14 +120,24 @@ check_result () {
        check_outcome success "$@"
 }
 
-check_result 'L K J I H G F E D C B A' --full-history
+check_result 'L K J I H F E D C G B A' --full-history --topo-order
+check_result 'L K I H G F E D C B J A' --full-history
+check_result 'L K I H G F E D C B J A' --full-history --date-order
+check_result 'L K I H G F E D B C J A' --full-history --author-date-order
 check_result 'K I H E C B A' --full-history -- file
 check_result 'K I H E C B A' --full-history --topo-order -- file
 check_result 'K I H E C B A' --full-history --date-order -- file
+check_result 'K I H E B C A' --full-history --author-date-order -- file
 check_result 'I E C B A' --simplify-merges -- file
+check_result 'I E C B A' --simplify-merges --topo-order -- file
+check_result 'I E C B A' --simplify-merges --date-order -- file
+check_result 'I E B C A' --simplify-merges --author-date-order -- file
 check_result 'I B A' -- file
 check_result 'I B A' --topo-order -- file
+check_result 'I B A' --date-order -- file
+check_result 'I B A' --author-date-order -- file
 check_result 'H' --first-parent -- another-file
+check_result 'H' --first-parent --topo-order -- another-file
 
 check_result 'E C B A' --full-history E -- lost
 test_expect_success 'full history simplification without parent' '
index 270e579c2d3a30b2a08517bc63fe6edf5221af59..bb5aeac07f8341ed44bfe25aba6238a92e1fc9e7 100755 (executable)
@@ -36,7 +36,13 @@ test_expect_success 'setup' '
        git tag foo/bar master &&
        commit master3 &&
        git update-ref refs/remotes/foo/baz master &&
-       commit master4
+       commit master4 &&
+       git update-ref refs/remotes/upstream/one subspace/one &&
+       git update-ref refs/remotes/upstream/two subspace/two &&
+       git update-ref refs/remotes/upstream/x subspace-x &&
+       git tag qux/one subspace/one &&
+       git tag qux/two subspace/two &&
+       git tag qux/x subspace-x
 '
 
 test_expect_success 'rev-parse --glob=refs/heads/subspace/*' '
@@ -153,6 +159,54 @@ test_expect_success 'rev-parse --all clears --exclude' '
        compare rev-parse "--exclude=* --all --all" "--all"
 '
 
+test_expect_success 'rev-parse --exclude=glob with --branches=glob' '
+       compare rev-parse "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two"
+'
+
+test_expect_success 'rev-parse --exclude=glob with --tags=glob' '
+       compare rev-parse "--exclude=qux/? --tags=qux/*" "qux/one qux/two"
+'
+
+test_expect_success 'rev-parse --exclude=glob with --remotes=glob' '
+       compare rev-parse "--exclude=upstream/? --remotes=upstream/*" "upstream/one upstream/two"
+'
+
+test_expect_success 'rev-parse --exclude=ref with --branches=glob' '
+       compare rev-parse "--exclude=subspace-x --branches=sub*" "subspace/one subspace/two"
+'
+
+test_expect_success 'rev-parse --exclude=ref with --tags=glob' '
+       compare rev-parse "--exclude=qux/x --tags=qux/*" "qux/one qux/two"
+'
+
+test_expect_success 'rev-parse --exclude=ref with --remotes=glob' '
+       compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
+'
+
+test_expect_success 'rev-list --exclude=glob with --branches=glob' '
+       compare rev-list "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two"
+'
+
+test_expect_success 'rev-list --exclude=glob with --tags=glob' '
+       compare rev-list "--exclude=qux/? --tags=qux/*" "qux/one qux/two"
+'
+
+test_expect_success 'rev-list --exclude=glob with --remotes=glob' '
+       compare rev-list "--exclude=upstream/? --remotes=upstream/*" "upstream/one upstream/two"
+'
+
+test_expect_success 'rev-list --exclude=ref with --branches=glob' '
+       compare rev-list "--exclude=subspace-x --branches=sub*" "subspace/one subspace/two"
+'
+
+test_expect_success 'rev-list --exclude=ref with --tags=glob' '
+       compare rev-list "--exclude=qux/x --tags=qux/*" "qux/one qux/two"
+'
+
+test_expect_success 'rev-list --exclude=ref with --remotes=glob' '
+       compare rev-list "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
+'
+
 test_expect_success 'rev-list --glob=refs/heads/subspace/*' '
 
        compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
@@ -245,7 +299,7 @@ test_expect_success 'rev-list --tags=foo' '
 
 test_expect_success 'rev-list --tags' '
 
-       compare rev-list "foo/bar" "--tags"
+       compare rev-list "foo/bar qux/x qux/two qux/one" "--tags"
 
 '
 
@@ -304,7 +358,7 @@ test_expect_success 'shortlog accepts --glob/--tags/--remotes' '
          "master other/three someref subspace-x subspace/one subspace/two" \
          "--glob=heads/*" &&
        compare shortlog foo/bar --tags=foo &&
-       compare shortlog foo/bar --tags &&
+       compare shortlog "foo/bar qux/one qux/two qux/x" --tags &&
        compare shortlog foo/baz --remotes=foo
 
 '
index a0c64e617a187fd4513a9c0fa3d281e29ab14fe8..b24d85003606bf2076902d944fb395bf55761d5a 100755 (executable)
@@ -56,18 +56,22 @@ test_expect_success 'setup' '
        git config core.commitGraph true
 '
 
-test_three_modes () {
+run_three_modes () {
        test_when_finished rm -rf .git/objects/info/commit-graph &&
-       test-tool reach $1 <input >actual &&
+       "$@" <input >actual &&
        test_cmp expect actual &&
        cp commit-graph-full .git/objects/info/commit-graph &&
-       test-tool reach $1 <input >actual &&
+       "$@" <input >actual &&
        test_cmp expect actual &&
        cp commit-graph-half .git/objects/info/commit-graph &&
-       test-tool reach $1 <input >actual &&
+       "$@" <input >actual &&
        test_cmp expect actual
 }
 
+test_three_modes () {
+       run_three_modes test-tool reach "$@"
+}
+
 test_expect_success 'ref_newer:miss' '
        cat >input <<-\EOF &&
        A:commit-5-7
@@ -265,6 +269,90 @@ test_expect_success 'commit_contains:miss' '
        test_three_modes commit_contains --tag
 '
 
+test_expect_success 'rev-list: basic topo-order' '
+       git rev-parse \
+               commit-6-6 commit-5-6 commit-4-6 commit-3-6 commit-2-6 commit-1-6 \
+               commit-6-5 commit-5-5 commit-4-5 commit-3-5 commit-2-5 commit-1-5 \
+               commit-6-4 commit-5-4 commit-4-4 commit-3-4 commit-2-4 commit-1-4 \
+               commit-6-3 commit-5-3 commit-4-3 commit-3-3 commit-2-3 commit-1-3 \
+               commit-6-2 commit-5-2 commit-4-2 commit-3-2 commit-2-2 commit-1-2 \
+               commit-6-1 commit-5-1 commit-4-1 commit-3-1 commit-2-1 commit-1-1 \
+       >expect &&
+       run_three_modes git rev-list --topo-order commit-6-6
+'
+
+test_expect_success 'rev-list: first-parent topo-order' '
+       git rev-parse \
+               commit-6-6 \
+               commit-6-5 \
+               commit-6-4 \
+               commit-6-3 \
+               commit-6-2 \
+               commit-6-1 commit-5-1 commit-4-1 commit-3-1 commit-2-1 commit-1-1 \
+       >expect &&
+       run_three_modes git rev-list --first-parent --topo-order commit-6-6
+'
+
+test_expect_success 'rev-list: range topo-order' '
+       git rev-parse \
+               commit-6-6 commit-5-6 commit-4-6 commit-3-6 commit-2-6 commit-1-6 \
+               commit-6-5 commit-5-5 commit-4-5 commit-3-5 commit-2-5 commit-1-5 \
+               commit-6-4 commit-5-4 commit-4-4 commit-3-4 commit-2-4 commit-1-4 \
+               commit-6-3 commit-5-3 commit-4-3 \
+               commit-6-2 commit-5-2 commit-4-2 \
+               commit-6-1 commit-5-1 commit-4-1 \
+       >expect &&
+       run_three_modes git rev-list --topo-order commit-3-3..commit-6-6
+'
+
+test_expect_success 'rev-list: range topo-order' '
+       git rev-parse \
+               commit-6-6 commit-5-6 commit-4-6 \
+               commit-6-5 commit-5-5 commit-4-5 \
+               commit-6-4 commit-5-4 commit-4-4 \
+               commit-6-3 commit-5-3 commit-4-3 \
+               commit-6-2 commit-5-2 commit-4-2 \
+               commit-6-1 commit-5-1 commit-4-1 \
+       >expect &&
+       run_three_modes git rev-list --topo-order commit-3-8..commit-6-6
+'
+
+test_expect_success 'rev-list: first-parent range topo-order' '
+       git rev-parse \
+               commit-6-6 \
+               commit-6-5 \
+               commit-6-4 \
+               commit-6-3 \
+               commit-6-2 \
+               commit-6-1 commit-5-1 commit-4-1 \
+       >expect &&
+       run_three_modes git rev-list --first-parent --topo-order commit-3-8..commit-6-6
+'
+
+test_expect_success 'rev-list: ancestry-path topo-order' '
+       git rev-parse \
+               commit-6-6 commit-5-6 commit-4-6 commit-3-6 \
+               commit-6-5 commit-5-5 commit-4-5 commit-3-5 \
+               commit-6-4 commit-5-4 commit-4-4 commit-3-4 \
+               commit-6-3 commit-5-3 commit-4-3 \
+       >expect &&
+       run_three_modes git rev-list --topo-order --ancestry-path commit-3-3..commit-6-6
+'
+
+test_expect_success 'rev-list: symmetric difference topo-order' '
+       git rev-parse \
+               commit-6-6 commit-5-6 commit-4-6 \
+               commit-6-5 commit-5-5 commit-4-5 \
+               commit-6-4 commit-5-4 commit-4-4 \
+               commit-6-3 commit-5-3 commit-4-3 \
+               commit-6-2 commit-5-2 commit-4-2 \
+               commit-6-1 commit-5-1 commit-4-1 \
+               commit-3-8 commit-2-8 commit-1-8 \
+               commit-3-7 commit-2-7 commit-1-7 \
+       >expect &&
+       run_three_modes git rev-list --topo-order commit-3-8...commit-6-6
+'
+
 test_expect_success 'get_reachable_subset:all' '
        cat >input <<-\EOF &&
        X:commit-9-1
index 19ccae28699da7949af3203cde62ac648c7effb4..86d3f93fa22e45ba9dda24c49ec02df14e22ebc3 100755 (executable)
@@ -176,8 +176,9 @@ test_expect_success GPG 'show good signature with custom format' '
        13B6F51ECDDE430D
        C O Mitter <committer@example.com>
        73D758744BE721698EC54E8713B6F51ECDDE430D
+       73D758744BE721698EC54E8713B6F51ECDDE430D
        EOF
-       git log -1 --format="%G?%n%GK%n%GS%n%GF" sixth-signed >actual &&
+       git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
        test_cmp expect actual
 '
 
@@ -187,30 +188,33 @@ test_expect_success GPG 'show bad signature with custom format' '
        13B6F51ECDDE430D
        C O Mitter <committer@example.com>
 
+
        EOF
-       git log -1 --format="%G?%n%GK%n%GS%n%GF" $(cat forged1.commit) >actual &&
+       git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
        test_cmp expect actual
 '
 
 test_expect_success GPG 'show untrusted signature with custom format' '
        cat >expect <<-\EOF &&
        U
-       61092E85B7227189
+       65A0EEA02E30CAD7
        Eris Discordia <discord@example.net>
+       F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
        D4BE22311AD3131E5EDA29A461092E85B7227189
        EOF
-       git log -1 --format="%G?%n%GK%n%GS%n%GF" eighth-signed-alt >actual &&
+       git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
        test_cmp expect actual
 '
 
 test_expect_success GPG 'show unknown signature with custom format' '
        cat >expect <<-\EOF &&
        E
-       61092E85B7227189
+       65A0EEA02E30CAD7
+
 
 
        EOF
-       GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF" eighth-signed-alt >actual &&
+       GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
        test_cmp expect actual
 '
 
@@ -220,8 +224,9 @@ test_expect_success GPG 'show lack of signature with custom format' '
 
 
 
+
        EOF
-       git log -1 --format="%G?%n%GK%n%GS%n%GF" seventh-unsigned >actual &&
+       git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
        test_cmp expect actual
 '
 
@@ -261,8 +266,9 @@ test_expect_success GPG 'show double signature with custom format' '
 
 
 
+
        EOF
-       git log -1 --format="%G?%n%GK%n%GS%n%GF" $(cat double-commit.commit) >actual &&
+       git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat double-commit.commit) >actual &&
        test_cmp expect actual
 '
 
index e2b1df817a50a48132964124d359c7dc29a89e23..d99218a725c5956d75e32684b196bdc050a0e8b1 100755 (executable)
@@ -103,4 +103,11 @@ test_expect_success GPG 'merge commit with bad signature with merge.verifySignat
        git merge --no-verify-signatures $(cat forged.commit)
 '
 
+test_expect_success GPG 'merge unsigned commit into unborn branch' '
+       test_when_finished "git checkout initial" &&
+       git checkout --orphan unborn &&
+       test_must_fail git merge --verify-signatures side-unsigned 2>mergeerror &&
+       test_i18ngrep "does not have a GPG signature" mergeerror
+'
+
 test_done
index a2135e0743ac60d8d4512210a81bac2102948fa1..532984569132de11f6f05b561f817817523a3468 100644 (file)
@@ -20,6 +20,9 @@
 
 int online_cpus(void)
 {
+#ifdef NO_PTHREADS
+       return 1;
+#else
 #ifdef _SC_NPROCESSORS_ONLN
        long ncpus;
 #endif
@@ -59,10 +62,12 @@ int online_cpus(void)
 #endif
 
        return 1;
+#endif
 }
 
 int init_recursive_mutex(pthread_mutex_t *m)
 {
+#ifndef NO_PTHREADS
        pthread_mutexattr_t a;
        int ret;
 
@@ -74,4 +79,47 @@ int init_recursive_mutex(pthread_mutex_t *m)
                pthread_mutexattr_destroy(&a);
        }
        return ret;
+#else
+       return 0;
+#endif
+}
+
+#ifdef NO_PTHREADS
+int dummy_pthread_create(pthread_t *pthread, const void *attr,
+                        void *(*fn)(void *), void *data)
+{
+       /*
+        * Do nothing.
+        *
+        * The main purpose of this function is to break compiler's
+        * flow analysis and avoid -Wunused-variable false warnings.
+        */
+       return ENOSYS;
+}
+
+int dummy_pthread_init(void *data)
+{
+       /*
+        * Do nothing.
+        *
+        * The main purpose of this function is to break compiler's
+        * flow analysis or it may realize that functions like
+        * pthread_mutex_init() is no-op, which means the (static)
+        * variable is not used/initialized at all and trigger
+        * -Wunused-variable
+        */
+       return ENOSYS;
 }
+
+int dummy_pthread_join(pthread_t pthread, void **retval)
+{
+       /*
+        * Do nothing.
+        *
+        * The main purpose of this function is to break compiler's
+        * flow analysis and avoid -Wunused-variable false warnings.
+        */
+       return ENOSYS;
+}
+
+#endif
index d9a769d19084587b397c50e9420843be38e89903..4961487ed914f4fea817df26904109bb05f2a2c5 100644 (file)
@@ -4,12 +4,54 @@
 #ifndef NO_PTHREADS
 #include <pthread.h>
 
-extern int online_cpus(void);
-extern int init_recursive_mutex(pthread_mutex_t*);
+#define HAVE_THREADS 1
 
 #else
 
-#define online_cpus() 1
+#define HAVE_THREADS 0
+
+/*
+ * macros instead of typedefs because pthread definitions may have
+ * been pulled in by some system dependencies even though the user
+ * wants to disable pthread.
+ */
+#define pthread_t int
+#define pthread_mutex_t int
+#define pthread_cond_t int
+#define pthread_key_t int
+
+#define pthread_mutex_init(mutex, attr) dummy_pthread_init(mutex)
+#define pthread_mutex_lock(mutex)
+#define pthread_mutex_unlock(mutex)
+#define pthread_mutex_destroy(mutex)
+
+#define pthread_cond_init(cond, attr) dummy_pthread_init(cond)
+#define pthread_cond_wait(cond, mutex)
+#define pthread_cond_signal(cond)
+#define pthread_cond_broadcast(cond)
+#define pthread_cond_destroy(cond)
+
+#define pthread_key_create(key, attr) dummy_pthread_init(key)
+#define pthread_key_delete(key)
+
+#define pthread_create(thread, attr, fn, data) \
+       dummy_pthread_create(thread, attr, fn, data)
+#define pthread_join(thread, retval) \
+       dummy_pthread_join(thread, retval)
+
+#define pthread_setspecific(key, data)
+#define pthread_getspecific(key) NULL
+
+int dummy_pthread_create(pthread_t *pthread, const void *attr,
+                        void *(*fn)(void *), void *data);
+int dummy_pthread_join(pthread_t pthread, void **retval);
+
+int dummy_pthread_init(void *);
 
 #endif
+
+int online_cpus(void);
+int init_recursive_mutex(pthread_mutex_t*);
+
+
 #endif /* THREAD_COMPAT_H */
index 187568a112a08c7d2ceda7cdc216b72ebcce6631..a24711374c41918bed46fbe5d5a3060312917fa6 100644 (file)
@@ -1559,6 +1559,7 @@ void wt_status_get_state(struct wt_status_state *state,
        struct object_id oid;
 
        if (!stat(git_path_merge_head(the_repository), &st)) {
+               wt_status_check_rebase(NULL, state);
                state->merge_in_progress = 1;
        } else if (wt_status_check_rebase(NULL, state)) {
                ;               /* all set */
@@ -1583,9 +1584,13 @@ static void wt_longstatus_print_state(struct wt_status *s)
        const char *state_color = color(WT_STATUS_HEADER, s);
        struct wt_status_state *state = &s->state;
 
-       if (state->merge_in_progress)
+       if (state->merge_in_progress) {
+               if (state->rebase_interactive_in_progress) {
+                       show_rebase_information(s, state_color);
+                       fputs("\n", s->fp);
+               }
                show_merge_in_progress(s, state_color);
-       else if (state->am_in_progress)
+       else if (state->am_in_progress)
                show_am_in_progress(s, state_color);
        else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
                show_rebase_in_progress(s, state_color);