From 0ffb5a6bf1b0fd9ce0c0b1fd9ce9fd30b89a2563 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Fri, 15 Nov 2024 00:54:04 +0000 Subject: Allow cloning from repositories owned by another user Historically, Git has allowed users to clone from an untrusted repository, and we have documented that this is safe to do so: `upload-pack` tries to avoid any dangerous configuration options or hooks from the repository it's serving, making it safe to clone an untrusted directory and run commands on the resulting clone. However, this was broken by f4aa8c8bb1 ("fetch/clone: detect dubious ownership of local repositories", 2024-04-10) in an attempt to make things more secure. That change resulted in a variety of problems when cloning locally and over SSH, but it did not change the stated security boundary. Because the security boundary has not changed, it is safe to adjust part of the code that patch introduced. To do that and restore the previous functionality, adjust enter_repo to take two flags instead of one. The two bits are - ENTER_REPO_STRICT: callers that require exact paths (as opposed to allowing known suffixes like ".git", ".git/.git" to be omitted) can set this bit. Corresponds to the "strict" parameter that the flags word replaces. - ENTER_REPO_ANY_OWNER_OK: callers that are willing to run without ownership check can set this bit. The former is --strict-paths option of "git daemon". The latter is set only by upload-pack, which honors the claimed security boundary. Note that local clones across ownership boundaries require --no-local so that upload-pack is used. Document this fact in the manual page and provide an example. This patch was based on one written by Junio C Hamano. Signed-off-by: Junio C Hamano --- Documentation/git-clone.txt | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'Documentation') diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 6e43eb9c20..5347cc5255 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -63,6 +63,9 @@ symbolic link, the clone will fail. This is a security measure to prevent the unintentional copying of files by dereferencing the symbolic links. + +This option does not work with repositories owned by other users for security +reasons, and `--no-local` must be specified for the clone to succeed. ++ *NOTE*: this operation can race with concurrent modification to the source repository, similar to running `cp -r src dst` while modifying `src`. @@ -381,6 +384,12 @@ $ cd my-linux $ git clone --bare -l /home/proj/.git /pub/scm/proj.git ------------ +* Clone a local repository from a different user: ++ +------------ +$ git clone --no-local /home/otheruser/proj.git /pub/scm/proj.git +------------ + CONFIGURATION ------------- -- cgit v1.3 From 1bc1e940918cd44cc78bff1dfd518e16fc5bad57 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 25 Nov 2024 12:14:01 +0900 Subject: doc: option value may be separate for valid reasons Even though `git help cli` recommends users to prefer using "--option=value" over "--option value", there can be reasons why giving them separately is a good idea. One reason is that shells do not perform tilde expansion for `--option=~/path/name` but they expand `--options ~/path/name` just fine. This is not a problem for many options whose option parsing is properly written using OPT_FILENAME(), because the value given to OPT_FILENAME() is tilde-expanded internally by us, but some commands take a pathname as a mere string, which needs this trick to have the shell help us. I think the reason we originally decided to recommend the stuck form was because an option that takes an optional value requires you to use it in the stuck form, and it is one less thing for users to worry about if they get into the habit to always use the stuck form. But we should be discouraging ourselves from adding an option with an optional value in the first place, and we might want to weaken the current recommendation. In any case, let's describe this one case where it is necessary to use the separate form, with an example. Reviewed-by: Eric Sunshine Signed-off-by: Junio C Hamano --- Documentation/gitcli.txt | 9 +++++++++ Documentation/gitcredentials.txt | 6 ++++++ 2 files changed, 15 insertions(+) (limited to 'Documentation') diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt index 7c709324ba..bd62cbd043 100644 --- a/Documentation/gitcli.txt +++ b/Documentation/gitcli.txt @@ -90,6 +90,15 @@ scripting Git: for long options. An option that takes optional option-argument must be written in the 'stuck' form. + * Despite the above suggestion, when Arg is a path relative to the + home directory of a user, e.g. ~/directory/file or ~u/d/f, you + may want to use the separate form, e.g. `git foo --file ~/mine`, + not `git foo --file=~/mine`. The shell will expand `~/` in the + former to your home directory, but most shells keep the tilde in + the latter. Some of our commands know how to tilde-expand the + option value even when given in the stuck form, but not all of + them do. + * When you give a revision parameter to a command, make sure the parameter is not ambiguous with a name of a file in the work tree. E.g. do not write `git log -1 HEAD` but write `git log -1 HEAD --`; the former will not work diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.txt index 71dd19731a..35a7452c8f 100644 --- a/Documentation/gitcredentials.txt +++ b/Documentation/gitcredentials.txt @@ -242,6 +242,12 @@ Here are some example specifications: [credential] helper = "foo --bar='whitespace arg'" +# store helper (discouraged) with custom location for the db file; +# use `--file ~/.git-secret.txt`, rather than `--file=~/.git-secret.txt`, +# to allow the shell to expand tilde to the home directory. +[credential] + helper = "store --file ~/.git-secret.txt" + # you can also use an absolute path, which will not use the git wrapper [credential] helper = "/path/to/my/helper --with-arguments" -- cgit v1.3 From 7725b8100ffbbff2750ee4d61a0fcc1f53a086e8 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 13:26:10 +0100 Subject: credential: sanitize the user prompt When asking the user interactively for credentials, we want to avoid misleading them e.g. via control sequences that pretend that the URL targets a trusted host when it does not. While Git learned, over the course of the preceding commits, to disallow URLs containing URL-encoded control characters by default, credential helpers are still allowed to specify values very freely (apart from Line Feed and NUL characters, anything is allowed), and this would allow, say, a username containing control characters to be specified that would then be displayed in the interactive terminal prompt asking the user for the password, potentially sending those control characters directly to the terminal. This is undesirable because control characters can be used to mislead users to divulge secret information to untrusted sites. To prevent such an attack vector, let's add a `git_prompt()` that forces the displayed text to be sanitized, i.e. displaying question marks instead of control characters. Note: While this commit's diff changes a lot of `user@host` strings to `user%40host`, which may look suspicious on the surface, there is a good reason for that: this string specifies a user name, not a @ combination! In the context of t5541, the actual combination looks like this: `user%40@127.0.0.1:5541`. Therefore, these string replacements document a net improvement introduced by this commit, as `user@host@127.0.0.1` could have left readers wondering where the user name ends and where the host name begins. Hinted-at-by: Jeff King Signed-off-by: Johannes Schindelin --- Documentation/config/credential.txt | 6 ++++++ credential.c | 7 ++++++- credential.h | 4 +++- t/t0300-credentials.sh | 20 ++++++++++++++++++++ t/t5541-http-push-smart.sh | 6 +++--- t/t5550-http-fetch-dumb.sh | 14 +++++++------- t/t5551-http-fetch-smart.sh | 16 ++++++++-------- 7 files changed, 53 insertions(+), 20 deletions(-) (limited to 'Documentation') diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt index 512f31876e..fd8113d6d4 100644 --- a/Documentation/config/credential.txt +++ b/Documentation/config/credential.txt @@ -14,6 +14,12 @@ credential.useHttpPath:: or https URL to be important. Defaults to false. See linkgit:gitcredentials[7] for more information. +credential.sanitizePrompt:: + By default, user names and hosts that are shown as part of the + password prompt are not allowed to contain control characters (they + will be URL-encoded by default). Configure this setting to `false` to + override that behavior. + credential.username:: If no username is set for a network authentication, use this username by default. See credential..* below, and diff --git a/credential.c b/credential.c index 572f1785da..1392a54d5c 100644 --- a/credential.c +++ b/credential.c @@ -67,6 +67,8 @@ static int credential_config_callback(const char *var, const char *value, } else if (!strcmp(key, "usehttppath")) c->use_http_path = git_config_bool(var, value); + else if (!strcmp(key, "sanitizeprompt")) + c->sanitize_prompt = git_config_bool(var, value); return 0; } @@ -179,7 +181,10 @@ static char *credential_ask_one(const char *what, struct credential *c, struct strbuf prompt = STRBUF_INIT; char *r; - credential_describe(c, &desc); + if (c->sanitize_prompt) + credential_format(c, &desc); + else + credential_describe(c, &desc); if (desc.len) strbuf_addf(&prompt, "%s for '%s': ", what, desc.buf); else diff --git a/credential.h b/credential.h index 935b28a70f..0364d436d2 100644 --- a/credential.h +++ b/credential.h @@ -119,7 +119,8 @@ struct credential { configured:1, quit:1, use_http_path:1, - username_from_proto:1; + username_from_proto:1, + sanitize_prompt:1; char *username; char *password; @@ -132,6 +133,7 @@ struct credential { #define CREDENTIAL_INIT { \ .helpers = STRING_LIST_INIT_DUP, \ .password_expiry_utc = TIME_MAX, \ + .sanitize_prompt = 1, \ } /* Initialize a credential structure, setting all fields to empty. */ diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index cb91be1427..b62c70c193 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -45,6 +45,10 @@ test_expect_success 'setup helper scripts' ' test -z "$pexpiry" || echo password_expiry_utc=$pexpiry EOF + write_script git-credential-cntrl-in-username <<-\EOF && + printf "username=\\007latrix Lestrange\\n" + EOF + PATH="$PWD:$PATH" ' @@ -825,4 +829,20 @@ test_expect_success 'credential config with partial URLs' ' test_i18ngrep "skipping credential lookup for key" stderr ' +BEL="$(printf '\007')" + +test_expect_success 'interactive prompt is sanitized' ' + check fill cntrl-in-username <<-EOF + protocol=https + host=example.org + -- + protocol=https + host=example.org + username=${BEL}latrix Lestrange + password=askpass-password + -- + askpass: Password for ${SQ}https://%07latrix%20Lestrange@example.org${SQ}: + EOF +' + test_done diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index d0211cd8be..2cd2e1a059 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -351,7 +351,7 @@ test_expect_success 'push over smart http with auth' ' git push "$HTTPD_URL"/auth/smart/test_repo.git && git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \ log -1 --format=%s >actual && - expect_askpass both user@host && + expect_askpass both user%40host && test_cmp expect actual ' @@ -363,7 +363,7 @@ test_expect_success 'push to auth-only-for-push repo' ' git push "$HTTPD_URL"/auth-push/smart/test_repo.git && git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \ log -1 --format=%s >actual && - expect_askpass both user@host && + expect_askpass both user%40host && test_cmp expect actual ' @@ -393,7 +393,7 @@ test_expect_success 'push into half-auth-complete requires password' ' git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" && git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \ log -1 --format=%s >actual && - expect_askpass both user@host && + expect_askpass both user%40host && test_cmp expect actual ' diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 8f182a3cbf..5d0e394609 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -90,13 +90,13 @@ test_expect_success 'http auth can use user/pass in URL' ' test_expect_success 'http auth can use just user in URL' ' set_askpass wrong pass@host && git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass && - expect_askpass pass user@host + expect_askpass pass user%40host ' test_expect_success 'http auth can request both user and pass' ' set_askpass user@host pass@host && git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both && - expect_askpass both user@host + expect_askpass both user%40host ' test_expect_success 'http auth respects credential helper config' ' @@ -114,14 +114,14 @@ test_expect_success 'http auth can get username from config' ' test_config_global "credential.$HTTPD_URL.username" user@host && set_askpass wrong pass@host && git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user && - expect_askpass pass user@host + expect_askpass pass user%40host ' test_expect_success 'configured username does not override URL' ' test_config_global "credential.$HTTPD_URL.username" wrong && set_askpass wrong pass@host && git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 && - expect_askpass pass user@host + expect_askpass pass user%40host ' test_expect_success 'set up repo with http submodules' ' @@ -142,7 +142,7 @@ test_expect_success 'cmdline credential config passes to submodule via clone' ' set_askpass wrong pass@host && git -c "credential.$HTTPD_URL.username=user@host" \ clone --recursive super super-clone && - expect_askpass pass user@host + expect_askpass pass user%40host ' test_expect_success 'cmdline credential config passes submodule via fetch' ' @@ -153,7 +153,7 @@ test_expect_success 'cmdline credential config passes submodule via fetch' ' git -C super-clone \ -c "credential.$HTTPD_URL.username=user@host" \ fetch --recurse-submodules && - expect_askpass pass user@host + expect_askpass pass user%40host ' test_expect_success 'cmdline credential config passes submodule update' ' @@ -170,7 +170,7 @@ test_expect_success 'cmdline credential config passes submodule update' ' git -C super-clone \ -c "credential.$HTTPD_URL.username=user@host" \ submodule update && - expect_askpass pass user@host + expect_askpass pass user%40host ' test_expect_success 'fetch changes via http' ' diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 0908534f25..8a27768dfb 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -181,7 +181,7 @@ test_expect_success 'clone from password-protected repository' ' echo two >expect && set_askpass user@host pass@host && git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth && - expect_askpass both user@host && + expect_askpass both user%40host && git --git-dir=smart-auth log -1 --format=%s >actual && test_cmp expect actual ' @@ -199,7 +199,7 @@ test_expect_success 'clone from auth-only-for-objects repository' ' echo two >expect && set_askpass user@host pass@host && git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth && - expect_askpass both user@host && + expect_askpass both user%40host && git --git-dir=half-auth log -1 --format=%s >actual && test_cmp expect actual ' @@ -224,14 +224,14 @@ test_expect_success 'redirects send auth to new location' ' set_askpass user@host pass@host && git -c credential.useHttpPath=true \ clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth && - expect_askpass both user@host auth/smart/repo.git + expect_askpass both user%40host auth/smart/repo.git ' test_expect_success 'GIT_TRACE_CURL redacts auth details' ' rm -rf redact-auth trace && set_askpass user@host pass@host && GIT_TRACE_CURL="$(pwd)/trace" git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth && - expect_askpass both user@host && + expect_askpass both user%40host && # Ensure that there is no "Basic" followed by a base64 string, but that # the auth details are redacted @@ -243,7 +243,7 @@ test_expect_success 'GIT_CURL_VERBOSE redacts auth details' ' rm -rf redact-auth trace && set_askpass user@host pass@host && GIT_CURL_VERBOSE=1 git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth 2>trace && - expect_askpass both user@host && + expect_askpass both user%40host && # Ensure that there is no "Basic" followed by a base64 string, but that # the auth details are redacted @@ -256,7 +256,7 @@ test_expect_success 'GIT_TRACE_CURL does not redact auth details if GIT_TRACE_RE set_askpass user@host pass@host && GIT_TRACE_REDACT=0 GIT_TRACE_CURL="$(pwd)/trace" \ git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth && - expect_askpass both user@host && + expect_askpass both user%40host && grep -i "Authorization: Basic [0-9a-zA-Z+/]" trace ' @@ -568,7 +568,7 @@ test_expect_success 'http auth remembers successful credentials' ' # the first request prompts the user... set_askpass user@host pass@host && git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null && - expect_askpass both user@host && + expect_askpass both user%40host && # ...and the second one uses the stored value rather than # prompting the user. @@ -599,7 +599,7 @@ test_expect_success 'http auth forgets bogus credentials' ' # us to prompt the user again. set_askpass user@host pass@host && git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null && - expect_askpass both user@host + expect_askpass both user%40host ' test_expect_success 'client falls back from v2 to v0 to match server' ' -- cgit v1.3 From b01b9b81d36759cdcd07305e78765199e1bc2060 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 4 Nov 2024 14:48:22 +0100 Subject: credential: disallow Carriage Returns in the protocol by default While Git has documented that the credential protocol is line-based, with newlines as terminators, the exact shape of a newline has not been documented. From Git's perspective, which is firmly rooted in the Linux ecosystem, it is clear that "a newline" means a Line Feed character. However, even Git's credential protocol respects Windows line endings (a Carriage Return character followed by a Line Feed character, "CR/LF") by virtue of using `strbuf_getline()`. There is a third category of line endings that has been used originally by MacOS, and that is respected by the default line readers of .NET and node.js: bare Carriage Returns. Git cannot handle those, and what is worse: Git's remedy against CVE-2020-5260 does not catch when credential helpers are used that interpret bare Carriage Returns as newlines. Git Credential Manager addressed this as CVE-2024-50338, but other credential helpers may still be vulnerable. So let's not only disallow Line Feed characters as part of the values in the credential protocol, but also disallow Carriage Return characters. In the unlikely event that a credential helper relies on Carriage Returns in the protocol, introduce an escape hatch via the `credential.protectProtocol` config setting. This addresses CVE-2024-52006. Signed-off-by: Johannes Schindelin --- Documentation/config/credential.txt | 5 +++++ credential.c | 21 ++++++++++++++------- credential.h | 4 +++- t/t0300-credentials.sh | 16 ++++++++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt index fd8113d6d4..9cadca7f73 100644 --- a/Documentation/config/credential.txt +++ b/Documentation/config/credential.txt @@ -20,6 +20,11 @@ credential.sanitizePrompt:: will be URL-encoded by default). Configure this setting to `false` to override that behavior. +credential.protectProtocol:: + By default, Carriage Return characters are not allowed in the protocol + that is used when Git talks to a credential helper. This setting allows + users to override this default. + credential.username:: If no username is set for a network authentication, use this username by default. See credential..* below, and diff --git a/credential.c b/credential.c index 1392a54d5c..b76a730901 100644 --- a/credential.c +++ b/credential.c @@ -69,6 +69,8 @@ static int credential_config_callback(const char *var, const char *value, c->use_http_path = git_config_bool(var, value); else if (!strcmp(key, "sanitizeprompt")) c->sanitize_prompt = git_config_bool(var, value); + else if (!strcmp(key, "protectprotocol")) + c->protect_protocol = git_config_bool(var, value); return 0; } @@ -262,7 +264,8 @@ int credential_read(struct credential *c, FILE *fp) return 0; } -static void credential_write_item(FILE *fp, const char *key, const char *value, +static void credential_write_item(const struct credential *c, + FILE *fp, const char *key, const char *value, int required) { if (!value && required) @@ -271,19 +274,23 @@ static void credential_write_item(FILE *fp, const char *key, const char *value, return; if (strchr(value, '\n')) die("credential value for %s contains newline", key); + if (c->protect_protocol && strchr(value, '\r')) + die("credential value for %s contains carriage return\n" + "If this is intended, set `credential.protectProtocol=false`", + key); fprintf(fp, "%s=%s\n", key, value); } void credential_write(const struct credential *c, FILE *fp) { - credential_write_item(fp, "protocol", c->protocol, 1); - credential_write_item(fp, "host", c->host, 1); - credential_write_item(fp, "path", c->path, 0); - credential_write_item(fp, "username", c->username, 0); - credential_write_item(fp, "password", c->password, 0); + credential_write_item(c, fp, "protocol", c->protocol, 1); + credential_write_item(c, fp, "host", c->host, 1); + credential_write_item(c, fp, "path", c->path, 0); + credential_write_item(c, fp, "username", c->username, 0); + credential_write_item(c, fp, "password", c->password, 0); if (c->password_expiry_utc != TIME_MAX) { char *s = xstrfmt("%"PRItime, c->password_expiry_utc); - credential_write_item(fp, "password_expiry_utc", s, 0); + credential_write_item(c, fp, "password_expiry_utc", s, 0); free(s); } } diff --git a/credential.h b/credential.h index 0364d436d2..2c0b39a925 100644 --- a/credential.h +++ b/credential.h @@ -120,7 +120,8 @@ struct credential { quit:1, use_http_path:1, username_from_proto:1, - sanitize_prompt:1; + sanitize_prompt:1, + protect_protocol:1; char *username; char *password; @@ -134,6 +135,7 @@ struct credential { .helpers = STRING_LIST_INIT_DUP, \ .password_expiry_utc = TIME_MAX, \ .sanitize_prompt = 1, \ + .protect_protocol = 1, \ } /* Initialize a credential structure, setting all fields to empty. */ diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index b62c70c193..168ae76550 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -720,6 +720,22 @@ test_expect_success 'url parser rejects embedded newlines' ' test_cmp expect stderr ' +test_expect_success 'url parser rejects embedded carriage returns' ' + test_config credential.helper "!true" && + test_must_fail git credential fill 2>stderr <<-\EOF && + url=https://example%0d.com/ + EOF + cat >expect <<-\EOF && + fatal: credential value for host contains carriage return + If this is intended, set `credential.protectProtocol=false` + EOF + test_cmp expect stderr && + GIT_ASKPASS=true \ + git -c credential.protectProtocol=false credential fill <<-\EOF + url=https://example%0d.com/ + EOF +' + test_expect_success 'host-less URLs are parsed as empty host' ' check fill "verbatim foo bar" <<-\EOF url=cert:///path/to/cert.pem -- cgit v1.3 From 54a3711a9dd968a04249beef157393d64b579d64 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:17:53 +0100 Subject: Git 2.40.4 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.40.4.txt | 5 +++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.40.4.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.40.4.txt b/Documentation/RelNotes/2.40.4.txt new file mode 100644 index 0000000000..0ff29f3cfc --- /dev/null +++ b/Documentation/RelNotes/2.40.4.txt @@ -0,0 +1,5 @@ +Git v2.40.4 Release Notes +========================= + +This release lets Git refuse to accept URLs that contain control +sequences. This addresses CVE-2024-50349 and CVE-2024-52006. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index b345e89cbe..4f4d294651 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.40.3 +DEF_VER=v2.40.4 LF=' ' diff --git a/RelNotes b/RelNotes index afb47e28e0..b401038a56 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.40.3.txt \ No newline at end of file +Documentation/RelNotes/2.40.4.txt \ No newline at end of file -- cgit v1.3 From 6fd641a521a722e438b291ec7b852b7bb508b18b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:27:54 +0100 Subject: Git 2.41.3 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.41.3.txt | 6 ++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.41.3.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.41.3.txt b/Documentation/RelNotes/2.41.3.txt new file mode 100644 index 0000000000..b5aba88790 --- /dev/null +++ b/Documentation/RelNotes/2.41.3.txt @@ -0,0 +1,6 @@ +Git v2.41.3 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4 to address +the security issues CVE-2024-50349 and CVE-2024-52006; see the +release notes for that version for details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 990ca9c643..664b521986 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.41.2 +DEF_VER=v2.41.3 LF=' ' diff --git a/RelNotes b/RelNotes index 04f6c71310..5bd6fdad36 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.41.2.txt \ No newline at end of file +Documentation/RelNotes/2.41.3.txt \ No newline at end of file -- cgit v1.3 From 54ddf17f827969c989576f2411d9ff519fa8091f Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:39:06 +0100 Subject: Git 2.42.4 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.42.4.txt | 6 ++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.42.4.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.42.4.txt b/Documentation/RelNotes/2.42.4.txt new file mode 100644 index 0000000000..3129d76e75 --- /dev/null +++ b/Documentation/RelNotes/2.42.4.txt @@ -0,0 +1,6 @@ +Git v2.42.4 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4 and v2.41.3 +to address the security issues CVE-2024-50349 and CVE-2024-52006; +see the release notes for these versions for details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 070d22c6d1..69948fce1b 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.42.3 +DEF_VER=v2.42.4 LF=' ' diff --git a/RelNotes b/RelNotes index 7af3372ac2..e0d3afd77a 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.42.3.txt \ No newline at end of file +Documentation/RelNotes/2.42.4.txt \ No newline at end of file -- cgit v1.3 From 664d4fa692cb8637a7c9297c94abf0de8593e585 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:52:18 +0100 Subject: Git 2.43.6 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.43.6.txt | 7 +++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.43.6.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.43.6.txt b/Documentation/RelNotes/2.43.6.txt new file mode 100644 index 0000000000..2114b9f78d --- /dev/null +++ b/Documentation/RelNotes/2.43.6.txt @@ -0,0 +1,7 @@ +Git v2.43.6 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4, v2.41.3 +and v2.42.4 to address the security issues CVE-2024-50349 and +CVE-2024-52006; see the release notes for these versions for +details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index fcaa390a61..81630dde84 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.43.5 +DEF_VER=v2.43.6 LF=' ' diff --git a/RelNotes b/RelNotes index 1abe69c298..0a9d8a03d7 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.43.5.txt \ No newline at end of file +Documentation/RelNotes/2.43.6.txt \ No newline at end of file -- cgit v1.3 From 2f323bb16219c105e0c576ea4c2ece9863f5d926 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:55:00 +0100 Subject: Git 2.44.3 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.44.3.txt | 7 +++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.44.3.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.44.3.txt b/Documentation/RelNotes/2.44.3.txt new file mode 100644 index 0000000000..5862845458 --- /dev/null +++ b/Documentation/RelNotes/2.44.3.txt @@ -0,0 +1,7 @@ +Git v2.44.3 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4, v2.41.3, +v2.42.4 and v2.43.6 to address the security issues CVE-2024-50349 +and CVE-2024-52006; see the release notes for these versions +for details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 9c631da5ce..33476e262d 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.44.2 +DEF_VER=v2.44.3 LF=' ' diff --git a/RelNotes b/RelNotes index 6ba9e6f4ce..509eba5f1a 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.44.2.txt \ No newline at end of file +Documentation/RelNotes/2.44.3.txt \ No newline at end of file -- cgit v1.3 From fc16eb306c2ad25c080612ae85fdeba1fbcbfc98 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:59:32 +0100 Subject: Git 2.45.3 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.45.3.txt | 7 ++++++- GIT-VERSION-GEN | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.45.3.txt b/Documentation/RelNotes/2.45.3.txt index 2a1e9aa608..ddb3cb694b 100644 --- a/Documentation/RelNotes/2.45.3.txt +++ b/Documentation/RelNotes/2.45.3.txt @@ -1,7 +1,12 @@ Git v2.45.3 Release Notes ========================= -This primarily is to backport various small fixes accumulated on the +This release merges up the fix that appears in v2.40.4, v2.41.3, +v2.42.4, v2.43.6 and v2.44.3 to address the security issues +CVE-2024-50349 and CVE-2024-52006; see the release notes for +these versions for details. + +This version also backports various small fixes accumulated on the 'master' front during the development towards Git 2.46, the next feature release. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index eb53b0ee01..f7c5d8f070 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.45.2 +DEF_VER=v2.45.3 LF=' ' -- cgit v1.3 From 5c21db3a0d5f4414b65e114ca21c5a1fe736f2bc Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 01:03:46 +0100 Subject: Git 2.46.3 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.46.3.txt | 6 ++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.46.3.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.46.3.txt b/Documentation/RelNotes/2.46.3.txt new file mode 100644 index 0000000000..4af032b63c --- /dev/null +++ b/Documentation/RelNotes/2.46.3.txt @@ -0,0 +1,6 @@ +Git v2.46.3 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4, v2.41.3, v2.42.4, +v2.43.6, v2.44.3 and v2.45.3 to address the security issues CVE-2024-50349 and +CVE-2024-52006; see the release notes for these versions for details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 05fa12fec7..7cde816ede 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.46.2 +DEF_VER=v2.46.3 LF=' ' diff --git a/RelNotes b/RelNotes index 0dfe046c88..686ec8709b 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.46.2.txt \ No newline at end of file +Documentation/RelNotes/2.46.3.txt \ No newline at end of file -- cgit v1.3 From e1fbebe347426ef7974dc2198f8a277b7c31c8fe Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 01:12:43 +0100 Subject: Git 2.47.2 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.47.2.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Documentation/RelNotes/2.47.2.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.47.2.txt b/Documentation/RelNotes/2.47.2.txt new file mode 100644 index 0000000000..7a52ad8cb4 --- /dev/null +++ b/Documentation/RelNotes/2.47.2.txt @@ -0,0 +1,7 @@ +Git v2.47.2 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4, v2.41.3, +v2.42.4, v2.43.6, v2.44.3, v2.45.3 and v2.46.3 to address the +security issues CVE-2024-50349 and CVE-2024-52006; see the release +notes for these versions for details. -- cgit v1.3 From 168ebb7159584df425797dd13d8d8986dc08051e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 27 Nov 2024 22:23:45 +0900 Subject: CodingGuidelines: a handful of error message guidelines It is more efficient to have something in the coding guidelines document to point at, when we want to review and comment on a new message in the codebase to make sure it "fits" in the set of existing messages. Let's write down established best practice we are aware of. Helped-by: Eric Sunshine Signed-off-by: Junio C Hamano --- Documentation/CodingGuidelines | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index 3263245b03..31714227ca 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -689,16 +689,30 @@ Program Output Error Messages - - Do not end error messages with a full stop. + - Do not end a single-sentence error message with a full stop. - Do not capitalize the first word, only because it is the first word - in the message ("unable to open %s", not "Unable to open %s"). But + in the message ("unable to open '%s'", not "Unable to open '%s'"). But "SHA-3 not supported" is fine, because the reason the first word is capitalized is not because it is at the beginning of the sentence, but because the word would be spelled in capital letters even when it appeared in the middle of the sentence. - - Say what the error is first ("cannot open %s", not "%s: cannot open") + - Say what the error is first ("cannot open '%s'", not "%s: cannot open"). + + - Enclose the subject of an error inside a pair of single quotes, + e.g. `die(_("unable to open '%s'"), path)`. + + - Unless there is a compelling reason not to, error messages from + porcelain commands should be marked for translation, e.g. + `die(_("bad revision %s"), revision)`. + + - Error messages from the plumbing commands are sometimes meant for + machine consumption and should not be marked for translation, + e.g., `die("bad revision %s", revision)`. + + - BUG("message") are for communicating the specific error to developers, + thus should not be translated. Externally Visible Names -- cgit v1.3 From 1860ba1a2a96c587fca1c294d8288accf9554096 Mon Sep 17 00:00:00 2001 From: Caleb White Date: Fri, 29 Nov 2024 22:22:34 +0000 Subject: worktree: add `relativeWorktrees` extension A new extension, `relativeWorktrees`, is added to indicate that at least one worktree in the repository has been linked with relative paths. This ensures older Git versions do not attempt to automatically prune worktrees with relative paths, as they would not not recognize the paths as being valid. Suggested-by: Junio C Hamano Signed-off-by: Caleb White Signed-off-by: Junio C Hamano --- Documentation/config/extensions.txt | 6 ++++++ repository.c | 1 + repository.h | 1 + setup.c | 7 +++++++ setup.h | 1 + 5 files changed, 16 insertions(+) (limited to 'Documentation') diff --git a/Documentation/config/extensions.txt b/Documentation/config/extensions.txt index 5dc569d1c9..5cb4721a0e 100644 --- a/Documentation/config/extensions.txt +++ b/Documentation/config/extensions.txt @@ -63,6 +63,12 @@ Note that this setting should only be set by linkgit:git-init[1] or linkgit:git-clone[1]. Trying to change it after initialization will not work and will produce hard-to-diagnose issues. +relativeWorktrees:: + If enabled, indicates at least one worktree has been linked with + relative paths. Automatically set if a worktree has been created or + repaired with either the `--relative-paths` option or with the + `worktree.useRelativePaths` config set to `true`. + worktreeConfig:: If enabled, then worktrees will load config settings from the `$GIT_DIR/config.worktree` file in addition to the diff --git a/repository.c b/repository.c index f988b8ae68..1a6a62bbd0 100644 --- a/repository.c +++ b/repository.c @@ -283,6 +283,7 @@ int repo_init(struct repository *repo, repo_set_compat_hash_algo(repo, format.compat_hash_algo); repo_set_ref_storage_format(repo, format.ref_storage_format); repo->repository_format_worktree_config = format.worktree_config; + repo->repository_format_relative_worktrees = format.relative_worktrees; /* take ownership of format.partial_clone */ repo->repository_format_partial_clone = format.partial_clone; diff --git a/repository.h b/repository.h index 24a66a496a..c4c92b2ab9 100644 --- a/repository.h +++ b/repository.h @@ -150,6 +150,7 @@ struct repository { /* Configurations */ int repository_format_worktree_config; + int repository_format_relative_worktrees; /* Indicate if a repository has a different 'commondir' from 'gitdir' */ unsigned different_commondir:1; diff --git a/setup.c b/setup.c index 1e5c2eacb1..39ff48d9dc 100644 --- a/setup.c +++ b/setup.c @@ -683,6 +683,9 @@ static enum extension_result handle_extension(const char *var, "extensions.refstorage", value); data->ref_storage_format = format; return EXTENSION_OK; + } else if (!strcmp(ext, "relativeworktrees")) { + data->relative_worktrees = git_config_bool(var, value); + return EXTENSION_OK; } return EXTENSION_UNKNOWN; } @@ -1854,6 +1857,8 @@ const char *setup_git_directory_gently(int *nongit_ok) repo_fmt.ref_storage_format); the_repository->repository_format_worktree_config = repo_fmt.worktree_config; + the_repository->repository_format_relative_worktrees = + repo_fmt.relative_worktrees; /* take ownership of repo_fmt.partial_clone */ the_repository->repository_format_partial_clone = repo_fmt.partial_clone; @@ -1950,6 +1955,8 @@ void check_repository_format(struct repository_format *fmt) fmt->ref_storage_format); the_repository->repository_format_worktree_config = fmt->worktree_config; + the_repository->repository_format_relative_worktrees = + fmt->relative_worktrees; the_repository->repository_format_partial_clone = xstrdup_or_null(fmt->partial_clone); clear_repository_format(&repo_fmt); diff --git a/setup.h b/setup.h index e496ab3e4d..18dc3b7368 100644 --- a/setup.h +++ b/setup.h @@ -129,6 +129,7 @@ struct repository_format { int precious_objects; char *partial_clone; /* value of extensions.partialclone */ int worktree_config; + int relative_worktrees; int is_bare; int hash_algo; int compat_hash_algo; -- cgit v1.3 From b7016344f1d4ef8457821e0436f335ec388b8dac Mon Sep 17 00:00:00 2001 From: Caleb White Date: Fri, 29 Nov 2024 22:22:55 +0000 Subject: worktree: add relative cli/config options to `add` command This introduces the `--[no-]relative-paths` CLI option and `worktree.useRelativePaths` configuration setting to the `worktree add` command. When enabled these options allow worktrees to be linked using relative paths, enhancing portability across environments where absolute paths may differ (e.g., containerized setups, shared network drives). Git still creates absolute paths by default, but these options allow users to opt-in to relative paths if desired. The t2408 test file is removed and more comprehensive tests are written for the various worktree operations in their own files. Signed-off-by: Caleb White Signed-off-by: Junio C Hamano --- Documentation/config/worktree.txt | 10 +++++++++ Documentation/git-worktree.txt | 5 +++++ builtin/worktree.c | 19 ++++++++-------- t/t2400-worktree-add.sh | 46 +++++++++++++++++++++++++++++++++++++++ t/t2401-worktree-prune.sh | 3 ++- t/t2402-worktree-list.sh | 22 +++++++++++++++++++ t/t2408-worktree-relative.sh | 39 --------------------------------- 7 files changed, 95 insertions(+), 49 deletions(-) delete mode 100755 t/t2408-worktree-relative.sh (limited to 'Documentation') diff --git a/Documentation/config/worktree.txt b/Documentation/config/worktree.txt index 048e349482..5e35c7d018 100644 --- a/Documentation/config/worktree.txt +++ b/Documentation/config/worktree.txt @@ -7,3 +7,13 @@ worktree.guessRemote:: such a branch exists, it is checked out and set as "upstream" for the new branch. If no such match can be found, it falls back to creating a new branch from the current HEAD. + +worktree.useRelativePaths:: + Link worktrees using relative paths (when "true") or absolute + paths (when "false"). This is particularly useful for setups + where the repository and worktrees may be moved between + different locations or environments. Defaults to "false". ++ +Note that setting `worktree.useRelativePaths` to "true" implies enabling the +`extension.relativeWorktrees` config (see linkgit:git-config[1]), +thus making it incompatible with older versions of Git. diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 70437c815f..60a671bbc2 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -216,6 +216,11 @@ To remove a locked worktree, specify `--force` twice. This can also be set up as the default behaviour by using the `worktree.guessRemote` config option. +--[no-]relative-paths:: + Link worktrees using relative paths or absolute paths (default). + Overrides the `worktree.useRelativePaths` config option, see + linkgit:git-config[1]. + --[no-]track:: When creating a new branch, if `` is a branch, mark it as "upstream" from the new branch. This is the diff --git a/builtin/worktree.c b/builtin/worktree.c index dae63dedf4..e3b4a71ee0 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -120,12 +120,14 @@ struct add_opts { int quiet; int checkout; int orphan; + int relative_paths; const char *keep_locked; }; static int show_only; static int verbose; static int guess_remote; +static int use_relative_paths; static timestamp_t expire; static int git_worktree_config(const char *var, const char *value, @@ -134,6 +136,9 @@ static int git_worktree_config(const char *var, const char *value, if (!strcmp(var, "worktree.guessremote")) { guess_remote = git_config_bool(var, value); return 0; + } else if (!strcmp(var, "worktree.userelativepaths")) { + use_relative_paths = git_config_bool(var, value); + return 0; } return git_default_config(var, value, ctx, cb); @@ -414,8 +419,7 @@ static int add_worktree(const char *path, const char *refname, const struct add_opts *opts) { struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT; - struct strbuf sb = STRBUF_INIT, sb_tmp = STRBUF_INIT; - struct strbuf sb_path_realpath = STRBUF_INIT, sb_repo_realpath = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT; const char *name; struct strvec child_env = STRVEC_INIT; unsigned int counter = 0; @@ -491,10 +495,7 @@ static int add_worktree(const char *path, const char *refname, strbuf_reset(&sb); strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); - strbuf_realpath(&sb_path_realpath, path, 1); - strbuf_realpath(&sb_repo_realpath, sb_repo.buf, 1); - write_file(sb.buf, "%s/.git", relative_path(sb_path_realpath.buf, sb_repo_realpath.buf, &sb_tmp)); - write_file(sb_git.buf, "gitdir: %s", relative_path(sb_repo_realpath.buf, sb_path_realpath.buf, &sb_tmp)); + write_worktree_linking_files(sb_git, sb, opts->relative_paths); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -578,12 +579,9 @@ done: strvec_clear(&child_env); strbuf_release(&sb); - strbuf_release(&sb_tmp); strbuf_release(&symref); strbuf_release(&sb_repo); - strbuf_release(&sb_repo_realpath); strbuf_release(&sb_git); - strbuf_release(&sb_path_realpath); strbuf_release(&sb_name); free_worktree(wt); return ret; @@ -796,12 +794,15 @@ static int add(int ac, const char **av, const char *prefix) PARSE_OPT_NOARG | PARSE_OPT_OPTARG), OPT_BOOL(0, "guess-remote", &guess_remote, N_("try to match the new branch name with a remote-tracking branch")), + OPT_BOOL(0, "relative-paths", &opts.relative_paths, + N_("use relative paths for worktrees")), OPT_END() }; int ret; memset(&opts, 0, sizeof(opts)); opts.checkout = 1; + opts.relative_paths = use_relative_paths; ac = parse_options(ac, av, prefix, options, git_worktree_add_usage, 0); if (!!opts.detach + !!new_branch + !!new_branch_force > 1) die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach"); diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index cfc4aeb179..bc4f4e90d6 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -1207,4 +1207,50 @@ test_expect_success '"add" with initialized submodule, with submodule.recurse se git -C project-clone -c submodule.recurse worktree add ../project-5 ' +test_expect_success 'can create worktrees with relative paths' ' + test_when_finished "git worktree remove relative" && + test_config worktree.useRelativePaths false && + git worktree add --relative-paths ./relative && + echo "gitdir: ../.git/worktrees/relative" >expect && + test_cmp expect relative/.git && + echo "../../../relative/.git" >expect && + test_cmp expect .git/worktrees/relative/gitdir +' + +test_expect_success 'can create worktrees with absolute paths' ' + test_config worktree.useRelativePaths true && + git worktree add ./relative && + echo "gitdir: ../.git/worktrees/relative" >expect && + test_cmp expect relative/.git && + git worktree add --no-relative-paths ./absolute && + echo "gitdir: $(pwd)/.git/worktrees/absolute" >expect && + test_cmp expect absolute/.git && + echo "$(pwd)/absolute/.git" >expect && + test_cmp expect .git/worktrees/absolute/gitdir +' + +test_expect_success 'move repo without breaking relative internal links' ' + test_when_finished rm -rf repo moved && + git init repo && + ( + cd repo && + test_commit initial && + git worktree add --relative-paths wt1 && + cd .. && + mv repo moved && + cd moved/wt1 && + git worktree list >out 2>err && + test_must_be_empty err + ) +' + +test_expect_success 'relative worktree sets extension config' ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo commit --allow-empty -m base && + git -C repo worktree add --relative-paths ./foo && + test_cmp_config -C repo 1 core.repositoryformatversion && + test_cmp_config -C repo true extensions.relativeworktrees +' + test_done diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh index 976d048e3e..5eb52b9abb 100755 --- a/t/t2401-worktree-prune.sh +++ b/t/t2401-worktree-prune.sh @@ -120,11 +120,12 @@ test_expect_success 'prune duplicate (main/linked)' ' ! test -d .git/worktrees/wt ' -test_expect_success 'not prune proper worktrees when run inside linked worktree' ' +test_expect_success 'not prune proper worktrees inside linked worktree with relative paths' ' test_when_finished rm -rf repo wt_ext && git init repo && ( cd repo && + git config worktree.useRelativePaths true && echo content >file && git add file && git commit -m msg && diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh index 33ea9cb21b..780daa6cd6 100755 --- a/t/t2402-worktree-list.sh +++ b/t/t2402-worktree-list.sh @@ -261,6 +261,7 @@ test_expect_success 'broken main worktree still at the top' ' ' test_expect_success 'linked worktrees are sorted' ' + test_when_finished "rm -rf sorted" && mkdir sorted && git init sorted/main && ( @@ -280,6 +281,27 @@ test_expect_success 'linked worktrees are sorted' ' test_cmp expected sorted/main/actual ' +test_expect_success 'linked worktrees with relative paths are shown with absolute paths' ' + test_when_finished "rm -rf sorted" && + mkdir sorted && + git init sorted/main && + ( + cd sorted/main && + test_tick && + test_commit new && + git worktree add --relative-paths ../first && + git worktree add ../second && + git worktree list --porcelain >out && + grep ^worktree out >actual + ) && + cat >expected <<-EOF && + worktree $(pwd)/sorted/main + worktree $(pwd)/sorted/first + worktree $(pwd)/sorted/second + EOF + test_cmp expected sorted/main/actual +' + test_expect_success 'worktree path when called in .git directory' ' git worktree list >list1 && git -C .git worktree list >list2 && diff --git a/t/t2408-worktree-relative.sh b/t/t2408-worktree-relative.sh deleted file mode 100755 index a3136db7e2..0000000000 --- a/t/t2408-worktree-relative.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -test_description='test worktrees linked with relative paths' - -TEST_PASSES_SANITIZE_LEAK=true -. ./test-lib.sh - -test_expect_success 'links worktrees with relative paths' ' - test_when_finished rm -rf repo && - git init repo && - ( - cd repo && - test_commit initial && - git worktree add wt1 && - echo "../../../wt1/.git" >expected_gitdir && - cat .git/worktrees/wt1/gitdir >actual_gitdir && - echo "gitdir: ../.git/worktrees/wt1" >expected_git && - cat wt1/.git >actual_git && - test_cmp expected_gitdir actual_gitdir && - test_cmp expected_git actual_git - ) -' - -test_expect_success 'move repo without breaking relative internal links' ' - test_when_finished rm -rf repo moved && - git init repo && - ( - cd repo && - test_commit initial && - git worktree add wt1 && - cd .. && - mv repo moved && - cd moved/wt1 && - git status >out 2>err && - test_must_be_empty err - ) -' - -test_done -- cgit v1.3 From e6df1ee2c13405ef7077256fef49424f69d61125 Mon Sep 17 00:00:00 2001 From: Caleb White Date: Fri, 29 Nov 2024 22:23:10 +0000 Subject: worktree: add relative cli/config options to `repair` command This teaches the `worktree repair` command to respect the `--[no-]relative-paths` CLI option and `worktree.useRelativePaths` config setting. If an existing worktree with an absolute path is repaired with `--relative-paths`, the links will be replaced with relative paths, even if the original path was correct. This allows a user to covert existing worktrees between absolute/relative as desired. To simplify things, both linking files are written when one of the files needs to be repaired. In some cases, this fixes the other file before it is checked, in other cases this results in a correct file being written with the same contents. Signed-off-by: Caleb White Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 3 +++ builtin/worktree.c | 6 +++-- t/t2406-worktree-repair.sh | 39 +++++++++++++++++++++++++++++ worktree.c | 56 ++++++++++++++++++++---------------------- worktree.h | 5 ++-- 5 files changed, 76 insertions(+), 33 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 60a671bbc2..8340b7f028 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -220,6 +220,9 @@ This can also be set up as the default behaviour by using the Link worktrees using relative paths or absolute paths (default). Overrides the `worktree.useRelativePaths` config option, see linkgit:git-config[1]. ++ +With `repair`, the linking files will be updated if there's an absolute/relative +mismatch, even if the links are correct. --[no-]track:: When creating a new branch, if `` is a branch, diff --git a/builtin/worktree.c b/builtin/worktree.c index 3021515069..fde9ff4dc9 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -1385,6 +1385,8 @@ static int repair(int ac, const char **av, const char *prefix) const char **p; const char *self[] = { ".", NULL }; struct option options[] = { + OPT_BOOL(0, "relative-paths", &use_relative_paths, + N_("use relative paths for worktrees")), OPT_END() }; int rc = 0; @@ -1392,8 +1394,8 @@ static int repair(int ac, const char **av, const char *prefix) ac = parse_options(ac, av, prefix, options, git_worktree_repair_usage, 0); p = ac > 0 ? av : self; for (; *p; p++) - repair_worktree_at_path(*p, report_repair, &rc); - repair_worktrees(report_repair, &rc); + repair_worktree_at_path(*p, report_repair, &rc, use_relative_paths); + repair_worktrees(report_repair, &rc, use_relative_paths); return rc; } diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh index 7686e60f6a..49b70b9995 100755 --- a/t/t2406-worktree-repair.sh +++ b/t/t2406-worktree-repair.sh @@ -216,4 +216,43 @@ test_expect_success 'repair copied main and linked worktrees' ' test_cmp dup/linked.expect dup/linked/.git ' +test_expect_success 'repair worktree with relative path with missing gitfile' ' + test_when_finished "rm -rf main wt" && + test_create_repo main && + git -C main config worktree.useRelativePaths true && + test_commit -C main init && + git -C main worktree add --detach ../wt && + rm wt/.git && + test_path_is_missing wt/.git && + git -C main worktree repair && + echo "gitdir: ../main/.git/worktrees/wt" >expect && + test_cmp expect wt/.git +' + +test_expect_success 'repair absolute worktree to use relative paths' ' + test_when_finished "rm -rf main side sidemoved" && + test_create_repo main && + test_commit -C main init && + git -C main worktree add --detach ../side && + echo "../../../../sidemoved/.git" >expect-gitdir && + echo "gitdir: ../main/.git/worktrees/side" >expect-gitfile && + mv side sidemoved && + git -C main worktree repair --relative-paths ../sidemoved && + test_cmp expect-gitdir main/.git/worktrees/side/gitdir && + test_cmp expect-gitfile sidemoved/.git +' + +test_expect_success 'repair relative worktree to use absolute paths' ' + test_when_finished "rm -rf main side sidemoved" && + test_create_repo main && + test_commit -C main init && + git -C main worktree add --relative-paths --detach ../side && + echo "$(pwd)/sidemoved/.git" >expect-gitdir && + echo "gitdir: $(pwd)/main/.git/worktrees/side" >expect-gitfile && + mv side sidemoved && + git -C main worktree repair ../sidemoved && + test_cmp expect-gitdir main/.git/worktrees/side/gitdir && + test_cmp expect-gitfile sidemoved/.git +' + test_done diff --git a/worktree.c b/worktree.c index c749cb1699..2e76bbc149 100644 --- a/worktree.c +++ b/worktree.c @@ -573,12 +573,13 @@ int other_head_refs(each_ref_fn fn, void *cb_data) * pointing at /worktrees/. */ static void repair_gitfile(struct worktree *wt, - worktree_repair_fn fn, void *cb_data) + worktree_repair_fn fn, void *cb_data, + int use_relative_paths) { struct strbuf dotgit = STRBUF_INIT; + struct strbuf gitdir = STRBUF_INIT; struct strbuf repo = STRBUF_INIT; struct strbuf backlink = STRBUF_INIT; - struct strbuf tmp = STRBUF_INIT; char *dotgit_contents = NULL; const char *repair = NULL; int err; @@ -594,6 +595,7 @@ static void repair_gitfile(struct worktree *wt, strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); strbuf_addf(&dotgit, "%s/.git", wt->path); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); if (dotgit_contents) { @@ -611,18 +613,20 @@ static void repair_gitfile(struct worktree *wt, repair = _(".git file broken"); else if (fspathcmp(backlink.buf, repo.buf)) repair = _(".git file incorrect"); + else if (use_relative_paths == is_absolute_path(dotgit_contents)) + repair = _(".git file absolute/relative path mismatch"); if (repair) { fn(0, wt->path, repair, cb_data); - write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, wt->path, &tmp)); + write_worktree_linking_files(dotgit, gitdir, use_relative_paths); } done: free(dotgit_contents); strbuf_release(&repo); strbuf_release(&dotgit); + strbuf_release(&gitdir); strbuf_release(&backlink); - strbuf_release(&tmp); } static void repair_noop(int iserr UNUSED, @@ -633,7 +637,7 @@ static void repair_noop(int iserr UNUSED, /* nothing */ } -void repair_worktrees(worktree_repair_fn fn, void *cb_data) +void repair_worktrees(worktree_repair_fn fn, void *cb_data, int use_relative_paths) { struct worktree **worktrees = get_worktrees_internal(1); struct worktree **wt = worktrees + 1; /* +1 skips main worktree */ @@ -641,7 +645,7 @@ void repair_worktrees(worktree_repair_fn fn, void *cb_data) if (!fn) fn = repair_noop; for (; *wt; wt++) - repair_gitfile(*wt, fn, cb_data); + repair_gitfile(*wt, fn, cb_data, use_relative_paths); free_worktrees(worktrees); } @@ -757,16 +761,14 @@ error: * the worktree's path. */ void repair_worktree_at_path(const char *path, - worktree_repair_fn fn, void *cb_data) + worktree_repair_fn fn, void *cb_data, + int use_relative_paths) { struct strbuf dotgit = STRBUF_INIT; - struct strbuf realdotgit = STRBUF_INIT; struct strbuf backlink = STRBUF_INIT; struct strbuf inferred_backlink = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; struct strbuf olddotgit = STRBUF_INIT; - struct strbuf realolddotgit = STRBUF_INIT; - struct strbuf tmp = STRBUF_INIT; char *dotgit_contents = NULL; const char *repair = NULL; int err; @@ -778,25 +780,25 @@ void repair_worktree_at_path(const char *path, goto done; strbuf_addf(&dotgit, "%s/.git", path); - if (!strbuf_realpath(&realdotgit, dotgit.buf, 0)) { + if (!strbuf_realpath(&dotgit, dotgit.buf, 0)) { fn(1, path, _("not a valid path"), cb_data); goto done; } - infer_backlink(realdotgit.buf, &inferred_backlink); + infer_backlink(dotgit.buf, &inferred_backlink); strbuf_realpath_forgiving(&inferred_backlink, inferred_backlink.buf, 0); - dotgit_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); + dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); if (dotgit_contents) { if (is_absolute_path(dotgit_contents)) { strbuf_addstr(&backlink, dotgit_contents); } else { - strbuf_addbuf(&backlink, &realdotgit); + strbuf_addbuf(&backlink, &dotgit); strbuf_strip_suffix(&backlink, ".git"); strbuf_addstr(&backlink, dotgit_contents); strbuf_realpath_forgiving(&backlink, backlink.buf, 0); } } else if (err == READ_GITFILE_ERR_NOT_A_FILE) { - fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); + fn(1, dotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); goto done; } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { if (inferred_backlink.len) { @@ -809,11 +811,11 @@ void repair_worktree_at_path(const char *path, */ strbuf_swap(&backlink, &inferred_backlink); } else { - fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); + fn(1, dotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); goto done; } } else { - fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); + fn(1, dotgit.buf, _("unable to locate repository; .git file broken"), cb_data); goto done; } @@ -835,39 +837,35 @@ void repair_worktree_at_path(const char *path, * in the "copy" repository. In this case, point the "copy" worktree's * .git file at the "copy" repository. */ - if (inferred_backlink.len && fspathcmp(backlink.buf, inferred_backlink.buf)) { + if (inferred_backlink.len && fspathcmp(backlink.buf, inferred_backlink.buf)) strbuf_swap(&backlink, &inferred_backlink); - } strbuf_addf(&gitdir, "%s/gitdir", backlink.buf); if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0) repair = _("gitdir unreadable"); + else if (use_relative_paths == is_absolute_path(olddotgit.buf)) + repair = _("gitdir absolute/relative path mismatch"); else { strbuf_rtrim(&olddotgit); - if (is_absolute_path(olddotgit.buf)) { - strbuf_addbuf(&realolddotgit, &olddotgit); - } else { - strbuf_addf(&realolddotgit, "%s/%s", backlink.buf, olddotgit.buf); - strbuf_realpath_forgiving(&realolddotgit, realolddotgit.buf, 0); + if (!is_absolute_path(olddotgit.buf)) { + strbuf_insertf(&olddotgit, 0, "%s/", backlink.buf); + strbuf_realpath_forgiving(&olddotgit, olddotgit.buf, 0); } - if (fspathcmp(realolddotgit.buf, realdotgit.buf)) + if (fspathcmp(olddotgit.buf, dotgit.buf)) repair = _("gitdir incorrect"); } if (repair) { fn(0, gitdir.buf, repair, cb_data); - write_file(gitdir.buf, "%s", relative_path(realdotgit.buf, backlink.buf, &tmp)); + write_worktree_linking_files(dotgit, gitdir, use_relative_paths); } done: free(dotgit_contents); strbuf_release(&olddotgit); - strbuf_release(&realolddotgit); strbuf_release(&backlink); strbuf_release(&inferred_backlink); strbuf_release(&gitdir); - strbuf_release(&realdotgit); strbuf_release(&dotgit); - strbuf_release(&tmp); } int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, timestamp_t expire) diff --git a/worktree.h b/worktree.h index 9c699d080d..38145df80f 100644 --- a/worktree.h +++ b/worktree.h @@ -129,7 +129,7 @@ typedef void (* worktree_repair_fn)(int iserr, const char *path, * function, if non-NULL, is called with the path of the worktree and a * description of the repair or error, along with the callback user-data. */ -void repair_worktrees(worktree_repair_fn, void *cb_data); +void repair_worktrees(worktree_repair_fn, void *cb_data, int use_relative_paths); /* * Repair the linked worktrees after the gitdir has been moved. @@ -151,7 +151,8 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path * worktree and a description of the repair or error, along with the callback * user-data. */ -void repair_worktree_at_path(const char *, worktree_repair_fn, void *cb_data); +void repair_worktree_at_path(const char *, worktree_repair_fn, + void *cb_data, int use_relative_paths); /* * Free up the memory for a worktree. -- cgit v1.3 From b7f7d16562c3c5af31d77254577e4afe9bf3e99a Mon Sep 17 00:00:00 2001 From: Bence Ferdinandy Date: Fri, 29 Nov 2024 00:06:46 +0100 Subject: fetch: add configuration for set_head behaviour In the current implementation, if refs/remotes/$remote/HEAD does not exist, running fetch will create it, but if it does exist it will not do anything, which is a somewhat safe and minimal approach. Unfortunately, for users who wish to NOT have refs/remotes/$remote/HEAD set for any reason (e.g. so that `git rev-parse origin` doesn't accidentally point them somewhere they do not want to), there is no way to remove this behaviour. On the other side of the spectrum, users may want fetch to automatically update HEAD or at least give them a warning if something changed on the remote. Introduce a new setting, remote.$remote.followRemoteHEAD with four options: - "never": do not ever do anything, not even create - "create": the current behaviour, now the default behaviour - "warn": print a message if remote and local HEAD is different - "always": silently update HEAD on every change Signed-off-by: Bence Ferdinandy Signed-off-by: Junio C Hamano --- Documentation/config/remote.txt | 11 +++++ builtin/fetch.c | 46 +++++++++++++++--- remote.c | 9 ++++ remote.h | 9 ++++ t/t5510-fetch.sh | 102 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 171 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/config/remote.txt b/Documentation/config/remote.txt index 6d8b7d6c63..024f92befc 100644 --- a/Documentation/config/remote.txt +++ b/Documentation/config/remote.txt @@ -101,6 +101,17 @@ remote..serverOption:: The default set of server options used when fetching from this remote. These server options can be overridden by the `--server-option=` command line arguments. + +remote..followRemoteHEAD:: + How linkgit:git-fetch[1] should handle updates to `remotes//HEAD`. + The default value is "create", which will create `remotes//HEAD` + if it exists on the remote, but not locally, but will not touch an + already existing local reference. Setting to "warn" will print + a message if the remote has a different value, than the local one and + in case there is no local reference, it behaves like "create". Setting + to "always" will silently update it to the value on the remote. + Finally, setting it to "never" will never change or create the local + reference. + This is a multi-valued variable, and an empty value can be used in a higher priority configuration file (e.g. `.git/config` in a repository) to clear diff --git a/builtin/fetch.c b/builtin/fetch.c index 2f416cf867..88c5c5d781 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1579,10 +1579,35 @@ static const char *strip_refshead(const char *name){ return name; } -static int set_head(const struct ref *remote_refs) +static void report_set_head(const char *remote, const char *head_name, + struct strbuf *buf_prev, int updateres) { + struct strbuf buf_prefix = STRBUF_INIT; + const char *prev_head = NULL; + + strbuf_addf(&buf_prefix, "refs/remotes/%s/", remote); + skip_prefix(buf_prev->buf, buf_prefix.buf, &prev_head); + + if (prev_head && strcmp(prev_head, head_name)) { + printf("'HEAD' at '%s' is '%s', but we have '%s' locally.\n", + remote, head_name, prev_head); + printf("Run 'git remote set-head %s %s' to follow the change.\n", + remote, head_name); + } + else if (updateres && buf_prev->len) { + printf("'HEAD' at '%s' is '%s', " + "but we have a detached HEAD pointing to '%s' locally.\n", + remote, head_name, buf_prev->buf); + printf("Run 'git remote set-head %s %s' to follow the change.\n", + remote, head_name); + } + strbuf_release(&buf_prefix); +} + +static int set_head(const struct ref *remote_refs, int follow_remote_head) { - int result = 0, is_bare; - struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT; + int result = 0, create_only, is_bare, was_detached; + struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT, + b_local_head = STRBUF_INIT; const char *remote = gtransport->remote->name; char *head_name = NULL; struct ref *ref, *matches; @@ -1603,6 +1628,8 @@ static int set_head(const struct ref *remote_refs) string_list_append(&heads, strip_refshead(ref->name)); } + if (follow_remote_head == FOLLOW_REMOTE_NEVER) + goto cleanup; if (!heads.nr) result = 1; @@ -1614,6 +1641,7 @@ static int set_head(const struct ref *remote_refs) if (!head_name) goto cleanup; is_bare = is_bare_repository(); + create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !is_bare; if (is_bare) { strbuf_addstr(&b_head, "HEAD"); strbuf_addf(&b_remote_head, "refs/heads/%s", head_name); @@ -1626,9 +1654,14 @@ static int set_head(const struct ref *remote_refs) result = 1; goto cleanup; } - if (refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf, - "fetch", NULL, !is_bare)) + was_detached = refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf, + "fetch", &b_local_head, create_only); + if (was_detached == -1) { result = 1; + goto cleanup; + } + if (follow_remote_head == FOLLOW_REMOTE_WARN && verbosity >= 0) + report_set_head(remote, head_name, &b_local_head, was_detached); cleanup: free(head_name); @@ -1636,6 +1669,7 @@ cleanup: free_refs(matches); string_list_clear(&heads, 0); strbuf_release(&b_head); + strbuf_release(&b_local_head); strbuf_release(&b_remote_head); return result; } @@ -1855,7 +1889,7 @@ static int do_fetch(struct transport *transport, "you need to specify exactly one branch with the --set-upstream option")); } } - if (set_head(remote_refs)) + if (set_head(remote_refs, transport->remote->follow_remote_head)) ; /* * Way too many cases where this can go wrong diff --git a/remote.c b/remote.c index 10104d11e3..0b18840d43 100644 --- a/remote.c +++ b/remote.c @@ -514,6 +514,15 @@ static int handle_config(const char *key, const char *value, } else if (!strcmp(subkey, "serveroption")) { return parse_transport_option(key, value, &remote->server_options); + } else if (!strcmp(subkey, "followremotehead")) { + if (!strcmp(value, "never")) + remote->follow_remote_head = FOLLOW_REMOTE_NEVER; + else if (!strcmp(value, "create")) + remote->follow_remote_head = FOLLOW_REMOTE_CREATE; + else if (!strcmp(value, "warn")) + remote->follow_remote_head = FOLLOW_REMOTE_WARN; + else if (!strcmp(value, "always")) + remote->follow_remote_head = FOLLOW_REMOTE_ALWAYS; } return 0; } diff --git a/remote.h b/remote.h index a7e5c4e07c..184b35653d 100644 --- a/remote.h +++ b/remote.h @@ -59,6 +59,13 @@ struct remote_state { void remote_state_clear(struct remote_state *remote_state); struct remote_state *remote_state_new(void); + enum follow_remote_head_settings { + FOLLOW_REMOTE_NEVER = -1, + FOLLOW_REMOTE_CREATE = 0, + FOLLOW_REMOTE_WARN = 1, + FOLLOW_REMOTE_ALWAYS = 2, + }; + struct remote { struct hashmap_entry ent; @@ -107,6 +114,8 @@ struct remote { char *http_proxy_authmethod; struct string_list server_options; + + enum follow_remote_head_settings follow_remote_head; }; /** diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 87698341f5..2467027d34 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -99,6 +99,108 @@ test_expect_success "fetch test remote HEAD change" ' branch=$(git rev-parse refs/remotes/origin/other) && test "z$head" = "z$branch"' +test_expect_success "fetch test followRemoteHEAD never" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git update-ref --no-deref -d refs/remotes/origin/HEAD && + git config set remote.origin.followRemoteHEAD "never" && + git fetch && + test_must_fail git rev-parse --verify refs/remotes/origin/HEAD + ) +' + +test_expect_success "fetch test followRemoteHEAD warn no change" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git rev-parse --verify refs/remotes/origin/other && + git remote set-head origin other && + git rev-parse --verify refs/remotes/origin/HEAD && + git rev-parse --verify refs/remotes/origin/main && + git config set remote.origin.followRemoteHEAD "warn" && + git fetch >output && + echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \ + "but we have ${SQ}other${SQ} locally." >expect && + echo "Run ${SQ}git remote set-head origin main${SQ} to follow the change." >>expect && + test_cmp expect output && + head=$(git rev-parse refs/remotes/origin/HEAD) && + branch=$(git rev-parse refs/remotes/origin/other) && + test "z$head" = "z$branch" + ) +' + +test_expect_success "fetch test followRemoteHEAD warn create" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git update-ref --no-deref -d refs/remotes/origin/HEAD && + git config set remote.origin.followRemoteHEAD "warn" && + git rev-parse --verify refs/remotes/origin/main && + output=$(git fetch) && + test "z" = "z$output" && + head=$(git rev-parse refs/remotes/origin/HEAD) && + branch=$(git rev-parse refs/remotes/origin/main) && + test "z$head" = "z$branch" + ) +' + +test_expect_success "fetch test followRemoteHEAD warn detached" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git update-ref --no-deref -d refs/remotes/origin/HEAD && + git update-ref refs/remotes/origin/HEAD HEAD && + HEAD=$(git log --pretty="%H") && + git config set remote.origin.followRemoteHEAD "warn" && + git fetch >output && + echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \ + "but we have a detached HEAD pointing to" \ + "${SQ}${HEAD}${SQ} locally." >expect && + echo "Run ${SQ}git remote set-head origin main${SQ} to follow the change." >>expect && + test_cmp expect output + ) +' + +test_expect_success "fetch test followRemoteHEAD warn quiet" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git rev-parse --verify refs/remotes/origin/other && + git remote set-head origin other && + git rev-parse --verify refs/remotes/origin/HEAD && + git rev-parse --verify refs/remotes/origin/main && + git config set remote.origin.followRemoteHEAD "warn" && + output=$(git fetch --quiet) && + test "z" = "z$output" && + head=$(git rev-parse refs/remotes/origin/HEAD) && + branch=$(git rev-parse refs/remotes/origin/other) && + test "z$head" = "z$branch" + ) +' + +test_expect_success "fetch test followRemoteHEAD always" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git rev-parse --verify refs/remotes/origin/other && + git remote set-head origin other && + git rev-parse --verify refs/remotes/origin/HEAD && + git rev-parse --verify refs/remotes/origin/main && + git config set remote.origin.followRemoteHEAD "always" && + git fetch && + head=$(git rev-parse refs/remotes/origin/HEAD) && + branch=$(git rev-parse refs/remotes/origin/main) && + test "z$head" = "z$branch" + ) +' + test_expect_success 'fetch --prune on its own works as expected' ' cd "$D" && git clone . prune && -- cgit v1.3 From 18693d7d65eb793eb64ef32685922c5739d53c26 Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Thu, 28 Nov 2024 20:44:51 +0100 Subject: Documentation/git-bundle.txt: fix word join typo Signed-off-by: Kristoffer Haugsbakk Signed-off-by: Junio C Hamano --- Documentation/git-bundle.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt index 3ab42a19ca..344e7cd829 100644 --- a/Documentation/git-bundle.txt +++ b/Documentation/git-bundle.txt @@ -31,7 +31,7 @@ Git commands that fetch or otherwise "read" via protocols such as possible linkgit:git-clone[1] a new repository from a bundle, to use linkgit:git-fetch[1] to fetch from one, and to list the references contained within it with linkgit:git-ls-remote[1]. There's no -corresponding "write" support, i.e.a 'git push' into a bundle is not +corresponding "write" support, i.e. a 'git push' into a bundle is not supported. See the "EXAMPLES" section below for examples of how to use bundles. -- cgit v1.3 From e2f5d3b491ee8becb37549f29a3cee50573d0bd3 Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Fri, 29 Nov 2024 19:52:29 +0100 Subject: Documentation/git-update-ref.txt: add missing word MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing word “that” in the phrase “after verifying that”, like what was done in 1b2dfb70504 (Documentation/git-update-ref.txt: drop “flag”, 2024-10-21) Signed-off-by: Kristoffer Haugsbakk Signed-off-by: Junio C Hamano --- Documentation/git-update-ref.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index afcf33cf60..70ad72717e 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -114,11 +114,11 @@ update:: ref does not exist before the update. create:: - Create with after verifying it does not + Create with after verifying that it does not exist. The given may not be zero. delete:: - Delete after verifying it exists with , if + Delete after verifying that it exists with , if given. If given, may not be zero. symref-update:: @@ -131,11 +131,11 @@ verify:: is zero or missing, the ref must not exist. symref-create: - Create symbolic ref with after verifying + Create symbolic ref with after verifying that it does not exist. symref-delete:: - Delete after verifying it exists with , if given. + Delete after verifying that it exists with , if given. symref-verify:: Verify symbolic against but do not change it. -- cgit v1.3 From bc1a980759bc61a426c26d3b47e2d77a708a038b Mon Sep 17 00:00:00 2001 From: Kai Koponen Date: Tue, 3 Dec 2024 12:14:34 -0500 Subject: doc: mention rev-list --ancestry-path restrictions The rev-list documentation doesn't mention that the given commit must be in the specified commit range, leading to unexpected results. Signed-off-by: Kai Koponen Signed-off-by: Junio C Hamano --- Documentation/rev-list-options.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 0d90d5b154..9d5243e0aa 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -401,7 +401,8 @@ Default mode:: --ancestry-path[=]:: When given a range of commits to display (e.g. 'commit1..commit2' - or 'commit2 {caret}commit1'), only display commits in that range + or 'commit2 {caret}commit1'), and a commit in that range, + only display commits in that range that are ancestors of , descendants of , or itself. If no commit is specified, use 'commit1' (the excluded part of the range) as . Can be passed multiple -- cgit v1.3 From 9e2b7005becaf730ff75f6efbef4542cc4454107 Mon Sep 17 00:00:00 2001 From: Bence Ferdinandy Date: Thu, 5 Dec 2024 13:16:21 +0100 Subject: fetch set_head: add warn-if-not-$branch option Currently if we want to have a remote/HEAD locally that is different from the one on the remote, but we still want to get a warning if remote changes HEAD, our only option is to have an indiscriminate warning with "follow_remote_head" set to "warn". Add a new option "warn-if-not-$branch", where $branch is a branch name we do not wish to get a warning about. If the remote HEAD is $branch do not warn, otherwise, behave as "warn". E.g. let's assume, that our remote origin has HEAD set to "master", but locally we have "git remote set-head origin seen". Setting 'remote.origin.followRemoteHEAD = "warn"' will always print a warning, even though the remote has not changed HEAD from "master". Setting 'remote.origin.followRemoteHEAD = "warn-if-not-master" will squelch the warning message, unless the remote changes HEAD from "master". Note, that should the remote change HEAD to "seen" (which we have locally), there will still be no warning. Improve the advice message in report_set_head to also include silencing the warning message with "warn-if-not-$branch". Signed-off-by: Bence Ferdinandy Signed-off-by: Junio C Hamano --- Documentation/config/remote.txt | 8 +++++--- builtin/fetch.c | 16 +++++++++++----- remote.c | 13 +++++++++++-- remote.h | 1 + t/t5510-fetch.sh | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/config/remote.txt b/Documentation/config/remote.txt index 024f92befc..4118c219c1 100644 --- a/Documentation/config/remote.txt +++ b/Documentation/config/remote.txt @@ -106,10 +106,12 @@ remote..followRemoteHEAD:: How linkgit:git-fetch[1] should handle updates to `remotes//HEAD`. The default value is "create", which will create `remotes//HEAD` if it exists on the remote, but not locally, but will not touch an - already existing local reference. Setting to "warn" will print + already existing local reference. Setting to "warn" will print a message if the remote has a different value, than the local one and - in case there is no local reference, it behaves like "create". Setting - to "always" will silently update it to the value on the remote. + in case there is no local reference, it behaves like "create". + A variant on "warn" is "warn-if-not-$branch", which behaves like + "warn", but if `HEAD` on the remote is `$branch` it will be silent. + Setting to "always" will silently update it to the value on the remote. Finally, setting it to "never" will never change or create the local reference. + diff --git a/builtin/fetch.c b/builtin/fetch.c index 897e71325f..c4257a7ead 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1584,10 +1584,12 @@ static void set_head_advice_msg(const char *remote, const char *head_name) const char message_advice_set_head[] = N_("Run 'git remote set-head %s %s' to follow the change, or set\n" "'remote.%s.followRemoteHEAD' configuration option to a different value\n" - "if you do not want to see this message."); + "if you do not want to see this message. Specifically running\n" + "'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n" + "until the remote changes HEAD to something else."); advise_if_enabled(ADVICE_FETCH_SET_HEAD_WARN, _(message_advice_set_head), - remote, head_name, remote); + remote, head_name, remote, remote, head_name); } static void report_set_head(const char *remote, const char *head_name, @@ -1612,7 +1614,8 @@ static void report_set_head(const char *remote, const char *head_name, strbuf_release(&buf_prefix); } -static int set_head(const struct ref *remote_refs, int follow_remote_head) +static int set_head(const struct ref *remote_refs, int follow_remote_head, + const char *no_warn_branch) { int result = 0, create_only, is_bare, was_detached; struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT, @@ -1669,7 +1672,9 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head) result = 1; goto cleanup; } - if (follow_remote_head == FOLLOW_REMOTE_WARN && verbosity >= 0) + if (verbosity >= 0 && + follow_remote_head == FOLLOW_REMOTE_WARN && + (!no_warn_branch || strcmp(no_warn_branch, head_name))) report_set_head(remote, head_name, &b_local_head, was_detached); cleanup: @@ -1898,7 +1903,8 @@ static int do_fetch(struct transport *transport, "you need to specify exactly one branch with the --set-upstream option")); } } - if (set_head(remote_refs, transport->remote->follow_remote_head)) + if (set_head(remote_refs, transport->remote->follow_remote_head, + transport->remote->no_warn_branch)) ; /* * Way too many cases where this can go wrong diff --git a/remote.c b/remote.c index 0b18840d43..4ec5d3f47b 100644 --- a/remote.c +++ b/remote.c @@ -515,14 +515,23 @@ static int handle_config(const char *key, const char *value, return parse_transport_option(key, value, &remote->server_options); } else if (!strcmp(subkey, "followremotehead")) { + const char *no_warn_branch; if (!strcmp(value, "never")) remote->follow_remote_head = FOLLOW_REMOTE_NEVER; else if (!strcmp(value, "create")) remote->follow_remote_head = FOLLOW_REMOTE_CREATE; - else if (!strcmp(value, "warn")) + else if (!strcmp(value, "warn")) { remote->follow_remote_head = FOLLOW_REMOTE_WARN; - else if (!strcmp(value, "always")) + remote->no_warn_branch = NULL; + } else if (skip_prefix(value, "warn-if-not-", &no_warn_branch)) { + remote->follow_remote_head = FOLLOW_REMOTE_WARN; + remote->no_warn_branch = no_warn_branch; + } else if (!strcmp(value, "always")) { remote->follow_remote_head = FOLLOW_REMOTE_ALWAYS; + } else { + warning(_("unrecognized followRemoteHEAD value '%s' ignored"), + value); + } } return 0; } diff --git a/remote.h b/remote.h index 184b35653d..bda10dd5c8 100644 --- a/remote.h +++ b/remote.h @@ -116,6 +116,7 @@ struct remote { struct string_list server_options; enum follow_remote_head_settings follow_remote_head; + const char *no_warn_branch; }; /** diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 5c96591b9e..13881603f6 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -182,6 +182,44 @@ test_expect_success "fetch test followRemoteHEAD warn quiet" ' ) ' +test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is same" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git rev-parse --verify refs/remotes/origin/other && + git remote set-head origin other && + git rev-parse --verify refs/remotes/origin/HEAD && + git rev-parse --verify refs/remotes/origin/main && + git config set remote.origin.followRemoteHEAD "warn-if-not-main" && + actual=$(git fetch) && + test "z" = "z$actual" && + head=$(git rev-parse refs/remotes/origin/HEAD) && + branch=$(git rev-parse refs/remotes/origin/other) && + test "z$head" = "z$branch" + ) +' + +test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is different" ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git rev-parse --verify refs/remotes/origin/other && + git remote set-head origin other && + git rev-parse --verify refs/remotes/origin/HEAD && + git rev-parse --verify refs/remotes/origin/main && + git config set remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" && + git fetch >actual && + echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \ + "but we have ${SQ}other${SQ} locally." >expect && + test_cmp expect actual && + head=$(git rev-parse refs/remotes/origin/HEAD) && + branch=$(git rev-parse refs/remotes/origin/other) && + test "z$head" = "z$branch" + ) +' + test_expect_success "fetch test followRemoteHEAD always" ' test_when_finished "git config unset remote.origin.followRemoteHEAD" && ( -- cgit v1.3 From a38edab7c88b5503bb2b5f5cbd49f6b97e9a6a4e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:41 +0100 Subject: Makefile: generate doc versions via GIT-VERSION-GEN The documentation we generate embeds information for the exact Git version used as well as the date of the commit. This information is injected by injecting attributes into the build process via command line argument. Refactor the logic so that we write the information into "asciidoc.conf" and "asciidoctor-extensions.rb" via `GIT-VERSION-GEN` for AsciiDoc and AsciiDoctor, respectively. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/.gitignore | 2 + Documentation/Makefile | 25 ++++-- Documentation/asciidoc.conf | 79 ----------------- Documentation/asciidoc.conf.in | 82 ++++++++++++++++++ Documentation/asciidoctor-extensions.rb | 135 ----------------------------- Documentation/asciidoctor-extensions.rb.in | 131 ++++++++++++++++++++++++++++ GIT-VERSION-GEN | 2 + 7 files changed, 233 insertions(+), 223 deletions(-) delete mode 100644 Documentation/asciidoc.conf create mode 100644 Documentation/asciidoc.conf.in delete mode 100644 Documentation/asciidoctor-extensions.rb create mode 100644 Documentation/asciidoctor-extensions.rb.in (limited to 'Documentation') diff --git a/Documentation/.gitignore b/Documentation/.gitignore index a48448de32..649df89474 100644 --- a/Documentation/.gitignore +++ b/Documentation/.gitignore @@ -15,3 +15,5 @@ tmp-doc-diff/ GIT-ASCIIDOCFLAGS /.build/ /GIT-EXCLUDED-PROGRAMS +/asciidoc.conf +/asciidoctor-extensions.rb diff --git a/Documentation/Makefile b/Documentation/Makefile index 0f55baa252..9371f29425 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -1,6 +1,8 @@ # Import tree-wide shared Makefile behavior and libraries include ../shared.mak +.PHONY: FORCE + # Guard against environment variables MAN1_TXT = MAN5_TXT = @@ -148,16 +150,12 @@ man5dir = $(mandir)/man5 man7dir = $(mandir)/man7 # DESTDIR = -GIT_DATE := $(shell git show --quiet --pretty='%as') - ASCIIDOC = asciidoc ASCIIDOC_EXTRA = ASCIIDOC_HTML = xhtml11 ASCIIDOC_DOCBOOK = docbook ASCIIDOC_CONF = -f asciidoc.conf -ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) $(ASCIIDOC_CONF) \ - -amanmanual='Git Manual' -amansource='Git $(GIT_VERSION)' \ - -arevdate='$(GIT_DATE)' +ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) $(ASCIIDOC_CONF) ASCIIDOC_DEPS = asciidoc.conf GIT-ASCIIDOCFLAGS TXT_TO_HTML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_HTML) TXT_TO_XML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_DOCBOOK) @@ -210,6 +208,14 @@ ASCIIDOC_DEPS = asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS DBLATEX_COMMON = XMLTO_EXTRA += --skip-validation XMLTO_EXTRA += -x manpage.xsl + +asciidoctor-extensions.rb: asciidoctor-extensions.rb.in FORCE + $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@+ + @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi +else +asciidoc.conf: asciidoc.conf.in FORCE + $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@+ + @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi endif ASCIIDOC_DEPS += docinfo.html @@ -341,6 +347,7 @@ clean: $(RM) SubmittingPatches.txt $(RM) $(cmds_txt) $(mergetools_txt) *.made $(RM) GIT-ASCIIDOCFLAGS + $(RM) asciidoc.conf asciidoctor-extensions.rb docinfo.html: docinfo-html.in $(QUIET_GEN)$(RM) $@ && cat $< >$@ @@ -364,7 +371,7 @@ manpage-cmd = $(QUIET_XMLTO)$(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< %.xml : %.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_XML) -d manpage -o $@ $< -user-manual.xml: user-manual.txt user-manual.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS +user-manual.xml: user-manual.txt user-manual.conf $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_XML) -d book -o $@ $< technical/api-index.txt: technical/api-index-skel.txt \ @@ -373,7 +380,7 @@ technical/api-index.txt: technical/api-index-skel.txt \ technical/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../ $(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt \ - asciidoc.conf GIT-ASCIIDOCFLAGS + $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt SubmittingPatches.txt: SubmittingPatches @@ -416,13 +423,13 @@ $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml howto-index.txt: howto-index.sh $(HOWTO_TXT) $(QUIET_GEN)'$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(HOWTO_TXT)) >$@ -$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt +$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt WEBDOC_DEST = /pub/software/scm/git/docs howto/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../ -$(patsubst %.txt,%.html,$(HOWTO_TXT)): %.html : %.txt GIT-ASCIIDOCFLAGS +$(patsubst %.txt,%.html,$(HOWTO_TXT)): %.html : %.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC) \ sed -e '1,/^$$/d' $< | \ $(TXT_TO_HTML) - >$@ diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf deleted file mode 100644 index f6da6d1fbd..0000000000 --- a/Documentation/asciidoc.conf +++ /dev/null @@ -1,79 +0,0 @@ -## linkgit: macro -# -# Usage: linkgit:command[manpage-section] -# -# Note, {0} is the manpage section, while {target} is the command. -# -# Show Git link as: (
); if section is defined, else just show -# the command. - -[macros] -(?su)[\\]?(?Plinkgit):(?P\S*?)\[(?P.*?)\]= - -[attributes] -asterisk=* -plus=+ -caret=^ -startsb=[ -endsb=] -backslash=\ -tilde=~ -apostrophe=' -backtick=` -litdd=-- - -ifdef::backend-docbook[] -[linkgit-inlinemacro] -{0%{target}} -{0#} -{0#{target}{0}} -{0#} - -[literal-inlinemacro] -{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1\2', re.sub(r'(\.\.\.?)([^\]$.])', r'\1\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} - -endif::backend-docbook[] - -ifdef::backend-docbook[] -ifdef::doctype-manpage[] -# The following two small workarounds insert a simple paragraph after screen -[listingblock] -{title} - -| - -{title#} - -[verseblock] -{title} -{title%} -{title#} -| - -{title#} -{title%} -endif::doctype-manpage[] -endif::backend-docbook[] - -ifdef::backend-xhtml11[] -[attributes] -git-relative-html-prefix= -[linkgit-inlinemacro] -{target}{0?({0})} - -[literal-inlinemacro] -{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1\2', re.sub(r'(\.\.\.?)([^\]$.])', r'\1\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} - -endif::backend-xhtml11[] - -ifdef::backend-docbook[] -ifdef::doctype-manpage[] -[paradef-default] -synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!\\0!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1\\2!g;s!<[-a-zA-Z0-9.]\\+>!\\0!g'" -endif::doctype-manpage[] -endif::backend-docbook[] - -ifdef::backend-xhtml11[] -[paradef-default] -synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!\\0!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1\\2!g;s!<[-a-zA-Z0-9.]\\+>!\\0!g'" -endif::backend-xhtml11[] diff --git a/Documentation/asciidoc.conf.in b/Documentation/asciidoc.conf.in new file mode 100644 index 0000000000..dbe36a52ea --- /dev/null +++ b/Documentation/asciidoc.conf.in @@ -0,0 +1,82 @@ +## linkgit: macro +# +# Usage: linkgit:command[manpage-section] +# +# Note, {0} is the manpage section, while {target} is the command. +# +# Show Git link as: (
); if section is defined, else just show +# the command. + +[macros] +(?su)[\\]?(?Plinkgit):(?P\S*?)\[(?P.*?)\]= + +[attributes] +asterisk=* +plus=+ +caret=^ +startsb=[ +endsb=] +backslash=\ +tilde=~ +apostrophe=' +backtick=` +litdd=-- +manmanual='Git Manual' +mansource='Git @GIT_VERSION@' +revdate='@GIT_DATE@' + +ifdef::backend-docbook[] +[linkgit-inlinemacro] +{0%{target}} +{0#} +{0#{target}{0}} +{0#} + +[literal-inlinemacro] +{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1\2', re.sub(r'(\.\.\.?)([^\]$.])', r'\1\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} + +endif::backend-docbook[] + +ifdef::backend-docbook[] +ifdef::doctype-manpage[] +# The following two small workarounds insert a simple paragraph after screen +[listingblock] +{title} + +| + +{title#} + +[verseblock] +{title} +{title%} +{title#} +| + +{title#} +{title%} +endif::doctype-manpage[] +endif::backend-docbook[] + +ifdef::backend-xhtml11[] +[attributes] +git-relative-html-prefix= +[linkgit-inlinemacro] +{target}{0?({0})} + +[literal-inlinemacro] +{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1\2', re.sub(r'(\.\.\.?)([^\]$.])', r'\1\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} + +endif::backend-xhtml11[] + +ifdef::backend-docbook[] +ifdef::doctype-manpage[] +[paradef-default] +synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!\\0!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1\\2!g;s!<[-a-zA-Z0-9.]\\+>!\\0!g'" +endif::doctype-manpage[] +endif::backend-docbook[] + +ifdef::backend-xhtml11[] +[paradef-default] +synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!\\0!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1\\2!g;s!<[-a-zA-Z0-9.]\\+>!\\0!g'" +endif::backend-xhtml11[] diff --git a/Documentation/asciidoctor-extensions.rb b/Documentation/asciidoctor-extensions.rb deleted file mode 100644 index cb24480b63..0000000000 --- a/Documentation/asciidoctor-extensions.rb +++ /dev/null @@ -1,135 +0,0 @@ -require 'asciidoctor' -require 'asciidoctor/extensions' -require 'asciidoctor/converter/docbook5' -require 'asciidoctor/converter/html5' - -module Git - module Documentation - class LinkGitProcessor < Asciidoctor::Extensions::InlineMacroProcessor - use_dsl - - named :chrome - - def process(parent, target, attrs) - prefix = parent.document.attr('git-relative-html-prefix') - if parent.document.doctype == 'book' - "" \ - "#{target}(#{attrs[1]})" - elsif parent.document.basebackend? 'html' - %(#{target}(#{attrs[1]})) - elsif parent.document.basebackend? 'docbook' - "\n" \ - "#{target}" \ - "#{attrs[1]}\n" \ - "" - end - end - end - - class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor - def process document, output - if document.basebackend? 'docbook' - mansource = document.attributes['mansource'] - manversion = document.attributes['manversion'] - manmanual = document.attributes['manmanual'] - new_tags = "" \ - "#{mansource}\n" \ - "#{manversion}\n" \ - "#{manmanual}\n" - output = output.sub(/<\/refmeta>/, new_tags + "") - end - output - end - end - - class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor - - use_dsl - named :synopsis - parse_content_as :simple - - def process parent, reader, attrs - outlines = reader.lines.map do |l| - l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2') - .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$]+)}, '\1{empty}`\2`{empty}') - .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__') - .gsub(']', ']{empty}') - end - create_block parent, :verse, outlines, attrs - end - end - - class GitDBConverter < Asciidoctor::Converter::DocBook5Converter - - extend Asciidoctor::Converter::Config - register_for 'docbook5' - - def convert_inline_quoted node - if (type = node.type) == :asciimath - # NOTE fop requires jeuclid to process mathml markup - asciimath_available? ? %(#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}) : %() - elsif type == :latexmath - # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math - %() - elsif type == :monospaced - node.text.gsub(/(\.\.\.?)([^\]$.])/, '\1\2') - .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1\2') - .gsub(/(<[-a-zA-Z0-9.]+>)/, '\1') - else - open, close, supports_phrase = QUOTE_TAGS[type] - text = node.text - if node.role - if supports_phrase - quoted_text = %(#{open}#{text}#{close}) - else - quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close}) - end - else - quoted_text = %(#{open}#{text}#{close}) - end - node.id ? %(#{quoted_text}) : quoted_text - end - end - end - - # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis - class GitHTMLConverter < Asciidoctor::Converter::Html5Converter - - extend Asciidoctor::Converter::Config - register_for 'html5' - - def convert_inline_quoted node - if node.type == :monospaced - node.text.gsub(/(\.\.\.?)([^\]$.])/, '\1\2') - .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1\2') - .gsub(/(<[-a-zA-Z0-9.]+>)/, '\1') - - else - open, close, tag = QUOTE_TAGS[node.type] - if node.id - class_attr = node.role ? %( class="#{node.role}") : '' - if tag - %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close}) - else - %(#{open}#{node.text}#{close}) - end - elsif node.role - if tag - %(#{open.chop} class="#{node.role}">#{node.text}#{close}) - else - %(#{open}#{node.text}#{close}) - end - else - %(#{open}#{node.text}#{close}) - end - end - end - end - end -end - -Asciidoctor::Extensions.register do - inline_macro Git::Documentation::LinkGitProcessor, :linkgit - block Git::Documentation::SynopsisBlock - postprocessor Git::Documentation::DocumentPostProcessor -end diff --git a/Documentation/asciidoctor-extensions.rb.in b/Documentation/asciidoctor-extensions.rb.in new file mode 100644 index 0000000000..c4c200dace --- /dev/null +++ b/Documentation/asciidoctor-extensions.rb.in @@ -0,0 +1,131 @@ +require 'asciidoctor' +require 'asciidoctor/extensions' +require 'asciidoctor/converter/docbook5' +require 'asciidoctor/converter/html5' + +module Git + module Documentation + class LinkGitProcessor < Asciidoctor::Extensions::InlineMacroProcessor + use_dsl + + named :chrome + + def process(parent, target, attrs) + prefix = parent.document.attr('git-relative-html-prefix') + if parent.document.doctype == 'book' + "" \ + "#{target}(#{attrs[1]})" + elsif parent.document.basebackend? 'html' + %(#{target}(#{attrs[1]})) + elsif parent.document.basebackend? 'docbook' + "\n" \ + "#{target}" \ + "#{attrs[1]}\n" \ + "" + end + end + end + + class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor + def process document, output + if document.basebackend? 'docbook' + new_tags = "" \ + "@GIT_VERSION@\n" \ + "Git Manual\n" + output = output.sub(/<\/refmeta>/, new_tags + "") + end + output + end + end + + class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor + + use_dsl + named :synopsis + parse_content_as :simple + + def process parent, reader, attrs + outlines = reader.lines.map do |l| + l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2') + .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$]+)}, '\1{empty}`\2`{empty}') + .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__') + .gsub(']', ']{empty}') + end + create_block parent, :verse, outlines, attrs + end + end + + class GitDBConverter < Asciidoctor::Converter::DocBook5Converter + + extend Asciidoctor::Converter::Config + register_for 'docbook5' + + def convert_inline_quoted node + if (type = node.type) == :asciimath + # NOTE fop requires jeuclid to process mathml markup + asciimath_available? ? %(#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}) : %() + elsif type == :latexmath + # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math + %() + elsif type == :monospaced + node.text.gsub(/(\.\.\.?)([^\]$.])/, '\1\2') + .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1\2') + .gsub(/(<[-a-zA-Z0-9.]+>)/, '\1') + else + open, close, supports_phrase = QUOTE_TAGS[type] + text = node.text + if node.role + if supports_phrase + quoted_text = %(#{open}#{text}#{close}) + else + quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close}) + end + else + quoted_text = %(#{open}#{text}#{close}) + end + node.id ? %(#{quoted_text}) : quoted_text + end + end + end + + # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis + class GitHTMLConverter < Asciidoctor::Converter::Html5Converter + + extend Asciidoctor::Converter::Config + register_for 'html5' + + def convert_inline_quoted node + if node.type == :monospaced + node.text.gsub(/(\.\.\.?)([^\]$.])/, '\1\2') + .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1\2') + .gsub(/(<[-a-zA-Z0-9.]+>)/, '\1') + + else + open, close, tag = QUOTE_TAGS[node.type] + if node.id + class_attr = node.role ? %( class="#{node.role}") : '' + if tag + %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close}) + else + %(#{open}#{node.text}#{close}) + end + elsif node.role + if tag + %(#{open.chop} class="#{node.role}">#{node.text}#{close}) + else + %(#{open}#{node.text}#{close}) + end + else + %(#{open}#{node.text}#{close}) + end + end + end + end + end +end + +Asciidoctor::Extensions.register do + inline_macro Git::Documentation::LinkGitProcessor, :linkgit + block Git::Documentation::SynopsisBlock + postprocessor Git::Documentation::DocumentPostProcessor +end diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index a1c8146f05..b4687784c1 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -53,6 +53,7 @@ fi GIT_VERSION=$(expr "$VN" : v*'\(.*\)') GIT_BUILT_FROM_COMMIT=$(git -C "$SOURCE_DIR" rev-parse -q --verify HEAD 2>/dev/null) +GIT_DATE=$(git -C "$SOURCE_DIR" show --quiet --format='%as' 2>/dev/null) if test -z "$GIT_USER_AGENT" then GIT_USER_AGENT="git/$GIT_VERSION" @@ -72,6 +73,7 @@ sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ -e "s|@GIT_PATCH_LEVEL@|$GIT_PATCH_LEVEL|" \ -e "s|@GIT_BUILT_FROM_COMMIT@|$GIT_BUILT_FROM_COMMIT|" \ -e "s|@GIT_USER_AGENT@|$GIT_USER_AGENT|" \ + -e "s|@GIT_DATE@|$GIT_DATE|" \ "$INPUT" >"$OUTPUT"+ if ! test -f "$OUTPUT" || ! cmp "$OUTPUT"+ "$OUTPUT" >/dev/null -- cgit v1.3 From 95bcd6f0b709ec6e761270732946651757cc11c3 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:50 +0100 Subject: Makefile: allow "bin-wrappers/" directory to exist The "bin-wrappers/" directory gets created by our build system and is populated with one script for each of our binaries. There isn't anything inherently wrong with the current layout, but it is somewhat hard to adapt for out-of-tree build systems. Adapt the layout such that our "bin-wrappers/" directory always exists and contains our "wrap-for-bin.sh" script to make things a little bit easier for subsequent steps. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- .gitignore | 1 - Documentation/CodingGuidelines | 2 +- Makefile | 6 +++--- bin-wrappers/.gitignore | 9 +++++++++ bin-wrappers/wrap-for-bin.sh | 36 ++++++++++++++++++++++++++++++++++++ contrib/buildsystems/CMakeLists.txt | 6 +++--- wrap-for-bin.sh | 36 ------------------------------------ 7 files changed, 52 insertions(+), 44 deletions(-) create mode 100644 bin-wrappers/.gitignore create mode 100755 bin-wrappers/wrap-for-bin.sh delete mode 100644 wrap-for-bin.sh (limited to 'Documentation') diff --git a/.gitignore b/.gitignore index d3be460040..e82aa19df0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ /GIT-TEST-SUITES /GIT-USER-AGENT /GIT-VERSION-FILE -/bin-wrappers/ /git /git-add /git-am diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index 87904791cb..1df9d0c42f 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -583,7 +583,7 @@ For C programs: Run `GIT_DEBUGGER=1 ./bin-wrappers/git foo` to simply use gdb as is, or run `GIT_DEBUGGER=" " ./bin-wrappers/git foo` to use your own debugger and arguments. Example: `GIT_DEBUGGER="ddd --gdb" - ./bin-wrappers/git log` (See `wrap-for-bin.sh`.) + ./bin-wrappers/git log` (See `bin-wrappers/wrap-for-bin.sh`.) - The primary data structure that a subsystem 'S' deals with is called `struct S`. Functions that operate on `struct S` are named diff --git a/Makefile b/Makefile index 009e7d8e95..6e93319bed 100644 --- a/Makefile +++ b/Makefile @@ -3202,8 +3202,7 @@ test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $( all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) -bin-wrappers/%: wrap-for-bin.sh - $(call mkdir_p_parent_template) +$(test_bindir_programs): bin-wrappers/%: bin-wrappers/wrap-for-bin.sh $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e 's|@BUILD_DIR@|$(shell pwd)|' \ -e 's|@PROG@|$(patsubst test-%,t/helper/test-%,$(@F))$(if $(filter-out $(BINDIR_PROGRAMS_NO_X),$(@F)),$(X),)|' < $< > $@ && \ @@ -3700,7 +3699,8 @@ clean: profile-clean coverage-clean cocciclean $(RM) $(SP_OBJ) $(RM) $(HCC) $(RM) version-def.h - $(RM) -r bin-wrappers $(dep_dirs) $(compdb_dir) compile_commands.json + $(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json + $(RM) $(test_bindir_programs) $(RM) -r po/build/ $(RM) *.pyc *.pyo */*.pyc */*.pyo $(GENERATED_H) $(ETAGS_TARGET) tags cscope* $(RM) -r .dist-tmp-dir .doc-tmp-dir diff --git a/bin-wrappers/.gitignore b/bin-wrappers/.gitignore new file mode 100644 index 0000000000..1c6c90458b --- /dev/null +++ b/bin-wrappers/.gitignore @@ -0,0 +1,9 @@ +/git +/git-cvsserver +/git-receive-pack +/git-shell +/git-upload-archive +/git-upload-pack +/scalar +/test-fake-ssh +/test-tool diff --git a/bin-wrappers/wrap-for-bin.sh b/bin-wrappers/wrap-for-bin.sh new file mode 100755 index 0000000000..7898a1c238 --- /dev/null +++ b/bin-wrappers/wrap-for-bin.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# wrap-for-bin.sh: Template for git executable wrapper scripts +# to run test suite against sandbox, but with only bindir-installed +# executables in PATH. The Makefile copies this into various +# files in bin-wrappers, substituting +# @BUILD_DIR@ and @PROG@. + +GIT_EXEC_PATH='@BUILD_DIR@' +if test -n "$NO_SET_GIT_TEMPLATE_DIR" +then + unset GIT_TEMPLATE_DIR +else + GIT_TEMPLATE_DIR='@BUILD_DIR@/templates/blt' + export GIT_TEMPLATE_DIR +fi +GITPERLLIB='@BUILD_DIR@/perl/build/lib'"${GITPERLLIB:+:$GITPERLLIB}" +GIT_TEXTDOMAINDIR='@BUILD_DIR@/po/build/locale' +PATH='@BUILD_DIR@/bin-wrappers:'"$PATH" + +export GIT_EXEC_PATH GITPERLLIB PATH GIT_TEXTDOMAINDIR + +case "$GIT_DEBUGGER" in +'') + exec "${GIT_EXEC_PATH}/@PROG@" "$@" + ;; +1) + unset GIT_DEBUGGER + exec gdb --args "${GIT_EXEC_PATH}/@PROG@" "$@" + ;; +*) + GIT_DEBUGGER_ARGS="$GIT_DEBUGGER" + unset GIT_DEBUGGER + exec ${GIT_DEBUGGER_ARGS} "${GIT_EXEC_PATH}/@PROG@" "$@" + ;; +esac diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index e7bd45cbb6..9348665f22 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -1095,20 +1095,20 @@ set(wrapper_test_scripts foreach(script ${wrapper_scripts}) - file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME) + file(STRINGS ${CMAKE_SOURCE_DIR}/bin-wrappers/wrap-for-bin.sh content NEWLINE_CONSUME) string(REPLACE "@BUILD_DIR@" "${CMAKE_BINARY_DIR}" content "${content}") string(REPLACE "@PROG@" "${script}${EXE_EXTENSION}" content "${content}") file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/${script} ${content}) endforeach() foreach(script ${wrapper_test_scripts}) - file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME) + file(STRINGS ${CMAKE_SOURCE_DIR}/bin-wrappers/wrap-for-bin.sh content NEWLINE_CONSUME) string(REPLACE "@BUILD_DIR@" "${CMAKE_BINARY_DIR}" content "${content}") string(REPLACE "@PROG@" "t/helper/${script}${EXE_EXTENSION}" content "${content}") file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/${script} ${content}) endforeach() -file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME) +file(STRINGS ${CMAKE_SOURCE_DIR}/bin-wrappers/wrap-for-bin.sh content NEWLINE_CONSUME) string(REPLACE "@BUILD_DIR@" "${CMAKE_BINARY_DIR}" content "${content}") string(REPLACE "@PROG@" "git-cvsserver" content "${content}") file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/git-cvsserver ${content}) diff --git a/wrap-for-bin.sh b/wrap-for-bin.sh deleted file mode 100644 index 7898a1c238..0000000000 --- a/wrap-for-bin.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# wrap-for-bin.sh: Template for git executable wrapper scripts -# to run test suite against sandbox, but with only bindir-installed -# executables in PATH. The Makefile copies this into various -# files in bin-wrappers, substituting -# @BUILD_DIR@ and @PROG@. - -GIT_EXEC_PATH='@BUILD_DIR@' -if test -n "$NO_SET_GIT_TEMPLATE_DIR" -then - unset GIT_TEMPLATE_DIR -else - GIT_TEMPLATE_DIR='@BUILD_DIR@/templates/blt' - export GIT_TEMPLATE_DIR -fi -GITPERLLIB='@BUILD_DIR@/perl/build/lib'"${GITPERLLIB:+:$GITPERLLIB}" -GIT_TEXTDOMAINDIR='@BUILD_DIR@/po/build/locale' -PATH='@BUILD_DIR@/bin-wrappers:'"$PATH" - -export GIT_EXEC_PATH GITPERLLIB PATH GIT_TEXTDOMAINDIR - -case "$GIT_DEBUGGER" in -'') - exec "${GIT_EXEC_PATH}/@PROG@" "$@" - ;; -1) - unset GIT_DEBUGGER - exec gdb --args "${GIT_EXEC_PATH}/@PROG@" "$@" - ;; -*) - GIT_DEBUGGER_ARGS="$GIT_DEBUGGER" - unset GIT_DEBUGGER - exec ${GIT_DEBUGGER_ARGS} "${GIT_EXEC_PATH}/@PROG@" "$@" - ;; -esac -- cgit v1.3 From 9219325be74c35c493a61ab3107d215cad91cf38 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:53 +0100 Subject: Documentation: allow sourcing generated includes from separate dir Our documentation uses "include::" directives to include parts that are either reused across multiple documents or parts that we generate at build time. Unfortunately, top-level includes are only ever resolved relative to the base directory, which is typically the directory of the including document. Most importantly, it is not possible to have either asciidoc or asciidoctor search multiple directories. It follows that both kinds of includes must live in the same directory. This is of course a bummer for out-of-tree builds, because here the dynamically-built includes live in the build directory whereas the static includes live in the source directory. Introduce a `build_dir` attribute and prepend it to all of our includes for dynamically-built files. This attribute gets set to the build directory and thus converts the include path to an absolute path, which asciidoc and asciidoctor know how to resolve. Note that this change also requires us to update "build-docdep.perl", which tries to figure out included files such our Makefile can set up proper build-time dependencies. This script simply scans through the source files for any lines that match "^include::" and treats the remainder of the line as included file path. But given that those may now contain the "{build_dir}" variable we have to teach the script to replace that attribute with the actual build directory. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 3 ++- Documentation/build-docdep.perl | 2 ++ Documentation/config/diff.txt | 2 +- Documentation/config/merge.txt | 2 +- Documentation/git.txt | 24 ++++++++++++------------ 5 files changed, 18 insertions(+), 15 deletions(-) (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index 9371f29425..a74fc0ff3d 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -224,6 +224,7 @@ SHELL_PATH ?= $(SHELL) # Shell quote; SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) +ASCIIDOC_EXTRA += -abuild_dir='$(shell pwd)' ifdef DEFAULT_PAGER DEFAULT_PAGER_SQ = $(subst ','\'',$(DEFAULT_PAGER)) ASCIIDOC_EXTRA += -a 'git-default-pager=$(DEFAULT_PAGER_SQ)' @@ -289,7 +290,7 @@ docdep_prereqs = \ cmd-list.made $(cmds_txt) doc.dep : $(docdep_prereqs) $(DOC_DEP_TXT) build-docdep.perl - $(QUIET_GEN)$(PERL_PATH) ./build-docdep.perl >$@ $(QUIET_STDERR) + $(QUIET_GEN)$(PERL_PATH) ./build-docdep.perl "$(shell pwd)" >$@ $(QUIET_STDERR) ifneq ($(MAKECMDGOALS),clean) -include doc.dep diff --git a/Documentation/build-docdep.perl b/Documentation/build-docdep.perl index 1b3ac8fdd9..315efaa2fa 100755 --- a/Documentation/build-docdep.perl +++ b/Documentation/build-docdep.perl @@ -1,5 +1,6 @@ #!/usr/bin/perl +my ($build_dir) = @ARGV; my %include = (); my %included = (); @@ -10,6 +11,7 @@ for my $text (<*.txt>) { chomp; s/^include::\s*//; s/\[\]//; + s/{build_dir}/${build_dir}/; $include{$text}{$_} = 1; $included{$_} = 1; } diff --git a/Documentation/config/diff.txt b/Documentation/config/diff.txt index 45f3fe855c..fdae13a212 100644 --- a/Documentation/config/diff.txt +++ b/Documentation/config/diff.txt @@ -218,7 +218,7 @@ endif::git-diff[] Set this option to `true` to make the diff driver cache the text conversion outputs. See linkgit:gitattributes[5] for details. -include::../mergetools-diff.txt[] +include::{build_dir}/mergetools-diff.txt[] `diff.indentHeuristic`:: Set this option to `false` to disable the default heuristics diff --git a/Documentation/config/merge.txt b/Documentation/config/merge.txt index 8851b6cede..82554d65a0 100644 --- a/Documentation/config/merge.txt +++ b/Documentation/config/merge.txt @@ -101,7 +101,7 @@ merge.guitool:: Any other value is treated as a custom merge tool and requires that a corresponding mergetool..cmd variable is defined. -include::../mergetools-merge.txt[] +include::{build_dir}/mergetools-merge.txt[] merge.verbosity:: Controls the amount of output shown by the recursive merge diff --git a/Documentation/git.txt b/Documentation/git.txt index d15a869762..44f0797ccf 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -245,17 +245,17 @@ ancillary user utilities. Main porcelain commands ~~~~~~~~~~~~~~~~~~~~~~~ -include::cmds-mainporcelain.txt[] +include::{build_dir}/cmds-mainporcelain.txt[] Ancillary Commands ~~~~~~~~~~~~~~~~~~ Manipulators: -include::cmds-ancillarymanipulators.txt[] +include::{build_dir}/cmds-ancillarymanipulators.txt[] Interrogators: -include::cmds-ancillaryinterrogators.txt[] +include::{build_dir}/cmds-ancillaryinterrogators.txt[] Interacting with Others @@ -264,7 +264,7 @@ Interacting with Others These commands are to interact with foreign SCM and with other people via patch over e-mail. -include::cmds-foreignscminterface.txt[] +include::{build_dir}/cmds-foreignscminterface.txt[] Reset, restore and revert ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -313,13 +313,13 @@ repositories. Manipulation commands ~~~~~~~~~~~~~~~~~~~~~ -include::cmds-plumbingmanipulators.txt[] +include::{build_dir}/cmds-plumbingmanipulators.txt[] Interrogation commands ~~~~~~~~~~~~~~~~~~~~~~ -include::cmds-plumbinginterrogators.txt[] +include::{build_dir}/cmds-plumbinginterrogators.txt[] In general, the interrogate commands do not touch the files in the working tree. @@ -328,12 +328,12 @@ the working tree. Syncing repositories ~~~~~~~~~~~~~~~~~~~~ -include::cmds-synchingrepositories.txt[] +include::{build_dir}/cmds-synchingrepositories.txt[] The following are helper commands used by the above; end users typically do not use them directly. -include::cmds-synchelpers.txt[] +include::{build_dir}/cmds-synchelpers.txt[] Internal helper commands @@ -342,14 +342,14 @@ Internal helper commands These are internal helper commands used by other commands; end users typically do not use them directly. -include::cmds-purehelpers.txt[] +include::{build_dir}/cmds-purehelpers.txt[] Guides ------ The following documentation pages are guides about Git concepts. -include::cmds-guide.txt[] +include::{build_dir}/cmds-guide.txt[] Repository, command and file interfaces --------------------------------------- @@ -358,7 +358,7 @@ This documentation discusses repository and command interfaces which users are expected to interact with directly. See `--user-formats` in linkgit:git-help[1] for more details on the criteria. -include::cmds-userinterfaces.txt[] +include::{build_dir}/cmds-userinterfaces.txt[] File formats, protocols and other developer interfaces ------------------------------------------------------ @@ -367,7 +367,7 @@ This documentation discusses file formats, over-the-wire protocols and other git developer interfaces. See `--developer-interfaces` in linkgit:git-help[1]. -include::cmds-developerinterfaces.txt[] +include::{build_dir}/cmds-developerinterfaces.txt[] Configuration Mechanism ----------------------- -- cgit v1.3 From 628d49f6e595694afc657fd80c1a12bb09c693b7 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:54 +0100 Subject: Documentation: teach "cmd-list.perl" about out-of-tree builds The "cmd-list.perl" script generates a list of commands that can be included into our manpages. The script doesn't know about out-of-tree builds and instead writes resulting files into the source directory. Adapt it such that we can read data from the source directory and write data into the build directory. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 2 +- Documentation/cmd-list.perl | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index a74fc0ff3d..e853d89eb5 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -312,7 +312,7 @@ cmds_txt = cmds-ancillaryinterrogators.txt \ $(cmds_txt): cmd-list.made cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) - $(QUIET_GEN)$(PERL_PATH) ./cmd-list.perl ../command-list.txt $(cmds_txt) $(QUIET_STDERR) && \ + $(QUIET_GEN)$(PERL_PATH) ./cmd-list.perl .. . $(cmds_txt) && \ date >$@ mergetools_txt = mergetools-diff.txt mergetools-merge.txt diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl index 755a110bc4..e260a98977 100755 --- a/Documentation/cmd-list.perl +++ b/Documentation/cmd-list.perl @@ -3,12 +3,13 @@ use File::Compare qw(compare); sub format_one { - my ($out, $nameattr) = @_; + my ($source_dir, $out, $nameattr) = @_; my ($name, $attr) = @$nameattr; + my ($path) = "$source_dir/Documentation/$name.txt"; my ($state, $description); my $mansection; $state = 0; - open I, '<', "$name.txt" or die "No such file $name.txt"; + open I, '<', "$path" or die "No such file $path.txt"; while () { if (/^(?:git|scalar)[a-z0-9-]*\(([0-9])\)$/) { $mansection = $1; @@ -29,7 +30,7 @@ sub format_one { } close I; if (!defined $description) { - die "No description found in $name.txt"; + die "No description found in $path.txt"; } if (my ($verify_name, $text) = ($description =~ /^($name) - (.*)/)) { print $out "linkgit:$name\[$mansection\]::\n\t"; @@ -43,9 +44,9 @@ sub format_one { } } -my ($input, @categories) = @ARGV; +my ($source_dir, $build_dir, @categories) = @ARGV; -open IN, "<$input"; +open IN, "<$source_dir/command-list.txt"; while () { last if /^### command list/; } @@ -63,17 +64,17 @@ close IN; for my $out (@categories) { my ($cat) = $out =~ /^cmds-(.*)\.txt$/; - open O, '>', "$out+" or die "Cannot open output file $out+"; + my ($path) = "$build_dir/$out"; + open O, '>', "$path+" or die "Cannot open output file $out+"; for (@{$cmds{$cat}}) { - format_one(\*O, $_); + format_one($source_dir, \*O, $_); } close O; - if (-f "$out" && compare("$out", "$out+") == 0) { - unlink "$out+"; + if (-f "$path" && compare("$path", "$path+") == 0) { + unlink "$path+"; } else { - print STDERR "$out\n"; - rename "$out+", "$out"; + rename "$path+", "$path"; } } -- cgit v1.3 From 023c3370ac330760aaf399cf6f6d9dbd7350e8e5 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:55 +0100 Subject: Documentation: extract script to generate a list of mergetools We include the list of available mergetools into our manpages. Extract the script that performs this logic such that we can reuse it in other build systems. While at it, refactor the Makefile targets such that we don't create "mergetools-list.made" anymore. It shouldn't be necessary, as we can instead have other targets depend on "mergetools-{diff,merge}.txt" directly. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 22 ++++++++-------------- Documentation/generate-mergetool-list.sh | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) create mode 100755 Documentation/generate-mergetool-list.sh (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index e853d89eb5..f0e5bc9c0c 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -282,11 +282,13 @@ ifneq ($(filter-out lint-docs clean,$(MAKECMDGOALS)),) -include ../GIT-VERSION-FILE endif +mergetools_txt = mergetools-diff.txt mergetools-merge.txt + # # Determine "include::" file references in asciidoc files. # docdep_prereqs = \ - mergetools-list.made $(mergetools_txt) \ + $(mergetools_txt) \ cmd-list.made $(cmds_txt) doc.dep : $(docdep_prereqs) $(DOC_DEP_TXT) build-docdep.perl @@ -315,19 +317,11 @@ cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) $(QUIET_GEN)$(PERL_PATH) ./cmd-list.perl .. . $(cmds_txt) && \ date >$@ -mergetools_txt = mergetools-diff.txt mergetools-merge.txt - -$(mergetools_txt): mergetools-list.made - -mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*) - $(QUIET_GEN) \ - $(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && TOOL_MODE=diff && \ - . ../git-mergetool--lib.sh && \ - show_tool_names can_diff' | sed -e "s/\([a-z0-9]*\)/\`\1\`;;/" >mergetools-diff.txt && \ - $(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && TOOL_MODE=merge && \ - . ../git-mergetool--lib.sh && \ - show_tool_names can_merge' | sed -e "s/\([a-z0-9]*\)/\`\1\`;;/" >mergetools-merge.txt && \ - date >$@ +mergetools-%.txt: generate-mergetool-list.sh ../git-mergetool--lib.sh $(wildcard ../mergetools/*) +mergetools-diff.txt: + $(QUIET_GEN)$(SHELL_PATH) ./generate-mergetool-list.sh .. diff $@ +mergetools-merge.txt: + $(QUIET_GEN)$(SHELL_PATH) ./generate-mergetool-list.sh .. merge $@ TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK)) diff --git a/Documentation/generate-mergetool-list.sh b/Documentation/generate-mergetool-list.sh new file mode 100755 index 0000000000..6700498b93 --- /dev/null +++ b/Documentation/generate-mergetool-list.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if test "$#" -ne 3 +then + echo >&2 "USAGE: $0 " + exit 1 +fi + +SOURCE_DIR="$1" +TOOL_MODE="$2" +OUTPUT="$3" +MERGE_TOOLS_DIR="$SOURCE_DIR/mergetools" + +( + . "$SOURCE_DIR"/git-mergetool--lib.sh && + show_tool_names can_$TOOL_MODE +) | sed -e "s/\([a-z0-9]*\)/\`\1\`;;/" >"$OUTPUT" -- cgit v1.3 From 00ab97b1bc07206be4d05547fe44bfd7afd607dc Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:58 +0100 Subject: Documentation: add comparison of build systems We're contemplating whether to eventually replace our build systems with a build system that is easier to use. Add a comparison of build systems to our technical documentation as a baseline for discussion. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 1 + Documentation/technical/build-systems.txt | 224 ++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 Documentation/technical/build-systems.txt (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index f0e5bc9c0c..3392e1ce7e 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -113,6 +113,7 @@ TECH_DOCS += MyFirstObjectWalk TECH_DOCS += SubmittingPatches TECH_DOCS += ToolsForGit TECH_DOCS += technical/bitmap-format +TECH_DOCS += technical/build-systems TECH_DOCS += technical/bundle-uri TECH_DOCS += technical/hash-function-transition TECH_DOCS += technical/long-running-process-protocol diff --git a/Documentation/technical/build-systems.txt b/Documentation/technical/build-systems.txt new file mode 100644 index 0000000000..d9dafb407c --- /dev/null +++ b/Documentation/technical/build-systems.txt @@ -0,0 +1,224 @@ += Build Systems + +The build system is the primary way for both developers and system integrators +to interact with the Git project. As such, being easy to use and extend for +those who are not directly developing Git itself is just as important as other +requirements we have on any potential build system. + +This document outlines the different requirements that we have for the build +system and then compares available build systems using these criteria. + +== Requirements + +The following subsections present a list of requirements that we have for any +potential build system. Sections are sorted by decreasing priority. + +=== Platform support + +The build system must have support for all of our platforms that we continually +test against as outlined by our platform support policy. These platforms are: + + - Linux + - Windows + - macOS + +Furthermore, the build system should have support for the following platforms +that generally have somebody running test pipelines against regularly: + + - AIX + - FreeBSD + - NetBSD + - NonStop + - OpenBSD + +The platforms which must be supported by the tool should be aligned with our +[platform support policy](platform-support.txt). + +=== Auto-detection of supported features + +The build system must support auto-detection of features which are or aren't +available on the current platform. Platform maintainers should not be required +to manually configure the complete build. + +Auto-detection of the following items is considered to be important: + + - Check for the existence of headers. + - Check for the existence of libraries. + - Check for the existence of exectuables. + - Check for the runtime behavior of specific functions. + - Check for specific link order requirements when multiple libraries are + involved. + +=== Ease of use + +The build system should be both easy to use and easy to extend. While this is +naturally a subjective metric it is likely not controversial to say that some +build systems are considerably harder to use than others. + +=== IDE support + +The build system should integrate with well-known IDEs. Well-known IDEs include: + + - Microsoft Visual Studio + - Visual Studio Code + - Xcode + +There are four levels of support: + + - Native integration into the IDE. + - Integration into the IDE via a plugin. + - Integration into the IDE via generating a project description with the build + system. + - No integration. + +Native integration is preferable, but integration via either a plugin or by +generating a project description via the build system are considered feasible +alternatives. + +Another important distinction is the level of integration. There are two +features that one generally wants to have: + + - Integration of build targets. + - Automatic setup of features like code completion with detected build + dependencies. + +The first bullet point is the bare minimum, but is not sufficient to be +considered proper integration. + +=== Out-of-tree builds + +The build system should support out-of-tree builds. Out-of-tree builds allow a +developer to configure multiple different build directories with different +configuration, e.g. one "debug" build and one "release" build. + +=== Cross-platform builds + +The build system should support cross-platform builds, e.g. building for arm on +an x86-64 host. + +=== Language support + +The following languages and toolchains are of relevance and should be supported +by the build system: + + - C: the primary compiled language used by Git, must be supported. Relevant + toolchains are GCC, Clang and MSVC. + - Rust: candidate as a second compiled lanugage, should be supported. Relevant + toolchains is the LLVM-based rustc. + +Built-in support for the respective languages is preferred over support that +needs to be wired up manually to avoid unnecessary complexity. Native support +includes the following features: + + - Compiling objects. + - Dependency tracking. + - Detection of available features. + - Discovery of relevant toolchains. + - Linking libraries and executables. + - Templating placeholders in scripts. + +=== Test integration + +It should be possible to integrate tests into the build system such that it is +possible to build and test Git within the build system. Features which are nice +to have: + + - Track build-time dependencies for respective tests. Unit tests have + different requirements than integration tests. + - Allow filtering of which tests to run. + - Allow running tests such that utilities like `test_pause` or `debug` work. + +== Comparison + +The following list of build systems are considered: + +- GNU Make +- autoconf +- CMake +- Meson + +=== GNU Make + +- Platform support: ubitquitous on all platforms, but not well-integrated into Windows. +- Auto-detection: no built-in support for auto-detection of features. +- Ease of use: easy to use, but discovering available options is hard. Makefile + rules can quickly get out of hand once reaching a certain scope. +- IDE support: execution of Makefile targets is supported by many IDEs +- Out-of-tree builds: supported in theory, not wired up in practice. +- Cross-platform builds: supported in theory, not wired up in practice. +- Language support: + - C: Limited built-in support, many parts need to be wired up manually. + - Rust: No built-in support, needs to be wired up manually. +- Test integration: partially supported, many parts need to be wired up + manually. + +=== autoconf + +- Platform support: ubiquitous on all platforms, but not well-integrated into Windows. +- Auto-detection: supported. +- Ease of use: easy to use, discovering available options is comparatively + easy. The autoconf syntax is prohibitively hard to extend though due to its + complex set of interacting files and the hard-to-understand M4 language. +- IDE support: no integration into IDEs at generation time. The generated + Makefiles have the same level of support as GNU Make. +- Out-of-tree builds: supported in theory, not wired up in practice. +- Cross-platform builds: supported. +- Language support: + - C: Limited built-in support, many parts need to be wired up manually. + - Rust: No built-in support, needs to be wired up manually. +- Test integration: partially supported, many parts need to be wired up + manually. + +=== CMake + +- Platform support: not as extensive as GNU Make or autoconf, but all major + platforms are supported. + - AIX + - Cygwin + - FreeBSD + - Linux + - OpenBSD + - Solaris + - Windows + - macOS +- Ease of use: easy to use, discovering available options is not always + trivial. The scripting language used by CMake is somewhat cumbersome to use, + but extending CMake build instructions is doable. +- IDE support: natively integrated into Microsoft Visual Studio. Can generate + project descriptions for Xcode. An extension is available for Visual Studio + Code. Many other IDEs have plugins for CMake. +- Out-of-tree builds: supported. +- Cross-platform builds: supported. +- Language support: + - C: Supported for GCC, Clang, MSVC and other toolchains. + - Rust: No built-in support, needs to be wired up manually. +- Test integration: supported, even though test dependencies are a bit + cumbersome to use via "test fixtures". Interactive test runs are not + supported. + +=== Meson + +- Platform: not as extensive as GNU Make or autoconf, but all major platforms + and some smaller ones are supported. + - AIX + - Cygwin + - DragonflyBSD + - FreeBSD + - Haiku + - Linux + - NetBSD + - OpenBSD + - Solaris + - Windows + - macOS +- Ease of use: easy to use, discovering available options is easy. The + scripting language is straight-forward to use. +- IDE support: Supports generating build instructions for Xcode and Microsoft + Visual Studio, a plugin exists for Visual Studio Code. +- Out-of-tree builds: supported. +- Cross-platform builds: supported. +- Language support: + - C: Supported for GCC, Clang, MSVC and other toolchains. + - Rust: Supported for rustc. +- Test integration: supported. Interactive tests are supported starting with + Meson 1.5.0 via the `--interactive` flag. -- cgit v1.3 From 904339edbd80ec5676616af6e072b41804c1c8eb Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:59 +0100 Subject: Introduce support for the Meson build system Introduce support for the Meson build system, a "modern" meta build system that supports many different platforms, including Linux, macOS, Windows and BSDs. Meson supports different backends, including Ninja, Xcode and Microsoft Visual Studio. Several common IDEs provide an integration with it. The biggest contender compared to Meson is probably CMake as outlined in our "Documentation/technical/build-systems.txt" file. Based on my own personal experience from working with both build systems extensively I strongly favor Meson over CMake. In my opinion, it feels significantly easier to use with a syntax that feels more like a "real" programming language. The second big reason is that Meson supports Rust natively, which may prove to be important given that the project may pick up Rust as another language eventually. Using Meson is rather straight-forward. An example: ``` # Meson uses out-of-tree builds. You can set up multiple build # directories, how you name them is completely up to you. $ mkdir build $ cd build $ meson setup .. -Dprefix=/tmp/git-installation # Build the project. This also provides several other targets like e.g. `install` or `test`. $ ninja # Meson has been wired up to support execution of our test suites. # Both our unit tests and our integration tests are supported. # Running `meson test` without any arguments will execute all tests, # but the syntax supports globbing to select only some tests. $ meson test 't-*' # Execute single test interactively to allow for debugging. $ meson test 't0000-*' --interactive --test-args=-ix ``` The build instructions have been successfully tested on the following systems, tests are passing: - Apple macOS 10.15. - FreeBSD 14.1. - NixOS 24.11. - OpenBSD 7.6. - Ubuntu 24.04. - Windows 10 with Cygwin. - Windows 10 with MinGW64, except for t9700, which is also broken with our Makefile. - Windows 10 with Visual Studio 2022 toolchain, using the Native Tools Command Prompt with `meson setup --vsenv`. Tests pass, except for t9700. - Windows 10 with Visual Studio 2022 solution, using the Native Tools Command Prompt with `meson setup --backend vs2022`. Tests pass, except for t9700. - Windows 10 with VS Code, using the Meson plug-in. It is expected that there will still be rough edges in the current version. If this patch lands the expectation is that it will coexist with our other build systems for a while. Like this, distributions can slowly migrate over to Meson and report any findings they have to us such that we can continue to iterate. A potential cutoff date for other build systems may be Git 3.0. Some notes: - The installed distribution is structured somewhat differently than how it used to be the case. All of our binaries are installed into `$libexec/git-core`, while all binaries part of `$bindir` are now symbolic links pointing to the former. This rule is consistent in itself and thus easier to reason about. - We do not install dashed binaries into `$libexec/git-core` anymore, so there won't e.g. be a symlink for git-add(1). These are not required by modern Git and there isn't really much of a use case for those anymore. By not installing those symlinks we thus start the deprecation of this layout. - We're targeting Meson 1.3.0, which has been released relatively recently November 2023. The only feature we use from that version is `fs.relative_to()`, which we could replace if necessary. If so, we could start to target Meson 1.0.0 and newer, released in December 2022. - The whole build instructions count around 3300 lines, half of which is listing all of our code and test files. Our Makefiles are around 5000 lines, autoconf adds another 1300 lines. CMake in comparison has only 1200 linescode, but it avoids listing individual files and does not wire up auto-configuration as extensively as the Meson instructions do. - We bundle a set of subproject wrappers for curl, expat, openssl, pcre2 and zlib. This allows developers to build Git without these dependencies preinstalled, and Meson will fetch and build them automatically. This is especially helpful on Windows. Helped-by: Eli Schwartz Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 324 ++++++ bin-wrappers/meson.build | 28 + contrib/completion/meson.build | 16 + contrib/meson.build | 1 + gitweb/meson.build | 89 ++ meson.build | 1901 ++++++++++++++++++++++++++++++++++++ meson_options.txt | 81 ++ perl/FromCPAN/Mail/meson.build | 7 + perl/FromCPAN/meson.build | 9 + perl/Git/LoadCPAN/Mail/meson.build | 7 + perl/Git/LoadCPAN/meson.build | 9 + perl/Git/SVN/Memoize/meson.build | 7 + perl/Git/SVN/meson.build | 20 + perl/Git/meson.build | 18 + perl/meson.build | 12 + po/meson.build | 27 + subprojects/.gitignore | 1 + subprojects/curl.wrap | 13 + subprojects/expat.wrap | 13 + subprojects/openssl.wrap | 15 + subprojects/pcre2.wrap | 16 + subprojects/zlib.wrap | 13 + t/helper/meson.build | 91 ++ t/meson.build | 1114 +++++++++++++++++++++ templates/hooks/meson.build | 26 + templates/info/meson.build | 7 + templates/meson.build | 15 + 27 files changed, 3880 insertions(+) create mode 100644 Documentation/meson.build create mode 100644 bin-wrappers/meson.build create mode 100644 contrib/completion/meson.build create mode 100644 contrib/meson.build create mode 100644 gitweb/meson.build create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100644 perl/FromCPAN/Mail/meson.build create mode 100644 perl/FromCPAN/meson.build create mode 100644 perl/Git/LoadCPAN/Mail/meson.build create mode 100644 perl/Git/LoadCPAN/meson.build create mode 100644 perl/Git/SVN/Memoize/meson.build create mode 100644 perl/Git/SVN/meson.build create mode 100644 perl/Git/meson.build create mode 100644 perl/meson.build create mode 100644 po/meson.build create mode 100644 subprojects/.gitignore create mode 100644 subprojects/curl.wrap create mode 100644 subprojects/expat.wrap create mode 100644 subprojects/openssl.wrap create mode 100644 subprojects/pcre2.wrap create mode 100644 subprojects/zlib.wrap create mode 100644 t/helper/meson.build create mode 100644 t/meson.build create mode 100644 templates/hooks/meson.build create mode 100644 templates/info/meson.build create mode 100644 templates/meson.build (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build new file mode 100644 index 0000000000..f2426ccaa3 --- /dev/null +++ b/Documentation/meson.build @@ -0,0 +1,324 @@ +manpages = { + # Category 1. + 'git-add.txt' : 1, + 'git-am.txt' : 1, + 'git-annotate.txt' : 1, + 'git-apply.txt' : 1, + 'git-archimport.txt' : 1, + 'git-archive.txt' : 1, + 'git-bisect.txt' : 1, + 'git-blame.txt' : 1, + 'git-branch.txt' : 1, + 'git-bugreport.txt' : 1, + 'git-bundle.txt' : 1, + 'git-cat-file.txt' : 1, + 'git-check-attr.txt' : 1, + 'git-check-ignore.txt' : 1, + 'git-check-mailmap.txt' : 1, + 'git-checkout-index.txt' : 1, + 'git-checkout.txt' : 1, + 'git-check-ref-format.txt' : 1, + 'git-cherry-pick.txt' : 1, + 'git-cherry.txt' : 1, + 'git-citool.txt' : 1, + 'git-clean.txt' : 1, + 'git-clone.txt' : 1, + 'git-column.txt' : 1, + 'git-commit-graph.txt' : 1, + 'git-commit-tree.txt' : 1, + 'git-commit.txt' : 1, + 'git-config.txt' : 1, + 'git-count-objects.txt' : 1, + 'git-credential-cache--daemon.txt' : 1, + 'git-credential-cache.txt' : 1, + 'git-credential-store.txt' : 1, + 'git-credential.txt' : 1, + 'git-cvsexportcommit.txt' : 1, + 'git-cvsimport.txt' : 1, + 'git-cvsserver.txt' : 1, + 'git-daemon.txt' : 1, + 'git-describe.txt' : 1, + 'git-diagnose.txt' : 1, + 'git-diff-files.txt' : 1, + 'git-diff-index.txt' : 1, + 'git-difftool.txt' : 1, + 'git-diff-tree.txt' : 1, + 'git-diff.txt' : 1, + 'git-fast-export.txt' : 1, + 'git-fast-import.txt' : 1, + 'git-fetch-pack.txt' : 1, + 'git-fetch.txt' : 1, + 'git-filter-branch.txt' : 1, + 'git-fmt-merge-msg.txt' : 1, + 'git-for-each-ref.txt' : 1, + 'git-for-each-repo.txt' : 1, + 'git-format-patch.txt' : 1, + 'git-fsck-objects.txt' : 1, + 'git-fsck.txt' : 1, + 'git-fsmonitor--daemon.txt' : 1, + 'git-gc.txt' : 1, + 'git-get-tar-commit-id.txt' : 1, + 'git-grep.txt' : 1, + 'git-gui.txt' : 1, + 'git-hash-object.txt' : 1, + 'git-help.txt' : 1, + 'git-hook.txt' : 1, + 'git-http-backend.txt' : 1, + 'git-http-fetch.txt' : 1, + 'git-http-push.txt' : 1, + 'git-imap-send.txt' : 1, + 'git-index-pack.txt' : 1, + 'git-init-db.txt' : 1, + 'git-init.txt' : 1, + 'git-instaweb.txt' : 1, + 'git-interpret-trailers.txt' : 1, + 'git-log.txt' : 1, + 'git-ls-files.txt' : 1, + 'git-ls-remote.txt' : 1, + 'git-ls-tree.txt' : 1, + 'git-mailinfo.txt' : 1, + 'git-mailsplit.txt' : 1, + 'git-maintenance.txt' : 1, + 'git-merge-base.txt' : 1, + 'git-merge-file.txt' : 1, + 'git-merge-index.txt' : 1, + 'git-merge-one-file.txt' : 1, + 'git-mergetool--lib.txt' : 1, + 'git-mergetool.txt' : 1, + 'git-merge-tree.txt' : 1, + 'git-merge.txt' : 1, + 'git-mktag.txt' : 1, + 'git-mktree.txt' : 1, + 'git-multi-pack-index.txt' : 1, + 'git-mv.txt' : 1, + 'git-name-rev.txt' : 1, + 'git-notes.txt' : 1, + 'git-p4.txt' : 1, + 'git-pack-objects.txt' : 1, + 'git-pack-redundant.txt' : 1, + 'git-pack-refs.txt' : 1, + 'git-patch-id.txt' : 1, + 'git-prune-packed.txt' : 1, + 'git-prune.txt' : 1, + 'git-pull.txt' : 1, + 'git-push.txt' : 1, + 'git-quiltimport.txt' : 1, + 'git-range-diff.txt' : 1, + 'git-read-tree.txt' : 1, + 'git-rebase.txt' : 1, + 'git-receive-pack.txt' : 1, + 'git-reflog.txt' : 1, + 'git-refs.txt' : 1, + 'git-remote-ext.txt' : 1, + 'git-remote-fd.txt' : 1, + 'git-remote.txt' : 1, + 'git-repack.txt' : 1, + 'git-replace.txt' : 1, + 'git-replay.txt' : 1, + 'git-request-pull.txt' : 1, + 'git-rerere.txt' : 1, + 'git-reset.txt' : 1, + 'git-restore.txt' : 1, + 'git-revert.txt' : 1, + 'git-rev-list.txt' : 1, + 'git-rev-parse.txt' : 1, + 'git-rm.txt' : 1, + 'git-send-email.txt' : 1, + 'git-send-pack.txt' : 1, + 'git-shell.txt' : 1, + 'git-sh-i18n--envsubst.txt' : 1, + 'git-sh-i18n.txt' : 1, + 'git-shortlog.txt' : 1, + 'git-show-branch.txt' : 1, + 'git-show-index.txt' : 1, + 'git-show-ref.txt' : 1, + 'git-show.txt' : 1, + 'git-sh-setup.txt' : 1, + 'git-sparse-checkout.txt' : 1, + 'git-stage.txt' : 1, + 'git-stash.txt' : 1, + 'git-status.txt' : 1, + 'git-stripspace.txt' : 1, + 'git-submodule.txt' : 1, + 'git-svn.txt' : 1, + 'git-switch.txt' : 1, + 'git-symbolic-ref.txt' : 1, + 'git-tag.txt' : 1, + 'git-unpack-file.txt' : 1, + 'git-unpack-objects.txt' : 1, + 'git-update-index.txt' : 1, + 'git-update-ref.txt' : 1, + 'git-update-server-info.txt' : 1, + 'git-upload-archive.txt' : 1, + 'git-upload-pack.txt' : 1, + 'git-var.txt' : 1, + 'git-verify-commit.txt' : 1, + 'git-verify-pack.txt' : 1, + 'git-verify-tag.txt' : 1, + 'git-version.txt' : 1, + 'git-web--browse.txt' : 1, + 'git-whatchanged.txt' : 1, + 'git-worktree.txt' : 1, + 'git-write-tree.txt' : 1, + 'git.txt' : 1, + 'gitk.txt' : 1, + 'gitweb.txt' : 1, + 'scalar.txt' : 1, + + # Category 5. + 'gitattributes.txt' : 5, + 'gitformat-bundle.txt' : 5, + 'gitformat-chunk.txt' : 5, + 'gitformat-commit-graph.txt' : 5, + 'gitformat-index.txt' : 5, + 'gitformat-pack.txt' : 5, + 'gitformat-signature.txt' : 5, + 'githooks.txt' : 5, + 'gitignore.txt' : 5, + 'gitmailmap.txt' : 5, + 'gitmodules.txt' : 5, + 'gitprotocol-capabilities.txt' : 5, + 'gitprotocol-common.txt' : 5, + 'gitprotocol-http.txt' : 5, + 'gitprotocol-pack.txt' : 5, + 'gitprotocol-v2.txt' : 5, + 'gitrepository-layout.txt' : 5, + 'gitweb.conf.txt' : 5, + + # Category 7. + 'gitcli.txt' : 7, + 'gitcore-tutorial.txt' : 7, + 'gitcredentials.txt' : 7, + 'gitcvs-migration.txt' : 7, + 'gitdiffcore.txt' : 7, + 'giteveryday.txt' : 7, + 'gitfaq.txt' : 7, + 'gitglossary.txt' : 7, + 'gitpacking.txt' : 7, + 'gitnamespaces.txt' : 7, + 'gitremote-helpers.txt' : 7, + 'gitrevisions.txt' : 7, + 'gitsubmodules.txt' : 7, + 'gittutorial-2.txt' : 7, + 'gittutorial.txt' : 7, + 'gitworkflows.txt' : 7, +} + +asciidoc = find_program('asciidoc') +git = find_program('git', required: false) +xmlto = find_program('xmlto') + +asciidoc_conf = custom_target( + command: [ + shell, + meson.project_source_root() / 'GIT-VERSION-GEN', + meson.project_source_root(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'asciidoc.conf.in', + output: 'asciidoc.conf', + depends: [git_version_file], +) + +asciidoc_common_options = [ + asciidoc, + '--conf-file=' + asciidoc_conf.full_path(), + '--attribute=build_dir=' + meson.current_build_dir(), +] + +cmd_lists = [ + 'cmds-ancillaryinterrogators.txt', + 'cmds-ancillarymanipulators.txt', + 'cmds-mainporcelain.txt', + 'cmds-plumbinginterrogators.txt', + 'cmds-plumbingmanipulators.txt', + 'cmds-synchingrepositories.txt', + 'cmds-synchelpers.txt', + 'cmds-guide.txt', + 'cmds-developerinterfaces.txt', + 'cmds-userinterfaces.txt', + 'cmds-purehelpers.txt', + 'cmds-foreignscminterface.txt', +] + +documentation_deps = [ + asciidoc_conf, +] + +documentation_deps += custom_target( + command: [ + perl, + meson.current_source_dir() / 'cmd-list.perl', + meson.project_source_root(), + meson.current_build_dir(), + ] + cmd_lists, + output: cmd_lists +) + +foreach mode : [ 'diff', 'merge' ] + documentation_deps += custom_target( + command: [ + shell, + meson.current_source_dir() / 'generate-mergetool-list.sh', + '..', + 'diff', + '@OUTPUT@' + ], + env: [ + 'MERGE_TOOLS_DIR=' + meson.project_source_root() / 'mergetools', + 'TOOL_MODE=' + mode, + ], + output: 'mergetools-' + mode + '.txt', + ) +endforeach + +foreach manpage, category : manpages + if get_option('docs').contains('man') + manpage_xml_target = custom_target( + command: asciidoc_common_options + [ + '--backend=docbook', + '--doctype=manpage', + '--out-file=@OUTPUT@', + meson.current_source_dir() / manpage, + ], + depends: documentation_deps, + output: fs.stem(manpage) + '.xml', + ) + + manpage_path = fs.stem(manpage) + '.' + category.to_string() + manpage_target = custom_target( + command: [ + xmlto, + '-m', + meson.current_source_dir() / 'manpage-normal.xsl', + '-m', + meson.current_source_dir() / 'manpage-bold-literal.xsl', + '--stringparam', + 'man.base.url.for.relative.links=' + get_option('prefix') / get_option('mandir'), + 'man', + manpage_xml_target, + '-o', + meson.current_build_dir(), + ], + output: manpage_path, + install: true, + install_dir: get_option('mandir') / 'man' + category.to_string(), + ) + endif + + if get_option('docs').contains('html') and category == 1 + custom_target( + command: asciidoc_common_options + [ + '--backend=xhtml11', + '--doctype=manpage', + '--out-file=@OUTPUT@', + meson.current_source_dir() / manpage, + ], + depends: documentation_deps, + output: fs.stem(manpage) + '.html', + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) + endif +endforeach diff --git a/bin-wrappers/meson.build b/bin-wrappers/meson.build new file mode 100644 index 0000000000..8a4e910c9b --- /dev/null +++ b/bin-wrappers/meson.build @@ -0,0 +1,28 @@ +bin_wrappers_config = configuration_data() +foreach key, value : { + 'BUILD_DIR': meson.project_build_root(), + 'MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools', + 'TEMPLATE_DIR': meson.project_build_root() / 'templates', + 'GIT_TEXTDOMAINDIR': meson.project_build_root() / 'po', + 'GITPERLLIB': meson.project_build_root() / 'perl/lib', +} + # Paths need to be Unix-style without drive prefixes as they get added to the + # PATH variable. And given that drive prefixes contain a colon we'd otherwise + # end up with a broken PATH if we didn't convert them. + if cygpath.found() + value = run_command(cygpath, value, check: true).stdout().strip() + endif + bin_wrappers_config.set(key, value) +endforeach + +foreach executable : bin_wrappers + executable_config = configuration_data() + executable_config.merge_from(bin_wrappers_config) + executable_config.set('PROG', executable.full_path()) + + configure_file( + input: 'wrap-for-bin.sh', + output: fs.stem(executable.full_path()), + configuration: executable_config, + ) +endforeach diff --git a/contrib/completion/meson.build b/contrib/completion/meson.build new file mode 100644 index 0000000000..3a9ddab594 --- /dev/null +++ b/contrib/completion/meson.build @@ -0,0 +1,16 @@ +foreach script : [ + 'git-completion.bash', + 'git-completion.tcsh', + 'git-completion.zsh', + 'git-prompt.sh' +] + if meson.version().version_compare('>=1.3.0') + test_dependencies += fs.copyfile(script) + else + configure_file( + input: script, + output: script, + copy: true, + ) + endif +endforeach diff --git a/contrib/meson.build b/contrib/meson.build new file mode 100644 index 0000000000..a7b77b87c2 --- /dev/null +++ b/contrib/meson.build @@ -0,0 +1 @@ +subdir('completion') diff --git a/gitweb/meson.build b/gitweb/meson.build new file mode 100644 index 0000000000..89b403dc9d --- /dev/null +++ b/gitweb/meson.build @@ -0,0 +1,89 @@ +gitweb_config = configuration_data() +gitweb_config.set_quoted('PERL_PATH', perl.full_path()) +gitweb_config.set_quoted('CSSMIN', '') +gitweb_config.set_quoted('JSMIN', '') +gitweb_config.set_quoted('GIT_BINDIR', get_option('prefix') / get_option('bindir')) +gitweb_config.set_quoted('GITWEB_CONFIG', get_option('gitweb_config')) +gitweb_config.set_quoted('GITWEB_CONFIG_SYSTEM', get_option('gitweb_config_system')) +gitweb_config.set_quoted('GITWEB_CONFIG_COMMON', get_option('gitweb_config_common')) +gitweb_config.set_quoted('GITWEB_HOME_LINK_STR', get_option('gitweb_home_link_str')) +gitweb_config.set_quoted('GITWEB_SITENAME', get_option('gitweb_sitename')) +gitweb_config.set_quoted('GITWEB_PROJECTROOT', get_option('gitweb_projectroot')) +gitweb_config.set_quoted('GITWEB_PROJECT_MAXDEPTH', get_option('gitweb_project_maxdepth')) +gitweb_config.set_quoted('GITWEB_EXPORT_OK', get_option('gitweb_export_ok')) +gitweb_config.set_quoted('GITWEB_STRICT_EXPORT', get_option('gitweb_strict_export')) +gitweb_config.set_quoted('GITWEB_BASE_URL', get_option('gitweb_base_url')) +gitweb_config.set_quoted('GITWEB_LIST', get_option('gitweb_list')) +gitweb_config.set_quoted('GITWEB_HOMETEXT', get_option('gitweb_hometext')) +gitweb_config.set_quoted('GITWEB_CSS', get_option('gitweb_css')) +gitweb_config.set_quoted('GITWEB_LOGO', get_option('gitweb_logo')) +gitweb_config.set_quoted('GITWEB_FAVICON', get_option('gitweb_favicon')) +gitweb_config.set_quoted('GITWEB_JS', get_option('gitweb_js')) +gitweb_config.set_quoted('GITWEB_SITE_HTML_HEAD_STRING', get_option('gitweb_site_html_head_string')) +gitweb_config.set_quoted('GITWEB_SITE_HEADER', get_option('gitweb_site_header')) +gitweb_config.set_quoted('GITWEB_SITE_FOOTER', get_option('gitweb_site_footer')) +gitweb_config.set_quoted('HIGHLIGHT_BIN', get_option('highlight_bin')) + +configure_file( + input: 'GITWEB-BUILD-OPTIONS.in', + output: 'GITWEB-BUILD-OPTIONS', + configuration: gitweb_config, +) + +test_dependencies += custom_target( + input: 'gitweb.perl', + output: 'gitweb.cgi', + command: [ + shell, + meson.current_source_dir() / 'generate-gitweb-cgi.sh', + meson.current_build_dir() / 'GITWEB-BUILD-OPTIONS', + git_version_file.full_path(), + '@INPUT@', + '@OUTPUT@', + ], + install: true, + install_dir: get_option('datadir') / 'gitweb', + depends: [git_version_file], +) + +javascript_files = [ + meson.current_source_dir() / 'static/js/adjust-timezone.js', + meson.current_source_dir() / 'static/js/blame_incremental.js', + meson.current_source_dir() / 'static/js/javascript-detection.js', + meson.current_source_dir() / 'static/js/lib/common-lib.js', + meson.current_source_dir() / 'static/js/lib/cookies.js', + meson.current_source_dir() / 'static/js/lib/datetime.js', +] + +test_dependencies += custom_target( + input: javascript_files, + output: 'gitweb.js', + command: [ + shell, + meson.current_source_dir() / 'generate-gitweb-js.sh', + '@OUTPUT@', + ] + javascript_files, + install: true, + install_dir: get_option('datadir') / 'gitweb/static', +) + +foreach asset : [ + 'static/git-favicon.png', + 'static/git-logo.png', + 'static/gitweb.css', +] + if meson.version().version_compare('>=1.3.0') + fs.copyfile(asset, + install: true, + install_dir: get_option('datadir') / 'gitweb' / fs.parent(asset), + ) + else + configure_file( + input: asset, + output: fs.stem(asset), + copy: true, + install: true, + install_dir: get_option('datadir') / 'gitweb' / fs.parent(asset), + ) + endif +endforeach diff --git a/meson.build b/meson.build new file mode 100644 index 0000000000..0dccebcdf1 --- /dev/null +++ b/meson.build @@ -0,0 +1,1901 @@ +# Meson build system +# ================== +# +# The Meson build system is an alternative to our Makefile that you can use to +# build, test and install Git. Using Meson results in a couple of benefits: +# +# - Out-of-tree builds. +# - Better integration into IDEs. +# - Easy-to-use autoconfiguration of available features on your system. +# +# To use Meson from the command line you need to have both Meson and Ninja +# installed. Alternatively, if you do not have Python available on your system, +# you can also use Muon instead of Meson and Samurai instead of Ninja, both of +# which are drop-ins replacement that only depend on C. +# +# Basic usage +# =========== +# +# In the most trivial case, you can configure, build and install Git like this: +# +# 1. Set up the build directory. This only needs to happen once per build +# directory you want to have. You can also configure multiple different +# build directories with different configurations. +# +# $ meson setup build/ +# +# The build directory gets ignored by Git automatically as Meson will write +# a ".gitignore" file into it. From hereon, we will assume that you execute +# commands inside this build directory. +# +# 2. Compile Git. You can either use Meson, Ninja or Samurai to do this, so all +# of the following invocations are equivalent: +# +# $ meson compile +# $ ninja +# $ samu +# +# The different invocations should ultimately not make much of a difference. +# Using Meson also works with other generators though, like when the build +# directory has been set up for use with Microsoft Visual Studio. +# +# Ninja and Samurai use multiple jobs by default, scaling with the number of +# processor cores available. You can pass the `-jN` flag to change this. +# +# Meson automatically picks up ccache and sccache when these are installed +# when setting up the build directory. You can override this behaviour when +# setting up the build directory by setting the `CC` environment variable to +# your desired compiler. +# +# 3. Execute tests. Again, you can either use Meson, Ninja or Samurai to do this: +# +# $ meson test +# $ ninja test +# $ samu test +# +# It is recommended to use Meson in this case though as it also provides you +# additional features that the other build systems don't have available. +# You can e.g. pass additional arguments to the test executables or run +# individual tests: +# +# # Execute the t0000-basic integration test and t-reftable-stack unit test. +# $ meson test t0000-basic t-reftable-stack +# +# # Execute all reftable unit tests. +# $ meson test t-reftable-* +# +# # Execute all tests and stop with the first failure. +# $ meson test --maxfail 1 +# +# # Execute single test interactively such that features like `debug ()` work. +# $ meson test -i --test-args='-ix' t1400-update-ref +# +# Test execution is parallelized by default and scales with the number of +# processor cores available. You can change the number of processes by passing +# the `-jN` flag to `meson test`. +# +# 4. Install the Git distribution. Again, this can be done via Meson, Ninja or +# Samurai: +# +# $ meson install +# $ ninja install +# $ samu install +# +# The prefix into which Git shall be installed is defined when setting up +# the build directory. More on that in the "Configuration" section. +# +# Meson supports multiple backends. The default backend generates Ninja build +# instructions, but it also supports the generation of Microsoft Visual +# Studio solutions as well as Xcode projects by passing the `--backend` option +# to `meson setup`. IDEs like Eclipse and Visual Studio Code provide plugins to +# import Meson files directly. +# +# Configuration +# ============= +# +# The exact configuration of Git is determined when setting up the build +# directory via `meson setup`. Unless told otherwise, Meson will automatically +# detect the availability of various bits and pieces. There are two different +# kinds of options that can be used to further tweak the build: +# +# - Built-in options provided by Meson. +# +# - Options defined by the project in the "meson_options.txt" file. +# +# Both kinds of options can be inspected by running `meson configure` in the +# build directory, which will give you a list of the current value for all +# options. +# +# Options can be configured either when setting up the build directory or can +# be changed in preexisting build directories: +# +# # Set up a new build directory with optimized settings that will be +# # installed into an alternative prefix. +# $ meson setup --buildtype release --optimization 3 --strip --prefix=/home/$USER build +# +# # Set up a new build directory with a higher warning level. Level 2 is +# # mostly equivalent to setting DEVELOPER=1, level 3 and "everything" +# # will enable even more warnings. +# $ meson setup -Dwarning_level=2 build +# +# # Set up a new build directory with 'address' and 'undefined' sanitizers +# # using Clang. +# $ CC=clang meson setup -Db_sanitize=address,undefined build +# +# # Disable tests in a preexisting build directory. +# $ meson configure -Dtests=false +# +# # Disable features based on Python +# $ meson configure -Dpython=disabled +# +# Options have a type like booleans, choices, strings or features. Features are +# somewhat special as they can have one of three values: enabled, disabled or +# auto. While the first two values are self-explanatory, "auto" will enable or +# disable the feature based on the availability of prerequisites to support it. +# Python-based features for example will be enabled automatically when a Python +# interpreter could be found. The default value of such features can be changed +# via `meson setup --auto-features={enabled,disabled,auto}`, which will set the +# value of all features with a value of "auto" to the provided one by default. +# +# It is also possible to store a set of configuration options in machine files. +# This can be useful in case you regularly want to reuse the same set of options: +# +# [binaries] +# c = ['clang'] +# ar = ['ar'] +# +# [project options] +# gettext = 'disabled' +# default_editor = 'vim' +# +# [built-in options] +# b_lto = true +# b_sanitize = 'address,undefined' +# +# These machine files can be passed to `meson setup` via the `--native-file` +# option. +# +# Subproject wrappers +# =================== +# +# Subproject wrappers are a feature provided by Meson that allows the automatic +# fallback to a "wrapped" dependency in case the dependency is not provided by +# the system. For example if the system is lacking curl, then Meson will use +# "subprojects/curl.wrap" to set up curl as a subproject and compile and link +# the dependency into Git itself. This is especially helpful on systems like +# Windows, where you typically don't have such dependencies installed. +# +# The use of subproject wrappers can be disabled by executing `meson setup` +# with the `--wrap-mode nofallback` option. + +project('git', 'c', + meson_version: '>=0.61.0', + version: 'v2.47.GIT', +) + +fs = import('fs') + +program_path = [] +# Git for Windows provides all the tools we need to build Git. +if host_machine.system() == 'windows' + program_path += [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] +endif + +cygpath = find_program('cygpath', dirs: program_path, required: false) +diff = find_program('diff', dirs: program_path) +shell = find_program('sh', dirs: program_path) +tar = find_program('tar', dirs: program_path) + +script_environment = environment() +foreach tool : ['cat', 'cut', 'grep', 'sed', 'sort', 'tr', 'uname'] + program = find_program(tool, dirs: program_path) + script_environment.prepend('PATH', fs.parent(program.full_path())) +endforeach + +git = find_program('git', dirs: program_path, required: false) +if git.found() + script_environment.prepend('PATH', fs.parent(git.full_path())) +endif + +if get_option('sane_tool_path') != '' + script_environment.prepend('PATH', get_option('sane_tool_path')) +endif + +compiler = meson.get_compiler('c') + +libgit_sources = [ + 'abspath.c', + 'add-interactive.c', + 'add-patch.c', + 'advice.c', + 'alias.c', + 'alloc.c', + 'apply.c', + 'archive-tar.c', + 'archive-zip.c', + 'archive.c', + 'attr.c', + 'base85.c', + 'bisect.c', + 'blame.c', + 'blob.c', + 'bloom.c', + 'branch.c', + 'bulk-checkin.c', + 'bundle-uri.c', + 'bundle.c', + 'cache-tree.c', + 'cbtree.c', + 'chdir-notify.c', + 'checkout.c', + 'chunk-format.c', + 'color.c', + 'column.c', + 'combine-diff.c', + 'commit-graph.c', + 'commit-reach.c', + 'commit.c', + 'compat/nonblock.c', + 'compat/obstack.c', + 'compat/terminal.c', + 'compat/zlib-uncompress2.c', + 'config.c', + 'connect.c', + 'connected.c', + 'convert.c', + 'copy.c', + 'credential.c', + 'csum-file.c', + 'ctype.c', + 'date.c', + 'decorate.c', + 'delta-islands.c', + 'diagnose.c', + 'diff-delta.c', + 'diff-merges.c', + 'diff-lib.c', + 'diff-no-index.c', + 'diff.c', + 'diffcore-break.c', + 'diffcore-delta.c', + 'diffcore-order.c', + 'diffcore-pickaxe.c', + 'diffcore-rename.c', + 'diffcore-rotate.c', + 'dir-iterator.c', + 'dir.c', + 'editor.c', + 'entry.c', + 'environment.c', + 'ewah/bitmap.c', + 'ewah/ewah_bitmap.c', + 'ewah/ewah_io.c', + 'ewah/ewah_rlw.c', + 'exec-cmd.c', + 'fetch-negotiator.c', + 'fetch-pack.c', + 'fmt-merge-msg.c', + 'fsck.c', + 'fsmonitor.c', + 'fsmonitor-ipc.c', + 'fsmonitor-settings.c', + 'gettext.c', + 'git-zlib.c', + 'gpg-interface.c', + 'graph.c', + 'grep.c', + 'hash-lookup.c', + 'hashmap.c', + 'help.c', + 'hex.c', + 'hex-ll.c', + 'hook.c', + 'ident.c', + 'json-writer.c', + 'kwset.c', + 'levenshtein.c', + 'line-log.c', + 'line-range.c', + 'linear-assignment.c', + 'list-objects-filter-options.c', + 'list-objects-filter.c', + 'list-objects.c', + 'lockfile.c', + 'log-tree.c', + 'loose.c', + 'ls-refs.c', + 'mailinfo.c', + 'mailmap.c', + 'match-trees.c', + 'mem-pool.c', + 'merge-blobs.c', + 'merge-ll.c', + 'merge-ort.c', + 'merge-ort-wrappers.c', + 'merge-recursive.c', + 'merge.c', + 'midx.c', + 'midx-write.c', + 'name-hash.c', + 'negotiator/default.c', + 'negotiator/noop.c', + 'negotiator/skipping.c', + 'notes-cache.c', + 'notes-merge.c', + 'notes-utils.c', + 'notes.c', + 'object-file-convert.c', + 'object-file.c', + 'object-name.c', + 'object.c', + 'oid-array.c', + 'oidmap.c', + 'oidset.c', + 'oidtree.c', + 'pack-bitmap-write.c', + 'pack-bitmap.c', + 'pack-check.c', + 'pack-mtimes.c', + 'pack-objects.c', + 'pack-revindex.c', + 'pack-write.c', + 'packfile.c', + 'pager.c', + 'parallel-checkout.c', + 'parse.c', + 'parse-options-cb.c', + 'parse-options.c', + 'patch-delta.c', + 'patch-ids.c', + 'path.c', + 'pathspec.c', + 'pkt-line.c', + 'preload-index.c', + 'pretty.c', + 'prio-queue.c', + 'progress.c', + 'promisor-remote.c', + 'prompt.c', + 'protocol.c', + 'protocol-caps.c', + 'prune-packed.c', + 'pseudo-merge.c', + 'quote.c', + 'range-diff.c', + 'reachable.c', + 'read-cache.c', + 'rebase-interactive.c', + 'rebase.c', + 'ref-filter.c', + 'reflog-walk.c', + 'reflog.c', + 'refs.c', + 'refs/debug.c', + 'refs/files-backend.c', + 'refs/reftable-backend.c', + 'refs/iterator.c', + 'refs/packed-backend.c', + 'refs/ref-cache.c', + 'refspec.c', + 'reftable/basics.c', + 'reftable/error.c', + 'reftable/block.c', + 'reftable/blocksource.c', + 'reftable/iter.c', + 'reftable/merged.c', + 'reftable/pq.c', + 'reftable/reader.c', + 'reftable/record.c', + 'reftable/stack.c', + 'reftable/system.c', + 'reftable/tree.c', + 'reftable/writer.c', + 'remote.c', + 'replace-object.c', + 'repo-settings.c', + 'repository.c', + 'rerere.c', + 'reset.c', + 'resolve-undo.c', + 'revision.c', + 'run-command.c', + 'send-pack.c', + 'sequencer.c', + 'serve.c', + 'server-info.c', + 'setup.c', + 'shallow.c', + 'sideband.c', + 'sigchain.c', + 'sparse-index.c', + 'split-index.c', + 'stable-qsort.c', + 'statinfo.c', + 'strbuf.c', + 'streaming.c', + 'string-list.c', + 'strmap.c', + 'strvec.c', + 'sub-process.c', + 'submodule-config.c', + 'submodule.c', + 'symlinks.c', + 'tag.c', + 'tempfile.c', + 'thread-utils.c', + 'tmp-objdir.c', + 'trace.c', + 'trace2.c', + 'trace2/tr2_cfg.c', + 'trace2/tr2_cmd_name.c', + 'trace2/tr2_ctr.c', + 'trace2/tr2_dst.c', + 'trace2/tr2_sid.c', + 'trace2/tr2_sysenv.c', + 'trace2/tr2_tbuf.c', + 'trace2/tr2_tgt_event.c', + 'trace2/tr2_tgt_normal.c', + 'trace2/tr2_tgt_perf.c', + 'trace2/tr2_tls.c', + 'trace2/tr2_tmr.c', + 'trailer.c', + 'transport-helper.c', + 'transport.c', + 'tree-diff.c', + 'tree-walk.c', + 'tree.c', + 'unpack-trees.c', + 'upload-pack.c', + 'url.c', + 'urlmatch.c', + 'usage.c', + 'userdiff.c', + 'utf8.c', + 'varint.c', + 'versioncmp.c', + 'walker.c', + 'wildmatch.c', + 'worktree.c', + 'wrapper.c', + 'write-or-die.c', + 'ws.c', + 'wt-status.c', + 'xdiff-interface.c', + 'xdiff/xdiffi.c', + 'xdiff/xemit.c', + 'xdiff/xhistogram.c', + 'xdiff/xmerge.c', + 'xdiff/xpatience.c', + 'xdiff/xprepare.c', + 'xdiff/xutils.c', +] + +builtin_sources = [ + 'builtin/add.c', + 'builtin/am.c', + 'builtin/annotate.c', + 'builtin/apply.c', + 'builtin/archive.c', + 'builtin/bisect.c', + 'builtin/blame.c', + 'builtin/branch.c', + 'builtin/bugreport.c', + 'builtin/bundle.c', + 'builtin/cat-file.c', + 'builtin/check-attr.c', + 'builtin/check-ignore.c', + 'builtin/check-mailmap.c', + 'builtin/check-ref-format.c', + 'builtin/checkout--worker.c', + 'builtin/checkout-index.c', + 'builtin/checkout.c', + 'builtin/clean.c', + 'builtin/clone.c', + 'builtin/column.c', + 'builtin/commit-graph.c', + 'builtin/commit-tree.c', + 'builtin/commit.c', + 'builtin/config.c', + 'builtin/count-objects.c', + 'builtin/credential-cache--daemon.c', + 'builtin/credential-cache.c', + 'builtin/credential-store.c', + 'builtin/credential.c', + 'builtin/describe.c', + 'builtin/diagnose.c', + 'builtin/diff-files.c', + 'builtin/diff-index.c', + 'builtin/diff-tree.c', + 'builtin/diff.c', + 'builtin/difftool.c', + 'builtin/fast-export.c', + 'builtin/fast-import.c', + 'builtin/fetch-pack.c', + 'builtin/fetch.c', + 'builtin/fmt-merge-msg.c', + 'builtin/for-each-ref.c', + 'builtin/for-each-repo.c', + 'builtin/fsck.c', + 'builtin/fsmonitor--daemon.c', + 'builtin/gc.c', + 'builtin/get-tar-commit-id.c', + 'builtin/grep.c', + 'builtin/hash-object.c', + 'builtin/help.c', + 'builtin/hook.c', + 'builtin/index-pack.c', + 'builtin/init-db.c', + 'builtin/interpret-trailers.c', + 'builtin/log.c', + 'builtin/ls-files.c', + 'builtin/ls-remote.c', + 'builtin/ls-tree.c', + 'builtin/mailinfo.c', + 'builtin/mailsplit.c', + 'builtin/merge-base.c', + 'builtin/merge-file.c', + 'builtin/merge-index.c', + 'builtin/merge-ours.c', + 'builtin/merge-recursive.c', + 'builtin/merge-tree.c', + 'builtin/merge.c', + 'builtin/mktag.c', + 'builtin/mktree.c', + 'builtin/multi-pack-index.c', + 'builtin/mv.c', + 'builtin/name-rev.c', + 'builtin/notes.c', + 'builtin/pack-objects.c', + 'builtin/pack-redundant.c', + 'builtin/pack-refs.c', + 'builtin/patch-id.c', + 'builtin/prune-packed.c', + 'builtin/prune.c', + 'builtin/pull.c', + 'builtin/push.c', + 'builtin/range-diff.c', + 'builtin/read-tree.c', + 'builtin/rebase.c', + 'builtin/receive-pack.c', + 'builtin/reflog.c', + 'builtin/refs.c', + 'builtin/remote-ext.c', + 'builtin/remote-fd.c', + 'builtin/remote.c', + 'builtin/repack.c', + 'builtin/replace.c', + 'builtin/replay.c', + 'builtin/rerere.c', + 'builtin/reset.c', + 'builtin/rev-list.c', + 'builtin/rev-parse.c', + 'builtin/revert.c', + 'builtin/rm.c', + 'builtin/send-pack.c', + 'builtin/shortlog.c', + 'builtin/show-branch.c', + 'builtin/show-index.c', + 'builtin/show-ref.c', + 'builtin/sparse-checkout.c', + 'builtin/stash.c', + 'builtin/stripspace.c', + 'builtin/submodule--helper.c', + 'builtin/symbolic-ref.c', + 'builtin/tag.c', + 'builtin/unpack-file.c', + 'builtin/unpack-objects.c', + 'builtin/update-index.c', + 'builtin/update-ref.c', + 'builtin/update-server-info.c', + 'builtin/upload-archive.c', + 'builtin/upload-pack.c', + 'builtin/var.c', + 'builtin/verify-commit.c', + 'builtin/verify-pack.c', + 'builtin/verify-tag.c', + 'builtin/worktree.c', + 'builtin/write-tree.c', +] + +libgit_sources += custom_target( + input: 'command-list.txt', + output: 'command-list.h', + command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'], + env: script_environment, +) + +libgit_sources += custom_target( + output: 'config-list.h', + command: [ + shell, + meson.current_source_dir() + '/generate-configlist.sh', + meson.current_source_dir(), + '@OUTPUT@', + ], + env: script_environment, +) + +libgit_sources += custom_target( + input: 'Documentation/githooks.txt', + output: 'hook-list.h', + command: [ + shell, + meson.current_source_dir() + '/generate-hooklist.sh', + meson.current_source_dir(), + '@OUTPUT@', + ], + env: script_environment, +) + +# This contains the variables for GIT-BUILD-OPTIONS, which we use to propagate +# build options to our tests. +build_options_config = configuration_data() +build_options_config.set('GIT_INTEROP_MAKE_OPTS', '') +build_options_config.set('GIT_PERF_LARGE_REPO', '') +build_options_config.set('GIT_PERF_MAKE_COMMAND', '') +build_options_config.set('GIT_PERF_MAKE_OPTS', '') +build_options_config.set('GIT_PERF_REPEAT_COUNT', '') +build_options_config.set('GIT_PERF_REPO', '') +build_options_config.set('GIT_TEST_CMP_USE_COPIED_CONTEXT', '') +build_options_config.set('GIT_TEST_INDEX_VERSION', '') +build_options_config.set('GIT_TEST_OPTS', '') +build_options_config.set('GIT_TEST_PERL_FATAL_WARNINGS', '') +build_options_config.set('GIT_TEST_UTF8_LOCALE', '') +build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) +build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) + +if get_option('sane_tool_path') != '' + build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + get_option('sane_tool_path') + '"|') +else + build_options_config.set_quoted('BROKEN_PATH_FIX', '/^\# @BROKEN_PATH_FIX@$/d') +endif + +test_output_directory = get_option('test_output_directory') +if test_output_directory == '' + test_output_directory = meson.project_build_root() / 'test-output' +endif + +# These variables are used for building libgit.a. +libgit_c_args = [ + '-DBINDIR="' + get_option('bindir') + '"', + '-DDEFAULT_EDITOR="' + get_option('default_editor') + '"', + '-DDEFAULT_GIT_TEMPLATE_DIR="' + get_option('datadir') / 'git-core/templates' + '"', + '-DDEFAULT_HELP_FORMAT="' + get_option('default_help_format') + '"', + '-DDEFAULT_PAGER="' + get_option('default_pager') + '"', + '-DETC_GITATTRIBUTES="' + get_option('gitattributes') + '"', + '-DETC_GITCONFIG="' + get_option('gitconfig') + '"', + '-DFALLBACK_RUNTIME_PREFIX="' + get_option('prefix') + '"', + '-DGIT_EXEC_PATH="' + get_option('prefix') / get_option('libexecdir') / 'git-core"', + '-DGIT_HOST_CPU="' + host_machine.cpu_family() + '"', + '-DGIT_HTML_PATH="' + get_option('datadir') / 'doc/git-doc"', + '-DGIT_INFO_PATH="' + get_option('infodir') + '"', + '-DGIT_LOCALE_PATH="' + get_option('localedir') + '"', + '-DGIT_MAN_PATH="' + get_option('mandir') + '"', + '-DPAGER_ENV="' + get_option('pager_environment') + '"', + '-DSHELL_PATH="' + fs.as_posix(shell.full_path()) + '"', +] +libgit_include_directories = [ '.' ] +libgit_dependencies = [ ] + +# Treat any warning level above 1 the same as we treat DEVELOPER=1 in our +# Makefile. +if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argument_syntax() == 'gcc' + foreach cflag : [ + '-Wdeclaration-after-statement', + '-Wformat-security', + '-Wold-style-definition', + '-Woverflow', + '-Wpointer-arith', + '-Wstrict-prototypes', + '-Wunused', + '-Wvla', + '-Wwrite-strings', + '-fno-common', + '-Wtautological-constant-out-of-range-compare', + # If a function is public, there should be a prototype and the right + # header file should be included. If not, it should be static. + '-Wmissing-prototypes', + # These are disabled because we have these all over the place. + '-Wno-empty-body', + '-Wno-missing-field-initializers', + '-Wno-sign-compare', + ] + if compiler.has_argument(cflag) + libgit_c_args += cflag + endif + endforeach +endif + +if get_option('b_sanitize').contains('address') + build_options_config.set('SANITIZE_ADDRESS', 'YesCompiledWithIt') +else + build_options_config.set('SANITIZE_ADDRESS', '') +endif +if get_option('b_sanitize').contains('leak') + libgit_c_args += '-DSUPPRESS_ANNOTATED_LEAKS' + build_options_config.set('SANITIZE_LEAK', 'YesCompiledWithIt') +else + build_options_config.set('SANITIZE_LEAK', '') +endif +if get_option('b_sanitize').contains('undefined') + libgit_c_args += '-DSHA1DC_FORCE_ALIGNED_ACCESS' +endif + +executable_suffix = '' +if host_machine.system() == 'cygwin' or host_machine.system() == 'windows' + executable_suffix = '.exe' + libgit_c_args += '-DSTRIP_EXTENSION="' + executable_suffix + '"' +endif +build_options_config.set_quoted('X', executable_suffix) + +python = import('python').find_installation('python3', required: get_option('python')) +if python.found() + build_options_config.set('NO_PYTHON', '') +else + libgit_c_args += '-DNO_PYTHON' + build_options_config.set('NO_PYTHON', '1') +endif + +# Perl is used for two different things: our test harness and to provide some +# features. It is optional if you want to neither execute tests nor use any of +# these optional features. +perl_required = get_option('perl') +if get_option('tests') + perl_required = true +endif + +# Note that we only set NO_PERL if the Perl features were disabled by the user. +# It may not be set when we have found Perl, but only use it to run tests. +perl = find_program('perl', version: '>=5.8.1', dirs: program_path, required: perl_required) +perl_features_enabled = perl.found() and get_option('perl').allowed() +if perl_features_enabled + build_options_config.set('NO_PERL', '') + + if get_option('runtime_prefix') + build_options_config.set('PERL_LOCALEDIR', '') + else + build_options_config.set_quoted('PERL_LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) + endif + + if get_option('perl_cpan_fallback') + build_options_config.set('NO_PERL_CPAN_FALLBACKS', '') + else + build_options_config.set_quoted('NO_PERL_CPAN_FALLBACKS', 'YesPlease') + endif +else + libgit_c_args += '-DNO_PERL' + build_options_config.set('NO_PERL', '1') + build_options_config.set('PERL_LOCALEDIR', '') + build_options_config.set('NO_PERL_CPAN_FALLBACKS', '') +endif + +zlib = dependency('zlib', default_options: ['default_library=static', 'tests=disabled']) +if zlib.version().version_compare('<1.2.0') + libgit_c_args += '-DNO_DEFLATE_BOUND' +endif +libgit_dependencies += zlib + +threads = dependency('threads', required: false) +if threads.found() + libgit_dependencies += threads + build_options_config.set('NO_PTHREADS', '') +else + libgit_c_args += '-DNO_PTHREADS' + build_options_config.set('NO_PTHREADS', '1') +endif + +msgfmt = find_program('msgfmt', dirs: program_path, required: false) +gettext_option = get_option('gettext').disable_auto_if(not msgfmt.found()) +if not msgfmt.found() and gettext_option.enabled() + error('Internationalization via libintl requires msgfmt') +endif + +if gettext_option.allowed() and host_machine.system() == 'darwin' and get_option('macos_use_homebrew_gettext') + if host_machine.cpu_family() == 'x86_64' + libintl_prefix = '/usr/local' + elif host_machine.cpu_family() == 'aarch64' + libintl_prefix = '/opt/homebrew' + else + error('Homebrew workaround not supported on current architecture') + endif + + intl = compiler.find_library('intl', dirs: libintl_prefix / 'lib', required: gettext_option) + if intl.found() + intl = declare_dependency( + dependencies: intl, + include_directories: libintl_prefix / 'include', + ) + endif +else + intl = dependency('intl', required: gettext_option) +endif +if intl.found() + libgit_dependencies += intl + build_options_config.set('NO_GETTEXT', '') + build_options_config.set('USE_GETTEXT_SCHEME', '') + + # POSIX nowadays requires `nl_langinfo()`, but some systems still don't have + # the function available. On such systems we instead fall back to libcharset. + # On native Windows systems we use our own emulation. + if host_machine.system() != 'windows' and not compiler.has_function('nl_langinfo') + libcharset = compiler.find_library('charset', required: true) + libgit_dependencies += libcharset + libgit_c_args += '-DHAVE_LIBCHARSET_H' + endif +else + libgit_c_args += '-DNO_GETTEXT' + build_options_config.set('NO_GETTEXT', '1') + build_options_config.set('USE_GETTEXT_SCHEME', 'fallthrough') +endif + +iconv = dependency('iconv', required: get_option('iconv')) +if iconv.found() + libgit_dependencies += iconv + build_options_config.set('NO_ICONV', '') + + have_old_iconv = false + if not compiler.compiles(''' + #include + + extern size_t iconv(iconv_t cd, + char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + ''', name: 'old iconv interface', dependencies: [iconv]) + libgit_c_args += '-DOLD_ICONV' + have_old_iconv = true + endif + + iconv_omits_bom_source = '''# + #include + + int main(int argc, const char **argv) + { + ''' + if have_old_iconv + iconv_omits_bom_source += ''' + typedef const char *iconv_ibp; + ''' + else + iconv_omits_bom_source += ''' + typedef char *iconv_ibp; + ''' + endif + iconv_omits_bom_source += ''' + int v; + iconv_t conv; + char in[] = "a"; iconv_ibp pin = in; + char out[20] = ""; char *pout = out; + size_t isz = sizeof in; + size_t osz = sizeof out; + + conv = iconv_open("UTF-16", "UTF-8"); + iconv(conv, &pin, &isz, &pout, &osz); + iconv_close(conv); + v = (unsigned char)(out[0]) + (unsigned char)(out[1]); + return v != 0xfe + 0xff; + } + ''' + + if compiler.run(iconv_omits_bom_source, + dependencies: iconv, + name: 'iconv omits BOM', + ).returncode() != 0 + libgit_c_args += '-DICONV_OMITS_BOM' + endif +else + libgit_c_args += '-DNO_ICONV' + build_options_config.set('NO_ICONV', '1') +endif + +pcre2 = dependency('libpcre2-8', required: get_option('pcre2'), default_options: ['default_library=static', 'test=false']) +if pcre2.found() + libgit_dependencies += pcre2 + libgit_c_args += '-DUSE_LIBPCRE2' + build_options_config.set('USE_LIBPCRE2', '1') +else + build_options_config.set('USE_LIBPCRE2', '') +endif + +curl = dependency('libcurl', version: '>=7.21.3', required: get_option('curl'), default_options: ['default_library=static', 'tests=disabled', 'tool=disabled']) +use_curl_for_imap_send = false +if curl.found() + if curl.version().version_compare('>=7.34.0') + libgit_c_args += '-DUSE_CURL_FOR_IMAP_SEND' + use_curl_for_imap_send = true + endif + + libgit_dependencies += curl + libgit_c_args += '-DCURL_DISABLE_TYPECHECK' + build_options_config.set('NO_CURL', '') +else + libgit_c_args += '-DNO_CURL' + build_options_config.set('NO_CURL', '1') +endif + +expat = dependency('expat', required: get_option('expat'), default_options: ['default_library=static', 'build_tests=false']) +if expat.found() + libgit_dependencies += expat + + if expat.version().version_compare('<=1.2') + libgit_c_args += '-DEXPAT_NEEDS_XMLPARSE_H' + endif + build_options_config.set('NO_EXPAT', '') +else + libgit_c_args += '-DNO_EXPAT' + build_options_config.set('NO_EXPAT', '1') +endif + +if not compiler.has_header('sys/select.h') + libgit_c_args += '-DNO_SYS_SELECT_H' +endif + +has_poll_h = compiler.has_header('poll.h') +if not has_poll_h + libgit_c_args += '-DNO_POLL_H' +endif + +has_sys_poll_h = compiler.has_header('sys/poll.h') +if not has_sys_poll_h + libgit_c_args += '-DNO_SYS_POLL_H' +endif + +if not has_poll_h and not has_sys_poll_h + libgit_c_args += '-DNO_POLL' + libgit_sources += 'compat/poll/poll.c' + libgit_include_directories += 'compat/poll' +endif + +if not compiler.has_header('inttypes.h') + libgit_c_args += '-DNO_INTTYPES_H' +endif + +if compiler.has_header('alloca.h') + libgit_c_args += '-DHAVE_ALLOCA_H' +endif + +if compiler.has_header('sys/sysinfo.h') + libgit_c_args += '-DHAVE_SYSINFO' +endif + +# Windows has libgen.h and a basename implementation, but we still need our own +# implementation to threat things like drive prefixes specially. +if host_machine.system() == 'windows' or not compiler.has_header('libgen.h') + libgit_c_args += '-DNO_LIBGEN_H' + libgit_sources += 'compat/basename.c' +endif + +if compiler.has_header('paths.h') + libgit_c_args += '-DHAVE_PATHS_H' +endif + +if compiler.has_header('strings.h') + libgit_c_args += '-DHAVE_STRINGS_H' +endif + +networking_dependencies = [ ] +if host_machine.system() == 'windows' + winsock = compiler.find_library('ws2_32', required: false) + if winsock.found() + networking_dependencies += winsock + endif +else + libresolv = compiler.find_library('resolv', required: false) + if libresolv.found() + networking_dependencies += libresolv + endif +endif +libgit_dependencies += networking_dependencies + +foreach symbol : ['inet_ntop', 'inet_pton', 'strerror'] + if not compiler.has_function(symbol, dependencies: networking_dependencies) + libgit_c_args += '-DNO_' + symbol.to_upper() + endif +endforeach + +has_ipv6 = compiler.has_function('getaddrinfo', dependencies: networking_dependencies) +if not has_ipv6 + libgit_c_args += '-DNO_IPV6' +endif + +if not compiler.compiles(''' + #ifdef _WIN32 + # include + #else + # include + # include + #endif + + void func(void) + { + struct sockaddr_storage x; + } +''', name: 'struct sockaddr_storage') + if has_ipv6 + libgit_c_args += '-Dsockaddr_storage=sockaddr_in6' + else + libgit_c_args += '-Dsockaddr_storage=sockaddr_in' + endif +endif + +if compiler.has_function('socket', dependencies: networking_dependencies) + libgit_sources += [ + 'unix-socket.c', + 'unix-stream-server.c', + ] + build_options_config.set('NO_UNIX_SOCKETS', '') +else + libgit_c_args += '-DNO_UNIX_SOCKETS' + build_options_config.set('NO_UNIX_SOCKETS', '1') +endif + +if not compiler.has_function('pread') + libgit_c_args += '-DNO_PREAD' + libgit_sources += 'compat/pread.c' +endif + +if host_machine.system() == 'darwin' + libgit_sources += 'compat/precompose_utf8.c' + libgit_c_args += '-DPRECOMPOSE_UNICODE' + libgit_c_args += '-DPROTECT_HFS_DEFAULT' +endif + +# Configure general compatibility wrappers. +if host_machine.system() == 'cygwin' + libgit_sources += [ + 'compat/win32/path-utils.c', + ] +elif host_machine.system() == 'windows' + libgit_sources += [ + 'compat/mingw.c', + 'compat/winansi.c', + 'compat/win32/flush.c', + 'compat/win32/path-utils.c', + 'compat/win32/pthread.c', + 'compat/win32/syslog.c', + 'compat/win32/dirent.c', + 'compat/win32mmap.c', + 'compat/nedmalloc/nedmalloc.c', + ] + + libgit_c_args += [ + '-DDETECT_MSYS_TTY', + '-DENSURE_MSYSTEM_IS_SET', + '-DNATIVE_CRLF', + '-DNOGDI', + '-DNO_POSIX_GOODIES', + '-DWIN32', + '-D_CONSOLE', + '-D_CONSOLE_DETECT_MSYS_TTY', + '-D__USE_MINGW_ANSI_STDIO=0', + ] + + libgit_dependencies += compiler.find_library('ntdll') + libgit_include_directories += 'compat/win32' + if compiler.get_id() == 'msvc' + libgit_include_directories += 'compat/vcbuild/include' + endif +endif + +if host_machine.system() == 'linux' + libgit_sources += 'compat/linux/procinfo.c' +elif host_machine.system() == 'windows' + libgit_sources += 'compat/win32/trace2_win32_process_info.c' +else + libgit_sources += 'compat/stub/procinfo.c' +endif + +if host_machine.system() == 'cygwin' or host_machine.system() == 'windows' + libgit_c_args += [ + '-DUNRELIABLE_FSTAT', + '-DMMAP_PREVENTS_DELETE', + '-DOBJECT_CREATION_MODE=1', + ] +endif + +# Configure the simple-ipc subsystem required fro the fsmonitor. +if host_machine.system() == 'windows' + libgit_sources += [ + 'compat/simple-ipc/ipc-shared.c', + 'compat/simple-ipc/ipc-win32.c', + ] + libgit_c_args += '-DSUPPORTS_SIMPLE_IPC' +else + libgit_sources += [ + 'compat/simple-ipc/ipc-shared.c', + 'compat/simple-ipc/ipc-unix-socket.c', + ] + libgit_c_args += '-DSUPPORTS_SIMPLE_IPC' +endif + +fsmonitor_backend = '' +if host_machine.system() == 'windows' + fsmonitor_backend = 'win32' +elif host_machine.system() == 'darwin' + fsmonitor_backend = 'darwin' + libgit_dependencies += dependency('CoreServices') +endif +if fsmonitor_backend != '' + libgit_c_args += '-DHAVE_FSMONITOR_DAEMON_BACKEND' + libgit_c_args += '-DHAVE_FSMONITOR_OS_SETTINGS' + + libgit_sources += [ + 'compat/fsmonitor/fsm-health-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-ipc-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-listen-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-path-utils-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-settings-' + fsmonitor_backend + '.c', + ] +endif +build_options_config.set_quoted('FSMONITOR_DAEMON_BACKEND', fsmonitor_backend) +build_options_config.set_quoted('FSMONITOR_OS_SETTINGS', fsmonitor_backend) + +if not get_option('b_sanitize').contains('address') and get_option('regex').allowed() and compiler.has_header('regex.h') and compiler.get_define('REG_STARTEND', prefix: '#include ') != '' + build_options_config.set('NO_REGEX', '') + + if compiler.get_define('REG_ENHANCED', prefix: '#include ') != '' + libgit_c_args += '-DUSE_ENHANCED_BASIC_REGULAR_EXPRESSIONS' + libgit_sources += 'compat/regcomp_enhanced.c' + endif +elif not get_option('regex').enabled() + libgit_c_args += [ + '-DNO_REGEX', + '-DGAWK', + '-DNO_MBSUPPORT', + ] + build_options_config.set('NO_REGEX', '1') + libgit_sources += 'compat/regex/regex.c' + libgit_include_directories += 'compat/regex' +else + error('Native regex support requested but not found') +endif + +# setitimer and friends are provided by compat/mingw.c. +if host_machine.system() != 'windows' + if not compiler.compiles(''' + #include + void func(void) + { + struct itimerval value; + } + ''', name: 'struct itimerval') + libgit_c_args += '-DNO_STRUCT_ITIMERVAL' + libgit_c_args += '-DNO_SETITIMER' + elif not compiler.has_function('setitimer') + libgit_c_args += '-DNO_SETITIMER' + endif +endif + +if compiler.has_member('struct stat', 'st_mtimespec.tv_nsec', prefix: '#include ') + libgit_c_args += '-DUSE_ST_TIMESPEC' +elif not compiler.has_member('struct stat', 'st_mtim.tv_nsec', prefix: '#include ') + libgit_c_args += '-DNO_NSEC' +endif + +if not compiler.has_member('struct stat', 'st_blocks', prefix: '#include ') + libgit_c_args += '-DNO_ST_BLOCKS_IN_STRUCT_STAT' +endif + +if not compiler.has_member('struct dirent', 'd_type', prefix: '#include ') + libgit_c_args += '-DNO_D_TYPE_IN_DIRENT' +endif + +if not compiler.has_member('struct passwd', 'pw_gecos', prefix: '#include ') + libgit_c_args += '-DNO_GECOS_IN_PWENT' +endif + +if compiler.has_function('sync_file_range') + libgit_c_args += '-DHAVE_SYNC_FILE_RANGE' +endif + +if not compiler.has_function('strcasestr') + libgit_c_args += '-DNO_STRCASESTR' + libgit_sources += 'compat/strcasestr.c' +endif + +if not compiler.has_function('memmem') + libgit_c_args += '-DNO_MEMMEM' + libgit_sources += 'compat/memmem.c' +endif + +if not compiler.has_function('strlcpy') + libgit_c_args += '-DNO_STRLCPY' + libgit_sources += 'compat/strlcpy.c' +endif + +if not compiler.has_function('strdup') + libgit_c_args += '-DOVERRIDE_STRDUP' + libgit_sources += 'compat/strdup.c' +endif + +if not compiler.has_function('strtoumax') + libgit_c_args += '-DNO_STRTOUMAX' + libgit_sources += [ + 'compat/strtoumax.c', + 'compat/strtoimax.c', + ] +endif + +if not compiler.has_function('strtoull') + libgit_c_args += '-DNO_STRTOULL' +endif + +if not compiler.has_function('setenv') + libgit_c_args += '-DNO_SETENV' + libgit_sources += 'compat/setenv.c' +endif + +if not compiler.has_function('qsort') + libgit_c_args += '-DINTERNAL_QSORT' +endif +libgit_sources += 'compat/qsort_s.c' + +# unsetenv is provided by compat/mingw.c. +if host_machine.system() != 'windows' and not compiler.has_function('unsetenv') + libgit_c_args += '-DNO_UNSETENV' + libgit_sources += 'compat/unsetenv.c' +endif + +if not compiler.has_function('mkdtemp') + libgit_c_args += '-DNO_MKDTEMP' + libgit_sources += 'compat/mkdtemp.c' +endif + +if not compiler.has_function('initgroups') + libgit_c_args += '-DNO_INITGROUPS' +endif + +if compiler.has_function('getdelim') + libgit_c_args += '-DHAVE_GETDELIM' +endif + +if host_machine.system() == 'windows' + libgit_c_args += '-DUSE_WIN32_MMAP' +elif not compiler.has_function('mmap') + libgit_c_args += '-DNO_MMAP' + libgit_sources += 'compat/mmap.c' +endif + +if compiler.has_function('clock_gettime') + libgit_c_args += '-DHAVE_CLOCK_GETTIME' +endif + +if compiler.compiles(''' + #include + + void func(void) + { + clockid_t id = CLOCK_MONOTONIC; + } +''', name: 'monotonic clock') + libgit_c_args += '-DHAVE_CLOCK_MONOTONIC' +endif + +if not compiler.compiles(''' + #include + + void func(void) + { + uintmax_t x = 0; + } +''', name: 'uintmax_t') + libgit_c_args += '-DNO_UINTMAX_T' +endif + +has_bsd_sysctl = false +if compiler.has_header('sys/sysctl.h') + if compiler.compiles(''' + #include + #include + + void func(void) + { + int val, mib[2] = { 0 }; + size_t len = sizeof(val); + sysctl(mib, 2, &val, &len, NULL, 0); + } + ''', name: 'BSD sysctl') + libgit_c_args += '-DHAVE_BSD_SYSCTL' + has_bsd_sysctl = true + endif +endif + +if not meson.is_cross_build() and compiler.run(''' + #include + + int main(int argc, const char **argv) + { + FILE *f = fopen(".", "r"); + return f ? 0 : 1; + } +''', name: 'fread reads directories').returncode() == 0 + libgit_c_args += '-DFREAD_READS_DIRECTORIES' + libgit_sources += 'compat/fopen.c' +endif + +if not meson.is_cross_build() and fs.exists('/dev/tty') + libgit_c_args += '-DHAVE_DEV_TTY' +endif + +https_backend = get_option('https_backend') + +security_framework = dependency('Security', required: https_backend == 'CommonCrypto') +core_foundation_framework = dependency('CoreFoundation', required: security_framework.found()) +if https_backend == 'auto' and security_framework.found() + https_backend = 'CommonCrypto' +endif + +openssl_required = https_backend == 'openssl' or get_option('sha1_backend') == 'openssl' or get_option('sha256_backend') == 'openssl' +openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static']) +if https_backend == 'auto' and openssl.found() + https_backend = 'openssl' +endif + +if https_backend == 'CommonCrypto' + libgit_dependencies += security_framework + libgit_dependencies += core_foundation_framework + libgit_c_args += '-DAPPLE_COMMON_CRYPTO' +elif https_backend == 'openssl' + libgit_dependencies += openssl +else + # We either couldn't find any dependencies with 'auto' or the user requested + # 'none'. Both cases are benign. +endif + +if https_backend != 'openssl' + libgit_c_args += '-DNO_OPENSSL' +endif + +sha1_backend = get_option('sha1_backend') +if sha1_backend == 'sha1dc' + libgit_c_args += '-DSHA1_DC' + libgit_c_args += '-DSHA1DC_NO_STANDARD_INCLUDES=1' + libgit_c_args += '-DSHA1DC_INIT_SAFE_HASH_DEFAULT=0' + libgit_c_args += '-DSHA1DC_CUSTOM_INCLUDE_SHA1_C="git-compat-util.h"' + libgit_c_args += '-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="git-compat-util.h"' + + libgit_sources += [ + 'sha1dc_git.c', + 'sha1dc/sha1.c', + 'sha1dc/ubc_check.c', + ] +elif sha1_backend == 'common-crypto' + libgit_c_args += '-DCOMMON_DIGEST_FOR_OPENSSL' + libgit_c_args += '-DSHA1_APPLE' + # Apple CommonCrypto requires chunking + libgit_c_args += '-DSHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' +elif sha1_backend == 'openssl' + libgit_c_args += '-DSHA1_OPENSSL' + libgit_dependencies += openssl +elif sha1_backend == 'block' + libgit_c_args += '-DSHA1_BLK' + libgit_sources += 'block-sha1/sha1.c' +else + error('Unhandled SHA1 backend ' + sha1_backend) +endif + +sha256_backend = get_option('sha256_backend') +if sha256_backend == 'openssl' + libgit_c_args += '-DSHA256_OPENSSL' + libgit_dependencies += openssl +elif sha256_backend == 'nettle' + nettle = dependency('nettle') + libgit_dependencies += nettle + libgit_c_args += '-DSHA256_NETTLE' +elif sha256_backend == 'gcrypt' + gcrypt = dependency('gcrypt') + libgit_dependencies += gcrypt + libgit_c_args += '-DSHA256_GCRYPT' +elif sha256_backend == 'block' + libgit_c_args += '-DSHA256_BLK' + libgit_sources += 'sha256/block/sha256.c' +else + error('Unhandled SHA256 backend ' + sha256_backend) +endif + +if compiler.has_header_symbol('stdlib.h', 'arc4random_buf') + libgit_c_args += '-DHAVE_ARC4RANDOM' +elif compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf') + libgit_c_args += '-DHAVE_ARC4RANDOM_BSD' +elif compiler.has_function('getrandom', prefix: '#include ') + libgit_c_args += '-DHAVE_GETRANDOM' +elif compiler.has_function('getentropy', prefix: '#include ') + libgit_c_args += '-DHAVE_GETENTROPY' +elif compiler.has_function('RtlGenRandom', prefix: '#include \n#include ') + libgit_c_args += '-DHAVE_RTLGENRANDOM' +elif openssl.found() + libgit_c_args += '-DHAVE_OPENSSL_CSPRNG' +endif + +if get_option('runtime_prefix') + libgit_c_args += '-DRUNTIME_PREFIX' + build_options_config.set('RUNTIME_PREFIX', 'true') + + if compiler.has_header('mach-o/dyld.h') + libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH' + endif + + if has_bsd_sysctl and compiler.compiles(''' + #include + + void func(void) + { + KERN_PROC_PATHNAME; KERN_PROC; + } + ''', name: 'BSD KERN_PROC_PATHNAME') + libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH' + endif + + if host_machine.system() == 'linux' + libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="/proc/self/exe' + '"' + elif host_machine.system() == 'openbsd' + libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="' + '/proc/curproc/file' + '"' + elif host_machine.system() == 'netbsd' + libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="' + '/proc/curproc/exe' + '"' + endif + + if host_machine.system() == 'windows' and compiler.compiles(''' + #include + + void func(void) + { + _wpgmptr; + } + ''', name: 'Win32 _wpgmptr') + libgit_c_args += '-DHAVE_WPGMPTR' + endif +else + build_options_config.set('RUNTIME_PREFIX', 'false') +endif + +foreach key, value : { + 'DIFF': diff.full_path(), + 'GIT_TEST_CMP': diff.full_path() + ' -u', + 'GIT_TEST_GITPERLLIB': meson.project_build_root() / 'perl', + 'GIT_TEST_MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools', + 'GIT_TEST_POPATH': meson.project_source_root() / 'po', + 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', + 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', + 'PAGER_ENV': get_option('pager_environment'), + 'PERL_PATH': perl.found() ? perl.full_path() : '', + 'PYTHON_PATH': python.found () ? python.full_path() : '', + 'SHELL_PATH': shell.full_path(), + 'TAR': tar.full_path(), + 'TEST_OUTPUT_DIRECTORY': test_output_directory, + 'TEST_SHELL_PATH': shell.full_path(), +} + if value != '' and cygpath.found() + value = run_command(cygpath, value, check: true).stdout().strip() + endif + build_options_config.set_quoted(key, value) +endforeach + +configure_file( + input: 'GIT-BUILD-OPTIONS.in', + output: 'GIT-BUILD-OPTIONS', + configuration: build_options_config, +) + +git_version_file = custom_target( + command: [ + shell, + meson.current_source_dir() / 'GIT-VERSION-GEN', + meson.current_source_dir(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'GIT-VERSION-FILE.in', + output: 'GIT-VERSION-FILE', + build_always_stale: true, +) + +version_def_h = custom_target( + command: [ + shell, + meson.current_source_dir() / 'GIT-VERSION-GEN', + meson.current_source_dir(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'version-def.h.in', + output: 'version-def.h', + # Depend on GIT-VERSION-FILE so that we don't always try to rebuild this + # target for the same commit. + depends: [git_version_file], +) + +# Build a separate library for "version.c" so that we do not have to rebuild +# everything when the current Git commit changes. +libgit_version_library = static_library('git-version', + sources: [ + 'version.c', + version_def_h, + ], + c_args: libgit_c_args, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) + +libgit_library = static_library('git', + sources: libgit_sources, + c_args: libgit_c_args, + link_with: libgit_version_library, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) + +libgit = declare_dependency( + compile_args: libgit_c_args, + link_with: libgit_library, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) + +common_main_sources = ['common-main.c'] +common_main_link_args = [ ] +if host_machine.system() == 'windows' + git_rc = custom_target( + command: [ + shell, + meson.current_source_dir() / 'GIT-VERSION-GEN', + meson.current_source_dir(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'git.rc.in', + output: 'git.rc', + depends: [git_version_file], + ) + + common_main_sources += import('windows').compile_resources(git_rc, + include_directories: [meson.current_source_dir()], + ) + if compiler.get_argument_syntax() == 'gcc' + common_main_link_args += [ + '-municode', + '-Wl,-nxcompat', + '-Wl,-dynamicbase', + '-Wl,-pic-executable,-e,mainCRTStartup', + ] + elif compiler.get_argument_syntax() == 'msvc' + common_main_link_args += [ + '/ENTRY:wmainCRTStartup', + 'invalidcontinue.obj', + ] + else + error('Unsupported compiler ' + compiler.get_id()) + endif +endif +common_main_library = static_library('common-main', + sources: common_main_sources, + c_args: libgit_c_args, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) +common_main = declare_dependency( + link_with: common_main_library, + link_args: common_main_link_args, +) + +bin_wrappers = [ ] +test_dependencies = [ ] + +git = executable('git', + sources: builtin_sources + 'git.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) +bin_wrappers += git + +test_dependencies += executable('git-daemon', + sources: 'daemon.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +test_dependencies += executable('git-sh-i18n--envsubst', + sources: 'sh-i18n--envsubst.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +bin_wrappers += executable('git-shell', + sources: 'shell.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +test_dependencies += executable('git-http-backend', + sources: 'http-backend.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +bin_wrappers += executable('scalar', + sources: 'scalar.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +if get_option('curl').enabled() + curl_sources = [ + 'http.c', + 'http-walker.c', + ] + + git_remote_http = executable('git-remote-http', + sources: curl_sources + 'remote-curl.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + test_dependencies += git_remote_http + + test_dependencies += executable('git-http-fetch', + sources: curl_sources + 'http-fetch.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + + if expat.found() + test_dependencies += executable('git-http-push', + sources: curl_sources + 'http-push.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + endif + + foreach alias : [ 'git-remote-https', 'git-remote-ftp', 'git-remote-ftps' ] + test_dependencies += executable(alias, + objects: git_remote_http.extract_all_objects(recursive: false), + dependencies: [libgit, common_main], + ) + + install_symlink(alias + executable_suffix, + install_dir: get_option('libexecdir') / 'git-core', + pointing_to: 'git-remote-http', + ) + endforeach +endif + +imap_send_sources = ['imap-send.c'] +if use_curl_for_imap_send + imap_send_sources += curl_sources +endif + +test_dependencies += executable('git-imap-send', + sources: imap_send_sources, + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +foreach alias : [ 'git-receive-pack', 'git-upload-archive', 'git-upload-pack' ] + bin_wrappers += executable(alias, + objects: git.extract_all_objects(recursive: false), + dependencies: [libgit, common_main], + ) + + install_symlink(alias + executable_suffix, + install_dir: get_option('libexecdir') / 'git-core', + pointing_to: 'git', + ) +endforeach + +foreach symlink : [ + 'git', + 'git-receive-pack', + 'git-shell', + 'git-upload-archive', + 'git-upload-pack', + 'scalar', +] + if meson.version().version_compare('>=1.3.0') + pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / symlink, get_option('bindir')) + else + pointing_to = '../libexec/git-core' / symlink + endif + + install_symlink(symlink, + install_dir: get_option('bindir'), + pointing_to: pointing_to, + ) +endforeach + +scripts_sh = [ + 'git-difftool--helper.sh', + 'git-filter-branch.sh', + 'git-merge-octopus.sh', + 'git-merge-one-file.sh', + 'git-merge-resolve.sh', + 'git-mergetool--lib.sh', + 'git-mergetool.sh', + 'git-quiltimport.sh', + 'git-request-pull.sh', + 'git-sh-i18n.sh', + 'git-sh-setup.sh', + 'git-submodule.sh', + 'git-web--browse.sh', +] +if perl_features_enabled + scripts_sh += 'git-instaweb.sh' +endif + +foreach script : scripts_sh + test_dependencies += custom_target( + input: script, + output: fs.stem(script), + command: [ + shell, + meson.project_source_root() / 'generate-script.sh', + '@INPUT@', + '@OUTPUT@', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) +endforeach + +if perl_features_enabled + scripts_perl = [ + 'git-archimport.perl', + 'git-cvsexportcommit.perl', + 'git-cvsimport.perl', + 'git-cvsserver.perl', + 'git-send-email.perl', + 'git-svn.perl', + ] + + pathsep = ':' + if host_machine.system() == 'windows' + pathsep = ';' + endif + + perl_header_template = 'perl/header_templates/fixed_prefix.template.pl' + if get_option('runtime_prefix') + perl_header_template = 'perl/header_templates/runtime_prefix.template.pl' + endif + + perl_header = configure_file( + input: perl_header_template, + output: 'GIT-PERL-HEADER', + configuration: { + 'GITEXECDIR_REL': get_option('libexecdir') / 'git-core', + 'PERLLIBDIR_REL': get_option('datadir') / 'perl5', + 'LOCALEDIR_REL': get_option('datadir') / 'locale', + 'INSTLIBDIR': get_option('datadir') / 'perl5', + 'PATHSEP': pathsep, + }, + ) + + generate_perl_command = [ + shell, + meson.project_source_root() / 'generate-perl.sh', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + git_version_file.full_path(), + perl_header, + '@INPUT@', + '@OUTPUT@', + ] + + foreach script : scripts_perl + generated_script = custom_target( + input: script, + output: fs.stem(script), + command: generate_perl_command, + install: true, + install_dir: get_option('libexecdir') / 'git-core', + depends: [git_version_file], + ) + test_dependencies += generated_script + + if script == 'git-cvsserver.perl' + bin_wrappers += generated_script + + if meson.version().version_compare('>=1.3.0') + pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / fs.stem(script), get_option('bindir')) + else + pointing_to = '../libexec/git-core' / fs.stem(script) + endif + + install_symlink(fs.stem(script), + install_dir: get_option('bindir'), + pointing_to: pointing_to, + ) + endif + endforeach + + subdir('perl') +endif + +if python.found() + scripts_python = [ + 'git-p4.py' + ] + + foreach script : scripts_python + generated_python = custom_target( + input: script, + output: fs.stem(script), + command: [ + shell, + meson.project_source_root() / 'generate-python.sh', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + '@INPUT@', + '@OUTPUT@', + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + test_dependencies += generated_python + endforeach +endif + +mergetools = [ + 'mergetools/araxis', + 'mergetools/bc', + 'mergetools/codecompare', + 'mergetools/deltawalker', + 'mergetools/diffmerge', + 'mergetools/diffuse', + 'mergetools/ecmerge', + 'mergetools/emerge', + 'mergetools/examdiff', + 'mergetools/guiffy', + 'mergetools/gvimdiff', + 'mergetools/kdiff3', + 'mergetools/kompare', + 'mergetools/meld', + 'mergetools/nvimdiff', + 'mergetools/opendiff', + 'mergetools/p4merge', + 'mergetools/smerge', + 'mergetools/tkdiff', + 'mergetools/tortoisemerge', + 'mergetools/vimdiff', + 'mergetools/vscode', + 'mergetools/winmerge', + 'mergetools/xxdiff', +] + +foreach mergetool : mergetools + install_data(mergetool, install_dir: get_option('libexecdir') / 'git-core' / 'mergetools') +endforeach + +if intl.found() + subdir('po') +endif +subdir('contrib') +subdir('gitweb') +subdir('templates') + +# Everything but the bin-wrappers need to come before this target such that we +# can properly set up test dependencies. The bin-wrappers themselves are set up +# at configuration time, so these are fine. +if get_option('tests') + subdir('t') +endif + +subdir('bin-wrappers') +if get_option('docs') != [] + subdir('Documentation') +endif + +summary({ + 'curl': curl.found(), + 'expat': expat.found(), + 'gettext': intl.found(), + 'https': https_backend, + 'iconv': iconv.found(), + 'pcre2': pcre2.found(), + 'perl': perl_features_enabled, + 'python': python.found(), +}, section: 'Auto-detected features') diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000000..32a72139ba --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,81 @@ +# Configuration for how Git behaves at runtime. +option('default_pager', type: 'string', value: 'less', + description: 'Fall-back pager.') +option('default_editor', type: 'string', value: 'vi', + description: 'Fall-back editor.') +option('gitconfig', type: 'string', value: '/etc/gitconfig', + description: 'Path to the global git configuration file.') +option('gitattributes', type: 'string', value: '/etc/gitattributes', + description: 'Path to the global git attributes file.') +option('pager_environment', type: 'string', value: 'LESS=FRX LV=-c', + description: 'Environment used when spawning the pager') +option('perl_cpan_fallback', type: 'boolean', value: true, + description: 'Install bundled copies of CPAN modules that serve as a fallback in case the modules are not available on the system.') +option('runtime_prefix', type: 'boolean', value: false, + description: 'Resolve ancillary tooling and support files relative to the location of the runtime binary instead of hard-coding them into the binary.') +option('sane_tool_path', type: 'string', value: '', + description: 'A colon-separated list of paths to prepend to PATH if your tools in /usr/bin are broken.') + +# Features supported by Git. +option('curl', type: 'feature', value: 'enabled', + description: 'Build helpers used to access remotes with the HTTP transport.') +option('expat', type: 'feature', value: 'enabled', + description: 'Build helpers used to push to remotes with the HTTP transport.') +option('gettext', type: 'feature', value: 'auto', + description: 'Build translation files.') +option('iconv', type: 'feature', value: 'auto', + description: 'Support reencoding strings with different encodings.') +option('pcre2', type: 'feature', value: 'enabled', + description: 'Support Perl-compatible regular expressions in e.g. git-grep(1).') +option('perl', type: 'feature', value: 'auto', + description: 'Build tools written in Perl.') +option('python', type: 'feature', value: 'auto', + description: 'Build tools written in Python.') +option('regex', type: 'feature', value: 'auto', + description: 'Use the system-provided regex library instead of the bundled one.') + +# Backends. +option('https_backend', type: 'combo', value: 'auto', choices: ['auto', 'openssl', 'CommonCrypto', 'none'], + description: 'The HTTPS backend to use when connecting to remotes.') +option('sha1_backend', type: 'combo', choices: ['openssl', 'block', 'sha1dc', 'common-crypto'], value: 'sha1dc', + description: 'The backend used for hashing objects with the SHA1 object format') +option('sha256_backend', type: 'combo', choices: ['openssl', 'nettle', 'gcrypt', 'block'], value: 'block', + description: 'The backend used for hashing objects with the SHA256 object format') + +# Build tweaks. +option('macos_use_homebrew_gettext', type: 'boolean', value: true, + description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.') + +# gitweb configuration. +option('gitweb_config', type: 'string', value: 'gitweb_config.perl') +option('gitweb_config_system', type: 'string', value: '/etc/gitweb.conf') +option('gitweb_config_common', type: 'string', value: '/etc/gitweb-common.conf') +option('gitweb_home_link_str', type: 'string', value: 'projects') +option('gitweb_sitename', type: 'string', value: '') +option('gitweb_projectroot', type: 'string', value: '/pub/git') +option('gitweb_project_maxdepth', type: 'string', value: '2007') +option('gitweb_export_ok', type: 'string', value: '') +option('gitweb_strict_export', type: 'string', value: '') +option('gitweb_base_url', type: 'string', value: '') +option('gitweb_list', type: 'string', value: '') +option('gitweb_hometext', type: 'string', value: 'indextext.html') +option('gitweb_css', type: 'string', value: 'static/gitweb.css') +option('gitweb_logo', type: 'string', value: 'static/git-logo.png') +option('gitweb_favicon', type: 'string', value: 'static/git-favicon.png') +option('gitweb_js', type: 'string', value: 'static/gitweb.js') +option('gitweb_site_html_head_string', type: 'string', value: '') +option('gitweb_site_header', type: 'string', value: '') +option('gitweb_site_footer', type: 'string', value: '') +option('highlight_bin', type: 'string', value: 'highlight') + +# Documentation. +option('docs', type: 'array', choices: ['man', 'html'], value: [], + description: 'Which documenattion formats to build and install.') +option('default_help_format', type: 'combo', choices: ['man', 'html'], value: 'man', + description: 'Default format used when executing git-help(1).') + +# Testing. +option('tests', type: 'boolean', value: true, + description: 'Enable building tests. This requires Perl, but is separate from the "perl" option such that you can build tests without Perl features enabled.') +option('test_output_directory', type: 'string', + description: 'Path to the directory used to store test outputs') diff --git a/perl/FromCPAN/Mail/meson.build b/perl/FromCPAN/Mail/meson.build new file mode 100644 index 0000000000..129cff161c --- /dev/null +++ b/perl/FromCPAN/Mail/meson.build @@ -0,0 +1,7 @@ +test_dependencies += custom_target( + input: 'Address.pm', + output: 'Address.pm', + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5/FromCPAN/Mail', +) diff --git a/perl/FromCPAN/meson.build b/perl/FromCPAN/meson.build new file mode 100644 index 0000000000..4e7ea909df --- /dev/null +++ b/perl/FromCPAN/meson.build @@ -0,0 +1,9 @@ +test_dependencies += custom_target( + input: 'Error.pm', + output: 'Error.pm', + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5/FromCPAN', +) + +subdir('Mail') diff --git a/perl/Git/LoadCPAN/Mail/meson.build b/perl/Git/LoadCPAN/Mail/meson.build new file mode 100644 index 0000000000..7da5b37adb --- /dev/null +++ b/perl/Git/LoadCPAN/Mail/meson.build @@ -0,0 +1,7 @@ +test_dependencies += custom_target( + input: 'Address.pm', + output: 'Address.pm', + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5/Git/LoadCPAN/Mail', +) diff --git a/perl/Git/LoadCPAN/meson.build b/perl/Git/LoadCPAN/meson.build new file mode 100644 index 0000000000..9468c073ae --- /dev/null +++ b/perl/Git/LoadCPAN/meson.build @@ -0,0 +1,9 @@ +test_dependencies += custom_target( + input: 'Error.pm', + output: 'Error.pm', + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5/Git/LoadCPAN', +) + +subdir('Mail') diff --git a/perl/Git/SVN/Memoize/meson.build b/perl/Git/SVN/Memoize/meson.build new file mode 100644 index 0000000000..515ab3dd92 --- /dev/null +++ b/perl/Git/SVN/Memoize/meson.build @@ -0,0 +1,7 @@ +test_dependencies += custom_target( + input: 'YAML.pm', + output: 'YAML.pm', + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5/Git/SVN', +) diff --git a/perl/Git/SVN/meson.build b/perl/Git/SVN/meson.build new file mode 100644 index 0000000000..8338531041 --- /dev/null +++ b/perl/Git/SVN/meson.build @@ -0,0 +1,20 @@ +foreach source : [ + 'Editor.pm', + 'Fetcher.pm', + 'GlobSpec.pm', + 'Log.pm', + 'Migration.pm', + 'Prompt.pm', + 'Ra.pm', + 'Utils.pm', +] + test_dependencies += custom_target( + input: source, + output: source, + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5/Git/SVN', + ) +endforeach + +subdir('Memoize') diff --git a/perl/Git/meson.build b/perl/Git/meson.build new file mode 100644 index 0000000000..259209d730 --- /dev/null +++ b/perl/Git/meson.build @@ -0,0 +1,18 @@ +foreach source : [ + 'I18N.pm', + 'IndexInfo.pm', + 'LoadCPAN.pm', + 'Packet.pm', + 'SVN.pm', +] + test_dependencies += custom_target( + input: source, + output: source, + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5/Git', + ) +endforeach + +subdir('LoadCPAN') +subdir('SVN') diff --git a/perl/meson.build b/perl/meson.build new file mode 100644 index 0000000000..c22d6f8a1a --- /dev/null +++ b/perl/meson.build @@ -0,0 +1,12 @@ +test_dependencies += custom_target( + input: 'Git.pm', + output: 'Git.pm', + command: generate_perl_command, + install: true, + install_dir: get_option('datadir') / 'perl5', +) + +subdir('Git') +if get_option('perl_cpan_fallback') + subdir('FromCPAN') +endif diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000000..d7154b6395 --- /dev/null +++ b/po/meson.build @@ -0,0 +1,27 @@ +i18n = import('i18n') + +translations = i18n.gettext('git', + languages: [ + 'bg', + 'ca', + 'de', + 'el', + 'es', + 'fr', + 'id', + 'is', + 'it', + 'ko', + 'pl', + 'pt_PT', + 'ru', + 'sv', + 'tr', + 'uk', + 'vi', + 'zh_CN', + 'zh_TW', + ], + install: true, +) +test_dependencies += translations[0] diff --git a/subprojects/.gitignore b/subprojects/.gitignore new file mode 100644 index 0000000000..63ea916ef5 --- /dev/null +++ b/subprojects/.gitignore @@ -0,0 +1 @@ +/*/ diff --git a/subprojects/curl.wrap b/subprojects/curl.wrap new file mode 100644 index 0000000000..f7e384b85c --- /dev/null +++ b/subprojects/curl.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = curl-8.10.1 +source_url = https://github.com/curl/curl/releases/download/curl-8_10_1/curl-8.10.1.tar.xz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/curl_8.10.1-1/curl-8.10.1.tar.xz +source_filename = curl-8.10.1.tar.xz +source_hash = 73a4b0e99596a09fa5924a4fb7e4b995a85fda0d18a2c02ab9cf134bebce04ee +patch_filename = curl_8.10.1-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/curl_8.10.1-1/get_patch +patch_hash = 707c28f35fc9b0e8d68c0c2800712007612f922a31da9637ce706a2159f3ddd8 +wrapdb_version = 8.10.1-1 + +[provide] +dependency_names = libcurl diff --git a/subprojects/expat.wrap b/subprojects/expat.wrap new file mode 100644 index 0000000000..2e0427dcfd --- /dev/null +++ b/subprojects/expat.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = expat-2.6.3 +source_url = https://github.com/libexpat/libexpat/releases/download/R_2_6_3/expat-2.6.3.tar.xz +source_filename = expat-2.6.3.tar.bz2 +source_hash = 274db254a6979bde5aad404763a704956940e465843f2a9bd9ed7af22e2c0efc +patch_filename = expat_2.6.3-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/expat_2.6.3-1/get_patch +patch_hash = cf017fbe105e31428b2768360bd9be39094df4e948a1e8d1c54b6f7c76460cb1 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/expat_2.6.3-1/expat-2.6.3.tar.bz2 +wrapdb_version = 2.6.3-1 + +[provide] +expat = expat_dep diff --git a/subprojects/openssl.wrap b/subprojects/openssl.wrap new file mode 100644 index 0000000000..873d55106e --- /dev/null +++ b/subprojects/openssl.wrap @@ -0,0 +1,15 @@ +[wrap-file] +directory = openssl-3.0.8 +source_url = https://www.openssl.org/source/openssl-3.0.8.tar.gz +source_filename = openssl-3.0.8.tar.gz +source_hash = 6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e +patch_filename = openssl_3.0.8-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-3/get_patch +patch_hash = 300da189e106942347d61a4a4295aa2edbcf06184f8d13b4cee0bed9fb936963 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-3/openssl-3.0.8.tar.gz +wrapdb_version = 3.0.8-3 + +[provide] +libcrypto = libcrypto_dep +libssl = libssl_dep +openssl = openssl_dep diff --git a/subprojects/pcre2.wrap b/subprojects/pcre2.wrap new file mode 100644 index 0000000000..7e18447254 --- /dev/null +++ b/subprojects/pcre2.wrap @@ -0,0 +1,16 @@ +[wrap-file] +directory = pcre2-10.44 +source_url = https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.44/pcre2-10.44.tar.bz2 +source_filename = pcre2-10.44.tar.bz2 +source_hash = d34f02e113cf7193a1ebf2770d3ac527088d485d4e047ed10e5d217c6ef5de96 +patch_filename = pcre2_10.44-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/pcre2_10.44-2/get_patch +patch_hash = 4336d422ee9043847e5e10dbbbd01940d4c9e5027f31ccdc33a7898a1ca94009 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/pcre2_10.44-2/pcre2-10.44.tar.bz2 +wrapdb_version = 10.44-2 + +[provide] +libpcre2-8 = libpcre2_8 +libpcre2-16 = libpcre2_16 +libpcre2-32 = libpcre2_32 +libpcre2-posix = libpcre2_posix diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap new file mode 100644 index 0000000000..aa14de1774 --- /dev/null +++ b/subprojects/zlib.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = zlib-1.3.1 +source_url = http://zlib.net/fossils/zlib-1.3.1.tar.gz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/zlib_1.3.1-1/zlib-1.3.1.tar.gz +source_filename = zlib-1.3.1.tar.gz +source_hash = 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 +patch_filename = zlib_1.3.1-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.3.1-1/get_patch +patch_hash = e79b98eb24a75392009cec6f99ca5cdca9881ff20bfa174e8b8926d5c7a47095 +wrapdb_version = 1.3.1-1 + +[provide] +zlib = zlib_dep diff --git a/t/helper/meson.build b/t/helper/meson.build new file mode 100644 index 0000000000..5e83884246 --- /dev/null +++ b/t/helper/meson.build @@ -0,0 +1,91 @@ +test_tool_sources = [ + '../unit-tests/test-lib.c', + 'test-advise.c', + 'test-bitmap.c', + 'test-bloom.c', + 'test-bundle-uri.c', + 'test-cache-tree.c', + 'test-chmtime.c', + 'test-config.c', + 'test-crontab.c', + 'test-csprng.c', + 'test-date.c', + 'test-delete-gpgsig.c', + 'test-delta.c', + 'test-dir-iterator.c', + 'test-drop-caches.c', + 'test-dump-cache-tree.c', + 'test-dump-fsmonitor.c', + 'test-dump-split-index.c', + 'test-dump-untracked-cache.c', + 'test-env-helper.c', + 'test-example-tap.c', + 'test-find-pack.c', + 'test-fsmonitor-client.c', + 'test-genrandom.c', + 'test-genzeros.c', + 'test-getcwd.c', + 'test-hash-speed.c', + 'test-hash.c', + 'test-hashmap.c', + 'test-hexdump.c', + 'test-json-writer.c', + 'test-lazy-init-name-hash.c', + 'test-match-trees.c', + 'test-mergesort.c', + 'test-mktemp.c', + 'test-online-cpus.c', + 'test-pack-mtimes.c', + 'test-parse-options.c', + 'test-parse-pathspec-file.c', + 'test-partial-clone.c', + 'test-path-utils.c', + 'test-pcre2-config.c', + 'test-pkt-line.c', + 'test-proc-receive.c', + 'test-progress.c', + 'test-reach.c', + 'test-read-cache.c', + 'test-read-graph.c', + 'test-read-midx.c', + 'test-ref-store.c', + 'test-reftable.c', + 'test-regex.c', + 'test-repository.c', + 'test-revision-walking.c', + 'test-rot13-filter.c', + 'test-run-command.c', + 'test-scrap-cache-tree.c', + 'test-serve-v2.c', + 'test-sha1.c', + 'test-sha256.c', + 'test-sigchain.c', + 'test-simple-ipc.c', + 'test-string-list.c', + 'test-submodule-config.c', + 'test-submodule-nested-repo-config.c', + 'test-submodule.c', + 'test-subprocess.c', + 'test-tool.c', + 'test-trace2.c', + 'test-truncate.c', + 'test-userdiff.c', + 'test-wildmatch.c', + 'test-windows-named-pipe.c', + 'test-write-cache.c', + 'test-xml-encode.c', +] + +test_tool = executable('test-tool', + sources: test_tool_sources, + dependencies: [libgit, common_main], +) +bin_wrappers += test_tool +test_dependencies += test_tool + +test_fake_ssh = executable('test-fake-ssh', + sources: 'test-fake-ssh.c', + dependencies: [libgit, common_main], +) +bin_wrappers += test_fake_ssh +test_dependencies += test_fake_ssh diff --git a/t/meson.build b/t/meson.build new file mode 100644 index 0000000000..13fe854ba0 --- /dev/null +++ b/t/meson.build @@ -0,0 +1,1114 @@ +clar_test_suites = [ + 'unit-tests/ctype.c', + 'unit-tests/strvec.c', +] + +clar_sources = [ + 'unit-tests/clar/clar.c', + 'unit-tests/unit-test.c', +] + +clar_decls_h = custom_target( + input: clar_test_suites, + output: 'clar-decls.h', + command : [ + shell, + meson.current_source_dir() + '/unit-tests/generate-clar-decls.sh', + '@OUTPUT@', + '@INPUT@', + ], + env: script_environment, +) +clar_sources += clar_decls_h + +clar_sources += custom_target( + input: clar_decls_h, + output: 'clar.suite', + command : [ + shell, + meson.current_source_dir() + '/unit-tests/generate-clar-suites.sh', + '@INPUT@', + '@OUTPUT@', + ], + env: script_environment, +) + +clar_unit_tests = executable('unit-tests', + sources: clar_sources + clar_test_suites, + dependencies: [libgit, common_main], +) +test('unit-tests', clar_unit_tests) + +unit_test_programs = [ + 'unit-tests/t-example-decorate.c', + 'unit-tests/t-hash.c', + 'unit-tests/t-hashmap.c', + 'unit-tests/t-mem-pool.c', + 'unit-tests/t-oid-array.c', + 'unit-tests/t-oidmap.c', + 'unit-tests/t-oidtree.c', + 'unit-tests/t-prio-queue.c', + 'unit-tests/t-reftable-basics.c', + 'unit-tests/t-reftable-block.c', + 'unit-tests/t-reftable-merged.c', + 'unit-tests/t-reftable-pq.c', + 'unit-tests/t-reftable-reader.c', + 'unit-tests/t-reftable-readwrite.c', + 'unit-tests/t-reftable-record.c', + 'unit-tests/t-reftable-stack.c', + 'unit-tests/t-reftable-tree.c', + 'unit-tests/t-strbuf.c', + 'unit-tests/t-strcmp-offset.c', + 'unit-tests/t-trailer.c', + 'unit-tests/t-urlmatch-normalization.c', +] + +foreach unit_test_program : unit_test_programs + unit_test_name = fs.stem(unit_test_program) + unit_test = executable(unit_test_name, + sources: [ + 'unit-tests/test-lib.c', + 'unit-tests/lib-oid.c', + 'unit-tests/lib-reftable.c', + unit_test_program, + ], + dependencies: [libgit, common_main], + ) + test(unit_test_name, unit_test, + workdir: meson.current_source_dir(), + timeout: 0, + ) +endforeach + +subdir('helper') + +integration_tests = [ + 't0000-basic.sh', + 't0001-init.sh', + 't0002-gitfile.sh', + 't0003-attributes.sh', + 't0004-unwritable.sh', + 't0005-signals.sh', + 't0006-date.sh', + 't0007-git-var.sh', + 't0008-ignores.sh', + 't0010-racy-git.sh', + 't0012-help.sh', + 't0013-sha1dc.sh', + 't0014-alias.sh', + 't0017-env-helper.sh', + 't0018-advice.sh', + 't0019-json-writer.sh', + 't0020-crlf.sh', + 't0021-conversion.sh', + 't0022-crlf-rename.sh', + 't0023-crlf-am.sh', + 't0024-crlf-archive.sh', + 't0025-crlf-renormalize.sh', + 't0026-eol-config.sh', + 't0027-auto-crlf.sh', + 't0028-working-tree-encoding.sh', + 't0029-core-unsetenvvars.sh', + 't0030-stripspace.sh', + 't0033-safe-directory.sh', + 't0034-root-safe-directory.sh', + 't0035-safe-bare-repository.sh', + 't0040-parse-options.sh', + 't0041-usage.sh', + 't0050-filesystem.sh', + 't0051-windows-named-pipe.sh', + 't0052-simple-ipc.sh', + 't0055-beyond-symlinks.sh', + 't0056-git-C.sh', + 't0060-path-utils.sh', + 't0061-run-command.sh', + 't0062-revision-walking.sh', + 't0063-string-list.sh', + 't0066-dir-iterator.sh', + 't0067-parse_pathspec_file.sh', + 't0068-for-each-repo.sh', + 't0070-fundamental.sh', + 't0071-sort.sh', + 't0080-unit-test-output.sh', + 't0081-find-pack.sh', + 't0090-cache-tree.sh', + 't0091-bugreport.sh', + 't0092-diagnose.sh', + 't0095-bloom.sh', + 't0100-previous.sh', + 't0101-at-syntax.sh', + 't0200-gettext-basic.sh', + 't0201-gettext-fallbacks.sh', + 't0202-gettext-perl.sh', + 't0203-gettext-setlocale-sanity.sh', + 't0204-gettext-reencode-sanity.sh', + 't0210-trace2-normal.sh', + 't0211-trace2-perf.sh', + 't0212-trace2-event.sh', + 't0300-credentials.sh', + 't0301-credential-cache.sh', + 't0302-credential-store.sh', + 't0303-credential-external.sh', + 't0410-partial-clone.sh', + 't0411-clone-from-partial.sh', + 't0450-txt-doc-vs-help.sh', + 't0500-progress-display.sh', + 't0600-reffiles-backend.sh', + 't0601-reffiles-pack-refs.sh', + 't0602-reffiles-fsck.sh', + 't0610-reftable-basics.sh', + 't0611-reftable-httpd.sh', + 't0612-reftable-jgit-compatibility.sh', + 't0613-reftable-write-options.sh', + 't1000-read-tree-m-3way.sh', + 't1001-read-tree-m-2way.sh', + 't1002-read-tree-m-u-2way.sh', + 't1003-read-tree-prefix.sh', + 't1004-read-tree-m-u-wf.sh', + 't1005-read-tree-reset.sh', + 't1006-cat-file.sh', + 't1007-hash-object.sh', + 't1008-read-tree-overlay.sh', + 't1009-read-tree-new-index.sh', + 't1010-mktree.sh', + 't1011-read-tree-sparse-checkout.sh', + 't1012-read-tree-df.sh', + 't1013-read-tree-submodule.sh', + 't1014-read-tree-confusing.sh', + 't1015-read-index-unmerged.sh', + 't1016-compatObjectFormat.sh', + 't1020-subdirectory.sh', + 't1021-rerere-in-workdir.sh', + 't1022-read-tree-partial-clone.sh', + 't1050-large.sh', + 't1051-large-conversion.sh', + 't1060-object-corruption.sh', + 't1090-sparse-checkout-scope.sh', + 't1091-sparse-checkout-builtin.sh', + 't1092-sparse-checkout-compatibility.sh', + 't1100-commit-tree-options.sh', + 't1300-config.sh', + 't1301-shared-repo.sh', + 't1302-repo-version.sh', + 't1303-wacky-config.sh', + 't1304-default-acl.sh', + 't1305-config-include.sh', + 't1306-xdg-files.sh', + 't1307-config-blob.sh', + 't1308-config-set.sh', + 't1309-early-config.sh', + 't1310-config-default.sh', + 't1350-config-hooks-path.sh', + 't1400-update-ref.sh', + 't1401-symbolic-ref.sh', + 't1402-check-ref-format.sh', + 't1403-show-ref.sh', + 't1404-update-ref-errors.sh', + 't1405-main-ref-store.sh', + 't1406-submodule-ref-store.sh', + 't1407-worktree-ref-store.sh', + 't1408-packed-refs.sh', + 't1409-avoid-packing-refs.sh', + 't1410-reflog.sh', + 't1411-reflog-show.sh', + 't1412-reflog-loop.sh', + 't1413-reflog-detach.sh', + 't1414-reflog-walk.sh', + 't1415-worktree-refs.sh', + 't1416-ref-transaction-hooks.sh', + 't1417-reflog-updateref.sh', + 't1418-reflog-exists.sh', + 't1419-exclude-refs.sh', + 't1420-lost-found.sh', + 't1430-bad-ref-name.sh', + 't1450-fsck.sh', + 't1451-fsck-buffer.sh', + 't1460-refs-migrate.sh', + 't1500-rev-parse.sh', + 't1501-work-tree.sh', + 't1502-rev-parse-parseopt.sh', + 't1503-rev-parse-verify.sh', + 't1504-ceiling-dirs.sh', + 't1505-rev-parse-last.sh', + 't1506-rev-parse-diagnosis.sh', + 't1507-rev-parse-upstream.sh', + 't1508-at-combinations.sh', + 't1509-root-work-tree.sh', + 't1510-repo-setup.sh', + 't1511-rev-parse-caret.sh', + 't1512-rev-parse-disambiguation.sh', + 't1513-rev-parse-prefix.sh', + 't1514-rev-parse-push.sh', + 't1515-rev-parse-outside-repo.sh', + 't1517-outside-repo.sh', + 't1600-index.sh', + 't1601-index-bogus.sh', + 't1700-split-index.sh', + 't1701-racy-split-index.sh', + 't1800-hook.sh', + 't2000-conflict-when-checking-files-out.sh', + 't2002-checkout-cache-u.sh', + 't2003-checkout-cache-mkdir.sh', + 't2004-checkout-cache-temp.sh', + 't2005-checkout-index-symlinks.sh', + 't2006-checkout-index-basic.sh', + 't2007-checkout-symlink.sh', + 't2008-checkout-subdir.sh', + 't2009-checkout-statinfo.sh', + 't2010-checkout-ambiguous.sh', + 't2011-checkout-invalid-head.sh', + 't2012-checkout-last.sh', + 't2013-checkout-submodule.sh', + 't2014-checkout-switch.sh', + 't2015-checkout-unborn.sh', + 't2016-checkout-patch.sh', + 't2017-checkout-orphan.sh', + 't2018-checkout-branch.sh', + 't2019-checkout-ambiguous-ref.sh', + 't2020-checkout-detach.sh', + 't2021-checkout-overwrite.sh', + 't2022-checkout-paths.sh', + 't2023-checkout-m.sh', + 't2024-checkout-dwim.sh', + 't2025-checkout-no-overlay.sh', + 't2026-checkout-pathspec-file.sh', + 't2027-checkout-track.sh', + 't2030-unresolve-info.sh', + 't2050-git-dir-relative.sh', + 't2060-switch.sh', + 't2070-restore.sh', + 't2071-restore-patch.sh', + 't2072-restore-pathspec-file.sh', + 't2080-parallel-checkout-basics.sh', + 't2081-parallel-checkout-collisions.sh', + 't2082-parallel-checkout-attributes.sh', + 't2100-update-cache-badpath.sh', + 't2101-update-index-reupdate.sh', + 't2102-update-index-symlinks.sh', + 't2103-update-index-ignore-missing.sh', + 't2104-update-index-skip-worktree.sh', + 't2105-update-index-gitfile.sh', + 't2106-update-index-assume-unchanged.sh', + 't2107-update-index-basic.sh', + 't2108-update-index-refresh-racy.sh', + 't2200-add-update.sh', + 't2201-add-update-typechange.sh', + 't2202-add-addremove.sh', + 't2203-add-intent.sh', + 't2204-add-ignored.sh', + 't2205-add-worktree-config.sh', + 't2300-cd-to-toplevel.sh', + 't2400-worktree-add.sh', + 't2401-worktree-prune.sh', + 't2402-worktree-list.sh', + 't2403-worktree-move.sh', + 't2404-worktree-config.sh', + 't2405-worktree-submodule.sh', + 't2406-worktree-repair.sh', + 't2407-worktree-heads.sh', + 't2500-untracked-overwriting.sh', + 't2501-cwd-empty.sh', + 't3000-ls-files-others.sh', + 't3001-ls-files-others-exclude.sh', + 't3002-ls-files-dashpath.sh', + 't3003-ls-files-exclude.sh', + 't3004-ls-files-basic.sh', + 't3005-ls-files-relative.sh', + 't3006-ls-files-long.sh', + 't3007-ls-files-recurse-submodules.sh', + 't3008-ls-files-lazy-init-name-hash.sh', + 't3009-ls-files-others-nonsubmodule.sh', + 't3010-ls-files-killed-modified.sh', + 't3011-common-prefixes-and-directory-traversal.sh', + 't3012-ls-files-dedup.sh', + 't3013-ls-files-format.sh', + 't3020-ls-files-error-unmatch.sh', + 't3040-subprojects-basic.sh', + 't3050-subprojects-fetch.sh', + 't3060-ls-files-with-tree.sh', + 't3070-wildmatch.sh', + 't3100-ls-tree-restrict.sh', + 't3101-ls-tree-dirname.sh', + 't3102-ls-tree-wildcards.sh', + 't3103-ls-tree-misc.sh', + 't3104-ls-tree-format.sh', + 't3105-ls-tree-output.sh', + 't3200-branch.sh', + 't3201-branch-contains.sh', + 't3202-show-branch.sh', + 't3203-branch-output.sh', + 't3204-branch-name-interpretation.sh', + 't3205-branch-color.sh', + 't3206-range-diff.sh', + 't3207-branch-submodule.sh', + 't3211-peel-ref.sh', + 't3300-funny-names.sh', + 't3301-notes.sh', + 't3302-notes-index-expensive.sh', + 't3303-notes-subtrees.sh', + 't3304-notes-mixed.sh', + 't3305-notes-fanout.sh', + 't3306-notes-prune.sh', + 't3307-notes-man.sh', + 't3308-notes-merge.sh', + 't3309-notes-merge-auto-resolve.sh', + 't3310-notes-merge-manual-resolve.sh', + 't3311-notes-merge-fanout.sh', + 't3320-notes-merge-worktrees.sh', + 't3321-notes-stripspace.sh', + 't3400-rebase.sh', + 't3401-rebase-and-am-rename.sh', + 't3402-rebase-merge.sh', + 't3403-rebase-skip.sh', + 't3404-rebase-interactive.sh', + 't3405-rebase-malformed.sh', + 't3406-rebase-message.sh', + 't3407-rebase-abort.sh', + 't3408-rebase-multi-line.sh', + 't3409-rebase-environ.sh', + 't3412-rebase-root.sh', + 't3413-rebase-hook.sh', + 't3415-rebase-autosquash.sh', + 't3416-rebase-onto-threedots.sh', + 't3417-rebase-whitespace-fix.sh', + 't3418-rebase-continue.sh', + 't3419-rebase-patch-id.sh', + 't3420-rebase-autostash.sh', + 't3421-rebase-topology-linear.sh', + 't3422-rebase-incompatible-options.sh', + 't3423-rebase-reword.sh', + 't3424-rebase-empty.sh', + 't3425-rebase-topology-merges.sh', + 't3426-rebase-submodule.sh', + 't3427-rebase-subtree.sh', + 't3428-rebase-signoff.sh', + 't3429-rebase-edit-todo.sh', + 't3430-rebase-merges.sh', + 't3431-rebase-fork-point.sh', + 't3432-rebase-fast-forward.sh', + 't3433-rebase-across-mode-change.sh', + 't3434-rebase-i18n.sh', + 't3435-rebase-gpg-sign.sh', + 't3436-rebase-more-options.sh', + 't3437-rebase-fixup-options.sh', + 't3438-rebase-broken-files.sh', + 't3500-cherry.sh', + 't3501-revert-cherry-pick.sh', + 't3502-cherry-pick-merge.sh', + 't3503-cherry-pick-root.sh', + 't3504-cherry-pick-rerere.sh', + 't3505-cherry-pick-empty.sh', + 't3506-cherry-pick-ff.sh', + 't3507-cherry-pick-conflict.sh', + 't3508-cherry-pick-many-commits.sh', + 't3509-cherry-pick-merge-df.sh', + 't3510-cherry-pick-sequence.sh', + 't3511-cherry-pick-x.sh', + 't3512-cherry-pick-submodule.sh', + 't3513-revert-submodule.sh', + 't3514-cherry-pick-revert-gpg.sh', + 't3600-rm.sh', + 't3601-rm-pathspec-file.sh', + 't3602-rm-sparse-checkout.sh', + 't3650-replay-basics.sh', + 't3700-add.sh', + 't3701-add-interactive.sh', + 't3702-add-edit.sh', + 't3703-add-magic-pathspec.sh', + 't3704-add-pathspec-file.sh', + 't3705-add-sparse-checkout.sh', + 't3800-mktag.sh', + 't3900-i18n-commit.sh', + 't3901-i18n-patch.sh', + 't3902-quoted.sh', + 't3903-stash.sh', + 't3904-stash-patch.sh', + 't3905-stash-include-untracked.sh', + 't3906-stash-submodule.sh', + 't3907-stash-show-config.sh', + 't3908-stash-in-worktree.sh', + 't3909-stash-pathspec-file.sh', + 't3910-mac-os-precompose.sh', + 't3920-crlf-messages.sh', + 't4000-diff-format.sh', + 't4001-diff-rename.sh', + 't4002-diff-basic.sh', + 't4003-diff-rename-1.sh', + 't4004-diff-rename-symlink.sh', + 't4005-diff-rename-2.sh', + 't4006-diff-mode.sh', + 't4007-rename-3.sh', + 't4008-diff-break-rewrite.sh', + 't4009-diff-rename-4.sh', + 't4010-diff-pathspec.sh', + 't4011-diff-symlink.sh', + 't4012-diff-binary.sh', + 't4013-diff-various.sh', + 't4014-format-patch.sh', + 't4015-diff-whitespace.sh', + 't4016-diff-quote.sh', + 't4017-diff-retval.sh', + 't4018-diff-funcname.sh', + 't4019-diff-wserror.sh', + 't4020-diff-external.sh', + 't4021-format-patch-numbered.sh', + 't4022-diff-rewrite.sh', + 't4023-diff-rename-typechange.sh', + 't4024-diff-optimize-common.sh', + 't4025-hunk-header.sh', + 't4026-color.sh', + 't4027-diff-submodule.sh', + 't4028-format-patch-mime-headers.sh', + 't4029-diff-trailing-space.sh', + 't4030-diff-textconv.sh', + 't4031-diff-rewrite-binary.sh', + 't4032-diff-inter-hunk-context.sh', + 't4033-diff-patience.sh', + 't4034-diff-words.sh', + 't4035-diff-quiet.sh', + 't4036-format-patch-signer-mime.sh', + 't4037-diff-r-t-dirs.sh', + 't4038-diff-combined.sh', + 't4039-diff-assume-unchanged.sh', + 't4040-whitespace-status.sh', + 't4041-diff-submodule-option.sh', + 't4042-diff-textconv-caching.sh', + 't4043-diff-rename-binary.sh', + 't4044-diff-index-unique-abbrev.sh', + 't4045-diff-relative.sh', + 't4046-diff-unmerged.sh', + 't4047-diff-dirstat.sh', + 't4048-diff-combined-binary.sh', + 't4049-diff-stat-count.sh', + 't4050-diff-histogram.sh', + 't4051-diff-function-context.sh', + 't4052-stat-output.sh', + 't4053-diff-no-index.sh', + 't4054-diff-bogus-tree.sh', + 't4055-diff-context.sh', + 't4056-diff-order.sh', + 't4057-diff-combined-paths.sh', + 't4058-diff-duplicates.sh', + 't4059-diff-submodule-not-initialized.sh', + 't4060-diff-submodule-option-diff-format.sh', + 't4061-diff-indent.sh', + 't4062-diff-pickaxe.sh', + 't4063-diff-blobs.sh', + 't4064-diff-oidfind.sh', + 't4065-diff-anchored.sh', + 't4066-diff-emit-delay.sh', + 't4067-diff-partial-clone.sh', + 't4068-diff-symmetric-merge-base.sh', + 't4069-remerge-diff.sh', + 't4100-apply-stat.sh', + 't4101-apply-nonl.sh', + 't4102-apply-rename.sh', + 't4103-apply-binary.sh', + 't4104-apply-boundary.sh', + 't4105-apply-fuzz.sh', + 't4106-apply-stdin.sh', + 't4107-apply-ignore-whitespace.sh', + 't4108-apply-threeway.sh', + 't4109-apply-multifrag.sh', + 't4110-apply-scan.sh', + 't4111-apply-subdir.sh', + 't4112-apply-renames.sh', + 't4113-apply-ending.sh', + 't4114-apply-typechange.sh', + 't4115-apply-symlink.sh', + 't4116-apply-reverse.sh', + 't4117-apply-reject.sh', + 't4118-apply-empty-context.sh', + 't4119-apply-config.sh', + 't4120-apply-popt.sh', + 't4121-apply-diffs.sh', + 't4122-apply-symlink-inside.sh', + 't4123-apply-shrink.sh', + 't4124-apply-ws-rule.sh', + 't4125-apply-ws-fuzz.sh', + 't4126-apply-empty.sh', + 't4127-apply-same-fn.sh', + 't4128-apply-root.sh', + 't4129-apply-samemode.sh', + 't4130-apply-criss-cross-rename.sh', + 't4131-apply-fake-ancestor.sh', + 't4132-apply-removal.sh', + 't4133-apply-filenames.sh', + 't4134-apply-submodule.sh', + 't4135-apply-weird-filenames.sh', + 't4136-apply-check.sh', + 't4137-apply-submodule.sh', + 't4138-apply-ws-expansion.sh', + 't4139-apply-escape.sh', + 't4140-apply-ita.sh', + 't4141-apply-too-large.sh', + 't4150-am.sh', + 't4151-am-abort.sh', + 't4152-am-subjects.sh', + 't4153-am-resume-override-opts.sh', + 't4200-rerere.sh', + 't4201-shortlog.sh', + 't4202-log.sh', + 't4203-mailmap.sh', + 't4204-patch-id.sh', + 't4205-log-pretty-formats.sh', + 't4206-log-follow-harder-copies.sh', + 't4207-log-decoration-colors.sh', + 't4208-log-magic-pathspec.sh', + 't4209-log-pickaxe.sh', + 't4210-log-i18n.sh', + 't4211-line-log.sh', + 't4212-log-corrupt.sh', + 't4213-log-tabexpand.sh', + 't4214-log-graph-octopus.sh', + 't4215-log-skewed-merges.sh', + 't4216-log-bloom.sh', + 't4217-log-limit.sh', + 't4252-am-options.sh', + 't4253-am-keep-cr-dos.sh', + 't4254-am-corrupt.sh', + 't4255-am-submodule.sh', + 't4256-am-format-flowed.sh', + 't4257-am-interactive.sh', + 't4258-am-quoted-cr.sh', + 't4300-merge-tree.sh', + 't4301-merge-tree-write-tree.sh', + 't5000-tar-tree.sh', + 't5001-archive-attr.sh', + 't5002-archive-attr-pattern.sh', + 't5003-archive-zip.sh', + 't5004-archive-corner-cases.sh', + 't5100-mailinfo.sh', + 't5150-request-pull.sh', + 't5200-update-server-info.sh', + 't5300-pack-object.sh', + 't5301-sliding-window.sh', + 't5302-pack-index.sh', + 't5303-pack-corruption-resilience.sh', + 't5304-prune.sh', + 't5305-include-tag.sh', + 't5306-pack-nobase.sh', + 't5307-pack-missing-commit.sh', + 't5308-pack-detect-duplicates.sh', + 't5309-pack-delta-cycles.sh', + 't5310-pack-bitmaps.sh', + 't5311-pack-bitmaps-shallow.sh', + 't5312-prune-corruption.sh', + 't5313-pack-bounds-checks.sh', + 't5314-pack-cycle-detection.sh', + 't5315-pack-objects-compression.sh', + 't5316-pack-delta-depth.sh', + 't5317-pack-objects-filter-objects.sh', + 't5318-commit-graph.sh', + 't5319-multi-pack-index.sh', + 't5320-delta-islands.sh', + 't5321-pack-large-objects.sh', + 't5322-pack-objects-sparse.sh', + 't5323-pack-redundant.sh', + 't5324-split-commit-graph.sh', + 't5325-reverse-index.sh', + 't5326-multi-pack-bitmaps.sh', + 't5327-multi-pack-bitmaps-rev.sh', + 't5328-commit-graph-64bit-time.sh', + 't5329-pack-objects-cruft.sh', + 't5330-no-lazy-fetch-with-commit-graph.sh', + 't5331-pack-objects-stdin.sh', + 't5332-multi-pack-reuse.sh', + 't5333-pseudo-merge-bitmaps.sh', + 't5334-incremental-multi-pack-index.sh', + 't5351-unpack-large-objects.sh', + 't5400-send-pack.sh', + 't5401-update-hooks.sh', + 't5402-post-merge-hook.sh', + 't5403-post-checkout-hook.sh', + 't5404-tracking-branches.sh', + 't5405-send-pack-rewind.sh', + 't5406-remote-rejects.sh', + 't5407-post-rewrite-hook.sh', + 't5408-send-pack-stdin.sh', + 't5409-colorize-remote-messages.sh', + 't5410-receive-pack-alternates.sh', + 't5411-proc-receive-hook.sh', + 't5500-fetch-pack.sh', + 't5501-fetch-push-alternates.sh', + 't5502-quickfetch.sh', + 't5503-tagfollow.sh', + 't5504-fetch-receive-strict.sh', + 't5505-remote.sh', + 't5506-remote-groups.sh', + 't5507-remote-environment.sh', + 't5509-fetch-push-namespaces.sh', + 't5510-fetch.sh', + 't5511-refspec.sh', + 't5512-ls-remote.sh', + 't5513-fetch-track.sh', + 't5514-fetch-multiple.sh', + 't5515-fetch-merge-logic.sh', + 't5516-fetch-push.sh', + 't5517-push-mirror.sh', + 't5518-fetch-exit-status.sh', + 't5519-push-alternates.sh', + 't5520-pull.sh', + 't5521-pull-options.sh', + 't5522-pull-symlink.sh', + 't5523-push-upstream.sh', + 't5524-pull-msg.sh', + 't5525-fetch-tagopt.sh', + 't5526-fetch-submodules.sh', + 't5527-fetch-odd-refs.sh', + 't5528-push-default.sh', + 't5529-push-errors.sh', + 't5530-upload-pack-error.sh', + 't5531-deep-submodule-push.sh', + 't5532-fetch-proxy.sh', + 't5533-push-cas.sh', + 't5534-push-signed.sh', + 't5535-fetch-push-symref.sh', + 't5536-fetch-conflicts.sh', + 't5537-fetch-shallow.sh', + 't5538-push-shallow.sh', + 't5539-fetch-http-shallow.sh', + 't5540-http-push-webdav.sh', + 't5541-http-push-smart.sh', + 't5542-push-http-shallow.sh', + 't5543-atomic-push.sh', + 't5544-pack-objects-hook.sh', + 't5545-push-options.sh', + 't5546-receive-limits.sh', + 't5547-push-quarantine.sh', + 't5548-push-porcelain.sh', + 't5549-fetch-push-http.sh', + 't5550-http-fetch-dumb.sh', + 't5551-http-fetch-smart.sh', + 't5552-skipping-fetch-negotiator.sh', + 't5553-set-upstream.sh', + 't5554-noop-fetch-negotiator.sh', + 't5555-http-smart-common.sh', + 't5557-http-get.sh', + 't5558-clone-bundle-uri.sh', + 't5559-http-fetch-smart-http2.sh', + 't5560-http-backend-noserver.sh', + 't5561-http-backend.sh', + 't5562-http-backend-content-length.sh', + 't5563-simple-http-auth.sh', + 't5564-http-proxy.sh', + 't5570-git-daemon.sh', + 't5571-pre-push-hook.sh', + 't5572-pull-submodule.sh', + 't5573-pull-verify-signatures.sh', + 't5574-fetch-output.sh', + 't5580-unc-paths.sh', + 't5581-http-curl-verbose.sh', + 't5582-fetch-negative-refspec.sh', + 't5583-push-branches.sh', + 't5600-clone-fail-cleanup.sh', + 't5601-clone.sh', + 't5602-clone-remote-exec.sh', + 't5603-clone-dirname.sh', + 't5604-clone-reference.sh', + 't5605-clone-local.sh', + 't5606-clone-options.sh', + 't5607-clone-bundle.sh', + 't5608-clone-2gb.sh', + 't5609-clone-branch.sh', + 't5610-clone-detached.sh', + 't5611-clone-config.sh', + 't5612-clone-refspec.sh', + 't5613-info-alternate.sh', + 't5614-clone-submodules-shallow.sh', + 't5615-alternate-env.sh', + 't5616-partial-clone.sh', + 't5617-clone-submodules-remote.sh', + 't5618-alternate-refs.sh', + 't5619-clone-local-ambiguous-transport.sh', + 't5700-protocol-v1.sh', + 't5701-git-serve.sh', + 't5702-protocol-v2.sh', + 't5703-upload-pack-ref-in-want.sh', + 't5704-protocol-violations.sh', + 't5705-session-id-in-capabilities.sh', + 't5730-protocol-v2-bundle-uri-file.sh', + 't5731-protocol-v2-bundle-uri-git.sh', + 't5732-protocol-v2-bundle-uri-http.sh', + 't5750-bundle-uri-parse.sh', + 't5801-remote-helpers.sh', + 't5802-connect-helper.sh', + 't5810-proto-disable-local.sh', + 't5811-proto-disable-git.sh', + 't5812-proto-disable-http.sh', + 't5813-proto-disable-ssh.sh', + 't5814-proto-disable-ext.sh', + 't5815-submodule-protos.sh', + 't5900-repo-selection.sh', + 't6000-rev-list-misc.sh', + 't6001-rev-list-graft.sh', + 't6002-rev-list-bisect.sh', + 't6003-rev-list-topo-order.sh', + 't6004-rev-list-path-optim.sh', + 't6005-rev-list-count.sh', + 't6006-rev-list-format.sh', + 't6007-rev-list-cherry-pick-file.sh', + 't6008-rev-list-submodule.sh', + 't6009-rev-list-parent.sh', + 't6010-merge-base.sh', + 't6011-rev-list-with-bad-commit.sh', + 't6012-rev-list-simplify.sh', + 't6013-rev-list-reverse-parents.sh', + 't6014-rev-list-all.sh', + 't6016-rev-list-graph-simplify-history.sh', + 't6017-rev-list-stdin.sh', + 't6018-rev-list-glob.sh', + 't6019-rev-list-ancestry-path.sh', + 't6020-bundle-misc.sh', + 't6021-rev-list-exclude-hidden.sh', + 't6022-rev-list-missing.sh', + 't6030-bisect-porcelain.sh', + 't6040-tracking-info.sh', + 't6041-bisect-submodule.sh', + 't6050-replace.sh', + 't6060-merge-index.sh', + 't6100-rev-list-in-order.sh', + 't6101-rev-parse-parents.sh', + 't6102-rev-list-unexpected-objects.sh', + 't6110-rev-list-sparse.sh', + 't6111-rev-list-treesame.sh', + 't6112-rev-list-filters-objects.sh', + 't6113-rev-list-bitmap-filters.sh', + 't6114-keep-packs.sh', + 't6115-rev-list-du.sh', + 't6120-describe.sh', + 't6130-pathspec-noglob.sh', + 't6131-pathspec-icase.sh', + 't6132-pathspec-exclude.sh', + 't6133-pathspec-rev-dwim.sh', + 't6134-pathspec-in-submodule.sh', + 't6135-pathspec-with-attrs.sh', + 't6136-pathspec-in-bare.sh', + 't6200-fmt-merge-msg.sh', + 't6300-for-each-ref.sh', + 't6301-for-each-ref-errors.sh', + 't6302-for-each-ref-filter.sh', + 't6400-merge-df.sh', + 't6401-merge-criss-cross.sh', + 't6402-merge-rename.sh', + 't6403-merge-file.sh', + 't6404-recursive-merge.sh', + 't6405-merge-symlinks.sh', + 't6406-merge-attr.sh', + 't6407-merge-binary.sh', + 't6408-merge-up-to-date.sh', + 't6409-merge-subtree.sh', + 't6411-merge-filemode.sh', + 't6412-merge-large-rename.sh', + 't6413-merge-crlf.sh', + 't6414-merge-rename-nocruft.sh', + 't6415-merge-dir-to-symlink.sh', + 't6416-recursive-corner-cases.sh', + 't6417-merge-ours-theirs.sh', + 't6418-merge-text-auto.sh', + 't6419-merge-ignorecase.sh', + 't6421-merge-partial-clone.sh', + 't6422-merge-rename-corner-cases.sh', + 't6423-merge-rename-directories.sh', + 't6424-merge-unrelated-index-changes.sh', + 't6425-merge-rename-delete.sh', + 't6426-merge-skip-unneeded-updates.sh', + 't6427-diff3-conflict-markers.sh', + 't6428-merge-conflicts-sparse.sh', + 't6429-merge-sequence-rename-caching.sh', + 't6430-merge-recursive.sh', + 't6431-merge-criscross.sh', + 't6432-merge-recursive-space-options.sh', + 't6433-merge-toplevel.sh', + 't6434-merge-recursive-rename-options.sh', + 't6435-merge-sparse.sh', + 't6436-merge-overwrite.sh', + 't6437-submodule-merge.sh', + 't6438-submodule-directory-file-conflicts.sh', + 't6439-merge-co-error-msgs.sh', + 't6500-gc.sh', + 't6501-freshen-objects.sh', + 't6600-test-reach.sh', + 't6700-tree-depth.sh', + 't7001-mv.sh', + 't7002-mv-sparse-checkout.sh', + 't7003-filter-branch.sh', + 't7004-tag.sh', + 't7005-editor.sh', + 't7006-pager.sh', + 't7007-show.sh', + 't7008-filter-branch-null-sha1.sh', + 't7010-setup.sh', + 't7011-skip-worktree-reading.sh', + 't7012-skip-worktree-writing.sh', + 't7030-verify-tag.sh', + 't7031-verify-tag-signed-ssh.sh', + 't7060-wtstatus.sh', + 't7061-wtstatus-ignore.sh', + 't7062-wtstatus-ignorecase.sh', + 't7063-status-untracked-cache.sh', + 't7064-wtstatus-pv2.sh', + 't7101-reset-empty-subdirs.sh', + 't7102-reset.sh', + 't7103-reset-bare.sh', + 't7104-reset-hard.sh', + 't7105-reset-patch.sh', + 't7106-reset-unborn-branch.sh', + 't7107-reset-pathspec-file.sh', + 't7110-reset-merge.sh', + 't7111-reset-table.sh', + 't7112-reset-submodule.sh', + 't7113-post-index-change-hook.sh', + 't7201-co.sh', + 't7300-clean.sh', + 't7301-clean-interactive.sh', + 't7400-submodule-basic.sh', + 't7401-submodule-summary.sh', + 't7402-submodule-rebase.sh', + 't7403-submodule-sync.sh', + 't7406-submodule-update.sh', + 't7407-submodule-foreach.sh', + 't7408-submodule-reference.sh', + 't7409-submodule-detached-work-tree.sh', + 't7411-submodule-config.sh', + 't7412-submodule-absorbgitdirs.sh', + 't7413-submodule-is-active.sh', + 't7414-submodule-mistakes.sh', + 't7416-submodule-dash-url.sh', + 't7417-submodule-path-url.sh', + 't7418-submodule-sparse-gitmodules.sh', + 't7419-submodule-set-branch.sh', + 't7420-submodule-set-url.sh', + 't7421-submodule-summary-add.sh', + 't7422-submodule-output.sh', + 't7423-submodule-symlinks.sh', + 't7424-submodule-mixed-ref-formats.sh', + 't7450-bad-git-dotfiles.sh', + 't7500-commit-template-squash-signoff.sh', + 't7501-commit-basic-functionality.sh', + 't7502-commit-porcelain.sh', + 't7503-pre-commit-and-pre-merge-commit-hooks.sh', + 't7504-commit-msg-hook.sh', + 't7505-prepare-commit-msg-hook.sh', + 't7506-status-submodule.sh', + 't7507-commit-verbose.sh', + 't7508-status.sh', + 't7509-commit-authorship.sh', + 't7510-signed-commit.sh', + 't7511-status-index.sh', + 't7512-status-help.sh', + 't7513-interpret-trailers.sh', + 't7514-commit-patch.sh', + 't7515-status-symlinks.sh', + 't7516-commit-races.sh', + 't7517-per-repo-email.sh', + 't7518-ident-corner-cases.sh', + 't7519-status-fsmonitor.sh', + 't7520-ignored-hook-warning.sh', + 't7521-ignored-mode.sh', + 't7524-commit-summary.sh', + 't7525-status-rename.sh', + 't7526-commit-pathspec-file.sh', + 't7527-builtin-fsmonitor.sh', + 't7528-signed-commit-ssh.sh', + 't7600-merge.sh', + 't7601-merge-pull-config.sh', + 't7602-merge-octopus-many.sh', + 't7603-merge-reduce-heads.sh', + 't7604-merge-custom-message.sh', + 't7605-merge-resolve.sh', + 't7606-merge-custom.sh', + 't7607-merge-state.sh', + 't7608-merge-messages.sh', + 't7609-mergetool--lib.sh', + 't7610-mergetool.sh', + 't7611-merge-abort.sh', + 't7612-merge-verify-signatures.sh', + 't7614-merge-signoff.sh', + 't7615-diff-algo-with-mergy-operations.sh', + 't7700-repack.sh', + 't7701-repack-unpack-unreachable.sh', + 't7702-repack-cyclic-alternate.sh', + 't7703-repack-geometric.sh', + 't7704-repack-cruft.sh', + 't7800-difftool.sh', + 't7810-grep.sh', + 't7811-grep-open.sh', + 't7812-grep-icase-non-ascii.sh', + 't7813-grep-icase-iso.sh', + 't7814-grep-recurse-submodules.sh', + 't7815-grep-binary.sh', + 't7816-grep-binary-pattern.sh', + 't7817-grep-sparse-checkout.sh', + 't7900-maintenance.sh', + 't8001-annotate.sh', + 't8002-blame.sh', + 't8003-blame-corner-cases.sh', + 't8004-blame-with-conflicts.sh', + 't8005-blame-i18n.sh', + 't8006-blame-textconv.sh', + 't8007-cat-file-textconv.sh', + 't8008-blame-formats.sh', + 't8009-blame-vs-topicbranches.sh', + 't8010-cat-file-filters.sh', + 't8011-blame-split-file.sh', + 't8012-blame-colors.sh', + 't8013-blame-ignore-revs.sh', + 't8014-blame-ignore-fuzzy.sh', + 't9001-send-email.sh', + 't9002-column.sh', + 't9003-help-autocorrect.sh', + 't9100-git-svn-basic.sh', + 't9101-git-svn-props.sh', + 't9102-git-svn-deep-rmdir.sh', + 't9103-git-svn-tracked-directory-removed.sh', + 't9104-git-svn-follow-parent.sh', + 't9105-git-svn-commit-diff.sh', + 't9106-git-svn-commit-diff-clobber.sh', + 't9107-git-svn-migrate.sh', + 't9108-git-svn-glob.sh', + 't9109-git-svn-multi-glob.sh', + 't9110-git-svn-use-svm-props.sh', + 't9111-git-svn-use-svnsync-props.sh', + 't9112-git-svn-md5less-file.sh', + 't9113-git-svn-dcommit-new-file.sh', + 't9114-git-svn-dcommit-merge.sh', + 't9115-git-svn-dcommit-funky-renames.sh', + 't9116-git-svn-log.sh', + 't9117-git-svn-init-clone.sh', + 't9118-git-svn-funky-branch-names.sh', + 't9119-git-svn-info.sh', + 't9120-git-svn-clone-with-percent-escapes.sh', + 't9121-git-svn-fetch-renamed-dir.sh', + 't9122-git-svn-author.sh', + 't9123-git-svn-rebuild-with-rewriteroot.sh', + 't9124-git-svn-dcommit-auto-props.sh', + 't9125-git-svn-multi-glob-branch-names.sh', + 't9126-git-svn-follow-deleted-readded-directory.sh', + 't9127-git-svn-partial-rebuild.sh', + 't9128-git-svn-cmd-branch.sh', + 't9129-git-svn-i18n-commitencoding.sh', + 't9130-git-svn-authors-file.sh', + 't9131-git-svn-empty-symlink.sh', + 't9132-git-svn-broken-symlink.sh', + 't9133-git-svn-nested-git-repo.sh', + 't9134-git-svn-ignore-paths.sh', + 't9135-git-svn-moved-branch-empty-file.sh', + 't9136-git-svn-recreated-branch-empty-file.sh', + 't9137-git-svn-dcommit-clobber-series.sh', + 't9138-git-svn-authors-prog.sh', + 't9139-git-svn-non-utf8-commitencoding.sh', + 't9140-git-svn-reset.sh', + 't9141-git-svn-multiple-branches.sh', + 't9142-git-svn-shallow-clone.sh', + 't9143-git-svn-gc.sh', + 't9144-git-svn-old-rev_map.sh', + 't9145-git-svn-master-branch.sh', + 't9146-git-svn-empty-dirs.sh', + 't9147-git-svn-include-paths.sh', + 't9148-git-svn-propset.sh', + 't9150-svk-mergetickets.sh', + 't9151-svn-mergeinfo.sh', + 't9152-svn-empty-dirs-after-gc.sh', + 't9153-git-svn-rewrite-uuid.sh', + 't9154-git-svn-fancy-glob.sh', + 't9155-git-svn-fetch-deleted-tag.sh', + 't9156-git-svn-fetch-deleted-tag-2.sh', + 't9157-git-svn-fetch-merge.sh', + 't9158-git-svn-mergeinfo.sh', + 't9159-git-svn-no-parent-mergeinfo.sh', + 't9160-git-svn-preserve-empty-dirs.sh', + 't9161-git-svn-mergeinfo-push.sh', + 't9162-git-svn-dcommit-interactive.sh', + 't9163-git-svn-reset-clears-caches.sh', + 't9164-git-svn-dcommit-concurrent.sh', + 't9165-git-svn-fetch-merge-branch-of-branch.sh', + 't9166-git-svn-fetch-merge-branch-of-branch2.sh', + 't9167-git-svn-cmd-branch-subproject.sh', + 't9168-git-svn-partially-globbed-names.sh', + 't9169-git-svn-dcommit-crlf.sh', + 't9200-git-cvsexportcommit.sh', + 't9210-scalar.sh', + 't9211-scalar-clone.sh', + 't9300-fast-import.sh', + 't9301-fast-import-notes.sh', + 't9302-fast-import-unpack-limit.sh', + 't9303-fast-import-compression.sh', + 't9304-fast-import-marks.sh', + 't9350-fast-export.sh', + 't9351-fast-export-anonymize.sh', + 't9400-git-cvsserver-server.sh', + 't9401-git-cvsserver-crlf.sh', + 't9402-git-cvsserver-refs.sh', + 't9500-gitweb-standalone-no-errors.sh', + 't9501-gitweb-standalone-http-status.sh', + 't9502-gitweb-standalone-parse-output.sh', + 't9600-cvsimport.sh', + 't9601-cvsimport-vendor-branch.sh', + 't9602-cvsimport-branches-tags.sh', + 't9603-cvsimport-patchsets.sh', + 't9604-cvsimport-timestamps.sh', + 't9700-perl-git.sh', + 't9800-git-p4-basic.sh', + 't9801-git-p4-branch.sh', + 't9802-git-p4-filetype.sh', + 't9803-git-p4-shell-metachars.sh', + 't9804-git-p4-label.sh', + 't9805-git-p4-skip-submit-edit.sh', + 't9806-git-p4-options.sh', + 't9807-git-p4-submit.sh', + 't9808-git-p4-chdir.sh', + 't9809-git-p4-client-view.sh', + 't9810-git-p4-rcs.sh', + 't9811-git-p4-label-import.sh', + 't9812-git-p4-wildcards.sh', + 't9813-git-p4-preserve-users.sh', + 't9814-git-p4-rename.sh', + 't9815-git-p4-submit-fail.sh', + 't9816-git-p4-locked.sh', + 't9817-git-p4-exclude.sh', + 't9818-git-p4-block.sh', + 't9819-git-p4-case-folding.sh', + 't9820-git-p4-editor-handling.sh', + 't9821-git-p4-path-variations.sh', + 't9822-git-p4-path-encoding.sh', + 't9823-git-p4-mock-lfs.sh', + 't9824-git-p4-git-lfs.sh', + 't9825-git-p4-handle-utf16-without-bom.sh', + 't9826-git-p4-keep-empty-commits.sh', + 't9827-git-p4-change-filetype.sh', + 't9828-git-p4-map-user.sh', + 't9829-git-p4-jobs.sh', + 't9830-git-p4-symlink-dir.sh', + 't9831-git-p4-triggers.sh', + 't9832-unshelve.sh', + 't9833-errors.sh', + 't9834-git-p4-file-dir-bug.sh', + 't9835-git-p4-metadata-encoding-python2.sh', + 't9836-git-p4-metadata-encoding-python3.sh', + 't9850-shell.sh', + 't9901-git-web--browse.sh', + 't9902-completion.sh', + 't9903-bash-prompt.sh', +] + +# GIT_BUILD_DIR needs to be Unix-style without drive prefixes as it get added +# to the PATH variable. And given that drive prefixes contain a colon we'd +# otherwise end up with a broken PATH if we didn't convert it. +git_build_dir = meson.project_build_root() +if cygpath.found() + git_build_dir = run_command(cygpath, git_build_dir, check: true).stdout().strip() +endif + +test_environment = script_environment +test_environment.set('GIT_BUILD_DIR', git_build_dir) + +foreach integration_test : integration_tests + test(fs.stem(integration_test), shell, + args: [ integration_test ], + workdir: meson.current_source_dir(), + env: test_environment, + depends: test_dependencies + bin_wrappers, + timeout: 0, + ) +endforeach diff --git a/templates/hooks/meson.build b/templates/hooks/meson.build new file mode 100644 index 0000000000..ef85e10a16 --- /dev/null +++ b/templates/hooks/meson.build @@ -0,0 +1,26 @@ +hooks = [ + 'applypatch-msg.sample', + 'commit-msg.sample', + 'fsmonitor-watchman.sample', + 'post-update.sample', + 'pre-applypatch.sample', + 'pre-commit.sample', + 'pre-merge-commit.sample', + 'prepare-commit-msg.sample', + 'pre-push.sample', + 'pre-rebase.sample', + 'pre-receive.sample', + 'push-to-checkout.sample', + 'sendemail-validate.sample', + 'update.sample', +] + +foreach hook : hooks + configure_file( + input: hook, + output: hook, + configuration: template_config, + install: true, + install_dir: get_option('datadir') / 'git-core/templates/hooks', + ) +endforeach diff --git a/templates/info/meson.build b/templates/info/meson.build new file mode 100644 index 0000000000..026f231385 --- /dev/null +++ b/templates/info/meson.build @@ -0,0 +1,7 @@ +configure_file( + input: 'exclude', + output: 'exclude', + configuration: template_config, + install: true, + install_dir: get_option('datadir') / 'git-core/templates/info', +) diff --git a/templates/meson.build b/templates/meson.build new file mode 100644 index 0000000000..1faf9a44ce --- /dev/null +++ b/templates/meson.build @@ -0,0 +1,15 @@ +template_config = configuration_data() +template_config.set('PERL_PATH', perl.found() ? fs.as_posix(perl.full_path()) : '') +template_config.set('SHELL_PATH', fs.as_posix(shell.full_path())) +template_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) + +configure_file( + input: 'description', + output: 'description', + configuration: template_config, + install: true, + install_dir: get_option('datadir') / 'git-core/templates', +) + +subdir('hooks') +subdir('info') -- cgit v1.3 From 8525e928868757c2ebce3859dae0a9fd0f9ac9fd Mon Sep 17 00:00:00 2001 From: Alejandro Barreto Date: Mon, 9 Dec 2024 19:18:14 +0000 Subject: Document HOME environment variable Git documentation refers to $HOME and $XDG_CONFIG_HOME often, but does not specify how or where these values come from on Windows where neither is set by default. The new documentation reflects the behavior of setup_windows_environment() in compat/mingw.c. Signed-off-by: Alejandro Barreto Signed-off-by: M Hickford Signed-off-by: Junio C Hamano --- Documentation/git.txt | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Documentation') diff --git a/Documentation/git.txt b/Documentation/git.txt index d15a869762..47509c9e1a 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -477,6 +477,14 @@ their values the same way as Boolean valued configuration variables, e.g. Here are the variables: +System +~~~~~~~~~~~~~~~~~~ +`HOME`:: + Specifies the path to the user's home directory. On Windows, if + unset, Git will set a process environment variable equal to: + `$HOMEDRIVE$HOMEPATH` if both `$HOMEDRIVE` and `$HOMEPATH` exist; + otherwise `$USERPROFILE` if `$USERPROFILE` exists. + The Git Repository ~~~~~~~~~~~~~~~~~~ These environment variables apply to 'all' core Git commands. Nb: it -- cgit v1.3 From caacdb5dfd60540ecec30ec479f147f3c8167e11 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 10 Dec 2024 09:36:41 +0900 Subject: The fifteenth batch Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index b9d1b129cd..bf75cda275 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -21,6 +21,9 @@ UI, Workflows & Features * Drop support for older libcURL and Perl. + * End-user experience of "git mergetool" when the command errors out + has been improved. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -107,6 +110,14 @@ Performance, Internal Implementation, Development Support etc. * Built-in Git subcommands are supplied the repository object to work with; they learned to do the same when they invoke sub-subcommands. + * Drop support for ancient environments in various CI jobs. + + * Isolates the reftable subsystem from the rest of Git's codebase by + using fewer pieces of Git's infrastructure. + + * Optimize reading random references out of the reftable backend by + allowing reuse of iterator objects. + Fixes since v2.47 ----------------- @@ -204,6 +215,15 @@ Fixes since v2.47 * The sequencer failed to honor core.commentString in some places. + * Describe a case where an option value needs to be spelled as a + separate argument, i.e. "--opt val", not "--opt=val". + (merge 1bc1e94091 jc/doc-opt-tilde-expand later to maint). + + * Loosen overly strict ownership check introduced in the recent past, + to keep the promise "cloning a suspicious repository is a safe + first step to inspect it". + (merge 0ffb5a6bf1 bc/allow-upload-pack-from-other-people later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 77af53f56f aa/t7300-modernize later to maint). (merge dcd590a39d bf/t-readme-mention-reftable later to maint). -- cgit v1.3 From 2ccc89b0c16c51561da90d21cfbb4b58cc877bf6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 13 Dec 2024 07:33:05 -0800 Subject: The sixteenth batch Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index bf75cda275..802e9a96e5 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -24,6 +24,10 @@ UI, Workflows & Features * End-user experience of "git mergetool" when the command errors out has been improved. + * "git bundle --unbundle" and "git clone" running on a bundle file + both learned to trigger fsck over the new objects with configurable + fck check levels. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -118,6 +122,13 @@ Performance, Internal Implementation, Development Support etc. * Optimize reading random references out of the reftable backend by allowing reuse of iterator objects. + * Backport oss-fuzz tests for us to our codebase. + + * Introduce a new repository extension to prevent older Git versions + from mis-interpreting worktrees created with relative paths. + + * Yet another "pass the repository through the callchain" topic. + Fixes since v2.47 ----------------- @@ -224,8 +235,19 @@ Fixes since v2.47 first step to inspect it". (merge 0ffb5a6bf1 bc/allow-upload-pack-from-other-people later to maint). + * "git fast-import" learned to reject paths with ".." and "." as + their components to avoid creating invalid tree objects. + (merge 8cb4c6e62f en/fast-import-verify-path later to maint). + + * The --ancestry-path option is designed to be given a commit that is + on the path, which was not documented, which has been corrected. + (merge bc1a980759 kk/doc-ancestry-path later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 77af53f56f aa/t7300-modernize later to maint). (merge dcd590a39d bf/t-readme-mention-reftable later to maint). (merge 68e3c69efa kh/trailer-in-glossary later to maint). (merge 91f88f76e6 tb/boundary-traversal-fix later to maint). + (merge 168ebb7159 jc/doc-error-message-guidelines later to maint). + (merge 18693d7d65 kh/doc-bundle-typofix later to maint). + (merge e2f5d3b491 kh/doc-update-ref-grammofix later to maint). -- cgit v1.3 From f8043236c6c9cb9e943a87ab2e55e8e394796727 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 16 Dec 2024 14:11:21 +0000 Subject: range-diff: optionally include merge commits' diffs in the analysis The `git log` command already offers support for including diffs for merges, via the `--diff-merges=` option. Let's add corresponding support for `git range-diff`, too. This makes it more convenient to spot differences between commit ranges that contain merges. This is especially true in scenarios with non-trivial merges, i.e. merges introducing changes other than, or in addition to, what merge ORT would have produced. Merging a topic branch that changes a function signature into a branch that added a caller of that function, for example, would require the merge commit itself to adjust that caller to the modified signature. In my code reviews, I found the `--diff-merges=remerge` option particularly useful. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-range-diff.txt | 13 ++++++++++++- builtin/range-diff.c | 10 ++++++++++ range-diff.c | 15 +++++++++++---- range-diff.h | 1 + t/t3206-range-diff.sh | 16 ++++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.txt index fbdbe0befe..00c649b140 100644 --- a/Documentation/git-range-diff.txt +++ b/Documentation/git-range-diff.txt @@ -10,7 +10,7 @@ SYNOPSIS [verse] 'git range-diff' [--color=[]] [--no-color] [] [--no-dual-color] [--creation-factor=] - [--left-only | --right-only] + [--left-only | --right-only] [--diff-merges=] ( | ... | ) [[--] ...] @@ -81,6 +81,17 @@ to revert to color all lines according to the outer diff markers Suppress commits that are missing from the second specified range (or the "right range" when using the `...` format). +--diff-merges=:: + Instead of ignoring merge commits, generate diffs for them using the + corresponding `--diff-merges=` option of linkgit:git-log[1], + and include them in the comparison. ++ +Note: In the common case, the `remerge` mode will be the most natural one +to use, as it shows only the diff on top of what Git's merge machinery would +have produced. In other words, if a merge commit is the result of a +non-conflicting `git merge`, the `remerge` mode will represent it with an empty +diff. + --[no-]notes[=]:: This flag is passed to the `git log` program (see linkgit:git-log[1]) that generates the patches. diff --git a/builtin/range-diff.c b/builtin/range-diff.c index 1b33ab66a7..901de5d133 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -21,6 +21,7 @@ int cmd_range_diff(int argc, { struct diff_options diffopt = { NULL }; struct strvec other_arg = STRVEC_INIT; + struct strvec diff_merges_arg = STRVEC_INIT; struct range_diff_options range_diff_opts = { .creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT, .diffopt = &diffopt, @@ -36,6 +37,8 @@ int cmd_range_diff(int argc, OPT_PASSTHRU_ARGV(0, "notes", &other_arg, N_("notes"), N_("passed to 'git log'"), PARSE_OPT_OPTARG), + OPT_PASSTHRU_ARGV(0, "diff-merges", &diff_merges_arg, + N_("style"), N_("passed to 'git log'"), 0), OPT_BOOL(0, "left-only", &left_only, N_("only emit output related to the first range")), OPT_BOOL(0, "right-only", &right_only, @@ -62,6 +65,12 @@ int cmd_range_diff(int argc, if (!simple_color) diffopt.use_color = 1; + /* If `--diff-merges` was specified, imply `--merges` */ + if (diff_merges_arg.nr) { + range_diff_opts.include_merges = 1; + strvec_pushv(&other_arg, diff_merges_arg.v); + } + for (i = 0; i < argc; i++) if (!strcmp(argv[i], "--")) { dash_dash = i; @@ -155,6 +164,7 @@ int cmd_range_diff(int argc, res = show_range_diff(range1.buf, range2.buf, &range_diff_opts); strvec_clear(&other_arg); + strvec_clear(&diff_merges_arg); strbuf_release(&range1); strbuf_release(&range2); diff --git a/range-diff.c b/range-diff.c index 10885ba301..19673d47d9 100644 --- a/range-diff.c +++ b/range-diff.c @@ -38,7 +38,8 @@ struct patch_util { * as struct object_id (will need to be free()d). */ static int read_patches(const char *range, struct string_list *list, - const struct strvec *other_arg) + const struct strvec *other_arg, + unsigned int include_merges) { struct child_process cp = CHILD_PROCESS_INIT; struct strbuf buf = STRBUF_INIT, contents = STRBUF_INIT; @@ -49,7 +50,7 @@ static int read_patches(const char *range, struct string_list *list, size_t size; int ret = -1; - strvec_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges", + strvec_pushl(&cp.args, "log", "--no-color", "-p", "--reverse", "--date-order", "--decorate=no", "--no-prefix", "--submodule=short", /* @@ -64,6 +65,8 @@ static int read_patches(const char *range, struct string_list *list, "--pretty=medium", "--show-notes-by-default", NULL); + if (!include_merges) + strvec_push(&cp.args, "--no-merges"); strvec_push(&cp.args, range); if (other_arg) strvec_pushv(&cp.args, other_arg->v); @@ -96,11 +99,14 @@ static int read_patches(const char *range, struct string_list *list, } if (skip_prefix(line, "commit ", &p)) { + char *q; if (util) { string_list_append(list, buf.buf)->util = util; strbuf_reset(&buf); } CALLOC_ARRAY(util, 1); + if (include_merges && (q = strstr(p, " (from "))) + *q = '\0'; if (repo_get_oid(the_repository, p, &util->oid)) { error(_("could not parse commit '%s'"), p); FREE_AND_NULL(util); @@ -571,13 +577,14 @@ int show_range_diff(const char *range1, const char *range2, struct string_list branch1 = STRING_LIST_INIT_DUP; struct string_list branch2 = STRING_LIST_INIT_DUP; + unsigned int include_merges = range_diff_opts->include_merges; if (range_diff_opts->left_only && range_diff_opts->right_only) res = error(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only"); - if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg)) + if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg, include_merges)) res = error(_("could not parse log for '%s'"), range1); - if (!res && read_patches(range2, &branch2, range_diff_opts->other_arg)) + if (!res && read_patches(range2, &branch2, range_diff_opts->other_arg, include_merges)) res = error(_("could not parse log for '%s'"), range2); if (!res) { diff --git a/range-diff.h b/range-diff.h index 2f69f6a434..cd85000b5a 100644 --- a/range-diff.h +++ b/range-diff.h @@ -16,6 +16,7 @@ struct range_diff_options { int creation_factor; unsigned dual_color:1; unsigned left_only:1, right_only:1; + unsigned include_merges:1; const struct diff_options *diffopt; /* may be NULL */ const struct strvec *other_arg; /* may be NULL */ }; diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index 86010931ab..c18a3fdab8 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -909,4 +909,20 @@ test_expect_success 'submodule changes are shown irrespective of diff.submodule' test_cmp expect actual ' +test_expect_success '--diff-merges' ' + renamed_oid=$(git rev-parse --short renamed-file) && + tree=$(git merge-tree unmodified renamed-file) && + clean=$(git commit-tree -m merge -p unmodified -p renamed-file $tree) && + clean_oid=$(git rev-parse --short $clean) && + conflict=$(git commit-tree -m merge -p unmodified -p renamed-file^ $tree) && + conflict_oid=$(git rev-parse --short $conflict) && + + git range-diff --diff-merges=1 $clean...$conflict >actual && + cat >expect <<-EOF && + 1: $renamed_oid < -: ------- s/12/B/ + 2: $clean_oid = 1: $conflict_oid merge + EOF + test_cmp expect actual +' + test_done -- cgit v1.3 From 4538338c7edb13a5e818abcfa5739f16ad3dda0c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 16 Dec 2024 14:11:22 +0000 Subject: range-diff: introduce the convenience option `--remerge-diff` Just like `git log`, now also `git range-diff` has that option as a shortcut for the common operation that would otherwise require the quite unwieldy (if theoretically "more correct") `--diff-mode=remerge` option. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-range-diff.txt | 4 ++++ builtin/range-diff.c | 2 ++ 2 files changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.txt index 00c649b140..db0e4279b5 100644 --- a/Documentation/git-range-diff.txt +++ b/Documentation/git-range-diff.txt @@ -11,6 +11,7 @@ SYNOPSIS 'git range-diff' [--color=[]] [--no-color] [] [--no-dual-color] [--creation-factor=] [--left-only | --right-only] [--diff-merges=] + [--remerge-diff] ( | ... | ) [[--] ...] @@ -92,6 +93,9 @@ have produced. In other words, if a merge commit is the result of a non-conflicting `git merge`, the `remerge` mode will represent it with an empty diff. +--remerge-diff:: + Convenience option, equivalent to `--diff-merges=remerge`. + --[no-]notes[=]:: This flag is passed to the `git log` program (see linkgit:git-log[1]) that generates the patches. diff --git a/builtin/range-diff.c b/builtin/range-diff.c index 901de5d133..2452654347 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -39,6 +39,8 @@ int cmd_range_diff(int argc, PARSE_OPT_OPTARG), OPT_PASSTHRU_ARGV(0, "diff-merges", &diff_merges_arg, N_("style"), N_("passed to 'git log'"), 0), + OPT_PASSTHRU_ARGV(0, "remerge-diff", &diff_merges_arg, NULL, + N_("passed to 'git log'"), PARSE_OPT_NOARG), OPT_BOOL(0, "left-only", &left_only, N_("only emit output related to the first range")), OPT_BOOL(0, "right-only", &right_only, -- cgit v1.3 From 063bcebf0c917140ca0e705cbe0fdea127e90086 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 16 Dec 2024 08:54:04 -0800 Subject: Git 2.48-rc0 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 22 ++++++++++++++++++++++ GIT-VERSION-GEN | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index 802e9a96e5..dc11ce58be 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -129,6 +129,11 @@ Performance, Internal Implementation, Development Support etc. * Yet another "pass the repository through the callchain" topic. + * "git describe" learned to stop digging the history needlessly + deeper. + + * Build procedure update plus introduction of Meson based builds. + Fixes since v2.47 ----------------- @@ -243,6 +248,23 @@ Fixes since v2.47 on the path, which was not documented, which has been corrected. (merge bc1a980759 kk/doc-ancestry-path later to maint). + + * "git tag" has been taught to refuse to create refs/tags/HEAD + as such a tag will be confusing in the context of UI provided by + the Git Porcelain commands. + (merge bbd445d5ef jc/forbid-head-as-tagname later to maint). + + * The advice messages now tell the newer 'git config set' command to + set the advice.token configuration variable to squelch a message. + (merge 6c397d0104 bf/explicit-config-set-in-advice-messages later to maint). + + * The syntax ":/" to name the latest commit with the matching + text was broken with a recent change, which has been corrected. + (merge 0ff919e87a ps/commit-with-message-syntax-fix later to maint). + + * Fix performance regression of a recent "fatten promisor pack with + local objects" protection against an unwanted gc. + * Other code cleanup, docfix, build fix, etc. (merge 77af53f56f aa/t7300-modernize later to maint). (merge dcd590a39d bf/t-readme-mention-reftable later to maint). diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index b4687784c1..de0e63bdfb 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,6 +1,6 @@ #!/bin/sh -DEF_VER=v2.47.GIT +DEF_VER=v2.48.0-rc0 LF=' ' -- cgit v1.3 From 246cebe3205694ce19eceaa795d20f24ba762c49 Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Mon, 16 Dec 2024 17:44:33 +0100 Subject: refs: add support for migrating reflogs The `git refs migrate` command was introduced in 25a0023f28 (builtin/refs: new command to migrate ref storage formats, 2024-06-06) to support migrating from one reference backend to another. One limitation of the command was that it didn't support migrating repositories which contained reflogs. A previous commit, added support for adding reflog updates in ref transactions. Using the added functionality bake in reflog support for `git refs migrate`. To ensure that the order of the reflogs is maintained during the migration, we add the index for each reflog update as we iterate over the reflogs from the old reference backend. This is to ensure that the order is maintained in the new backend. Helped-by: Patrick Steinhardt Signed-off-by: Karthik Nayak Signed-off-by: Junio C Hamano --- Documentation/git-refs.txt | 2 - refs.c | 92 ++++++++++++++++++++++++++++++++-------------- t/t1460-refs-migrate.sh | 73 +++++++++++++++++++++++++----------- 3 files changed, 115 insertions(+), 52 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-refs.txt b/Documentation/git-refs.txt index ce31f93061..9829984b0a 100644 --- a/Documentation/git-refs.txt +++ b/Documentation/git-refs.txt @@ -57,8 +57,6 @@ KNOWN LIMITATIONS The ref format migration has several known limitations in its current form: -* It is not possible to migrate repositories that have reflogs. - * It is not possible to migrate repositories that have worktrees. * There is no way to block concurrent writes to the repository during an diff --git a/refs.c b/refs.c index 8b3882cff1..5d541ddc41 100644 --- a/refs.c +++ b/refs.c @@ -30,6 +30,7 @@ #include "date.h" #include "commit.h" #include "wildmatch.h" +#include "ident.h" /* * List of all available backends @@ -2673,6 +2674,7 @@ struct migration_data { struct ref_store *old_refs; struct ref_transaction *transaction; struct strbuf *errbuf; + struct strbuf sb; }; static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, @@ -2705,6 +2707,52 @@ done: return ret; } +struct reflog_migration_data { + unsigned int index; + const char *refname; + struct ref_store *old_refs; + struct ref_transaction *transaction; + struct strbuf *errbuf; + struct strbuf *sb; +}; + +static int migrate_one_reflog_entry(struct object_id *old_oid, + struct object_id *new_oid, + const char *committer, + timestamp_t timestamp, int tz, + const char *msg, void *cb_data) +{ + struct reflog_migration_data *data = cb_data; + const char *date; + int ret; + + date = show_date(timestamp, tz, DATE_MODE(NORMAL)); + strbuf_reset(data->sb); + /* committer contains name and email */ + strbuf_addstr(data->sb, fmt_ident("", committer, WANT_BLANK_IDENT, date, 0)); + + ret = ref_transaction_update_reflog(data->transaction, data->refname, + new_oid, old_oid, data->sb->buf, + REF_HAVE_NEW | REF_HAVE_OLD, msg, + data->index++, data->errbuf); + return ret; +} + +static int migrate_one_reflog(const char *refname, void *cb_data) +{ + struct migration_data *migration_data = cb_data; + struct reflog_migration_data data = { + .refname = refname, + .old_refs = migration_data->old_refs, + .transaction = migration_data->transaction, + .errbuf = migration_data->errbuf, + .sb = &migration_data->sb, + }; + + return refs_for_each_reflog_ent(migration_data->old_refs, refname, + migrate_one_reflog_entry, &data); +} + static int move_files(const char *from_path, const char *to_path, struct strbuf *errbuf) { struct strbuf from_buf = STRBUF_INIT, to_buf = STRBUF_INIT; @@ -2771,13 +2819,6 @@ done: return ret; } -static int count_reflogs(const char *reflog UNUSED, void *payload) -{ - size_t *reflog_count = payload; - (*reflog_count)++; - return 0; -} - static int has_worktrees(void) { struct worktree **worktrees = get_worktrees(); @@ -2802,8 +2843,9 @@ int repo_migrate_ref_storage_format(struct repository *repo, struct ref_store *old_refs = NULL, *new_refs = NULL; struct ref_transaction *transaction = NULL; struct strbuf new_gitdir = STRBUF_INIT; - struct migration_data data; - size_t reflog_count = 0; + struct migration_data data = { + .sb = STRBUF_INIT, + }; int did_migrate_refs = 0; int ret; @@ -2815,21 +2857,6 @@ int repo_migrate_ref_storage_format(struct repository *repo, old_refs = get_main_ref_store(repo); - /* - * We do not have any interfaces that would allow us to write many - * reflog entries. Once we have them we can remove this restriction. - */ - if (refs_for_each_reflog(old_refs, count_reflogs, &reflog_count) < 0) { - strbuf_addstr(errbuf, "cannot count reflogs"); - ret = -1; - goto done; - } - if (reflog_count) { - strbuf_addstr(errbuf, "migrating reflogs is not supported yet"); - ret = -1; - goto done; - } - /* * Worktrees complicate the migration because every worktree has a * separate ref storage. While it should be feasible to implement, this @@ -2855,17 +2882,21 @@ int repo_migrate_ref_storage_format(struct repository *repo, * This operation is safe as we do not yet modify the main * repository. * - * 3. If we're in dry-run mode then we are done and can hand over the + * 3. Enumerate all reflogs and write them into the new ref storage. + * This operation is safe as we do not yet modify the main + * repository. + * + * 4. If we're in dry-run mode then we are done and can hand over the * directory to the caller for inspection. If not, we now start * with the destructive part. * - * 4. Delete the old ref storage from disk. As we have a copy of refs + * 5. Delete the old ref storage from disk. As we have a copy of refs * in the new ref storage it's okay(ish) if we now get interrupted * as there is an equivalent copy of all refs available. * - * 5. Move the new ref storage files into place. + * 6. Move the new ref storage files into place. * - * 6. Change the repository format to the new ref format. + * 7. Change the repository format to the new ref format. */ strbuf_addf(&new_gitdir, "%s/%s", old_refs->gitdir, "ref_migration.XXXXXX"); if (!mkdtemp(new_gitdir.buf)) { @@ -2907,6 +2938,10 @@ int repo_migrate_ref_storage_format(struct repository *repo, if (ret < 0) goto done; + ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data); + if (ret < 0) + goto done; + ret = ref_transaction_commit(transaction, errbuf); if (ret < 0) goto done; @@ -2982,6 +3017,7 @@ done: } ref_transaction_free(transaction); strbuf_release(&new_gitdir); + strbuf_release(&data.sb); return ret; } diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh index 1bfff3a7af..f59bc4860f 100755 --- a/t/t1460-refs-migrate.sh +++ b/t/t1460-refs-migrate.sh @@ -7,23 +7,44 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +# Migrate the provided repository from one format to the other and +# verify that the references and logs are migrated over correctly. +# Usage: test_migration +# is the relative path to the repo to be migrated. +# is the ref format to be migrated to. +# (true or false) whether to skip reflog verification. test_migration () { - git -C "$1" for-each-ref --include-root-refs \ + repo=$1 && + format=$2 && + skip_reflog_verify=${3:-false} && + git -C "$repo" for-each-ref --include-root-refs \ --format='%(refname) %(objectname) %(symref)' >expect && - git -C "$1" refs migrate --ref-format="$2" && - git -C "$1" for-each-ref --include-root-refs \ + if ! $skip_reflog_verify + then + git -C "$repo" reflog --all >expect_logs && + git -C "$repo" reflog list >expect_log_list + fi && + + git -C "$repo" refs migrate --ref-format="$2" && + + git -C "$repo" for-each-ref --include-root-refs \ --format='%(refname) %(objectname) %(symref)' >actual && test_cmp expect actual && + if ! $skip_reflog_verify + then + git -C "$repo" reflog --all >actual_logs && + git -C "$repo" reflog list >actual_log_list && + test_cmp expect_logs actual_logs && + test_cmp expect_log_list actual_log_list + fi && - git -C "$1" rev-parse --show-ref-format >actual && - echo "$2" >expect && + git -C "$repo" rev-parse --show-ref-format >actual && + echo "$format" >expect && test_cmp expect actual } test_expect_success 'setup' ' - rm -rf .git && - # The migration does not yet support reflogs. - git config --global core.logAllRefUpdates false + rm -rf .git ' test_expect_success "superfluous arguments" ' @@ -78,19 +99,6 @@ do test_cmp expect err ' - test_expect_success "$from_format -> $to_format: migration with reflog fails" ' - test_when_finished "rm -rf repo" && - git init --ref-format=$from_format repo && - test_config -C repo core.logAllRefUpdates true && - test_commit -C repo logged && - test_must_fail git -C repo refs migrate \ - --ref-format=$to_format 2>err && - cat >expect <<-EOF && - error: migrating reflogs is not supported yet - EOF - test_cmp expect err - ' - test_expect_success "$from_format -> $to_format: migration with worktree fails" ' test_when_finished "rm -rf repo" && git init --ref-format=$from_format repo && @@ -141,7 +149,7 @@ do test_commit -C repo initial && test-tool -C repo ref-store main update-ref "" refs/heads/broken \ "$(test_oid 001)" "$ZERO_OID" REF_SKIP_CREATE_REFLOG,REF_SKIP_OID_VERIFICATION && - test_migration repo "$to_format" && + test_migration repo "$to_format" true && test_oid 001 >expect && git -C repo rev-parse refs/heads/broken >actual && test_cmp expect actual @@ -195,6 +203,27 @@ do git -C repo rev-parse --show-ref-format >actual && test_cmp expect actual ' + + test_expect_success "$from_format -> $to_format: reflogs of symrefs with target deleted" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo branch branch-1 HEAD && + git -C repo symbolic-ref refs/heads/symref refs/heads/branch-1 && + cat >input <<-EOF && + delete refs/heads/branch-1 + EOF + git -C repo update-ref --stdin $to_format: reflogs order is retained" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit --date "100005000 +0700" --no-tag -C repo initial && + test_commit --date "100003000 +0700" --no-tag -C repo second && + test_migration repo "$to_format" + ' done done -- cgit v1.3 From a803b1e17160b51e3a0b2a7766955753fea22bf5 Mon Sep 17 00:00:00 2001 From: Kyle Lippincott Date: Wed, 18 Dec 2024 00:57:02 +0000 Subject: doc: remove extra quotes in generated docs Commit a38edab7c8 (Makefile: generate doc versions via GIT-VERSION-GEN, 2024-12-06) moved these variables from the Makefile to asciidoc.conf.in. When doing so, some extraneous quotes were added; these are visible in the generated .xml files, at least, and possibly in other locations: --- a/tmp/orig-git-bisect.xml +++ b/Documentation/git-bisect.xml @@ -5,14 +5,14 @@ git-bisect(1) - 2024-12-06 -2024-12-06 + '2024-12-06'^M +'2024-12-06'^M git-bisect 1 -Git 2.47.1.409.g9bb10d27e7 -Git Manual +'Git 2.47.1.410.ga38edab7c8'^M +'Git Manual'^M git-bisect Signed-off-by: Kyle Lippincott Signed-off-by: Junio C Hamano --- Documentation/asciidoc.conf.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/asciidoc.conf.in b/Documentation/asciidoc.conf.in index dbe36a52ea..b89bccf230 100644 --- a/Documentation/asciidoc.conf.in +++ b/Documentation/asciidoc.conf.in @@ -21,9 +21,9 @@ tilde=~ apostrophe=' backtick=` litdd=-- -manmanual='Git Manual' -mansource='Git @GIT_VERSION@' -revdate='@GIT_DATE@' +manmanual=Git Manual +mansource=Git @GIT_VERSION@ +revdate=@GIT_DATE@ ifdef::backend-docbook[] [linkgit-inlinemacro] -- cgit v1.3 From ff795a5c5ed2e2d07c688c217a615d89e3f5733b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 19 Dec 2024 10:57:38 -0800 Subject: Finishing touches before 2.48-rc1 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index dc11ce58be..cc752d5466 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -28,6 +28,13 @@ UI, Workflows & Features both learned to trigger fsck over the new objects with configurable fck check levels. + * When "git fetch $remote" notices that refs/remotes/$remote/HEAD is + missing and discovers what branch the other side points with its + HEAD, refs/remotes/$remote/HEAD is updated to point to it. + + * "git fetch" honors "remote..followRemoteHEAD" settings to + tweak the remote-tracking HEAD in "refs/remotes//HEAD". + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -265,6 +272,14 @@ Fixes since v2.47 * Fix performance regression of a recent "fatten promisor pack with local objects" protection against an unwanted gc. + * "git log -p --remerge-diff --reverse" was completely broken. + (merge f94bfa1516 js/log-remerge-keep-ancestry later to maint). + + * "git bundle create" with an annotated tag on the positive end of + the revision range had a workaround code for older limitation in + the revision walker, which has become unnecessary. + (merge dd1072dfa8 tc/bundle-with-tag-remove-workaround later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 77af53f56f aa/t7300-modernize later to maint). (merge dcd590a39d bf/t-readme-mention-reftable later to maint). @@ -273,3 +288,4 @@ Fixes since v2.47 (merge 168ebb7159 jc/doc-error-message-guidelines later to maint). (merge 18693d7d65 kh/doc-bundle-typofix later to maint). (merge e2f5d3b491 kh/doc-update-ref-grammofix later to maint). + (merge 8525e92886 mh/doc-windows-home-env later to maint). -- cgit v1.3 From 1b0882cba2f17ae126cba42bf58354f9290089d9 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 20 Dec 2024 20:44:21 +0100 Subject: Makefile: stop including "GIT-VERSION-FILE" in docs We include "GIT-VERSION-FILE" in our docs Makefile, but don't actually use the "GIT_VERSION" variable that it provides. This is a leftover from the conversion to make "GIT-VERSION-GEN" generate version information in-place by substituting placeholders in 4838deab65 (Makefile: refactor GIT-VERSION-GEN to be reusable, 2024-12-06) and subsequent commits, where all usages of the variable were removed. Stop including the file. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 7 ------- 1 file changed, 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index 3392e1ce7e..44c9e9369a 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -276,13 +276,6 @@ install-pdf: pdf install-html: html '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) -../GIT-VERSION-FILE: FORCE - $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE - -ifneq ($(filter-out lint-docs clean,$(MAKECMDGOALS)),) --include ../GIT-VERSION-FILE -endif - mergetools_txt = mergetools-diff.txt mergetools-merge.txt # -- cgit v1.3 From b329f2eb002a53f2283b45de2ba5884f7b8cd5ba Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 20 Dec 2024 20:44:22 +0100 Subject: Makefile: drop unneeded indirection for GIT-VERSION-GEN outputs Some of the callsites of GIT-VERSION-GEN generate the target file with a "+" suffix first and then move the file into place when the new contents are different compared to the old contents. This allows us to avoid a needless rebuild by not updating timestamps of the target file when its contents will remain unchanged anyway. In fact though, this exact logic is already handled in GIT-VERSION-GEN, so doing this manually is pointless. This is a leftover from an earlier version of 4838deab65 (Makefile: refactor GIT-VERSION-GEN to be reusable, 2024-12-06), where the script didn't handle that logic for us. Drop the needless indirection. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 6 ++---- Makefile | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index 44c9e9369a..1a398d0dc3 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -211,12 +211,10 @@ XMLTO_EXTRA += --skip-validation XMLTO_EXTRA += -x manpage.xsl asciidoctor-extensions.rb: asciidoctor-extensions.rb.in FORCE - $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@+ - @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi + $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@ else asciidoc.conf: asciidoc.conf.in FORCE - $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@+ - @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi + $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@ endif ASCIIDOC_DEPS += docinfo.html diff --git a/Makefile b/Makefile index c4b9d2801a..fab398e885 100644 --- a/Makefile +++ b/Makefile @@ -2509,8 +2509,7 @@ pager.sp pager.s pager.o: EXTRA_CPPFLAGS = \ -DPAGER_ENV='$(PAGER_ENV_CQ_SQ)' version-def.h: version-def.h.in GIT-VERSION-GEN GIT-VERSION-FILE GIT-USER-AGENT - $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" $< $@+ - @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi + $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" $< $@ version.sp version.s version.o: version-def.h @@ -2551,8 +2550,7 @@ $(SCRIPT_SH_GEN) $(SCRIPT_LIB) : % : %.sh generate-script.sh GIT-BUILD-OPTIONS G mv $@+ $@ git.rc: git.rc.in GIT-VERSION-GEN GIT-VERSION-FILE - $(QUIET_GEN)$(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" $< $@+ - @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi + $(QUIET_GEN)$(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" $< $@ git.res: git.rc GIT-PREFIX $(QUIET_RC)$(RC) -i $< -o $@ -- cgit v1.3 From 114494ae2c6f473dd9c9745a9b4fc6c55b70f2e8 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 20 Dec 2024 20:44:23 +0100 Subject: Makefile: introduce template for GIT-VERSION-GEN Introduce a new template to call GIT-VERSION-GEN. This will allow us to iterate on how exactly the script is called in subsequent commits without having to adapt all call sites every time. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 4 ++-- Makefile | 6 +++--- shared.mak | 8 ++++++++ 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index 1a398d0dc3..ff30ab6c42 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -211,10 +211,10 @@ XMLTO_EXTRA += --skip-validation XMLTO_EXTRA += -x manpage.xsl asciidoctor-extensions.rb: asciidoctor-extensions.rb.in FORCE - $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@ + $(QUIET_GEN)$(call version_gen,"$(shell pwd)/..",$<,$@) else asciidoc.conf: asciidoc.conf.in FORCE - $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ../GIT-VERSION-GEN "$(shell pwd)/.." $< $@ + $(QUIET_GEN)$(call version_gen,"$(shell pwd)/..",$<,$@) endif ASCIIDOC_DEPS += docinfo.html diff --git a/Makefile b/Makefile index fab398e885..c6973a720a 100644 --- a/Makefile +++ b/Makefile @@ -593,7 +593,7 @@ include shared.mak GIT-VERSION-FILE: FORCE @OLD=$$(cat $@ 2>/dev/null || :) && \ - $(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" GIT-VERSION-FILE.in $@ && \ + $(call version_gen,"$(shell pwd)",GIT-VERSION-FILE.in,$@) && \ NEW=$$(cat $@ 2>/dev/null || :) && \ if test "$$OLD" != "$$NEW"; then echo "$$NEW" >&2; fi -include GIT-VERSION-FILE @@ -2509,7 +2509,7 @@ pager.sp pager.s pager.o: EXTRA_CPPFLAGS = \ -DPAGER_ENV='$(PAGER_ENV_CQ_SQ)' version-def.h: version-def.h.in GIT-VERSION-GEN GIT-VERSION-FILE GIT-USER-AGENT - $(QUIET_GEN)GIT_USER_AGENT="$(GIT_USER_AGENT)" $(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" $< $@ + $(QUIET_GEN)$(call version_gen,"$(shell pwd)",$<,$@) version.sp version.s version.o: version-def.h @@ -2550,7 +2550,7 @@ $(SCRIPT_SH_GEN) $(SCRIPT_LIB) : % : %.sh generate-script.sh GIT-BUILD-OPTIONS G mv $@+ $@ git.rc: git.rc.in GIT-VERSION-GEN GIT-VERSION-FILE - $(QUIET_GEN)$(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" $< $@ + $(QUIET_GEN)$(call version_gen,"$(shell pwd)",$<,$@) git.res: git.rc GIT-PREFIX $(QUIET_RC)$(RC) -i $< -o $@ diff --git a/shared.mak b/shared.mak index 29bebd30d8..b23c5505c9 100644 --- a/shared.mak +++ b/shared.mak @@ -116,3 +116,11 @@ endef define libpath_template -L$(1) $(if $(filter-out -L,$(CC_LD_DYNPATH)),$(CC_LD_DYNPATH)$(1)) endef + +# Populate build information into a file via GIT-VERSION-GEN. Requires the +# absolute path to the root source directory as well as input and output files +# as arguments, in that order. +define version_gen +GIT_USER_AGENT="$(GIT_USER_AGENT)" \ +$(SHELL_PATH) "$(1)/GIT-VERSION-GEN" "$(1)" "$(2)" "$(3)" +endef -- cgit v1.3 From 992bc5618f2879a8d7f00a60489e78c48e661820 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 20 Dec 2024 20:44:24 +0100 Subject: GIT-VERSION-GEN: fix overriding GIT_VERSION GIT-VERSION-GEN tries to derive the version that Git is being built from via multiple different sources in the following order: 1. A file called "version" in the source tree's root directory, if it exists. 2. The current commit in case Git is built from a Git repository. 3. Otherwise, we use a fallback version stored in a variable which is bumped whenever a new Git version is getting tagged. It used to be possible to override the version by overriding the `GIT_VERSION` Makefile variable (e.g. `make GIT_VERSION=foo`). This worked somewhat by chance, only: `GIT-VERSION-GEN` would write the actual Git version into `GIT-VERSION-FILE`, not the overridden value, but when including the file into our Makefile we would not override the `GIT_VERSION` variable because it has already been set by the user. And because our Makefile used the variable to propagate the version to our build tools instead of using `GIT-VERSION-FILE` the resulting build artifacts used the overridden version. But that subtle mechanism broke with 4838deab65 (Makefile: refactor GIT-VERSION-GEN to be reusable, 2024-12-06) and subsequent commits because the version information is not propagated via the Makefile variable anymore, but instead via the files that `GIT-VERSION-GEN` started to write. And as the script never knew about the `GIT_VERSION` environment variable in the first place it uses one of the values listed above instead of the overridden value. Fix this issue by making `GIT-VERSION-GEN` handle the case where `GIT_VERSION` has been set via the environment. Note that this requires us to introduce a new GIT_VERSION_OVERRIDE variable that stores a potential user-provided value, either via the environment or via "config.mak". Ideally we wouldn't need it and could just continue to use GIT_VERSION for this. But unfortunately, Makefiles will first include all sub-Makefiles before figuring out whether it needs to re-make any of them [1]. Consequently, if there already is a GIT-VERSION-FILE, we would have slurped in its value of GIT_VERSION before we call GIT-VERSION-GEN, and because GIT-VERSION-GEN now uses that value as an override it would mean that the first generated value for GIT_VERSION will remain unchanged. Furthermore we have to move the include for "GIT-VERSION-FILE" after the includes for "config.mak" and related so that GIT_VERSION_OVERRIDE can be set to the value provided by "config.mak". [1]: https://www.gnu.org/software/make/manual/html_node/Remaking-Makefiles.html Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 4 ++++ GIT-VERSION-GEN | 48 ++++++++++++++++++++++++++---------------------- Makefile | 19 ++++++++++++------- shared.mak | 1 + 4 files changed, 43 insertions(+), 29 deletions(-) (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index ff30ab6c42..a89823e1d1 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -181,6 +181,10 @@ endif -include ../config.mak.autogen -include ../config.mak +# Set GIT_VERSION_OVERRIDE such that version_gen knows to substitute +# GIT_VERSION in case it was set by the user. +GIT_VERSION_OVERRIDE := $(GIT_VERSION) + ifndef NO_MAN_BOLD_LITERAL XMLTO_EXTRA += -m manpage-bold-literal.xsl endif diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index b4687784c1..2fee5e7e80 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -27,31 +27,35 @@ fi GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.." export GIT_CEILING_DIRECTORIES -# First see if there is a version file (included in release tarballs), -# then try git-describe, then default. -if test -f "$SOURCE_DIR"/version +if test -z "$GIT_VERSION" then - VN=$(cat "$SOURCE_DIR"/version) || VN="$DEF_VER" -elif { - test -d "$SOURCE_DIR/.git" || - test -d "${GIT_DIR:-.git}" || - test -f "$SOURCE_DIR"/.git; - } && - VN=$(git -C "$SOURCE_DIR" describe --match "v[0-9]*" HEAD 2>/dev/null) && - case "$VN" in - *$LF*) (exit 1) ;; - v[0-9]*) - git -C "$SOURCE_DIR" update-index -q --refresh - test -z "$(git -C "$SOURCE_DIR" diff-index --name-only HEAD --)" || - VN="$VN-dirty" ;; - esac -then - VN=$(echo "$VN" | sed -e 's/-/./g'); -else - VN="$DEF_VER" + # First see if there is a version file (included in release tarballs), + # then try git-describe, then default. + if test -f "$SOURCE_DIR"/version + then + VN=$(cat "$SOURCE_DIR"/version) || VN="$DEF_VER" + elif { + test -d "$SOURCE_DIR/.git" || + test -d "${GIT_DIR:-.git}" || + test -f "$SOURCE_DIR"/.git; + } && + VN=$(git -C "$SOURCE_DIR" describe --match "v[0-9]*" HEAD 2>/dev/null) && + case "$VN" in + *$LF*) (exit 1) ;; + v[0-9]*) + git -C "$SOURCE_DIR" update-index -q --refresh + test -z "$(git -C "$SOURCE_DIR" diff-index --name-only HEAD --)" || + VN="$VN-dirty" ;; + esac + then + VN=$(echo "$VN" | sed -e 's/-/./g'); + else + VN="$DEF_VER" + fi + + GIT_VERSION=$(expr "$VN" : v*'\(.*\)') fi -GIT_VERSION=$(expr "$VN" : v*'\(.*\)') GIT_BUILT_FROM_COMMIT=$(git -C "$SOURCE_DIR" rev-parse -q --verify HEAD 2>/dev/null) GIT_DATE=$(git -C "$SOURCE_DIR" show --quiet --format='%as' 2>/dev/null) if test -z "$GIT_USER_AGENT" diff --git a/Makefile b/Makefile index c6973a720a..5e14da0ae6 100644 --- a/Makefile +++ b/Makefile @@ -591,13 +591,6 @@ include shared.mak # # Disable -pedantic compilation. -GIT-VERSION-FILE: FORCE - @OLD=$$(cat $@ 2>/dev/null || :) && \ - $(call version_gen,"$(shell pwd)",GIT-VERSION-FILE.in,$@) && \ - NEW=$$(cat $@ 2>/dev/null || :) && \ - if test "$$OLD" != "$$NEW"; then echo "$$NEW" >&2; fi --include GIT-VERSION-FILE - # Set our default configuration. # # Among the variables below, these: @@ -1465,6 +1458,18 @@ ifdef DEVELOPER include config.mak.dev endif +GIT-VERSION-FILE: FORCE + @OLD=$$(cat $@ 2>/dev/null || :) && \ + $(call version_gen,"$(shell pwd)",GIT-VERSION-FILE.in,$@) && \ + NEW=$$(cat $@ 2>/dev/null || :) && \ + if test "$$OLD" != "$$NEW"; then echo "$$NEW" >&2; fi + +# We need to set GIT_VERSION_OVERRIDE before including the version file as +# otherwise any user-provided value for GIT_VERSION would have been overridden +# already. +GIT_VERSION_OVERRIDE := $(GIT_VERSION) +-include GIT-VERSION-FILE + # what 'all' will build and 'install' will install in gitexecdir, # excluding programs for built-in commands ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) diff --git a/shared.mak b/shared.mak index b23c5505c9..a66f46969e 100644 --- a/shared.mak +++ b/shared.mak @@ -122,5 +122,6 @@ endef # as arguments, in that order. define version_gen GIT_USER_AGENT="$(GIT_USER_AGENT)" \ +GIT_VERSION="$(GIT_VERSION_OVERRIDE)" \ $(SHELL_PATH) "$(1)/GIT-VERSION-GEN" "$(1)" "$(2)" "$(3)" endef -- cgit v1.3 From 1bc815c3d0eff054c7a032130206d16839bb331a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 20 Dec 2024 20:44:26 +0100 Subject: meson: add options to override build information We inject various different kinds of build information into build artifacts, like the version string or the commit from which Git was built. Add options to let users explicitly override this information with Meson. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 1 + meson.build | 13 +++++++++++++ meson_options.txt | 10 ++++++++++ 3 files changed, 24 insertions(+) (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build index f2426ccaa3..fca3eab1f1 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -219,6 +219,7 @@ asciidoc_conf = custom_target( input: meson.current_source_dir() / 'asciidoc.conf.in', output: 'asciidoc.conf', depends: [git_version_file], + env: version_gen_environment, ) asciidoc_common_options = [ diff --git a/meson.build b/meson.build index 0dccebcdf1..be32d60e84 100644 --- a/meson.build +++ b/meson.build @@ -201,6 +201,16 @@ if get_option('sane_tool_path') != '' script_environment.prepend('PATH', get_option('sane_tool_path')) endif +# The environment used by GIT-VERSION-GEN. Note that we explicitly override +# environment variables that might be set by the user. This is by design so +# that we always use whatever Meson has configured instead of what is present +# in the environment. +version_gen_environment = script_environment +version_gen_environment.set('GIT_BUILT_FROM_COMMIT', get_option('built_from_commit')) +version_gen_environment.set('GIT_DATE', get_option('build_date')) +version_gen_environment.set('GIT_USER_AGENT', get_option('user_agent')) +version_gen_environment.set('GIT_VERSION', get_option('version')) + compiler = meson.get_compiler('c') libgit_sources = [ @@ -1485,6 +1495,7 @@ git_version_file = custom_target( ], input: meson.current_source_dir() / 'GIT-VERSION-FILE.in', output: 'GIT-VERSION-FILE', + env: version_gen_environment, build_always_stale: true, ) @@ -1501,6 +1512,7 @@ version_def_h = custom_target( # Depend on GIT-VERSION-FILE so that we don't always try to rebuild this # target for the same commit. depends: [git_version_file], + env: version_gen_environment, ) # Build a separate library for "version.c" so that we do not have to rebuild @@ -1544,6 +1556,7 @@ if host_machine.system() == 'windows' input: meson.current_source_dir() / 'git.rc.in', output: 'git.rc', depends: [git_version_file], + env: version_gen_environment, ) common_main_sources += import('windows').compile_resources(git_rc, diff --git a/meson_options.txt b/meson_options.txt index 32a72139ba..8ead134955 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -16,6 +16,16 @@ option('runtime_prefix', type: 'boolean', value: false, option('sane_tool_path', type: 'string', value: '', description: 'A colon-separated list of paths to prepend to PATH if your tools in /usr/bin are broken.') +# Build information compiled into Git and other parts like documentation. +option('build_date', type: 'string', value: '', + description: 'Build date reported by our documentation.') +option('built_from_commit', type: 'string', value: '', + description: 'Commit that Git was built from reported by git-version(1).') +option('user_agent', type: 'string', value: '', + description: 'User agent reported to remote servers.') +option('version', type: 'string', value: '', + description: 'Version string reported by git-version(1) and other tools.') + # Features supported by Git. option('curl', type: 'feature', value: 'enabled', description: 'Build helpers used to access remotes with the HTTP transport.') -- cgit v1.3 From 49edce4ff96d003e2b50202105107ef42e1f730e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 20 Dec 2024 10:02:15 -0800 Subject: show-index: the short help should say the command reads from its input The short help text given by "git show-index -h" says $ git show-index -h usage: git show-index [--object-format=] --[no-]object-format specify the hash algorithm to use The command takes a pack .idx file from its standard input. The user has to _know_ this, as there is no indication from this output. Give a hint that the data to work on is fed from its standard input. Signed-off-by: Junio C Hamano --- Documentation/git-show-index.txt | 2 +- builtin/show-index.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt index e49318a5a0..7e574ea243 100644 --- a/Documentation/git-show-index.txt +++ b/Documentation/git-show-index.txt @@ -9,7 +9,7 @@ git-show-index - Show packed archive index SYNOPSIS -------- [verse] -'git show-index' [--object-format=] +'git show-index' [--object-format=] < DESCRIPTION diff --git a/builtin/show-index.c b/builtin/show-index.c index f164c01bbe..8678b741a4 100644 --- a/builtin/show-index.c +++ b/builtin/show-index.c @@ -7,7 +7,7 @@ #include "parse-options.h" static const char *const show_index_usage[] = { - "git show-index [--object-format=]", + "git show-index [--object-format=] < ", NULL }; -- cgit v1.3 From 298805c823067ca32b1577662c87f77240e36aec Mon Sep 17 00:00:00 2001 From: Martin Ågren Date: Sat, 21 Dec 2024 00:18:16 +0100 Subject: asciidoctor-extensions.rb.in: delete existing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the recent a38edab7c8 (Makefile: generate doc versions via GIT-VERSION-GEN, 2024-12-06), building with Asciidoctor results in manpages where the headers no longer contain "Git Manual" and the footers no longer identify the built Git version. Before a38edab7c8, we used to just provide a few attributes to Asciidoctor (and asciidoc). Commit 7a30134358 (asciidoctor-extensions: provide ``, 2019-09-16) noted that older versions of Asciidoctor didn't propagate those attributes into the built XML files, so we started injecting them ourselves from this script. With newer versions of Asciidoctor, we'd end up with some harmless duplication among the tags in the final XML. Post-a38edab7c8, we don't provide these attributes and Asciidoctor inserts empty-ish values. After our additions from 7a30134358, we get     2.47.1.[...] Git Manual When these are handled, it appears to be first come first served, meaning that our additions have no effect and we regress as described in the first paragraph. Remove existing "source" or "manual" tags before adding ours. I considered removing all to get a nice clean slate, instead of just those two that we want to replace to be a bit more precise. I opted for the latter. Maybe one day, Asciidoctor learns to insert something useful there which `xmlto` can pick up and make good use of -- let's not interfere. Signed-off-by: Martin Ågren Signed-off-by: Junio C Hamano --- Documentation/asciidoctor-extensions.rb.in | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/asciidoctor-extensions.rb.in b/Documentation/asciidoctor-extensions.rb.in index c4c200dace..d8d06f9a57 100644 --- a/Documentation/asciidoctor-extensions.rb.in +++ b/Documentation/asciidoctor-extensions.rb.in @@ -29,6 +29,8 @@ module Git class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor def process document, output if document.basebackend? 'docbook' + output = output.sub(/.*?<\/refmiscinfo>/, "") + output = output.sub(/.*?<\/refmiscinfo>/, "") new_tags = "" \ "@GIT_VERSION@\n" \ "Git Manual\n" -- cgit v1.3 From c683924d06e3c1f0166054450d4a7ecbabca0756 Mon Sep 17 00:00:00 2001 From: Martin Ågren Date: Sat, 21 Dec 2024 00:18:17 +0100 Subject: asciidoctor-extensions.rb.in: add missing word MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit a38edab7c8 (Makefile: generate doc versions via GIT-VERSION-GEN, 2024-12-06) stopped providing an attribute value "Git $(GIT_VERSION)" to asciidoc/Asciidoctor over the command line. Instead, we now provide the attribute to asciidoc through a generated asciidoc.conf, where the value is generated as "Git @GIT_VERSION@". In the similar mechanism for Asciidoctor, we forgot the "Git" prefix. Restore it. Signed-off-by: Martin Ågren Signed-off-by: Junio C Hamano --- Documentation/asciidoctor-extensions.rb.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/asciidoctor-extensions.rb.in b/Documentation/asciidoctor-extensions.rb.in index d8d06f9a57..fd1b84c2be 100644 --- a/Documentation/asciidoctor-extensions.rb.in +++ b/Documentation/asciidoctor-extensions.rb.in @@ -32,7 +32,7 @@ module Git output = output.sub(/.*?<\/refmiscinfo>/, "") output = output.sub(/.*?<\/refmiscinfo>/, "") new_tags = "" \ - "@GIT_VERSION@\n" \ + "Git @GIT_VERSION@\n" \ "Git Manual\n" output = output.sub(/<\/refmeta>/, new_tags + "") end -- cgit v1.3 From beb8081f3153fe17907131b94b4c7d32167ff26d Mon Sep 17 00:00:00 2001 From: Martin Ågren Date: Sat, 21 Dec 2024 00:18:18 +0100 Subject: asciidoctor-extensions.rb.in: inject GIT_DATE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a38edab7c8 (Makefile: generate doc versions via GIT-VERSION-GEN, 2024-12-06), we no longer inject GIT_DATE when building with Asciidoctor. Replace the tag in the XML to inject the value of GIT_DATE. Unlike as handled in a recent commit, we have no reason to expect that this tag might be missing, so there's no need for "maybe remove, then add" and we can just outright replace the one that Asciidoctor has generated based on the mtime of the source file. Compared to pre-a38edab7c8, we now end up injecting this also in the build of Git.3pm, which until now has been using the mtime of Git.pm. That is arguably even a good change since it results in more reproducible builds. Signed-off-by: Martin Ågren Signed-off-by: Junio C Hamano --- Documentation/asciidoctor-extensions.rb.in | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/asciidoctor-extensions.rb.in b/Documentation/asciidoctor-extensions.rb.in index fd1b84c2be..2494f17a51 100644 --- a/Documentation/asciidoctor-extensions.rb.in +++ b/Documentation/asciidoctor-extensions.rb.in @@ -31,6 +31,7 @@ module Git if document.basebackend? 'docbook' output = output.sub(/.*?<\/refmiscinfo>/, "") output = output.sub(/.*?<\/refmiscinfo>/, "") + output = output.sub(/.*?<\/date>/, "@GIT_DATE@") new_tags = "" \ "Git @GIT_VERSION@\n" \ "Git Manual\n" -- cgit v1.3 From 996f0c583b36aa5d6c6308285aea1421eb7efae7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 23 Dec 2024 08:45:57 -0800 Subject: Hopefully the final batch before 2.48-rc1 Let's wait for git-gui, gitk, and possibly po/ and delay the tagging of the -rc1. Many people are already offline for the end-of-year holidays and it is a slow week, and 'master' front has too many new things graduated from 'next' a bit too early for me to feel comfortable. Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 27 +++++++++++++++++++++++++++ GIT-VERSION-GEN | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index cc752d5466..33c11e742f 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -35,6 +35,10 @@ UI, Workflows & Features * "git fetch" honors "remote..followRemoteHEAD" settings to tweak the remote-tracking HEAD in "refs/remotes//HEAD". + * "git range-diff" learned to optionally show and compare merge + commits in the ranges being compared, with the --diff-merges + option. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -141,6 +145,22 @@ Performance, Internal Implementation, Development Support etc. * Build procedure update plus introduction of Meson based builds. + * Recent reftable updates mistook a NULL return from a request for + 0-byte allocation as OOM and died unnecessarily, which has been + corrected. + + * Reftable backend adds check for upper limit of log's update_index. + + * Start working to make the codebase buildable with -Wsign-compare. + + * Regression fix for 'show-index' when run outside of a repository. + + * The meson-build procedure is integrated into CI to catch and + prevent bitrotting. + + * "git refs migrate" learned to also migrate the reflog data across + backends. + Fixes since v2.47 ----------------- @@ -280,6 +300,13 @@ Fixes since v2.47 the revision walker, which has become unnecessary. (merge dd1072dfa8 tc/bundle-with-tag-remove-workaround later to maint). + * GitLab CI updates. + (merge c6b43f663e ps/ci-gitlab-update later to maint). + + * Code to reuse objects based on bitmap contents have been tightened + to avoid race condition even when multiple packs are involved. + (merge 62b3ec8a3f tb/bitmap-fix-pack-reuse later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 77af53f56f aa/t7300-modernize later to maint). (merge dcd590a39d bf/t-readme-mention-reftable later to maint). diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 497b4e48d2..194ec0f9ad 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,6 +1,6 @@ #!/bin/sh -DEF_VER=v2.48.0-rc0 +DEF_VER=v2.48.0-rc1 LF=' ' -- cgit v1.3 From b59358100c203b104e53523e1a4e3c2ad426334c Mon Sep 17 00:00:00 2001 From: Alexander Shopov Date: Tue, 24 Dec 2024 13:29:09 +0100 Subject: Update the official repo of gitk Point out: - current maintaner - contribution flow is via the mailing list Signed-off-by: Alexander Shopov Signed-off-by: Junio C Hamano --- Documentation/SubmittingPatches | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index d8a8caa791..3968abcc4c 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -692,16 +692,17 @@ rebase when I receive your patches). Some parts of the system have dedicated maintainers with their own repositories. -- `git-gui/` comes from git-gui project, maintained by Johannes Sixt: +- `git-gui/` comes from the git-gui project, maintained by Johannes Sixt: https://github.com/j6t/git-gui -- `gitk-git/` comes from Paul Mackerras's gitk project: + Contibutions should go via the git mailing list. - git://git.ozlabs.org/~paulus/gitk +- `gitk-git/` comes from the gitk project, maintained by Johannes Sixt: - Those who are interested in improving gitk can volunteer to help Paul - maintain it, cf. . + https://github.com/j6t/gitk + + Contibutions should go via the git mailing list. - `po/` comes from the localization coordinator, Jiang Xin: -- cgit v1.3 From d838d821c9687a789673b2ac9dff707fdc599e1e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:29 +0100 Subject: meson: wire up support for AsciiDoctor While our Makefile supports both Asciidoc and AsciiDoctor, our Meson build instructions only support the former. Wire up support for the latter, as well. Our Makefile always favors Asciidoc, but Meson will automatically figure out which of both to use based on whether they are installed or not. To keep compatibility with our Makefile it favors Asciidoc over Asciidoctor in case both are available. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 110 ++++++++++++++++++++++++++++++++++------------ meson_options.txt | 2 + 2 files changed, 84 insertions(+), 28 deletions(-) (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build index fca3eab1f1..acd6d86ec7 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -204,29 +204,87 @@ manpages = { 'gitworkflows.txt' : 7, } -asciidoc = find_program('asciidoc') -git = find_program('git', required: false) -xmlto = find_program('xmlto') +docs_backend = get_option('docs_backend') +if docs_backend == 'auto' + if find_program('asciidoc', required: false).found() + docs_backend = 'asciidoc' + elif find_program('asciidoctor', required: false).found() + docs_backend = 'asciidoctor' + else + error('Neither asciidoc nor asciidoctor were found.') + endif +endif -asciidoc_conf = custom_target( - command: [ - shell, - meson.project_source_root() / 'GIT-VERSION-GEN', - meson.project_source_root(), - '@INPUT@', - '@OUTPUT@', - ], - input: meson.current_source_dir() / 'asciidoc.conf.in', - output: 'asciidoc.conf', - depends: [git_version_file], - env: version_gen_environment, -) +if docs_backend == 'asciidoc' + asciidoc = find_program('asciidoc', required: true) + asciidoc_html = 'xhtml11' + asciidoc_docbook = 'docbook' + xmlto_extra = [ ] -asciidoc_common_options = [ - asciidoc, - '--conf-file=' + asciidoc_conf.full_path(), - '--attribute=build_dir=' + meson.current_build_dir(), -] + asciidoc_conf = custom_target( + command: [ + shell, + meson.project_source_root() / 'GIT-VERSION-GEN', + meson.project_source_root(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'asciidoc.conf.in', + output: 'asciidoc.conf', + depends: [git_version_file], + env: version_gen_environment, + ) + + asciidoc_common_options = [ + asciidoc, + '--conf-file=' + asciidoc_conf.full_path(), + '--attribute=build_dir=' + meson.current_build_dir(), + ] + + documentation_deps = [ + asciidoc_conf, + ] +elif docs_backend == 'asciidoctor' + asciidoctor = find_program('asciidoctor', required: true) + asciidoc_html = 'xhtml5' + asciidoc_docbook = 'docbook5' + xmlto_extra = [ + '--skip-validation', + '-x', meson.current_source_dir() / 'manpage.xsl', + ] + + asciidoctor_extensions = custom_target( + command: [ + shell, + meson.project_source_root() / 'GIT-VERSION-GEN', + meson.project_source_root(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'asciidoctor-extensions.rb.in', + output: 'asciidoctor-extensions.rb', + depends: [git_version_file], + env: version_gen_environment, + ) + + asciidoc_common_options = [ + asciidoctor, + '--attribute', 'compat-mode', + '--attribute', 'tabsize=8', + '--attribute', 'litdd=--', + '--attribute', 'docinfo=shared', + '--attribute', 'build_dir=' + meson.current_build_dir(), + '--load-path', meson.current_build_dir(), + '--require', 'asciidoctor-extensions', + ] + + documentation_deps = [ + asciidoctor_extensions, + ] +endif + +git = find_program('git', required: false) +xmlto = find_program('xmlto') cmd_lists = [ 'cmds-ancillaryinterrogators.txt', @@ -243,10 +301,6 @@ cmd_lists = [ 'cmds-foreignscminterface.txt', ] -documentation_deps = [ - asciidoc_conf, -] - documentation_deps += custom_target( command: [ perl, @@ -278,7 +332,7 @@ foreach manpage, category : manpages if get_option('docs').contains('man') manpage_xml_target = custom_target( command: asciidoc_common_options + [ - '--backend=docbook', + '--backend=' + asciidoc_docbook, '--doctype=manpage', '--out-file=@OUTPUT@', meson.current_source_dir() / manpage, @@ -301,7 +355,7 @@ foreach manpage, category : manpages manpage_xml_target, '-o', meson.current_build_dir(), - ], + ] + xmlto_extra, output: manpage_path, install: true, install_dir: get_option('mandir') / 'man' + category.to_string(), @@ -311,7 +365,7 @@ foreach manpage, category : manpages if get_option('docs').contains('html') and category == 1 custom_target( command: asciidoc_common_options + [ - '--backend=xhtml11', + '--backend=' + asciidoc_html, '--doctype=manpage', '--out-file=@OUTPUT@', meson.current_source_dir() / manpage, diff --git a/meson_options.txt b/meson_options.txt index 4be7eab399..f50bb40cdf 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -85,6 +85,8 @@ option('docs', type: 'array', choices: ['man', 'html'], value: [], description: 'Which documenattion formats to build and install.') option('default_help_format', type: 'combo', choices: ['man', 'html'], value: 'man', description: 'Default format used when executing git-help(1).') +option('docs_backend', type: 'combo', choices: ['asciidoc', 'asciidoctor', 'auto'], value: 'auto', + description: 'Which backend to use to generate documentation.') # Testing. option('tests', type: 'boolean', value: true, -- cgit v1.3 From 2a8bd34c5576e02fed38d85dc5c90ffb9d4ecfb3 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:30 +0100 Subject: meson: properly wire up dependencies for our docs A couple of Meson documentation targets use `meson.current_source_dir()` to resolve inputs. This has the downside that it does not automagically make Meson track these inputs as a dependency. After all, string arguments really can be anything, even if they happen to match an actual filesystem path. Adapt these build targets to instead use inputs. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build index acd6d86ec7..b3c8b6c563 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -229,7 +229,7 @@ if docs_backend == 'asciidoc' '@INPUT@', '@OUTPUT@', ], - input: meson.current_source_dir() / 'asciidoc.conf.in', + input: 'asciidoc.conf.in', output: 'asciidoc.conf', depends: [git_version_file], env: version_gen_environment, @@ -261,7 +261,7 @@ elif docs_backend == 'asciidoctor' '@INPUT@', '@OUTPUT@', ], - input: meson.current_source_dir() / 'asciidoctor-extensions.rb.in', + input: 'asciidoctor-extensions.rb.in', output: 'asciidoctor-extensions.rb', depends: [git_version_file], env: version_gen_environment, @@ -304,10 +304,11 @@ cmd_lists = [ documentation_deps += custom_target( command: [ perl, - meson.current_source_dir() / 'cmd-list.perl', + '@INPUT@', meson.project_source_root(), meson.current_build_dir(), ] + cmd_lists, + input: 'cmd-list.perl', output: cmd_lists ) @@ -315,7 +316,7 @@ foreach mode : [ 'diff', 'merge' ] documentation_deps += custom_target( command: [ shell, - meson.current_source_dir() / 'generate-mergetool-list.sh', + '@INPUT@', '..', 'diff', '@OUTPUT@' @@ -324,6 +325,7 @@ foreach mode : [ 'diff', 'merge' ] 'MERGE_TOOLS_DIR=' + meson.project_source_root() / 'mergetools', 'TOOL_MODE=' + mode, ], + input: 'generate-mergetool-list.sh', output: 'mergetools-' + mode + '.txt', ) endforeach @@ -335,9 +337,10 @@ foreach manpage, category : manpages '--backend=' + asciidoc_docbook, '--doctype=manpage', '--out-file=@OUTPUT@', - meson.current_source_dir() / manpage, + '@INPUT@', ], depends: documentation_deps, + input: manpage, output: fs.stem(manpage) + '.xml', ) @@ -345,10 +348,8 @@ foreach manpage, category : manpages manpage_target = custom_target( command: [ xmlto, - '-m', - meson.current_source_dir() / 'manpage-normal.xsl', - '-m', - meson.current_source_dir() / 'manpage-bold-literal.xsl', + '-m', '@INPUT0@', + '-m', '@INPUT1@', '--stringparam', 'man.base.url.for.relative.links=' + get_option('prefix') / get_option('mandir'), 'man', @@ -356,6 +357,10 @@ foreach manpage, category : manpages '-o', meson.current_build_dir(), ] + xmlto_extra, + input: [ + 'manpage-normal.xsl', + 'manpage-bold-literal.xsl', + ], output: manpage_path, install: true, install_dir: get_option('mandir') / 'man' + category.to_string(), @@ -368,9 +373,10 @@ foreach manpage, category : manpages '--backend=' + asciidoc_html, '--doctype=manpage', '--out-file=@OUTPUT@', - meson.current_source_dir() / manpage, + '@INPUT@', ], depends: documentation_deps, + input: manpage, output: fs.stem(manpage) + '.html', install: true, install_dir: get_option('datadir') / 'doc/git-doc', -- cgit v1.3 From b88540045c3d70dbf4138c8f32209fea32e40d90 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:31 +0100 Subject: meson: fix generation of merge tools Our buildsystems generate a list of diff and merge tools that ultimately end up in our documentation. And while Meson does wire up the logic, it tries to use the TOOL_MODE environment variable to set up the mode. This is wrong though: the mode is set via an argument that we have fixed to 'diff' mode by accident. Fix this such that merge tools are properly generated. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build index b3c8b6c563..c2512328ca 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -318,12 +318,11 @@ foreach mode : [ 'diff', 'merge' ] shell, '@INPUT@', '..', - 'diff', + mode, '@OUTPUT@' ], env: [ 'MERGE_TOOLS_DIR=' + meson.project_source_root() / 'mergetools', - 'TOOL_MODE=' + mode, ], input: 'generate-mergetool-list.sh', output: 'mergetools-' + mode + '.txt', -- cgit v1.3 From 0696ebe9ce533cf3c839c9eb2bd2331c8fa0f014 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:32 +0100 Subject: meson: generate HTML pages for all man page categories When generating HTML pages for our man pages we only generate them for category 1 in Meson, which are the pages corresponding to our built-in commands. I cannot tell why I added this filter though: our Makefile installs all man pages, so a Meson-based build misses out on many of them. Fix this by removing the filter. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build index c2512328ca..48583e9a7f 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -366,7 +366,7 @@ foreach manpage, category : manpages ) endif - if get_option('docs').contains('html') and category == 1 + if get_option('docs').contains('html') custom_target( command: asciidoc_common_options + [ '--backend=' + asciidoc_html, -- cgit v1.3 From 851ecc4290cbdb57f36f10b77da9c1ae13c10469 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:33 +0100 Subject: Documentation: inline user-manual.conf When generating our user manual we set up a bit of extra configuration compared to our normal configuration. This is done by having an extra "user-manual.conf" file that Asciidoc seems to pull in automatically due to matching filenames with "user-manual.txt". This dependency is quite hidden though and thus easy to miss. Furthermore, it seems that Asciidoc does not know to pull it in for out-of-tree builds where we use relative paths. The setup in AsciiDoctor is somewhat different: instead of having two sets of configuration, we condition the use of manual-specific configs based on whether the document type is "book". And as we only build our user manual with that type this is sufficient. Use the same trick for our user manual by inlining the configuration into "asciidoc.conf.in" and making it conditional on whether or not "doctype-book" is defined. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 2 +- Documentation/asciidoc.conf.in | 10 ++++++++++ Documentation/user-manual.conf | 11 ----------- 3 files changed, 11 insertions(+), 12 deletions(-) delete mode 100644 Documentation/user-manual.conf (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index a89823e1d1..4f152077dd 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -362,7 +362,7 @@ manpage-cmd = $(QUIET_XMLTO)$(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< %.xml : %.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_XML) -d manpage -o $@ $< -user-manual.xml: user-manual.txt user-manual.conf $(ASCIIDOC_DEPS) +user-manual.xml: user-manual.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_XML) -d book -o $@ $< technical/api-index.txt: technical/api-index-skel.txt \ diff --git a/Documentation/asciidoc.conf.in b/Documentation/asciidoc.conf.in index b89bccf230..f2aef6cb79 100644 --- a/Documentation/asciidoc.conf.in +++ b/Documentation/asciidoc.conf.in @@ -25,12 +25,22 @@ manmanual=Git Manual mansource=Git @GIT_VERSION@ revdate=@GIT_DATE@ +ifdef::doctype-book[] +[titles] + underlines="__","==","--","~~","^^" +endif::doctype-book[] + ifdef::backend-docbook[] [linkgit-inlinemacro] +ifndef::doctype-book[] {0%{target}} {0#} {0#{target}{0}} {0#} +endif::doctype-book[] +ifdef::doctype-book[] +{target}{0?({0})} +endif::doctype-book[] [literal-inlinemacro] {eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1\2', re.sub(r'(\.\.\.?)([^\]$.])', r'\1\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} diff --git a/Documentation/user-manual.conf b/Documentation/user-manual.conf deleted file mode 100644 index 0148f126dc..0000000000 --- a/Documentation/user-manual.conf +++ /dev/null @@ -1,11 +0,0 @@ -[titles] - underlines="__","==","--","~~","^^" - -[attributes] -caret=^ -startsb=[ -endsb=] -tilde=~ - -[linkgit-inlinemacro] -{target}{0?({0})} -- cgit v1.3 From ae0b33939d233fa340f1ebb768588dc46a128e4c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:34 +0100 Subject: meson: generate user manual Our documentation contains a user manual that gives people a short introduction to Git. Our Makefile knows to generate the manual into three different formats: an HTML page, a PDF and an info page. The Meson build instructions don't yet generate any of these. While wiring up all these formats I hit a couple of road blocks with how we generate our info pages. Even though I eventually resolved these, it made me question whether anybody actually uses info pages in the first place. Checking through a couple of downstream consumers I couldn't find a single user of either the info pages nor of our PDF manual in Arch Linux, Debian, Fedora, Ubuntu, FreeBSD or OpenBSDFedora. So it's rather safe to assume that there aren't really any users out there, and thus the added complexity does not seem worth it. Wire up support for building the user manual in HTML format and conciously skip over the other two formats. This is basically a form of silent deprecation: if people out there use the other two formats they will eventually complain about them missing in Meson, which means we can wire them up at a later point. If they don't we can phase out these formats eventually. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build index 48583e9a7f..404cb20d10 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -382,3 +382,35 @@ foreach manpage, category : manpages ) endif endforeach + +if get_option('docs').contains('html') + xsltproc = find_program('xsltproc') + + user_manual_xml = custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_docbook, + '--doctype=book', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + input: 'user-manual.txt', + output: 'user-manual.xml', + depends: documentation_deps, + ) + + custom_target( + command: [ + xsltproc, + '--xinclude', + '--stringparam', 'html.stylesheet', 'docbook-xsl.css', + '--param', 'generate.consistent.ids', '1', + '--output', '@OUTPUT@', + '@INPUT@', + user_manual_xml, + ], + input: 'docbook.xsl', + output: 'user-manual.html', + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) +endif -- cgit v1.3 From 88e08b92e9a55fa453d44b26061a6a67a7eefafc Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:35 +0100 Subject: Documentation: refactor "api-index.sh" for out-of-tree builds The "api-index.sh" script generates an index of API-related documentation. The script does not handle out-of-tree builds and thus cannot be used easily by Meson. Refactor it to be independent of locations by both accepting a source directory where the API docs live as well as a path to an output file. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 2 +- Documentation/technical/api-index.sh | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index 4f152077dd..b2d146c44f 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -367,7 +367,7 @@ user-manual.xml: user-manual.txt $(ASCIIDOC_DEPS) technical/api-index.txt: technical/api-index-skel.txt \ technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS)) - $(QUIET_GEN)cd technical && '$(SHELL_PATH_SQ)' ./api-index.sh + $(QUIET_GEN)'$(SHELL_PATH_SQ)' technical/api-index.sh ./technical ./technical/api-index.txt technical/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../ $(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt \ diff --git a/Documentation/technical/api-index.sh b/Documentation/technical/api-index.sh index 9c3f4131b8..2964885574 100755 --- a/Documentation/technical/api-index.sh +++ b/Documentation/technical/api-index.sh @@ -1,6 +1,17 @@ #!/bin/sh +if test $# -ne 2 +then + echo >&2 "USAGE: $0 " + exit 1 +fi + +SOURCE_DIR="$1" +OUTPUT="$2" + ( + cd "$SOURCE_DIR" + c=//////////////////////////////////////////////////////////////// skel=api-index-skel.txt sed -e '/^\/\/ table of contents begin/q' "$skel" @@ -18,11 +29,11 @@ done echo "$c" sed -n -e '/^\/\/ table of contents end/,$p' "$skel" -) >api-index.txt+ +) >"$OUTPUT"+ -if test -f api-index.txt && cmp api-index.txt api-index.txt+ >/dev/null +if test -f "$OUTPUT" && cmp "$OUTPUT" "$OUTPUT"+ >/dev/null then - rm -f api-index.txt+ + rm -f "$OUTPUT"+ else - mv api-index.txt+ api-index.txt + mv "$OUTPUT"+ "$OUTPUT" fi -- cgit v1.3 From 8922506cb2c34527f8b2321b4f7a4b454a325a07 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:36 +0100 Subject: Documentation: refactor "howto-index.sh" for out-of-tree builds The "howto-index.sh" is used to generate an index of our how-to docs. It receives as input the paths to these documents, which would typically be relative to the "Documentation/" directory in Makefile-based builds. In an out-of-tree build though it will get relative that may be rooted somewhere else entirely. The file paths do end up in the generated index, and the expectation is that they should always start with "howto/". But for out-of-tree builds we would populate it with the paths relative to the build directory, which is wrong. Fix the issue by using `$(basename "$file")` to generate the path. While at it, move the script into "howto/" to align it with the location of the comparable "api-index.sh" script. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/Makefile | 4 +-- Documentation/howto-index.sh | 56 -------------------------------------- Documentation/howto/howto-index.sh | 56 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 58 deletions(-) delete mode 100755 Documentation/howto-index.sh create mode 100755 Documentation/howto/howto-index.sh (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index b2d146c44f..e284ec8b98 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -411,8 +411,8 @@ gitman.info: gitman.texi $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml $(QUIET_DB2TEXI)$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@ -howto-index.txt: howto-index.sh $(HOWTO_TXT) - $(QUIET_GEN)'$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(HOWTO_TXT)) >$@ +howto-index.txt: howto/howto-index.sh $(HOWTO_TXT) + $(QUIET_GEN)'$(SHELL_PATH_SQ)' ./howto/howto-index.sh $(sort $(HOWTO_TXT)) >$@ $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt diff --git a/Documentation/howto-index.sh b/Documentation/howto-index.sh deleted file mode 100755 index 167b363668..0000000000 --- a/Documentation/howto-index.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh - -cat <<\EOF -Git Howto Index -=============== - -Here is a collection of mailing list postings made by various -people describing how they use Git in their workflow. - -EOF - -for txt -do - title=$(expr "$txt" : '.*/\(.*\)\.txt$') - from=$(sed -ne ' - /^$/q - /^From:[ ]/{ - s/// - s/^[ ]*// - s/[ ]*$// - s/^/by / - p - } - ' "$txt") - - abstract=$(sed -ne ' - /^Abstract:[ ]/{ - s/^[^ ]*// - x - s/.*// - x - : again - /^[ ]/{ - s/^[ ]*// - H - n - b again - } - x - p - q - }' "$txt") - - if grep 'Content-type: text/asciidoc' >/dev/null $txt - then - file=$(expr "$txt" : '\(.*\)\.txt$').html - else - file="$txt" - fi - - echo "* link:$file[$title] $from -$abstract - -" - -done diff --git a/Documentation/howto/howto-index.sh b/Documentation/howto/howto-index.sh new file mode 100755 index 0000000000..eecd123a93 --- /dev/null +++ b/Documentation/howto/howto-index.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +cat <<\EOF +Git Howto Index +=============== + +Here is a collection of mailing list postings made by various +people describing how they use Git in their workflow. + +EOF + +for txt +do + title=$(expr "$txt" : '.*/\(.*\)\.txt$') + from=$(sed -ne ' + /^$/q + /^From:[ ]/{ + s/// + s/^[ ]*// + s/[ ]*$// + s/^/by / + p + } + ' "$txt") + + abstract=$(sed -ne ' + /^Abstract:[ ]/{ + s/^[^ ]*// + x + s/.*// + x + : again + /^[ ]/{ + s/^[ ]*// + H + n + b again + } + x + p + q + }' "$txt") + + if grep 'Content-type: text/asciidoc' >/dev/null $txt + then + file=$(expr "$txt" : '\(.*\)\.txt$').html + else + file="$txt" + fi + + echo "* link:howto/$(basename "$file")[$title] $from +$abstract + +" + +done -- cgit v1.3 From bcf7edee09e8f9c1779fafa953832f63e9a23545 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:37 +0100 Subject: meson: generate articles While the Meson build system already knows to generate man pages and our user manual, it does not yet generate the random assortment of articles that we have. Plug this gap. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/howto/meson.build | 62 ++++++++++++++++++++++++++++++++++ Documentation/meson.build | 36 ++++++++++++++++++++ Documentation/technical/meson.build | 66 +++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 Documentation/howto/meson.build create mode 100644 Documentation/technical/meson.build (limited to 'Documentation') diff --git a/Documentation/howto/meson.build b/Documentation/howto/meson.build new file mode 100644 index 0000000000..c023c10416 --- /dev/null +++ b/Documentation/howto/meson.build @@ -0,0 +1,62 @@ +howto_sources = [ + 'coordinate-embargoed-releases.txt', + 'keep-canonical-history-correct.txt', + 'maintain-git.txt', + 'new-command.txt', + 'rebase-from-internal-branch.txt', + 'rebuild-from-update-hook.txt', + 'recover-corrupted-blob-object.txt', + 'recover-corrupted-object-harder.txt', + 'revert-a-faulty-merge.txt', + 'revert-branch-rebase.txt', + 'separating-topic-branches.txt', + 'setup-git-server-over-http.txt', + 'update-hook-example.txt', + 'use-git-daemon.txt', + 'using-merge-subtree.txt', + 'using-signed-tag-in-pull-request.txt', +] + +howto_index = custom_target( + command: [ + shell, + meson.current_source_dir() / 'howto-index.sh', + '@INPUT@', + ], + env: script_environment, + capture: true, + input: howto_sources, + output: 'howto-index.txt', +) + +custom_target( + command: asciidoc_html_options, + input: howto_index, + output: 'howto-index.html', + depends: documentation_deps, + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', +) + +foreach howto : howto_sources + howto_stripped = custom_target( + command: [ + find_program('sed'), + '-e', + '1,/^$/d', + '@INPUT@', + ], + input: howto, + output: fs.stem(howto) + '.stripped', + capture: true, + ) + + custom_target( + command: asciidoc_html_options, + input: howto_stripped, + output: fs.stem(howto_stripped.full_path()) + '.html', + depends: documentation_deps, + install: true, + install_dir: get_option('datadir') / 'doc/git-doc/howto', + ) +endforeach diff --git a/Documentation/meson.build b/Documentation/meson.build index 404cb20d10..8c6ff0bce1 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -413,4 +413,40 @@ if get_option('docs').contains('html') install: true, install_dir: get_option('datadir') / 'doc/git-doc', ) + + articles = [ + 'DecisionMaking.txt', + 'MyFirstContribution.txt', + 'MyFirstObjectWalk.txt', + 'ReviewingGuidelines.txt', + 'SubmittingPatches', + 'ToolsForGit.txt', + 'git-bisect-lk2009.txt', + 'git-tools.txt', + ] + + foreach article : articles + custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_html, + '--out-file=@OUTPUT@', + '@INPUT@', + ], + input: article, + output: fs.stem(article) + '.html', + depends: documentation_deps, + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) + endforeach + + asciidoc_html_options = asciidoc_common_options + [ + '--backend=' + asciidoc_html, + '--out-file=@OUTPUT@', + '--attribute', 'git-relative-html-prefix=../', + '@INPUT@', + ] + + subdir('howto') + subdir('technical') endif diff --git a/Documentation/technical/meson.build b/Documentation/technical/meson.build new file mode 100644 index 0000000000..21dfb8b5c9 --- /dev/null +++ b/Documentation/technical/meson.build @@ -0,0 +1,66 @@ +api_docs = [ + 'api-error-handling.txt', + 'api-merge.txt', + 'api-parse-options.txt', + 'api-simple-ipc.txt', + 'api-trace2.txt', +] + +articles = [ + 'bitmap-format.txt', + 'build-systems.txt', + 'bundle-uri.txt', + 'commit-graph.txt', + 'directory-rename-detection.txt', + 'hash-function-transition.txt', + 'long-running-process-protocol.txt', + 'multi-pack-index.txt', + 'packfile-uri.txt', + 'pack-heuristics.txt', + 'parallel-checkout.txt', + 'partial-clone.txt', + 'platform-support.txt', + 'racy-git.txt', + 'reftable.txt', + 'remembering-renames.txt', + 'repository-version.txt', + 'rerere.txt', + 'scalar.txt', + 'send-pack-pipeline.txt', + 'shallow.txt', + 'sparse-checkout.txt', + 'sparse-index.txt', + 'trivial-merge.txt', + 'unit-tests.txt', +] + +api_index = custom_target( + command: [ + shell, + meson.current_source_dir() / 'api-index.sh', + meson.current_source_dir(), + '@OUTPUT@', + ], + env: script_environment, + input: api_docs, + output: 'api-index.txt', +) + +custom_target( + command: asciidoc_html_options, + input: api_index, + output: 'api-index.html', + depends: documentation_deps, + install: true, + install_dir: get_option('datadir') / 'doc/git-doc/technical', +) + +foreach article : api_docs + articles + custom_target( + command: asciidoc_html_options, + input: article, + output: fs.stem(article) + '.html', + install: true, + install_dir: get_option('datadir') / 'doc/git-doc/technical', + ) +endforeach -- cgit v1.3 From 7a3136e5c713c4a5ed2af51ccb8abb5cfa3d98bf Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:38 +0100 Subject: meson: install static files for HTML documentation Now that we generate man pages, articles and user manual with Meson the only thing that is still missing in an installation of HTML documents is a couple of static files. Wire these up to finalize Meson's support for generating HTML documentation. Diffing an installation that uses our Makefile with an installation that uses Meson only surfaces a couple of discepancies now: - Meson doesn't install "everyday.html" and "git-remote-helpers.html". These files are marked as obsolete and don't contain any useful information anymore: they simply point to their modern equivalents. - Meson doesn't install "*.txt" files when asking for HTML docs. I'm not sure why our Makefiles do this in the first place, and it does seem like the resulting installation is fully functional even without those files. Other than that, both layout and file contents are the exact same. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'Documentation') diff --git a/Documentation/meson.build b/Documentation/meson.build index 8c6ff0bce1..4d95111565 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -384,6 +384,27 @@ foreach manpage, category : manpages endforeach if get_option('docs').contains('html') + configure_file( + input: 'docinfo-html.in', + output: 'docinfo.html', + copy: true, + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) + + configure_file( + input: 'docbook-xsl.css', + output: 'docbook-xsl.css', + copy: true, + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) + + install_symlink('index.html', + install_dir: get_option('datadir') / 'doc/git-doc', + pointing_to: 'git.html', + ) + xsltproc = find_program('xsltproc') user_manual_xml = custom_target( -- cgit v1.3 From 5419445b4d19b0979b14f239fe2362210174f613 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 14:59:40 +0100 Subject: Documentation: wire up sanity checks for Meson Wire up sanity checks for Meson to verify that no man pages are missing. This check is similar to the same check we already have for our tests. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/.gitignore | 1 + Documentation/Makefile | 16 ++++++++++++++++ Documentation/meson.build | 31 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) (limited to 'Documentation') diff --git a/Documentation/.gitignore b/Documentation/.gitignore index 649df89474..9f4bb3c4bf 100644 --- a/Documentation/.gitignore +++ b/Documentation/.gitignore @@ -12,6 +12,7 @@ cmds-*.txt mergetools-*.txt SubmittingPatches.txt tmp-doc-diff/ +tmp-meson-diff/ GIT-ASCIIDOCFLAGS /.build/ /GIT-EXCLUDED-PROGRAMS diff --git a/Documentation/Makefile b/Documentation/Makefile index e284ec8b98..aedfe99d1d 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -339,6 +339,7 @@ clean: $(RM) $(cmds_txt) $(mergetools_txt) *.made $(RM) GIT-ASCIIDOCFLAGS $(RM) asciidoc.conf asciidoctor-extensions.rb + $(RM) -rf tmp-meson-diff docinfo.html: docinfo-html.in $(QUIET_GEN)$(RM) $@ && cat $< >$@ @@ -494,6 +495,20 @@ lint-docs-fsck-msgids: $(LINT_DOCS_FSCK_MSGIDS) lint-docs-manpages: $(QUIET_GEN)./lint-manpages.sh +.PHONY: lint-docs-meson +lint-docs-meson: + @# awk acts up when trying to match single quotes, so we use \047 instead. + @mkdir -p tmp-meson-diff && \ + awk "/^manpages = {$$/ {flag=1 ; next } /^}$$/ { flag=0 } flag { gsub(/^ \047/, \"\"); gsub(/\047 : [157],\$$/, \"\"); print }" meson.build | \ + grep -v -e '#' -e '^$$' | \ + sort >tmp-meson-diff/meson.txt && \ + ls git*.txt scalar.txt | grep -v -e git-bisect-lk2009.txt -e git-tools.txt >tmp-meson-diff/actual.txt && \ + if ! cmp tmp-meson-diff/meson.txt tmp-meson-diff/actual.txt; then \ + echo "Meson man pages differ from actual man pages:"; \ + diff -u tmp-meson-diff/meson.txt tmp-meson-diff/actual.txt; \ + exit 1; \ + fi + ## Lint: list of targets above .PHONY: lint-docs lint-docs: lint-docs-fsck-msgids @@ -501,6 +516,7 @@ lint-docs: lint-docs-gitlink lint-docs: lint-docs-man-end-blurb lint-docs: lint-docs-man-section-order lint-docs: lint-docs-manpages +lint-docs: lint-docs-meson ifeq ($(wildcard po/Makefile),po/Makefile) doc-l10n install-l10n:: diff --git a/Documentation/meson.build b/Documentation/meson.build index 4d95111565..2a26fa8a5f 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -471,3 +471,34 @@ if get_option('docs').contains('html') subdir('howto') subdir('technical') endif + +# Sanity check that we are not missing any tests present in 't/'. This check +# only runs once at configure time and is thus best-effort, only. Furthermore, +# it only verifies man pages for the sake of simplicity. +configured_manpages = manpages.keys() + [ 'git-bisect-lk2009.txt', 'git-tools.txt' ] +actual_manpages = run_command(shell, '-c', 'ls git*.txt scalar.txt', + check: true, + env: script_environment, +).stdout().strip().split('\n') + +if configured_manpages != actual_manpages + missing_manpage = [ ] + foreach actual_manpage : actual_manpages + if actual_manpage not in configured_manpages + missing_manpage += actual_manpage + endif + endforeach + if missing_manpage.length() > 0 + error('Man page found, but not configured:\n\n - ' + '\n - '.join(missing_manpage)) + endif + + superfluous_manpage = [ ] + foreach configured_manpage : configured_manpages + if configured_manpage not in actual_manpages + superfluous_manpage += configured_manpage + endif + endforeach + if superfluous_manpage.length() > 0 + error('Man page configured, but not found:\n\n - ' + '\n - '.join(superfluous_manpage)) + endif +endif -- cgit v1.3 From bc2c65770dca70c1d4e151fad971bc7c7235a702 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 30 Dec 2024 06:58:28 -0800 Subject: Git 2.48-rc1 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index 33c11e742f..f9fc8c1086 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -161,6 +161,9 @@ Performance, Internal Implementation, Development Support etc. * "git refs migrate" learned to also migrate the reflog data across backends. + * The developer documentation has been updated to give the latest + info on gitk and git-gui maintainer. + Fixes since v2.47 ----------------- -- cgit v1.3 From d062ccf4c3af1e5153ed5064d4d05b05e0fdd4d5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 1 Jan 2025 09:20:53 -0800 Subject: A bit more post Git 2.48-rc1 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index f9fc8c1086..d62c62dc17 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -165,6 +165,10 @@ Performance, Internal Implementation, Development Support etc. info on gitk and git-gui maintainer. + * CI jobs that run threaded programs under LSan has been giving false + positives from time to time, which has been worked around. + + Fixes since v2.47 ----------------- @@ -310,6 +314,12 @@ Fixes since v2.47 to avoid race condition even when multiple packs are involved. (merge 62b3ec8a3f tb/bitmap-fix-pack-reuse later to maint). + * An earlier "csum-file checksum does not have to be computed with + sha1dc" topic had a few code paths that had initialized an + implementation of a hash function to be used by an unmatching hash + by mistake, which have been corrected. + (merge 599a63409b ps/weak-sha1-for-tail-sum-fix later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 77af53f56f aa/t7300-modernize later to maint). (merge dcd590a39d bf/t-readme-mention-reftable later to maint). -- cgit v1.3 From 38d7016891e37a789d389eddc7cd3dc9b76370b4 Mon Sep 17 00:00:00 2001 From: Martin Ågren Date: Fri, 3 Jan 2025 12:33:30 +0100 Subject: git.txt: fix heading line of tildes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two-line heading added in 8525e92886 (Document HOME environment variable, 2024-12-09) uses too many tilde characters, so the heading isn't detected as such. Both AsciiDoc and Asciidoctor end up misrendering this in different ways. Use the correct number of tilde characters to fix this. Signed-off-by: Martin Ågren Signed-off-by: Junio C Hamano --- Documentation/git.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/git.txt b/Documentation/git.txt index 47509c9e1a..e9f55620e8 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -478,7 +478,7 @@ their values the same way as Boolean valued configuration variables, e.g. Here are the variables: System -~~~~~~~~~~~~~~~~~~ +~~~~~~ `HOME`:: Specifies the path to the user's home directory. On Windows, if unset, Git will set a process environment variable equal to: -- cgit v1.3 From b67a603f6360051f174a00f8d10dc088dc7093be Mon Sep 17 00:00:00 2001 From: Martin Ågren Date: Fri, 3 Jan 2025 12:33:31 +0100 Subject: gitcli.txt: typeset pathnames as monospace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1bc1e94091 (doc: option value may be separate for valid reasons, 2024-11-25) added a paragraph discussing tilde-expansion of, e.g., ~/directory/file. The tilde character has a special meaning to asciidoc tools. In this particular case, AsciiDoc matches up the two tildes in "e.g. ~/directory/file or ~u/d/f" and sets the text between them using subscript. In the manpage, where subscripting is not possible, this renders as "e.g. /directory/file oru/d/f". These paths are literal values, which our coding guidelines want typeset as verbatim using backticks. Do that. One effect of this is indeed that the asciidoc tools stop interpreting tilde and other special characters. Signed-off-by: Martin Ågren Signed-off-by: Junio C Hamano --- Documentation/gitcli.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt index bd62cbd043..fcd86d2eee 100644 --- a/Documentation/gitcli.txt +++ b/Documentation/gitcli.txt @@ -91,7 +91,7 @@ scripting Git: written in the 'stuck' form. * Despite the above suggestion, when Arg is a path relative to the - home directory of a user, e.g. ~/directory/file or ~u/d/f, you + home directory of a user, e.g. `~/directory/file` or `~u/d/f`, you may want to use the separate form, e.g. `git foo --file ~/mine`, not `git foo --file=~/mine`. The shell will expand `~/` in the former to your home directory, but most shells keep the tilde in -- cgit v1.3 From 14650065b76b28d3cfa9453356ac5669b19e706e Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Tue, 7 Jan 2025 18:37:06 +0100 Subject: RelNotes/2.48.0: fix typos etc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct verb tense, add missing words, avoid double blank lines, and rephrase things that don’t read well to me like “Turn this linkage to relative paths”. Signed-off-by: Kristoffer Haugsbakk Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.48.0.txt | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt index d62c62dc17..eff93be37a 100644 --- a/Documentation/RelNotes/2.48.0.txt +++ b/Documentation/RelNotes/2.48.0.txt @@ -47,15 +47,15 @@ Performance, Internal Implementation, Development Support etc. * The way AsciiDoc is used for SYNOPSIS part of the manual pages has been revamped. The sources, at least for the simple cases, got - vastly pleasant to work with. + vastly more pleasant to work with. * The reftable library is now prepared to expect that the memory allocation function given to it may fail to allocate and to deal with such an error. * An extra worktree attached to a repository points at each other to - allow finding the repository from the worktree and vice versa - possible. Turn this linkage to relative paths. + allow finding the repository from the worktree (and vice versa) + possible. Use relative paths for this linkage. * Enable Windows-based CI in GitLab. @@ -94,7 +94,7 @@ Performance, Internal Implementation, Development Support etc. * Update the project's CodingGuidelines to discourage naming functions with a "_1()" suffix. - * Updates the '.clang-format' to match project conventions. + * Update '.clang-format' to match project conventions. * Centralize documentation for repository extensions into a single place. @@ -116,7 +116,7 @@ Performance, Internal Implementation, Development Support etc. * The migration procedure between two ref backends has been optimized. * "git fsck" learned to issue warnings on "curiously formatted" ref - contents that have always been taken valid but something Git + contents that have always been treated as valid but that Git wouldn't have written itself (e.g., missing terminating end-of-line after the full object name). @@ -127,13 +127,13 @@ Performance, Internal Implementation, Development Support etc. * Drop support for ancient environments in various CI jobs. - * Isolates the reftable subsystem from the rest of Git's codebase by + * Isolate the reftable subsystem from the rest of Git's codebase by using fewer pieces of Git's infrastructure. * Optimize reading random references out of the reftable backend by allowing reuse of iterator objects. - * Backport oss-fuzz tests for us to our codebase. + * Backport oss-fuzz tests to our codebase. * Introduce a new repository extension to prevent older Git versions from mis-interpreting worktrees created with relative paths. @@ -173,13 +173,13 @@ Fixes since v2.47 ----------------- * Doc update to clarify how periodical maintenance are scheduled, - spread across time to avoid thundering hurds. + spread across time to avoid thundering herds. * Use after free and double freeing at the end in "git log -L... -p" had been identified and fixed. * On macOS, fsmonitor can fall into a race condition that results in - a client waiting forever to be notified for an event that have + a client waiting forever to be notified about an event that has already happened. This problem has been corrected. * "git maintenance start" crashed due to an uninitialized variable @@ -203,7 +203,7 @@ Fixes since v2.47 * The dumb-http code regressed when the result of re-indexing a pack yielded an *.idx file that differs in content from the *.idx file it downloaded from the remote. This has been corrected by no longer - relying on: the *.idx file we got from the remote. + relying on the *.idx file we got from the remote. * When called with '--left-right' and '--use-bitmap-index', 'rev-list' will produce output without any left/right markers, which has been @@ -227,7 +227,7 @@ Fixes since v2.47 * "git gc" discards any objects that are outside promisor packs that are referred to by an object in a promisor pack, and we do not refetch them from the promisor at runtime, resulting an unusable - repository. Work it around by including these objects in the + repository. Work around it by including these objects in the referring promisor pack at the receiving end of the fetch. * Avoid build/test breakage on a system without working malloc debug @@ -282,9 +282,8 @@ Fixes since v2.47 on the path, which was not documented, which has been corrected. (merge bc1a980759 kk/doc-ancestry-path later to maint). - * "git tag" has been taught to refuse to create refs/tags/HEAD - as such a tag will be confusing in the context of UI provided by + since such a tag will be confusing in the context of the UI provided by the Git Porcelain commands. (merge bbd445d5ef jc/forbid-head-as-tagname later to maint). -- cgit v1.3 From 6a63995335e7a941d34bdafb93a56f789ebeed75 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Tue, 7 Jan 2025 21:24:21 +0000 Subject: docs: fix typesetting of merge driver placeholders Following the `CodingGuidlines`, since these placeholders are literal they should be typeset verbatim, so fix some that aren't. Signed-off-by: Matthew Hughes Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index e6150595af..5d12b78549 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -1166,7 +1166,7 @@ internal merge and the final merge. The merge driver can learn the pathname in which the merged result will be stored via placeholder `%P`. The conflict labels to be used for the common ancestor, local head and other head can be passed by -using '%S', '%X' and '%Y` respectively. +using `%S`, `%X` and `%Y` respectively. `conflict-marker-size` ^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.3 From 21e1b4486586d3a15d2d7bf0479e77636359b816 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 8 Jan 2025 23:35:23 +0000 Subject: difftool docs: restore correct position of tool list 2a9dfdf260 (difftool docs: de-duplicate configuration sections, 2022-09-07) moved the difftool documentation, but missed moving this "include" line that includes the generated list of diff tools, as referenced in the moved text. Restore the correct position of the included list. Signed-off-by: Adam Johnson Signed-off-by: Junio C Hamano --- Documentation/config/diff.txt | 2 -- Documentation/config/difftool.txt | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/config/diff.txt b/Documentation/config/diff.txt index fdae13a212..1135a62a0a 100644 --- a/Documentation/config/diff.txt +++ b/Documentation/config/diff.txt @@ -218,8 +218,6 @@ endif::git-diff[] Set this option to `true` to make the diff driver cache the text conversion outputs. See linkgit:gitattributes[5] for details. -include::{build_dir}/mergetools-diff.txt[] - `diff.indentHeuristic`:: Set this option to `false` to disable the default heuristics that shift diff hunk boundaries to make patches easier to read. diff --git a/Documentation/config/difftool.txt b/Documentation/config/difftool.txt index 447c40d85a..6cd47331a9 100644 --- a/Documentation/config/difftool.txt +++ b/Documentation/config/difftool.txt @@ -13,6 +13,8 @@ diff.guitool:: and requires that a corresponding difftool..cmd variable is defined. +include::{build_dir}/mergetools-diff.txt[] + difftool..cmd:: Specify the command to invoke the specified diff tool. The specified command is evaluated in shell with the following -- cgit v1.3 From cf5b8276dcfdad44f02c082a934be5589ff14586 Mon Sep 17 00:00:00 2001 From: M Hickford Date: Fri, 10 Jan 2025 22:54:36 +0000 Subject: docs: list popular credential helpers git-credential-store saves credentials unencrypted on disk. It is the least secure choice of credential helper. Nevertheless, it appears several times more popular than any other credential helper [1]. Inform users about more secure alternatives. [1] https://stackoverflow.com/questions/35942754/how-can-i-save-username-and-password-in-git Signed-off-by: M Hickford Signed-off-by: Junio C Hamano --- Documentation/gitcredentials.txt | 41 ++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.txt index 35a7452c8f..3337bb475d 100644 --- a/Documentation/gitcredentials.txt +++ b/Documentation/gitcredentials.txt @@ -66,18 +66,7 @@ storage provided by the OS or other programs. Alternatively, a credential-generating helper might generate credentials for certain servers via some API. -To use a helper, you must first select one to use. Git currently -includes the following helpers: - -cache:: - - Cache credentials in memory for a short period of time. See - linkgit:git-credential-cache[1] for details. - -store:: - - Store credentials indefinitely on disk. See - linkgit:git-credential-store[1] for details. +To use a helper, you must first select one to use (see below for a list). You may also have third-party helpers installed; search for `credential-*` in the output of `git help -a`, and consult the @@ -106,6 +95,28 @@ $ git config --global credential.helper foo === Available helpers +Git currently includes the following helpers: + +cache:: + + Cache credentials in memory for a short period of time. See + linkgit:git-credential-cache[1] for details. + +store:: + + Store credentials indefinitely on disk. See + linkgit:git-credential-store[1] for details. + +Popular helpers with secure persistent storage include: + + - git-credential-libsecret (Linux) + + - git-credential-osxkeychain (macOS) + + - git-credential-wincred (Windows) + + - https://github.com/git-ecosystem/git-credential-manager[Git Credential Manager] (cross platform, included in Git for Windows) + The community maintains a comprehensive list of Git credential helpers at https://git-scm.com/doc/credential-helpers. @@ -116,6 +127,12 @@ OAuth credential helper. Initial authentication opens a browser window to the host. Subsequent authentication happens in the background. Many popular Git hosts support OAuth. +Popular helpers with OAuth support include: + + - https://github.com/git-ecosystem/git-credential-manager[Git Credential Manager] (cross platform, included in Git for Windows) + + - https://github.com/hickford/git-credential-oauth[git-credential-oauth] (cross platform, included in many Linux distributions) + CREDENTIAL CONTEXTS ------------------- -- cgit v1.3 From a90ff409f0490aef6266f17656fa626154af9715 Mon Sep 17 00:00:00 2001 From: M Hickford Date: Fri, 10 Jan 2025 22:54:37 +0000 Subject: docs: discuss caching personal access tokens Describe problems storing personal access tokens in git-credential-cache and suggest alternatives. Research suggests that many users are confused about this: > the point of passwords is that (ideally) you memorise them [so] > they're never stored anywhere in plain text. Yet GitHub's personal > access token system seems to basically force you to store the token in > plain text? https://stackoverflow.com/questions/46645843/where-to-store-my-git-personal-access-token#comment89963004_46645843 Signed-off-by: M Hickford Signed-off-by: Junio C Hamano --- Documentation/git-credential-cache.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'Documentation') diff --git a/Documentation/git-credential-cache.txt b/Documentation/git-credential-cache.txt index 487cc557a8..54fa7a27e1 100644 --- a/Documentation/git-credential-cache.txt +++ b/Documentation/git-credential-cache.txt @@ -78,6 +78,23 @@ variable (this example increases the cache time to 1 hour): $ git config credential.helper 'cache --timeout=3600' ------------------------------------------------------- +PERSONAL ACCESS TOKENS +---------------------- + +Some remotes accept personal access tokens, which are randomly +generated and hard to memorise. They typically have a lifetime of weeks +or months. + +git-credential-cache is inherently unsuitable for persistent storage of +personal access tokens. The credential will be forgotten after the cache +timeout. Even if you configure a long timeout, credentials will be +forgotten if the daemon dies. + +To avoid frequently regenerating personal access tokens, configure a +credential helper with persistent storage. Alternatively, configure an +OAuth credential helper to generate credentials automatically. See +linkgit:gitcredentials[7], sections "Available helpers" and "OAuth". + GIT --- Part of the linkgit:git[1] suite -- cgit v1.3 From 77b2d29e91c568dc3b08adbfc48fea641d4e39f7 Mon Sep 17 00:00:00 2001 From: Jean-Noël Avila Date: Fri, 10 Jan 2025 10:08:23 +0000 Subject: doc: convert git-notes to new documentation format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Switch the synopsis to a synopsis block which will automatically format placeholders in italics and keywords in monospace - Use __ instead of in the description - Use `backticks` for keywords and more complex option descriptions. The new rendering engine will apply synopsis rules to these spans. Signed-off-by: Jean-Noël Avila Signed-off-by: Junio C Hamano --- Documentation/config/notes.txt | 32 +++---- Documentation/git-notes.txt | 191 +++++++++++++++++++++-------------------- 2 files changed, 112 insertions(+), 111 deletions(-) (limited to 'Documentation') diff --git a/Documentation/config/notes.txt b/Documentation/config/notes.txt index 43db8e808d..b7e536496f 100644 --- a/Documentation/config/notes.txt +++ b/Documentation/config/notes.txt @@ -1,4 +1,4 @@ -notes.mergeStrategy:: +`notes.mergeStrategy`:: Which merge strategy to choose by default when resolving notes conflicts. Must be one of `manual`, `ours`, `theirs`, `union`, or `cat_sort_uniq`. Defaults to `manual`. See the "NOTES MERGE STRATEGIES" @@ -7,17 +7,17 @@ notes.mergeStrategy:: This setting can be overridden by passing the `--strategy` option to linkgit:git-notes[1]. -notes..mergeStrategy:: +`notes..mergeStrategy`:: Which merge strategy to choose when doing a notes merge into - refs/notes/. This overrides the more general - "notes.mergeStrategy". See the "NOTES MERGE STRATEGIES" section in + `refs/notes/`. This overrides the more general + `notes.mergeStrategy`. See the "NOTES MERGE STRATEGIES" section in linkgit:git-notes[1] for more information on the available strategies. -notes.displayRef:: +`notes.displayRef`:: Which ref (or refs, if a glob or specified more than once), in addition to the default set by `core.notesRef` or `GIT_NOTES_REF`, to read notes from when showing commit - messages with the 'git log' family of commands. + messages with the `git log` family of commands. + This setting can be overridden with the `GIT_NOTES_DISPLAY_REF` environment variable, which must be a colon separated list of refs or @@ -26,27 +26,27 @@ globs. A warning will be issued for refs that do not exist, but a glob that does not match any refs is silently ignored. + -This setting can be disabled by the `--no-notes` option to the 'git -log' family of commands, or by the `--notes=` option accepted by +This setting can be disabled by the `--no-notes` option to the linkgit:git-log[1] +family of commands, or by the `--notes=` option accepted by those commands. + -The effective value of "core.notesRef" (possibly overridden by -GIT_NOTES_REF) is also implicitly added to the list of refs to be +The effective value of `core.notesRef` (possibly overridden by +`GIT_NOTES_REF`) is also implicitly added to the list of refs to be displayed. -notes.rewrite.:: - When rewriting commits with (currently `amend` or +`notes.rewrite.`:: + When rewriting commits with __ (currently `amend` or `rebase`), if this variable is `false`, git will not copy notes from the original to the rewritten commit. Defaults to - `true`. See also "`notes.rewriteRef`" below. + `true`. See also `notes.rewriteRef` below. + This setting can be overridden with the `GIT_NOTES_REWRITE_REF` environment variable, which must be a colon separated list of refs or globs. -notes.rewriteMode:: +`notes.rewriteMode`:: When copying notes during a rewrite (see the - "notes.rewrite." option), determines what to do if + `notes.rewrite.` option), determines what to do if the target commit already has a note. Must be one of `overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`. Defaults to `concatenate`. @@ -54,7 +54,7 @@ notes.rewriteMode:: This setting can be overridden with the `GIT_NOTES_REWRITE_MODE` environment variable. -notes.rewriteRef:: +`notes.rewriteRef`:: When copying notes during a rewrite, specifies the (fully qualified) ref whose notes should be copied. May be a glob, in which case notes in all matching refs will be copied. You diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index 84022f99d7..5c8e6ff566 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -7,19 +7,19 @@ git-notes - Add or inspect object notes SYNOPSIS -------- -[verse] -'git notes' [list []] -'git notes' add [-f] [--allow-empty] [--[no-]separator | --separator=] [--[no-]stripspace] [-F | -m | (-c | -C) ] [-e] [] -'git notes' copy [-f] ( --stdin | [] ) -'git notes' append [--allow-empty] [--[no-]separator | --separator=] [--[no-]stripspace] [-F | -m | (-c | -C) ] [-e] [] -'git notes' edit [--allow-empty] [] [--[no-]stripspace] -'git notes' show [] -'git notes' merge [-v | -q] [-s ] -'git notes' merge --commit [-v | -q] -'git notes' merge --abort [-v | -q] -'git notes' remove [--ignore-missing] [--stdin] [...] -'git notes' prune [-n] [-v] -'git notes' get-ref +[synopsis] +git notes [list []] +git notes add [-f] [--allow-empty] [--[no-]separator | --separator=] [--[no-]stripspace] [-F | -m | (-c | -C) ] [-e] [] +git notes copy [-f] ( --stdin | [] ) +git notes append [--allow-empty] [--[no-]separator | --separator=] [--[no-]stripspace] [-F | -m | (-c | -C) ] [-e] [] +git notes edit [--allow-empty] [] [--[no-]stripspace] +git notes show [] +git notes merge [-v | -q] [-s ] +git notes merge --commit [-v | -q] +git notes merge --abort [-v | -q] +git notes remove [--ignore-missing] [--stdin] [...] +git notes prune [-n] [-v] +git notes get-ref DESCRIPTION @@ -33,34 +33,34 @@ ENVIRONMENT sections below. If this ref does not exist, it will be quietly created when it is first needed to store a note. A typical use of notes is to supplement a commit message without -changing the commit itself. Notes can be shown by 'git log' along with +changing the commit itself. Notes can be shown by `git log` along with the original commit message. To distinguish these notes from the message stored in the commit object, the notes are indented like the -message, after an unindented line saying "Notes ():" (or +message, after an unindented line saying "Notes (__):" (or "Notes:" for `refs/notes/commits`). Notes can also be added to patches prepared with `git format-patch` by using the `--notes` option. Such notes are added as a patch commentary after a three dash separator line. -To change which notes are shown by 'git log', see the -"notes.displayRef" discussion in <>. +To change which notes are shown by `git log`, see the +`notes.displayRef` discussion in <>. -See the "notes.rewrite." configuration for a way to carry +See the `notes.rewrite.` configuration for a way to carry notes across commands that rewrite commits. SUBCOMMANDS ----------- -list:: +`list`:: List the notes object for a given object. If no object is given, show a list of all note objects and the objects they - annotate (in the format " "). + annotate (in the format "` `"). This is the default subcommand if no subcommand is given. -add:: - Add notes for a given object (defaults to HEAD). Abort if the +`add`:: + Add notes for a given object (defaults to `HEAD`). Abort if the object already has notes (use `-f` to overwrite existing notes). However, if you're using `add` interactively (using an editor to supply the notes contents), then - instead of aborting - @@ -71,10 +71,10 @@ add:: fine-tune the message(s) supplied from `-m` and `-F` options interactively (using an editor) before adding the note. -copy:: +`copy`:: Copy the notes for the first object onto the second object (defaults to - HEAD). Abort if the second object already has notes, or if the first - object has none (use -f to overwrite existing notes to the + `HEAD`). Abort if the second object already has notes, or if the first + object has none (use `-f` to overwrite existing notes to the second object). This subcommand is equivalent to: `git notes add [-f] -C $(git notes list ) ` + @@ -84,27 +84,27 @@ In `--stdin` mode, take lines in the format SP [ SP ] LF ---------- + -on standard input, and copy the notes from each to its -corresponding . (The optional `` is ignored so that +on standard input, and copy the notes from each __ to its +corresponding __. (The optional __ is ignored so that the command can read the input given to the `post-rewrite` hook.) -append:: +`append`:: Append new message(s) given by `-m` or `-F` options to an existing note, or add them as a new note if one does not - exist, for the object (defaults to HEAD). When appending to + exist, for the object (defaults to `HEAD`). When appending to an existing note, a blank line is added before each new message as an inter-paragraph separator. The separator can be customized with the `--separator` option. Edit the notes to be appended given by `-m` and `-F` options with `-e` interactively (using an editor) before appending the note. -edit:: - Edit the notes for a given object (defaults to HEAD). +`edit`:: + Edit the notes for a given object (defaults to `HEAD`). -show:: - Show the notes for a given object (defaults to HEAD). +`show`:: + Show the notes for a given object (defaults to `HEAD`). -merge:: +`merge`:: Merge the given notes ref into the current notes ref. This will try to merge the changes made by the given notes ref (called "remote") since the merge-base (if @@ -112,35 +112,35 @@ merge:: + If conflicts arise and a strategy for automatically resolving conflicting notes (see the "NOTES MERGE STRATEGIES" section) is not given, -the "manual" resolver is used. This resolver checks out the +the `manual` resolver is used. This resolver checks out the conflicting notes in a special worktree (`.git/NOTES_MERGE_WORKTREE`), and instructs the user to manually resolve the conflicts there. When done, the user can either finalize the merge with -'git notes merge --commit', or abort the merge with -'git notes merge --abort'. +`git notes merge --commit`, or abort the merge with +`git notes merge --abort`. -remove:: - Remove the notes for given objects (defaults to HEAD). When +`remove`:: + Remove the notes for given objects (defaults to `HEAD`). When giving zero or one object from the command line, this is equivalent to specifying an empty note message to the `edit` subcommand. -prune:: +`prune`:: Remove all notes for non-existing/unreachable objects. -get-ref:: +`get-ref`:: Print the current notes ref. This provides an easy way to retrieve the current notes ref (e.g. from scripts). OPTIONS ------- --f:: ---force:: +`-f`:: +`--force`:: When adding notes to an object that already has notes, overwrite the existing notes (instead of aborting). --m :: ---message=:: +`-m `:: +`--message=`:: Use the given note message (instead of prompting). If multiple `-m` options are given, their values are concatenated as separate paragraphs. @@ -148,95 +148,96 @@ OPTIONS single line between paragraphs will be stripped out. If you wish to keep them verbatim, use `--no-stripspace`. --F :: ---file=:: - Take the note message from the given file. Use '-' to +`-F `:: +`--file=`:: + Take the note message from the given file. Use `-` to read the note message from the standard input. Lines starting with `#` and empty lines other than a single line between paragraphs will be stripped out. If you wish to keep them verbatim, use `--no-stripspace`. --C :: ---reuse-message=:: +`-C `:: +`--reuse-message=`:: Take the given blob object (for example, another note) as the note message. (Use `git notes copy ` instead to copy notes between objects.). By default, message will be copied verbatim, but if you wish to strip out the lines starting with `#` and empty lines other than a single line - between paragraphs, use with`--stripspace` option. + between paragraphs, use with `--stripspace` option. --c :: ---reedit-message=:: - Like '-C', but with `-c` the editor is invoked, so that +`-c `:: +`--reedit-message=`:: + Like `-C`, but with `-c` the editor is invoked, so that the user can further edit the note message. ---allow-empty:: +`--allow-empty`:: Allow an empty note object to be stored. The default behavior is to automatically remove empty notes. ---[no-]separator, --separator=:: +`--[no-]separator`:: +`--separator=`:: Specify a string used as a custom inter-paragraph separator (a newline is added at the end as needed). If `--no-separator`, no separators will be added between paragraphs. Defaults to a blank line. ---[no-]stripspace:: +`--[no-]stripspace`:: Strip leading and trailing whitespace from the note message. Also strip out empty lines other than a single line between paragraphs. Lines starting with `#` will be stripped out in non-editor cases like `-m`, `-F` and `-C`, but not in editor case like `git notes edit`, `-c`, etc. ---ref :: - Manipulate the notes tree in . This overrides - `GIT_NOTES_REF` and the "core.notesRef" configuration. The ref +`--ref `:: + Manipulate the notes tree in __. This overrides + `GIT_NOTES_REF` and the `core.notesRef` configuration. The ref specifies the full refname when it begins with `refs/notes/`; when it begins with `notes/`, `refs/` and otherwise `refs/notes/` is prefixed to form a full name of the ref. ---ignore-missing:: +`--ignore-missing`:: Do not consider it an error to request removing notes from an object that does not have notes attached to it. ---stdin:: +`--stdin`:: Also read the object names to remove notes from the standard input (there is no reason you cannot combine this with object names from the command line). --n:: ---dry-run:: +`-n`:: +`--dry-run`:: Do not remove anything; just report the object names whose notes would be removed. --s :: ---strategy=:: +`-s `:: +`--strategy=`:: When merging notes, resolve notes conflicts using the given - strategy. The following strategies are recognized: "manual" - (default), "ours", "theirs", "union" and "cat_sort_uniq". - This option overrides the "notes.mergeStrategy" configuration setting. + strategy. The following strategies are recognized: `manual` + (default), `ours`, `theirs`, `union` and `cat_sort_uniq`. + This option overrides the `notes.mergeStrategy` configuration setting. See the "NOTES MERGE STRATEGIES" section below for more information on each notes merge strategy. ---commit:: - Finalize an in-progress 'git notes merge'. Use this option - when you have resolved the conflicts that 'git notes merge' - stored in .git/NOTES_MERGE_WORKTREE. This amends the partial - merge commit created by 'git notes merge' (stored in - .git/NOTES_MERGE_PARTIAL) by adding the notes in - .git/NOTES_MERGE_WORKTREE. The notes ref stored in the - .git/NOTES_MERGE_REF symref is updated to the resulting commit. - ---abort:: - Abort/reset an in-progress 'git notes merge', i.e. a notes merge +`--commit`:: + Finalize an in-progress `git notes merge`. Use this option + when you have resolved the conflicts that `git notes merge` + stored in `.git/NOTES_MERGE_WORKTREE`. This amends the partial + merge commit created by `git notes merge` (stored in + `.git/NOTES_MERGE_PARTIAL`) by adding the notes in + `.git/NOTES_MERGE_WORKTREE`. The notes ref stored in the + `.git/NOTES_MERGE_REF` symref is updated to the resulting commit. + +`--abort`:: + Abort/reset an in-progress `git notes merge`, i.e. a notes merge with conflicts. This simply removes all files related to the notes merge. --q:: ---quiet:: +`-q`:: +`--quiet`:: When merging notes, operate quietly. --v:: ---verbose:: +`-v`:: +`--verbose`:: When merging notes, be more verbose. When pruning notes, report all object names whose notes are removed. @@ -270,28 +271,28 @@ object, in which case the history of the notes can be read with NOTES MERGE STRATEGIES ---------------------- -The default notes merge strategy is "manual", which checks out +The default notes merge strategy is `manual`, which checks out conflicting notes in a special work tree for resolving notes conflicts (`.git/NOTES_MERGE_WORKTREE`), and instructs the user to resolve the conflicts in that work tree. When done, the user can either finalize the merge with -'git notes merge --commit', or abort the merge with -'git notes merge --abort'. +`git notes merge --commit`, or abort the merge with +`git notes merge --abort`. Users may select an automated merge strategy from among the following using -either -s/--strategy option or configuring notes.mergeStrategy accordingly: +either `-s`/`--strategy` option or configuring `notes.mergeStrategy` accordingly: -"ours" automatically resolves conflicting notes in favor of the local +`ours` automatically resolves conflicting notes in favor of the local version (i.e. the current notes ref). -"theirs" automatically resolves notes conflicts in favor of the remote +`theirs` automatically resolves notes conflicts in favor of the remote version (i.e. the given notes ref being merged into the current notes ref). -"union" automatically resolves notes conflicts by concatenating the +`union` automatically resolves notes conflicts by concatenating the local and remote versions. -"cat_sort_uniq" is similar to "union", but in addition to concatenating +`cat_sort_uniq` is similar to `union`, but in addition to concatenating the local and remote versions, this strategy also sorts the resulting lines, and removes duplicate lines from the result. This is equivalent to applying the "cat | sort | uniq" shell pipeline to the local and @@ -320,7 +321,7 @@ Notes: In principle, a note is a regular Git blob, and any kind of (non-)format is accepted. You can binary-safely create notes from -arbitrary files using 'git hash-object': +arbitrary files using `git hash-object`: ------------ $ cc *.c @@ -331,7 +332,7 @@ $ git notes --ref=built add --allow-empty -C "$blob" HEAD (You cannot simply use `git notes --ref=built add -F a.out HEAD` because that is not binary-safe.) Of course, it doesn't make much sense to display non-text-format notes -with 'git log', so if you use such notes, you'll probably need to write +with `git log`, so if you use such notes, you'll probably need to write some special-purpose tools to do something useful with them. @@ -339,7 +340,7 @@ some special-purpose tools to do something useful with them. CONFIGURATION ------------- -core.notesRef:: +`core.notesRef`:: Notes ref to read and manipulate instead of `refs/notes/commits`. Must be an unabbreviated ref name. This setting can be overridden through the environment and -- cgit v1.3 From 69666e6746e4e87535ebf89c463980a9c655bae7 Mon Sep 17 00:00:00 2001 From: Jean-Noël Avila Date: Fri, 10 Jan 2025 10:09:19 +0000 Subject: doc: convert git-restore to new style format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Switch the synopsis to a 'synopsis' block which will automatically format placeholders in italics and keywords in monospace - Use __ instead of in the description - Use backticks for keywords and more complex option descriptions. The new rendering engine will apply synopsis rules to these spans. While at it, also convert an option description to imperative mood. Signed-off-by: Jean-Noël Avila Signed-off-by: Junio C Hamano --- Documentation/git-restore.txt | 110 +++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 55 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-restore.txt b/Documentation/git-restore.txt index 975825b44a..751f01b441 100644 --- a/Documentation/git-restore.txt +++ b/Documentation/git-restore.txt @@ -7,10 +7,10 @@ git-restore - Restore working tree files SYNOPSIS -------- -[verse] -'git restore' [] [--source=] [--staged] [--worktree] [--] ... -'git restore' [] [--source=] [--staged] [--worktree] --pathspec-from-file= [--pathspec-file-nul] -'git restore' (-p|--patch) [] [--source=] [--staged] [--worktree] [--] [...] +[synopsis] +git restore [] [--source=] [--staged] [--worktree] [--] ... +git restore [] [--source=] [--staged] [--worktree] --pathspec-from-file= [--pathspec-file-nul] +git restore (-p|--patch) [] [--source=] [--staged] [--worktree] [--] [...] DESCRIPTION ----------- @@ -32,8 +32,8 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. OPTIONS ------- --s :: ---source=:: +`-s `:: +`--source=`:: Restore the working tree files with the content from the given tree. It is common to specify the source tree by naming a commit, branch or tag associated with it. @@ -41,79 +41,79 @@ OPTIONS If not specified, the contents are restored from `HEAD` if `--staged` is given, otherwise from the index. + -As a special case, you may use `"A...B"` as a shortcut for the -merge base of `A` and `B` if there is exactly one merge base. You can -leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. +As a special case, you may use `"..."` as a shortcut for the +merge base of __ and __ if there is exactly one merge base. You can +leave out at most one of ___ and __, in which case it defaults to `HEAD`. --p:: ---patch:: +`-p`:: +`--patch`:: Interactively select hunks in the difference between the - restore source and the restore location. See the ``Interactive - Mode'' section of linkgit:git-add[1] to learn how to operate + restore source and the restore location. See the "Interactive + Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. + Note that `--patch` can accept no pathspec and will prompt to restore all modified paths. --W:: ---worktree:: --S:: ---staged:: +`-W`:: +`--worktree`:: +`-S`:: +`--staged`:: Specify the restore location. If neither option is specified, by default the working tree is restored. Specifying `--staged` will only restore the index. Specifying both restores both. --q:: ---quiet:: +`-q`:: +`--quiet`:: Quiet, suppress feedback messages. Implies `--no-progress`. ---progress:: ---no-progress:: +`--progress`:: +`--no-progress`:: Progress status is reported on the standard error stream by default when it is attached to a terminal, unless `--quiet` is specified. This flag enables progress reporting even if not attached to a terminal, regardless of `--quiet`. ---ours:: ---theirs:: +`--ours`:: +`--theirs`:: When restoring files in the working tree from the index, use - stage #2 ('ours') or #3 ('theirs') for unmerged paths. + stage #2 (`ours`) or #3 (`theirs`) for unmerged paths. This option cannot be used when checking out paths from a tree-ish (i.e. with the `--source` option). + -Note that during `git rebase` and `git pull --rebase`, 'ours' and -'theirs' may appear swapped. See the explanation of the same options +Note that during `git rebase` and `git pull --rebase`, `ours` and +`theirs` may appear swapped. See the explanation of the same options in linkgit:git-checkout[1] for details. --m:: ---merge:: +`-m`:: +`--merge`:: When restoring files on the working tree from the index, recreate the conflicted merge in the unmerged paths. This option cannot be used when checking out paths from a tree-ish (i.e. with the `--source` option). ---conflict=