summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.24.0.txt27
-rw-r--r--Documentation/config/format.txt2
-rw-r--r--Documentation/git-format-patch.txt3
-rw-r--r--Documentation/git-stash.txt5
-rw-r--r--Documentation/gitremote-helpers.txt5
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile3
-rw-r--r--azure-pipelines.yml4
-rw-r--r--builtin/grep.c1
-rw-r--r--builtin/log.c16
-rw-r--r--builtin/stash.c2
-rwxr-xr-xci/install-dependencies.sh5
-rw-r--r--column.c13
-rw-r--r--compat/win32/pthread.h2
-rw-r--r--contrib/completion/git-completion.zsh5
-rw-r--r--contrib/diff-highlight/DiffHighlight.pm2
-rw-r--r--fsmonitor.c29
-rw-r--r--git-compat-util.h2
-rwxr-xr-xgit-legacy-stash.sh2
-rw-r--r--grep.c47
-rw-r--r--grep.h2
-rw-r--r--http-push.c8
-rw-r--r--remote-curl.c35
-rw-r--r--repo-settings.c2
-rw-r--r--t/helper/test-progress.c2
-rwxr-xr-xt/t1308-config-set.sh8
-rwxr-xr-xt/t1600-index.sh4
-rwxr-xr-xt/t3906-stash-submodule.sh42
-rwxr-xr-xt/t4014-format-patch.sh26
-rw-r--r--t/t4018/dts-nodes-boolean-prop9
-rw-r--r--t/t4018/dts-nodes-multiline-prop13
-rw-r--r--t/t4018/dts-root2
-rw-r--r--t/t4018/dts-root-comment8
-rwxr-xr-xt/t5541-http-push-smart.sh40
-rwxr-xr-xt/t7419-submodule-set-branch.sh6
-rwxr-xr-xt/t7519-status-fsmonitor.sh17
-rwxr-xr-xt/t7519/fsmonitor-env24
-rw-r--r--transport-helper.c4
-rw-r--r--transport.h3
-rw-r--r--userdiff.c3
-rw-r--r--utf8.c6
41 files changed, 370 insertions, 71 deletions
diff --git a/Documentation/RelNotes/2.24.0.txt b/Documentation/RelNotes/2.24.0.txt
index 22de0bc497..125169d0da 100644
--- a/Documentation/RelNotes/2.24.0.txt
+++ b/Documentation/RelNotes/2.24.0.txt
@@ -75,6 +75,9 @@ UI, Workflows & Features
submodules, but this did not apply to "git fetch --multiple" that
fetches from multiple remote repositories. It now does.
+ * The installation instruction for zsh completion script (in
+ contrib/) has been a bit improved.
+
Performance, Internal Implementation, Development Support etc.
@@ -327,6 +330,20 @@ Fixes since v2.23
corrected.
(merge 2b6a9b13ca tg/range-diff-output-update later to maint).
+ * Dev support update.
+ (merge 4f3c1dc5d6 dl/allow-running-cocci-verbosely later to maint).
+
+ * "git format-patch -o <outdir>" did an equivalent of "mkdir <outdir>"
+ not "mkdir -p <outdir>", which was corrected.
+
+ * "git stash save" lost local changes to submodules, which has been
+ corrected.
+ (merge 556895d0c8 jj/stash-reset-only-toplevel later to maint).
+
+ * The atomic push over smart HTTP transport did not work, which has
+ been corrected.
+ (merge 6f1194246a bc/smart-http-atomic-push later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge d1387d3895 en/fast-import-merge-doc later to maint).
(merge 1c24a54ea4 bm/repository-layout-typofix later to maint).
@@ -368,3 +385,13 @@ Fixes since v2.23
(merge d928a8388a am/t0028-utf16-tests later to maint).
(merge b05b40930e dl/t0000-skip-test-test later to maint).
(merge 03d3b1297c js/xdiffi-comment-updates later to maint).
+ (merge 57d8f4b4c7 js/doc-stash-save later to maint).
+ (merge 8c1cfd58e3 ta/t1308-typofix later to maint).
+ (merge fa364ad790 bb/utf8-wcwidth-cleanup later to maint).
+ (merge 68b69211b2 bb/compat-util-comment-fix later to maint).
+ (merge 5cc6a4be11 rs/http-push-simplify later to maint).
+ (merge a81e42d235 rs/column-use-utf8-strnwidth later to maint).
+ (merge 062a309d36 rs/remote-curl-use-argv-array later to maint).
+ (merge 3b3c79f6c9 nr/diff-highlight-indent-fix later to maint).
+ (merge 3444ec2eb2 wb/fsmonitor-bitmap-fix later to maint).
+ (merge 10da030ab7 cb/pcre2-chartables-leakfix later to maint).
diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index cb629fa769..40cad9278f 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -81,7 +81,7 @@ format.coverLetter::
format.outputDirectory::
Set a custom directory to store the resulting files instead of the
- current working directory.
+ current working directory. All directory components will be created.
format.useAutoBase::
A boolean value which lets you enable the `--base=auto` option of
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 0ac56f4b70..2035d4d5d5 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -66,7 +66,8 @@ they are created in the current working directory. The default path
can be set with the `format.outputDirectory` configuration option.
The `-o` option takes precedence over `format.outputDirectory`.
To store patches in the current working directory even when
-`format.outputDirectory` points elsewhere, use `-o .`.
+`format.outputDirectory` points elsewhere, use `-o .`. All directory
+components will be created.
By default, the subject of a single patch is "[PATCH] " followed by
the concatenation of lines from the commit message up to the first blank
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 8fbe12c66c..53e1a1205d 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -87,8 +87,9 @@ The `--patch` option implies `--keep-index`. You can use
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
This option is deprecated in favour of 'git stash push'. It
- differs from "stash push" in that it cannot take pathspecs,
- and any non-option arguments form the message.
+ differs from "stash push" in that it cannot take pathspecs.
+ Instead, all non-option arguments are concatenated to form the stash
+ message.
list [<options>]::
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
index a5c3c04371..f48a031dc3 100644
--- a/Documentation/gitremote-helpers.txt
+++ b/Documentation/gitremote-helpers.txt
@@ -509,6 +509,11 @@ set by Git if the remote helper has the 'option' capability.
Indicate that only the objects wanted need to be fetched, not
their dependents.
+'option atomic' {'true'|'false'}::
+ When pushing, request the remote server to update refs in a single atomic
+ transaction. If successful, all refs will be updated, or none will. If the
+ remote side does not support this capability, the push will fail.
+
SEE ALSO
--------
linkgit:git-remote[1]
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 98f88a28d3..64543ede28 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.23.GIT
+DEF_VER=v2.24.0-rc0
LF='
'
diff --git a/Makefile b/Makefile
index de60c8e7aa..58b92af54b 100644
--- a/Makefile
+++ b/Makefile
@@ -1885,6 +1885,7 @@ ifndef V
QUIET_SP = @echo ' ' SP $<;
QUIET_HDR = @echo ' ' HDR $(<:hcc=h);
QUIET_RC = @echo ' ' RC $@;
+ QUIET_SPATCH = @echo ' ' SPATCH $<;
QUIET_SUBDIR0 = +@subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
$(MAKE) $(PRINT_DIR) -C $$subdir
@@ -2813,7 +2814,7 @@ FOUND_C_SOURCES = $(filter %.c,$(shell $(FIND_SOURCE_FILES)))
COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
%.cocci.patch: %.cocci $(COCCI_SOURCES)
- @echo ' ' SPATCH $<; \
+ $(QUIET_SPATCH) \
if test $(SPATCH_BATCH_SIZE) = 0; then \
limit=; \
else \
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 9f099b9529..af2a5ea484 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -157,7 +157,7 @@ jobs:
displayName: 'Download git-sdk-64-minimal'
- powershell: |
& git-sdk-64-minimal\usr\bin\bash.exe -lc @"
- make vcxproj
+ make NDEBUG=1 DEVELOPER=1 vcxproj
"@
if (!$?) { exit(1) }
displayName: Generate Visual Studio Solution
@@ -255,7 +255,7 @@ jobs:
cd t &&
PATH=\"`$PWD/helper:`$PATH\" &&
- test-tool.exe run-command testsuite -V -x --write-junit-xml \
+ test-tool.exe run-command testsuite --jobs=10 -V -x --write-junit-xml \
`$(test-tool.exe path-utils slice-tests \
`$SYSTEM_JOBPOSITIONINPHASE `$SYSTEM_TOTALJOBSINPHASE t[0-9]*.sh)
"@
diff --git a/builtin/grep.c b/builtin/grep.c
index 69ac053acc..50ce8d9461 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1147,5 +1147,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
run_pager(&opt, prefix);
clear_pathspec(&pathspec);
free_grep_patterns(&opt);
+ grep_destroy();
return !hit;
}
diff --git a/builtin/log.c b/builtin/log.c
index c4b35fdaf9..89873d2dc2 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1766,10 +1766,26 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
setup_pager();
if (output_directory) {
+ int saved;
if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
rev.diffopt.use_color = GIT_COLOR_NEVER;
if (use_stdout)
die(_("standard output, or directory, which one?"));
+ /*
+ * We consider <outdir> as 'outside of gitdir', therefore avoid
+ * applying adjust_shared_perm in s-c-l-d.
+ */
+ saved = get_shared_repository();
+ set_shared_repository(0);
+ switch (safe_create_leading_directories_const(output_directory)) {
+ case SCLD_OK:
+ case SCLD_EXISTS:
+ break;
+ default:
+ die(_("could not create leading directories "
+ "of '%s'"), output_directory);
+ }
+ set_shared_repository(saved);
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
die_errno(_("could not create directory '%s'"),
output_directory);
diff --git a/builtin/stash.c b/builtin/stash.c
index bb4f6d8d76..4e806176b0 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1392,7 +1392,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
argv_array_pushl(&cp.args, "reset", "--hard", "-q",
- NULL);
+ "--no-recurse-submodules", NULL);
if (run_command(&cp)) {
ret = -1;
goto done;
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index b54ccb4b52..4e64a19112 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -40,6 +40,11 @@ osx-clang|osx-gcc)
test -z "$BREW_INSTALL_PACKAGES" ||
brew install $BREW_INSTALL_PACKAGES
brew link --force gettext
+ brew cask install perforce || {
+ # Update the definitions and try again
+ git -C "$(brew --repository)"/Library/Taps/homebrew/homebrew-cask pull &&
+ brew cask install perforce
+ } ||
brew install caskroom/cask/perforce
case "$jobname" in
osx-gcc)
diff --git a/column.c b/column.c
index 7a17c14b82..4a38eed322 100644
--- a/column.c
+++ b/column.c
@@ -23,18 +23,7 @@ struct column_data {
/* return length of 's' in letters, ANSI escapes stripped */
static int item_length(const char *s)
{
- int len, i = 0;
- struct strbuf str = STRBUF_INIT;
-
- strbuf_addstr(&str, s);
- while ((s = strstr(str.buf + i, "\033[")) != NULL) {
- int len = strspn(s + 2, "0123456789;");
- i = s - str.buf;
- strbuf_remove(&str, i, len + 3); /* \033[<len><func char> */
- }
- len = utf8_strwidth(str.buf);
- strbuf_release(&str);
- return len;
+ return utf8_strnwidth(s, -1, 1);
}
/*
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
index f1cfe73de9..737983d00b 100644
--- a/compat/win32/pthread.h
+++ b/compat/win32/pthread.h
@@ -51,7 +51,7 @@ typedef struct {
} pthread_t;
int pthread_create(pthread_t *thread, const void *unused,
- void *(*start_routine)(void*), void *arg);
+ void *(*start_routine)(void*), void *arg);
/*
* To avoid the need of copying a struct, we use small macro wrapper to pass
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index 886bf95d1f..eef4eff53d 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -11,8 +11,9 @@
#
# zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh
#
-# The recommended way to install this script is to copy to '~/.zsh/_git', and
-# then add the following to your ~/.zshrc file:
+# The recommended way to install this script is to make a copy of it in
+# ~/.zsh/ directory as ~/.zsh/git-completion.zsh and then add the following
+# to your ~/.zshrc file:
#
# fpath=(~/.zsh $fpath)
diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm
index 7440aa1c46..e2589922a6 100644
--- a/contrib/diff-highlight/DiffHighlight.pm
+++ b/contrib/diff-highlight/DiffHighlight.pm
@@ -72,7 +72,7 @@ sub handle_line {
(?:$COLOR?\|$COLOR?[ ])* # zero or more trailing "|"
[ ]* # trailing whitespace for merges
/x) {
- my $graph_prefix = $&;
+ my $graph_prefix = $&;
# We must flush before setting graph indent, since the
# new commit may be indented differently from what we
diff --git a/fsmonitor.c b/fsmonitor.c
index 231e83a94d..1f4aa1b150 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c
@@ -14,8 +14,13 @@ struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
static void fsmonitor_ewah_callback(size_t pos, void *is)
{
struct index_state *istate = (struct index_state *)is;
- struct cache_entry *ce = istate->cache[pos];
+ struct cache_entry *ce;
+ if (pos >= istate->cache_nr)
+ BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" >= %u)",
+ (uintmax_t)pos, istate->cache_nr);
+
+ ce = istate->cache[pos];
ce->ce_flags &= ~CE_FSMONITOR_VALID;
}
@@ -50,17 +55,24 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data,
}
istate->fsmonitor_dirty = fsmonitor_dirty;
+ if (istate->fsmonitor_dirty->bit_size > istate->cache_nr)
+ BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
+ (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
+
trace_printf_key(&trace_fsmonitor, "read fsmonitor extension successful");
return 0;
}
void fill_fsmonitor_bitmap(struct index_state *istate)
{
- unsigned int i;
+ unsigned int i, skipped = 0;
istate->fsmonitor_dirty = ewah_new();
- for (i = 0; i < istate->cache_nr; i++)
- if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
- ewah_set(istate->fsmonitor_dirty, i);
+ for (i = 0; i < istate->cache_nr; i++) {
+ if (istate->cache[i]->ce_flags & CE_REMOVE)
+ skipped++;
+ else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
+ ewah_set(istate->fsmonitor_dirty, i - skipped);
+ }
}
void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
@@ -71,6 +83,10 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
uint32_t ewah_size = 0;
int fixup = 0;
+ if (istate->fsmonitor_dirty->bit_size > istate->cache_nr)
+ BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
+ (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
+
put_be32(&hdr_version, INDEX_EXTENSION_VERSION);
strbuf_add(sb, &hdr_version, sizeof(uint32_t));
@@ -236,6 +252,9 @@ void tweak_fsmonitor(struct index_state *istate)
}
/* Mark all previously saved entries as dirty */
+ if (istate->fsmonitor_dirty->bit_size > istate->cache_nr)
+ BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
+ (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);
/* Now mark the untracked cache for fsmonitor usage */
diff --git a/git-compat-util.h b/git-compat-util.h
index 8b8b29a867..607dca7534 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -77,7 +77,7 @@
#endif
/*
* ARRAY_SIZE - get the number of elements in a visible array
- * <at> x: the array whose size you want.
+ * @x: the array whose size you want.
*
* This does not work on pointers, or arrays declared as [], or
* function parameters. With correct compiler support, such usage
diff --git a/git-legacy-stash.sh b/git-legacy-stash.sh
index f60e9b3e87..07ad4a5459 100755
--- a/git-legacy-stash.sh
+++ b/git-legacy-stash.sh
@@ -370,7 +370,7 @@ push_stash () {
git diff-index -p --cached --binary HEAD -- "$@" |
git apply --index -R
else
- git reset --hard -q
+ git reset --hard -q --no-recurse-submodules
fi
if test "$keep_index" = "t" && test -n "$i_tree"
diff --git a/grep.c b/grep.c
index 0bb4cbd3d8..b7ae5a442a 100644
--- a/grep.c
+++ b/grep.c
@@ -16,6 +16,20 @@ static int grep_source_is_binary(struct grep_source *gs,
static struct grep_opt grep_defaults;
+#ifdef USE_LIBPCRE2
+static pcre2_general_context *pcre2_global_context;
+
+static void *pcre2_malloc(PCRE2_SIZE size, MAYBE_UNUSED void *memory_data)
+{
+ return malloc(size);
+}
+
+static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data)
+{
+ return free(pointer);
+}
+#endif
+
static const char *color_grep_slots[] = {
[GREP_COLOR_CONTEXT] = "context",
[GREP_COLOR_FILENAME] = "filename",
@@ -150,12 +164,28 @@ int grep_config(const char *var, const char *value, void *cb)
* Initialize one instance of grep_opt and copy the
* default values from the template we read the configuration
* information in an earlier call to git_config(grep_config).
+ *
+ * If using PCRE, make sure that the library is configured
+ * to use the same allocator as Git (e.g. nedmalloc on Windows).
+ *
+ * Any allocated memory needs to be released in grep_destroy().
*/
void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix)
{
struct grep_opt *def = &grep_defaults;
int i;
+#if defined(USE_LIBPCRE2)
+ if (!pcre2_global_context)
+ pcre2_global_context = pcre2_general_context_create(
+ pcre2_malloc, pcre2_free, NULL);
+#endif
+
+#ifdef USE_LIBPCRE1
+ pcre_malloc = malloc;
+ pcre_free = free;
+#endif
+
memset(opt, 0, sizeof(*opt));
opt->repo = repo;
opt->prefix = prefix;
@@ -178,6 +208,13 @@ void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix
color_set(opt->colors[i], def->colors[i]);
}
+void grep_destroy(void)
+{
+#ifdef USE_LIBPCRE2
+ pcre2_general_context_free(pcre2_global_context);
+#endif
+}
+
static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt)
{
/*
@@ -461,7 +498,6 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
PCRE2_UCHAR errbuf[256];
PCRE2_SIZE erroffset;
int options = PCRE2_MULTILINE;
- const uint8_t *character_tables = NULL;
int jitret;
int patinforet;
size_t jitsizearg;
@@ -470,11 +506,15 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
p->pcre2_compile_context = NULL;
+ /* pcre2_global_context is initialized in append_grep_pattern */
if (opt->ignore_case) {
if (!opt->ignore_locale && has_non_ascii(p->pattern)) {
- character_tables = pcre2_maketables(NULL);
+ if (!pcre2_global_context)
+ BUG("pcre2_global_context uninitialized");
+ p->pcre2_tables = pcre2_maketables(pcre2_global_context);
p->pcre2_compile_context = pcre2_compile_context_create(NULL);
- pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
+ pcre2_set_character_tables(p->pcre2_compile_context,
+ p->pcre2_tables);
}
options |= PCRE2_CASELESS;
}
@@ -571,6 +611,7 @@ static void free_pcre2_pattern(struct grep_pat *p)
pcre2_compile_context_free(p->pcre2_compile_context);
pcre2_code_free(p->pcre2_pattern);
pcre2_match_data_free(p->pcre2_match_data);
+ free((void *)p->pcre2_tables);
}
#else /* !USE_LIBPCRE2 */
static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
diff --git a/grep.h b/grep.h
index 05dc1bb98e..811fd274c9 100644
--- a/grep.h
+++ b/grep.h
@@ -78,6 +78,7 @@ struct grep_pat {
pcre2_code *pcre2_pattern;
pcre2_match_data *pcre2_match_data;
pcre2_compile_context *pcre2_compile_context;
+ const uint8_t *pcre2_tables;
uint32_t pcre2_jit_on;
unsigned fixed:1;
unsigned is_fixed:1;
@@ -172,6 +173,7 @@ struct grep_opt {
void init_grep_defaults(struct repository *);
int grep_config(const char *var, const char *value, void *);
void grep_init(struct grep_opt *, struct repository *repo, const char *prefix);
+void grep_destroy(void);
void grep_commit_pattern_type(enum grep_pattern_type, struct grep_opt *opt);
void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);
diff --git a/http-push.c b/http-push.c
index 0353f9f514..822f326599 100644
--- a/http-push.c
+++ b/http-push.c
@@ -501,10 +501,10 @@ static void release_request(struct transfer_request *request)
if (request == request_queue_head) {
request_queue_head = request->next;
} else {
- while (entry->next != NULL && entry->next != request)
+ while (entry && entry->next != request)
entry = entry->next;
- if (entry->next == request)
- entry->next = entry->next->next;
+ if (entry)
+ entry->next = request->next;
}
free(request->url);
@@ -981,7 +981,7 @@ static int unlock_remote(struct remote_lock *lock)
while (prev && prev->next != lock)
prev = prev->next;
if (prev)
- prev->next = prev->next->next;
+ prev->next = lock->next;
}
free(lock->owner);
diff --git a/remote-curl.c b/remote-curl.c
index 051f26629d..350d92a074 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -40,7 +40,8 @@ struct options {
push_cert : 2,
deepen_relative : 1,
from_promisor : 1,
- no_dependents : 1;
+ no_dependents : 1,
+ atomic : 1;
};
static struct options options;
static struct string_list cas_options = STRING_LIST_INIT_DUP;
@@ -148,6 +149,14 @@ static int set_option(const char *name, const char *value)
else
return -1;
return 0;
+ } else if (!strcmp(name, "atomic")) {
+ if (!strcmp(value, "true"))
+ options.atomic = 1;
+ else if (!strcmp(value, "false"))
+ options.atomic = 0;
+ else
+ return -1;
+ return 0;
} else if (!strcmp(name, "push-option")) {
if (*value != '"')
string_list_append(&options.push_options, value);
@@ -1154,7 +1163,7 @@ static void parse_fetch(struct strbuf *buf)
strbuf_reset(buf);
}
-static int push_dav(int nr_spec, char **specs)
+static int push_dav(int nr_spec, const char **specs)
{
struct child_process child = CHILD_PROCESS_INIT;
size_t i;
@@ -1175,7 +1184,7 @@ static int push_dav(int nr_spec, char **specs)
return 0;
}
-static int push_git(struct discovery *heads, int nr_spec, char **specs)
+static int push_git(struct discovery *heads, int nr_spec, const char **specs)
{
struct rpc_state rpc;
int i, err;
@@ -1196,6 +1205,8 @@ static int push_git(struct discovery *heads, int nr_spec, char **specs)
argv_array_push(&args, "--signed=yes");
else if (options.push_cert == SEND_PACK_PUSH_CERT_IF_ASKED)
argv_array_push(&args, "--signed=if-asked");
+ if (options.atomic)
+ argv_array_push(&args, "--atomic");
if (options.verbosity == 0)
argv_array_push(&args, "--quiet");
else if (options.verbosity > 1)
@@ -1225,7 +1236,7 @@ static int push_git(struct discovery *heads, int nr_spec, char **specs)
return err;
}
-static int push(int nr_spec, char **specs)
+static int push(int nr_spec, const char **specs)
{
struct discovery *heads = discover_refs("git-receive-pack", 1);
int ret;
@@ -1240,14 +1251,12 @@ static int push(int nr_spec, char **specs)
static void parse_push(struct strbuf *buf)
{
- char **specs = NULL;
- int alloc_spec = 0, nr_spec = 0, i, ret;
+ struct argv_array specs = ARGV_ARRAY_INIT;
+ int ret;
do {
- if (starts_with(buf->buf, "push ")) {
- ALLOC_GROW(specs, nr_spec + 1, alloc_spec);
- specs[nr_spec++] = xstrdup(buf->buf + 5);
- }
+ if (starts_with(buf->buf, "push "))
+ argv_array_push(&specs, buf->buf + 5);
else
die(_("http transport does not support %s"), buf->buf);
@@ -1258,7 +1267,7 @@ static void parse_push(struct strbuf *buf)
break;
} while (1);
- ret = push(nr_spec, specs);
+ ret = push(specs.argc, specs.argv);
printf("\n");
fflush(stdout);
@@ -1266,9 +1275,7 @@ static void parse_push(struct strbuf *buf)
exit(128); /* error already reported */
free_specs:
- for (i = 0; i < nr_spec; i++)
- free(specs[i]);
- free(specs);
+ argv_array_clear(&specs);
}
static int stateless_connect(const char *service_name)
diff --git a/repo-settings.c b/repo-settings.c
index 05546db98e..a703e407a3 100644
--- a/repo-settings.c
+++ b/repo-settings.c
@@ -22,7 +22,7 @@ void prepare_repo_settings(struct repository *r)
UPDATE_DEFAULT_BOOL(r->settings.core_commit_graph, 1);
UPDATE_DEFAULT_BOOL(r->settings.gc_write_commit_graph, 1);
- if (!repo_config_get_bool(r, "index.version", &value))
+ if (!repo_config_get_int(r, "index.version", &value))
r->settings.index_version = value;
if (!repo_config_get_maybe_bool(r, "core.untrackedcache", &value)) {
if (value == 0)
diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c
index 4e9f7fafdf..42b96cb103 100644
--- a/t/helper/test-progress.c
+++ b/t/helper/test-progress.c
@@ -29,7 +29,7 @@ void progress_test_force_update(void);
int cmd__progress(int argc, const char **argv)
{
- uint64_t total = 0;
+ int total = 0;
const char *title;
struct strbuf line = STRBUF_INIT;
struct progress *progress;
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index d0a2727b85..7b4e1a63eb 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -166,14 +166,14 @@ test_expect_success 'find value with highest priority from a configset' '
'
test_expect_success 'find value_list for a key from a configset' '
- cat >except <<-\EOF &&
+ cat >expect <<-\EOF &&
+ lama
+ ball
sam
bat
hask
- lama
- ball
EOF
- test-tool config configset_get_value case.baz config2 .git/config >actual &&
+ test-tool config configset_get_value_multi case.baz config2 .git/config >actual &&
test_cmp expect actual
'
diff --git a/t/t1600-index.sh b/t/t1600-index.sh
index c77721b580..b7c31aa86a 100755
--- a/t/t1600-index.sh
+++ b/t/t1600-index.sh
@@ -87,6 +87,10 @@ test_index_version () {
}
test_expect_success 'index version config precedence' '
+ test_index_version 0 false 0 2 &&
+ test_index_version 2 false 0 2 &&
+ test_index_version 3 false 0 2 &&
+ test_index_version 4 false 0 4 &&
test_index_version 2 false 4 4 &&
test_index_version 2 true 0 2 &&
test_index_version 0 true 0 4 &&
diff --git a/t/t3906-stash-submodule.sh b/t/t3906-stash-submodule.sh
index d7219d6f8f..b93d1d74da 100755
--- a/t/t3906-stash-submodule.sh
+++ b/t/t3906-stash-submodule.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='stash apply can handle submodules'
+test_description='stash can handle submodules'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh
@@ -21,4 +21,44 @@ KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1
KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
test_submodule_switch "git_stash"
+setup_basic () {
+ test_when_finished "rm -rf main sub" &&
+ git init sub &&
+ (
+ cd sub &&
+ test_commit sub_file
+ ) &&
+ git init main &&
+ (
+ cd main &&
+ git submodule add ../sub &&
+ test_commit main_file
+ )
+}
+
+test_expect_success 'stash push with submodule.recurse=true preserves dirty submodule worktree' '
+ setup_basic &&
+ (
+ cd main &&
+ git config submodule.recurse true &&
+ echo "x" >main_file.t &&
+ echo "y" >sub/sub_file.t &&
+ git stash push &&
+ test_must_fail git -C sub diff --quiet
+ )
+'
+
+test_expect_success 'stash push and pop with submodule.recurse=true preserves dirty submodule worktree' '
+ setup_basic &&
+ (
+ cd main &&
+ git config submodule.recurse true &&
+ echo "x" >main_file.t &&
+ echo "y" >sub/sub_file.t &&
+ git stash push &&
+ git stash pop &&
+ test_must_fail git -C sub diff --quiet
+ )
+'
+
test_done
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 72b09896cf..b8969998b5 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -1606,6 +1606,32 @@ test_expect_success 'From line has expected format' '
test_cmp from filtered
'
+test_expect_success 'format-patch -o with no leading directories' '
+ rm -fr patches &&
+ git format-patch -o patches master..side &&
+ count=$(git rev-list --count master..side) &&
+ ls patches >list &&
+ test_line_count = $count list
+'
+
+test_expect_success 'format-patch -o with leading existing directories' '
+ rm -rf existing-dir &&
+ mkdir existing-dir &&
+ git format-patch -o existing-dir/patches master..side &&
+ count=$(git rev-list --count master..side) &&
+ ls existing-dir/patches >list &&
+ test_line_count = $count list
+'
+
+test_expect_success 'format-patch -o with leading non-existing directories' '
+ rm -rf non-existing-dir &&
+ git format-patch -o non-existing-dir/patches master..side &&
+ count=$(git rev-list --count master..side) &&
+ test_path_is_dir non-existing-dir &&
+ ls non-existing-dir/patches >list &&
+ test_line_count = $count list
+'
+
test_expect_success 'format-patch format.outputDirectory option' '
test_config format.outputDirectory patches &&
rm -fr patches &&
diff --git a/t/t4018/dts-nodes-boolean-prop b/t/t4018/dts-nodes-boolean-prop
new file mode 100644
index 0000000000..afc6b5b404
--- /dev/null
+++ b/t/t4018/dts-nodes-boolean-prop
@@ -0,0 +1,9 @@
+/ {
+ label_1: node1@ff00 {
+ RIGHT@deadf00,4000 {
+ boolean-prop1;
+
+ ChangeMe;
+ };
+ };
+};
diff --git a/t/t4018/dts-nodes-multiline-prop b/t/t4018/dts-nodes-multiline-prop
new file mode 100644
index 0000000000..072d58b69d
--- /dev/null
+++ b/t/t4018/dts-nodes-multiline-prop
@@ -0,0 +1,13 @@
+/ {
+ label_1: node1@ff00 {
+ RIGHT@deadf00,4000 {
+ multilineprop = <3>,
+ <4>,
+ <5>,
+ <6>,
+ <7>;
+
+ ChangeMe = <0xffeedd00>;
+ };
+ };
+};
diff --git a/t/t4018/dts-root b/t/t4018/dts-root
index 2ef9e6ffaa..4353b8220c 100644
--- a/t/t4018/dts-root
+++ b/t/t4018/dts-root
@@ -1,4 +1,4 @@
-/RIGHT { /* Technically just supposed to be a slash */
+/ { RIGHT /* Technically just supposed to be a slash and brace */
#size-cells = <1>;
ChangeMe = <0xffeedd00>;
diff --git a/t/t4018/dts-root-comment b/t/t4018/dts-root-comment
new file mode 100644
index 0000000000..333a625c70
--- /dev/null
+++ b/t/t4018/dts-root-comment
@@ -0,0 +1,8 @@
+/ { RIGHT /* Technically just supposed to be a slash and brace */
+ #size-cells = <1>;
+
+ /* This comment should be ignored */
+
+ some-property = <40+2>;
+ ChangeMe = <0xffeedd00>;
+};
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index 92bac43257..4c970787b0 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -184,11 +184,12 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat
test_config -C "$d" http.receivepack true &&
up="$HTTPD_URL"/smart/atomic-branches.git &&
- # Tell "$up" about two branches for now
+ # Tell "$up" about three branches for now
test_commit atomic1 &&
test_commit atomic2 &&
git branch collateral &&
- git push "$up" master collateral &&
+ git branch other &&
+ git push "$up" master collateral other &&
# collateral is a valid push, but should be failed by atomic push
git checkout collateral &&
@@ -226,6 +227,41 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat
grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output
'
+test_expect_success 'push --atomic fails on server-side errors' '
+ # Use previously set up repository
+ d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git &&
+ test_config -C "$d" http.receivepack true &&
+ up="$HTTPD_URL"/smart/atomic-branches.git &&
+
+ # break ref updates for other on the remote site
+ mkdir "$d/refs/heads/other.lock" &&
+
+ # add the new commit to other
+ git branch -f other collateral &&
+
+ # --atomic should cause entire push to be rejected
+ test_must_fail git push --atomic "$up" atomic other 2>output &&
+
+ # the new branch should not have been created upstream
+ test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
+
+ # upstream should still reflect atomic2, the last thing we pushed
+ # successfully
+ git rev-parse atomic2 >expected &&
+ # ...to other.
+ git -C "$d" rev-parse refs/heads/other >actual &&
+ test_cmp expected actual &&
+
+ # the new branch should not have been created upstream
+ test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
+
+ # the failed refs should be indicated to the user
+ grep "^ ! .*rejected.* other -> other .*atomic transaction failed" output &&
+
+ # the collateral failure refs should be indicated to the user
+ grep "^ ! .*rejected.* atomic -> atomic .*atomic transaction failed" output
+'
+
test_expect_success 'push --all can push to empty repo' '
d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
git init --bare "$d" &&
diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh
index c4b370ea85..fd25f786a3 100755
--- a/t/t7419-submodule-set-branch.sh
+++ b/t/t7419-submodule-set-branch.sh
@@ -34,7 +34,7 @@ test_expect_success 'submodule config cache setup' '
test_expect_success 'ensure submodule branch is unset' '
(cd super &&
- test_must_fail grep branch .gitmodules
+ ! grep branch .gitmodules
)
'
@@ -54,7 +54,7 @@ test_expect_success 'test submodule set-branch --branch' '
test_expect_success 'test submodule set-branch --default' '
(cd super &&
git submodule set-branch --default submodule &&
- test_must_fail grep branch .gitmodules &&
+ ! grep branch .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
a
@@ -80,7 +80,7 @@ test_expect_success 'test submodule set-branch -b' '
test_expect_success 'test submodule set-branch -d' '
(cd super &&
git submodule set-branch -d submodule &&
- test_must_fail grep branch .gitmodules &&
+ ! grep branch .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
a
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index 81a375fa0f..d8df990972 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -354,4 +354,21 @@ test_expect_success 'discard_index() also discards fsmonitor info' '
test_cmp expect actual
'
+# Test staging/unstaging files that appear at the end of the index. Test
+# file names begin with 'z' so that they are sorted to the end of the index.
+test_expect_success 'status succeeds after staging/unstaging ' '
+ test_create_repo fsmonitor-stage-unstage &&
+ (
+ cd fsmonitor-stage-unstage &&
+ test_commit initial &&
+ git update-index --fsmonitor &&
+ removed=$(test_seq 1 100 | sed "s/^/z/") &&
+ touch $removed &&
+ git add $removed &&
+ git config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" &&
+ FSMONITOR_LIST="$removed" git restore -S $removed &&
+ FSMONITOR_LIST="$removed" git status
+ )
+'
+
test_done
diff --git a/t/t7519/fsmonitor-env b/t/t7519/fsmonitor-env
new file mode 100755
index 0000000000..8f1f7ab164
--- /dev/null
+++ b/t/t7519/fsmonitor-env
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An test hook script to integrate with git to test fsmonitor.
+#
+# The hook is passed a version (currently 1) and a time in nanoseconds
+# formatted as a string and outputs to stdout all files that have been
+# modified since the given time. Paths must be relative to the root of
+# the working tree and separated by a single NUL.
+#
+#echo "$0 $*" >&2
+
+if test "$#" -ne 2
+then
+ echo "$0: exactly 2 arguments expected" >&2
+ exit 2
+fi
+
+if test "$1" != 1
+then
+ echo "Unsupported core.fsmonitor hook version." >&2
+ exit 1
+fi
+
+printf '%s\n' $FSMONITOR_LIST
diff --git a/transport-helper.c b/transport-helper.c
index 9e1279b928..a9d690297e 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -854,6 +854,10 @@ static void set_common_push_options(struct transport *transport,
die(_("helper %s does not support --signed=if-asked"), name);
}
+ if (flags & TRANSPORT_PUSH_ATOMIC)
+ if (set_helper_option(transport, TRANS_OPT_ATOMIC, "true") != 0)
+ die(_("helper %s does not support --atomic"), name);
+
if (flags & TRANSPORT_PUSH_OPTIONS) {
struct string_list_item *item;
for_each_string_list_item(item, transport->push_options)
diff --git a/transport.h b/transport.h
index 0b5f7806f6..e0131daab9 100644
--- a/transport.h
+++ b/transport.h
@@ -208,6 +208,9 @@ void transport_check_allowed(const char *type);
/* Filter objects for partial clone and fetch */
#define TRANS_OPT_LIST_OBJECTS_FILTER "filter"
+/* Request atomic (all-or-nothing) updates when pushing */
+#define TRANS_OPT_ATOMIC "atomic"
+
/**
* Returns 0 if the option was used, non-zero otherwise. Prints a
* message to stderr if the option is not used.
diff --git a/userdiff.c b/userdiff.c
index 86e3244e15..e187d356f6 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -25,8 +25,9 @@ IPATTERN("ada",
"|=>|\\.\\.|\\*\\*|:=|/=|>=|<=|<<|>>|<>"),
PATTERNS("dts",
"!;\n"
+ "!=\n"
/* lines beginning with a word optionally preceded by '&' or the root */
- "^[ \t]*((/|&?[a-zA-Z_]).*)",
+ "^[ \t]*((/[ \t]*\\{|&?[a-zA-Z_]).*)",
/* -- */
/* Property names and math operators */
"[a-zA-Z0-9,._+?#-]+"
diff --git a/utf8.c b/utf8.c
index 3b42fadffd..5c8f151f75 100644
--- a/utf8.c
+++ b/utf8.c
@@ -95,13 +95,11 @@ static int git_wcwidth(ucs_char_t ch)
return -1;
/* binary search in table of non-spacing characters */
- if (bisearch(ch, zero_width, sizeof(zero_width)
- / sizeof(struct interval) - 1))
+ if (bisearch(ch, zero_width, ARRAY_SIZE(zero_width) - 1))
return 0;
/* binary search in table of double width characters */
- if (bisearch(ch, double_width, sizeof(double_width)
- / sizeof(struct interval) - 1))
+ if (bisearch(ch, double_width, ARRAY_SIZE(double_width) - 1))
return 2;
return 1;