Merge branch 'jk/cached-commit-buffer' into maint
Code clean-up.
* jk/cached-commit-buffer:
revision: drop --show-all option
commit: drop uses of get_cached_commit_buffer()
diff --git a/.travis.yml b/.travis.yml
index 4684b3f..5f5ee4f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -33,7 +33,6 @@
compiler:
addons:
before_install:
- before_script:
script:
- >
test "$TRAVIS_REPO_SLUG" != "git/git" ||
@@ -46,7 +45,6 @@
services:
- docker
before_install:
- before_script:
script: ci/run-linux32-docker.sh
- env: jobname=StaticAnalysis
os: linux
@@ -56,7 +54,6 @@
packages:
- coccinelle
before_install:
- before_script:
script: ci/run-static-analysis.sh
after_failure:
- env: jobname=Documentation
@@ -68,13 +65,11 @@
- asciidoc
- xmlto
before_install:
- before_script:
script: ci/test-documentation.sh
after_failure:
before_install: ci/install-dependencies.sh
-before_script: ci/run-build.sh
-script: ci/run-tests.sh
+script: ci/run-build-and-tests.sh
after_failure: ci/print-test-failures.sh
notifications:
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 8c74a2c..f970a43 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -144,6 +144,8 @@
Use the given <msg> as the commit message.
If multiple `-m` options are given, their values are
concatenated as separate paragraphs.
++
+The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
-t <file>::
--template=<file>::
diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt
index 9dd19a1..ff446f1 100644
--- a/Documentation/git-interpret-trailers.txt
+++ b/Documentation/git-interpret-trailers.txt
@@ -51,7 +51,7 @@
will be added before the new trailer.
Existing trailers are extracted from the input message by looking for
-a group of one or more lines that (i) are all trailers, or (ii) contains at
+a group of one or more lines that (i) is all trailers, or (ii) contains at
least one Git-generated or user-configured trailer and consists of at
least 25% trailers.
The group must be preceded by one or more empty (or whitespace-only) lines.
diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt
index 82a4125..e73ef54 100644
--- a/Documentation/git-show.txt
+++ b/Documentation/git-show.txt
@@ -9,7 +9,7 @@
SYNOPSIS
--------
[verse]
-'git show' [options] <object>...
+'git show' [options] [<object>...]
DESCRIPTION
-----------
@@ -35,7 +35,7 @@
OPTIONS
-------
<object>...::
- The names of objects to show.
+ The names of objects to show (defaults to 'HEAD').
For a more complete list of ways to spell object names, see
"SPECIFYING REVISIONS" section in linkgit:gitrevisions[7].
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 81cab9a..f9c91c7 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -149,14 +149,15 @@
Short Format
~~~~~~~~~~~~
-In the short-format, the status of each path is shown as
+In the short-format, the status of each path is shown as one of these
+forms
- XY PATH1 -> PATH2
+ XY PATH
+ XY ORIG_PATH -> PATH
-where `PATH1` is the path in the `HEAD`, and the " `-> PATH2`" part is
-shown only when `PATH1` corresponds to a different path in the
-index/worktree (i.e. the file is renamed). The `XY` is a two-letter
-status code.
+where `ORIG_PATH` is where the renamed/copied contents came
+from. `ORIG_PATH` is only shown when the entry is renamed or
+copied. The `XY` is a two-letter status code.
The fields (including the `->`) are separated from each other by a
single space. If a filename contains whitespace or other nonprintable
@@ -183,15 +184,17 @@
X Y Meaning
-------------------------------------------------
- [MD] not updated
+ [AMD] not updated
M [ MD] updated in index
A [ MD] added to index
- D [ M] deleted from index
+ D deleted from index
R [ MD] renamed in index
C [ MD] copied in index
[MARC] index and work tree matches
[ MARC] M work tree changed since index
[ MARC] D deleted in work tree
+ [ D] R renamed in work tree
+ [ D] C copied in work tree
-------------------------------------------------
D D unmerged, both deleted
A U unmerged, added by us
@@ -309,13 +312,13 @@
of similarity between the source and target of the
move or copy). For example "R100" or "C75".
<path> The pathname. In a renamed/copied entry, this
- is the path in the index and in the working tree.
+ is the target path.
<sep> When the `-z` option is used, the 2 pathnames are separated
with a NUL (ASCII 0x00) byte; otherwise, a tab (ASCII 0x09)
byte separates them.
- <origPath> The pathname in the commit at HEAD. This is only
- present in a renamed/copied entry, and tells
- where the renamed/copied contents came from.
+ <origPath> The pathname in the commit at HEAD or in the index.
+ This is only present in a renamed/copied entry, and
+ tells where the renamed/copied contents came from.
--------------------------------------------------------
Unmerged entries have the following format; the first character is
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index ff61200..71c5618 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -70,8 +70,8 @@
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
- SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
- initialized, `+` if the currently checked out submodule commit
+ SHA-1. Each SHA-1 will possibly be prefixed with `-` if the submodule is
+ not initialized, `+` if the currently checked out submodule commit
does not match the SHA-1 found in the index of the containing
repository and `U` if the submodule has merge conflicts.
+
@@ -132,15 +132,15 @@
the submodules. The "updating" can be done in several ways depending
on command line options and the value of `submodule.<name>.update`
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`:
+the configuration variable. If neither is given, a 'checkout' is performed.
+The 'update' procedures supported both from the command line as well as
+through the `submodule.<name>.update` configuration are:
checkout;; the commit recorded in the superproject will be
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
+`git checkout --force`), even if the commit specified
in the index of the containing repository already matches the commit
checked out in the submodule.
@@ -150,8 +150,8 @@
merge;; the commit recorded in the superproject will be merged
into the current branch in the submodule.
-The following procedures are only available via the `submodule.<name>.update`
-configuration variable:
+The following 'update' 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
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index bdb0342..ad2383d 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -484,8 +484,8 @@
linkgit:git-config[1]) than using the `--fsmonitor` option to
`git update-index` in each repository, especially if you want to do so
across all repositories you use, because you can set the configuration
-variable to `true` (or `false`) in your `$HOME/.gitconfig` just once
-and have it affect all repositories you touch.
+variable in your `$HOME/.gitconfig` just once and have it affect all
+repositories you touch.
When the `core.fsmonitor` configuration variable is changed, the
file system monitor is added to or removed from the index the next time
diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 41585f5..5ac3f68 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -52,10 +52,11 @@
directory specific files such as HEAD, index, etc. `-` may also be
specified as `<commit-ish>`; it is synonymous with `@{-1}`.
+
-If <commit-ish> is a branch name (call it `<branch>` and is not found,
+If <commit-ish> is a branch name (call it `<branch>`) and is not found,
and neither `-b` nor `-B` nor `--detach` are used, but there does
exist a tracking branch in exactly one remote (call it `<remote>`)
-with a matching name, treat as equivalent to
+with a matching name, treat as equivalent to:
++
------------
$ git worktree add --track -b <branch> <path> <remote>/<branch>
------------
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 3f4161a..8163b57 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -646,6 +646,16 @@
variable.
See `GIT_TRACE` for available trace output options.
+`GIT_TRACE_CURL_NO_DATA`::
+ When a curl trace is enabled (see `GIT_TRACE_CURL` above), do not dump
+ data (that is, only dump info lines and headers).
+
+`GIT_REDACT_COOKIES`::
+ This can be set to a comma-separated list of strings. When a curl trace
+ is enabled (see `GIT_TRACE_CURL` above), whenever a "Cookies:" header
+ sent by the client is dumped, values of cookies whose key is in that
+ list (case-sensitive) are redacted.
+
`GIT_LITERAL_PATHSPECS`::
Setting this variable to `1` will cause Git to treat all
pathspecs literally, rather than as glob patterns. For example,
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index 63260f0..ff5d7f9 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -102,12 +102,11 @@
(relative to the toplevel of the work tree if not from a
`.gitignore` file).
- - Otherwise, Git treats the pattern as a shell glob suitable
- for consumption by fnmatch(3) with the FNM_PATHNAME flag:
- wildcards in the pattern will not match a / in the pathname.
- For example, "Documentation/{asterisk}.html" matches
- "Documentation/git.html" but not "Documentation/ppc/ppc.html"
- or "tools/perf/Documentation/perf.html".
+ - Otherwise, Git treats the pattern as a shell glob: "`*`" matches
+ anything except "`/`", "`?`" matches any one character except "`/`"
+ and "`[]`" matches one character in a selected range. See
+ fnmatch(3) and the FNM_PATHNAME flag for a more detailed
+ description.
- A leading slash matches the beginning of the pathname.
For example, "/{asterisk}.c" matches "cat-file.c" but not
diff --git a/Documentation/gitsubmodules.txt b/Documentation/gitsubmodules.txt
index 46cf120..4d6c177 100644
--- a/Documentation/gitsubmodules.txt
+++ b/Documentation/gitsubmodules.txt
@@ -36,8 +36,8 @@
superproject expects the submodule’s working directory to be at.
The section `submodule.foo.*` in the `.gitmodules` file gives additional
-hints to Gits porcelain layer such as where to obtain the submodule via
-the `submodule.foo.url` setting.
+hints to Git's porcelain layer. For example, the `submodule.foo.url`
+setting specifies where to obtain the submodule.
Submodules can be used for at least two different use cases:
@@ -51,18 +51,21 @@
2. Splitting a (logically single) project into multiple
repositories and tying them back together. This can be used to
- overcome current limitations of Gits implementation to have
+ overcome current limitations of Git's implementation to have
finer grained access:
- * Size of the git repository:
+ * Size of the Git repository:
In its current form Git scales up poorly for large repositories containing
content that is not compressed by delta computation between trees.
- However you can also use submodules to e.g. hold large binary assets
- and these repositories are then shallowly cloned such that you do not
+ For example, you can use submodules to hold large binary assets
+ and these repositories can be shallowly cloned such that you do not
have a large history locally.
* Transfer size:
In its current form Git requires the whole working tree present. It
does not allow partial trees to be transferred in fetch or clone.
+ If the project you work on consists of multiple repositories tied
+ together as submodules in a superproject, you can avoid fetching the
+ working trees of the repositories you are not interested in.
* Access control:
By restricting user access to submodules, this can be used to implement
read/write policies for different users.
@@ -73,9 +76,10 @@
Submodule operations can be configured using the following mechanisms
(from highest to lowest precedence):
- * The command line for those commands that support taking submodule specs.
- Most commands have a boolean flag '--recurse-submodules' whether to
- recurse into submodules. Examples are `ls-files` or `checkout`.
+ * The command line for those commands that support taking submodules
+ as part of their pathspecs. Most commands have a boolean flag
+ `--recurse-submodules` which specify whether to recurse into submodules.
+ Examples are `grep` and `checkout`.
Some commands take enums, such as `fetch` and `push`, where you can
specify how submodules are affected.
@@ -87,8 +91,8 @@
For example an effect from the submodule's `.gitignore` file
would be observed when you run `git status --ignore-submodules=none` in
the superproject. This collects information from the submodule's working
-directory by running `status` in the submodule, which does pay attention
-to its `.gitignore` file.
+directory by running `status` in the submodule while paying attention
+to the `.gitignore` file of the submodule.
+
The submodule's `$GIT_DIR/config` file would come into play when running
`git push --recurse-submodules=check` in the superproject, as this would
@@ -97,20 +101,20 @@
file.
* The configuration file `$GIT_DIR/config` in the superproject.
- Typical configuration at this place is controlling if a submodule
- is recursed into at all via the `active` flag for example.
+ Git only recurses into active submodules (see "ACTIVE SUBMODULES"
+ section below).
+
If the submodule is not yet initialized, then the configuration
-inside the submodule does not exist yet, so configuration where to
+inside the submodule does not exist yet, so where to
obtain the submodule from is configured here for example.
- * the `.gitmodules` file inside the superproject. Additionally to the
- required mapping between submodule's name and path, a project usually
+ * The `.gitmodules` file inside the superproject. A project usually
uses this file to suggest defaults for the upstream collection
- of repositories.
+ of repositories for the mapping that is required between a
+ submodule's name and its path.
+
-This file mainly serves as the mapping between name and path in
-the superproject, such that the submodule's git directory can be
+This file mainly serves as the mapping between the name and path of submodules
+in the superproject, such that the submodule's Git directory can be
located.
+
If the submodule has never been initialized, this is the only place
@@ -137,8 +141,8 @@
of the superproject.
* Deinitialized submodule: A `gitlink`, and a `.gitmodules` entry,
-but no submodule working directory. The submodule’s git directory
-may be there as after deinitializing the git directory is kept around.
+but no submodule working directory. The submodule’s Git directory
+may be there as after deinitializing the Git directory is kept around.
The directory which is supposed to be the working directory is empty instead.
+
A submodule can be deinitialized by running `git submodule deinit`.
@@ -160,6 +164,60 @@
To completely remove a submodule, manually delete
`$GIT_DIR/modules/<name>/`.
+ACTIVE SUBMODULES
+-----------------
+
+A submodule is considered active,
+
+ (a) if `submodule.<name>.active` is set to `true`
+ or
+ (b) if the submodule's path matches the pathspec in `submodule.active`
+ or
+ (c) if `submodule.<name>.url` is set.
+
+and these are evaluated in this order.
+
+For example:
+
+ [submodule "foo"]
+ active = false
+ url = https://example.org/foo
+ [submodule "bar"]
+ active = true
+ url = https://example.org/bar
+ [submodule "baz"]
+ url = https://example.org/baz
+
+In the above config only the submodule 'bar' and 'baz' are active,
+'bar' due to (a) and 'baz' due to (c). 'foo' is inactive because
+(a) takes precedence over (c)
+
+Note that (c) is a historical artefact and will be ignored if the
+(a) and (b) specify that the submodule is not active. In other words,
+if we have an `submodule.<name>.active` set to `false` or if the
+submodule's path is excluded in the pathspec in `submodule.active`, the
+url doesn't matter whether it is present or not. This is illustrated in
+the example that follows.
+
+ [submodule "foo"]
+ active = true
+ url = https://example.org/foo
+ [submodule "bar"]
+ url = https://example.org/bar
+ [submodule "baz"]
+ url = https://example.org/baz
+ [submodule "bob"]
+ ignore = true
+ [submodule]
+ active = b*
+ active = :(exclude) baz
+
+In here all submodules except 'baz' (foo, bar, bob) are active.
+'foo' due to its own active flag and all the others due to the
+submodule active pathspec, which specifies that any submodule
+starting with 'b' except 'baz' are also active, regardless of the
+presence of the .url field.
+
Workflow for a third party library
----------------------------------
diff --git a/Documentation/technical/api-submodule-config.txt b/Documentation/technical/api-submodule-config.txt
index 3dce003..ee907c4 100644
--- a/Documentation/technical/api-submodule-config.txt
+++ b/Documentation/technical/api-submodule-config.txt
@@ -4,7 +4,7 @@
The submodule config cache API allows to read submodule
configurations/information from specified revisions. Internally
information is lazily read into a cache that is used to avoid
-unnecessary parsing of the same .gitmodule files. Lookups can be done by
+unnecessary parsing of the same .gitmodules files. Lookups can be done by
submodule path or name.
Usage
diff --git a/Makefile b/Makefile
index 1a9b23b..7f40f76 100644
--- a/Makefile
+++ b/Makefile
@@ -2176,6 +2176,8 @@
http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp: SPARSE_FLAGS += \
-DCURL_DISABLE_TYPECHECK
+pack-revindex.sp: SPARSE_FLAGS += -Wno-memcpy-max-count
+
ifdef NO_EXPAT
http-walker.sp http-walker.s http-walker.o: EXTRA_CPPFLAGS = -DNO_EXPAT
endif
diff --git a/bisect.c b/bisect.c
index 0d9e731..f6d05bd 100644
--- a/bisect.c
+++ b/bisect.c
@@ -132,7 +132,7 @@
unsigned flags = commit->object.flags;
enum object_type type;
unsigned long size;
- char *buf = read_sha1_file(commit->object.sha1, &type, &size);
+ char *buf = read_sha1_file(commit->object.oid.hash, &type, &size);
const char *subject_start;
int subject_len;
@@ -144,10 +144,10 @@
fprintf(stderr, "%3d", weight(p));
else
fprintf(stderr, "---");
- fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
+ fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.oid.hash));
for (pp = commit->parents; pp; pp = pp->next)
fprintf(stderr, " %.*s", 8,
- sha1_to_hex(pp->item->object.sha1));
+ sha1_to_hex(pp->item->object.oid.hash));
subject_len = find_commit_subject(buf, &subject_start);
if (subject_len)
diff --git a/builtin/commit.c b/builtin/commit.c
index 8a87701..4610e3d 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -701,7 +701,7 @@
}
}
- if (have_option_m) {
+ if (have_option_m && !fixup_message) {
strbuf_addbuf(&sb, &message);
hook_arg1 = "message";
} else if (logfile && !strcmp(logfile, "-")) {
@@ -731,6 +731,8 @@
ctx.output_encoding = get_commit_output_encoding();
format_commit_message(commit, "fixup! %s\n\n",
&sb, &ctx);
+ if (have_option_m)
+ strbuf_addbuf(&sb, &message);
hook_arg1 = "message";
} else if (!stat(git_path_merge_msg(), &statbuf)) {
/*
@@ -1197,8 +1199,8 @@
f++;
if (f > 1)
die(_("Only one of -c/-C/-F/--fixup can be used."));
- if (have_option_m && f > 0)
- die((_("Option -m cannot be combined with -c/-C/-F/--fixup.")));
+ if (have_option_m && (edit_message || use_message || logfile))
+ die((_("Option -m cannot be combined with -c/-C/-F.")));
if (f || have_option_m)
template_file = NULL;
if (edit_message)
@@ -1507,7 +1509,7 @@
rev.show_root_diff = 1;
get_commit_format(format.buf, &rev);
rev.always_show_header = 0;
- rev.diffopt.detect_rename = 1;
+ rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
rev.diffopt.break_opt = 0;
diff_setup_done(&rev.diffopt);
diff --git a/builtin/describe.c b/builtin/describe.c
index 6fe1c51..c428984 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -383,7 +383,7 @@
if (!match_cnt) {
struct object_id *cmit_oid = &cmit->object.oid;
if (always) {
- strbuf_addstr(dst, find_unique_abbrev(cmit_oid->hash, abbrev));
+ strbuf_add_unique_abbrev(dst, cmit_oid->hash, abbrev);
if (suffix)
strbuf_addstr(dst, suffix);
return;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 04846d4..92ce775 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -171,7 +171,13 @@
static int traverse_one_object(struct object *obj)
{
- return fsck_walk(obj, obj, &fsck_walk_options);
+ int result = fsck_walk(obj, obj, &fsck_walk_options);
+
+ if (obj->type == OBJ_TREE) {
+ struct tree *tree = (struct tree *)obj;
+ free_tree_buffer(tree);
+ }
+ return result;
}
static int traverse_reachable(void)
diff --git a/builtin/mv.c b/builtin/mv.c
index cf3684d..8ce6a2d 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -286,8 +286,7 @@
pos = cache_name_pos(src, strlen(src));
assert(pos >= 0);
- if (!show_only)
- rename_cache_entry_at(pos, dst);
+ rename_cache_entry_at(pos, dst);
}
if (gitmodules_modified)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 7cef5b1..9efdc22 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -14,7 +14,7 @@
#include "worktree.h"
static const char * const worktree_usage[] = {
- N_("git worktree add [<options>] <path> [<branch>]"),
+ N_("git worktree add [<options>] <path> [<commit-ish>]"),
N_("git worktree list [<options>]"),
N_("git worktree lock [<options>] <path>"),
N_("git worktree prune [<options>]"),
diff --git a/cache-tree.c b/cache-tree.c
index e03e72c..0dd6292 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -608,7 +608,7 @@
hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);
- entries = read_index_from(index_state, index_path);
+ entries = read_index_from(index_state, index_path, get_git_dir());
if (entries < 0) {
ret = WRITE_TREE_UNREADABLE_INDEX;
goto out;
diff --git a/cache.h b/cache.h
index d8b975a..fd755c3 100644
--- a/cache.h
+++ b/cache.h
@@ -345,7 +345,8 @@
struct split_index *split_index;
struct cache_time timestamp;
unsigned name_hash_initialized : 1,
- initialized : 1;
+ initialized : 1,
+ drop_cache_tree : 1;
struct hashmap name_hash;
struct hashmap dir_hash;
unsigned char sha1[20];
@@ -371,7 +372,7 @@
#define active_cache_tree (the_index.cache_tree)
#define read_cache() read_index(&the_index)
-#define read_cache_from(path) read_index_from(&the_index, (path))
+#define read_cache_from(path) read_index_from(&the_index, (path), (get_git_dir()))
#define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec))
#define is_cache_unborn() is_index_unborn(&the_index)
#define read_cache_unmerged() read_index_unmerged(&the_index)
@@ -616,7 +617,8 @@
extern int read_index_preload(struct index_state *, const struct pathspec *pathspec);
extern int do_read_index(struct index_state *istate, const char *path,
int must_exist); /* for testting only! */
-extern int read_index_from(struct index_state *, const char *path);
+extern int read_index_from(struct index_state *, const char *path,
+ const char *gitdir);
extern int is_index_unborn(struct index_state *);
extern int read_index_unmerged(struct index_state *);
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
new file mode 100755
index 0000000..3e23e65
--- /dev/null
+++ b/ci/run-build-and-tests.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Build and test Git
+#
+
+. ${0%/*}/lib-travisci.sh
+
+ln -s $HOME/travis-cache/.prove t/.prove
+
+make --jobs=2
+make --quiet test
+if test "$jobname" = "linux-gcc"
+then
+ GIT_TEST_SPLIT_INDEX=YesPlease make --quiet test
+fi
+
+check_unignored_build_artifacts
+
+save_good_tree
diff --git a/ci/run-build.sh b/ci/run-build.sh
deleted file mode 100755
index 4f940d1..0000000
--- a/ci/run-build.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# Build Git
-#
-
-. ${0%/*}/lib-travisci.sh
-
-make --jobs=2
diff --git a/ci/run-tests.sh b/ci/run-tests.sh
deleted file mode 100755
index 22355f0..0000000
--- a/ci/run-tests.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-#
-# Test Git
-#
-
-. ${0%/*}/lib-travisci.sh
-
-ln -s $HOME/travis-cache/.prove t/.prove
-make --quiet test
-
-check_unignored_build_artifacts
-
-save_good_tree
diff --git a/config.mak.uname b/config.mak.uname
index 685a80d..6a1d0de 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -182,7 +182,6 @@
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
X = .exe
UNRELIABLE_FSTAT = UnfortunatelyYes
- SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
MMAP_PREVENTS_DELETE = UnfortunatelyYes
COMPAT_OBJS += compat/cygwin.o
diff --git a/contrib/coccinelle/strbuf.cocci b/contrib/coccinelle/strbuf.cocci
index 1d580e4..ce2e92c 100644
--- a/contrib/coccinelle/strbuf.cocci
+++ b/contrib/coccinelle/strbuf.cocci
@@ -1,21 +1,6 @@
@ strbuf_addf_with_format_only @
expression E;
-constant fmt;
-@@
- strbuf_addf(E,
-(
- fmt
-|
- _(fmt)
-)
- );
-
-@ script:python @
-fmt << strbuf_addf_with_format_only.fmt;
-@@
-cocci.include_match("%" not in fmt)
-
-@ extends strbuf_addf_with_format_only @
+constant fmt !~ "%";
@@
- strbuf_addf
+ strbuf_addstr
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3683c77..88813e9 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -594,7 +594,7 @@
__git_list_merge_strategies ()
{
- git merge -s help 2>&1 |
+ LANG=C LC_ALL=C git merge -s help 2>&1 |
sed -n -e '/[Aa]vailable strategies are: /,/^$/{
s/\.$//
s/.*://
diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt
index 60d76cd..352deda 100644
--- a/contrib/subtree/git-subtree.txt
+++ b/contrib/subtree/git-subtree.txt
@@ -28,7 +28,7 @@
Subtrees are not to be confused with submodules, which are meant for
the same task. Unlike submodules, subtrees do not need any special
-constructions (like .gitmodule files or gitlinks) be present in
+constructions (like .gitmodules files or gitlinks) be present in
your repository, and do not force end-users of your
repository to do anything special or to understand how subtrees
work. A subtree is just a subdirectory that can be
diff --git a/daemon.c b/daemon.c
index e37e343..72dfeaf 100644
--- a/daemon.c
+++ b/daemon.c
@@ -597,6 +597,7 @@
if (strncasecmp("host=", extra_args, 5) == 0) {
val = extra_args + 5;
vallen = strlen(val) + 1;
+ loginfo("Extended attribute \"host\": %s", val);
if (*val) {
/* Split <host>:<port> at colon. */
char *host;
@@ -647,9 +648,11 @@
}
}
- if (git_protocol.len > 0)
+ if (git_protocol.len > 0) {
+ loginfo("Extended attribute \"protocol\": %s", git_protocol.buf);
argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=%s",
git_protocol.buf);
+ }
strbuf_release(&git_protocol);
}
@@ -757,14 +760,8 @@
alarm(0);
len = strlen(line);
- if (pktlen != len)
- loginfo("Extended attributes (%d bytes) exist <%.*s>",
- (int) pktlen - len,
- (int) pktlen - len, line + len + 1);
- if (len && line[len-1] == '\n') {
- line[--len] = 0;
- pktlen--;
- }
+ if (len && line[len-1] == '\n')
+ line[len-1] = 0;
/* parse additional args hidden behind a NUL byte */
if (len != pktlen)
diff --git a/diff.c b/diff.c
index fb22b19..e9d0e38 100644
--- a/diff.c
+++ b/diff.c
@@ -246,7 +246,7 @@
*/
void init_diff_ui_defaults(void)
{
- diff_detect_rename_default = 1;
+ diff_detect_rename_default = DIFF_DETECT_RENAME;
}
int git_diff_heuristic_config(const char *var, const char *value, void *cb)
@@ -5454,6 +5454,7 @@
void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc)
{
+ fflush(stdout);
if (degraded_cc)
warning(_(degrade_cc_to_c_warning));
else if (needed)
diff --git a/git-sh-i18n.sh b/git-sh-i18n.sh
index 1ef1889..9d065fb 100644
--- a/git-sh-i18n.sh
+++ b/git-sh-i18n.sh
@@ -17,15 +17,15 @@
# First decide what scheme to use...
GIT_INTERNAL_GETTEXT_SH_SCHEME=fallthrough
-if test -n "@@USE_GETTEXT_SCHEME@@"
+if test -n "$GIT_GETTEXT_POISON"
+then
+ GIT_INTERNAL_GETTEXT_SH_SCHEME=poison
+elif test -n "@@USE_GETTEXT_SCHEME@@"
then
GIT_INTERNAL_GETTEXT_SH_SCHEME="@@USE_GETTEXT_SCHEME@@"
elif test -n "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS"
then
: no probing necessary
-elif test -n "$GIT_GETTEXT_POISON"
-then
- GIT_INTERNAL_GETTEXT_SH_SCHEME=poison
elif type gettext.sh >/dev/null 2>&1
then
# GNU libintl's gettext.sh
diff --git a/git-svn.perl b/git-svn.perl
index 76a75d0..a6b6c3e 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -1200,6 +1200,11 @@
$ctx->copy($src, $rev, $dst)
unless $_dry_run;
+ # Release resources held by ctx before creating another SVN::Ra
+ # so destruction is orderly. This seems necessary with SVN 1.9.5
+ # to avoid segfaults.
+ $ctx = undef;
+
$gs->fetch_all;
}
diff --git a/hashmap.h b/hashmap.h
index 7ce79f3..d375d9c 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -400,7 +400,6 @@
*/
static inline void hashmap_enable_item_counting(struct hashmap *map)
{
- void *item;
unsigned int n = 0;
struct hashmap_iter iter;
@@ -408,7 +407,7 @@
return;
hashmap_iter_init(map, &iter);
- while ((item = hashmap_iter_next(&iter)))
+ while (hashmap_iter_next(&iter))
n++;
map->do_count_items = 1;
diff --git a/http.c b/http.c
index 5977712..32a8238 100644
--- a/http.c
+++ b/http.c
@@ -13,8 +13,11 @@
#include "transport.h"
#include "packfile.h"
#include "protocol.h"
+#include "string-list.h"
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
+static int trace_curl_data = 1;
+static struct string_list cookies_to_redact = STRING_LIST_INIT_DUP;
#if LIBCURL_VERSION_NUM >= 0x070a08
long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
#else
@@ -575,6 +578,54 @@
/* Everything else is opaque and possibly sensitive */
strbuf_setlen(header, sensitive_header - header->buf);
strbuf_addstr(header, " <redacted>");
+ } else if (cookies_to_redact.nr &&
+ skip_prefix(header->buf, "Cookie:", &sensitive_header)) {
+ struct strbuf redacted_header = STRBUF_INIT;
+ char *cookie;
+
+ while (isspace(*sensitive_header))
+ sensitive_header++;
+
+ /*
+ * The contents of header starting from sensitive_header will
+ * subsequently be overridden, so it is fine to mutate this
+ * string (hence the assignment to "char *").
+ */
+ cookie = (char *) sensitive_header;
+
+ while (cookie) {
+ char *equals;
+ char *semicolon = strstr(cookie, "; ");
+ if (semicolon)
+ *semicolon = 0;
+ equals = strchrnul(cookie, '=');
+ if (!equals) {
+ /* invalid cookie, just append and continue */
+ strbuf_addstr(&redacted_header, cookie);
+ continue;
+ }
+ *equals = 0; /* temporarily set to NUL for lookup */
+ if (string_list_lookup(&cookies_to_redact, cookie)) {
+ strbuf_addstr(&redacted_header, cookie);
+ strbuf_addstr(&redacted_header, "=<redacted>");
+ } else {
+ *equals = '=';
+ strbuf_addstr(&redacted_header, cookie);
+ }
+ if (semicolon) {
+ /*
+ * There are more cookies. (Or, for some
+ * reason, the input string ends in "; ".)
+ */
+ strbuf_addstr(&redacted_header, "; ");
+ cookie = semicolon + strlen("; ");
+ } else {
+ cookie = NULL;
+ }
+ }
+
+ strbuf_setlen(header, sensitive_header - header->buf);
+ strbuf_addbuf(header, &redacted_header);
}
}
@@ -645,24 +696,32 @@
curl_dump_header(text, (unsigned char *)data, size, DO_FILTER);
break;
case CURLINFO_DATA_OUT:
- text = "=> Send data";
- curl_dump_data(text, (unsigned char *)data, size);
+ if (trace_curl_data) {
+ text = "=> Send data";
+ curl_dump_data(text, (unsigned char *)data, size);
+ }
break;
case CURLINFO_SSL_DATA_OUT:
- text = "=> Send SSL data";
- curl_dump_data(text, (unsigned char *)data, size);
+ if (trace_curl_data) {
+ text = "=> Send SSL data";
+ curl_dump_data(text, (unsigned char *)data, size);
+ }
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
curl_dump_header(text, (unsigned char *)data, size, NO_FILTER);
break;
case CURLINFO_DATA_IN:
- text = "<= Recv data";
- curl_dump_data(text, (unsigned char *)data, size);
+ if (trace_curl_data) {
+ text = "<= Recv data";
+ curl_dump_data(text, (unsigned char *)data, size);
+ }
break;
case CURLINFO_SSL_DATA_IN:
- text = "<= Recv SSL data";
- curl_dump_data(text, (unsigned char *)data, size);
+ if (trace_curl_data) {
+ text = "<= Recv SSL data";
+ curl_dump_data(text, (unsigned char *)data, size);
+ }
break;
default: /* we ignore unknown types by default */
@@ -807,6 +866,13 @@
if (getenv("GIT_CURL_VERBOSE"))
curl_easy_setopt(result, CURLOPT_VERBOSE, 1L);
setup_curl_trace(result);
+ if (getenv("GIT_TRACE_CURL_NO_DATA"))
+ trace_curl_data = 0;
+ if (getenv("GIT_REDACT_COOKIES")) {
+ string_list_split(&cookies_to_redact,
+ getenv("GIT_REDACT_COOKIES"), ',', -1);
+ string_list_sort(&cookies_to_redact);
+ }
curl_easy_setopt(result, CURLOPT_USERAGENT,
user_agent ? user_agent : git_user_agent());
diff --git a/mailinfo.c b/mailinfo.c
index a89db22..d04142c 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -1167,11 +1167,13 @@
strbuf_release(&mi->inbody_header_accum);
free(mi->message_id);
- for (i = 0; mi->p_hdr_data[i]; i++)
- strbuf_release(mi->p_hdr_data[i]);
+ if (mi->p_hdr_data)
+ for (i = 0; mi->p_hdr_data[i]; i++)
+ strbuf_release(mi->p_hdr_data[i]);
free(mi->p_hdr_data);
- for (i = 0; mi->s_hdr_data[i]; i++)
- strbuf_release(mi->s_hdr_data[i]);
+ if (mi->s_hdr_data)
+ for (i = 0; mi->s_hdr_data[i]; i++)
+ strbuf_release(mi->s_hdr_data[i]);
free(mi->s_hdr_data);
while (mi->content < mi->content_top) {
diff --git a/oidmap.c b/oidmap.c
index 6db4fff..d9fb19b 100644
--- a/oidmap.c
+++ b/oidmap.c
@@ -33,12 +33,19 @@
void *oidmap_get(const struct oidmap *map, const struct object_id *key)
{
+ if (!map->map.cmpfn)
+ return NULL;
+
return hashmap_get_from_hash(&map->map, hash(key), key);
}
void *oidmap_remove(struct oidmap *map, const struct object_id *key)
{
struct hashmap_entry entry;
+
+ if (!map->map.cmpfn)
+ oidmap_init(map, 0);
+
hashmap_entry_init(&entry, hash(key));
return hashmap_remove(&map->map, &entry, key);
}
@@ -46,6 +53,10 @@
void *oidmap_put(struct oidmap *map, void *entry)
{
struct oidmap_entry *to_put = entry;
+
+ if (!map->map.cmpfn)
+ oidmap_init(map, 0);
+
hashmap_entry_init(&to_put->internal_entry, hash(&to_put->oid));
return hashmap_put(&map->map, to_put);
}
diff --git a/read-cache.c b/read-cache.c
index 2eb81a6..198e72b 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1603,7 +1603,7 @@
int read_index(struct index_state *istate)
{
- return read_index_from(istate, get_index_file());
+ return read_index_from(istate, get_index_file(), get_git_dir());
}
static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *ondisk,
@@ -1863,20 +1863,19 @@
* This way, shared index can be removed if they have not been used
* for some time.
*/
-static void freshen_shared_index(char *base_sha1_hex, int warn)
+static void freshen_shared_index(const char *shared_index, int warn)
{
- char *shared_index = git_pathdup("sharedindex.%s", base_sha1_hex);
if (!check_and_freshen_file(shared_index, 1) && warn)
warning("could not freshen shared index '%s'", shared_index);
- free(shared_index);
}
-int read_index_from(struct index_state *istate, const char *path)
+int read_index_from(struct index_state *istate, const char *path,
+ const char *gitdir)
{
struct split_index *split_index;
int ret;
char *base_sha1_hex;
- const char *base_path;
+ char *base_path;
/* istate->initialized covers both .git/index and .git/sharedindex.xxx */
if (istate->initialized)
@@ -1896,16 +1895,17 @@
split_index->base = xcalloc(1, sizeof(*split_index->base));
base_sha1_hex = sha1_to_hex(split_index->base_sha1);
- base_path = git_path("sharedindex.%s", base_sha1_hex);
+ base_path = xstrfmt("%s/sharedindex.%s", gitdir, base_sha1_hex);
ret = do_read_index(split_index->base, base_path, 1);
if (hashcmp(split_index->base_sha1, split_index->base->sha1))
die("broken index, expect %s in %s, got %s",
base_sha1_hex, base_path,
sha1_to_hex(split_index->base->sha1));
- freshen_shared_index(base_sha1_hex, 0);
+ freshen_shared_index(base_path, 0);
merge_base_index(istate);
post_read_index_from(istate);
+ free(base_path);
return ret;
}
@@ -2243,7 +2243,7 @@
struct stat st;
struct ondisk_cache_entry_extended ondisk;
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
- int drop_cache_tree = 0;
+ int drop_cache_tree = istate->drop_cache_tree;
for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
@@ -2472,32 +2472,21 @@
}
static int write_shared_index(struct index_state *istate,
- struct lock_file *lock, unsigned flags)
+ struct tempfile **temp)
{
- struct tempfile *temp;
struct split_index *si = istate->split_index;
int ret;
- temp = mks_tempfile(git_path("sharedindex_XXXXXX"));
- if (!temp) {
- hashclr(si->base_sha1);
- return do_write_locked_index(istate, lock, flags);
- }
move_cache_to_base_index(istate);
- ret = do_write_index(si->base, temp, 1);
+ ret = do_write_index(si->base, *temp, 1);
+ if (ret)
+ return ret;
+ ret = adjust_shared_perm(get_tempfile_path(*temp));
if (ret) {
- delete_tempfile(&temp);
+ error("cannot fix permission bits on %s", get_tempfile_path(*temp));
return ret;
}
- ret = adjust_shared_perm(get_tempfile_path(temp));
- if (ret) {
- int save_errno = errno;
- error("cannot fix permission bits on %s", get_tempfile_path(temp));
- delete_tempfile(&temp);
- errno = save_errno;
- return ret;
- }
- ret = rename_tempfile(&temp,
+ ret = rename_tempfile(temp,
git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
if (!ret) {
hashcpy(si->base_sha1, si->base->sha1);
@@ -2565,7 +2554,22 @@
new_shared_index = istate->cache_changed & SPLIT_INDEX_ORDERED;
if (new_shared_index) {
- ret = write_shared_index(istate, lock, flags);
+ struct tempfile *temp;
+ int saved_errno;
+
+ temp = mks_tempfile(git_path("sharedindex_XXXXXX"));
+ if (!temp) {
+ hashclr(si->base_sha1);
+ ret = do_write_locked_index(istate, lock, flags);
+ goto out;
+ }
+ ret = write_shared_index(istate, &temp);
+
+ saved_errno = errno;
+ if (is_tempfile_active(temp))
+ delete_tempfile(&temp);
+ errno = saved_errno;
+
if (ret)
goto out;
}
@@ -2573,8 +2577,11 @@
ret = write_split_index(istate, lock, flags);
/* Freshen the shared index only if the split-index was written */
- if (!ret && !new_shared_index)
- freshen_shared_index(sha1_to_hex(si->base_sha1), 1);
+ if (!ret && !new_shared_index) {
+ const char *shared_index = git_path("sharedindex.%s",
+ sha1_to_hex(si->base_sha1));
+ freshen_shared_index(shared_index, 1);
+ }
out:
if (flags & COMMIT_LOCK)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index f75d960..bec8e30 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2931,13 +2931,12 @@
if (initial_ref_transaction_commit(packed_transaction, err)) {
ret = TRANSACTION_GENERIC_ERROR;
- goto cleanup;
}
+ packed_refs_unlock(refs->packed_ref_store);
cleanup:
if (packed_transaction)
ref_transaction_free(packed_transaction);
- packed_refs_unlock(refs->packed_ref_store);
transaction->state = REF_TRANSACTION_CLOSED;
string_list_clear(&affected_refnames, 0);
return ret;
diff --git a/repository.c b/repository.c
index f66fcb1..4ffbe9b 100644
--- a/repository.c
+++ b/repository.c
@@ -236,5 +236,5 @@
if (!repo->index)
repo->index = xcalloc(1, sizeof(*repo->index));
- return read_index_from(repo->index, repo->index_file);
+ return read_index_from(repo->index, repo->index_file, repo->gitdir);
}
diff --git a/revision.c b/revision.c
index f4b1f72..e5e527b 100644
--- a/revision.c
+++ b/revision.c
@@ -1347,7 +1347,8 @@
continue; /* current index already taken care of */
if (read_index_from(&istate,
- worktree_git_path(wt, "index")) > 0)
+ worktree_git_path(wt, "index"),
+ get_worktree_git_dir(wt)) > 0)
do_add_index_objects_to_pending(revs, &istate);
discard_index(&istate);
}
diff --git a/split-index.c b/split-index.c
index 83e39ec..284d04d 100644
--- a/split-index.c
+++ b/split-index.c
@@ -238,6 +238,8 @@
ALLOC_GROW(entries, nr_entries+1, nr_alloc);
entries[nr_entries++] = ce;
}
+ if (is_null_oid(&ce->oid))
+ istate->drop_cache_tree = 1;
}
}
diff --git a/submodule-config.c b/submodule-config.c
index 2aa8a17..602ba8c 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -9,7 +9,7 @@
/*
* submodule cache lookup structure
* There is one shared set of 'struct submodule' entries which can be
- * looked up by their sha1 blob id of the .gitmodule file and either
+ * looked up by their sha1 blob id of the .gitmodules file and either
* using path or name as key.
* for_path stores submodule entries with path as key
* for_name stores submodule entries with name as key
@@ -91,7 +91,7 @@
/*
* We iterate over the name hash here to be symmetric with the
* allocation of struct submodule entries. Each is allocated by
- * their .gitmodule blob sha1 and submodule name.
+ * their .gitmodules blob sha1 and submodule name.
*/
hashmap_iter_init(&cache->for_name, &iter);
while ((entry = hashmap_iter_next(&iter)))
diff --git a/submodule.c b/submodule.c
index 2967704..47ddc9b 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1657,7 +1657,9 @@
else
argv_array_push(&cp.args, "-m");
- argv_array_push(&cp.args, old ? old : EMPTY_TREE_SHA1_HEX);
+ if (!(flags & SUBMODULE_MOVE_HEAD_FORCE))
+ argv_array_push(&cp.args, old ? old : EMPTY_TREE_SHA1_HEX);
+
argv_array_push(&cp.args, new ? new : EMPTY_TREE_SHA1_HEX);
if (run_command(&cp)) {
diff --git a/t/README b/t/README
index b3f7b44..1a1361a 100644
--- a/t/README
+++ b/t/README
@@ -655,7 +655,7 @@
test_expect_code 1 git merge "merge msg" B master
'
- - test_must_fail <git-command>
+ - test_must_fail [<options>] <git-command>
Run a git command and ensure it fails in a controlled way. Use
this instead of "! <git-command>". When git-command dies due to a
@@ -663,11 +663,21 @@
treats it as just another expected failure, which would let such a
bug go unnoticed.
- - test_might_fail <git-command>
+ Accepts the following options:
+
+ ok=<signal-name>[,<...>]:
+ Don't treat an exit caused by the given signal as error.
+ Multiple signals can be specified as a comma separated list.
+ Currently recognized signal names are: sigpipe, success.
+ (Don't use 'success', use 'test_might_fail' instead.)
+
+ - test_might_fail [<options>] <git-command>
Similar to test_must_fail, but tolerate success, too. Use this
instead of "<git-command> || :" to catch failures due to segv.
+ Accepts the same options as test_must_fail.
+
- test_cmp <expected> <actual>
Check whether the content of the <actual> file matches the
diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh
index 987d406..edbea2d 100644
--- a/t/lib-git-daemon.sh
+++ b/t/lib-git-daemon.sh
@@ -32,7 +32,8 @@
GIT_DAEMON_PID=
GIT_DAEMON_DOCUMENT_ROOT_PATH="$PWD"/repo
-GIT_DAEMON_URL=git://127.0.0.1:$LIB_GIT_DAEMON_PORT
+GIT_DAEMON_HOST_PORT=127.0.0.1:$LIB_GIT_DAEMON_PORT
+GIT_DAEMON_URL=git://$GIT_DAEMON_HOST_PORT
start_git_daemon() {
if test -n "$GIT_DAEMON_PID"
@@ -53,11 +54,19 @@
"$@" "$GIT_DAEMON_DOCUMENT_ROOT_PATH" \
>&3 2>git_daemon_output &
GIT_DAEMON_PID=$!
+ >daemon.log
{
- read line <&7
- echo >&4 "$line"
- cat <&7 >&4 &
- } 7<git_daemon_output &&
+ read -r line <&7
+ printf "%s\n" "$line"
+ printf >&4 "%s\n" "$line"
+ (
+ while read -r line <&7
+ do
+ printf "%s\n" "$line"
+ printf >&4 "%s\n" "$line"
+ done
+ ) &
+ } 7<git_daemon_output >>"$TRASH_DIRECTORY/daemon.log" &&
# Check expected output
if test x"$(expr "$line" : "\[[0-9]*\] \(.*\)")" != x"Ready to rumble"
@@ -90,3 +99,25 @@
GIT_DAEMON_PID=
rm -f git_daemon_output
}
+
+# A stripped-down version of a netcat client, that connects to a "host:port"
+# given in $1, sends its stdin followed by EOF, then dumps the response (until
+# EOF) to stdout.
+fake_nc() {
+ if ! test_declared_prereq FAKENC
+ then
+ echo >&4 "fake_nc: need to declare FAKENC prerequisite"
+ return 127
+ fi
+ perl -Mstrict -MIO::Socket::INET -e '
+ my $s = IO::Socket::INET->new(shift)
+ or die "unable to open socket: $!";
+ print $s <STDIN>;
+ $s->shutdown(1);
+ print <$s>;
+ ' "$@"
+}
+
+test_lazy_prereq FAKENC '
+ perl -MIO::Socket::INET -e "exit 0"
+'
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh
index 38dadd2..1f38a85 100755
--- a/t/lib-submodule-update.sh
+++ b/t/lib-submodule-update.sh
@@ -664,8 +664,8 @@
cd submodule_update &&
git -C sub1 checkout -b keep_branch &&
git -C sub1 rev-parse HEAD >expect &&
- git branch -t check-keep origin/modify_sub1 &&
- $command check-keep &&
+ git branch -t modify_sub1 origin/modify_sub1 &&
+ $command modify_sub1 &&
test_superproject_content origin/modify_sub1 &&
test_submodule_content sub1 origin/modify_sub1 &&
git -C sub1 rev-parse keep_branch >actual &&
@@ -885,6 +885,7 @@
(
cd submodule_update &&
git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
+ echo ignored >.git/modules/sub1/info/exclude &&
: >sub1/ignored &&
$command replace_sub1_with_file &&
test_superproject_content origin/replace_sub1_with_file &&
@@ -1014,4 +1015,18 @@
test_submodule_content sub1 origin/modify_sub1
)
'
+
+ test_expect_success "$command: changed submodule worktree is reset" '
+ prolog &&
+ reset_work_tree_to_interested add_sub1 &&
+ (
+ cd submodule_update &&
+ rm sub1/file1 &&
+ : >sub1/new_file &&
+ git -C sub1 add new_file &&
+ $command HEAD &&
+ test_path_is_file sub1/file1 &&
+ test_path_is_missing sub1/new_file
+ )
+ '
}
diff --git a/t/t0205-gettext-poison.sh b/t/t0205-gettext-poison.sh
index 2361590..438e778 100755
--- a/t/t0205-gettext-poison.sh
+++ b/t/t0205-gettext-poison.sh
@@ -7,10 +7,6 @@
. ./lib-gettext.sh
-test_expect_success GETTEXT_POISON "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" '
- test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME"
-'
-
test_expect_success GETTEXT_POISON 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is poison' '
test "$GIT_INTERNAL_GETTEXT_SH_SCHEME" = "poison"
'
diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh
index af9b847..a66936f 100755
--- a/t/t1700-split-index.sh
+++ b/t/t1700-split-index.sh
@@ -401,4 +401,42 @@
0642 -rw-r---w-
EOF
+test_expect_success POSIXPERM,SANITY 'graceful handling when splitting index is not allowed' '
+ test_create_repo ro &&
+ (
+ cd ro &&
+ test_commit initial &&
+ git update-index --split-index &&
+ test -f .git/sharedindex.*
+ ) &&
+ cp ro/.git/index new-index &&
+ test_when_finished "chmod u+w ro/.git" &&
+ chmod u-w ro/.git &&
+ GIT_INDEX_FILE="$(pwd)/new-index" git -C ro update-index --split-index &&
+ chmod u+w ro/.git &&
+ rm ro/.git/sharedindex.* &&
+ GIT_INDEX_FILE=new-index git ls-files >actual &&
+ echo initial.t >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'writing split index with null sha1 does not write cache tree' '
+ git config core.splitIndex true &&
+ git config splitIndex.maxPercentChange 0 &&
+ git commit -m "commit" &&
+ {
+ git ls-tree HEAD &&
+ printf "160000 commit $_z40\\tbroken\\n"
+ } >broken-tree &&
+ echo "add broken entry" >msg &&
+
+ tree=$(git mktree <broken-tree) &&
+ test_tick &&
+ commit=$(git commit-tree $tree -p HEAD <msg) &&
+ git update-ref HEAD "$commit" &&
+ GIT_ALLOW_NULL_SHA1=1 git reset --hard &&
+ (test-dump-cache-tree >cache-tree.out || true) &&
+ test_line_count = 0 cache-tree.out
+'
+
test_done
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index 1bdf38e..78236dc 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -25,6 +25,18 @@
test_cmp expect actual
'
+test_expect_success 'git status with porcelain v2' '
+ git status --porcelain=v2 | grep -v "^?" >actual &&
+ nam1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d &&
+ nam2=ce013625030ba8dba906f756967f9e9ca394464a &&
+ cat >expect <<-EOF &&
+ 1 DA N... 100644 000000 100644 $nam1 $_z40 1.t
+ 1 A. N... 000000 100644 100644 $_z40 $nam2 elif
+ 1 .A N... 000000 000000 100644 $_z40 $_z40 file
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success 'check result of "add -N"' '
git ls-files -s file >actual &&
empty=$(git hash-object --stdin </dev/null) &&
@@ -150,5 +162,65 @@
)
'
+test_expect_success 'rename detection finds the right names' '
+ git init rename-detection &&
+ (
+ cd rename-detection &&
+ echo contents >first &&
+ git add first &&
+ git commit -m first &&
+ mv first third &&
+ git add -N third &&
+
+ git status | grep -v "^?" >actual.1 &&
+ test_i18ngrep "renamed: *first -> third" actual.1 &&
+
+ git status --porcelain | grep -v "^?" >actual.2 &&
+ cat >expected.2 <<-\EOF &&
+ R first -> third
+ EOF
+ test_cmp expected.2 actual.2 &&
+
+ hash=12f00e90b6ef79117ce6e650416b8cf517099b78 &&
+ git status --porcelain=v2 | grep -v "^?" >actual.3 &&
+ cat >expected.3 <<-EOF &&
+ 2 .R N... 100644 100644 100644 $hash $hash R100 third first
+ EOF
+ test_cmp expected.3 actual.3
+ )
+'
+
+test_expect_success 'double rename detection in status' '
+ git init rename-detection-2 &&
+ (
+ cd rename-detection-2 &&
+ echo contents >first &&
+ git add first &&
+ git commit -m first &&
+ git mv first second &&
+ mv second third &&
+ git add -N third &&
+
+ git status | grep -v "^?" >actual.1 &&
+ test_i18ngrep "renamed: *first -> second" actual.1 &&
+ test_i18ngrep "renamed: *second -> third" actual.1 &&
+
+ git status --porcelain | grep -v "^?" >actual.2 &&
+ cat >expected.2 <<-\EOF &&
+ R first -> second
+ R second -> third
+ EOF
+ test_cmp expected.2 actual.2 &&
+
+ hash=12f00e90b6ef79117ce6e650416b8cf517099b78 &&
+ git status --porcelain=v2 | grep -v "^?" >actual.3 &&
+ cat >expected.3 <<-EOF &&
+ 2 R. N... 100644 100644 100644 $hash $hash R100 second first
+ 2 .R N... 100644 100644 100644 $hash $hash R100 third second
+ EOF
+ test_cmp expected.3 actual.3
+ )
+'
+
test_done
diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh
index eadf4f6..a07816d 100755
--- a/t/t4001-diff-rename.sh
+++ b/t/t4001-diff-rename.sh
@@ -134,11 +134,15 @@
git rm path1 &&
mkdir subdir &&
git mv another-path subdir/path1 &&
- git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"'
+ git status >out &&
+ test_i18ngrep "renamed: .*path1 -> subdir/path1" out
+'
test_expect_success 'favour same basenames even with minor differences' '
git show HEAD:path1 | sed "s/15/16/" > subdir/path1 &&
- git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"'
+ git status >out &&
+ test_i18ngrep "renamed: .*path1 -> subdir/path1" out
+'
test_expect_success 'two files with same basename and same content' '
git reset --hard &&
@@ -148,7 +152,8 @@
git add dir &&
git commit -m 2 &&
git mv dir other-dir &&
- git status | test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file"
+ git status >out &&
+ test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file" out
'
test_expect_success 'setup for many rename source candidates' '
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 668c54b..3debc87 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -222,12 +222,9 @@
(
cd descriptive &&
git fetch o 2>actual &&
- grep " -> refs/crazyheads/descriptive-branch$" actual |
- test_i18ngrep "new branch" &&
- grep " -> descriptive-tag$" actual |
- test_i18ngrep "new tag" &&
- grep " -> crazy$" actual |
- test_i18ngrep "new ref"
+ test_i18ngrep "new branch.* -> refs/crazyheads/descriptive-branch$" actual &&
+ test_i18ngrep "new tag.* -> descriptive-tag$" actual &&
+ test_i18ngrep "new ref.* -> crazy$" actual
) &&
git checkout master
'
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index a552ad4..74486c7 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -485,7 +485,7 @@
)
'
-test_expect_success "'fetch.recurseSubmodules=on-demand' works also without .gitmodule entry" '
+test_expect_success "'fetch.recurseSubmodules=on-demand' works also without .gitmodules entry" '
(
cd downstream &&
git fetch --recurse-submodules
diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh
index 2e42cf3..644736b 100755
--- a/t/t5536-fetch-conflicts.sh
+++ b/t/t5536-fetch-conflicts.sh
@@ -22,7 +22,7 @@
cat >expected &&
# We're not interested in the error
# "fatal: The remote end hung up unexpectedly":
- test_i18ngrep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort &&
+ test_i18ngrep -E '^(fatal|warning):' error | grep -v 'hung up' >actual | sort &&
test_i18ncmp expected actual
}
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index d38bf32..21340e8 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -234,7 +234,7 @@
test_commit no-progress &&
test_terminal git push --no-progress >output 2>&1 &&
test_i18ngrep "^To http" output &&
- test_i18ngrep ! "^Writing objects"
+ test_i18ngrep ! "^Writing objects" output
'
test_expect_success 'push --progress shows progress to non-tty' '
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index a51b7e2..f5721b4 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -364,5 +364,38 @@
submodule update sub
'
+test_expect_success 'GIT_REDACT_COOKIES redacts cookies' '
+ rm -rf clone &&
+ echo "Set-Cookie: Foo=1" >cookies &&
+ echo "Set-Cookie: Bar=2" >>cookies &&
+ GIT_TRACE_CURL=true GIT_REDACT_COOKIES=Bar,Baz \
+ git -c "http.cookieFile=$(pwd)/cookies" clone \
+ $HTTPD_URL/smart/repo.git clone 2>err &&
+ grep "Cookie:.*Foo=1" err &&
+ grep "Cookie:.*Bar=<redacted>" err &&
+ ! grep "Cookie:.*Bar=2" err
+'
+
+test_expect_success 'GIT_REDACT_COOKIES handles empty values' '
+ rm -rf clone &&
+ echo "Set-Cookie: Foo=" >cookies &&
+ GIT_TRACE_CURL=true GIT_REDACT_COOKIES=Foo \
+ git -c "http.cookieFile=$(pwd)/cookies" clone \
+ $HTTPD_URL/smart/repo.git clone 2>err &&
+ grep "Cookie:.*Foo=<redacted>" err
+'
+
+test_expect_success 'GIT_TRACE_CURL_NO_DATA prevents data from being traced' '
+ rm -rf clone &&
+ GIT_TRACE_CURL=true \
+ git clone $HTTPD_URL/smart/repo.git clone 2>err &&
+ grep "=> Send data" err &&
+
+ rm -rf clone &&
+ GIT_TRACE_CURL=true GIT_TRACE_CURL_NO_DATA=1 \
+ git clone $HTTPD_URL/smart/repo.git clone 2>err &&
+ ! grep "=> Send data" err
+'
+
stop_httpd
test_done
diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh
index 225a022..755b05a 100755
--- a/t/t5570-git-daemon.sh
+++ b/t/t5570-git-daemon.sh
@@ -167,23 +167,48 @@
git init --bare "$repo" &&
git push "$repo" HEAD &&
>"$repo"/git-daemon-export-ok &&
- rm -rf tmp.git &&
GIT_OVERRIDE_VIRTUAL_HOST=localhost \
- git clone --bare "$GIT_DAEMON_URL/interp.git" tmp.git &&
- rm -rf tmp.git &&
+ git ls-remote "$GIT_DAEMON_URL/interp.git" &&
GIT_OVERRIDE_VIRTUAL_HOST=LOCALHOST \
- git clone --bare "$GIT_DAEMON_URL/interp.git" tmp.git
+ git ls-remote "$GIT_DAEMON_URL/interp.git"
'
test_expect_success 'hostname cannot break out of directory' '
- rm -rf tmp.git &&
repo="$GIT_DAEMON_DOCUMENT_ROOT_PATH/../escape.git" &&
git init --bare "$repo" &&
git push "$repo" HEAD &&
>"$repo"/git-daemon-export-ok &&
test_must_fail \
env GIT_OVERRIDE_VIRTUAL_HOST=.. \
- git clone --bare "$GIT_DAEMON_URL/escape.git" tmp.git
+ git ls-remote "$GIT_DAEMON_URL/escape.git"
+'
+
+test_expect_success 'daemon log records all attributes' '
+ cat >expect <<-\EOF &&
+ Extended attribute "host": localhost
+ Extended attribute "protocol": version=1
+ EOF
+ >daemon.log &&
+ GIT_OVERRIDE_VIRTUAL_HOST=localhost \
+ git -c protocol.version=1 \
+ ls-remote "$GIT_DAEMON_URL/interp.git" &&
+ grep -i extended.attribute daemon.log | cut -d" " -f2- >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success FAKENC 'hostname interpolation works after LF-stripping' '
+ {
+ printf "git-upload-pack /interp.git\n\0host=localhost" | packetize
+ printf "0000"
+ } >input &&
+ fake_nc "$GIT_DAEMON_HOST_PORT" <input >output &&
+ depacketize <output >output.raw &&
+
+ # just pick out the value of master, which avoids any protocol
+ # particulars
+ perl -lne "print \$1 if m{^(\\S+) refs/heads/master}" <output.raw >actual &&
+ git -C "$repo" rev-parse master >expect &&
+ test_cmp expect actual
'
stop_git_daemon
diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh
index d911afd..872788a 100755
--- a/t/t5812-proto-disable-http.sh
+++ b/t/t5812-proto-disable-http.sh
@@ -20,10 +20,7 @@
test_must_fail env GIT_ALLOW_PROTOCOL=http:https \
GIT_SMART_HTTP=0 \
git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr &&
- {
- test_i18ngrep "ftp.*disabled" stderr ||
- test_i18ngrep "your curl version is too old"
- }
+ test_i18ngrep -E "(ftp.*disabled|your curl version is too old)" stderr
'
test_expect_success 'curl limits redirects' '
diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh
index 05ebba7..c01f721 100755
--- a/t/t6022-merge-rename.sh
+++ b/t/t6022-merge-rename.sh
@@ -242,10 +242,12 @@
rm -f A M N &&
git reset --hard &&
git checkout change+rename &&
- GIT_MERGE_VERBOSITY=3 git merge change | test_i18ngrep "^Skipped B" &&
+ GIT_MERGE_VERBOSITY=3 git merge change >out &&
+ test_i18ngrep "^Skipped B" out &&
git reset --hard HEAD^ &&
git checkout change &&
- GIT_MERGE_VERBOSITY=3 git merge change+rename | test_i18ngrep "^Skipped B"
+ GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&
+ test_i18ngrep "^Skipped B" out
'
test_expect_success 'setup for rename + d/f conflicts' '
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 6e5031f..d4e6485 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -39,6 +39,12 @@
grep "^R100..*path1/COPYING..*path0/COPYING"'
test_expect_success \
+ 'mv --dry-run does not move file' \
+ 'git mv -n path0/COPYING MOVED &&
+ test -f path0/COPYING &&
+ test ! -f MOVED'
+
+test_expect_success \
'checking -k on non-existing file' \
'git mv -k idontexist path0'
diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
index c207171..fc018e3 100755
--- a/t/t7409-submodule-detached-work-tree.sh
+++ b/t/t7409-submodule-detached-work-tree.sh
@@ -6,7 +6,7 @@
test_description='Test submodules on detached working tree
This test verifies that "git submodule" initialization, update and addition works
-on detahced working trees
+on detached working trees
'
TEST_NO_CREATE_REPO=1
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 1d33c5f..170b481 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -272,6 +272,14 @@
commit_msg_is "fixup! target message subject line"
'
+test_expect_success 'commit --fixup -m"something" -m"extra"' '
+ commit_for_rebase_autosquash_setup &&
+ git commit --fixup HEAD~1 -m"something" -m"extra" &&
+ commit_msg_is "fixup! target message subject linesomething
+
+extra"
+'
+
test_expect_success 'commit --squash works with -F' '
commit_for_rebase_autosquash_setup &&
echo "log message from file" >msgfile &&
@@ -325,7 +333,6 @@
test_must_fail git commit --fixup HEAD~1 --squash HEAD~2 &&
test_must_fail git commit --fixup HEAD~1 -C HEAD~2 &&
test_must_fail git commit --fixup HEAD~1 -c HEAD~2 &&
- test_must_fail git commit --fixup HEAD~1 -m "cmdline message" &&
test_must_fail git commit --fixup HEAD~1 -F log
'
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 4d261c2..81869d8 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -6,6 +6,12 @@
# May be altered later in the test
PREREQ="PERL"
+replace_variable_fields () {
+ sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \
+ -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
+ -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/"
+}
+
test_expect_success $PREREQ 'prepare reference tree' '
echo "1A quick brown fox jumps over the" >file &&
echo "lazy dog" >>file &&
@@ -296,10 +302,7 @@
--bcc=bcc@example.com \
--in-reply-to="<unique-message-id@example.com>" \
--smtp-server relay.example.com \
- $patches |
- sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \
- -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
- -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
+ $patches | replace_variable_fields \
>actual-show-all-headers &&
test_cmp expected-show-all-headers actual-show-all-headers
'
@@ -554,12 +557,6 @@
EOF
"
-replace_variable_fields () {
- sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \
- -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
- -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/"
-}
-
test_suppression () {
git send-email \
--dry-run \
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 1701fe2..8a8a932 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -610,6 +610,14 @@
#
# Writing this as "! git checkout ../outerspace" is wrong, because
# the failure could be due to a segv. We want a controlled failure.
+#
+# Accepts the following options:
+#
+# ok=<signal-name>[,<...>]:
+# Don't treat an exit caused by the given signal as error.
+# Multiple signals can be specified as a comma separated list.
+# Currently recognized signal names are: sigpipe, success.
+# (Don't use 'success', use 'test_might_fail' instead.)
test_must_fail () {
case "$1" in
@@ -656,6 +664,8 @@
#
# Writing "git config --unset all.configuration || :" would be wrong,
# because we want to notice if it fails due to segv.
+#
+# Accepts the same options as test_must_fail.
test_might_fail () {
test_must_fail ok=success "$@"
@@ -705,6 +715,60 @@
cmp "$@"
}
+# Use this instead of test_cmp to compare files that contain expected and
+# actual output from git commands that can be translated. When running
+# under GETTEXT_POISON this pretends that the command produced expected
+# results.
+test_i18ncmp () {
+ test -n "$GETTEXT_POISON" || test_cmp "$@"
+}
+
+# Use this instead of "grep expected-string actual" to see if the
+# output from a git command that can be translated either contains an
+# expected string, or does not contain an unwanted one. When running
+# under GETTEXT_POISON this pretends that the command produced expected
+# results.
+test_i18ngrep () {
+ eval "last_arg=\${$#}"
+
+ test -f "$last_arg" ||
+ error "bug in the test script: test_i18ngrep requires a file" \
+ "to read as the last parameter"
+
+ if test $# -lt 2 ||
+ { test "x!" = "x$1" && test $# -lt 3 ; }
+ then
+ error "bug in the test script: too few parameters to test_i18ngrep"
+ fi
+
+ if test -n "$GETTEXT_POISON"
+ then
+ # pretend success
+ return 0
+ fi
+
+ if test "x!" = "x$1"
+ then
+ shift
+ ! grep "$@" && return 0
+
+ echo >&2 "error: '! grep $@' did find a match in:"
+ else
+ grep "$@" && return 0
+
+ echo >&2 "error: 'grep $@' didn't find a match in:"
+ fi
+
+ if test -s "$last_arg"
+ then
+ cat >&2 "$last_arg"
+ else
+ echo >&2 "<File '$last_arg' is empty>"
+ fi
+
+ return 1
+}
+
# Call any command "$@" but be more verbose about its
# failure. This is handy for commands like "test" which do
# not output anything when they fail.
@@ -1020,3 +1084,37 @@
"$@"
)
}
+
+# convert stdin to pktline representation; note that empty input becomes an
+# empty packet, not a flush packet (for that you can just print 0000 yourself).
+packetize() {
+ cat >packetize.tmp &&
+ len=$(wc -c <packetize.tmp) &&
+ printf '%04x%s' "$(($len + 4))" &&
+ cat packetize.tmp &&
+ rm -f packetize.tmp
+}
+
+# Parse the input as a series of pktlines, writing the result to stdout.
+# Sideband markers are removed automatically, and the output is routed to
+# stderr if appropriate.
+#
+# NUL bytes are converted to "\\0" for ease of parsing with text tools.
+depacketize () {
+ perl -e '
+ while (read(STDIN, $len, 4) == 4) {
+ if ($len eq "0000") {
+ print "FLUSH\n";
+ } else {
+ read(STDIN, $buf, hex($len) - 4);
+ $buf =~ s/\0/\\0/g;
+ if ($buf =~ s/^[\x2\x3]//) {
+ print STDERR $buf;
+ } else {
+ $buf =~ s/^\x1//;
+ print $buf;
+ }
+ }
+ }
+ '
+}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 9a0a21f..816e692 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -116,6 +116,7 @@
my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
print join("\n", @vars);
')
+unset XDG_CACHE_HOME
unset XDG_CONFIG_HOME
unset GITPERLLIB
GIT_AUTHOR_EMAIL=author@example.com
@@ -1062,32 +1063,6 @@
test_set_prereq C_LOCALE_OUTPUT
fi
-# Use this instead of test_cmp to compare files that contain expected and
-# actual output from git commands that can be translated. When running
-# under GETTEXT_POISON this pretends that the command produced expected
-# results.
-test_i18ncmp () {
- test -n "$GETTEXT_POISON" || test_cmp "$@"
-}
-
-# Use this instead of "grep expected-string actual" to see if the
-# output from a git command that can be translated either contains an
-# expected string, or does not contain an unwanted one. When running
-# under GETTEXT_POISON this pretends that the command produced expected
-# results.
-test_i18ngrep () {
- if test -n "$GETTEXT_POISON"
- then
- : # pretend success
- elif test "x!" = "x$1"
- then
- shift
- ! grep "$@"
- else
- grep "$@"
- fi
-}
-
test_lazy_prereq PIPE '
# test whether the filesystem supports FIFOs
test_have_prereq !MINGW,!CYGWIN &&
diff --git a/unpack-trees.c b/unpack-trees.c
index bf8b602..96c3327 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -2139,6 +2139,9 @@
ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE))
update |= CE_UPDATE;
}
+ if (o->update && S_ISGITLINK(old->ce_mode) &&
+ should_update_submodules() && !verify_uptodate(old, o))
+ update |= CE_UPDATE;
add_entry(o, old, update, 0);
return 0;
}
diff --git a/wt-status.c b/wt-status.c
index ef26f07..f5debcd 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -360,8 +360,6 @@
switch (change_type) {
case WT_STATUS_UPDATED:
status = d->index_status;
- if (d->head_path)
- one_name = d->head_path;
break;
case WT_STATUS_CHANGED:
if (d->new_submodule_commits || d->dirty_submodule) {
@@ -382,6 +380,14 @@
change_type);
}
+ /*
+ * Only pick up the rename it's relevant. If the rename is for
+ * the changed section and we're printing the updated section,
+ * ignore it.
+ */
+ if (d->rename_status == status)
+ one_name = d->rename_source;
+
one = quote_path(one_name, s->prefix, &onebuf);
two = quote_path(two_name, s->prefix, &twobuf);
@@ -391,7 +397,7 @@
die("BUG: unhandled diff status %c", status);
len = label_width - utf8_strwidth(what);
assert(len >= 0);
- if (status == DIFF_STATUS_COPIED || status == DIFF_STATUS_RENAMED)
+ if (one_name != two_name)
status_printf_more(s, c, "%s%.*s%s -> %s",
what, len, padding, one, two);
else
@@ -406,7 +412,8 @@
strbuf_release(&twobuf);
}
-static char short_submodule_status(struct wt_status_change_data *d) {
+static char short_submodule_status(struct wt_status_change_data *d)
+{
if (d->new_submodule_commits)
return 'M';
if (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
@@ -432,7 +439,7 @@
struct wt_status_change_data *d;
p = q->queue[i];
- it = string_list_insert(&s->change, p->one->path);
+ it = string_list_insert(&s->change, p->two->path);
d = it->util;
if (!d) {
d = xcalloc(1, sizeof(*d));
@@ -459,6 +466,14 @@
/* mode_worktree is zero for a delete. */
break;
+ case DIFF_STATUS_COPIED:
+ case DIFF_STATUS_RENAMED:
+ if (d->rename_status)
+ die("BUG: multiple renames on the same target? how?");
+ d->rename_source = xstrdup(p->one->path);
+ d->rename_score = p->score * 100 / MAX_SCORE;
+ d->rename_status = p->status;
+ /* fallthru */
case DIFF_STATUS_MODIFIED:
case DIFF_STATUS_TYPE_CHANGED:
case DIFF_STATUS_UNMERGED:
@@ -467,8 +482,8 @@
oidcpy(&d->oid_index, &p->one->oid);
break;
- case DIFF_STATUS_UNKNOWN:
- die("BUG: worktree status unknown???");
+ default:
+ die("BUG: unhandled diff-files status '%c'", p->status);
break;
}
@@ -530,8 +545,11 @@
case DIFF_STATUS_COPIED:
case DIFF_STATUS_RENAMED:
- d->head_path = xstrdup(p->one->path);
- d->score = p->score * 100 / MAX_SCORE;
+ if (d->rename_status)
+ die("BUG: multiple renames on the same target? how?");
+ d->rename_source = xstrdup(p->one->path);
+ d->rename_score = p->score * 100 / MAX_SCORE;
+ d->rename_status = p->status;
/* fallthru */
case DIFF_STATUS_MODIFIED:
case DIFF_STATUS_TYPE_CHANGED:
@@ -548,6 +566,10 @@
* values in these fields.
*/
break;
+
+ default:
+ die("BUG: unhandled diff-index status '%c'", p->status);
+ break;
}
}
}
@@ -602,7 +624,7 @@
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = wt_status_collect_updated_cb;
rev.diffopt.format_callback_data = s;
- rev.diffopt.detect_rename = 1;
+ rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
rev.diffopt.rename_limit = 200;
rev.diffopt.break_opt = 0;
copy_pathspec(&rev.prune_data, &s->pathspec);
@@ -962,7 +984,7 @@
setup_revisions(0, NULL, &rev, &opt);
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
- rev.diffopt.detect_rename = 1;
+ rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
rev.diffopt.file = s->fp;
rev.diffopt.close_file = 0;
/*
@@ -1719,13 +1741,14 @@
putchar(' ');
if (s->null_termination) {
fprintf(stdout, "%s%c", it->string, 0);
- if (d->head_path)
- fprintf(stdout, "%s%c", d->head_path, 0);
+ if (d->rename_source)
+ fprintf(stdout, "%s%c", d->rename_source, 0);
} else {
struct strbuf onebuf = STRBUF_INIT;
const char *one;
- if (d->head_path) {
- one = quote_path(d->head_path, s->prefix, &onebuf);
+
+ if (d->rename_source) {
+ one = quote_path(d->rename_source, s->prefix, &onebuf);
if (*one != '"' && strchr(one, ' ') != NULL) {
putchar('"');
strbuf_addch(&onebuf, '"');
@@ -2030,10 +2053,10 @@
struct wt_status *s)
{
struct wt_status_change_data *d = it->util;
- struct strbuf buf_index = STRBUF_INIT;
- struct strbuf buf_head = STRBUF_INIT;
- const char *path_index = NULL;
- const char *path_head = NULL;
+ struct strbuf buf = STRBUF_INIT;
+ struct strbuf buf_from = STRBUF_INIT;
+ const char *path = NULL;
+ const char *path_from = NULL;
char key[3];
char submodule_token[5];
char sep_char, eol_char;
@@ -2052,8 +2075,8 @@
*/
sep_char = '\0';
eol_char = '\0';
- path_index = it->string;
- path_head = d->head_path;
+ path = it->string;
+ path_from = d->rename_source;
} else {
/*
* Path(s) are C-quoted if necessary. Current path is ALWAYS first.
@@ -2063,27 +2086,27 @@
*/
sep_char = '\t';
eol_char = '\n';
- path_index = quote_path(it->string, s->prefix, &buf_index);
- if (d->head_path)
- path_head = quote_path(d->head_path, s->prefix, &buf_head);
+ path = quote_path(it->string, s->prefix, &buf);
+ if (d->rename_source)
+ path_from = quote_path(d->rename_source, s->prefix, &buf_from);
}
- if (path_head)
+ if (path_from)
fprintf(s->fp, "2 %s %s %06o %06o %06o %s %s %c%d %s%c%s%c",
key, submodule_token,
d->mode_head, d->mode_index, d->mode_worktree,
oid_to_hex(&d->oid_head), oid_to_hex(&d->oid_index),
- key[0], d->score,
- path_index, sep_char, path_head, eol_char);
+ d->rename_status, d->rename_score,
+ path, sep_char, path_from, eol_char);
else
fprintf(s->fp, "1 %s %s %06o %06o %06o %s %s %s%c",
key, submodule_token,
d->mode_head, d->mode_index, d->mode_worktree,
oid_to_hex(&d->oid_head), oid_to_hex(&d->oid_index),
- path_index, eol_char);
+ path, eol_char);
- strbuf_release(&buf_index);
- strbuf_release(&buf_head);
+ strbuf_release(&buf);
+ strbuf_release(&buf_from);
}
/*
diff --git a/wt-status.h b/wt-status.h
index fe27b46..3f84d5c 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -44,10 +44,11 @@
int worktree_status;
int index_status;
int stagemask;
- int score;
int mode_head, mode_index, mode_worktree;
struct object_id oid_head, oid_index;
- char *head_path;
+ int rename_status;
+ int rename_score;
+ char *rename_source;
unsigned dirty_submodule : 2;
unsigned new_submodule_commits : 1;
};