]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'ss/faq-ignore'
authorJunio C Hamano <gitster@pobox.com>
Wed, 13 May 2020 19:19:19 +0000 (12:19 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 13 May 2020 19:19:19 +0000 (12:19 -0700)
Random bits of FAQ.

* ss/faq-ignore:
  gitfaq: files in .gitignore are tracked

56 files changed:
Documentation/CodingGuidelines
Documentation/RelNotes/2.27.0.txt
Documentation/config/credential.txt
Documentation/git-credential-store.txt
Documentation/git-credential.txt
Documentation/git-merge.txt
Documentation/git-rebase.txt
Documentation/git-restore.txt
Documentation/gitattributes.txt
Documentation/gitcredentials.txt
builtin/am.c
builtin/branch.c
builtin/checkout.c
builtin/commit.c
builtin/fetch.c
builtin/for-each-ref.c
builtin/merge.c
builtin/pack-objects.c
builtin/prune.c
builtin/rebase.c
builtin/receive-pack.c
builtin/repack.c
builtin/rev-parse.c
builtin/tag.c
commit-graph.c
commit.c
commit.h
credential-store.c
credential.h
environment.c
fetch-pack.c
git.c
list-objects-filter.c
pack-bitmap.c
ref-filter.c
ref-filter.h
run-command.c
run-command.h
send-pack.c
shallow.c
shallow.h [new file with mode: 0644]
t/perf/p5310-pack-bitmaps.sh
t/t0000-basic.sh
t/t0302-credential-store.sh
t/t1011-read-tree-sparse-checkout.sh
t/t1091-sparse-checkout-builtin.sh
t/t2070-restore.sh
t/t4018-diff-funcname.sh
t/t4018/markdown-heading-indented [new file with mode: 0644]
t/t4018/markdown-heading-non-headings [new file with mode: 0644]
t/t6113-rev-list-bitmap-filters.sh
t/t6300-for-each-ref.sh
t/test-lib.sh
unpack-trees.c
upload-pack.c
userdiff.c

index 390ceece523ed9ec2221563d991f8ec0bf83b461..a89e8dcfbc70541280173973acff2020e6e92fb6 100644 (file)
@@ -95,10 +95,6 @@ For shell scripts specifically (not exhaustive):
 
  - We use Arithmetic Expansion $(( ... )).
 
- - Inside Arithmetic Expansion, spell shell variables with $ in front
-   of them, as some shells do not grok $((x)) while accepting $(($x))
-   just fine (e.g. dash older than 0.5.4).
-
  - We do not use Process Substitution <(list) or >(list).
 
  - Do not write control structures on a single line with semicolon.
index 9c7041eb0821a180d9a39545909a62e86aceeef5..2a8c6e8f282437ab3d72835d4370f08fb040f5d0 100644 (file)
@@ -99,6 +99,15 @@ UI, Workflows & Features
  * The approxidate parser learns to parse seconds with fraction and
    ignore fractional part.
 
+ * The userdiff patterns for Markdown documents have been added.
+
+ * The sparse-checkout patterns have been forbidden from excluding all
+   paths, leaving an empty working tree, for a long time.  This
+   limitation has been lifted.
+
+ * "git restore --staged --worktree" now defaults to take the contents
+   out of "HEAD", instead of erring out.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -372,6 +381,45 @@ Fixes since v2.26
    correctly honor the core.sharedRepository settings and some were
    left read-write.
 
+ * In error messages that "git switch" mentions its option to create a
+   new branch, "-b/-B" options were shown, where "-c/-C" options
+   should be, which has been corrected.
+   (merge 7c16ef7577 dl/switch-c-option-in-error-message later to maint).
+
+ * With the recent tightening of the code that is used to parse
+   various parts of a URL for use in the credential subsystem, a
+   hand-edited credential-store file causes the credential helper to
+   die, which is a bit too harsh to the users.  Demote the error
+   behaviour to just ignore and keep using well-formed lines instead.
+   (merge c03859a665 cb/credential-store-ignore-bogus-lines later to maint).
+
+ * The samples in the credential documentation has been updated to
+   make it clear that we depict what would appear in the .git/config
+   file, by adding appropriate quotes as needed..
+   (merge 177681a07e jk/credential-sample-update later to maint).
+
+ * "git branch" and other "for-each-ref" variants accepted multiple
+   --sort=<key> options in the increasing order of precedence, but it
+   had a few breakages around "--ignore-case" handling, and tie-breaking
+   with the refname, which have been fixed.
+   (merge 7c5045fc18 jk/for-each-ref-multi-key-sort-fix later to maint).
+
+ * The coding guideline for shell scripts instructed to refer to a
+   variable with dollar-sign inside arithmetic expansion to work
+   around a bug in old versions of dash, which is a thing of the past.
+   Now we are not forbidden from writing $((var+1)).
+   (merge 32b5fe7f0e jk/arith-expansion-coding-guidelines later to maint).
+
+ * The <stdlib.h> header on NetBSD brings in its own definition of
+   hmac() function (eek), which conflicts with our own and unrelated
+   function with the same name.  Our function has been renamed to work
+   around the issue.
+   (merge 3013118eb8 cb/avoid-colliding-with-netbsd-hmac later to maint).
+
+ * The basic test did not honor $TEST_SHELL_PATH setting, which has
+   been corrected.
+   (merge 0555e4af58 cb/t0000-use-the-configured-shell later to maint).
+
  * Other code cleanup, docfix, build fix, etc.
    (merge 564956f358 jc/maintain-doc later to maint).
    (merge 7422b2a0a1 sg/commit-slab-clarify-peek later to maint).
@@ -399,3 +447,4 @@ Fixes since v2.26
    (merge 4d9378bfad eb/gitweb-more-trailers later to maint).
    (merge bdccbf7047 mt/doc-worktree-ref later to maint).
    (merge ce9baf234f dl/push-recurse-submodules-fix later to maint).
+   (merge 4153274052 bc/doc-credential-helper-value later to maint).
index 60fb3189e16144a277cab1c80222c556ce939ed5..9d01641c282aa9cf472dc782e13cd9c430b17e3a 100644 (file)
@@ -1,9 +1,13 @@
 credential.helper::
        Specify an external helper to be called when a username or
        password credential is needed; the helper may consult external
-       storage to avoid prompting the user for the credentials. Note
-       that multiple helpers may be defined. See linkgit:gitcredentials[7]
-       for details.
+       storage to avoid prompting the user for the credentials. This is
+       normally the name of a credential helper with possible
+       arguments, but may also be an absolute path with arguments or, if
+       preceded by `!`, shell commands.
++
+Note that multiple helpers may be defined. See linkgit:gitcredentials[7]
+for details and examples.
 
 credential.useHttpPath::
        When acquiring credentials, consider the "path" component of an http
index 693dd9d9d760fe2a113d4e15ab7816f34b2cd47d..76b0798856336fe739e8325ed1b5716abb099bfe 100644 (file)
@@ -94,6 +94,10 @@ stored on its own line as a URL like:
 https://user:pass@example.com
 ------------------------------
 
+No other kinds of lines (e.g. empty lines or comment lines) are
+allowed in the file, even though some may be silently ignored. Do
+not view or edit the file with editors.
+
 When Git needs authentication for a particular URL context,
 credential-store will consider that context a pattern to match against
 each entry in the credentials file.  If the protocol, hostname, and
index 6f0c7ca80f7331b103249922d54ebe692698bbe7..8d990e92fd9c03a05f099908584c22068a868904 100644 (file)
@@ -103,17 +103,20 @@ INPUT/OUTPUT FORMAT
 `git credential` reads and/or writes (depending on the action used)
 credential information in its standard input/output. This information
 can correspond either to keys for which `git credential` will obtain
-the login/password information (e.g. host, protocol, path), or to the
-actual credential data to be obtained (login/password).
+the login information (e.g. host, protocol, path), or to the actual
+credential data to be obtained (username/password).
 
 The credential is split into a set of named attributes, with one
-attribute per line. Each attribute is
-specified by a key-value pair, separated by an `=` (equals) sign,
-followed by a newline. The key may contain any bytes except `=`,
-newline, or NUL. The value may contain any bytes except newline or NUL.
+attribute per line. Each attribute is specified by a key-value pair,
+separated by an `=` (equals) sign, followed by a newline.
+
+The key may contain any bytes except `=`, newline, or NUL. The value may
+contain any bytes except newline or NUL.
+
 In both cases, all bytes are treated as-is (i.e., there is no quoting,
 and one cannot transmit a value with newline or NUL in it). The list of
 attributes is terminated by a blank line or end-of-file.
+
 Git understands the following attributes:
 
 `protocol`::
@@ -123,7 +126,8 @@ Git understands the following attributes:
 
 `host`::
 
-       The remote hostname for a network credential.
+       The remote hostname for a network credential.  This includes
+       the port number if one was specified (e.g., "example.com:8088").
 
 `path`::
 
@@ -134,7 +138,7 @@ Git understands the following attributes:
 `username`::
 
        The credential's username, if we already have one (e.g., from a
-       URL, from the user, or from a previously run helper).
+       URL, the configuration, the user, or from a previously run helper).
 
 `password`::
 
@@ -146,8 +150,12 @@ Git understands the following attributes:
        value is parsed as a URL and treated as if its constituent parts
        were read (e.g., `url=https://example.com` would behave as if
        `protocol=https` and `host=example.com` had been provided). This
-       can help callers avoid parsing URLs themselves.  Note that any
-       components which are missing from the URL (e.g., there is no
-       username in the example above) will be set to empty; if you want
-       to provide a URL and override some attributes, provide the URL
-       attribute first, followed by any overrides.
+       can help callers avoid parsing URLs themselves.
+
+       Note that specifying a protocol is mandatory and if the URL
+       doesn't specify a hostname (e.g., "cert:///path/to/file") the
+       credential will contain a hostname attribute whose value is an
+       empty string.
+
+       Components which are missing from the URL (e.g., there is no
+       username in the example above) will be left unset.
index ec06b2f8c243d6ecaf11a0e36b160a49b5a325d6..3819fadac1f1e4daa3bc44beed5602c413830851 100644 (file)
@@ -106,12 +106,12 @@ commit or stash your changes before running 'git merge'.
 `MERGE_HEAD` is present unless `MERGE_AUTOSTASH` is also present in
 which case 'git merge --abort' applies the stash entry to the worktree
 whereas 'git reset --merge' will save the stashed changes in the stash
-reflog.
+list.
 
 --quit::
        Forget about the current merge in progress. Leave the index
        and the working tree as-is. If `MERGE_AUTOSTASH` is present, the
-       stash entry will be saved to the stash reflog.
+       stash entry will be saved to the stash list.
 
 --continue::
        After a 'git merge' stops due to conflicts you can conclude the
index 794f2f39f12a23b341d1043696e26c74de67831c..4624cfd28838054f814d07366810110732e5a3bb 100644 (file)
@@ -257,7 +257,7 @@ See also INCOMPATIBLE OPTIONS below.
        Abort the rebase operation but HEAD is not reset back to the
        original branch. The index and working tree are also left
        unchanged as a result. If a temporary stash entry was created
-       using --autostash, it will be saved to the stash reflog.
+       using --autostash, it will be saved to the stash list.
 
 --apply:
        Use applying strategies to rebase (calling `git-am`
index 8e3b33980281336765ac1749cfe6add3ce9cda4e..84c6c400109851ac34185a4f9004aada07aa79aa 100644 (file)
@@ -22,9 +22,8 @@ The command can also be used to restore the content in the index with
 `--staged`, or restore both the working tree and the index with
 `--staged --worktree`.
 
-By default, the restore sources for working tree and the index are the
-index and `HEAD` respectively. `--source` could be used to specify a
-commit as the restore source.
+By default, if `--staged` is given, the contents are restored from `HEAD`,
+otherwise from the index. Use `--source` to restore from a different commit.
 
 See "Reset, restore and revert" in linkgit:git[1] for the differences
 between the three commands.
@@ -39,10 +38,8 @@ OPTIONS
        tree. It is common to specify the source tree by naming a
        commit, branch or tag associated with it.
 +
-If not specified, the default restore source for the working tree is
-the index, and the default restore source for the index is
-`HEAD`. When both `--staged` and `--worktree` are specified,
-`--source` must also be specified.
+If not specified, the contents are restored from `HEAD` if `--staged` is
+given, otherwise from the index.
 
 -p::
 --patch::
index 508fe713c4cfb1e2126bc96fc201ca2cd49c6222..2d0a03715be65edfc4c8be6ca8f2a959ddde7540 100644 (file)
@@ -824,6 +824,8 @@ patterns are available:
 
 - `java` suitable for source code in the Java language.
 
+- `markdown` suitable for Markdown documents.
+
 - `matlab` suitable for source code in the MATLAB and Octave languages.
 
 - `objc` suitable for source code in the Objective-C language.
index 1814d2d23c189c9597205eb2c0ca7f3d0c2306c3..9e481aec858d6eb36a98f3b7432e9847c50dc58b 100644 (file)
@@ -216,20 +216,26 @@ Here are some example specifications:
 
 ----------------------------------------------------
 # run "git credential-foo"
-foo
+[credential]
+       helper = foo
 
 # same as above, but pass an argument to the helper
-foo --bar=baz
+[credential]
+       helper = "foo --bar=baz"
 
 # the arguments are parsed by the shell, so use shell
 # quoting if necessary
-foo --bar="whitespace arg"
+[credential]
+       helper = "foo --bar='whitespace arg'"
 
 # you can also use an absolute path, which will not use the git wrapper
-/path/to/my/helper --with-arguments
+[credential]
+       helper = "/path/to/my/helper --with-arguments"
 
 # or you can specify your own shell snippet
-!f() { echo "password=`cat $HOME/.secret`"; }; f
+[credential "https://example.com"]
+       username = your_user
+       helper = "!f() { test \"$1\" = get && echo \"password=$(cat $HOME/.secret)\"; }; f"
 ----------------------------------------------------
 
 Generally speaking, rule (3) above is the simplest for users to specify.
@@ -262,16 +268,26 @@ For a `get` operation, the helper should produce a list of attributes on
 stdout in the same format (see linkgit:git-credential[1] for common
 attributes). A helper is free to produce a subset, or even no values at
 all if it has nothing useful to provide. Any provided attributes will
-overwrite those already known about by Git.  If a helper outputs a
-`quit` attribute with a value of `true` or `1`, no further helpers will
-be consulted, nor will the user be prompted (if no credential has been
-provided, the operation will then fail).
+overwrite those already known about by Git's credential subsystem.
+
+While it is possible to override all attributes, well behaving helpers
+should refrain from doing so for any attribute other than username and
+password.
+
+If a helper outputs a `quit` attribute with a value of `true` or `1`,
+no further helpers will be consulted, nor will the user be prompted
+(if no credential has been provided, the operation will then fail).
+
+Similarly, no more helpers will be consulted once both username and
+password had been provided.
 
 For a `store` or `erase` operation, the helper's output is ignored.
-If it fails to perform the requested operation, it may complain to
-stderr to inform the user. If it does not support the requested
-operation (e.g., a read-only store), it should silently ignore the
-request.
+
+If a helper fails to perform the requested operation or needs to notify
+the user of a potential issue, it may write to stderr.
+
+If it does not support the requested operation (e.g., a read-only store),
+it should silently ignore the request.
 
 If a helper receives any other operation, it should silently ignore the
 request. This leaves room for future operations to be added (older
index e3dfd93c258f6930ac36fa42c6fd9b8c80045576..69e50de018ba01cb2243221f1c7b5d7617afc72d 100644 (file)
@@ -1691,7 +1691,6 @@ static int do_interactive(struct am_state *state)
  */
 static void am_run(struct am_state *state, int resume)
 {
-       const char *argv_gc_auto[] = {"gc", "--auto", NULL};
        struct strbuf sb = STRBUF_INIT;
 
        unlink(am_path(state, "dirtyindex"));
@@ -1796,7 +1795,7 @@ next:
        if (!state->rebasing) {
                am_destroy(state);
                close_object_store(the_repository->objects);
-               run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+               run_auto_gc(state->quiet);
        }
 }
 
index 176e524a94d2ae015c905cb75711edd1548f080e..accb61b1aae3837a0771839c7b167c85243808f8 100644 (file)
@@ -737,7 +737,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                 */
                if (!sorting)
                        sorting = ref_default_sorting();
-               sorting->ignore_case = icase;
+               ref_sorting_icase_all(sorting, icase);
                print_ref_list(&filter, sorting, &format);
                print_columns(&output, colopts, NULL);
                string_list_clear(&output, 0);
index 0b18591ffac6b8a130ecef150596fe4c9dced4ab..e9d111bb8360d19c4c81fa6d8caa54b8049576fe 100644 (file)
@@ -1544,6 +1544,9 @@ static struct option *add_checkout_path_options(struct checkout_opts *opts,
        return newopts;
 }
 
+/* create-branch option (either b or c) */
+static char cb_option = 'b';
+
 static int checkout_main(int argc, const char **argv, const char *prefix,
                         struct checkout_opts *opts, struct option *options,
                         const char * const usagestr[])
@@ -1586,7 +1589,8 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
        }
 
        if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
-               die(_("-b, -B and --orphan are mutually exclusive"));
+               die(_("-%c, -%c and --orphan are mutually exclusive"),
+                               cb_option, toupper(cb_option));
 
        if (opts->overlay_mode == 1 && opts->patch_mode)
                die(_("-p and --overlay are mutually exclusive"));
@@ -1605,16 +1609,16 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
        if (opts->checkout_index < 0 || opts->checkout_worktree < 0)
                BUG("these flags should be non-negative by now");
        /*
-        * convenient shortcut: "git restore --staged" equals
-        * "git restore --staged --source HEAD"
+        * convenient shortcut: "git restore --staged [--worktree]" equals
+        * "git restore --staged [--worktree] --source HEAD"
         */
-       if (!opts->from_treeish && opts->checkout_index && !opts->checkout_worktree)
+       if (!opts->from_treeish && opts->checkout_index)
                opts->from_treeish = "HEAD";
 
        /*
         * From here on, new_branch will contain the branch to be checked out,
         * and new_branch_force and new_orphan_branch will tell us which one of
-        * -b/-B/--orphan is being used.
+        * -b/-B/-c/-C/--orphan is being used.
         */
        if (opts->new_branch_force)
                opts->new_branch = opts->new_branch_force;
@@ -1622,7 +1626,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
        if (opts->new_orphan_branch)
                opts->new_branch = opts->new_orphan_branch;
 
-       /* --track without -b/-B/--orphan should DWIM */
+       /* --track without -c/-C/-b/-B/--orphan should DWIM */
        if (opts->track != BRANCH_TRACK_UNSPECIFIED && !opts->new_branch) {
                const char *argv0 = argv[0];
                if (!argc || !strcmp(argv0, "--"))
@@ -1631,7 +1635,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
                skip_prefix(argv0, "remotes/", &argv0);
                argv0 = strchr(argv0, '/');
                if (!argv0 || !argv0[1])
-                       die(_("missing branch name; try -b"));
+                       die(_("missing branch name; try -%c"), cb_option);
                opts->new_branch = argv0 + 1;
        }
 
@@ -1822,6 +1826,8 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
        options = add_common_options(&opts, options);
        options = add_common_switch_branch_options(&opts, options);
 
+       cb_option = 'c';
+
        ret = checkout_main(argc, argv, prefix, &opts,
                            options, switch_branch_usage);
        FREE_AND_NULL(options);
index a73de0a4c529f658c04e6a2a453b93c1c70718c8..d1b7396052a2449f3ebda88df62cf7b89499090f 100644 (file)
@@ -1494,7 +1494,6 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 
 int cmd_commit(int argc, const char **argv, const char *prefix)
 {
-       const char *argv_gc_auto[] = {"gc", "--auto", NULL};
        static struct wt_status s;
        static struct option builtin_commit_options[] = {
                OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
@@ -1703,7 +1702,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        git_test_write_commit_graph_or_die();
 
        repo_rerere(the_repository, 0);
-       run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+       run_auto_gc(quiet);
        run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
        if (amend && !no_post_rewrite) {
                commit_post_rewrite(the_repository, current_head, &oid);
index 3ae52c015d30243a40b2647f90e9c50bafa2f160..b5788c16bf43da12c81525498cf056a9b828962e 100644 (file)
@@ -27,6 +27,7 @@
 #include "branch.h"
 #include "promisor-remote.h"
 #include "commit-graph.h"
+#include "shallow.h"
 
 #define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000)
 
@@ -1752,7 +1753,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        struct remote *remote = NULL;
        int result = 0;
        int prune_tags_ok = 1;
-       struct argv_array argv_gc_auto = ARGV_ARRAY_INIT;
 
        packet_trace_identity("fetch");
 
@@ -1879,13 +1879,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 
        close_object_store(the_repository->objects);
 
-       if (enable_auto_gc) {
-               argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
-               if (verbosity < 0)
-                       argv_array_push(&argv_gc_auto, "--quiet");
-               run_command_v_opt(argv_gc_auto.argv, RUN_GIT_CMD);
-               argv_array_clear(&argv_gc_auto);
-       }
+       if (enable_auto_gc)
+               run_auto_gc(verbosity < 0);
 
        return result;
 }
index 465153e85337fdf6b857a94b8c245fe33832b0dc..57489e4eab1c16d94806e82471371b9be574d9ef 100644 (file)
@@ -70,7 +70,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 
        if (!sorting)
                sorting = ref_default_sorting();
-       sorting->ignore_case = icase;
+       ref_sorting_icase_all(sorting, icase);
        filter.ignore_case = icase;
 
        filter.name_patterns = argv;
index 923e32acf1a969810077eb9c42d14bce132ecfc7..ca6a5dc4bf782ef1ac88c817365483cc22c18f58 100644 (file)
@@ -450,7 +450,6 @@ static void finish(struct commit *head_commit,
                if (verbosity >= 0 && !merge_msg.len)
                        printf(_("No merge message -- not updating HEAD\n"));
                else {
-                       const char *argv_gc_auto[] = { "gc", "--auto", NULL };
                        update_ref(reflog_message.buf, "HEAD", new_head, head,
                                   0, UPDATE_REFS_DIE_ON_ERR);
                        /*
@@ -458,7 +457,7 @@ static void finish(struct commit *head_commit,
                         * user should see them.
                         */
                        close_object_store(the_repository->objects);
-                       run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+                       run_auto_gc(verbosity < 0);
                }
        }
        if (new_head && show_diffstat) {
index 03b85f5166d358bda7c8dd3d1edc3097a1227388..c5b433a23fdbf078c3e8894bdb0490ae736e02cd 100644 (file)
@@ -34,6 +34,7 @@
 #include "dir.h"
 #include "midx.h"
 #include "trace2.h"
+#include "shallow.h"
 
 #define IN_PACK(obj) oe_in_pack(&to_pack, obj)
 #define SIZE(obj) oe_size(&to_pack, obj)
index fd9acc722247ece74483f6a2a7674a4c5f712570..02c6ab7cbaafbac6492fd458bedc0f162e81d683 100644 (file)
@@ -8,6 +8,7 @@
 #include "progress.h"
 #include "prune-packed.h"
 #include "object-store.h"
+#include "shallow.h"
 
 static const char * const prune_usage[] = {
        N_("git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"),
index ca6aa0dc7a8685a7dbdd5e07f5b20be7e3a38756..37ba76ac3d26f86ef3c16b65d2293b873efd8ee5 100644 (file)
@@ -722,7 +722,6 @@ static int rebase_write_basic_state(struct rebase_options *opts)
 static int finish_rebase(struct rebase_options *opts)
 {
        struct strbuf dir = STRBUF_INIT;
-       const char *argv_gc_auto[] = { "gc", "--auto", NULL };
        int ret = 0;
 
        delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
@@ -732,7 +731,7 @@ static int finish_rebase(struct rebase_options *opts)
         * We ignore errors in 'gc --auto', since the
         * user should see them.
         */
-       run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+       run_auto_gc(!(opts->flags & (REBASE_NO_QUIET|REBASE_VERBOSE)));
        if (opts->type == REBASE_MERGE) {
                struct replay_opts replay = REPLAY_OPTS_INIT;
 
index a00f91c1a0a8b5979e0f2cde49637c3552bb256b..ea3d0f01af3b7cfd90e1e235ee4e8694dabf8791 100644 (file)
@@ -28,6 +28,7 @@
 #include "protocol.h"
 #include "commit-reach.h"
 #include "worktree.h"
+#include "shallow.h"
 
 static const char * const receive_pack_usage[] = {
        N_("git receive-pack <git-dir>"),
@@ -418,7 +419,7 @@ static int copy_to_sideband(int in, int out, void *arg)
        return 0;
 }
 
-static void hmac(unsigned char *out,
+static void hmac_hash(unsigned char *out,
                      const char *key_in, size_t key_len,
                      const char *text, size_t text_len)
 {
@@ -463,10 +464,10 @@ static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp)
        unsigned char hash[GIT_MAX_RAWSZ];
 
        strbuf_addf(&buf, "%s:%"PRItime, path, stamp);
-       hmac(hash, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));
+       hmac_hash(hash, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));
        strbuf_release(&buf);
 
-       /* RFC 2104 5. HMAC-SHA1-80 */
+       /* RFC 2104 5. HMAC-SHA1 or HMAC-SHA256 */
        strbuf_addf(&buf, "%"PRItime"-%.*s", stamp, (int)the_hash_algo->hexsz, hash_to_hex(hash));
        return strbuf_detach(&buf, NULL);
 }
@@ -876,7 +877,7 @@ static void refuse_unconfigured_deny_delete_current(void)
 static int command_singleton_iterator(void *cb_data, struct object_id *oid);
 static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
 {
-       struct lock_file shallow_lock = LOCK_INIT;
+       struct shallow_lock shallow_lock = SHALLOW_LOCK_INIT;
        struct oid_array extra = OID_ARRAY_INIT;
        struct check_connected_options opt = CHECK_CONNECTED_INIT;
        uint32_t mask = 1 << (cmd->index % 32);
index 1b686ee9cee7c13f7c0052f397e1006d079667a0..df287739d9081cbccb203ca3f8cc744490e949ca 100644 (file)
@@ -13,6 +13,7 @@
 #include "prune-packed.h"
 #include "object-store.h"
 #include "promisor-remote.h"
+#include "shallow.h"
 
 static int delta_base_offset = 1;
 static int pack_kept_objects = -1;
index 06056434ed1f552ba70e1944718cc2fe79e434bc..669dd2fd6f087628c3d7dc9ba165771825418799 100644 (file)
@@ -16,6 +16,7 @@
 #include "split-index.h"
 #include "submodule.h"
 #include "commit-reach.h"
+#include "shallow.h"
 
 #define DO_REVS                1
 #define DO_NOREV       2
index b93b7365f48bcfd4dee8f9587c933a4e22ff8d07..5cbd80dc3e93f478eb0ff47465a1e4b287b897d2 100644 (file)
@@ -485,7 +485,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        }
        if (!sorting)
                sorting = ref_default_sorting();
-       sorting->ignore_case = icase;
+       ref_sorting_icase_all(sorting, icase);
        filter.ignore_case = icase;
        if (cmdmode == 'l') {
                int ret;
index aa3adb912f06305f342c076cfc5e210ca50a3834..e3420ddcbff5e829aa821d6c42c740e6eb819d37 100644 (file)
@@ -18,6 +18,7 @@
 #include "progress.h"
 #include "bloom.h"
 #include "commit-slab.h"
+#include "shallow.h"
 
 void git_test_write_commit_graph_or_die(void)
 {
@@ -281,8 +282,7 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
                if (data + graph_size - chunk_lookup <
                    GRAPH_CHUNKLOOKUP_WIDTH) {
                        error(_("commit-graph chunk lookup table entry missing; file may be incomplete"));
-                       free(graph);
-                       return NULL;
+                       goto free_and_return;
                }
 
                chunk_id = get_be32(chunk_lookup + 0);
@@ -293,8 +293,7 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
                if (chunk_offset > graph_size - the_hash_algo->rawsz) {
                        error(_("commit-graph improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32),
                              (uint32_t)chunk_offset);
-                       free(graph);
-                       return NULL;
+                       goto free_and_return;
                }
 
                switch (chunk_id) {
@@ -361,8 +360,7 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
 
                if (chunk_repeated) {
                        error(_("commit-graph chunk id %08x appears multiple times"), chunk_id);
-                       free(graph);
-                       return NULL;
+                       goto free_and_return;
                }
 
                if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP)
@@ -381,17 +379,20 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
                /* We need both the bloom chunks to exist together. Else ignore the data */
                graph->chunk_bloom_indexes = NULL;
                graph->chunk_bloom_data = NULL;
-               graph->bloom_filter_settings = NULL;
+               FREE_AND_NULL(graph->bloom_filter_settings);
        }
 
        hashcpy(graph->oid.hash, graph->data + graph->data_len - graph->hash_len);
 
-       if (verify_commit_graph_lite(graph)) {
-               free(graph);
-               return NULL;
-       }
+       if (verify_commit_graph_lite(graph))
+               goto free_and_return;
 
        return graph;
+
+free_and_return:
+       free(graph->bloom_filter_settings);
+       free(graph);
+       return NULL;
 }
 
 static struct commit_graph *load_commit_graph_one(const char *graph_file,
index c7099daeac3b86a91dea48314da446b9494129e7..87686a7055bc5c502de88032d1c474e32539e6a0 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -20,6 +20,7 @@
 #include "refs.h"
 #include "commit-reach.h"
 #include "run-command.h"
+#include "shallow.h"
 
 static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
 
@@ -110,7 +111,7 @@ static const unsigned char *commit_graft_sha1_access(size_t index, void *table)
        return commit_graft_table[index]->oid.hash;
 }
 
-static int commit_graft_pos(struct repository *r, const unsigned char *sha1)
+int commit_graft_pos(struct repository *r, const unsigned char *sha1)
 {
        return sha1_pos(sha1, r->parsed_objects->grafts,
                        r->parsed_objects->grafts_nr,
@@ -245,19 +246,6 @@ int for_each_commit_graft(each_commit_graft_fn fn, void *cb_data)
        return ret;
 }
 
-int unregister_shallow(const struct object_id *oid)
-{
-       int pos = commit_graft_pos(the_repository, oid->hash);
-       if (pos < 0)
-               return -1;
-       if (pos + 1 < the_repository->parsed_objects->grafts_nr)
-               MOVE_ARRAY(the_repository->parsed_objects->grafts + pos,
-                          the_repository->parsed_objects->grafts + pos + 1,
-                          the_repository->parsed_objects->grafts_nr - pos - 1);
-       the_repository->parsed_objects->grafts_nr--;
-       return 0;
-}
-
 struct commit_buffer {
        void *buffer;
        unsigned long size;
index ab91d21131c8dfbc5386a3c5c9ac538f64d94601..1b2dea5d85ebe52c8e5f32f1e5e26ff33e0c566c 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -236,6 +236,8 @@ struct commit_graft {
 typedef int (*each_commit_graft_fn)(const struct commit_graft *, void *);
 
 struct commit_graft *read_graft_line(struct strbuf *line);
+/* commit_graft_pos returns an index into r->parsed_objects->grafts. */
+int commit_graft_pos(struct repository *r, const unsigned char *sha1);
 int register_commit_graft(struct repository *r, struct commit_graft *, int);
 void prepare_commit_graft(struct repository *r);
 struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid);
@@ -247,55 +249,7 @@ struct commit *get_fork_point(const char *refname, struct commit *commit);
 
 struct oid_array;
 struct ref;
-int register_shallow(struct repository *r, const struct object_id *oid);
-int unregister_shallow(const struct object_id *oid);
-int commit_shallow_file(struct repository *r, struct lock_file *lk);
-void rollback_shallow_file(struct repository *r, struct lock_file *lk);
 int for_each_commit_graft(each_commit_graft_fn, void *);
-int is_repository_shallow(struct repository *r);
-struct commit_list *get_shallow_commits(struct object_array *heads,
-                                       int depth, int shallow_flag, int not_shallow_flag);
-struct commit_list *get_shallow_commits_by_rev_list(
-               int ac, const char **av, int shallow_flag, int not_shallow_flag);
-void set_alternate_shallow_file(struct repository *r, const char *path, int override);
-int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
-                         const struct oid_array *extra);
-void setup_alternate_shallow(struct lock_file *shallow_lock,
-                            const char **alternate_shallow_file,
-                            const struct oid_array *extra);
-const char *setup_temporary_shallow(const struct oid_array *extra);
-void advertise_shallow_grafts(int);
-
-/*
- * Initialize with prepare_shallow_info() or zero-initialize (equivalent to
- * prepare_shallow_info with a NULL oid_array).
- */
-struct shallow_info {
-       struct oid_array *shallow;
-       int *ours, nr_ours;
-       int *theirs, nr_theirs;
-       struct oid_array *ref;
-
-       /* for receive-pack */
-       uint32_t **used_shallow;
-       int *need_reachability_test;
-       int *reachable;
-       int *shallow_ref;
-       struct commit **commits;
-       int nr_commits;
-};
-
-void prepare_shallow_info(struct shallow_info *, struct oid_array *);
-void clear_shallow_info(struct shallow_info *);
-void remove_nonexistent_theirs_shallow(struct shallow_info *);
-void assign_shallow_commits_to_refs(struct shallow_info *info,
-                                   uint32_t **used,
-                                   int *ref_status);
-int delayed_reachability_test(struct shallow_info *si, int c);
-#define PRUNE_SHOW_ONLY 1
-#define PRUNE_QUICK 2
-void prune_shallow(unsigned options);
-extern struct trace_key trace_shallow;
 
 int interactive_add(int argc, const char **argv, const char *prefix, int patch);
 int run_add_interactive(const char *revision, const char *patch_mode,
index c010497cb21db3c2bc921caf1b34be3e60ff5570..294e77168156225efcb3b6840bc1dd7883c6dcac 100644 (file)
@@ -24,8 +24,8 @@ static int parse_credential_file(const char *fn,
        }
 
        while (strbuf_getline_lf(&line, fh) != EOF) {
-               credential_from_url(&entry, line.buf);
-               if (entry.username && entry.password &&
+               if (!credential_from_url_gently(&entry, line.buf, 1) &&
+                   entry.username && entry.password &&
                    credential_match(c, &entry)) {
                        found_credential = 1;
                        if (match_cb) {
index d99ec42b2a8c96a298e75b809bf86e47d6d38211..c0e17e3554fce30586abe8a32aad503e4ec92b03 100644 (file)
@@ -177,8 +177,8 @@ void credential_write(const struct credential *, FILE *);
  * Parse a url into a credential struct, replacing any existing contents.
  *
  * If the url can't be parsed (e.g., a missing "proto://" component), the
- * resulting credential will be empty but we'll still return success from the
- * "gently" form.
+ * resulting credential will be empty and the function will return an
+ * error (even in the "gently" form).
  *
  * If we encounter a component which cannot be represented as a credential
  * value (e.g., because it contains a newline), the "gently" form will return
@@ -189,7 +189,7 @@ void credential_write(const struct credential *, FILE *);
 void credential_from_url(struct credential *, const char *url);
 int credential_from_url_gently(struct credential *, const char *url, int quiet);
 
-int credential_match(const struct credential *have,
-                    const struct credential *want);
+int credential_match(const struct credential *want,
+                    const struct credential *have);
 
 #endif /* CREDENTIAL_H */
index 10c9061c432cf9d82e0fbd14fed7c4a9a304c447..aaca0e91ac8f4a3043dfbe963b33a376e72020fd 100644 (file)
@@ -17,6 +17,7 @@
 #include "argv-array.h"
 #include "object-store.h"
 #include "chdir-notify.h"
+#include "shallow.h"
 
 int trust_executable_bit = 1;
 int trust_ctime = 1;
index f73a2ce6cba2af20669c9bf98acabb878725a0a7..7eaa19d7c17abeb4d2975d112a79762507a81009 100644 (file)
@@ -22,6 +22,7 @@
 #include "connected.h"
 #include "fetch-negotiator.h"
 #include "fsck.h"
+#include "shallow.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -34,7 +35,7 @@ static int fetch_fsck_objects = -1;
 static int transfer_fsck_objects = -1;
 static int agent_supported;
 static int server_supports_filtering;
-static struct lock_file shallow_lock;
+static struct shallow_lock shallow_lock;
 static const char *alternate_shallow_file;
 static struct strbuf fsck_msg_types = STRBUF_INIT;
 
diff --git a/git.c b/git.c
index 2e4efb4ff08f16cd6040350bf2720e0375adab96..a2d337eed77c13bf43ffde57642af9c1ea68b2db 100644 (file)
--- a/git.c
+++ b/git.c
@@ -4,6 +4,7 @@
 #include "help.h"
 #include "run-command.h"
 #include "alias.h"
+#include "shallow.h"
 
 #define RUN_SETUP              (1<<0)
 #define RUN_SETUP_GENTLY       (1<<1)
index 1e8d4e763da07377263086d252d1228004971383..0a3ef3cab3ac31abb679a18f048798e7e4ac54ea 100644 (file)
@@ -663,6 +663,9 @@ struct filter *list_objects_filter__init(
 
        assert((sizeof(s_filters) / sizeof(s_filters[0])) == LOFC__COUNT);
 
+       if (!filter_options)
+               return NULL;
+
        if (filter_options->choice >= LOFC__COUNT)
                BUG("invalid list-objects filter choice: %d",
                    filter_options->choice);
index 49a8d10d0cf99716ea37b78bec578ca96c17de20..4077e731e800c52548243452e9a5cf715a8f43b0 100644 (file)
@@ -506,7 +506,8 @@ static int should_include(struct commit *commit, void *_data)
 static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
                                   struct rev_info *revs,
                                   struct object_list *roots,
-                                  struct bitmap *seen)
+                                  struct bitmap *seen,
+                                  struct list_objects_filter_options *filter)
 {
        struct bitmap *base = NULL;
        int needs_walk = 0;
@@ -599,8 +600,9 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
                show_data.bitmap_git = bitmap_git;
                show_data.base = base;
 
-               traverse_commit_list(revs, show_commit, show_object,
-                                    &show_data);
+               traverse_commit_list_filtered(filter, revs,
+                                             show_commit, show_object,
+                                             &show_data, NULL);
        }
 
        return base;
@@ -715,8 +717,9 @@ static int in_bitmapped_pack(struct bitmap_index *bitmap_git,
        return 0;
 }
 
-static struct bitmap *find_tip_blobs(struct bitmap_index *bitmap_git,
-                                    struct object_list *tip_objects)
+static struct bitmap *find_tip_objects(struct bitmap_index *bitmap_git,
+                                      struct object_list *tip_objects,
+                                      enum object_type type)
 {
        struct bitmap *result = bitmap_new();
        struct object_list *p;
@@ -724,7 +727,7 @@ static struct bitmap *find_tip_blobs(struct bitmap_index *bitmap_git,
        for (p = tip_objects; p; p = p->next) {
                int pos;
 
-               if (p->item->type != OBJ_BLOB)
+               if (p->item->type != type)
                        continue;
 
                pos = bitmap_position(bitmap_git, &p->item->oid);
@@ -737,9 +740,10 @@ static struct bitmap *find_tip_blobs(struct bitmap_index *bitmap_git,
        return result;
 }
 
-static void filter_bitmap_blob_none(struct bitmap_index *bitmap_git,
-                                   struct object_list *tip_objects,
-                                   struct bitmap *to_filter)
+static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git,
+                                      struct object_list *tip_objects,
+                                      struct bitmap *to_filter,
+                                      enum object_type type)
 {
        struct eindex *eindex = &bitmap_git->ext_index;
        struct bitmap *tips;
@@ -747,18 +751,21 @@ static void filter_bitmap_blob_none(struct bitmap_index *bitmap_git,
        eword_t mask;
        uint32_t i;
 
+       if (type != OBJ_BLOB && type != OBJ_TREE)
+               BUG("filter_bitmap_exclude_type: unsupported type '%d'", type);
+
        /*
         * The non-bitmap version of this filter never removes
-        * blobs which the other side specifically asked for,
+        * objects which the other side specifically asked for,
         * so we must match that behavior.
         */
-       tips = find_tip_blobs(bitmap_git, tip_objects);
+       tips = find_tip_objects(bitmap_git, tip_objects, type);
 
        /*
         * We can use the blob type-bitmap to work in whole words
         * for the objects that are actually in the bitmapped packfile.
         */
-       for (i = 0, init_type_iterator(&it, bitmap_git, OBJ_BLOB);
+       for (i = 0, init_type_iterator(&it, bitmap_git, type);
             i < to_filter->word_alloc && ewah_iterator_next(&mask, &it);
             i++) {
                if (i < tips->word_alloc)
@@ -773,7 +780,7 @@ static void filter_bitmap_blob_none(struct bitmap_index *bitmap_git,
         */
        for (i = 0; i < eindex->count; i++) {
                uint32_t pos = i + bitmap_git->pack->num_objects;
-               if (eindex->objects[i]->type == OBJ_BLOB &&
+               if (eindex->objects[i]->type == type &&
                    bitmap_get(to_filter, pos) &&
                    !bitmap_get(tips, pos))
                        bitmap_unset(to_filter, pos);
@@ -782,6 +789,14 @@ static void filter_bitmap_blob_none(struct bitmap_index *bitmap_git,
        bitmap_free(tips);
 }
 
+static void filter_bitmap_blob_none(struct bitmap_index *bitmap_git,
+                                   struct object_list *tip_objects,
+                                   struct bitmap *to_filter)
+{
+       filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter,
+                                  OBJ_BLOB);
+}
+
 static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git,
                                     uint32_t pos)
 {
@@ -820,7 +835,7 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git,
        eword_t mask;
        uint32_t i;
 
-       tips = find_tip_blobs(bitmap_git, tip_objects);
+       tips = find_tip_objects(bitmap_git, tip_objects, OBJ_BLOB);
 
        for (i = 0, init_type_iterator(&it, bitmap_git, OBJ_BLOB);
             i < to_filter->word_alloc && ewah_iterator_next(&mask, &it);
@@ -854,6 +869,20 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git,
        bitmap_free(tips);
 }
 
+static void filter_bitmap_tree_depth(struct bitmap_index *bitmap_git,
+                                    struct object_list *tip_objects,
+                                    struct bitmap *to_filter,
+                                    unsigned long limit)
+{
+       if (limit)
+               BUG("filter_bitmap_tree_depth given non-zero limit");
+
+       filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter,
+                                  OBJ_TREE);
+       filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter,
+                                  OBJ_BLOB);
+}
+
 static int filter_bitmap(struct bitmap_index *bitmap_git,
                         struct object_list *tip_objects,
                         struct bitmap *to_filter,
@@ -877,6 +906,15 @@ static int filter_bitmap(struct bitmap_index *bitmap_git,
                return 0;
        }
 
+       if (filter->choice == LOFC_TREE_DEPTH &&
+           filter->tree_exclude_depth == 0) {
+               if (bitmap_git)
+                       filter_bitmap_tree_depth(bitmap_git, tip_objects,
+                                                to_filter,
+                                                filter->tree_exclude_depth);
+               return 0;
+       }
+
        /* filter choice not handled */
        return -1;
 }
@@ -963,7 +1001,8 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
 
        if (haves) {
                revs->ignore_missing_links = 1;
-               haves_bitmap = find_objects(bitmap_git, revs, haves, NULL);
+               haves_bitmap = find_objects(bitmap_git, revs, haves, NULL,
+                                           filter);
                reset_revision_walk();
                revs->ignore_missing_links = 0;
 
@@ -971,7 +1010,8 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
                        BUG("failed to perform bitmap walk");
        }
 
-       wants_bitmap = find_objects(bitmap_git, revs, wants, haves_bitmap);
+       wants_bitmap = find_objects(bitmap_git, revs, wants, haves_bitmap,
+                                   filter);
 
        if (!wants_bitmap)
                BUG("failed to perform bitmap walk");
index 35776838f4540d793132989a7c5e8dded3848e04..bf7b70299b43b1145c22b353f78eed1ec372f023 100644 (file)
@@ -2295,7 +2295,7 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru
                if (va->value < vb->value)
                        cmp = -1;
                else if (va->value == vb->value)
-                       cmp = cmp_fn(a->refname, b->refname);
+                       cmp = 0;
                else
                        cmp = 1;
        }
@@ -2314,7 +2314,16 @@ static int compare_refs(const void *a_, const void *b_, void *ref_sorting)
                if (cmp)
                        return cmp;
        }
-       return 0;
+       s = ref_sorting;
+       return s && s->ignore_case ?
+               strcasecmp(a->refname, b->refname) :
+               strcmp(a->refname, b->refname);
+}
+
+void ref_sorting_icase_all(struct ref_sorting *sorting, int flag)
+{
+       for (; sorting; sorting = sorting->next)
+               sorting->ignore_case = !!flag;
 }
 
 void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array)
index 64330e9601a6bf88b52f01ac3b9db88df8321d1b..8ecc33cdfa5006e34251131b0c6c93b335383809 100644 (file)
@@ -114,6 +114,8 @@ void ref_array_clear(struct ref_array *array);
 int verify_ref_format(struct ref_format *format);
 /*  Sort the given ref_array as per the ref_sorting provided */
 void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);
+/*  Set the ignore_case flag for all elements of a sorting list */
+void ref_sorting_icase_all(struct ref_sorting *sorting, int flag);
 /*  Based on the given format and quote_style, fill the strbuf */
 int format_ref_array_item(struct ref_array_item *info,
                          const struct ref_format *format,
index 0f41af3b550f1f58d89f496b539e44f28559fbf6..9b3a57d1e392c8d311cfbfbad7859e9e627cd5ef 100644 (file)
@@ -1864,3 +1864,16 @@ int run_processes_parallel_tr2(int n, get_next_task_fn get_next_task,
 
        return result;
 }
+
+int run_auto_gc(int quiet)
+{
+       struct argv_array argv_gc_auto = ARGV_ARRAY_INIT;
+       int status;
+
+       argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
+       if (quiet)
+               argv_array_push(&argv_gc_auto, "--quiet");
+       status = run_command_v_opt(argv_gc_auto.argv, RUN_GIT_CMD);
+       argv_array_clear(&argv_gc_auto);
+       return status;
+}
index 0f3cc73ab6727e9b3805d93e5e4ab4dec3c1d5cb..191dfcdafe3dfcf6aff4b1c15e1be0924fbdb2d1 100644 (file)
@@ -218,6 +218,11 @@ LAST_ARG_MUST_BE_NULL
 int run_hook_le(const char *const *env, const char *name, ...);
 int run_hook_ve(const char *const *env, const char *name, va_list args);
 
+/*
+ * Trigger an auto-gc
+ */
+int run_auto_gc(int quiet);
+
 #define RUN_COMMAND_NO_STDIN 1
 #define RUN_GIT_CMD         2  /*If this is to be git sub-command */
 #define RUN_COMMAND_STDOUT_TO_STDERR 4
index d1b7edc9957874dea1a1d1c8daf62e2ef2d7f8d8..0abee22283dae8ceba42eb4b9b5ecb4842c98984 100644 (file)
@@ -15,6 +15,7 @@
 #include "oid-array.h"
 #include "gpg-interface.h"
 #include "cache.h"
+#include "shallow.h"
 
 int option_parse_push_signed(const struct option *opt,
                             const char *arg, int unset)
index 321a27670fcc9197e4254ac2e2df7bbd698c632c..b826de9b676c1c0d61fb30638284ed32c0f8403e 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -14,6 +14,7 @@
 #include "commit-slab.h"
 #include "list-objects.h"
 #include "commit-reach.h"
+#include "shallow.h"
 
 void set_alternate_shallow_file(struct repository *r, const char *path, int override)
 {
@@ -38,6 +39,19 @@ int register_shallow(struct repository *r, const struct object_id *oid)
        return register_commit_graft(r, graft, 0);
 }
 
+int unregister_shallow(const struct object_id *oid)
+{
+       int pos = commit_graft_pos(the_repository, oid->hash);
+       if (pos < 0)
+               return -1;
+       if (pos + 1 < the_repository->parsed_objects->grafts_nr)
+               MOVE_ARRAY(the_repository->parsed_objects->grafts + pos,
+                          the_repository->parsed_objects->grafts + pos + 1,
+                          the_repository->parsed_objects->grafts_nr - pos - 1);
+       the_repository->parsed_objects->grafts_nr--;
+       return 0;
+}
+
 int is_repository_shallow(struct repository *r)
 {
        FILE *fp;
@@ -78,16 +92,16 @@ static void reset_repository_shallow(struct repository *r)
        stat_validity_clear(r->parsed_objects->shallow_stat);
 }
 
-int commit_shallow_file(struct repository *r, struct lock_file *lk)
+int commit_shallow_file(struct repository *r, struct shallow_lock *lk)
 {
-       int res = commit_lock_file(lk);
+       int res = commit_lock_file(&lk->lock);
        reset_repository_shallow(r);
        return res;
 }
 
-void rollback_shallow_file(struct repository *r, struct lock_file *lk)
+void rollback_shallow_file(struct repository *r, struct shallow_lock *lk)
 {
-       rollback_lock_file(lk);
+       rollback_lock_file(&lk->lock);
        reset_repository_shallow(r);
 }
 
@@ -352,22 +366,22 @@ const char *setup_temporary_shallow(const struct oid_array *extra)
        return "";
 }
 
-void setup_alternate_shallow(struct lock_file *shallow_lock,
+void setup_alternate_shallow(struct shallow_lock *shallow_lock,
                             const char **alternate_shallow_file,
                             const struct oid_array *extra)
 {
        struct strbuf sb = STRBUF_INIT;
        int fd;
 
-       fd = hold_lock_file_for_update(shallow_lock,
+       fd = hold_lock_file_for_update(&shallow_lock->lock,
                                       git_path_shallow(the_repository),
                                       LOCK_DIE_ON_ERROR);
        check_shallow_file_for_update(the_repository);
        if (write_shallow_commits(&sb, 0, extra)) {
                if (write_in_full(fd, sb.buf, sb.len) < 0)
                        die_errno("failed to write to %s",
-                                 get_lock_file_path(shallow_lock));
-               *alternate_shallow_file = get_lock_file_path(shallow_lock);
+                                 get_lock_file_path(&shallow_lock->lock));
+               *alternate_shallow_file = get_lock_file_path(&shallow_lock->lock);
        } else
                /*
                 * is_repository_shallow() sees empty string as "no
@@ -400,7 +414,7 @@ void advertise_shallow_grafts(int fd)
  */
 void prune_shallow(unsigned options)
 {
-       struct lock_file shallow_lock = LOCK_INIT;
+       struct shallow_lock shallow_lock = SHALLOW_LOCK_INIT;
        struct strbuf sb = STRBUF_INIT;
        unsigned flags = SEEN_ONLY;
        int fd;
@@ -414,14 +428,14 @@ void prune_shallow(unsigned options)
                strbuf_release(&sb);
                return;
        }
-       fd = hold_lock_file_for_update(&shallow_lock,
+       fd = hold_lock_file_for_update(&shallow_lock.lock,
                                       git_path_shallow(the_repository),
                                       LOCK_DIE_ON_ERROR);
        check_shallow_file_for_update(the_repository);
        if (write_shallow_commits_1(&sb, 0, NULL, flags)) {
                if (write_in_full(fd, sb.buf, sb.len) < 0)
                        die_errno("failed to write to %s",
-                                 get_lock_file_path(&shallow_lock));
+                                 get_lock_file_path(&shallow_lock.lock));
                commit_shallow_file(the_repository, &shallow_lock);
        } else {
                unlink(git_path_shallow(the_repository));
diff --git a/shallow.h b/shallow.h
new file mode 100644 (file)
index 0000000..5b4a96d
--- /dev/null
+++ b/shallow.h
@@ -0,0 +1,81 @@
+#ifndef SHALLOW_H
+#define SHALLOW_H
+
+#include "lockfile.h"
+#include "object.h"
+#include "repository.h"
+#include "strbuf.h"
+
+void set_alternate_shallow_file(struct repository *r, const char *path, int override);
+int register_shallow(struct repository *r, const struct object_id *oid);
+int unregister_shallow(const struct object_id *oid);
+int is_repository_shallow(struct repository *r);
+
+/*
+ * Lock for updating the $GIT_DIR/shallow file.
+ *
+ * Use `commit_shallow_file()` to commit an update, or
+ * `rollback_shallow_file()` to roll it back. In either case, any
+ * in-memory cached information about which commits are shallow will be
+ * appropriately invalidated so that future operations reflect the new
+ * state.
+ */
+struct shallow_lock {
+       struct lock_file lock;
+};
+#define SHALLOW_LOCK_INIT { LOCK_INIT }
+
+/* commit $GIT_DIR/shallow and reset stat-validity checks */
+int commit_shallow_file(struct repository *r, struct shallow_lock *lk);
+/* rollback $GIT_DIR/shallow and reset stat-validity checks */
+void rollback_shallow_file(struct repository *r, struct shallow_lock *lk);
+
+struct commit_list *get_shallow_commits(struct object_array *heads,
+                                       int depth, int shallow_flag, int not_shallow_flag);
+struct commit_list *get_shallow_commits_by_rev_list(
+               int ac, const char **av, int shallow_flag, int not_shallow_flag);
+int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
+                         const struct oid_array *extra);
+
+void setup_alternate_shallow(struct shallow_lock *shallow_lock,
+                            const char **alternate_shallow_file,
+                            const struct oid_array *extra);
+
+const char *setup_temporary_shallow(const struct oid_array *extra);
+
+void advertise_shallow_grafts(int);
+
+#define PRUNE_SHOW_ONLY 1
+#define PRUNE_QUICK 2
+void prune_shallow(unsigned options);
+
+/*
+ * Initialize with prepare_shallow_info() or zero-initialize (equivalent to
+ * prepare_shallow_info with a NULL oid_array).
+ */
+struct shallow_info {
+       struct oid_array *shallow;
+       int *ours, nr_ours;
+       int *theirs, nr_theirs;
+       struct oid_array *ref;
+
+       /* for receive-pack */
+       uint32_t **used_shallow;
+       int *need_reachability_test;
+       int *reachable;
+       int *shallow_ref;
+       struct commit **commits;
+       int nr_commits;
+};
+
+void prepare_shallow_info(struct shallow_info *, struct oid_array *);
+void clear_shallow_info(struct shallow_info *);
+void remove_nonexistent_theirs_shallow(struct shallow_info *);
+void assign_shallow_commits_to_refs(struct shallow_info *info,
+                                   uint32_t **used,
+                                   int *ref_status);
+int delayed_reachability_test(struct shallow_info *si, int c);
+
+extern struct trace_key trace_shallow;
+
+#endif /* SHALLOW_H */
index 80c53edca7af46556e50aa64c0fdfb912cae6a70..b3e725f0310a7b4d8343089de922c7eb6d148a52 100755 (executable)
@@ -53,6 +53,11 @@ test_perf 'rev-list count with blob:limit=1k' '
                --filter=blob:limit=1k >/dev/null
 '
 
+test_perf 'rev-list count with tree:0' '
+       git rev-list --use-bitmap-index --count --objects --all \
+               --filter=tree:0 >/dev/null
+'
+
 test_perf 'simulated partial clone' '
        git pack-objects --stdout --all --filter=blob:none </dev/null >/dev/null
 '
@@ -86,4 +91,9 @@ test_perf 'pack to file (partial bitmap)' '
        git pack-objects --use-bitmap-index --all pack2b </dev/null >/dev/null
 '
 
+test_perf 'rev-list with tree filter (partial bitmap)' '
+       git rev-list --use-bitmap-index --count --objects --all \
+               --filter=tree:0 >/dev/null
+'
+
 test_done
index f58f3deaa8372480980410e4ee8d3d19f94b9e46..2ff176cd5d954cb1c83f062adbdb28a7e14d2668 100755 (executable)
@@ -77,9 +77,7 @@ _run_sub_test_lib_test_common () {
                # the sub-test.
                sane_unset HARNESS_ACTIVE &&
                cd "$name" &&
-               cat >"$name.sh" <<-EOF &&
-               #!$SHELL_PATH
-
+               write_script "$name.sh" "$TEST_SHELL_PATH" <<-EOF &&
                test_description='$descr (run in sub test-lib)
 
                This is run in a sub test-lib so that we do not get incorrect
@@ -94,7 +92,6 @@ _run_sub_test_lib_test_common () {
                . "\$TEST_DIRECTORY"/test-lib.sh
                EOF
                cat >>"$name.sh" &&
-               chmod +x "$name.sh" &&
                export TEST_DIRECTORY &&
                TEST_OUTPUT_DIRECTORY=$(pwd) &&
                export TEST_OUTPUT_DIRECTORY &&
@@ -103,7 +100,7 @@ _run_sub_test_lib_test_common () {
                then
                        ./"$name.sh" "$@" >out 2>err
                else
-                       !  ./"$name.sh" "$@" >out 2>err
+                       ! ./"$name.sh" "$@" >out 2>err
                fi
        )
 }
index d6b54e8c65a3ec4408fe07ee76a6d8bed957207a..716bf1af9fd04e64b7d5c03570b5ba74a8529d46 100755 (executable)
@@ -107,7 +107,6 @@ test_expect_success 'store: if both xdg and home files exist, only store in home
        test_must_be_empty "$HOME/.config/git/credentials"
 '
 
-
 test_expect_success 'erase: erase matching credentials from both xdg and home files' '
        echo "https://home-user:home-pass@example.com" >"$HOME/.git-credentials" &&
        mkdir -p "$HOME/.config/git" &&
@@ -120,4 +119,94 @@ test_expect_success 'erase: erase matching credentials from both xdg and home fi
        test_must_be_empty "$HOME/.config/git/credentials"
 '
 
+invalid_credential_test() {
+       test_expect_success "get: ignore credentials without $1 as invalid" '
+               echo "$2" >"$HOME/.git-credentials" &&
+               check fill store <<-\EOF
+               protocol=https
+               host=example.com
+               --
+               protocol=https
+               host=example.com
+               username=askpass-username
+               password=askpass-password
+               --
+               askpass: Username for '\''https://example.com'\'':
+               askpass: Password for '\''https://askpass-username@example.com'\'':
+               --
+               EOF
+       '
+}
+
+invalid_credential_test "scheme" ://user:pass@example.com
+invalid_credential_test "valid host/path" https://user:pass@
+invalid_credential_test "username/password" https://pass@example.com
+
+test_expect_success 'get: credentials with DOS line endings are invalid' '
+       printf "https://user:pass@example.com\r\n" >"$HOME/.git-credentials" &&
+       check fill store <<-\EOF
+       protocol=https
+       host=example.com
+       --
+       protocol=https
+       host=example.com
+       username=askpass-username
+       password=askpass-password
+       --
+       askpass: Username for '\''https://example.com'\'':
+       askpass: Password for '\''https://askpass-username@example.com'\'':
+       --
+       EOF
+'
+
+test_expect_success 'get: credentials with path and DOS line endings are valid' '
+       printf "https://user:pass@example.com/repo.git\r\n" >"$HOME/.git-credentials" &&
+       check fill store <<-\EOF
+       url=https://example.com/repo.git
+       --
+       protocol=https
+       host=example.com
+       username=user
+       password=pass
+       --
+       EOF
+'
+
+test_expect_success 'get: credentials with DOS line endings are invalid if path is relevant' '
+       printf "https://user:pass@example.com/repo.git\r\n" >"$HOME/.git-credentials" &&
+       test_config credential.useHttpPath true &&
+       check fill store <<-\EOF
+       url=https://example.com/repo.git
+       --
+       protocol=https
+       host=example.com
+       path=repo.git
+       username=askpass-username
+       password=askpass-password
+       --
+       askpass: Username for '\''https://example.com/repo.git'\'':
+       askpass: Password for '\''https://askpass-username@example.com/repo.git'\'':
+       --
+       EOF
+'
+
+test_expect_success 'get: store file can contain empty/bogus lines' '
+       echo "" >"$HOME/.git-credentials" &&
+       q_to_tab <<-\CREDENTIAL >>"$HOME/.git-credentials" &&
+       #comment
+       Q
+       https://user:pass@example.com
+       CREDENTIAL
+       check fill store <<-\EOF
+       protocol=https
+       host=example.com
+       --
+       protocol=https
+       host=example.com
+       username=user
+       password=pass
+       --
+       EOF
+'
+
 test_done
index 63223e13bd1bd20d2539a3e577a84c47416b5ed5..140f45997736c0ead2d059183881a5cbf2c96758 100755 (executable)
@@ -74,13 +74,19 @@ test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-
 test_expect_success 'read-tree with empty .git/info/sparse-checkout' '
        git config core.sparsecheckout true &&
        echo >.git/info/sparse-checkout &&
-       read_tree_u_must_fail -m -u HEAD &&
+       read_tree_u_must_succeed -m -u HEAD &&
        git ls-files --stage >result &&
        test_cmp expected result &&
        git ls-files -t >result &&
+       cat >expected.swt <<-\EOF &&
+       S init.t
+       S sub/added
+       S sub/addedtoo
+       S subsub/added
+       EOF
        test_cmp expected.swt result &&
-       test -f init.t &&
-       test -f sub/added
+       test -f init.t &&
+       test -f sub/added
 '
 
 test_expect_success 'match directories with trailing slash' '
index dee99eeec305ea77b9d6ad9cdd904409e157da85..88cdde255cdad7a0b138033b3ff9a997e4a2c0b2 100755 (executable)
@@ -106,10 +106,8 @@ test_expect_success 'set enables config' '
                cd empty-config &&
                test_commit test file &&
                test_path_is_missing .git/config.worktree &&
-               test_must_fail git sparse-checkout set nothing &&
+               git sparse-checkout set nothing &&
                test_path_is_file .git/config.worktree &&
-               test_must_fail git config core.sparseCheckout &&
-               git sparse-checkout set "/*" &&
                test_cmp_config true core.sparseCheckout
        )
 '
@@ -302,8 +300,8 @@ test_expect_success 'revert to old sparse-checkout on empty update' '
                echo >file &&
                git add file &&
                git commit -m "test" &&
-               test_must_fail git sparse-checkout set nothing 2>err &&
-               test_i18ngrep "Sparse checkout leaves no entry on working directory" err &&
+               git sparse-checkout set nothing 2>err &&
+               test_i18ngrep "Sparse checkout leaves no entry on working directory" err &&
                test_i18ngrep ! ".git/index.lock" err &&
                git sparse-checkout set file
        )
index 076d0df7fc0602e8d47c03ffa6ddb6dff0b985a9..89e5a142c9e2284ca7931560af50074b0d6e6c8e 100755 (executable)
@@ -69,6 +69,17 @@ test_expect_success 'restore --staged uses HEAD as source' '
        test_cmp expected actual
 '
 
+test_expect_success 'restore --worktree --staged uses HEAD as source' '
+       test_when_finished git reset --hard &&
+       git show HEAD:./first.t >expected &&
+       echo dirty >>first.t &&
+       git add first.t &&
+       git restore --worktree --staged first.t &&
+       git show :./first.t >actual &&
+       test_cmp expected actual &&
+       test_cmp expected first.t
+'
+
 test_expect_success 'restore --ignore-unmerged ignores unmerged entries' '
        git init unmerged &&
        (
index 02255a08bf1718659f9815e37644c07a196ab850..9d077975791c1c002b4a927dfae71de594c8855f 100755 (executable)
@@ -38,6 +38,7 @@ diffpatterns="
        golang
        html
        java
+       markdown
        matlab
        objc
        pascal
diff --git a/t/t4018/markdown-heading-indented b/t/t4018/markdown-heading-indented
new file mode 100644 (file)
index 0000000..1991c2b
--- /dev/null
@@ -0,0 +1,6 @@
+Indented headings are allowed, as long as the indent is no more than 3 spaces.
+
+   ### RIGHT
+
+- something
+- ChangeMe
diff --git a/t/t4018/markdown-heading-non-headings b/t/t4018/markdown-heading-non-headings
new file mode 100644 (file)
index 0000000..c479c1a
--- /dev/null
@@ -0,0 +1,17 @@
+Headings can be right next to other lines of the file:
+# RIGHT
+Indents of four or more spaces make a code block:
+
+    # code comment, not heading
+
+If there's no space after the final hash, it's not a heading:
+
+#hashtag
+
+Sequences of more than 6 hashes don't make a heading:
+
+####### over-enthusiastic heading
+
+So the detected heading should be right up at the start of this file.
+
+ChangeMe
index 145603f124574cb209155dd643fdc555685a79fa..2b551e6fd0ce1d6706334eaa2a65cda7f9e56618 100755 (executable)
@@ -53,4 +53,25 @@ test_expect_success 'blob:limit filter with specified blob' '
        test_bitmap_traversal expect actual
 '
 
+test_expect_success 'tree:0 filter' '
+       git rev-list --objects --filter=tree:0 HEAD >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter=tree:0 HEAD >actual &&
+       test_bitmap_traversal expect actual
+'
+
+test_expect_success 'tree:0 filter with specified blob, tree' '
+       git rev-list --objects --filter=tree:0 HEAD HEAD:two.t >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter=tree:0 HEAD HEAD:two.t >actual &&
+       test_bitmap_traversal expect actual
+'
+
+test_expect_success 'tree:1 filter' '
+       git rev-list --objects --filter=tree:1 HEAD >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter=tree:1 HEAD >actual &&
+       test_cmp expect actual
+'
+
 test_done
index b3c1092338a89831206163275e32190a5e162cbd..da59fadc5d8f915cbb60cd426c58becb04e7c42a 100755 (executable)
@@ -650,17 +650,59 @@ test_atom refs/tags/signed-long contents "subject line
 body contents
 $sig"
 
-sort >expected <<EOF
-$(git rev-parse refs/tags/bogo) <committer@example.com> refs/tags/bogo
-$(git rev-parse refs/tags/master) <committer@example.com> refs/tags/master
-EOF
+test_expect_success 'set up multiple-sort tags' '
+       for when in 100000 200000
+       do
+               for email in user1 user2
+               do
+                       for ref in ref1 ref2
+                       do
+                               GIT_COMMITTER_DATE="@$when +0000" \
+                               GIT_COMMITTER_EMAIL="$email@example.com" \
+                               git tag -m "tag $ref-$when-$email" \
+                               multi-$ref-$when-$email || return 1
+                       done
+               done
+       done
+'
 
 test_expect_success 'Verify sort with multiple keys' '
-       git for-each-ref --format="%(objectname) %(taggeremail) %(refname)" --sort=objectname --sort=taggeremail \
-               refs/tags/bogo refs/tags/master > actual &&
+       cat >expected <<-\EOF &&
+       100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+       100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+       100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+       100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+       200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+       200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+       200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+       200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+       EOF
+       git for-each-ref \
+               --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+               --sort=-refname \
+               --sort=taggeremail \
+               --sort=taggerdate \
+               "refs/tags/multi-*" >actual &&
        test_cmp expected actual
 '
 
+test_expect_success 'equivalent sorts fall back on refname' '
+       cat >expected <<-\EOF &&
+       100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+       100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+       100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+       100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+       200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+       200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+       200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+       200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+       EOF
+       git for-each-ref \
+               --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+               --sort=taggerdate \
+               "refs/tags/multi-*" >actual &&
+       test_cmp expected actual
+'
 
 test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
        test_when_finished "git checkout master" &&
@@ -895,4 +937,44 @@ test_expect_success 'for-each-ref --ignore-case ignores case' '
        test_cmp expect actual
 '
 
+test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' '
+       # name refs numerically to avoid case-insensitive filesystem conflicts
+       nr=0 &&
+       for email in a A b B
+       do
+               for subject in a A b B
+               do
+                       GIT_COMMITTER_EMAIL="$email@example.com" \
+                       git tag -m "tag $subject" icase-$(printf %02d $nr) &&
+                       nr=$((nr+1))||
+                       return 1
+               done
+       done &&
+       git for-each-ref --ignore-case \
+               --format="%(taggeremail) %(subject) %(refname)" \
+               --sort=refname \
+               --sort=subject \
+               --sort=taggeremail \
+               refs/tags/icase-* >actual &&
+       cat >expect <<-\EOF &&
+       <a@example.com> tag a refs/tags/icase-00
+       <a@example.com> tag A refs/tags/icase-01
+       <A@example.com> tag a refs/tags/icase-04
+       <A@example.com> tag A refs/tags/icase-05
+       <a@example.com> tag b refs/tags/icase-02
+       <a@example.com> tag B refs/tags/icase-03
+       <A@example.com> tag b refs/tags/icase-06
+       <A@example.com> tag B refs/tags/icase-07
+       <b@example.com> tag a refs/tags/icase-08
+       <b@example.com> tag A refs/tags/icase-09
+       <B@example.com> tag a refs/tags/icase-12
+       <B@example.com> tag A refs/tags/icase-13
+       <b@example.com> tag b refs/tags/icase-10
+       <b@example.com> tag B refs/tags/icase-11
+       <B@example.com> tag b refs/tags/icase-14
+       <B@example.com> tag B refs/tags/icase-15
+       EOF
+       test_cmp expect actual
+'
+
 test_done
index 1b221951a8e78da99dbec41047a6d9274d686f76..baf94546da10b369ba1f96d5d40b8ae43dfafe57 100644 (file)
@@ -677,14 +677,16 @@ die () {
 
 file_lineno () {
        test -z "$GIT_TEST_FRAMEWORK_SELFTEST" && test -n "$BASH" || return 0
-       local i
-       for i in ${!BASH_SOURCE[*]}
-       do
-               case $i,"${BASH_SOURCE[$i]##*/}" in
-               0,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:$LINENO: ${1+$1: }"; return;;
-               *,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:${BASH_LINENO[$(($i-1))]}: ${1+$1: }"; return;;
-               esac
-       done
+       eval '
+               local i
+               for i in ${!BASH_SOURCE[*]}
+               do
+                       case $i,"${BASH_SOURCE[$i]##*/}" in
+                       0,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:$LINENO: ${1+$1: }"; return;;
+                       *,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:${BASH_LINENO[$(($i-1))]}: ${1+$1: }"; return;;
+                       esac
+               done
+       '
 }
 
 GIT_EXIT_OK=
index 6bbf58d28eaefb5428f0198e8da897f08bcec94c..1fe3764f2b217263d00332bcca203f0c9ef6ee5f 100644 (file)
@@ -1677,8 +1677,6 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        }
 
        if (!o->skip_sparse_checkout) {
-               int empty_worktree = 1;
-
                /*
                 * Sparse checkout loop #2: set NEW_SKIP_WORKTREE on entries not in loop #1
                 * If they will have NEW_SKIP_WORKTREE, also set CE_SKIP_WORKTREE
@@ -1706,19 +1704,6 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 
                        if (apply_sparse_checkout(&o->result, ce, o))
                                ret = 1;
-
-                       if (!ce_skip_worktree(ce))
-                               empty_worktree = 0;
-               }
-               /*
-                * Sparse checkout is meant to narrow down checkout area
-                * but it does not make sense to narrow down to empty working
-                * tree. This is usually a mistake in sparse checkout rules.
-                * Do not allow users to do that.
-                */
-               if (o->result.cache_nr && empty_worktree) {
-                       ret = unpack_failed(o, "Sparse checkout leaves no entry on working directory");
-                       goto done;
                }
                if (ret == 1) {
                        /*
@@ -1779,7 +1764,7 @@ enum update_sparsity_result update_sparsity(struct unpack_trees_options *o)
 {
        enum update_sparsity_result ret = UPDATE_SPARSITY_SUCCESS;
        struct pattern_list pl;
-       int i, empty_worktree;
+       int i;
        unsigned old_show_all_errors;
        int free_pattern_list = 0;
 
@@ -1810,7 +1795,6 @@ enum update_sparsity_result update_sparsity(struct unpack_trees_options *o)
 
        /* Then loop over entries and update/remove as needed */
        ret = UPDATE_SPARSITY_SUCCESS;
-       empty_worktree = 1;
        for (i = 0; i < o->src_index->cache_nr; i++) {
                struct cache_entry *ce = o->src_index->cache[i];
 
@@ -1824,28 +1808,12 @@ enum update_sparsity_result update_sparsity(struct unpack_trees_options *o)
 
                if (apply_sparse_checkout(o->src_index, ce, o))
                        ret = UPDATE_SPARSITY_WARNINGS;
-
-               if (!ce_skip_worktree(ce))
-                       empty_worktree = 0;
-       }
-
-       /*
-        * Sparse checkout is meant to narrow down checkout area
-        * but it does not make sense to narrow down to empty working
-        * tree. This is usually a mistake in sparse checkout rules.
-        * Do not allow users to do that.
-        */
-       if (o->src_index->cache_nr && empty_worktree) {
-               unpack_failed(o, "Sparse checkout leaves no entry on working directory");
-               ret = UPDATE_SPARSITY_INDEX_UPDATE_FAILURES;
-               goto done;
        }
 
 skip_sparse_checkout:
        if (check_updates(o, o->src_index))
                ret = UPDATE_SPARSITY_WORKTREE_UPDATE_FAILURES;
 
-done:
        display_warning_msgs(o);
        o->show_all_errors = old_show_all_errors;
        if (free_pattern_list)
index 902d0ad5e157fde33ec013476086740946e285df..613a960624bb731b7ef2645334bd30505ced2b82 100644 (file)
@@ -26,6 +26,7 @@
 #include "serve.h"
 #include "commit-graph.h"
 #include "commit-reach.h"
+#include "shallow.h"
 
 /* Remember to update object flag allocation in object.h */
 #define THEY_HAVE      (1u << 11)
index 30ab42df8ef2b0a93b007b5afb484ccd4102c3b0..1df884ef0bbfbba5a751eafc1922369ad818fce5 100644 (file)
@@ -79,6 +79,9 @@ PATTERNS("java",
         "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
         "|[-+*/<>%&^|=!]="
         "|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|"),
+PATTERNS("markdown",
+        "^ {0,3}#{1,6}[ \t].*",
+        "[^<>= \t]+"),
 PATTERNS("matlab",
         /*
          * Octave pattern is mostly the same as matlab, except that '%%%' and