Merge branch 'cw/completion'
authorJunio C Hamano <gitster@pobox.com>
Wed, 15 Feb 2017 20:54:19 +0000 (12:54 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Feb 2017 20:54:19 +0000 (12:54 -0800)
More command line completion (in contrib/) for recent additions.

* cw/completion:
completion: recognize more long-options
completion: teach remote subcommands to complete options
completion: teach replace to complete options
completion: teach ls-remote to complete options
completion: improve bash completion for git-add
completion: add subcommand completion for rerere
completion: teach submodule subcommands to complete options

28 files changed:
Documentation/RelNotes/2.12.0.txt
Documentation/git-difftool.txt
Documentation/git-push.txt
Documentation/git-reset.txt
Documentation/git-submodule.txt
Documentation/rev-list-options.txt
GIT-VERSION-GEN
apply.c
builtin/diff-tree.c
builtin/diff.c
builtin/difftool.c
builtin/worktree.c
contrib/coccinelle/swap.cocci [new file with mode: 0644]
contrib/completion/git-completion.bash
diff-no-index.c
diff.c
dir.c
git-compat-util.h
graph.c
line-range.c
merge-recursive.c
object.c
pack-revindex.c
prio-queue.c
strbuf.h
t/perf/p5302-pack-index.sh
t/t4202-log.sh
t/t7800-difftool.sh
index 0c6eed2007f1b184815d601054b73bf5f452c6ae..1841b065e8adcc34f9e6188f22a540fde33a315a 100644 (file)
@@ -436,6 +436,20 @@ notes for details).
    with AsciiDoc.  "make USE_ASCIIDOCTOR=YesPlease" to use it out of
    the box to document our pages is getting closer to reality.
 
+ * Correct command line completion (in contrib/) on "git svn"
+   (merge 2cbad17642 ew/complete-svn-authorship-options later to maint).
+
+ * Incorrect usage help message for "git worktree prune" has been fixed.
+   (merge 2488dcab22 ps/worktree-prune-help-fix later to maint).
+
+ * Adjust a perf test to new world order where commands that do
+   require a repository are really strict about having a repository.
+   (merge c86000c1a7 rs/p5302-create-repositories-before-tests later to maint).
+
+ * "git log --graph" did not work well with "--name-only", even though
+   other forms of "diff" output were handled correctly.
+   (merge f5022b5fed jk/log-graph-name-only later to maint).
+
  * Other minor doc, test and build updates and code cleanups.
    (merge f2627d9b19 sb/submodule-config-cleanup later to maint).
    (merge 384f1a167b sb/unpack-trees-cleanup later to maint).
@@ -444,3 +458,4 @@ notes for details).
    (merge 0aaad415bc rs/absolute-pathdup later to maint).
    (merge 4432dd6b5b rs/receive-pack-cleanup later to maint).
    (merge 540a398e9c sg/mailmap-self later to maint).
+   (merge 209df269a6 nd/rev-list-all-includes-HEAD-doc later to maint).
index 224fb3090bba3f9dfd98448019a2ff6303b268f7..96c26e6aa82c98da1652023f0d04b4b63c8a4944 100644 (file)
@@ -86,10 +86,11 @@ instead.  `--no-symlinks` is the default on Windows.
        Additionally, `$BASE` is set in the environment.
 
 -g::
---gui::
+--[no-]gui::
        When 'git-difftool' is invoked with the `-g` or `--gui` option
        the default diff tool will be read from the configured
-       `diff.guitool` variable instead of `diff.tool`.
+       `diff.guitool` variable instead of `diff.tool`. The `--no-gui`
+       option can be used to override this setting.
 
 --[no-]trust-exit-code::
        'git-difftool' invokes a diff tool individually on each file.
index 8eefabd0d1610eadf9d459817e2457d2ce2dd6d9..1624a35888c2e39f70b925a2f176d53dd02b809e 100644 (file)
@@ -272,7 +272,7 @@ origin +master` to force a push to the `master` branch). See the
        standard error stream is not directed to a terminal.
 
 --no-recurse-submodules::
---recurse-submodules=check|on-demand|no::
+--recurse-submodules=check|on-demand|only|no::
        May be used to make sure all submodule commits used by the
        revisions to be pushed are available on a remote-tracking branch.
        If 'check' is used Git will verify that all submodule commits that
@@ -280,11 +280,12 @@ origin +master` to force a push to the `master` branch). See the
        remote of the submodule. If any commits are missing the push will
        be aborted and exit with non-zero status. If 'on-demand' is used
        all submodules that changed in the revisions to be pushed will be
-       pushed. If on-demand was not able to push all necessary revisions
-       it will also be aborted and exit with non-zero status. A value of
-       'no' or using `--no-recurse-submodules` can be used to override the
-       push.recurseSubmodules configuration variable when no submodule
-       recursion is required.
+       pushed. If on-demand was not able to push all necessary revisions it will
+       also be aborted and exit with non-zero status. If 'only' is used all
+       submodules will be recursively pushed while the superproject is left
+       unpushed. A value of 'no' or using `--no-recurse-submodules` can be used
+       to override the push.recurseSubmodules configuration variable when no
+       submodule recursion is required.
 
 --[no-]verify::
        Toggle the pre-push hook (see linkgit:githooks[5]).  The
index 25432d9257f9c06773edc8ca3d24ddae16bddf99..add6220fce774d80ba25f50b99a721b2947e4f5d 100644 (file)
@@ -292,6 +292,44 @@ $ git reset --keep start                    <3>
 <3> But you can use "reset --keep" to remove the unwanted commit after
     you switched to "branch2".
 
+Split a commit into two::
++
+Suppose that you have created a commit, but later decide that you want to break
+apart the changes into two logical chunks and commit each separately. You want
+to include part of the original commit into the first commit, while including
+the remainder in a second commit. You can use git reset to rewind the history
+without changing the index, and then use git add -p to interactively select
+which hunks to put into the first commit.
++
+------------
+$ git reset HEAD^                           <1>
+$ git add -p                                <2>
+$ git diff --cached                         <3>
+$ git commit -c HEAD@{1}                    <4>
+...
+$ git add ...                               <5>
+$ git diff --cached                         <6>
+$ git commit ...                            <7>
+------------
++
+<1> First, reset the history back one commit so that we remove the original
+    commit, but leave the working tree with all the changes.
+<2> Now, interactively select hunks to add to a new commit using git add -p.
+    This will ask for each hunk separately and you can use simple commands like
+    "yes, include", "no don't include" or even "edit".
+<3> Once satisfied with the hunks, you should verify that it is what you
+    expected by using git diff --cached to show all changes in the index.
+<4> Next, commit the changes stored in the index. "-c" specifies to load the
+    editor with a commit message from a previous commit so that you can re-use the
+    original commit message. HEAD@{1} is special notation to reference what
+    HEAD used to be prior to the reset command. See linkgit:git-reflog[1] for
+    more details.
+<5> Now you've created the first commit, and can repeat steps 2-4 as often as
+    you like to break the work into any number of commits. Here we show a second
+    step which simply adds the remaining changes.
+<6> Then check again that the changes are what you expected to add.
+<7> And finally commit the remaining changes.
+
 
 DISCUSSION
 ----------
index 918bd1d1bd062ae16c00509a1ac1051714f9ca51..4a4cede144cac1799db6915964ad03ca252026f0 100644 (file)
@@ -9,17 +9,12 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
-'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
-             [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
+'git submodule' [--quiet] add [<options>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
-'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
-             [--[no-]recommend-shallow] [-f|--force] [--rebase|--merge]
-             [--reference <repository>] [--depth <depth>] [--recursive]
-             [--jobs <n>] [--] [<path>...]
-'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
-             [commit] [--] [<path>...]
+'git submodule' [--quiet] update [<options>] [--] [<path>...]
+'git submodule' [--quiet] summary [<options>] [--] [<path>...]
 'git submodule' [--quiet] foreach [--recursive] <command>
 'git submodule' [--quiet] sync [--recursive] [--] [<path>...]
 'git submodule' [--quiet] absorbgitdirs [--] [<path>...]
@@ -63,7 +58,7 @@ if you choose to go that route.
 
 COMMANDS
 --------
-add::
+add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]::
        Add the given repository as a submodule at the given path
        to the changeset to be committed next to the current
        project: the current project is termed the "superproject".
@@ -104,7 +99,7 @@ together in the same relative location, and only the
 superproject's URL needs to be provided: git-submodule will correctly
 locate the submodule using the relative URL in .gitmodules.
 
-status::
+status [--cached] [--recursive] [--] [<path>...]::
        Show the status of the submodules. This will print the SHA-1 of the
        currently checked out commit for each submodule, along with the
        submodule path and the output of 'git describe' for the
@@ -121,7 +116,7 @@ submodules with respect to the commit recorded in the index or the HEAD,
 linkgit:git-status[1] and linkgit:git-diff[1] will provide that information
 too (and can also report changes to a submodule's work tree).
 
-init::
+init [--] [<path>...]::
        Initialize the submodules recorded in the index (which were
        added and committed elsewhere) by copying submodule
        names and urls from .gitmodules to .git/config.
@@ -136,7 +131,7 @@ init::
        the explicit 'init' step if you do not intend to customize
        any submodule locations.
 
-deinit::
+deinit [-f|--force] (--all|[--] <path>...)::
        Unregister the given submodules, i.e. remove the whole
        `submodule.$name` section from .git/config together with their work
        tree. Further calls to `git submodule update`, `git submodule foreach`
@@ -152,20 +147,20 @@ instead of deinit-ing everything, to prevent mistakes.
 If `--force` is specified, the submodule's working tree will
 be removed even if it contains local modifications.
 
-update::
+update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge] [--reference <repository>] [--depth <depth>] [--recursive] [--jobs <n>] [--] [<path>...]::
 +
 --
 Update the registered submodules to match what the superproject
 expects by cloning missing submodules and updating the working tree of
 the submodules. The "updating" can be done in several ways depending
 on command line options and the value of `submodule.<name>.update`
-configuration variable. Supported update procedures are:
+configuration variable. The command line option takes precedence over
+the configuration variable. if neither is given, a checkout is performed.
+update procedures supported both from the command line as well as setting
+`submodule.<name>.update`:
 
        checkout;; the commit recorded in the superproject will be
-           checked out in the submodule on a detached HEAD. This is
-           done when `--checkout` option is given, or no option is
-           given, and `submodule.<name>.update` is unset, or if it is
-           set to 'checkout'.
+           checked out in the submodule on a detached HEAD.
 +
 If `--force` is specified, the submodule will be checked out (using
 `git checkout --force` if appropriate), even if the commit specified
@@ -173,23 +168,21 @@ in the index of the containing repository already matches the commit
 checked out in the submodule.
 
        rebase;; the current branch of the submodule will be rebased
-           onto the commit recorded in the superproject. This is done
-           when `--rebase` option is given, or no option is given, and
-           `submodule.<name>.update` is set to 'rebase'.
+           onto the commit recorded in the superproject.
 
        merge;; the commit recorded in the superproject will be merged
-           into the current branch in the submodule. This is done
-           when `--merge` option is given, or no option is given, and
-           `submodule.<name>.update` is set to 'merge'.
+           into the current branch in the submodule.
+
+The following procedures are only available via the `submodule.<name>.update`
+configuration variable:
 
        custom command;; arbitrary shell command that takes a single
            argument (the sha1 of the commit recorded in the
-           superproject) is executed. This is done when no option is
-           given, and `submodule.<name>.update` has the form of
-           '!command'.
+           superproject) is executed. When `submodule.<name>.update`
+           is set to '!command', the remainder after the exclamation mark
+           is the custom command.
 
-When no option is given and `submodule.<name>.update` is set to 'none',
-the submodule is not updated.
+       none;; the submodule is not updated.
 
 If the submodule is not yet initialized, and you just want to use the
 setting as stored in .gitmodules, you can automatically initialize the
@@ -198,7 +191,7 @@ submodule with the `--init` option.
 If `--recursive` is specified, this command will recurse into the
 registered submodules, and update any nested submodules within.
 --
-summary::
+summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::
        Show commit summary between the given commit (defaults to HEAD) and
        working tree/index. For a submodule in question, a series of commits
        in the submodule between the given super project commit and the
@@ -211,7 +204,7 @@ summary::
 Using the `--submodule=log` option with linkgit:git-diff[1] will provide that
 information too.
 
-foreach::
+foreach [--recursive] <command>::
        Evaluates an arbitrary shell command in each checked out submodule.
        The command has access to the variables $name, $path, $sha1 and
        $toplevel:
@@ -232,7 +225,7 @@ As an example, +git submodule foreach \'echo $path {backtick}git
 rev-parse HEAD{backtick}'+ will show the path and currently checked out
 commit for each submodule.
 
-sync::
+sync [--recursive] [--] [<path>...]::
        Synchronizes submodules' remote URL configuration setting
        to the value specified in .gitmodules. It will only affect those
        submodules which already have a URL entry in .git/config (that is the
index 5da7cf5a8d02d6fd52993f042f29efe4cc749051..a02f7324c01ee5811441d2a6dcb93aafd892298c 100644 (file)
@@ -133,8 +133,8 @@ parents) and `--max-parents=-1` (negative numbers denote no upper limit).
        for all following revision specifiers, up to the next `--not`.
 
 --all::
-       Pretend as if all the refs in `refs/` are listed on the
-       command line as '<commit>'.
+       Pretend as if all the refs in `refs/`, along with `HEAD`, are
+       listed on the command line as '<commit>'.
 
 --branches[=<pattern>]::
        Pretend as if all the refs in `refs/heads` are listed
index 4bed33d2aee963ed3f46104afff4bd6788e612c8..1eabbd88ac5bf7bc49c69003277872cd87a61102 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.12.0-rc0
+DEF_VER=v2.12.0-rc1
 
 LF='
 '
diff --git a/apply.c b/apply.c
index 2ed808d429969ff9516ba1bf166c3fdfa6d63ed5..0e2caeab9cc523364e0cfbb8cbbb5aba1a0a58ee 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -2187,29 +2187,20 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si
        return offset + hdrsize + patchsize;
 }
 
-#define swap(a,b) myswap((a),(b),sizeof(a))
-
-#define myswap(a, b, size) do {                \
-       unsigned char mytmp[size];      \
-       memcpy(mytmp, &a, size);                \
-       memcpy(&a, &b, size);           \
-       memcpy(&b, mytmp, size);                \
-} while (0)
-
 static void reverse_patches(struct patch *p)
 {
        for (; p; p = p->next) {
                struct fragment *frag = p->fragments;
 
-               swap(p->new_name, p->old_name);
-               swap(p->new_mode, p->old_mode);
-               swap(p->is_new, p->is_delete);
-               swap(p->lines_added, p->lines_deleted);
-               swap(p->old_sha1_prefix, p->new_sha1_prefix);
+               SWAP(p->new_name, p->old_name);
+               SWAP(p->new_mode, p->old_mode);
+               SWAP(p->is_new, p->is_delete);
+               SWAP(p->lines_added, p->lines_deleted);
+               SWAP(p->old_sha1_prefix, p->new_sha1_prefix);
 
                for (; frag; frag = frag->next) {
-                       swap(frag->newpos, frag->oldpos);
-                       swap(frag->newlines, frag->oldlines);
+                       SWAP(frag->newpos, frag->oldpos);
+                       SWAP(frag->newlines, frag->oldlines);
                }
        }
 }
index 806dd7a885e9e7b87e19ca8acd2b6d0383b41d85..8ce00480cd484e10b0b46d931c934fcd3ba7b71e 100644 (file)
@@ -147,9 +147,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
                tree1 = opt->pending.objects[0].item;
                tree2 = opt->pending.objects[1].item;
                if (tree2->flags & UNINTERESTING) {
-                       struct object *tmp = tree2;
-                       tree2 = tree1;
-                       tree1 = tmp;
+                       SWAP(tree2, tree1);
                }
                diff_tree_sha1(tree1->oid.hash,
                               tree2->oid.hash,
index 7f91f6d2267db962fb7c25e92983afd4e811d43e..3d64b8533732b5d4af971e6b1cd23ff66123e8e9 100644 (file)
@@ -45,12 +45,9 @@ static void stuff_change(struct diff_options *opt,
                return;
 
        if (DIFF_OPT_TST(opt, REVERSE_DIFF)) {
-               unsigned tmp;
-               const unsigned char *tmp_u;
-               const char *tmp_c;
-               tmp = old_mode; old_mode = new_mode; new_mode = tmp;
-               tmp_u = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_u;
-               tmp_c = old_name; old_name = new_name; new_name = tmp_c;
+               SWAP(old_mode, new_mode);
+               SWAP(old_sha1, new_sha1);
+               SWAP(old_name, new_name);
        }
 
        if (opt->prefix &&
index b5e85ab0794fc08941cfdb87c4a8c2e62447e199..d13350ce832cd8c0064c8a5b2d3c9be64f876b8d 100644 (file)
@@ -647,10 +647,6 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
-       /* NEEDSWORK: once we no longer spawn anything, remove this */
-       setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
-       setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
-
        git_config(difftool_config, NULL);
        symlinks = has_symlinks;
 
@@ -661,6 +657,10 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
        if (tool_help)
                return print_tool_help();
 
+       /* NEEDSWORK: once we no longer spawn anything, remove this */
+       setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
+       setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
+
        if (use_gui_tool && diff_gui_tool && *diff_gui_tool)
                setenv("GIT_DIFF_TOOL", diff_gui_tool, 1);
        else if (difftool_cmd) {
index 9a97e37a3fa53e730f0963f8f00bbca9f6d6efc6..831fe058a53da95643b1a93038f576d5bffea7ef 100644 (file)
@@ -125,9 +125,9 @@ static int prune(int ac, const char **av, const char *prefix)
 {
        struct option options[] = {
                OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
-               OPT__VERBOSE(&verbose, N_("report pruned objects")),
+               OPT__VERBOSE(&verbose, N_("report pruned working trees")),
                OPT_EXPIRY_DATE(0, "expire", &expire,
-                               N_("expire objects older than <time>")),
+                               N_("expire working trees older than <time>")),
                OPT_END()
        };
 
diff --git a/contrib/coccinelle/swap.cocci b/contrib/coccinelle/swap.cocci
new file mode 100644 (file)
index 0000000..a0934d1
--- /dev/null
@@ -0,0 +1,28 @@
+@ swap_with_declaration @
+type T;
+identifier tmp;
+T a, b;
+@@
+- T tmp = a;
++ T tmp;
++ tmp = a;
+  a = b;
+  b = tmp;
+
+@ swap @
+type T;
+T tmp, a, b;
+@@
+- tmp = a;
+- a = b;
+- b = tmp;
++ SWAP(a, b);
+
+@ extends swap @
+identifier unused;
+@@
+  {
+  ...
+- T unused;
+  ... when != unused
+  }
index b09b55f429496cd2295cce5c5e23bc66c7d32dc2..41ee52991d0c1b1fa2a6021133cffecd3ca9deb0 100644 (file)
@@ -1692,7 +1692,7 @@ _git_pull ()
        __git_complete_remote_or_refspec
 }
 
-__git_push_recurse_submodules="check on-demand"
+__git_push_recurse_submodules="check on-demand only"
 
 __git_complete_force_with_lease ()
 {
@@ -2684,14 +2684,14 @@ _git_svn ()
                        --no-metadata --use-svm-props --use-svnsync-props
                        --log-window-size= --no-checkout --quiet
                        --repack-flags --use-log-author --localtime
+                       --add-author-from
                        --ignore-paths= --include-paths= $remote_opts
                        "
                local init_opts="
                        --template= --shared= --trunk= --tags=
                        --branches= --stdlayout --minimize-url
                        --no-metadata --use-svm-props --use-svnsync-props
-                       --rewrite-root= --prefix= --use-log-author
-                       --add-author-from $remote_opts
+                       --rewrite-root= --prefix= $remote_opts
                        "
                local cmt_opts="
                        --edit --rmdir --find-copies-harder --copy-similarity=
index f420786039d387d3a943d510c802ecd90c3ddf28..df762fd0f7d1ec74175a42de07b064107d3a601a 100644 (file)
@@ -185,10 +185,8 @@ static int queue_diff(struct diff_options *o,
                struct diff_filespec *d1, *d2;
 
                if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
-                       unsigned tmp;
-                       const char *tmp_c;
-                       tmp = mode1; mode1 = mode2; mode2 = tmp;
-                       tmp_c = name1; name1 = name2; name2 = tmp_c;
+                       SWAP(mode1, mode2);
+                       SWAP(name1, name2);
                }
 
                d1 = noindex_filespec(name1, mode1);
diff --git a/diff.c b/diff.c
index d91a344908abe7335eaffef4157fc59fefdf3815..051761be405ece65423d43830f08ed7b7dec9756 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -4450,6 +4450,7 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
                name_a = p->two->path;
                name_b = NULL;
                strip_prefix(opt->prefix_length, &name_a, &name_b);
+               fprintf(opt->file, "%s", diff_line_prefix(opt));
                write_name_quoted(name_a, opt->file, opt->line_termination);
        }
 }
@@ -5117,14 +5118,10 @@ void diff_change(struct diff_options *options,
                return;
 
        if (DIFF_OPT_TST(options, REVERSE_DIFF)) {
-               unsigned tmp;
-               const unsigned char *tmp_c;
-               tmp = old_mode; old_mode = new_mode; new_mode = tmp;
-               tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
-               tmp = old_sha1_valid; old_sha1_valid = new_sha1_valid;
-                       new_sha1_valid = tmp;
-               tmp = old_dirty_submodule; old_dirty_submodule = new_dirty_submodule;
-                       new_dirty_submodule = tmp;
+               SWAP(old_mode, new_mode);
+               SWAP(old_sha1, new_sha1);
+               SWAP(old_sha1_valid, new_sha1_valid);
+               SWAP(old_dirty_submodule, new_dirty_submodule);
        }
 
        if (options->prefix &&
diff --git a/dir.c b/dir.c
index 65c3e681b8e04aa47b6cf41faca0822ead59fb6a..4541f9e1460cde7945e2443f2fee5c7df18073f5 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -174,20 +174,19 @@ char *common_prefix(const struct pathspec *pathspec)
 
 int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec)
 {
-       char *prefix;
+       const char *prefix;
        size_t prefix_len;
 
        /*
         * Calculate common prefix for the pathspec, and
         * use that to optimize the directory walk
         */
-       prefix = common_prefix(pathspec);
-       prefix_len = prefix ? strlen(prefix) : 0;
+       prefix_len = common_prefix_len(pathspec);
+       prefix = prefix_len ? pathspec->items[0].match : "";
 
        /* Read the directory and prune it */
        read_directory(dir, prefix, prefix_len, pathspec);
 
-       free(prefix);
        return prefix_len;
 }
 
index f46d40e4a475c9bd35ff02373101e8431e722b7d..ef6d560e156c0adefd897e04377b09d5c32edf08 100644 (file)
@@ -527,6 +527,16 @@ static inline int ends_with(const char *str, const char *suffix)
        return strip_suffix(str, suffix, &len);
 }
 
+#define SWAP(a, b) do {                                                \
+       void *_swap_a_ptr = &(a);                               \
+       void *_swap_b_ptr = &(b);                               \
+       unsigned char _swap_buffer[sizeof(a)];                  \
+       memcpy(_swap_buffer, _swap_a_ptr, sizeof(a));           \
+       memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a) +            \
+              BUILD_ASSERT_OR_ZERO(sizeof(a) == sizeof(b)));   \
+       memcpy(_swap_b_ptr, _swap_buffer, sizeof(a));           \
+} while (0)
+
 #if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
 
 #ifndef PROT_READ
diff --git a/graph.c b/graph.c
index 0649007704ac635af163a4e1016121744a951d1c..8b9049dd2c725f58314042deebfb69030e4321d3 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -497,7 +497,6 @@ static void graph_update_width(struct git_graph *graph,
 static void graph_update_columns(struct git_graph *graph)
 {
        struct commit_list *parent;
-       struct column *tmp_columns;
        int max_new_columns;
        int mapping_idx;
        int i, seen_this, is_commit_in_columns;
@@ -510,11 +509,8 @@ static void graph_update_columns(struct git_graph *graph)
         * We'll re-use the old columns array as storage to compute the new
         * columns list for the commit after this one.
         */
-       tmp_columns = graph->columns;
-       graph->columns = graph->new_columns;
+       SWAP(graph->columns, graph->new_columns);
        graph->num_columns = graph->num_new_columns;
-
-       graph->new_columns = tmp_columns;
        graph->num_new_columns = 0;
 
        /*
@@ -1031,7 +1027,6 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct strbuf
 static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf *sb)
 {
        int i;
-       int *tmp_mapping;
        short used_horizontal = 0;
        int horizontal_edge = -1;
        int horizontal_edge_target = -1;
@@ -1166,9 +1161,7 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
        /*
         * Swap mapping and new_mapping
         */
-       tmp_mapping = graph->mapping;
-       graph->mapping = graph->new_mapping;
-       graph->new_mapping = tmp_mapping;
+       SWAP(graph->mapping, graph->new_mapping);
 
        /*
         * If graph->mapping indicates that all of the branch lines
index de4e32f9424fbc0770756c3f61751fc69bfeb17e..323399d16cfa828adce913c9ff994e860ce2e7a5 100644 (file)
@@ -269,8 +269,7 @@ int parse_range_arg(const char *arg, nth_line_fn_t nth_line_cb,
                return -1;
 
        if (*begin && *end && *end < *begin) {
-               long tmp;
-               tmp = *end; *end = *begin; *begin = tmp;
+               SWAP(*end, *begin);
        }
 
        return 0;
index d3272094430ccd3914c8214df73ba8e11363cfa7..b7ff1ada3c350dce75ff09709395e97a60c96b96 100644 (file)
@@ -1390,14 +1390,11 @@ static int process_renames(struct merge_options *o,
                        branch1 = o->branch1;
                        branch2 = o->branch2;
                } else {
-                       struct rename *tmp;
                        renames1 = b_renames;
                        renames2Dst = &a_by_dst;
                        branch1 = o->branch2;
                        branch2 = o->branch1;
-                       tmp = ren2;
-                       ren2 = ren1;
-                       ren1 = tmp;
+                       SWAP(ren2, ren1);
                }
 
                if (ren1->processed)
index 67d9a9e2211fc2f6ab5772bfe58e42a2a95e469d..e680d881a45756eb234a80a9909c24a7b146c1f7 100644 (file)
--- a/object.c
+++ b/object.c
@@ -104,9 +104,7 @@ struct object *lookup_object(const unsigned char *sha1)
                 * that we do not need to walk the hash table the next
                 * time we look for it.
                 */
-               struct object *tmp = obj_hash[i];
-               obj_hash[i] = obj_hash[first];
-               obj_hash[first] = tmp;
+               SWAP(obj_hash[i], obj_hash[first]);
        }
        return obj;
 }
index 6bc7c940335cdf2d31cb38c2db6f8f6c985d3c3b..1b7ebd8d7eefbcc646867db3e52536b4aac42208 100644 (file)
@@ -59,7 +59,6 @@ static void sort_revindex(struct revindex_entry *entries, unsigned n, off_t max)
         * be a no-op, as everybody lands in the same zero-th bucket.
         */
        for (bits = 0; max >> bits; bits += DIGIT_SIZE) {
-               struct revindex_entry *swap;
                unsigned i;
 
                memset(pos, 0, BUCKETS * sizeof(*pos));
@@ -97,9 +96,7 @@ static void sort_revindex(struct revindex_entry *entries, unsigned n, off_t max)
                 * Now "to" contains the most sorted list, so we swap "from" and
                 * "to" for the next iteration.
                 */
-               swap = from;
-               from = to;
-               to = swap;
+               SWAP(from, to);
        }
 
        /*
index e4365b00d6c3366e6753fc6da3fe1a165ab1222d..17252d231b31f2b8d82d7160d7b95709e14779ff 100644 (file)
@@ -12,9 +12,7 @@ static inline int compare(struct prio_queue *queue, int i, int j)
 
 static inline void swap(struct prio_queue *queue, int i, int j)
 {
-       struct prio_queue_entry tmp = queue->array[i];
-       queue->array[i] = queue->array[j];
-       queue->array[j] = tmp;
+       SWAP(queue->array[i], queue->array[j]);
 }
 
 void prio_queue_reverse(struct prio_queue *queue)
index 2262b12683b5d91d536baa0b71094098872200d1..cf1b5409e7c39eba4981a0a23e8250249a9202f1 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -109,9 +109,7 @@ extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
  */
 static inline void strbuf_swap(struct strbuf *a, struct strbuf *b)
 {
-       struct strbuf tmp = *a;
-       *a = *b;
-       *b = tmp;
+       SWAP(*a, *b);
 }
 
 
index 5ee9211f988dce1f334d796623feccda85641bbe..99bdb16c8583a98b0c33cddadabb85f47b7d5c41 100755 (executable)
@@ -13,6 +13,13 @@ test_expect_success 'repack' '
        export PACK
 '
 
+test_expect_success 'create target repositories' '
+       for repo in t1 t2 t3 t4 t5 t6
+       do
+               git init --bare $repo
+       done
+'
+
 test_perf 'index-pack 0 threads' '
        GIT_DIR=t1 git index-pack --threads=1 --stdin < $PACK
 '
index 08ea725de3307c886d8f341b49c61c0d3436f91c..48b55bfd274a7adffe18af13489a54a7d92707a4 100755 (executable)
@@ -1212,6 +1212,54 @@ test_expect_success 'log --line-prefix="*** " --graph with diff and stats' '
        test_i18ncmp expect actual.sanitized
 '
 
+cat >expect <<-\EOF
+* reach
+|
+| A    reach.t
+* Merge branch 'tangle'
+*   Merge branch 'side'
+|\
+| * side-2
+|
+|   A  2
+* Second
+|
+| A    one
+* sixth
+
+  D    a/two
+EOF
+
+test_expect_success 'log --graph with --name-status' '
+       git log --graph --format=%s --name-status tangle..reach >actual &&
+       sanitize_output <actual >actual.sanitized &&
+       test_cmp expect actual.sanitized
+'
+
+cat >expect <<-\EOF
+* reach
+|
+| reach.t
+* Merge branch 'tangle'
+*   Merge branch 'side'
+|\
+| * side-2
+|
+|   2
+* Second
+|
+| one
+* sixth
+
+  a/two
+EOF
+
+test_expect_success 'log --graph with --name-only' '
+       git log --graph --format=%s --name-only tangle..reach >actual &&
+       sanitize_output <actual >actual.sanitized &&
+       test_cmp expect actual.sanitized
+'
+
 test_expect_success 'dotdot is a parent directory' '
        mkdir -p a/b &&
        ( echo sixth && echo fifth ) >expect &&
index aa0ef02597f051b17747df4c9cf3d4b50563ed69..25241f40967ef1fb547771e64c69927de2f101ce 100755 (executable)
@@ -23,6 +23,18 @@ prompt_given ()
        test "$prompt" = "Launch 'test-tool' [Y/n]? branch"
 }
 
+test_expect_success 'basic usage requires no repo' '
+       test_expect_code 129 git difftool -h >output &&
+       grep ^usage: output &&
+       # create a ceiling directory to prevent Git from finding a repo
+       mkdir -p not/repo &&
+       test_when_finished rm -r not &&
+       test_expect_code 129 \
+       env GIT_CEILING_DIRECTORIES="$(pwd)/not" \
+       git -C not/repo difftool -h >output &&
+       grep ^usage: output
+'
+
 # Create a file on master and change it on branch
 test_expect_success 'setup' '
        echo master >file &&
@@ -278,8 +290,8 @@ test_expect_success 'difftool + mergetool config variables' '
 test_expect_success 'difftool.<tool>.path' '
        test_config difftool.tkdiff.path echo &&
        git difftool --tool=tkdiff --no-prompt branch >output &&
-       lines=$(grep file output | wc -l) &&
-       test "$lines" -eq 1
+       grep file output >grep-output &&
+       test_line_count = 1 grep-output
 '
 
 test_expect_success 'difftool --extcmd=cat' '
@@ -416,9 +428,12 @@ run_dir_diff_test 'difftool --dir-diff branch from subdirectory' '
                git difftool --dir-diff $symlinks --extcmd ls branch >output &&
                # "sub" must only exist in "right"
                # "file" and "file2" must be listed in both "left" and "right"
-               test "1" = $(grep sub output | wc -l) &&
-               test "2" = $(grep file"$" output | wc -l) &&
-               test "2" = $(grep file2 output | wc -l)
+               grep sub output > sub-output &&
+               test_line_count = 1 sub-output &&
+               grep file"$" output >file-output &&
+               test_line_count = 2 file-output &&
+               grep file2 output >file2-output &&
+               test_line_count = 2 file2-output
        )
 '
 
@@ -428,9 +443,11 @@ run_dir_diff_test 'difftool --dir-diff v1 from subdirectory' '
                git difftool --dir-diff $symlinks --extcmd ls v1 >output &&
                # "sub" and "file" exist in both v1 and HEAD.
                # "file2" is unchanged.
-               test "2" = $(grep sub output | wc -l) &&
-               test "2" = $(grep file output | wc -l) &&
-               test "0" = $(grep file2 output | wc -l)
+               grep sub output >sub-output &&
+               test_line_count = 2 sub-output &&
+               grep file output >file-output &&
+               test_line_count = 2 file-output &&
+               ! grep file2 output
        )
 '
 
@@ -440,8 +457,9 @@ run_dir_diff_test 'difftool --dir-diff branch from subdirectory w/ pathspec' '
                git difftool --dir-diff $symlinks --extcmd ls branch -- .>output &&
                # "sub" only exists in "right"
                # "file" and "file2" must not be listed
-               test "1" = $(grep sub output | wc -l) &&
-               test "0" = $(grep file output | wc -l)
+               grep sub output >sub-output &&
+               test_line_count = 1 sub-output &&
+               ! grep file output
        )
 '
 
@@ -451,8 +469,9 @@ run_dir_diff_test 'difftool --dir-diff v1 from subdirectory w/ pathspec' '
                git difftool --dir-diff $symlinks --extcmd ls v1 -- .>output &&
                # "sub" exists in v1 and HEAD
                # "file" is filtered out by the pathspec
-               test "2" = $(grep sub output | wc -l) &&
-               test "0" = $(grep file output | wc -l)
+               grep sub output >sub-output &&
+               test_line_count = 2 sub-output &&
+               ! grep file output
        )
 '