summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.32.0.txt29
-rw-r--r--Documentation/config/stash.txt6
-rw-r--r--Documentation/git-stash.txt6
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile35
-rw-r--r--builtin/clean.c4
-rw-r--r--builtin/fsck.c3
-rw-r--r--builtin/init-db.c3
-rw-r--r--builtin/ls-files.c3
-rw-r--r--builtin/pack-objects.c174
-rw-r--r--builtin/rev-parse.c2
-rw-r--r--builtin/stash.c5
-rw-r--r--builtin/worktree.c4
-rw-r--r--compat/simple-ipc/ipc-shared.c10
-rw-r--r--compat/simple-ipc/ipc-unix-socket.c8
-rw-r--r--compat/simple-ipc/ipc-win32.c8
-rw-r--r--contrib/buildsystems/CMakeLists.txt10
-rw-r--r--contrib/completion/git-completion.bash2
-rw-r--r--contrib/completion/git-completion.zsh2
-rw-r--r--contrib/completion/git-prompt.sh6
-rw-r--r--diff-no-index.c5
-rw-r--r--dir.c145
-rw-r--r--dir.h6
-rw-r--r--entry.c5
-rwxr-xr-xgit-send-email.perl15
-rw-r--r--http.c15
-rw-r--r--notes-merge.c5
-rw-r--r--object-file.c4
-rw-r--r--pack-objects.h159
-rw-r--r--packfile.c5
-rw-r--r--perl/Git.pm13
-rw-r--r--perl/Git/I18N.pm10
-rw-r--r--ref-filter.c2
-rw-r--r--remote-curl.c2
-rw-r--r--rerere.c4
-rw-r--r--simple-ipc.h4
-rw-r--r--sparse-index.c2
-rw-r--r--t/README5
-rw-r--r--t/lib-parallel-checkout.sh2
-rwxr-xr-xt/t0001-init.sh28
-rwxr-xr-xt/t0027-auto-crlf.sh7
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh6
-rwxr-xr-xt/t1306-xdg-files.sh2
-rwxr-xr-xt/t1500-rev-parse.sh4
-rwxr-xr-xt/t2080-parallel-checkout-basics.sh2
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh5
-rwxr-xr-xt/t3003-ls-files-exclude.sh4
-rwxr-xr-xt/t3070-wildmatch.sh5
-rwxr-xr-xt/t3905-stash-include-untracked.sh2
-rwxr-xr-xt/t5551-http-fetch-smart.sh41
-rwxr-xr-xt/t6302-for-each-ref-filter.sh19
-rwxr-xr-xt/t7063-status-untracked-cache.sh206
-rwxr-xr-xt/t7300-clean.sh42
-rwxr-xr-xt/t7500-commit-template-squash-signoff.sh2
-rwxr-xr-xt/t7519-status-fsmonitor.sh8
-rwxr-xr-xt/t9001-send-email.sh25
-rw-r--r--t/test-lib.sh7
-rw-r--r--worktree.c12
-rw-r--r--write-or-die.c5
59 files changed, 737 insertions, 425 deletions
diff --git a/Documentation/RelNotes/2.32.0.txt b/Documentation/RelNotes/2.32.0.txt
index b47d569dc9..87d56fa1aa 100644
--- a/Documentation/RelNotes/2.32.0.txt
+++ b/Documentation/RelNotes/2.32.0.txt
@@ -47,11 +47,6 @@ UI, Workflows & Features
tweak both the message and the contents, and only the message,
respectively.
- * When accessing a server with a URL like https://user:pass@site/, we
- did not to fall back to the basic authentication with the
- credential material embedded in the URL after the "Negotiate"
- authentication failed. Now we do.
-
* "git send-email" learned to honor the core.hooksPath configuration.
* "git format-patch -v<n>" learned to allow a reroll count that is
@@ -371,6 +366,30 @@ Fixes since v2.31
empty directories under $GIT_DIR/refs/ for
(merge 5f03e5126d wc/packed-ref-removal-cleanup later to maint).
+ * "git clean" and "git ls-files -i" had confusion around working on
+ or showing ignored paths inside an ignored directory, which has
+ been corrected.
+ (merge b548f0f156 en/dir-traversal later to maint).
+
+ * The handling of "%(push)" formatting element of "for-each-ref" and
+ friends was broken when the same codepath started handling
+ "%(push:<what>)", which has been corrected.
+ (merge 1e1c4c5eac zh/ref-filter-push-remote-fix later to maint).
+
+ * The bash prompt script (in contrib/) did not work under "set -u".
+ (merge 5c0cbdb107 en/prompt-under-set-u later to maint).
+
+ * The "chainlint" feature in the test framework is a handy way to
+ catch common mistakes in writing new tests, but tends to get
+ expensive. An knob to selectively disable it has been introduced
+ to help running tests that the developer has not modified.
+ (merge 2d86a96220 jk/test-chainlint-softer later to maint).
+
+ * The "rev-parse" command did not diagnose the lack of argument to
+ "--path-format" option, which was introduced in v2.31 era, which
+ has been corrected.
+ (merge 99fc555188 wm/rev-parse-path-format-wo-arg later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge f451960708 dl/cat-file-doc-cleanup later to maint).
(merge 12604a8d0c sv/t9801-test-path-is-file-cleanup later to maint).
diff --git a/Documentation/config/stash.txt b/Documentation/config/stash.txt
index 413f907cba..9ed775281f 100644
--- a/Documentation/config/stash.txt
+++ b/Documentation/config/stash.txt
@@ -6,9 +6,9 @@ stash.useBuiltin::
remaining users that setting this now does nothing.
stash.showIncludeUntracked::
- If this is set to true, the `git stash show` command without an
- option will show the untracked files of a stash entry. Defaults to
- false. See description of 'show' command in linkgit:git-stash[1].
+ If this is set to true, the `git stash show` command will show
+ the untracked files of a stash entry. Defaults to false. See
+ description of 'show' command in linkgit:git-stash[1].
stash.showPatch::
If this is set to true, the `git stash show` command without an
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index a8c8c32f1e..be6084ccef 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -91,8 +91,10 @@ show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]::
By default, the command shows the diffstat, but it will accept any
format known to 'git diff' (e.g., `git stash show -p stash@{1}`
to view the second most recent entry in patch form).
- You can use stash.showIncludeUntracked, stash.showStat, and
- stash.showPatch config variables to change the default behavior.
+ If no `<diff-option>` is provided, the default behavior will be given
+ by the `stash.showStat`, and `stash.showPatch` config variables. You
+ can also use `stash.showIncludeUntracked` to set whether
+ `--include-untracked` is enabled by default.
pop [--index] [-q|--quiet] [<stash>]::
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index dd1d8099c7..c0942f12a3 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.32.0-rc0
+DEF_VER=v2.32.0-rc3
LF='
'
diff --git a/Makefile b/Makefile
index 3a2d3c80a8..c3565fc0f8 100644
--- a/Makefile
+++ b/Makefile
@@ -1687,13 +1687,31 @@ ifdef NO_UNIX_SOCKETS
else
LIB_OBJS += unix-socket.o
LIB_OBJS += unix-stream-server.o
- LIB_OBJS += compat/simple-ipc/ipc-shared.o
- LIB_OBJS += compat/simple-ipc/ipc-unix-socket.o
endif
+# Simple IPC requires threads and platform-specific IPC support.
+# Only platforms that have both should include these source files
+# in the build.
+#
+# On Windows-based systems, Simple IPC requires threads and Windows
+# Named Pipes. These are always available, so Simple IPC support
+# is optional.
+#
+# On Unix-based systems, Simple IPC requires pthreads and Unix
+# domain sockets. So support is only enabled when both are present.
+#
ifdef USE_WIN32_IPC
+ BASIC_CFLAGS += -DSUPPORTS_SIMPLE_IPC
LIB_OBJS += compat/simple-ipc/ipc-shared.o
LIB_OBJS += compat/simple-ipc/ipc-win32.o
+else
+ifndef NO_PTHREADS
+ifndef NO_UNIX_SOCKETS
+ BASIC_CFLAGS += -DSUPPORTS_SIMPLE_IPC
+ LIB_OBJS += compat/simple-ipc/ipc-shared.o
+ LIB_OBJS += compat/simple-ipc/ipc-unix-socket.o
+endif
+endif
endif
ifdef NO_ICONV
@@ -1987,6 +2005,7 @@ ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG))
ETC_GITATTRIBUTES_SQ = $(subst ','\'',$(ETC_GITATTRIBUTES))
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
+NO_GETTEXT_SQ = $(subst ','\'',$(NO_GETTEXT))
bindir_SQ = $(subst ','\'',$(bindir))
bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
mandir_SQ = $(subst ','\'',$(mandir))
@@ -2271,10 +2290,13 @@ perl_localedir_SQ = $(localedir_SQ)
ifndef NO_PERL
PERL_HEADER_TEMPLATE = perl/header_templates/fixed_prefix.template.pl
-PERL_DEFINES = $(PERL_PATH_SQ):$(PERLLIB_EXTRA_SQ):$(perllibdir_SQ)
-
-PERL_DEFINES := $(PERL_PATH_SQ) $(PERLLIB_EXTRA_SQ) $(perllibdir_SQ)
+PERL_DEFINES =
+PERL_DEFINES += $(PERL_PATH_SQ)
+PERL_DEFINES += $(PERLLIB_EXTRA_SQ)
+PERL_DEFINES += $(perllibdir_SQ)
PERL_DEFINES += $(RUNTIME_PREFIX)
+PERL_DEFINES += $(NO_PERL_CPAN_FALLBACKS)
+PERL_DEFINES += $(NO_GETTEXT)
# Support Perl runtime prefix. In this mode, a different header is installed
# into Perl scripts.
@@ -2676,9 +2698,10 @@ endif
NO_PERL_CPAN_FALLBACKS_SQ = $(subst ','\'',$(NO_PERL_CPAN_FALLBACKS))
endif
-perl/build/lib/%.pm: perl/%.pm
+perl/build/lib/%.pm: perl/%.pm GIT-PERL-DEFINES
$(QUIET_GEN)mkdir -p $(dir $@) && \
sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' \
+ -e 's|@@NO_GETTEXT@@|$(NO_GETTEXT_SQ)|g' \
-e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
< $< > $@
diff --git a/builtin/clean.c b/builtin/clean.c
index f6d7e8119c..4944cf440b 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -189,10 +189,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
strbuf_complete(path, '/');
len = path->len;
- while ((e = readdir(dir)) != NULL) {
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
- if (is_dot_or_dotdot(e->d_name))
- continue;
strbuf_setlen(path, len);
strbuf_addstr(path, e->d_name);
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 87a99b0108..b42b6fe21f 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -109,7 +109,8 @@ static int fsck_error_func(struct fsck_options *o,
static struct object_array pending;
-static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options)
+static int mark_object(struct object *obj, enum object_type type,
+ void *data, struct fsck_options *options)
{
struct object *parent = data;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index c19b35f1e6..2167796ff2 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -212,8 +212,9 @@ static int create_default_files(const char *template_path,
* values (since we've just potentially changed what's available on
* disk).
*/
- git_config_get_value("init.templatedir", &init_template_dir);
+ git_config_get_pathname("init.templatedir", &init_template_dir);
copy_templates(template_path, init_template_dir);
+ free((char *)init_template_dir);
git_config_clear();
reset_shared_repository();
git_config(git_default_config, NULL);
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 844c7f4e0e..45cc3b23dd 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -752,6 +752,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
if (pathspec.nr && error_unmatch)
ps_matched = xcalloc(pathspec.nr, 1);
+ if ((dir.flags & DIR_SHOW_IGNORED) && !show_others && !show_cached)
+ die("ls-files -i must be used with either -o or -c");
+
if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given)
die("ls-files --ignored needs some exclude pattern");
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 6ded130e45..de00adbb9e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -37,6 +37,134 @@
#include "shallow.h"
#include "promisor-remote.h"
+/*
+ * Objects we are going to pack are collected in the `to_pack` structure.
+ * It contains an array (dynamically expanded) of the object data, and a map
+ * that can resolve SHA1s to their position in the array.
+ */
+static struct packing_data to_pack;
+
+static inline struct object_entry *oe_delta(
+ const struct packing_data *pack,
+ const struct object_entry *e)
+{
+ if (!e->delta_idx)
+ return NULL;
+ if (e->ext_base)
+ return &pack->ext_bases[e->delta_idx - 1];
+ else
+ return &pack->objects[e->delta_idx - 1];
+}
+
+static inline unsigned long oe_delta_size(struct packing_data *pack,
+ const struct object_entry *e)
+{
+ if (e->delta_size_valid)
+ return e->delta_size_;
+
+ /*
+ * pack->delta_size[] can't be NULL because oe_set_delta_size()
+ * must have been called when a new delta is saved with
+ * oe_set_delta().
+ * If oe_delta() returns NULL (i.e. default state, which means
+ * delta_size_valid is also false), then the caller must never
+ * call oe_delta_size().
+ */
+ return pack->delta_size[e - pack->objects];
+}
+
+unsigned long oe_get_size_slow(struct packing_data *pack,
+ const struct object_entry *e);
+
+static inline unsigned long oe_size(struct packing_data *pack,
+ const struct object_entry *e)
+{
+ if (e->size_valid)
+ return e->size_;
+
+ return oe_get_size_slow(pack, e);
+}
+
+static inline void oe_set_delta(struct packing_data *pack,
+ struct object_entry *e,
+ struct object_entry *delta)
+{
+ if (delta)
+ e->delta_idx = (delta - pack->objects) + 1;
+ else
+ e->delta_idx = 0;
+}
+
+static inline struct object_entry *oe_delta_sibling(
+ const struct packing_data *pack,
+ const struct object_entry *e)
+{
+ if (e->delta_sibling_idx)
+ return &pack->objects[e->delta_sibling_idx - 1];
+ return NULL;
+}
+
+static inline struct object_entry *oe_delta_child(
+ const struct packing_data *pack,
+ const struct object_entry *e)
+{
+ if (e->delta_child_idx)
+ return &pack->objects[e->delta_child_idx - 1];
+ return NULL;
+}
+
+static inline void oe_set_delta_child(struct packing_data *pack,
+ struct object_entry *e,
+ struct object_entry *delta)
+{
+ if (delta)
+ e->delta_child_idx = (delta - pack->objects) + 1;
+ else
+ e->delta_child_idx = 0;
+}
+
+static inline void oe_set_delta_sibling(struct packing_data *pack,
+ struct object_entry *e,
+ struct object_entry *delta)
+{
+ if (delta)
+ e->delta_sibling_idx = (delta - pack->objects) + 1;
+ else
+ e->delta_sibling_idx = 0;
+}
+
+static inline void oe_set_size(struct packing_data *pack,
+ struct object_entry *e,
+ unsigned long size)
+{
+ if (size < pack->oe_size_limit) {
+ e->size_ = size;
+ e->size_valid = 1;
+ } else {
+ e->size_valid = 0;
+ if (oe_get_size_slow(pack, e) != size)
+ BUG("'size' is supposed to be the object size!");
+ }
+}
+
+static inline void oe_set_delta_size(struct packing_data *pack,
+ struct object_entry *e,
+ unsigned long size)
+{
+ if (size < pack->oe_delta_size_limit) {
+ e->delta_size_ = size;
+ e->delta_size_valid = 1;
+ } else {
+ packing_data_lock(pack);
+ if (!pack->delta_size)
+ ALLOC_ARRAY(pack->delta_size, pack->nr_alloc);
+ packing_data_unlock(pack);
+
+ pack->delta_size[e - pack->objects] = size;
+ e->delta_size_valid = 0;
+ }
+}
+
#define IN_PACK(obj) oe_in_pack(&to_pack, obj)
#define SIZE(obj) oe_size(&to_pack, obj)
#define SET_SIZE(obj,size) oe_set_size(&to_pack, obj, size)
@@ -56,13 +184,6 @@ static const char *pack_usage[] = {
NULL
};
-/*
- * Objects we are going to pack are collected in the `to_pack` structure.
- * It contains an array (dynamically expanded) of the object data, and a map
- * that can resolve SHA1s to their position in the array.
- */
-static struct packing_data to_pack;
-
static struct pack_idx_entry **written_list;
static uint32_t nr_result, nr_written, nr_seen;
static struct bitmap_index *bitmap_git;
@@ -301,6 +422,17 @@ static void copy_pack_data(struct hashfile *f,
}
}
+static inline int oe_size_greater_than(struct packing_data *pack,
+ const struct object_entry *lhs,
+ unsigned long rhs)
+{
+ if (lhs->size_valid)
+ return lhs->size_ > rhs;
+ if (rhs < pack->oe_size_limit) /* rhs < 2^x <= lhs ? */
+ return 1;
+ return oe_get_size_slow(pack, lhs) > rhs;
+}
+
/* Return 0 if we will bust the pack-size limit */
static unsigned long write_no_reuse_object(struct hashfile *f, struct object_entry *entry,
unsigned long limit, int usable_delta)
@@ -642,6 +774,14 @@ static int mark_tagged(const char *path, const struct object_id *oid, int flag,
return 0;
}
+static inline unsigned char oe_layer(struct packing_data *pack,
+ struct object_entry *e)
+{
+ if (!pack->layer)
+ return 0;
+ return pack->layer[e - pack->objects];
+}
+
static inline void add_to_write_order(struct object_entry **wo,
unsigned int *endp,
struct object_entry *e)
@@ -2231,6 +2371,26 @@ static pthread_mutex_t progress_mutex;
* progress_mutex for protection.
*/
+static inline int oe_size_less_than(struct packing_data *pack,
+ const struct object_entry *lhs,
+ unsigned long rhs)
+{
+ if (lhs->size_valid)
+ return lhs->size_ < rhs;
+ if (rhs < pack->oe_size_limit) /* rhs < 2^x <= lhs ? */
+ return 0;
+ return oe_get_size_slow(pack, lhs) < rhs;
+}
+
+static inline void oe_set_tree_depth(struct packing_data *pack,
+ struct object_entry *e,
+ unsigned int tree_depth)
+{
+ if (!pack->tree_depth)
+ CALLOC_ARRAY(pack->tree_depth, pack->nr_alloc);
+ pack->tree_depth[e - pack->objects] = tree_depth;
+}
+
/*
* Return the size of the object without doing any delta
* reconstruction (so non-deltas are true object sizes, but deltas
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 85bad9052e..7af8dab8bc 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -759,6 +759,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (opt_with_value(arg, "--path-format", &arg)) {
+ if (!arg)
+ die("--path-format requires an argument");
if (!strcmp(arg, "absolute")) {
format = FORMAT_CANONICAL;
} else if (!strcmp(arg, "relative")) {
diff --git a/builtin/stash.c b/builtin/stash.c
index 56a33fb83a..01066d7085 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -833,7 +833,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
UNTRACKED_NONE,
UNTRACKED_INCLUDE,
UNTRACKED_ONLY
- } show_untracked = UNTRACKED_NONE;
+ } show_untracked = show_include_untracked ? UNTRACKED_INCLUDE : UNTRACKED_NONE;
struct option options[] = {
OPT_SET_INT('u', "include-untracked", &show_untracked,
N_("include untracked files in the stash"),
@@ -876,9 +876,6 @@ static int show_stash(int argc, const char **argv, const char *prefix)
if (show_patch)
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
- if (show_include_untracked)
- show_untracked = UNTRACKED_INCLUDE;
-
if (!show_stat && !show_patch) {
free_stash_info(&info);
return 0;
diff --git a/builtin/worktree.c b/builtin/worktree.c
index f754978e47..976bf8ed06 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -118,10 +118,8 @@ static void prune_worktrees(void)
struct dirent *d;
if (!dir)
return;
- while ((d = readdir(dir)) != NULL) {
+ while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
char *path;
- if (is_dot_or_dotdot(d->d_name))
- continue;
strbuf_reset(&reason);
if (should_prune_worktree(d->d_name, &reason, &path, expire))
prune_worktree(d->d_name, reason.buf);
diff --git a/compat/simple-ipc/ipc-shared.c b/compat/simple-ipc/ipc-shared.c
index 1edec81595..1b9d359ab6 100644
--- a/compat/simple-ipc/ipc-shared.c
+++ b/compat/simple-ipc/ipc-shared.c
@@ -4,7 +4,13 @@
#include "pkt-line.h"
#include "thread-utils.h"
-#ifdef SUPPORTS_SIMPLE_IPC
+#ifndef SUPPORTS_SIMPLE_IPC
+/*
+ * This source file should only be compiled when Simple IPC is supported.
+ * See the top-level Makefile.
+ */
+#error SUPPORTS_SIMPLE_IPC not defined
+#endif
int ipc_server_run(const char *path, const struct ipc_server_opts *opts,
ipc_server_application_cb *application_cb,
@@ -24,5 +30,3 @@ int ipc_server_run(const char *path, const struct ipc_server_opts *opts,
return ret;
}
-
-#endif /* SUPPORTS_SIMPLE_IPC */
diff --git a/compat/simple-ipc/ipc-unix-socket.c b/compat/simple-ipc/ipc-unix-socket.c
index 38689b278d..1927e6ef4b 100644
--- a/compat/simple-ipc/ipc-unix-socket.c
+++ b/compat/simple-ipc/ipc-unix-socket.c
@@ -6,8 +6,12 @@
#include "unix-socket.h"
#include "unix-stream-server.h"
-#ifdef NO_UNIX_SOCKETS
-#error compat/simple-ipc/ipc-unix-socket.c requires Unix sockets
+#ifndef SUPPORTS_SIMPLE_IPC
+/*
+ * This source file should only be compiled when Simple IPC is supported.
+ * See the top-level Makefile.
+ */
+#error SUPPORTS_SIMPLE_IPC not defined
#endif
enum ipc_active_state ipc_get_active_state(const char *path)
diff --git a/compat/simple-ipc/ipc-win32.c b/compat/simple-ipc/ipc-win32.c
index 8f89c02037..8dc7bda087 100644
--- a/compat/simple-ipc/ipc-win32.c
+++ b/compat/simple-ipc/ipc-win32.c
@@ -4,8 +4,12 @@
#include "pkt-line.h"
#include "thread-utils.h"
-#ifndef GIT_WINDOWS_NATIVE
-#error This file can only be compiled on Windows
+#ifndef SUPPORTS_SIMPLE_IPC
+/*
+ * This source file should only be compiled when Simple IPC is supported.
+ * See the top-level Makefile.
+ */
+#error SUPPORTS_SIMPLE_IPC not defined
#endif
static int initialize_pipe_name(const char *path, wchar_t *wpath, size_t alloc)
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 75ed198a6a..a87841340e 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -252,8 +252,15 @@ endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
list(APPEND compat_SOURCES compat/simple-ipc/ipc-shared.c compat/simple-ipc/ipc-win32.c)
+ add_compile_definitions(SUPPORTS_SIMPLE_IPC)
+ set(SUPPORTS_SIMPLE_IPC 1)
else()
- list(APPEND compat_SOURCES compat/simple-ipc/ipc-shared.c compat/simple-ipc/ipc-unix-socket.c)
+ # Simple IPC requires both Unix sockets and pthreads on Unix-based systems.
+ if(NOT NO_UNIX_SOCKETS AND NOT NO_PTHREADS)
+ list(APPEND compat_SOURCES compat/simple-ipc/ipc-shared.c compat/simple-ipc/ipc-unix-socket.c)
+ add_compile_definitions(SUPPORTS_SIMPLE_IPC)
+ set(SUPPORTS_SIMPLE_IPC 1)
+ endif()
endif()
set(EXE_EXTENSION ${CMAKE_EXECUTABLE_SUFFIX})
@@ -974,6 +981,7 @@ file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "X='${EXE_EXTENSION}'\n")
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_GETTEXT='${NO_GETTEXT}'\n")
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "RUNTIME_PREFIX='${RUNTIME_PREFIX}'\n")
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PYTHON='${NO_PYTHON}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "SUPPORTS_SIMPLE_IPC='${SUPPORTS_SIMPLE_IPC}'\n")
if(WIN32)
file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/x64-windows/bin\"\n")
endif()
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3c5739b905..b50c5d0ea3 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1306,7 +1306,7 @@ __git_count_arguments ()
local word i c=0
# Skip "git" (first argument)
- for ((i="$__git_cmd_idx"; i < ${#words[@]}; i++)); do
+ for ((i=$__git_cmd_idx; i < ${#words[@]}; i++)); do
word="${words[i]}"
case "$word" in
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index 6c56296997..cac6f61881 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -251,7 +251,7 @@ __git_zsh_main ()
done
;;
(arg)
- local command="${words[1]}" __git_dir
+ local command="${words[1]}" __git_dir __git_cmd_idx=1
if (( $+opt_args[--bare] )); then
__git_dir='.'
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 4640a1535d..db7c0068fb 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -433,8 +433,8 @@ __git_ps1 ()
fi
local sparse=""
- if [ -z "${GIT_PS1_COMPRESSSPARSESTATE}" ] &&
- [ -z "${GIT_PS1_OMITSPARSESTATE}" ] &&
+ if [ -z "${GIT_PS1_COMPRESSSPARSESTATE-}" ] &&
+ [ -z "${GIT_PS1_OMITSPARSESTATE-}" ] &&
[ "$(git config --bool core.sparseCheckout)" = "true" ]; then
sparse="|SPARSE"
fi
@@ -543,7 +543,7 @@ __git_ps1 ()
u="%${ZSH_VERSION+%}"
fi
- if [ -n "${GIT_PS1_COMPRESSSPARSESTATE}" ] &&
+ if [ -n "${GIT_PS1_COMPRESSSPARSESTATE-}" ] &&
[ "$(git config --bool core.sparseCheckout)" = "true" ]; then
h="?"
fi
diff --git a/diff-no-index.c b/diff-no-index.c
index 308922e2b3..9a8b09346b 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -26,9 +26,8 @@ static int read_directory_contents(const char *path, struct string_list *list)
if (!(dir = opendir(path)))
return error("Could not open directory %s", path);
- while ((e = readdir(dir)))
- if (!is_dot_or_dotdot(e->d_name))
- string_list_insert(list, e->d_name);
+ while ((e = readdir_skip_dot_and_dotdot(dir)))
+ string_list_insert(list, e->d_name);
closedir(dir);
return 0;
diff --git a/dir.c b/dir.c
index c617dc763b..ebe5ec046e 100644
--- a/dir.c
+++ b/dir.c
@@ -59,6 +59,17 @@ void dir_init(struct dir_struct *dir)
memset(dir, 0, sizeof(*dir));
}
+struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp)
+{
+ struct dirent *e;
+
+ while ((e = readdir(dirp)) != NULL) {
+ if (!is_dot_or_dotdot(e->d_name))
+ break;
+ }
+ return e;
+}
+
int count_slashes(const char *s)
{
int cnt = 0;
@@ -1749,13 +1760,13 @@ static enum exist_status directory_exists_in_index(struct index_state *istate,
* Case 3: if we didn't have it in the index previously, we
* have a few sub-cases:
*
- * (a) if "show_other_directories" is true, we show it as
- * just a directory, unless "hide_empty_directories" is
+ * (a) if DIR_SHOW_OTHER_DIRECTORIES flag is set, we show it as
+ * just a directory, unless DIR_HIDE_EMPTY_DIRECTORIES is
* also true, in which case we need to check if it contains any
* untracked and / or ignored files.
- * (b) if it looks like a git directory, and we don't have
- * 'no_gitlinks' set we treat it as a gitlink, and show it
- * as a directory.
+ * (b) if it looks like a git directory and we don't have the
+ * DIR_NO_GITLINKS flag, then we treat it as a gitlink, and
+ * show it as a directory.
* (c) otherwise, we recurse into it.
*/
static enum path_treatment treat_directory(struct dir_struct *dir,
@@ -1843,7 +1854,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
return path_recurse;
}
- /* This is the "show_other_directories" case */
+ assert(dir->flags & DIR_SHOW_OTHER_DIRECTORIES);
/*
* If we have a pathspec which could match something _below_ this
@@ -1854,27 +1865,42 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
if (matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC)
return path_recurse;
+ /* Special cases for where this directory is excluded/ignored */
+ if (excluded) {
+ /*
+ * If DIR_SHOW_OTHER_DIRECTORIES is set and we're not
+ * hiding empty directories, there is no need to
+ * recurse into an ignored directory.
+ */
+ if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
+ return path_excluded;
+
+ /*
+ * Even if we are hiding empty directories, we can still avoid
+ * recursing into ignored directories for DIR_SHOW_IGNORED_TOO
+ * if DIR_SHOW_IGNORED_TOO_MODE_MATCHING is also set.
+ */
+ if ((dir->flags & DIR_SHOW_IGNORED_TOO) &&
+ (dir->flags & DIR_SHOW_IGNORED_TOO_MODE_MATCHING))
+ return path_excluded;
+ }
+
/*
- * Other than the path_recurse case immediately above, we only need
- * to recurse into untracked/ignored directories if either of the
- * following bits is set:
- * - DIR_SHOW_IGNORED_TOO (because then we need to determine if
- * there are ignored entries below)
+ * Other than the path_recurse case above, we only need to
+ * recurse into untracked directories if any of the following
+ * bits is set:
+ * - DIR_SHOW_IGNORED (because then we need to determine if
+ * there are ignored entries below)
+ * - DIR_SHOW_IGNORED_TOO (same as above)
* - DIR_HIDE_EMPTY_DIRECTORIES (because we have to determine if
* the directory is empty)
*/
- if (!(dir->flags & (DIR_SHOW_IGNORED_TOO | DIR_HIDE_EMPTY_DIRECTORIES)))
- return excluded ? path_excluded : path_untracked;
-
- /*
- * ...and even if DIR_SHOW_IGNORED_TOO is set, we can still avoid
- * recursing into ignored directories if the path is excluded and
- * DIR_SHOW_IGNORED_TOO_MODE_MATCHING is also set.
- */
- if (excluded &&
- (dir->flags & DIR_SHOW_IGNORED_TOO) &&
- (dir->flags & DIR_SHOW_IGNORED_TOO_MODE_MATCHING))
- return path_excluded;
+ if (!excluded &&
+ !(dir->flags & (DIR_SHOW_IGNORED |
+ DIR_SHOW_IGNORED_TOO |
+ DIR_HIDE_EMPTY_DIRECTORIES))) {
+ return path_untracked;
+ }
/*
* Even if we don't want to know all the paths under an untracked or
@@ -2326,7 +2352,7 @@ static int read_cached_dir(struct cached_dir *cdir)
struct dirent *de;
if (cdir->fdir) {
- de = readdir(cdir->fdir);
+ de = readdir_skip_dot_and_dotdot(cdir->fdir);
if (!de) {
cdir->d_name = NULL;
cdir->d_type = DT_UNKNOWN;
@@ -2440,6 +2466,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
if (open_cached_dir(&cdir, dir, untracked, istate, &path, check_only))
goto out;
+ dir->visited_directories++;
if (untracked)
untracked->check_only = !!check_only;
@@ -2448,6 +2475,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
/* check how the file or directory should be treated */
state = treat_path(dir, untracked, &cdir, istate, &path,
baselen, pathspec);
+ dir->visited_paths++;
if (state > dir_state)
dir_state = state;
@@ -2760,15 +2788,53 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
return root;
}
+static void emit_traversal_statistics(struct dir_struct *dir,
+ struct repository *repo,
+ const char *path,
+ int path_len)
+{
+ if (!trace2_is_enabled())
+ return;
+
+ if (!path_len) {
+ trace2_data_string("read_directory", repo, "path", "");
+ } else {
+ struct strbuf tmp = STRBUF_INIT;
+ strbuf_add(&tmp, path, path_len);
+ trace2_data_string("read_directory", repo, "path", tmp.buf);
+ strbuf_release(&tmp);
+ }
+
+ trace2_data_intmax("read_directory", repo,
+ "directories-visited", dir->visited_directories);
+ trace2_data_intmax("read_directory", repo,
+ "paths-visited", dir->visited_paths);
+
+ if (!dir->untracked)
+ return;
+ trace2_data_intmax("read_directory", repo,
+ "node-creation", dir->untracked->dir_created);
+ trace2_data_intmax("read_directory", repo,
+ "gitignore-invalidation",
+ dir->untracked->gitignore_invalidated);
+ trace2_data_intmax("read_directory", repo,
+ "directory-invalidation",
+ dir->untracked->dir_invalidated);
+ trace2_data_intmax("read_directory", repo,
+ "opendir", dir->untracked->dir_opened);
+}
+
int read_directory(struct dir_struct *dir, struct index_state *istate,
const char *path, int len, const struct pathspec *pathspec)
{
struct untracked_cache_dir *untracked;
- trace_performance_enter();
+ trace2_region_enter("dir", "read_directory", istate->repo);
+ dir->visited_paths = 0;
+ dir->visited_directories = 0;
if (has_symlink_leading_path(path, len)) {
- trace_performance_leave("read directory %.*s", len, path);
+ trace2_region_leave("dir", "read_directory", istate->repo);
return dir->nr;
}
@@ -2784,23 +2850,15 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
QSORT(dir->entries, dir->nr, cmp_dir_entry);
QSORT(dir->ignored, dir->ignored_nr, cmp_dir_entry);
- trace_performance_leave("read directory %.*s", len, path);
+ emit_traversal_statistics(dir, istate->repo, path, len);
+
+ trace2_region_leave("dir", "read_directory", istate->repo);
if (dir->untracked) {
static int force_untracked_cache = -1;
- static struct trace_key trace_untracked_stats = TRACE_KEY_INIT(UNTRACKED_STATS);
if (force_untracked_cache < 0)
force_untracked_cache =
git_env_bool("GIT_FORCE_UNTRACKED_CACHE", 0);
- trace_printf_key(&trace_untracked_stats,
- "node creation: %u\n"
- "gitignore invalidation: %u\n"
- "directory invalidation: %u\n"
- "opendir: %u\n",
- dir->untracked->dir_created,
- dir->untracked->gitignore_invalidated,
- dir->untracked->dir_invalidated,
- dir->untracked->dir_opened);
if (force_untracked_cache &&
dir->untracked == istate->untracked &&
(dir->untracked->dir_opened ||
@@ -2811,6 +2869,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
FREE_AND_NULL(dir->untracked);
}
}
+
return dir->nr;
}
@@ -2892,11 +2951,9 @@ int is_empty_dir(const char *path)
if (!dir)
return 0;
- while ((e = readdir(dir)) != NULL)
- if (!is_dot_or_dotdot(e->d_name)) {
- ret = 0;
- break;
- }
+ e = readdir_skip_dot_and_dotdot(dir);
+ if (e)
+ ret = 0;
closedir(dir);
return ret;
@@ -2936,10 +2993,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
strbuf_complete(path, '/');
len = path->len;
- while ((e = readdir(dir)) != NULL) {
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
- if (is_dot_or_dotdot(e->d_name))
- continue;
strbuf_setlen(path, len);
strbuf_addstr(path, e->d_name);
diff --git a/dir.h b/dir.h
index 35963f9e2c..e3db9b9ec6 100644
--- a/dir.h
+++ b/dir.h
@@ -336,8 +336,14 @@ struct dir_struct {
struct oid_stat ss_info_exclude;
struct oid_stat ss_excludes_file;
unsigned unmanaged_exclude_files;
+
+ /* Stats about the traversal */
+ unsigned visited_paths;
+ unsigned visited_directories;
};
+struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp);
+
/*Count the number of slashes for string s*/
int count_slashes(const char *s);
diff --git a/entry.c b/entry.c
index 3f376b9fdf..711ee0693c 100644
--- a/entry.c
+++ b/entry.c
@@ -58,12 +58,9 @@ static void remove_subtree(struct strbuf *path)
if (!dir)
die_errno("cannot opendir '%s'", path->buf);
- while ((de = readdir(dir)) != NULL) {
+ while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
- if (is_dot_or_dotdot(de->d_name))
- continue;
-
strbuf_addch(path, '/');
strbuf_addstr(path, de->d_name);
if (lstat(path->buf, &st))
diff --git a/git-send-email.perl b/git-send-email.perl
index 175da07d94..25be2ebd2a 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -219,8 +219,18 @@ sub system_or_msg {
my $exit_code = $? >> 8;
return unless $signalled or $exit_code;
+ my @sprintf_args = ($args->[0], $exit_code);
+ if (defined $msg) {
+ # Quiet the 'redundant' warning category, except we
+ # need to support down to Perl 5.8, so we can't do a
+ # "no warnings 'redundant'", since that category was
+ # introduced in perl 5.22, and asking for it will die
+ # on older perls.
+ no warnings;
+ return sprintf($msg, @sprintf_args);
+ }
return sprintf(__("fatal: command '%s' died with exit code %d"),
- $args->[0], $exit_code);
+ @sprintf_args);
}
sub system_or_die {
@@ -1949,7 +1959,8 @@ sub validate_patch {
my ($fn, $xfer_encoding) = @_;
if ($repo) {
- my $validate_hook = catfile($repo->hooks_path(),
+ my $hooks_path = $repo->command_oneline('rev-parse', '--git-path', 'hooks');
+ my $validate_hook = catfile($hooks_path,
'sendemail-validate');
my $hook_error;
if (-x $validate_hook) {
diff --git a/http.c b/http.c
index c83bc33a5f..8119247149 100644
--- a/http.c
+++ b/http.c
@@ -1650,18 +1650,17 @@ static int handle_curl_result(struct slot_results *results)
} else if (missing_target(results))
return HTTP_MISSING_TARGET;
else if (results->http_code == 401) {
-#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
- http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
- if (results->auth_avail) {
- http_auth_methods &= results->auth_avail;
- http_auth_methods_restricted = 1;
- return HTTP_REAUTH;
- }
-#endif
if (http_auth.username && http_auth.password) {
credential_reject(&http_auth);
return HTTP_NOAUTH;
} else {
+#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
+ http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
+ if (results->auth_avail) {
+ http_auth_methods &= results->auth_avail;
+ http_auth_methods_restricted = 1;
+ }
+#endif
return HTTP_REAUTH;
}
} else {
diff --git a/notes-merge.c b/notes-merge.c
index 12e8472b65..46c1f7c7f1 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -695,13 +695,10 @@ int notes_merge_commit(struct notes_merge_options *o,
strbuf_addch(&path, '/');
baselen = path.len;
- while ((e = readdir(dir)) != NULL) {
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct stat st;
struct object_id obj_oid, blob_oid;
- if (is_dot_or_dotdot(e->d_name))
- continue;
-
if (get_oid_hex(e->d_name, &obj_oid)) {
if (o->verbosity >= 3)
printf("Skipping non-SHA1 entry '%s%s'\n",
diff --git a/object-file.c b/object-file.c
index 884855b9df..f233b440b2 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2350,10 +2350,8 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
strbuf_addch(path, '/');
baselen = path->len;
- while ((de = readdir(dir))) {
+ while ((de = readdir_skip_dot_and_dotdot(dir))) {
size_t namelen;
- if (is_dot_or_dotdot(de->d_name))
- continue;
namelen = strlen(de->d_name);
strbuf_setlen(path, baselen);
diff --git a/pack-objects.h b/pack-objects.h
index 9d88e3e518..dca2351ef9 100644
--- a/pack-objects.h
+++ b/pack-objects.h
@@ -268,152 +268,10 @@ static inline void oe_set_in_pack(struct packing_data *pack,
pack->in_pack[e - pack->objects] = p;
}
-static inline struct object_entry *oe_delta(
- const struct packing_data *pack,
- const struct object_entry *e)
-{
- if (!e->delta_idx)
- return NULL;
- if (e->ext_base)
- return &pack->ext_bases[e->delta_idx - 1];
- else
- return &pack->objects[e->delta_idx - 1];
-}
-
-static inline void oe_set_delta(struct packing_data *pack,
- struct object_entry *e,
- struct object_entry *delta)
-{
- if (delta)
- e->delta_idx = (delta - pack->objects) + 1;
- else
- e->delta_idx = 0;
-}
-
void oe_set_delta_ext(struct packing_data *pack,
struct object_entry *e,
const struct object_id *oid);
-static inline struct object_entry *oe_delta_child(
- const struct packing_data *pack,
- const struct object_entry *e)
-{
- if (e->delta_child_idx)
- return &pack->objects[e->delta_child_idx - 1];
- return NULL;
-}
-
-static inline void oe_set_delta_child(struct packing_data *pack,
- struct object_entry *e,
- struct object_entry *delta)
-{
- if (delta)
- e->delta_child_idx = (delta - pack->objects) + 1;
- else
- e->delta_child_idx = 0;
-}
-
-static inline struct object_entry *oe_delta_sibling(
- const struct packing_data *pack,
- const struct object_entry *e)
-{
- if (e->delta_sibling_idx)
- return &pack->objects[e->delta_sibling_idx - 1];
- return NULL;
-}
-
-static inline void oe_set_delta_sibling(struct packing_data *pack,
- struct object_entry *e,
- struct object_entry *delta)
-{
- if (delta)
- e->delta_sibling_idx = (delta - pack->objects) + 1;
- else
- e->delta_sibling_idx = 0;
-}
-
-unsigned long oe_get_size_slow(struct packing_data *pack,
- const struct object_entry *e);
-static inline unsigned long oe_size(struct packing_data *pack,
- const struct object_entry *e)
-{
- if (e->size_valid)
- return e->size_;
-
- return oe_get_size_slow(pack, e);
-}
-
-static inline int oe_size_less_than(struct packing_data *pack,
- const struct object_entry *lhs,
- unsigned long rhs)
-{
- if (lhs->size_valid)
- return lhs->size_ < rhs;
- if (rhs < pack->oe_size_limit) /* rhs < 2^x <= lhs ? */
- return 0;
- return oe_get_size_slow(pack, lhs) < rhs;
-}
-
-static inline int oe_size_greater_than(struct packing_data *pack,
- const struct object_entry *lhs,
- unsigned long rhs)
-{
- if (lhs->size_valid)
- return lhs->size_ > rhs;
- if (rhs < pack->oe_size_limit) /* rhs < 2^x <= lhs ? */
- return 1;
- return oe_get_size_slow(pack, lhs) > rhs;
-}
-
-static inline void oe_set_size(struct packing_data *pack,
- struct object_entry *e,
- unsigned long size)
-{
- if (size < pack->oe_size_limit) {
- e->size_ = size;
- e->size_valid = 1;
- } else {
- e->size_valid = 0;
- if (oe_get_size_slow(pack, e) != size)
- BUG("'size' is supposed to be the object size!");
- }
-}
-
-static inline unsigned long oe_delta_size(struct packing_data *pack,
- const struct object_entry *e)
-{
- if (e->delta_size_valid)
- return e->delta_size_;
-
- /*
- * pack->delta_size[] can't be NULL because oe_set_delta_size()
- * must have been called when a new delta is saved with
- * oe_set_delta().
- * If oe_delta() returns NULL (i.e. default state, which means
- * delta_size_valid is also false), then the caller must never
- * call oe_delta_size().
- */
- return pack->delta_size[e - pack->objects];
-}
-
-static inline void oe_set_delta_size(struct packing_data *pack,
- struct object_entry *e,
- unsigned long size)
-{
- if (size < pack->oe_delta_size_limit) {
- e->delta_size_ = size;
- e->delta_size_valid = 1;
- } else {
- packing_data_lock(pack);
- if (!pack->delta_size)
- ALLOC_ARRAY(pack->delta_size, pack->nr_alloc);
- packing_data_unlock(pack);
-
- pack->delta_size[e - pack->objects] = size;
- e->delta_size_valid = 0;
- }
-}
-
static inline unsigned int oe_tree_depth(struct packing_data *pack,
struct object_entry *e)
{
@@ -422,23 +280,6 @@ static inline unsigned int oe_tree_depth(struct packing_data *pack,
return pack->tree_depth[e - pack->objects];
}
-static inline void oe_set_tree_depth(struct packing_data *pack,
- struct object_entry *e,
- unsigned int tree_depth)
-{
- if (!pack->tree_depth)
- CALLOC_ARRAY(pack->tree_depth, pack->nr_alloc);
- pack->tree_depth[e - pack->objects] = tree_depth;
-}
-
-static inline unsigned char oe_layer(struct packing_data *pack,
- struct object_entry *e)
-{
- if (!pack->layer)
- return 0;
- return pack->layer[e - pack->objects];
-}
-
static inline void oe_set_layer(struct packing_data *pack,
struct object_entry *e,
unsigned char layer)
diff --git a/packfile.c b/packfile.c
index b79cbc8cd4..755aa7aec5 100644
--- a/packfile.c
+++ b/packfile.c
@@ -813,10 +813,7 @@ void for_each_file_in_pack_dir(const char *objdir,
}
strbuf_addch(&path, '/');
dirnamelen = path.len;
- while ((de = readdir(dir)) != NULL) {
- if (is_dot_or_dotdot(de->d_name))
- continue;
-
+ while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) {
strbuf_setlen(&path, dirnamelen);
strbuf_addstr(&path, de->d_name);
diff --git a/perl/Git.pm b/perl/Git.pm
index 73ebbf80cc..02eacef0c2 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -619,19 +619,6 @@ Return path to the git repository. Must be called on a repository instance.
sub repo_path { $_[0]->{opts}->{Repository} }
-=item hooks_path ()
-
-Return path to the hooks directory. Must be called on a repository instance.
-
-=cut
-
-sub hooks_path {
- my ($self) = @_;
-
- my $dir = $self->command_oneline('rev-parse', '--git-path', 'hooks');
- my $abs = abs_path($dir);
- return $abs;
-}
=item wc_path ()
diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm
index 2037f387c8..895e759c57 100644
--- a/perl/Git/I18N.pm
+++ b/perl/Git/I18N.pm
@@ -16,9 +16,19 @@ BEGIN {
our @EXPORT = qw(__ __n N__);
our @EXPORT_OK = @EXPORT;
+# See Git::LoadCPAN's NO_PERL_CPAN_FALLBACKS_STR for a description of
+# this "'@@' [...] '@@'" pattern.
+use constant NO_GETTEXT_STR => '@@' . 'NO_GETTEXT' . '@@';
+use constant NO_GETTEXT => (
+ q[@@NO_GETTEXT@@] ne ''
+ and
+ q[@@NO_GETTEXT@@] ne NO_GETTEXT_STR
+);
+
sub __bootstrap_locale_messages {
our $TEXTDOMAIN = 'git';
our $TEXTDOMAINDIR ||= $ENV{GIT_TEXTDOMAINDIR} || '@@LOCALEDIR@@';
+ die "NO_GETTEXT=" . NO_GETTEXT_STR if NO_GETTEXT;
require POSIX;
POSIX->import(qw(setlocale));
diff --git a/ref-filter.c b/ref-filter.c
index e2eac50d95..97116e12d7 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1730,7 +1730,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
else
v->s = xstrdup("");
continue;
- } else if (atom->u.remote_ref.push) {
+ } else if (!strcmp(atom->name, "push") || starts_with(atom->name, "push:")) {
const char *branch_name;
v->s = xstrdup("");
if (!skip_prefix(ref->refname, "refs/heads/",
diff --git a/remote-curl.c b/remote-curl.c
index 0290b04891..9d432c299a 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -555,6 +555,8 @@ static void output_refs(struct ref *refs)
struct ref *posn;
if (options.object_format && options.hash_algo) {
printf(":object-format %s\n", options.hash_algo->name);
+ repo_set_hash_algo(the_repository,
+ hash_algo_by_ptr(options.hash_algo));
}
for (posn = refs; posn; posn = posn->next) {
if (posn->symref)
diff --git a/rerere.c b/rerere.c
index dee60dc6df..d83d58df4f 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1190,13 +1190,11 @@ void rerere_gc(struct repository *r, struct string_list *rr)
if (!dir)
die_errno(_("unable to open rr-cache directory"));
/* Collect stale conflict IDs ... */
- while ((e = readdir(dir))) {
+ while ((e = readdir_skip_dot_and_dotdot(dir))) {
struct rerere_dir *rr_dir;
struct rerere_id id;
int now_empty;
- if (is_dot_or_dotdot(e->d_name))
- continue;
if (!is_rr_cache_dirname(e->d_name))
continue; /* or should we remove e->d_name? */
diff --git a/simple-ipc.h b/simple-ipc.h
index dc3606e30b..2c48a5ee00 100644
--- a/simple-ipc.h
+++ b/simple-ipc.h
@@ -5,10 +5,6 @@
* See Documentation/technical/api-simple-ipc.txt
*/
-#if defined(GIT_WINDOWS_NATIVE) || !defined(NO_UNIX_SOCKETS)
-#define SUPPORTS_SIMPLE_IPC
-#endif
-
#ifdef SUPPORTS_SIMPLE_IPC
#include "pkt-line.h"
diff --git a/sparse-index.c b/sparse-index.c
index b0d5dc5f08..affc4048f2 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -34,7 +34,7 @@ static int convert_to_sparse_rec(struct index_state *istate,
int i, can_convert = 1;
int start_converted = num_converted;
enum pattern_match_result match;
- int dtype;
+ int dtype = DT_UNKNOWN;
struct strbuf child_path = STRBUF_INIT;
struct pattern_list *pl = istate->sparse_checkout_patterns;
diff --git a/t/README b/t/README
index a8cfd37387..1a2072b2c8 100644
--- a/t/README
+++ b/t/README
@@ -196,6 +196,11 @@ appropriately before running "make". Short options can be bundled, i.e.
this feature by setting the GIT_TEST_CHAIN_LINT environment
variable to "1" or "0", respectively.
+ A few test scripts disable some of the more advanced
+ chain-linting detection in the name of efficiency. You can
+ override this by setting the GIT_TEST_CHAIN_LINT_HARDER
+ environment variable to "1".
+
--stress::
Run the test script repeatedly in multiple parallel jobs until
one of them fails. Useful for reproducing rare failures in
diff --git a/t/lib-parallel-checkout.sh b/t/lib-parallel-checkout.sh
index 21f5759732..83b279a846 100644
--- a/t/lib-parallel-checkout.sh
+++ b/t/lib-parallel-checkout.sh
@@ -27,7 +27,7 @@ test_checkout_workers () {
rm -f "$trace_file" &&
GIT_TRACE2="$(pwd)/$trace_file" "$@" 2>&8 &&
- local workers=$(grep "child_start\[..*\] git checkout--worker" "$trace_file" | wc -l) &&
+ local workers="$(grep "child_start\[..*\] git checkout--worker" "$trace_file" | wc -l)" &&
test $workers -eq $expected_workers &&
rm "$trace_file"
} 8>&2 2>&4
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 0803994874..acd662e403 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -186,21 +186,33 @@ test_expect_success 'init with --template (blank)' '
test_path_is_missing template-blank/.git/info/exclude
'
-test_expect_success 'init with init.templatedir set' '
- mkdir templatedir-source &&
- echo Content >templatedir-source/file &&
- test_config_global init.templatedir "${HOME}/templatedir-source" &&
+init_no_templatedir_env () {
(
- mkdir templatedir-set &&
- cd templatedir-set &&
sane_unset GIT_TEMPLATE_DIR &&
NO_SET_GIT_TEMPLATE_DIR=t &&
export NO_SET_GIT_TEMPLATE_DIR &&
- git init
- ) &&
+ git init "$1"
+ )
+}
+
+test_expect_success 'init with init.templatedir set' '
+ mkdir templatedir-source &&
+ echo Content >templatedir-source/file &&
+ test_config_global init.templatedir "${HOME}/templatedir-source" &&
+
+ init_no_templatedir_env templatedir-set &&
test_cmp templatedir-source/file templatedir-set/.git/file
'
+test_expect_success 'init with init.templatedir using ~ expansion' '
+ mkdir -p templatedir-source &&
+ echo Content >templatedir-source/file &&
+ test_config_global init.templatedir "~/templatedir-source" &&
+
+ init_no_templatedir_env templatedir-expansion &&
+ test_cmp templatedir-source/file templatedir-expansion/.git/file
+'
+
test_expect_success 'init --bare/--shared overrides system/global config' '
test_config_global core.bare false &&
test_config_global core.sharedRepository 0640 &&
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
index d24d5acfbc..4a5c5c602c 100755
--- a/t/t0027-auto-crlf.sh
+++ b/t/t0027-auto-crlf.sh
@@ -386,7 +386,9 @@ test_expect_success 'setup main' '
test_tick
'
-
+# Disable extra chain-linting for the next set of tests. There are many
+# auto-generated ones that are not worth checking over and over.
+GIT_TEST_CHAIN_LINT_HARDER_DEFAULT=0
warn_LF_CRLF="LF will be replaced by CRLF"
warn_CRLF_LF="CRLF will be replaced by LF"
@@ -597,6 +599,9 @@ do
checkout_files auto "$id" "" false native $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul
done
+# The rest of the tests are unique; do the usual linting.
+unset GIT_TEST_CHAIN_LINT_HARDER_DEFAULT
+
# Should be the last test case: remove some files from the worktree
test_expect_success 'ls-files --eol -d -z' '
rm crlf_false_attr__CRLF.txt crlf_false_attr__CRLF_mix_LF.txt crlf_false_attr__LF.txt .gitattributes &&
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 12e6c45302..e9a815ca7a 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -106,18 +106,18 @@ init_repos () {
run_on_sparse () {
(
cd sparse-checkout &&
- "$@" >../sparse-checkout-out 2>../sparse-checkout-err
+ GIT_PROGRESS_DELAY=100000 "$@" >../sparse-checkout-out 2>../sparse-checkout-err
) &&
(
cd sparse-index &&
- "$@" >../sparse-index-out 2>../sparse-index-err
+ GIT_PROGRESS_DELAY=100000 "$@" >../sparse-index-out 2>../sparse-index-err
)
}
run_on_all () {
(
cd full-checkout &&
- "$@" >../full-checkout-out 2>../full-checkout-err
+ GIT_PROGRESS_DELAY=100000 "$@" >../full-checkout-out 2>../full-checkout-err
) &&
run_on_sparse "$@"
}
diff --git a/t/t1306-xdg-files.sh b/t/t1306-xdg-files.sh
index dd87b43be1..40d3c42618 100755
--- a/t/t1306-xdg-files.sh
+++ b/t/t1306-xdg-files.sh
@@ -116,7 +116,7 @@ test_expect_success 'Exclusion in a non-XDG global ignore file' '
test_expect_success 'Checking XDG ignore file when HOME is unset' '
(sane_unset HOME &&
git config --unset core.excludesfile &&
- git ls-files --exclude-standard --ignored >actual) &&
+ git ls-files --exclude-standard --ignored --others >actual) &&
test_must_be_empty actual
'
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index deae916707..1c2df08333 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -146,6 +146,10 @@ test_expect_success '--path-format can change in the middle of the command line'
test_cmp expect actual
'
+test_expect_success '--path-format does not segfault without an argument' '
+ test_must_fail git rev-parse --path-format
+'
+
test_expect_success 'git-common-dir from worktree root' '
echo .git >expect &&
git rev-parse --git-common-dir >actual &&
diff --git a/t/t2080-parallel-checkout-basics.sh b/t/t2080-parallel-checkout-basics.sh
index 7087818550..3e0f8c675f 100755
--- a/t/t2080-parallel-checkout-basics.sh
+++ b/t/t2080-parallel-checkout-basics.sh
@@ -114,7 +114,7 @@ do
test_expect_success "$mode checkout" '
repo=various_$mode &&
- cp -R various $repo &&
+ cp -R -P various $repo &&
# The just copied files have more recent timestamps than their
# associated index entries. So refresh the cached timestamps
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 1ec7cb57c7..516c95ea0e 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -292,6 +292,11 @@ EOF
test_cmp expect actual
'
+test_expect_success 'ls-files with "**" patterns and --directory' '
+ # Expectation same as previous test
+ git ls-files --directory -o -i --exclude "**/a.1" >actual &&
+ test_cmp expect actual
+'
test_expect_success 'ls-files with "**" patterns and no slashes' '
git ls-files -o -i --exclude "one**a.1" >actual &&
diff --git a/t/t3003-ls-files-exclude.sh b/t/t3003-ls-files-exclude.sh
index d5ec333131..c41c4f046a 100755
--- a/t/t3003-ls-files-exclude.sh
+++ b/t/t3003-ls-files-exclude.sh
@@ -29,11 +29,11 @@ test_expect_success 'add file to gitignore' '
'
check_all_output
-test_expect_success 'ls-files -i lists only tracked-but-ignored files' '
+test_expect_success 'ls-files -i -c lists only tracked-but-ignored files' '
echo content >other-file &&
git add other-file &&
echo file >expect &&
- git ls-files -i --exclude-standard >output &&
+ git ls-files -i -c --exclude-standard >output &&
test_cmp expect output
'
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 891d4d7cb9..56ea4bda13 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,6 +4,11 @@ test_description='wildmatch tests'
. ./test-lib.sh
+# Disable expensive chain-lint tests; all of the tests in this script
+# are variants of a few trivial test-tool invocations, and there are a lot of
+# them.
+GIT_TEST_CHAIN_LINT_HARDER_DEFAULT=0
+
should_create_test_file() {
file=$1
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index 5bed8fd2fd..dd2cdcc114 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -333,6 +333,8 @@ test_expect_success 'stash show --include-untracked shows untracked files' '
git stash show -p --include-untracked >actual &&
test_cmp expect actual &&
git stash show --include-untracked -p >actual &&
+ test_cmp expect actual &&
+ git -c stash.showIncludeUntracked=true stash show -p >actual &&
test_cmp expect actual
'
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 984dba22af..4f87d90c5b 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -517,4 +517,45 @@ test_expect_success 'server-side error detected' '
test_i18ngrep "server-side error" actual
'
+test_expect_success 'http auth remembers successful credentials' '
+ rm -f .git-credentials &&
+ test_config credential.helper store &&
+
+ # the first request prompts the user...
+ set_askpass user@host pass@host &&
+ git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
+ expect_askpass both user@host &&
+
+ # ...and the second one uses the stored value rather than
+ # prompting the user.
+ set_askpass bogus-user bogus-pass &&
+ git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
+ expect_askpass none
+'
+
+test_expect_success 'http auth forgets bogus credentials' '
+ # seed credential store with bogus values. In real life,
+ # this would probably come from a password which worked
+ # for a previous request.
+ rm -f .git-credentials &&
+ test_config credential.helper store &&
+ {
+ echo "url=$HTTPD_URL" &&
+ echo "username=bogus" &&
+ echo "password=bogus"
+ } | git credential approve &&
+
+ # we expect this to use the bogus values and fail, never even
+ # prompting the user...
+ set_askpass user@host pass@host &&
+ test_must_fail git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
+ expect_askpass none &&
+
+ # ...but now we should have forgotten the bad value, causing
+ # us to prompt the user again.
+ set_askpass user@host pass@host &&
+ git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
+ expect_askpass both user@host
+'
+
test_done
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 9866b1b573..1537aa2179 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -117,6 +117,25 @@ test_expect_success '%(color) must fail' '
test_must_fail git for-each-ref --format="%(color)%(refname)"
'
+test_expect_success '%(color:#aa22ac) must succeed' '
+ test_when_finished rm -rf test &&
+ git init test &&
+ (
+ cd test &&
+ test_commit initial &&
+ git branch -M main &&
+ cat >expect <<-\EOF &&
+ refs/heads/main
+ refs/tags/initial
+ EOF
+ git remote add origin nowhere &&
+ git config branch.main.remote origin &&
+ git config branch.main.merge refs/heads/main &&
+ git for-each-ref --format="%(color:#aa22ac)%(refname)" >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'left alignment is default' '
cat >expect <<-\EOF &&
refname is refs/heads/main |refs/heads/main
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index accefde72f..a0c123b0a7 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -57,6 +57,20 @@ iuc () {
return $ret
}
+get_relevant_traces () {
+ # From the GIT_TRACE2_PERF data of the form
+ # $TIME $FILE:$LINE | d0 | main | data | r1 | ? | ? | read_directo | $RELEVANT_STAT
+ # extract the $RELEVANT_STAT fields. We don't care about region_enter
+ # or region_leave, or stats for things outside read_directory.
+ INPUT_FILE=$1
+ OUTPUT_FILE=$2
+ grep data.*read_directo $INPUT_FILE |
+ cut -d "|" -f 9 |
+ grep -v visited \
+ >"$OUTPUT_FILE"
+}
+
+
test_lazy_prereq UNTRACKED_CACHE '
{ git update-index --test-untracked-cache; ret=$?; } &&
test $ret -ne 1
@@ -129,19 +143,21 @@ EOF
test_expect_success 'status first time (empty cache)' '
avoid_racy &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 3
-gitignore invalidation: 1
-directory invalidation: 0
-opendir: 4
+ ....path:
+ ....node-creation:3
+ ....gitignore-invalidation:1
+ ....directory-invalidation:0
+ ....opendir:4
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'untracked cache after first status' '
@@ -151,19 +167,21 @@ test_expect_success 'untracked cache after first status' '
test_expect_success 'status second time (fully populated cache)' '
avoid_racy &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 0
-directory invalidation: 0
-opendir: 0
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:0
+ ....directory-invalidation:0
+ ....opendir:0
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'untracked cache after second status' '
@@ -174,8 +192,8 @@ test_expect_success 'untracked cache after second status' '
test_expect_success 'modify in root directory, one dir invalidation' '
avoid_racy &&
: >four &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -189,13 +207,15 @@ A two
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 0
-directory invalidation: 1
-opendir: 1
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:0
+ ....directory-invalidation:1
+ ....opendir:1
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
@@ -223,8 +243,8 @@ EOF
test_expect_success 'new .gitignore invalidates recursively' '
avoid_racy &&
echo four >.gitignore &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -238,13 +258,15 @@ A two
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 1
-directory invalidation: 1
-opendir: 4
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:1
+ ....directory-invalidation:1
+ ....opendir:4
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
@@ -272,8 +294,8 @@ EOF
test_expect_success 'new info/exclude invalidates everything' '
avoid_racy &&
echo three >>.git/info/exclude &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -285,13 +307,15 @@ A two
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 1
-directory invalidation: 0
-opendir: 4
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:1
+ ....directory-invalidation:0
+ ....opendir:4
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'verify untracked cache dump' '
@@ -330,8 +354,8 @@ EOF
'
test_expect_success 'status after the move' '
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -343,13 +367,15 @@ A one
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 0
-directory invalidation: 0
-opendir: 1
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:0
+ ....directory-invalidation:0
+ ....opendir:1
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'verify untracked cache dump' '
@@ -389,8 +415,8 @@ EOF
'
test_expect_success 'status after the move' '
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -402,13 +428,15 @@ A two
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 0
-directory invalidation: 0
-opendir: 1
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:0
+ ....directory-invalidation:0
+ ....opendir:1
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'verify untracked cache dump' '
@@ -438,8 +466,8 @@ test_expect_success 'set up for sparse checkout testing' '
'
test_expect_success 'status after commit' '
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -448,13 +476,15 @@ test_expect_success 'status after commit' '
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 0
-directory invalidation: 0
-opendir: 2
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:0
+ ....directory-invalidation:0
+ ....opendir:2
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'untracked cache correct after commit' '
@@ -496,9 +526,9 @@ test_expect_success 'create/modify files, some of which are gitignored' '
'
test_expect_success 'test sparse status with untracked cache' '
- : >../trace &&
+ : >../trace.output &&
avoid_racy &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../status.actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -509,13 +539,15 @@ test_expect_success 'test sparse status with untracked cache' '
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../status.actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 1
-directory invalidation: 2
-opendir: 2
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:1
+ ....directory-invalidation:2
+ ....opendir:2
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'untracked cache correct after status' '
@@ -539,8 +571,8 @@ EOF
test_expect_success 'test sparse status again with untracked cache' '
avoid_racy &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../status.actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -551,13 +583,15 @@ test_expect_success 'test sparse status again with untracked cache' '
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../status.actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 0
-directory invalidation: 0
-opendir: 0
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:0
+ ....directory-invalidation:0
+ ....opendir:0
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'set up for test of subdir and sparse checkouts' '
@@ -568,8 +602,8 @@ test_expect_success 'set up for test of subdir and sparse checkouts' '
test_expect_success 'test sparse status with untracked cache and subdir' '
avoid_racy &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../status.actual &&
iuc status --porcelain >../status.iuc &&
cat >../status.expect <<EOF &&
@@ -581,13 +615,15 @@ test_expect_success 'test sparse status with untracked cache and subdir' '
EOF
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../status.actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 2
-gitignore invalidation: 0
-directory invalidation: 1
-opendir: 3
+ ....path:
+ ....node-creation:2
+ ....gitignore-invalidation:0
+ ....directory-invalidation:1
+ ....opendir:3
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
@@ -616,19 +652,21 @@ EOF
test_expect_success 'test sparse status again with untracked cache and subdir' '
avoid_racy &&
- : >../trace &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ : >../trace.output &&
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
git status --porcelain >../status.actual &&
iuc status --porcelain >../status.iuc &&
test_cmp ../status.expect ../status.iuc &&
test_cmp ../status.expect ../status.actual &&
+ get_relevant_traces ../trace.output ../trace.relevant &&
cat >../trace.expect <<EOF &&
-node creation: 0
-gitignore invalidation: 0
-directory invalidation: 0
-opendir: 0
+ ....path:
+ ....node-creation:0
+ ....gitignore-invalidation:0
+ ....directory-invalidation:0
+ ....opendir:0
EOF
- test_cmp ../trace.expect ../trace
+ test_cmp ../trace.expect ../trace.relevant
'
test_expect_success 'move entry in subdir from untracked to cached' '
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index a74816ca8b..0399701e62 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -746,4 +746,46 @@ test_expect_success 'clean untracked paths by pathspec' '
test_must_be_empty actual
'
+test_expect_success 'avoid traversing into ignored directories' '
+ test_when_finished rm -f output error trace.* &&
+ test_create_repo avoid-traversing-deep-hierarchy &&
+ (
+ cd avoid-traversing-deep-hierarchy &&
+
+ mkdir -p untracked/subdir/with/a &&
+ >untracked/subdir/with/a/random-file.txt &&
+
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
+ git clean -ffdxn -e untracked
+ ) &&
+
+ # Make sure we only visited into the top-level directory, and did
+ # not traverse into the "untracked" subdirectory since it was excluded
+ grep data.*read_directo.*directories-visited trace.output |
+ cut -d "|" -f 9 >trace.relevant &&
+ cat >trace.expect <<-EOF &&
+ ..directories-visited:1
+ EOF
+ test_cmp trace.expect trace.relevant
+'
+
+test_expect_success 'traverse into directories that may have ignored entries' '
+ test_when_finished rm -f output &&
+ test_create_repo need-to-traverse-into-hierarchy &&
+ (
+ cd need-to-traverse-into-hierarchy &&
+ mkdir -p modules/foobar/src/generated &&
+ > modules/foobar/src/generated/code.c &&
+ > modules/foobar/Makefile &&
+ echo "/modules/**/src/generated/" >.gitignore &&
+
+ git clean -fX modules/foobar >../output &&
+
+ grep Removing ../output &&
+
+ test_path_is_missing modules/foobar/src/generated/code.c &&
+ test_path_is_file modules/foobar/Makefile
+ )
+'
+
test_done
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 9092db5fdc..7d02f79c0d 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -413,7 +413,7 @@ test_expect_success 'amend! commit allows empty commit msg body with --allow-emp
'
test_fixup_reword_opt () {
- test_expect_success C_LOCALE_OUTPUT "--fixup=reword: incompatible with $1" "
+ test_expect_success "--fixup=reword: incompatible with $1" "
echo 'fatal: reword option of --fixup is mutually exclusive with'\
'--patch/--interactive/--all/--include/--only' >expect &&
test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index 45d025f960..637391c6ce 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -334,7 +334,7 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR'
git config core.fsmonitor .git/hooks/fsmonitor-test &&
git update-index --untracked-cache &&
git update-index --fsmonitor &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-before" \
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace-before" \
git status &&
test-tool dump-untracked-cache >../before
) &&
@@ -346,12 +346,12 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR'
EOF
(
cd dot-git &&
- GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-after" \
+ GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace-after" \
git status &&
test-tool dump-untracked-cache >../after
) &&
- grep "directory invalidation" trace-before >>before &&
- grep "directory invalidation" trace-after >>after &&
+ grep "directory-invalidation" trace-before | cut -d"|" -f 9 >>before &&
+ grep "directory-invalidation" trace-after | cut -d"|" -f 9 >>after &&
# UNTR extension unchanged, dir invalidation count unchanged
test_cmp before after
'
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 65b3035371..3b7540050c 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -539,7 +539,7 @@ test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
test_path_is_file my-hooks.ran &&
cat >expect <<-EOF &&
fatal: longline.patch: rejected by sendemail-validate hook
- fatal: command '"'"'$(pwd)/my-hooks/sendemail-validate'"'"' died with exit code 1
+ fatal: command '"'"'my-hooks/sendemail-validate'"'"' died with exit code 1
warning: no patches were sent
EOF
test_cmp expect actual
@@ -644,14 +644,33 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
test_cmp expect actual
'
+test_set_editor "$(pwd)/fake-editor"
+
+test_expect_success $PREREQ 'setup erroring fake editor' '
+ write_script fake-editor <<-\EOF
+ echo >&2 "I am about to error"
+ exit 1
+ EOF
+'
+
+test_expect_success $PREREQ 'fake editor dies with error' '
+ clean_fake_sendmail &&
+ test_must_fail git send-email \
+ --compose --subject foo \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches 2>err &&
+ grep "I am about to error" err &&
+ grep "the editor exited uncleanly, aborting everything" err
+'
+
test_expect_success $PREREQ 'setup fake editor' '
write_script fake-editor <<-\EOF
echo fake edit >>"$1"
EOF
'
-test_set_editor "$(pwd)/fake-editor"
-
test_expect_success $PREREQ '--compose works' '
clean_fake_sendmail &&
git send-email \
diff --git a/t/test-lib.sh b/t/test-lib.sh
index adaa2db601..adaf03543e 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -947,8 +947,11 @@ test_run_ () {
trace=
# 117 is magic because it is unlikely to match the exit
# code of other programs
- if $(printf '%s\n' "$1" | sed -f "$GIT_BUILD_DIR/t/chainlint.sed" | grep -q '?![A-Z][A-Z]*?!') ||
- test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)"
+ if test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)" ||
+ {
+ test "${GIT_TEST_CHAIN_LINT_HARDER:-${GIT_TEST_CHAIN_LINT_HARDER_DEFAULT:-1}}" != 0 &&
+ $(printf '%s\n' "$1" | sed -f "$GIT_BUILD_DIR/t/chainlint.sed" | grep -q '?![A-Z][A-Z]*?!')
+ }
then
BUG "broken &&-chain or run-away HERE-DOC: $1"
fi
diff --git a/worktree.c b/worktree.c
index f35ac40a84..237517baee 100644
--- a/worktree.c
+++ b/worktree.c
@@ -128,10 +128,8 @@ struct worktree **get_worktrees(void)
dir = opendir(path.buf);
strbuf_release(&path);
if (dir) {
- while ((d = readdir(dir)) != NULL) {
+ while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
struct worktree *linked = NULL;
- if (is_dot_or_dotdot(d->d_name))
- continue;
if ((linked = get_linked_worktree(d->d_name))) {
ALLOC_GROW(list, counter + 1, alloc);
@@ -486,13 +484,9 @@ int submodule_uses_worktrees(const char *path)
if (!dir)
return 0;
- while ((d = readdir(dir)) != NULL) {
- if (is_dot_or_dotdot(d->d_name))
- continue;
-
+ d = readdir_skip_dot_and_dotdot(dir);
+ if (d != NULL)
ret = 1;
- break;
- }
closedir(dir);
return ret;
}
diff --git a/write-or-die.c b/write-or-die.c
index eab8c8d0b9..d33e68f6ab 100644
--- a/write-or-die.c
+++ b/write-or-die.c
@@ -57,8 +57,9 @@ void fprintf_or_die(FILE *f, const char *fmt, ...)
void fsync_or_die(int fd, const char *msg)
{
- if (fsync(fd) < 0) {
- die_errno("fsync error on '%s'", msg);
+ while (fsync(fd) < 0) {
+ if (errno != EINTR)
+ die_errno("fsync error on '%s'", msg);
}
}