]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'js/azure-ci-osx-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 24 Oct 2019 04:34:02 +0000 (13:34 +0900)
committerJunio C Hamano <gitster@pobox.com>
Thu, 24 Oct 2019 04:34:02 +0000 (13:34 +0900)
Update installation procedure for Perforce on MacOS in the CI jobs
running on Azure pipelines, which was failing.

* js/azure-ci-osx-fix:
  ci(osx): use new location of the `perforce` cask

38 files changed:
Documentation/RelNotes/2.24.0.txt
Documentation/config/format.txt
Documentation/git-format-patch.txt
Documentation/git-stash.txt
Documentation/gitremote-helpers.txt
GIT-VERSION-GEN
Makefile
azure-pipelines.yml
builtin/grep.c
builtin/log.c
builtin/stash.c
column.c
compat/win32/pthread.h
contrib/completion/git-completion.zsh
contrib/diff-highlight/DiffHighlight.pm
fsmonitor.c
git-compat-util.h
git-legacy-stash.sh
grep.c
grep.h
http-push.c
remote-curl.c
t/helper/test-progress.c
t/t1308-config-set.sh
t/t3906-stash-submodule.sh
t/t4014-format-patch.sh
t/t4018/dts-nodes-boolean-prop [new file with mode: 0644]
t/t4018/dts-nodes-multiline-prop [new file with mode: 0644]
t/t4018/dts-root
t/t4018/dts-root-comment [new file with mode: 0644]
t/t5541-http-push-smart.sh
t/t7419-submodule-set-branch.sh
t/t7519-status-fsmonitor.sh
t/t7519/fsmonitor-env [new file with mode: 0755]
transport-helper.c
transport.h
userdiff.c
utf8.c

index 22de0bc4973d4052ac6038ee5a517e2b6fae58eb..125169d0daf2804d002ad58480f0f2a1b7090447 100644 (file)
@@ -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).
index cb629fa769b7ffb61f4c825894a450aea2e8c1e2..40cad9278fd1734ce5bc7445611dbeb70d00168d 100644 (file)
@@ -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
index 0ac56f4b7080bc3d8718e7cad7dab4fedca0f670..2035d4d5d53df801186ee7a713a51634d6ac9fd9 100644 (file)
@@ -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
index 8fbe12c66c823bce8756eaf3c836d5e8f0f7a340..53e1a1205d3088ed83300df89a02216dd46e556f 100644 (file)
@@ -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>]::
 
index a5c3c04371205e0a3694d403b934ab43eacea0f7..f48a031dc346a307aa33aebc62686709a18673f6 100644 (file)
@@ -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]
index 98f88a28d3227c436ecf1765f75b7f4e8e336834..64543ede287d0f85e96e5cd1846aed6bc9438495 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.23.GIT
+DEF_VER=v2.24.0-rc0
 
 LF='
 '
index de60c8e7aada06eac8a5083881f4fa8e56ef83c8..58b92af54b2af48c132bf3d7beb8feaf05a450ed 100644 (file)
--- 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 \
index 9f099b9529449c246a347c9597a1c41298b920d7..af2a5ea4845fd2af06e99ed1619f44c167055294 100644 (file)
@@ -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)
       "@
index 69ac053acc16be6b12e0743dfabf8a481e1f92cb..50ce8d946128c9f54d43d234a2117f3dba6d2299 100644 (file)
@@ -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;
 }
index c4b35fdaf9b77c05da927fb3a2800a7fd8da9f91..89873d2dc2a3dc1e0e50a97e14bf8b1894231593 100644 (file)
@@ -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);
index bb4f6d8d762d833e6cc15accf70f2680dd7af721..4e806176b0828b65cf405492ca2cd2d157e3fc4a 100644 (file)
@@ -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;
index 7a17c14b822faac1a00b62412611825f0952a935..4a38eed3226043764922e327cfda0e79b6f79dbf 100644 (file)
--- 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);
 }
 
 /*
index f1cfe73de9fc7db2f6b230ff9aab1b08069cda51..737983d00bae9190e6a328ccf9a2b1a4914fa109 100644 (file)
@@ -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
index 886bf95d1f5940987f5c4411097fd09b000be037..eef4eff53dff12f86d8982e6818ec92086aa4d80 100644 (file)
@@ -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)
 
index 7440aa1c4638103c952c225f2c9b77d8c9451b08..e2589922a659641526b8d946ccc06f87e9731de2 100644 (file)
@@ -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
index 231e83a94db58e4efb2f4d7a1dbe90220bd2f317..1f4aa1b150dbe948910705c9ff4e75ad0a6a12a1 100644 (file)
@@ -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 */
index 8b8b29a867bdaa47595197474d064a0e0305d193..607dca75341201748f00bede9602d4084065275d 100644 (file)
@@ -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
index f60e9b3e877b24e42431654e1de19911bdfc4f25..07ad4a545910da5ff5a591c159da292d5101dec3 100755 (executable)
@@ -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 0bb4cbd3d82ceef5517905a35a7f6820b7fb555a..b7ae5a442a624810471cc4dc8ab84cd1a35c963a 100644 (file)
--- 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 05dc1bb98e5e2209a945da6024a757ce02d4d103..811fd274c95b0528223fff8d684c5299c10a9967 100644 (file)
--- 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);
index 0353f9f5143d7fff3a2b4b11d02375255258319b..822f32659936d68de9bb7ee979a113fc12de2b65 100644 (file)
@@ -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);
index 051f26629d7b9f6679e47f6dc353f09c16c377ae..350d92a074ed82a99060cebb1a4a3fb0a98cfd8e 100644 (file)
@@ -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)
index 4e9f7fafdfb0ecabcb7f8cd48f371be3cf088c6c..42b96cb103c6acee9ad2a9dfad8afbaa7ef854e9 100644 (file)
@@ -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;
index d0a2727b850a6a5fa855a5787a221ce1078f2c7c..7b4e1a63eba2ffc2083061285b1a6cbbcb9c253d 100755 (executable)
@@ -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
 '
 
index d7219d6f8f18868ad901e522715a8195c3d58940..b93d1d74da7b41c51ba483fc015ac56f13799341 100755 (executable)
@@ -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
index 72b09896cf51a856cc279634e8ab1cb75a238a0f..b8969998b5090984e608391167531cfc771f0ad3 100755 (executable)
@@ -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 (file)
index 0000000..afc6b5b
--- /dev/null
@@ -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 (file)
index 0000000..072d58b
--- /dev/null
@@ -0,0 +1,13 @@
+/ {
+       label_1: node1@ff00 {
+               RIGHT@deadf00,4000 {
+                       multilineprop = <3>,
+                                       <4>,
+                                       <5>,
+                                       <6>,
+                                       <7>;
+
+                       ChangeMe = <0xffeedd00>;
+               };
+       };
+};
index 2ef9e6ffaa2ca9a1343bc7481562467fa0683b08..4353b8220c9160860fc9432d7abc55da19de07d2 100644 (file)
@@ -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 (file)
index 0000000..333a625
--- /dev/null
@@ -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>;
+};
index 92bac4325733e270133b270095f213c9db0a0108..4c970787b0ec1fcc3d18cdcab0f5c8fd15f16afd 100755 (executable)
@@ -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" &&
index c4b370ea8533984e31a9ae501994ce9926627f98..fd25f786a3655e7486222b568e91779b9b5d99bb 100755 (executable)
@@ -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
index 81a375fa0ff9845cb755dd77df9921d2b71c764b..d8df99097237b970cb6643fd77bb32ef80d4ffc6 100755 (executable)
@@ -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 (executable)
index 0000000..8f1f7ab
--- /dev/null
@@ -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
index 9e1279b928bb3eadf110e43c091b4a3ba789fe3b..a9d690297e1fe33abdafed6126f0b4541ce35af5 100644 (file)
@@ -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)
index 0b5f7806f625d888175e1c633ec2b59d8d07803b..e0131daab987f582801972fe84aa412d235c89f7 100644 (file)
@@ -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.
index 86e3244e15ddc8beaf2fc6e6a0b4b0767c87f96c..e187d356f6fff746547f14129cbe7668e11b4adb 100644 (file)
@@ -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 3b42fadffd7ccb89a5658fdf8d314014f299a769..5c8f151f755960abadf210fcb9101ca6c6aec45a 100644 (file)
--- 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;