aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Documentation/Makefile3
-rw-r--r--Documentation/MyFirstContribution.txt2
-rw-r--r--Documentation/MyFirstObjectWalk.txt2
-rw-r--r--Documentation/RelNotes/2.38.0.txt33
-rw-r--r--Documentation/ReviewingGuidelines.txt162
-rwxr-xr-xDocumentation/cmd-list.perl2
-rw-r--r--Documentation/git.txt2
-rw-r--r--Documentation/gitprotocol-capabilities.txt4
-rw-r--r--Documentation/gitprotocol-v2.txt4
-rw-r--r--Documentation/scalar.txt (renamed from contrib/scalar/scalar.txt)4
-rw-r--r--Documentation/technical/api-error-handling.txt2
-rw-r--r--Documentation/technical/api-parse-options.txt2
-rw-r--r--Documentation/technical/bundle-uri.txt9
-rw-r--r--Documentation/technical/commit-graph.txt4
-rw-r--r--Documentation/technical/remembering-renames.txt2
-rw-r--r--Documentation/technical/scalar.txt61
-rw-r--r--Documentation/user-manual.txt2
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile32
-rw-r--r--advice.c19
-rw-r--r--advice.h1
-rw-r--r--builtin/clone.c2
-rw-r--r--builtin/diagnose.c2
-rw-r--r--builtin/fetch-pack.c1
-rw-r--r--builtin/fetch.c2
-rw-r--r--builtin/gc.c6
-rw-r--r--builtin/help.c2
-rw-r--r--builtin/ls-files.c2
-rw-r--r--builtin/mv.c161
-rw-r--r--builtin/submodule--helper.c7
-rw-r--r--bundle.h1
-rw-r--r--command-list.txt3
-rw-r--r--commit-graph.c2
-rw-r--r--contrib/buildsystems/CMakeLists.txt11
-rw-r--r--contrib/scalar/.gitignore2
-rw-r--r--contrib/scalar/Makefile35
-rw-r--r--contrib/scalar/t/Makefile81
-rw-r--r--contrib/subtree/t/Makefile1
-rw-r--r--diagnose.c70
-rw-r--r--help.c2
-rw-r--r--list-objects-filter-options.c85
-rw-r--r--list-objects-filter-options.h5
-rw-r--r--po/id.po2628
-rw-r--r--reftable/merged.c4
-rw-r--r--reftable/pq.c4
-rw-r--r--reftable/pq.h2
-rw-r--r--reftable/pq_test.c2
-rw-r--r--revision.c1
-rw-r--r--scalar.c (renamed from contrib/scalar/scalar.c)20
-rw-r--r--t/Makefile50
-rw-r--r--t/README5
-rwxr-xr-xt/chainlint.pl770
-rw-r--r--t/chainlint.sed399
-rw-r--r--t/chainlint/blank-line-before-esac.expect18
-rw-r--r--t/chainlint/blank-line-before-esac.test19
-rw-r--r--t/chainlint/block.expect15
-rw-r--r--t/chainlint/block.test15
-rw-r--r--t/chainlint/chain-break-background.expect9
-rw-r--r--t/chainlint/chain-break-background.test10
-rw-r--r--t/chainlint/chain-break-continue.expect12
-rw-r--r--t/chainlint/chain-break-continue.test13
-rw-r--r--t/chainlint/chain-break-false.expect9
-rw-r--r--t/chainlint/chain-break-false.test10
-rw-r--r--t/chainlint/chain-break-return-exit.expect19
-rw-r--r--t/chainlint/chain-break-return-exit.test23
-rw-r--r--t/chainlint/chain-break-status.expect9
-rw-r--r--t/chainlint/chain-break-status.test11
-rw-r--r--t/chainlint/chained-block.expect9
-rw-r--r--t/chainlint/chained-block.test11
-rw-r--r--t/chainlint/chained-subshell.expect10
-rw-r--r--t/chainlint/chained-subshell.test13
-rw-r--r--t/chainlint/command-substitution-subsubshell.expect2
-rw-r--r--t/chainlint/command-substitution-subsubshell.test3
-rw-r--r--t/chainlint/complex-if-in-cuddled-loop.expect2
-rw-r--r--t/chainlint/double-here-doc.expect2
-rw-r--r--t/chainlint/double-here-doc.test12
-rw-r--r--t/chainlint/dqstring-line-splice.expect3
-rw-r--r--t/chainlint/dqstring-line-splice.test7
-rw-r--r--t/chainlint/dqstring-no-interpolate.expect11
-rw-r--r--t/chainlint/dqstring-no-interpolate.test15
-rw-r--r--t/chainlint/empty-here-doc.expect3
-rw-r--r--t/chainlint/empty-here-doc.test5
-rw-r--r--t/chainlint/exclamation.expect4
-rw-r--r--t/chainlint/exclamation.test8
-rw-r--r--t/chainlint/for-loop-abbreviated.expect5
-rw-r--r--t/chainlint/for-loop-abbreviated.test6
-rw-r--r--t/chainlint/for-loop.expect4
-rw-r--r--t/chainlint/function.expect11
-rw-r--r--t/chainlint/function.test13
-rw-r--r--t/chainlint/here-doc-indent-operator.expect5
-rw-r--r--t/chainlint/here-doc-indent-operator.test13
-rw-r--r--t/chainlint/here-doc-multi-line-string.expect3
-rw-r--r--t/chainlint/if-condition-split.expect7
-rw-r--r--t/chainlint/if-condition-split.test8
-rw-r--r--t/chainlint/if-in-loop.expect2
-rw-r--r--t/chainlint/if-in-loop.test2
-rw-r--r--t/chainlint/loop-detect-failure.expect15
-rw-r--r--t/chainlint/loop-detect-failure.test17
-rw-r--r--t/chainlint/loop-detect-status.expect18
-rw-r--r--t/chainlint/loop-detect-status.test19
-rw-r--r--t/chainlint/loop-in-if.expect2
-rw-r--r--t/chainlint/loop-upstream-pipe.expect10
-rw-r--r--t/chainlint/loop-upstream-pipe.test11
-rw-r--r--t/chainlint/multi-line-string.expect11
-rw-r--r--t/chainlint/nested-loop-detect-failure.expect31
-rw-r--r--t/chainlint/nested-loop-detect-failure.test35
-rw-r--r--t/chainlint/nested-subshell.expect2
-rw-r--r--t/chainlint/one-liner-for-loop.expect9
-rw-r--r--t/chainlint/one-liner-for-loop.test10
-rw-r--r--t/chainlint/return-loop.expect5
-rw-r--r--t/chainlint/return-loop.test6
-rw-r--r--t/chainlint/semicolon.expect2
-rw-r--r--t/chainlint/sqstring-in-sqstring.expect4
-rw-r--r--t/chainlint/sqstring-in-sqstring.test5
-rw-r--r--t/chainlint/t7900-subtree.expect13
-rw-r--r--t/chainlint/token-pasting.expect27
-rw-r--r--t/chainlint/token-pasting.test32
-rw-r--r--t/chainlint/while-loop.expect4
-rw-r--r--t/perf/README4
-rwxr-xr-xt/perf/p9210-scalar.sh39
-rw-r--r--t/perf/perf-lib.sh13
-rwxr-xr-xt/perf/run3
-rwxr-xr-xt/t0012-help.sh2
-rwxr-xr-xt/t0027-auto-crlf.sh7
-rwxr-xr-xt/t0092-diagnose.sh12
-rwxr-xr-xt/t1800-hook.sh6
-rwxr-xr-xt/t3070-wildmatch.sh5
-rwxr-xr-xt/t7002-mv-sparse-checkout.sh226
-rwxr-xr-xt/t9210-scalar.sh (renamed from contrib/scalar/t/t9099-scalar.sh)10
-rwxr-xr-xt/t9211-scalar-clone.sh151
-rw-r--r--t/test-lib.sh12
-rw-r--r--transport-helper.c2
-rw-r--r--transport.c1
-rw-r--r--upload-pack.c1
135 files changed, 4167 insertions, 1730 deletions
diff --git a/.gitignore b/.gitignore
index 80b530bbed..b3dcafcb33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -181,10 +181,12 @@
/git-verify-commit
/git-verify-pack
/git-verify-tag
+/git-version
/git-web--browse
/git-whatchanged
/git-worktree
/git-write-tree
+/scalar
/git-core-*/?*
/git.res
/gitweb/GITWEB-BUILD-OPTIONS
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 849af6da30..d47acb2e25 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -21,6 +21,7 @@ MAN1_TXT += $(filter-out \
MAN1_TXT += git.txt
MAN1_TXT += gitk.txt
MAN1_TXT += gitweb.txt
+MAN1_TXT += scalar.txt
# man5 / man7 guides (note: new guides should also be added to command-list.txt)
MAN5_TXT += gitattributes.txt
@@ -102,6 +103,7 @@ SP_ARTICLES += howto/coordinate-embargoed-releases
API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
SP_ARTICLES += $(API_DOCS)
+TECH_DOCS += ReviewingGuidelines
TECH_DOCS += MyFirstContribution
TECH_DOCS += MyFirstObjectWalk
TECH_DOCS += SubmittingPatches
@@ -116,6 +118,7 @@ TECH_DOCS += technical/parallel-checkout
TECH_DOCS += technical/partial-clone
TECH_DOCS += technical/racy-git
TECH_DOCS += technical/reftable
+TECH_DOCS += technical/scalar
TECH_DOCS += technical/send-pack-pipeline
TECH_DOCS += technical/shallow
TECH_DOCS += technical/trivial-merge
diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.txt
index 1da15d9ad4..1a4be8ee0a 100644
--- a/Documentation/MyFirstContribution.txt
+++ b/Documentation/MyFirstContribution.txt
@@ -1160,7 +1160,7 @@ all named like `v2-000n-my-commit-subject.patch`. `-v2` will also format
your patches by prefixing them with "[PATCH v2]" instead of "[PATCH]",
and your range-diff will be prefaced with "Range-diff against v1".
-Afer you run this command, `format-patch` will output the patches to the `psuh/`
+After you run this command, `format-patch` will output the patches to the `psuh/`
directory, alongside the v1 patches. Using a single directory makes it easy to
refer to the old v1 patches while proofreading the v2 patches, but you will need
to be careful to send out only the v2 patches. We will use a pattern like
diff --git a/Documentation/MyFirstObjectWalk.txt b/Documentation/MyFirstObjectWalk.txt
index 8d9e85566e..eee513e86f 100644
--- a/Documentation/MyFirstObjectWalk.txt
+++ b/Documentation/MyFirstObjectWalk.txt
@@ -534,7 +534,7 @@ the arguments to `traverse_commit_list()`.
- `void *show_data`: A context buffer which is passed in turn to `show_commit`
and `show_object`.
-In addition, `traverse_commit_list_filtered()` has an additional paramter:
+In addition, `traverse_commit_list_filtered()` has an additional parameter:
- `struct oidset *omitted`: A linked-list of object IDs which the provided
filter caused to be omitted.
diff --git a/Documentation/RelNotes/2.38.0.txt b/Documentation/RelNotes/2.38.0.txt
index 01617baa98..870581fc57 100644
--- a/Documentation/RelNotes/2.38.0.txt
+++ b/Documentation/RelNotes/2.38.0.txt
@@ -6,7 +6,7 @@ UI, Workflows & Features
* "git remote show [-n] frotz" now pays attention to negative
pathspec.
- * "git push" sometimes perform poorly when reachability bitmaps are
+ * "git push" sometimes performs poorly when reachability bitmaps are
used, even in a repository where other operations are helped by
bitmaps. The push.useBitmaps configuration variable is introduced
to allow disabling use of reachability bitmaps only for "git push".
@@ -27,7 +27,7 @@ UI, Workflows & Features
what locale they are in by sending Accept-Language HTTP header, but
this was done only for some requests but not others.
- * Introduce a discovery.barerepository configuration variable that
+ * Introduce a safe.barerepository configuration variable that
allows users to forbid discovery of bare repositories.
* Various messages that come from the pack-bitmap codepaths have been
@@ -79,12 +79,15 @@ UI, Workflows & Features
* "git format-patch --from=<ident>" can be told to add an in-body
"From:" line even for commits that are authored by the given
- <ident> with "--force-in-body-from"option.
+ <ident> with "--force-in-body-from" option.
* The built-in fsmonitor refuses to work on a network mounted
repositories; a configuration knob for users to override this has
been introduced.
+ * The "scalar" addition from Microsoft is now part of the core Git
+ installation.
+
Performance, Internal Implementation, Development Support etc.
@@ -127,7 +130,7 @@ Performance, Internal Implementation, Development Support etc.
* The way "git multi-pack" uses parse-options API has been improved.
- * A coccinelle rule (in contrib/) to encourage use of COPY_ARRAY
+ * A Coccinelle rule (in contrib/) to encourage use of COPY_ARRAY
macro has been improved.
* API tweak to make it easier to run fuzz testing on commit-graph parser.
@@ -172,6 +175,12 @@ Performance, Internal Implementation, Development Support etc.
* Share the text used to explain configuration variables used by "git
<subcmd>" in "git help <subcmd>" with the text from "git help config".
+ * "git mv A B" in a sparsely populated working tree can be asked to
+ move a path from a directory that is "in cone" to another directory
+ that is "out of cone". Handling of such a case has been improved.
+
+ * The chainlint script for our tests has been revamped.
+
Fixes since v2.37
-----------------
@@ -297,7 +306,7 @@ Fixes since v2.37
* "git fsck" reads mode from tree objects but canonicalizes the mode
before passing it to the logic to check object sanity, which has
hid broken tree objects from the checking logic. This has been
- corrected, but to help exiting projects with broken tree objects
+ corrected, but to help existing projects with broken tree objects
that they cannot fix retroactively, the severity of anomalies this
code detects has been demoted to "info" for now.
@@ -306,12 +315,10 @@ Fixes since v2.37
* An earlier optimization discarded a tree-object buffer that is
still in use, which has been corrected.
- (merge 1490d7d82d jk/is-promisor-object-keep-tree-in-use later to maint).
* Fix deadlocks between main Git process and subprocess spawned via
the pipe_command() API, that can kill "git add -p" that was
reimplemented in C recently.
- (merge 716c1f649e jk/pipe-command-nonblock later to maint).
* The sequencer machinery translated messages left in the reflog by
mistake, which has been corrected.
@@ -319,20 +326,16 @@ Fixes since v2.37
* xcalloc(), imitating calloc(), takes "number of elements of the
array", and "size of a single element", in this order. A call that
does not follow this ordering has been corrected.
- (merge c4bbd9bb8f sg/xcalloc-cocci-fix later to maint).
* The preload-index codepath made copies of pathspec to give to
multiple threads, which were left leaked.
- (merge 23578904da ad/preload-plug-memleak later to maint).
* Update the version of Ubuntu used for GitHub Actions CI from 18.04
to 22.04.
- (merge ef46584831 ds/github-actions-use-newer-ubuntu later to maint).
* The auto-stashed local changes created by "git merge --autostash"
was mixed into a conflicted state left in the working tree, which
has been corrected.
- (merge d3a9295ada en/merge-unstash-only-on-clean-merge later to maint).
* Multi-pack index got corrupted when preferred pack changed from one
pack to another in a certain way, which has been corrected.
@@ -387,6 +390,14 @@ Fixes since v2.37
been corrected.
(merge 49ca2fba39 jk/proto-v2-ref-prefix-fix later to maint).
+ * A result from opendir() was leaking in the commit-graph expiration
+ codepath, which has been plugged.
+ (merge 12f1ae5324 ml/commit-graph-expire-dir-leak-fix later to maint).
+
+ * Just like we have coding guidelines, we now have guidelines for
+ reviewers.
+ (merge e01b851923 vd/doc-reviewing-guidelines later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge 77b9e85c0f vd/fix-perf-tests later to maint).
(merge 0682bc43f5 jk/test-crontab-fixes later to maint).
diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.txt
new file mode 100644
index 0000000000..0e323d5477
--- /dev/null
+++ b/Documentation/ReviewingGuidelines.txt
@@ -0,0 +1,162 @@
+Reviewing Patches in the Git Project
+====================================
+
+Introduction
+------------
+The Git development community is a widely distributed, diverse, ever-changing
+group of individuals. Asynchronous communication via the Git mailing list poses
+unique challenges when reviewing or discussing patches. This document contains
+some guiding principles and helpful tools you can use to make your reviews both
+more efficient for yourself and more effective for other contributors.
+
+Note that none of the recommendations here are binding or in any way a
+requirement of participation in the Git community. They are provided as a
+resource to supplement your skills as a contributor.
+
+Principles
+----------
+
+Selecting patch(es) to review
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you are looking for a patch series in need of review, start by checking
+latest "What's cooking in git.git" email
+(https://lore.kernel.org/git/xmqqilm1yp3m.fsf@gitster.g/[example]). The "What's
+cooking" emails & replies can be found using the query `s:"What's cooking"` on
+the https://lore.kernel.org/git/[`lore.kernel.org` mailing list archive];
+alternatively, you can find the contents of the "What's cooking" email tracked
+in `whats-cooking.txt` on the `todo` branch of Git. Topics tagged with "Needs
+review" and those in the "[New Topics]" section are typically those that would
+benefit the most from additional review.
+
+Patches can also be searched manually in the mailing list archive using a query
+like `s:"PATCH" -s:"Re:"`. You can browse these results for topics relevant to
+your expertise or interest.
+
+If you've already contributed to Git, you may also be CC'd in another
+contributor's patch series. These are topics where the author feels that your
+attention is warranted. This may be because their patch changes something you
+wrote previously (making you a good judge of whether the new approach does or
+doesn't work), or because you have the expertise to provide an exceptionally
+helpful review. There is no requirement to review these patches but, in the
+spirit of open source collaboration, you should strongly consider doing so.
+
+Reviewing patches
+~~~~~~~~~~~~~~~~~
+While every contributor takes their own approach to reviewing patches, here are
+some general pieces of advice to make your reviews as clear and helpful as
+possible. The advice is broken into two rough categories: high-level reviewing
+guidance, and concrete tips for interacting with patches on the mailing list.
+
+==== High-level guidance
+- Remember to review the content of commit messages for correctness and clarity,
+ in addition to the code change in the patch's diff. The commit message of a
+ patch should accurately and fully explain the code change being made in the
+ diff.
+
+- Reviewing test coverage is an important - but easy to overlook - component of
+ reviews. A patch's changes may be covered by existing tests, or new tests may
+ be introduced to exercise new behavior. Checking out a patch or series locally
+ allows you to manually mutate lines of new & existing tests to verify expected
+ pass/fail behavior. You can use this information to verify proper coverage or
+ to suggest additional tests the author could add.
+
+- When providing a recommendation, be as clear as possible about whether you
+ consider it "blocking" (the code would be broken or otherwise made worse if an
+ issue isn't fixed) or "non-blocking" (the patch could be made better by taking
+ the recommendation, but acceptance of the series does not require it).
+ Non-blocking recommendations can be particularly ambiguous when they are
+ related to - but outside the scope of - a series ("nice-to-have"s), or when
+ they represent only stylistic differences between the author and reviewer.
+
+- When commenting on an issue, try to include suggestions for how the author
+ could fix it. This not only helps the author to understand and fix the issue,
+ it also deepens and improves your understanding of the topic.
+
+- Reviews do not need to exclusively point out problems. Feel free to "think out
+ loud" in your review: describe how you read & understood a complex section of
+ a patch, ask a question about something that confused you, point out something
+ you found exceptionally well-written, etc. In particular, uplifting feedback
+ goes a long way towards encouraging contributors to participate more actively
+ in the Git community.
+
+==== Performing your review
+- Provide your review comments per-patch in a plaintext "Reply-All" email to the
+ relevant patch. Comments should be made inline, immediately below the relevant
+ section(s).
+
+- You may find that the limited context provided in the patch diff is sometimes
+ insufficient for a thorough review. In such cases, you can review patches in
+ your local tree by either applying patches with linkgit:git-am[1] or checking
+ out the associated branch from https://github.com/gitster/git once the series
+ is tracked there.
+
+- Large, complicated patch diffs are sometimes unavoidable, such as when they
+ refactor existing code. If you find such a patch difficult to parse, try
+ reviewing the diff produced with the `--color-moved` and/or
+ `--ignore-space-change` options.
+
+- If a patch is long, you are encouraged to delete parts of it that are
+ unrelated to your review from the email reply. Make sure to leave enough
+ context for readers to understand your comments!
+
+- If you cannot complete a full review of a series all at once, consider letting
+ the author know (on- or off-list) if/when you plan to review the rest of the
+ series.
+
+Completing a review
+~~~~~~~~~~~~~~~~~~~
+Once each patch of a series is reviewed, the author (and/or other contributors)
+may discuss the review(s). This may result in no changes being applied, or the
+author will send a new version of their patch(es).
+
+After a series is rerolled in response to your or others' review, make sure to
+re-review the updates. If you are happy with the state of the patch series,
+explicitly indicate your approval (typically with a reply to the latest
+version's cover letter). Optionally, you can let the author know that they can
+add a "Reviewed-by: <you>" trailer if they resubmit the reviewed patch verbatim
+in a later iteration of the series.
+
+Finally, subsequent "What's cooking" emails may explicitly ask whether a
+reviewed topic is ready for merging to the `next` branch (typically phrased
+"Will merge to \'next\'?"). You can help the maintainer and author by responding
+with a short description of the state of your (and others', if applicable)
+review, including the links to the relevant thread(s).
+
+Terminology
+-----------
+nit: ::
+ Denotes a small issue that should be fixed, such as a typographical error
+ or mis-alignment of conditions in an `if()` statement.
+
+aside: ::
+optional: ::
+non-blocking: ::
+ Indicates to the reader that the following comment should not block the
+ acceptance of the patch or series. These are typically recommendations
+ related to code organization & style, or musings about topics related to
+ the patch in question, but beyond its scope.
+
+s/<before>/<after>/::
+ Shorthand for "you wrote <before>, but I think you meant <after>," usually
+ for misspellings or other typographical errors. The syntax is a reference
+ to "substitute" command commonly found in Unix tools such as `ed`, `sed`,
+ `vim`, and `perl`.
+
+cover letter::
+ The "Patch 0" of a multi-patch series. This email describes the
+ high-level intent and structure of the patch series to readers on the
+ Git mailing list. It is also where the changelog notes and range-diff of
+ subsequent versions are provided by the author.
++
+On single-patch submissions, cover letter content is typically not sent as a
+separate email. Instead, it is inserted between the end of the patch's commit
+message (after the `---`) and the beginning of the diff.
+
+#leftoverbits::
+ Used by either an author or a reviewer to describe features or suggested
+ changes that are out-of-scope of a given patch or series, but are relevant
+ to the topic for the sake of discussion.
+
+See Also
+--------
+link:MyFirstContribution.html[MyFirstContribution]
diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl
index af5da45d28..9515a499a3 100755
--- a/Documentation/cmd-list.perl
+++ b/Documentation/cmd-list.perl
@@ -10,7 +10,7 @@ sub format_one {
$state = 0;
open I, '<', "$name.txt" or die "No such file $name.txt";
while (<I>) {
- if (/^git[a-z0-9-]*\(([0-9])\)$/) {
+ if (/^(git|scalar)[a-z0-9-]*\(([0-9])\)$/) {
$mansection = $1;
next;
}
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 0ef7f5e4ec..0c15ef3a8e 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -344,7 +344,7 @@ Repository, command and file interfaces
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 critera.
+linkgit:git-help[1] for more details on the criteria.
include::cmds-userinterfaces.txt[]
diff --git a/Documentation/gitprotocol-capabilities.txt b/Documentation/gitprotocol-capabilities.txt
index c6dcc7d565..0fb5ea0c1c 100644
--- a/Documentation/gitprotocol-capabilities.txt
+++ b/Documentation/gitprotocol-capabilities.txt
@@ -388,8 +388,8 @@ the server as well.
Session IDs should be unique to a given process. They must fit within a
packet-line, and must not contain non-printable or whitespace characters. The
current implementation uses trace2 session IDs (see
-link:api-trace2.html[api-trace2] for details), but this may change and users of
-the session ID should not rely on this fact.
+link:technical/api-trace2.html[api-trace2] for details), but this may change
+and users of the session ID should not rely on this fact.
GIT
---
diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.txt
index c9c0f9160b..59bf41cefb 100644
--- a/Documentation/gitprotocol-v2.txt
+++ b/Documentation/gitprotocol-v2.txt
@@ -544,8 +544,8 @@ the server as well.
Session IDs should be unique to a given process. They must fit within a
packet-line, and must not contain non-printable or whitespace characters. The
current implementation uses trace2 session IDs (see
-link:api-trace2.html[api-trace2] for details), but this may change and users of
-the session ID should not rely on this fact.
+link:technical/api-trace2.html[api-trace2] for details), but this may change
+and users of the session ID should not rely on this fact.
object-info
~~~~~~~~~~~
diff --git a/contrib/scalar/scalar.txt b/Documentation/scalar.txt
index 1a12dc4507..f33436c7f6 100644
--- a/contrib/scalar/scalar.txt
+++ b/Documentation/scalar.txt
@@ -161,6 +161,6 @@ SEE ALSO
--------
linkgit:git-clone[1], linkgit:git-maintenance[1].
-Scalar
+GIT
---
-Associated with the linkgit:git[1] suite
+Part of the linkgit:git[1] suite
diff --git a/Documentation/technical/api-error-handling.txt b/Documentation/technical/api-error-handling.txt
index 70bf1d3e52..665c4960b4 100644
--- a/Documentation/technical/api-error-handling.txt
+++ b/Documentation/technical/api-error-handling.txt
@@ -46,7 +46,7 @@ parse-options.c.
returns -1 after reporting the situation to the caller.
These reports will be logged via the trace2 facility. See the "error"
-event in link:api-trace2.txt[trace2 API].
+event in link:api-trace2.html[trace2 API].
Customizable error handlers
---------------------------
diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index c2a5e42914..61fa6ee167 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -60,7 +60,7 @@ Subcommands are special in a couple of ways:
* All arguments following the subcommand are considered to be arguments of
the subcommand, and, conversely, arguments meant for the subcommand may
- not preceed the subcommand.
+ not precede the subcommand.
Therefore, if the options array contains at least one subcommand and
`parse_options()` encounters the first dashless argument, it will either:
diff --git a/Documentation/technical/bundle-uri.txt b/Documentation/technical/bundle-uri.txt
index c25c42378a..18f2dedd40 100644
--- a/Documentation/technical/bundle-uri.txt
+++ b/Documentation/technical/bundle-uri.txt
@@ -3,8 +3,7 @@ Bundle URIs
Git bundles are files that store a pack-file along with some extra metadata,
including a set of refs and a (possibly empty) set of necessary commits. See
-linkgit:git-bundle[1] and link:bundle-format.txt[the bundle format] for more
-information.
+linkgit:git-bundle[1] and linkgit:gitformat-bundle[5] for more information.
Bundle URIs are locations where Git can download one or more bundles in
order to bootstrap the object database in advance of fetching the remaining
@@ -290,7 +289,7 @@ expect that the process will end when all prerequisite commit OIDs in a
thin bundle are already in the object database.
When using the `creationToken` heuristic, the client can avoid downloading
-any bundles if their creation tokenss are not larger than the stored
+any bundles if their creation tokens are not larger than the stored
creation token. After fetching new bundles, Git updates this local
creation token.
@@ -319,7 +318,7 @@ Here are a few example error conditions:
Git's other HTTP protocols in terms of handling specific 400-level
errors.
-* The server reports any other failure reponse.
+* The server reports any other failure response.
* The client receives data that is not parsable as a bundle or bundle list.
@@ -447,7 +446,7 @@ created every hour, and then once a day those "hourly" bundles could be
merged into a "daily" bundle. The daily bundles are merged into the
oldest bundle after 30 days.
-It is recommened that this bundle strategy is repeated with the `blob:none`
+It is recommended that this bundle strategy is repeated with the `blob:none`
filter if clients of this repository are expecting to use blobless partial
clones. This list of blobless bundles stays in the same list as the full
bundles, but uses the `bundle.<id>.filter` key to separate the two groups.
diff --git a/Documentation/technical/commit-graph.txt b/Documentation/technical/commit-graph.txt
index f05e7bda1a..90c9760c23 100644
--- a/Documentation/technical/commit-graph.txt
+++ b/Documentation/technical/commit-graph.txt
@@ -40,7 +40,7 @@ Values 1-4 satisfy the requirements of parse_commit_gently().
There are two definitions of generation number:
1. Corrected committer dates (generation number v2)
-2. Topological levels (generation nummber v1)
+2. Topological levels (generation number v1)
Define "corrected committer date" of a commit recursively as follows:
@@ -48,7 +48,7 @@ Define "corrected committer date" of a commit recursively as follows:
equal to its committer date.
* A commit with at least one parent has corrected committer date equal to
- the maximum of its commiter date and one more than the largest corrected
+ the maximum of its committer date and one more than the largest corrected
committer date among its parents.
* As a special case, a root commit with timestamp zero has corrected commit
diff --git a/Documentation/technical/remembering-renames.txt b/Documentation/technical/remembering-renames.txt
index af091a7556..1e34d91390 100644
--- a/Documentation/technical/remembering-renames.txt
+++ b/Documentation/technical/remembering-renames.txt
@@ -407,7 +407,7 @@ considered to be "irrelevant". See for example the following commits:
no longer relevant", 2021-03-13)
Relevance is always determined by what the _other_ side of history has
-done, in terms of modifing a file that our side renamed, or adding a
+done, in terms of modifying a file that our side renamed, or adding a
file to a directory which our side renamed. This means that a path
that is "irrelevant" when picking the first commit of a series in a
rebase or cherry-pick, may suddenly become "relevant" when picking the
diff --git a/Documentation/technical/scalar.txt b/Documentation/technical/scalar.txt
index 0600150b3a..921cb104c3 100644
--- a/Documentation/technical/scalar.txt
+++ b/Documentation/technical/scalar.txt
@@ -64,64 +64,3 @@ some "global" `git` options (e.g., `-c` and `-C`).
Because `scalar` is not invoked as a Git subcommand (like `git scalar`), it is
built and installed as its own executable in the `bin/` directory, alongside
`git`, `git-gui`, etc.
-
-Roadmap
--------
-
-NOTE: this section will be removed once the remaining tasks outlined in this
-roadmap are complete.
-
-Scalar is a large enough project that it is being upstreamed incrementally,
-living in `contrib/` until it is feature-complete. So far, the following patch
-series have been accepted:
-
-- `scalar-the-beginning`: The initial patch series which sets up
- `contrib/scalar/` and populates it with a minimal `scalar` command that
- demonstrates the fundamental ideas.
-
-- `scalar-c-and-C`: The `scalar` command learns about two options that can be
- specified before the command, `-c <key>=<value>` and `-C <directory>`.
-
-- `scalar-diagnose`: The `scalar` command is taught the `diagnose` subcommand.
-
-- `scalar-generalize-diagnose`: Move the functionality of `scalar diagnose`
- into `git diagnose` and `git bugreport --diagnose`.
-
-- 'scalar-add-fsmonitor: Enable the built-in FSMonitor in Scalar
- enlistments. At the end of this series, Scalar should be feature-complete
- from the perspective of a user.
-
-Roughly speaking (and subject to change), the following series are needed to
-"finish" this initial version of Scalar:
-
-- Move Scalar to toplevel: Move Scalar out of `contrib/` and into the root of
- `git`. This includes a variety of related updates, including:
- - building & installing Scalar in the Git root-level 'make [install]'.
- - builing & testing Scalar as part of CI.
- - moving and expanding test coverage of Scalar (including perf tests).
- - implementing 'scalar help'/'git help scalar' to display scalar
- documentation.
-
-Finally, there are two additional patch series that exist in Microsoft's fork of
-Git, but there is no current plan to upstream them. There are some interesting
-ideas there, but the implementation is too specific to Azure Repos and/or VFS
-for Git to be of much help in general.
-
-These still exist mainly because the GVFS protocol is what Azure Repos has
-instead of partial clone, while Git is focused on improving partial clone:
-
-- `scalar-with-gvfs`: The primary purpose of this patch series is to support
- existing Scalar users whose repositories are hosted in Azure Repos (which does
- not support Git's partial clones, but supports its predecessor, the GVFS
- protocol, which is used by Scalar to emulate the partial clone).
-
- Since the GVFS protocol will never be supported by core Git, this patch series
- will remain in Microsoft's fork of Git.
-
-- `run-scalar-functional-tests`: The Scalar project developed a quite
- comprehensive set of integration tests (or, "Functional Tests"). They are the
- sole remaining part of the original C#-based Scalar project, and this patch
- adds a GitHub workflow that runs them all.
-
- Since the tests partially depend on features that are only provided in the
- `scalar-with-gvfs` patch series, this patch cannot be upstreamed.
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index ca9decdd95..dc9c6a663a 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -3133,7 +3133,7 @@ those "loose" objects.
You can save space and make Git faster by moving these loose objects in
to a "pack file", which stores a group of objects in an efficient
compressed format; the details of how pack files are formatted can be
-found in link:gitformat-pack[5].
+found in linkgit:gitformat-pack[5].
To put the loose objects into a pack, just run git repack:
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index ecd94fd3f2..a6d1044e8d 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.38.0-rc0
+DEF_VER=v2.38.0-rc1
LF='
'
diff --git a/Makefile b/Makefile
index d9247ead45..cac3452edb 100644
--- a/Makefile
+++ b/Makefile
@@ -605,7 +605,9 @@ FUZZ_OBJS =
FUZZ_PROGRAMS =
GIT_OBJS =
LIB_OBJS =
+SCALAR_OBJS =
OBJECTS =
+OTHER_PROGRAMS =
PROGRAM_OBJS =
PROGRAMS =
EXCLUDED_PROGRAMS =
@@ -816,13 +818,16 @@ BUILT_INS += git-show$X
BUILT_INS += git-stage$X
BUILT_INS += git-status$X
BUILT_INS += git-switch$X
+BUILT_INS += git-version$X
BUILT_INS += git-whatchanged$X
# what 'all' will build but not install in gitexecdir
-OTHER_PROGRAMS = git$X
+OTHER_PROGRAMS += git$X
+OTHER_PROGRAMS += scalar$X
# what test wrappers are needed and 'install' will install, in bindir
BINDIR_PROGRAMS_NEED_X += git
+BINDIR_PROGRAMS_NEED_X += scalar
BINDIR_PROGRAMS_NEED_X += git-receive-pack
BINDIR_PROGRAMS_NEED_X += git-shell
BINDIR_PROGRAMS_NEED_X += git-upload-archive
@@ -2220,7 +2225,7 @@ profile-fast: profile-clean
all:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
ifneq (,$X)
- $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) git$X)), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';)
+ $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) $(OTHER_PROGRAMS))), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';)
endif
all::
@@ -2543,7 +2548,12 @@ GIT_OBJS += git.o
.PHONY: git-objs
git-objs: $(GIT_OBJS)
+SCALAR_OBJS += scalar.o
+.PHONY: scalar-objs
+scalar-objs: $(SCALAR_OBJS)
+
OBJECTS += $(GIT_OBJS)
+OBJECTS += $(SCALAR_OBJS)
OBJECTS += $(PROGRAM_OBJS)
OBJECTS += $(TEST_OBJS)
OBJECTS += $(XDIFF_OBJS)
@@ -2554,10 +2564,6 @@ ifndef NO_CURL
OBJECTS += http.o http-walker.o remote-curl.o
endif
-SCALAR_SOURCES := contrib/scalar/scalar.c
-SCALAR_OBJECTS := $(SCALAR_SOURCES:c=o)
-OBJECTS += $(SCALAR_OBJECTS)
-
.PHONY: objects
objects: $(OBJECTS)
@@ -2683,7 +2689,7 @@ $(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS)
-contrib/scalar/scalar$X: $(SCALAR_OBJECTS) GIT-LDFLAGS $(GITLIBS)
+scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
$(filter %.o,$^) $(LIBS)
@@ -2739,8 +2745,7 @@ XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \
--keyword=__ --keyword=N__ --keyword="__n:1,2"
MSGMERGE_FLAGS = --add-location --backup=off --update
-LOCALIZED_C = $(sort $(FOUND_C_SOURCES) $(FOUND_H_SOURCES) $(SCALAR_SOURCES) \
- $(GENERATED_H))
+LOCALIZED_C = $(sort $(FOUND_C_SOURCES) $(FOUND_H_SOURCES) $(GENERATED_H))
LOCALIZED_SH = $(sort $(SCRIPT_SH) git-sh-setup.sh)
LOCALIZED_PERL = $(sort $(SCRIPT_PERL))
@@ -3054,7 +3059,7 @@ bin-wrappers/%: wrap-for-bin.sh
$(call mkdir_p_parent_template)
$(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's|@@BUILD_DIR@@|$(shell pwd)|' \
- -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%$(X),$(@F))$(patsubst git%,$(X),$(filter $(@F),$(BINDIR_PROGRAMS_NEED_X)))|' < $< > $@ && \
+ -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%,$(@F))$(if $(filter-out $(BINDIR_PROGRAMS_NO_X),$(@F)),$(X),)|' < $< > $@ && \
chmod +x $@
# GNU make supports exporting all variables by "export" without parameters.
@@ -3268,14 +3273,14 @@ ifndef NO_TCLTK
$(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install
endif
ifneq (,$X)
- $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) git$X)), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
+ $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) $(OTHER_PROGRAMS))), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
endif
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
destdir_from_execdir_SQ=$$(echo '$(gitexecdir_relative_SQ)' | sed -e 's|[^/][^/]*|..|g') && \
{ test "$$bindir/" = "$$execdir/" || \
- for p in git$X $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \
+ for p in $(OTHER_PROGRAMS) $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \
$(RM) "$$execdir/$$p" && \
test -n "$(INSTALL_SYMLINKS)" && \
ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/$$p" "$$execdir/$$p" || \
@@ -3450,7 +3455,7 @@ clean: profile-clean coverage-clean cocciclean
$(RM) git.res
$(RM) $(OBJECTS)
$(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
- $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
+ $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS)
$(RM) $(TEST_PROGRAMS)
$(RM) $(FUZZ_PROGRAMS)
$(RM) $(SP_OBJ)
@@ -3501,6 +3506,7 @@ ALL_COMMANDS += git-citool
ALL_COMMANDS += git-gui
ALL_COMMANDS += gitk
ALL_COMMANDS += gitweb
+ALL_COMMANDS += scalar
.PHONY: check-docs
check-docs::
diff --git a/advice.c b/advice.c
index 6fda9edbc2..fd18968943 100644
--- a/advice.c
+++ b/advice.c
@@ -261,3 +261,22 @@ void detach_advice(const char *new_name)
fprintf(stderr, fmt, new_name);
}
+
+void advise_on_moving_dirty_path(struct string_list *pathspec_list)
+{
+ struct string_list_item *item;
+
+ if (!pathspec_list->nr)
+ return;
+
+ fprintf(stderr, _("The following paths have been moved outside the\n"
+ "sparse-checkout definition but are not sparse due to local\n"
+ "modifications.\n"));
+ for_each_string_list_item(item, pathspec_list)
+ fprintf(stderr, "%s\n", item->string);
+
+ advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
+ _("To correct the sparsity of these paths, do the following:\n"
+ "* Use \"git add --sparse <paths>\" to update the index\n"
+ "* Use \"git sparse-checkout reapply\" to apply the sparsity rules"));
+}
diff --git a/advice.h b/advice.h
index 7ddc6cbc1a..07e0f76833 100644
--- a/advice.h
+++ b/advice.h
@@ -74,5 +74,6 @@ void NORETURN die_conclude_merge(void);
void NORETURN die_ff_impossible(void);
void advise_on_updating_sparse_paths(struct string_list *pathspec_list);
void detach_advice(const char *new_name);
+void advise_on_moving_dirty_path(struct string_list *pathspec_list);
#endif /* ADVICE_H */
diff --git a/builtin/clone.c b/builtin/clone.c
index e21d42dfee..d269d6fec6 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -73,7 +73,7 @@ static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;
static int option_dissociate;
static int max_jobs = -1;
static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;
-static struct list_objects_filter_options filter_options;
+static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
static int option_filter_submodules = -1; /* unspecified */
static int config_filter_submodules = -1; /* unspecified */
static struct string_list server_options = STRING_LIST_INIT_NODUP;
diff --git a/builtin/diagnose.c b/builtin/diagnose.c
index cd260c2015..576e0e8e38 100644
--- a/builtin/diagnose.c
+++ b/builtin/diagnose.c
@@ -22,7 +22,7 @@ int cmd_diagnose(int argc, const char **argv, const char *prefix)
N_("specify a destination for the diagnostics archive")),
OPT_STRING('s', "suffix", &option_suffix, N_("format"),
N_("specify a strftime format suffix for the filename")),
- OPT_CALLBACK_F(0, "mode", &mode, N_("(stats|all)"),
+ OPT_CALLBACK_F(0, "mode", &mode, "(stats|all)",
N_("specify the content of the diagnostic archive"),
PARSE_OPT_NONEG, option_parse_diagnose),
OPT_END()
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index f045bbbe94..afe679368d 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -62,6 +62,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
packet_trace_identity("fetch-pack");
memset(&args, 0, sizeof(args));
+ list_objects_filter_init(&args.filter_options);
args.uploadpack = "git-upload-pack";
for (i = 1; i < argc && *argv[i] == '-'; i++) {
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 3aecbe4a3d..a0fca93bb6 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -80,7 +80,7 @@ static int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT;
static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
static int shown_url = 0;
static struct refspec refmap = REFSPEC_INIT_FETCH;
-static struct list_objects_filter_options filter_options;
+static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
static struct string_list server_options = STRING_LIST_INIT_DUP;
static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
static int fetch_write_commit_graph = -1;
diff --git a/builtin/gc.c b/builtin/gc.c
index 0accc02406..2753bd15a5 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1461,7 +1461,7 @@ static char *get_maintpath(void)
}
static char const * const builtin_maintenance_register_usage[] = {
- N_("git maintenance register"),
+ "git maintenance register",
NULL
};
@@ -1519,7 +1519,7 @@ done:
}
static char const * const builtin_maintenance_unregister_usage[] = {
- N_("git maintenance unregister"),
+ "git maintenance unregister",
NULL
};
@@ -2542,7 +2542,7 @@ static int maintenance_start(int argc, const char **argv, const char *prefix)
}
static const char *const builtin_maintenance_stop_usage[] = {
- N_("git maintenance stop"),
+ "git maintenance stop",
NULL
};
diff --git a/builtin/help.c b/builtin/help.c
index 09ac4289f1..6f2796f211 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -440,6 +440,8 @@ static const char *cmd_to_page(const char *git_cmd)
return git_cmd;
else if (is_git_command(git_cmd))
return xstrfmt("git-%s", git_cmd);
+ else if (!strcmp("scalar", git_cmd))
+ return xstrdup(git_cmd);
else
return xstrfmt("git%s", git_cmd);
}
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 779dc18e59..4cf8a23648 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -257,7 +257,7 @@ static size_t expand_show_index(struct strbuf *sb, const char *start,
end = strchr(start + 1, ')');
if (!end)
- die(_("bad ls-files format: element '%s'"
+ die(_("bad ls-files format: element '%s' "
"does not end in ')'"), start);
len = end - start + 1;
diff --git a/builtin/mv.c b/builtin/mv.c
index 4729bb1a1a..3413ad1c9b 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -21,7 +21,6 @@ static const char * const builtin_mv_usage[] = {
};
enum update_mode {
- BOTH = 0,
WORKING_DIRECTORY = (1 << 1),
INDEX = (1 << 2),
SPARSE = (1 << 3),
@@ -72,7 +71,7 @@ static const char **internal_prefix_pathspec(const char *prefix,
static const char *add_slash(const char *path)
{
size_t len = strlen(path);
- if (path[len - 1] != '/') {
+ if (len && path[len - 1] != '/') {
char *with_slash = xmalloc(st_add(len, 2));
memcpy(with_slash, path, len);
with_slash[len++] = '/';
@@ -125,16 +124,15 @@ static int index_range_of_same_dir(const char *src, int length,
}
/*
- * Check if an out-of-cone directory should be in the index. Imagine this case
- * that all the files under a directory are marked with 'CE_SKIP_WORKTREE' bit
- * and thus the directory is sparsified.
- *
- * Return 0 if such directory exist (i.e. with any of its contained files not
- * marked with CE_SKIP_WORKTREE, the directory would be present in working tree).
- * Return 1 otherwise.
+ * Given the path of a directory that does not exist on-disk, check whether the
+ * directory contains any entries in the index with the SKIP_WORKTREE flag
+ * enabled.
+ * Return 1 if such index entries exist.
+ * Return 0 otherwise.
*/
-static int check_dir_in_index(const char *name)
+static int empty_dir_has_sparse_contents(const char *name)
{
+ int ret = 0;
const char *with_slash = add_slash(name);
int length = strlen(with_slash);
@@ -144,14 +142,18 @@ static int check_dir_in_index(const char *name)
if (pos < 0) {
pos = -pos - 1;
if (pos >= the_index.cache_nr)
- return 1;
+ goto free_return;
ce = active_cache[pos];
if (strncmp(with_slash, ce->name, length))
- return 1;
+ goto free_return;
if (ce_skip_worktree(ce))
- return 0;
+ ret = 1;
}
- return 1;
+
+free_return:
+ if (with_slash != name)
+ free((char *)with_slash);
+ return ret;
}
int cmd_mv(int argc, const char **argv, const char *prefix)
@@ -168,12 +170,17 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
OPT_END(),
};
const char **source, **destination, **dest_path, **submodule_gitfile;
- enum update_mode *modes;
+ const char *dst_w_slash;
+ const char **src_dir = NULL;
+ int src_dir_nr = 0, src_dir_alloc = 0;
+ struct strbuf a_src_dir = STRBUF_INIT;
+ enum update_mode *modes, dst_mode = 0;
struct stat st;
struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
struct lock_file lock_file = LOCK_INIT;
struct cache_entry *ce;
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
+ struct string_list dirty_paths = STRING_LIST_INIT_NODUP;
git_config(git_default_config, NULL);
@@ -198,6 +205,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (argc == 1 && is_directory(argv[0]) && !is_directory(argv[1]))
flags = 0;
dest_path = internal_prefix_pathspec(prefix, argv + argc, 1, flags);
+ dst_w_slash = add_slash(dest_path[0]);
submodule_gitfile = xcalloc(argc, sizeof(char *));
if (dest_path[0][0] == '\0')
@@ -205,12 +213,31 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
else if (!lstat(dest_path[0], &st) &&
S_ISDIR(st.st_mode)) {
- dest_path[0] = add_slash(dest_path[0]);
- destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
+ destination = internal_prefix_pathspec(dst_w_slash, argv, argc, DUP_BASENAME);
} else {
- if (argc != 1)
+ if (!path_in_sparse_checkout(dst_w_slash, &the_index) &&
+ empty_dir_has_sparse_contents(dst_w_slash)) {
+ destination = internal_prefix_pathspec(dst_w_slash, argv, argc, DUP_BASENAME);
+ dst_mode = SKIP_WORKTREE_DIR;
+ } else if (argc != 1) {
die(_("destination '%s' is not a directory"), dest_path[0]);
- destination = dest_path;
+ } else {
+ destination = dest_path;
+ /*
+ * <destination> is a file outside of sparse-checkout
+ * cone. Insist on cone mode here for backward
+ * compatibility. We don't want dst_mode to be assigned
+ * for a file when the repo is using no-cone mode (which
+ * is deprecated at this point) sparse-checkout. As
+ * SPARSE here is only considering cone-mode situation.
+ */
+ if (!path_in_cone_mode_sparse_checkout(destination[0], &the_index))
+ dst_mode = SPARSE;
+ }
+ }
+ if (dst_w_slash != dest_path[0]) {
+ free((char *)dst_w_slash);
+ dst_w_slash = NULL;
}
/* Checking */
@@ -232,7 +259,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (pos < 0) {
const char *src_w_slash = add_slash(src);
if (!path_in_sparse_checkout(src_w_slash, &the_index) &&
- !check_dir_in_index(src)) {
+ empty_dir_has_sparse_contents(src)) {
modes[i] |= SKIP_WORKTREE_DIR;
goto dir_check;
}
@@ -290,6 +317,10 @@ dir_check:
/* last - first >= 1 */
modes[i] |= WORKING_DIRECTORY;
+
+ ALLOC_GROW(src_dir, src_dir_nr + 1, src_dir_alloc);
+ src_dir[src_dir_nr++] = src;
+
n = argc + last - first;
REALLOC_ARRAY(source, n);
REALLOC_ARRAY(destination, n);
@@ -346,6 +377,18 @@ dir_check:
goto act_on_entry;
}
+ if (ignore_sparse &&
+ (dst_mode & (SKIP_WORKTREE_DIR | SPARSE)) &&
+ index_entry_exists(&the_index, dst, strlen(dst))) {
+ bad = _("destination exists in the index");
+ if (force) {
+ if (verbose)
+ warning(_("overwriting '%s'"), dst);
+ bad = NULL;
+ } else {
+ goto act_on_entry;
+ }
+ }
/*
* We check if the paths are in the sparse-checkout
* definition as a very final check, since that
@@ -396,6 +439,7 @@ remove_entry:
const char *src = source[i], *dst = destination[i];
enum update_mode mode = modes[i];
int pos;
+ int sparse_and_dirty = 0;
struct checkout state = CHECKOUT_INIT;
state.istate = &the_index;
@@ -406,6 +450,7 @@ remove_entry:
if (show_only)
continue;
if (!(mode & (INDEX | SPARSE | SKIP_WORKTREE_DIR)) &&
+ !(dst_mode & (SKIP_WORKTREE_DIR | SPARSE)) &&
rename(src, dst) < 0) {
if (ignore_errors)
continue;
@@ -425,20 +470,81 @@ remove_entry:
pos = cache_name_pos(src, strlen(src));
assert(pos >= 0);
+ if (!(mode & SPARSE) && !lstat(src, &st))
+ sparse_and_dirty = ce_modified(active_cache[pos], &st, 0);
rename_cache_entry_at(pos, dst);
- if ((mode & SPARSE) &&
- (path_in_sparse_checkout(dst, &the_index))) {
- int dst_pos;
+ if (ignore_sparse &&
+ core_apply_sparse_checkout &&
+ core_sparse_checkout_cone) {
+ /*
+ * NEEDSWORK: we are *not* paying attention to
+ * "out-to-out" move (<source> is out-of-cone and
+ * <destination> is out-of-cone) at this point. It
+ * should be added in a future patch.
+ */
+ if ((mode & SPARSE) &&
+ path_in_sparse_checkout(dst, &the_index)) {
+ /* from out-of-cone to in-cone */
+ int dst_pos = cache_name_pos(dst, strlen(dst));
+ struct cache_entry *dst_ce = active_cache[dst_pos];
+
+ dst_ce->ce_flags &= ~CE_SKIP_WORKTREE;
+
+ if (checkout_entry(dst_ce, &state, NULL, NULL))
+ die(_("cannot checkout %s"), dst_ce->name);
+ } else if ((dst_mode & (SKIP_WORKTREE_DIR | SPARSE)) &&
+ !(mode & SPARSE) &&
+ !path_in_sparse_checkout(dst, &the_index)) {
+ /* from in-cone to out-of-cone */
+ int dst_pos = cache_name_pos(dst, strlen(dst));
+ struct cache_entry *dst_ce = active_cache[dst_pos];
- dst_pos = cache_name_pos(dst, strlen(dst));
- active_cache[dst_pos]->ce_flags &= ~CE_SKIP_WORKTREE;
+ /*
+ * if src is clean, it will suffice to remove it
+ */
+ if (!sparse_and_dirty) {
+ dst_ce->ce_flags |= CE_SKIP_WORKTREE;
+ unlink_or_warn(src);
+ } else {
+ /*
+ * if src is dirty, move it to the
+ * destination and create leading
+ * dirs if necessary
+ */
+ char *dst_dup = xstrdup(dst);
+ string_list_append(&dirty_paths, dst);
+ safe_create_leading_directories(dst_dup);
+ FREE_AND_NULL(dst_dup);
+ rename(src, dst);
+ }
+ }
+ }
+ }
- if (checkout_entry(active_cache[dst_pos], &state, NULL, NULL))
- die(_("cannot checkout %s"), active_cache[dst_pos]->name);
+ /*
+ * cleanup the empty src_dirs
+ */
+ for (i = 0; i < src_dir_nr; i++) {
+ int dummy;
+ strbuf_addstr(&a_src_dir, src_dir[i]);
+ /*
+ * if entries under a_src_dir are all moved away,
+ * recursively remove a_src_dir to cleanup
+ */
+ if (index_range_of_same_dir(a_src_dir.buf, a_src_dir.len,
+ &dummy, &dummy) < 1) {
+ remove_dir_recursively(&a_src_dir, 0);
}
+ strbuf_reset(&a_src_dir);
}
+ strbuf_release(&a_src_dir);
+ free(src_dir);
+
+ if (dirty_paths.nr)
+ advise_on_moving_dirty_path(&dirty_paths);
+
if (gitmodules_modified)
stage_updated_gitmodules(&the_index);
@@ -447,6 +553,7 @@ remove_entry:
die(_("Unable to write new index file"));
string_list_clear(&src_for_dst, 0);
+ string_list_clear(&dirty_paths, 0);
UNLEAK(source);
UNLEAK(dest_path);
free(submodule_gitfile);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ad834f9ed5..0b4acb442b 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1746,8 +1746,10 @@ static int module_clone(int argc, const char **argv, const char *prefix)
{
int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
- struct list_objects_filter_options filter_options = { 0 };
struct string_list reference = STRING_LIST_INIT_NODUP;
+ struct list_objects_filter_options filter_options =
+ LIST_OBJECTS_FILTER_INIT;
+
struct option module_clone_options[] = {
OPT_STRING(0, "prefix", &clone_data.prefix,
N_("path"),
@@ -2620,7 +2622,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct pathspec pathspec = { 0 };
struct pathspec pathspec2 = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
- struct list_objects_filter_options filter_options = { 0 };
+ struct list_objects_filter_options filter_options =
+ LIST_OBJECTS_FILTER_INIT;
int ret;
struct option module_update_options[] = {
OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
diff --git a/bundle.h b/bundle.h
index 0c052f5496..68ff39a0a7 100644
--- a/bundle.h
+++ b/bundle.h
@@ -18,6 +18,7 @@ struct bundle_header {
{ \
.prerequisites = STRING_LIST_INIT_DUP, \
.references = STRING_LIST_INIT_DUP, \
+ .filter = LIST_OBJECTS_FILTER_INIT, \
}
void bundle_header_init(struct bundle_header *header);
void bundle_header_release(struct bundle_header *header);
diff --git a/command-list.txt b/command-list.txt
index f96bdabd7d..54b2a50f5f 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -91,6 +91,7 @@ git-cvsimport foreignscminterface
git-cvsserver foreignscminterface
git-daemon synchingrepositories
git-describe mainporcelain
+git-diagnose ancillaryinterrogators
git-diff mainporcelain info
git-diff-files plumbinginterrogators
git-diff-index plumbinginterrogators
@@ -198,6 +199,7 @@ git-var plumbinginterrogators
git-verify-commit ancillaryinterrogators
git-verify-pack plumbinginterrogators
git-verify-tag ancillaryinterrogators
+git-version ancillaryinterrogators
git-whatchanged ancillaryinterrogators complete
git-worktree mainporcelain
git-write-tree plumbingmanipulators
@@ -235,3 +237,4 @@ gittutorial guide
gittutorial-2 guide
gitweb ancillaryinterrogators
gitworkflows guide
+scalar mainporcelain
diff --git a/commit-graph.c b/commit-graph.c
index 06f7d9e0b6..a7d8755932 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -2265,6 +2265,8 @@ static void expire_commit_graphs(struct write_commit_graph_context *ctx)
}
out:
+ if(dir)
+ closedir(dir);
strbuf_release(&path);
}
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 2237109b57..ea2a531be8 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -610,7 +610,7 @@ unset(CMAKE_REQUIRED_INCLUDES)
#programs
set(PROGRAMS_BUILT
git git-daemon git-http-backend git-sh-i18n--envsubst
- git-shell)
+ git-shell scalar)
if(NOT CURL_FOUND)
list(APPEND excluded_progs git-http-fetch git-http-push)
@@ -757,6 +757,9 @@ target_link_libraries(git-sh-i18n--envsubst common-main)
add_executable(git-shell ${CMAKE_SOURCE_DIR}/shell.c)
target_link_libraries(git-shell common-main)
+add_executable(scalar ${CMAKE_SOURCE_DIR}/scalar.c)
+target_link_libraries(scalar common-main)
+
if(CURL_FOUND)
add_library(http_obj OBJECT ${CMAKE_SOURCE_DIR}/http.c)
@@ -903,7 +906,7 @@ list(TRANSFORM git_perl_scripts PREPEND "${CMAKE_BINARY_DIR}/")
#install
foreach(program ${PROGRAMS_BUILT})
-if(program STREQUAL "git" OR program STREQUAL "git-shell")
+if(program MATCHES "^(git|git-shell|scalar)$")
install(TARGETS ${program}
RUNTIME DESTINATION bin)
else()
@@ -977,7 +980,7 @@ endif()
#wrapper scripts
set(wrapper_scripts
- git git-upload-pack git-receive-pack git-upload-archive git-shell git-remote-ext)
+ git git-upload-pack git-receive-pack git-upload-archive git-shell git-remote-ext scalar)
set(wrapper_test_scripts
test-fake-ssh test-tool)
@@ -1076,7 +1079,7 @@ if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH})
"string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY/../${BUILD_DIR_RELATIVE}\\\"\" content \"\${content}\")\n"
"file(WRITE ${CMAKE_SOURCE_DIR}/t/test-lib.sh \${content})")
#misc copies
- file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.sed DESTINATION ${CMAKE_BINARY_DIR}/t/)
+ file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.pl DESTINATION ${CMAKE_BINARY_DIR}/t/)
file(COPY ${CMAKE_SOURCE_DIR}/po/is.po DESTINATION ${CMAKE_BINARY_DIR}/po/)
file(COPY ${CMAKE_SOURCE_DIR}/mergetools/tkdiff DESTINATION ${CMAKE_BINARY_DIR}/mergetools/)
file(COPY ${CMAKE_SOURCE_DIR}/contrib/completion/git-prompt.sh DESTINATION ${CMAKE_BINARY_DIR}/contrib/completion/)
diff --git a/contrib/scalar/.gitignore b/contrib/scalar/.gitignore
deleted file mode 100644
index ff3d47e84d..0000000000
--- a/contrib/scalar/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/*.exe
-/scalar
diff --git a/contrib/scalar/Makefile b/contrib/scalar/Makefile
deleted file mode 100644
index 37f283f35d..0000000000
--- a/contrib/scalar/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# The default target of this Makefile is...
-all::
-
-# Import tree-wide shared Makefile behavior and libraries
-include ../../shared.mak
-
-include ../../config.mak.uname
--include ../../config.mak.autogen
--include ../../config.mak
-
-TARGETS = scalar$(X) scalar.o
-GITLIBS = ../../common-main.o ../../libgit.a ../../xdiff/lib.a
-
-all:: scalar$(X) ../../bin-wrappers/scalar
-
-$(GITLIBS):
- $(QUIET_SUBDIR0)../.. $(QUIET_SUBDIR1) $(subst ../../,,$@)
-
-$(TARGETS): $(GITLIBS) scalar.c
- $(QUIET_SUBDIR0)../.. $(QUIET_SUBDIR1) $(patsubst %,contrib/scalar/%,$@)
-
-clean:
- $(RM) $(TARGETS) ../../bin-wrappers/scalar
-
-../../bin-wrappers/scalar: ../../wrap-for-bin.sh Makefile
- @mkdir -p ../../bin-wrappers
- $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
- -e 's|@@BUILD_DIR@@|$(shell cd ../.. && pwd)|' \
- -e 's|@@PROG@@|contrib/scalar/scalar$(X)|' < $< > $@ && \
- chmod +x $@
-
-test: all
- $(MAKE) -C t
-
-.PHONY: $(GITLIBS) all clean test FORCE
diff --git a/contrib/scalar/t/Makefile b/contrib/scalar/t/Makefile
deleted file mode 100644
index 1ed174a8cf..0000000000
--- a/contrib/scalar/t/Makefile
+++ /dev/null
@@ -1,81 +0,0 @@
-# Import tree-wide shared Makefile behavior and libraries
-include ../../../shared.mak
-
-# Run scalar tests
-#
-# Copyright (c) 2005,2021 Junio C Hamano, Johannes Schindelin
-#
-
--include ../../../config.mak.autogen
--include ../../../config.mak
-
-SHELL_PATH ?= $(SHELL)
-PERL_PATH ?= /usr/bin/perl
-RM ?= rm -f
-PROVE ?= prove
-DEFAULT_TEST_TARGET ?= test
-TEST_LINT ?= test-lint
-
-ifdef TEST_OUTPUT_DIRECTORY
-TEST_RESULTS_DIRECTORY = $(TEST_OUTPUT_DIRECTORY)/test-results
-else
-TEST_RESULTS_DIRECTORY = ../../../t/test-results
-endif
-
-# Shell quote;
-SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
-PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
-TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY))
-
-T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
-
-all: $(DEFAULT_TEST_TARGET)
-
-test: $(TEST_LINT)
- $(MAKE) aggregate-results-and-cleanup
-
-prove: $(TEST_LINT)
- @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
- $(MAKE) clean-except-prove-cache
-
-$(T):
- @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
-
-clean-except-prove-cache:
- $(RM) -r 'trash directory'.*
- $(RM) -r valgrind/bin
-
-clean: clean-except-prove-cache
- $(RM) .prove
-
-test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
-
-test-lint-duplicates:
- @dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
- test -z "$$dups" || { \
- echo >&2 "duplicate test numbers:" $$dups; exit 1; }
-
-test-lint-executable:
- @bad=`for i in $(T); do test -x "$$i" || echo $$i; done` && \
- test -z "$$bad" || { \
- echo >&2 "non-executable tests:" $$bad; exit 1; }
-
-test-lint-shell-syntax:
- @'$(PERL_PATH_SQ)' ../../../t/check-non-portable-shell.pl $(T)
-
-aggregate-results-and-cleanup: $(T)
- $(MAKE) aggregate-results
- $(MAKE) clean
-
-aggregate-results:
- for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \
- echo "$$f"; \
- done | '$(SHELL_PATH_SQ)' ../../../t/aggregate-results.sh
-
-valgrind:
- $(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind"
-
-test-results:
- mkdir -p test-results
-
-.PHONY: $(T) aggregate-results clean valgrind
diff --git a/contrib/subtree/t/Makefile b/contrib/subtree/t/Makefile
index 3d278bb0ed..4655e0987b 100644
--- a/contrib/subtree/t/Makefile
+++ b/contrib/subtree/t/Makefile
@@ -51,6 +51,7 @@ clean-except-prove-cache:
$(RM) -r valgrind/bin
clean: clean-except-prove-cache
+ $(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
$(RM) .prove
test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
diff --git a/diagnose.c b/diagnose.c
index beb0a8741b..8f26569896 100644
--- a/diagnose.c
+++ b/diagnose.c
@@ -66,17 +66,53 @@ static int dir_file_stats(struct object_directory *object_dir, void *data)
return 0;
}
-static int count_files(char *path)
+/*
+ * Get the d_type of a dirent. If the d_type is unknown, derive it from
+ * stat.st_mode.
+ *
+ * Note that 'path' is assumed to have a trailing slash. It is also modified
+ * in-place during the execution of the function, but is then reverted to its
+ * original value before returning.
+ */
+static unsigned char get_dtype(struct dirent *e, struct strbuf *path)
{
- DIR *dir = opendir(path);
+ struct stat st;
+ unsigned char dtype = DTYPE(e);
+ size_t base_path_len;
+
+ if (dtype != DT_UNKNOWN)
+ return dtype;
+
+ /* d_type unknown in dirent, try to fall back on lstat results */
+ base_path_len = path->len;
+ strbuf_addstr(path, e->d_name);
+ if (lstat(path->buf, &st))
+ goto cleanup;
+
+ /* determine d_type from st_mode */
+ if (S_ISREG(st.st_mode))
+ dtype = DT_REG;
+ else if (S_ISDIR(st.st_mode))
+ dtype = DT_DIR;
+ else if (S_ISLNK(st.st_mode))
+ dtype = DT_LNK;
+
+cleanup:
+ strbuf_setlen(path, base_path_len);
+ return dtype;
+}
+
+static int count_files(struct strbuf *path)
+{
+ DIR *dir = opendir(path->buf);
struct dirent *e;
int count = 0;
if (!dir)
return 0;
- while ((e = readdir(dir)) != NULL)
- if (!is_dot_or_dotdot(e->d_name) && e->d_type == DT_REG)
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL)
+ if (get_dtype(e, path) == DT_REG)
count++;
closedir(dir);
@@ -104,13 +140,13 @@ static void loose_objs_stats(struct strbuf *buf, const char *path)
strbuf_addch(&count_path, '/');
base_path_len = count_path.len;
- while ((e = readdir(dir)) != NULL)
- if (!is_dot_or_dotdot(e->d_name) &&
- e->d_type == DT_DIR && strlen(e->d_name) == 2 &&
+ while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL)
+ if (get_dtype(e, &count_path) == DT_DIR &&
+ strlen(e->d_name) == 2 &&
!hex_to_bytes(&c, e->d_name, 1)) {
strbuf_setlen(&count_path, base_path_len);
- strbuf_addstr(&count_path, e->d_name);
- total += (count = count_files(count_path.buf));
+ strbuf_addf(&count_path, "%s/", e->d_name);
+ total += (count = count_files(&count_path));
strbuf_addf(buf, "%s : %7d files\n", e->d_name, count);
}
@@ -144,22 +180,28 @@ static int add_directory_to_archiver(struct strvec *archiver_args,
len = buf.len;
strvec_pushf(archiver_args, "--prefix=%s", buf.buf);
- while (!res && (e = readdir(dir))) {
- if (!strcmp(".", e->d_name) || !strcmp("..", e->d_name))
- continue;
+ while (!res && (e = readdir_skip_dot_and_dotdot(dir))) {
+ struct strbuf abspath = STRBUF_INIT;
+ unsigned char dtype;
+
+ strbuf_add_absolute_path(&abspath, at_root ? "." : path);
+ strbuf_addch(&abspath, '/');
+ dtype = get_dtype(e, &abspath);
strbuf_setlen(&buf, len);
strbuf_addstr(&buf, e->d_name);
- if (e->d_type == DT_REG)
+ if (dtype == DT_REG)
strvec_pushf(archiver_args, "--add-file=%s", buf.buf);
- else if (e->d_type != DT_DIR)
+ else if (dtype != DT_DIR)
warning(_("skipping '%s', which is neither file nor "
"directory"), buf.buf);
else if (recurse &&
add_directory_to_archiver(archiver_args,
buf.buf, recurse) < 0)
res = -1;
+
+ strbuf_release(&abspath);
}
closedir(dir);
diff --git a/help.c b/help.c
index ec670d5f68..d04542d826 100644
--- a/help.c
+++ b/help.c
@@ -39,7 +39,7 @@ static struct category_description main_categories[] = {
{ CAT_synchingrepositories, N_("Low-level Commands / Syncing Repositories") },
{ CAT_purehelpers, N_("Low-level Commands / Internal Helpers") },
{ CAT_userinterfaces, N_("User-facing repository, command and file interfaces") },
- { CAT_developerinterfaces, N_("Developer-facing file file formats, protocols and interfaces") },
+ { CAT_developerinterfaces, N_("Developer-facing file formats, protocols and other interfaces") },
{ 0, NULL }
};
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 6cc4eb8e1c..5339660238 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -108,7 +108,7 @@ int gently_parse_list_objects_filter(
strbuf_addf(errbuf, _("invalid filter-spec '%s'"), arg);
- memset(filter_options, 0, sizeof(*filter_options));
+ list_objects_filter_init(filter_options);
return 1;
}
@@ -143,6 +143,7 @@ static int parse_combine_subfilter(
ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
filter_options->sub_alloc);
+ list_objects_filter_init(&filter_options->sub[new_index]);
decoded = url_percent_decode(subspec->buf);
@@ -187,10 +188,8 @@ static int parse_combine_filter(
cleanup:
strbuf_list_free(subspecs);
- if (result) {
+ if (result)
list_objects_filter_release(filter_options);
- memset(filter_options, 0, sizeof(*filter_options));
- }
return result;
}
@@ -204,10 +203,10 @@ static int allow_unencoded(char ch)
static void filter_spec_append_urlencode(
struct list_objects_filter_options *filter, const char *raw)
{
- struct strbuf buf = STRBUF_INIT;
- strbuf_addstr_urlencode(&buf, raw, allow_unencoded);
- trace_printf("Add to combine filter-spec: %s\n", buf.buf);
- string_list_append_nodup(&filter->filter_spec, strbuf_detach(&buf, NULL));
+ size_t orig_len = filter->filter_spec.len;
+ strbuf_addstr_urlencode(&filter->filter_spec, raw, allow_unencoded);
+ trace_printf("Add to combine filter-spec: %s\n",
+ filter->filter_spec.buf + orig_len);
}
/*
@@ -225,14 +224,13 @@ static void transform_to_combine_type(
struct list_objects_filter_options *sub_array =
xcalloc(initial_sub_alloc, sizeof(*sub_array));
sub_array[0] = *filter_options;
- memset(filter_options, 0, sizeof(*filter_options));
- string_list_init_dup(&filter_options->filter_spec);
+ list_objects_filter_init(filter_options);
filter_options->sub = sub_array;
filter_options->sub_alloc = initial_sub_alloc;
}
filter_options->sub_nr = 1;
filter_options->choice = LOFC_COMBINE;
- string_list_append(&filter_options->filter_spec, "combine:");
+ strbuf_addstr(&filter_options->filter_spec, "combine:");
filter_spec_append_urlencode(
filter_options,
list_objects_filter_spec(&filter_options->sub[0]));
@@ -240,7 +238,7 @@ static void transform_to_combine_type(
* We don't need the filter_spec strings for subfilter specs, only the
* top level.
*/
- string_list_clear(&filter_options->sub[0].filter_spec, /*free_util=*/0);
+ strbuf_release(&filter_options->sub[0].filter_spec);
}
void list_objects_filter_die_if_populated(
@@ -257,32 +255,32 @@ void parse_list_objects_filter(
struct strbuf errbuf = STRBUF_INIT;
int parse_error;
- if (!filter_options->filter_spec.strdup_strings) {
- if (filter_options->filter_spec.nr)
- BUG("unexpected non-allocated string in filter_spec");
- filter_options->filter_spec.strdup_strings = 1;
- }
+ if (!filter_options->filter_spec.buf)
+ BUG("filter_options not properly initialized");
if (!filter_options->choice) {
- string_list_append(&filter_options->filter_spec, arg);
+ strbuf_addstr(&filter_options->filter_spec, arg);
parse_error = gently_parse_list_objects_filter(
filter_options, arg, &errbuf);
} else {
+ struct list_objects_filter_options *sub;
+
/*
* Make filter_options an LOFC_COMBINE spec so we can trivially
* add subspecs to it.
*/
transform_to_combine_type(filter_options);
- string_list_append(&filter_options->filter_spec, "+");
+ strbuf_addch(&filter_options->filter_spec, '+');
filter_spec_append_urlencode(filter_options, arg);
ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
filter_options->sub_alloc);
+ sub = &filter_options->sub[filter_options->sub_nr - 1];
- parse_error = gently_parse_list_objects_filter(
- &filter_options->sub[filter_options->sub_nr - 1], arg,
- &errbuf);
+ list_objects_filter_init(sub);
+ parse_error = gently_parse_list_objects_filter(sub, arg,
+ &errbuf);
}
if (parse_error)
die("%s", errbuf.buf);
@@ -306,31 +304,18 @@ int opt_parse_list_objects_filter(const struct option *opt,
const char *list_objects_filter_spec(struct list_objects_filter_options *filter)
{
- if (!filter->filter_spec.nr)
+ if (!filter->filter_spec.len)
BUG("no filter_spec available for this filter");
- if (filter->filter_spec.nr != 1) {
- struct strbuf concatted = STRBUF_INIT;
- strbuf_add_separated_string_list(
- &concatted, "", &filter->filter_spec);
- string_list_clear(&filter->filter_spec, /*free_util=*/0);
- string_list_append_nodup(
- &filter->filter_spec, strbuf_detach(&concatted, NULL));
- }
-
- return filter->filter_spec.items[0].string;
+ return filter->filter_spec.buf;
}
const char *expand_list_objects_filter_spec(
struct list_objects_filter_options *filter)
{
if (filter->choice == LOFC_BLOB_LIMIT) {
- struct strbuf expanded_spec = STRBUF_INIT;
- strbuf_addf(&expanded_spec, "blob:limit=%lu",
+ strbuf_release(&filter->filter_spec);
+ strbuf_addf(&filter->filter_spec, "blob:limit=%lu",
filter->blob_limit_value);
- string_list_clear(&filter->filter_spec, /*free_util=*/0);
- string_list_append_nodup(
- &filter->filter_spec,
- strbuf_detach(&expanded_spec, NULL));
}
return list_objects_filter_spec(filter);
@@ -343,12 +328,12 @@ void list_objects_filter_release(
if (!filter_options)
return;
- string_list_clear(&filter_options->filter_spec, /*free_util=*/0);
+ strbuf_release(&filter_options->filter_spec);
free(filter_options->sparse_oid_name);
for (sub = 0; sub < filter_options->sub_nr; sub++)
list_objects_filter_release(&filter_options->sub[sub]);
free(filter_options->sub);
- memset(filter_options, 0, sizeof(*filter_options));
+ list_objects_filter_init(filter_options);
}
void partial_clone_register(
@@ -401,11 +386,11 @@ void partial_clone_get_default_filter_spec(
/*
* Parse default value, but silently ignore it if it is invalid.
*/
- if (!promisor)
+ if (!promisor || !promisor->partial_clone_filter)
return;
- string_list_append(&filter_options->filter_spec,
- promisor->partial_clone_filter);
+ strbuf_addstr(&filter_options->filter_spec,
+ promisor->partial_clone_filter);
gently_parse_list_objects_filter(filter_options,
promisor->partial_clone_filter,
&errbuf);
@@ -417,17 +402,21 @@ void list_objects_filter_copy(
const struct list_objects_filter_options *src)
{
int i;
- struct string_list_item *item;
/* Copy everything. We will overwrite the pointers shortly. */
memcpy(dest, src, sizeof(struct list_objects_filter_options));
- string_list_init_dup(&dest->filter_spec);
- for_each_string_list_item(item, &src->filter_spec)
- string_list_append(&dest->filter_spec, item->string);
+ strbuf_init(&dest->filter_spec, 0);
+ strbuf_addbuf(&dest->filter_spec, &src->filter_spec);
dest->sparse_oid_name = xstrdup_or_null(src->sparse_oid_name);
ALLOC_ARRAY(dest->sub, dest->sub_alloc);
for (i = 0; i < src->sub_nr; i++)
list_objects_filter_copy(&dest->sub[i], &src->sub[i]);
}
+
+void list_objects_filter_init(struct list_objects_filter_options *filter_options)
+{
+ struct list_objects_filter_options blank = LIST_OBJECTS_FILTER_INIT;
+ memcpy(filter_options, &blank, sizeof(*filter_options));
+}
diff --git a/list-objects-filter-options.h b/list-objects-filter-options.h
index ffc02d77e7..7eeadab2dd 100644
--- a/list-objects-filter-options.h
+++ b/list-objects-filter-options.h
@@ -35,7 +35,7 @@ struct list_objects_filter_options {
* To get the raw filter spec given by the user, use the result of
* list_objects_filter_spec().
*/
- struct string_list filter_spec;
+ struct strbuf filter_spec;
/*
* 'choice' is determined by parsing the filter-spec. This indicates
@@ -69,6 +69,9 @@ struct list_objects_filter_options {
*/
};
+#define LIST_OBJECTS_FILTER_INIT { .filter_spec = STRBUF_INIT }
+void list_objects_filter_init(struct list_objects_filter_options *filter_options);
+
/*
* Parse value of the argument to the "filter" keyword.
* On the command line this looks like:
diff --git a/po/id.po b/po/id.po
index 794bf8f1c5..750ac41eea 100644
--- a/po/id.po
+++ b/po/id.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2022-06-21 20:20+0000\n"
+"POT-Creation-Date: 2022-09-19 22:57+0000\n"
"PO-Revision-Date: 2022-06-18 16:30+0700\n"
"Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n"
"Language-Team: Indonesian\n"
@@ -22,7 +22,7 @@ msgstr ""
msgid "Huh (%s)?"
msgstr "Huh (%s)?"
-#: add-interactive.c builtin/rebase.c reset.c sequencer.c
+#: add-interactive.c builtin/merge.c builtin/rebase.c reset.c sequencer.c
msgid "could not read index"
msgstr "tidak dapat membaca indeks"
@@ -203,8 +203,8 @@ msgid "unstaged"
msgstr "tak tergelar"
#: add-interactive.c apply.c builtin/am.c builtin/bugreport.c builtin/clone.c
-#: builtin/fetch.c builtin/merge.c builtin/pull.c builtin/submodule--helper.c
-#: git-add--interactive.perl
+#: builtin/diagnose.c builtin/fetch.c builtin/merge.c builtin/pull.c
+#: builtin/submodule--helper.c git-add--interactive.perl
msgid "path"
msgstr "jalur"
@@ -464,22 +464,22 @@ msgstr ""
#: add-patch.c git-add--interactive.perl
#, c-format, perl-format
msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Terapkan perubahan mode ke indeks dan pohon kerja [y,n,q,a,d%s,?]? "
+msgstr "Terapkan perubahan mode pada indeks dan pohon kerja [y,n,q,a,d%s,?]? "
#: add-patch.c git-add--interactive.perl
#, c-format, perl-format
msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Terapkan penghapusan ke indeks dan pohon kerja [y,n,q,a,d%s,?]? "
+msgstr "Terapkan penghapusan pada indeks dan pohon kerja [y,n,q,a,d%s,?]? "
#: add-patch.c git-add--interactive.perl
#, c-format, perl-format
msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Terapkan penambahan ke indeks dan pohon kerja [y,n,q,a,d%s,?]? "
+msgstr "Terapkan penambahan pada indeks dan pohon kerja [y,n,q,a,d%s,?]? "
#: add-patch.c git-add--interactive.perl
#, c-format, perl-format
msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Terapkan bingkah ini ke indeks dan pohon kerja [y,n,q,a,d%s,?]? "
+msgstr "Terapkan bingkah ini pada indeks dan pohon kerja [y,n,q,a,d%s,?]? "
#: add-patch.c
msgid ""
@@ -495,6 +495,26 @@ msgstr ""
"a - terapkan bingkah ini dan semua bingkah selanjutnya dalam berkas\n"
"d - jangan terapkan bingkah ini atau bingkah selanjutnya dalam berkas\n"
+#: add-patch.c git-add--interactive.perl
+#, c-format, perl-format
+msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? "
+msgstr "Terapkan perubahan mode pada pohon kerja [y,n,q,a,d%s,?]?"
+
+#: add-patch.c git-add--interactive.perl
+#, c-format, perl-format
+msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? "
+msgstr "Terapkan penghapusan pada pohon kerja [y,n,q,a,d%s,?]?"
+
+#: add-patch.c git-add--interactive.perl
+#, c-format, perl-format
+msgid "Apply addition to worktree [y,n,q,a,d%s,?]? "
+msgstr "Terapkan penambahan pada pohon kerja [y,n,q,a,d%s,?]?"
+
+#: add-patch.c git-add--interactive.perl
+#, c-format, perl-format
+msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? "
+msgstr "Terapkan bingkah ini pada pohon kerja [y,n,q,a,d%s,?]?"
+
#: add-patch.c
msgid ""
"y - apply this hunk to worktree\n"
@@ -515,11 +535,6 @@ msgid "could not parse hunk header '%.*s'"
msgstr "tidak dapat menguraikan kepala bingkah '%.*s'"
#: add-patch.c
-#, c-format
-msgid "could not parse colored hunk header '%.*s'"
-msgstr "tidak dapat menguraikan kepala bingkah berwarna '%.*s'"
-
-#: add-patch.c
msgid "could not parse diff"
msgstr "tidak dapat menguraikan diff"
@@ -626,11 +641,11 @@ msgstr ""
#: add-patch.c
msgid "The selected hunks do not apply to the index!"
-msgstr "Bingkah yang dipilih tidak diterapkan ke indeks!"
+msgstr "Bingkah yang dipilih tidak diterapkan pada indeks!"
#: add-patch.c git-add--interactive.perl
msgid "Apply them to the worktree anyway? "
-msgstr "Tetap terapkan itu ke pohon kerja? "
+msgstr "Tetap terapkan pada pohon kerja? "
#: add-patch.c git-add--interactive.perl
msgid "Nothing was applied.\n"
@@ -857,6 +872,26 @@ msgstr ""
"ke false\n"
"\n"
+#: advice.c
+#, c-format
+msgid ""
+"The following paths have been moved outside the\n"
+"sparse-checkout definition but are not sparse due to local\n"
+"modifications.\n"
+msgstr ""
+"Jalur berikut sudah dipindahkan di luar definisi sparse-checkout\n"
+"tetapi bukan jarang karena perubahan lokal.\n"
+
+#: advice.c
+msgid ""
+"To correct the sparsity of these paths, do the following:\n"
+"* Use \"git add --sparse <paths>\" to update the index\n"
+"* Use \"git sparse-checkout reapply\" to apply the sparsity rules"
+msgstr ""
+"Untuk memperbaiki kejarangan jalur tersebut, lakukan hal-hal berikut:\n"
+"* Gunakan \"git add --sparse <jalur>\" untuk memperbarui indeks\n"
+"* Gunakan \"git sparse-checkout reapply\" untuk menerapkan aturan kejarangan"
+
#: alias.c
msgid "cmdline ends with \\"
msgstr "baris perintah diakhiri dengan \\"
@@ -1097,7 +1132,7 @@ msgstr ""
msgid "patch failed: %s:%ld"
msgstr "tambalan gagal: %s:%ld"
-#: apply.c
+#: apply.c builtin/mv.c
#, c-format
msgid "cannot checkout %s"
msgstr "tidak dapat men-checkout %s"
@@ -1495,6 +1530,11 @@ msgstr "tidak dapat mengaruskan blob %s"
msgid "unsupported file mode: 0%o (SHA1: %s)"
msgstr "mode berkas tidak didukung: 0%o (SHA1: %s)"
+#: archive-tar.c archive-zip.c builtin/pack-objects.c
+#, c-format
+msgid "deflate error (%d)"
+msgstr "kesalahan deflasi (%d)"
+
#: archive-tar.c
#, c-format
msgid "unable to start '%s' filter"
@@ -1519,11 +1559,6 @@ msgstr "jalur bukan UTF-8 valid: %s"
msgid "path too long (%d chars, SHA1: %s): %s"
msgstr "jalur terlalu panjang (%d karakter, SHA1: %s): %s"
-#: archive-zip.c builtin/pack-objects.c
-#, c-format
-msgid "deflate error (%d)"
-msgstr "kesalahan deflasi (%d)"
-
#: archive-zip.c
#, c-format
msgid "timestamp too large for this system: %<PRIuMAX>"
@@ -1841,8 +1876,8 @@ msgstr ""
"--reverse dan --first-parent bersama-sama butuh komit terbaru yang disebutkan"
#: blame.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c bundle.c midx.c ref-filter.c
-#: remote.c sequencer.c submodule.c
+#: builtin/pack-objects.c builtin/shortlog.c bundle.c midx.c pack-bitmap.c
+#: ref-filter.c remote.c sequencer.c submodule.c
msgid "revision walk setup failed"
msgstr "persiapan jalan revisi gagal"
@@ -2248,19 +2283,19 @@ msgstr ""
#: builtin/reset.c builtin/rm.c builtin/submodule--helper.c read-cache.c
#: rerere.c submodule.c
msgid "index file corrupt"
-msgstr ""
+msgstr "berkas indeks rusak"
#: builtin/am.c builtin/mailinfo.c mailinfo.c
#, c-format
msgid "bad action '%s' for '%s'"
-msgstr ""
+msgstr "tindakan jelek '%s' untuk '%s'"
#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
#: builtin/pull.c diff-merges.c gpg-interface.c ls-refs.c parallel-checkout.c
#: sequencer.c setup.c
#, c-format
msgid "invalid value for '%s': '%s'"
-msgstr ""
+msgstr "nilai tidak valid untuk '%s': '%s'"
#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c
#, c-format
@@ -2274,7 +2309,7 @@ msgstr "tidak dapat mengurai skrip pengarang"
#: builtin/am.c builtin/replace.c commit.c sequencer.c
#, c-format
msgid "could not parse %s"
-msgstr ""
+msgstr "tidak dapat menguraikan %s"
#: builtin/am.c
#, c-format
@@ -2300,7 +2335,7 @@ msgstr "fseek gagal"
msgid "could not open '%s' for reading"
msgstr "tidak dapat membuka '%s' untuk dibaca"
-#: builtin/am.c builtin/rebase.c strbuf.c wrapper.c
+#: builtin/am.c builtin/rebase.c sequencer.c strbuf.c wrapper.c
#, c-format
msgid "could not open '%s' for writing"
msgstr "tidak dapat membuka '%s' untuk ditulis"
@@ -2384,7 +2419,7 @@ msgstr "baris identitas tidak valid: %.*s"
#: builtin/am.c builtin/checkout.c builtin/clone.c commit-graph.c
#, c-format
msgid "unable to parse commit %s"
-msgstr ""
+msgstr "tidak dapat menguraikan komit %s"
#: builtin/am.c
msgid "Repository lacks necessary blobs to fall back on 3-way merge."
@@ -2618,8 +2653,8 @@ msgid "n"
msgstr "n"
#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
-#: builtin/for-each-ref.c builtin/ls-tree.c builtin/replace.c builtin/tag.c
-#: builtin/verify-tag.c
+#: builtin/diagnose.c builtin/for-each-ref.c builtin/ls-files.c
+#: builtin/ls-tree.c builtin/replace.c builtin/tag.c builtin/verify-tag.c
msgid "format"
msgstr "format"
@@ -2723,7 +2758,7 @@ msgstr "mode interaktif butuh tambalan pada baris perintah"
msgid "git apply [<options>] [<patch>...]"
msgstr "git apply [<opsi>] [<tambalan>...]"
-#: builtin/archive.c contrib/scalar/scalar.c
+#: builtin/archive.c diagnose.c
msgid "could not redirect output"
msgstr "tidak dapat mengalihkan keluaran"
@@ -3611,8 +3646,8 @@ msgstr "pengurutan dan penyaringan tak peka kapital"
msgid "recurse through submodules"
msgstr "rekursi melalui submodul"
-#: builtin/branch.c builtin/for-each-ref.c builtin/ls-tree.c builtin/tag.c
-#: builtin/verify-tag.c
+#: builtin/branch.c builtin/for-each-ref.c builtin/ls-files.c builtin/ls-tree.c
+#: builtin/tag.c builtin/verify-tag.c
msgid "format to use for the output"
msgstr "format yang digunakan untuk keluaran"
@@ -3721,28 +3756,34 @@ msgstr ""
#: builtin/bugreport.c
msgid "git version:\n"
-msgstr ""
+msgstr "versi git:\n"
#: builtin/bugreport.c
#, c-format
msgid "uname() failed with error '%s' (%d)\n"
-msgstr ""
+msgstr "uname() gagal dengan kesalahan '%s' (%d)\n"
#: builtin/bugreport.c
msgid "compiler info: "
-msgstr ""
+msgstr "info pengompilasi: "
#: builtin/bugreport.c
msgid "libc info: "
-msgstr ""
+msgstr "info pustaka c: "
#: builtin/bugreport.c
msgid "not run from a git repository - no hooks to show\n"
msgstr ""
+"tidak dijalankan dari sebuah repositori git - tidak ada kait yang "
+"diperlihatkan\n"
#: builtin/bugreport.c
-msgid "git bugreport [-o|--output-directory <file>] [-s|--suffix <format>]"
+msgid ""
+"git bugreport [-o|--output-directory <file>] [-s|--suffix <format>] [--"
+"diagnose[=<mode>]"
msgstr ""
+"git bugreport [-o|--output-directory <berkas>] [-s|--suffix <format>] [--"
+"diagnose[=<mode>]]"
#: builtin/bugreport.c
msgid ""
@@ -3762,37 +3803,67 @@ msgid ""
"Please review the rest of the bug report below.\n"
"You can delete any lines you don't wish to share.\n"
msgstr ""
+"Terima kasih telah mengisi laporan bug Git!\n"
+"Mohon jawab pertanyaan berikut untuk membantu memahami masalah Anda.\n"
+"\n"
+"Apa yang Anda lakukan sebelum bug terjadi? (Tahap-tahap untuk mereproduksi "
+"masalah Anda)\n"
+"Apa yang Anda harapkan? (Perilaku yang diharapkan)\n"
+"\n"
+"Apa yang terjadi? (Perilaku sebenarnya)\n"
+"\n"
+"Apa yang berbeda antara apa yang Anda harapkan dan yang sebenarnya terjadi?\n"
+"\n"
+"Apalagi yang Anda ingin tambahkan?\n"
+"\n"
+"Mohon tinjau sisa laporan bug di bawah ini.\n"
+"Anda dapat menghapus baris-baris yang Anda tidak ingin dibagi.\n"
+
+#: builtin/bugreport.c builtin/commit.c builtin/fast-export.c builtin/rebase.c
+#: parse-options.h
+msgid "mode"
+msgstr "mode"
#: builtin/bugreport.c
-msgid "specify a destination for the bugreport file"
-msgstr ""
+msgid ""
+"create an additional zip archive of detailed diagnostics (default 'stats')"
+msgstr "buat arsip zip tambahan dari diagnostik terperinci (asali 'stats')"
#: builtin/bugreport.c
-msgid "specify a strftime format suffix for the filename"
-msgstr ""
+msgid "specify a destination for the bugreport file(s)"
+msgstr "sebutkan tujuan untuk berkas(-berkas) laporan bug"
#: builtin/bugreport.c
+msgid "specify a strftime format suffix for the filename(s)"
+msgstr "sebutkan akhiran format strftime untuk nama(-nama) berkas"
+
+#: builtin/bugreport.c builtin/diagnose.c
#, c-format
msgid "could not create leading directories for '%s'"
-msgstr ""
+msgstr "tidak dapat membuat direktori utama untuk '%s'"
+
+#: builtin/bugreport.c builtin/diagnose.c
+#, c-format
+msgid "unable to create diagnostics archive %s"
+msgstr "tidak dapat membuat arsip diagnostik %s"
#: builtin/bugreport.c
msgid "System Info"
-msgstr ""
+msgstr "Informasi Sistem"
#: builtin/bugreport.c
msgid "Enabled Hooks"
-msgstr ""
+msgstr "Kait Aktif"
#: builtin/bugreport.c
#, c-format
msgid "unable to write to %s"
-msgstr ""
+msgstr "tidak dapat menulis ke %s"
#: builtin/bugreport.c
#, c-format
msgid "Created new report at '%s'.\n"
-msgstr ""
+msgstr "Laporan baru dibuat pada '%s'.\n"
#: builtin/bundle.c
msgid "git bundle create [<options>] <file> <git-rev-list args>"
@@ -3851,11 +3922,6 @@ msgstr "Perlu sebuah repositori untuk membongkar bundel."
msgid "Unbundling objects"
msgstr "Membongkar bundel objek"
-#: builtin/bundle.c builtin/remote.c
-#, c-format
-msgid "Unknown subcommand: %s"
-msgstr "Subperintah tidak dikenal: %s"
-
#: builtin/cat-file.c merge-recursive.c
#, c-format
msgid "cannot read object %s '%s'"
@@ -3954,6 +4020,10 @@ msgstr "perlihatkan ukuran objek"
msgid "allow -s and -t to work with broken/corrupt objects"
msgstr "perbolehkan -s dan -t bekerja dengan objek rusak"
+#: builtin/cat-file.c builtin/log.c
+msgid "use mail map file"
+msgstr "gunakan berkas peta surat"
+
#: builtin/cat-file.c
msgid "Batch objects requested on stdin (or --batch-all-objects)"
msgstr "Objek batch diminta pada masukan standar (atau --batch-all-objects)"
@@ -3967,6 +4037,10 @@ msgid "like --batch, but don't emit <contents>"
msgstr "seperti --batch, tapi jangan keluarkan <isi>"
#: builtin/cat-file.c
+msgid "stdin is NUL-terminated"
+msgstr "stdin diakhiri dengan NUL"
+
+#: builtin/cat-file.c
msgid "read commands from stdin"
msgstr "baca perintah dari masukan standar"
@@ -4139,60 +4213,62 @@ msgstr ""
#: builtin/checkout--worker.c
msgid "git checkout--worker [<options>]"
-msgstr ""
+msgstr "git checkout--worker [<opsi>]"
#: builtin/checkout--worker.c builtin/checkout-index.c builtin/column.c
#: builtin/submodule--helper.c builtin/worktree.c
msgid "string"
-msgstr ""
+msgstr "untai"
#: builtin/checkout--worker.c builtin/checkout-index.c
msgid "when creating files, prepend <string>"
-msgstr ""
+msgstr "saat membuat berkas, awali dengan <string>"
#: builtin/checkout-index.c
msgid "git checkout-index [<options>] [--] [<file>...]"
-msgstr ""
+msgstr "git checkout-index [<opsi>] [--] [<berkas>...]"
#: builtin/checkout-index.c
msgid "stage should be between 1 and 3 or all"
-msgstr ""
+msgstr "tahap seharusnya antara 1 dan 3 atau semua"
#: builtin/checkout-index.c
msgid "check out all files in the index"
-msgstr ""
+msgstr "check out semua berkas di dalam indeks"
#: builtin/checkout-index.c
msgid "do not skip files with skip-worktree set"
-msgstr ""
+msgstr "jangan lewatkan berkas dengan skip-worktree tersetel"
#: builtin/checkout-index.c
msgid "force overwrite of existing files"
-msgstr ""
+msgstr "paksa timpa berkas yang ada"
#: builtin/checkout-index.c
msgid "no warning for existing files and files not in index"
msgstr ""
+"tanpa peringatan untuk berkas yang ada dan berkas yang tidak ada di dalam "
+"indeks"
#: builtin/checkout-index.c
msgid "don't checkout new files"
-msgstr ""
+msgstr "jangan checkout berkas baru"
#: builtin/checkout-index.c
msgid "update stat information in the index file"
-msgstr ""
+msgstr "perbarui informasi stat di dalam berkas indeks"
#: builtin/checkout-index.c
msgid "read list of paths from the standard input"
-msgstr ""
+msgstr "baca daftar jalur dari masukan standar"
#: builtin/checkout-index.c
msgid "write the content to temporary files"
-msgstr ""
+msgstr "tulis isi ke berkas sementara"
#: builtin/checkout-index.c
msgid "copy out the files from named stage"
-msgstr ""
+msgstr "salin berkas dari tahap bernama"
#: builtin/checkout.c
msgid "git checkout [<options>] <branch>"
@@ -5063,6 +5139,14 @@ msgstr ""
"inisialisasi berkas checkout tipis agar memasukkan hanya berkas pada akar"
#: builtin/clone.c
+msgid "uri"
+msgstr "URI"
+
+#: builtin/clone.c
+msgid "a URI for downloading bundles before fetching from origin remote"
+msgstr "sebuah URI untuk mengunduh bundel sebelum mengambil dari remote asal"
+
+#: builtin/clone.c
#, c-format
msgid "info: Could not add alternate for '%s': %s\n"
msgstr "info: Tidak dapat menambahkan alternatif untuk '%s': %s\n"
@@ -5136,9 +5220,8 @@ msgid "failed to initialize sparse-checkout"
msgstr "gagal menginisalisasi checkout tipis"
#: builtin/clone.c
-msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
-msgstr ""
-"HEAD remote merujuk pada ref yang tidak ada, tidak dapat men-checkout.\n"
+msgid "remote HEAD refers to nonexistent ref, unable to checkout"
+msgstr "HEAD remote merujuk pada ref yang tidak ada, tidak dapat men-checkout"
#: builtin/clone.c
msgid "unable to checkout working tree"
@@ -5160,7 +5243,7 @@ msgstr "tidak dapat batal-taut berkas alternatif sementara"
msgid "Too many arguments."
msgstr "Terlalu banyak argumen."
-#: builtin/clone.c contrib/scalar/scalar.c
+#: builtin/clone.c scalar.c
msgid "You must specify a repository to clone."
msgstr "Anda harus sebutkan repositori untuk diklon."
@@ -5170,6 +5253,14 @@ msgid "options '%s' and '%s %s' cannot be used together"
msgstr "opsi '%s' dan '%s %s' tidak dapat digunakan bersamaan"
#: builtin/clone.c
+msgid ""
+"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
+"exclude"
+msgstr ""
+"--bundle-uri tidak kompatibel dengan --depth, --shallow-since, dan --shallow-"
+"exclude"
+
+#: builtin/clone.c
#, c-format
msgid "repository '%s' does not exist"
msgstr "repositori '%s' tidak ada"
@@ -5262,6 +5353,15 @@ msgid "cannot clone from filtered bundle"
msgstr "tidak dapat mengkloning dari bundel tersaring"
#: builtin/clone.c
+msgid "failed to initialize the repo, skipping bundle URI"
+msgstr "gagal menginisialisasi repo, melewatkan URI bundel"
+
+#: builtin/clone.c
+#, c-format
+msgid "failed to fetch objects from bundle URI '%s'"
+msgstr "gagal mengambil objek dari URI bundel '%s'"
+
+#: builtin/clone.c
msgid "remote transport reported error"
msgstr "transportasi remote melaporkan kesalahan"
@@ -5310,6 +5410,8 @@ msgstr ""
msgid ""
"git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"
msgstr ""
+"git commit-graph verify [--object-dir <direktori objek>] [--shallow] [--"
+"[no-]progress]"
#: builtin/commit-graph.c
msgid ""
@@ -5317,96 +5419,96 @@ msgid ""
"split[=<strategy>]] [--reachable|--stdin-packs|--stdin-commits] [--changed-"
"paths] [--[no-]max-new-filters <n>] [--[no-]progress] <split options>"
msgstr ""
+"git commit-graph write [--object-dir <direktori objek>] [--append] [--"
+"split[=<strategi>]] [--reachable|--stdin-packs|--stdin-commits] [--changed-"
+"paths] [--[no-]max-new-filters <n>] [--[-no-]progrss] <opsi pemisah>"
#: builtin/commit-graph.c builtin/fetch.c builtin/log.c
msgid "dir"
-msgstr ""
+msgstr "direktori"
#: builtin/commit-graph.c
msgid "the object directory to store the graph"
-msgstr ""
+msgstr "direktori objek untuk menyimpan grafik"
#: builtin/commit-graph.c
msgid "if the commit-graph is split, only verify the tip file"
-msgstr ""
+msgstr "jika grafik komit terpisah, hanya verifikasi berkas ujung"
#: builtin/commit-graph.c
#, c-format
msgid "Could not open commit-graph '%s'"
-msgstr ""
+msgstr "Tidak dapat membuka grafik komit '%s'"
#: builtin/commit-graph.c
#, c-format
msgid "unrecognized --split argument, %s"
-msgstr ""
+msgstr "argumen --split tidak dikenal, %s"
#: builtin/commit-graph.c
#, c-format
msgid "unexpected non-hex object ID: %s"
-msgstr ""
+msgstr "ID objek non-heks tidak diharapkan: %s"
#: builtin/commit-graph.c
#, c-format
msgid "invalid object: %s"
-msgstr ""
+msgstr "objek tidak valid: %s"
#: builtin/commit-graph.c parse-options-cb.c
#, c-format
msgid "option `%s' expects a numerical value"
-msgstr ""
+msgstr "opsi `%s' mengharapkan nilai numerik"
#: builtin/commit-graph.c
msgid "start walk at all refs"
-msgstr ""
+msgstr "mulai berjalan pada semua referensi"
#: builtin/commit-graph.c
msgid "scan pack-indexes listed by stdin for commits"
-msgstr ""
+msgstr "pindai indeks pak yang disebutkan oleh masukan standar untuk komit"
#: builtin/commit-graph.c
msgid "start walk at commits listed by stdin"
-msgstr ""
+msgstr "mulai berjalan pada komit yang disebutkan oleh masukan standar"
#: builtin/commit-graph.c
msgid "include all commits already in the commit-graph file"
-msgstr ""
+msgstr "masukkan semua komit yang sudah ada di dalam berkas grafik komit"
#: builtin/commit-graph.c
msgid "enable computation for changed paths"
-msgstr ""
+msgstr "aktifkan perhitungan perubahan jalur"
#: builtin/commit-graph.c
msgid "allow writing an incremental commit-graph file"
-msgstr ""
+msgstr "perbolehkan menulis berkas grafik komit bertambah"
#: builtin/commit-graph.c
msgid "maximum number of commits in a non-base split commit-graph"
-msgstr ""
+msgstr "jumlah komit maksimal di dalam grafik komit terpisah non-dasar"
#: builtin/commit-graph.c
msgid "maximum ratio between two levels of a split commit-graph"
-msgstr ""
+msgstr "rasio maksimum di antara dua tingkat grafik komit terpisah"
#: builtin/commit-graph.c
msgid "only expire files older than a given date-time"
msgstr ""
+"hanya kadaluarsakan berkas yang lebih tua dari tanggal-waktu yang diberikan"
#: builtin/commit-graph.c
msgid "maximum number of changed-path Bloom filters to compute"
-msgstr ""
+msgstr "jumlah penyaring Bloom berubah jalur maksimum yang dihitung"
#: builtin/commit-graph.c
msgid "use at most one of --reachable, --stdin-commits, or --stdin-packs"
msgstr ""
+"gunakan hanya satu dari --reachable, --stdin-commits, atau --stdin-packs"
#: builtin/commit-graph.c
msgid "Collecting commits from input"
-msgstr ""
-
-#: builtin/commit-graph.c builtin/multi-pack-index.c
-#, c-format
-msgid "unrecognized subcommand: %s"
-msgstr ""
+msgstr "Mengumpulkan komit dari masukan"
#: builtin/commit-tree.c
msgid ""
@@ -5842,10 +5944,6 @@ msgstr "perlihatkan status dalam format panjang (asali)"
msgid "terminate entries with NUL"
msgstr "akhiri entri dengan NUL"
-#: builtin/commit.c builtin/fast-export.c builtin/rebase.c parse-options.h
-msgid "mode"
-msgstr "mode"
-
#: builtin/commit.c
msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
msgstr ""
@@ -6593,6 +6691,28 @@ msgstr "Tidak ada nama yang ditemukan, tidak dapat menjelaskan apapun."
msgid "option '%s' and commit-ishes cannot be used together"
msgstr "opsi '%s' dan mirip-komit tidak dapat digunakan bersamaan"
+#: builtin/diagnose.c
+msgid ""
+"git diagnose [-o|--output-directory <path>] [-s|--suffix <format>] [--"
+"mode=<mode>]"
+msgstr ""
+
+#: builtin/diagnose.c
+msgid "specify a destination for the diagnostics archive"
+msgstr ""
+
+#: builtin/diagnose.c
+msgid "specify a strftime format suffix for the filename"
+msgstr ""
+
+#: builtin/diagnose.c
+msgid "(stats|all)"
+msgstr ""
+
+#: builtin/diagnose.c
+msgid "specify the content of the diagnostic archive"
+msgstr ""
+
#: builtin/diff-tree.c
msgid "--merge-base only works with two commits"
msgstr "--merge-base hanya bekerja dengan dua komit"
@@ -7074,12 +7194,8 @@ msgid "[rejected]"
msgstr "[tertolak]"
#: builtin/fetch.c
-msgid "can't fetch in current branch"
-msgstr "tidak dapat mengambil di cabang saat ini"
-
-#: builtin/fetch.c
-msgid "checked out in another worktree"
-msgstr "ter-check out di dalam pohon kerja lainnya"
+msgid "can't fetch into checked-out branch"
+msgstr "tidak dapat mengambil ke dalam cabang ter-checkout"
#: builtin/fetch.c
msgid "[tag update]"
@@ -7327,106 +7443,107 @@ msgstr "--stdin hanya dapat digunakan saat mengambil dari satu remote"
msgid ""
"git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"
msgstr ""
+"git fmt-merge-msg [-m <pesan>] [--log[=<n>] | --no-log] [--file <berkas>]"
#: builtin/fmt-merge-msg.c
msgid "populate log with at most <n> entries from shortlog"
-msgstr ""
+msgstr "isi log dengan paling banyak <n> entri dari shortlog"
#: builtin/fmt-merge-msg.c
msgid "alias for --log (deprecated)"
-msgstr ""
+msgstr "alias untuk --log (usang)"
#: builtin/fmt-merge-msg.c
msgid "text"
-msgstr ""
+msgstr "teks"
#: builtin/fmt-merge-msg.c
msgid "use <text> as start of message"
-msgstr ""
+msgstr "gunakan <teks> sebagai awal pesan"
#: builtin/fmt-merge-msg.c
msgid "use <name> instead of the real target branch"
-msgstr ""
+msgstr "gunakan <nama> daripada cabang target sebenarnya"
#: builtin/fmt-merge-msg.c
msgid "file to read from"
-msgstr ""
+msgstr "berkas untuk dibaca"
#: builtin/for-each-ref.c
msgid "git for-each-ref [<options>] [<pattern>]"
-msgstr ""
+msgstr "git for-each-ref [<opsi>] [<pola>]"
#: builtin/for-each-ref.c
msgid "git for-each-ref [--points-at <object>]"
-msgstr ""
+msgstr "git for-each-ref [--points-at <objek>]"
#: builtin/for-each-ref.c
msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
-msgstr ""
+msgstr "git for-each-ref [--merged [<komit>]] [--no-merged [<komit>]]"
#: builtin/for-each-ref.c
msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
-msgstr ""
+msgstr "git for-each-ref [--contains [<komit>]] [--no-contains [<komit>]]"
#: builtin/for-each-ref.c
msgid "quote placeholders suitably for shells"
-msgstr ""
+msgstr "kutip tempat penampung yang sesuai untuk cangkang"
#: builtin/for-each-ref.c
msgid "quote placeholders suitably for perl"
-msgstr ""
+msgstr "kutip tempat penampung yang sesuai untuk perl"
#: builtin/for-each-ref.c
msgid "quote placeholders suitably for python"
-msgstr ""
+msgstr "kutip tempat penampung yang sesuai untuk python"
#: builtin/for-each-ref.c
msgid "quote placeholders suitably for Tcl"
-msgstr ""
+msgstr "kutip tempat penampung yang sesuai untuk Tcl"
#: builtin/for-each-ref.c
msgid "show only <n> matched refs"
-msgstr ""
+msgstr "hanya perlihatkan <n> referensi yang cocok"
#: builtin/for-each-ref.c builtin/tag.c
msgid "respect format colors"
-msgstr ""
+msgstr "hargai warna format"
#: builtin/for-each-ref.c
msgid "print only refs which points at the given object"
-msgstr ""
+msgstr "hanya cetak referensi yang menunjuk pada objek yang diberikan"
#: builtin/for-each-ref.c
msgid "print only refs that are merged"
-msgstr ""
+msgstr "hanya cetak referensi yang tergabung"
#: builtin/for-each-ref.c
msgid "print only refs that are not merged"
-msgstr ""
+msgstr "hanya cetak referensi yang tidak tergabung"
#: builtin/for-each-ref.c
msgid "print only refs which contain the commit"
-msgstr ""
+msgstr "hanya cetak referensi yang berisi komit"
#: builtin/for-each-ref.c
msgid "print only refs which don't contain the commit"
-msgstr ""
+msgstr "hanya cetak referensi yang tidak berisi komit"
#: builtin/for-each-repo.c
msgid "git for-each-repo --config=<config> <command-args>"
-msgstr ""
+msgstr "git for-each-repo --config=<konfigurasi> <argumen perintah>"
#: builtin/for-each-repo.c
msgid "config"
-msgstr ""
+msgstr "konfigurasi"
#: builtin/for-each-repo.c
msgid "config key storing a list of repository paths"
-msgstr ""
+msgstr "kunci konfigurasi yang menampung daftar jalur repositori"
#: builtin/for-each-repo.c
msgid "missing --config=<config>"
-msgstr ""
+msgstr "kehilangan --config=<config>"
#: builtin/fsck.c
msgid "unknown"
@@ -7626,6 +7743,11 @@ msgid "non-tree in cache-tree"
msgstr "bukan pohon pada pohon tembolok"
#: builtin/fsck.c
+#, c-format
+msgid "%s: invalid sha1 pointer in resolve-undo"
+msgstr "%s: penunjuk sha1 tidak valid di resolve-undo"
+
+#: builtin/fsck.c
msgid "git fsck [<options>] [<object>...]"
msgstr "git fsck [<opsi>] [<objek>...]"
@@ -8012,10 +8134,18 @@ msgid "use at most one of --auto and --schedule=<frequency>"
msgstr "gunakan paling banyak satu dari --auto dan --schedule=<frekuensi>"
#: builtin/gc.c
+msgid "git maintenance register"
+msgstr "git maintenance register"
+
+#: builtin/gc.c
msgid "failed to run 'git config'"
msgstr "gagal menjalankan 'git config'"
#: builtin/gc.c
+msgid "git maintenance unregister"
+msgstr "git maintenance unregister"
+
+#: builtin/gc.c
#, c-format
msgid "failed to expand path '%s'"
msgstr "gagal memperluas jalur '%s'"
@@ -8048,15 +8178,19 @@ msgstr ""
"gagal menjalankan 'crontab -l'; sistem Anda mungkin tidak mendukung 'cron'"
#: builtin/gc.c
+msgid "failed to create crontab temporary file"
+msgstr "tidak dapat membuat berkas crontab sementara"
+
+#: builtin/gc.c
+msgid "failed to open temporary file"
+msgstr "tidak dapat membuka berkas sementara"
+
+#: builtin/gc.c
msgid "failed to run 'crontab'; your system might not support 'cron'"
msgstr ""
"gagal menjalankan 'crontab'; sistem Anda mungkin tidak mendukung 'cron'"
#: builtin/gc.c
-msgid "failed to open stdin of 'crontab'"
-msgstr "gagal membuka masukan standar dari 'crontab'"
-
-#: builtin/gc.c
msgid "'crontab' died"
msgstr "'crontab' mati"
@@ -8113,13 +8247,12 @@ msgid "failed to add repo to global config"
msgstr "gagal menambahkan repositori ke konfigurasi global"
#: builtin/gc.c
-msgid "git maintenance <subcommand> [<options>]"
-msgstr "git maintenance <subperintah> [<opsi>]"
+msgid "git maintenance stop"
+msgstr "git maintenance stop"
#: builtin/gc.c
-#, c-format
-msgid "invalid subcommand: %s"
-msgstr "subperintah tidak valid: %s"
+msgid "git maintenance <subcommand> [<options>]"
+msgstr "git maintenance <subperintah> [<opsi>]"
#: builtin/grep.c
msgid "git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"
@@ -8346,6 +8479,10 @@ msgid "allow calling of grep(1) (ignored by this build)"
msgstr "perbolehkan pemanggilan grep(1) (diabaikan oleh bangunan ini)"
#: builtin/grep.c
+msgid "maximum number of results per file"
+msgstr "jumlah hasil maksimum tiap berkas"
+
+#: builtin/grep.c
msgid "no pattern given"
msgstr "tidak ada pola yang diberikan"
@@ -8458,12 +8595,23 @@ msgid "print list of useful guides"
msgstr "cetak daftar panduan berguna"
#: builtin/help.c
+msgid "print list of user-facing repository, command and file interfaces"
+msgstr ""
+"cetak daftar repositori, perintah, dan antarmuka berkas yang menghadap "
+"pengguna"
+
+#: builtin/help.c
+msgid "print list of file formats, protocols and other developer interfaces"
+msgstr "cetak daftar format berkas, protokol, dan antarmuka pengembang lainnya"
+
+#: builtin/help.c
msgid "print all configuration variable names"
msgstr "cetak semua nama variabel konfigurasi"
#: builtin/help.c
-msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>]"
-msgstr "git help [[-i|--info] [-m|--man] [-w|--web]] [<perintah>]"
+msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]"
+msgstr ""
+"git help [[-i|--info] [-m|--man] [-w|--web]] [<perintah>|<dokumentasi>]"
#: builtin/help.c
#, c-format
@@ -8538,6 +8686,7 @@ msgstr "opsi '%s' tidak mengambil argumen bukan opsi"
msgid ""
"the '--no-[external-commands|aliases]' options can only be used with '--all'"
msgstr ""
+"opsi '--no-[external-commands|aliases]' hanya dapat digunakan dengan '--all'"
#: builtin/help.c
#, c-format
@@ -8550,11 +8699,11 @@ msgstr "'git help config' untuk informasi lebih lanjut"
#: builtin/hook.c
msgid "git hook run [--ignore-missing] <hook-name> [-- <hook-args>]"
-msgstr ""
+msgstr "git hook run [--ignore-missing] <nama kait> [-- <argumen kait>]"
#: builtin/hook.c
msgid "silently ignore missing requested <hook-name>"
-msgstr ""
+msgstr "diam-diam abaikan <nama kait> yang diminta yang hilang"
#: builtin/index-pack.c
#, c-format
@@ -9055,8 +9204,8 @@ msgid "show source"
msgstr "perlihatkan sumber"
#: builtin/log.c
-msgid "use mail map file"
-msgstr "gunakan berkas peta surat"
+msgid "clear all previously-defined decoration filters"
+msgstr ""
#: builtin/log.c
msgid "only decorate refs that match <pattern>"
@@ -9390,6 +9539,10 @@ msgid "percentage by which creation is weighted"
msgstr "persentase dimana pembuatan tertimbang"
#: builtin/log.c
+msgid "show in-body From: even if identical to the e-mail header"
+msgstr ""
+
+#: builtin/log.c
#, c-format
msgid "invalid ident line: %s"
msgstr "baris identitas tidak valid: %s"
@@ -9467,10 +9620,25 @@ msgstr ""
"secara manual.\n"
#: builtin/ls-files.c
+#, c-format
+msgid "bad ls-files format: element '%s' does not start with '('"
+msgstr "format ls-files jelek: elemen '%s' tidak dimulai dengan '('"
+
+#: builtin/ls-files.c
+#, c-format
+msgid "bad ls-files format: element '%s' does not end in ')'"
+msgstr "format ls-files jelek: elemen '%s' tidak diakhiri dengan ')'"
+
+#: builtin/ls-files.c
+#, c-format
+msgid "bad ls-files format: %%%.*s"
+msgstr "format ls-files jelek: %%%.*s"
+
+#: builtin/ls-files.c
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<opsi>] [<berkas>...]"
-#: builtin/ls-files.c
+#: builtin/ls-files.c builtin/merge-tree.c
msgid "separate paths with the NUL character"
msgstr "pisahkan jalur dengan karakter NUL"
@@ -9579,6 +9747,14 @@ msgstr "hapus entri duplikat"
msgid "show sparse directories in the presence of a sparse index"
msgstr "perlihatkan direktori tipis di hadapan indeks tipis"
+#: builtin/ls-files.c
+msgid ""
+"--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, "
+"--eol"
+msgstr ""
+"--format tidak dapat digunakan dengan -s, -o, -k, -t, --resolve-undo, --"
+"deduplicate, --eol"
+
#: builtin/ls-remote.c
msgid ""
"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
@@ -9795,73 +9971,119 @@ msgid ""
"git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> "
"<orig-file> <file2>"
msgstr ""
+"git merge-file [<opsi>] [-L <nama 1> [-L <asli> [-L <nama 2>]]] <berkas 1> "
+"<berkas asli> <berkas 2>"
#: builtin/merge-file.c
msgid "send results to standard output"
-msgstr ""
+msgstr "kirim hasil ke keluaran standar"
#: builtin/merge-file.c
msgid "use a diff3 based merge"
-msgstr ""
+msgstr "gunakan penggabungan berdasarkan diff3"
#: builtin/merge-file.c
msgid "use a zealous diff3 based merge"
-msgstr ""
+msgstr "gunakan penggabungan berdasarkan diff3 yang bersemangat"
#: builtin/merge-file.c
msgid "for conflicts, use our version"
-msgstr ""
+msgstr "untuk konflik, gunakan versi kami"
#: builtin/merge-file.c
msgid "for conflicts, use their version"
-msgstr ""
+msgstr "untuk konflik, gunakan versi mereka"
#: builtin/merge-file.c
msgid "for conflicts, use a union version"
-msgstr ""
+msgstr "untuk konflik, gunakan versi bersatu"
#: builtin/merge-file.c
msgid "for conflicts, use this marker size"
-msgstr ""
+msgstr "untuk konflik, gunakan ukuran penanda ini"
#: builtin/merge-file.c
msgid "do not warn about conflicts"
-msgstr ""
+msgstr "jangan peringatkan tentang konflik"
#: builtin/merge-file.c
msgid "set labels for file1/orig-file/file2"
-msgstr ""
+msgstr "setel label untuk file1/orig-file/file2"
#: builtin/merge-recursive.c
#, c-format
msgid "unknown option %s"
-msgstr ""
+msgstr "opsi tidak dikenal %s"
#: builtin/merge-recursive.c
#, c-format
msgid "could not parse object '%s'"
-msgstr ""
+msgstr "tidak dapat menguraikan objek '%s'"
#: builtin/merge-recursive.c
#, c-format
msgid "cannot handle more than %d base. Ignoring %s."
msgid_plural "cannot handle more than %d bases. Ignoring %s."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "tidak dapat menangani lebih dari %d dasar. Mengabaikan %s."
+msgstr[1] "tidak dapat menangani lebih dari %d dasar. Mengabaikan %s."
#: builtin/merge-recursive.c
msgid "not handling anything other than two heads merge."
-msgstr ""
+msgstr "tidak menangani apapun selain penggabungan dua kepala"
#: builtin/merge-recursive.c
#, c-format
msgid "could not resolve ref '%s'"
-msgstr ""
+msgstr "tidak dapat menguraikan referensi '%s'"
#: builtin/merge-recursive.c
#, c-format
msgid "Merging %s with %s\n"
-msgstr ""
+msgstr "Menggabungkan %s dengan %s\n"
+
+#: builtin/merge-tree.c builtin/merge.c
+msgid "not something we can merge"
+msgstr "bukan sesuatu yang kami bisa gabungkan"
+
+#: builtin/merge-tree.c builtin/merge.c
+msgid "refusing to merge unrelated histories"
+msgstr "menolak menggabungkan riwayat tak terkait"
+
+#: builtin/merge-tree.c
+msgid "failure to merge"
+msgstr "kegagalan penggabungan"
+
+#: builtin/merge-tree.c
+msgid "git merge-tree [--write-tree] [<options>] <branch1> <branch2>"
+msgstr "git merge-tree [--write-tree] [<opsi>] <cabang 1> <cabang 2>"
+
+#: builtin/merge-tree.c
+msgid "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"
+msgstr "git merge-tree [--trivial-merge] <pohon dasar> <cabang 1> <cabang 2>"
+
+#: builtin/merge-tree.c
+msgid "do a real merge instead of a trivial merge"
+msgstr "lakukan penggabungan sebenarnya daripada penggabungan sepele"
+
+#: builtin/merge-tree.c
+msgid "do a trivial merge only"
+msgstr "hanya lakukan penggabungan sepele"
+
+#: builtin/merge-tree.c
+msgid "also show informational/conflict messages"
+msgstr "perlihatkan juga pesan informasi/konflik"
+
+#: builtin/merge-tree.c
+msgid "list filenames without modes/oids/stages"
+msgstr "daftar nama berkas tanpa mode/oid/tahap"
+
+#: builtin/merge-tree.c builtin/merge.c builtin/pull.c
+msgid "allow merging unrelated histories"
+msgstr "perbolehkan penggabungan riwayat yang tak terkait"
+
+#: builtin/merge-tree.c
+msgid "--trivial-merge is incompatible with all other options"
+msgstr "--trivial-merge tidak kompatibel dengan semua opsi lainnya"
#: builtin/merge.c
msgid "git merge [<options>] [<commit>...]"
@@ -9969,10 +10191,6 @@ msgstr "--abort tapi biarkan indeks dan pohon kerja"
msgid "continue the current in-progress merge"
msgstr "lanjutkan penggabungan yang sedang berlangsung saat ini"
-#: builtin/merge.c builtin/pull.c
-msgid "allow merging unrelated histories"
-msgstr "perbolehkan penggabungan riwayat yang tak terkait"
-
#: builtin/merge.c
msgid "bypass pre-merge-commit and commit-msg hooks"
msgstr "lewati kail pre-merge-commit dan commit-msg"
@@ -10114,7 +10332,7 @@ msgstr "Nilai jelek '%s' dalam lingkungan '%s'"
#: builtin/merge.c read-cache.c strbuf.c wrapper.c
#, c-format
msgid "could not close '%s'"
-msgstr ""
+msgstr "tidak dapat menutup '%s'"
#: builtin/merge.c
#, c-format
@@ -10122,10 +10340,6 @@ msgid "not something we can merge in %s: %s"
msgstr "bukan sesuatu yang kami bisa gabungkan di %s: %s"
#: builtin/merge.c
-msgid "not something we can merge"
-msgstr "bukan sesuatu yang kami bisa gabungkan"
-
-#: builtin/merge.c
msgid "--abort expects no arguments"
msgstr "--abort harap tanpa argumen"
@@ -10188,14 +10402,20 @@ msgid "Can merge only exactly one commit into empty head"
msgstr "Hanya bisa menggabungkan tepantnya satu komit ke kepala kosong"
#: builtin/merge.c
-msgid "refusing to merge unrelated histories"
-msgstr "menolak menggabungkan riwayat tak terkait"
-
-#: builtin/merge.c
#, c-format
msgid "Updating %s..%s\n"
msgstr "Memperbarui %s..%s\n"
+#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c
+#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by merge:\n"
+" %s"
+msgstr ""
+"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh "
+"penggabungan:\n"
+" %s"
+
#: builtin/merge.c
#, c-format
msgid "Trying really trivial in-index merge...\n"
@@ -10238,6 +10458,11 @@ msgstr ""
"Penggabungan otomatis berjalan baik; berhenti sebelum mengkomit seperti yang "
"diminta\n"
+#: builtin/merge.c
+#, c-format
+msgid "When finished, apply stashed changes with `git stash pop`\n"
+msgstr "Ketika selesai terapkan perubahan terstase dengan `git stash pop`\n"
+
#: builtin/mktag.c
#, c-format
msgid "warning: tag input does not pass fsck: %s"
@@ -10388,6 +10613,10 @@ msgid "bad source"
msgstr "sumber jelek"
#: builtin/mv.c
+msgid "destination exists"
+msgstr "tujuan ada"
+
+#: builtin/mv.c
msgid "can not move directory into itself"
msgstr "tidak dapat memindahkan direktori ke dirinya sendiri"
@@ -10408,10 +10637,6 @@ msgid "conflicted"
msgstr "terkonflik"
#: builtin/mv.c
-msgid "destination exists"
-msgstr "tujuan ada"
-
-#: builtin/mv.c
#, c-format
msgid "overwriting '%s'"
msgstr "menimpa '%s'"
@@ -10429,6 +10654,10 @@ msgid "destination directory does not exist"
msgstr "direktori tujuan tidak ada"
#: builtin/mv.c
+msgid "destination exists in the index"
+msgstr "tujuan ada dalam indeks"
+
+#: builtin/mv.c
#, c-format
msgid "%s, source=%s, destination=%s"
msgstr "%s, source=%s, destination=%s"
@@ -10882,10 +11111,10 @@ msgstr "referensi catatan"
msgid "use notes from <notes-ref>"
msgstr "gunakan catatan dari <referensi catatan>"
-#: builtin/notes.c builtin/stash.c
+#: builtin/notes.c builtin/remote.c parse-options.c
#, c-format
-msgid "unknown subcommand: %s"
-msgstr "subperintah tidak dikenal: %s"
+msgid "unknown subcommand: `%s'"
+msgstr "subperintah tidak dikenal: `%s'"
#: builtin/pack-objects.c
msgid ""
@@ -11498,7 +11727,7 @@ msgstr "Lihat git-pull(1) untuk selengkapnya."
msgid "<remote>"
msgstr "<remote>"
-#: builtin/pull.c contrib/scalar/scalar.c
+#: builtin/pull.c scalar.c
msgid "<branch>"
msgstr "<cabang>"
@@ -11944,47 +12173,54 @@ msgstr "opsi dorong harus tidak ada karakter baris baru"
#: builtin/range-diff.c
msgid "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"
msgstr ""
+"git range-diff [<opsi>] <dasar lama>..<ujung lama> <dasar-baru>..<ujung baru>"
#: builtin/range-diff.c
msgid "git range-diff [<options>] <old-tip>...<new-tip>"
-msgstr ""
+msgstr "git range-diff [<opsi>] <ujung lama>...<ujung baru>"
#: builtin/range-diff.c
msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
-msgstr ""
+msgstr "git range-diff [<opsi>] <dasar> <ujung lama> <ujung baru>"
#: builtin/range-diff.c
msgid "use simple diff colors"
-msgstr ""
+msgstr "gunakan warna diff sederhana"
#: builtin/range-diff.c
msgid "notes"
-msgstr ""
+msgstr "catatan"
#: builtin/range-diff.c
msgid "passed to 'git log'"
-msgstr ""
+msgstr "lewatkan ke 'git log'"
#: builtin/range-diff.c
msgid "only emit output related to the first range"
-msgstr ""
+msgstr "hanya keluarkan keluaran relatif terhadap rentang pertama"
#: builtin/range-diff.c
msgid "only emit output related to the second range"
-msgstr ""
+msgstr "hanya keluarkan keluaran relatif terhadap rentang kedua"
+
+#: builtin/range-diff.c
+#, c-format
+msgid "not a revision: '%s'"
+msgstr "bukan sebuah revisi: '%s'"
#: builtin/range-diff.c
#, c-format
msgid "not a commit range: '%s'"
-msgstr ""
+msgstr "bukan sebuah rentang komit '%s'"
#: builtin/range-diff.c
-msgid "single arg format must be symmetric range"
-msgstr ""
+#, c-format
+msgid "not a symmetric range: '%s'"
+msgstr "bukan sebuah rentang simetris: '%s'"
#: builtin/range-diff.c
msgid "need two commit ranges"
-msgstr ""
+msgstr "butuh dua rentang komit"
#: builtin/read-tree.c
msgid ""
@@ -12323,6 +12559,10 @@ msgid "move commits that begin with squash!/fixup! under -i"
msgstr "pindahakan komit yang diawali dengan squash!/fixup! di bawah -i"
#: builtin/rebase.c
+msgid "update branches that point to commits that are being rebased"
+msgstr ""
+
+#: builtin/rebase.c
msgid "add exec lines after each commit of the editable list"
msgstr ""
"tambahkan baris exec setelah setiap komit dari daftar yang bisa disunting"
@@ -12956,6 +13196,10 @@ msgid " tracked"
msgstr " dilacak"
#: builtin/remote.c
+msgid " skipped"
+msgstr ""
+
+#: builtin/remote.c
msgid " stale (use 'git remote prune' to remove)"
msgstr " basi (gunakan 'git remote prune' untuk hapus)"
@@ -13794,12 +14038,17 @@ msgstr "Tidak dapat menyetel ulang berkas indeks ke revisi '%s'."
msgid "Could not write new index file."
msgstr "Tidak dapat menulis berkas indeks baru."
-#: builtin/rev-list.c pack-bitmap.c
+#: builtin/rev-list.c
#, c-format
msgid "unable to get disk usage of %s"
msgstr ""
#: builtin/rev-list.c
+#, c-format
+msgid "invalid value for '%s': '%s', the only allowed format is '%s'"
+msgstr ""
+
+#: builtin/rev-list.c
msgid "rev-list does not support display of notes"
msgstr "rev-list tidak mendukung penampilan catatan"
@@ -13833,6 +14082,10 @@ msgid "no usage string given before the `--' separator"
msgstr "tidak ada untai penggunaan yang diberikan sebelum pemisah `--'"
#: builtin/rev-parse.c
+msgid "missing opt-spec before option flags"
+msgstr ""
+
+#: builtin/rev-parse.c
msgid "Needed a single revision"
msgstr "Butuh satu revisi"
@@ -14392,7 +14645,7 @@ msgstr "inisialisasi checkout tipis dalam mode kerucut"
msgid "toggle the use of a sparse index"
msgstr "gunakan indeks tipis"
-#: builtin/sparse-checkout.c commit-graph.c midx.c
+#: builtin/sparse-checkout.c commit-graph.c midx.c sequencer.c
#, c-format
msgid "unable to create leading directories of %s"
msgstr ""
@@ -14800,6 +15053,11 @@ msgstr "Mengharapkan nama referensi penuh, dapat %s"
#: builtin/submodule--helper.c
#, c-format
+msgid "could not get a repository handle for submodule '%s'"
+msgstr "tidak dapat mendapat pegangan repositori untuk submodul '%s'"
+
+#: builtin/submodule--helper.c
+#, c-format
msgid ""
"could not look up configuration '%s'. Assuming this repository is its own "
"authoritative upstream."
@@ -14808,14 +15066,6 @@ msgstr ""
"hulu otoritatif tersendiri."
#: builtin/submodule--helper.c
-msgid "alternative anchor for relative paths"
-msgstr "jangkar alternatif untuk jalur relatif"
-
-#: builtin/submodule--helper.c
-msgid "git submodule--helper list [--prefix=<path>] [<path>...]"
-msgstr "git submodule--helper list [--prefix=<jalur>] [<jalur>...]"
-
-#: builtin/submodule--helper.c
#, c-format
msgid "No url found for submodule path '%s' in .gitmodules"
msgstr "Tidak ada url yang ditemukan untuk jalur submodul '%s' di .gitmodules"
@@ -14854,9 +15104,8 @@ msgid "recurse into nested submodules"
msgstr "rekursi ke dalam submodul bersarang"
#: builtin/submodule--helper.c
-msgid "git submodule--helper foreach [--quiet] [--recursive] [--] <command>"
-msgstr ""
-"git submodule--helper foreach [--quiet] [--recursive] [--] [<perintah>]"
+msgid "git submodule foreach [--quiet] [--recursive] [--] <command>"
+msgstr "git submodule foreach [--quiet] [--recursive] [--] [<perintah>]"
#: builtin/submodule--helper.c
#, c-format
@@ -14883,8 +15132,8 @@ msgid "suppress output for initializing a submodule"
msgstr "sembunyikan keluaran menginisialisasi submodul"
#: builtin/submodule--helper.c
-msgid "git submodule--helper init [<options>] [<path>]"
-msgstr "git submodule--helper init [<opsi>] [<jalur>]"
+msgid "git submodule init [<options>] [<path>]"
+msgstr "git submodule init [<opsi>] [<jalur>]"
#: builtin/submodule--helper.c
#, c-format
@@ -14918,10 +15167,6 @@ msgid "git submodule status [--quiet] [--cached] [--recursive] [<path>...]"
msgstr "git submodule status [--quiet] [--cached] [--recursive] [<jalur>...]"
#: builtin/submodule--helper.c
-msgid "git submodule--helper name <path>"
-msgstr "git submodule--helper name <jalur>"
-
-#: builtin/submodule--helper.c
#, c-format
msgid "* %s %s(blob)->%s(submodule)"
msgstr "* %s %s(blob)->%s(submodul)"
@@ -14963,8 +15208,8 @@ msgid "limit the summary size"
msgstr "batasi ukuran ringkasan"
#: builtin/submodule--helper.c
-msgid "git submodule--helper summary [<options>] [<commit>] [--] [<path>]"
-msgstr "git submodule--helper summary [<opsi>] [<commit>] -- [<jalur>]"
+msgid "git submodule summary [<options>] [<commit>] [--] [<path>]"
+msgstr "git submodule summary [<opsi>] [<commit>] -- [<jalur>]"
#: builtin/submodule--helper.c
msgid "could not fetch a revision for HEAD"
@@ -14982,11 +15227,6 @@ msgstr "gagal mendaftarkan url untuk jalur submodul '%s'"
#: builtin/submodule--helper.c
#, c-format
-msgid "failed to get the default remote for submodule '%s'"
-msgstr "gagal mendapatkan remote asali untuk submodul '%s'"
-
-#: builtin/submodule--helper.c
-#, c-format
msgid "failed to update remote for submodule '%s'"
msgstr "gagal memperbarui remote untuk submodul '%s'"
@@ -14995,8 +15235,8 @@ msgid "suppress output of synchronizing submodule url"
msgstr "sembunyikan keluaran mensinkronisasi url submodul"
#: builtin/submodule--helper.c
-msgid "git submodule--helper sync [--quiet] [--recursive] [<path>]"
-msgstr "git submodule--helper sync [--quiet] [--recursive] [<jalur>]"
+msgid "git submodule sync [--quiet] [--recursive] [<path>]"
+msgstr "git submodule sync [--quiet] [--recursive] [<jalur>]"
#: builtin/submodule--helper.c
#, c-format
@@ -15069,6 +15309,11 @@ msgstr ""
#: builtin/submodule--helper.c
#, c-format
+msgid "could not get a repository handle for gitdir '%s'"
+msgstr "tidak dapat mendapat pegangan repositori untuk direktori git '%s'"
+
+#: builtin/submodule--helper.c
+#, c-format
msgid "submodule '%s' cannot add alternate: %s"
msgstr "submodul '%s' tidak dapat menambahkan pengganti: %s"
@@ -15104,6 +15349,10 @@ msgid "could not get submodule directory for '%s'"
msgstr "tidak dapat mendapatkan direktori submodul untuk '%s'"
#: builtin/submodule--helper.c
+msgid "alternative anchor for relative paths"
+msgstr "jangkar alternatif untuk jalur relatif"
+
+#: builtin/submodule--helper.c
msgid "where the new submodule will be cloned to"
msgstr "di mana submodul baru akan dikloning"
@@ -15139,11 +15388,6 @@ msgstr ""
#: builtin/submodule--helper.c
#, c-format
-msgid "Invalid update mode '%s' for submodule path '%s'"
-msgstr "Mode pembaruan '%s' tidak valid untuk jalur submodul '%s'"
-
-#: builtin/submodule--helper.c
-#, c-format
msgid "Invalid update mode '%s' configured for submodule path '%s'"
msgstr "Mode pembaruan '%s' tidak valid untuk jalur submodul '%s'"
@@ -15234,6 +15478,11 @@ msgstr ""
#: builtin/submodule--helper.c
#, c-format
+msgid "could not initialize submodule at path '%s'"
+msgstr "tidak dapat menginisialisasi submodul pada jalur '%s'"
+
+#: builtin/submodule--helper.c
+#, c-format
msgid ""
"Submodule (%s) branch configured to inherit branch from superproject, but "
"the superproject is not on any branch"
@@ -15243,11 +15492,6 @@ msgstr ""
#: builtin/submodule--helper.c
#, c-format
-msgid "could not get a repository handle for submodule '%s'"
-msgstr "tidak dapat mendapat pegangan repositori untuk submodul '%s'"
-
-#: builtin/submodule--helper.c
-#, c-format
msgid "Unable to find current revision in submodule path '%s'"
msgstr "Tidak dapat menemukan revisi saat ini pada jalur submodul '%s'"
@@ -15291,12 +15535,16 @@ msgid "path into the working tree"
msgstr "jalur ke dalam pohon kerja"
#: builtin/submodule--helper.c
-msgid "path into the working tree, across nested submodule boundaries"
-msgstr "jalur ke dalam pohon kerja, melintasi perbatasan submodul bersarang"
+msgid "use the 'checkout' update strategy (default)"
+msgstr "gunakan strategi pembaruan 'checkout' (asali)"
+
+#: builtin/submodule--helper.c
+msgid "use the 'merge' update strategy"
+msgstr "gunakan strategi penmbaruan 'merge'"
#: builtin/submodule--helper.c
-msgid "rebase, merge, checkout or none"
-msgstr "dasarkan ulang, gabungkan, checkout atau tidak sama sekali"
+msgid "use the 'rebase' update strategy"
+msgstr "gunakan strategi pembaruan 'rebase'"
#: builtin/submodule--helper.c
msgid "create a shallow clone truncated to the specified number of revisions"
@@ -15315,6 +15563,11 @@ msgid "don't print cloning progress"
msgstr "jangan cetak perkembangan pengkloningan"
#: builtin/submodule--helper.c
+msgid "disallow cloning into non-empty directory, implies --init"
+msgstr ""
+"tak perbolehkan kloning ke dalam direktori berisi, mengimplikasikan --init"
+
+#: builtin/submodule--helper.c
msgid ""
"git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] "
"[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-"
@@ -15327,16 +15580,12 @@ msgstr ""
"[--] [<jalur>...]"
#: builtin/submodule--helper.c
-msgid "bad value for update parameter"
-msgstr "nilai jelek untuk parameter pembaruan"
-
-#: builtin/submodule--helper.c
msgid "recurse into submodules"
msgstr "rekursi ke dalam submodul"
#: builtin/submodule--helper.c
-msgid "git submodule--helper absorb-git-dirs [<options>] [<path>...]"
-msgstr "git submodule--helper absorb-git-dirs [<opsi>] [<jalur>...]"
+msgid "git submodule absorbgitdirs [<options>] [<path>...]"
+msgstr "git submodule absorbgitdirs [<opsi>] [<jalur>...]"
#: builtin/submodule--helper.c
msgid "check if it is safe to write to the .gitmodules file"
@@ -15363,8 +15612,8 @@ msgid "suppress output for setting url of a submodule"
msgstr "sembunyikan keluaran penyetelan url submodule"
#: builtin/submodule--helper.c
-msgid "git submodule--helper set-url [--quiet] <path> <newurl>"
-msgstr "git submodule--helper set-url [--quiet] <jalur> <url baru>"
+msgid "git submodule set-url [--quiet] <path> <newurl>"
+msgstr "git submodule set-url [--quiet] <jalur> <url baru>"
#: builtin/submodule--helper.c
msgid "set the default tracking branch to master"
@@ -15375,14 +15624,12 @@ msgid "set the default tracking branch"
msgstr "setel cabang pelacak asali"
#: builtin/submodule--helper.c
-msgid "git submodule--helper set-branch [-q|--quiet] (-d|--default) <path>"
-msgstr "git submodule--helper set-branch [-q|--quiet] (-d|--default) <jalur>"
+msgid "git submodule set-branch [-q|--quiet] (-d|--default) <path>"
+msgstr "git submodule set-branch [-q|--quiet] (-d|--default) <jalur>"
#: builtin/submodule--helper.c
-msgid ""
-"git submodule--helper set-branch [-q|--quiet] (-b|--branch) <branch> <path>"
-msgstr ""
-"git submodule--helper set-branch [-q|--quiet] (-b|--branch) <cabang> <jalur>"
+msgid "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>"
+msgstr "git submodule set-branch [-q|--quiet] (-b|--branch) <cabang> <jalur>"
#: builtin/submodule--helper.c
msgid "--branch or --default required"
@@ -15500,8 +15747,8 @@ msgstr ""
"setel nama submodul ke untai yang diberikan daripada diasalkan ke jalurnya"
#: builtin/submodule--helper.c
-msgid "git submodule--helper add [<options>] [--] <repository> [<path>]"
-msgstr "git submodule--helper add [<opsi>] [--] <repositori> [<jalur>]"
+msgid "git submodule add [<options>] [--] <repository> [<path>]"
+msgstr "git submodule add [<opsi>] [--] <repositori> [<jalur>]"
#: builtin/submodule--helper.c
msgid "Relative path can only be used from the toplevel of the working tree"
@@ -15758,6 +16005,19 @@ msgid "pack exceeds maximum allowed size"
msgstr "paket melebihi ukuran maksimum yang diperbolehkan"
#: builtin/unpack-objects.c
+msgid "failed to write object in stream"
+msgstr "gagal menulis objek di dalam arus"
+
+#: builtin/unpack-objects.c
+#, c-format
+msgid "inflate returned (%d)"
+msgstr "inflate mengembalikan (%d)"
+
+#: builtin/unpack-objects.c
+msgid "invalid blob object from stream"
+msgstr "objek blob tidak valid dari arus"
+
+#: builtin/unpack-objects.c
msgid "Unpacking objects"
msgstr "Membongkar objek"
@@ -16414,6 +16674,33 @@ msgstr "tulis objek pohon untuk subdirektori <prefiks>"
msgid "only useful for debugging"
msgstr "hanya berguna untuk penirkutuan"
+#: bulk-checkin.c
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr ""
+
+#: bundle-uri.c
+msgid "failed to create temporary file"
+msgstr "tidak dapat membuat berkas sementara"
+
+#: bundle-uri.c
+msgid "insufficient capabilities"
+msgstr "tidak cukup kemampuan"
+
+#: bundle-uri.c
+#, c-format
+msgid "failed to download bundle from URI '%s'"
+msgstr "gagal mengunduh bundel dari URI '%s'"
+
+#: bundle-uri.c
+#, c-format
+msgid "file at URI '%s' is not a bundle"
+msgstr "berkas pada URI '%s' bukan sebuah bundle"
+
+#: bundle-uri.c
+#, c-format
+msgid "failed to unbundle bundle from URI '%s'"
+msgstr "gagal membongkar bundel dari URI '%s'"
+
#: bundle.c
#, c-format
msgid "unrecognized bundle hash algorithm: %s"
@@ -16502,936 +16789,1000 @@ msgstr "index-pack mati"
#: chunk-format.c
msgid "terminating chunk id appears earlier than expected"
-msgstr ""
+msgstr "id bingkah pengakhiran muncul lebih awal dari yang diharapkan"
#: chunk-format.c
#, c-format
msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>"
-msgstr ""
+msgstr "offset bingkah %<PRIx64> dan %<PRIx64> tidak tepat"
#: chunk-format.c
#, c-format
msgid "duplicate chunk ID %<PRIx32> found"
-msgstr ""
+msgstr "ID bingkah duplikat %<PRIx32> ditemukan"
#: chunk-format.c
#, c-format
msgid "final chunk has non-zero id %<PRIx32>"
-msgstr ""
+msgstr "bingkah terakhir punya id bukan nol %<PRIx32>"
#: chunk-format.c
msgid "invalid hash version"
-msgstr ""
+msgstr "versi hash tidak valid"
#: color.c
#, c-format
msgid "invalid color value: %.*s"
-msgstr ""
+msgstr "nilai warna tidak valid: %.*s"
#: command-list.h
msgid "Add file contents to the index"
-msgstr ""
+msgstr "Tambahkan isi berkas ke indeks"
#: command-list.h
msgid "Apply a series of patches from a mailbox"
-msgstr ""
+msgstr "Terapkan rangkaian tambalan dari kotak surat"
#: command-list.h
msgid "Annotate file lines with commit information"
-msgstr ""
+msgstr "Anotasi baris berkas dengan informasi komit"
#: command-list.h
msgid "Apply a patch to files and/or to the index"
-msgstr ""
+msgstr "Terapkan tambalan pada berkas dan/atau pada indeks"
#: command-list.h
msgid "Import a GNU Arch repository into Git"
-msgstr ""
+msgstr "Impor repositori GNU Arch ke dalam Git"
#: command-list.h
msgid "Create an archive of files from a named tree"
-msgstr ""
+msgstr "Buat arsip berkas dari pohon bernama"
#: command-list.h
msgid "Use binary search to find the commit that introduced a bug"
-msgstr ""
+msgstr "Gunakan pencarian biner untuk mencari komit yang memasukkan bug"
#: command-list.h
msgid "Show what revision and author last modified each line of a file"
msgstr ""
+"Perlihatkan revisi dan pengarang apa yang terakhir kali mengubah setiap "
+"baris berkas"
#: command-list.h
msgid "List, create, or delete branches"
-msgstr ""
+msgstr "Daftar, buat, atau hapus cabang"
#: command-list.h
msgid "Collect information for user to file a bug report"
-msgstr ""
+msgstr "Kumpulkan informasi agar pengguna melaporkan laporan bug"
#: command-list.h
msgid "Move objects and refs by archive"
-msgstr ""
+msgstr "Pindahkan objek dan referensi oleh arsip"
#: command-list.h
msgid "Provide content or type and size information for repository objects"
msgstr ""
+"Sediakan isi atau informasi tipe dan ukuran berkas untuk objek repositori"
#: command-list.h
msgid "Display gitattributes information"
-msgstr ""
+msgstr "Perlihatkan informasi gitattributes"
#: command-list.h
msgid "Debug gitignore / exclude files"
-msgstr ""
+msgstr "Nirkutukan berkas gitignore / exclude"
#: command-list.h
msgid "Show canonical names and email addresses of contacts"
-msgstr ""
+msgstr "Perlihatkan nama dan alamat email kanonikal"
#: command-list.h
msgid "Ensures that a reference name is well formed"
-msgstr ""
+msgstr "Pastikan bahwa nama referensi baik dan benar"
#: command-list.h
msgid "Switch branches or restore working tree files"
-msgstr ""
+msgstr "Ganti cabang atau kembalikan berkas pohon kerja"
#: command-list.h
msgid "Copy files from the index to the working tree"
-msgstr ""
+msgstr "Salin berkas dari indeks ke pohon kerja"
#: command-list.h
msgid "Find commits yet to be applied to upstream"
-msgstr ""
+msgstr "Cari komit yang belum diterapkan pada hulu"
#: command-list.h
msgid "Apply the changes introduced by some existing commits"
-msgstr ""
+msgstr "Terapkan perubahan yang dimasukkan oleh beberapa komit yang ada"
#: command-list.h
msgid "Graphical alternative to git-commit"
-msgstr ""
+msgstr "Alternatif grafik untuk git-commit"
#: command-list.h
msgid "Remove untracked files from the working tree"
-msgstr ""
+msgstr "Hapus berkas tak terlacak dari pohon kerja"
#: command-list.h
msgid "Clone a repository into a new directory"
-msgstr ""
+msgstr "Salin repositori ke dalam direktori baru"
#: command-list.h
msgid "Display data in columns"
-msgstr ""
+msgstr "Tampilkan data dalam kolom"
#: command-list.h
msgid "Record changes to the repository"
-msgstr ""
+msgstr "Rekam perubahan ke dalam repositori"
#: command-list.h
msgid "Write and verify Git commit-graph files"
-msgstr ""
+msgstr "Tulis dan verifikasi berkas Git commit-graph"
#: command-list.h
msgid "Create a new commit object"
-msgstr ""
+msgstr "Buat objek komit baru"
#: command-list.h
msgid "Get and set repository or global options"
-msgstr ""
+msgstr "Dapatkan dan setel opsi repositori atau global"
#: command-list.h
msgid "Count unpacked number of objects and their disk consumption"
-msgstr ""
+msgstr "Hitung jumlah berkas tak terlacak dan penggunaan disknya"
#: command-list.h
msgid "Retrieve and store user credentials"
-msgstr ""
+msgstr "Dapatkan dan simpan kredensial pengguna"
#: command-list.h
msgid "Helper to temporarily store passwords in memory"
-msgstr ""
+msgstr "Pembantu untuk sementara simpan kata sandi di memori"
#: command-list.h
msgid "Helper to store credentials on disk"
-msgstr ""
+msgstr "Pembantu untuk menyimpan kredensial pada disk"
#: command-list.h
msgid "Export a single commit to a CVS checkout"
-msgstr ""
+msgstr "Ekspor satu komit tunggal ke checkout CVS"
#: command-list.h
msgid "Salvage your data out of another SCM people love to hate"
-msgstr ""
+msgstr "Selamatkan data karena pengguna SCM lainnya yang suka membenci"
#: command-list.h
msgid "A CVS server emulator for Git"
-msgstr ""
+msgstr "Emulator peladen CVS untuk Git"
#: command-list.h
msgid "A really simple server for Git repositories"
-msgstr ""
+msgstr "Peladen sederhana beneran untuk repositori Git"
#: command-list.h
msgid "Give an object a human readable name based on an available ref"
msgstr ""
+"Berikan nama yang dapat dibaca manusia pada objek berdasarkan referensi yang "
+"ada"
#: command-list.h
msgid "Show changes between commits, commit and working tree, etc"
msgstr ""
+"Perlihatkan perubahan di antara komit-komit, komit dan pohon kerja, dll"
#: command-list.h
msgid "Compares files in the working tree and the index"
-msgstr ""
+msgstr "Bandingkan berkas di dalam pohon kerja dan indeks"
#: command-list.h
msgid "Compare a tree to the working tree or index"
-msgstr ""
+msgstr "Bandingkan pohon kepada pohon kerja atau indeks"
#: command-list.h
msgid "Compares the content and mode of blobs found via two tree objects"
-msgstr ""
+msgstr "Bandingkan isi dan mode blob yang ditemukan lewat dua objek pohon"
#: command-list.h
msgid "Show changes using common diff tools"
-msgstr ""
+msgstr "Perlihatkan perubahan menggunakan alat diff umum"
#: command-list.h
msgid "Git data exporter"
-msgstr ""
+msgstr "Eksportir data Git"
#: command-list.h
msgid "Backend for fast Git data importers"
-msgstr ""
+msgstr "Tulang punggung untuk importir data Git"
#: command-list.h
msgid "Download objects and refs from another repository"
-msgstr ""
+msgstr "Unduh objek dan referensi dari repositori yang lain"
#: command-list.h
msgid "Receive missing objects from another repository"
-msgstr ""
+msgstr "Terima objek yang hilang dari repositori yang lain"
#: command-list.h
msgid "Rewrite branches"
-msgstr ""
+msgstr "Tulis ulang cabang"
#: command-list.h
msgid "Produce a merge commit message"
-msgstr ""
+msgstr "Buat pesan komit penggabungan"
#: command-list.h
msgid "Output information on each ref"
-msgstr ""
+msgstr "Keluarkan informasi pada setiap referensi"
#: command-list.h
msgid "Run a Git command on a list of repositories"
-msgstr ""
+msgstr "Jalankan perintah Git pada daftar repositori"
#: command-list.h
msgid "Prepare patches for e-mail submission"
-msgstr ""
+msgstr "Siapkan tambalan untuk pengiriman surel"
#: command-list.h
msgid "Verifies the connectivity and validity of the objects in the database"
-msgstr ""
+msgstr "Verifikasi hubungan dan validitas objek di dalam basis data"
#: command-list.h
msgid "Cleanup unnecessary files and optimize the local repository"
-msgstr ""
+msgstr "Bersihkan berkas yang tak perlu dan optimalkan repositori lokal"
#: command-list.h
msgid "Extract commit ID from an archive created using git-archive"
-msgstr ""
+msgstr "Ekstrak ID komit dari arsip yang dibuat dengan git-archive"
#: command-list.h
msgid "Print lines matching a pattern"
-msgstr ""
+msgstr "Cetak baris yang cocok dengan sebuah pola"
#: command-list.h
msgid "A portable graphical interface to Git"
-msgstr ""
+msgstr "Sebuah antarmuka grafis Git portabel"
#: command-list.h
msgid "Compute object ID and optionally creates a blob from a file"
-msgstr ""
+msgstr "Hitung ID objek dan buat blob dari berkas (opsional)"
#: command-list.h
msgid "Display help information about Git"
-msgstr ""
+msgstr "Perlihatkan bantuan mengenai Git"
#: command-list.h
msgid "Run git hooks"
-msgstr ""
+msgstr "Jalankan kait git"
#: command-list.h
msgid "Server side implementation of Git over HTTP"
-msgstr ""
+msgstr "Impementasi sisi peladen dari Git lewat HTTP"
#: command-list.h
msgid "Download from a remote Git repository via HTTP"
-msgstr ""
+msgstr "Unduh dari repositori Git remote lewat HTTP"
#: command-list.h
msgid "Push objects over HTTP/DAV to another repository"
-msgstr ""
+msgstr "Dorong objek lewat HTTP/DAV ke repositori lainnya"
#: command-list.h
msgid "Send a collection of patches from stdin to an IMAP folder"
-msgstr ""
+msgstr "Kirim koleksi tambalan dari masukan standar ke sebuah direktori IMAP"
#: command-list.h
msgid "Build pack index file for an existing packed archive"
-msgstr ""
+msgstr "Bangun berkas indeks pak dari arsip terpak yang sudah ada"
#: command-list.h
msgid "Create an empty Git repository or reinitialize an existing one"
-msgstr ""
+msgstr "Buat repositori Git kosong atau inisialisasi ulang yang sudah ada"
#: command-list.h
msgid "Instantly browse your working repository in gitweb"
-msgstr ""
+msgstr "Jelajahi repositori kerja Anda secara instan di gitweb"
#: command-list.h
msgid "Add or parse structured information in commit messages"
-msgstr ""
+msgstr "Tambah atau urai informasi terstruktur di dalam pesan komit"
#: command-list.h
msgid "Show commit logs"
-msgstr ""
+msgstr "Perlihatkan log komit"
#: command-list.h
msgid "Show information about files in the index and the working tree"
msgstr ""
+"Perlihatkan informasi mengenai berkas-berkas di dalam indeks dan pohon kerja"
#: command-list.h
msgid "List references in a remote repository"
-msgstr ""
+msgstr "Daftar referensi di repositori remote"
#: command-list.h
msgid "List the contents of a tree object"
-msgstr ""
+msgstr "Daftar isi objek pohon"
#: command-list.h
msgid "Extracts patch and authorship from a single e-mail message"
-msgstr ""
+msgstr "Ekstrak berkas dan kepengarangan dari pesan surel tunggal"
#: command-list.h
msgid "Simple UNIX mbox splitter program"
-msgstr ""
+msgstr "Program pemisah mbox UNIX sederhana"
#: command-list.h
msgid "Run tasks to optimize Git repository data"
-msgstr ""
+msgstr "Jalankan tugas untuk mengoptimalkan data repositori Git"
#: command-list.h
msgid "Join two or more development histories together"
-msgstr ""
+msgstr "Gabungkan dua riwayat pengembangan atau lebih bersama-sama"
#: command-list.h
msgid "Find as good common ancestors as possible for a merge"
-msgstr ""
+msgstr "Cari leluhur umum sebaik-baiknya untuk penggabungan"
#: command-list.h
msgid "Run a three-way file merge"
-msgstr ""
+msgstr "Lakukan penggabungan berkas tiga arah"
#: command-list.h
msgid "Run a merge for files needing merging"
-msgstr ""
+msgstr "Lakukan penggabungan untuk berkas yang perlu digabungkan"
#: command-list.h
msgid "The standard helper program to use with git-merge-index"
-msgstr ""
+msgstr "Program pembantu standar untuk digunakan dengan git-merge-index"
#: command-list.h
-msgid "Show three-way merge without touching index"
-msgstr ""
+msgid "Perform merge without touching index or working tree"
+msgstr "Lakukan penggabungan tanpa menyentuh indeks atau pohon kerja"
#: command-list.h
msgid "Run merge conflict resolution tools to resolve merge conflicts"
msgstr ""
+"Jalankan alat penyelesaian konflik penggabungan untuk menyelesaikan konflik "
+"penggabungan"
#: command-list.h
msgid "Creates a tag object with extra validation"
-msgstr ""
+msgstr "Buat objek tag dengan validasi ekstra"
#: command-list.h
msgid "Build a tree-object from ls-tree formatted text"
-msgstr ""
+msgstr "Bangun objek pohon dari teks berformat ls-tree"
#: command-list.h
msgid "Write and verify multi-pack-indexes"
-msgstr ""
+msgstr "Tulis dan verifikasi indeks multipak"
#: command-list.h
msgid "Move or rename a file, a directory, or a symlink"
-msgstr ""
+msgstr "Pindahkan atau namai ulang berkas, direktori, atau tautan simbolik"
#: command-list.h
msgid "Find symbolic names for given revs"
-msgstr ""
+msgstr "Cari nama simbolik untuk revisi yang diberikan"
#: command-list.h
msgid "Add or inspect object notes"
-msgstr ""
+msgstr "Tambahkan atau inspeksi catatan objek"
#: command-list.h
msgid "Import from and submit to Perforce repositories"
-msgstr ""
+msgstr "Impor dari dan kirimkan ke repositori Perfore"
#: command-list.h
msgid "Create a packed archive of objects"
-msgstr ""
+msgstr "Buat arsip terpak dari objek"
#: command-list.h
msgid "Find redundant pack files"
-msgstr ""
+msgstr "Cari berkas pak berlebihan"
#: command-list.h
msgid "Pack heads and tags for efficient repository access"
-msgstr ""
+msgstr "Pak kepala dan tag untuk akses repositori yang efisien"
#: command-list.h
msgid "Compute unique ID for a patch"
-msgstr ""
+msgstr "Hitung ID unik untuk sebuah tambalan"
#: command-list.h
msgid "Prune all unreachable objects from the object database"
-msgstr ""
+msgstr "Pangkas semua objek tak tercapai dari basis data objek"
#: command-list.h
msgid "Remove extra objects that are already in pack files"
-msgstr ""
+msgstr "Hapus semua objek ekstra yang sudah ada di dalam berkas pak"
#: command-list.h
msgid "Fetch from and integrate with another repository or a local branch"
-msgstr ""
+msgstr "Ambil dan integrasikan dengan repositori lain atau sebuah cabang lokal"
#: command-list.h
msgid "Update remote refs along with associated objects"
-msgstr ""
+msgstr "Perbarui referensi remote bersama dengan objek yang terkait"
#: command-list.h
msgid "Applies a quilt patchset onto the current branch"
-msgstr ""
+msgstr "Terapkan set tambalan quilt pada cabang saat ini"
#: command-list.h
msgid "Compare two commit ranges (e.g. two versions of a branch)"
-msgstr ""
+msgstr "Bandingkan dua rentang komit (misalnya dua versi cabang)"
#: command-list.h
msgid "Reads tree information into the index"
-msgstr ""
+msgstr "Baca informasi pohon ke dalam indeks"
#: command-list.h
msgid "Reapply commits on top of another base tip"
-msgstr ""
+msgstr "Terapkan ulang komit-komit di atas dasar ujung yang lainnya"
#: command-list.h
msgid "Receive what is pushed into the repository"
-msgstr ""
+msgstr "Terima apa yang didorong pada repositori"
#: command-list.h
msgid "Manage reflog information"
-msgstr ""
+msgstr "Kelola informasi log referensi"
#: command-list.h
msgid "Manage set of tracked repositories"
-msgstr ""
+msgstr "Kelola set repositori terlacak"
#: command-list.h
msgid "Pack unpacked objects in a repository"
-msgstr ""
+msgstr "Pak objek tak terpak di dalam repositori"
#: command-list.h
msgid "Create, list, delete refs to replace objects"
-msgstr ""
+msgstr "Buat, daftar, hapus referensi untuk mengganti objek"
#: command-list.h
msgid "Generates a summary of pending changes"
-msgstr ""
+msgstr "Buat ringkasan perubahan tertunda"
#: command-list.h
msgid "Reuse recorded resolution of conflicted merges"
-msgstr ""
+msgstr "Gunakan ulang resolusi konflik penggabungan terekam"
#: command-list.h
msgid "Reset current HEAD to the specified state"
-msgstr ""
+msgstr "Setel ulang HEAD saat ini ke keadaan yang disebutkan"
#: command-list.h
msgid "Restore working tree files"
-msgstr ""
+msgstr "Pulihkan berkas pohon kerja"
#: command-list.h
msgid "Lists commit objects in reverse chronological order"
-msgstr ""
+msgstr "Daftar objek komit dalam urutan kronologis terbalik"
#: command-list.h
msgid "Pick out and massage parameters"
-msgstr ""
+msgstr "Ambil dan pijat parameter"
#: command-list.h
msgid "Revert some existing commits"
-msgstr ""
+msgstr "Balikkan beberapa komit yang sudah ada"
#: command-list.h
msgid "Remove files from the working tree and from the index"
-msgstr ""
+msgstr "Hapus berkas dari pohon kerja dan indeks"
#: command-list.h
msgid "Send a collection of patches as emails"
-msgstr ""
+msgstr "Kirim koleksi tambalan sebagai surel"
#: command-list.h
msgid "Push objects over Git protocol to another repository"
-msgstr ""
+msgstr "Dorong objek lewat protokol Git ke repositori lainnya"
#: command-list.h
msgid "Git's i18n setup code for shell scripts"
-msgstr ""
+msgstr "kode penyusunan i18n Git untuk skrip cangkang"
#: command-list.h
msgid "Common Git shell script setup code"
-msgstr ""
+msgstr "kode penyusunan skrip cangkang umum Git"
#: command-list.h
msgid "Restricted login shell for Git-only SSH access"
-msgstr ""
+msgstr "Cangkang masuk terbatas untuk akses SSH hanya Git"
#: command-list.h
msgid "Summarize 'git log' output"
-msgstr ""
+msgstr "Rangkum keluaran 'git log'"
#: command-list.h
msgid "Show various types of objects"
-msgstr ""
+msgstr "Perlihatkan berbagai tipe objek"
#: command-list.h
msgid "Show branches and their commits"
-msgstr ""
+msgstr "Perlihatkan cabang dan komitnya"
#: command-list.h
msgid "Show packed archive index"
-msgstr ""
+msgstr "Perlihatkan indeks arsip terpak"
#: command-list.h
msgid "List references in a local repository"
-msgstr ""
+msgstr "Daftar referensi di repositori lokal"
#: command-list.h
msgid "Reduce your working tree to a subset of tracked files"
-msgstr ""
+msgstr "Kurangi pohon kerja Anda sampai subset berkas terlacak"
#: command-list.h
msgid "Add file contents to the staging area"
-msgstr ""
+msgstr "Tambahkan isi berkas ke area penggelaran"
#: command-list.h
msgid "Stash the changes in a dirty working directory away"
-msgstr ""
+msgstr "Stase perubahan di dalam direktori kerja"
#: command-list.h
msgid "Show the working tree status"
-msgstr ""
+msgstr "Perlihatkan status pohon kerja"
#: command-list.h
msgid "Remove unnecessary whitespace"
-msgstr ""
+msgstr "Hapus spasi yang tidak diperlukan"
#: command-list.h
msgid "Initialize, update or inspect submodules"
-msgstr ""
+msgstr "Inisialisasi, perbarui atau inspeksi submodul"
#: command-list.h
msgid "Bidirectional operation between a Subversion repository and Git"
-msgstr ""
+msgstr "Operasi dua arah antara repositori Subversion dan Git"
#: command-list.h
msgid "Switch branches"
-msgstr ""
+msgstr "Ganti cabang"
#: command-list.h
msgid "Read, modify and delete symbolic refs"
-msgstr ""
+msgstr "Baca, ubah dan hapus referensi simbolik"
#: command-list.h
msgid "Create, list, delete or verify a tag object signed with GPG"
msgstr ""
+"Buat, daftar, hapus atau verifikasi objek tag yang ditandatangani dengan GPG"
#: command-list.h
msgid "Creates a temporary file with a blob's contents"
-msgstr ""
+msgstr "Buat berkas sementara dengan isi blob"
#: command-list.h
msgid "Unpack objects from a packed archive"
-msgstr ""
+msgstr "Bongkar objek dari arsip terpak"
#: command-list.h
msgid "Register file contents in the working tree to the index"
-msgstr ""
+msgstr "Daftarkan isi berkas dalam pohon kerja ke indeks"
#: command-list.h
msgid "Update the object name stored in a ref safely"
-msgstr ""
+msgstr "Perbarui nama objek yang disimpan di dalam referensi secara aman"
#: command-list.h
msgid "Update auxiliary info file to help dumb servers"
-msgstr ""
+msgstr "Perbarui berkas info tambahan untuk membantu peladen bodoh"
#: command-list.h
msgid "Send archive back to git-archive"
-msgstr ""
+msgstr "Kirim arsip kembali ke git-archive"
#: command-list.h
msgid "Send objects packed back to git-fetch-pack"
-msgstr ""
+msgstr "Kirim objek terpak kembali ke git-fetch-pack"
#: command-list.h
msgid "Show a Git logical variable"
-msgstr ""
+msgstr "Perlihatkan variabel logikal Git"
#: command-list.h
msgid "Check the GPG signature of commits"
-msgstr ""
+msgstr "Periksa tandatangan GPG komit"
#: command-list.h
msgid "Validate packed Git archive files"
-msgstr ""
+msgstr "Validasi berkas arsip Git terpak"
#: command-list.h
msgid "Check the GPG signature of tags"
-msgstr ""
+msgstr "Periksa tandatangan GPG tag"
#: command-list.h
msgid "Show logs with difference each commit introduces"
-msgstr ""
+msgstr "Perlihatkan log dengan perbedaan yang dimasukkan setiap komit"
#: command-list.h
msgid "Manage multiple working trees"
-msgstr ""
+msgstr "Kelola banyak pohon kerja"
#: command-list.h
msgid "Create a tree object from the current index"
-msgstr ""
+msgstr "Buat objek pohon dari indeks saat ini"
#: command-list.h
msgid "Defining attributes per path"
-msgstr ""
+msgstr "Tentukan atribut tiap jalur"
#: command-list.h
msgid "Git command-line interface and conventions"
-msgstr ""
+msgstr "Antarmuka baris perintah dan konvensi Git"
#: command-list.h
msgid "A Git core tutorial for developers"
-msgstr ""
+msgstr "Tutorial Git dasar untuk pengembang"
#: command-list.h
msgid "Providing usernames and passwords to Git"
-msgstr ""
+msgstr "Sediakan nama pengguna dan kata sandi ke Git"
#: command-list.h
msgid "Git for CVS users"
-msgstr ""
+msgstr "Git untuk pengguna CVS"
#: command-list.h
msgid "Tweaking diff output"
-msgstr ""
+msgstr "Ubah keluaran diff"
#: command-list.h
msgid "A useful minimum set of commands for Everyday Git"
-msgstr ""
+msgstr "Set perintah berguna minimal untuk Git setiap hari"
#: command-list.h
msgid "Frequently asked questions about using Git"
-msgstr ""
+msgstr "Pertanyaan yang sering diajukan tentang penggunaan Git"
+
+#: command-list.h
+msgid "The bundle file format"
+msgstr "Format berkas bundel"
+
+#: command-list.h
+msgid "Chunk-based file formats"
+msgstr "Berkas format berbasis bingkah"
+
+#: command-list.h
+msgid "Git commit graph format"
+msgstr "Format grafik komit Git"
+
+#: command-list.h
+msgid "Git index format"
+msgstr "Format indeks Git"
+
+#: command-list.h
+msgid "Git pack format"
+msgstr "Format pak Git"
+
+#: command-list.h
+msgid "Git cryptographic signature formats"
+msgstr "Format tandatangan kriptografik Git"
#: command-list.h
msgid "A Git Glossary"
-msgstr ""
+msgstr "Glosarium Git"
#: command-list.h
msgid "Hooks used by Git"
-msgstr ""
+msgstr "Kait yang digunakan oleh Git"
#: command-list.h
msgid "Specifies intentionally untracked files to ignore"
-msgstr ""
+msgstr "Sengaja menyebutkan berkas tak terlacak untuk diabaikan"
#: command-list.h
msgid "The Git repository browser"
-msgstr ""
+msgstr "Penjelajah repositori Git"
#: command-list.h
msgid "Map author/committer names and/or E-Mail addresses"
-msgstr ""
+msgstr "Petakan nama pengarang/pengkomit dan/atau alamat surel"
#: command-list.h
msgid "Defining submodule properties"
-msgstr ""
+msgstr "Menentukan properti submodul"
#: command-list.h
msgid "Git namespaces"
-msgstr ""
+msgstr "Nama lingkup Git"
+
+#: command-list.h
+msgid "Protocol v0 and v1 capabilities"
+msgstr "Kemampuan protokol v0 dan v1"
+
+#: command-list.h
+msgid "Things common to various protocols"
+msgstr "Hal-hal yang umum pada berbagai protokol"
+
+#: command-list.h
+msgid "Git HTTP-based protocols"
+msgstr "Protokol Git berbasis HTTP"
+
+#: command-list.h
+msgid "How packs are transferred over-the-wire"
+msgstr "Bagaimana pak ditransfer lewat kabel"
+
+#: command-list.h
+msgid "Git Wire Protocol, Version 2"
+msgstr "Protokol kabel Git, versi 2"
#: command-list.h
msgid "Helper programs to interact with remote repositories"
-msgstr ""
+msgstr "Program pembantu untuk berinteraksi dengan repositori remote"
#: command-list.h
msgid "Git Repository Layout"
-msgstr ""
+msgstr "Tata letak repositori Git"
#: command-list.h
msgid "Specifying revisions and ranges for Git"
-msgstr ""
+msgstr "Menyebutkan revisi dan rentang untuk Git"
#: command-list.h
msgid "Mounting one repository inside another"
-msgstr ""
+msgstr "Menaiki satu repositori di dalam lainnya"
#: command-list.h
msgid "A tutorial introduction to Git"
-msgstr ""
+msgstr "Tutorial perkenalan Git"
#: command-list.h
msgid "A tutorial introduction to Git: part two"
-msgstr ""
+msgstr "Tutorial perkenalan Git: bagian dua"
#: command-list.h
msgid "Git web interface (web frontend to Git repositories)"
-msgstr ""
+msgstr "Antarmuka web Git (tampilan depan web untuk repositori Git)"
#: command-list.h
msgid "An overview of recommended workflows with Git"
-msgstr ""
+msgstr "Selayang pandang alur kerja yang direkomendasikan dengan Git"
+
+#: command-list.h
+msgid "A tool for managing large Git repositories"
+msgstr "Alat untuk mengelola repositori Git besar"
#: commit-graph.c
msgid "commit-graph file is too small"
-msgstr ""
+msgstr "berkas grafik komit terlalu kecil"
#: commit-graph.c
#, c-format
msgid "commit-graph signature %X does not match signature %X"
-msgstr ""
+msgstr "tanda tangan grafik komit %X tidak cocok dengan tanda tangan %X"
#: commit-graph.c
#, c-format
msgid "commit-graph version %X does not match version %X"
-msgstr ""
+msgstr "versi grafik komit %X tidak cocok dengan versi %X"
#: commit-graph.c
#, c-format
msgid "commit-graph hash version %X does not match version %X"
-msgstr ""
+msgstr "versi hash grafik komit %X tidak cocok dengan versi %X"
#: commit-graph.c
#, c-format
msgid "commit-graph file is too small to hold %u chunks"
-msgstr ""
+msgstr "berkas grafik komit terlalu kecil untuk menyimpan %u bingkah"
#: commit-graph.c
msgid "commit-graph has no base graphs chunk"
-msgstr ""
+msgstr "grafik komit tidak punya bingkah grafik dasar"
#: commit-graph.c
msgid "commit-graph chain does not match"
-msgstr ""
+msgstr "rantai grafik komit tidak cocok"
#: commit-graph.c
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
-msgstr ""
+msgstr "rantai grafik komit tidak cocok: baris '%s' bukan sebuah hash"
#: commit-graph.c
msgid "unable to find all commit-graph files"
-msgstr ""
+msgstr "tidak dapat menemukan semua berkas grafik komit"
#: commit-graph.c
msgid "invalid commit position. commit-graph is likely corrupt"
-msgstr ""
+msgstr "posisi komit tidak valid. grafik komit mungkin rusak"
#: commit-graph.c
#, c-format
msgid "could not find commit %s"
-msgstr ""
+msgstr "tidak dapat menemukan komit %s"
#: commit-graph.c
msgid "commit-graph requires overflow generation data but has none"
-msgstr ""
+msgstr "grafik komit memerlukan pembuatan data meluap tapi tidak punya"
#: commit-graph.c
msgid "Loading known commits in commit graph"
-msgstr ""
+msgstr "Memuat komit yang dikenal di grafik komit"
#: commit-graph.c
msgid "Expanding reachable commits in commit graph"
-msgstr ""
+msgstr "Memperluas komit yang dapat dijangkau di grafik komit"
#: commit-graph.c
msgid "Clearing commit marks in commit graph"
-msgstr ""
+msgstr "Membersihkan penanda komit di grafik komit"
#: commit-graph.c
msgid "Computing commit graph topological levels"
-msgstr ""
+msgstr "Menghitung tingat topologis grafik komit"
#: commit-graph.c
msgid "Computing commit graph generation numbers"
-msgstr ""
+msgstr "Menghitung jumlah pembuatan grafik komit"
#: commit-graph.c
msgid "Computing commit changed paths Bloom filters"
-msgstr ""
+msgstr "Menghitung komit yang berubah jalurnya oleh penyaring Bloom"
#: commit-graph.c
msgid "Collecting referenced commits"
-msgstr ""
+msgstr "Mengumpulkan komit tereferensi"
#: commit-graph.c
#, c-format
msgid "Finding commits for commit graph in %<PRIuMAX> pack"
msgid_plural "Finding commits for commit graph in %<PRIuMAX> packs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Mencari komit untuk grafik komit di dalam pak %<PRIuMAX>"
+msgstr[1] "Mencari komit untuk grafik komit di dalam pak %<PRIuMAX>"
#: commit-graph.c
#, c-format
msgid "error adding pack %s"
-msgstr ""
+msgstr "kesalahan menambahkan pak %s"
#: commit-graph.c
#, c-format
msgid "error opening index for %s"
-msgstr ""
+msgstr "kesalahan membuka indeks untuk %s"
#: commit-graph.c
msgid "Finding commits for commit graph among packed objects"
-msgstr ""
+msgstr "Mencari komit untuk grafik komit di antara objek terpak"
#: commit-graph.c
msgid "Finding extra edges in commit graph"
-msgstr ""
+msgstr "Mencari tepi ekstra di dalam grafik komit"
#: commit-graph.c
msgid "failed to write correct number of base graph ids"
-msgstr ""
+msgstr "gagal menulis jumlah id grafik dasar yang benar"
#: commit-graph.c
msgid "unable to create temporary graph layer"
-msgstr ""
+msgstr "tidak dapat membuat lapisan grafik dasar"
#: commit-graph.c
#, c-format
msgid "unable to adjust shared permissions for '%s'"
-msgstr ""
+msgstr "tidak dapat menyesuaikan perizinan berbagi untuk '%s'"
#: commit-graph.c
#, c-format
msgid "Writing out commit graph in %d pass"
msgid_plural "Writing out commit graph in %d passes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Menulis grafik komit dalam %d fase"
+msgstr[1] "Menulis grafik komit dalam %d fase"
#: commit-graph.c
msgid "unable to open commit-graph chain file"
-msgstr ""
+msgstr "tidak dapat membuka berkas rantai grafik komit"
#: commit-graph.c
msgid "failed to rename base commit-graph file"
-msgstr ""
+msgstr "gagal menamai ulang berkas grafik komit dasar"
#: commit-graph.c
msgid "failed to rename temporary commit-graph file"
-msgstr ""
+msgstr "gagal menamai ulang berkas grafik komit sementara"
#: commit-graph.c
msgid "Scanning merged commits"
-msgstr ""
+msgstr "Memindai komit tergabung"
#: commit-graph.c
msgid "Merging commit-graph"
-msgstr ""
+msgstr "Menggabungkan grafik komit"
#: commit-graph.c
msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled"
-msgstr ""
+msgstr "mencoba menulis grafik komit, tapi 'core.commitGraph' dimatikan"
#: commit-graph.c
msgid "too many commits to write graph"
-msgstr ""
+msgstr "terlalu banyak komit untuk menulis grafik"
#: commit-graph.c
msgid "the commit-graph file has incorrect checksum and is likely corrupt"
-msgstr ""
+msgstr "berkas grafik komit punya checksum salah dan mungkin rusak"
#: commit-graph.c
#, c-format
msgid "commit-graph has incorrect OID order: %s then %s"
-msgstr ""
+msgstr "grafik komit punya urutan OID salah: %s lalu %s"
#: commit-graph.c
#, c-format
msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u"
-msgstr ""
+msgstr "grafik komit punya nilai kipas keluar salah: fanout[%d] = %u != %u"
#: commit-graph.c
#, c-format
msgid "failed to parse commit %s from commit-graph"
-msgstr ""
+msgstr "gagal menguraikan komit %s dari grafik komit"
#: commit-graph.c
msgid "Verifying commits in commit graph"
-msgstr ""
+msgstr "Memverifikasi komit di dalam grafik komit"
#: commit-graph.c
#, c-format
msgid "failed to parse commit %s from object database for commit-graph"
-msgstr ""
+msgstr "gagal menguraikan komit %s dari basis data objek untuk grafik komit"
#: commit-graph.c
#, c-format
msgid "root tree OID for commit %s in commit-graph is %s != %s"
-msgstr ""
+msgstr "OID pohon akar untuk komit %s di dalam grafik komit yaitu %s != %s"
#: commit-graph.c
#, c-format
msgid "commit-graph parent list for commit %s is too long"
-msgstr ""
+msgstr "daftar induk grafik komit untuk %s terlalu panjang"
#: commit-graph.c
#, c-format
msgid "commit-graph parent for %s is %s != %s"
-msgstr ""
+msgstr "induk grafik komit untuk %s adalah %s != %s"
#: commit-graph.c
#, c-format
msgid "commit-graph parent list for commit %s terminates early"
-msgstr ""
+msgstr "daftar induk grafik komit untuk komit %s berakhir lebih awal"
#: commit-graph.c
#, c-format
msgid ""
"commit-graph has generation number zero for commit %s, but non-zero elsewhere"
msgstr ""
+"grafik komit punya angka pembuatan nol untuk komit %s, tapi bukan nol di "
+"tempat lain"
#: commit-graph.c
#, c-format
msgid ""
"commit-graph has non-zero generation number for commit %s, but zero elsewhere"
msgstr ""
+"grafik komit punya angka pembuatan bukan nol untuk komit %s, tapi nol di "
+"tempat lain"
#: commit-graph.c
#, c-format
msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>"
-msgstr ""
+msgstr "pembuatan grafik komit untuk komit %s yaitu %<PRIuMAX> < %<PRIuMAX>"
#: commit-graph.c
#, c-format
msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
msgstr ""
+"tanggal komit untuk komit %s di dalam grafik komit yaitu %<PRIuMAX> != "
+"%<PRIuMAX>"
#: commit.c
#, c-format
@@ -17485,6 +17836,16 @@ msgstr ""
msgid "no libc information available\n"
msgstr ""
+#: compat/disk.h
+#, c-format
+msgid "could not determine free disk size for '%s'"
+msgstr ""
+
+#: compat/disk.h
+#, c-format
+msgid "could not get info for '%s'"
+msgstr ""
+
#: compat/fsmonitor/fsm-health-win32.c
#, c-format
msgid "[GLE %ld] health thread could not open '%ls'"
@@ -17553,6 +17914,16 @@ msgstr ""
msgid "could not read directory changes [GLE %ld]"
msgstr ""
+#: compat/fsmonitor/fsm-settings-win32.c
+#, c-format
+msgid "[GLE %ld] unable to open for read '%ls'"
+msgstr ""
+
+#: compat/fsmonitor/fsm-settings-win32.c
+#, c-format
+msgid "[GLE %ld] unable to get protocol information for '%ls'"
+msgstr ""
+
#: compat/mingw.c
#, c-format
msgid "failed to copy SID (%ld)"
@@ -18231,224 +18602,6 @@ msgstr "gagal menulis ke rev-list"
msgid "failed to close rev-list's stdin"
msgstr "gagal menutup masukan standar rev-list"
-#: contrib/scalar/scalar.c worktree.c
-#, c-format
-msgid "'%s' does not exist"
-msgstr "'%s' tidak ada"
-
-#: contrib/scalar/scalar.c
-msgid "need a working directory"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "could not find enlistment root"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not switch to '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not configure %s=%s"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "could not configure log.excludeDecoration"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "Scalar enlistments require a worktree"
-msgstr ""
-
-#: contrib/scalar/scalar.c dir.c
-#, c-format
-msgid "could not open directory '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "skipping '%s', which is neither file nor directory"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not determine free disk size for '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not get info for '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "remote HEAD is not a branch: '%.*s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "failed to get default branch name from remote; using local default"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "failed to get default branch name"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "failed to unregister repository"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "failed to delete enlistment directory"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "branch to checkout after clone"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "when cloning, create full working directory"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "only download metadata for the branch that will be checked out"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "scalar clone [<options>] [--] <repo> [<dir>]"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "cannot deduce worktree name from '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "directory '%s' exists already"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "failed to get default branch for '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not configure remote in '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not configure '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "partial clone failed; attempting full clone"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "could not configure for full clone"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "scalar diagnose [<enlistment>]"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not create directory for '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "could not duplicate stdout"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "failed to write archive"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "`scalar list` does not take arguments"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "scalar register [<enlistment>]"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "reconfigure all registered enlistments"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "scalar reconfigure [--all | <enlistment>]"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "--all or <enlistment>, but not both"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "git repository gone in '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid ""
-"scalar run <task> [<enlistment>]\n"
-"Tasks:\n"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "no such task: '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "scalar unregister [<enlistment>]"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "scalar delete <enlistment>"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "refusing to delete current working directory"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "include Git version"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "include Git's build options"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "scalar verbose [-v | --verbose] [--build-options]"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "-C requires a <directory>"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-#, c-format
-msgid "could not change to '%s'"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid "-c requires a <key>=<value> argument"
-msgstr ""
-
-#: contrib/scalar/scalar.c
-msgid ""
-"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n"
-"\n"
-"Commands:\n"
-msgstr ""
-
#: convert.c
#, c-format
msgid "illegal crlf_action %d"
@@ -18664,57 +18817,93 @@ msgstr[1] "%<PRIuMAX> tahun yang lalu"
#: delta-islands.c
msgid "Propagating island marks"
-msgstr ""
+msgstr "Menyebarkan penanda pulau"
#: delta-islands.c
#, c-format
msgid "bad tree object %s"
-msgstr ""
+msgstr "objek pohon jelek %s"
#: delta-islands.c
#, c-format
msgid "failed to load island regex for '%s': %s"
-msgstr ""
+msgstr "gagal memuat regex pulau untuk '%s': %s"
#: delta-islands.c
#, c-format
msgid "island regex from config has too many capture groups (max=%d)"
msgstr ""
+"regeks pulau dari konfigurasi punya terlalu banyak grup tangkap (max=%d)"
#: delta-islands.c
#, c-format
msgid "Marked %d islands, done.\n"
-msgstr ""
+msgstr "%d pulau ditandai, selesai.\n"
+
+#: diagnose.c
+#, c-format
+msgid "invalid --%s value '%s'"
+msgstr "nilai --%s tidak valid '%s'"
+
+#: diagnose.c
+#, c-format
+msgid "could not archive missing directory '%s'"
+msgstr "tidak dapat mengarsipkan direktori hilang '%s'"
+
+#: diagnose.c dir.c
+#, c-format
+msgid "could not open directory '%s'"
+msgstr "tidak dapat membuka direktori '%s'"
+
+#: diagnose.c
+#, c-format
+msgid "skipping '%s', which is neither file nor directory"
+msgstr "melewatkan '%s', yang bukan berkas atau direktori"
+
+#: diagnose.c
+msgid "could not duplicate stdout"
+msgstr "tidak dapat menggandakan keluaran standar"
+
+#: diagnose.c
+#, c-format
+msgid "could not add directory '%s' to archiver"
+msgstr "tidak dapat menambahkan direktori '%s' ke pengarsip"
+
+#: diagnose.c
+msgid "failed to write archive"
+msgstr "gagal menulis arsip"
#: diff-lib.c
msgid "--merge-base does not work with ranges"
-msgstr ""
+msgstr "--merge-base tidak bekerja dengan rentang"
#: diff-lib.c
msgid "--merge-base only works with commits"
-msgstr ""
+msgstr "--merge-base hanya bekerja dengan komit"
#: diff-lib.c
msgid "unable to get HEAD"
-msgstr ""
+msgstr "tidak dapat mendapatkan HEAD"
#: diff-lib.c
msgid "no merge base found"
-msgstr ""
+msgstr "dasar penggabungan tidak ditemukan"
#: diff-lib.c
msgid "multiple merge bases found"
-msgstr ""
+msgstr "banyak dasar penggabungan ditemukan"
#: diff-no-index.c
msgid "git diff --no-index [<options>] <path> <path>"
-msgstr ""
+msgstr "git diff --no-index [<opsi>] <jalur> <jalur>"
#: diff-no-index.c
msgid ""
"Not a git repository. Use --no-index to compare two paths outside a working "
"tree"
msgstr ""
+"Bukan sebuah repositori git. Gunakan --no-index untuk membandingkan dua "
+"jalur di luar pohon kerja"
#: diff.c
#, c-format
@@ -18802,7 +18991,7 @@ msgstr "nilai --stat tidak valid: %s"
#: diff.c parse-options.c
#, c-format
msgid "%s expects a numerical value"
-msgstr "%s harap nilai numerik"
+msgstr "%s berharap nilai numerik"
#: diff.c
#, c-format
@@ -19343,53 +19532,53 @@ msgstr ""
#: diffcore-order.c
#, c-format
msgid "failed to read orderfile '%s'"
-msgstr ""
+msgstr "gagal membaca berkas urutan '%s'"
#: diffcore-rename.c
msgid "Performing inexact rename detection"
-msgstr ""
+msgstr "Melakukan deteksi penamaan ulang tidak eksak"
#: diffcore-rotate.c
#, c-format
msgid "No such path '%s' in the diff"
-msgstr ""
+msgstr "Tidak ada jalur seperti '%s' di dalam diff"
#: dir.c
#, c-format
msgid "pathspec '%s' did not match any file(s) known to git"
-msgstr ""
+msgstr "spek jalur '%s' tidak cocok dengan berkas apapun yang git kenal"
#: dir.c
#, c-format
msgid "unrecognized pattern: '%s'"
-msgstr ""
+msgstr "pola tidak dikenal: '%s'"
#: dir.c
#, c-format
msgid "unrecognized negative pattern: '%s'"
-msgstr ""
+msgstr "pola negatif tidak dikenal: '%s'"
#: dir.c
#, c-format
msgid "your sparse-checkout file may have issues: pattern '%s' is repeated"
-msgstr ""
+msgstr "berkas sparse-checkout Anda mungkin ada masalah: pola '%s' diulangi"
#: dir.c
msgid "disabling cone pattern matching"
-msgstr ""
+msgstr "mematikan pencocokan pola kerucut"
#: dir.c
#, c-format
msgid "cannot use %s as an exclude file"
-msgstr ""
+msgstr "tidak dapat menggunakan %s sebagai berkas pengecualian"
#: dir.c
msgid "failed to get kernel name and information"
-msgstr ""
+msgstr "gagal mendapatkan nama dan informasi kernel"
#: dir.c
msgid "untracked cache is disabled on this system or location"
-msgstr ""
+msgstr "tembolok tak terlacat dimatikan pada sistem atau lokasi ini"
#: dir.c
msgid ""
@@ -19402,22 +19591,22 @@ msgstr ""
#: dir.c
#, c-format
msgid "index file corrupt in repo %s"
-msgstr ""
+msgstr "berkas indeks rusak pada repo %s"
#: dir.c
#, c-format
msgid "could not create directories for %s"
-msgstr ""
+msgstr "tidak dapat membuat direktori untuk %s"
#: dir.c
#, c-format
msgid "could not migrate git directory from '%s' to '%s'"
-msgstr ""
+msgstr "tidak dapat memigrasikan direktori git dari '%s' ke '%s'"
#: editor.c
#, c-format
msgid "hint: Waiting for your editor to close the file...%c"
-msgstr ""
+msgstr "petunjuk: Menunggu penyunting Anda untuk menutup berkas...%c"
#: entry.c
msgid "Filtering content"
@@ -19460,6 +19649,10 @@ msgid "unable to write to remote"
msgstr "tidak dapat menulis ke remote"
#: fetch-pack.c
+msgid "Server supports filter"
+msgstr "Peladen mendukung saringan"
+
+#: fetch-pack.c
#, c-format
msgid "invalid shallow line: %s"
msgstr "baris dangkal tidak valid: %s"
@@ -19601,10 +19794,6 @@ msgid "Server does not support shallow requests"
msgstr "Peladen tidak mendukung permintaan dangkal"
#: fetch-pack.c
-msgid "Server supports filter"
-msgstr "Peladen mendukung saringan"
-
-#: fetch-pack.c
msgid "unable to write request to remote"
msgstr "tidak dapat menulis permintaan kepada remote"
@@ -20027,6 +20216,14 @@ msgid "Low-level Commands / Internal Helpers"
msgstr "Perintah Tingak Rendah / Pembantu Internal"
#: help.c
+msgid "User-facing repository, command and file interfaces"
+msgstr ""
+
+#: help.c
+msgid "Developer-facing file file formats, protocols and interfaces"
+msgstr ""
+
+#: help.c
#, c-format
msgid "available git commands in '%s'"
msgstr "perintah git yang tersedia di '%s'"
@@ -20044,6 +20241,14 @@ msgid "The Git concept guides are:"
msgstr "Panduan konsep Git adalah:"
#: help.c
+msgid "User-facing repository, command and file interfaces:"
+msgstr ""
+
+#: help.c
+msgid "File formats, protocols and other developer interfaces:"
+msgstr ""
+
+#: help.c
msgid "External commands"
msgstr "Perintah eksternal"
@@ -20140,11 +20345,6 @@ msgstr ""
"Anda dapat menonaktifkan peringatan ini dengan `git config advice."
"ignoredHook false`."
-#: hook.c
-#, c-format
-msgid "Couldn't start hook '%s'\n"
-msgstr "Tidak dapat memulai kait '%s'\n"
-
#: http-fetch.c
#, c-format
msgid "argument to --packfile must be a valid hash (got '%s')"
@@ -20354,21 +20554,16 @@ msgstr ""
msgid "quoted CRLF detected"
msgstr ""
-#: merge-ort-wrappers.c merge-recursive.c
-#, c-format
-msgid ""
-"Your local changes to the following files would be overwritten by merge:\n"
-" %s"
-msgstr ""
-"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh "
-"penggabungan:\n"
-" %s"
-
#: merge-ort.c merge-recursive.c
#, c-format
msgid "Failed to merge submodule %s (not checked out)"
msgstr "Gagal menggabungkan submodul %s (tidak di-checkout)"
+#: merge-ort.c
+#, c-format
+msgid "Failed to merge submodule %s (no merge base)"
+msgstr "Gagal menggabungkan submodul %s (tidak ada dasar penggabungan)"
+
#: merge-ort.c merge-recursive.c
#, c-format
msgid "Failed to merge submodule %s (commits not present)"
@@ -20393,28 +20588,10 @@ msgstr "Gagal menggabungkan submodul %s"
#: merge-ort.c
#, c-format
msgid ""
-"Failed to merge submodule %s, but a possible merge resolution exists:\n"
-"%s\n"
-msgstr ""
-"Gagal menggabungkan submodul %s, tetapi sebuah penyelesaian penggabungan "
-"yang mungkin ada:\n"
-"%s\n"
-
-#: merge-ort.c merge-recursive.c
-#, c-format
-msgid ""
-"If this is correct simply add it to the index for example\n"
-"by using:\n"
-"\n"
-" git update-index --cacheinfo 160000 %s \"%s\"\n"
-"\n"
-"which will accept this suggestion.\n"
+"Failed to merge submodule %s, but a possible merge resolution exists: %s"
msgstr ""
-"Jika benar, cukup misalkan tambahkan ke indeks dengan menggunakan:\n"
-"\n"
-" git update-index --cacheinfo 160000 %s \"%s\"\n"
-"\n"
-"yang akan menerima saran ini.\n"
+"Gagal menggabungkan submodul %s, tetapi ada kemungkinan penyelesaian "
+"penggabungan: %s"
#: merge-ort.c
#, c-format
@@ -20603,14 +20780,47 @@ msgstr ""
"KONFLIK (pengubahan/penghapusan): %s dihapus di %s dan diubah di %s. Versi "
"%s dari %s ditinggalkan di dalam pohon."
+#. TRANSLATORS: This is a line of advice to resolve a merge
+#. conflict in a submodule. The first argument is the submodule
+#. name, and the second argument is the abbreviated id of the
+#. commit that needs to be merged. For example:
+#. - go to submodule (mysubmodule), and either merge commit abc1234"
+#.
#: merge-ort.c
#, c-format
msgid ""
-"Note: %s not up to date and in way of checking out conflicted version; old "
-"copy renamed to %s"
+" - go to submodule (%s), and either merge commit %s\n"
+" or update to an existing commit which has merged those changes\n"
msgstr ""
-"Catatan: %s tidak terbaru dan dalam men-checkout versi berkonflik; salinan "
-"lama dinamai ulang ke %s"
+" - pergi ke submodul (%s), dan baik gabungkan komit %s\n"
+" atau perbarui ke komit yang sudah ada yang sudah menggabungkan "
+"perubahan tersebut\n"
+
+#: merge-ort.c
+#, c-format
+msgid ""
+"Recursive merging with submodules currently only supports trivial cases.\n"
+"Please manually handle the merging of each conflicted submodule.\n"
+"This can be accomplished with the following steps:\n"
+"%s - come back to superproject and run:\n"
+"\n"
+" git add %s\n"
+"\n"
+" to record the above merge or update\n"
+" - resolve any other conflicts in the superproject\n"
+" - commit the resulting index in the superproject\n"
+msgstr ""
+"Saat ini penggabungan rekursif dengan submodul hanya mendukung kasus-kasus "
+"sepele.\n"
+"Mohon tangani penggabungan setiap submodul berkonflik secara manual.\n"
+"Hal ini dapat dicapai dengan langkah berikut:\n"
+"%s - kembali ke proyek induk dan jalankan:\n"
+"\n"
+" git add %s\n"
+"\n"
+" untuk merekam penggabungan di atas atau perbarui\n"
+" - selesaikan semua konflik lainnya di dalam proyek induk\n"
+" - komit hasil indeks di dalam proyek induk\n"
#. TRANSLATORS: The %s arguments are: 1) tree hash of a merge
#. base, and 2-3) the trees for the two trees we're merging.
@@ -20702,6 +20912,22 @@ msgstr "Sebuah resolusi penggabungan yang mungkin ditemukan untuk submodul:\n"
#: merge-recursive.c
#, c-format
+msgid ""
+"If this is correct simply add it to the index for example\n"
+"by using:\n"
+"\n"
+" git update-index --cacheinfo 160000 %s \"%s\"\n"
+"\n"
+"which will accept this suggestion.\n"
+msgstr ""
+"Jika benar, cukup misalkan tambahkan ke indeks dengan menggunakan:\n"
+"\n"
+" git update-index --cacheinfo 160000 %s \"%s\"\n"
+"\n"
+"yang akan menerima saran ini.\n"
+
+#: merge-recursive.c
+#, c-format
msgid "Failed to merge submodule %s (multiple merges found)"
msgstr "Gagal menggabungkan submodul %s (banyak penggabungan ditemukan)"
@@ -21350,6 +21576,26 @@ msgstr "kebingungan oleh data sumber objek tidak stabil untuk %s"
#: object-file.c
#, c-format
+msgid "write stream object %ld != %<PRIuMAX>"
+msgstr "tulis objek arus %ld != %<PRIuMAX>"
+
+#: object-file.c
+#, c-format
+msgid "unable to stream deflate new object (%d)"
+msgstr "tidak dapat mengempis arus objek baru (%d)"
+
+#: object-file.c
+#, c-format
+msgid "deflateEnd on stream object failed (%d)"
+msgstr "deflateEnd pada objek arus gagal (%d)"
+
+#: object-file.c
+#, c-format
+msgid "unable to create directory %s"
+msgstr "gagal membuat direktori %s"
+
+#: object-file.c
+#, c-format
msgid "cannot read object for %s"
msgstr "tidak dapat membaca objek untuk %s"
@@ -21616,6 +21862,72 @@ msgstr "tidak dapat menguraikan objek: %s"
msgid "hash mismatch %s"
msgstr "hash tidak cocok %s"
+#: pack-bitmap-write.c
+msgid "trying to write commit not in index"
+msgstr "mencoba menulis komit yang bukan di indeks"
+
+#: pack-bitmap.c
+msgid "failed to load bitmap index (corrupted?)"
+msgstr "gagal menulis indeks bitmap (rusak?)"
+
+#: pack-bitmap.c
+msgid "corrupted bitmap index (too small)"
+msgstr "indeks bitmap rusak (terlalu kecil)"
+
+#: pack-bitmap.c
+msgid "corrupted bitmap index file (wrong header)"
+msgstr "berkas indeks bitmap rusak (kepala salah)"
+
+#: pack-bitmap.c
+#, c-format
+msgid "unsupported version '%d' for bitmap index file"
+msgstr "versi '%d' tidak didukung untuk berkas indeks bitmap"
+
+#: pack-bitmap.c
+msgid "corrupted bitmap index file (too short to fit hash cache)"
+msgstr "berkas indeks bitmap rusak (terlalu pendek untuk masuk tembolok hash)"
+
+#: pack-bitmap.c
+msgid "corrupted bitmap index file (too short to fit lookup table)"
+msgstr ""
+"berkas indeks bitmap rusak (terlalu pendek untuk masuk tabel pencarian)"
+
+#: pack-bitmap.c
+#, c-format
+msgid "duplicate entry in bitmap index: '%s'"
+msgstr "entri duplikat di indeks bitmap: '%s'"
+
+#: pack-bitmap.c
+#, c-format
+msgid "corrupt ewah bitmap: truncated header for entry %d"
+msgstr "bitmap ewah rusak: kepala terpotong untuk entri %d"
+
+#: pack-bitmap.c
+#, c-format
+msgid "corrupt ewah bitmap: commit index %u out of range"
+msgstr "bitmap ewah rusak: indeks komit %u di luar jangkauan"
+
+#: pack-bitmap.c
+msgid "corrupted bitmap pack index"
+msgstr "indeks pak bitmap rusak"
+
+#: pack-bitmap.c
+msgid "invalid XOR offset in bitmap pack index"
+msgstr "offset XOR tidak valid di indeks pak bitmap"
+
+#: pack-bitmap.c
+msgid "cannot fstat bitmap file"
+msgstr "tidak dapat fstat berkas bitmap"
+
+#: pack-bitmap.c
+#, c-format
+msgid "ignoring extra bitmap file: '%s'"
+msgstr "mengabaikan berkas bitmap tambahan: '%s'"
+
+#: pack-bitmap.c
+msgid "checksum doesn't match in MIDX and bitmap"
+msgstr "checksum tidak cocok di MIDX dan bitmap"
+
#: pack-bitmap.c
msgid "multi-pack bitmap is missing required reverse index"
msgstr "bitmap multipak kehilangan indeks balik yang diperlukan"
@@ -21631,9 +21943,69 @@ msgid "preferred pack (%s) is invalid"
msgstr "pak yang disukai '%s' kadaluarsa"
#: pack-bitmap.c
+msgid "corrupt bitmap lookup table: triplet position out of index"
+msgstr "tabel pencarian bitmap rusak: posisi kembar tiga di luar indeks"
+
+#: pack-bitmap.c
+msgid "corrupt bitmap lookup table: xor chain exceed entry count"
+msgstr "tabel pencarian bitmap rusak: rantai xor melebihi hitungan entri"
+
+#: pack-bitmap.c
+#, c-format
+msgid "corrupt bitmap lookup table: commit index %u out of range"
+msgstr "tabel pencarian bitmap rusak: indeks komit %u di luar jangkauan"
+
+#: pack-bitmap.c
+#, c-format
+msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
+msgstr "bitmap ewah rusak: kepala terpotong untuk bitmap komit \"%s\""
+
+#: pack-bitmap.c
+#, c-format
+msgid "object '%s' not found in type bitmaps"
+msgstr "objek '%s' tidak ditemukan di bitmap tipe"
+
+#: pack-bitmap.c
+#, c-format
+msgid "object '%s' does not have a unique type"
+msgstr "objek '%s' tidak punya tipe unik"
+
+#: pack-bitmap.c
+#, c-format
+msgid "object '%s': real type '%s', expected: '%s'"
+msgstr "objek '%s': bertipe sebenarnya '%s', diharapkan '%s'"
+
+#: pack-bitmap.c
+#, c-format
+msgid "object not in bitmap: '%s'"
+msgstr "object bukan di bitmap: '%s'"
+
+#: pack-bitmap.c
+msgid "failed to load bitmap indexes"
+msgstr "gagal memuat indeks bitmap"
+
+#: pack-bitmap.c
+msgid "you must specify exactly one commit to test"
+msgstr "Anda harus sebutkan tepat satu komit untuk diuji"
+
+#: pack-bitmap.c
+#, c-format
+msgid "commit '%s' doesn't have an indexed bitmap"
+msgstr "komit '%s' tidak punya bitmap terindeks"
+
+#: pack-bitmap.c
+msgid "mismatch in bitmap results"
+msgstr "ketidaksesuaian di dalam hasil bitmap"
+
+#: pack-bitmap.c
#, c-format
-msgid "could not find %s in pack %s at offset %<PRIuMAX>"
-msgstr "tidak dapat menemukan %s di dalam pak %s pada offset %<PRIuMAX>"
+msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>"
+msgstr "tidak dapat menemukan %s di dalam pak '%s' pada offset %<PRIuMAX>"
+
+#: pack-bitmap.c
+#, c-format
+msgid "unable to get disk usage of '%s'"
+msgstr "tidak dapat mendapatkan penggunaan disk dari '%s'"
#: pack-mtimes.c
#, c-format
@@ -21726,91 +22098,97 @@ msgstr "offset di luar ujung indeks pak untuk %s (indeks terpotong?)"
#: parse-options-cb.c
#, c-format
msgid "malformed expiration date '%s'"
-msgstr ""
+msgstr "tanggal kadaluarsa rusak '%s'"
#: parse-options-cb.c
#, c-format
msgid "option `%s' expects \"always\", \"auto\", or \"never\""
-msgstr ""
+msgstr "opsi `%s' mengharapkan \"always\", \"auto\", atau \"never\""
#: parse-options-cb.c
#, c-format
msgid "malformed object name '%s'"
-msgstr ""
+msgstr "nama objek rusak '%s'"
#: parse-options-cb.c
#, c-format
msgid "option `%s' expects \"%s\" or \"%s\""
-msgstr ""
+msgstr "opsi `%s' mengharapkan \"%s\" atau \"%s\""
#: parse-options.c
#, c-format
msgid "%s requires a value"
-msgstr ""
+msgstr "%s butuh sebuah nilai"
#: parse-options.c
#, c-format
msgid "%s is incompatible with %s"
-msgstr ""
+msgstr "%s tidak kompatibel dengan %s"
#: parse-options.c
#, c-format
msgid "%s : incompatible with something else"
-msgstr ""
+msgstr "%s : tidak kompatibel dengan sesuatu yang lain"
#: parse-options.c
#, c-format
msgid "%s takes no value"
-msgstr ""
+msgstr "%s tidak mengambil nilai apapun"
#: parse-options.c
#, c-format
msgid "%s isn't available"
-msgstr ""
+msgstr "%s tidak ada"
#: parse-options.c
#, c-format
msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
msgstr ""
+"%s mengharapkan nilai bilangan bulat non negatif dengan akhiran opsional k/m/"
+"g"
#: parse-options.c
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
-msgstr ""
+msgstr "opsi ambigu: %s (bisa jadi --%s%s atau --%s%s)"
#: parse-options.c
#, c-format
msgid "did you mean `--%s` (with two dashes)?"
-msgstr ""
+msgstr "mungkin maksud Anda `--%s` (dengan dua tanda strip)?"
#: parse-options.c
#, c-format
msgid "alias of --%s"
-msgstr ""
+msgstr "alias untuk --%s"
+
+#: parse-options.c
+msgid "need a subcommand"
+msgstr "butuh sebuah subperintah"
#: parse-options.c
#, c-format
msgid "unknown option `%s'"
-msgstr ""
+msgstr "opsi tidak dikenal `%s'"
#: parse-options.c
#, c-format
msgid "unknown switch `%c'"
-msgstr ""
+msgstr "sakelar tidak dikenal `%c'"
#: parse-options.c
#, c-format
msgid "unknown non-ascii option in string: `%s'"
-msgstr ""
+msgstr "opsi non-ascii di dalam untai tidak dikenal: `%s'"
#: parse-options.c
msgid "..."
-msgstr ""
+msgstr "..."
#: parse-options.c
#, c-format
msgid "usage: %s"
-msgstr ""
+msgstr "penggunaan: %s"
#. TRANSLATORS: the colon here should align with the
#. one in "usage: %s" translation.
@@ -21818,7 +22196,7 @@ msgstr ""
#: parse-options.c
#, c-format
msgid " or: %s"
-msgstr ""
+msgstr " atau: %s"
#. TRANSLATORS: You should only need to translate this format
#. string if your language is a RTL language (e.g. Arabic,
@@ -21842,130 +22220,135 @@ msgstr ""
#: parse-options.c
#, c-format
msgid "%*s%s"
-msgstr ""
+msgstr "%*s%s"
#: parse-options.c
#, c-format
msgid " %s"
-msgstr ""
+msgstr " %s"
#: parse-options.c
msgid "-NUM"
-msgstr ""
+msgstr "-NUM"
#: parse-options.h
msgid "expiry-date"
-msgstr ""
+msgstr "tanggal kadaluarsa"
#: parse-options.h
msgid "no-op (backward compatibility)"
-msgstr ""
+msgstr "tanpa operasi (kompatibilitas ke belakang)"
#: parse-options.h
msgid "be more verbose"
-msgstr ""
+msgstr "jadi lebih berkata-kata"
#: parse-options.h
msgid "be more quiet"
-msgstr ""
+msgstr "jadi lebih dian"
#: parse-options.h
msgid "use <n> digits to display object names"
-msgstr ""
+msgstr "gunakan <n> digit untuk menampilkan nama objek"
#: parse-options.h
msgid "how to strip spaces and #comments from message"
-msgstr ""
+msgstr "bagaimana cara mengupas spasi dan #komentar dari pesan"
#: parse-options.h
msgid "read pathspec from file"
-msgstr ""
+msgstr "baca spek jalur dari berkas"
#: parse-options.h
msgid ""
"with --pathspec-from-file, pathspec elements are separated with NUL character"
msgstr ""
+"dengan --pathspec-from-file, elemen spek jalur dipisahkan dengan karakter NUL"
#: path.c
#, c-format
msgid "Could not make %s writable by group"
-msgstr ""
+msgstr "Tidak dapat membuat %s bisa ditulis oleh grup"
#: pathspec.c
msgid "Escape character '\\' not allowed as last character in attr value"
msgstr ""
+"Karakter pelarian '\\' tidak diperbolehkan sebagai karakter terakhir dalam "
+"nilai atribut"
#: pathspec.c
msgid "Only one 'attr:' specification is allowed."
-msgstr ""
+msgstr "Hanya satu spesifikasi 'attr:' yang diperbolehkan."
#: pathspec.c
msgid "attr spec must not be empty"
-msgstr ""
+msgstr "spek atribut tidak boleh kosong"
#: pathspec.c
#, c-format
msgid "invalid attribute name %s"
-msgstr ""
+msgstr "nama atribut tidak valid %s"
#: pathspec.c
msgid "global 'glob' and 'noglob' pathspec settings are incompatible"
-msgstr ""
+msgstr "setelan spek jalur global 'glob' dan 'noglob' tidak kompatibel"
#: pathspec.c
msgid ""
"global 'literal' pathspec setting is incompatible with all other global "
"pathspec settings"
msgstr ""
+"setelan spek jalur global 'literal' tidak kompatibel dengan semua setelan "
+"spek jalur lainnya"
#: pathspec.c
msgid "invalid parameter for pathspec magic 'prefix'"
-msgstr ""
+msgstr "parameter tidak valid untuk spek jalur ajaib 'prefix'"
#: pathspec.c
#, c-format
msgid "Invalid pathspec magic '%.*s' in '%s'"
-msgstr ""
+msgstr "Spek jalur ajaib '%.*s' tidak valid di '%s'"
#: pathspec.c
#, c-format
msgid "Missing ')' at the end of pathspec magic in '%s'"
-msgstr ""
+msgstr "Kehilangan ')' pada akhir spek jalur ajaib di '%s'"
#: pathspec.c
#, c-format
msgid "Unimplemented pathspec magic '%c' in '%s'"
-msgstr ""
+msgstr "Spek jalur ajaib '%c' tidak diterapkan di '%s'"
#: pathspec.c
#, c-format
msgid "%s: 'literal' and 'glob' are incompatible"
-msgstr ""
+msgstr "%s: 'literal' dan 'glob' tidak kompatibel"
#: pathspec.c
#, c-format
msgid "%s: '%s' is outside repository at '%s'"
-msgstr ""
+msgstr "%s: '%s' di luar repositori pada '%s'"
#: pathspec.c
#, c-format
msgid "'%s' (mnemonic: '%c')"
-msgstr ""
+msgstr "'%s' (mnemonik: '%c')"
#: pathspec.c
#, c-format
msgid "%s: pathspec magic not supported by this command: %s"
-msgstr ""
+msgstr "%s: spek jalur ajaib tidak didukung oleh perintah ini: %s"
#: pathspec.c
#, c-format
msgid "pathspec '%s' is beyond a symbolic link"
-msgstr ""
+msgstr "spek jalur '%s' di luar tautan simbolik"
#: pathspec.c
#, c-format
msgid "line is badly quoted: %s"
-msgstr ""
+msgstr "baris dikutip jelek: %s"
#: pkt-line.c
msgid "unable to write flush packet"
@@ -22059,20 +22442,20 @@ msgstr ""
#: prune-packed.c
msgid "Removing duplicate objects"
-msgstr ""
+msgstr "Menghapus objek duplikat"
#: range-diff.c
msgid "could not start `log`"
-msgstr ""
+msgstr "tidak dapat memulai `log`"
#: range-diff.c
msgid "could not read `log` output"
-msgstr ""
+msgstr "tidak dapat membaca keluaran `log`"
#: range-diff.c sequencer.c
#, c-format
msgid "could not parse commit '%s'"
-msgstr ""
+msgstr "tidak dapat menguraikan komit '%s'"
#: range-diff.c
#, c-format
@@ -22080,20 +22463,22 @@ msgid ""
"could not parse first line of `log` output: did not start with 'commit ': "
"'%s'"
msgstr ""
+"tidak dapat menguraikan baris pertama dari keluaran `log`: tidak dimulai "
+"dengan 'commit ': '%s'"
#: range-diff.c
#, c-format
msgid "could not parse git header '%.*s'"
-msgstr ""
+msgstr "tidak dapat menguraikan kepala git '%.*s'"
#: range-diff.c
msgid "failed to generate diff"
-msgstr ""
+msgstr "gagal membuat diff"
#: range-diff.c
#, c-format
msgid "could not parse log for '%s'"
-msgstr ""
+msgstr "tidak dapat menguraikan log untuk '%s'"
#: read-cache.c
#, c-format
@@ -22313,9 +22698,12 @@ msgid ""
"l, label <label> = label current HEAD with a name\n"
"t, reset <label> = reset HEAD to a label\n"
"m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]\n"
-". create a merge commit using the original merge commit's\n"
-". message (or the oneline, if no original merge commit was\n"
-". specified); use -c <commit> to reword the commit message\n"
+" create a merge commit using the original merge commit's\n"
+" message (or the oneline, if no original merge commit was\n"
+" specified); use -c <commit> to reword the commit message\n"
+"u, update-ref <ref> = track a placeholder for the <ref> to be updated\n"
+" to this position in the new commits. The <ref> is\n"
+" updated at the end of the rebase\n"
"\n"
"These lines can be re-ordered; they are executed from top to bottom.\n"
msgstr ""
@@ -22326,20 +22714,23 @@ msgstr ""
"e, edit <komit> = gunakan komit, tapi berhenti untuk amandemen\n"
"s, squash <komit> = gunakan komit, tapi lebur ke komit sebelumnya\n"
"f, fixup [-C | -c] <komit> = seperti \"squash\" tapi hanya pertahankan\n"
-" pesan komit sebelumnya, kecuali -C digunakan, dimana\n"
-" hanya pertahankan pesan komit ini; -c sama dengan -C "
-"tapi\n"
-" buka penyuntingx, exec <perintah> = jalankan perintah "
-"(sisa baris) menggunakan cangkang\n"
+" pesan komit sebelumnya; kecuali -C digunakan, dimana\n"
+" hanya pertahankan pesan komit ini; -c sama dengan -C\n"
+" tapi buka penyunting\n"
+"x, exec <perintah> = jalankan perintah (sisa baris) menggunakan cangkang\n"
"b, break = berhenti disini (lanjutkan pendasaran ulang nanti dengan 'git "
"rebase --continue')\n"
"d, drop <komit> = hapus komit\n"
"l, label <label> = tandai HEAD saat ini dengan nama\n"
"t, reset <label> = setel ulang HEAD ke sebuah label\n"
"m, merge [-C <komit> | -c <komit>] <label> [# <satu baris>]\n"
-". buat komit penggabungan dengan pesan komit penggabungan asli\n"
-". (atau satu baris, jika tidak ada komit penggabungan asli yang\n"
-". disebutkan); gunakan -c <komit> untuk menulis ulang pesan komit\n"
+" buat komit penggabungan dengan pesan komit penggabungan asli\n"
+" (atau satu baris, jika tidak ada komit penggabungan asli yang\n"
+" disebutkan); gunakan -c <komit> untuk menulis ulang pesan komit\n"
+"u, update-ref <referensi> = lacak tempat penampung untuk <referensi> yang\n"
+" akan diperbarui ke posisi ini di dalam komit\n"
+" baru. <referensi> diperbarui pada "
+"akhir pendasaran ulang.\n"
"\n"
"Baris diatas dapat disusun ulang; hal itu dieksekusi dari atas ke bawah.\n"
@@ -22431,245 +22822,246 @@ msgstr "%s: 'preserve' digantikan oleh 'merges'"
#: ref-filter.c wt-status.c
msgid "gone"
-msgstr ""
+msgstr "pergi"
#: ref-filter.c
#, c-format
msgid "ahead %d"
-msgstr ""
+msgstr "di depan %d"
#: ref-filter.c
#, c-format
msgid "behind %d"
-msgstr ""
+msgstr "di belakang %d"
#: ref-filter.c
#, c-format
msgid "ahead %d, behind %d"
-msgstr ""
+msgstr "di depan %d, di belakang %d"
#: ref-filter.c
#, c-format
msgid "expected format: %%(color:<color>)"
-msgstr ""
+msgstr "format yang diharapkan: %%(color:<warna>)"
#: ref-filter.c
#, c-format
msgid "unrecognized color: %%(color:%s)"
-msgstr ""
+msgstr "warna tidak dikenal: %%(color:%s)"
#: ref-filter.c
#, c-format
msgid "Integer value expected refname:lstrip=%s"
-msgstr ""
+msgstr "Nilai bilangan bulat diharapkan refname:lstrip=%s"
#: ref-filter.c
#, c-format
msgid "Integer value expected refname:rstrip=%s"
-msgstr ""
+msgstr "Nilai bilangan bulat diharapkan refname:rstrip=%s"
#: ref-filter.c
#, c-format
msgid "unrecognized %%(%s) argument: %s"
-msgstr ""
+msgstr "argumen %%(%s) tidak dikenal: %s"
#: ref-filter.c
#, c-format
msgid "%%(objecttype) does not take arguments"
-msgstr ""
+msgstr "%%(objecttype) tidak mengambil argumen"
#: ref-filter.c
#, c-format
msgid "%%(deltabase) does not take arguments"
-msgstr ""
+msgstr "%%(deltabase) tidak mengambil argumen"
#: ref-filter.c
#, c-format
msgid "%%(body) does not take arguments"
-msgstr ""
+msgstr "%%(body) tidak mengambil argumen"
#: ref-filter.c
#, c-format
msgid "expected %%(trailers:key=<value>)"
-msgstr ""
+msgstr "diharapkan %%(trailers:key=<nilai>)"
#: ref-filter.c
#, c-format
msgid "unknown %%(trailers) argument: %s"
-msgstr ""
+msgstr "argumen %%(trailers) tidak dikenal: %s"
#: ref-filter.c
#, c-format
msgid "positive value expected contents:lines=%s"
-msgstr ""
+msgstr "nilai positif diharapkan contents:lines=%s"
#: ref-filter.c
#, c-format
msgid "positive value expected '%s' in %%(%s)"
-msgstr ""
+msgstr "nilai positif '%s' diharapkan di %%(%s)"
#: ref-filter.c
#, c-format
msgid "unrecognized email option: %s"
-msgstr ""
+msgstr "opsi surel tidak dikenal: %s"
#: ref-filter.c
#, c-format
msgid "expected format: %%(align:<width>,<position>)"
-msgstr ""
+msgstr "format diharapkan: %%(align:<lebar>,<posisi>)"
#: ref-filter.c
#, c-format
msgid "unrecognized position:%s"
-msgstr ""
+msgstr "posisi tidak dikenal: %s"
#: ref-filter.c
#, c-format
msgid "unrecognized width:%s"
-msgstr ""
+msgstr "lebar tidak dikenal: %s"
#: ref-filter.c
#, c-format
msgid "positive width expected with the %%(align) atom"
-msgstr ""
+msgstr "lebar positif diharapkan dengan atom %%(align)"
#: ref-filter.c
#, c-format
msgid "%%(rest) does not take arguments"
-msgstr ""
+msgstr "%%(rest) tidak mengambil argumen"
#: ref-filter.c
#, c-format
msgid "malformed field name: %.*s"
-msgstr ""
+msgstr "nama bidang rusak: %.*s"
#: ref-filter.c
#, c-format
msgid "unknown field name: %.*s"
-msgstr ""
+msgstr "nama bidang tidak dikenal: %.*s"
#: ref-filter.c
#, c-format
msgid ""
"not a git repository, but the field '%.*s' requires access to object data"
msgstr ""
+"bukan sebuah repositori git, tapi bidang '%.*s' butuh akses ke data objek"
#: ref-filter.c
#, c-format
msgid "format: %%(%s) atom used without a %%(%s) atom"
-msgstr ""
+msgstr "format: atom %%(%s) digunakan tanpa sebuah atom %%(%s)"
#: ref-filter.c
#, c-format
msgid "format: %%(then) atom used more than once"
-msgstr ""
+msgstr "format: atom%%(then) digunakan lebih dari sekali"
#: ref-filter.c
#, c-format
msgid "format: %%(then) atom used after %%(else)"
-msgstr ""
+msgstr "format: atom %%(then) digunakan setelah %%(else)"
#: ref-filter.c
#, c-format
msgid "format: %%(else) atom used more than once"
-msgstr ""
+msgstr "format: atom %%(else) digunakan lebih dari sekali"
#: ref-filter.c
#, c-format
msgid "format: %%(end) atom used without corresponding atom"
-msgstr ""
+msgstr "format: atom %%(end) digunakan tanpa atom yang bersesuaian"
#: ref-filter.c
#, c-format
msgid "malformed format string %s"
-msgstr ""
+msgstr "untai format %s rusak"
#: ref-filter.c
#, c-format
msgid "this command reject atom %%(%.*s)"
-msgstr ""
+msgstr "perintah ini menolak atom %%(%.*s)"
#: ref-filter.c
#, c-format
msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
-msgstr ""
+msgstr "--format=%.*s tidak dapat digunakan dengan --python, --shell, --tcl"
#: ref-filter.c
#, c-format
msgid "(no branch, rebasing %s)"
-msgstr ""
+msgstr "(tanpa cabang, mendasarkan ulang %s)"
#: ref-filter.c
#, c-format
msgid "(no branch, rebasing detached HEAD %s)"
-msgstr ""
+msgstr "(tanpa cabang, mendasarkan ulang HEAD tercopot %s)"
#: ref-filter.c
#, c-format
msgid "(no branch, bisect started on %s)"
-msgstr ""
+msgstr "(tanpa cabang, pembagian dua dimulai pada %s)"
#: ref-filter.c
#, c-format
msgid "(HEAD detached at %s)"
-msgstr ""
+msgstr "(HEAD tercopot pada %s)"
#: ref-filter.c
#, c-format
msgid "(HEAD detached from %s)"
-msgstr ""
+msgstr "(HEAD tercopot dari %s)"
#: ref-filter.c
msgid "(no branch)"
-msgstr ""
+msgstr "(tanpa cabang)"
#: ref-filter.c
#, c-format
msgid "missing object %s for %s"
-msgstr ""
+msgstr "objek %s hilang untuk %s"
#: ref-filter.c
#, c-format
msgid "parse_object_buffer failed on %s for %s"
-msgstr ""
+msgstr "parse_object_buffer gagal pada %s untuk %s"
#: ref-filter.c
#, c-format
msgid "malformed object at '%s'"
-msgstr ""
+msgstr "objek rusak pada '%s'"
#: ref-filter.c
#, c-format
msgid "ignoring ref with broken name %s"
-msgstr ""
+msgstr "mengabaikan referensi dengan nama rusak %s"
#: ref-filter.c refs.c
#, c-format
msgid "ignoring broken ref %s"
-msgstr ""
+msgstr "mengabaikan referensi rusak %s"
#: ref-filter.c
#, c-format
msgid "format: %%(end) atom missing"
-msgstr ""
+msgstr "format: atom %%(end) hilang"
#: ref-filter.c
#, c-format
msgid "malformed object name %s"
-msgstr ""
+msgstr "nama objek rusak %s"
#: ref-filter.c
#, c-format
msgid "option `%s' must point to a commit"
-msgstr ""
+msgstr "opsi `%s' harus menunjuk pada sebuah komit"
#: ref-filter.h
msgid "key"
-msgstr ""
+msgstr "kunci"
#: ref-filter.h
msgid "field name to sort on"
-msgstr ""
+msgstr "nama bidang untuk diurutkan"
#: reflog.c
#, c-format
@@ -22799,139 +23191,150 @@ msgstr "spek referensi tidak valid '%s'"
#: remote-curl.c
#, c-format
msgid "invalid quoting in push-option value: '%s'"
-msgstr ""
+msgstr "kuotasi tidak valid dalam nilai push-option: '%s'"
#: remote-curl.c
#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
-msgstr ""
+msgstr "%sinfo/refs tidak valid: apakah ini sebuah repositori git?"
#: remote-curl.c
msgid "invalid server response; expected service, got flush packet"
msgstr ""
+"tanggapan peladen tidak valid; mengharapkan layanan, dapat bilasan paket"
#: remote-curl.c
#, c-format
msgid "invalid server response; got '%s'"
-msgstr ""
+msgstr "tanggapan peladen tidak valid; dapat '%s'"
#: remote-curl.c
#, c-format
msgid "repository '%s' not found"
-msgstr ""
+msgstr "repositori '%s' tidak ditemukan"
#: remote-curl.c
#, c-format
msgid "Authentication failed for '%s'"
-msgstr ""
+msgstr "Autentikasi gagal untuk '%s'"
#: remote-curl.c
#, c-format
msgid "unable to access '%s' with http.pinnedPubkey configuration: %s"
-msgstr ""
+msgstr "tidak dapat mengakses '%s' dengan konfigurasi http.pinnedPubkey: %s"
#: remote-curl.c
#, c-format
msgid "unable to access '%s': %s"
-msgstr ""
+msgstr "tidak dapat mengakses '%s': %s"
#: remote-curl.c
#, c-format
msgid "redirecting to %s"
-msgstr ""
+msgstr "mengalihkan ke %s"
#: remote-curl.c
msgid "shouldn't have EOF when not gentle on EOF"
-msgstr ""
+msgstr "seharusnya tidak punya EOF ketika tidak lembut pada EOF"
#: remote-curl.c
msgid "remote server sent unexpected response end packet"
-msgstr ""
+msgstr "peladen remote mengirim paket ujung tanggapan yang tak diharapkan"
#: remote-curl.c
msgid "unable to rewind rpc post data - try increasing http.postBuffer"
msgstr ""
+"tidak dapat memutar ulang data post rpc - coba menaikkan http.postBuffer"
#: remote-curl.c
#, c-format
msgid "remote-curl: bad line length character: %.4s"
-msgstr ""
+msgstr "remote-curl: karakter panjang baris jelek : %.4s"
#: remote-curl.c
msgid "remote-curl: unexpected response end packet"
-msgstr ""
+msgstr "remote-curl: paket ujung tanggapan tidak diharapkan"
#: remote-curl.c
#, c-format
msgid "RPC failed; %s"
-msgstr ""
+msgstr "RPC gagal; %s"
#: remote-curl.c
msgid "cannot handle pushes this big"
-msgstr ""
+msgstr "tidak dapat menangani dorongan sebesar ini"
#: remote-curl.c
#, c-format
msgid "cannot deflate request; zlib deflate error %d"
-msgstr ""
+msgstr "tidak dapat mengempiskan permintaan; kesalahan mengempiskan zlib %d"
#: remote-curl.c
#, c-format
msgid "cannot deflate request; zlib end error %d"
-msgstr ""
+msgstr "tidak dapat mengempiskan permintaan; kesalahan ujung zlib %d"
#: remote-curl.c
#, c-format
msgid "%d bytes of length header were received"
-msgstr ""
+msgstr "%d bita dari kepala panjang diterima"
#: remote-curl.c
#, c-format
msgid "%d bytes of body are still expected"
-msgstr ""
+msgstr "%d bita badan masih diharapkan"
#: remote-curl.c
msgid "dumb http transport does not support shallow capabilities"
-msgstr ""
+msgstr "transportasi http bodoh tidak mendukung kemampuan dangkal"
#: remote-curl.c
msgid "fetch failed."
-msgstr ""
+msgstr "pengambilan gagal."
#: remote-curl.c
msgid "cannot fetch by sha1 over smart http"
-msgstr ""
+msgstr "tidak dapat mengambil oleh sha1 melalui http pintar"
#: remote-curl.c
#, c-format
msgid "protocol error: expected sha/ref, got '%s'"
-msgstr ""
+msgstr "kesalahan protokol: sha/referensi diharapkan, dapat '%s'"
#: remote-curl.c
#, c-format
msgid "http transport does not support %s"
-msgstr ""
+msgstr "transportasi http tidak mendukung %s"
+
+#: remote-curl.c
+msgid "protocol error: expected '<url> <path>', missing space"
+msgstr "kesalahan protokol: '<url> <jalur>' diharapkan, spasi hilang"
+
+#: remote-curl.c
+#, c-format
+msgid "failed to download file at URL '%s'"
+msgstr "gagal mengunduh berkas pada URL '%s'"
#: remote-curl.c
msgid "git-http-push failed"
-msgstr ""
+msgstr "git-http-push gagal"
#: remote-curl.c
msgid "remote-curl: usage: git remote-curl <remote> [<url>]"
-msgstr ""
+msgstr "remote-curl: penggunaan: git remote-curl <remote> [<url>]"
#: remote-curl.c
msgid "remote-curl: error reading command stream from git"
-msgstr ""
+msgstr "remote-curl: kesalahan membaca arus perintah dari git"
#: remote-curl.c
msgid "remote-curl: fetch attempted without a local repo"
-msgstr ""
+msgstr "remote-curl: pengambilan dicoba tanpa repositori lokal"
#: remote-curl.c
#, c-format
msgid "remote-curl: unknown command '%s' from git"
-msgstr ""
+msgstr "remote-curl: perintah tidak dikenal '%s' dari git"
#: remote.c
#, c-format
@@ -23176,7 +23579,9 @@ msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
msgid_plural ""
"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
msgstr[0] ""
+"Cabang Anda di belakang '%s' oleh %d komit, dan bisa di maju-cepatkan.\n"
msgstr[1] ""
+"Cabang Anda di belakan '%s' oleh %d komit, dan bisa di maju-cepatkan.\n"
#: remote.c
msgid " (use \"git pull\" to update your local branch)\n"
@@ -23214,17 +23619,17 @@ msgstr "tidak dapat mencopot satu komponen dari url '%s'"
#: replace-object.c
#, c-format
msgid "bad replace ref name: %s"
-msgstr ""
+msgstr "nama referensi pengganti jelek: %s"
#: replace-object.c
#, c-format
msgid "duplicate replace ref: %s"
-msgstr ""
+msgstr "referensi pengganti duplikat: %s"
#: replace-object.c
#, c-format
msgid "replace depth too high for object %s"
-msgstr ""
+msgstr "kedalaman penggantian terlalu tinggi untuk objek %s"
#: rerere.c
msgid "corrupt MERGE_RR"
@@ -23311,6 +23716,8 @@ msgstr "tidak dapat membuka direktori rr-cache"
#: rerere.h
msgid "update the index with reused conflict resolution if possible"
msgstr ""
+"perbarui indeks dengan resolusi konflik yang digunakan kembali bila "
+"memungkinkan"
#: reset.c
msgid "could not determine HEAD revision"
@@ -23322,6 +23729,16 @@ msgid "failed to find tree of %s"
msgstr "gagal menemukan pohon %s"
#: revision.c
+#, c-format
+msgid "resolve-undo records `%s` which is missing"
+msgstr "resolve-undo merekam `%s` yang dimana hilang"
+
+#: revision.c
+#, c-format
+msgid "could not get commit for ancestry-path argument %s"
+msgstr "tidak dapat mendapatkan komit untuk argumen jalur leluhur '%s'"
+
+#: revision.c
msgid "--unpacked=<packfile> no longer supported"
msgstr "--unpacked=<berkas pak> tidak didukung lagi"
@@ -23345,6 +23762,215 @@ msgstr "-L belum mendukung format diff selain -p dan -s"
#: run-command.c
#, c-format
msgid "cannot create async thread: %s"
+msgstr "tidak dapat membuat utas async: %s"
+
+#: scalar.c worktree.c
+#, c-format
+msgid "'%s' does not exist"
+msgstr "'%s' tidak ada"
+
+#: scalar.c
+#, c-format
+msgid "could not switch to '%s'"
+msgstr ""
+
+#: scalar.c
+msgid "need a working directory"
+msgstr ""
+
+#: scalar.c
+msgid "Scalar enlistments require a worktree"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "could not configure %s=%s"
+msgstr ""
+
+#: scalar.c
+msgid "could not configure log.excludeDecoration"
+msgstr ""
+
+#: scalar.c
+msgid "could not add enlistment"
+msgstr ""
+
+#: scalar.c
+msgid "could not set recommended config"
+msgstr ""
+
+#: scalar.c
+msgid "could not turn on maintenance"
+msgstr ""
+
+#: scalar.c
+msgid "could not start the FSMonitor daemon"
+msgstr ""
+
+#: scalar.c
+msgid "could not turn off maintenance"
+msgstr ""
+
+#: scalar.c
+msgid "could not remove enlistment"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "remote HEAD is not a branch: '%.*s'"
+msgstr ""
+
+#: scalar.c
+msgid "failed to get default branch name from remote; using local default"
+msgstr ""
+
+#: scalar.c
+msgid "failed to get default branch name"
+msgstr ""
+
+#: scalar.c
+msgid "failed to unregister repository"
+msgstr ""
+
+#: scalar.c
+msgid "failed to stop the FSMonitor daemon"
+msgstr ""
+
+#: scalar.c
+msgid "failed to delete enlistment directory"
+msgstr ""
+
+#: scalar.c
+msgid "branch to checkout after clone"
+msgstr ""
+
+#: scalar.c
+msgid "when cloning, create full working directory"
+msgstr ""
+
+#: scalar.c
+msgid "only download metadata for the branch that will be checked out"
+msgstr ""
+
+#: scalar.c
+msgid "scalar clone [<options>] [--] <repo> [<dir>]"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "cannot deduce worktree name from '%s'"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "directory '%s' exists already"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "failed to get default branch for '%s'"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "could not configure remote in '%s'"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "could not configure '%s'"
+msgstr ""
+
+#: scalar.c
+msgid "partial clone failed; attempting full clone"
+msgstr ""
+
+#: scalar.c
+msgid "could not configure for full clone"
+msgstr ""
+
+#: scalar.c
+msgid "scalar diagnose [<enlistment>]"
+msgstr ""
+
+#: scalar.c
+msgid "`scalar list` does not take arguments"
+msgstr ""
+
+#: scalar.c
+msgid "scalar register [<enlistment>]"
+msgstr ""
+
+#: scalar.c
+msgid "reconfigure all registered enlistments"
+msgstr ""
+
+#: scalar.c
+msgid "scalar reconfigure [--all | <enlistment>]"
+msgstr ""
+
+#: scalar.c
+msgid "--all or <enlistment>, but not both"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "git repository gone in '%s'"
+msgstr ""
+
+#: scalar.c
+msgid ""
+"scalar run <task> [<enlistment>]\n"
+"Tasks:\n"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "no such task: '%s'"
+msgstr ""
+
+#: scalar.c
+msgid "scalar unregister [<enlistment>]"
+msgstr ""
+
+#: scalar.c
+msgid "scalar delete <enlistment>"
+msgstr ""
+
+#: scalar.c
+msgid "refusing to delete current working directory"
+msgstr ""
+
+#: scalar.c
+msgid "include Git version"
+msgstr ""
+
+#: scalar.c
+msgid "include Git's build options"
+msgstr ""
+
+#: scalar.c
+msgid "scalar verbose [-v | --verbose] [--build-options]"
+msgstr ""
+
+#: scalar.c
+msgid "-C requires a <directory>"
+msgstr ""
+
+#: scalar.c
+#, c-format
+msgid "could not change to '%s'"
+msgstr ""
+
+#: scalar.c
+msgid "-c requires a <key>=<value> argument"
+msgstr ""
+
+#: scalar.c
+msgid ""
+"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n"
+"\n"
+"Commands:\n"
msgstr ""
#: send-pack.c
@@ -23493,11 +24119,6 @@ msgstr "perubahan lokal Anda akan ditimpa oleh %s."
msgid "commit your changes or stash them to proceed."
msgstr "komit perubahan Anda atau stase untuk melanjutkan."
-#: sequencer.c
-#, c-format
-msgid "%s: fast-forward"
-msgstr "%s: maju-cepat"
-
#. TRANSLATORS: %s will be "revert", "cherry-pick" or
#. "rebase".
#.
@@ -24090,6 +24711,30 @@ msgid "merge: Unable to write new index file"
msgstr "merge: Tidak dapat menulis berkas indeks baru"
#: sequencer.c
+#, c-format
+msgid ""
+"another 'rebase' process appears to be running; '%s.lock' already exists"
+msgstr ""
+
+#: sequencer.c
+#, c-format
+msgid ""
+"Updated the following refs with %s:\n"
+"%s"
+msgstr ""
+"Referensi berikut diperbarui dengan %s:\n"
+"%s"
+
+#: sequencer.c
+#, c-format
+msgid ""
+"Failed to update the following refs with %s:\n"
+"%s"
+msgstr ""
+"Gagal memperbarui referensi berikut dengan %s:\n"
+"%s"
+
+#: sequencer.c
msgid "Cannot autostash"
msgstr "Tidak dapat menstase otomatis"
@@ -24293,6 +24938,11 @@ msgstr "tidak dapat melewatkan perintah pick yang tidak perlu"
msgid "the script was already rearranged."
msgstr "skrip sudah ditata ulang."
+#: sequencer.c
+#, c-format
+msgid "update-refs file at '%s' is invalid"
+msgstr "berkas update-refs pada '%s' tidak valid"
+
#: setup.c
#, c-format
msgid "'%s' is outside repository at '%s'"
@@ -24438,18 +25088,24 @@ msgstr ""
#: setup.c
#, c-format
msgid ""
-"unsafe repository ('%s' is owned by someone else)\n"
-"To add an exception for this directory, call:\n"
+"detected dubious ownership in repository at '%s'\n"
+"%sTo add an exception for this directory, call:\n"
"\n"
"\tgit config --global --add safe.directory %s"
msgstr ""
-"repositori tidak aman ('%s' dimiliki oleh orang lain)\n"
-"Untuk menambahkan pengecualian untuk direktori ini, panggil:\n"
+"perizinan meragukan terdeteksi di dalam repositori pada '%s'\n"
+"%sUntuk menambahkan pengecualian untuk direktori ini, panggil:\n"
"\n"
"\tgit config --global --add safe.directory %s"
#: setup.c
#, c-format
+msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')"
+msgstr ""
+"tidak dapat menggunakan repositori bare '%s' (safe.bareRepository yaitu '%s')"
+
+#: setup.c
+#, c-format
msgid ""
"problem with core.sharedRepository filemode value (0%.3o).\n"
"The owner of files must always have read and write permissions."
@@ -25180,6 +25836,8 @@ msgid ""
"Your local changes to the following files would be overwritten by checkout:\n"
"%%sPlease commit your changes or stash them before you switch branches."
msgstr ""
+"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh checkout:\n"
+"%%sMohon komit atau stase sebelum Anda mengganti cabang."
#: unpack-trees.c
#, c-format
@@ -25187,6 +25845,8 @@ msgid ""
"Your local changes to the following files would be overwritten by checkout:\n"
"%%s"
msgstr ""
+"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh checkout:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25194,6 +25854,9 @@ msgid ""
"Your local changes to the following files would be overwritten by merge:\n"
"%%sPlease commit your changes or stash them before you merge."
msgstr ""
+"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh "
+"penggabungan:\n"
+"%%sMohon komit atau stase sebelum Anda gabungkan."
#: unpack-trees.c
#, c-format
@@ -25201,6 +25864,9 @@ msgid ""
"Your local changes to the following files would be overwritten by merge:\n"
"%%s"
msgstr ""
+"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh "
+"penggabungan:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25208,6 +25874,8 @@ msgid ""
"Your local changes to the following files would be overwritten by %s:\n"
"%%sPlease commit your changes or stash them before you %s."
msgstr ""
+"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh %s:\n"
+"%%sMohon komit atau stase sebelum Anda %s."
#: unpack-trees.c
#, c-format
@@ -25215,6 +25883,8 @@ msgid ""
"Your local changes to the following files would be overwritten by %s:\n"
"%%s"
msgstr ""
+"Perubahan lokal Anda terhadap berkas berikut akan ditimpa oleh %s:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25222,6 +25892,9 @@ msgid ""
"Updating the following directories would lose untracked files in them:\n"
"%s"
msgstr ""
+"Memperbarui direktori berikut akan menghilangkan berkas tak terlacak di "
+"dalam:\n"
+"%s"
#: unpack-trees.c
#, c-format
@@ -25229,6 +25902,8 @@ msgid ""
"Refusing to remove the current working directory:\n"
"%s"
msgstr ""
+"Menolak menghapus direktori kerja saat ini:\n"
+"%s"
#: unpack-trees.c
#, c-format
@@ -25236,6 +25911,8 @@ msgid ""
"The following untracked working tree files would be removed by checkout:\n"
"%%sPlease move or remove them before you switch branches."
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan dihapus oleh checkout:\n"
+"%%sMohon pindahkan atau hapus sebelum Anda berganti cabang."
#: unpack-trees.c
#, c-format
@@ -25243,6 +25920,8 @@ msgid ""
"The following untracked working tree files would be removed by checkout:\n"
"%%s"
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan dihapus oleh checkout:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25250,6 +25929,8 @@ msgid ""
"The following untracked working tree files would be removed by merge:\n"
"%%sPlease move or remove them before you merge."
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan dihapus oleh penggabungan:\n"
+"%%sMohon pindahkan atau hapus sebelum Anda gabungkan."
#: unpack-trees.c
#, c-format
@@ -25257,6 +25938,8 @@ msgid ""
"The following untracked working tree files would be removed by merge:\n"
"%%s"
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan dihapus oleh penggabungan:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25264,6 +25947,8 @@ msgid ""
"The following untracked working tree files would be removed by %s:\n"
"%%sPlease move or remove them before you %s."
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan dihapus oleh %s:\n"
+"%%sMohon pindahkan atau hapus sebelum Anda %s."
#: unpack-trees.c
#, c-format
@@ -25271,6 +25956,8 @@ msgid ""
"The following untracked working tree files would be removed by %s:\n"
"%%s"
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan dihapus oleh %s:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25279,6 +25966,8 @@ msgid ""
"checkout:\n"
"%%sPlease move or remove them before you switch branches."
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan ditimpa oleh checkout:\n"
+"%%sMohon pindahkan atau hapus sebelum Anda berganti cabang."
#: unpack-trees.c
#, c-format
@@ -25287,6 +25976,8 @@ msgid ""
"checkout:\n"
"%%s"
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan ditimpa oleh checkout:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25294,6 +25985,8 @@ msgid ""
"The following untracked working tree files would be overwritten by merge:\n"
"%%sPlease move or remove them before you merge."
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan ditimpa oleh penggabungan:\n"
+"%%sMohon pindahkan atau hapus sebelum Anda gabungkan."
#: unpack-trees.c
#, c-format
@@ -25301,6 +25994,8 @@ msgid ""
"The following untracked working tree files would be overwritten by merge:\n"
"%%s"
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan ditimpa oleh penggabungan:\n"
+"%%s"
#: unpack-trees.c
#, c-format
@@ -25308,6 +26003,8 @@ msgid ""
"The following untracked working tree files would be overwritten by %s:\n"
"%%sPlease move or remove them before you %s."
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan ditimpa oleh %s:\n"
+"%%sMohon pindahkan atau hapus sebelum Anda %s."
#: unpack-trees.c
#, c-format
@@ -25315,11 +26012,13 @@ msgid ""
"The following untracked working tree files would be overwritten by %s:\n"
"%%s"
msgstr ""
+"Berkas pohon kerja tak terlacak berikut akan ditimpa oleh %s:\n"
+"%%s"
#: unpack-trees.c
#, c-format
msgid "Entry '%s' overlaps with '%s'. Cannot bind."
-msgstr ""
+msgstr "Entri '%s' tumpang tindih dengan '%s'. Tidak dapat mengikat."
#: unpack-trees.c
#, c-format
@@ -25327,6 +26026,8 @@ msgid ""
"Cannot update submodule:\n"
"%s"
msgstr ""
+"Tidak dapat memperbarui submodul:\n"
+"%s"
#: unpack-trees.c
#, c-format
@@ -25335,6 +26036,8 @@ msgid ""
"patterns:\n"
"%s"
msgstr ""
+"Jalur berikut tidak diperbarui dan dibiarkan walaupun merupakan pola tipis:\n"
+"%s"
#: unpack-trees.c
#, c-format
@@ -25342,6 +26045,9 @@ msgid ""
"The following paths are unmerged and were left despite sparse patterns:\n"
"%s"
msgstr ""
+"Jalur berikut tidak digabungkan dan dibiarkan walaupun merupakan pola "
+"tipis:\n"
+"%s"
#: unpack-trees.c
#, c-format
@@ -25350,11 +26056,13 @@ msgid ""
"patterns:\n"
"%s"
msgstr ""
+"Jalur berikut sudah ada dan tidak diperbarui walaupun merupakan pola tipis:\n"
+"%s"
#: unpack-trees.c
#, c-format
msgid "Aborting\n"
-msgstr ""
+msgstr "Membatalkan\n"
#: unpack-trees.c
#, c-format
@@ -25362,10 +26070,12 @@ msgid ""
"After fixing the above paths, you may want to run `git sparse-checkout "
"reapply`.\n"
msgstr ""
+"Setelah memperbarui jalur tersebut, Anda mungkin ingin menjalankan `git "
+"sparse-checkout reapply`.\n"
#: unpack-trees.c
msgid "Updating files"
-msgstr ""
+msgstr "Memperbarui berkas"
#: unpack-trees.c
msgid ""
@@ -25373,15 +26083,18 @@ msgid ""
"on a case-insensitive filesystem) and only one from the same\n"
"colliding group is in the working tree:\n"
msgstr ""
+"jalur berikut bertabrakan (misalnya jalur peka huruf besar-kecil pada\n"
+"sistem berkas tidak peka huruf besar-kecil) dan hanya satu dari grup\n"
+"bertabrakan yang sama yang berada di dalam pohon kerja:\n"
#: unpack-trees.c
msgid "Updating index flags"
-msgstr ""
+msgstr "Memperbarui bendera indeks"
#: unpack-trees.c
#, c-format
msgid "worktree and untracked commit have duplicate entries: %s"
-msgstr ""
+msgstr "pohon kerja dan komit tak terlacak punya entri duplikat: %s"
#: upload-pack.c
msgid "expected flush after fetch arguments"
@@ -25416,6 +26129,22 @@ msgstr ""
msgid "invalid '..' path segment"
msgstr ""
+#: usage.c
+msgid "usage: "
+msgstr "penggunaan: "
+
+#: usage.c
+msgid "fatal: "
+msgstr "fatal: "
+
+#: usage.c
+msgid "error: "
+msgstr "kesalahan: "
+
+#: usage.c
+msgid "warning: "
+msgstr "peringatan: "
+
#: walker.c
msgid "Fetching objects"
msgstr ""
@@ -26093,7 +26822,7 @@ msgstr "juga indeks Anda berisi perubahan yang belum dikomit."
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "tidak dapat %s: indeks Anda berisi perubahan yang belum dikomit."
-#: git-merge-octopus.sh
+#: git-merge-octopus.sh git-merge-resolve.sh
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
@@ -26329,26 +27058,6 @@ msgid "ignoring unmerged: %s\n"
msgstr ""
#: git-add--interactive.perl
-#, perl-format
-msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? "
-msgstr ""
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? "
-msgstr ""
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "Apply addition to worktree [y,n,q,a,d%s,?]? "
-msgstr ""
-
-#: git-add--interactive.perl
-#, perl-format
-msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? "
-msgstr ""
-
-#: git-add--interactive.perl
msgid "No other hunks to goto\n"
msgstr ""
@@ -26810,3 +27519,56 @@ msgstr "Melewati %s dengan akhiran cadangan '%s'.\n"
#, perl-format
msgid "Do you really want to send %s? [y|N]: "
msgstr "Anda benar-benar ingin mengirim %s? [y|N]: "
+
+#, c-format
+#~ msgid "could not parse colored hunk header '%.*s'"
+#~ msgstr "tidak dapat menguraikan kepala bingkah berwarna '%.*s'"
+
+#, c-format
+#~ msgid "Unknown subcommand: %s"
+#~ msgstr "Subperintah tidak dikenal: %s"
+
+#~ msgid "checked out in another worktree"
+#~ msgstr "ter-check out di dalam pohon kerja lainnya"
+
+#~ msgid "failed to open stdin of 'crontab'"
+#~ msgstr "gagal membuka masukan standar dari 'crontab'"
+
+#~ msgid "git submodule--helper list [--prefix=<path>] [<path>...]"
+#~ msgstr "git submodule--helper list [--prefix=<jalur>] [<jalur>...]"
+
+#~ msgid "git submodule--helper name <path>"
+#~ msgstr "git submodule--helper name <jalur>"
+
+#, c-format
+#~ msgid "failed to get the default remote for submodule '%s'"
+#~ msgstr "gagal mendapatkan remote asali untuk submodul '%s'"
+
+#, c-format
+#~ msgid "Invalid update mode '%s' for submodule path '%s'"
+#~ msgstr "Mode pembaruan '%s' tidak valid untuk jalur submodul '%s'"
+
+#~ msgid "path into the working tree, across nested submodule boundaries"
+#~ msgstr "jalur ke dalam pohon kerja, melintasi perbatasan submodul bersarang"
+
+#~ msgid "rebase, merge, checkout or none"
+#~ msgstr "dasarkan ulang, gabungkan, checkout atau tidak sama sekali"
+
+#~ msgid "bad value for update parameter"
+#~ msgstr "nilai jelek untuk parameter pembaruan"
+
+#, c-format
+#~ msgid "Couldn't start hook '%s'\n"
+#~ msgstr "Tidak dapat memulai kait '%s'\n"
+
+#, c-format
+#~ msgid ""
+#~ "Note: %s not up to date and in way of checking out conflicted version; "
+#~ "old copy renamed to %s"
+#~ msgstr ""
+#~ "Catatan: %s tidak terbaru dan dalam men-checkout versi berkonflik; "
+#~ "salinan lama dinamai ulang ke %s"
+
+#, c-format
+#~ msgid "%s: fast-forward"
+#~ msgstr "%s: maju-cepat"
diff --git a/reftable/merged.c b/reftable/merged.c
index 2a6efa110d..5ded470c08 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -36,7 +36,7 @@ static int merged_iter_init(struct merged_iter *mi)
.rec = rec,
.index = i,
};
- merged_iter_pqueue_add(&mi->pq, e);
+ merged_iter_pqueue_add(&mi->pq, &e);
}
}
@@ -71,7 +71,7 @@ static int merged_iter_advance_nonnull_subiter(struct merged_iter *mi,
return 0;
}
- merged_iter_pqueue_add(&mi->pq, e);
+ merged_iter_pqueue_add(&mi->pq, &e);
return 0;
}
diff --git a/reftable/pq.c b/reftable/pq.c
index 96ca6dd37b..dcefeb793a 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -71,7 +71,7 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
return e;
}
-void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, struct pq_entry e)
+void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
{
int i = 0;
@@ -81,7 +81,7 @@ void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, struct pq_entry e)
pq->cap * sizeof(struct pq_entry));
}
- pq->heap[pq->len++] = e;
+ pq->heap[pq->len++] = *e;
i = pq->len - 1;
while (i > 0) {
int j = (i - 1) / 2;
diff --git a/reftable/pq.h b/reftable/pq.h
index 56fc1b6d87..e85bac9b52 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -26,7 +26,7 @@ struct pq_entry merged_iter_pqueue_top(struct merged_iter_pqueue pq);
int merged_iter_pqueue_is_empty(struct merged_iter_pqueue pq);
void merged_iter_pqueue_check(struct merged_iter_pqueue pq);
struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
-void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, struct pq_entry e);
+void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/pq_test.c b/reftable/pq_test.c
index 7de5e886f3..011b5c7502 100644
--- a/reftable/pq_test.c
+++ b/reftable/pq_test.c
@@ -46,7 +46,7 @@ static void test_pq(void)
.u.ref = {
.refname = names[i],
} } };
- merged_iter_pqueue_add(&pq, e);
+ merged_iter_pqueue_add(&pq, &e);
merged_iter_pqueue_check(pq);
i = (i * 7) % N;
} while (i != 1);
diff --git a/revision.c b/revision.c
index d5f4463cb6..36e31942ce 100644
--- a/revision.c
+++ b/revision.c
@@ -1907,6 +1907,7 @@ void repo_init_revisions(struct repository *r,
}
init_display_notes(&revs->notes_opt);
+ list_objects_filter_init(&revs->filter);
}
static void add_pending_commit_list(struct rev_info *revs,
diff --git a/contrib/scalar/scalar.c b/scalar.c
index 642d16124e..c5c1ce6891 100644
--- a/contrib/scalar/scalar.c
+++ b/scalar.c
@@ -819,6 +819,25 @@ static int cmd_delete(int argc, const char **argv)
return res;
}
+static int cmd_help(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END(),
+ };
+ const char * const usage[] = {
+ "scalar help",
+ NULL
+ };
+
+ argc = parse_options(argc, argv, NULL, options,
+ usage, 0);
+
+ if (argc != 0)
+ usage_with_options(usage, options);
+
+ return run_git("help", "scalar", NULL);
+}
+
static int cmd_version(int argc, const char **argv)
{
int verbose = 0, build_options = 0;
@@ -858,6 +877,7 @@ static struct {
{ "run", cmd_run },
{ "reconfigure", cmd_reconfigure },
{ "delete", cmd_delete },
+ { "help", cmd_help },
{ "version", cmd_version },
{ "diagnose", cmd_diagnose },
{ NULL, NULL},
diff --git a/t/Makefile b/t/Makefile
index 1c80c0c79a..882782a519 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -36,14 +36,21 @@ CHAINLINTTMP_SQ = $(subst ','\'',$(CHAINLINTTMP))
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
+TLIBS = $(sort $(wildcard lib-*.sh)) annotate-tests.sh
TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh))
+TINTEROP = $(sort $(wildcard interop/i[0-9][0-9][0-9][0-9]-*.sh))
CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test)))
-CHAINLINT = sed -f chainlint.sed
+CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl
+
+# `test-chainlint` (which is a dependency of `test-lint`, `test` and `prove`)
+# checks all tests in all scripts via a single invocation, so tell individual
+# scripts not to "chainlint" themselves
+CHAINLINTSUPPRESS = GIT_TEST_CHAIN_LINT=0 && export GIT_TEST_CHAIN_LINT &&
all: $(DEFAULT_TEST_TARGET)
test: pre-clean check-chainlint $(TEST_LINT)
- $(MAKE) aggregate-results-and-cleanup
+ $(CHAINLINTSUPPRESS) $(MAKE) aggregate-results-and-cleanup
failed:
@failed=$$(cd '$(TEST_RESULTS_DIRECTORY_SQ)' && \
@@ -52,7 +59,7 @@ failed:
test -z "$$failed" || $(MAKE) $$failed
prove: pre-clean check-chainlint $(TEST_LINT)
- @echo "*** prove ***"; $(PROVE) --exec '$(TEST_SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
+ @echo "*** prove ***"; $(CHAINLINTSUPPRESS) $(PROVE) --exec '$(TEST_SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
$(MAKE) clean-except-prove-cache
$(T):
@@ -66,6 +73,7 @@ clean-except-prove-cache: clean-chainlint
$(RM) -r valgrind/bin
clean: clean-except-prove-cache
+ $(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
$(RM) .prove
clean-chainlint:
@@ -73,13 +81,35 @@ clean-chainlint:
check-chainlint:
@mkdir -p '$(CHAINLINTTMP_SQ)' && \
- sed -e '/^# LINT: /d' $(patsubst %,chainlint/%.test,$(CHAINLINTTESTS)) >'$(CHAINLINTTMP_SQ)'/tests && \
- sed -e '/^[ ]*$$/d' $(patsubst %,chainlint/%.expect,$(CHAINLINTTESTS)) >'$(CHAINLINTTMP_SQ)'/expect && \
- $(CHAINLINT) '$(CHAINLINTTMP_SQ)'/tests | grep -v '^[ ]*$$' >'$(CHAINLINTTMP_SQ)'/actual && \
- diff -u '$(CHAINLINTTMP_SQ)'/expect '$(CHAINLINTTMP_SQ)'/actual
+ for i in $(CHAINLINTTESTS); do \
+ echo "test_expect_success '$$i' '" && \
+ sed -e '/^# LINT: /d' chainlint/$$i.test && \
+ echo "'"; \
+ done >'$(CHAINLINTTMP_SQ)'/tests && \
+ { \
+ echo "# chainlint: $(CHAINLINTTMP_SQ)/tests" && \
+ for i in $(CHAINLINTTESTS); do \
+ echo "# chainlint: $$i" && \
+ sed -e '/^[ ]*$$/d' chainlint/$$i.expect; \
+ done \
+ } >'$(CHAINLINTTMP_SQ)'/expect && \
+ $(CHAINLINT) --emit-all '$(CHAINLINTTMP_SQ)'/tests | \
+ grep -v '^[ ]*$$' >'$(CHAINLINTTMP_SQ)'/actual && \
+ if test -f ../GIT-BUILD-OPTIONS; then \
+ . ../GIT-BUILD-OPTIONS; \
+ fi && \
+ if test -x ../git$$X; then \
+ DIFFW="../git$$X --no-pager diff -w --no-index"; \
+ else \
+ DIFFW="diff -w -u"; \
+ fi && \
+ $$DIFFW '$(CHAINLINTTMP_SQ)'/expect '$(CHAINLINTTMP_SQ)'/actual
test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \
test-lint-filenames
+ifneq ($(GIT_TEST_CHAIN_LINT),0)
+test-lint: test-chainlint
+endif
test-lint-duplicates:
@dups=`echo $(T) $(TPERF) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
@@ -102,6 +132,9 @@ test-lint-filenames:
test -z "$$bad" || { \
echo >&2 "non-portable file name(s): $$bad"; exit 1; }
+test-chainlint:
+ @$(CHAINLINT) $(T) $(TLIBS) $(TPERF) $(TINTEROP)
+
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
$(MAKE) clean
@@ -117,4 +150,5 @@ valgrind:
perf:
$(MAKE) -C perf/ all
-.PHONY: pre-clean $(T) aggregate-results clean valgrind perf check-chainlint clean-chainlint
+.PHONY: pre-clean $(T) aggregate-results clean valgrind perf \
+ check-chainlint clean-chainlint test-chainlint
diff --git a/t/README b/t/README
index 2f439f9658..979b2d4833 100644
--- a/t/README
+++ b/t/README
@@ -196,11 +196,6 @@ appropriately before running "make". Short options can be bundled, i.e.
this feature by setting the GIT_TEST_CHAIN_LINT environment
variable to "1" or "0", respectively.
- A few test scripts disable some of the more advanced
- chain-linting detection in the name of efficiency. You can
- override this by setting the GIT_TEST_CHAIN_LINT_HARDER
- environment variable to "1".
-
--stress::
Run the test script repeatedly in multiple parallel jobs until
one of them fails. Useful for reproducing rare failures in
diff --git a/t/chainlint.pl b/t/chainlint.pl
new file mode 100755
index 0000000000..976db4b8a0
--- /dev/null
+++ b/t/chainlint.pl
@@ -0,0 +1,770 @@
+#!/usr/bin/env perl
+#
+# Copyright (c) 2021-2022 Eric Sunshine <sunshine@sunshineco.com>
+#
+# This tool scans shell scripts for test definitions and checks those tests for
+# problems, such as broken &&-chains, which might hide bugs in the tests
+# themselves or in behaviors being exercised by the tests.
+#
+# Input arguments are pathnames of shell scripts containing test definitions,
+# or globs referencing a collection of scripts. For each problem discovered,
+# the pathname of the script containing the test is printed along with the test
+# name and the test body with a `?!FOO?!` annotation at the location of each
+# detected problem, where "FOO" is a tag such as "AMP" which indicates a broken
+# &&-chain. Returns zero if no problems are discovered, otherwise non-zero.
+
+use warnings;
+use strict;
+use Config;
+use File::Glob;
+use Getopt::Long;
+
+my $jobs = -1;
+my $show_stats;
+my $emit_all;
+
+# Lexer tokenizes POSIX shell scripts. It is roughly modeled after section 2.3
+# "Token Recognition" of POSIX chapter 2 "Shell Command Language". Although
+# similar to lexical analyzers for other languages, this one differs in a few
+# substantial ways due to quirks of the shell command language.
+#
+# For instance, in many languages, newline is just whitespace like space or
+# TAB, but in shell a newline is a command separator, thus a distinct lexical
+# token. A newline is significant and returned as a distinct token even at the
+# end of a shell comment.
+#
+# In other languages, `1+2` would typically be scanned as three tokens
+# (`1`, `+`, and `2`), but in shell it is a single token. However, the similar
+# `1 + 2`, which embeds whitepace, is scanned as three token in shell, as well.
+# In shell, several characters with special meaning lose that meaning when not
+# surrounded by whitespace. For instance, the negation operator `!` is special
+# when standing alone surrounded by whitespace; whereas in `foo!uucp` it is
+# just a plain character in the longer token "foo!uucp". In many other
+# languages, `"string"/foo:'string'` might be scanned as five tokens ("string",
+# `/`, `foo`, `:`, and 'string'), but in shell, it is just a single token.
+#
+# The lexical analyzer for the shell command language is also somewhat unusual
+# in that it recursively invokes the parser to handle the body of `$(...)`
+# expressions which can contain arbitrary shell code. Such expressions may be
+# encountered both inside and outside of double-quoted strings.
+#
+# The lexical analyzer is responsible for consuming shell here-doc bodies which
+# extend from the line following a `<<TAG` operator until a line consisting
+# solely of `TAG`. Here-doc consumption begins when a newline is encountered.
+# It is legal for multiple here-doc `<<TAG` operators to be present on a single
+# line, in which case their bodies must be present one following the next, and
+# are consumed in the (left-to-right) order the `<<TAG` operators appear on the
+# line. A special complication is that the bodies of all here-docs must be
+# consumed when the newline is encountered even if the parse context depth has
+# changed. For instance, in `cat <<A && x=$(cat <<B &&\n`, bodies of here-docs
+# "A" and "B" must be consumed even though "A" was introduced outside the
+# recursive parse context in which "B" was introduced and in which the newline
+# is encountered.
+package Lexer;
+
+sub new {
+ my ($class, $parser, $s) = @_;
+ bless {
+ parser => $parser,
+ buff => $s,
+ heretags => []
+ } => $class;
+}
+
+sub scan_heredoc_tag {
+ my $self = shift @_;
+ ${$self->{buff}} =~ /\G(-?)/gc;
+ my $indented = $1;
+ my $tag = $self->scan_token();
+ $tag =~ s/['"\\]//g;
+ push(@{$self->{heretags}}, $indented ? "\t$tag" : "$tag");
+ return "<<$indented$tag";
+}
+
+sub scan_op {
+ my ($self, $c) = @_;
+ my $b = $self->{buff};
+ return $c unless $$b =~ /\G(.)/sgc;
+ my $cc = $c . $1;
+ return scan_heredoc_tag($self) if $cc eq '<<';
+ return $cc if $cc =~ /^(?:&&|\|\||>>|;;|<&|>&|<>|>\|)$/;
+ pos($$b)--;
+ return $c;
+}
+
+sub scan_sqstring {
+ my $self = shift @_;
+ ${$self->{buff}} =~ /\G([^']*'|.*\z)/sgc;
+ return "'" . $1;
+}
+
+sub scan_dqstring {
+ my $self = shift @_;
+ my $b = $self->{buff};
+ my $s = '"';
+ while (1) {
+ # slurp up non-special characters
+ $s .= $1 if $$b =~ /\G([^"\$\\]+)/gc;
+ # handle special characters
+ last unless $$b =~ /\G(.)/sgc;
+ my $c = $1;
+ $s .= '"', last if $c eq '"';
+ $s .= '$' . $self->scan_dollar(), next if $c eq '$';
+ if ($c eq '\\') {
+ $s .= '\\', last unless $$b =~ /\G(.)/sgc;
+ $c = $1;
+ next if $c eq "\n"; # line splice
+ # backslash escapes only $, `, ", \ in dq-string
+ $s .= '\\' unless $c =~ /^[\$`"\\]$/;
+ $s .= $c;
+ next;
+ }
+ die("internal error scanning dq-string '$c'\n");
+ }
+ return $s;
+}
+
+sub scan_balanced {
+ my ($self, $c1, $c2) = @_;
+ my $b = $self->{buff};
+ my $depth = 1;
+ my $s = $c1;
+ while ($$b =~ /\G([^\Q$c1$c2\E]*(?:[\Q$c1$c2\E]|\z))/gc) {
+ $s .= $1;
+ $depth++, next if $s =~ /\Q$c1\E$/;
+ $depth--;
+ last if $depth == 0;
+ }
+ return $s;
+}
+
+sub scan_subst {
+ my $self = shift @_;
+ my @tokens = $self->{parser}->parse(qr/^\)$/);
+ $self->{parser}->next_token(); # closing ")"
+ return @tokens;
+}
+
+sub scan_dollar {
+ my $self = shift @_;
+ my $b = $self->{buff};
+ return $self->scan_balanced('(', ')') if $$b =~ /\G\((?=\()/gc; # $((...))
+ return '(' . join(' ', $self->scan_subst()) . ')' if $$b =~ /\G\(/gc; # $(...)
+ return $self->scan_balanced('{', '}') if $$b =~ /\G\{/gc; # ${...}
+ return $1 if $$b =~ /\G(\w+)/gc; # $var
+ return $1 if $$b =~ /\G([@*#?$!0-9-])/gc; # $*, $1, $$, etc.
+ return '';
+}
+
+sub swallow_heredocs {
+ my $self = shift @_;
+ my $b = $self->{buff};
+ my $tags = $self->{heretags};
+ while (my $tag = shift @$tags) {
+ my $indent = $tag =~ s/^\t// ? '\\s*' : '';
+ $$b =~ /(?:\G|\n)$indent\Q$tag\E(?:\n|\z)/gc;
+ }
+}
+
+sub scan_token {
+ my $self = shift @_;
+ my $b = $self->{buff};
+ my $token = '';
+RESTART:
+ $$b =~ /\G[ \t]+/gc; # skip whitespace (but not newline)
+ return "\n" if $$b =~ /\G#[^\n]*(?:\n|\z)/gc; # comment
+ while (1) {
+ # slurp up non-special characters
+ $token .= $1 if $$b =~ /\G([^\\;&|<>(){}'"\$\s]+)/gc;
+ # handle special characters
+ last unless $$b =~ /\G(.)/sgc;
+ my $c = $1;
+ last if $c =~ /^[ \t]$/; # whitespace ends token
+ pos($$b)--, last if length($token) && $c =~ /^[;&|<>(){}\n]$/;
+ $token .= $self->scan_sqstring(), next if $c eq "'";
+ $token .= $self->scan_dqstring(), next if $c eq '"';
+ $token .= $c . $self->scan_dollar(), next if $c eq '$';
+ $self->swallow_heredocs(), $token = $c, last if $c eq "\n";
+ $token = $self->scan_op($c), last if $c =~ /^[;&|<>]$/;
+ $token = $c, last if $c =~ /^[(){}]$/;
+ if ($c eq '\\') {
+ $token .= '\\', last unless $$b =~ /\G(.)/sgc;
+ $c = $1;
+ next if $c eq "\n" && length($token); # line splice
+ goto RESTART if $c eq "\n"; # line splice
+ $token .= '\\' . $c;
+ next;
+ }
+ die("internal error scanning character '$c'\n");
+ }
+ return length($token) ? $token : undef;
+}
+
+# ShellParser parses POSIX shell scripts (with minor extensions for Bash). It
+# is a recursive descent parser very roughly modeled after section 2.10 "Shell
+# Grammar" of POSIX chapter 2 "Shell Command Language".
+package ShellParser;
+
+sub new {
+ my ($class, $s) = @_;
+ my $self = bless {
+ buff => [],
+ stop => [],
+ output => []
+ } => $class;
+ $self->{lexer} = Lexer->new($self, $s);
+ return $self;
+}
+
+sub next_token {
+ my $self = shift @_;
+ return pop(@{$self->{buff}}) if @{$self->{buff}};
+ return $self->{lexer}->scan_token();
+}
+
+sub untoken {
+ my $self = shift @_;
+ push(@{$self->{buff}}, @_);
+}
+
+sub peek {
+ my $self = shift @_;
+ my $token = $self->next_token();
+ return undef unless defined($token);
+ $self->untoken($token);
+ return $token;
+}
+
+sub stop_at {
+ my ($self, $token) = @_;
+ return 1 unless defined($token);
+ my $stop = ${$self->{stop}}[-1] if @{$self->{stop}};
+ return defined($stop) && $token =~ $stop;
+}
+
+sub expect {
+ my ($self, $expect) = @_;
+ my $token = $self->next_token();
+ return $token if defined($token) && $token eq $expect;
+ push(@{$self->{output}}, "?!ERR?! expected '$expect' but found '" . (defined($token) ? $token : "<end-of-input>") . "'\n");
+ $self->untoken($token) if defined($token);
+ return ();
+}
+
+sub optional_newlines {
+ my $self = shift @_;
+ my @tokens;
+ while (my $token = $self->peek()) {
+ last unless $token eq "\n";
+ push(@tokens, $self->next_token());
+ }
+ return @tokens;
+}
+
+sub parse_group {
+ my $self = shift @_;
+ return ($self->parse(qr/^}$/),
+ $self->expect('}'));
+}
+
+sub parse_subshell {
+ my $self = shift @_;
+ return ($self->parse(qr/^\)$/),
+ $self->expect(')'));
+}
+
+sub parse_case_pattern {
+ my $self = shift @_;
+ my @tokens;
+ while (defined(my $token = $self->next_token())) {
+ push(@tokens, $token);
+ last if $token eq ')';
+ }
+ return @tokens;
+}
+
+sub parse_case {
+ my $self = shift @_;
+ my @tokens;
+ push(@tokens,
+ $self->next_token(), # subject
+ $self->optional_newlines(),
+ $self->expect('in'),
+ $self->optional_newlines());
+ while (1) {
+ my $token = $self->peek();
+ last unless defined($token) && $token ne 'esac';
+ push(@tokens,
+ $self->parse_case_pattern(),
+ $self->optional_newlines(),
+ $self->parse(qr/^(?:;;|esac)$/)); # item body
+ $token = $self->peek();
+ last unless defined($token) && $token ne 'esac';
+ push(@tokens,
+ $self->expect(';;'),
+ $self->optional_newlines());
+ }
+ push(@tokens, $self->expect('esac'));
+ return @tokens;
+}
+
+sub parse_for {
+ my $self = shift @_;
+ my @tokens;
+ push(@tokens,
+ $self->next_token(), # variable
+ $self->optional_newlines());
+ my $token = $self->peek();
+ if (defined($token) && $token eq 'in') {
+ push(@tokens,
+ $self->expect('in'),
+ $self->optional_newlines());
+ }
+ push(@tokens,
+ $self->parse(qr/^do$/), # items
+ $self->expect('do'),
+ $self->optional_newlines(),
+ $self->parse_loop_body(),
+ $self->expect('done'));
+ return @tokens;
+}
+
+sub parse_if {
+ my $self = shift @_;
+ my @tokens;
+ while (1) {
+ push(@tokens,
+ $self->parse(qr/^then$/), # if/elif condition
+ $self->expect('then'),
+ $self->optional_newlines(),
+ $self->parse(qr/^(?:elif|else|fi)$/)); # if/elif body
+ my $token = $self->peek();
+ last unless defined($token) && $token eq 'elif';
+ push(@tokens, $self->expect('elif'));
+ }
+ my $token = $self->peek();
+ if (defined($token) && $token eq 'else') {
+ push(@tokens,
+ $self->expect('else'),
+ $self->optional_newlines(),
+ $self->parse(qr/^fi$/)); # else body
+ }
+ push(@tokens, $self->expect('fi'));
+ return @tokens;
+}
+
+sub parse_loop_body {
+ my $self = shift @_;
+ return $self->parse(qr/^done$/);
+}
+
+sub parse_loop {
+ my $self = shift @_;
+ return ($self->parse(qr/^do$/), # condition
+ $self->expect('do'),
+ $self->optional_newlines(),
+ $self->parse_loop_body(),
+ $self->expect('done'));
+}
+
+sub parse_func {
+ my $self = shift @_;
+ return ($self->expect('('),
+ $self->expect(')'),
+ $self->optional_newlines(),
+ $self->parse_cmd()); # body
+}
+
+sub parse_bash_array_assignment {
+ my $self = shift @_;
+ my @tokens = $self->expect('(');
+ while (defined(my $token = $self->next_token())) {
+ push(@tokens, $token);
+ last if $token eq ')';
+ }
+ return @tokens;
+}
+
+my %compound = (
+ '{' => \&parse_group,
+ '(' => \&parse_subshell,
+ 'case' => \&parse_case,
+ 'for' => \&parse_for,
+ 'if' => \&parse_if,
+ 'until' => \&parse_loop,
+ 'while' => \&parse_loop);
+
+sub parse_cmd {
+ my $self = shift @_;
+ my $cmd = $self->next_token();
+ return () unless defined($cmd);
+ return $cmd if $cmd eq "\n";
+
+ my $token;
+ my @tokens = $cmd;
+ if ($cmd eq '!') {
+ push(@tokens, $self->parse_cmd());
+ return @tokens;
+ } elsif (my $f = $compound{$cmd}) {
+ push(@tokens, $self->$f());
+ } elsif (defined($token = $self->peek()) && $token eq '(') {
+ if ($cmd !~ /\w=$/) {
+ push(@tokens, $self->parse_func());
+ return @tokens;
+ }
+ $tokens[-1] .= join(' ', $self->parse_bash_array_assignment());
+ }
+
+ while (defined(my $token = $self->next_token())) {
+ $self->untoken($token), last if $self->stop_at($token);
+ push(@tokens, $token);
+ last if $token =~ /^(?:[;&\n|]|&&|\|\|)$/;
+ }
+ push(@tokens, $self->next_token()) if $tokens[-1] ne "\n" && defined($token = $self->peek()) && $token eq "\n";
+ return @tokens;
+}
+
+sub accumulate {
+ my ($self, $tokens, $cmd) = @_;
+ push(@$tokens, @$cmd);
+}
+
+sub parse {
+ my ($self, $stop) = @_;
+ push(@{$self->{stop}}, $stop);
+ goto DONE if $self->stop_at($self->peek());
+ my @tokens;
+ while (my @cmd = $self->parse_cmd()) {
+ $self->accumulate(\@tokens, \@cmd);
+ last if $self->stop_at($self->peek());
+ }
+DONE:
+ pop(@{$self->{stop}});
+ return @tokens;
+}
+
+# TestParser is a subclass of ShellParser which, beyond parsing shell script
+# code, is also imbued with semantic knowledge of test construction, and checks
+# tests for common problems (such as broken &&-chains) which might hide bugs in
+# the tests themselves or in behaviors being exercised by the tests. As such,
+# TestParser is only called upon to parse test bodies, not the top-level
+# scripts in which the tests are defined.
+package TestParser;
+
+use base 'ShellParser';
+
+sub find_non_nl {
+ my $tokens = shift @_;
+ my $n = shift @_;
+ $n = $#$tokens if !defined($n);
+ $n-- while $n >= 0 && $$tokens[$n] eq "\n";
+ return $n;
+}
+
+sub ends_with {
+ my ($tokens, $needles) = @_;
+ my $n = find_non_nl($tokens);
+ for my $needle (reverse(@$needles)) {
+ return undef if $n < 0;
+ $n = find_non_nl($tokens, $n), next if $needle eq "\n";
+ return undef if $$tokens[$n] !~ $needle;
+ $n--;
+ }
+ return 1;
+}
+
+sub match_ending {
+ my ($tokens, $endings) = @_;
+ for my $needles (@$endings) {
+ next if @$tokens < scalar(grep {$_ ne "\n"} @$needles);
+ return 1 if ends_with($tokens, $needles);
+ }
+ return undef;
+}
+
+sub parse_loop_body {
+ my $self = shift @_;
+ my @tokens = $self->SUPER::parse_loop_body(@_);
+ # did loop signal failure via "|| return" or "|| exit"?
+ return @tokens if !@tokens || grep(/^(?:return|exit|\$\?)$/, @tokens);
+ # did loop upstream of a pipe signal failure via "|| echo 'impossible
+ # text'" as the final command in the loop body?
+ return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]);
+ # flag missing "return/exit" handling explicit failure in loop body
+ my $n = find_non_nl(\@tokens);
+ splice(@tokens, $n + 1, 0, '?!LOOP?!');
+ return @tokens;
+}
+
+my @safe_endings = (
+ [qr/^(?:&&|\|\||\||&)$/],
+ [qr/^(?:exit|return)$/, qr/^(?:\d+|\$\?)$/],
+ [qr/^(?:exit|return)$/, qr/^(?:\d+|\$\?)$/, qr/^;$/],
+ [qr/^(?:exit|return|continue)$/],
+ [qr/^(?:exit|return|continue)$/, qr/^;$/]);
+
+sub accumulate {
+ my ($self, $tokens, $cmd) = @_;
+ goto DONE unless @$tokens;
+ goto DONE if @$cmd == 1 && $$cmd[0] eq "\n";
+
+ # did previous command end with "&&", "|", "|| return" or similar?
+ goto DONE if match_ending($tokens, \@safe_endings);
+
+ # if this command handles "$?" specially, then okay for previous
+ # command to be missing "&&"
+ for my $token (@$cmd) {
+ goto DONE if $token =~ /\$\?/;
+ }
+
+ # if this command is "false", "return 1", or "exit 1" (which signal
+ # failure explicitly), then okay for all preceding commands to be
+ # missing "&&"
+ if ($$cmd[0] =~ /^(?:false|return|exit)$/) {
+ @$tokens = grep(!/^\?!AMP\?!$/, @$tokens);
+ goto DONE;
+ }
+
+ # flag missing "&&" at end of previous command
+ my $n = find_non_nl($tokens);
+ splice(@$tokens, $n + 1, 0, '?!AMP?!') unless $n < 0;
+
+DONE:
+ $self->SUPER::accumulate($tokens, $cmd);
+}
+
+# ScriptParser is a subclass of ShellParser which identifies individual test
+# definitions within test scripts, and passes each test body through TestParser
+# to identify possible problems. ShellParser detects test definitions not only
+# at the top-level of test scripts but also within compound commands such as
+# loops and function definitions.
+package ScriptParser;
+
+use base 'ShellParser';
+
+sub new {
+ my $class = shift @_;
+ my $self = $class->SUPER::new(@_);
+ $self->{ntests} = 0;
+ return $self;
+}
+
+# extract the raw content of a token, which may be a single string or a
+# composition of multiple strings and non-string character runs; for instance,
+# `"test body"` unwraps to `test body`; `word"a b"42'c d'` to `worda b42c d`
+sub unwrap {
+ my $token = @_ ? shift @_ : $_;
+ # simple case: 'sqstring' or "dqstring"
+ return $token if $token =~ s/^'([^']*)'$/$1/;
+ return $token if $token =~ s/^"([^"]*)"$/$1/;
+
+ # composite case
+ my ($s, $q, $escaped);
+ while (1) {
+ # slurp up non-special characters
+ $s .= $1 if $token =~ /\G([^\\'"]*)/gc;
+ # handle special characters
+ last unless $token =~ /\G(.)/sgc;
+ my $c = $1;
+ $q = undef, next if defined($q) && $c eq $q;
+ $q = $c, next if !defined($q) && $c =~ /^['"]$/;
+ if ($c eq '\\') {
+ last unless $token =~ /\G(.)/sgc;
+ $c = $1;
+ $s .= '\\' if $c eq "\n"; # preserve line splice
+ }
+ $s .= $c;
+ }
+ return $s
+}
+
+sub check_test {
+ my $self = shift @_;
+ my ($title, $body) = map(unwrap, @_);
+ $self->{ntests}++;
+ my $parser = TestParser->new(\$body);
+ my @tokens = $parser->parse();
+ return unless $emit_all || grep(/\?![^?]+\?!/, @tokens);
+ my $c = main::fd_colors(1);
+ my $checked = join(' ', @tokens);
+ $checked =~ s/^\n//;
+ $checked =~ s/^ //mg;
+ $checked =~ s/ $//mg;
+ $checked =~ s/(\?![^?]+\?!)/$c->{rev}$c->{red}$1$c->{reset}/mg;
+ $checked .= "\n" unless $checked =~ /\n$/;
+ push(@{$self->{output}}, "$c->{blue}# chainlint: $title$c->{reset}\n$checked");
+}
+
+sub parse_cmd {
+ my $self = shift @_;
+ my @tokens = $self->SUPER::parse_cmd();
+ return @tokens unless @tokens && $tokens[0] =~ /^test_expect_(?:success|failure)$/;
+ my $n = $#tokens;
+ $n-- while $n >= 0 && $tokens[$n] =~ /^(?:[;&\n|]|&&|\|\|)$/;
+ $self->check_test($tokens[1], $tokens[2]) if $n == 2; # title body
+ $self->check_test($tokens[2], $tokens[3]) if $n > 2; # prereq title body
+ return @tokens;
+}
+
+# main contains high-level functionality for processing command-line switches,
+# feeding input test scripts to ScriptParser, and reporting results.
+package main;
+
+my $getnow = sub { return time(); };
+my $interval = sub { return time() - shift; };
+if (eval {require Time::HiRes; Time::HiRes->import(); 1;}) {
+ $getnow = sub { return [Time::HiRes::gettimeofday()]; };
+ $interval = sub { return Time::HiRes::tv_interval(shift); };
+}
+
+# Restore TERM if test framework set it to "dumb" so 'tput' will work; do this
+# outside of get_colors() since under 'ithreads' all threads use %ENV of main
+# thread and ignore %ENV changes in subthreads.
+$ENV{TERM} = $ENV{USER_TERM} if $ENV{USER_TERM};
+
+my @NOCOLORS = (bold => '', rev => '', reset => '', blue => '', green => '', red => '');
+my %COLORS = ();
+sub get_colors {
+ return \%COLORS if %COLORS;
+ if (exists($ENV{NO_COLOR}) ||
+ system("tput sgr0 >/dev/null 2>&1") != 0 ||
+ system("tput bold >/dev/null 2>&1") != 0 ||
+ system("tput rev >/dev/null 2>&1") != 0 ||
+ system("tput setaf 1 >/dev/null 2>&1") != 0) {
+ %COLORS = @NOCOLORS;
+ return \%COLORS;
+ }
+ %COLORS = (bold => `tput bold`,
+ rev => `tput rev`,
+ reset => `tput sgr0`,
+ blue => `tput setaf 4`,
+ green => `tput setaf 2`,
+ red => `tput setaf 1`);
+ chomp(%COLORS);
+ return \%COLORS;
+}
+
+my %FD_COLORS = ();
+sub fd_colors {
+ my $fd = shift;
+ return $FD_COLORS{$fd} if exists($FD_COLORS{$fd});
+ $FD_COLORS{$fd} = -t $fd ? get_colors() : {@NOCOLORS};
+ return $FD_COLORS{$fd};
+}
+
+sub ncores {
+ # Windows
+ return $ENV{NUMBER_OF_PROCESSORS} if exists($ENV{NUMBER_OF_PROCESSORS});
+ # Linux / MSYS2 / Cygwin / WSL
+ do { local @ARGV='/proc/cpuinfo'; return scalar(grep(/^processor\s*:/, <>)); } if -r '/proc/cpuinfo';
+ # macOS & BSD
+ return qx/sysctl -n hw.ncpu/ if $^O =~ /(?:^darwin$|bsd)/;
+ return 1;
+}
+
+sub show_stats {
+ my ($start_time, $stats) = @_;
+ my $walltime = $interval->($start_time);
+ my ($usertime) = times();
+ my ($total_workers, $total_scripts, $total_tests, $total_errs) = (0, 0, 0, 0);
+ my $c = fd_colors(2);
+ print(STDERR $c->{green});
+ for (@$stats) {
+ my ($worker, $nscripts, $ntests, $nerrs) = @$_;
+ print(STDERR "worker $worker: $nscripts scripts, $ntests tests, $nerrs errors\n");
+ $total_workers++;
+ $total_scripts += $nscripts;
+ $total_tests += $ntests;
+ $total_errs += $nerrs;
+ }
+ printf(STDERR "total: %d workers, %d scripts, %d tests, %d errors, %.2fs/%.2fs (wall/user)$c->{reset}\n", $total_workers, $total_scripts, $total_tests, $total_errs, $walltime, $usertime);
+}
+
+sub check_script {
+ my ($id, $next_script, $emit) = @_;
+ my ($nscripts, $ntests, $nerrs) = (0, 0, 0);
+ while (my $path = $next_script->()) {
+ $nscripts++;
+ my $fh;
+ unless (open($fh, "<", $path)) {
+ $emit->("?!ERR?! $path: $!\n");
+ next;
+ }
+ my $s = do { local $/; <$fh> };
+ close($fh);
+ my $parser = ScriptParser->new(\$s);
+ 1 while $parser->parse_cmd();
+ if (@{$parser->{output}}) {
+ my $c = fd_colors(1);
+ my $s = join('', @{$parser->{output}});
+ $emit->("$c->{bold}$c->{blue}# chainlint: $path$c->{reset}\n" . $s);
+ $nerrs += () = $s =~ /\?![^?]+\?!/g;
+ }
+ $ntests += $parser->{ntests};
+ }
+ return [$id, $nscripts, $ntests, $nerrs];
+}
+
+sub exit_code {
+ my $stats = shift @_;
+ for (@$stats) {
+ my ($worker, $nscripts, $ntests, $nerrs) = @$_;
+ return 1 if $nerrs;
+ }
+ return 0;
+}
+
+Getopt::Long::Configure(qw{bundling});
+GetOptions(
+ "emit-all!" => \$emit_all,
+ "jobs|j=i" => \$jobs,
+ "stats|show-stats!" => \$show_stats) or die("option error\n");
+$jobs = ncores() if $jobs < 1;
+
+my $start_time = $getnow->();
+my @stats;
+
+my @scripts;
+push(@scripts, File::Glob::bsd_glob($_)) for (@ARGV);
+unless (@scripts) {
+ show_stats($start_time, \@stats) if $show_stats;
+ exit;
+}
+
+unless ($Config{useithreads} && eval {
+ require threads; threads->import();
+ require Thread::Queue; Thread::Queue->import();
+ 1;
+ }) {
+ push(@stats, check_script(1, sub { shift(@scripts); }, sub { print(@_); }));
+ show_stats($start_time, \@stats) if $show_stats;
+ exit(exit_code(\@stats));
+}
+
+my $script_queue = Thread::Queue->new();
+my $output_queue = Thread::Queue->new();
+
+sub next_script { return $script_queue->dequeue(); }
+sub emit { $output_queue->enqueue(@_); }
+
+sub monitor {
+ while (my $s = $output_queue->dequeue()) {
+ print($s);
+ }
+}
+
+my $mon = threads->create({'context' => 'void'}, \&monitor);
+threads->create({'context' => 'list'}, \&check_script, $_, \&next_script, \&emit) for 1..$jobs;
+
+$script_queue->enqueue(@scripts);
+$script_queue->end();
+
+for (threads->list()) {
+ push(@stats, $_->join()) unless $_ == $mon;
+}
+
+$output_queue->end();
+$mon->join();
+
+show_stats($start_time, \@stats) if $show_stats;
+exit(exit_code(\@stats));
diff --git a/t/chainlint.sed b/t/chainlint.sed
deleted file mode 100644
index dc4ce37cb5..0000000000
--- a/t/chainlint.sed
+++ /dev/null
@@ -1,399 +0,0 @@
-#------------------------------------------------------------------------------
-# Detect broken &&-chains in tests.
-#
-# At present, only &&-chains in subshells are examined by this linter;
-# top-level &&-chains are instead checked directly by the test framework. Like
-# the top-level &&-chain linter, the subshell linter (intentionally) does not
-# check &&-chains within {...} blocks.
-#
-# Checking for &&-chain breakage is done line-by-line by pure textual
-# inspection.
-#
-# Incomplete lines (those ending with "\") are stitched together with following
-# lines to simplify processing, particularly of "one-liner" statements.
-# Top-level here-docs are swallowed to avoid false positives within the
-# here-doc body, although the statement to which the here-doc is attached is
-# retained.
-#
-# Heuristics are used to detect end-of-subshell when the closing ")" is cuddled
-# with the final subshell statement on the same line:
-#
-# (cd foo &&
-# bar)
-#
-# in order to avoid misinterpreting the ")" in constructs such as "x=$(...)"
-# and "case $x in *)" as ending the subshell.
-#
-# Lines missing a final "&&" are flagged with "?!AMP?!", as are lines which
-# chain commands with ";" internally rather than "&&". A line may be flagged
-# for both violations.
-#
-# Detection of a missing &&-link in a multi-line subshell is complicated by the
-# fact that the last statement before the closing ")" must not end with "&&".
-# Since processing is line-by-line, it is not known whether a missing "&&" is
-# legitimate or not until the _next_ line is seen. To accommodate this, within
-# multi-line subshells, each line is stored in sed's "hold" area until after
-# the next line is seen and processed. If the next line is a stand-alone ")",
-# then a missing "&&" on the previous line is legitimate; otherwise a missing
-# "&&" is a break in the &&-chain.
-#
-# (
-# cd foo &&
-# bar
-# )
-#
-# In practical terms, when "bar" is encountered, it is flagged with "?!AMP?!",
-# but when the stand-alone ")" line is seen which closes the subshell, the
-# "?!AMP?!" violation is removed from the "bar" line (retrieved from the "hold"
-# area) since the final statement of a subshell must not end with "&&". The
-# final line of a subshell may still break the &&-chain by using ";" internally
-# to chain commands together rather than "&&", but an internal "?!AMP?!" is
-# never removed from a line even though a line-ending "?!AMP?!" might be.
-#
-# Care is taken to recognize the last _statement_ of a multi-line subshell, not
-# necessarily the last textual _line_ within the subshell, since &&-chaining
-# applies to statements, not to lines. Consequently, blank lines, comment
-# lines, and here-docs are swallowed (but not the command to which the here-doc
-# is attached), leaving the last statement in the "hold" area, not the last
-# line, thus simplifying &&-link checking.
-#
-# The final statement before "done" in for- and while-loops, and before "elif",
-# "else", and "fi" in if-then-else likewise must not end with "&&", thus
-# receives similar treatment.
-#
-# Swallowing here-docs with arbitrary tags requires a bit of finesse. When a
-# line such as "cat <<EOF" is seen, the here-doc tag is copied to the front of
-# the line enclosed in angle brackets as a sentinel, giving "<EOF>cat <<EOF".
-# As each subsequent line is read, it is appended to the target line and a
-# (whitespace-loose) back-reference match /^<(.*)>\n\1$/ is attempted to see if
-# the content inside "<...>" matches the entirety of the newly-read line. For
-# instance, if the next line read is "some data", when concatenated with the
-# target line, it becomes "<EOF>cat <<EOF\nsome data", and a match is attempted
-# to see if "EOF" matches "some data". Since it doesn't, the next line is
-# attempted. When a line consisting of only "EOF" (and possible whitespace) is
-# encountered, it is appended to the target line giving "<EOF>cat <<EOF\nEOF",
-# in which case the "EOF" inside "<...>" does match the text following the
-# newline, thus the closing here-doc tag has been found. The closing tag line
-# and the "<...>" prefix on the target line are then discarded, leaving just
-# the target line "cat <<EOF".
-#------------------------------------------------------------------------------
-
-# incomplete line -- slurp up next line
-:squash
-/\\$/ {
- N
- s/\\\n//
- bsquash
-}
-
-# here-doc -- swallow it to avoid false hits within its body (but keep the
-# command to which it was attached)
-/<<-*[ ]*[\\'"]*[A-Za-z0-9_]/ {
- /"[^"]*<<[^"]*"/bnotdoc
- s/^\(.*<<-*[ ]*\)[\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1\2/
- :hered
- N
- /^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{
- s/\n.*$//
- bhered
- }
- s/^<[^>]*>//
- s/\n.*$//
-}
-:notdoc
-
-# one-liner "(...) &&"
-/^[ ]*!*[ ]*(..*)[ ]*&&[ ]*$/boneline
-
-# same as above but without trailing "&&"
-/^[ ]*!*[ ]*(..*)[ ]*$/boneline
-
-# one-liner "(...) >x" (or "2>x" or "<x" or "|x" or "&"
-/^[ ]*!*[ ]*(..*)[ ]*[0-9]*[<>|&]/boneline
-
-# multi-line "(...\n...)"
-/^[ ]*(/bsubsh
-
-# innocuous line -- print it and advance to next line
-b
-
-# found one-liner "(...)" -- mark suspect if it uses ";" internally rather than
-# "&&" (but not ";" in a string)
-:oneline
-/;/{
- /"[^"]*;[^"]*"/!s/;/; ?!AMP?!/
-}
-b
-
-:subsh
-# bare "(" line? -- stash for later printing
-/^[ ]*([ ]*$/ {
- h
- bnextln
-}
-# "(..." line -- "(" opening subshell cuddled with command; temporarily replace
-# "(" with sentinel "^" and process the line as if "(" had been seen solo on
-# the preceding line; this temporary replacement prevents several rules from
-# accidentally thinking "(" introduces a nested subshell; "^" is changed back
-# to "(" at output time
-x
-s/.*//
-x
-s/(/^/
-bslurp
-
-:nextln
-N
-s/.*\n//
-
-:slurp
-# incomplete line "...\"
-/\\$/bicmplte
-# multi-line quoted string "...\n..."?
-/"/bdqstr
-# multi-line quoted string '...\n...'? (but not contraction in string "it's")
-/'/{
- /"[^'"]*'[^'"]*"/!bsqstr
-}
-:folded
-# here-doc -- swallow it (but not "<<" in a string)
-/<<-*[ ]*[\\'"]*[A-Za-z0-9_]/{
- /"[^"]*<<[^"]*"/!bheredoc
-}
-# comment or empty line -- discard since final non-comment, non-empty line
-# before closing ")", "done", "elsif", "else", or "fi" will need to be
-# re-visited to drop "suspect" marking since final line of those constructs
-# legitimately lacks "&&", so "suspect" mark must be removed
-/^[ ]*#/bnextln
-/^[ ]*$/bnextln
-# in-line comment -- strip it (but not "#" in a string, Bash ${#...} array
-# length, or Perforce "//depot/path#42" revision in filespec)
-/[ ]#/{
- /"[^"]*#[^"]*"/!s/[ ]#.*$//
-}
-# one-liner "case ... esac"
-/^[ ^]*case[ ]*..*esac/bchkchn
-# multi-line "case ... esac"
-/^[ ^]*case[ ]..*[ ]in/bcase
-# multi-line "for ... done" or "while ... done"
-/^[ ^]*for[ ]..*[ ]in/bcont
-/^[ ^]*while[ ]/bcont
-/^[ ]*do[ ]/bcont
-/^[ ]*do[ ]*$/bcont
-/;[ ]*do/bcont
-/^[ ]*done[ ]*&&[ ]*$/bdone
-/^[ ]*done[ ]*$/bdone
-/^[ ]*done[ ]*[<>|]/bdone
-/^[ ]*done[ ]*)/bdone
-/||[ ]*exit[ ]/bcont
-/||[ ]*exit[ ]*$/bcont
-# multi-line "if...elsif...else...fi"
-/^[ ^]*if[ ]/bcont
-/^[ ]*then[ ]/bcont
-/^[ ]*then[ ]*$/bcont
-/;[ ]*then/bcont
-/^[ ]*elif[ ]/belse
-/^[ ]*elif[ ]*$/belse
-/^[ ]*else[ ]/belse
-/^[ ]*else[ ]*$/belse
-/^[ ]*fi[ ]*&&[ ]*$/bdone
-/^[ ]*fi[ ]*$/bdone
-/^[ ]*fi[ ]*[<>|]/bdone
-/^[ ]*fi[ ]*)/bdone
-# nested one-liner "(...) &&"
-/^[ ^]*(.*)[ ]*&&[ ]*$/bchkchn
-# nested one-liner "(...)"
-/^[ ^]*(.*)[ ]*$/bchkchn
-# nested one-liner "(...) >x" (or "2>x" or "<x" or "|x")
-/^[ ^]*(.*)[ ]*[0-9]*[<>|]/bchkchn
-# nested multi-line "(...\n...)"
-/^[ ^]*(/bnest
-# multi-line "{...\n...}"
-/^[ ^]*{/bblock
-# closing ")" on own line -- exit subshell
-/^[ ]*)/bclssolo
-# "$((...))" -- arithmetic expansion; not closing ")"
-/\$(([^)][^)]*))[^)]*$/bchkchn
-# "$(...)" -- command substitution; not closing ")"
-/\$([^)][^)]*)[^)]*$/bchkchn
-# multi-line "$(...\n...)" -- command substitution; treat as nested subshell
-/\$([^)]*$/bnest
-# "=(...)" -- Bash array assignment; not closing ")"
-/=(/bchkchn
-# closing "...) &&"
-/)[ ]*&&[ ]*$/bclose
-# closing "...)"
-/)[ ]*$/bclose
-# closing "...) >x" (or "2>x" or "<x" or "|x")
-/)[ ]*[<>|]/bclose
-:chkchn
-# mark suspect if line uses ";" internally rather than "&&" (but not ";" in a
-# string and not ";;" in one-liner "case...esac")
-/;/{
- /;;/!{
- /"[^"]*;[^"]*"/!s/;/; ?!AMP?!/
- }
-}
-# line ends with pipe "...|" -- valid; not missing "&&"
-/|[ ]*$/bcont
-# missing end-of-line "&&" -- mark suspect
-/&&[ ]*$/!s/$/ ?!AMP?!/
-:cont
-# retrieve and print previous line
-x
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-n
-bslurp
-
-# found incomplete line "...\" -- slurp up next line
-:icmplte
-N
-s/\\\n//
-bslurp
-
-# check for multi-line double-quoted string "...\n..." -- fold to one line
-:dqstr
-# remove all quote pairs
-s/"\([^"]*\)"/@!\1@!/g
-# done if no dangling quote
-/"/!bdqdone
-# otherwise, slurp next line and try again
-N
-s/\n//
-bdqstr
-:dqdone
-s/@!/"/g
-bfolded
-
-# check for multi-line single-quoted string '...\n...' -- fold to one line
-:sqstr
-# remove all quote pairs
-s/'\([^']*\)'/@!\1@!/g
-# done if no dangling quote
-/'/!bsqdone
-# otherwise, slurp next line and try again
-N
-s/\n//
-bsqstr
-:sqdone
-s/@!/'/g
-bfolded
-
-# found here-doc -- swallow it to avoid false hits within its body (but keep
-# the command to which it was attached)
-:heredoc
-s/^\(.*\)<<\(-*[ ]*\)[\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\3>\1?!HERE?!\2\3/
-:hdocsub
-N
-/^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{
- s/\n.*$//
- bhdocsub
-}
-s/^<[^>]*>//
-s/\n.*$//
-bfolded
-
-# found "case ... in" -- pass through untouched
-:case
-x
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-n
-:cascom
-/^[ ]*#/{
- N
- s/.*\n//
- bcascom
-}
-/^[ ]*esac/bslurp
-bcase
-
-# found "else" or "elif" -- drop "suspect" from final line before "else" since
-# that line legitimately lacks "&&"
-:else
-x
-s/\( ?!AMP?!\)* ?!AMP?!$//
-x
-bcont
-
-# found "done" closing for-loop or while-loop, or "fi" closing if-then -- drop
-# "suspect" from final contained line since that line legitimately lacks "&&"
-:done
-x
-s/\( ?!AMP?!\)* ?!AMP?!$//
-x
-# is 'done' or 'fi' cuddled with ")" to close subshell?
-/done.*)/bclose
-/fi.*)/bclose
-bchkchn
-
-# found nested multi-line "(...\n...)" -- pass through untouched
-:nest
-x
-:nstslrp
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-n
-:nstcom
-# comment -- not closing ")" if in comment
-/^[ ]*#/{
- N
- s/.*\n//
- bnstcom
-}
-# closing ")" on own line -- stop nested slurp
-/^[ ]*)/bnstcl
-# "$((...))" -- arithmetic expansion; not closing ")"
-/\$(([^)][^)]*))[^)]*$/bnstcnt
-# "$(...)" -- command substitution; not closing ")"
-/\$([^)][^)]*)[^)]*$/bnstcnt
-# closing "...)" -- stop nested slurp
-/)/bnstcl
-:nstcnt
-x
-bnstslrp
-:nstcl
-# is it "))" which closes nested and parent subshells?
-/)[ ]*)/bslurp
-bchkchn
-
-# found multi-line "{...\n...}" block -- pass through untouched
-:block
-x
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-n
-:blkcom
-/^[ ]*#/{
- N
- s/.*\n//
- bblkcom
-}
-# closing "}" -- stop block slurp
-/}/bchkchn
-bblock
-
-# found closing ")" on own line -- drop "suspect" from final line of subshell
-# since that line legitimately lacks "&&" and exit subshell loop
-:clssolo
-x
-s/\( ?!AMP?!\)* ?!AMP?!$//
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-p
-x
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-b
-
-# found closing "...)" -- exit subshell loop
-:close
-x
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-p
-x
-s/^\([ ]*\)^/\1(/
-s/?!HERE?!/<</g
-b
diff --git a/t/chainlint/blank-line-before-esac.expect b/t/chainlint/blank-line-before-esac.expect
new file mode 100644
index 0000000000..48ed4eb124
--- /dev/null
+++ b/t/chainlint/blank-line-before-esac.expect
@@ -0,0 +1,18 @@
+test_done ( ) {
+ case "$test_failure" in
+ 0 )
+ test_at_end_hook_
+
+ exit 0 ;;
+
+ * )
+ if test $test_external_has_tap -eq 0
+ then
+ say_color error "# failed $test_failure among $msg"
+ say "1..$test_count"
+ fi
+
+ exit 1 ;;
+
+ esac
+}
diff --git a/t/chainlint/blank-line-before-esac.test b/t/chainlint/blank-line-before-esac.test
new file mode 100644
index 0000000000..cecccad19f
--- /dev/null
+++ b/t/chainlint/blank-line-before-esac.test
@@ -0,0 +1,19 @@
+# LINT: blank line before "esac"
+test_done () {
+ case "$test_failure" in
+ 0)
+ test_at_end_hook_
+
+ exit 0 ;;
+
+ *)
+ if test $test_external_has_tap -eq 0
+ then
+ say_color error "# failed $test_failure among $msg"
+ say "1..$test_count"
+ fi
+
+ exit 1 ;;
+
+ esac
+}
diff --git a/t/chainlint/block.expect b/t/chainlint/block.expect
index da60257ebc..a3bcea492a 100644
--- a/t/chainlint/block.expect
+++ b/t/chainlint/block.expect
@@ -1,7 +1,7 @@
(
foo &&
{
- echo a
+ echo a ?!AMP?!
echo b
} &&
bar &&
@@ -9,4 +9,15 @@
echo c
} ?!AMP?!
baz
-)
+) &&
+
+{
+ echo a ; ?!AMP?! echo b
+} &&
+{ echo a ; ?!AMP?! echo b ; } &&
+
+{
+ echo "${var}9" &&
+ echo "done"
+} &&
+finis
diff --git a/t/chainlint/block.test b/t/chainlint/block.test
index 0a82fd579f..4ab69a4afc 100644
--- a/t/chainlint/block.test
+++ b/t/chainlint/block.test
@@ -11,4 +11,17 @@
echo c
}
baz
-)
+) &&
+
+# LINT: ";" not allowed in place of "&&"
+{
+ echo a; echo b
+} &&
+{ echo a; echo b; } &&
+
+# LINT: "}" inside string not mistaken as end of block
+{
+ echo "${var}9" &&
+ echo "done"
+} &&
+finis
diff --git a/t/chainlint/chain-break-background.expect b/t/chainlint/chain-break-background.expect
new file mode 100644
index 0000000000..28f9114f42
--- /dev/null
+++ b/t/chainlint/chain-break-background.expect
@@ -0,0 +1,9 @@
+JGIT_DAEMON_PID= &&
+git init --bare empty.git &&
+> empty.git/git-daemon-export-ok &&
+mkfifo jgit_daemon_output &&
+{
+ jgit daemon --port="$JGIT_DAEMON_PORT" . > jgit_daemon_output &
+ JGIT_DAEMON_PID=$!
+} &&
+test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
diff --git a/t/chainlint/chain-break-background.test b/t/chainlint/chain-break-background.test
new file mode 100644
index 0000000000..e10f656b05
--- /dev/null
+++ b/t/chainlint/chain-break-background.test
@@ -0,0 +1,10 @@
+JGIT_DAEMON_PID= &&
+git init --bare empty.git &&
+>empty.git/git-daemon-export-ok &&
+mkfifo jgit_daemon_output &&
+{
+# LINT: exit status of "&" is always 0 so &&-chaining immaterial
+ jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
+ JGIT_DAEMON_PID=$!
+} &&
+test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
diff --git a/t/chainlint/chain-break-continue.expect b/t/chainlint/chain-break-continue.expect
new file mode 100644
index 0000000000..47a3457710
--- /dev/null
+++ b/t/chainlint/chain-break-continue.expect
@@ -0,0 +1,12 @@
+git ls-tree --name-only -r refs/notes/many_notes |
+while read path
+do
+ test "$path" = "foobar/non-note.txt" && continue
+ test "$path" = "deadbeef" && continue
+ test "$path" = "de/adbeef" && continue
+
+ if test $(expr length "$path") -ne $hexsz
+ then
+ return 1
+ fi
+done
diff --git a/t/chainlint/chain-break-continue.test b/t/chainlint/chain-break-continue.test
new file mode 100644
index 0000000000..f0af71d8bd
--- /dev/null
+++ b/t/chainlint/chain-break-continue.test
@@ -0,0 +1,13 @@
+git ls-tree --name-only -r refs/notes/many_notes |
+while read path
+do
+# LINT: broken &&-chain okay if explicit "continue"
+ test "$path" = "foobar/non-note.txt" && continue
+ test "$path" = "deadbeef" && continue
+ test "$path" = "de/adbeef" && continue
+
+ if test $(expr length "$path") -ne $hexsz
+ then
+ return 1
+ fi
+done
diff --git a/t/chainlint/chain-break-false.expect b/t/chainlint/chain-break-false.expect
new file mode 100644
index 0000000000..989766fb85
--- /dev/null
+++ b/t/chainlint/chain-break-false.expect
@@ -0,0 +1,9 @@
+if condition not satisified
+then
+ echo it did not work...
+ echo failed!
+ false
+else
+ echo it went okay ?!AMP?!
+ congratulate user
+fi
diff --git a/t/chainlint/chain-break-false.test b/t/chainlint/chain-break-false.test
new file mode 100644
index 0000000000..a5aaff8c8a
--- /dev/null
+++ b/t/chainlint/chain-break-false.test
@@ -0,0 +1,10 @@
+# LINT: broken &&-chain okay if explicit "false" signals failure
+if condition not satisified
+then
+ echo it did not work...
+ echo failed!
+ false
+else
+ echo it went okay
+ congratulate user
+fi
diff --git a/t/chainlint/chain-break-return-exit.expect b/t/chainlint/chain-break-return-exit.expect
new file mode 100644
index 0000000000..1732d221c3
--- /dev/null
+++ b/t/chainlint/chain-break-return-exit.expect
@@ -0,0 +1,19 @@
+case "$(git ls-files)" in
+one ) echo pass one ;;
+* ) echo bad one ; return 1 ;;
+esac &&
+(
+ case "$(git ls-files)" in
+ two ) echo pass two ;;
+ * ) echo bad two ; exit 1 ;;
+esac
+) &&
+case "$(git ls-files)" in
+dir/two"$LF"one ) echo pass both ;;
+* ) echo bad ; return 1 ;;
+esac &&
+
+for i in 1 2 3 4 ; do
+ git checkout main -b $i || return $?
+ test_commit $i $i $i tag$i || return $?
+done
diff --git a/t/chainlint/chain-break-return-exit.test b/t/chainlint/chain-break-return-exit.test
new file mode 100644
index 0000000000..46542edf88
--- /dev/null
+++ b/t/chainlint/chain-break-return-exit.test
@@ -0,0 +1,23 @@
+case "$(git ls-files)" in
+one) echo pass one ;;
+# LINT: broken &&-chain okay if explicit "return 1" signals failuire
+*) echo bad one; return 1 ;;
+esac &&
+(
+ case "$(git ls-files)" in
+ two) echo pass two ;;
+# LINT: broken &&-chain okay if explicit "exit 1" signals failuire
+ *) echo bad two; exit 1 ;;
+ esac
+) &&
+case "$(git ls-files)" in
+dir/two"$LF"one) echo pass both ;;
+# LINT: broken &&-chain okay if explicit "return 1" signals failuire
+*) echo bad; return 1 ;;
+esac &&
+
+for i in 1 2 3 4 ; do
+# LINT: broken &&-chain okay if explicit "return $?" signals failure
+ git checkout main -b $i || return $?
+ test_commit $i $i $i tag$i || return $?
+done
diff --git a/t/chainlint/chain-break-status.expect b/t/chainlint/chain-break-status.expect
new file mode 100644
index 0000000000..f4bada9463
--- /dev/null
+++ b/t/chainlint/chain-break-status.expect
@@ -0,0 +1,9 @@
+OUT=$(( ( large_git ; echo $? 1 >& 3 ) | : ) 3 >& 1) &&
+test_match_signal 13 "$OUT" &&
+
+{ test-tool sigchain > actual ; ret=$? ; } &&
+{
+ test_match_signal 15 "$ret" ||
+ test "$ret" = 3
+} &&
+test_cmp expect actual
diff --git a/t/chainlint/chain-break-status.test b/t/chainlint/chain-break-status.test
new file mode 100644
index 0000000000..a6602a7b99
--- /dev/null
+++ b/t/chainlint/chain-break-status.test
@@ -0,0 +1,11 @@
+# LINT: broken &&-chain okay if next command handles "$?" explicitly
+OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&
+test_match_signal 13 "$OUT" &&
+
+# LINT: broken &&-chain okay if next command handles "$?" explicitly
+{ test-tool sigchain >actual; ret=$?; } &&
+{
+ test_match_signal 15 "$ret" ||
+ test "$ret" = 3
+} &&
+test_cmp expect actual
diff --git a/t/chainlint/chained-block.expect b/t/chainlint/chained-block.expect
new file mode 100644
index 0000000000..574cdceb07
--- /dev/null
+++ b/t/chainlint/chained-block.expect
@@ -0,0 +1,9 @@
+echo nobody home && {
+ test the doohicky ?!AMP?!
+ right now
+} &&
+
+GIT_EXTERNAL_DIFF=echo git diff | {
+ read path oldfile oldhex oldmode newfile newhex newmode &&
+ test "z$oh" = "z$oldhex"
+}
diff --git a/t/chainlint/chained-block.test b/t/chainlint/chained-block.test
new file mode 100644
index 0000000000..86f81ece63
--- /dev/null
+++ b/t/chainlint/chained-block.test
@@ -0,0 +1,11 @@
+# LINT: start of block chained to preceding command
+echo nobody home && {
+ test the doohicky
+ right now
+} &&
+
+# LINT: preceding command pipes to block on same line
+GIT_EXTERNAL_DIFF=echo git diff | {
+ read path oldfile oldhex oldmode newfile newhex newmode &&
+ test "z$oh" = "z$oldhex"
+}
diff --git a/t/chainlint/chained-subshell.expect b/t/chainlint/chained-subshell.expect
new file mode 100644
index 0000000000..af0369d328
--- /dev/null
+++ b/t/chainlint/chained-subshell.expect
@@ -0,0 +1,10 @@
+mkdir sub && (
+ cd sub &&
+ foo the bar ?!AMP?!
+ nuff said
+) &&
+
+cut "-d " -f actual | ( read s1 s2 s3 &&
+test -f $s1 ?!AMP?!
+test $(cat $s2) = tree2path1 &&
+test $(cat $s3) = tree3path1 )
diff --git a/t/chainlint/chained-subshell.test b/t/chainlint/chained-subshell.test
new file mode 100644
index 0000000000..4ff6ddd8cb
--- /dev/null
+++ b/t/chainlint/chained-subshell.test
@@ -0,0 +1,13 @@
+# LINT: start of subshell chained to preceding command
+mkdir sub && (
+ cd sub &&
+ foo the bar
+ nuff said
+) &&
+
+# LINT: preceding command pipes to subshell on same line
+cut "-d " -f actual | (read s1 s2 s3 &&
+test -f $s1
+test $(cat $s2) = tree2path1 &&
+# LINT: closing subshell ")" correctly detected on same line as "$(...)"
+test $(cat $s3) = tree3path1)
diff --git a/t/chainlint/command-substitution-subsubshell.expect b/t/chainlint/command-substitution-subsubshell.expect
new file mode 100644
index 0000000000..ab2f79e845
--- /dev/null
+++ b/t/chainlint/command-substitution-subsubshell.expect
@@ -0,0 +1,2 @@
+OUT=$(( ( large_git 1 >& 3 ) | : ) 3 >& 1) &&
+test_match_signal 13 "$OUT"
diff --git a/t/chainlint/command-substitution-subsubshell.test b/t/chainlint/command-substitution-subsubshell.test
new file mode 100644
index 0000000000..321de2951c
--- /dev/null
+++ b/t/chainlint/command-substitution-subsubshell.test
@@ -0,0 +1,3 @@
+# LINT: subshell nested in subshell nested in command substitution
+OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
+test_match_signal 13 "$OUT"
diff --git a/t/chainlint/complex-if-in-cuddled-loop.expect b/t/chainlint/complex-if-in-cuddled-loop.expect
index 2fca183409..dac2d0fd1d 100644
--- a/t/chainlint/complex-if-in-cuddled-loop.expect
+++ b/t/chainlint/complex-if-in-cuddled-loop.expect
@@ -4,6 +4,6 @@
:
else
echo >file
- fi
+ fi ?!LOOP?!
done) &&
test ! -f file
diff --git a/t/chainlint/double-here-doc.expect b/t/chainlint/double-here-doc.expect
new file mode 100644
index 0000000000..75477bb1ad
--- /dev/null
+++ b/t/chainlint/double-here-doc.expect
@@ -0,0 +1,2 @@
+run_sub_test_lib_test_err run-inv-range-start "--run invalid range start" --run="a-5" <<-EOF &&
+check_sub_test_lib_test_err run-inv-range-start <<-EOF_OUT 3 <<-EOF_ERR
diff --git a/t/chainlint/double-here-doc.test b/t/chainlint/double-here-doc.test
new file mode 100644
index 0000000000..cd584a4357
--- /dev/null
+++ b/t/chainlint/double-here-doc.test
@@ -0,0 +1,12 @@
+run_sub_test_lib_test_err run-inv-range-start \
+ "--run invalid range start" \
+ --run="a-5" <<-\EOF &&
+test_expect_success "passing test #1" "true"
+test_done
+EOF
+check_sub_test_lib_test_err run-inv-range-start \
+ <<-\EOF_OUT 3<<-EOF_ERR
+> FATAL: Unexpected exit with code 1
+EOF_OUT
+> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
+EOF_ERR
diff --git a/t/chainlint/dqstring-line-splice.expect b/t/chainlint/dqstring-line-splice.expect
new file mode 100644
index 0000000000..bf9ced60d4
--- /dev/null
+++ b/t/chainlint/dqstring-line-splice.expect
@@ -0,0 +1,3 @@
+echo 'fatal: reword option of --fixup is mutually exclusive with' '--patch/--interactive/--all/--include/--only' > expect &&
+test_must_fail git commit --fixup=reword:HEAD~ $1 2 > actual &&
+test_cmp expect actual
diff --git a/t/chainlint/dqstring-line-splice.test b/t/chainlint/dqstring-line-splice.test
new file mode 100644
index 0000000000..b40714439f
--- /dev/null
+++ b/t/chainlint/dqstring-line-splice.test
@@ -0,0 +1,7 @@
+# LINT: line-splice within DQ-string
+'"
+echo 'fatal: reword option of --fixup is mutually exclusive with'\
+ '--patch/--interactive/--all/--include/--only' >expect &&
+test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
+test_cmp expect actual
+"'
diff --git a/t/chainlint/dqstring-no-interpolate.expect b/t/chainlint/dqstring-no-interpolate.expect
new file mode 100644
index 0000000000..10724987a5
--- /dev/null
+++ b/t/chainlint/dqstring-no-interpolate.expect
@@ -0,0 +1,11 @@
+grep "^ ! [rejected][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
+
+grep "^\.git$" output.txt &&
+
+
+(
+ cd client$version &&
+ GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. $(cat ../input)
+) > output &&
+ cut -d ' ' -f 2 < output | sort > actual &&
+ test_cmp expect actual
diff --git a/t/chainlint/dqstring-no-interpolate.test b/t/chainlint/dqstring-no-interpolate.test
new file mode 100644
index 0000000000..d2f4219cbb
--- /dev/null
+++ b/t/chainlint/dqstring-no-interpolate.test
@@ -0,0 +1,15 @@
+# LINT: regex dollar-sign eol anchor in double-quoted string not special
+grep "^ ! \[rejected\][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
+
+# LINT: escaped "$" not mistaken for variable expansion
+grep "^\\.git\$" output.txt &&
+
+'"
+(
+ cd client$version &&
+# LINT: escaped dollar-sign in double-quoted test body
+ GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. \$(cat ../input)
+) >output &&
+ cut -d ' ' -f 2 <output | sort >actual &&
+ test_cmp expect actual
+"'
diff --git a/t/chainlint/empty-here-doc.expect b/t/chainlint/empty-here-doc.expect
new file mode 100644
index 0000000000..f42f2d41ba
--- /dev/null
+++ b/t/chainlint/empty-here-doc.expect
@@ -0,0 +1,3 @@
+git ls-tree $tree path > current &&
+cat > expected <<EOF &&
+test_output
diff --git a/t/chainlint/empty-here-doc.test b/t/chainlint/empty-here-doc.test
new file mode 100644
index 0000000000..24fc165de3
--- /dev/null
+++ b/t/chainlint/empty-here-doc.test
@@ -0,0 +1,5 @@
+git ls-tree $tree path >current &&
+# LINT: empty here-doc
+cat >expected <<\EOF &&
+EOF
+test_output
diff --git a/t/chainlint/exclamation.expect b/t/chainlint/exclamation.expect
new file mode 100644
index 0000000000..2d961a58c6
--- /dev/null
+++ b/t/chainlint/exclamation.expect
@@ -0,0 +1,4 @@
+if ! condition ; then echo nope ; else yep ; fi &&
+test_prerequisite !MINGW &&
+mail uucp!address &&
+echo !whatever!
diff --git a/t/chainlint/exclamation.test b/t/chainlint/exclamation.test
new file mode 100644
index 0000000000..323595b5bd
--- /dev/null
+++ b/t/chainlint/exclamation.test
@@ -0,0 +1,8 @@
+# LINT: "! word" is two tokens
+if ! condition; then echo nope; else yep; fi &&
+# LINT: "!word" is single token, not two tokens "!" and "word"
+test_prerequisite !MINGW &&
+# LINT: "word!word" is single token, not three tokens "word", "!", and "word"
+mail uucp!address &&
+# LINT: "!word!" is single token, not three tokens "!", "word", and "!"
+echo !whatever!
diff --git a/t/chainlint/for-loop-abbreviated.expect b/t/chainlint/for-loop-abbreviated.expect
new file mode 100644
index 0000000000..a21007a63f
--- /dev/null
+++ b/t/chainlint/for-loop-abbreviated.expect
@@ -0,0 +1,5 @@
+for it
+do
+ path=$(expr "$it" : ( [^:]*) ) &&
+ git update-index --add "$path" || exit
+done
diff --git a/t/chainlint/for-loop-abbreviated.test b/t/chainlint/for-loop-abbreviated.test
new file mode 100644
index 0000000000..1084eccb89
--- /dev/null
+++ b/t/chainlint/for-loop-abbreviated.test
@@ -0,0 +1,6 @@
+# LINT: for-loop lacking optional "in [word...]" before "do"
+for it
+do
+ path=$(expr "$it" : '\([^:]*\)') &&
+ git update-index --add "$path" || exit
+done
diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect
index 6671b8cd84..a5810c9bdd 100644
--- a/t/chainlint/for-loop.expect
+++ b/t/chainlint/for-loop.expect
@@ -2,10 +2,10 @@
for i in a b c
do
echo $i ?!AMP?!
- cat <<-EOF
+ cat <<-EOF ?!LOOP?!
done ?!AMP?!
for i in a b c; do
echo $i &&
- cat $i
+ cat $i ?!LOOP?!
done
)
diff --git a/t/chainlint/function.expect b/t/chainlint/function.expect
new file mode 100644
index 0000000000..a14388e6b9
--- /dev/null
+++ b/t/chainlint/function.expect
@@ -0,0 +1,11 @@
+sha1_file ( ) {
+ echo "$*" | sed "s#..#.git/objects/&/#"
+} &&
+
+remove_object ( ) {
+ file=$(sha1_file "$*") &&
+ test -e "$file" ?!AMP?!
+ rm -f "$file"
+} ?!AMP?!
+
+sha1_file arg && remove_object arg
diff --git a/t/chainlint/function.test b/t/chainlint/function.test
new file mode 100644
index 0000000000..5ee59562c9
--- /dev/null
+++ b/t/chainlint/function.test
@@ -0,0 +1,13 @@
+# LINT: "()" in function definition not mistaken for subshell
+sha1_file() {
+ echo "$*" | sed "s#..#.git/objects/&/#"
+} &&
+
+# LINT: broken &&-chain in function and after function
+remove_object() {
+ file=$(sha1_file "$*") &&
+ test -e "$file"
+ rm -f "$file"
+}
+
+sha1_file arg && remove_object arg
diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect
new file mode 100644
index 0000000000..fb6cf7285d
--- /dev/null
+++ b/t/chainlint/here-doc-indent-operator.expect
@@ -0,0 +1,5 @@
+cat > expect <<-EOF &&
+
+cat > expect <<-EOF ?!AMP?!
+
+cleanup
diff --git a/t/chainlint/here-doc-indent-operator.test b/t/chainlint/here-doc-indent-operator.test
new file mode 100644
index 0000000000..c8a6f18eb4
--- /dev/null
+++ b/t/chainlint/here-doc-indent-operator.test
@@ -0,0 +1,13 @@
+# LINT: whitespace between operator "<<-" and tag legal
+cat >expect <<- EOF &&
+header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
+num_commits: $1
+chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
+EOF
+
+# LINT: not an indented here-doc; just a plain here-doc with tag named "-EOF"
+cat >expect << -EOF
+this is not indented
+-EOF
+
+cleanup
diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect
index 2578191ca8..be64b26869 100644
--- a/t/chainlint/here-doc-multi-line-string.expect
+++ b/t/chainlint/here-doc-multi-line-string.expect
@@ -1,4 +1,5 @@
(
- cat <<-TXT && echo "multi-line string" ?!AMP?!
+ cat <<-TXT && echo "multi-line
+ string" ?!AMP?!
bap
)
diff --git a/t/chainlint/if-condition-split.expect b/t/chainlint/if-condition-split.expect
new file mode 100644
index 0000000000..ee745ef8d7
--- /dev/null
+++ b/t/chainlint/if-condition-split.expect
@@ -0,0 +1,7 @@
+if bob &&
+ marcia ||
+ kevin
+then
+ echo "nomads" ?!AMP?!
+ echo "for sure"
+fi
diff --git a/t/chainlint/if-condition-split.test b/t/chainlint/if-condition-split.test
new file mode 100644
index 0000000000..240daa9fd5
--- /dev/null
+++ b/t/chainlint/if-condition-split.test
@@ -0,0 +1,8 @@
+# LINT: "if" condition split across multiple lines at "&&" or "||"
+if bob &&
+ marcia ||
+ kevin
+then
+ echo "nomads"
+ echo "for sure"
+fi
diff --git a/t/chainlint/if-in-loop.expect b/t/chainlint/if-in-loop.expect
index 03b82a3e58..d6514ae749 100644
--- a/t/chainlint/if-in-loop.expect
+++ b/t/chainlint/if-in-loop.expect
@@ -3,7 +3,7 @@
do
if false
then
- echo "err" ?!AMP?!
+ echo "err"
exit 1
fi ?!AMP?!
foo
diff --git a/t/chainlint/if-in-loop.test b/t/chainlint/if-in-loop.test
index f0cf19cfad..90c23976fe 100644
--- a/t/chainlint/if-in-loop.test
+++ b/t/chainlint/if-in-loop.test
@@ -3,7 +3,7 @@
do
if false
then
-# LINT: missing "&&" on "echo"
+# LINT: missing "&&" on "echo" okay since "exit 1" signals error explicitly
echo "err"
exit 1
# LINT: missing "&&" on "fi"
diff --git a/t/chainlint/loop-detect-failure.expect b/t/chainlint/loop-detect-failure.expect
new file mode 100644
index 0000000000..a66025c39d
--- /dev/null
+++ b/t/chainlint/loop-detect-failure.expect
@@ -0,0 +1,15 @@
+git init r1 &&
+for n in 1 2 3 4 5
+do
+ echo "This is file: $n" > r1/file.$n &&
+ git -C r1 add file.$n &&
+ git -C r1 commit -m "$n" || return 1
+done &&
+
+git init r2 &&
+for n in 1000 10000
+do
+ printf "%"$n"s" X > r2/large.$n &&
+ git -C r2 add large.$n &&
+ git -C r2 commit -m "$n" ?!LOOP?!
+done
diff --git a/t/chainlint/loop-detect-failure.test b/t/chainlint/loop-detect-failure.test
new file mode 100644
index 0000000000..b9791cc802
--- /dev/null
+++ b/t/chainlint/loop-detect-failure.test
@@ -0,0 +1,17 @@
+git init r1 &&
+# LINT: loop handles failure explicitly with "|| return 1"
+for n in 1 2 3 4 5
+do
+ echo "This is file: $n" > r1/file.$n &&
+ git -C r1 add file.$n &&
+ git -C r1 commit -m "$n" || return 1
+done &&
+
+git init r2 &&
+# LINT: loop fails to handle failure explicitly with "|| return 1"
+for n in 1000 10000
+do
+ printf "%"$n"s" X > r2/large.$n &&
+ git -C r2 add large.$n &&
+ git -C r2 commit -m "$n"
+done
diff --git a/t/chainlint/loop-detect-status.expect b/t/chainlint/loop-detect-status.expect
new file mode 100644
index 0000000000..0ad23bb35e
--- /dev/null
+++ b/t/chainlint/loop-detect-status.expect
@@ -0,0 +1,18 @@
+( while test $i -le $blobcount
+do
+ printf "Generating blob $i/$blobcount\r" >& 2 &&
+ printf "blob\nmark :$i\ndata $blobsize\n" &&
+
+ printf "%-${blobsize}s" $i &&
+ echo "M 100644 :$i $i" >> commit &&
+ i=$(($i+1)) ||
+ echo $? > exit-status
+done &&
+echo "commit refs/heads/main" &&
+echo "author A U Thor <author@email.com> 123456789 +0000" &&
+echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
+echo "data 5" &&
+echo ">2gb" &&
+cat commit ) |
+git fast-import --big-file-threshold=2 &&
+test ! -f exit-status
diff --git a/t/chainlint/loop-detect-status.test b/t/chainlint/loop-detect-status.test
new file mode 100644
index 0000000000..1c6c23cfc9
--- /dev/null
+++ b/t/chainlint/loop-detect-status.test
@@ -0,0 +1,19 @@
+# LINT: "$?" handled explicitly within loop body
+(while test $i -le $blobcount
+ do
+ printf "Generating blob $i/$blobcount\r" >&2 &&
+ printf "blob\nmark :$i\ndata $blobsize\n" &&
+ #test-tool genrandom $i $blobsize &&
+ printf "%-${blobsize}s" $i &&
+ echo "M 100644 :$i $i" >> commit &&
+ i=$(($i+1)) ||
+ echo $? > exit-status
+ done &&
+ echo "commit refs/heads/main" &&
+ echo "author A U Thor <author@email.com> 123456789 +0000" &&
+ echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
+ echo "data 5" &&
+ echo ">2gb" &&
+ cat commit) |
+git fast-import --big-file-threshold=2 &&
+test ! -f exit-status
diff --git a/t/chainlint/loop-in-if.expect b/t/chainlint/loop-in-if.expect
index e1be42376c..6c5d6e5b24 100644
--- a/t/chainlint/loop-in-if.expect
+++ b/t/chainlint/loop-in-if.expect
@@ -4,7 +4,7 @@
while true
do
echo "pop" ?!AMP?!
- echo "glup"
+ echo "glup" ?!LOOP?!
done ?!AMP?!
foo
fi ?!AMP?!
diff --git a/t/chainlint/loop-upstream-pipe.expect b/t/chainlint/loop-upstream-pipe.expect
new file mode 100644
index 0000000000..0b82ecc4b9
--- /dev/null
+++ b/t/chainlint/loop-upstream-pipe.expect
@@ -0,0 +1,10 @@
+(
+ git rev-list --objects --no-object-names base..loose |
+ while read oid
+ do
+ path="$objdir/$(test_oid_to_path "$oid")" &&
+ printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" ||
+ echo "object list generation failed for $oid"
+ done |
+ sort -k1
+) >expect &&
diff --git a/t/chainlint/loop-upstream-pipe.test b/t/chainlint/loop-upstream-pipe.test
new file mode 100644
index 0000000000..efb77da897
--- /dev/null
+++ b/t/chainlint/loop-upstream-pipe.test
@@ -0,0 +1,11 @@
+(
+ git rev-list --objects --no-object-names base..loose |
+ while read oid
+ do
+# LINT: "|| echo" signals failure in loop upstream of a pipe
+ path="$objdir/$(test_oid_to_path "$oid")" &&
+ printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" ||
+ echo "object list generation failed for $oid"
+ done |
+ sort -k1
+) >expect &&
diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect
index ab0dadf748..27ff95218e 100644
--- a/t/chainlint/multi-line-string.expect
+++ b/t/chainlint/multi-line-string.expect
@@ -1,9 +1,14 @@
(
- x="line 1 line 2 line 3" &&
- y="line 1 line2" ?!AMP?!
+ x="line 1
+ line 2
+ line 3" &&
+ y="line 1
+ line2" ?!AMP?!
foobar
) &&
(
- echo "xyz" "abc def ghi" &&
+ echo "xyz" "abc
+ def
+ ghi" &&
barfoo
)
diff --git a/t/chainlint/nested-loop-detect-failure.expect b/t/chainlint/nested-loop-detect-failure.expect
new file mode 100644
index 0000000000..4793a0e8e1
--- /dev/null
+++ b/t/chainlint/nested-loop-detect-failure.expect
@@ -0,0 +1,31 @@
+for i in 0 1 2 3 4 5 6 7 8 9 ;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9 ;
+ do
+ echo "$i$j" > "path$i$j" ?!LOOP?!
+ done ?!LOOP?!
+done &&
+
+for i in 0 1 2 3 4 5 6 7 8 9 ;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9 ;
+ do
+ echo "$i$j" > "path$i$j" || return 1
+ done
+done &&
+
+for i in 0 1 2 3 4 5 6 7 8 9 ;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9 ;
+ do
+ echo "$i$j" > "path$i$j" ?!LOOP?!
+ done || return 1
+done &&
+
+for i in 0 1 2 3 4 5 6 7 8 9 ;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9 ;
+ do
+ echo "$i$j" > "path$i$j" || return 1
+ done || return 1
+done
diff --git a/t/chainlint/nested-loop-detect-failure.test b/t/chainlint/nested-loop-detect-failure.test
new file mode 100644
index 0000000000..e6f0c1acfb
--- /dev/null
+++ b/t/chainlint/nested-loop-detect-failure.test
@@ -0,0 +1,35 @@
+# LINT: neither loop handles failure explicitly with "|| return 1"
+for i in 0 1 2 3 4 5 6 7 8 9;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9;
+ do
+ echo "$i$j" >"path$i$j"
+ done
+done &&
+
+# LINT: inner loop handles failure explicitly with "|| return 1"
+for i in 0 1 2 3 4 5 6 7 8 9;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9;
+ do
+ echo "$i$j" >"path$i$j" || return 1
+ done
+done &&
+
+# LINT: outer loop handles failure explicitly with "|| return 1"
+for i in 0 1 2 3 4 5 6 7 8 9;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9;
+ do
+ echo "$i$j" >"path$i$j"
+ done || return 1
+done &&
+
+# LINT: inner & outer loops handles failure explicitly with "|| return 1"
+for i in 0 1 2 3 4 5 6 7 8 9;
+do
+ for j in 0 1 2 3 4 5 6 7 8 9;
+ do
+ echo "$i$j" >"path$i$j" || return 1
+ done || return 1
+done
diff --git a/t/chainlint/nested-subshell.expect b/t/chainlint/nested-subshell.expect
index 41a48adaa2..02e0a9f1bb 100644
--- a/t/chainlint/nested-subshell.expect
+++ b/t/chainlint/nested-subshell.expect
@@ -6,7 +6,7 @@
) >file &&
cd foo &&
(
- echo a
+ echo a ?!AMP?!
echo b
) >file
)
diff --git a/t/chainlint/one-liner-for-loop.expect b/t/chainlint/one-liner-for-loop.expect
new file mode 100644
index 0000000000..51a3dc7c54
--- /dev/null
+++ b/t/chainlint/one-liner-for-loop.expect
@@ -0,0 +1,9 @@
+git init dir-rename-and-content &&
+(
+ cd dir-rename-and-content &&
+ test_write_lines 1 2 3 4 5 >foo &&
+ mkdir olddir &&
+ for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?!
+ git add foo olddir &&
+ git commit -m "original" &&
+)
diff --git a/t/chainlint/one-liner-for-loop.test b/t/chainlint/one-liner-for-loop.test
new file mode 100644
index 0000000000..4bd8c066c7
--- /dev/null
+++ b/t/chainlint/one-liner-for-loop.test
@@ -0,0 +1,10 @@
+git init dir-rename-and-content &&
+(
+ cd dir-rename-and-content &&
+ test_write_lines 1 2 3 4 5 >foo &&
+ mkdir olddir &&
+# LINT: one-liner for-loop missing "|| exit"; also broken &&-chain
+ for i in a b c; do echo $i >olddir/$i; done
+ git add foo olddir &&
+ git commit -m "original" &&
+)
diff --git a/t/chainlint/return-loop.expect b/t/chainlint/return-loop.expect
new file mode 100644
index 0000000000..cfc0549bef
--- /dev/null
+++ b/t/chainlint/return-loop.expect
@@ -0,0 +1,5 @@
+while test $i -lt $((num - 5))
+do
+ git notes add -m "notes for commit$i" HEAD~$i || return 1
+ i=$((i + 1))
+done
diff --git a/t/chainlint/return-loop.test b/t/chainlint/return-loop.test
new file mode 100644
index 0000000000..f90b171300
--- /dev/null
+++ b/t/chainlint/return-loop.test
@@ -0,0 +1,6 @@
+while test $i -lt $((num - 5))
+do
+# LINT: "|| return {n}" valid loop escape outside subshell; no "&&" needed
+ git notes add -m "notes for commit$i" HEAD~$i || return 1
+ i=$((i + 1))
+done
diff --git a/t/chainlint/semicolon.expect b/t/chainlint/semicolon.expect
index ed0b3707ae..3aa2259f36 100644
--- a/t/chainlint/semicolon.expect
+++ b/t/chainlint/semicolon.expect
@@ -15,5 +15,5 @@
) &&
(cd foo &&
for i in a b c; do
- echo;
+ echo; ?!LOOP?!
done)
diff --git a/t/chainlint/sqstring-in-sqstring.expect b/t/chainlint/sqstring-in-sqstring.expect
new file mode 100644
index 0000000000..cf0b591cf7
--- /dev/null
+++ b/t/chainlint/sqstring-in-sqstring.expect
@@ -0,0 +1,4 @@
+perl -e '
+ defined($_ = -s $_) or die for @ARGV;
+ exit 1 if $ARGV[0] <= $ARGV[1];
+' test-2-$packname_2.pack test-3-$packname_3.pack
diff --git a/t/chainlint/sqstring-in-sqstring.test b/t/chainlint/sqstring-in-sqstring.test
new file mode 100644
index 0000000000..77a425e0c7
--- /dev/null
+++ b/t/chainlint/sqstring-in-sqstring.test
@@ -0,0 +1,5 @@
+# LINT: SQ-string Perl code fragment within SQ-string
+perl -e '\''
+ defined($_ = -s $_) or die for @ARGV;
+ exit 1 if $ARGV[0] <= $ARGV[1];
+'\'' test-2-$packname_2.pack test-3-$packname_3.pack
diff --git a/t/chainlint/t7900-subtree.expect b/t/chainlint/t7900-subtree.expect
index 1cccc7bf7e..69167da2f2 100644
--- a/t/chainlint/t7900-subtree.expect
+++ b/t/chainlint/t7900-subtree.expect
@@ -1,10 +1,17 @@
(
- chks="sub1sub2sub3sub4" &&
+ chks="sub1
+sub2
+sub3
+sub4" &&
chks_sub=$(cat <<TXT | sed "s,^,sub dir/,"
) &&
- chkms="main-sub1main-sub2main-sub3main-sub4" &&
+ chkms="main-sub1
+main-sub2
+main-sub3
+main-sub4" &&
chkms_sub=$(cat <<TXT | sed "s,^,sub dir/,"
) &&
subfiles=$(git ls-files) &&
- check_equal "$subfiles" "$chkms$chks"
+ check_equal "$subfiles" "$chkms
+$chks"
)
diff --git a/t/chainlint/token-pasting.expect b/t/chainlint/token-pasting.expect
new file mode 100644
index 0000000000..342360bcd0
--- /dev/null
+++ b/t/chainlint/token-pasting.expect
@@ -0,0 +1,27 @@
+git config filter.rot13.smudge ./rot13.sh &&
+git config filter.rot13.clean ./rot13.sh &&
+
+{
+ echo "*.t filter=rot13" ?!AMP?!
+ echo "*.i ident"
+} > .gitattributes &&
+
+{
+ echo a b c d e f g h i j k l m ?!AMP?!
+ echo n o p q r s t u v w x y z ?!AMP?!
+ echo '$Id$'
+} > test &&
+cat test > test.t &&
+cat test > test.o &&
+cat test > test.i &&
+git add test test.t test.i &&
+rm -f test test.t test.i &&
+git checkout -- test test.t test.i &&
+
+echo "content-test2" > test2.o &&
+echo "content-test3 - filename with special characters" > "test3 'sq',$x=.o" ?!AMP?!
+
+downstream_url_for_sed=$(
+ printf "%sn" "$downstream_url" |
+ sed -e 's/\/\\/g' -e 's/[[/.*^$]/\&/g'
+)
diff --git a/t/chainlint/token-pasting.test b/t/chainlint/token-pasting.test
new file mode 100644
index 0000000000..b4610ce815
--- /dev/null
+++ b/t/chainlint/token-pasting.test
@@ -0,0 +1,32 @@
+# LINT: single token; composite of multiple strings
+git config filter.rot13.smudge ./rot13.sh &&
+git config filter.rot13.clean ./rot13.sh &&
+
+{
+ echo "*.t filter=rot13"
+ echo "*.i ident"
+} >.gitattributes &&
+
+{
+ echo a b c d e f g h i j k l m
+ echo n o p q r s t u v w x y z
+# LINT: exit/enter string context and escaped-quote outside of string
+ echo '\''$Id$'\''
+} >test &&
+cat test >test.t &&
+cat test >test.o &&
+cat test >test.i &&
+git add test test.t test.i &&
+rm -f test test.t test.i &&
+git checkout -- test test.t test.i &&
+
+echo "content-test2" >test2.o &&
+# LINT: exit/enter string context and escaped-quote outside of string
+echo "content-test3 - filename with special characters" >"test3 '\''sq'\'',\$x=.o"
+
+# LINT: single token; composite of multiple strings
+downstream_url_for_sed=$(
+ printf "%s\n" "$downstream_url" |
+# LINT: exit/enter string context; "&" inside string not command terminator
+ sed -e '\''s/\\/\\\\/g'\'' -e '\''s/[[/.*^$]/\\&/g'\''
+)
diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect
index 0d3a9b3d12..f272aa21fe 100644
--- a/t/chainlint/while-loop.expect
+++ b/t/chainlint/while-loop.expect
@@ -2,10 +2,10 @@
while true
do
echo foo ?!AMP?!
- cat <<-EOF
+ cat <<-EOF ?!LOOP?!
done ?!AMP?!
while true; do
echo foo &&
- cat bar
+ cat bar ?!LOOP?!
done
)
diff --git a/t/perf/README b/t/perf/README
index fb9127a66f..8f217d7be7 100644
--- a/t/perf/README
+++ b/t/perf/README
@@ -95,6 +95,10 @@ You can set the following variables (also in your config.mak):
Git (e.g., performance of index-pack as the number of threads
changes). These can be enabled with GIT_PERF_EXTRA.
+ GIT_PERF_USE_SCALAR
+ Boolean indicating whether to register test repo(s) with Scalar
+ before executing tests.
+
You can also pass the options taken by ordinary git tests; the most
useful one is:
diff --git a/t/perf/p9210-scalar.sh b/t/perf/p9210-scalar.sh
new file mode 100755
index 0000000000..265f7cd1fe
--- /dev/null
+++ b/t/perf/p9210-scalar.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+test_description='test scalar performance'
+. ./perf-lib.sh
+
+test_perf_large_repo "$TRASH_DIRECTORY/to-clone"
+
+test_expect_success 'enable server-side partial clone' '
+ git -C to-clone config uploadpack.allowFilter true &&
+ git -C to-clone config uploadpack.allowAnySHA1InWant true
+'
+
+test_perf 'scalar clone' '
+ rm -rf scalar-clone &&
+ scalar clone "file://$(pwd)/to-clone" scalar-clone
+'
+
+test_perf 'git clone' '
+ rm -rf git-clone &&
+ git clone "file://$(pwd)/to-clone" git-clone
+'
+
+test_compare_perf () {
+ command=$1
+ shift
+ args=$*
+ test_perf "$command $args (scalar)" "
+ $command -C scalar-clone/src $args
+ "
+
+ test_perf "$command $args (non-scalar)" "
+ $command -C git-clone $args
+ "
+}
+
+test_compare_perf git status
+test_compare_perf test_commit --append --no-tag A
+
+test_done
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index 27c2801792..e7786775a9 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -49,6 +49,9 @@ export TEST_DIRECTORY TRASH_DIRECTORY GIT_BUILD_DIR GIT_TEST_CMP
MODERN_GIT=$GIT_BUILD_DIR/bin-wrappers/git
export MODERN_GIT
+MODERN_SCALAR=$GIT_BUILD_DIR/bin-wrappers/scalar
+export MODERN_SCALAR
+
perf_results_dir=$TEST_RESULTS_DIR
test -n "$GIT_PERF_SUBSECTION" && perf_results_dir="$perf_results_dir/$GIT_PERF_SUBSECTION"
mkdir -p "$perf_results_dir"
@@ -120,6 +123,10 @@ test_perf_create_repo_from () {
# status" due to a locked index. Since we have
# a copy it's fine to remove the lock.
rm .git/index.lock
+ fi &&
+ if test_bool_env GIT_PERF_USE_SCALAR false
+ then
+ "$MODERN_SCALAR" register
fi
) || error "failed to copy repository '$source' to '$repo'"
}
@@ -130,7 +137,11 @@ test_perf_fresh_repo () {
"$MODERN_GIT" init -q "$repo" &&
(
cd "$repo" &&
- test_perf_do_repo_symlink_config_
+ test_perf_do_repo_symlink_config_ &&
+ if test_bool_env GIT_PERF_USE_SCALAR false
+ then
+ "$MODERN_SCALAR" register
+ fi
)
}
diff --git a/t/perf/run b/t/perf/run
index 55219aa405..33da4d2aba 100755
--- a/t/perf/run
+++ b/t/perf/run
@@ -171,6 +171,9 @@ run_subsection () {
get_var_from_env_or_config "GIT_PERF_MAKE_COMMAND" "perf" "makeCommand"
get_var_from_env_or_config "GIT_PERF_MAKE_OPTS" "perf" "makeOpts"
+ get_var_from_env_or_config "GIT_PERF_USE_SCALAR" "perf" "useScalar" "--bool"
+ export GIT_PERF_USE_SCALAR
+
get_var_from_env_or_config "GIT_PERF_REPO_NAME" "perf" "repoName"
export GIT_PERF_REPO_NAME
diff --git a/t/t0012-help.sh b/t/t0012-help.sh
index 4ed2f242eb..dbfc5c8267 100755
--- a/t/t0012-help.sh
+++ b/t/t0012-help.sh
@@ -231,7 +231,7 @@ test_expect_success "'git help -a' section spacing" '
User-facing repository, command and file interfaces
- Developer-facing file file formats, protocols and interfaces
+ Developer-facing file formats, protocols and other interfaces
EOF
test_cmp expect actual
'
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
index a22e0e1382..a94ac1eae3 100755
--- a/t/t0027-auto-crlf.sh
+++ b/t/t0027-auto-crlf.sh
@@ -387,9 +387,7 @@ test_expect_success 'setup main' '
test_tick
'
-# Disable extra chain-linting for the next set of tests. There are many
-# auto-generated ones that are not worth checking over and over.
-GIT_TEST_CHAIN_LINT_HARDER_DEFAULT=0
+
warn_LF_CRLF="LF will be replaced by CRLF"
warn_CRLF_LF="CRLF will be replaced by LF"
@@ -606,9 +604,6 @@ do
checkout_files "" "$id" "crlf" true "" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
done
-# The rest of the tests are unique; do the usual linting.
-unset GIT_TEST_CHAIN_LINT_HARDER_DEFAULT
-
# Should be the last test case: remove some files from the worktree
test_expect_success 'ls-files --eol -d -z' '
rm crlf_false_attr__CRLF.txt crlf_false_attr__CRLF_mix_LF.txt crlf_false_attr__LF.txt .gitattributes &&
diff --git a/t/t0092-diagnose.sh b/t/t0092-diagnose.sh
index fca9b58489..133e5747d6 100755
--- a/t/t0092-diagnose.sh
+++ b/t/t0092-diagnose.sh
@@ -28,12 +28,23 @@ test_expect_success UNZIP 'creates diagnostics zip archive' '
! "$GIT_UNZIP" -l "$zip_path" | grep ".git/"
'
+test_expect_success UNZIP 'counts loose objects' '
+ test_commit A &&
+
+ # After committing, should have non-zero loose objects
+ git diagnose -o test-count -s 1 >out &&
+ zip_path=test-count/git-diagnostics-1.zip &&
+ "$GIT_UNZIP" -p "$zip_path" objects-local.txt >out &&
+ grep "^Total: [1-9][0-9]* loose objects" out
+'
+
test_expect_success UNZIP '--mode=stats excludes .git dir contents' '
test_when_finished rm -rf report &&
git diagnose -o report -s test --mode=stats >out &&
# Includes pack quantity/size info
+ zip_path=report/git-diagnostics-test.zip &&
"$GIT_UNZIP" -p "$zip_path" packs-local.txt >out &&
grep ".git/objects" out &&
@@ -47,6 +58,7 @@ test_expect_success UNZIP '--mode=all includes .git dir contents' '
git diagnose -o report -s test --mode=all >out &&
# Includes pack quantity/size info
+ zip_path=report/git-diagnostics-test.zip &&
"$GIT_UNZIP" -p "$zip_path" packs-local.txt >out &&
grep ".git/objects" out &&
diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh
index 64096adac7..43fcb7c0bf 100755
--- a/t/t1800-hook.sh
+++ b/t/t1800-hook.sh
@@ -157,9 +157,9 @@ test_expect_success 'git hook run a hook with a bad shebang' '
write_script bad-hooks/test-hook "/bad/path/no/spaces" </dev/null &&
# TODO: We should emit the same (or at least a more similar)
- # error on Windows and !Windows. See the OS-specific code in
- # start_command()
- if test_have_prereq !WINDOWS
+ # error on MINGW (essentially Git for Windows) and all other
+ # platforms.. See the OS-specific code in start_command()
+ if test_have_prereq !MINGW
then
cat >expect <<-\EOF
fatal: cannot run bad-hooks/test-hook: ...
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index f9539968e4..5d871fde96 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,11 +5,6 @@ test_description='wildmatch tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-# Disable expensive chain-lint tests; all of the tests in this script
-# are variants of a few trivial test-tool invocations, and there are a lot of
-# them.
-GIT_TEST_CHAIN_LINT_HARDER_DEFAULT=0
-
should_create_test_file() {
file=$1
diff --git a/t/t7002-mv-sparse-checkout.sh b/t/t7002-mv-sparse-checkout.sh
index 71fe29690f..26582ae4e5 100755
--- a/t/t7002-mv-sparse-checkout.sh
+++ b/t/t7002-mv-sparse-checkout.sh
@@ -28,12 +28,25 @@ test_expect_success 'setup' "
updated in the index:
EOF
- cat >sparse_hint <<-EOF
+ cat >sparse_hint <<-EOF &&
hint: If you intend to update such entries, try one of the following:
hint: * Use the --sparse option.
hint: * Disable or modify the sparsity rules.
hint: Disable this message with \"git config advice.updateSparsePath false\"
EOF
+
+ cat >dirty_error_header <<-EOF &&
+ The following paths have been moved outside the
+ sparse-checkout definition but are not sparse due to local
+ modifications.
+ EOF
+
+ cat >dirty_hint <<-EOF
+ hint: To correct the sparsity of these paths, do the following:
+ hint: * Use \"git add --sparse <paths>\" to update the index
+ hint: * Use \"git sparse-checkout reapply\" to apply the sparsity rules
+ hint: Disable this message with \"git config advice.updateSparsePath false\"
+ EOF
"
test_expect_success 'mv refuses to move sparse-to-sparse' '
@@ -290,4 +303,215 @@ test_expect_success 'move sparse file to existing destination with --force and -
test_cmp expect sub/file1
'
+test_expect_success 'move clean path from in-cone to out-of-cone' '
+ test_when_finished "cleanup_sparse_checkout" &&
+ setup_sparse_checkout &&
+
+ test_must_fail git mv sub/d folder1 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo "folder1/d" >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse sub/d folder1 2>stderr &&
+ test_must_be_empty stderr &&
+
+ test_path_is_missing sub/d &&
+ test_path_is_missing folder1/d &&
+ git ls-files -t >actual &&
+ ! grep "^H sub/d\$" actual &&
+ grep "S folder1/d" actual
+'
+
+test_expect_success 'move clean path from in-cone to out-of-cone overwrite' '
+ test_when_finished "cleanup_sparse_checkout" &&
+ setup_sparse_checkout &&
+ echo "sub/file1 overwrite" >sub/file1 &&
+ git add sub/file1 &&
+
+ test_must_fail git mv sub/file1 folder1 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo "folder1/file1" >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ test_must_fail git mv --sparse sub/file1 folder1 2>stderr &&
+ echo "fatal: destination exists in the index, source=sub/file1, destination=folder1/file1" \
+ >expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse -f sub/file1 folder1 2>stderr &&
+ test_must_be_empty stderr &&
+
+ test_path_is_missing sub/file1 &&
+ test_path_is_missing folder1/file1 &&
+ git ls-files -t >actual &&
+ ! grep "H sub/file1" actual &&
+ grep "S folder1/file1" actual &&
+
+ # compare file content before move and after move
+ echo "sub/file1 overwrite" >expect &&
+ git ls-files -s -- folder1/file1 | awk "{print \$2}" >oid &&
+ git cat-file blob $(cat oid) >actual &&
+ test_cmp expect actual
+'
+
+# This test is testing the same behavior as the
+# "move clean path from in-cone to out-of-cone overwrite" above.
+# The only difference is the <destination> changes from "folder1" to "folder1/file1"
+test_expect_success 'move clean path from in-cone to out-of-cone file overwrite' '
+ test_when_finished "cleanup_sparse_checkout" &&
+ setup_sparse_checkout &&
+ echo "sub/file1 overwrite" >sub/file1 &&
+ git add sub/file1 &&
+
+ test_must_fail git mv sub/file1 folder1/file1 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo "folder1/file1" >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ test_must_fail git mv --sparse sub/file1 folder1/file1 2>stderr &&
+ echo "fatal: destination exists in the index, source=sub/file1, destination=folder1/file1" \
+ >expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse -f sub/file1 folder1/file1 2>stderr &&
+ test_must_be_empty stderr &&
+
+ test_path_is_missing sub/file1 &&
+ test_path_is_missing folder1/file1 &&
+ git ls-files -t >actual &&
+ ! grep "H sub/file1" actual &&
+ grep "S folder1/file1" actual &&
+
+ # compare file content before move and after move
+ echo "sub/file1 overwrite" >expect &&
+ git ls-files -s -- folder1/file1 | awk "{print \$2}" >oid &&
+ git cat-file blob $(cat oid) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'move directory with one of the files overwrite' '
+ test_when_finished "cleanup_sparse_checkout" &&
+ mkdir -p folder1/dir &&
+ touch folder1/dir/file1 &&
+ git add folder1 &&
+ git sparse-checkout set --cone sub &&
+
+ echo test >sub/dir/file1 &&
+ git add sub/dir/file1 &&
+
+ test_must_fail git mv sub/dir folder1 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo "folder1/dir/e" >>expect &&
+ echo "folder1/dir/file1" >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ test_must_fail git mv --sparse sub/dir folder1 2>stderr &&
+ echo "fatal: destination exists in the index, source=sub/dir/file1, destination=folder1/dir/file1" \
+ >expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse -f sub/dir folder1 2>stderr &&
+ test_must_be_empty stderr &&
+
+ test_path_is_missing sub/dir/file1 &&
+ test_path_is_missing sub/dir/e &&
+ test_path_is_missing folder1/file1 &&
+ git ls-files -t >actual &&
+ ! grep "H sub/dir/file1" actual &&
+ ! grep "H sub/dir/e" actual &&
+ grep "S folder1/dir/file1" actual &&
+
+ # compare file content before move and after move
+ echo test >expect &&
+ git ls-files -s -- folder1/dir/file1 | awk "{print \$2}" >oid &&
+ git cat-file blob $(cat oid) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'move dirty path from in-cone to out-of-cone' '
+ test_when_finished "cleanup_sparse_checkout" &&
+ setup_sparse_checkout &&
+ echo "modified" >>sub/d &&
+
+ test_must_fail git mv sub/d folder1 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo "folder1/d" >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse sub/d folder1 2>stderr &&
+ cat dirty_error_header >expect &&
+ echo "folder1/d" >>expect &&
+ cat dirty_hint >>expect &&
+ test_cmp expect stderr &&
+
+ test_path_is_missing sub/d &&
+ test_path_is_file folder1/d &&
+ git ls-files -t >actual &&
+ ! grep "^H sub/d\$" actual &&
+ grep "H folder1/d" actual
+'
+
+test_expect_success 'move dir from in-cone to out-of-cone' '
+ test_when_finished "cleanup_sparse_checkout" &&
+ setup_sparse_checkout &&
+ mkdir sub/dir/deep &&
+
+ test_must_fail git mv sub/dir folder1 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo "folder1/dir/e" >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse sub/dir folder1 2>stderr &&
+ test_must_be_empty stderr &&
+
+ test_path_is_missing sub/dir &&
+ test_path_is_missing folder1 &&
+ git ls-files -t >actual &&
+ ! grep "H sub/dir/e" actual &&
+ grep "S folder1/dir/e" actual
+'
+
+test_expect_success 'move partially-dirty dir from in-cone to out-of-cone' '
+ test_when_finished "cleanup_sparse_checkout" &&
+ setup_sparse_checkout &&
+ mkdir sub/dir/deep &&
+ touch sub/dir/e2 sub/dir/e3 &&
+ git add sub/dir/e2 sub/dir/e3 &&
+ echo "modified" >>sub/dir/e2 &&
+ echo "modified" >>sub/dir/e3 &&
+
+ test_must_fail git mv sub/dir folder1 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo "folder1/dir/e" >>expect &&
+ echo "folder1/dir/e2" >>expect &&
+ echo "folder1/dir/e3" >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse sub/dir folder1 2>stderr &&
+ cat dirty_error_header >expect &&
+ echo "folder1/dir/e2" >>expect &&
+ echo "folder1/dir/e3" >>expect &&
+ cat dirty_hint >>expect &&
+ test_cmp expect stderr &&
+
+ test_path_is_missing sub/dir &&
+ test_path_is_missing folder1/dir/e &&
+ test_path_is_file folder1/dir/e2 &&
+ test_path_is_file folder1/dir/e3 &&
+ git ls-files -t >actual &&
+ ! grep "H sub/dir/e" actual &&
+ ! grep "H sub/dir/e2" actual &&
+ ! grep "H sub/dir/e3" actual &&
+ grep "S folder1/dir/e" actual &&
+ grep "H folder1/dir/e2" actual &&
+ grep "H folder1/dir/e3" actual
+'
+
test_done
diff --git a/contrib/scalar/t/t9099-scalar.sh b/t/t9210-scalar.sh
index dfb949f52e..14ca575a21 100755
--- a/contrib/scalar/t/t9099-scalar.sh
+++ b/t/t9210-scalar.sh
@@ -2,15 +2,9 @@
test_description='test the `scalar` command'
-TEST_DIRECTORY=$PWD/../../../t
-export TEST_DIRECTORY
+. ./test-lib.sh
-# Make it work with --no-bin-wrappers
-PATH=$PWD/..:$PATH
-
-. ../../../t/test-lib.sh
-
-GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab ../cron.txt,launchctl:true,schtasks:true"
+GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true"
export GIT_TEST_MAINT_SCHEDULER
test_expect_success 'scalar shows a usage' '
diff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh
new file mode 100755
index 0000000000..dd33d87e9b
--- /dev/null
+++ b/t/t9211-scalar-clone.sh
@@ -0,0 +1,151 @@
+#!/bin/sh
+
+test_description='test the `scalar clone` subcommand'
+
+. ./test-lib.sh
+
+GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true"
+export GIT_TEST_MAINT_SCHEDULER
+
+test_expect_success 'set up repository to clone' '
+ rm -rf .git &&
+ git init to-clone &&
+ (
+ cd to-clone &&
+ git branch -m base &&
+
+ test_commit first &&
+ test_commit second &&
+ test_commit third &&
+
+ git switch -c parallel first &&
+ mkdir -p 1/2 &&
+ test_commit 1/2/3 &&
+
+ git switch base &&
+
+ # By default, permit
+ git config uploadpack.allowfilter true &&
+ git config uploadpack.allowanysha1inwant true
+ )
+'
+
+cleanup_clone () {
+ rm -rf "$1"
+}
+
+test_expect_success 'creates content in enlistment root' '
+ enlistment=cloned &&
+
+ scalar clone "file://$(pwd)/to-clone" $enlistment &&
+ ls -A $enlistment >enlistment-root &&
+ test_line_count = 1 enlistment-root &&
+ test_path_is_dir $enlistment/src &&
+ test_path_is_dir $enlistment/src/.git &&
+
+ cleanup_clone $enlistment
+'
+
+test_expect_success 'with spaces' '
+ enlistment="cloned with space" &&
+
+ scalar clone "file://$(pwd)/to-clone" "$enlistment" &&
+ test_path_is_dir "$enlistment" &&
+ test_path_is_dir "$enlistment/src" &&
+ test_path_is_dir "$enlistment/src/.git" &&
+
+ cleanup_clone "$enlistment"
+'
+
+test_expect_success 'partial clone if supported by server' '
+ enlistment=partial-clone &&
+
+ scalar clone "file://$(pwd)/to-clone" $enlistment &&
+
+ (
+ cd $enlistment/src &&
+
+ # Two promisor packs: one for refs, the other for blobs
+ ls .git/objects/pack/pack-*.promisor >promisorlist &&
+ test_line_count = 2 promisorlist
+ ) &&
+
+ cleanup_clone $enlistment
+'
+
+test_expect_success 'fall back on full clone if partial unsupported' '
+ enlistment=no-partial-support &&
+
+ test_config -C to-clone uploadpack.allowfilter false &&
+ test_config -C to-clone uploadpack.allowanysha1inwant false &&
+
+ scalar clone "file://$(pwd)/to-clone" $enlistment 2>err &&
+ grep "filtering not recognized by server, ignoring" err &&
+
+ (
+ cd $enlistment/src &&
+
+ # Still get a refs promisor file, but none for blobs
+ ls .git/objects/pack/pack-*.promisor >promisorlist &&
+ test_line_count = 1 promisorlist
+ ) &&
+
+ cleanup_clone $enlistment
+'
+
+test_expect_success 'initializes sparse-checkout by default' '
+ enlistment=sparse &&
+
+ scalar clone "file://$(pwd)/to-clone" $enlistment &&
+ (
+ cd $enlistment/src &&
+ test_cmp_config true core.sparseCheckout &&
+ test_cmp_config true core.sparseCheckoutCone
+ ) &&
+
+ cleanup_clone $enlistment
+'
+
+test_expect_success '--full-clone does not create sparse-checkout' '
+ enlistment=full-clone &&
+
+ scalar clone --full-clone "file://$(pwd)/to-clone" $enlistment &&
+ (
+ cd $enlistment/src &&
+ test_cmp_config "" --default "" core.sparseCheckout &&
+ test_cmp_config "" --default "" core.sparseCheckoutCone
+ ) &&
+
+ cleanup_clone $enlistment
+'
+
+test_expect_success '--single-branch clones HEAD only' '
+ enlistment=single-branch &&
+
+ scalar clone --single-branch "file://$(pwd)/to-clone" $enlistment &&
+ (
+ cd $enlistment/src &&
+ git for-each-ref refs/remotes/origin >out &&
+ test_line_count = 1 out &&
+ grep "refs/remotes/origin/base" out
+ ) &&
+
+ cleanup_clone $enlistment
+'
+
+test_expect_success '--no-single-branch clones all branches' '
+ enlistment=no-single-branch &&
+
+ scalar clone --no-single-branch "file://$(pwd)/to-clone" $enlistment &&
+ (
+ cd $enlistment/src &&
+ git for-each-ref refs/remotes/origin >out &&
+ test_line_count = 2 out &&
+ grep "refs/remotes/origin/base" out &&
+ grep "refs/remotes/origin/parallel" out
+ ) &&
+
+ cleanup_clone $enlistment
+'
+
+test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 377cc1c120..a65df2fd22 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1091,11 +1091,7 @@ test_run_ () {
trace=
# 117 is magic because it is unlikely to match the exit
# code of other programs
- if test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)" ||
- {
- test "${GIT_TEST_CHAIN_LINT_HARDER:-${GIT_TEST_CHAIN_LINT_HARDER_DEFAULT:-1}}" != 0 &&
- $(printf '%s\n' "$1" | sed -f "$GIT_BUILD_DIR/t/chainlint.sed" | grep -q '?![A-Z][A-Z]*?!')
- }
+ if test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)"
then
BUG "broken &&-chain or run-away HERE-DOC: $1"
fi
@@ -1591,6 +1587,12 @@ then
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true"
fi
+if test "${GIT_TEST_CHAIN_LINT:-1}" != 0
+then
+ "$PERL_PATH" "$TEST_DIRECTORY/chainlint.pl" "$0" ||
+ BUG "lint error (see '?!...!? annotations above)"
+fi
+
# Last-minute variable setup
USER_HOME="$HOME"
HOME="$TRASH_DIRECTORY"
diff --git a/transport-helper.c b/transport-helper.c
index 322c722478..e95267a4ab 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1286,6 +1286,8 @@ int transport_helper_init(struct transport *transport, const char *name)
if (getenv("GIT_TRANSPORT_HELPER_DEBUG"))
debug = 1;
+ list_objects_filter_init(&data->transport_options.filter_options);
+
transport->data = data;
transport->vtable = &vtable;
transport->smart_options = &(data->transport_options);
diff --git a/transport.c b/transport.c
index 1687ad7e2c..f78e29058f 100644
--- a/transport.c
+++ b/transport.c
@@ -1113,6 +1113,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
* will be checked individually in git_connect.
*/
struct git_transport_data *data = xcalloc(1, sizeof(*data));
+ list_objects_filter_init(&data->options.filter_options);
ret->data = data;
ret->vtable = &builtin_smart_vtable;
ret->smart_options = &(data->options);
diff --git a/upload-pack.c b/upload-pack.c
index abf2c11cfe..0b8311bd68 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -141,6 +141,7 @@ static void upload_pack_data_init(struct upload_pack_data *data)
data->allow_filter_fallback = 1;
data->tree_filter_max_depth = ULONG_MAX;
packet_writer_init(&data->writer, 1);
+ list_objects_filter_init(&data->filter_options);
data->keepalive = 5;
data->advertise_sid = 0;