From: Junio C Hamano Date: Mon, 25 Mar 2013 21:00:56 +0000 (-0700) Subject: Merge branch 'mg/unsigned-time-t' X-Git-Tag: v1.8.3-rc0~176 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/f10a012088a7b6e418ec3f726142a8ddfa3d0264?hp=e1033da6af80b77d720ba7df9b8d3439666582e4 Merge branch 'mg/unsigned-time-t' A few workarounds for systems with unsigned time_t. * mg/unsigned-time-t: Fix time offset calculation in case of unsigned time_t date.c: fix unsigned time_t comparison --- diff --git a/Documentation/RelNotes/1.8.1.5.txt b/Documentation/RelNotes/1.8.1.5.txt index 92da6b2777..efa68aef22 100644 --- a/Documentation/RelNotes/1.8.1.5.txt +++ b/Documentation/RelNotes/1.8.1.5.txt @@ -1,9 +1,19 @@ Git 1.8.1.5 Release Notes ========================= -Fixes since v1.8.1.5 +Fixes since v1.8.1.4 -------------------- + * Given a string with a multi-byte character that begins with '-' on + the command line where an option is expected, the option parser + used just one byte of the unknown letter when reporting an error. + + * In v1.8.1, the attribute parser was tightened too restrictive to + error out upon seeing an entry that begins with an ! (exclamation), + which may confuse users to expect a "negative match", which does + not exist. This has been demoted to a warning; such an entry is + still ignored. + * "git apply --summary" has been taught to make sure the similarity value shown in its output is sensible, even when the input had a bogus value. diff --git a/Documentation/RelNotes/1.8.2.1.txt b/Documentation/RelNotes/1.8.2.1.txt new file mode 100644 index 0000000000..e77f8333ea --- /dev/null +++ b/Documentation/RelNotes/1.8.2.1.txt @@ -0,0 +1,29 @@ +Git v1.8.2.1 Release Notes +========================== + +Fixes since v1.8.2 +------------------ + + * The "--color=" argument to the commands in the diff family + was described poorly. + + * The arguments given to pre-rebase hook were not documented. + + * The v4 index format was not documented. + + * The "--match=" argument "git describe" takes uses glob + pattern but it wasn't obvious from the documentation. + + * Some sources failed to compile on systems that lack NI_MAXHOST in + their system header (e.g. z/OS). + + * Add an example use of "--env-filter" in "filter-branch" + documentation. + + * "git bundle verify" did not say "records a complete history" for a + bundle that does not have any prerequisites. + + * In the v1.8.0 era, we changed symbols that do not have to be global + to file scope static, but a few functions in graph.c were used by + CGit from sideways bypassing the entry points of the API the + in-tree users use. diff --git a/Documentation/RelNotes/1.8.2.txt b/Documentation/RelNotes/1.8.2.txt index 861ef026d6..fc606ae116 100644 --- a/Documentation/RelNotes/1.8.2.txt +++ b/Documentation/RelNotes/1.8.2.txt @@ -1,19 +1,8 @@ Git v1.8.2 Release Notes ======================== -Backward compatibility notes ----------------------------- - -In the next major release Git 2.0 (not *this* one), we will change the -behavior of the "git push" command. - -When "git push [$there]" does not say what to push, we have used the -traditional "matching" semantics so far (all your branches were sent -to the remote as long as there already are branches of the same name -over there). We will use the "simple" semantics that pushes the -current branch to the branch with the same name, only when the current -branch is set to integrate with that remote branch. There is a user -preference configuration variable "push.default" to change this. +Backward compatibility notes (this release) +------------------------------------------- "git push $there tag v1.2.3" used to allow replacing a tag v1.2.3 that already exists in the repository $there, if the rewritten tag @@ -22,17 +11,41 @@ that the old tag v1.2.3 points at. This was found to be error prone and starting with this release, any attempt to update an existing ref under refs/tags/ hierarchy will fail, without "--force". -When "git add -u" and "git add -A", that does not specify what paths -to add on the command line, is run from inside a subdirectory, the +When "git add -u" and "git add -A" that does not specify what paths +to add on the command line is run from inside a subdirectory, the scope of the operation has always been limited to the subdirectory. Many users found this counter-intuitive, given that "git commit -a" and other commands operate on the entire tree regardless of where you -are. In this release, these commands give warning in such a case and -encourage the user to say "git add -u/-A ." instead when restricting -the scope to the current directory. At Git 2.0 (not *this* one), we -plan to change these commands without pathspec to operate on the -entire tree, and training your fingers to type "." will protect you -against the future change. +are. In this release, these commands give a warning message that +suggests the users to use "git add -u/-A ." when they want to limit +the scope to the current directory; doing so will squelch the message, +while training their fingers. + + +Backward compatibility notes (for Git 2.0) +------------------------------------------ + +When "git push [$there]" does not say what to push, we have used the +traditional "matching" semantics so far (all your branches were sent +to the remote as long as there already are branches of the same name +over there). In Git 2.0, the default will change to the "simple" +semantics that pushes the current branch to the branch with the same +name, only when the current branch is set to integrate with that +remote branch. There is a user preference configuration variable +"push.default" to change this. If you are an old-timer who is used +to the "matching" semantics, you can set it to "matching" to keep the +traditional behaviour. If you want to live in the future early, +you can set it to "simple" today without waiting for Git 2.0. + +When "git add -u" and "git add -A", that does not specify what paths +to add on the command line is run from inside a subdirectory, these +commands will operate on the entire tree in Git 2.0 for consistency +with "git commit -a" and other commands. Because there will be no +mechanism to make "git add -u" behave as if "git add -u .", it is +important for those who are used to "git add -u" (without pathspec) +updating the index only for paths in the current subdirectory to start +training their fingers to explicitly say "git add -u ." when they mean +it before Git 2.0 comes. Updates since v1.8.1 @@ -463,3 +476,20 @@ details). * Scripts to test bash completion was inherently flaky as it was affected by whatever random things the user may have on $PATH. + + * An element on GIT_CEILING_DIRECTORIES could be a "logical" pathname + that uses a symbolic link to point at somewhere else (e.g. /home/me + that points at /net/host/export/home/me, and the latter directory + is automounted). Earlier when Git saw such a pathname e.g. /home/me + on this environment variable, the "ceiling" mechanism did not take + effect. With this release (the fix has also been merged to the + v1.8.1.x maintenance series), elements on GIT_CEILING_DIRECTORIES + are by default checked for such aliasing coming from symbolic + links. As this needs to actually resolve symbolic links for each + element on the GIT_CEILING_DIRECTORIES, you can disable this + mechanism for some elements by listing them after an empty element + on the GIT_CEILING_DIRECTORIES. e.g. Setting /home/me::/home/him to + GIT_CEILING_DIRECTORIES makes Git resolve symbolic links in + /home/me when checking if the current directory is under /home/me, + but does not do so for /home/him. + (merge 7ec30aa mh/maint-ceil-absolute later to maint). diff --git a/Documentation/RelNotes/1.8.3.txt b/Documentation/RelNotes/1.8.3.txt new file mode 100644 index 0000000000..23bd0c45bb --- /dev/null +++ b/Documentation/RelNotes/1.8.3.txt @@ -0,0 +1,162 @@ +Git v1.8.3 Release Notes +======================== + +Backward compatibility notes (for Git 2.0) +------------------------------------------ + +When "git push [$there]" does not say what to push, we have used the +traditional "matching" semantics so far (all your branches were sent +to the remote as long as there already are branches of the same name +over there). In Git 2.0, the default will change to the "simple" +semantics that pushes the current branch to the branch with the same +name, only when the current branch is set to integrate with that +remote branch. There is a user preference configuration variable +"push.default" to change this. If you are an old-timer who is used +to the "matching" semantics, you can set it to "matching" to keep the +traditional behaviour. If you want to live in the future early, +you can set it to "simple" today without waiting for Git 2.0. + +When "git add -u" and "git add -A", that does not specify what paths +to add on the command line is run from inside a subdirectory, these +commands will operate on the entire tree in Git 2.0 for consistency +with "git commit -a" and other commands. Because there will be no +mechanism to make "git add -u" behave as if "git add -u .", it is +important for those who are used to "git add -u" (without pathspec) +updating the index only for paths in the current subdirectory to start +training their fingers to explicitly say "git add -u ." when they mean +it before Git 2.0 comes. + + +Updates since v1.8.2 +-------------------- + +UI, Workflows & Features + + * When the interactive access to git-shell is not enabled, it issues + a message meant to help the system admininstrator to enable it. + An explicit way to help the end users who connect to the service by + issuing custom messages to refuse such an access has been added. + + * "git status" suggests users to look into using--untracked=no option + when it takes too long. + + * "git fetch" learned to fetch a commit at the tip of an unadvertised + ref by specifying a raw object name from the command line when the + server side supports this feature. + + * "git count-objects -v" learned to report leftover temporary + packfiles and other garbage in the object store. + + * A new read-only credential helper (in contrib/) to interact with + the .netrc/.authinfo files has been added. + + * "git send-email" can be used with the credential helper system. + + +Foreign Interface + + + +Performance, Internal Implementation, etc. + + * Updates for building under msvc. + + * A few codepaths knew how much data they need to put in the + hashtables they use upfront, but still started from a small table + repeatedly growing and rehashing. + + +Also contains minor documentation updates and code clean-ups. + + +Fixes since v1.8.2 +------------------ + +Unless otherwise noted, all the fixes since v1.8.2 in the maintenance +track are contained in this release (see release notes to them for +details). + + * Clarify in the documentation "what" gets pushed to "where" when the + command line to "git push" does not say these explicitly. + (merge cfe1348 jc/maint-push-refspec-default-doc later to maint). + + * The "--color=" argument to the commands in the diff family + was described poorly. + (merge 3d0e75f jc/color-diff-doc later to maint). + + * The arguments given to pre-rebase hook were not documented. + (merge 0414acc wk/doc-pre-rebase later to maint). + + * The v4 index format was not documented. + (merge 647d879 nd/doc-index-format later to maint). + + * The "--match=" argument "git describe" takes uses glob + pattern but it wasn't obvious from the documentation. + (merge 5229149 gp/describe-match-uses-glob-pattern later to maint). + + * Some sources failed to compile on systems that lack NI_MAXHOST in + their system header (e.g. z/OS). + (merge 3b130ade dm/ni-maxhost-may-be-missing later to maint). + + * Add an example use of "--env-filter" in "filter-branch" + documentation. + (merge 21b6e4f tk/doc-filter-branch later to maint). + + * "git bundle verify" did not say "records a complete history" for a + bundle that does not have any prerequisites. + (merge a02ffe0 lf/bundle-verify-list-prereqs later to maint). + + * In the v1.8.0 era, we changed symbols that do not have to be global + to file scope static, but a few functions in graph.c were used by + CGit from sideways bypassing the entry points of the API the + in-tree users use. + (merge ac751a0 jk/graph-c-expose-symbols-for-cgit later to maint). + + * "git update-index -h" did not do the usual "-h(elp)" thing. + + * "git index-pack" had a buffer-overflow while preparing an + informational message when the translated version of it was too + long. + (merge 5c3459f nd/index-pack-l10n-buf-overflow later to maint). + + * 'git commit -m "$msg"' used to add an extra newline even when + $msg already ended with one. + (merge 46fbf75 bc/commit-complete-lines-given-via-m-option later to maint). + + * The SSL peer verification done by "git imap-send" did not ask for + Server Name Indication (RFC 4366), failing to connect SSL/TLS + sites that serve multiple hostnames on a single IP. + (merge 698a1ec ob/imap-send-ssl-verify later to maint). + + * perl/Git.pm::cat_blob slurped everything in core only to write it + out to a file descriptor, which was not a very smart thing to do. + (merge 712c6ad jc/perl-cat-blob later to maint). + + * "git branch" did not bother to check nonsense command line + parameters and issue errors in many cases. + (merge 8efb889 nd/branch-error-cases later to maint). + + * Verification of signed tags were not done correctly when not in C + or en/US locale. + (merge 0174eea mg/gpg-interface-using-status later to maint). + + * Some platforms and users spell UTF-8 differently; retry with the + most official "UTF-8" when the system does not understand the + user-supplied encoding name that are the common alternative + spellings of UTF-8. + (merge 5c680be jk/utf-8-can-be-spelled-differently later to maint). + + * When export-subst is used, "zip" output recorded incorrect + size of the file. + (merge d3c1472 rs/zip-compresssed-size-with-export-subst later to maint). + + * "git am $maildir/" applied messages in an unexpected order; sort + filenames read from the maildir/ in a way that is more likely to + sort messages in the order the writing MUA meant to, by sorting + numeric segment in numeric order and non-numeric segment in + alphabetical order. + (merge 18505c3 jk/mailsplit-maildir-muttsort later to maint). + + * "git submodule update", when recursed into sub-submodules, did not + acccumulate the prefix paths. + (merge 75bf5e6 we/submodule-update-prefix-output later to maint). diff --git a/Documentation/config.txt b/Documentation/config.txt index bbba728d09..c1f435f6df 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -178,6 +178,10 @@ advice.*:: the template shown when writing commit messages in linkgit:git-commit[1], and in the help message shown by linkgit:git-checkout[1] when switching branch. + statusUoption:: + Advise to consider using the `-u` option to linkgit:git-status[1] + when the command takes more than 2 seconds to enumerate untracked + files. commitBeforeMerge:: Advice shown when linkgit:git-merge[1] refuses to merge to avoid overwriting local changes. @@ -443,7 +447,7 @@ core.sharedRepository:: core.warnAmbiguousRefs:: If true, Git will warn you if the ref name you passed it is ambiguous - and might match multiple refs in the .git/refs/ tree. True by default. + and might match multiple refs in the repository. True by default. core.compression:: An integer -1..9, indicating a default compression level. @@ -2119,7 +2123,13 @@ uploadpack.hiderefs:: are under the hierarchies listed on the value of this variable is excluded, and is hidden from `git ls-remote`, `git fetch`, etc. An attempt to fetch a hidden ref by `git - fetch` will fail. + fetch` will fail. See also `uploadpack.allowtipsha1inwant`. + +uploadpack.allowtipsha1inwant:: + When `uploadpack.hiderefs` is in effect, allow `upload-pack` + to accept a fetch request that asks for an object at the tip + of a hidden ref (by default, such a request is rejected). + see also `uploadpack.hiderefs`. url..insteadOf:: Any URL that starts with this value will be rewritten to diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 869d965a3b..104579dc75 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -195,8 +195,8 @@ any of those replacements occurred. --color[=]:: Show colored diff. - The value must be `always` (the default for ``), `never`, or `auto`. - The default value is `never`. + `--color` (i.e. without '=') is the same as `--color=always`. + '' can be one of `always`, `never`, or `auto`. ifdef::git-diff[] It can be changed by the `color.ui` and `color.diff` configuration settings. diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 388a2254f9..b0944e57d5 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -100,12 +100,9 @@ apply to the index. See EDITING PATCHES below. -u:: --update:: - Only match against already tracked files in - the index rather than the working tree. That means that it - will never stage new files, but that it will stage modified - new contents of tracked files and that it will remove files - from the index if the corresponding files in the working tree - have been removed. + Update the index just where it already has an entry matching + . This removes as well as modifies index entries to + match the working tree, but adds no new files. + If no is given, the current version of Git defaults to "."; in other words, update all tracked files in the current directory @@ -114,10 +111,15 @@ of Git, hence the form without should not be used. -A:: --all:: - Like `-u`, but match against files in the - working tree in addition to the index. That means that it - will find new files as well as staging modified content and - removing files that are no longer in the working tree. + Update the index not only where the working tree has a file + matching but also where the index already has an + entry. This adds, modifies, and removes index entries to + match the working tree. ++ +If no is given, the current version of Git defaults to +"."; in other words, update all files in the current directory +and its subdirectories. This default will change in a future version +of Git, hence the form without should not be used. -N:: --intent-to-add:: diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 0eb79ccdba..24a99ccc99 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -172,16 +172,25 @@ OPTIONS linkgit:git-commit-tree[1]. --cleanup=:: - This option sets how the commit message is cleaned up. - The '' can be one of 'verbatim', 'whitespace', 'strip', - and 'default'. The 'default' mode will strip leading and - trailing empty lines and #commentary from the commit message - only if the message is to be edited. Otherwise only whitespace - removed. The 'verbatim' mode does not change message at all, - 'whitespace' removes just leading/trailing whitespace lines - and 'strip' removes both whitespace and commentary. The default - can be changed by the 'commit.cleanup' configuration variable - (see linkgit:git-config[1]). + This option determines how the supplied commit message should be + cleaned up before committing. The '' can be `strip`, + `whitespace`, `verbatim`, or `default`. ++ +-- +strip:: + Strip leading and trailing empty lines, trailing whitespace, and + #commentary and collapse consecutive empty lines. +whitespace:: + Same as `strip` except #commentary is not removed. +verbatim:: + Do not change the message at all. +default:: + Same as `strip` if the message is to be edited. + Otherwise `whitespace`. +-- ++ +The default can be changed by the 'commit.cleanup' configuration +variable (see linkgit:git-config[1]). -e:: --edit:: diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt index 23c80cea64..da6e72e696 100644 --- a/Documentation/git-count-objects.txt +++ b/Documentation/git-count-objects.txt @@ -20,11 +20,23 @@ OPTIONS ------- -v:: --verbose:: - In addition to the number of loose objects and disk - space consumed, it reports the number of in-pack - objects, number of packs, disk space consumed by those packs, - and number of objects that can be removed by running - `git prune-packed`. + Report in more detail: ++ +count: the number of loose objects ++ +size: disk space consumed by loose objects, in KiB ++ +in-pack: the number of in-pack objects ++ +size-pack: disk space consumed by the packs, in KiB ++ +prune-packable: the number of loose objects that are also present in +the packs. These objects could be pruned using `git prune-packed`. ++ +garbage: the number of files in object database that are not valid +loose objects nor valid packs ++ +size-garbage: disk space consumed by garbage files, in KiB GIT --- diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt index 32da244fd5..3c81e85ec5 100644 --- a/Documentation/git-describe.txt +++ b/Documentation/git-describe.txt @@ -81,8 +81,9 @@ OPTIONS that points at object deadbee....). --match :: - Only consider tags matching the given pattern (can be used to avoid - leaking private tags made from the repository). + Only consider tags matching the given `glob(7)` pattern, + excluding the "refs/tags/" prefix. This can be used to avoid + leaking private tags from the repository. --always:: Show uniquely abbreviated commit object as fallback. diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index dfd12c94e4..e4c8e82660 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -64,8 +64,11 @@ argument is always evaluated in the shell context using the 'eval' command Prior to that, the $GIT_COMMIT environment variable will be set to contain the id of the commit being rewritten. Also, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, -and GIT_COMMITTER_DATE are set according to the current commit. The values -of these variables after the filters have run, are used for the new commit. +and GIT_COMMITTER_DATE are taken from the current commit and exported to +the environment, in order to affect the author and committer identities of +the replacement commit created by linkgit:git-commit-tree[1] after the +filters have run. + If any evaluation of returns a non-zero exit status, the whole operation will be aborted. @@ -329,6 +332,26 @@ git filter-branch --msg-filter ' ' HEAD~10..HEAD -------------------------------------------------------- +The `--env-filter` option can be used to modify committer and/or author +identity. For example, if you found out that your commits have the wrong +identity due to a misconfigured user.email, you can make a correction, +before publishing the project, like this: + +-------------------------------------------------------- +git filter-branch --env-filter ' + if test "$GIT_AUTHOR_EMAIL" = "root@localhost" + then + GIT_AUTHOR_EMAIL=john@example.com + export GIT_AUTHOR_EMAIL + fi + if test "$GIT_COMMITTER_EMAIL" = "root@localhost" + then + GIT_COMMITTER_EMAIL=john@example.com + export GIT_COMMITTER_EMAIL + fi +' -- --all +-------------------------------------------------------- + To restrict rewriting to only part of the history, specify a revision range in addition to the new branch name. The new branch name will point to the top-most revision that a 'git rev-list' of this range diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index 13980257ee..eb2883c94c 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects SYNOPSIS -------- [verse] -'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=] +'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] [--receive-pack=] [--repo=] [-f | --force] [--prune] [-v | --verbose] [-u | --set-upstream] [ [...]] @@ -23,6 +23,17 @@ You can make interesting things happen to a repository every time you push into it, by setting up 'hooks' there. See documentation for linkgit:git-receive-pack[1]. +When the command line does not specify where to push with the +`` argument, `branch.*.remote` configuration for the +current branch is consulted to determine where to push. If the +configuration is missing, it defaults to 'origin'. + +When the command line does not specify what to push with `...` +arguments or `--all`, `--mirror`, `--tags` options, the command finds +the default `` by consulting `remote.*.push` configuration, +and if it is not found, honors `push.default` configuration to decide +what to push (See gitlink:git-config[1] for the meaning of `push.default`). + OPTIONS[[OPTIONS]] ------------------ @@ -33,13 +44,10 @@ OPTIONS[[OPTIONS]] of a remote (see the section <> below). ...:: + Specify what destination ref to update with what source object. The format of a parameter is an optional plus - `+`, followed by the source ref , followed + `+`, followed by the source object , followed by a colon `:`, followed by the destination ref . - It is used to specify with what object the ref - in the remote repository is to be updated. If not specified, - the behavior of the command is controlled by the `push.default` - configuration variable. + The is often the name of the branch you would want to push, but it can be any arbitrary "SHA-1 expression", such as `master~4` or @@ -66,10 +74,7 @@ the remote repository. The special refspec `:` (or `+:` to allow non-fast-forward updates) directs Git to push "matching" branches: for every branch that exists on the local side, the remote side is updated if a branch of the same name -already exists on the remote side. This is the default operation mode -if no explicit refspec is found (that is neither on the command line -nor in any Push line of the corresponding remotes file---see below) and -no `push.default` configuration variable is set. +already exists on the remote side. --all:: Instead of naming each ref to push, specifies that all @@ -112,6 +117,12 @@ no `push.default` configuration variable is set. addition to refspecs explicitly listed on the command line. +--follow-tags:: + Push all the refs that would be pushed without this option, + and also push annotated tags in `refs/tags` that are missing + from the remote but are pointing at committish that are + reachable from the refs being pushed. + --receive-pack=:: --exec=:: Path to the 'git-receive-pack' program on the remote diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt index 92bac27e05..1d876c2619 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.txt @@ -149,6 +149,10 @@ files that aren't ignored are present in the submodules work tree. Ignored files are deemed expendable and won't stop a submodule's work tree from being removed. +If you only want to remove the local checkout of a submodule from your +work tree without committing the removal, +use linkgit:git-submodule[1] `deinit` instead. + EXAMPLES -------- `git rm Documentation/\*.txt`:: diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 44a1f7c4e8..0cffef8aa5 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -164,8 +164,8 @@ Sending Furthermore, passwords need not be specified in configuration files or on the command line. If a username has been specified (with '--smtp-user' or a 'sendemail.smtpuser'), but no password has been -specified (with '--smtp-pass' or 'sendemail.smtppass'), then the -user is prompted for a password while the input is masked for privacy. +specified (with '--smtp-pass' or 'sendemail.smtppass'), then +a password is obtained using 'git-credential'. --smtp-server=:: If set, specifies the outgoing SMTP server to use (e.g. diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index 9b9250600f..c35051ba58 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -9,25 +9,81 @@ git-shell - Restricted login shell for Git-only SSH access SYNOPSIS -------- [verse] -'git shell' [-c ] +'chsh' -s $(command -v git-shell) +'git clone' `@localhost:/path/to/repo.git` +'ssh' `@localhost` DESCRIPTION ----------- -A login shell for SSH accounts to provide restricted Git access. When -'-c' is given, the program executes non-interactively; - can be one of 'git receive-pack', 'git upload-pack', 'git -upload-archive', 'cvs server', or a command in COMMAND_DIR. The shell -is started in interactive mode when no arguments are given; in this -case, COMMAND_DIR must exist, and any of the executables in it can be -invoked. +This is a login shell for SSH accounts to provide restricted Git access. +It permits execution only of server-side Git commands implementing the +pull/push functionality, plus custom commands present in a subdirectory +named `git-shell-commands` in the user's home directory. -'cvs server' is a special command which executes git-cvsserver. +COMMANDS +-------- + +'git shell' accepts the following commands after the '-c' option: + +'git receive-pack ':: +'git upload-pack ':: +'git upload-archive ':: + Call the corresponding server-side command to support + the client's 'git push', 'git fetch', or 'git archive --remote' + request. +'cvs server':: + Imitate a CVS server. See linkgit:git-cvsserver[1]. + +If a `~/git-shell-commands` directory is present, 'git shell' will +also handle other, custom commands by running +"`git-shell-commands/ `" from the user's home +directory. + +INTERACTIVE USE +--------------- + +By default, the commands above can be executed only with the '-c' +option; the shell is not interactive. -COMMAND_DIR is the path "$HOME/git-shell-commands". The user must have -read and execute permissions to the directory in order to execute the -programs in it. The programs are executed with a cwd of $HOME, and - is parsed as a command-line string. +If a `~/git-shell-commands` directory is present, 'git shell' +can also be run interactively (with no arguments). If a `help` +command is present in the `git-shell-commands` directory, it is +run to provide the user with an overview of allowed actions. Then a +"git> " prompt is presented at which one can enter any of the +commands from the `git-shell-commands` directory, or `exit` to close +the connection. + +Generally this mode is used as an administrative interface to allow +users to list repositories they have access to, create, delete, or +rename repositories, or change repository descriptions and +permissions. + +If a `no-interactive-login` command exists, then it is run and the +interactive shell is aborted. + +EXAMPLE +------- + +To disable interactive logins, displaying a greeting instead: ++ +---------------- +$ chsh -s /usr/bin/git-shell +$ mkdir $HOME/git-shell-commands +$ cat >$HOME/git-shell-commands/no-interactive-login <<\EOF +#!/bin/sh +printf '%s\n' "Hi $USER! You've successfully authenticated, but I do not" +printf '%s\n' "provide interactive shell access." +exit 128 +EOF +$ chmod +x $HOME/git-shell-commands/no-interactive-login +---------------- + +SEE ALSO +-------- +ssh(1), +linkgit:git-daemon[1], +contrib/git-shell-commands/README GIT --- diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 0412c4017d..9046df98a0 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -46,15 +46,21 @@ OPTIONS Show untracked files. + The mode parameter is optional (defaults to 'all'), and is used to -specify the handling of untracked files; when -u is not used, the -default is 'normal', i.e. show untracked files and directories. +specify the handling of untracked files. + The possible options are: + - - 'no' - Show no untracked files - - 'normal' - Shows untracked files and directories + - 'no' - Show no untracked files. + - 'normal' - Shows untracked files and directories. - 'all' - Also shows individual files in untracked directories. + +When `-u` option is not used, untracked files and directories are +shown (i.e. the same as specifying `normal`), to help you avoid +forgetting to add newly created files. Because it takes extra work +to find untracked files in the filesystem, this mode may take some +time in a large working tree. You can use `no` to have `git status` +return more quickly without showing untracked files. ++ The default can be changed using the status.showUntrackedFiles configuration variable documented in linkgit:git-config[1]. diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index a0c9df85f4..74d5bdc59d 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -13,8 +13,10 @@ SYNOPSIS [--reference ] [--] [] 'git submodule' [--quiet] status [--cached] [--recursive] [--] [...] 'git submodule' [--quiet] init [--] [...] -'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] [--rebase] - [--reference ] [--merge] [--recursive] [--] [...] +'git submodule' [--quiet] deinit [-f|--force] [--] ... +'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] + [-f|--force] [--rebase] [--reference ] + [--merge] [--recursive] [--] [...] 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) ] [commit] [--] [...] 'git submodule' [--quiet] foreach [--recursive] @@ -134,6 +136,19 @@ init:: the explicit 'init' step if you do not intend to customize any submodule locations. +deinit:: + Unregister the given submodules, i.e. remove the whole + `submodule.$name` section from .git/config together with their work + tree. Further calls to `git submodule update`, `git submodule foreach` + and `git submodule sync` will skip any unregistered submodules until + they are initialized again, so use this command if you don't want to + have a local checkout of the submodule in your work tree anymore. If + you really want to remove a submodule from the repository and commit + that use linkgit:git-rm[1] instead. ++ +If `--force` is specified, the submodule's work tree will be removed even if +it contains local modifications. + update:: Update the registered submodules, i.e. clone missing submodules and checkout the commit specified in the index of the containing repository. @@ -213,8 +228,10 @@ OPTIONS -f:: --force:: - This option is only valid for add and update commands. + This option is only valid for add, deinit and update commands. When running add, allow adding an otherwise ignored submodule path. + When running deinit the submodule work trees will be removed even if + they contain local changes. When running update, throw away local changes in submodules when switching to a different commit; and always run a checkout operation in the submodule, even if the commit listed in the index of the diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index 77a912d4ea..c92775829b 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -145,7 +145,15 @@ you will need to handle the situation manually. --index-version :: Write the resulting index out in the named on-disk format version. - The current default version is 2. + Supported versions are 2, 3 and 4. The current default version is 2 + or 3, depending on whether extra features are used, such as + `git add -N`. ++ +Version 4 performs a simple pathname compression that reduces index +size by 30%-50% on large repositories, which results in faster load +time. Version 4 is relatively young (first released in in 1.8.0 in +October 2012). Other Git implementations such as JGit and libgit2 +may not support it yet. -z:: Only meaningful with `--stdin` or `--index-info`; paths are diff --git a/Documentation/git.txt b/Documentation/git.txt index 0847cdcc68..7efaa591b8 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,15 @@ unreleased) version of Git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.8.1.4/git.html[documentation for release 1.8.1.4] +* link:v1.8.2/git.html[documentation for release 1.8.2] * release notes for + link:RelNotes/1.8.2.txt[1.8.2]. + +* link:v1.8.1.5/git.html[documentation for release 1.8.1.5] + +* release notes for + link:RelNotes/1.8.1.5.txt[1.8.1.5], link:RelNotes/1.8.1.4.txt[1.8.1.4], link:RelNotes/1.8.1.3.txt[1.8.1.3], link:RelNotes/1.8.1.2.txt[1.8.1.2], @@ -678,12 +684,19 @@ Git so take care if using Cogito etc. The '--namespace' command-line option also sets this value. 'GIT_CEILING_DIRECTORIES':: - This should be a colon-separated list of absolute paths. - If set, it is a list of directories that Git should not chdir - up into while looking for a repository directory. - It will not exclude the current working directory or - a GIT_DIR set on the command line or in the environment. - (Useful for excluding slow-loading network directories.) + This should be a colon-separated list of absolute paths. If + set, it is a list of directories that Git should not chdir up + into while looking for a repository directory (useful for + excluding slow-loading network directories). It will not + exclude the current working directory or a GIT_DIR set on the + command line or in the environment. Normally, Git has to read + the entries in this list and resolve any symlink that + might be present in order to compare them with the current + directory. However, if even this access is slow, you + can add an empty entry to the list to tell Git that the + subsequent entries are not symlinks and needn't be resolved; + e.g., + 'GIT_CEILING_DIRECTORIES=/maybe/symlink::/very/slow/non/symlink'. 'GIT_DISCOVERY_ACROSS_FILESYSTEM':: When run in a directory that does not have ".git" repository diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt index dc9e617a10..9ac5088acd 100644 --- a/Documentation/gitcli.txt +++ b/Documentation/gitcli.txt @@ -107,13 +107,14 @@ couple of magic command line options: --------------------------------------------- $ git describe -h usage: git describe [options] * + or: git describe [options] --dirty --contains find the tag that comes after the commit --debug debug search strategy on stderr - --all use any ref in .git/refs - --tags use any tag in .git/refs/tags - --abbrev [] use digits to display SHA-1s - --candidates consider most recent tags (default: 10) + --all use any ref + --tags use any tag, even unannotated + --long always use long format + --abbrev[=] use digits to display SHA-1s --------------------------------------------- --help-all:: diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 8181e4ed2a..dc6693fe48 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -140,9 +140,11 @@ the outcome of 'git commit'. pre-rebase ~~~~~~~~~~ -This hook is called by 'git rebase' and can be used to prevent a branch -from getting rebased. - +This hook is called by 'git rebase' and can be used to prevent a +branch from getting rebased. The hook may be called with one or +two parameters. The first parameter is the upstream from which +the series was forked. The second parameter is the branch being +rebased, and is not set when rebasing the current branch. post-checkout ~~~~~~~~~~~~~ @@ -365,7 +367,7 @@ preceding SP is also omitted. Currently, no commands pass any 'extra-info'. The hook always runs after the automatic note copying (see -"notes.rewrite." in linkgit:git-config.txt) has happened, and +"notes.rewrite." in linkgit:git-config.txt[1]) has happened, and thus has access to these notes. The following command-specific comments apply: diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 105f18a6f9..293965524e 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -133,6 +133,7 @@ The placeholders are: - '%GG': raw verification message from GPG for a signed commit - '%G?': show either "G" for Good or "B" for Bad for a signed commit - '%GS': show the name of the signer for a signed commit +- '%GK': show the key used to sign a signed commit - '%gD': reflog selector, e.g., `refs/stash@{1}` - '%gd': shortened reflog selector, e.g., `stash@{1}` - '%gn': reflog identity name diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index 678d1756a5..314e25da73 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -88,10 +88,10 @@ some output processing may assume ref names in UTF-8. The construct '@\{-\}' means the th branch checked out before the current one. -'@\{upstream\}', e.g. 'master@\{upstream\}', '@\{u\}':: - The suffix '@\{upstream\}' to a ref (short form '@\{u\}') refers to - the branch the ref is set to build on top of. A missing ref defaults - to the current branch. +'@\{upstream\}', e.g. 'master@\{upstream\}', '@\{u\}':: + The suffix '@\{upstream\}' to a branchname (short form '@\{u\}') + refers to the branch that the branch specified by branchname is set to build on + top of. A missing branchname defaults to the current one. '{caret}', e.g. 'HEAD{caret}, v1.5.1{caret}0':: A suffix '{caret}' to a revision parameter means the first parent of diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt index 27c716b15f..0810251f5a 100644 --- a/Documentation/technical/index-format.txt +++ b/Documentation/technical/index-format.txt @@ -12,7 +12,7 @@ Git index format The signature is { 'D', 'I', 'R', 'C' } (stands for "dircache") 4-byte version number: - The current supported versions are 2 and 3. + The current supported versions are 2, 3 and 4. 32-bit number of index entries. @@ -93,8 +93,8 @@ Git index format 12-bit name length if the length is less than 0xFFF; otherwise 0xFFF is stored in this field. - (Version 3) A 16-bit field, only applicable if the "extended flag" - above is 1, split into (high to low bits). + (Version 3 or later) A 16-bit field, only applicable if the + "extended flag" above is 1, split into (high to low bits). 1-bit reserved for future diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 5f36f8115f..e831cc2020 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -19,7 +19,7 @@ Further chapters cover more specialized topics. Comprehensive reference documentation is available through the man pages, or linkgit:git-help[1] command. For example, for the command -"git clone ", you can either use: +`git clone `, you can either use: ------------------------------------------------ $ man git-clone @@ -66,11 +66,11 @@ $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git The initial clone may be time-consuming for a large project, but you will only need to clone once. -The clone command creates a new directory named after the project ("git" -or "linux-2.6" in the examples above). After you cd into this +The clone command creates a new directory named after the project (`git` +or `linux-2.6` in the examples above). After you cd into this directory, you will see that it contains a copy of the project files, called the <>, together with a special -top-level directory named ".git", which contains all the information +top-level directory named `.git`, which contains all the information about the history of the project. [[how-to-check-out]] @@ -188,7 +188,7 @@ As you can see, a commit shows who made the latest change, what they did, and why. Every commit has a 40-hexdigit id, sometimes called the "object name" or the -"SHA-1 id", shown on the first line of the "git show" output. You can usually +"SHA-1 id", shown on the first line of the `git show` output. You can usually refer to a commit by a shorter name, such as a tag or a branch name, but this longer name can also be useful. Most importantly, it is a globally unique name for this commit: so if you tell somebody else the object name (for @@ -268,35 +268,35 @@ Manipulating branches Creating, deleting, and modifying branches is quick and easy; here's a summary of the commands: -git branch:: +`git branch`:: list all branches -git branch :: - create a new branch named , referencing the same +`git branch `:: + create a new branch named ``, referencing the same point in history as the current branch -git branch :: - create a new branch named , referencing - , which may be specified any way you like, +`git branch `:: + create a new branch named ``, referencing + ``, which may be specified any way you like, including using a branch name or a tag name -git branch -d :: - delete the branch ; if the branch you are deleting +`git branch -d `:: + delete the branch ``; if the branch you are deleting points to a commit which is not reachable from the current branch, this command will fail with a warning. -git branch -D :: +`git branch -D `:: even if the branch points to a commit not reachable from the current branch, you may know that that commit is still reachable from some other branch or tag. In that case it is safe to use this command to force Git to delete the branch. -git checkout :: - make the current branch , updating the working - directory to reflect the version referenced by -git checkout -b :: - create a new branch referencing , and +`git checkout `:: + make the current branch ``, updating the working + directory to reflect the version referenced by `` +`git checkout -b `:: + create a new branch `` referencing ``, and check it out. The special symbol "HEAD" can always be used to refer to the current -branch. In fact, Git uses a file named "HEAD" in the .git directory to -remember which branch is current: +branch. In fact, Git uses a file named `HEAD` in the `.git` directory +to remember which branch is current: ------------------------------------------------ $ cat .git/HEAD @@ -346,7 +346,7 @@ of the HEAD in the repository that you cloned from. That repository may also have had other branches, though, and your local repository keeps branches which track each of those remote branches, called remote-tracking branches, which you -can view using the "-r" option to linkgit:git-branch[1]: +can view using the `-r` option to linkgit:git-branch[1]: ------------------------------------------------ $ git branch -r @@ -364,7 +364,7 @@ In this example, "origin" is called a remote repository, or "remote" for short. The branches of this repository are called "remote branches" from our point of view. The remote-tracking branches listed above were created based on the remote branches at clone time and will -be updated by "git fetch" (hence "git pull") and "git push". See +be updated by `git fetch` (hence `git pull`) and `git push`. See <> for details. You might want to build on one of these remote-tracking branches @@ -374,7 +374,7 @@ on a branch of your own, just as you would for a tag: $ git checkout -b my-todo-copy origin/todo ------------------------------------------------ -You can also check out "origin/todo" directly to examine it or +You can also check out `origin/todo` directly to examine it or write a one-off patch. See <>. Note that the name "origin" is just the name that Git uses by default @@ -386,17 +386,17 @@ Naming branches, tags, and other references Branches, remote-tracking branches, and tags are all references to commits. All references are named with a slash-separated path name -starting with "refs"; the names we've been using so far are actually +starting with `refs`; the names we've been using so far are actually shorthand: - - The branch "test" is short for "refs/heads/test". - - The tag "v2.6.18" is short for "refs/tags/v2.6.18". - - "origin/master" is short for "refs/remotes/origin/master". + - The branch `test` is short for `refs/heads/test`. + - The tag `v2.6.18` is short for `refs/tags/v2.6.18`. + - `origin/master` is short for `refs/remotes/origin/master`. The full name is occasionally useful if, for example, there ever exists a tag and a branch with the same name. -(Newly created refs are actually stored in the .git/refs directory, +(Newly created refs are actually stored in the `.git/refs` directory, under the path given by their name. However, for efficiency reasons they may also be packed together in a single file; see linkgit:git-pack-refs[1]). @@ -418,7 +418,7 @@ Eventually the developer cloned from will do additional work in her repository, creating new commits and advancing the branches to point at the new commits. -The command "git fetch", with no arguments, will update all of the +The command `git fetch`, with no arguments, will update all of the remote-tracking branches to the latest version found in her repository. It will not touch any of your own branches--not even the "master" branch that was created for you on clone. @@ -438,7 +438,7 @@ $ git fetch linux-nfs ------------------------------------------------- New remote-tracking branches will be stored under the shorthand name -that you gave "git remote add", in this case linux-nfs: +that you gave `git remote add`, in this case `linux-nfs`: ------------------------------------------------- $ git branch -r @@ -446,10 +446,10 @@ linux-nfs/master origin/master ------------------------------------------------- -If you run "git fetch " later, the remote-tracking branches for the -named will be updated. +If you run `git fetch ` later, the remote-tracking branches +for the named `` will be updated. -If you examine the file .git/config, you will see that Git has added +If you examine the file `.git/config`, you will see that Git has added a new stanza: ------------------------------------------------- @@ -462,7 +462,7 @@ $ cat .git/config ------------------------------------------------- This is what causes Git to track the remote's branches; you may modify -or delete these configuration options by editing .git/config with a +or delete these configuration options by editing `.git/config` with a text editor. (See the "CONFIGURATION FILE" section of linkgit:git-config[1] for details.) @@ -499,7 +499,7 @@ Bisecting: 3537 revisions left to test after this [65934a9a028b88e83e2b0f8b36618fe503349f8e] BLOCK: Make USB storage depend on SCSI rather than selecting it [try #6] ------------------------------------------------- -If you run "git branch" at this point, you'll see that Git has +If you run `git branch` at this point, you'll see that Git has temporarily moved you in "(no branch)". HEAD is now detached from any branch and points directly to a commit (with commit id 65934...) that is reachable from "master" but not from v2.6.18. Compile and test it, @@ -545,11 +545,11 @@ id, and check it out with: $ git reset --hard fb47ddb2db... ------------------------------------------------- -then test, run "bisect good" or "bisect bad" as appropriate, and +then test, run `bisect good` or `bisect bad` as appropriate, and continue. -Instead of "git bisect visualize" and then "git reset --hard -fb47ddb2db...", you might just want to tell Git that you want to skip +Instead of `git bisect visualize` and then `git reset --hard +fb47ddb2db...`, you might just want to tell Git that you want to skip the current commit: ------------------------------------------------- @@ -561,8 +561,8 @@ bad one between some first skipped commits and a later bad commit. There are also ways to automate the bisecting process if you have a test script that can tell a good from a bad commit. See -linkgit:git-bisect[1] for more information about this and other "git -bisect" features. +linkgit:git-bisect[1] for more information about this and other `git +bisect` features. [[naming-commits]] Naming commits @@ -591,7 +591,7 @@ $ git show HEAD~4 # the great-great-grandparent ------------------------------------------------- Recall that merge commits may have more than one parent; by default, -^ and ~ follow the first parent listed in the commit, but you can +`^` and `~` follow the first parent listed in the commit, but you can also choose: ------------------------------------------------- @@ -640,7 +640,7 @@ running $ git tag stable-1 1b2e1d63ff ------------------------------------------------- -You can use stable-1 to refer to the commit 1b2e1d63ff. +You can use `stable-1` to refer to the commit 1b2e1d63ff. This creates a "lightweight" tag. If you would also like to include a comment with the tag, and possibly sign it cryptographically, then you @@ -669,7 +669,7 @@ $ git log -S'foo()' # commits which add or remove any file data ------------------------------------------------- And of course you can combine all of these; the following finds -commits since v2.5 which touch the Makefile or any file under fs: +commits since v2.5 which touch the `Makefile` or any file under `fs`: ------------------------------------------------- $ git log v2.5.. Makefile fs/ @@ -681,7 +681,7 @@ You can also ask git log to show patches: $ git log -p ------------------------------------------------- -See the "--pretty" option in the linkgit:git-log[1] man page for more +See the `--pretty` option in the linkgit:git-log[1] man page for more display options. Note that git log starts with the most recent commit and works @@ -742,8 +742,8 @@ Examples Counting the number of commits on a branch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suppose you want to know how many commits you've made on "mybranch" -since it diverged from "origin": +Suppose you want to know how many commits you've made on `mybranch` +since it diverged from `origin`: ------------------------------------------------- $ git log --pretty=oneline origin..mybranch | wc -l @@ -780,7 +780,7 @@ $ git rev-list master e05db0fd4f31dde7005f075a84f96b360d05984b ------------------------------------------------- -Or you could recall that the ... operator selects all commits +Or you could recall that the `...` operator selects all commits contained reachable from either one reference or the other but not both; so @@ -880,7 +880,7 @@ Showing commits unique to a given branch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Suppose you would like to see all the commits reachable from the branch -head named "master" but not from any other head in your repository. +head named `master` but not from any other head in your repository. We can list all the heads in this repository with linkgit:git-show-ref[1]: @@ -894,7 +894,7 @@ a07157ac624b2524a059a3414e99f6f44bebc1e7 refs/heads/master 1e87486ae06626c2f31eaa63d26fc0fd646c8af2 refs/heads/tutorial-fixes ------------------------------------------------- -We can get just the branch-head names, and remove "master", with +We can get just the branch-head names, and remove `master`, with the help of the standard utilities cut and grep: ------------------------------------------------- @@ -939,7 +939,7 @@ is preceded by `project/`. The output file format is inferred from the output file extension if possible, see linkgit:git-archive[1] for details. -Versions of Git older than 1.7.7 don't know about the 'tar.gz' format, +Versions of Git older than 1.7.7 don't know about the `tar.gz` format, you'll need to use gzip explicitly: ------------------------------------------------- @@ -1062,7 +1062,7 @@ at step 3, Git maintains a snapshot of the tree's contents in a special staging area called "the index." At the beginning, the content of the index will be identical to -that of the HEAD. The command "git diff --cached", which shows +that of the HEAD. The command `git diff --cached`, which shows the difference between the HEAD and the index, should therefore produce no output at that point. @@ -1101,7 +1101,7 @@ $ git diff shows the difference between the working tree and the index file. -Note that "git add" always adds just the current contents of a file +Note that `git add` always adds just the current contents of a file to the index; further changes to the same file will be ignored unless you run `git add` on the file again. @@ -1172,8 +1172,9 @@ annoying to have these untracked files lying around; e.g. they make `git add .` practically useless, and they keep showing up in the output of `git status`. -You can tell Git to ignore certain files by creating a file called .gitignore -in the top level of your working directory, with contents such as: +You can tell Git to ignore certain files by creating a file called +`.gitignore` in the top level of your working directory, with contents +such as: ------------------------------------------------- # Lines starting with '#' are considered comments. @@ -1197,10 +1198,10 @@ for other users who clone your repository. If you wish the exclude patterns to affect only certain repositories (instead of every repository for a given project), you may instead put -them in a file in your repository named .git/info/exclude, or in any file -specified by the `core.excludesfile` configuration variable. Some Git -commands can also take exclude patterns directly on the command line. -See linkgit:gitignore[5] for the details. +them in a file in your repository named `.git/info/exclude`, or in any +file specified by the `core.excludesfile` configuration variable. +Some Git commands can also take exclude patterns directly on the +command line. See linkgit:gitignore[5] for the details. [[how-to-merge]] How to merge @@ -1213,10 +1214,10 @@ linkgit:git-merge[1]: $ git merge branchname ------------------------------------------------- -merges the development in the branch "branchname" into the current +merges the development in the branch `branchname` into the current branch. -A merge is made by combining the changes made in "branchname" and the +A merge is made by combining the changes made in `branchname` and the changes made up to the latest commit in your current branch since their histories forked. The work tree is overwritten by the result of the merge when this combining is done cleanly, or overwritten by a @@ -1338,7 +1339,7 @@ that part is not conflicting and is not shown. Same for stage 3). The diff above shows the differences between the working-tree version of file.txt and the stage 2 and stage 3 versions. So instead of preceding -each line by a single "+" or "-", it now uses two columns: the first +each line by a single `+` or `-`, it now uses two columns: the first column is used for differences between the first parent and the working directory copy, and the second for differences between the second parent and the working directory copy. (See the "COMBINED DIFF FORMAT" section @@ -1613,7 +1614,7 @@ dangling tree b24c2473f1fd3d91352a624795be026d64c8841f You will see informational messages on dangling objects. They are objects that still exist in the repository but are no longer referenced by any of -your branches, and can (and will) be removed after a while with "gc". +your branches, and can (and will) be removed after a while with `gc`. You can run `git fsck --no-dangling` to suppress these messages, and still view real errors. @@ -1625,9 +1626,9 @@ Recovering lost changes Reflogs ^^^^^^^ -Say you modify a branch with +linkgit:git-reset[1] \--hard+, and then -realize that the branch was the only reference you had to that point in -history. +Say you modify a branch with <>, +and then realize that the branch was the only reference you had to +that point in history. Fortunately, Git also keeps a log, called a "reflog", of all the previous values of each branch. So in this case you can still find the @@ -1638,8 +1639,8 @@ $ git log master@{1} ------------------------------------------------- This lists the commits reachable from the previous version of the -"master" branch head. This syntax can be used with any Git command -that accepts a commit, not just with git log. Some other examples: +`master` branch head. This syntax can be used with any Git command +that accepts a commit, not just with `git log`. Some other examples: ------------------------------------------------- $ git show master@{2} # See where the branch pointed 2, @@ -1743,8 +1744,8 @@ one step: $ git pull origin master ------------------------------------------------- -In fact, if you have "master" checked out, then this branch has been -configured by "git clone" to get changes from the HEAD branch of the +In fact, if you have `master` checked out, then this branch has been +configured by `git clone` to get changes from the HEAD branch of the origin repository. So often you can accomplish the above with just a simple @@ -1759,11 +1760,11 @@ the current branch. More generally, a branch that is created from a remote-tracking branch will pull by default from that branch. See the descriptions of the -branch..remote and branch..merge options in +`branch..remote` and `branch..merge` options in linkgit:git-config[1], and the discussion of the `--track` option in linkgit:git-checkout[1], to learn how to control these defaults. -In addition to saving you keystrokes, "git pull" also helps you by +In addition to saving you keystrokes, `git pull` also helps you by producing a default commit message documenting the branch and repository that you pulled from. @@ -1771,7 +1772,7 @@ repository that you pulled from. <>; instead, your branch will just be updated to point to the latest commit from the upstream branch.) -The `git pull` command can also be given "." as the "remote" repository, +The `git pull` command can also be given `.` as the "remote" repository, in which case it just merges in a branch from the current repository; so the commands @@ -1796,7 +1797,7 @@ $ git format-patch origin ------------------------------------------------- will produce a numbered series of files in the current directory, one -for each patch in the current branch but not in origin/HEAD. +for each patch in the current branch but not in `origin/HEAD`. `git format-patch` can include an initial "cover letter". You can insert commentary on individual patches after the three dash line which @@ -1818,7 +1819,7 @@ Importing patches to a project Git also provides a tool called linkgit:git-am[1] (am stands for "apply mailbox"), for importing such an emailed series of patches. Just save all of the patch-containing messages, in order, into a -single mailbox file, say "patches.mbox", then run +single mailbox file, say `patches.mbox`, then run ------------------------------------------------- $ git am -3 patches.mbox @@ -1826,7 +1827,7 @@ $ git am -3 patches.mbox Git will apply each patch in order; if any conflicts are found, it will stop, and you can fix the conflicts as described in -"<>". (The "-3" option tells +"<>". (The `-3` option tells Git to perform a merge; if you would prefer it just to abort and leave your tree and index untouched, you may omit that option.) @@ -1902,7 +1903,7 @@ We explain how to do this in the following sections. Setting up a public repository ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Assume your personal repository is in the directory ~/proj. We +Assume your personal repository is in the directory `~/proj`. We first create a new clone of the repository and tell `git daemon` that it is meant to be public: @@ -1912,10 +1913,10 @@ $ touch proj.git/git-daemon-export-ok ------------------------------------------------- The resulting directory proj.git contains a "bare" git repository--it is -just the contents of the ".git" directory, without any files checked out +just the contents of the `.git` directory, without any files checked out around it. -Next, copy proj.git to the server where you plan to host the +Next, copy `proj.git` to the server where you plan to host the public repository. You can use scp, rsync, or whatever is most convenient. @@ -1926,8 +1927,8 @@ Exporting a Git repository via the Git protocol This is the preferred method. If someone else administers the server, they should tell you what -directory to put the repository in, and what git:// URL it will appear -at. You can then skip to the section +directory to put the repository in, and what `git://` URL it will +appear at. You can then skip to the section "<>", below. @@ -1962,7 +1963,7 @@ $ mv hooks/post-update.sample hooks/post-update (For an explanation of the last two lines, see linkgit:git-update-server-info[1] and linkgit:githooks[5].) -Advertise the URL of proj.git. Anybody else should then be able to +Advertise the URL of `proj.git`. Anybody else should then be able to clone or pull from that URL, for example with a command line like: ------------------------------------------------- @@ -1985,8 +1986,8 @@ access, which you will need to update the public repository with the latest changes created in your private repository. The simplest way to do this is using linkgit:git-push[1] and ssh; to -update the remote branch named "master" with the latest state of your -branch named "master", run +update the remote branch named `master` with the latest state of your +branch named `master`, run ------------------------------------------------- $ git push ssh://yourserver.com/~you/proj.git master:master @@ -2002,7 +2003,7 @@ As with `git fetch`, `git push` will complain if this does not result in a <>; see the following section for details on handling this case. -Note that the target of a "push" is normally a +Note that the target of a `push` is normally a <> repository. You can also push to a repository that has a checked-out working tree, but a push to update the currently checked-out branch is denied by default to prevent confusion. @@ -2030,9 +2031,9 @@ which lets you do the same push with just $ git push public-repo master ------------------------------------------------- -See the explanations of the remote..url, branch..remote, -and remote..push options in linkgit:git-config[1] for -details. +See the explanations of the `remote..url`, +`branch..remote`, and `remote..push` options in +linkgit:git-config[1] for details. [[forcing-push]] What to do when a push fails @@ -2167,7 +2168,7 @@ linkgit:git-fetch[1] to keep them up-to-date; see Now create the branches in which you are going to work; these start out at the current tip of origin/master branch, and should be set up (using -the --track option to linkgit:git-branch[1]) to merge changes in from +the `--track` option to linkgit:git-branch[1]) to merge changes in from Linus by default. ------------------------------------------------- @@ -2186,7 +2187,7 @@ Important note! If you have any local changes in these branches, then this merge will create a commit object in the history (with no local changes Git will simply do a "fast-forward" merge). Many people dislike the "noise" that this creates in the Linux history, so you should avoid -doing this capriciously in the "release" branch, as these noisy commits +doing this capriciously in the `release` branch, as these noisy commits will become part of the permanent history when you ask Linus to pull from the release branch. @@ -2228,7 +2229,7 @@ patches), and create a new branch from a recent stable tag of Linus's branch. Picking a stable base for your branch will: 1) help you: by avoiding inclusion of unrelated and perhaps lightly tested changes -2) help future bug hunters that use "git bisect" to find problems +2) help future bug hunters that use `git bisect` to find problems ------------------------------------------------- $ git checkout -b speed-up-spinlocks v2.6.35 @@ -2253,9 +2254,9 @@ It is unlikely that you would have any conflicts here ... but you might if you spent a while on this step and had also pulled new versions from upstream. Some time later when enough time has passed and testing done, you can pull the -same branch into the "release" tree ready to go upstream. This is where you +same branch into the `release` tree ready to go upstream. This is where you see the value of keeping each patch (or patch series) in its own branch. It -means that the patches can be moved into the "release" tree in any order. +means that the patches can be moved into the `release` tree in any order. ------------------------------------------------- $ git checkout release && git pull . speed-up-spinlocks @@ -2288,7 +2289,7 @@ If it has been merged, then there will be no output.) Once a patch completes the great cycle (moving from test to release, then pulled by Linus, and finally coming back into your local -"origin/master" branch), the branch for this change is no longer needed. +`origin/master` branch), the branch for this change is no longer needed. You detect this when the output from: ------------------------------------------------- @@ -2303,8 +2304,8 @@ $ git branch -d branchname Some changes are so trivial that it is not necessary to create a separate branch and then merge into each of the test and release branches. For -these changes, just apply directly to the "release" branch, and then -merge that into the "test" branch. +these changes, just apply directly to the `release` branch, and then +merge that into the `test` branch. After pushing your work to `mytree`, you can use linkgit:git-request-pull[1] to prepare a "please pull" request message @@ -2337,7 +2338,7 @@ origin) fi ;; *) - echo "Usage: $0 origin|test|release" 1>&2 + echo "usage: $0 origin|test|release" 1>&2 exit 1 ;; esac @@ -2351,7 +2352,7 @@ pname=$0 usage() { - echo "Usage: $pname branch test|release" 1>&2 + echo "usage: $pname branch test|release" 1>&2 exit 1 } @@ -2475,8 +2476,8 @@ you are rewriting history. Keeping a patch series up to date using git rebase -------------------------------------------------- -Suppose that you create a branch "mywork" on a remote-tracking branch -"origin", and create some commits on top of it: +Suppose that you create a branch `mywork` on a remote-tracking branch +`origin`, and create some commits on top of it: ------------------------------------------------- $ git checkout -b mywork origin @@ -2488,7 +2489,7 @@ $ git commit ------------------------------------------------- You have performed no merges into mywork, so it is just a simple linear -sequence of patches on top of "origin": +sequence of patches on top of `origin`: ................................................ o--o--O <-- origin @@ -2497,7 +2498,7 @@ sequence of patches on top of "origin": ................................................ Some more interesting work has been done in the upstream project, and -"origin" has advanced: +`origin` has advanced: ................................................ o--o--O--o--o--o <-- origin @@ -2505,7 +2506,7 @@ Some more interesting work has been done in the upstream project, and a--b--c <-- mywork ................................................ -At this point, you could use "pull" to merge your changes back in; +At this point, you could use `pull` to merge your changes back in; the result would create a new merge commit, like this: ................................................ @@ -2524,7 +2525,7 @@ $ git rebase origin ------------------------------------------------- This will remove each of your commits from mywork, temporarily saving -them as patches (in a directory named ".git/rebase-apply"), update mywork to +them as patches (in a directory named `.git/rebase-apply`), update mywork to point at the latest version of origin, then apply each of the saved patches to the new mywork. The result will look like: @@ -2795,10 +2796,10 @@ arbitrary name: $ git fetch origin todo:my-todo-work ------------------------------------------------- -The first argument, "origin", just tells Git to fetch from the +The first argument, `origin`, just tells Git to fetch from the repository you originally cloned from. The second argument tells Git -to fetch the branch named "todo" from the remote repository, and to -store it locally under the name refs/heads/my-todo-work. +to fetch the branch named `todo` from the remote repository, and to +store it locally under the name `refs/heads/my-todo-work`. You can also fetch branches from other repositories; so @@ -2806,8 +2807,8 @@ You can also fetch branches from other repositories; so $ git fetch git://example.com/proj.git master:example-master ------------------------------------------------- -will create a new branch named "example-master" and store in it the -branch named "master" from the repository at the given URL. If you +will create a new branch named `example-master` and store in it the +branch named `master` from the repository at the given URL. If you already have a branch named example-master, it will attempt to <> to the commit given by example.com's master branch. In more detail: @@ -2816,7 +2817,7 @@ master branch. In more detail: git fetch and fast-forwards --------------------------- -In the previous example, when updating an existing branch, "git fetch" +In the previous example, when updating an existing branch, `git fetch` checks to make sure that the most recent commit on the remote branch is a descendant of the most recent commit on your copy of the branch before updating your copy of the branch to point at the new @@ -2842,11 +2843,11 @@ resulting in a situation like: o--o--o <-- new head of the branch ................................................ -In this case, "git fetch" will fail, and print out a warning. +In this case, `git fetch` will fail, and print out a warning. In that case, you can still force Git to update to the new head, as described in the following section. However, note that in the -situation above this may mean losing the commits labeled "a" and "b", +situation above this may mean losing the commits labeled `a` and `b`, unless you've already created a reference of your own pointing to them. @@ -2861,7 +2862,7 @@ descendant of the old head, you may force the update with: $ git fetch git://example.com/proj.git +master:refs/remotes/example/master ------------------------------------------------- -Note the addition of the "+" sign. Alternatively, you can use the "-f" +Note the addition of the `+` sign. Alternatively, you can use the `-f` flag to force updates of all the fetched branches, as in: ------------------------------------------------- @@ -2875,7 +2876,7 @@ may be lost, as we saw in the previous section. Configuring remote-tracking branches ------------------------------------ -We saw above that "origin" is just a shortcut to refer to the +We saw above that `origin` is just a shortcut to refer to the repository that you originally cloned from. This information is stored in Git configuration variables, which you can see using linkgit:git-config[1]: @@ -2984,7 +2985,7 @@ Commit Object ~~~~~~~~~~~~~ The "commit" object links a physical state of a tree with a description -of how we got there and why. Use the --pretty=raw option to +of how we got there and why. Use the `--pretty=raw` option to linkgit:git-show[1] or linkgit:git-log[1] to examine your favorite commit: @@ -3026,7 +3027,7 @@ of the tree referred to by this commit with the trees associated with its parents. In particular, Git does not attempt to record file renames explicitly, though it can identify cases where the existence of the same file data at changing paths suggests a rename. (See, for example, the --M option to linkgit:git-diff[1]). +`-M` option to linkgit:git-diff[1]). A commit is usually created by linkgit:git-commit[1], which creates a commit whose parent is normally the current HEAD, and whose tree is @@ -3077,7 +3078,7 @@ Blob Object ~~~~~~~~~~~ You can use linkgit:git-show[1] to examine the contents of a blob; take, -for example, the blob in the entry for "COPYING" from the tree above: +for example, the blob in the entry for `COPYING` from the tree above: ------------------------------------------------ $ git show 6ff87c4664 @@ -3160,14 +3161,14 @@ nLE/L9aUXdWeTFPron96DLA= See the linkgit:git-tag[1] command to learn how to create and verify tag objects. (Note that linkgit:git-tag[1] can also be used to create "lightweight tags", which are not tag objects at all, but just simple -references whose names begin with "refs/tags/"). +references whose names begin with `refs/tags/`). [[pack-files]] How Git stores objects efficiently: pack files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Newly created objects are initially created in a file named after the -object's SHA-1 hash (stored in .git/objects). +object's SHA-1 hash (stored in `.git/objects`). Unfortunately this system becomes inefficient once a project has a lot of objects. Try this on an old project: @@ -3208,9 +3209,9 @@ $ git prune to remove any of the "loose" objects that are now contained in the pack. This will also remove any unreferenced objects (which may be -created when, for example, you use "git reset" to remove a commit). +created when, for example, you use `git reset` to remove a commit). You can verify that the loose objects are gone by looking at the -.git/objects directory or by running +`.git/objects` directory or by running ------------------------------------------------ $ git count-objects @@ -3237,7 +3238,7 @@ branch still exists, as does everything it pointed to. The branch pointer itself just doesn't, since you replaced it with another one. There are also other situations that cause dangling objects. For -example, a "dangling blob" may arise because you did a "git add" of a +example, a "dangling blob" may arise because you did a `git add` of a file, but then, before you actually committed it and made it part of the bigger picture, you changed something else in that file and committed that *updated* thing--the old state that you added originally ends up @@ -3280,14 +3281,14 @@ $ git show ------------------------------------------------ to show what the contents of the blob were (or, for a tree, basically -what the "ls" for that directory was), and that may give you some idea +what the `ls` for that directory was), and that may give you some idea of what the operation was that left that dangling object. Usually, dangling blobs and trees aren't very interesting. They're almost always the result of either being a half-way mergebase (the blob will often even have the conflict markers from a merge in it, if you have had conflicting merges that you fixed up by hand), or simply -because you interrupted a "git fetch" with ^C or something like that, +because you interrupted a `git fetch` with ^C or something like that, leaving _some_ of the new objects in the object database, but just dangling and useless. @@ -3298,16 +3299,16 @@ state, you can just prune all unreachable objects: $ git prune ------------------------------------------------ -and they'll be gone. But you should only run "git prune" on a quiescent +and they'll be gone. But you should only run `git prune` on a quiescent repository--it's kind of like doing a filesystem fsck recovery: you don't want to do that while the filesystem is mounted. -(The same is true of "git fsck" itself, btw, but since +(The same is true of `git fsck` itself, btw, but since `git fsck` never actually *changes* the repository, it just reports on what it found, `git fsck` itself is never 'dangerous' to run. Running it while somebody is actually changing the repository can cause confusing and scary messages, but it won't actually do anything bad. In -contrast, running "git prune" while somebody is actively changing the +contrast, running `git prune` while somebody is actively changing the repository is a *BAD* idea). [[recovering-from-repository-corruption]] @@ -3345,7 +3346,7 @@ missing blob 4b9458b3786228369c63936db65827de3cc06200 Now you know that blob 4b9458b3 is missing, and that the tree 2d9263c6 points to it. If you could find just one copy of that missing blob object, possibly in some other repository, you could move it into -.git/objects/4b/9458b3... and be done. Suppose you can't. You can +`.git/objects/4b/9458b3...` and be done. Suppose you can't. You can still examine the tree that pointed to it with linkgit:git-ls-tree[1], which might output something like: @@ -3360,10 +3361,10 @@ $ git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8 ------------------------------------------------ So now you know that the missing blob was the data for a file named -"myfile". And chances are you can also identify the directory--let's -say it's in "somedirectory". If you're lucky the missing copy might be +`myfile`. And chances are you can also identify the directory--let's +say it's in `somedirectory`. If you're lucky the missing copy might be the same as the copy you have checked out in your working tree at -"somedirectory/myfile"; you can test whether that's right with +`somedirectory/myfile`; you can test whether that's right with linkgit:git-hash-object[1]: ------------------------------------------------ @@ -3418,7 +3419,7 @@ $ git hash-object -w and your repository is good again! -(Btw, you could have ignored the fsck, and started with doing a +(Btw, you could have ignored the `fsck`, and started with doing a ------------------------------------------------ $ git log --raw --all @@ -3432,7 +3433,7 @@ just missing one particular blob version. The index ----------- -The index is a binary file (generally kept in .git/index) containing a +The index is a binary file (generally kept in `.git/index`) containing a sorted list of path names, each with permissions and the SHA-1 of a blob object; linkgit:git-ls-files[1] can show you the contents of the index: @@ -3572,7 +3573,7 @@ $ ls -a The `git submodule add ` command does a couple of things: -- It clones the submodule from to the given under the +- It clones the submodule from `` to the given `` under the current directory and by default checks out the master branch. - It adds the submodule's clone path to the linkgit:gitmodules[5] file and adds this file to the index, ready to be committed. @@ -3700,11 +3701,11 @@ Unable to checkout '261dfac35cb99d380eb966e102c1197139f7fa24' in submodule path In older Git versions it could be easily forgotten to commit new or modified files in a submodule, which silently leads to similar problems as not pushing -the submodule changes. Starting with Git 1.7.0 both "git status" and "git diff" +the submodule changes. Starting with Git 1.7.0 both `git status` and `git diff` in the superproject show submodules as modified when they contain new or -modified files to protect against accidentally committing such a state. "git -diff" will also add a "-dirty" to the work tree side when generating patch -output or used with the --submodule option: +modified files to protect against accidentally committing such a state. `git +diff` will also add a `-dirty` to the work tree side when generating patch +output or used with the `--submodule` option: ------------------------------------------------- $ git diff @@ -3880,7 +3881,7 @@ or, if you want to check out all of the index, use `-a`. NOTE! `git checkout-index` normally refuses to overwrite old files, so if you have an old version of the tree already checked out, you will -need to use the "-f" flag ('before' the "-a" flag or the filename) to +need to use the `-f` flag ('before' the `-a` flag or the filename) to 'force' the checkout. @@ -3891,7 +3892,7 @@ from one representation to the other: Tying it all together ~~~~~~~~~~~~~~~~~~~~~ -To commit a tree you have instantiated with "git write-tree", you'd +To commit a tree you have instantiated with `git write-tree`, you'd create a "commit" object that refers to that tree and the history behind it--most notably the "parent" commits that preceded it in history. @@ -4152,8 +4153,9 @@ As a result, the general consistency of an object can always be tested independently of the contents or the type of the object: all objects can be validated by verifying that (a) their hashes match the content of the file and (b) the object successfully inflates to a stream of bytes that -forms a sequence of {plus} {plus} {plus} {plus} . +forms a sequence of +` + + + + + `. The structured objects can further have their structure and connectivity to other objects verified. This is generally done with @@ -4632,10 +4634,10 @@ Think about how to create a clear chapter dependency graph that will allow people to get to important topics without necessarily reading everything in between. -Scan Documentation/ for other stuff left out; in particular: +Scan `Documentation/` for other stuff left out; in particular: - howto's -- some of technical/? +- some of `technical/`? - hooks - list of commands in linkgit:git[1] diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 7952039453..6722e621d1 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.8.2-rc1 +DEF_VER=v1.8.2.GIT LF=' ' diff --git a/Makefile b/Makefile index 7c75e3b108..598d6313da 100644 --- a/Makefile +++ b/Makefile @@ -101,8 +101,6 @@ all:: # # Define NO_MKSTEMPS if you don't have mkstemps in the C library. # -# Define NO_STRTOK_R if you don't have strtok_r in the C library. -# # Define NO_FNMATCH if you don't have fnmatch in the C library. # # Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the @@ -619,22 +617,6 @@ LIB_FILE = libgit.a XDIFF_LIB = xdiff/lib.a VCSSVN_LIB = vcs-svn/lib.a -LIB_H += xdiff/xinclude.h -LIB_H += xdiff/xmacros.h -LIB_H += xdiff/xdiff.h -LIB_H += xdiff/xtypes.h -LIB_H += xdiff/xutils.h -LIB_H += xdiff/xprepare.h -LIB_H += xdiff/xdiffi.h -LIB_H += xdiff/xemit.h - -LIB_H += vcs-svn/line_buffer.h -LIB_H += vcs-svn/sliding_window.h -LIB_H += vcs-svn/repo_tree.h -LIB_H += vcs-svn/fast_export.h -LIB_H += vcs-svn/svndiff.h -LIB_H += vcs-svn/svndump.h - GENERATED_H += common-cmds.h LIB_H += advice.h @@ -736,11 +718,24 @@ LIB_H += url.h LIB_H += userdiff.h LIB_H += utf8.h LIB_H += varint.h +LIB_H += vcs-svn/fast_export.h +LIB_H += vcs-svn/line_buffer.h +LIB_H += vcs-svn/repo_tree.h +LIB_H += vcs-svn/sliding_window.h +LIB_H += vcs-svn/svndiff.h +LIB_H += vcs-svn/svndump.h LIB_H += walker.h LIB_H += wildmatch.h LIB_H += wt-status.h LIB_H += xdiff-interface.h LIB_H += xdiff/xdiff.h +LIB_H += xdiff/xdiffi.h +LIB_H += xdiff/xemit.h +LIB_H += xdiff/xinclude.h +LIB_H += xdiff/xmacros.h +LIB_H += xdiff/xprepare.h +LIB_H += xdiff/xtypes.h +LIB_H += xdiff/xutils.h LIB_OBJS += abspath.o LIB_OBJS += advice.o @@ -1249,10 +1244,6 @@ endif ifdef NO_STRTOULL COMPAT_CFLAGS += -DNO_STRTOULL endif -ifdef NO_STRTOK_R - COMPAT_CFLAGS += -DNO_STRTOK_R - COMPAT_OBJS += compat/strtok_r.o -endif ifdef NO_FNMATCH COMPAT_CFLAGS += -Icompat/fnmatch COMPAT_CFLAGS += -DNO_FNMATCH diff --git a/RelNotes b/RelNotes index bdce3136ea..80b7e388ad 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/1.8.2.txt \ No newline at end of file +Documentation/RelNotes/1.8.3.txt \ No newline at end of file diff --git a/advice.c b/advice.c index 780f58da0f..3bc86260b8 100644 --- a/advice.c +++ b/advice.c @@ -8,6 +8,7 @@ int advice_push_already_exists = 1; int advice_push_fetch_first = 1; int advice_push_needs_force = 1; int advice_status_hints = 1; +int advice_status_u_option = 1; int advice_commit_before_merge = 1; int advice_resolve_conflict = 1; int advice_implicit_identity = 1; @@ -25,6 +26,7 @@ static struct { { "pushfetchfirst", &advice_push_fetch_first }, { "pushneedsforce", &advice_push_needs_force }, { "statushints", &advice_status_hints }, + { "statusuoption", &advice_status_u_option }, { "commitbeforemerge", &advice_commit_before_merge }, { "resolveconflict", &advice_resolve_conflict }, { "implicitidentity", &advice_implicit_identity }, diff --git a/advice.h b/advice.h index fad36df467..af0c983c68 100644 --- a/advice.h +++ b/advice.h @@ -11,6 +11,7 @@ extern int advice_push_already_exists; extern int advice_push_fetch_first; extern int advice_push_needs_force; extern int advice_status_hints; +extern int advice_status_u_option; extern int advice_commit_before_merge; extern int advice_resolve_conflict; extern int advice_implicit_identity; diff --git a/archive-zip.c b/archive-zip.c index d3aef532b7..a8d119305f 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -240,7 +240,6 @@ static int write_zip_entry(struct archiver_args *args, (mode & 0111) ? ((mode) << 16) : 0; if (S_ISREG(mode) && args->compression_level != 0 && size > 0) method = 8; - compressed_size = (method == 0) ? size : 0; if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert && size > big_file_threshold) { @@ -259,6 +258,7 @@ static int write_zip_entry(struct archiver_args *args, crc = crc32(crc, buffer, size); out = buffer; } + compressed_size = (method == 0) ? size : 0; } else { return error("unsupported file mode: 0%o (SHA1: %s)", mode, sha1_to_hex(sha1)); diff --git a/archive.c b/archive.c index 93e00bb4ae..d254fa5d5c 100644 --- a/archive.c +++ b/archive.c @@ -234,7 +234,7 @@ static void parse_pathspec_arg(const char **pathspec, ar_args->pathspec = pathspec = get_pathspec("", pathspec); if (pathspec) { while (*pathspec) { - if (!path_exists(ar_args->tree, *pathspec)) + if (**pathspec && !path_exists(ar_args->tree, *pathspec)) die("path not found: %s", *pathspec); pathspec++; } diff --git a/attr.c b/attr.c index 4657cc233c..e2f9377891 100644 --- a/attr.c +++ b/attr.c @@ -255,9 +255,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, &res->u.pat.patternlen, &res->u.pat.flags, &res->u.pat.nowildcardlen); - if (res->u.pat.flags & EXC_FLAG_NEGATIVE) - die(_("Negative patterns are forbidden in git attributes\n" - "Use '\\!' for literal leading exclamation.")); + if (res->u.pat.flags & EXC_FLAG_NEGATIVE) { + warning(_("Negative patterns are ignored in git attributes\n" + "Use '\\!' for literal leading exclamation.")); + return NULL; + } } res->is_macro = is_macro; res->num_attr = num_attr; diff --git a/builtin/add.c b/builtin/add.c index 0dd014eb96..ab1c9e8fb7 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -328,9 +328,9 @@ static void warn_pathless_add(const char *option_name, const char *short_name) { * this is not the original behavior and can't be * changed until users trained themselves not to type * "git add -u" or "git add -A". For now, we warn and - * keep the old behavior. Later, this warning can be - * turned into a die(...), and eventually we may - * reallow the command with a new behavior. + * keep the old behavior. Later, the behavior can be changed + * to tree-wide, keeping the warning for a while, and + * eventually we can drop the warning. */ warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n" "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n" diff --git a/builtin/branch.c b/builtin/branch.c index 6371bf96c4..00d17d25d1 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -889,6 +889,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix) } else if (new_upstream) { struct branch *branch = branch_get(argv[0]); + if (argc > 1) + die(_("too many branches to set new upstream")); + + if (!branch) { + if (!argc || !strcmp(argv[0], "HEAD")) + die(_("could not set upstream of HEAD to %s when " + "it does not point to any branch."), + new_upstream); + die(_("no such branch '%s'"), argv[0]); + } + if (!ref_exists(branch->refname)) die(_("branch '%s' does not exist"), branch->name); @@ -901,6 +912,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix) struct branch *branch = branch_get(argv[0]); struct strbuf buf = STRBUF_INIT; + if (argc > 1) + die(_("too many branches to unset upstream")); + + if (!branch) { + if (!argc || !strcmp(argv[0], "HEAD")) + die(_("could not unset upstream of HEAD when " + "it does not point to any branch.")); + die(_("no such branch '%s'"), argv[0]); + } + if (!branch_has_merge_config(branch)) { die(_("Branch '%s' has no upstream information"), branch->name); } @@ -916,6 +937,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix) int branch_existed = 0, remote_tracking = 0; struct strbuf buf = STRBUF_INIT; + if (!strcmp(argv[0], "HEAD")) + die(_("it does not make sense to create 'HEAD' manually")); + + if (!branch) + die(_("no such branch '%s'"), argv[0]); + if (kinds != REF_LOCAL_BRANCH) die(_("-a and -r options to 'git branch' do not make sense with a branch name")); diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 00528ddc38..ad29000736 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -193,7 +193,7 @@ static int batch_one_object(const char *obj_name, int print_contents) unsigned char sha1[20]; enum object_type type = 0; unsigned long size; - void *contents = contents; + void *contents; if (!obj_name) return 1; diff --git a/builtin/commit.c b/builtin/commit.c index 3348aa14e9..d21d07a1a8 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -124,8 +124,10 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset) if (unset) strbuf_setlen(buf, 0); else { + if (buf->len) + strbuf_addch(buf, '\n'); strbuf_addstr(buf, arg); - strbuf_addstr(buf, "\n\n"); + strbuf_complete_line(buf); } return 0; } diff --git a/builtin/count-objects.c b/builtin/count-objects.c index 9afaa88f77..3a01a8d085 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -9,11 +9,22 @@ #include "builtin.h" #include "parse-options.h" +static unsigned long garbage; +static off_t size_garbage; + +static void real_report_garbage(const char *desc, const char *path) +{ + struct stat st; + if (!stat(path, &st)) + size_garbage += st.st_size; + warning("%s: %s", desc, path); + garbage++; +} + static void count_objects(DIR *d, char *path, int len, int verbose, unsigned long *loose, off_t *loose_size, - unsigned long *packed_loose, - unsigned long *garbage) + unsigned long *packed_loose) { struct dirent *ent; while ((ent = readdir(d)) != NULL) { @@ -46,9 +57,11 @@ static void count_objects(DIR *d, char *path, int len, int verbose, } if (bad) { if (verbose) { - error("garbage found: %.*s/%s", - len + 2, path, ent->d_name); - (*garbage)++; + struct strbuf sb = STRBUF_INIT; + strbuf_addf(&sb, "%.*s/%s", + len + 2, path, ent->d_name); + report_garbage("garbage found", sb.buf); + strbuf_release(&sb); } continue; } @@ -76,7 +89,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) const char *objdir = get_object_directory(); int len = strlen(objdir); char *path = xmalloc(len + 50); - unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0; + unsigned long loose = 0, packed = 0, packed_loose = 0; off_t loose_size = 0; struct option opts[] = { OPT__VERBOSE(&verbose, N_("be verbose")), @@ -87,6 +100,8 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) /* we do not take arguments other than flags for now */ if (argc) usage_with_options(count_objects_usage, opts); + if (verbose) + report_garbage = real_report_garbage; memcpy(path, objdir, len); if (len && objdir[len-1] != '/') path[len++] = '/'; @@ -97,7 +112,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) if (!d) continue; count_objects(d, path, len, verbose, - &loose, &loose_size, &packed_loose, &garbage); + &loose, &loose_size, &packed_loose); closedir(d); } if (verbose) { @@ -122,6 +137,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) printf("size-pack: %lu\n", (unsigned long) (size_pack / 1024)); printf("prune-packable: %lu\n", packed_loose); printf("garbage: %lu\n", garbage); + printf("size-garbage: %lu\n", (unsigned long) (size_garbage / 1024)); } else printf("%lu objects, %lu kilobytes\n", diff --git a/builtin/describe.c b/builtin/describe.c index 04c185b1fb..6636a68cd9 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -137,40 +137,39 @@ static void add_to_known_names(const char *path, static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data) { - int might_be_tag = !prefixcmp(path, "refs/tags/"); + int is_tag = !prefixcmp(path, "refs/tags/"); unsigned char peeled[20]; - int is_tag, prio; + int is_annotated, prio; - if (!all && !might_be_tag) + /* Reject anything outside refs/tags/ unless --all */ + if (!all && !is_tag) return 0; + /* Accept only tags that match the pattern, if given */ + if (pattern && (!is_tag || fnmatch(pattern, path + 10, 0))) + return 0; + + /* Is it annotated? */ if (!peel_ref(path, peeled)) { - is_tag = !!hashcmp(sha1, peeled); + is_annotated = !!hashcmp(sha1, peeled); } else { hashcpy(peeled, sha1); - is_tag = 0; + is_annotated = 0; } - /* If --all, then any refs are used. - * If --tags, then any tags are used. - * Otherwise only annotated tags are used. + /* + * By default, we only use annotated tags, but with --tags + * we fall back to lightweight ones (even without --tags, + * we still remember lightweight ones, only to give hints + * in an error message). --all allows any refs to be used. */ - if (might_be_tag) { - if (is_tag) - prio = 2; - else - prio = 1; - - if (pattern && fnmatch(pattern, path + 10, 0)) - prio = 0; - } + if (is_annotated) + prio = 2; + else if (is_tag) + prio = 1; else prio = 0; - if (!all) { - if (!prio) - return 0; - } add_to_known_names(all ? path + 5 : path + 10, peeled, prio, sha1); return 0; } @@ -402,8 +401,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix) struct option options[] = { OPT_BOOLEAN(0, "contains", &contains, N_("find the tag that comes after the commit")), OPT_BOOLEAN(0, "debug", &debug, N_("debug search strategy on stderr")), - OPT_BOOLEAN(0, "all", &all, N_("use any ref in .git/refs")), - OPT_BOOLEAN(0, "tags", &tags, N_("use any tag in .git/refs/tags")), + OPT_BOOLEAN(0, "all", &all, N_("use any ref")), + OPT_BOOLEAN(0, "tags", &tags, N_("use any tag, even unannotated")), OPT_BOOLEAN(0, "long", &longformat, N_("always use long format")), OPT__ABBREV(&abbrev), OPT_SET_INT(0, "exact-match", &max_candidates, diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 940ae35dc2..670e81fd99 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -7,12 +7,31 @@ static const char fetch_pack_usage[] = "[--include-tag] [--upload-pack=] [--depth=] " "[--no-progress] [-v] [:] [...]"; +static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc, + const char *name, int namelen) +{ + struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1); + + memcpy(ref->name, name, namelen); + ref->name[namelen] = '\0'; + (*nr)++; + ALLOC_GROW(*sought, *nr, *alloc); + (*sought)[*nr - 1] = ref; +} + +static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, + const char *string) +{ + add_sought_entry_mem(sought, nr, alloc, string, strlen(string)); +} + int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret; struct ref *ref = NULL; const char *dest = NULL; - struct string_list sought = STRING_LIST_INIT_DUP; + struct ref **sought = NULL; + int nr_sought = 0, alloc_sought = 0; int fd[2]; char *pack_lockfile = NULL; char **pack_lockfile_ptr = NULL; @@ -94,7 +113,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) * refs from the standard input: */ for (; i < argc; i++) - string_list_append(&sought, xstrdup(argv[i])); + add_sought_entry(&sought, &nr_sought, &alloc_sought, argv[i]); if (args.stdin_refs) { if (args.stateless_rpc) { /* in stateless RPC mode we use pkt-line to read @@ -107,14 +126,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) break; if (line[n-1] == '\n') n--; - string_list_append(&sought, xmemdupz(line, n)); + add_sought_entry_mem(&sought, &nr_sought, &alloc_sought, line, n); } } else { /* read from stdin one ref per line, until EOF */ struct strbuf line = STRBUF_INIT; while (strbuf_getline(&line, stdin, '\n') != EOF) - string_list_append(&sought, strbuf_detach(&line, NULL)); + add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf); strbuf_release(&line); } } @@ -131,7 +150,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) get_remote_heads(fd[0], &ref, 0, NULL); ref = fetch_pack(&args, fd, conn, ref, dest, - &sought, pack_lockfile_ptr); + sought, nr_sought, pack_lockfile_ptr); if (pack_lockfile) { printf("lock %s\n", pack_lockfile); fflush(stdout); @@ -141,7 +160,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) if (finish_connect(conn)) return 1; - ret = !ref || sought.nr; + ret = !ref; /* * If the heads to pull were given, we should have consumed @@ -149,8 +168,13 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) * remote no-such-ref' would silently succeed without issuing * an error. */ - for (i = 0; i < sought.nr; i++) - error("no such remote ref %s", sought.items[i].string); + for (i = 0; i < nr_sought; i++) { + if (!sought[i] || sought[i]->matched) + continue; + error("no such remote ref %s", sought[i]->name); + ret = 1; + } + while (ref) { printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index b49612f0ce..265a9253bf 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -492,7 +492,7 @@ static void fmt_merge_msg_sigs(struct strbuf *out) if (size == len) ; /* merely annotated */ - else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig)) { + else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig, NULL)) { if (!sig.len) strbuf_addstr(&sig, "gpg verification failed.\n"); } diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 43d364b8d5..ef62124aa4 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1099,7 +1099,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha if (fix_thin_pack) { struct sha1file *f; unsigned char read_sha1[20], tail_sha1[20]; - char msg[48]; + struct strbuf msg = STRBUF_INIT; int nr_unresolved = nr_deltas - nr_resolved_deltas; int nr_objects_initial = nr_objects; if (nr_unresolved <= 0) @@ -1109,9 +1109,10 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha * sizeof(*objects)); f = sha1fd(output_fd, curr_pack); fix_unresolved_deltas(f, nr_unresolved); - sprintf(msg, _("completed with %d local objects"), - nr_objects - nr_objects_initial); - stop_progress_msg(&progress, msg); + strbuf_addf(&msg, _("completed with %d local objects"), + nr_objects - nr_objects_initial); + stop_progress_msg(&progress, msg.buf); + strbuf_release(&msg); sha1close(f, tail_sha1, 0); hashcpy(read_sha1, pack_sha1); fixup_pack_header_footer(output_fd, pack_sha1, diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c index 2d4327801e..06296d4bdf 100644 --- a/builtin/mailsplit.c +++ b/builtin/mailsplit.c @@ -130,6 +130,27 @@ static int populate_maildir_list(struct string_list *list, const char *path) return 0; } +static int maildir_filename_cmp(const char *a, const char *b) +{ + while (*a && *b) { + if (isdigit(*a) && isdigit(*b)) { + long int na, nb; + na = strtol(a, (char **)&a, 10); + nb = strtol(b, (char **)&b, 10); + if (na != nb) + return na - nb; + /* strtol advanced our pointers */ + } + else { + if (*a != *b) + return (unsigned char)*a - (unsigned char)*b; + a++; + b++; + } + } + return (unsigned char)*a - (unsigned char)*b; +} + static int split_maildir(const char *maildir, const char *dir, int nr_prec, int skip) { @@ -139,6 +160,8 @@ static int split_maildir(const char *maildir, const char *dir, int i; struct string_list list = STRING_LIST_INIT_DUP; + list.cmp = maildir_filename_cmp; + if (populate_maildir_list(&list, maildir) < 0) goto out; diff --git a/builtin/push.c b/builtin/push.c index 42b129d36c..5e4a0e958f 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -437,6 +437,8 @@ int cmd_push(int argc, const char **argv, const char *prefix) OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"), TRANSPORT_PUSH_PRUNE), OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK), + OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"), + TRANSPORT_PUSH_FOLLOW_TAGS), OPT_END() }; diff --git a/builtin/reflog.c b/builtin/reflog.c index 1fedf66329..72a0af70c3 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -414,7 +414,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused, if (cb.unreachable_expire_kind == UE_HEAD) { struct commit_list *elem; for (elem = tips; elem; elem = elem->next) - clear_commit_marks(tip_commit, REACHABLE); + clear_commit_marks(elem->item, REACHABLE); free_commit_list(tips); } else { clear_commit_marks(tip_commit, REACHABLE); diff --git a/builtin/update-index.c b/builtin/update-index.c index ada1dff846..5c7762eef4 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -796,7 +796,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) }; if (argc == 2 && !strcmp(argv[1], "-h")) - usage(update_index_usage[0]); + usage_with_options(update_index_usage, options); git_config(git_default_config, NULL); diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index a8eee886a5..9cdf332333 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -29,7 +29,7 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose) if (size == len) return error("no signature found"); - return verify_signed_buffer(buf, len, buf + len, size - len, NULL); + return verify_signed_buffer(buf, len, buf + len, size - len, NULL, NULL); } static int verify_tag(const char *name, int verbose) diff --git a/bundle.c b/bundle.c index 8d12816b9d..6210a6be89 100644 --- a/bundle.c +++ b/bundle.c @@ -183,17 +183,17 @@ int verify_bundle(struct bundle_header *header, int verbose) struct ref_list *r; r = &header->references; - printf_ln(Q_("The bundle contains %d ref", - "The bundle contains %d refs", + printf_ln(Q_("The bundle contains this ref:", + "The bundle contains these %d refs:", r->nr), r->nr); list_refs(r, 0, NULL); + r = &header->prerequisites; if (!r->nr) { printf_ln(_("The bundle records a complete history.")); } else { - r = &header->prerequisites; - printf_ln(Q_("The bundle requires this ref", - "The bundle requires these %d refs", + printf_ln(Q_("The bundle requires this ref:", + "The bundle requires these %d refs:", r->nr), r->nr); list_refs(r, 0, NULL); diff --git a/cache.h b/cache.h index e493563f4c..fc5c5b5733 100644 --- a/cache.h +++ b/cache.h @@ -341,9 +341,11 @@ static inline enum object_type object_type(unsigned int mode) OBJ_BLOB; } +/* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR" #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE" #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE" +#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX" #define DEFAULT_GIT_DIR_ENVIRONMENT ".git" #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" #define INDEX_ENVIRONMENT "GIT_INDEX_FILE" @@ -365,13 +367,24 @@ static inline enum object_type object_type(unsigned int mode) #define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS" /* - * Repository-local GIT_* environment variables - * The array is NULL-terminated to simplify its usage in contexts such - * environment creation or simple walk of the list. - * The number of non-NULL entries is available as a macro. + * This environment variable is expected to contain a boolean indicating + * whether we should or should not treat: + * + * GIT_DIR=foo.git git ... + * + * as if GIT_WORK_TREE=. was given. It's not expected that users will make use + * of this, but we use it internally to communicate to sub-processes that we + * are in a bare repo. If not set, defaults to true. + */ +#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE" + +/* + * Repository-local GIT_* environment variables; these will be cleared + * when git spawns a sub-process that runs inside another repository. + * The array is NULL-terminated, which makes it easy to pass in the "env" + * parameter of a run-command invocation, or to do a simple walk. */ -#define LOCAL_REPO_ENV_SIZE 9 -extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1]; +extern const char * const local_repo_env[]; extern int is_bare_repository_cfg; extern int is_bare_repository(void); @@ -1017,7 +1030,8 @@ struct ref { force:1, forced_update:1, merge:1, - deletion:1; + deletion:1, + matched:1; enum { REF_STATUS_NONE = 0, REF_STATUS_OK, @@ -1057,6 +1071,9 @@ extern const char *parse_feature_value(const char *feature_list, const char *fea extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path); +/* A hook for count-objects to report invalid files in pack directory */ +extern void (*report_garbage)(const char *desc, const char *path); + extern void prepare_packed_git(void); extern void reprepare_packed_git(void); extern void install_packed_git(struct packed_git *pack); diff --git a/commit.c b/commit.c index e8eb0aec55..b4512ab0b2 100644 --- a/commit.c +++ b/commit.c @@ -463,14 +463,23 @@ static void clear_commit_marks_1(struct commit_list **plist, } } -void clear_commit_marks(struct commit *commit, unsigned int mark) +void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark) { struct commit_list *list = NULL; - commit_list_insert(commit, &list); + + while (nr--) { + commit_list_insert(*commit, &list); + commit++; + } while (list) clear_commit_marks_1(&list, pop_commit(&list), mark); } +void clear_commit_marks(struct commit *commit, unsigned int mark) +{ + clear_commit_marks_many(1, &commit, mark); +} + void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark) { struct object *object; @@ -797,8 +806,7 @@ struct commit_list *get_merge_bases_many(struct commit *one, if (!result || !result->next) { if (cleanup) { clear_commit_marks(one, all_flags); - for (i = 0; i < n; i++) - clear_commit_marks(twos[i], all_flags); + clear_commit_marks_many(n, twos, all_flags); } return result; } @@ -816,8 +824,7 @@ struct commit_list *get_merge_bases_many(struct commit *one, free_commit_list(result); clear_commit_marks(one, all_flags); - for (i = 0; i < n; i++) - clear_commit_marks(twos[i], all_flags); + clear_commit_marks_many(n, twos, all_flags); cnt = remove_redundant(rslt, cnt); result = NULL; @@ -852,25 +859,36 @@ int is_descendant_of(struct commit *commit, struct commit_list *with_commit) } /* - * Is "commit" an ancestor of (i.e. reachable from) the "reference"? + * Is "commit" an ancestor of one of the "references"? */ -int in_merge_bases(struct commit *commit, struct commit *reference) +int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference) { struct commit_list *bases; - int ret = 0; + int ret = 0, i; - if (parse_commit(commit) || parse_commit(reference)) + if (parse_commit(commit)) return ret; + for (i = 0; i < nr_reference; i++) + if (parse_commit(reference[i])) + return ret; - bases = paint_down_to_common(commit, 1, &reference); + bases = paint_down_to_common(commit, nr_reference, reference); if (commit->object.flags & PARENT2) ret = 1; clear_commit_marks(commit, all_flags); - clear_commit_marks(reference, all_flags); + clear_commit_marks_many(nr_reference, reference, all_flags); free_commit_list(bases); return ret; } +/* + * Is "commit" an ancestor of (i.e. reachable from) the "reference"? + */ +int in_merge_bases(struct commit *commit, struct commit *reference) +{ + return in_merge_bases_many(commit, 1, &reference); +} + struct commit_list *reduce_heads(struct commit_list *heads) { struct commit_list *p; diff --git a/commit.h b/commit.h index 4138bb4c08..2d90d9c27c 100644 --- a/commit.h +++ b/commit.h @@ -137,6 +137,7 @@ struct commit *pop_most_recent_commit(struct commit_list **list, struct commit *pop_commit(struct commit_list **stack); void clear_commit_marks(struct commit *commit, unsigned int mark); +void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark); void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark); /* @@ -176,6 +177,7 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads, int is_descendant_of(struct commit *, struct commit_list *); int in_merge_bases(struct commit *, struct commit *); +int in_merge_bases_many(struct commit *, int, struct commit **); extern int interactive_add(int argc, const char **argv, const char *prefix, int patch); extern int run_add_interactive(const char *revision, const char *patch_mode, diff --git a/compat/msvc.h b/compat/msvc.h index aa4b56315a..96b6d605da 100644 --- a/compat/msvc.h +++ b/compat/msvc.h @@ -12,6 +12,8 @@ #define __attribute__(x) #define strncasecmp _strnicmp #define ftruncate _chsize +#define strtoull _strtoui64 +#define strtoll _strtoi64 static __inline int strcasecmp (const char *s1, const char *s2) { diff --git a/compat/strtok_r.c b/compat/strtok_r.c deleted file mode 100644 index 7b5d568a96..0000000000 --- a/compat/strtok_r.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Reentrant string tokenizer. Generic version. - Copyright (C) 1991,1996-1999,2001,2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include "../git-compat-util.h" - -/* Parse S into tokens separated by characters in DELIM. - If S is NULL, the saved pointer in SAVE_PTR is used as - the next starting point. For example: - char s[] = "-abc-=-def"; - char *sp; - x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" - x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL - x = strtok_r(NULL, "=", &sp); // x = NULL - // s = "abc\0-def\0" -*/ -char * -gitstrtok_r (char *s, const char *delim, char **save_ptr) -{ - char *token; - - if (s == NULL) - s = *save_ptr; - - /* Scan leading delimiters. */ - s += strspn (s, delim); - if (*s == '\0') - { - *save_ptr = s; - return NULL; - } - - /* Find the end of the token. */ - token = s; - s = strpbrk (token, delim); - if (s == NULL) - /* This token finishes the string. */ - *save_ptr = token + strlen (token); - else - { - /* Terminate the token and make *SAVE_PTR point past it. */ - *s = '\0'; - *save_ptr = s + 1; - } - return token; -} diff --git a/compat/vcbuild/include/sys/poll.h b/compat/vcbuild/include/sys/poll.h deleted file mode 100644 index 0d8552a2c6..0000000000 --- a/compat/vcbuild/include/sys/poll.h +++ /dev/null @@ -1 +0,0 @@ -/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/unistd.h b/compat/vcbuild/include/unistd.h index b14fcf94da..c65c2cd566 100644 --- a/compat/vcbuild/include/unistd.h +++ b/compat/vcbuild/include/unistd.h @@ -49,6 +49,9 @@ typedef int64_t off64_t; #define INTMAX_MAX _I64_MAX #define UINTMAX_MAX _UI64_MAX +#define UINT32_MAX 0xffffffff /* 4294967295U */ + +#define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 diff --git a/config.mak.uname b/config.mak.uname index 8743a6d0af..9080054f76 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -321,13 +321,11 @@ ifeq ($(uname_S),Windows) NO_UNSETENV = YesPlease NO_STRCASESTR = YesPlease NO_STRLCPY = YesPlease - NO_STRTOK_R = YesPlease NO_FNMATCH = YesPlease NO_MEMMEM = YesPlease # NEEDS_LIBICONV = YesPlease NO_ICONV = YesPlease NO_STRTOUMAX = YesPlease - NO_STRTOULL = YesPlease NO_MKDTEMP = YesPlease NO_MKSTEMPS = YesPlease SNPRINTF_RETURNS_BOGUS = YesPlease @@ -344,6 +342,9 @@ ifeq ($(uname_S),Windows) NO_CURL = YesPlease NO_PYTHON = YesPlease BLK_SHA1 = YesPlease + ETAGS_TARGET = ETAGS + NO_INET_PTON = YesPlease + NO_INET_NTOP = YesPlease NO_POSIX_GOODIES = UnfortunatelyYes NATIVE_CRLF = YesPlease DEFAULT_HELP_FORMAT = html @@ -476,7 +477,6 @@ ifneq (,$(findstring MINGW,$(uname_S))) NO_UNSETENV = YesPlease NO_STRCASESTR = YesPlease NO_STRLCPY = YesPlease - NO_STRTOK_R = YesPlease NO_FNMATCH = YesPlease NO_MEMMEM = YesPlease NEEDS_LIBICONV = YesPlease diff --git a/configure.ac b/configure.ac index 1991258ae0..f3462d9c81 100644 --- a/configure.ac +++ b/configure.ac @@ -901,12 +901,6 @@ GIT_CHECK_FUNC(strcasestr, [NO_STRCASESTR=YesPlease]) GIT_CONF_SUBST([NO_STRCASESTR]) # -# Define NO_STRTOK_R if you don't have strtok_r -GIT_CHECK_FUNC(strtok_r, -[NO_STRTOK_R=], -[NO_STRTOK_R=YesPlease]) -GIT_CONF_SUBST([NO_STRTOK_R]) -# # Define NO_FNMATCH if you don't have fnmatch GIT_CHECK_FUNC(fnmatch, [NO_FNMATCH=], diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index b62bec0279..2ba1461422 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -299,9 +299,12 @@ __git_index_file_list_filter () # the second argument. __git_ls_files_helper () { - # NOTE: $2 is not quoted in order to support multiple options - cd "$1" && git ls-files --exclude-standard $2 -} 2>/dev/null + ( + test -n "${CDPATH+set}" && unset CDPATH + # NOTE: $2 is not quoted in order to support multiple options + cd "$1" && git ls-files --exclude-standard $2 + ) 2>/dev/null +} # Execute git diff-index, returning paths relative to the directory @@ -309,8 +312,11 @@ __git_ls_files_helper () # specified in the second argument. __git_diff_index_helper () { - cd "$1" && git diff-index --name-only --relative "$2" -} 2>/dev/null + ( + test -n "${CDPATH+set}" && unset CDPATH + cd "$1" && git diff-index --name-only --relative "$2" + ) 2>/dev/null +} # __git_index_files accepts 1 or 2 arguments: # 1: Options to pass to ls-files (required). @@ -2413,7 +2419,7 @@ _git_submodule () { __git_has_doubledash && return - local subcommands="add status init update summary foreach sync" + local subcommands="add status init deinit update summary foreach sync" if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then case "$cur" in --*) diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh index 45775021ff..cf8116d477 100644 --- a/contrib/completion/git-completion.zsh +++ b/contrib/completion/git-completion.zsh @@ -60,6 +60,15 @@ __gitcomp_nl () compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0 } +__gitcomp_file () +{ + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -p "${2-}" -f -- ${=1} && _ret=0 +} + _git () { local _ret=1 diff --git a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c index 41f61c5db3..f2cdefee60 100644 --- a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c +++ b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c @@ -401,7 +401,7 @@ static void usage(const char *name) const char *basename = strrchr(name,'/'); basename = (basename) ? basename + 1 : name; - fprintf(stderr, "Usage: %s <", basename); + fprintf(stderr, "usage: %s <", basename); while(try_op->name) { fprintf(stderr,"%s",(try_op++)->name); if(try_op->name) diff --git a/contrib/credential/netrc/Makefile b/contrib/credential/netrc/Makefile new file mode 100644 index 0000000000..51b76138a5 --- /dev/null +++ b/contrib/credential/netrc/Makefile @@ -0,0 +1,5 @@ +test: + ./test.pl + +testverbose: + ./test.pl -d -v diff --git a/contrib/credential/netrc/git-credential-netrc b/contrib/credential/netrc/git-credential-netrc new file mode 100755 index 0000000000..6c51c43885 --- /dev/null +++ b/contrib/credential/netrc/git-credential-netrc @@ -0,0 +1,421 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Getopt::Long; +use File::Basename; + +my $VERSION = "0.1"; + +my %options = ( + help => 0, + debug => 0, + verbose => 0, + insecure => 0, + file => [], + + # identical token maps, e.g. host -> host, will be inserted later + tmap => { + port => 'protocol', + machine => 'host', + path => 'path', + login => 'username', + user => 'username', + password => 'password', + } + ); + +# Map each credential protocol token to itself on the netrc side. +foreach (values %{$options{tmap}}) { + $options{tmap}->{$_} = $_; +} + +# Now, $options{tmap} has a mapping from the netrc format to the Git credential +# helper protocol. + +# Next, we build the reverse token map. + +# When $rmap{foo} contains 'bar', that means that what the Git credential helper +# protocol calls 'bar' is found as 'foo' in the netrc/authinfo file. Keys in +# %rmap are what we expect to read from the netrc/authinfo file. + +my %rmap; +foreach my $k (keys %{$options{tmap}}) { + push @{$rmap{$options{tmap}->{$k}}}, $k; +} + +Getopt::Long::Configure("bundling"); + +# TODO: maybe allow the token map $options{tmap} to be configurable. +GetOptions(\%options, + "help|h", + "debug|d", + "insecure|k", + "verbose|v", + "file|f=s@", + ); + +if ($options{help}) { + my $shortname = basename($0); + $shortname =~ s/git-credential-//; + + print <{machine}) { + next; + } + if (defined $nentry->{port} && $nentry->{port} =~ m/^\d+$/) { + $num_port = $nentry->{port}; + delete $nentry->{port}; + } + + # create the new entry for the credential helper protocol + $entry{$options{tmap}->{$_}} = $nentry->{$_} foreach keys %$nentry; + + # for "host X port Y" where Y is an integer (captured by + # $num_port above), set the host to "X:Y" + if (defined $entry{host} && defined $num_port) { + $entry{host} = join(':', $entry{host}, $num_port); + } + + push @entries, \%entry; + } + + return @entries; +} + +sub net_netrc_loader { + my $fh = shift @_; + my @entries; + my ($mach, $macdef, $tok, @tok); + + LINE: + while (<$fh>) { + undef $macdef if /\A\n\Z/; + + if ($macdef) { + next LINE; + } + + s/^\s*//; + chomp; + + while (length && s/^("((?:[^"]+|\\.)*)"|((?:[^\\\s]+|\\.)*))\s*//) { + (my $tok = $+) =~ s/\\(.)/$1/g; + push(@tok, $tok); + } + + TOKEN: + while (@tok) { + if ($tok[0] eq "default") { + shift(@tok); + $mach = { machine => undef }; + next TOKEN; + } + + $tok = shift(@tok); + + if ($tok eq "machine") { + my $host = shift @tok; + $mach = { machine => $host }; + push @entries, $mach; + } elsif (exists $options{tmap}->{$tok}) { + unless ($mach) { + log_debug("Skipping token $tok because no machine was given"); + next TOKEN; + } + + my $value = shift @tok; + unless (defined $value) { + log_debug("Token $tok had no value, skipping it."); + next TOKEN; + } + + # Following line added by rmerrell to remove '/' escape char in .netrc + $value =~ s/\/\\/\\/g; + $mach->{$tok} = $value; + } elsif ($tok eq "macdef") { # we ignore macros + next TOKEN unless $mach; + my $value = shift @tok; + $macdef = 1; + } + } + } + + return @entries; +} + +sub read_credential_data_from_stdin { + # the query: start with every token with no value + my %q = map { $_ => undef } values(%{$options{tmap}}); + + while () { + next unless m/^([^=]+)=(.+)/; + + my ($token, $value) = ($1, $2); + die "Unknown search token $token" unless exists $q{$token}; + $q{$token} = $value; + log_debug("We were given search token $token and value $value"); + } + + foreach (sort keys %q) { + log_debug("Searching for %s = %s", $_, $q{$_} || '(any value)'); + } + + return \%q; +} + +# takes the search tokens and then a list of entries +# each entry is a hash reference +sub find_netrc_entry { + my $query = shift @_; + + ENTRY: + foreach my $entry (@_) + { + my $entry_text = join ', ', map { "$_=$entry->{$_}" } keys %$entry; + foreach my $check (sort keys %$query) { + if (defined $query->{$check}) { + log_debug("compare %s [%s] to [%s] (entry: %s)", + $check, + $entry->{$check}, + $query->{$check}, + $entry_text); + unless ($query->{$check} eq $entry->{$check}) { + next ENTRY; + } + } else { + log_debug("OK: any value satisfies check $check"); + } + } + + return $entry; + } + + # nothing was found + return; +} + +sub print_credential_data { + my $entry = shift @_; + my $query = shift @_; + + log_debug("entry has passed all the search checks"); + TOKEN: + foreach my $git_token (sort keys %$entry) { + log_debug("looking for useful token $git_token"); + # don't print unknown (to the credential helper protocol) tokens + next TOKEN unless exists $query->{$git_token}; + + # don't print things asked in the query (the entry matches them) + next TOKEN if defined $query->{$git_token}; + + log_debug("FOUND: $git_token=$entry->{$git_token}"); + printf "%s=%s\n", $git_token, $entry->{$git_token}; + } +} +sub log_verbose { + return unless $options{verbose}; + printf STDERR @_; + printf STDERR "\n"; +} + +sub log_debug { + return unless $options{debug}; + printf STDERR @_; + printf STDERR "\n"; +} diff --git a/contrib/credential/netrc/test.netrc b/contrib/credential/netrc/test.netrc new file mode 100644 index 0000000000..ba119a937f --- /dev/null +++ b/contrib/credential/netrc/test.netrc @@ -0,0 +1,13 @@ +machine imap login tzz@lifelogs.com port imaps password letmeknow +machine imap login bob port imaps password bobwillknow + +# comment test + +machine imap2 login tzz port 1099 password tzzknow +machine imap2 login bob password bobwillknow + +# another command + +machine github.com + multilinetoken anothervalue + login carol password carolknows diff --git a/contrib/credential/netrc/test.pl b/contrib/credential/netrc/test.pl new file mode 100755 index 0000000000..169b6463c3 --- /dev/null +++ b/contrib/credential/netrc/test.pl @@ -0,0 +1,106 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use Test; +use IPC::Open2; + +BEGIN { plan tests => 15 } + +my @global_credential_args = @ARGV; +my $netrc = './test.netrc'; +print "# Testing insecure file, nothing should be found\n"; +chmod 0644, $netrc; +my $cred = run_credential(['-f', $netrc, 'get'], + { host => 'github.com' }); + +ok(scalar keys %$cred, 0, "Got 0 keys from insecure file"); + +print "# Testing missing file, nothing should be found\n"; +chmod 0644, $netrc; +$cred = run_credential(['-f', '///nosuchfile///', 'get'], + { host => 'github.com' }); + +ok(scalar keys %$cred, 0, "Got 0 keys from missing file"); + +chmod 0600, $netrc; + +print "# Testing with invalid data\n"; +$cred = run_credential(['-f', $netrc, 'get'], + "bad data"); +ok(scalar keys %$cred, 4, "Got first found keys with bad data"); + +print "# Testing netrc file for a missing corovamilkbar entry\n"; +$cred = run_credential(['-f', $netrc, 'get'], + { host => 'corovamilkbar' }); + +ok(scalar keys %$cred, 0, "Got no corovamilkbar keys"); + +print "# Testing netrc file for a github.com entry\n"; +$cred = run_credential(['-f', $netrc, 'get'], + { host => 'github.com' }); + +ok(scalar keys %$cred, 2, "Got 2 Github keys"); + +ok($cred->{password}, 'carolknows', "Got correct Github password"); +ok($cred->{username}, 'carol', "Got correct Github username"); + +print "# Testing netrc file for a username-specific entry\n"; +$cred = run_credential(['-f', $netrc, 'get'], + { host => 'imap', username => 'bob' }); + +ok(scalar keys %$cred, 2, "Got 2 username-specific keys"); + +ok($cred->{password}, 'bobwillknow', "Got correct user-specific password"); +ok($cred->{protocol}, 'imaps', "Got correct user-specific protocol"); + +print "# Testing netrc file for a host:port-specific entry\n"; +$cred = run_credential(['-f', $netrc, 'get'], + { host => 'imap2:1099' }); + +ok(scalar keys %$cred, 2, "Got 2 host:port-specific keys"); + +ok($cred->{password}, 'tzzknow', "Got correct host:port-specific password"); +ok($cred->{username}, 'tzz', "Got correct host:port-specific username"); + +print "# Testing netrc file that 'host:port kills host' entry\n"; +$cred = run_credential(['-f', $netrc, 'get'], + { host => 'imap2' }); + +ok(scalar keys %$cred, 2, "Got 2 'host:port kills host' keys"); + +ok($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password"); +ok($cred->{username}, 'bob', "Got correct 'host:port kills host' username"); + +sub run_credential +{ + my $args = shift @_; + my $data = shift @_; + my $pid = open2(my $chld_out, my $chld_in, + './git-credential-netrc', @global_credential_args, + @$args); + + die "Couldn't open pipe to netrc credential helper: $!" unless $pid; + + if (ref $data eq 'HASH') + { + print $chld_in "$_=$data->{$_}\n" foreach sort keys %$data; + } + else + { + print $chld_in "$data\n"; + } + + close $chld_in; + my %ret; + + while (<$chld_out>) + { + chomp; + next unless m/^([^=]+)=(.+)/; + + $ret{$1} = $2; + } + + return \%ret; +} diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c index 6beed123ab..3940202b36 100644 --- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c +++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c @@ -154,7 +154,7 @@ static void read_credential(void) int main(int argc, const char **argv) { const char *usage = - "Usage: git credential-osxkeychain "; + "usage: git credential-osxkeychain "; if (!argv[1]) die(usage); diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c index cbaec5f24b..a1d38f035b 100644 --- a/contrib/credential/wincred/git-credential-wincred.c +++ b/contrib/credential/wincred/git-credential-wincred.c @@ -9,6 +9,8 @@ /* common helpers */ +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + static void die(const char *err, ...) { char msg[4096]; @@ -30,14 +32,6 @@ static void *xmalloc(size_t size) return ret; } -static char *xstrdup(const char *str) -{ - char *ret = strdup(str); - if (!ret) - die("Out of memory"); - return ret; -} - /* MinGW doesn't have wincred.h, so we need to define stuff */ typedef struct _CREDENTIAL_ATTRIBUTEW { @@ -67,20 +61,14 @@ typedef struct _CREDENTIALW { #define CRED_MAX_ATTRIBUTES 64 typedef BOOL (WINAPI *CredWriteWT)(PCREDENTIALW, DWORD); -typedef BOOL (WINAPI *CredUnPackAuthenticationBufferWT)(DWORD, PVOID, DWORD, - LPWSTR, DWORD *, LPWSTR, DWORD *, LPWSTR, DWORD *); typedef BOOL (WINAPI *CredEnumerateWT)(LPCWSTR, DWORD, DWORD *, PCREDENTIALW **); -typedef BOOL (WINAPI *CredPackAuthenticationBufferWT)(DWORD, LPWSTR, LPWSTR, - PBYTE, DWORD *); typedef VOID (WINAPI *CredFreeT)(PVOID); typedef BOOL (WINAPI *CredDeleteWT)(LPCWSTR, DWORD, DWORD); -static HMODULE advapi, credui; +static HMODULE advapi; static CredWriteWT CredWriteW; -static CredUnPackAuthenticationBufferWT CredUnPackAuthenticationBufferW; static CredEnumerateWT CredEnumerateW; -static CredPackAuthenticationBufferWT CredPackAuthenticationBufferW; static CredFreeT CredFree; static CredDeleteWT CredDeleteW; @@ -88,74 +76,84 @@ static void load_cred_funcs(void) { /* load DLLs */ advapi = LoadLibrary("advapi32.dll"); - credui = LoadLibrary("credui.dll"); - if (!advapi || !credui) - die("failed to load DLLs"); + if (!advapi) + die("failed to load advapi32.dll"); /* get function pointers */ CredWriteW = (CredWriteWT)GetProcAddress(advapi, "CredWriteW"); - CredUnPackAuthenticationBufferW = (CredUnPackAuthenticationBufferWT) - GetProcAddress(credui, "CredUnPackAuthenticationBufferW"); CredEnumerateW = (CredEnumerateWT)GetProcAddress(advapi, "CredEnumerateW"); - CredPackAuthenticationBufferW = (CredPackAuthenticationBufferWT) - GetProcAddress(credui, "CredPackAuthenticationBufferW"); CredFree = (CredFreeT)GetProcAddress(advapi, "CredFree"); CredDeleteW = (CredDeleteWT)GetProcAddress(advapi, "CredDeleteW"); - if (!CredWriteW || !CredUnPackAuthenticationBufferW || - !CredEnumerateW || !CredPackAuthenticationBufferW || !CredFree || - !CredDeleteW) + if (!CredWriteW || !CredEnumerateW || !CredFree || !CredDeleteW) die("failed to load functions"); } -static char target_buf[1024]; -static char *protocol, *host, *path, *username; -static WCHAR *wusername, *password, *target; +static WCHAR *wusername, *password, *protocol, *host, *path, target[1024]; -static void write_item(const char *what, WCHAR *wbuf) +static void write_item(const char *what, LPCWSTR wbuf, int wlen) { char *buf; - int len = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, + int len = WideCharToMultiByte(CP_UTF8, 0, wbuf, wlen, NULL, 0, NULL, FALSE); buf = xmalloc(len); - if (!WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, len, NULL, FALSE)) + if (!WideCharToMultiByte(CP_UTF8, 0, wbuf, wlen, buf, len, NULL, FALSE)) die("WideCharToMultiByte failed!"); printf("%s=", what); - fwrite(buf, 1, len - 1, stdout); + fwrite(buf, 1, len, stdout); putchar('\n'); free(buf); } -static int match_attr(const CREDENTIALW *cred, const WCHAR *keyword, - const char *want) +/* + * Match an (optional) expected string and a delimiter in the target string, + * consuming the matched text by updating the target pointer. + */ +static int match_part(LPCWSTR *ptarget, LPCWSTR want, LPCWSTR delim) { - int i; - if (!want) - return 1; - - for (i = 0; i < cred->AttributeCount; ++i) - if (!wcscmp(cred->Attributes[i].Keyword, keyword)) - return !strcmp((const char *)cred->Attributes[i].Value, - want); - - return 0; /* not found */ + LPCWSTR delim_pos, start = *ptarget; + int len; + + /* find start of delimiter (or end-of-string if delim is empty) */ + if (*delim) + delim_pos = wcsstr(start, delim); + else + delim_pos = start + wcslen(start); + + /* + * match text up to delimiter, or end of string (e.g. the '/' after + * host is optional if not followed by a path) + */ + if (delim_pos) + len = delim_pos - start; + else + len = wcslen(start); + + /* update ptarget if we either found a delimiter or need a match */ + if (delim_pos || want) + *ptarget = delim_pos ? delim_pos + wcslen(delim) : start + len; + + return !want || (!wcsncmp(want, start, len) && !want[len]); } static int match_cred(const CREDENTIALW *cred) { - return (!wusername || !wcscmp(wusername, cred->UserName)) && - match_attr(cred, L"git_protocol", protocol) && - match_attr(cred, L"git_host", host) && - match_attr(cred, L"git_path", path); + LPCWSTR target = cred->TargetName; + if (wusername && wcscmp(wusername, cred->UserName)) + return 0; + + return match_part(&target, L"git", L":") && + match_part(&target, protocol, L"://") && + match_part(&target, wusername, L"@") && + match_part(&target, host, L"/") && + match_part(&target, path, L""); } static void get_credential(void) { - WCHAR *user_buf, *pass_buf; - DWORD user_buf_size = 0, pass_buf_size = 0; - CREDENTIALW **creds, *cred = NULL; + CREDENTIALW **creds; DWORD num_creds; int i; @@ -165,90 +163,36 @@ static void get_credential(void) /* search for the first credential that matches username */ for (i = 0; i < num_creds; ++i) if (match_cred(creds[i])) { - cred = creds[i]; + write_item("username", creds[i]->UserName, + wcslen(creds[i]->UserName)); + write_item("password", + (LPCWSTR)creds[i]->CredentialBlob, + creds[i]->CredentialBlobSize / sizeof(WCHAR)); break; } - if (!cred) - return; - - CredUnPackAuthenticationBufferW(0, cred->CredentialBlob, - cred->CredentialBlobSize, NULL, &user_buf_size, NULL, NULL, - NULL, &pass_buf_size); - - user_buf = xmalloc(user_buf_size * sizeof(WCHAR)); - pass_buf = xmalloc(pass_buf_size * sizeof(WCHAR)); - - if (!CredUnPackAuthenticationBufferW(0, cred->CredentialBlob, - cred->CredentialBlobSize, user_buf, &user_buf_size, NULL, NULL, - pass_buf, &pass_buf_size)) - die("CredUnPackAuthenticationBuffer failed"); CredFree(creds); - - /* zero-terminate (sizes include zero-termination) */ - user_buf[user_buf_size - 1] = L'\0'; - pass_buf[pass_buf_size - 1] = L'\0'; - - write_item("username", user_buf); - write_item("password", pass_buf); - - free(user_buf); - free(pass_buf); -} - -static void write_attr(CREDENTIAL_ATTRIBUTEW *attr, const WCHAR *keyword, - const char *value) -{ - attr->Keyword = (LPWSTR)keyword; - attr->Flags = 0; - attr->ValueSize = strlen(value) + 1; /* store zero-termination */ - attr->Value = (LPBYTE)value; } static void store_credential(void) { CREDENTIALW cred; - BYTE *auth_buf; - DWORD auth_buf_size = 0; - CREDENTIAL_ATTRIBUTEW attrs[CRED_MAX_ATTRIBUTES]; if (!wusername || !password) return; - /* query buffer size */ - CredPackAuthenticationBufferW(0, wusername, password, - NULL, &auth_buf_size); - - auth_buf = xmalloc(auth_buf_size); - - if (!CredPackAuthenticationBufferW(0, wusername, password, - auth_buf, &auth_buf_size)) - die("CredPackAuthenticationBuffer failed"); - cred.Flags = 0; cred.Type = CRED_TYPE_GENERIC; cred.TargetName = target; cred.Comment = L"saved by git-credential-wincred"; - cred.CredentialBlobSize = auth_buf_size; - cred.CredentialBlob = auth_buf; + cred.CredentialBlobSize = (wcslen(password)) * sizeof(WCHAR); + cred.CredentialBlob = (LPVOID)password; cred.Persist = CRED_PERSIST_LOCAL_MACHINE; - cred.AttributeCount = 1; - cred.Attributes = attrs; + cred.AttributeCount = 0; + cred.Attributes = NULL; cred.TargetAlias = NULL; cred.UserName = wusername; - write_attr(attrs, L"git_protocol", protocol); - - if (host) { - write_attr(attrs + cred.AttributeCount, L"git_host", host); - cred.AttributeCount++; - } - - if (path) { - write_attr(attrs + cred.AttributeCount, L"git_path", path); - cred.AttributeCount++; - } - if (!CredWriteW(&cred, 0)) die("CredWrite failed"); } @@ -284,10 +228,13 @@ static void read_credential(void) while (fgets(buf, sizeof(buf), stdin)) { char *v; + int len = strlen(buf); + /* strip trailing CR / LF */ + while (len && strchr("\r\n", buf[len - 1])) + buf[--len] = 0; - if (!strcmp(buf, "\n")) + if (!*buf) break; - buf[strlen(buf)-1] = '\0'; v = strchr(buf, '='); if (!v) @@ -295,13 +242,12 @@ static void read_credential(void) *v++ = '\0'; if (!strcmp(buf, "protocol")) - protocol = xstrdup(v); + protocol = utf8_to_utf16_dup(v); else if (!strcmp(buf, "host")) - host = xstrdup(v); + host = utf8_to_utf16_dup(v); else if (!strcmp(buf, "path")) - path = xstrdup(v); + path = utf8_to_utf16_dup(v); else if (!strcmp(buf, "username")) { - username = xstrdup(v); wusername = utf8_to_utf16_dup(v); } else if (!strcmp(buf, "password")) password = utf8_to_utf16_dup(v); @@ -313,7 +259,7 @@ static void read_credential(void) int main(int argc, char *argv[]) { const char *usage = - "Usage: git credential-wincred \n"; + "usage: git credential-wincred \n"; if (!argv[1]) die(usage); @@ -330,22 +276,20 @@ int main(int argc, char *argv[]) return 0; /* prepare 'target', the unique key for the credential */ - strncat(target_buf, "git:", sizeof(target_buf)); - strncat(target_buf, protocol, sizeof(target_buf)); - strncat(target_buf, "://", sizeof(target_buf)); - if (username) { - strncat(target_buf, username, sizeof(target_buf)); - strncat(target_buf, "@", sizeof(target_buf)); + wcscpy(target, L"git:"); + wcsncat(target, protocol, ARRAY_SIZE(target)); + wcsncat(target, L"://", ARRAY_SIZE(target)); + if (wusername) { + wcsncat(target, wusername, ARRAY_SIZE(target)); + wcsncat(target, L"@", ARRAY_SIZE(target)); } if (host) - strncat(target_buf, host, sizeof(target_buf)); + wcsncat(target, host, ARRAY_SIZE(target)); if (path) { - strncat(target_buf, "/", sizeof(target_buf)); - strncat(target_buf, path, sizeof(target_buf)); + wcsncat(target, L"/", ARRAY_SIZE(target)); + wcsncat(target, path, ARRAY_SIZE(target)); } - target = utf8_to_utf16_dup(target_buf); - if (!strcmp(argv[1], "get")) get_credential(); else if (!strcmp(argv[1], "store")) diff --git a/contrib/examples/git-remote.perl b/contrib/examples/git-remote.perl index b17952a785..d42df7b418 100755 --- a/contrib/examples/git-remote.perl +++ b/contrib/examples/git-remote.perl @@ -347,7 +347,7 @@ sub rm_remote { } sub add_usage { - print STDERR "Usage: git remote add [-f] [-t track]* [-m master] \n"; + print STDERR "usage: git remote add [-f] [-t track]* [-m master] \n"; exit(1); } @@ -380,7 +380,7 @@ sub add_usage { } } if ($i >= @ARGV) { - print STDERR "Usage: git remote show \n"; + print STDERR "usage: git remote show \n"; exit(1); } my $status = 0; @@ -410,7 +410,7 @@ sub add_usage { } } if ($i >= @ARGV) { - print STDERR "Usage: git remote prune \n"; + print STDERR "usage: git remote prune \n"; exit(1); } my $status = 0; @@ -458,13 +458,13 @@ sub add_usage { } elsif ($ARGV[0] eq 'rm') { if (@ARGV <= 1) { - print STDERR "Usage: git remote rm \n"; + print STDERR "usage: git remote rm \n"; exit(1); } exit(rm_remote($ARGV[1])); } else { - print STDERR "Usage: git remote\n"; + print STDERR "usage: git remote\n"; print STDERR " git remote add \n"; print STDERR " git remote rm \n"; print STDERR " git remote show \n"; diff --git a/contrib/examples/git-svnimport.perl b/contrib/examples/git-svnimport.perl index b09ff8f12f..c414f0d9c7 100755 --- a/contrib/examples/git-svnimport.perl +++ b/contrib/examples/git-svnimport.perl @@ -36,7 +36,7 @@ sub usage() { print STDERR <...' - exit(1) + print 'usage:', argv[0], '...' + exit(1) branch_ref = 'refs/heads/import-zips' committer_name = 'Z Ip Creator' @@ -28,51 +28,51 @@ fast_import = popen('git fast-import --quiet', 'w') def printlines(list): - for str in list: - fast_import.write(str + "\n") + for str in list: + fast_import.write(str + "\n") for zipfile in argv[1:]: - commit_time = 0 - next_mark = 1 - common_prefix = None - mark = dict() - - zip = ZipFile(zipfile, 'r') - for name in zip.namelist(): - if name.endswith('/'): - continue - info = zip.getinfo(name) - - if commit_time < info.date_time: - commit_time = info.date_time - if common_prefix == None: - common_prefix = name[:name.rfind('/') + 1] - else: - while not name.startswith(common_prefix): - last_slash = common_prefix[:-1].rfind('/') + 1 - common_prefix = common_prefix[:last_slash] - - mark[name] = ':' + str(next_mark) - next_mark += 1 - - printlines(('blob', 'mark ' + mark[name], \ - 'data ' + str(info.file_size))) - fast_import.write(zip.read(name) + "\n") - - committer = committer_name + ' <' + committer_email + '> %d +0000' % \ - mktime(commit_time + (0, 0, 0)) - - printlines(('commit ' + branch_ref, 'committer ' + committer, \ - 'data < %d +0000' % \ + mktime(commit_time + (0, 0, 0)) + + printlines(('commit ' + branch_ref, 'committer ' + committer, \ + 'data < +"usage: setgitperms.perl [OPTION]... <--read|--write> This program uses a file `.gitmeta` to store/restore permissions and uid/gid info for all files/dirs tracked by git in the repository. diff --git a/contrib/mw-to-git/t/install-wiki.sh b/contrib/mw-to-git/t/install-wiki.sh index c6d6fa3aef..70a53f67fd 100755 --- a/contrib/mw-to-git/t/install-wiki.sh +++ b/contrib/mw-to-git/t/install-wiki.sh @@ -15,7 +15,7 @@ fi . "$WIKI_TEST_DIR"/test-gitmw-lib.sh usage () { - echo "Usage: " + echo "usage: " echo " ./install-wiki.sh " echo " install | -i : Install a wiki on your computer." echo " delete | -d : Delete the wiki and all its pages and " diff --git a/daemon.c b/daemon.c index 4602b46a5c..df8c0ab058 100644 --- a/daemon.c +++ b/daemon.c @@ -9,10 +9,6 @@ #define HOST_NAME_MAX 256 #endif -#ifndef NI_MAXSERV -#define NI_MAXSERV 32 -#endif - #ifdef NO_INITGROUPS #define initgroups(x, y) (0) /* nothing */ #endif diff --git a/diff.c b/diff.c index 156fec4470..db952a5bc7 100644 --- a/diff.c +++ b/diff.c @@ -1264,6 +1264,7 @@ static char *pprint_rename(const char *a, const char *b) const char *new = b; struct strbuf name = STRBUF_INIT; int pfx_length, sfx_length; + int pfx_adjust_for_slash; int len_a = strlen(a); int len_b = strlen(b); int a_midlen, b_midlen; @@ -1290,7 +1291,18 @@ static char *pprint_rename(const char *a, const char *b) old = a + len_a; new = b + len_b; sfx_length = 0; - while (a <= old && b <= new && *old == *new) { + /* + * If there is a common prefix, it must end in a slash. In + * that case we let this loop run 1 into the prefix to see the + * same slash. + * + * If there is no common prefix, we cannot do this as it would + * underrun the input strings. + */ + pfx_adjust_for_slash = (pfx_length ? 1 : 0); + while (a + pfx_length - pfx_adjust_for_slash <= old && + b + pfx_length - pfx_adjust_for_slash <= new && + *old == *new) { if (*old == '/') sfx_length = len_a - (old - a); old--; @@ -4662,7 +4674,7 @@ int diff_result_code(struct diff_options *opt, int status) { int result = 0; - diff_warn_rename_limit("diff.renamelimit", + diff_warn_rename_limit("diff.renameLimit", opt->needed_rename_limit, opt->degraded_cc_to_c); if (!DIFF_OPT_TST(opt, EXIT_WITH_STATUS) && diff --git a/diffcore-rename.c b/diffcore-rename.c index 512d0ac5fd..6c7a72fbe7 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -389,6 +389,7 @@ static int find_exact_renames(struct diff_options *options) struct hash_table file_table; init_hash(&file_table); + preallocate_hash(&file_table, rename_src_nr + rename_dst_nr); for (i = 0; i < rename_src_nr; i++) insert_file_table(&file_table, -1, i, rename_src[i].p->one); diff --git a/environment.c b/environment.c index 89d6c70c15..e2e75c1660 100644 --- a/environment.c +++ b/environment.c @@ -83,20 +83,20 @@ static const char *git_dir; static char *git_object_dir, *git_index_file, *git_graft_file; /* - * Repository-local GIT_* environment variables - * Remember to update local_repo_env_size in cache.h when - * the size of the list changes + * Repository-local GIT_* environment variables; see cache.h for details. */ -const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = { +const char * const local_repo_env[] = { ALTERNATE_DB_ENVIRONMENT, CONFIG_ENVIRONMENT, CONFIG_DATA_ENVIRONMENT, DB_ENVIRONMENT, GIT_DIR_ENVIRONMENT, GIT_WORK_TREE_ENVIRONMENT, + GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, GRAFT_ENVIRONMENT, INDEX_ENVIRONMENT, NO_REPLACE_OBJECTS_ENVIRONMENT, + GIT_PREFIX_ENVIRONMENT, NULL }; diff --git a/fast-import.c b/fast-import.c index c2a814ec66..a0c2c2ff14 100644 --- a/fast-import.c +++ b/fast-import.c @@ -2265,7 +2265,7 @@ static void file_change_m(struct branch *b) const char *p = command_buf.buf + 2; static struct strbuf uq = STRBUF_INIT; const char *endp; - struct object_entry *oe = oe; + struct object_entry *oe; unsigned char sha1[20]; uint16_t mode, inline_data = 0; @@ -2292,6 +2292,7 @@ static void file_change_m(struct branch *b) hashcpy(sha1, oe->idx.sha1); } else if (!prefixcmp(p, "inline ")) { inline_data = 1; + oe = NULL; /* not used with inline_data, but makes gcc happy */ p += strlen("inline"); /* advance to space */ } else { if (get_sha1_hex(p, sha1)) @@ -2434,7 +2435,7 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout) { const char *p = command_buf.buf + 2; static struct strbuf uq = STRBUF_INIT; - struct object_entry *oe = oe; + struct object_entry *oe; struct branch *s; unsigned char sha1[20], commit_sha1[20]; char path[60]; @@ -2613,7 +2614,7 @@ static int parse_from(struct branch *b) static struct hash_list *parse_merge(unsigned int *count) { - struct hash_list *list = NULL, *n, *e = e; + struct hash_list *list = NULL, **tail = &list, *n; const char *from; struct branch *s; @@ -2641,11 +2642,9 @@ static struct hash_list *parse_merge(unsigned int *count) die("Invalid ref name or SHA1 expression: %s", from); n->next = NULL; - if (list) - e->next = n; - else - list = n; - e = n; + *tail = n; + tail = &n->next; + (*count)++; read_next_command(); } diff --git a/fetch-pack.c b/fetch-pack.c index 6d8926a550..cef8fde61b 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -36,7 +36,7 @@ static int marked; #define MAX_IN_VAIN 256 static struct commit_list *rev_list; -static int non_common_revs, multi_ack, use_sideband; +static int non_common_revs, multi_ack, use_sideband, allow_tip_sha1_in_want; static void rev_list_push(struct commit *commit, int mark) { @@ -520,47 +520,37 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args, } } -static int non_matching_ref(struct string_list_item *item, void *unused) -{ - if (item->util) { - item->util = NULL; - return 0; - } - else - return 1; -} - static void filter_refs(struct fetch_pack_args *args, - struct ref **refs, struct string_list *sought) + struct ref **refs, + struct ref **sought, int nr_sought) { struct ref *newlist = NULL; struct ref **newtail = &newlist; struct ref *ref, *next; - int sought_pos; + int i; - sought_pos = 0; + i = 0; for (ref = *refs; ref; ref = next) { int keep = 0; next = ref->next; + if (!memcmp(ref->name, "refs/", 5) && check_refname_format(ref->name + 5, 0)) ; /* trash */ else { - while (sought_pos < sought->nr) { - int cmp = strcmp(ref->name, sought->items[sought_pos].string); + while (i < nr_sought) { + int cmp = strcmp(ref->name, sought[i]->name); if (cmp < 0) break; /* definitely do not have it */ else if (cmp == 0) { keep = 1; /* definitely have it */ - sought->items[sought_pos++].util = "matched"; - break; + sought[i]->matched = 1; } - else - sought_pos++; /* might have it; keep looking */ + i++; } } - if (! keep && args->fetch_all && + if (!keep && args->fetch_all && (!args->depth || prefixcmp(ref->name, "refs/tags/"))) keep = 1; @@ -573,7 +563,21 @@ static void filter_refs(struct fetch_pack_args *args, } } - filter_string_list(sought, 0, non_matching_ref, NULL); + /* Append unmatched requests to the list */ + if (allow_tip_sha1_in_want) { + for (i = 0; i < nr_sought; i++) { + ref = sought[i]; + if (ref->matched) + continue; + if (get_sha1_hex(ref->name, ref->old_sha1)) + continue; + + ref->matched = 1; + *newtail = ref; + ref->next = NULL; + newtail = &ref->next; + } + } *refs = newlist; } @@ -583,7 +587,8 @@ static void mark_alternate_complete(const struct ref *ref, void *unused) } static int everything_local(struct fetch_pack_args *args, - struct ref **refs, struct string_list *sought) + struct ref **refs, + struct ref **sought, int nr_sought) { struct ref *ref; int retval; @@ -637,7 +642,7 @@ static int everything_local(struct fetch_pack_args *args, } } - filter_refs(args, refs, sought); + filter_refs(args, refs, sought, nr_sought); for (retval = 1, ref = *refs; ref ; ref = ref->next) { const unsigned char *remote = ref->old_sha1; @@ -767,10 +772,17 @@ static int get_pack(struct fetch_pack_args *args, return 0; } +static int cmp_ref_by_name(const void *a_, const void *b_) +{ + const struct ref *a = *((const struct ref **)a_); + const struct ref *b = *((const struct ref **)b_); + return strcmp(a->name, b->name); +} + static struct ref *do_fetch_pack(struct fetch_pack_args *args, int fd[2], const struct ref *orig_ref, - struct string_list *sought, + struct ref **sought, int nr_sought, char **pack_lockfile) { struct ref *ref = copy_ref_list(orig_ref); @@ -779,6 +791,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, int agent_len; sort_ref_list(&ref, ref_compare_name); + qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name); if (is_repository_shallow() && !server_supports("shallow")) die("Server does not support shallow clients"); @@ -808,6 +821,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, fprintf(stderr, "Server supports side-band\n"); use_sideband = 1; } + if (server_supports("allow-tip-sha1-in-want")) { + if (args->verbose) + fprintf(stderr, "Server supports allow-tip-sha1-in-want\n"); + allow_tip_sha1_in_want = 1; + } if (!server_supports("thin-pack")) args->use_thin_pack = 0; if (!server_supports("no-progress")) @@ -827,7 +845,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, agent_len, agent_feature); } - if (everything_local(args, &ref, sought)) { + if (everything_local(args, &ref, sought, nr_sought)) { packet_flush(fd[1]); goto all_done; } @@ -890,11 +908,32 @@ static void fetch_pack_setup(void) did_setup = 1; } +static int remove_duplicates_in_refs(struct ref **ref, int nr) +{ + struct string_list names = STRING_LIST_INIT_NODUP; + int src, dst; + + for (src = dst = 0; src < nr; src++) { + struct string_list_item *item; + item = string_list_insert(&names, ref[src]->name); + if (item->util) + continue; /* already have it */ + item->util = ref[src]; + if (src != dst) + ref[dst] = ref[src]; + dst++; + } + for (src = dst; src < nr; src++) + ref[src] = NULL; + string_list_clear(&names, 0); + return dst; +} + struct ref *fetch_pack(struct fetch_pack_args *args, int fd[], struct child_process *conn, const struct ref *ref, const char *dest, - struct string_list *sought, + struct ref **sought, int nr_sought, char **pack_lockfile) { struct stat st; @@ -906,16 +945,14 @@ struct ref *fetch_pack(struct fetch_pack_args *args, st.st_mtime = 0; } - if (sought->nr) { - sort_string_list(sought); - string_list_remove_duplicates(sought, 0); - } + if (nr_sought) + nr_sought = remove_duplicates_in_refs(sought, nr_sought); if (!ref) { packet_flush(fd[1]); die("no matching remote head"); } - ref_cpy = do_fetch_pack(args, fd, ref, sought, pack_lockfile); + ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, pack_lockfile); if (args->depth > 0) { static struct lock_file lock; diff --git a/fetch-pack.h b/fetch-pack.h index cb148719bf..dc5266c970 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -20,17 +20,16 @@ struct fetch_pack_args { }; /* - * sought contains the full names of remote references that should be - * updated from. On return, the names that were found on the remote - * will have been removed from the list. The util members of the - * string_list_items are used internally; they must be NULL on entry - * (and will be NULL on exit). + * sought represents remote references that should be updated from. + * On return, the names that were found on the remote will have been + * marked as such. */ struct ref *fetch_pack(struct fetch_pack_args *args, int fd[], struct child_process *conn, const struct ref *ref, const char *dest, - struct string_list *sought, + struct ref **sought, + int nr_sought, char **pack_lockfile); #endif diff --git a/git-archimport.perl b/git-archimport.perl index bc32f18d6d..9cb123a07d 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -75,7 +75,7 @@ =head1 Devel Notes sub usage() { print STDERR < #include @@ -213,6 +216,17 @@ extern char *gitbasename(char *); #include #endif +/* On most systems would have given us this, but + * not on some systems (e.g. z/OS). + */ +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + /* On most systems would have given us this, but * not on some systems (e.g. GNU/Hurd). */ @@ -421,11 +435,6 @@ extern uintmax_t gitstrtoumax(const char *, char **, int); extern intmax_t gitstrtoimax(const char *, char **, int); #endif -#ifdef NO_STRTOK_R -#define strtok_r gitstrtok_r -extern char *gitstrtok_r(char *s, const char *delim, char **save_ptr); -#endif - #ifdef NO_HSTRERROR #define hstrerror githstrerror extern const char *githstrerror(int herror); diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index e6bf25232c..d13f02da95 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -420,7 +420,7 @@ sub usage { print STDERR <info("--------------- STARTING -----------------"); my $usage = - "Usage: git cvsserver [options] [pserver|server] [ ...]\n". + "usage: git cvsserver [options] [pserver|server] [ ...]\n". " --base-path : Prepend to requested CVSROOT\n". " Can be read from GIT_CVSSERVER_BASE_PATH\n". " --strict-paths : Don't allow recursing into subdirectories\n". diff --git a/git-difftool.perl b/git-difftool.perl index 0a90de4146..12231fbc67 100755 --- a/git-difftool.perl +++ b/git-difftool.perl @@ -336,7 +336,7 @@ sub main } if ($opts{gui}) { my $guitool = Git::config('diff.guitool'); - if (length($guitool) > 0) { + if (defined($guitool) && length($guitool) > 0) { $ENV{GIT_DIFF_TOOL} = $guitool; } } diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh index f612cb847a..3373c040d4 100755 --- a/git-merge-one-file.sh +++ b/git-merge-one-file.sh @@ -18,7 +18,7 @@ USAGE=' ' USAGE="$USAGE " -LONG_USAGE="Usage: git merge-one-file $USAGE +LONG_USAGE="usage: git merge-one-file $USAGE Blob ids and modes should be empty for missing files." diff --git a/git-p4.py b/git-p4.py index 647f110202..911bbce6c5 100755 --- a/git-p4.py +++ b/git-p4.py @@ -79,12 +79,27 @@ def p4_build_cmd(cmd): real_cmd += cmd return real_cmd -def chdir(dir): - # P4 uses the PWD environment variable rather than getcwd(). Since we're - # not using the shell, we have to set it ourselves. This path could - # be relative, so go there first, then figure out where we ended up. - os.chdir(dir) - os.environ['PWD'] = os.getcwd() +def chdir(path, is_client_path=False): + """Do chdir to the given path, and set the PWD environment + variable for use by P4. It does not look at getcwd() output. + Since we're not using the shell, it is necessary to set the + PWD environment variable explicitly. + + Normally, expand the path to force it to be absolute. This + addresses the use of relative path names inside P4 settings, + e.g. P4CONFIG=.p4config. P4 does not simply open the filename + as given; it looks for .p4config using PWD. + + If is_client_path, the path was handed to us directly by p4, + and may be a symbolic link. Do not call os.getcwd() in this + case, because it will cause p4 to think that PWD is not inside + the client path. + """ + + os.chdir(path) + if not is_client_path: + path = os.getcwd() + os.environ['PWD'] = path def die(msg): if verbose: @@ -1624,7 +1639,7 @@ def run(self, args): new_client_dir = True os.makedirs(self.clientPath) - chdir(self.clientPath) + chdir(self.clientPath, is_client_path=True) if self.dry_run: print "Would synchronize p4 checkout in %s" % self.clientPath else: diff --git a/git-pull.sh b/git-pull.sh index 266e682f6c..5d97e97bd9 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -279,7 +279,7 @@ fi merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit case "$rebase" in true) - eval="git-rebase $diffstat $strategy_args $merge_args" + eval="git-rebase $diffstat $strategy_args $merge_args $verbosity" eval="$eval --onto $merge_head ${oldremoteref:-$merge_head}" ;; *) diff --git a/git-relink.perl b/git-relink.perl index f29285c411..236a3521a1 100755 --- a/git-relink.perl +++ b/git-relink.perl @@ -163,7 +163,7 @@ ($$) sub usage() { - print("Usage: git relink [--safe] ... \n"); + print("usage: git relink [--safe] ... \n"); print("All directories should contain a .git/objects/ subdirectory.\n"); print("Options\n"); print("\t--safe\t" . diff --git a/git-send-email.perl b/git-send-email.perl index be809e5b59..c3501d987e 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -1045,6 +1045,47 @@ sub maildomain { return maildomain_net() || maildomain_mta() || 'localhost.localdomain'; } +sub smtp_host_string { + if (defined $smtp_server_port) { + return "$smtp_server:$smtp_server_port"; + } else { + return $smtp_server; + } +} + +# Returns 1 if authentication succeeded or was not necessary +# (smtp_user was not specified), and 0 otherwise. + +sub smtp_auth_maybe { + if (!defined $smtp_authuser || $auth) { + return 1; + } + + # Workaround AUTH PLAIN/LOGIN interaction defect + # with Authen::SASL::Cyrus + eval { + require Authen::SASL; + Authen::SASL->import(qw(Perl)); + }; + + # TODO: Authentication may fail not because credentials were + # invalid but due to other reasons, in which we should not + # reject credentials. + $auth = Git::credential({ + 'protocol' => 'smtp', + 'host' => smtp_host_string(), + 'username' => $smtp_authuser, + # if there's no password, "git credential fill" will + # give us one, otherwise it'll just pass this one. + 'password' => $smtp_authpass + }, sub { + my $cred = shift; + return !!$smtp->auth($cred->{'username'}, $cred->{'password'}); + }); + + return $auth; +} + # Returns 1 if the message was sent, and 0 otherwise. # In actuality, the whole program dies when there # is an error sending a message. @@ -1155,9 +1196,7 @@ sub send_message { else { require Net::SMTP; $smtp_domain ||= maildomain(); - $smtp ||= Net::SMTP->new((defined $smtp_server_port) - ? "$smtp_server:$smtp_server_port" - : $smtp_server, + $smtp ||= Net::SMTP->new(smtp_host_string(), Hello => $smtp_domain, Debug => $debug_net_smtp); if ($smtp_encryption eq 'tls' && $smtp) { @@ -1185,31 +1224,7 @@ sub send_message { defined $smtp_server_port ? " port=$smtp_server_port" : ""; } - if (defined $smtp_authuser) { - # Workaround AUTH PLAIN/LOGIN interaction defect - # with Authen::SASL::Cyrus - eval { - require Authen::SASL; - Authen::SASL->import(qw(Perl)); - }; - - if (!defined $smtp_authpass) { - - system "stty -echo"; - - do { - print "Password: "; - $_ = ; - print "\n"; - } while (!defined $_); - - chomp($smtp_authpass = $_); - - system "stty echo"; - } - - $auth ||= $smtp->auth( $smtp_authuser, $smtp_authpass ) or die $smtp->message; - } + smtp_auth_maybe or die $smtp->message; $smtp->mail( $raw_from ) or die $smtp->message; $smtp->to( @recipients ) or die $smtp->message; diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 795edd2852..9cfbe7f143 100644 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -84,14 +84,14 @@ if test -n "$OPTIONS_SPEC"; then else dashless=$(basename "$0" | sed -e 's/-/ /') usage() { - die "Usage: $dashless $USAGE" + die "usage: $dashless $USAGE" } if [ -z "$LONG_USAGE" ] then - LONG_USAGE="Usage: $dashless $USAGE" + LONG_USAGE="usage: $dashless $USAGE" else - LONG_USAGE="Usage: $dashless $USAGE + LONG_USAGE="usage: $dashless $USAGE $LONG_USAGE" fi diff --git a/git-submodule.sh b/git-submodule.sh index 004c034bc0..204bc78a9f 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -8,6 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /') USAGE="[--quiet] add [-b ] [-f|--force] [--name ] [--reference ] [--] [] or: $dashless [--quiet] status [--cached] [--recursive] [--] [...] or: $dashless [--quiet] init [--] [...] + or: $dashless [--quiet] deinit [-f|--force] [--] ... or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference ] [--merge] [--recursive] [--] [...] or: $dashless [--quiet] summary [--cached|--files] [--summary-limit ] [commit] [--] [...] or: $dashless [--quiet] foreach [--recursive] @@ -546,6 +547,80 @@ cmd_init() done } +# +# Unregister submodules from .git/config and remove their work tree +# +# $@ = requested paths (use '.' to deinit all submodules) +# +cmd_deinit() +{ + # parse $args after "submodule ... deinit". + while test $# -ne 0 + do + case "$1" in + -f|--force) + force=$1 + ;; + -q|--quiet) + GIT_QUIET=1 + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift + done + + if test $# = 0 + then + die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")" + fi + + module_list "$@" | + while read mode sha1 stage sm_path + do + die_if_unmatched "$mode" + name=$(module_name "$sm_path") || exit + + # Remove the submodule work tree (unless the user already did it) + if test -d "$sm_path" + then + # Protect submodules containing a .git directory + if test -d "$sm_path/.git" + then + echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")" + die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")" + fi + + if test -z "$force" + then + git rm -n "$sm_path" || + die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")" + fi + rm -rf "$sm_path" || say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")" + fi + + mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")" + + # Remove the .git/config entries (unless the user already did it) + if test -n "$(git config --get-regexp submodule."$name\.")" + then + # Remove the whole section so we have a clean state when + # the user later decides to init this submodule again + url=$(git config submodule."$name".url) + git config --remove-section submodule."$name" 2>/dev/null && + say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$sm_path'")" + fi + done +} + # # Update each submodule path to correct revision, using clone and checkout as needed # @@ -622,7 +697,7 @@ cmd_update() die_if_unmatched "$mode" if test "$stage" = U then - echo >&2 "Skipping unmerged submodule $sm_path" + echo >&2 "Skipping unmerged submodule $prefix$sm_path" continue fi name=$(module_name "$sm_path") || exit @@ -637,7 +712,7 @@ cmd_update() if test "$update_module" = "none" then - echo "Skipping submodule '$sm_path'" + echo "Skipping submodule '$prefix$sm_path'" continue fi @@ -646,7 +721,7 @@ cmd_update() # Only mention uninitialized submodules when its # path have been specified test "$#" != "0" && - say "$(eval_gettext "Submodule path '\$sm_path' not initialized + say "$(eval_gettext "Submodule path '\$prefix\$sm_path' not initialized Maybe you want to use 'update --init'?")" continue fi @@ -659,7 +734,7 @@ Maybe you want to use 'update --init'?")" else subsha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD) || - die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")" + die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")" fi if test -n "$remote" @@ -692,7 +767,7 @@ Maybe you want to use 'update --init'?")" (clear_local_git_env; cd "$sm_path" && ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) && test -z "$rev") || git-fetch)) || - die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")" + die "$(eval_gettext "Unable to fetch in submodule path '\$prefix\$sm_path'")" fi # Is this something we just cloned? @@ -706,20 +781,20 @@ Maybe you want to use 'update --init'?")" case "$update_module" in rebase) command="git rebase" - die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$sm_path'")" - say_msg="$(eval_gettext "Submodule path '\$sm_path': rebased into '\$sha1'")" + die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$prefix\$sm_path'")" + say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': rebased into '\$sha1'")" must_die_on_failure=yes ;; merge) command="git merge" - die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$sm_path'")" - say_msg="$(eval_gettext "Submodule path '\$sm_path': merged in '\$sha1'")" + die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$prefix\$sm_path'")" + say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': merged in '\$sha1'")" must_die_on_failure=yes ;; *) command="git checkout $subforce -q" - die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$sm_path'")" - say_msg="$(eval_gettext "Submodule path '\$sm_path': checked out '\$sha1'")" + die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$prefix\$sm_path'")" + say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': checked out '\$sha1'")" ;; esac @@ -737,11 +812,16 @@ Maybe you want to use 'update --init'?")" if test -n "$recursive" then - (clear_local_git_env; cd "$sm_path" && eval cmd_update "$orig_flags") + ( + prefix="$prefix$sm_path/" + clear_local_git_env + cd "$sm_path" && + eval cmd_update "$orig_flags" + ) res=$? if test $res -gt 0 then - die_msg="$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")" + die_msg="$(eval_gettext "Failed to recurse into submodule path '\$prefix\$sm_path'")" if test $res -eq 1 then err="${err};$die_msg" @@ -1157,7 +1237,7 @@ cmd_sync() while test $# != 0 && test -z "$command" do case "$1" in - add | foreach | init | update | status | summary | sync) + add | foreach | init | deinit | update | status | summary | sync) command=$1 ;; -q|--quiet) diff --git a/git-svn.perl b/git-svn.perl index b46795f593..6c7bd95032 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -382,7 +382,7 @@ sub usage { my $fd = $exit ? \*STDERR : \*STDOUT; print $fd <<""; git-svn - bidirectional operations between a single Subversion tree and git -Usage: git svn [options] [arguments]\n +usage: git svn [options] [arguments]\n print $fd "Available commands:\n" unless $cmd; @@ -534,7 +534,7 @@ sub cmd_fetch { } my ($remote) = @_; if (@_ > 1) { - die "Usage: $0 fetch [--all] [--parent] [svn-remote]\n"; + die "usage: $0 fetch [--all] [--parent] [svn-remote]\n"; } $Git::SVN::no_reuse_existing = undef; if ($_fetch_parent) { @@ -1404,7 +1404,7 @@ sub cmd_multi_fetch { # this command is special because it requires no metadata sub cmd_commit_diff { my ($ta, $tb, $url) = @_; - my $usage = "Usage: $0 commit-diff -r ". + my $usage = "usage: $0 commit-diff -r ". " []"; fatal($usage) if (!defined $ta || !defined $tb); my $svn_path = ''; diff --git a/git.c b/git.c index b10c18b041..850d3f5527 100644 --- a/git.c +++ b/git.c @@ -6,10 +6,10 @@ #include "run-command.h" const char git_usage_string[] = - "git [--version] [--exec-path[=]] [--html-path] [--man-path] [--info-path]\n" + "git [--version] [--help] [-c name=value]\n" + " [--exec-path[=]] [--html-path] [--man-path] [--info-path]\n" " [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]\n" " [--git-dir=] [--work-tree=] [--namespace=]\n" - " [-c name=value] [--help]\n" " []"; const char git_more_info_string[] = @@ -125,6 +125,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) static char git_dir[PATH_MAX+1]; is_bare_repository_cfg = 1; setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0); + setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1); if (envchanged) *envchanged = 1; } else if (!strcmp(cmd, "-c")) { @@ -545,7 +546,7 @@ int main(int argc, const char **argv) commit_pager_choice(); printf("usage: %s\n\n", git_usage_string); list_common_cmds_help(); - printf("\n%s\n", git_more_info_string); + printf("\n%s\n", _(git_more_info_string)); exit(1); } cmd = argv[0]; diff --git a/gitweb/README b/gitweb/README index 6da4778b73..471dcfb691 100644 --- a/gitweb/README +++ b/gitweb/README @@ -1,9 +1,6 @@ GIT web Interface ================= -The one working on: - http://git.kernel.org/ - From the git version 1.4.0 gitweb is bundled with git. diff --git a/gpg-interface.c b/gpg-interface.c index 45590330aa..8b0e87436b 100644 --- a/gpg-interface.c +++ b/gpg-interface.c @@ -96,15 +96,18 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig /* * Run "gpg" to see if the payload matches the detached signature. * gpg_output, when set, receives the diagnostic output from GPG. + * gpg_status, when set, receives the status output from GPG. */ int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, - struct strbuf *gpg_output) + struct strbuf *gpg_output, struct strbuf *gpg_status) { struct child_process gpg; - const char *args_gpg[] = {NULL, "--verify", "FILE", "-", NULL}; + const char *args_gpg[] = {NULL, "--status-fd=1", "--verify", "FILE", "-", NULL}; char path[PATH_MAX]; int fd, ret; + struct strbuf buf = STRBUF_INIT; + struct strbuf *pbuf = &buf; args_gpg[0] = gpg_program; fd = git_mkstemp(path, PATH_MAX, ".git_vtag_tmpXXXXXX"); @@ -119,9 +122,10 @@ int verify_signed_buffer(const char *payload, size_t payload_size, memset(&gpg, 0, sizeof(gpg)); gpg.argv = args_gpg; gpg.in = -1; + gpg.out = -1; if (gpg_output) gpg.err = -1; - args_gpg[2] = path; + args_gpg[3] = path; if (start_command(&gpg)) { unlink(path); return error(_("could not run gpg.")); @@ -134,9 +138,17 @@ int verify_signed_buffer(const char *payload, size_t payload_size, strbuf_read(gpg_output, gpg.err, 0); close(gpg.err); } + if (gpg_status) + pbuf = gpg_status; + strbuf_read(pbuf, gpg.out, 0); + close(gpg.out); + ret = finish_command(&gpg); unlink_or_warn(path); + ret |= !strstr(pbuf->buf, "\n[GNUPG:] GOODSIG "); + strbuf_release(&buf); /* no matter it was used or not */ + return ret; } diff --git a/gpg-interface.h b/gpg-interface.h index b9c36088ce..cf99021842 100644 --- a/gpg-interface.h +++ b/gpg-interface.h @@ -2,7 +2,7 @@ #define GPG_INTERFACE_H extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key); -extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output); +extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output, struct strbuf *gpg_status); extern int git_gpg_config(const char *, const char *, void *); extern void set_signing_key(const char *); extern const char *get_signing_key(void); diff --git a/graph.c b/graph.c index 2a3fc5c0ec..b24d04c406 100644 --- a/graph.c +++ b/graph.c @@ -7,34 +7,6 @@ /* Internal API */ -/* - * Output the next line for a graph. - * This formats the next graph line into the specified strbuf. It is not - * terminated with a newline. - * - * Returns 1 if the line includes the current commit, and 0 otherwise. - * graph_next_line() will return 1 exactly once for each time - * graph_update() is called. - */ -static int graph_next_line(struct git_graph *graph, struct strbuf *sb); - -/* - * Set up a custom scheme for column colors. - * - * The default column color scheme inserts ANSI color escapes to colorize - * the graph. The various color escapes are stored in an array of strings - * where each entry corresponds to a color, except for the last entry, - * which denotes the escape for resetting the color back to the default. - * When generating the graph, strings from this array are inserted before - * and after the various column characters. - * - * This function allows you to enable a custom array of color escapes. - * The 'colors_max' argument is the index of the last "reset" entry. - * - * This functions must be called BEFORE graph_init() is called. - */ -static void graph_set_column_colors(const char **colors, unsigned short colors_max); - /* * Output a padding line in the graph. * This is similar to graph_next_line(). However, it is guaranteed to @@ -90,7 +62,7 @@ enum graph_state { static const char **column_colors; static unsigned short column_colors_max; -static void graph_set_column_colors(const char **colors, unsigned short colors_max) +void graph_set_column_colors(const char **colors, unsigned short colors_max) { column_colors = colors; column_colors_max = colors_max; @@ -1144,7 +1116,7 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf graph_update_state(graph, GRAPH_PADDING); } -static int graph_next_line(struct git_graph *graph, struct strbuf *sb) +int graph_next_line(struct git_graph *graph, struct strbuf *sb) { switch (graph->state) { case GRAPH_PADDING: diff --git a/graph.h b/graph.h index 19b0f66316..0be62bd8b1 100644 --- a/graph.h +++ b/graph.h @@ -4,6 +4,25 @@ /* A graph is a pointer to this opaque structure */ struct git_graph; +/* + * Set up a custom scheme for column colors. + * + * The default column color scheme inserts ANSI color escapes to colorize + * the graph. The various color escapes are stored in an array of strings + * where each entry corresponds to a color, except for the last entry, + * which denotes the escape for resetting the color back to the default. + * When generating the graph, strings from this array are inserted before + * and after the various column characters. + * + * This function allows you to enable a custom array of color escapes. + * The 'colors_max' argument is the index of the last "reset" entry. + * + * This functions must be called BEFORE graph_init() is called. + * + * NOTE: This function isn't used in Git outside graph.c but it is used + * by CGit (http://git.zx2c4.com/cgit/) to use HTML for colors. + */ +void graph_set_column_colors(const char **colors, unsigned short colors_max); /* * Create a new struct git_graph. @@ -33,6 +52,20 @@ void graph_update(struct git_graph *graph, struct commit *commit); */ int graph_is_commit_finished(struct git_graph const *graph); +/* + * Output the next line for a graph. + * This formats the next graph line into the specified strbuf. It is not + * terminated with a newline. + * + * Returns 1 if the line includes the current commit, and 0 otherwise. + * graph_next_line() will return 1 exactly once for each time + * graph_update() is called. + * + * NOTE: This function isn't used in Git outside graph.c but it is used + * by CGit (http://git.zx2c4.com/cgit/) to wrap HTML around graph lines. + */ +int graph_next_line(struct git_graph *graph, struct strbuf *sb); + /* * graph_show_*: helper functions for printing to stdout diff --git a/grep.c b/grep.c index 4bd1b8b1dd..bb548cae69 100644 --- a/grep.c +++ b/grep.c @@ -625,7 +625,8 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt) for (p = opt->header_list; p; p = p->next) { if (p->token != GREP_PATTERN_HEAD) die("bug: a non-header pattern in grep header list."); - if (p->field < 0 || GREP_HEADER_FIELD_MAX <= p->field) + if (p->field < GREP_HEADER_FIELD_MIN || + GREP_HEADER_FIELD_MAX <= p->field) die("bug: unknown header field %d", p->field); compile_regexp(p, opt); } diff --git a/grep.h b/grep.h index 8fc854f400..e4a1df56a4 100644 --- a/grep.h +++ b/grep.h @@ -28,7 +28,8 @@ enum grep_context { }; enum grep_header_field { - GREP_HEADER_AUTHOR = 0, + GREP_HEADER_FIELD_MIN = 0, + GREP_HEADER_AUTHOR = GREP_HEADER_FIELD_MIN, GREP_HEADER_COMMITTER, GREP_HEADER_REFLOG, diff --git a/hash.h b/hash.h index b875ce67c4..1d43ac0ba0 100644 --- a/hash.h +++ b/hash.h @@ -40,4 +40,11 @@ static inline void init_hash(struct hash_table *table) table->array = NULL; } +static inline void preallocate_hash(struct hash_table *table, unsigned int elts) +{ + assert(table->size == 0 && table->nr == 0 && table->array == NULL); + table->size = elts * 2; + table->array = xcalloc(sizeof(struct hash_table_entry), table->size); +} + #endif diff --git a/imap-send.c b/imap-send.c index 43ac4e0bdf..d9bcfb44dc 100644 --- a/imap-send.c +++ b/imap-send.c @@ -304,6 +304,17 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve return -1; } +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + /* + * SNI (RFC4366) + * OpenSSL does not document this function, but the implementation + * returns 1 on success, 0 on failure after calling SSLerr(). + */ + ret = SSL_set_tlsext_host_name(sock->ssl, server.host); + if (ret != 1) + warning("SSL_set_tlsext_host_name(%s) failed.", server.host); +#endif + ret = SSL_connect(sock->ssl); if (ret <= 0) { socket_perror("SSL_connect", sock, ret); diff --git a/log-tree.c b/log-tree.c index 5dc45c4812..3d88823871 100644 --- a/log-tree.c +++ b/log-tree.c @@ -444,7 +444,7 @@ static void show_signature(struct rev_info *opt, struct commit *commit) status = verify_signed_buffer(payload.buf, payload.len, signature.buf, signature.len, - &gpg_output); + &gpg_output, NULL); if (status && !gpg_output.len) strbuf_addstr(&gpg_output, "No signature\n"); @@ -508,20 +508,17 @@ static void show_one_mergetag(struct rev_info *opt, gpg_message_offset = verify_message.len; payload_size = parse_signature(extra->value, extra->len); - if ((extra->len <= payload_size) || - (verify_signed_buffer(extra->value, payload_size, - extra->value + payload_size, - extra->len - payload_size, - &verify_message) && - verify_message.len <= gpg_message_offset)) { - strbuf_addstr(&verify_message, "No signature\n"); - status = -1; - } - else if (strstr(verify_message.buf + gpg_message_offset, - ": Good signature from ")) - status = 0; - else - status = -1; + status = -1; + if (extra->len > payload_size) + if (verify_signed_buffer(extra->value, payload_size, + extra->value + payload_size, + extra->len - payload_size, + &verify_message, NULL)) { + if (verify_message.len <= gpg_message_offset) + strbuf_addstr(&verify_message, "No signature\n"); + else + status = 0; + } show_sig_lines(opt, status, verify_message.buf); strbuf_release(&verify_message); diff --git a/name-hash.c b/name-hash.c index 942c459622..9bac31a6ab 100644 --- a/name-hash.c +++ b/name-hash.c @@ -92,6 +92,8 @@ static void lazy_init_name_hash(struct index_state *istate) if (istate->name_hash_initialized) return; + if (istate->cache_nr) + preallocate_hash(&istate->name_hash, istate->cache_nr); for (nr = 0; nr < istate->cache_nr; nr++) hash_index_entry(istate, istate->cache[nr]); istate->name_hash_initialized = 1; diff --git a/perl/Git.pm b/perl/Git.pm index a56d1e76f7..96cac39a4c 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -60,6 +60,7 @@ =head1 SYNOPSIS version exec_path html_path hash_object git_cmd_try remote_refs prompt get_tz_offset + credential credential_read credential_write temp_acquire temp_release temp_reset temp_path); @@ -269,13 +270,13 @@ sub command { if (not defined wantarray) { # Nothing to pepper the possible exception with. - _cmd_close($fh, $ctx); + _cmd_close($ctx, $fh); } elsif (not wantarray) { local $/; my $text = <$fh>; try { - _cmd_close($fh, $ctx); + _cmd_close($ctx, $fh); } catch Git::Error::Command with { # Pepper with the output: my $E = shift; @@ -288,7 +289,7 @@ sub command { my @lines = <$fh>; defined and chomp for @lines; try { - _cmd_close($fh, $ctx); + _cmd_close($ctx, $fh); } catch Git::Error::Command with { my $E = shift; $E->{'-outputref'} = \@lines; @@ -315,7 +316,7 @@ sub command_oneline { my $line = <$fh>; defined $line and chomp $line; try { - _cmd_close($fh, $ctx); + _cmd_close($ctx, $fh); } catch Git::Error::Command with { # Pepper with the output: my $E = shift; @@ -383,7 +384,7 @@ sub command_input_pipe { sub command_close_pipe { my ($self, $fh, $ctx) = _maybe_self(@_); $ctx ||= ''; - _cmd_close($fh, $ctx); + _cmd_close($ctx, $fh); } =item command_bidi_pipe ( COMMAND [, ARGUMENTS... ] ) @@ -420,7 +421,7 @@ sub command_bidi_pipe { is: my ($pid, $in, $out, $ctx) = $r->command_bidi_pipe('cat-file --batch-check'); - print "000000000\n" $out; + print $out "000000000\n"; while (<$in>) { ... } $r->command_close_bidi_pipe($pid, $in, $out, $ctx); @@ -428,23 +429,26 @@ sub command_bidi_pipe { currently it is simply the command name but in future the context might have more complicated structure. +C and C may be C if they have been closed prior to +calling this function. This may be useful in a query-response type of +commands where caller first writes a query and later reads response, eg: + + my ($pid, $in, $out, $ctx) = $r->command_bidi_pipe('cat-file --batch-check'); + print $out "000000000\n"; + close $out; + while (<$in>) { ... } + $r->command_close_bidi_pipe($pid, $in, undef, $ctx); + +This idiom may prevent potential dead locks caused by data sent to the output +pipe not being flushed and thus not reaching the executed command. + =cut sub command_close_bidi_pipe { local $?; - my ($pid, $in, $out, $ctx) = @_; - foreach my $fh ($in, $out) { - unless (close $fh) { - if ($!) { - carp "error closing pipe: $!"; - } elsif ($? >> 8) { - throw Git::Error::Command($ctx, $? >>8); - } - } - } - + my ($self, $pid, $in, $out, $ctx) = _maybe_self(@_); + _cmd_close($ctx, (grep { defined } ($in, $out))); waitpid $pid, 0; - if ($? >> 8) { throw Git::Error::Command($ctx, $? >>8); } @@ -965,20 +969,22 @@ sub cat_blob { my $size = $1; my $blob; - my $bytesRead = 0; + my $bytesLeft = $size; while (1) { - my $bytesLeft = $size - $bytesRead; last unless $bytesLeft; my $bytesToRead = $bytesLeft < 1024 ? $bytesLeft : 1024; - my $read = read($in, $blob, $bytesToRead, $bytesRead); + my $read = read($in, $blob, $bytesToRead); unless (defined($read)) { $self->_close_cat_blob(); throw Error::Simple("in pipe went bad"); } - - $bytesRead += $read; + unless (print $fh $blob) { + $self->_close_cat_blob(); + throw Error::Simple("couldn't write to passed in filehandle"); + } + $bytesLeft -= $read; } # Skip past the trailing newline. @@ -993,11 +999,6 @@ sub cat_blob { throw Error::Simple("didn't find newline after blob"); } - unless (print $fh $blob) { - $self->_close_cat_blob(); - throw Error::Simple("couldn't write to passed in filehandle"); - } - return $size; } @@ -1023,6 +1024,156 @@ sub _close_cat_blob { } +=item credential_read( FILEHANDLE ) + +Reads credential key-value pairs from C. Reading stops at EOF or +when an empty line is encountered. Each line must be of the form C +with a non-empty key. Function returns hash with all read values. Any white +space (other than new-line character) is preserved. + +=cut + +sub credential_read { + my ($self, $reader) = _maybe_self(@_); + my %credential; + while (<$reader>) { + chomp; + if ($_ eq '') { + last; + } elsif (!/^([^=]+)=(.*)$/) { + throw Error::Simple("unable to parse git credential data:\n$_"); + } + $credential{$1} = $2; + } + return %credential; +} + +=item credential_write( FILEHANDLE, CREDENTIAL_HASHREF ) + +Writes credential key-value pairs from hash referenced by +C to C. Keys and values cannot contain +new-lines or NUL bytes characters, and key cannot contain equal signs nor be +empty (if they do Error::Simple is thrown). Any white space is preserved. If +value for a key is C, it will be skipped. + +If C<'url'> key exists it will be written first. (All the other key-value +pairs are written in sorted order but you should not depend on that). Once +all lines are written, an empty line is printed. + +=cut + +sub credential_write { + my ($self, $writer, $credential) = _maybe_self(@_); + my ($key, $value); + + # Check if $credential is valid prior to writing anything + while (($key, $value) = each %$credential) { + if (!defined $key || !length $key) { + throw Error::Simple("credential key empty or undefined"); + } elsif ($key =~ /[=\n\0]/) { + throw Error::Simple("credential key contains invalid characters: $key"); + } elsif (defined $value && $value =~ /[\n\0]/) { + throw Error::Simple("credential value for key=$key contains invalid characters: $value"); + } + } + + for $key (sort { + # url overwrites other fields, so it must come first + return -1 if $a eq 'url'; + return 1 if $b eq 'url'; + return $a cmp $b; + } keys %$credential) { + if (defined $credential->{$key}) { + print $writer $key, '=', $credential->{$key}, "\n"; + } + } + print $writer "\n"; +} + +sub _credential_run { + my ($self, $credential, $op) = _maybe_self(@_); + my ($pid, $reader, $writer, $ctx) = command_bidi_pipe('credential', $op); + + credential_write $writer, $credential; + close $writer; + + if ($op eq "fill") { + %$credential = credential_read $reader; + } + if (<$reader>) { + throw Error::Simple("unexpected output from git credential $op response:\n$_\n"); + } + + command_close_bidi_pipe($pid, $reader, undef, $ctx); +} + +=item credential( CREDENTIAL_HASHREF [, OPERATION ] ) + +=item credential( CREDENTIAL_HASHREF, CODE ) + +Executes C for a given set of credentials and specified +operation. In both forms C needs to be a reference to +a hash which stores credentials. Under certain conditions the hash can +change. + +In the first form, C can be C<'fill'>, C<'approve'> or C<'reject'>, +and function will execute corresponding C sub-command. If +it's omitted C<'fill'> is assumed. In case of C<'fill'> the values stored in +C will be changed to the ones returned by the C command. The usual usage would look something like: + + my %cred = ( + 'protocol' => 'https', + 'host' => 'example.com', + 'username' => 'bob' + ); + Git::credential \%cred; + if (try_to_authenticate($cred{'username'}, $cred{'password'})) { + Git::credential \%cred, 'approve'; + ... do more stuff ... + } else { + Git::credential \%cred, 'reject'; + } + +In the second form, C needs to be a reference to a subroutine. The +function will execute C to fill the provided credential +hash, then call C with C as the sole argument. If +C's return value is defined, the function will execute C (if return value yields true) or C (if return +value is false). If the return value is undef, nothing at all is executed; +this is useful, for example, if the credential could neither be verified nor +rejected due to an unrelated network error. The return value is the same as +what C returns. With this form, the usage might look as follows: + + if (Git::credential { + 'protocol' => 'https', + 'host' => 'example.com', + 'username' => 'bob' + }, sub { + my $cred = shift; + return !!try_to_authenticate($cred->{'username'}, + $cred->{'password'}); + }) { + ... do more stuff ... + } + +=cut + +sub credential { + my ($self, $credential, $op_or_code) = (_maybe_self(@_), 'fill'); + + if ('CODE' eq ref $op_or_code) { + _credential_run $credential, 'fill'; + my $ret = $op_or_code->($credential); + if (defined $ret) { + _credential_run $credential, $ret ? 'approve' : 'reject'; + } + return $ret; + } else { + _credential_run $credential, $op_or_code; + } +} + { # %TEMP_* Lexical Context my (%TEMP_FILEMAP, %TEMP_FILES); @@ -1378,9 +1529,11 @@ sub _setup_git_cmd_env { # Close pipe to a subprocess. sub _cmd_close { - my ($fh, $ctx) = @_; - if (not close $fh) { - if ($!) { + my $ctx = shift @_; + foreach my $fh (@_) { + if (close $fh) { + # nop + } elsif ($!) { # It's just close, no point in fatalities carp "error closing pipe: $!"; } elsif ($? >> 8) { diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index 0ebc68ac7e..5273ee8867 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -1493,13 +1493,18 @@ sub lookup_svn_merge { my @merged_commit_ranges; # find the tip for my $range ( @ranges ) { + if ($range =~ /[*]$/) { + warn "W: Ignoring partial merge in svn:mergeinfo " + ."dirprop: $source:$range\n"; + next; + } my ($bottom, $top) = split "-", $range; $top ||= $bottom; my $bottom_commit = $gs->find_rev_after( $bottom, 1, $top ); my $top_commit = $gs->find_rev_before( $top, 1, $bottom ); unless ($top_commit and $bottom_commit) { - warn "W:unknown path/rev in svn:mergeinfo " + warn "W: unknown path/rev in svn:mergeinfo " ."dirprop: $source:$range\n"; next; } diff --git a/po/de.po b/po/de.po index d309415bb8..83c30b1587 100644 --- a/po/de.po +++ b/po/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: git 1.8.2\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2013-01-25 12:33+0800\n" +"POT-Creation-Date: 2013-03-05 12:36+0800\n" "PO-Revision-Date: 2012-10-02 19:35+0200\n" "Last-Translator: Ralf Thielow \n" "Language-Team: German <>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: advice.c:45 +#: advice.c:49 #, c-format msgid "hint: %.*s\n" msgstr "Hinweis: %.*s\n" @@ -26,7 +26,7 @@ msgstr "Hinweis: %.*s\n" #. * Message used both when 'git commit' fails and when #. * other commands doing a merge do. #. -#: advice.c:75 +#: advice.c:79 msgid "" "Fix them up in the work tree,\n" "and then use 'git add/rm ' as\n" @@ -73,11 +73,11 @@ msgstr "Prefix" msgid "prepend prefix to each pathname in the archive" msgstr "stellt einen Präfix vor jeden Pfadnamen in der Ausgabe" -#: archive.c:326 builtin/archive.c:91 builtin/blame.c:2380 -#: builtin/blame.c:2381 builtin/config.c:55 builtin/fast-export.c:653 +#: archive.c:326 builtin/archive.c:91 builtin/blame.c:2366 +#: builtin/blame.c:2367 builtin/config.c:55 builtin/fast-export.c:653 #: builtin/fast-export.c:655 builtin/grep.c:715 builtin/hash-object.c:77 -#: builtin/ls-files.c:494 builtin/ls-files.c:497 builtin/notes.c:540 -#: builtin/notes.c:697 builtin/read-tree.c:107 parse-options.h:149 +#: builtin/ls-files.c:497 builtin/ls-files.c:500 builtin/notes.c:536 +#: builtin/notes.c:693 builtin/read-tree.c:107 parse-options.h:149 msgid "file" msgstr "Datei" @@ -117,7 +117,7 @@ msgstr "Projektarchiv" msgid "retrieve the archive from remote repository " msgstr "ruft das Archiv von externem Projektarchiv ab" -#: archive.c:347 builtin/archive.c:95 builtin/notes.c:619 +#: archive.c:347 builtin/archive.c:95 builtin/notes.c:615 msgid "command" msgstr "Programm" @@ -127,10 +127,10 @@ msgstr "Pfad zum externen \"git-upload-archive\"-Programm" #: attr.c:259 msgid "" -"Negative patterns are forbidden in git attributes\n" +"Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." msgstr "" -"Verneinende Muster sind in Git-Attributen verboten.\n" +"Verneinende Muster werden in Git-Attributen ignoriert.\n" "Benutzen Sie '\\!' für führende Ausrufezeichen." #: bundle.c:36 @@ -306,23 +306,23 @@ msgid_plural "%lu years ago" msgstr[0] "vor %lu Jahr" msgstr[1] "vor %lu Jahren" -#: diff.c:111 +#: diff.c:112 #, c-format msgid " Failed to parse dirstat cut-off percentage '%s'\n" msgstr "" " Fehler beim Parsen des abgeschnittenen \"dirstat\" Prozentsatzes '%s'\n" -#: diff.c:116 +#: diff.c:117 #, c-format msgid " Unknown dirstat parameter '%s'\n" msgstr " Unbekannter \"dirstat\" Parameter '%s'\n" -#: diff.c:194 +#: diff.c:210 #, c-format msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "Unbekannter Wert in Konfigurationsvariable 'diff.dirstat': '%s'" -#: diff.c:237 +#: diff.c:260 #, c-format msgid "" "Found errors in 'diff.dirstat' config variable:\n" @@ -331,7 +331,7 @@ msgstr "" "Fehler in 'diff.dirstat' Konfigurationsvariable gefunden:\n" "%s" -#: diff.c:3494 +#: diff.c:3468 #, c-format msgid "" "Failed to parse --dirstat/-X option parameter:\n" @@ -340,12 +340,12 @@ msgstr "" "Fehler beim Parsen des --dirstat/-X Optionsparameters:\n" "%s" -#: diff.c:3508 +#: diff.c:3482 #, c-format msgid "Failed to parse --submodule option parameter: '%s'" msgstr "Fehler beim Parsen des --submodule Optionsparameters: '%s'" -#: gpg-interface.c:59 +#: gpg-interface.c:59 gpg-interface.c:127 msgid "could not run gpg." msgstr "konnte gpg nicht ausführen" @@ -357,6 +357,16 @@ msgstr "gpg hat die Daten nicht akzeptiert" msgid "gpg failed to sign the data" msgstr "gpg beim Signieren der Daten fehlgeschlagen" +#: gpg-interface.c:112 +#, c-format +msgid "could not create temporary file '%s': %s" +msgstr "konnte temporäre Datei '%s' nicht erstellen: %s" + +#: gpg-interface.c:115 +#, c-format +msgid "failed writing detached signature to '%s': %s" +msgstr "Fehler beim Schreiben der Signatur nach '%s': %s" + #: grep.c:1622 #, c-format msgid "'%s': unable to read %s" @@ -381,7 +391,11 @@ msgstr "Vorhandene Git-Kommandos in '%s'" msgid "git commands available from elsewhere on your $PATH" msgstr "Vorhandene Git-Kommandos irgendwo in Ihrem $PATH" -#: help.c:275 +#: help.c:235 +msgid "The most commonly used git commands are:" +msgstr "Die allgemein verwendeten Git-Kommandos sind:" + +#: help.c:292 #, c-format msgid "" "'%s' appears to be a git command, but we were not\n" @@ -390,11 +404,11 @@ msgstr "" "'%s' scheint ein git-Kommando zu sein, konnte aber\n" "nicht ausgeführt werden. Vielleicht ist git-%s fehlerhaft?" -#: help.c:332 +#: help.c:349 msgid "Uh oh. Your system reports no Git commands at all." msgstr "Uh oh. Keine Git-Kommandos auf Ihrem System vorhanden." -#: help.c:354 +#: help.c:371 #, c-format msgid "" "WARNING: You called a Git command named '%s', which does not exist.\n" @@ -403,17 +417,17 @@ msgstr "" "Warnung: Sie haben das nicht existierende Git-Kommando '%s' ausgeführt.\n" "Setze fort unter der Annahme, dass Sie '%s' gemeint haben" -#: help.c:359 +#: help.c:376 #, c-format msgid "in %0.1f seconds automatically..." msgstr "automatisch in %0.1f Sekunden..." -#: help.c:366 +#: help.c:383 #, c-format msgid "git: '%s' is not a git command. See 'git --help'." msgstr "git: '%s' ist kein Git-Kommando. Siehe 'git --help'." -#: help.c:370 +#: help.c:387 msgid "" "\n" "Did you mean this?" @@ -694,39 +708,53 @@ msgstr "Konnte Objekt '%s' nicht parsen." msgid "Unable to write index." msgstr "Konnte Bereitstellung nicht schreiben." -#: parse-options.c:485 +#: parse-options.c:489 msgid "..." msgstr "..." -#: parse-options.c:503 +#: parse-options.c:507 #, c-format msgid "usage: %s" msgstr "Verwendung: %s" #. TRANSLATORS: the colon here should align with the #. one in "usage: %s" translation -#: parse-options.c:507 +#: parse-options.c:511 #, c-format msgid " or: %s" msgstr " oder: %s" -#: parse-options.c:510 +#: parse-options.c:514 #, c-format msgid " %s" msgstr " %s" -#: remote.c:1686 +#: parse-options.c:548 +msgid "-NUM" +msgstr "-NUM" + +#: pathspec.c:83 +#, c-format +msgid "Path '%s' is in submodule '%.*s'" +msgstr "Pfad '%s' befindet sich in Unterprojekt '%.*s'" + +#: pathspec.c:99 +#, c-format +msgid "'%s' is beyond a symbolic link" +msgstr "'%s' ist über einem symbolischen Link" + +#: remote.c:1653 #, c-format msgid "Your branch is ahead of '%s' by %d commit.\n" msgid_plural "Your branch is ahead of '%s' by %d commits.\n" msgstr[0] "Ihr Zweig ist vor '%s' um %d Version.\n" msgstr[1] "Ihr Zweig ist vor '%s' um %d Versionen.\n" -#: remote.c:1692 +#: remote.c:1659 msgid " (use \"git push\" to publish your local commits)\n" msgstr " (benutzen Sie \"git push\" um lokalen Versionen herauszubringen)\n" -#: remote.c:1695 +#: remote.c:1662 #, c-format msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n" msgid_plural "" @@ -737,12 +765,12 @@ msgstr[1] "" "Ihr Zweig ist zu '%s' um %d Versionen hinterher, und kann vorgespult " "werden.\n" -#: remote.c:1703 +#: remote.c:1670 msgid " (use \"git pull\" to update your local branch)\n" msgstr "" " (benutzen Sie \"git pull\" um Ihren lokalen Zweig zu aktualisieren)\n" -#: remote.c:1706 +#: remote.c:1673 #, c-format msgid "" "Your branch and '%s' have diverged,\n" @@ -757,20 +785,20 @@ msgstr[1] "" "Ihr Zweig und '%s' sind divergiert,\n" "und haben jeweils %d und %d unterschiedliche Versionen.\n" -#: remote.c:1716 +#: remote.c:1683 msgid " (use \"git pull\" to merge the remote branch into yours)\n" msgstr "" " (benutzen Sie \"git pull\" um Ihren Zweig mit dem externen " "zusammenzuführen)\n" -#: sequencer.c:123 builtin/merge.c:761 builtin/merge.c:875 builtin/merge.c:985 -#: builtin/merge.c:995 +#: sequencer.c:123 builtin/merge.c:761 builtin/merge.c:874 builtin/merge.c:984 +#: builtin/merge.c:994 #, c-format msgid "Could not open '%s' for writing" msgstr "Konnte '%s' nicht zum Schreiben öffnen." -#: sequencer.c:125 builtin/merge.c:333 builtin/merge.c:764 builtin/merge.c:987 -#: builtin/merge.c:1000 +#: sequencer.c:125 builtin/merge.c:333 builtin/merge.c:764 builtin/merge.c:986 +#: builtin/merge.c:999 #, c-format msgid "Could not write to '%s'" msgstr "Konnte nicht nach '%s' schreiben." @@ -973,7 +1001,7 @@ msgstr "kann Zweigspitze (HEAD) nicht auflösen" msgid "cannot abort from a branch yet to be born" msgstr "kann nicht abbrechen: bin auf einem Zweig, der noch geboren wird" -#: sequencer.c:821 builtin/apply.c:4016 +#: sequencer.c:821 builtin/apply.c:4056 #, c-format msgid "cannot open %s: %s" msgstr "Kann %s nicht öffnen: %s" @@ -1202,160 +1230,185 @@ msgstr "nicht zusammengeführt: %s" msgid "bug: unhandled diff status %c" msgstr "Fehler: unbehandelter Differenz-Status %c" -#: wt-status.c:787 +#: wt-status.c:789 msgid "You have unmerged paths." msgstr "Sie haben nicht zusammengeführte Pfade." -#: wt-status.c:790 wt-status.c:914 +#: wt-status.c:792 wt-status.c:944 msgid " (fix conflicts and run \"git commit\")" msgstr " (beheben Sie die Konflikte und führen Sie \"git commit\" aus)" -#: wt-status.c:793 +#: wt-status.c:795 msgid "All conflicts fixed but you are still merging." msgstr "" "Alle Konflikte sind behoben, aber Sie sind immer noch beim Zusammenführen." -#: wt-status.c:796 +#: wt-status.c:798 msgid " (use \"git commit\" to conclude merge)" msgstr " (benutzen Sie \"git commit\" um die Zusammenführung abzuschließen)" -#: wt-status.c:806 +#: wt-status.c:808 msgid "You are in the middle of an am session." msgstr "Eine \"am\"-Sitzung ist im Gange." -#: wt-status.c:809 +#: wt-status.c:811 msgid "The current patch is empty." msgstr "Der aktuelle Patch ist leer." -#: wt-status.c:813 +#: wt-status.c:815 msgid " (fix conflicts and then run \"git am --resolved\")" msgstr "" " (beheben Sie die Konflikte und führen Sie dann \"git am --resolved\" aus)" -#: wt-status.c:815 +#: wt-status.c:817 msgid " (use \"git am --skip\" to skip this patch)" msgstr " (benutzen Sie \"git am --skip\" um diesen Patch auszulassen)" -#: wt-status.c:817 +#: wt-status.c:819 msgid " (use \"git am --abort\" to restore the original branch)" msgstr "" " (benutzen Sie \"git am --abort\" um den ursprünglichen Zweig " "wiederherzustellen)" -#: wt-status.c:875 wt-status.c:885 +#: wt-status.c:879 wt-status.c:896 +#, c-format +msgid "You are currently rebasing branch '%s' on '%s'." +msgstr "Sie sind gerade beim Neuaufbau von Zweig '%s' auf '%s'." + +#: wt-status.c:884 wt-status.c:901 msgid "You are currently rebasing." msgstr "Sie sind gerade beim Neuaufbau." -#: wt-status.c:878 +#: wt-status.c:887 msgid " (fix conflicts and then run \"git rebase --continue\")" msgstr "" " (beheben Sie die Konflikte und führen Sie dann \"git rebase --continue\" " "aus)" -#: wt-status.c:880 +#: wt-status.c:889 msgid " (use \"git rebase --skip\" to skip this patch)" msgstr " (benutzen Sie \"git rebase --skip\" um diesen Patch auszulassen)" -#: wt-status.c:882 +#: wt-status.c:891 msgid " (use \"git rebase --abort\" to check out the original branch)" msgstr "" " (benutzen Sie \"git rebase --abort\" um den ursprünglichen Zweig " "auszuchecken)" -#: wt-status.c:888 +#: wt-status.c:904 msgid " (all conflicts fixed: run \"git rebase --continue\")" msgstr " (alle Konflikte behoben: führen Sie \"git rebase --continue\" aus)" -#: wt-status.c:890 +#: wt-status.c:908 +#, c-format +msgid "" +"You are currently splitting a commit while rebasing branch '%s' on '%s'." +msgstr "" +"Sie teilen gerade eine Version auf, während ein Neuaufbau von Zweig '%s' auf " +"'%s' im Gange ist." + +#: wt-status.c:913 msgid "You are currently splitting a commit during a rebase." msgstr "Sie teilen gerade eine Version während eines Neuaufbaus auf." -#: wt-status.c:893 +#: wt-status.c:916 msgid " (Once your working directory is clean, run \"git rebase --continue\")" msgstr "" " (Sobald Ihr Arbeitsverzeichnis sauber ist, führen Sie \"git rebase --" "continue\" aus)" -#: wt-status.c:895 +#: wt-status.c:920 +#, c-format +msgid "You are currently editing a commit while rebasing branch '%s' on '%s'." +msgstr "" +"Sie editieren gerade eine Version während eines Neuaufbaus von Zweig '%s' " +"auf '%s'." + +#: wt-status.c:925 msgid "You are currently editing a commit during a rebase." msgstr "Sie editieren gerade eine Version während eines Neuaufbaus." -#: wt-status.c:898 +#: wt-status.c:928 msgid " (use \"git commit --amend\" to amend the current commit)" msgstr "" " (benutzen Sie \"git commit --amend\" um die aktuelle Version nachzubessern)" -#: wt-status.c:900 +#: wt-status.c:930 msgid "" " (use \"git rebase --continue\" once you are satisfied with your changes)" msgstr "" " (benutzen Sie \"git rebase --continue\" sobald Ihre Änderungen " "abgeschlossen sind)" -#: wt-status.c:910 +#: wt-status.c:940 msgid "You are currently cherry-picking." msgstr "Sie führen gerade \"cherry-pick\" aus." -#: wt-status.c:917 +#: wt-status.c:947 msgid " (all conflicts fixed: run \"git commit\")" msgstr " (alle Konflikte behoben: führen Sie \"git commit\" aus)" -#: wt-status.c:926 +#: wt-status.c:958 +#, c-format +msgid "You are currently bisecting branch '%s'." +msgstr "Sie sind gerade bei einer binären Suche in Zweig '%s'." + +#: wt-status.c:962 msgid "You are currently bisecting." -msgstr "Sie sind gerade beim Halbieren." +msgstr "Sie sind gerade bei einer binären Suche." -#: wt-status.c:929 +#: wt-status.c:965 msgid " (use \"git bisect reset\" to get back to the original branch)" msgstr "" " (benutzen Sie \"git bisect reset\" um zum ursprünglichen Zweig " "zurückzukehren)" -#: wt-status.c:980 +#: wt-status.c:1064 msgid "On branch " msgstr "Auf Zweig " -#: wt-status.c:987 +#: wt-status.c:1071 msgid "Not currently on any branch." msgstr "Im Moment auf keinem Zweig." -#: wt-status.c:999 +#: wt-status.c:1083 msgid "Initial commit" msgstr "Initiale Version" -#: wt-status.c:1013 +#: wt-status.c:1097 msgid "Untracked files" msgstr "Unbeobachtete Dateien" -#: wt-status.c:1015 +#: wt-status.c:1099 msgid "Ignored files" msgstr "Ignorierte Dateien" -#: wt-status.c:1017 +#: wt-status.c:1101 #, c-format msgid "Untracked files not listed%s" msgstr "Unbeobachtete Dateien nicht aufgelistet%s" -#: wt-status.c:1019 +#: wt-status.c:1103 msgid " (use -u option to show untracked files)" msgstr " (benutzen Sie die Option -u um unbeobachteten Dateien anzuzeigen)" -#: wt-status.c:1025 +#: wt-status.c:1109 msgid "No changes" msgstr "Keine Änderungen" -#: wt-status.c:1030 +#: wt-status.c:1114 #, c-format msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" msgstr "" "keine Änderungen zum Eintragen hinzugefügt (benutzen Sie \"git add\" und/" "oder \"git commit -a\")\n" -#: wt-status.c:1033 +#: wt-status.c:1117 #, c-format msgid "no changes added to commit\n" msgstr "keine Änderungen zum Eintragen hinzugefügt\n" -#: wt-status.c:1036 +#: wt-status.c:1120 #, c-format msgid "" "nothing added to commit but untracked files present (use \"git add\" to " @@ -1364,199 +1417,239 @@ msgstr "" "nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien " "(benutzen Sie \"git add\" zum Beobachten)\n" -#: wt-status.c:1039 +#: wt-status.c:1123 #, c-format msgid "nothing added to commit but untracked files present\n" msgstr "nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien\n" -#: wt-status.c:1042 +#: wt-status.c:1126 #, c-format msgid "nothing to commit (create/copy files and use \"git add\" to track)\n" msgstr "" "nichts einzutragen (Erstellen/Kopieren Sie Dateien und benutzen Sie \"git add" "\" zum Beobachten)\n" -#: wt-status.c:1045 wt-status.c:1050 +#: wt-status.c:1129 wt-status.c:1134 #, c-format msgid "nothing to commit\n" msgstr "nichts einzutragen\n" -#: wt-status.c:1048 +#: wt-status.c:1132 #, c-format msgid "nothing to commit (use -u to show untracked files)\n" msgstr "" "nichts einzutragen (benutzen Sie die Option -u, um unbeobachtete Dateien " "anzuzeigen)\n" -#: wt-status.c:1052 +#: wt-status.c:1136 #, c-format msgid "nothing to commit, working directory clean\n" msgstr "nichts einzutragen, Arbeitsverzeichnis sauber\n" -#: wt-status.c:1160 +#: wt-status.c:1244 msgid "HEAD (no branch)" msgstr "HEAD (kein Zweig)" -#: wt-status.c:1166 +#: wt-status.c:1250 msgid "Initial commit on " msgstr "Initiale Version auf " -#: wt-status.c:1181 +#: wt-status.c:1265 msgid "behind " msgstr "hinterher " -#: wt-status.c:1184 wt-status.c:1187 +#: wt-status.c:1268 wt-status.c:1271 msgid "ahead " msgstr "voraus " -#: wt-status.c:1189 +#: wt-status.c:1273 msgid ", behind " msgstr ", hinterher " -#: builtin/add.c:19 -msgid "git add [options] [--] ..." -msgstr "git add [Optionen] [--] [...]" +#: compat/precompose_utf8.c:58 builtin/clone.c:341 +#, c-format +msgid "failed to unlink '%s'" +msgstr "Konnte '%s' nicht entfernen." + +#: builtin/add.c:20 +msgid "git add [options] [--] ..." +msgstr "git add [Optionen] [--] [...]" -#: builtin/add.c:62 +#: builtin/add.c:63 #, c-format msgid "unexpected diff status %c" msgstr "unerwarteter Differenz-Status %c" -#: builtin/add.c:67 builtin/commit.c:231 +#: builtin/add.c:68 builtin/commit.c:231 msgid "updating files failed" msgstr "Aktualisierung der Dateien fehlgeschlagen" -#: builtin/add.c:77 +#: builtin/add.c:78 #, c-format msgid "remove '%s'\n" msgstr "lösche '%s'\n" -#: builtin/add.c:176 -#, c-format -msgid "Path '%s' is in submodule '%.*s'" -msgstr "Pfad '%s' befindet sich in Unterprojekt '%.*s'" - -#: builtin/add.c:192 +#: builtin/add.c:148 msgid "Unstaged changes after refreshing the index:" msgstr "" "Nicht bereitgestellte Änderungen nach Aktualisierung der Bereitstellung:" -#: builtin/add.c:195 builtin/add.c:460 builtin/rm.c:275 +#: builtin/add.c:151 builtin/add.c:460 builtin/rm.c:275 #, c-format msgid "pathspec '%s' did not match any files" msgstr "Pfadspezifikation '%s' stimmt mit keinen Dateien überein" -#: builtin/add.c:209 -#, c-format -msgid "'%s' is beyond a symbolic link" -msgstr "'%s' ist über einem symbolischen Link" - -#: builtin/add.c:276 +#: builtin/add.c:234 msgid "Could not read the index" msgstr "Konnte die Bereitstellung nicht lesen" -#: builtin/add.c:286 +#: builtin/add.c:244 #, c-format msgid "Could not open '%s' for writing." msgstr "Konnte '%s' nicht zum Schreiben öffnen." -#: builtin/add.c:290 +#: builtin/add.c:248 msgid "Could not write patch" msgstr "Konnte Patch nicht schreiben" -#: builtin/add.c:295 +#: builtin/add.c:253 #, c-format msgid "Could not stat '%s'" msgstr "Konnte Verzeichnis '%s' nicht lesen" -#: builtin/add.c:297 +#: builtin/add.c:255 msgid "Empty patch. Aborted." msgstr "Leerer Patch. Abgebrochen." -#: builtin/add.c:303 +#: builtin/add.c:261 #, c-format msgid "Could not apply '%s'" msgstr "Konnte '%s' nicht anwenden." -#: builtin/add.c:313 +#: builtin/add.c:271 msgid "The following paths are ignored by one of your .gitignore files:\n" msgstr "" "Die folgenden Pfade werden durch eine Ihrer \".gitignore\" Dateien " "ignoriert:\n" -#: builtin/add.c:319 builtin/clean.c:160 builtin/fetch.c:78 builtin/mv.c:63 -#: builtin/prune-packed.c:76 builtin/push.c:396 builtin/remote.c:1253 +#: builtin/add.c:277 builtin/clean.c:161 builtin/fetch.c:78 builtin/mv.c:63 +#: builtin/prune-packed.c:76 builtin/push.c:425 builtin/remote.c:1253 #: builtin/rm.c:206 msgid "dry run" msgstr "Probelauf" -#: builtin/add.c:320 builtin/apply.c:4365 builtin/commit.c:1160 -#: builtin/count-objects.c:82 builtin/fsck.c:613 builtin/log.c:1522 -#: builtin/mv.c:62 builtin/read-tree.c:112 +#: builtin/add.c:278 builtin/apply.c:4405 builtin/check-ignore.c:19 +#: builtin/commit.c:1150 builtin/count-objects.c:82 builtin/fsck.c:613 +#: builtin/log.c:1522 builtin/mv.c:62 builtin/read-tree.c:112 msgid "be verbose" msgstr "erweiterte Ausgaben" -#: builtin/add.c:322 +#: builtin/add.c:280 msgid "interactive picking" msgstr "interaktives Auswählen" -#: builtin/add.c:323 builtin/checkout.c:1031 builtin/reset.c:258 +#: builtin/add.c:281 builtin/checkout.c:1031 builtin/reset.c:258 msgid "select hunks interactively" msgstr "interaktiv Bereiche auswählen" -#: builtin/add.c:324 +#: builtin/add.c:282 msgid "edit current diff and apply" msgstr "aktuelle Unterschiede editieren und anwenden" -#: builtin/add.c:325 +#: builtin/add.c:283 msgid "allow adding otherwise ignored files" msgstr "erlaubt das Hinzufügen andernfalls ignorierter Dateien" -#: builtin/add.c:326 +#: builtin/add.c:284 msgid "update tracked files" msgstr "aktualisiert beobachtete Dateien" -#: builtin/add.c:327 +#: builtin/add.c:285 msgid "record only the fact that the path will be added later" msgstr "speichert nur, dass der Pfad später hinzugefügt werden soll" -#: builtin/add.c:328 +#: builtin/add.c:286 msgid "add changes from all tracked and untracked files" msgstr "" "fügt Änderungen von allen beobachteten und unbeobachteten Dateien hinzu" -#: builtin/add.c:329 +#: builtin/add.c:287 msgid "don't add, only refresh the index" msgstr "fügt nichts hinzu, aktualisiert nur die Bereitstellung" -#: builtin/add.c:330 +#: builtin/add.c:288 msgid "just skip files which cannot be added because of errors" msgstr "" "überspringt Dateien, die aufgrund von Fehlern nicht hinzugefügt werden " "konnten" -#: builtin/add.c:331 +#: builtin/add.c:289 msgid "check if - even missing - files are ignored in dry run" msgstr "prüft ob - auch fehlende - Dateien im Probelauf ignoriert werden" -#: builtin/add.c:353 +#: builtin/add.c:311 #, c-format msgid "Use -f if you really want to add them.\n" msgstr "Verwenden Sie -f wenn Sie diese wirklich hinzufügen möchten.\n" -#: builtin/add.c:354 +#: builtin/add.c:312 msgid "no files added" msgstr "keine Dateien hinzugefügt" -#: builtin/add.c:360 +#: builtin/add.c:318 msgid "adding files failed" msgstr "Hinzufügen von Dateien fehlgeschlagen" -#: builtin/add.c:392 +#. +#. * To be consistent with "git add -p" and most Git +#. * commands, we should default to being tree-wide, but +#. * this is not the original behavior and can't be +#. * changed until users trained themselves not to type +#. * "git add -u" or "git add -A". For now, we warn and +#. * keep the old behavior. Later, this warning can be +#. * turned into a die(...), and eventually we may +#. * reallow the command with a new behavior. +#. +#: builtin/add.c:335 +#, c-format +msgid "" +"The behavior of 'git add %s (or %s)' with no path argument from a\n" +"subdirectory of the tree will change in Git 2.0 and should not be used " +"anymore.\n" +"To add content for the whole tree, run:\n" +"\n" +" git add %s :/\n" +" (or git add %s :/)\n" +"\n" +"To restrict the command to the current directory, run:\n" +"\n" +" git add %s .\n" +" (or git add %s .)\n" +"\n" +"With the current Git version, the command is restricted to the current " +"directory." +msgstr "" +"Das Verhalten von 'git add %s (oder %s)' ohne ein Pfad-Argument von\n" +"einem Unterverzeichnis aus wird in Git 2.0 geändert und sollte nicht\n" +"mehr verwendet werden.\n" +"Um Dateien des gesamten Projektverzeichnisses hinzuzufügen, führen Sie aus:\n" +"\n" +" git add %s :/\n" +" (oder git add %s :/)\n" +"\n" +"Zur Einschränkung auf das aktuelle Verzeichnis führen Sie aus:\n" +"\n" +" git add %s .\n" +" (oder git add %s .)\n" +"\n" +"Mit der aktuellen Version von Git ist das Kommando auf das aktuelle\n" +"Verzeichnis beschränkt." + +#: builtin/add.c:381 msgid "-A and -u are mutually incompatible" msgstr "Die Optionen -A und -u sind zueinander inkompatibel." -#: builtin/add.c:394 +#: builtin/add.c:383 msgid "Option --ignore-missing can only be used together with --dry-run" msgstr "" "Die Option --ignore-missing kann nur zusammen mit --dry-run verwendet werden." @@ -1571,12 +1664,12 @@ msgstr "Nichts spezifiziert, nichts hinzugefügt.\n" msgid "Maybe you wanted to say 'git add .'?\n" msgstr "Wollten Sie vielleicht 'git add .' sagen?\n" -#: builtin/add.c:421 builtin/clean.c:203 builtin/commit.c:291 builtin/mv.c:82 -#: builtin/rm.c:235 +#: builtin/add.c:421 builtin/check-ignore.c:67 builtin/clean.c:204 +#: builtin/commit.c:291 builtin/mv.c:82 builtin/rm.c:235 msgid "index file corrupt" msgstr "Bereitstellungsdatei beschädigt" -#: builtin/add.c:481 builtin/apply.c:4461 builtin/mv.c:229 builtin/rm.c:370 +#: builtin/add.c:481 builtin/apply.c:4501 builtin/mv.c:229 builtin/rm.c:370 msgid "Unable to write new index file" msgstr "Konnte neue Bereitstellungsdatei nicht schreiben." @@ -1633,17 +1726,17 @@ msgstr "" msgid "git apply: bad git-diff - expected /dev/null on line %d" msgstr "git apply: ungültiges 'git-diff' - erwartete /dev/null in Zeile %d" -#: builtin/apply.c:1420 +#: builtin/apply.c:1422 #, c-format msgid "recount: unexpected line: %.*s" msgstr "recount: unerwartete Zeile: %.*s" -#: builtin/apply.c:1477 +#: builtin/apply.c:1479 #, c-format msgid "patch fragment without header at line %d: %.*s" msgstr "Patch-Fragment ohne Kopfbereich bei Zeile %d: %.*s" -#: builtin/apply.c:1494 +#: builtin/apply.c:1496 #, c-format msgid "" "git diff header lacks filename information when removing %d leading pathname " @@ -1658,66 +1751,66 @@ msgstr[1] "" "Dem Kopfbereich von \"git diff\" fehlen Informationen zum Dateinamen, wenn " "%d vorangestellte Teile des Pfades entfernt werden (Zeile %d)" -#: builtin/apply.c:1654 +#: builtin/apply.c:1656 msgid "new file depends on old contents" msgstr "neue Datei hängt von alten Inhalten ab" -#: builtin/apply.c:1656 +#: builtin/apply.c:1658 msgid "deleted file still has contents" msgstr "entfernte Datei hat noch Inhalte" -#: builtin/apply.c:1682 +#: builtin/apply.c:1684 #, c-format msgid "corrupt patch at line %d" msgstr "fehlerhafter Patch bei Zeile %d" -#: builtin/apply.c:1718 +#: builtin/apply.c:1720 #, c-format msgid "new file %s depends on old contents" msgstr "neue Datei %s hängt von alten Inhalten ab" -#: builtin/apply.c:1720 +#: builtin/apply.c:1722 #, c-format msgid "deleted file %s still has contents" msgstr "entfernte Datei %s hat noch Inhalte" -#: builtin/apply.c:1723 +#: builtin/apply.c:1725 #, c-format msgid "** warning: file %s becomes empty but is not deleted" msgstr "** Warnung: Datei %s wird leer, aber nicht entfernt." -#: builtin/apply.c:1869 +#: builtin/apply.c:1871 #, c-format msgid "corrupt binary patch at line %d: %.*s" msgstr "fehlerhafter Binär-Patch bei Zeile %d: %.*s" #. there has to be one hunk (forward hunk) -#: builtin/apply.c:1898 +#: builtin/apply.c:1900 #, c-format msgid "unrecognized binary patch at line %d" msgstr "nicht erkannter Binär-Patch bei Zeile %d" -#: builtin/apply.c:1984 +#: builtin/apply.c:1986 #, c-format msgid "patch with only garbage at line %d" msgstr "Patch mit nutzlosen Informationen bei Zeile %d" -#: builtin/apply.c:2074 +#: builtin/apply.c:2076 #, c-format msgid "unable to read symlink %s" msgstr "konnte symbolische Verknüpfung %s nicht lesen" -#: builtin/apply.c:2078 +#: builtin/apply.c:2080 #, c-format msgid "unable to open or read %s" msgstr "konnte %s nicht öffnen oder lesen" -#: builtin/apply.c:2682 +#: builtin/apply.c:2684 #, c-format msgid "invalid start of line: '%c'" msgstr "Ungültiger Zeilenanfang: '%c'" -#: builtin/apply.c:2800 +#: builtin/apply.c:2802 #, c-format msgid "Hunk #%d succeeded at %d (offset %d line)." msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." @@ -1725,12 +1818,12 @@ msgstr[0] "Patch-Bereich #%d erfolgreich angewendet bei %d (%d Zeile versetzt)" msgstr[1] "" "Patch-Bereich #%d erfolgreich angewendet bei %d (%d Zeilen versetzt)" -#: builtin/apply.c:2812 +#: builtin/apply.c:2814 #, c-format msgid "Context reduced to (%ld/%ld) to apply fragment at %d" msgstr "Kontext reduziert zu (%ld/%ld) um Patch-Bereich bei %d anzuwenden" -#: builtin/apply.c:2818 +#: builtin/apply.c:2820 #, c-format msgid "" "while searching for:\n" @@ -1739,340 +1832,340 @@ msgstr "" "bei der Suche nach:\n" "%.*s" -#: builtin/apply.c:2837 +#: builtin/apply.c:2839 #, c-format msgid "missing binary patch data for '%s'" msgstr "keine Daten in Binär-Patch für '%s'" -#: builtin/apply.c:2940 +#: builtin/apply.c:2942 #, c-format msgid "binary patch does not apply to '%s'" msgstr "Konnte Binär-Patch nicht auf '%s' anwenden" -#: builtin/apply.c:2946 +#: builtin/apply.c:2948 #, c-format msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" msgstr "" "Binär-Patch für '%s' erzeugt falsches Ergebnis (erwartete %s, bekam %s)" -#: builtin/apply.c:2967 +#: builtin/apply.c:2969 #, c-format msgid "patch failed: %s:%ld" msgstr "Anwendung des Patches fehlgeschlagen: %s:%ld" -#: builtin/apply.c:3089 +#: builtin/apply.c:3091 #, c-format msgid "cannot checkout %s" msgstr "kann %s nicht auschecken" -#: builtin/apply.c:3134 builtin/apply.c:3143 builtin/apply.c:3187 +#: builtin/apply.c:3136 builtin/apply.c:3145 builtin/apply.c:3189 #, c-format msgid "read of %s failed" msgstr "Konnte %s nicht lesen" -#: builtin/apply.c:3167 builtin/apply.c:3389 +#: builtin/apply.c:3169 builtin/apply.c:3391 #, c-format msgid "path %s has been renamed/deleted" msgstr "Pfad %s wurde umbenannt/gelöscht" -#: builtin/apply.c:3248 builtin/apply.c:3403 +#: builtin/apply.c:3250 builtin/apply.c:3405 #, c-format msgid "%s: does not exist in index" msgstr "%s ist nicht bereitgestellt" -#: builtin/apply.c:3252 builtin/apply.c:3395 builtin/apply.c:3417 +#: builtin/apply.c:3254 builtin/apply.c:3397 builtin/apply.c:3419 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: builtin/apply.c:3257 builtin/apply.c:3411 +#: builtin/apply.c:3259 builtin/apply.c:3413 #, c-format msgid "%s: does not match index" msgstr "%s entspricht nicht der Bereitstellung" -#: builtin/apply.c:3359 +#: builtin/apply.c:3361 msgid "removal patch leaves file contents" msgstr "Lösch-Patch hinterlässt Dateiinhalte" -#: builtin/apply.c:3428 +#: builtin/apply.c:3430 #, c-format msgid "%s: wrong type" msgstr "%s: falscher Typ" -#: builtin/apply.c:3430 +#: builtin/apply.c:3432 #, c-format msgid "%s has type %o, expected %o" msgstr "%s ist vom Typ %o, erwartete %o" -#: builtin/apply.c:3531 +#: builtin/apply.c:3533 #, c-format msgid "%s: already exists in index" msgstr "%s ist bereits bereitgestellt" -#: builtin/apply.c:3534 +#: builtin/apply.c:3536 #, c-format msgid "%s: already exists in working directory" msgstr "%s existiert bereits im Arbeitsverzeichnis" -#: builtin/apply.c:3554 +#: builtin/apply.c:3556 #, c-format msgid "new mode (%o) of %s does not match old mode (%o)" msgstr "neuer Modus (%o) von %s entspricht nicht dem alten Modus (%o)" -#: builtin/apply.c:3559 +#: builtin/apply.c:3561 #, c-format msgid "new mode (%o) of %s does not match old mode (%o) of %s" msgstr "neuer Modus (%o) von %s entspricht nicht dem alten Modus (%o) von %s" -#: builtin/apply.c:3567 +#: builtin/apply.c:3569 #, c-format msgid "%s: patch does not apply" msgstr "%s: Patch konnte nicht angewendet werden" -#: builtin/apply.c:3580 +#: builtin/apply.c:3582 #, c-format msgid "Checking patch %s..." msgstr "Prüfe Patch %s..." -#: builtin/apply.c:3635 builtin/checkout.c:215 builtin/reset.c:124 +#: builtin/apply.c:3675 builtin/checkout.c:215 builtin/reset.c:124 #, c-format msgid "make_cache_entry failed for path '%s'" msgstr "make_cache_entry für Pfad '%s' fehlgeschlagen" -#: builtin/apply.c:3778 +#: builtin/apply.c:3818 #, c-format msgid "unable to remove %s from index" msgstr "konnte %s nicht aus der Bereitstellung entfernen" -#: builtin/apply.c:3806 +#: builtin/apply.c:3846 #, c-format msgid "corrupt patch for subproject %s" msgstr "fehlerhafter Patch für Unterprojekt %s" -#: builtin/apply.c:3810 +#: builtin/apply.c:3850 #, c-format msgid "unable to stat newly created file '%s'" msgstr "konnte neu erstellte Datei '%s' nicht lesen" -#: builtin/apply.c:3815 +#: builtin/apply.c:3855 #, c-format msgid "unable to create backing store for newly created file %s" msgstr "kann internen Speicher für eben erstellte Datei %s nicht erzeugen" -#: builtin/apply.c:3818 builtin/apply.c:3926 +#: builtin/apply.c:3858 builtin/apply.c:3966 #, c-format msgid "unable to add cache entry for %s" msgstr "kann für %s keinen Eintrag in den Zwischenspeicher hinzufügen" -#: builtin/apply.c:3851 +#: builtin/apply.c:3891 #, c-format msgid "closing file '%s'" msgstr "schließe Datei '%s'" -#: builtin/apply.c:3900 +#: builtin/apply.c:3940 #, c-format msgid "unable to write file '%s' mode %o" msgstr "konnte Datei '%s' mit Modus %o nicht schreiben" -#: builtin/apply.c:3987 +#: builtin/apply.c:4027 #, c-format msgid "Applied patch %s cleanly." msgstr "Patch %s sauber angewendet" -#: builtin/apply.c:3995 +#: builtin/apply.c:4035 msgid "internal error" msgstr "interner Fehler" #. Say this even without --verbose -#: builtin/apply.c:3998 +#: builtin/apply.c:4038 #, c-format msgid "Applying patch %%s with %d reject..." msgid_plural "Applying patch %%s with %d rejects..." msgstr[0] "Wende Patch %%s mit %d Zurückweisung an..." msgstr[1] "Wende Patch %%s mit %d Zurückweisungen an..." -#: builtin/apply.c:4008 +#: builtin/apply.c:4048 #, c-format msgid "truncating .rej filename to %.*s.rej" msgstr "Verkürze Name von .rej Datei zu %.*s.rej" -#: builtin/apply.c:4029 +#: builtin/apply.c:4069 #, c-format msgid "Hunk #%d applied cleanly." msgstr "Patch-Bereich #%d sauber angewendet." -#: builtin/apply.c:4032 +#: builtin/apply.c:4072 #, c-format msgid "Rejected hunk #%d." msgstr "Patch-Bereich #%d zurückgewiesen." -#: builtin/apply.c:4182 +#: builtin/apply.c:4222 msgid "unrecognized input" msgstr "nicht erkannte Eingabe" -#: builtin/apply.c:4193 +#: builtin/apply.c:4233 msgid "unable to read index file" msgstr "Konnte Bereitstellungsdatei nicht lesen" -#: builtin/apply.c:4312 builtin/apply.c:4315 builtin/clone.c:91 +#: builtin/apply.c:4352 builtin/apply.c:4355 builtin/clone.c:91 #: builtin/fetch.c:63 msgid "path" msgstr "Pfad" -#: builtin/apply.c:4313 +#: builtin/apply.c:4353 msgid "don't apply changes matching the given path" msgstr "wendet keine Änderungen im angegebenen Pfad an" -#: builtin/apply.c:4316 +#: builtin/apply.c:4356 msgid "apply changes matching the given path" msgstr "wendet Änderungen nur im angegebenen Pfad an" -#: builtin/apply.c:4318 +#: builtin/apply.c:4358 msgid "num" msgstr "Anzahl" -#: builtin/apply.c:4319 +#: builtin/apply.c:4359 msgid "remove leading slashes from traditional diff paths" msgstr "" "entfernt vorangestellte Schrägstriche von herkömmlichen " "Differenzpfaden" -#: builtin/apply.c:4322 +#: builtin/apply.c:4362 msgid "ignore additions made by the patch" msgstr "ignoriert hinzugefügte Zeilen des Patches" -#: builtin/apply.c:4324 +#: builtin/apply.c:4364 msgid "instead of applying the patch, output diffstat for the input" msgstr "" "anstatt der Anwendung des Patches, wird der \"diffstat\" für die Eingabe " "ausgegeben" -#: builtin/apply.c:4328 +#: builtin/apply.c:4368 msgid "show number of added and deleted lines in decimal notation" msgstr "" "zeigt die Anzahl von hinzugefügten/entfernten Zeilen in Dezimalnotation" -#: builtin/apply.c:4330 +#: builtin/apply.c:4370 msgid "instead of applying the patch, output a summary for the input" msgstr "" "anstatt der Anwendung des Patches, wird eine Zusammenfassung für die Eingabe " "ausgegeben" -#: builtin/apply.c:4332 +#: builtin/apply.c:4372 msgid "instead of applying the patch, see if the patch is applicable" msgstr "" "anstatt der Anwendung des Patches, zeige ob Patch angewendet werden kann" -#: builtin/apply.c:4334 +#: builtin/apply.c:4374 msgid "make sure the patch is applicable to the current index" msgstr "" "stellt sicher, dass der Patch in der aktuellen Bereitstellung angewendet " "werden kann" -#: builtin/apply.c:4336 +#: builtin/apply.c:4376 msgid "apply a patch without touching the working tree" msgstr "wendet einen Patch an, ohne Änderungen im Arbeitszweig vorzunehmen" -#: builtin/apply.c:4338 +#: builtin/apply.c:4378 msgid "also apply the patch (use with --stat/--summary/--check)" msgstr "wendet den Patch an (Benutzung mit --stat/--summary/--check)" -#: builtin/apply.c:4340 +#: builtin/apply.c:4380 msgid "attempt three-way merge if a patch does not apply" msgstr "" "versucht 3-Wege-Zusammenführung, wenn der Patch nicht angewendet werden " "konnte" -#: builtin/apply.c:4342 +#: builtin/apply.c:4382 msgid "build a temporary index based on embedded index information" msgstr "" "erstellt eine temporäre Bereitstellung basierend auf den integrierten " "Bereitstellungsinformationen" -#: builtin/apply.c:4344 builtin/checkout-index.c:197 builtin/ls-files.c:460 +#: builtin/apply.c:4384 builtin/checkout-index.c:197 builtin/ls-files.c:463 msgid "paths are separated with NUL character" msgstr "Pfade sind getrennt durch NUL Zeichen" -#: builtin/apply.c:4347 +#: builtin/apply.c:4387 msgid "ensure at least lines of context match" msgstr "stellt sicher, dass mindestens Zeilen des Kontextes übereinstimmen" -#: builtin/apply.c:4348 +#: builtin/apply.c:4388 msgid "action" msgstr "Aktion" -#: builtin/apply.c:4349 +#: builtin/apply.c:4389 msgid "detect new or modified lines that have whitespace errors" msgstr "ermittelt neue oder geänderte Zeilen die Fehler in Leerzeichen haben" -#: builtin/apply.c:4352 builtin/apply.c:4355 +#: builtin/apply.c:4392 builtin/apply.c:4395 msgid "ignore changes in whitespace when finding context" msgstr "ignoriert Änderungen in Leerzeichen bei der Suche des Kontextes" -#: builtin/apply.c:4358 +#: builtin/apply.c:4398 msgid "apply the patch in reverse" msgstr "wendet den Patch in umgekehrter Reihenfolge an" -#: builtin/apply.c:4360 +#: builtin/apply.c:4400 msgid "don't expect at least one line of context" msgstr "erwartet keinen Kontext" -#: builtin/apply.c:4362 +#: builtin/apply.c:4402 msgid "leave the rejected hunks in corresponding *.rej files" msgstr "" "hinterlässt zurückgewiesene Patch-Bereiche in den entsprechenden *.rej " "Dateien" -#: builtin/apply.c:4364 +#: builtin/apply.c:4404 msgid "allow overlapping hunks" msgstr "erlaubt sich überlappende Patch-Bereiche" -#: builtin/apply.c:4367 +#: builtin/apply.c:4407 msgid "tolerate incorrectly detected missing new-line at the end of file" msgstr "toleriert fehlerhaft erkannten fehlenden Zeilenumbruch am Dateiende" -#: builtin/apply.c:4370 +#: builtin/apply.c:4410 msgid "do not trust the line counts in the hunk headers" msgstr "vertraut nicht den Zeilennummern im Kopf des Patch-Bereiches" -#: builtin/apply.c:4372 +#: builtin/apply.c:4412 msgid "root" msgstr "Wurzelverzeichnis" -#: builtin/apply.c:4373 +#: builtin/apply.c:4413 msgid "prepend to all filenames" msgstr "stellt vor alle Dateinamen" -#: builtin/apply.c:4395 +#: builtin/apply.c:4435 msgid "--3way outside a repository" msgstr "" "Die Option --3way kann nicht außerhalb eines Projektarchivs verwendet werden." -#: builtin/apply.c:4403 +#: builtin/apply.c:4443 msgid "--index outside a repository" msgstr "" "Die Option --index kann nicht außerhalb eines Projektarchivs verwendet " "werden." -#: builtin/apply.c:4406 +#: builtin/apply.c:4446 msgid "--cached outside a repository" msgstr "" "Die Option --cached kann nicht außerhalb eines Projektarchivs verwendet " "werden." -#: builtin/apply.c:4422 +#: builtin/apply.c:4462 #, c-format msgid "can't open patch '%s'" msgstr "kann Patch '%s' nicht öffnen" -#: builtin/apply.c:4436 +#: builtin/apply.c:4476 #, c-format msgid "squelched %d whitespace error" msgid_plural "squelched %d whitespace errors" msgstr[0] "unterdrückte %d Fehler in Leerzeichen" msgstr[1] "unterdrückte %d Fehler in Leerzeichen" -#: builtin/apply.c:4442 builtin/apply.c:4452 +#: builtin/apply.c:4482 builtin/apply.c:4492 #, c-format msgid "%d line adds whitespace errors." msgid_plural "%d lines add whitespace errors." @@ -2134,96 +2227,96 @@ msgstr "git blame [Optionen] [rev-opts] [rev] [--] Datei" msgid "[rev-opts] are documented in git-rev-list(1)" msgstr "[rev-opts] sind dokumentiert in git-rev-list(1)" -#: builtin/blame.c:2364 +#: builtin/blame.c:2350 msgid "Show blame entries as we find them, incrementally" msgstr "Zeigt \"blame\"-Einträge schrittweise, während wir sie generieren" -#: builtin/blame.c:2365 +#: builtin/blame.c:2351 msgid "Show blank SHA-1 for boundary commits (Default: off)" msgstr "Zeigt leere SHA-1 für Grenzversionen (Standard: aus)" -#: builtin/blame.c:2366 +#: builtin/blame.c:2352 msgid "Do not treat root commits as boundaries (Default: off)" msgstr "Behandelt Ursprungsversionen nicht als Grenzen (Standard: aus)" -#: builtin/blame.c:2367 +#: builtin/blame.c:2353 msgid "Show work cost statistics" msgstr "Zeigt Statistiken zum Arbeitsaufwand" -#: builtin/blame.c:2368 +#: builtin/blame.c:2354 msgid "Show output score for blame entries" msgstr "Zeigt Ausgabebewertung für \"blame\"-Einträge" -#: builtin/blame.c:2369 +#: builtin/blame.c:2355 msgid "Show original filename (Default: auto)" msgstr "Zeigt ursprünglichen Dateinamen (Standard: auto)" -#: builtin/blame.c:2370 +#: builtin/blame.c:2356 msgid "Show original linenumber (Default: off)" msgstr "Zeigt ursprüngliche Zeilennummer (Standard: aus)" -#: builtin/blame.c:2371 +#: builtin/blame.c:2357 msgid "Show in a format designed for machine consumption" msgstr "Anzeige in einem Format für maschinelle Auswertung" -#: builtin/blame.c:2372 +#: builtin/blame.c:2358 msgid "Show porcelain format with per-line commit information" msgstr "" "Anzeige in Format für Fremdprogramme mit Versionsinformationen pro Zeile" -#: builtin/blame.c:2373 +#: builtin/blame.c:2359 msgid "Use the same output mode as git-annotate (Default: off)" msgstr "Benutzt den gleichen Ausgabemodus wie \"git-annotate\" (Standard: aus)" -#: builtin/blame.c:2374 +#: builtin/blame.c:2360 msgid "Show raw timestamp (Default: off)" msgstr "Zeigt unbearbeiteten Zeitstempel (Standard: aus)" -#: builtin/blame.c:2375 +#: builtin/blame.c:2361 msgid "Show long commit SHA1 (Default: off)" msgstr "Zeigt langen Versions-SHA1 (Standard: aus)" -#: builtin/blame.c:2376 +#: builtin/blame.c:2362 msgid "Suppress author name and timestamp (Default: off)" msgstr "Unterdrückt den Namen des Autors und den Zeitstempel (Standard: aus)" -#: builtin/blame.c:2377 +#: builtin/blame.c:2363 msgid "Show author email instead of name (Default: off)" msgstr "Zeigt anstatt des Namens die Email-Adresse des Autors (Standard: aus)" -#: builtin/blame.c:2378 +#: builtin/blame.c:2364 msgid "Ignore whitespace differences" msgstr "Ignoriert Unterschiede in Leerzeichen" -#: builtin/blame.c:2379 +#: builtin/blame.c:2365 msgid "Spend extra cycles to find better match" msgstr "arbeite länger, um bessere Übereinstimmungen zu finden" -#: builtin/blame.c:2380 +#: builtin/blame.c:2366 msgid "Use revisions from instead of calling git-rev-list" msgstr "Benutzt Revisionen von anstatt \"git-rev-list\" aufzurufen" -#: builtin/blame.c:2381 +#: builtin/blame.c:2367 msgid "Use 's contents as the final image" msgstr "Benutzt Inhalte der en als entgültiges Abbild" -#: builtin/blame.c:2382 builtin/blame.c:2383 +#: builtin/blame.c:2368 builtin/blame.c:2369 msgid "score" msgstr "Bewertung" -#: builtin/blame.c:2382 +#: builtin/blame.c:2368 msgid "Find line copies within and across files" msgstr "Findet kopierte Zeilen innerhalb oder zwischen Dateien" -#: builtin/blame.c:2383 +#: builtin/blame.c:2369 msgid "Find line movements within and across files" msgstr "Findet verschobene Zeilen innerhalb oder zwischen Dateien" -#: builtin/blame.c:2384 +#: builtin/blame.c:2370 msgid "n,m" msgstr "n,m" -#: builtin/blame.c:2384 +#: builtin/blame.c:2370 msgid "Process only line range n,m, counting from 1" msgstr "Verarbeitet nur Zeilen im Bereich n,m, gezählt von 1" @@ -2360,10 +2453,19 @@ msgstr "[%s: %d voraus, %d hinterher]" msgid "[ahead %d, behind %d]" msgstr "[%d voraus, %d hinterher]" +#: builtin/branch.c:469 +msgid " **** invalid ref ****" +msgstr " **** ungültige Referenz ****" + #: builtin/branch.c:560 msgid "(no branch)" msgstr "(kein Zweig)" +#: builtin/branch.c:593 +#, c-format +msgid "object '%s' does not point to a commit" +msgstr "Objekt '%s' zeigt auf keine Version" + #: builtin/branch.c:625 msgid "some refs could not be read" msgstr "Konnte einige Referenzen nicht lesen" @@ -2437,8 +2539,8 @@ msgid "act on remote-tracking branches" msgstr "wirkt auf externe Übernahmezweige" #: builtin/branch.c:761 builtin/branch.c:767 builtin/branch.c:788 -#: builtin/branch.c:794 builtin/commit.c:1378 builtin/commit.c:1379 -#: builtin/commit.c:1380 builtin/commit.c:1381 builtin/tag.c:470 +#: builtin/branch.c:794 builtin/commit.c:1366 builtin/commit.c:1367 +#: builtin/commit.c:1368 builtin/commit.c:1369 builtin/tag.c:468 msgid "commit" msgstr "Version" @@ -2507,27 +2609,54 @@ msgstr "Konnte Zweigspitze (HEAD) nicht als gültige Referenz auflösen." msgid "HEAD not found below refs/heads!" msgstr "Zweigspitze (HEAD) wurde nicht unter \"refs/heads\" gefunden!" -#: builtin/branch.c:836 +#: builtin/branch.c:839 msgid "--column and --verbose are incompatible" msgstr "Die Optionen --column und --verbose sind inkompatibel." -#: builtin/branch.c:887 +#: builtin/branch.c:845 +msgid "branch name required" +msgstr "Zweigname erforderlich" + +#: builtin/branch.c:860 +msgid "Cannot give description to detached HEAD" +msgstr "" +"zu losgelöster Zweigspitze (HEAD) kann keine Beschreibung hinterlegt werden" + +#: builtin/branch.c:865 +msgid "cannot edit description of more than one branch" +msgstr "Beschreibung von mehr als einem Zweig kann nicht bearbeitet werden" + +#: builtin/branch.c:872 +#, c-format +msgid "No commit on branch '%s' yet." +msgstr "Noch keine Version in Zweig '%s'." + +#: builtin/branch.c:875 +#, c-format +msgid "No branch named '%s'." +msgstr "Zweig '%s' nicht vorhanden." + +#: builtin/branch.c:888 +msgid "too many branches for a rename operation" +msgstr "zu viele Zweige für eine Umbenennen-Operation angegeben" + +#: builtin/branch.c:893 #, c-format msgid "branch '%s' does not exist" msgstr "Zweig '%s' existiert nicht" -#: builtin/branch.c:899 +#: builtin/branch.c:905 #, c-format msgid "Branch '%s' has no upstream information" msgstr "Zweig '%s' hat keinen externen Übernahmezweig gesetzt" -#: builtin/branch.c:914 +#: builtin/branch.c:920 msgid "-a and -r options to 'git branch' do not make sense with a branch name" msgstr "" "Die Optionen -a und -r bei 'git branch' können nicht gemeimsam mit einem " "Zweignamen verwendet werden." -#: builtin/branch.c:917 +#: builtin/branch.c:923 #, c-format msgid "" "The --set-upstream flag is deprecated and will be removed. Consider using --" @@ -2536,7 +2665,7 @@ msgstr "" "Die --set-upstream Option ist veraltet und wird entfernt. Benutzen Sie --" "track oder --set-upstream-to\n" -#: builtin/branch.c:934 +#: builtin/branch.c:940 #, c-format msgid "" "\n" @@ -2547,12 +2676,12 @@ msgstr "" "Wenn Sie wollten, dass '%s' den Zweig '%s' als externen Übernahmezweig hat, " "führen Sie aus:\n" -#: builtin/branch.c:935 +#: builtin/branch.c:941 #, c-format msgid " git branch -d %s\n" msgstr " git branch -d %s\n" -#: builtin/branch.c:936 +#: builtin/branch.c:942 #, c-format msgid " git branch --set-upstream-to %s\n" msgstr " git branch --set-upstream-to %s\n" @@ -2630,14 +2759,39 @@ msgstr "gibt alle Attribute einer Datei aus" msgid "use .gitattributes only from the index" msgstr "verwendet .gitattributes nur von der Bereitstellung" -#: builtin/check-attr.c:21 builtin/hash-object.c:75 +#: builtin/check-attr.c:21 builtin/check-ignore.c:22 builtin/hash-object.c:75 msgid "read file names from stdin" msgstr "liest Dateinamen von der Standard-Eingabe" -#: builtin/check-attr.c:23 +#: builtin/check-attr.c:23 builtin/check-ignore.c:24 msgid "input paths are terminated by a null character" msgstr "Eingabepfade sind durch ein NUL Zeichen abgeschlossen" +#: builtin/check-ignore.c:18 builtin/checkout.c:1012 builtin/gc.c:177 +msgid "suppress progress reporting" +msgstr "unterdrückt Fortschrittsanzeige" + +#: builtin/check-ignore.c:151 +msgid "cannot specify pathnames with --stdin" +msgstr "Angabe von Pfadnamen kann nicht gemeinsam mit --stdin verwendet werden" + +#: builtin/check-ignore.c:154 +msgid "-z only makes sense with --stdin" +msgstr "Die Option -z kann nur mit --stdin verwendet werden." + +#: builtin/check-ignore.c:156 +msgid "no path specified" +msgstr "kein Pfad angegeben" + +#: builtin/check-ignore.c:160 +msgid "--quiet is only valid with a single pathname" +msgstr "Die Option --quiet ist nur mit einem einzelnen Pfadnamen gültig." + +#: builtin/check-ignore.c:162 +msgid "cannot have both --quiet and --verbose" +msgstr "" +"Die Optionen --quiet und --verbose können nicht gemeinsam verwendet werden." + #: builtin/checkout-index.c:126 msgid "git checkout-index [options] [--] [...]" msgstr "git checkout-index [Optionen] [--] [...]" @@ -2874,10 +3028,6 @@ msgstr "'%s' kann nicht mit '%s' verwendet werden" msgid "Cannot switch branch to a non-commit '%s'" msgstr "Kann Zweig nicht zu Nicht-Version '%s' wechseln" -#: builtin/checkout.c:1012 builtin/gc.c:177 -msgid "suppress progress reporting" -msgstr "unterdrückt Fortschrittsanzeige" - #: builtin/checkout.c:1013 builtin/checkout.c:1015 builtin/clone.c:89 #: builtin/remote.c:169 builtin/remote.c:171 msgid "branch" @@ -3011,47 +3161,47 @@ msgstr "Würde Projektarchiv %s überspringen\n" msgid "failed to remove %s" msgstr "Fehler beim Löschen von %s" -#: builtin/clean.c:159 +#: builtin/clean.c:160 msgid "do not print names of files removed" msgstr "gibt keine Namen von gelöschten Dateien aus" -#: builtin/clean.c:161 +#: builtin/clean.c:162 msgid "force" msgstr "erzwingt Aktion" -#: builtin/clean.c:163 +#: builtin/clean.c:164 msgid "remove whole directories" msgstr "löscht ganze Verzeichnisse" -#: builtin/clean.c:164 builtin/describe.c:413 builtin/grep.c:717 -#: builtin/ls-files.c:491 builtin/name-rev.c:231 builtin/show-ref.c:182 +#: builtin/clean.c:165 builtin/describe.c:413 builtin/grep.c:717 +#: builtin/ls-files.c:494 builtin/name-rev.c:231 builtin/show-ref.c:182 msgid "pattern" msgstr "Muster" -#: builtin/clean.c:165 +#: builtin/clean.c:166 msgid "add to ignore rules" msgstr "fügt zu den Regeln für ignorierte Pfade hinzu" -#: builtin/clean.c:166 +#: builtin/clean.c:167 msgid "remove ignored files, too" msgstr "löscht auch ignorierte Dateien" -#: builtin/clean.c:168 +#: builtin/clean.c:169 msgid "remove only ignored files" msgstr "löscht nur ignorierte Dateien" -#: builtin/clean.c:186 +#: builtin/clean.c:187 msgid "-x and -X cannot be used together" msgstr "Die Optionen -x und -X können nicht gemeinsam verwendet werden." -#: builtin/clean.c:190 +#: builtin/clean.c:191 msgid "" "clean.requireForce set to true and neither -n nor -f given; refusing to clean" msgstr "" "clean.requireForce auf \"true\" gesetzt und weder -n noch -f gegeben; " "Säuberung verweigert" -#: builtin/clean.c:193 +#: builtin/clean.c:194 msgid "" "clean.requireForce defaults to true and neither -n nor -f given; refusing to " "clean" @@ -3064,7 +3214,7 @@ msgid "git clone [options] [--] []" msgstr "git clone [Optionen] [--] []" #: builtin/clone.c:64 builtin/fetch.c:82 builtin/merge.c:212 -#: builtin/push.c:407 +#: builtin/push.c:436 msgid "force progress reporting" msgstr "erzwingt Fortschrittsanzeige" @@ -3178,11 +3328,6 @@ msgstr "%s existiert und ist kein Verzeichnis" msgid "failed to stat %s\n" msgstr "Konnte %s nicht lesen\n" -#: builtin/clone.c:341 -#, c-format -msgid "failed to unlink '%s'" -msgstr "Konnte '%s' nicht entfernen" - #: builtin/clone.c:346 #, c-format msgid "failed to create link '%s'" @@ -3247,7 +3392,7 @@ msgstr "Zielpfad '%s' existiert bereits und ist kein leeres Verzeichnis." msgid "working tree '%s' already exists." msgstr "Arbeitsbaum '%s' existiert bereits." -#: builtin/clone.c:759 builtin/clone.c:773 +#: builtin/clone.c:759 builtin/clone.c:771 #, c-format msgid "could not create leading directories of '%s'" msgstr "Konnte führende Verzeichnisse von '%s' nicht erstellen." @@ -3257,27 +3402,27 @@ msgstr "Konnte führende Verzeichnisse von '%s' nicht erstellen." msgid "could not create work tree dir '%s'." msgstr "Konnte Arbeitsverzeichnis '%s' nicht erstellen." -#: builtin/clone.c:783 +#: builtin/clone.c:781 #, c-format msgid "Cloning into bare repository '%s'...\n" msgstr "Klone in bloßes Projektarchiv '%s'...\n" -#: builtin/clone.c:785 +#: builtin/clone.c:783 #, c-format msgid "Cloning into '%s'...\n" msgstr "Klone nach '%s'...\n" -#: builtin/clone.c:827 +#: builtin/clone.c:818 #, c-format msgid "Don't know how to clone %s" msgstr "Weiß nicht wie %s zu klonen ist." -#: builtin/clone.c:876 +#: builtin/clone.c:867 #, c-format msgid "Remote branch %s not found in upstream %s" msgstr "externer Zweig %s nicht im anderen Projektarchiv %s gefunden" -#: builtin/clone.c:883 +#: builtin/clone.c:874 msgid "You appear to have cloned an empty repository." msgstr "Sie scheinen ein leeres Projektarchiv geklont zu haben." @@ -3314,12 +3459,12 @@ msgid "--command must be the first argument" msgstr "Die Option --command muss an erster Stelle stehen." #: builtin/commit.c:34 -msgid "git commit [options] [--] ..." -msgstr "git commit [Optionen] [--] ..." +msgid "git commit [options] [--] ..." +msgstr "git commit [Optionen] [--] ..." #: builtin/commit.c:39 -msgid "git status [options] [--] ..." -msgstr "git status [Optionen] [--] ..." +msgid "git status [options] [--] ..." +msgstr "git status [Optionen] [--] ..." #: builtin/commit.c:44 msgid "" @@ -3495,23 +3640,26 @@ msgstr "" "und versuchen Sie es erneut.\n" #: builtin/commit.c:735 +#, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" -"with '#' will be ignored, and an empty message aborts the commit.\n" +"with '%c' will be ignored, and an empty message aborts the commit.\n" msgstr "" "Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen,\n" -"die mit '#' beginnen, werden ignoriert, und eine leere Versionsbeschreibung\n" +"die mit '%c' beginnen, werden ignoriert, und eine leere " +"Versionsbeschreibung\n" "bricht die Eintragung ab.\n" #: builtin/commit.c:740 +#, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" -"with '#' will be kept; you may remove them yourself if you want to.\n" +"with '%c' will be kept; you may remove them yourself if you want to.\n" "An empty message aborts the commit.\n" msgstr "" "Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen, " "die\n" -"mit '#' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese " +"mit '%c' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese " "entfernen.\n" "Eine leere Versionsbeschreibung bricht die Eintragung ab.\n" @@ -3533,7 +3681,7 @@ msgstr "Kann Bereitstellung nicht lesen" msgid "Error building trees" msgstr "Fehler beim Erzeugen der Zweige" -#: builtin/commit.c:832 builtin/tag.c:361 +#: builtin/commit.c:832 builtin/tag.c:359 #, c-format msgid "Please supply the message using either -m or -F option.\n" msgstr "Bitte liefere eine Beschreibung entweder mit der Option -m oder -F.\n" @@ -3543,123 +3691,123 @@ msgstr "Bitte liefere eine Beschreibung entweder mit der Option -m oder -F.\n" msgid "No existing author found with '%s'" msgstr "Kein existierender Autor mit '%s' gefunden." -#: builtin/commit.c:944 builtin/commit.c:1148 +#: builtin/commit.c:944 builtin/commit.c:1138 #, c-format msgid "Invalid untracked files mode '%s'" msgstr "Ungültiger Modus '%s' für unbeobachtete Dateien" -#: builtin/commit.c:984 +#: builtin/commit.c:974 msgid "Using both --reset-author and --author does not make sense" msgstr "" "Die Optionen --reset-author und --author können nicht gemeinsam verwendet " "werden." -#: builtin/commit.c:995 +#: builtin/commit.c:985 msgid "You have nothing to amend." msgstr "Sie haben nichts zum nachbessern." -#: builtin/commit.c:998 +#: builtin/commit.c:988 msgid "You are in the middle of a merge -- cannot amend." msgstr "Eine Zusammenführung ist im Gange -- kann nicht nachbessern." -#: builtin/commit.c:1000 +#: builtin/commit.c:990 msgid "You are in the middle of a cherry-pick -- cannot amend." msgstr "\"cherry-pick\" ist im Gange -- kann nicht nachbessern." -#: builtin/commit.c:1003 +#: builtin/commit.c:993 msgid "Options --squash and --fixup cannot be used together" msgstr "" "Die Optionen --squash und --fixup können nicht gemeinsam verwendet werden." -#: builtin/commit.c:1013 +#: builtin/commit.c:1003 msgid "Only one of -c/-C/-F/--fixup can be used." msgstr "Es kann nur eine Option von -c/-C/-F/--fixup verwendet werden." -#: builtin/commit.c:1015 +#: builtin/commit.c:1005 msgid "Option -m cannot be combined with -c/-C/-F/--fixup." msgstr "Die Option -m kann nicht mit -c/-C/-F/--fixup kombiniert werden." -#: builtin/commit.c:1023 +#: builtin/commit.c:1013 msgid "--reset-author can be used only with -C, -c or --amend." msgstr "" "Die Option --reset--author kann nur mit -C, -c oder --amend verwendet werden." -#: builtin/commit.c:1040 +#: builtin/commit.c:1030 msgid "Only one of --include/--only/--all/--interactive/--patch can be used." msgstr "" "Es kann nur eine Option von --include/--only/--all/--interactive/--patch " "verwendet werden." -#: builtin/commit.c:1042 +#: builtin/commit.c:1032 msgid "No paths with --include/--only does not make sense." msgstr "" "Die Optionen --include und --only können nur mit der Angabe von Pfaden " "verwendet werden." -#: builtin/commit.c:1044 +#: builtin/commit.c:1034 msgid "Clever... amending the last one with dirty index." msgstr "" "Klug... die letzte Version mit einer unsauberen Bereitstellung nachbessern." -#: builtin/commit.c:1046 +#: builtin/commit.c:1036 msgid "Explicit paths specified without -i nor -o; assuming --only paths..." msgstr "" "Explizite Pfade ohne -i oder -o angegeben; unter der Annahme von --only " "Pfaden..." -#: builtin/commit.c:1056 builtin/tag.c:577 +#: builtin/commit.c:1046 builtin/tag.c:575 #, c-format msgid "Invalid cleanup mode %s" msgstr "Ungültiger \"cleanup\" Modus %s" -#: builtin/commit.c:1061 +#: builtin/commit.c:1051 msgid "Paths with -a does not make sense." msgstr "Die Option -a kann nur mit der Angabe von Pfaden verwendet werden." -#: builtin/commit.c:1067 builtin/commit.c:1202 +#: builtin/commit.c:1057 builtin/commit.c:1192 msgid "--long and -z are incompatible" msgstr "Die Optionen --long und -z sind inkompatibel." -#: builtin/commit.c:1162 builtin/commit.c:1400 +#: builtin/commit.c:1152 builtin/commit.c:1388 msgid "show status concisely" msgstr "zeigt Status im Kurzformat" -#: builtin/commit.c:1164 builtin/commit.c:1402 +#: builtin/commit.c:1154 builtin/commit.c:1390 msgid "show branch information" msgstr "zeigt Zweiginformationen" -#: builtin/commit.c:1166 builtin/commit.c:1404 builtin/push.c:397 +#: builtin/commit.c:1156 builtin/commit.c:1392 builtin/push.c:426 msgid "machine-readable output" msgstr "maschinenlesbare Ausgabe" -#: builtin/commit.c:1169 builtin/commit.c:1406 +#: builtin/commit.c:1159 builtin/commit.c:1394 msgid "show status in long format (default)" msgstr "zeigt Status im Langformat (Standard)" -#: builtin/commit.c:1172 builtin/commit.c:1409 +#: builtin/commit.c:1162 builtin/commit.c:1397 msgid "terminate entries with NUL" msgstr "schließt Einträge mit NUL-Zeichen ab" -#: builtin/commit.c:1174 builtin/commit.c:1412 builtin/fast-export.c:647 -#: builtin/fast-export.c:650 builtin/tag.c:461 +#: builtin/commit.c:1164 builtin/commit.c:1400 builtin/fast-export.c:647 +#: builtin/fast-export.c:650 builtin/tag.c:459 msgid "mode" msgstr "Modus" -#: builtin/commit.c:1175 builtin/commit.c:1412 +#: builtin/commit.c:1165 builtin/commit.c:1400 msgid "show untracked files, optional modes: all, normal, no. (Default: all)" msgstr "" "zeigt nicht beobachtete Dateien, optionale Modi: all, normal, no. (Standard: " "all)" -#: builtin/commit.c:1178 +#: builtin/commit.c:1168 msgid "show ignored files" msgstr "zeigt ignorierte Dateien" -#: builtin/commit.c:1179 parse-options.h:151 +#: builtin/commit.c:1169 parse-options.h:151 msgid "when" msgstr "wann" -#: builtin/commit.c:1180 +#: builtin/commit.c:1170 msgid "" "ignore changes to submodules, optional when: all, dirty, untracked. " "(Default: all)" @@ -3667,219 +3815,219 @@ msgstr "" "ignoriert Änderungen in Unterprojekten, optional wenn: all, dirty, " "untracked. (Standard: all)" -#: builtin/commit.c:1182 +#: builtin/commit.c:1172 msgid "list untracked files in columns" msgstr "listet unbeobachtete Dateien in Spalten auf" -#: builtin/commit.c:1256 +#: builtin/commit.c:1246 msgid "couldn't look up newly created commit" msgstr "Konnte neu erstellte Version nicht nachschlagen." -#: builtin/commit.c:1258 +#: builtin/commit.c:1248 msgid "could not parse newly created commit" msgstr "Konnte neulich erstellte Version nicht analysieren." -#: builtin/commit.c:1299 +#: builtin/commit.c:1289 msgid "detached HEAD" msgstr "losgelöste Zweigspitze (HEAD)" -#: builtin/commit.c:1301 +#: builtin/commit.c:1291 msgid " (root-commit)" msgstr " (Basis-Version)" -#: builtin/commit.c:1370 +#: builtin/commit.c:1358 msgid "suppress summary after successful commit" msgstr "unterdrückt Zusammenfassung nach erfolgreicher Eintragung" -#: builtin/commit.c:1371 +#: builtin/commit.c:1359 msgid "show diff in commit message template" msgstr "zeigt Unterschiede in Versionsbeschreibungsvorlage an" -#: builtin/commit.c:1373 +#: builtin/commit.c:1361 msgid "Commit message options" msgstr "Optionen für Versionsbeschreibung" -#: builtin/commit.c:1374 builtin/tag.c:459 +#: builtin/commit.c:1362 builtin/tag.c:457 msgid "read message from file" msgstr "liest Beschreibung von Datei" -#: builtin/commit.c:1375 +#: builtin/commit.c:1363 msgid "author" msgstr "Autor" -#: builtin/commit.c:1375 +#: builtin/commit.c:1363 msgid "override author for commit" msgstr "überschreibt Autor von Version" -#: builtin/commit.c:1376 builtin/gc.c:178 +#: builtin/commit.c:1364 builtin/gc.c:178 msgid "date" msgstr "Datum" -#: builtin/commit.c:1376 +#: builtin/commit.c:1364 msgid "override date for commit" msgstr "überschreibt Datum von Version" -#: builtin/commit.c:1377 builtin/merge.c:206 builtin/notes.c:537 -#: builtin/notes.c:694 builtin/tag.c:457 +#: builtin/commit.c:1365 builtin/merge.c:206 builtin/notes.c:533 +#: builtin/notes.c:690 builtin/tag.c:455 msgid "message" msgstr "Beschreibung" -#: builtin/commit.c:1377 +#: builtin/commit.c:1365 msgid "commit message" msgstr "Versionsbeschreibung" -#: builtin/commit.c:1378 +#: builtin/commit.c:1366 msgid "reuse and edit message from specified commit" msgstr "verwendet wieder und editiert Beschreibung von der angegebenen Version" -#: builtin/commit.c:1379 +#: builtin/commit.c:1367 msgid "reuse message from specified commit" msgstr "verwendet Beschreibung der angegebenen Version wieder" -#: builtin/commit.c:1380 +#: builtin/commit.c:1368 msgid "use autosquash formatted message to fixup specified commit" msgstr "" "verwendet eine automatisch zusammengesetzte Beschreibung zum Nachbessern der " "angegebenen Version" -#: builtin/commit.c:1381 +#: builtin/commit.c:1369 msgid "use autosquash formatted message to squash specified commit" msgstr "" "verwendet eine automatisch zusammengesetzte Beschreibung zum Zusammenführen " "der angegebenen Version" -#: builtin/commit.c:1382 +#: builtin/commit.c:1370 msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "Setzt Sie als Autor der Version (verwendet mit -C/-c/--amend)" -#: builtin/commit.c:1383 builtin/log.c:1102 builtin/revert.c:109 +#: builtin/commit.c:1371 builtin/log.c:1102 builtin/revert.c:109 msgid "add Signed-off-by:" msgstr "fügt 'Signed-off-by:'-Zeile hinzu" -#: builtin/commit.c:1384 +#: builtin/commit.c:1372 msgid "use specified template file" msgstr "verwendet angegebene Vorlagendatei" -#: builtin/commit.c:1385 +#: builtin/commit.c:1373 msgid "force edit of commit" msgstr "erzwingt Bearbeitung der Version" -#: builtin/commit.c:1386 +#: builtin/commit.c:1374 msgid "default" msgstr "Standard" -#: builtin/commit.c:1386 builtin/tag.c:462 +#: builtin/commit.c:1374 builtin/tag.c:460 msgid "how to strip spaces and #comments from message" msgstr "" "wie Leerzeichen und #Kommentare von der Beschreibung getrennt werden sollen" -#: builtin/commit.c:1387 +#: builtin/commit.c:1375 msgid "include status in commit message template" msgstr "fügt Status in die Versionsbeschreibungsvorlage ein" -#: builtin/commit.c:1388 builtin/merge.c:213 builtin/tag.c:463 +#: builtin/commit.c:1376 builtin/merge.c:213 builtin/tag.c:461 msgid "key id" msgstr "Schlüssel-ID" -#: builtin/commit.c:1389 builtin/merge.c:214 +#: builtin/commit.c:1377 builtin/merge.c:214 msgid "GPG sign commit" msgstr "signiert Version mit GPG" #. end commit message options -#: builtin/commit.c:1392 +#: builtin/commit.c:1380 msgid "Commit contents options" msgstr "Optionen für Versionsinhalt" -#: builtin/commit.c:1393 +#: builtin/commit.c:1381 msgid "commit all changed files" msgstr "trägt alle geänderten Dateien ein" -#: builtin/commit.c:1394 +#: builtin/commit.c:1382 msgid "add specified files to index for commit" msgstr "trägt die angegebenen Dateien zusätzlich zur Bereitstellung ein" -#: builtin/commit.c:1395 +#: builtin/commit.c:1383 msgid "interactively add files" msgstr "interaktives Hinzufügen von Dateien" -#: builtin/commit.c:1396 +#: builtin/commit.c:1384 msgid "interactively add changes" msgstr "interaktives Hinzufügen von Änderungen" -#: builtin/commit.c:1397 +#: builtin/commit.c:1385 msgid "commit only specified files" msgstr "trägt nur die angegebenen Dateien ein" -#: builtin/commit.c:1398 +#: builtin/commit.c:1386 msgid "bypass pre-commit hook" msgstr "umgeht \"pre-commit hook\"" -#: builtin/commit.c:1399 +#: builtin/commit.c:1387 msgid "show what would be committed" msgstr "zeigt an, was eingetragen werden würde" -#: builtin/commit.c:1410 +#: builtin/commit.c:1398 msgid "amend previous commit" msgstr "ändert vorherige Version" -#: builtin/commit.c:1411 +#: builtin/commit.c:1399 msgid "bypass post-rewrite hook" msgstr "umgeht \"post-rewrite hook\"" -#: builtin/commit.c:1416 +#: builtin/commit.c:1404 msgid "ok to record an empty change" msgstr "erlaubt Aufzeichnung einer leeren Änderung" -#: builtin/commit.c:1419 +#: builtin/commit.c:1407 msgid "ok to record a change with an empty message" msgstr "erlaubt Aufzeichnung einer Änderung mit einer leeren Beschreibung" -#: builtin/commit.c:1451 +#: builtin/commit.c:1439 msgid "could not parse HEAD commit" msgstr "Konnte Version der Zweigspitze (HEAD) nicht analysieren." -#: builtin/commit.c:1489 builtin/merge.c:508 +#: builtin/commit.c:1477 builtin/merge.c:508 #, c-format msgid "could not open '%s' for reading" msgstr "Konnte '%s' nicht zum Lesen öffnen." -#: builtin/commit.c:1496 +#: builtin/commit.c:1484 #, c-format msgid "Corrupt MERGE_HEAD file (%s)" msgstr "Beschädigte MERGE_HEAD-Datei (%s)" -#: builtin/commit.c:1503 +#: builtin/commit.c:1491 msgid "could not read MERGE_MODE" msgstr "Konnte MERGE_MODE nicht lesen" -#: builtin/commit.c:1522 +#: builtin/commit.c:1510 #, c-format msgid "could not read commit message: %s" msgstr "Konnte Versionsbeschreibung nicht lesen: %s" -#: builtin/commit.c:1536 +#: builtin/commit.c:1524 #, c-format msgid "Aborting commit; you did not edit the message.\n" msgstr "Eintragung abgebrochen; Sie haben die Beschreibung nicht editiert.\n" -#: builtin/commit.c:1541 +#: builtin/commit.c:1529 #, c-format msgid "Aborting commit due to empty commit message.\n" msgstr "Eintragung aufgrund leerer Versionsbeschreibung abgebrochen.\n" -#: builtin/commit.c:1556 builtin/merge.c:833 builtin/merge.c:858 +#: builtin/commit.c:1544 builtin/merge.c:832 builtin/merge.c:857 msgid "failed to write commit object" msgstr "Fehler beim Schreiben des Versionsobjektes." -#: builtin/commit.c:1577 +#: builtin/commit.c:1565 msgid "cannot lock HEAD ref" msgstr "Kann Referenz der Zweigspitze (HEAD) nicht sperren." -#: builtin/commit.c:1581 +#: builtin/commit.c:1569 msgid "cannot update HEAD ref" msgstr "Kann Referenz der Zweigspitze (HEAD) nicht aktualisieren." -#: builtin/commit.c:1592 +#: builtin/commit.c:1580 msgid "" "Repository has been updated, but unable to write\n" "new_index file. Check that disk is not full or quota is\n" @@ -4291,88 +4439,92 @@ msgstr "erlaubt Aktualisierung der \"HEAD\"-Referenz" msgid "deepen history of shallow clone" msgstr "vertieft die Historie eines flachen Klon" -#: builtin/fetch.c:85 builtin/log.c:1119 +#: builtin/fetch.c:86 +msgid "convert to a complete repository" +msgstr "konvertiert zu einem vollständigen Projektarchiv" + +#: builtin/fetch.c:88 builtin/log.c:1119 msgid "dir" msgstr "Verzeichnis" -#: builtin/fetch.c:86 +#: builtin/fetch.c:89 msgid "prepend this to submodule path output" msgstr "stellt dies an die Ausgabe der Unterprojekt-Pfade voran" -#: builtin/fetch.c:89 +#: builtin/fetch.c:92 msgid "default mode for recursion" msgstr "Standard-Modus für Rekursion" -#: builtin/fetch.c:201 +#: builtin/fetch.c:204 msgid "Couldn't find remote ref HEAD" msgstr "Konnte externe Referenz der Zweigspitze (HEAD) nicht finden." -#: builtin/fetch.c:254 +#: builtin/fetch.c:257 #, c-format msgid "object %s not found" msgstr "Objekt %s nicht gefunden" -#: builtin/fetch.c:259 +#: builtin/fetch.c:262 msgid "[up to date]" msgstr "[aktuell]" -#: builtin/fetch.c:273 +#: builtin/fetch.c:276 #, c-format msgid "! %-*s %-*s -> %s (can't fetch in current branch)" msgstr "! %-*s %-*s -> %s (kann nicht im aktuellen Zweig anfordern)" -#: builtin/fetch.c:274 builtin/fetch.c:360 +#: builtin/fetch.c:277 builtin/fetch.c:363 msgid "[rejected]" msgstr "[zurückgewiesen]" -#: builtin/fetch.c:285 +#: builtin/fetch.c:288 msgid "[tag update]" msgstr "[Markierungsaktualisierung]" -#: builtin/fetch.c:287 builtin/fetch.c:322 builtin/fetch.c:340 +#: builtin/fetch.c:290 builtin/fetch.c:325 builtin/fetch.c:343 msgid " (unable to update local ref)" msgstr " (kann lokale Referenz nicht aktualisieren)" -#: builtin/fetch.c:305 +#: builtin/fetch.c:308 msgid "[new tag]" msgstr "[neue Markierung]" -#: builtin/fetch.c:308 +#: builtin/fetch.c:311 msgid "[new branch]" msgstr "[neuer Zweig]" -#: builtin/fetch.c:311 +#: builtin/fetch.c:314 msgid "[new ref]" msgstr "[neue Referenz]" -#: builtin/fetch.c:356 +#: builtin/fetch.c:359 msgid "unable to update local ref" msgstr "kann lokale Referenz nicht aktualisieren" -#: builtin/fetch.c:356 +#: builtin/fetch.c:359 msgid "forced update" msgstr "Aktualisierung erzwungen" -#: builtin/fetch.c:362 +#: builtin/fetch.c:365 msgid "(non-fast-forward)" msgstr "(kein Vorspulen)" -#: builtin/fetch.c:393 builtin/fetch.c:685 +#: builtin/fetch.c:396 builtin/fetch.c:688 #, c-format msgid "cannot open %s: %s\n" msgstr "kann %s nicht öffnen: %s\n" -#: builtin/fetch.c:402 +#: builtin/fetch.c:405 #, c-format msgid "%s did not send all necessary objects\n" msgstr "%s hat nicht alle erforderlichen Objekte gesendet\n" -#: builtin/fetch.c:488 +#: builtin/fetch.c:491 #, c-format msgid "From %.*s\n" msgstr "Von %.*s\n" -#: builtin/fetch.c:499 +#: builtin/fetch.c:502 #, c-format msgid "" "some local refs could not be updated; try running\n" @@ -4381,57 +4533,57 @@ msgstr "" "Einige lokale Referenzen konnten nicht aktualisiert werden; versuchen Sie\n" "'git remote prune %s' um jeden älteren, widersprüchlichen Zweig zu löschen." -#: builtin/fetch.c:549 +#: builtin/fetch.c:552 #, c-format msgid " (%s will become dangling)" msgstr " (%s wird unreferenziert)" -#: builtin/fetch.c:550 +#: builtin/fetch.c:553 #, c-format msgid " (%s has become dangling)" msgstr " (%s wurde unreferenziert)" -#: builtin/fetch.c:557 +#: builtin/fetch.c:560 msgid "[deleted]" msgstr "[gelöscht]" -#: builtin/fetch.c:558 builtin/remote.c:1055 +#: builtin/fetch.c:561 builtin/remote.c:1055 msgid "(none)" msgstr "(nichts)" -#: builtin/fetch.c:675 +#: builtin/fetch.c:678 #, c-format msgid "Refusing to fetch into current branch %s of non-bare repository" msgstr "" "Das Anfordern in den aktuellen Zweig %s von einem nicht-bloßen Projektarchiv " "wurde verweigert." -#: builtin/fetch.c:709 +#: builtin/fetch.c:712 #, c-format msgid "Don't know how to fetch from %s" msgstr "Weiß nicht wie von %s angefordert wird." -#: builtin/fetch.c:786 +#: builtin/fetch.c:789 #, c-format msgid "Option \"%s\" value \"%s\" is not valid for %s" msgstr "Option \"%s\" Wert \"%s\" ist nicht gültig für %s" -#: builtin/fetch.c:789 +#: builtin/fetch.c:792 #, c-format msgid "Option \"%s\" is ignored for %s\n" msgstr "Option \"%s\" wird ignoriert für %s\n" -#: builtin/fetch.c:891 +#: builtin/fetch.c:894 #, c-format msgid "Fetching %s\n" msgstr "Fordere an von %s\n" -#: builtin/fetch.c:893 builtin/remote.c:100 +#: builtin/fetch.c:896 builtin/remote.c:100 #, c-format msgid "Could not fetch %s" msgstr "Konnte nicht von %s anfordern" -#: builtin/fetch.c:912 +#: builtin/fetch.c:915 msgid "" "No remote repository specified. Please, specify either a URL or a\n" "remote name from which new revisions should be fetched." @@ -4440,24 +4592,35 @@ msgstr "" "oder den Namen des externen Archivs an, von welchem neue\n" "Revisionen angefordert werden sollen." -#: builtin/fetch.c:932 +#: builtin/fetch.c:935 msgid "You need to specify a tag name." msgstr "Sie müssen den Namen der Markierung angeben." -#: builtin/fetch.c:984 +#: builtin/fetch.c:981 +msgid "--depth and --unshallow cannot be used together" +msgstr "" +"Die Optionen --depth und --unshallow können nicht gemeinsam verwendet werden." + +#: builtin/fetch.c:983 +msgid "--unshallow on a complete repository does not make sense" +msgstr "" +"Die Option --unshallow kann nicht in einem vollständigen Projektarchiv " +"verwendet werden." + +#: builtin/fetch.c:1002 msgid "fetch --all does not take a repository argument" msgstr "fetch --all akzeptiert kein Projektarchiv als Argument" -#: builtin/fetch.c:986 +#: builtin/fetch.c:1004 msgid "fetch --all does not make sense with refspecs" msgstr "fetch --all kann nicht mit Referenzspezifikationen verwendet werden." -#: builtin/fetch.c:997 +#: builtin/fetch.c:1015 #, c-format msgid "No such remote or remote group: %s" msgstr "Kein externes Archiv (einzeln oder Gruppe): %s" -#: builtin/fetch.c:1005 +#: builtin/fetch.c:1023 msgid "Fetching a group and specifying refspecs does not make sense" msgstr "" "Das Abholen einer Gruppe von externen Archiven kann nicht mit der Angabe\n" @@ -4470,7 +4633,7 @@ msgstr "" #: builtin/fmt-merge-msg.c:659 builtin/fmt-merge-msg.c:662 builtin/grep.c:701 #: builtin/merge.c:188 builtin/show-branch.c:656 builtin/show-ref.c:175 -#: builtin/tag.c:448 parse-options.h:133 parse-options.h:239 +#: builtin/tag.c:446 parse-options.h:133 parse-options.h:239 msgid "n" msgstr "Anzahl" @@ -4835,31 +4998,31 @@ msgstr "keine Muster angegeben" msgid "bad object %s" msgstr "ungültiges Objekt %s" -#: builtin/grep.c:866 +#: builtin/grep.c:868 msgid "--open-files-in-pager only works on the worktree" msgstr "" "Die Option --open-files-in-pager kann nur innerhalb des Arbeitsbaums " "verwendet werden." -#: builtin/grep.c:889 +#: builtin/grep.c:891 msgid "--cached or --untracked cannot be used with --no-index." msgstr "" "Die Optionen --cached und --untracked können nicht mit --no-index verwendet " "werden." -#: builtin/grep.c:894 +#: builtin/grep.c:896 msgid "--no-index or --untracked cannot be used with revs." msgstr "" "Die Optionen --no-index und --untracked können nicht mit Versionen verwendet " "werden." -#: builtin/grep.c:897 +#: builtin/grep.c:899 msgid "--[no-]exclude-standard cannot be used for tracked contents." msgstr "" "Die Option --[no-]exclude-standard kann nicht mit beobachteten Inhalten " "verwendet werden." -#: builtin/grep.c:905 +#: builtin/grep.c:907 msgid "both --cached and trees are given." msgstr "Die Option --cached kann nicht mit Zweigen verwendet werden." @@ -4899,50 +5062,50 @@ msgstr "speichert Datei wie sie ist, ohne Filter" msgid "process file as it were from this path" msgstr "verarbeitet Datei, als ob sie von diesem Pfad wäre" -#: builtin/help.c:43 +#: builtin/help.c:42 msgid "print all available commands" msgstr "Anzeige aller vorhandenen Kommandos" -#: builtin/help.c:44 +#: builtin/help.c:43 msgid "show man page" msgstr "zeigt Handbuch" -#: builtin/help.c:45 +#: builtin/help.c:44 msgid "show manual in web browser" msgstr "zeigt Handbuch in einem Webbrowser" -#: builtin/help.c:47 +#: builtin/help.c:46 msgid "show info page" msgstr "zeigt Info-Seite" -#: builtin/help.c:53 +#: builtin/help.c:52 msgid "git help [--all] [--man|--web|--info] [command]" msgstr "git help [--all] [--man|--web|--info] [Kommando]" -#: builtin/help.c:65 +#: builtin/help.c:64 #, c-format msgid "unrecognized help format '%s'" msgstr "nicht erkanntes Hilfeformat: %s" -#: builtin/help.c:93 +#: builtin/help.c:92 msgid "Failed to start emacsclient." msgstr "Konnte emacsclient nicht starten." -#: builtin/help.c:106 +#: builtin/help.c:105 msgid "Failed to parse emacsclient version." msgstr "Konnte Version des emacsclient nicht parsen." -#: builtin/help.c:114 +#: builtin/help.c:113 #, c-format msgid "emacsclient version '%d' too old (< 22)." msgstr "Version des emacsclient '%d' ist zu alt (< 22)." -#: builtin/help.c:132 builtin/help.c:160 builtin/help.c:169 builtin/help.c:177 +#: builtin/help.c:131 builtin/help.c:159 builtin/help.c:168 builtin/help.c:176 #, c-format msgid "failed to exec '%s': %s" msgstr "Fehler beim Ausführen von '%s': %s" -#: builtin/help.c:217 +#: builtin/help.c:216 #, c-format msgid "" "'%s': path for unsupported man viewer.\n" @@ -4951,7 +5114,7 @@ msgstr "" "'%s': Pfad für nicht unterstützten Handbuchbetrachter.\n" "Sie könnten stattdessen 'man..cmd' benutzen." -#: builtin/help.c:229 +#: builtin/help.c:228 #, c-format msgid "" "'%s': cmd for supported man viewer.\n" @@ -4960,29 +5123,25 @@ msgstr "" "'%s': Kommando für unterstützten Handbuchbetrachter.\n" "Sie könnten stattdessen 'man..path' benutzen." -#: builtin/help.c:299 -msgid "The most commonly used git commands are:" -msgstr "Die allgemein verwendeten Git-Kommandos sind:" - -#: builtin/help.c:367 +#: builtin/help.c:349 #, c-format msgid "'%s': unknown man viewer." msgstr "'%s': unbekannter Handbuch-Betrachter." -#: builtin/help.c:384 +#: builtin/help.c:366 msgid "no man viewer handled the request" msgstr "kein Handbuch-Betrachter konnte mit dieser Anfrage umgehen" -#: builtin/help.c:392 +#: builtin/help.c:374 msgid "no info viewer handled the request" msgstr "kein Informations-Betrachter konnte mit dieser Anfrage umgehen" -#: builtin/help.c:447 builtin/help.c:454 +#: builtin/help.c:429 builtin/help.c:436 #, c-format msgid "usage: %s%s" msgstr "Verwendung: %s%s" -#: builtin/help.c:470 +#: builtin/help.c:452 #, c-format msgid "`git %s' is aliased to `%s'" msgstr "für `git %s' wurde der Alias `%s' angelegt" @@ -5683,100 +5842,100 @@ msgstr "" msgid "Unknown commit %s" msgstr "Unbekannte Version %s" -#: builtin/ls-files.c:408 +#: builtin/ls-files.c:409 msgid "git ls-files [options] [...]" msgstr "git ls-files [Optionen] [...]" -#: builtin/ls-files.c:463 +#: builtin/ls-files.c:466 msgid "identify the file status with tags" msgstr "zeigt den Dateistatus mit Markierungen" -#: builtin/ls-files.c:465 +#: builtin/ls-files.c:468 msgid "use lowercase letters for 'assume unchanged' files" msgstr "" "verwendet Kleinbuchstaben für Dateien mit 'assume unchanged' Markierung" -#: builtin/ls-files.c:467 +#: builtin/ls-files.c:470 msgid "show cached files in the output (default)" msgstr "zeigt zwischengespeicherten Dateien in der Ausgabe an (Standard)" -#: builtin/ls-files.c:469 +#: builtin/ls-files.c:472 msgid "show deleted files in the output" msgstr "zeigt entfernte Dateien in der Ausgabe an" -#: builtin/ls-files.c:471 +#: builtin/ls-files.c:474 msgid "show modified files in the output" msgstr "zeigt geänderte Dateien in der Ausgabe an" -#: builtin/ls-files.c:473 +#: builtin/ls-files.c:476 msgid "show other files in the output" msgstr "zeigt sonstige Dateien in der Ausgabe an" -#: builtin/ls-files.c:475 +#: builtin/ls-files.c:478 msgid "show ignored files in the output" msgstr "zeigt ignorierte Dateien in der Ausgabe an" -#: builtin/ls-files.c:478 +#: builtin/ls-files.c:481 msgid "show staged contents' object name in the output" msgstr "zeigt Objektnamen von Inhalten in der Bereitstellung in der Ausgabe an" -#: builtin/ls-files.c:480 +#: builtin/ls-files.c:483 msgid "show files on the filesystem that need to be removed" msgstr "zeigt Dateien im Dateisystem, die gelöscht werden müssen, an" -#: builtin/ls-files.c:482 +#: builtin/ls-files.c:485 msgid "show 'other' directories' name only" msgstr "zeigt nur Namen von 'sonstigen' Verzeichnissen an" -#: builtin/ls-files.c:485 +#: builtin/ls-files.c:488 msgid "don't show empty directories" msgstr "zeigt keine leeren Verzeichnisse an" -#: builtin/ls-files.c:488 +#: builtin/ls-files.c:491 msgid "show unmerged files in the output" msgstr "zeigt nicht zusammengeführte Dateien in der Ausgabe an" -#: builtin/ls-files.c:490 +#: builtin/ls-files.c:493 msgid "show resolve-undo information" msgstr "zeigt 'resolve-undo' Informationen an" -#: builtin/ls-files.c:492 +#: builtin/ls-files.c:495 msgid "skip files matching pattern" msgstr "lässt Dateien aus, die einem Muster entsprechen" -#: builtin/ls-files.c:495 +#: builtin/ls-files.c:498 msgid "exclude patterns are read from " msgstr "schließt Muster, gelesen von , aus" -#: builtin/ls-files.c:498 +#: builtin/ls-files.c:501 msgid "read additional per-directory exclude patterns in " msgstr "liest zusätzliche pro-Verzeichnis Auschlussmuster aus " -#: builtin/ls-files.c:500 +#: builtin/ls-files.c:503 msgid "add the standard git exclusions" msgstr "fügt die standardmäßigen Git-Ausschlüsse hinzu" -#: builtin/ls-files.c:503 +#: builtin/ls-files.c:506 msgid "make the output relative to the project top directory" msgstr "Ausgabe relativ zum Projektverzeichnis" -#: builtin/ls-files.c:506 +#: builtin/ls-files.c:509 msgid "if any is not in the index, treat this as an error" msgstr "" "behandle es als Fehler, wenn sich eine nicht in der Bereitstellung " "befindet" -#: builtin/ls-files.c:507 +#: builtin/ls-files.c:510 msgid "tree-ish" msgstr "Versionsreferenz" -#: builtin/ls-files.c:508 +#: builtin/ls-files.c:511 msgid "pretend that paths removed since are still present" msgstr "" "gibt vor, dass Pfade, die seit gelöscht wurden, immer " "noch vorhanden sind" -#: builtin/ls-files.c:510 +#: builtin/ls-files.c:513 msgid "show debugging data" msgstr "zeigt Ausgaben zur Fehlersuche an" @@ -5892,7 +6051,7 @@ msgstr "erlaubt Vorspulen (Standard)" msgid "abort if fast-forward is not possible" msgstr "bricht ab, wenn kein Vorspulen möglich ist" -#: builtin/merge.c:202 builtin/notes.c:870 builtin/revert.c:112 +#: builtin/merge.c:202 builtin/notes.c:866 builtin/revert.c:112 msgid "strategy" msgstr "Strategie" @@ -6000,11 +6159,12 @@ msgstr "" "Zusammenführung abzuschließen.\n" #: builtin/merge.c:788 +#, c-format msgid "" "Please enter a commit message to explain why this merge is necessary,\n" "especially if it merges an updated upstream into a topic branch.\n" "\n" -"Lines starting with '#' will be ignored, and an empty message aborts\n" +"Lines starting with '%c' will be ignored, and an empty message aborts\n" "the commit.\n" msgstr "" "Bitte geben Sie eine Versionsbeschreibung ein um zu erklären, warum diese " @@ -6012,59 +6172,59 @@ msgstr "" "insbesondere wenn es einen aktualisierten, externen Zweig mit einem Thema-" "Zweig zusammenführt.\n" "\n" -"Zeilen beginnend mit '#' werden ignoriert, und eine leere Beschreibung " +"Zeilen beginnend mit '%c' werden ignoriert, und eine leere Beschreibung " "bricht die Eintragung ab.\n" -#: builtin/merge.c:813 +#: builtin/merge.c:812 msgid "Empty commit message." msgstr "Leere Versionsbeschreibung" -#: builtin/merge.c:825 +#: builtin/merge.c:824 #, c-format msgid "Wonderful.\n" msgstr "Wunderbar.\n" -#: builtin/merge.c:890 +#: builtin/merge.c:889 #, c-format msgid "Automatic merge failed; fix conflicts and then commit the result.\n" msgstr "" "Automatische Zusammenführung fehlgeschlagen; beheben Sie die Konflikte und " "tragen Sie dann das Ergebnis ein.\n" -#: builtin/merge.c:906 +#: builtin/merge.c:905 #, c-format msgid "'%s' is not a commit" msgstr "'%s' ist keine Version" -#: builtin/merge.c:947 +#: builtin/merge.c:946 msgid "No current branch." msgstr "Sie befinden sich auf keinem Zweig." -#: builtin/merge.c:949 +#: builtin/merge.c:948 msgid "No remote for the current branch." msgstr "Kein externes Archiv für den aktuellen Zweig." -#: builtin/merge.c:951 +#: builtin/merge.c:950 msgid "No default upstream defined for the current branch." msgstr "" "Es ist kein externes Standard-Projektarchiv für den aktuellen Zweig " "definiert." -#: builtin/merge.c:956 +#: builtin/merge.c:955 #, c-format msgid "No remote tracking branch for %s from %s" msgstr "Kein externer Übernahmezweig für %s von %s" -#: builtin/merge.c:1043 builtin/merge.c:1200 +#: builtin/merge.c:1042 builtin/merge.c:1199 #, c-format msgid "%s - not something we can merge" msgstr "%s - nichts was wir zusammenführen können" -#: builtin/merge.c:1111 +#: builtin/merge.c:1110 msgid "There is no merge to abort (MERGE_HEAD missing)." msgstr "Es gibt keine Zusammenführung zum Abbrechen (vermisse MERGE_HEAD)" -#: builtin/merge.c:1127 git-pull.sh:31 +#: builtin/merge.c:1126 git-pull.sh:31 msgid "" "You have not concluded your merge (MERGE_HEAD exists).\n" "Please, commit your changes before you can merge." @@ -6072,12 +6232,12 @@ msgstr "" "Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert).\n" "Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können." -#: builtin/merge.c:1130 git-pull.sh:34 +#: builtin/merge.c:1129 git-pull.sh:34 msgid "You have not concluded your merge (MERGE_HEAD exists)." msgstr "" "Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert)." -#: builtin/merge.c:1134 +#: builtin/merge.c:1133 msgid "" "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" "Please, commit your changes before you can merge." @@ -6085,82 +6245,82 @@ msgstr "" "Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert).\n" "Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können." -#: builtin/merge.c:1137 +#: builtin/merge.c:1136 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)." msgstr "" "Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert)." -#: builtin/merge.c:1146 +#: builtin/merge.c:1145 msgid "You cannot combine --squash with --no-ff." msgstr "Sie können --squash nicht mit --no-ff kombinieren." -#: builtin/merge.c:1151 +#: builtin/merge.c:1150 msgid "You cannot combine --no-ff with --ff-only." msgstr "Sie können --no-ff nicht mit --ff--only kombinieren." -#: builtin/merge.c:1158 +#: builtin/merge.c:1157 msgid "No commit specified and merge.defaultToUpstream not set." msgstr "Keine Version angegeben und merge.defaultToUpstream ist nicht gesetzt." -#: builtin/merge.c:1190 +#: builtin/merge.c:1189 msgid "Can merge only exactly one commit into empty head" msgstr "Kann nur exakt eine Version in einem leeren Zweig zusammenführen." -#: builtin/merge.c:1193 +#: builtin/merge.c:1192 msgid "Squash commit into empty head not supported yet" msgstr "Bin auf einem Zweig, der noch geboren wird; kann nicht quetschen." -#: builtin/merge.c:1195 +#: builtin/merge.c:1194 msgid "Non-fast-forward commit does not make sense into an empty head" msgstr "" "Nicht vorzuspulende Version kann nicht in einem leeren Zweig verwendet " "werden." -#: builtin/merge.c:1311 +#: builtin/merge.c:1310 #, c-format msgid "Updating %s..%s\n" msgstr "Aktualisiere %s..%s\n" -#: builtin/merge.c:1350 +#: builtin/merge.c:1349 #, c-format msgid "Trying really trivial in-index merge...\n" msgstr "Probiere wirklich triviale \"in-index\"-Zusammenführung...\n" -#: builtin/merge.c:1357 +#: builtin/merge.c:1356 #, c-format msgid "Nope.\n" msgstr "Nein.\n" -#: builtin/merge.c:1389 +#: builtin/merge.c:1388 msgid "Not possible to fast-forward, aborting." msgstr "Vorspulen nicht möglich, breche ab." -#: builtin/merge.c:1412 builtin/merge.c:1491 +#: builtin/merge.c:1411 builtin/merge.c:1490 #, c-format msgid "Rewinding the tree to pristine...\n" msgstr "Rücklauf des Zweiges bis zum Ursprung...\n" -#: builtin/merge.c:1416 +#: builtin/merge.c:1415 #, c-format msgid "Trying merge strategy %s...\n" msgstr "Probiere Zusammenführungsstrategie %s...\n" -#: builtin/merge.c:1482 +#: builtin/merge.c:1481 #, c-format msgid "No merge strategy handled the merge.\n" msgstr "Keine Zusammenführungsstrategie behandelt diese Zusammenführung.\n" -#: builtin/merge.c:1484 +#: builtin/merge.c:1483 #, c-format msgid "Merge with strategy %s failed.\n" msgstr "Zusammenführung mit Strategie %s fehlgeschlagen.\n" -#: builtin/merge.c:1493 +#: builtin/merge.c:1492 #, c-format msgid "Using the %s to prepare resolving by hand.\n" msgstr "Benutzen Sie \"%s\" um die Auflösung per Hand vorzubereiten.\n" -#: builtin/merge.c:1505 +#: builtin/merge.c:1504 #, c-format msgid "Automatic merge went well; stopped before committing as requested\n" msgstr "" @@ -6477,82 +6637,77 @@ msgstr "git notes prune []" msgid "git notes get-ref" msgstr "git notes get-ref" -#: builtin/notes.c:142 +#: builtin/notes.c:139 #, c-format msgid "unable to start 'show' for object '%s'" msgstr "konnte 'show' für Objekt '%s' nicht starten" -#: builtin/notes.c:148 -msgid "can't fdopen 'show' output fd" -msgstr "konnte Datei-Deskriptor für Ausgabe von 'show' nicht öffnen" - -#: builtin/notes.c:158 -#, c-format -msgid "failed to close pipe to 'show' for object '%s'" -msgstr "Schließen der Verbindung zu 'show' ist für Objekt '%s' fehlgeschlagen." +#: builtin/notes.c:143 +msgid "could not read 'show' output" +msgstr "Konnte Ausgabe von 'show' nicht lesen." -#: builtin/notes.c:161 +#: builtin/notes.c:151 #, c-format msgid "failed to finish 'show' for object '%s'" msgstr "konnte 'show' für Objekt '%s' nicht abschließen" -#: builtin/notes.c:178 builtin/tag.c:347 +#: builtin/notes.c:169 builtin/tag.c:341 #, c-format msgid "could not create file '%s'" msgstr "konnte Datei '%s' nicht erstellen" -#: builtin/notes.c:192 +#: builtin/notes.c:188 msgid "Please supply the note contents using either -m or -F option" msgstr "" "Bitte liefern Sie den Notiz-Inhalt unter Verwendung der Option -m oder -F." -#: builtin/notes.c:213 builtin/notes.c:976 +#: builtin/notes.c:209 builtin/notes.c:972 #, c-format msgid "Removing note for object %s\n" msgstr "Entferne Notiz für Objekt %s\n" -#: builtin/notes.c:218 +#: builtin/notes.c:214 msgid "unable to write note object" msgstr "Konnte Notiz-Objekt nicht schreiben" -#: builtin/notes.c:220 +#: builtin/notes.c:216 #, c-format msgid "The note contents has been left in %s" msgstr "Die Notiz-Inhalte wurden in %s belassen" -#: builtin/notes.c:254 builtin/tag.c:542 +#: builtin/notes.c:250 builtin/tag.c:540 #, c-format msgid "cannot read '%s'" msgstr "kann '%s' nicht lesen" -#: builtin/notes.c:256 builtin/tag.c:545 +#: builtin/notes.c:252 builtin/tag.c:543 #, c-format msgid "could not open or read '%s'" msgstr "konnte '%s' nicht öffnen oder lesen" -#: builtin/notes.c:275 builtin/notes.c:448 builtin/notes.c:450 -#: builtin/notes.c:510 builtin/notes.c:564 builtin/notes.c:647 -#: builtin/notes.c:652 builtin/notes.c:727 builtin/notes.c:769 -#: builtin/notes.c:971 builtin/tag.c:558 +#: builtin/notes.c:271 builtin/notes.c:444 builtin/notes.c:446 +#: builtin/notes.c:506 builtin/notes.c:560 builtin/notes.c:643 +#: builtin/notes.c:648 builtin/notes.c:723 builtin/notes.c:765 +#: builtin/notes.c:967 builtin/tag.c:556 #, c-format msgid "Failed to resolve '%s' as a valid ref." msgstr "Konnte '%s' nicht als gültige Referenz auflösen." -#: builtin/notes.c:278 +#: builtin/notes.c:274 #, c-format msgid "Failed to read object '%s'." msgstr "Fehler beim Lesen des Objektes '%s'." -#: builtin/notes.c:302 +#: builtin/notes.c:298 msgid "Cannot commit uninitialized/unreferenced notes tree" msgstr "Kann uninitialisierten/unreferenzierten Notiz-Baum nicht eintragen." -#: builtin/notes.c:343 +#: builtin/notes.c:339 #, c-format msgid "Bad notes.rewriteMode value: '%s'" msgstr "Ungültiger notes.rewriteMode Wert: '%s'" -#: builtin/notes.c:353 +#: builtin/notes.c:349 #, c-format msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" msgstr "" @@ -6560,58 +6715,58 @@ msgstr "" #. TRANSLATORS: The first %s is the name of the #. environment variable, the second %s is its value -#: builtin/notes.c:380 +#: builtin/notes.c:376 #, c-format msgid "Bad %s value: '%s'" msgstr "Ungültiger %s Wert: '%s'" -#: builtin/notes.c:444 +#: builtin/notes.c:440 #, c-format msgid "Malformed input line: '%s'." msgstr "Fehlerhafte Eingabezeile: '%s'." -#: builtin/notes.c:459 +#: builtin/notes.c:455 #, c-format msgid "Failed to copy notes from '%s' to '%s'" msgstr "Fehler beim Kopieren der Notizen von '%s' nach '%s'" -#: builtin/notes.c:503 builtin/notes.c:557 builtin/notes.c:630 -#: builtin/notes.c:642 builtin/notes.c:715 builtin/notes.c:762 -#: builtin/notes.c:1036 +#: builtin/notes.c:499 builtin/notes.c:553 builtin/notes.c:626 +#: builtin/notes.c:638 builtin/notes.c:711 builtin/notes.c:758 +#: builtin/notes.c:1032 msgid "too many parameters" msgstr "zu viele Parameter" -#: builtin/notes.c:516 builtin/notes.c:775 +#: builtin/notes.c:512 builtin/notes.c:771 #, c-format msgid "No note found for object %s." msgstr "Kein Notiz für Objekt %s gefunden." -#: builtin/notes.c:538 builtin/notes.c:695 +#: builtin/notes.c:534 builtin/notes.c:691 msgid "note contents as a string" msgstr "Notizinhalte als Zeichenkette" -#: builtin/notes.c:541 builtin/notes.c:698 +#: builtin/notes.c:537 builtin/notes.c:694 msgid "note contents in a file" msgstr "Notizinhalte in einer Datei" -#: builtin/notes.c:543 builtin/notes.c:546 builtin/notes.c:700 -#: builtin/notes.c:703 builtin/tag.c:476 +#: builtin/notes.c:539 builtin/notes.c:542 builtin/notes.c:696 +#: builtin/notes.c:699 builtin/tag.c:474 msgid "object" msgstr "Objekt" -#: builtin/notes.c:544 builtin/notes.c:701 +#: builtin/notes.c:540 builtin/notes.c:697 msgid "reuse and edit specified note object" msgstr "Wiederverwendung und Bearbeitung des angegebenen Notiz-Objektes" -#: builtin/notes.c:547 builtin/notes.c:704 +#: builtin/notes.c:543 builtin/notes.c:700 msgid "reuse specified note object" msgstr "Wiederverwendung des angegebenen Notiz-Objektes" -#: builtin/notes.c:549 builtin/notes.c:617 +#: builtin/notes.c:545 builtin/notes.c:613 msgid "replace existing notes" msgstr "ersetzt existierende Notizen" -#: builtin/notes.c:583 +#: builtin/notes.c:579 #, c-format msgid "" "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -6620,26 +6775,26 @@ msgstr "" "Konnte Notizen nicht hinzufügen. Existierende Notizen für Objekt %s " "gefunden. Verwenden Sie '-f' um die existierenden Notizen zu überschreiben." -#: builtin/notes.c:588 builtin/notes.c:665 +#: builtin/notes.c:584 builtin/notes.c:661 #, c-format msgid "Overwriting existing notes for object %s\n" msgstr "Überschreibe existierende Notizen für Objekt %s\n" -#: builtin/notes.c:618 +#: builtin/notes.c:614 msgid "read objects from stdin" msgstr "liest Objekte von der Standard-Eingabe" -#: builtin/notes.c:620 +#: builtin/notes.c:616 msgid "load rewriting config for (implies --stdin)" msgstr "" "lädt Konfiguration für beim Umschreiben von Versionen (impliziert " "--stdin)" -#: builtin/notes.c:638 +#: builtin/notes.c:634 msgid "too few parameters" msgstr "zu wenig Parameter" -#: builtin/notes.c:659 +#: builtin/notes.c:655 #, c-format msgid "" "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -6648,12 +6803,12 @@ msgstr "" "Kann Notizen nicht kopieren. Existierende Notizen für Objekt %s gefunden. " "Verwenden Sie '-f' um die existierenden Notizen zu überschreiben." -#: builtin/notes.c:671 +#: builtin/notes.c:667 #, c-format msgid "Missing notes on source object %s. Cannot copy." msgstr "Keine Notizen für Quell-Objekt %s. Kopie nicht möglich." -#: builtin/notes.c:720 +#: builtin/notes.c:716 #, c-format msgid "" "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n" @@ -6662,15 +6817,15 @@ msgstr "" "Die Optionen -m/-F/-c/-C sind für das Unterkommando 'edit' veraltet.\n" "Bitte benutzen Sie stattdessen 'git notes add -f -m/-F/-c/-C'.\n" -#: builtin/notes.c:867 +#: builtin/notes.c:863 msgid "General options" msgstr "Allgemeine Optionen" -#: builtin/notes.c:869 +#: builtin/notes.c:865 msgid "Merge options" msgstr "Optionen für Zusammenführung" -#: builtin/notes.c:871 +#: builtin/notes.c:867 msgid "" "resolve notes conflicts using the given strategy (manual/ours/theirs/union/" "cat_sort_uniq)" @@ -6678,46 +6833,46 @@ msgstr "" "löst Konflikte bei Notizen mit der angegebenen Strategie auf (manual/ours/" "theirs/union/cat_sort_uniq)" -#: builtin/notes.c:873 +#: builtin/notes.c:869 msgid "Committing unmerged notes" msgstr "trägt nicht zusammengeführte Notizen ein" -#: builtin/notes.c:875 +#: builtin/notes.c:871 msgid "finalize notes merge by committing unmerged notes" msgstr "" "schließt Zusammenführung von Notizen ab, in dem nicht zusammengeführte " "Notizen eingetragen werden" -#: builtin/notes.c:877 +#: builtin/notes.c:873 msgid "Aborting notes merge resolution" msgstr "bricht Konfliktauflösung bei Zusammenführung von Notizen ab" -#: builtin/notes.c:879 +#: builtin/notes.c:875 msgid "abort notes merge" msgstr "bricht Zusammenführung von Notizen ab" -#: builtin/notes.c:974 +#: builtin/notes.c:970 #, c-format msgid "Object %s has no note\n" msgstr "Objekt %s hat keine Notiz\n" -#: builtin/notes.c:986 +#: builtin/notes.c:982 msgid "attempt to remove non-existent note is not an error" msgstr "der Versuch, eine nicht existierende Notiz zu löschen, ist kein Fehler" -#: builtin/notes.c:989 +#: builtin/notes.c:985 msgid "read object names from the standard input" msgstr "liest Objektnamen von der Standard-Eingabe" -#: builtin/notes.c:1070 +#: builtin/notes.c:1066 msgid "notes_ref" msgstr "Notiz-Referenz" -#: builtin/notes.c:1071 +#: builtin/notes.c:1067 msgid "use notes from " msgstr "verwendet Notizen von " -#: builtin/notes.c:1106 builtin/remote.c:1598 +#: builtin/notes.c:1102 builtin/remote.c:1598 #, c-format msgid "Unknown subcommand: %s" msgstr "Unbekanntes Unterkommando: %s" @@ -7095,28 +7250,56 @@ msgstr "" #: builtin/push.c:224 msgid "" -"Updates were rejected because the destination reference already exists\n" -"in the remote." +"Updates were rejected because the remote contains work that you do\n" +"not have locally. This is usually caused by another repository pushing\n" +"to the same ref. You may want to first merge the remote changes (e.g.,\n" +"'git pull') before pushing again.\n" +"See the 'Note about fast-forwards' in 'git push --help' for details." +msgstr "" +"Aktualisierungen wurden zurückgewiesen, weil das Fernarchiv Versionen " +"enthält,\n" +"die lokal nicht vorhanden sind. Das wird üblicherweise durch das Versenden " +"von\n" +"Versionen auf dieselbe Referenz von einem anderen Projektarchiv aus " +"verursacht.\n" +"Vielleicht müssen Sie die externen Änderungen zusammenzuführen (z.B. 'git " +"pull')\n" +"bevor Sie erneut versenden.\n" +"Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n" +"für weitere Details." + +#: builtin/push.c:231 +msgid "Updates were rejected because the tag already exists in the remote." msgstr "" -"Aktualisierungen wurden zurückgewiesen, weil die Zielreferenz bereits\n" +"Aktualisierungen wurden zurückgewiesen, weil die Markierung bereits\n" "im Fernarchiv existiert." -#: builtin/push.c:269 +#: builtin/push.c:234 +msgid "" +"You cannot update a remote ref that points at a non-commit object,\n" +"or update a remote ref to make it point at a non-commit object,\n" +"without using the '--force' option.\n" +msgstr "" +"Sie können keine externe Referenz aktualisieren, die auf ein Objekt zeigt,\n" +"das keine Version ist, oder es auf ein solches Objekt zeigen lassen, ohne\n" +"die Option '--force' zu verwenden.\n" + +#: builtin/push.c:294 #, c-format msgid "Pushing to %s\n" msgstr "Versende nach %s\n" -#: builtin/push.c:273 +#: builtin/push.c:298 #, c-format msgid "failed to push some refs to '%s'" msgstr "Fehler beim Versenden einiger Referenzen nach '%s'" -#: builtin/push.c:302 +#: builtin/push.c:331 #, c-format msgid "bad repository '%s'" msgstr "ungültiges Projektarchiv '%s'" -#: builtin/push.c:303 +#: builtin/push.c:332 msgid "" "No configured push destination.\n" "Either specify the URL from the command-line or configure a remote " @@ -7138,82 +7321,86 @@ msgstr "" "\n" " git push \n" -#: builtin/push.c:318 +#: builtin/push.c:347 msgid "--all and --tags are incompatible" msgstr "Die Optionen --all und --tags sind inkompatibel." -#: builtin/push.c:319 +#: builtin/push.c:348 msgid "--all can't be combined with refspecs" msgstr "" "Die Option --all kann nicht mit Referenzspezifikationen kombiniert werden." -#: builtin/push.c:324 +#: builtin/push.c:353 msgid "--mirror and --tags are incompatible" msgstr "Die Optionen --mirror und --tags sind inkompatibel." -#: builtin/push.c:325 +#: builtin/push.c:354 msgid "--mirror can't be combined with refspecs" msgstr "" "Die Option --mirror kann nicht mit Referenzspezifikationen kombiniert werden." -#: builtin/push.c:330 +#: builtin/push.c:359 msgid "--all and --mirror are incompatible" msgstr "Die Optionen --all und --mirror sind inkompatibel." -#: builtin/push.c:390 +#: builtin/push.c:419 msgid "repository" msgstr "Projektarchiv" -#: builtin/push.c:391 +#: builtin/push.c:420 msgid "push all refs" msgstr "versendet alle Referenzen" -#: builtin/push.c:392 +#: builtin/push.c:421 msgid "mirror all refs" msgstr "spiegelt alle Referenzen" -#: builtin/push.c:394 +#: builtin/push.c:423 msgid "delete refs" msgstr "löscht Referenzen" -#: builtin/push.c:395 +#: builtin/push.c:424 msgid "push tags (can't be used with --all or --mirror)" msgstr "" "versendet Markierungen (kann nicht mit --all oder --mirror verwendet werden)" -#: builtin/push.c:398 +#: builtin/push.c:427 msgid "force updates" msgstr "erzwingt Aktualisierung" -#: builtin/push.c:399 +#: builtin/push.c:428 msgid "check" msgstr "" -#: builtin/push.c:400 +#: builtin/push.c:429 msgid "control recursive pushing of submodules" msgstr "steuert rekursives Versenden von Unterprojekten" -#: builtin/push.c:402 +#: builtin/push.c:431 msgid "use thin pack" msgstr "verwendet kleinere Pakete" -#: builtin/push.c:403 builtin/push.c:404 +#: builtin/push.c:432 builtin/push.c:433 msgid "receive pack program" msgstr "'receive pack' Programm" -#: builtin/push.c:405 +#: builtin/push.c:434 msgid "set upstream for git pull/status" msgstr "setzt externes Projektarchiv für \"git pull/status\"" -#: builtin/push.c:408 +#: builtin/push.c:437 msgid "prune locally removed refs" msgstr "entfernt lokal gelöschte Referenzen" -#: builtin/push.c:418 +#: builtin/push.c:439 +msgid "bypass pre-push hook" +msgstr "umgeht \"pre-push hook\"" + +#: builtin/push.c:448 msgid "--delete is incompatible with --all, --mirror and --tags" msgstr "Die Option --delete ist inkompatibel mit --all, --mirror und --tags." -#: builtin/push.c:420 +#: builtin/push.c:450 msgid "--delete doesn't make sense without any refs" msgstr "Die Option --delete kann nur mit Referenzen verwendet werden." @@ -8390,170 +8577,164 @@ msgid "could not verify the tag '%s'" msgstr "Konnte Markierung '%s' nicht verifizieren" #: builtin/tag.c:249 +#, c-format msgid "" "\n" -"#\n" -"# Write a tag message\n" -"# Lines starting with '#' will be ignored.\n" -"#\n" +"Write a tag message\n" +"Lines starting with '%c' will be ignored.\n" msgstr "" "\n" -"#\n" -"# Geben Sie eine Markierungsbeschreibung ein.\n" -"# Zeilen, die mit '#' beginnen, werden ignoriert.\n" -"#\n" +"Geben Sie eine Markierungsbeschreibung ein.\n" +"Zeilen, die mit '%c' beginnen, werden ignoriert.\n" -#: builtin/tag.c:256 +#: builtin/tag.c:253 +#, c-format msgid "" "\n" -"#\n" -"# Write a tag message\n" -"# Lines starting with '#' will be kept; you may remove them yourself if you " +"Write a tag message\n" +"Lines starting with '%c' will be kept; you may remove them yourself if you " "want to.\n" -"#\n" msgstr "" "\n" -"#\n" -"# Geben Sie eine Markierungsbeschreibung ein.\n" -"# Zeilen, die mit '#' beginnen, werden behalten; Sie dürfen diese\n" -"# selbst entfernen wenn Sie möchten.\n" -"#\n" +"Geben Sie eine Markierungsbeschreibung ein.\n" +"Zeilen, die mit '%c' beginnen, werden behalten; Sie dürfen diese\n" +"selbst entfernen wenn Sie möchten.\n" -#: builtin/tag.c:298 +#: builtin/tag.c:292 msgid "unable to sign the tag" msgstr "konnte Markierung nicht signieren" -#: builtin/tag.c:300 +#: builtin/tag.c:294 msgid "unable to write tag file" msgstr "konnte Markierungsdatei nicht schreiben" -#: builtin/tag.c:325 +#: builtin/tag.c:319 msgid "bad object type." msgstr "ungültiger Objekt-Typ" -#: builtin/tag.c:338 +#: builtin/tag.c:332 msgid "tag header too big." msgstr "Markierungskopf zu groß." -#: builtin/tag.c:370 +#: builtin/tag.c:368 msgid "no tag message?" msgstr "keine Markierungsbeschreibung?" -#: builtin/tag.c:376 +#: builtin/tag.c:374 #, c-format msgid "The tag message has been left in %s\n" msgstr "Die Markierungsbeschreibung wurde gelassen in %s\n" -#: builtin/tag.c:425 +#: builtin/tag.c:423 msgid "switch 'points-at' requires an object" msgstr "Option 'points-at' erfordert ein Objekt" -#: builtin/tag.c:427 +#: builtin/tag.c:425 #, c-format msgid "malformed object name '%s'" msgstr "fehlerhafter Objekt-Name '%s'" -#: builtin/tag.c:447 +#: builtin/tag.c:445 msgid "list tag names" msgstr "listet Markierungsnamen auf" -#: builtin/tag.c:449 +#: builtin/tag.c:447 msgid "print lines of each tag message" msgstr "zeigt Zeilen jeder Markierungsbeschreibung" -#: builtin/tag.c:451 +#: builtin/tag.c:449 msgid "delete tags" msgstr "löscht Markierungen" -#: builtin/tag.c:452 +#: builtin/tag.c:450 msgid "verify tags" msgstr "überprüft Markierungen" -#: builtin/tag.c:454 +#: builtin/tag.c:452 msgid "Tag creation options" msgstr "Optionen für Erstellung von Markierungen" -#: builtin/tag.c:456 +#: builtin/tag.c:454 msgid "annotated tag, needs a message" msgstr "annotierte Markierung, benötigt eine Beschreibung" -#: builtin/tag.c:458 +#: builtin/tag.c:456 msgid "tag message" msgstr "Markierungsbeschreibung" -#: builtin/tag.c:460 +#: builtin/tag.c:458 msgid "annotated and GPG-signed tag" msgstr "annotierte und GPG-signierte Markierung" -#: builtin/tag.c:464 +#: builtin/tag.c:462 msgid "use another key to sign the tag" msgstr "verwendet einen anderen Schlüssel um die Markierung zu signieren" -#: builtin/tag.c:465 +#: builtin/tag.c:463 msgid "replace the tag if exists" msgstr "ersetzt die Markierung, wenn sie existiert" -#: builtin/tag.c:466 +#: builtin/tag.c:464 msgid "show tag list in columns" msgstr "zeigt Liste der Markierungen in Spalten" -#: builtin/tag.c:468 +#: builtin/tag.c:466 msgid "Tag listing options" msgstr "Optionen für Auflistung der Markierungen" -#: builtin/tag.c:471 +#: builtin/tag.c:469 msgid "print only tags that contain the commit" msgstr "gibt nur Markierungen aus, die diese Version beinhalten" -#: builtin/tag.c:477 +#: builtin/tag.c:475 msgid "print only tags of the object" msgstr "gibt nur Markierungen von dem Objekt aus" -#: builtin/tag.c:506 +#: builtin/tag.c:504 msgid "--column and -n are incompatible" msgstr "--column und -n sind inkompatibel" -#: builtin/tag.c:523 +#: builtin/tag.c:521 msgid "-n option is only allowed with -l." msgstr "-n Option ist nur erlaubt mit -l." -#: builtin/tag.c:525 +#: builtin/tag.c:523 msgid "--contains option is only allowed with -l." msgstr "--contains Option ist nur erlaubt mit -l." -#: builtin/tag.c:527 +#: builtin/tag.c:525 msgid "--points-at option is only allowed with -l." msgstr "--points-at Option ist nur erlaubt mit -l." -#: builtin/tag.c:535 +#: builtin/tag.c:533 msgid "only one -F or -m option is allowed." msgstr "nur eine -F oder -m Option ist erlaubt." -#: builtin/tag.c:555 +#: builtin/tag.c:553 msgid "too many params" msgstr "zu viele Parameter" -#: builtin/tag.c:561 +#: builtin/tag.c:559 #, c-format msgid "'%s' is not a valid tag name." msgstr "'%s' ist kein gültiger Markierungsname." -#: builtin/tag.c:566 +#: builtin/tag.c:564 #, c-format msgid "tag '%s' already exists" msgstr "Markierung '%s' existiert bereits" -#: builtin/tag.c:584 +#: builtin/tag.c:582 #, c-format msgid "%s: cannot lock the ref" msgstr "%s: kann Referenz nicht sperren" -#: builtin/tag.c:586 +#: builtin/tag.c:584 #, c-format msgid "%s: cannot update the ref" msgstr "%s: kann Referenz nicht aktualisieren" -#: builtin/tag.c:588 +#: builtin/tag.c:586 #, c-format msgid "Updated tag '%s' (was %s)\n" msgstr "Aktualisierte Markierung '%s' (war %s)\n" @@ -8798,7 +8979,7 @@ msgid "Print lines matching a pattern" msgstr "Stellt Zeilen dar, die einem Muster entsprechen" #: common-cmds.h:17 -msgid "Create an empty git repository or reinitialize an existing one" +msgid "Create an empty Git repository or reinitialize an existing one" msgstr "" "Erstellt ein leeres Git-Projektarchiv oder initialisiert ein bestehendes neu" @@ -8832,8 +9013,7 @@ msgstr "Baut lokale Versionen auf einem aktuellerem externen Zweig neu auf" #: common-cmds.h:24 msgid "Reset current HEAD to the specified state" -msgstr "" -"Setzt die aktuelle Zweigspitze (HEAD) zu einem spezifizierten Zustand" +msgstr "Setzt die aktuelle Zweigspitze (HEAD) zu einem spezifizierten Zustand" #: common-cmds.h:25 msgid "Remove files from the working tree and from the index" @@ -9069,7 +9249,7 @@ msgstr "" #: git-bisect.sh:140 msgid "won't bisect on seeked tree" -msgstr "\"bisect\" auf gesuchtem Zweig nicht möglich" +msgstr "binäre Suche auf gesuchtem Zweig nicht möglich" #: git-bisect.sh:144 msgid "Bad HEAD - strange symbolic ref" @@ -9102,7 +9282,7 @@ msgstr "'git bisect bad' kann nur ein Argument entgegennehmen." #. this is less optimum. #: git-bisect.sh:273 msgid "Warning: bisecting only with a bad commit." -msgstr "Warnung: halbiere nur mit einer fehlerhaften Version" +msgstr "Warnung: binäre Suche nur mit einer fehlerhaften Version" #. TRANSLATORS: Make sure to include [Y] and [n] in your #. translation. The program will only accept English input @@ -9132,7 +9312,7 @@ msgstr "" #: git-bisect.sh:347 git-bisect.sh:474 msgid "We are not bisecting." -msgstr "Wir sind nicht beim Halbieren." +msgstr "keine binäre Suche im Gange" #: git-bisect.sh:354 #, sh-format @@ -9172,12 +9352,12 @@ msgid "" "bisect run failed:\n" "exit code $res from '$command' is < 0 or >= 128" msgstr "" -"Ausführung der Halbierung fehlgeschlagen:\n" +"'bisect run' fehlgeschlagen:\n" "Rückkehrwert $res von '$command' ist < 0 oder >= 128" #: git-bisect.sh:453 msgid "bisect run cannot continue any more" -msgstr "Ausführung der Halbierung kann nicht mehr fortgesetzt werden" +msgstr "'bisect run' kann nicht mehr fortgesetzt werden" #: git-bisect.sh:459 #, sh-format @@ -9185,12 +9365,12 @@ msgid "" "bisect run failed:\n" "'bisect_state $state' exited with error code $res" msgstr "" -"Ausführung der Halbierung fehlgeschlagen:\n" +"'bisect run' fehlgeschlagen:\n" "'bisect_state $state' wurde mit Fehlerwert $res beendet" #: git-bisect.sh:466 msgid "bisect run success" -msgstr "Halbierung erfolgreich ausgeführt" +msgstr "'bisect run' erfolgreich ausgeführt" #: git-pull.sh:21 msgid "" @@ -9725,18 +9905,25 @@ msgid "blob" msgstr "Blob" #: git-submodule.sh:979 -msgid "# Submodules changed but not updated:" -msgstr "# Unterprojekte geändert, aber nicht aktualisiert:" +msgid "Submodules changed but not updated:" +msgstr "Unterprojekte geändert, aber nicht aktualisiert:" #: git-submodule.sh:981 -msgid "# Submodule changes to be committed:" -msgstr "# Änderungen in Unterprojekt zum Eintragen:" +msgid "Submodule changes to be committed:" +msgstr "Änderungen in Unterprojekt zum Eintragen:" #: git-submodule.sh:1129 #, sh-format msgid "Synchronizing submodule url for '$prefix$sm_path'" msgstr "Synchronisiere Unterprojekt-URL für '$prefix$sm_path'" +#~ msgid "can't fdopen 'show' output fd" +#~ msgstr "konnte Datei-Deskriptor für Ausgabe von 'show' nicht öffnen" + +#~ msgid "failed to close pipe to 'show' for object '%s'" +#~ msgstr "" +#~ "Schließen der Verbindung zu 'show' ist für Objekt '%s' fehlgeschlagen." + #~ msgid "You do not have a valid HEAD" #~ msgstr "Sie haben keine gültige Zweigspitze (HEAD)" diff --git a/po/git.pot b/po/git.pot index a2ab9e8263..a826dcbf9f 100644 --- a/po/git.pot +++ b/po/git.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2013-02-19 13:32+0800\n" +"POT-Creation-Date: 2013-03-05 12:36+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -122,7 +122,7 @@ msgstr "" #: attr.c:259 msgid "" -"Negative patterns are forbidden in git attributes\n" +"Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." msgstr "" diff --git a/po/sv.po b/po/sv.po index 9ac06c9700..15f1aa82a0 100644 --- a/po/sv.po +++ b/po/sv.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: git 1.8.2\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2013-02-19 13:32+0800\n" -"PO-Revision-Date: 2013-02-19 10:25+0100\n" +"POT-Creation-Date: 2013-03-05 12:36+0800\n" +"PO-Revision-Date: 2013-03-05 09:17+0100\n" "Last-Translator: Peter Krefting \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -127,10 +127,10 @@ msgstr "sökväg till kommandot git-upload-archive på fjärren" #: attr.c:259 msgid "" -"Negative patterns are forbidden in git attributes\n" +"Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." msgstr "" -"Negativa mönster är förbjudna i git-attribut\n" +"Negativa mönster ignoreras i git-attribut\n" "Använd '\\!' för att inleda med ett utropstecken." #: bundle.c:36 diff --git a/po/vi.po b/po/vi.po index f1ab8621ec..7d9d05d6cb 100644 --- a/po/vi.po +++ b/po/vi.po @@ -6,10 +6,10 @@ # msgid "" msgstr "" -"Project-Id-Version: git-v1.8.2-rc0-16-g20a59\n" +"Project-Id-Version: git-v1.8.2-rc2-4-g77995\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2013-02-19 13:32+0800\n" -"PO-Revision-Date: 2013-02-20 07:14+0700\n" +"POT-Creation-Date: 2013-03-05 12:36+0800\n" +"PO-Revision-Date: 2013-03-06 13:55+0700\n" "Last-Translator: Trần Ngọc Quân \n" "Language-Team: Vietnamese \n" "Language: vi\n" @@ -131,11 +131,11 @@ msgstr "đường dẫn đến lệnh git-upload-pack trên máy chủ" #: attr.c:259 msgid "" -"Negative patterns are forbidden in git attributes\n" +"Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." msgstr "" -"Các mẫu dạng phủ định bị cấm dùng trong các thuộc tính của git\n" -"Dùng “\\!” cho các chuỗi văn bản có dấu chấm than." +"Các mẫu dạng phủ định bị cấm dùng cho các thuộc tính của git\n" +"Dùng “\\!” cho các chuỗi văn bản có dấu chấm than dẫn đầu." #: bundle.c:36 #, c-format @@ -1269,7 +1269,7 @@ msgstr " (dùng \"git am --abort\" để phục hồi lại nhánh nguyên th #: wt-status.c:879 wt-status.c:896 #, c-format msgid "You are currently rebasing branch '%s' on '%s'." -msgstr "Bạn hiện nay đang thực hiện việc rebase nhánh '%s' trên '%s'." +msgstr "Bạn hiện nay đang thực hiện việc rebase nhánh “%s” trên “%s”." #: wt-status.c:884 wt-status.c:901 msgid "You are currently rebasing." @@ -1298,7 +1298,7 @@ msgid "" "You are currently splitting a commit while rebasing branch '%s' on '%s'." msgstr "" "Bạn hiện nay đang thực hiện việc chia tách một lần chuyển giao (commit) " -"trong khi đang rebase nhánh '%s' trên '%s'." +"trong khi đang rebase nhánh “%s” trên “%s”." #: wt-status.c:913 msgid "You are currently splitting a commit during a rebase." @@ -1317,7 +1317,7 @@ msgstr "" msgid "You are currently editing a commit while rebasing branch '%s' on '%s'." msgstr "" "Bạn hiện nay đang thực hiện việc sửa chữa một lần chuyển giao (commit) trong " -"khi đang rebase nhánh '%s' trên '%s'." +"khi đang rebase nhánh “%s” trên “%s”." #: wt-status.c:925 msgid "You are currently editing a commit during a rebase." @@ -1348,7 +1348,7 @@ msgstr " (khi tất cả các xung đột đã sửa xong: chạy lệnh \"git msgid "You are currently bisecting branch '%s'." msgstr "" "Bạn hiện nay đang thực hiện thao tác di chuyển nửa bước (bisect) trên nhánh " -"'%s'." +"“%s”." #: wt-status.c:962 msgid "You are currently bisecting." diff --git a/po/zh_CN.po b/po/zh_CN.po index 583ed3385d..c48ae10d78 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2013-02-19 13:32+0800\n" -"PO-Revision-Date: 2013-02-19 14:44+0800\n" +"POT-Creation-Date: 2013-03-05 12:36+0800\n" +"PO-Revision-Date: 2013-03-05 13:07+0800\n" "Last-Translator: Jiang Xin \n" "Language-Team: GitHub \n" "Language: zh_CN\n" @@ -130,10 +130,10 @@ msgstr "远程 git-upload-archive 命令的路径" #: attr.c:259 msgid "" -"Negative patterns are forbidden in git attributes\n" +"Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." msgstr "" -"在 git attributes 中不允许使用负值模版\n" +"负值模版在 git attributes 中被忽略\n" "当字符串确实要以感叹号开始时,使用 '\\!'。" #: bundle.c:36 diff --git a/pretty.c b/pretty.c index eae57ad9d7..41f04e669d 100644 --- a/pretty.c +++ b/pretty.c @@ -345,7 +345,7 @@ static int needs_rfc2047_encoding(const char *line, int len, return 0; } -static void add_rfc2047(struct strbuf *sb, const char *line, int len, +static void add_rfc2047(struct strbuf *sb, const char *line, size_t len, const char *encoding, enum rfc2047_type type) { static const int max_encoded_length = 76; /* per rfc2047 */ @@ -355,9 +355,22 @@ static void add_rfc2047(struct strbuf *sb, const char *line, int len, strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_addf(sb, "=?%s?q?", encoding); line_len += strlen(encoding) + 5; /* 5 for =??q? */ - for (i = 0; i < len; i++) { - unsigned ch = line[i] & 0xFF; - int is_special = is_rfc2047_special(ch, type); + + while (len) { + /* + * RFC 2047, section 5 (3): + * + * Each 'encoded-word' MUST represent an integral number of + * characters. A multi-octet character may not be split across + * adjacent 'encoded- word's. + */ + const unsigned char *p = (const unsigned char *)line; + int chrlen = mbs_chrlen(&line, &len, encoding); + int is_special = (chrlen > 1) || is_rfc2047_special(*p, type); + + /* "=%02X" * chrlen, or the byte itself */ + const char *encoded_fmt = is_special ? "=%02X" : "%c"; + int encoded_len = is_special ? 3 * chrlen : 1; /* * According to RFC 2047, we could encode the special character @@ -367,18 +380,15 @@ static void add_rfc2047(struct strbuf *sb, const char *line, int len, * causes ' ' to be encoded as '=20', avoiding this problem. */ - if (line_len + 2 + (is_special ? 3 : 1) > max_encoded_length) { + if (line_len + encoded_len + 2 > max_encoded_length) { + /* It won't fit with trailing "?=" --- break the line */ strbuf_addf(sb, "?=\n =?%s?q?", encoding); line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */ } - if (is_special) { - strbuf_addf(sb, "=%02X", ch); - line_len += 3; - } else { - strbuf_addch(sb, ch); - line_len++; - } + for (i = 0; i < chrlen; i++) + strbuf_addf(sb, encoded_fmt, p[i]); + line_len += encoded_len; } strbuf_addstr(sb, "?="); } @@ -759,8 +769,10 @@ struct format_commit_context { unsigned commit_signature_parsed:1; struct { char *gpg_output; + char *gpg_status; char good_bad; char *signer; + char *key; } signature; char *message; size_t width, indent1, indent2; @@ -948,13 +960,13 @@ static struct { char result; const char *check; } signature_check[] = { - { 'G', ": Good signature from " }, - { 'B', ": BAD signature from " }, + { 'G', "\n[GNUPG:] GOODSIG " }, + { 'B', "\n[GNUPG:] BADSIG " }, }; static void parse_signature_lines(struct format_commit_context *ctx) { - const char *buf = ctx->signature.gpg_output; + const char *buf = ctx->signature.gpg_status; int i; for (i = 0; i < ARRAY_SIZE(signature_check); i++) { @@ -964,6 +976,8 @@ static void parse_signature_lines(struct format_commit_context *ctx) continue; ctx->signature.good_bad = signature_check[i].result; found += strlen(signature_check[i].check); + ctx->signature.key = xmemdupz(found, 16); + found += 17; next = strchrnul(found, '\n'); ctx->signature.signer = xmemdupz(found, next - found); break; @@ -975,6 +989,7 @@ static void parse_commit_signature(struct format_commit_context *ctx) struct strbuf payload = STRBUF_INIT; struct strbuf signature = STRBUF_INIT; struct strbuf gpg_output = STRBUF_INIT; + struct strbuf gpg_status = STRBUF_INIT; int status; ctx->commit_signature_parsed = 1; @@ -984,13 +999,15 @@ static void parse_commit_signature(struct format_commit_context *ctx) goto out; status = verify_signed_buffer(payload.buf, payload.len, signature.buf, signature.len, - &gpg_output); + &gpg_output, &gpg_status); if (status && !gpg_output.len) goto out; ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL); + ctx->signature.gpg_status = strbuf_detach(&gpg_status, NULL); parse_signature_lines(ctx); out: + strbuf_release(&gpg_status); strbuf_release(&gpg_output); strbuf_release(&payload); strbuf_release(&signature); @@ -1200,6 +1217,10 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder, if (c->signature.signer) strbuf_addstr(sb, c->signature.signer); break; + case 'K': + if (c->signature.key) + strbuf_addstr(sb, c->signature.key); + break; } return 2; } diff --git a/read-cache.c b/read-cache.c index 827ae55c50..670a06bc79 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1260,7 +1260,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size) if (hdr->hdr_signature != htonl(CACHE_SIGNATURE)) return error("bad signature"); hdr_version = ntohl(hdr->hdr_version); - if (hdr_version < 2 || 4 < hdr_version) + if (hdr_version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < hdr_version) return error("bad index version %d", hdr_version); git_SHA1_Init(&c); git_SHA1_Update(&c, hdr, size - 20); diff --git a/remote.c b/remote.c index e53a6eb776..57f36e14da 100644 --- a/remote.c +++ b/remote.c @@ -15,6 +15,7 @@ static struct refspec s_tag_refspec = { 0, 1, 0, + 0, "refs/tags/*", "refs/tags/*" }; @@ -538,7 +539,7 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp /* * Before going on, special case ":" (or "+:") as a refspec - * for matching refs. + * for pushing matching refs. */ if (!fetch && rhs == lhs && rhs[1] == '\0') { rs[i].matching = 1; @@ -565,26 +566,25 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0); if (fetch) { - /* - * LHS - * - empty is allowed; it means HEAD. - * - otherwise it must be a valid looking ref. - */ + unsigned char unused[40]; + + /* LHS */ if (!*rs[i].src) - ; /* empty is ok */ - else if (check_refname_format(rs[i].src, flags)) + ; /* empty is ok; it means "HEAD" */ + else if (llen == 40 && !get_sha1_hex(rs[i].src, unused)) + rs[i].exact_sha1 = 1; /* ok */ + else if (!check_refname_format(rs[i].src, flags)) + ; /* valid looking ref is ok */ + else goto invalid; - /* - * RHS - * - missing is ok, and is same as empty. - * - empty is ok; it means not to store. - * - otherwise it must be a valid looking ref. - */ + /* RHS */ if (!rs[i].dst) - ; /* ok */ + ; /* missing is ok; it is the same as empty */ else if (!*rs[i].dst) - ; /* ok */ - else if (check_refname_format(rs[i].dst, flags)) + ; /* empty is ok; it means "do not store" */ + else if (!check_refname_format(rs[i].dst, flags)) + ; /* valid looking ref is ok */ + else goto invalid; } else { /* @@ -1195,6 +1195,101 @@ static struct ref **tail_ref(struct ref **head) return tail; } +struct tips { + struct commit **tip; + int nr, alloc; +}; + +static void add_to_tips(struct tips *tips, const unsigned char *sha1) +{ + struct commit *commit; + + if (is_null_sha1(sha1)) + return; + commit = lookup_commit_reference_gently(sha1, 1); + if (!commit || (commit->object.flags & TMP_MARK)) + return; + commit->object.flags |= TMP_MARK; + ALLOC_GROW(tips->tip, tips->nr + 1, tips->alloc); + tips->tip[tips->nr++] = commit; +} + +static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***dst_tail) +{ + struct string_list dst_tag = STRING_LIST_INIT_NODUP; + struct string_list src_tag = STRING_LIST_INIT_NODUP; + struct string_list_item *item; + struct ref *ref; + struct tips sent_tips; + + /* + * Collect everything we know they would have at the end of + * this push, and collect all tags they have. + */ + memset(&sent_tips, 0, sizeof(sent_tips)); + for (ref = *dst; ref; ref = ref->next) { + if (ref->peer_ref && + !is_null_sha1(ref->peer_ref->new_sha1)) + add_to_tips(&sent_tips, ref->peer_ref->new_sha1); + else + add_to_tips(&sent_tips, ref->old_sha1); + if (!prefixcmp(ref->name, "refs/tags/")) + string_list_append(&dst_tag, ref->name); + } + clear_commit_marks_many(sent_tips.nr, sent_tips.tip, TMP_MARK); + + sort_string_list(&dst_tag); + + /* Collect tags they do not have. */ + for (ref = src; ref; ref = ref->next) { + if (prefixcmp(ref->name, "refs/tags/")) + continue; /* not a tag */ + if (string_list_has_string(&dst_tag, ref->name)) + continue; /* they already have it */ + if (sha1_object_info(ref->new_sha1, NULL) != OBJ_TAG) + continue; /* be conservative */ + item = string_list_append(&src_tag, ref->name); + item->util = ref; + } + string_list_clear(&dst_tag, 0); + + /* + * At this point, src_tag lists tags that are missing from + * dst, and sent_tips lists the tips we are pushing or those + * that we know they already have. An element in the src_tag + * that is an ancestor of any of the sent_tips needs to be + * sent to the other side. + */ + if (sent_tips.nr) { + for_each_string_list_item(item, &src_tag) { + struct ref *ref = item->util; + struct ref *dst_ref; + struct commit *commit; + + if (is_null_sha1(ref->new_sha1)) + continue; + commit = lookup_commit_reference_gently(ref->new_sha1, 1); + if (!commit) + /* not pushing a commit, which is not an error */ + continue; + + /* + * Is this tag, which they do not have, reachable from + * any of the commits we are sending? + */ + if (!in_merge_bases_many(commit, sent_tips.nr, sent_tips.tip)) + continue; + + /* Add it in */ + dst_ref = make_linked_ref(ref->name, dst_tail); + hashcpy(dst_ref->new_sha1, ref->new_sha1); + dst_ref->peer_ref = copy_ref(ref); + } + } + string_list_clear(&src_tag, 0); + free(sent_tips.tip); +} + /* * Given the set of refs the local repository has, the set of refs the * remote repository has, and the refspec used for push, determine @@ -1257,6 +1352,10 @@ int match_push_refs(struct ref *src, struct ref **dst, free_name: free(dst_name); } + + if (flags & MATCH_REFS_FOLLOW_TAGS) + add_missing_tags(src, dst, &dst_tail); + if (send_prune) { /* check for missing refs on the remote */ for (ref = *dst; ref; ref = ref->next) { @@ -1466,7 +1565,12 @@ int get_fetch_map(const struct ref *remote_refs, } else { const char *name = refspec->src[0] ? refspec->src : "HEAD"; - ref_map = get_remote_ref(remote_refs, name); + if (refspec->exact_sha1) { + ref_map = alloc_ref(name); + get_sha1_hex(name, ref_map->old_sha1); + } else { + ref_map = get_remote_ref(remote_refs, name); + } if (!missing_ok && !ref_map) die("Couldn't find remote ref %s", name); if (ref_map) { diff --git a/remote.h b/remote.h index 251d8fd965..8743d6ef9d 100644 --- a/remote.h +++ b/remote.h @@ -62,6 +62,7 @@ struct refspec { unsigned force : 1; unsigned pattern : 1; unsigned matching : 1; + unsigned exact_sha1 : 1; char *src; char *dst; @@ -148,7 +149,8 @@ enum match_refs_flags { MATCH_REFS_NONE = 0, MATCH_REFS_ALL = (1 << 0), MATCH_REFS_MIRROR = (1 << 1), - MATCH_REFS_PRUNE = (1 << 2) + MATCH_REFS_PRUNE = (1 << 2), + MATCH_REFS_FOLLOW_TAGS = (1 << 3) }; /* Reporting of tracking info */ diff --git a/run-command.c b/run-command.c index 07e27ff4c8..765c2ce056 100644 --- a/run-command.c +++ b/run-command.c @@ -273,7 +273,7 @@ int start_command(struct child_process *cmd) { int need_in, need_out, need_err; int fdin[2], fdout[2], fderr[2]; - int failed_errno = failed_errno; + int failed_errno; char *str; /* @@ -341,6 +341,7 @@ int start_command(struct child_process *cmd) notify_pipe[0] = notify_pipe[1] = -1; cmd->pid = fork(); + failed_errno = errno; if (!cmd->pid) { /* * Redirect the channel to write syscall error messages to @@ -420,7 +421,7 @@ int start_command(struct child_process *cmd) } if (cmd->pid < 0) error("cannot fork() for %s: %s", cmd->argv[0], - strerror(failed_errno = errno)); + strerror(errno)); else if (cmd->clean_on_exit) mark_child_for_cleanup(cmd->pid); diff --git a/setup.c b/setup.c index 2e1521b09e..9107f54a07 100644 --- a/setup.c +++ b/setup.c @@ -523,6 +523,12 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, set_git_work_tree(core_worktree); } } + else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) { + /* #16d */ + set_git_dir(gitdirenv); + free(gitfile); + return NULL; + } else /* #2, #10 */ set_git_work_tree("."); @@ -601,6 +607,8 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi if (check_repository_format_gently(".", nongit_ok)) return NULL; + setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1); + /* --work-tree is set without --git-dir; use discovered one */ if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { const char *gitdir; @@ -650,22 +658,32 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_ /* * A "string_list_each_func_t" function that canonicalizes an entry * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or - * discards it if unusable. + * discards it if unusable. The presence of an empty entry in + * GIT_CEILING_DIRECTORIES turns off canonicalization for all + * subsequent entries. */ static int canonicalize_ceiling_entry(struct string_list_item *item, - void *unused) + void *cb_data) { + int *empty_entry_found = cb_data; char *ceil = item->string; - const char *real_path; - if (!*ceil || !is_absolute_path(ceil)) + if (!*ceil) { + *empty_entry_found = 1; return 0; - real_path = real_path_if_valid(ceil); - if (!real_path) + } else if (!is_absolute_path(ceil)) { return 0; - free(item->string); - item->string = xstrdup(real_path); - return 1; + } else if (*empty_entry_found) { + /* Keep entry but do not canonicalize it */ + return 1; + } else { + const char *real_path = real_path_if_valid(ceil); + if (!real_path) + return 0; + free(item->string); + item->string = xstrdup(real_path); + return 1; + } } /* @@ -705,9 +723,11 @@ static const char *setup_git_directory_gently_1(int *nongit_ok) return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok); if (env_ceiling_dirs) { + int empty_entry_found = 0; + string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1); filter_string_list(&ceiling_dirs, 0, - canonicalize_ceiling_entry, NULL); + canonicalize_ceiling_entry, &empty_entry_found); ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs); string_list_clear(&ceiling_dirs, 0); } @@ -782,9 +802,9 @@ const char *setup_git_directory_gently(int *nongit_ok) prefix = setup_git_directory_gently_1(nongit_ok); if (prefix) - setenv("GIT_PREFIX", prefix, 1); + setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1); else - setenv("GIT_PREFIX", "", 1); + setenv(GIT_PREFIX_ENVIRONMENT, "", 1); if (startup_info) { startup_info->have_repository = !nongit_ok || !*nongit_ok; diff --git a/sha1_file.c b/sha1_file.c index 40b23297b2..16967d3b9a 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -21,6 +21,7 @@ #include "sha1-lookup.h" #include "bulk-checkin.h" #include "streaming.h" +#include "dir.h" #ifndef O_NOATIME #if defined(__linux__) && (defined(__i386__) || defined(__PPC__)) @@ -1000,6 +1001,63 @@ void install_packed_git(struct packed_git *pack) packed_git = pack; } +void (*report_garbage)(const char *desc, const char *path); + +static void report_helper(const struct string_list *list, + int seen_bits, int first, int last) +{ + const char *msg; + switch (seen_bits) { + case 0: + msg = "no corresponding .idx nor .pack"; + break; + case 1: + msg = "no corresponding .idx"; + break; + case 2: + msg = "no corresponding .pack"; + break; + default: + return; + } + for (; first < last; first++) + report_garbage(msg, list->items[first].string); +} + +static void report_pack_garbage(struct string_list *list) +{ + int i, baselen = -1, first = 0, seen_bits = 0; + + if (!report_garbage) + return; + + sort_string_list(list); + + for (i = 0; i < list->nr; i++) { + const char *path = list->items[i].string; + if (baselen != -1 && + strncmp(path, list->items[first].string, baselen)) { + report_helper(list, seen_bits, first, i); + baselen = -1; + seen_bits = 0; + } + if (baselen == -1) { + const char *dot = strrchr(path, '.'); + if (!dot) { + report_garbage("garbage found", path); + continue; + } + baselen = dot - path + 1; + first = i; + } + if (!strcmp(path + baselen, "pack")) + seen_bits |= 1; + else if (!strcmp(path + baselen, "idx")) + seen_bits |= 2; + } + report_helper(list, seen_bits, first, list->nr); +} + static void prepare_packed_git_one(char *objdir, int local) { /* Ensure that this buffer is large enough so that we can @@ -1009,6 +1067,7 @@ static void prepare_packed_git_one(char *objdir, int local) int len; DIR *dir; struct dirent *de; + struct string_list garbage = STRING_LIST_INIT_DUP; sprintf(path, "%s/pack", objdir); len = strlen(path); @@ -1024,29 +1083,49 @@ static void prepare_packed_git_one(char *objdir, int local) int namelen = strlen(de->d_name); struct packed_git *p; - if (!has_extension(de->d_name, ".idx")) + if (len + namelen + 1 > sizeof(path)) { + if (report_garbage) { + struct strbuf sb = STRBUF_INIT; + strbuf_addf(&sb, "%.*s/%s", len - 1, path, de->d_name); + report_garbage("path too long", sb.buf); + strbuf_release(&sb); + } continue; + } - if (len + namelen + 1 > sizeof(path)) + if (is_dot_or_dotdot(de->d_name)) continue; - /* Don't reopen a pack we already have. */ strcpy(path + len, de->d_name); - for (p = packed_git; p; p = p->next) { - if (!memcmp(path, p->pack_name, len + namelen - 4)) - break; + + if (has_extension(de->d_name, ".idx")) { + /* Don't reopen a pack we already have. */ + for (p = packed_git; p; p = p->next) { + if (!memcmp(path, p->pack_name, len + namelen - 4)) + break; + } + if (p == NULL && + /* + * See if it really is a valid .idx file with + * corresponding .pack file that we can map. + */ + (p = add_packed_git(path, len + namelen, local)) != NULL) + install_packed_git(p); } - if (p) - continue; - /* See if it really is a valid .idx file with corresponding - * .pack file that we can map. - */ - p = add_packed_git(path, len + namelen, local); - if (!p) + + if (!report_garbage) continue; - install_packed_git(p); + + if (has_extension(de->d_name, ".idx") || + has_extension(de->d_name, ".pack") || + has_extension(de->d_name, ".keep")) + string_list_append(&garbage, path); + else + report_garbage("garbage found", path); } closedir(dir); + report_pack_garbage(&garbage); + string_list_clear(&garbage, 0); } static int sort_pack(const void *a_, const void *b_) diff --git a/sha1_name.c b/sha1_name.c index 95003c77ea..c50630a3ea 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -1137,7 +1137,8 @@ int get_sha1_blob(const char *name, unsigned char *sha1) static void diagnose_invalid_sha1_path(const char *prefix, const char *filename, const unsigned char *tree_sha1, - const char *object_name) + const char *object_name, + int object_name_len) { struct stat st; unsigned char sha1[20]; @@ -1147,8 +1148,8 @@ static void diagnose_invalid_sha1_path(const char *prefix, prefix = ""; if (!lstat(filename, &st)) - die("Path '%s' exists on disk, but not in '%s'.", - filename, object_name); + die("Path '%s' exists on disk, but not in '%.*s'.", + filename, object_name_len, object_name); if (errno == ENOENT || errno == ENOTDIR) { char *fullname = xmalloc(strlen(filename) + strlen(prefix) + 1); @@ -1158,16 +1159,16 @@ static void diagnose_invalid_sha1_path(const char *prefix, if (!get_tree_entry(tree_sha1, fullname, sha1, &mode)) { die("Path '%s' exists, but not '%s'.\n" - "Did you mean '%s:%s' aka '%s:./%s'?", + "Did you mean '%.*s:%s' aka '%.*s:./%s'?", fullname, filename, - object_name, + object_name_len, object_name, fullname, - object_name, + object_name_len, object_name, filename); } - die("Path '%s' does not exist in '%s'", - filename, object_name); + die("Path '%s' does not exist in '%.*s'", + filename, object_name_len, object_name); } } @@ -1332,13 +1333,8 @@ static int get_sha1_with_context_1(const char *name, } if (*cp == ':') { unsigned char tree_sha1[20]; - char *object_name = NULL; - if (only_to_die) { - object_name = xmalloc(cp-name+1); - strncpy(object_name, name, cp-name); - object_name[cp-name] = '\0'; - } - if (!get_sha1_1(name, cp-name, tree_sha1, GET_SHA1_TREEISH)) { + int len = cp - name; + if (!get_sha1_1(name, len, tree_sha1, GET_SHA1_TREEISH)) { const char *filename = cp+1; char *new_filename = NULL; @@ -1348,8 +1344,8 @@ static int get_sha1_with_context_1(const char *name, ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode); if (ret && only_to_die) { diagnose_invalid_sha1_path(prefix, filename, - tree_sha1, object_name); - free(object_name); + tree_sha1, + name, len); } hashcpy(oc->tree, tree_sha1); strncpy(oc->path, filename, @@ -1360,7 +1356,7 @@ static int get_sha1_with_context_1(const char *name, return ret; } else { if (only_to_die) - die("Invalid object name '%s'.", object_name); + die("Invalid object name '%.*s'.", len, name); } } return ret; diff --git a/shell.c b/shell.c index 84b237fef3..1429870a8f 100644 --- a/shell.c +++ b/shell.c @@ -6,6 +6,7 @@ #define COMMAND_DIR "git-shell-commands" #define HELP_COMMAND COMMAND_DIR "/help" +#define NOLOGIN_COMMAND COMMAND_DIR "/no-interactive-login" static int do_generic_cmd(const char *me, char *arg) { @@ -65,6 +66,18 @@ static void run_shell(void) { int done = 0; static const char *help_argv[] = { HELP_COMMAND, NULL }; + + if (!access(NOLOGIN_COMMAND, F_OK)) { + /* Interactive login disabled. */ + const char *argv[] = { NOLOGIN_COMMAND, NULL }; + int status; + + status = run_command_v_opt(argv, 0); + if (status < 0) + exit(127); + exit(status); + } + /* Print help if enabled */ run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE); diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index 199f22c231..c5e55b190b 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -148,7 +148,7 @@ stop_httpd () { convert_to_rev_db () { "$PERL_PATH" -w -- - "$@" <<\EOF use strict; -@ARGV == 2 or die "Usage: convert_to_rev_db "; +@ARGV == 2 or die "usage: convert_to_rev_db "; open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]"; open my $rd, '<', $ARGV[0] or die "$!: couldn't open: $ARGV[0]"; my $size = (stat($rd))[7]; diff --git a/t/perf/README b/t/perf/README index b2dbad4d50..c552f561bf 100644 --- a/t/perf/README +++ b/t/perf/README @@ -56,7 +56,7 @@ You can set the following variables (also in your config.mak): GIT_PERF_REPEAT_COUNT Number of times a test should be repeated for best-of-N - measurements. Defaults to 5. + measurements. Defaults to 3. GIT_PERF_MAKE_OPTS Options to use when automatically building a git tree for diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 43b25137e9..0b98b6f8d0 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -198,7 +198,8 @@ test_expect_success 'root subdir attribute test' ' test_expect_success 'negative patterns' ' echo "!f test=bar" >.gitattributes && - test_must_fail git check-attr test -- f + git check-attr test -- '"'"'!f'"'"' 2>errors && + test_i18ngrep "Negative patterns are ignored" errors ' test_expect_success 'patterns starting with exclamation' ' diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh index 5378787e1b..4e9fa3cd68 100755 --- a/t/t0024-crlf-archive.sh +++ b/t/t0024-crlf-archive.sh @@ -3,12 +3,6 @@ test_description='respect crlf in git archive' . ./test-lib.sh -GIT_UNZIP=${GIT_UNZIP:-unzip} - -test_lazy_prereq UNZIP ' - "$GIT_UNZIP" -v - test $? -ne 127 -' test_expect_success setup ' diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh index cce87a5ab5..3d51615e42 100755 --- a/t/t1504-ceiling-dirs.sh +++ b/t/t1504-ceiling-dirs.sh @@ -44,6 +44,10 @@ test_prefix ceil_at_sub "" GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" test_prefix ceil_at_sub_slash "" +if test_have_prereq SYMLINKS +then + ln -s sub top +fi mkdir -p sub/dir || exit 1 cd sub/dir || exit 1 @@ -68,6 +72,19 @@ test_fail subdir_ceil_at_sub GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" test_fail subdir_ceil_at_sub_slash +if test_have_prereq SYMLINKS +then + GIT_CEILING_DIRECTORIES="$TRASH_ROOT/top" + test_fail subdir_ceil_at_top + GIT_CEILING_DIRECTORIES="$TRASH_ROOT/top/" + test_fail subdir_ceil_at_top_slash + + GIT_CEILING_DIRECTORIES=":$TRASH_ROOT/top" + test_prefix subdir_ceil_at_top_no_resolve "sub/dir/" + GIT_CEILING_DIRECTORIES=":$TRASH_ROOT/top/" + test_prefix subdir_ceil_at_top_slash_no_resolve "sub/dir/" +fi + GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir" test_prefix subdir_ceil_at_subdir "sub/dir/" diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index d6e576192f..b27a7209f7 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -54,6 +54,10 @@ test_expect_success 'my-side@{upstream} resolves to correct full name' ' test refs/remotes/origin/side = "$(full_name my-side@{u})" ' +test_expect_success 'refs/heads/my-side@{upstream} does not resolve to my-side{upstream}' ' + test_must_fail full_name refs/heads/my-side@{upstream} +' + test_expect_success 'my-side@{u} resolves to correct commit' ' git checkout side && test_commit 5 && diff --git a/t/t1509/prepare-chroot.sh b/t/t1509/prepare-chroot.sh index c5334a8fa4..62691172e3 100755 --- a/t/t1509/prepare-chroot.sh +++ b/t/t1509/prepare-chroot.sh @@ -14,7 +14,7 @@ xmkdir() { R="$1" -[ -n "$R" ] || die "Usage: prepare-chroot.sh " +[ -n "$R" ] || die "usage: prepare-chroot.sh " [ -x git ] || die "This script needs to be executed at git source code's top directory" [ -x /bin/busybox ] || die "You need busybox" diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh index 80aedfca8c..cf2ee7885a 100755 --- a/t/t1510-repo-setup.sh +++ b/t/t1510-repo-setup.sh @@ -517,6 +517,25 @@ test_expect_success '#16c: bare .git has no worktree' ' "$here/16c/.git" "(null)" "$here/16c/sub" "(null)" ' +test_expect_success '#16d: bareness preserved across alias' ' + setup_repo 16d unset "" unset && + ( + cd 16d/.git && + test_must_fail git status && + git config alias.st status && + test_must_fail git st + ) +' + +test_expect_success '#16e: bareness preserved by --bare' ' + setup_repo 16e unset "" unset && + ( + cd 16e/.git && + test_must_fail git status && + test_must_fail git --bare status + ) +' + test_expect_success '#17: GIT_WORK_TREE without explicit GIT_DIR is accepted (bare case)' ' # Just like #16. setup_repo 17a unset "" true && diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index 4cdebda6a5..c317254b9a 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -80,6 +80,22 @@ test_expect_success 'change gets noticed' ' ' +# Note that this is scheduled to change in Git 2.0, when +# "git add -u" will become full-tree by default. +test_expect_success 'non-limited update in subdir leaves root alone' ' + ( + cd dir1 && + echo even more >>sub2 && + git add -u + ) && + cat >expect <<-\EOF && + check + top + EOF + git diff-files --name-only >actual && + test_cmp expect actual +' + test_expect_success SYMLINKS 'replace a file with a symlink' ' rm foo && diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index f3e0e4a38c..12f1e4a63c 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -42,6 +42,10 @@ test_expect_success \ 'git branch a/b/c should create a branch' \ 'git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c' +test_expect_success \ + 'git branch HEAD should fail' \ + 'test_must_fail git branch HEAD' + cat >expect < 1117150200 +0000 branch: Created from master EOF @@ -388,6 +392,14 @@ test_expect_success \ 'git tag foobar && test_must_fail git branch --track my11 foobar' +test_expect_success '--set-upstream-to fails on multiple branches' \ + 'test_must_fail git branch --set-upstream-to master a b c' + +test_expect_success '--set-upstream-to fails on detached HEAD' \ + 'git checkout HEAD^{} && + test_must_fail git branch --set-upstream-to master && + git checkout -' + test_expect_success 'use --set-upstream-to modify HEAD' \ 'test_config branch.master.remote foo && test_config branch.master.merge foo && @@ -417,6 +429,15 @@ test_expect_success 'test --unset-upstream on HEAD' \ test_must_fail git branch --unset-upstream ' +test_expect_success '--unset-upstream should fail on multiple branches' \ + 'test_must_fail git branch --unset-upstream a b c' + +test_expect_success '--unset-upstream should fail on detached HEAD' \ + 'git checkout HEAD^{} && + test_must_fail git branch --unset-upstream && + git checkout - +' + test_expect_success 'test --unset-upstream on a particular branch' \ 'git branch my15 git branch --set-upstream-to master my14 && diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index 844277cfa6..2f327b7495 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh @@ -102,4 +102,58 @@ test_expect_success 'setup for many rename source candidates' ' grep warning actual.err ' +test_expect_success 'rename pretty print with nothing in common' ' + mkdir -p a/b/ && + : >a/b/c && + git add a/b/c && + git commit -m "create a/b/c" && + mkdir -p c/b/ && + git mv a/b/c c/b/a && + git commit -m "a/b/c -> c/b/a" && + git diff -M --summary HEAD^ HEAD >output && + test_i18ngrep " a/b/c => c/b/a " output && + git diff -M --stat HEAD^ HEAD >output && + test_i18ngrep " a/b/c => c/b/a " output +' + +test_expect_success 'rename pretty print with common prefix' ' + mkdir -p c/d && + git mv c/b/a c/d/e && + git commit -m "c/b/a -> c/d/e" && + git diff -M --summary HEAD^ HEAD >output && + test_i18ngrep " c/{b/a => d/e} " output && + git diff -M --stat HEAD^ HEAD >output && + test_i18ngrep " c/{b/a => d/e} " output +' + +test_expect_success 'rename pretty print with common suffix' ' + mkdir d && + git mv c/d/e d/e && + git commit -m "c/d/e -> d/e" && + git diff -M --summary HEAD^ HEAD >output && + test_i18ngrep " {c/d => d}/e " output && + git diff -M --stat HEAD^ HEAD >output && + test_i18ngrep " {c/d => d}/e " output +' + +test_expect_success 'rename pretty print with common prefix and suffix' ' + mkdir d/f && + git mv d/e d/f/e && + git commit -m "d/e -> d/f/e" && + git diff -M --summary HEAD^ HEAD >output && + test_i18ngrep " d/{ => f}/e " output && + git diff -M --stat HEAD^ HEAD >output && + test_i18ngrep " d/{ => f}/e " output +' + +test_expect_success 'rename pretty print common prefix and suffix overlap' ' + mkdir d/f/f && + git mv d/f/e d/f/f/e && + git commit -m "d/f/e d/f/f/e" && + git diff -M --summary HEAD^ HEAD >output && + test_i18ngrep " d/f/{ => f}/e " output && + git diff -M --stat HEAD^ HEAD >output && + test_i18ngrep " d/f/{ => f}/e " output +' + test_done diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 7fa3647514..bb1fc47fe8 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -837,25 +837,26 @@ Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?= =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?= =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?= - =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?= - =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= - =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?= - =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= + =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?= =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?= =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?= - =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?= - =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= - =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?= - =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= + =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?= =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?= =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?= - =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?= - =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= - =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?= - =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= - =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?= + =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= + =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?= + =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?= + =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?= + =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?= + =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?= + =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?= + =?UTF-8?q?bar?= EOF test_expect_success 'format-patch wraps extremely long subject (rfc2047)' ' rm -rf patches/ && diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh index 7cfe9ca3da..4e7b05dd23 100755 --- a/t/t5003-archive-zip.sh +++ b/t/t5003-archive-zip.sh @@ -3,15 +3,9 @@ test_description='git archive --format=zip test' . ./test-lib.sh -GIT_UNZIP=${GIT_UNZIP:-unzip} SUBSTFORMAT=%H%n -test_lazy_prereq UNZIP ' - "$GIT_UNZIP" -v - test $? -ne 127 -' - test_lazy_prereq UNZIP_SYMLINKS ' ( mkdir unzip-symlinks && @@ -76,6 +70,12 @@ test_expect_success \ git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \ git commit-tree $treeid >.git/info/attributes && + git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \ + >a/substfile1 +' + test_expect_success \ 'create bare clone' \ 'git clone --bare . bare.git && diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh new file mode 100755 index 0000000000..cdb7d7a7f9 --- /dev/null +++ b/t/t5004-archive-corner-cases.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +test_description='test corner cases of git-archive' +. ./test-lib.sh + +test_expect_success 'create commit with empty tree' ' + git commit --allow-empty -m foo +' + +# Make a dir and clean it up afterwards +make_dir() { + mkdir "$1" && + test_when_finished "rm -rf '$1'" +} + +# Check that the dir given in "$1" contains exactly the +# set of paths given as arguments. +check_dir() { + dir=$1; shift + { + echo "$dir" && + for i in "$@"; do + echo "$dir/$i" + done + } | sort >expect && + find "$dir" -print | sort >actual && + test_cmp expect actual +} + +test_expect_success 'tar archive of empty tree is empty' ' + git archive --format=tar HEAD >empty.tar && + make_dir extract && + "$TAR" xf empty.tar -C extract && + check_dir extract +' + +test_expect_success 'tar archive of empty tree with prefix' ' + git archive --format=tar --prefix=foo/ HEAD >prefix.tar && + make_dir extract && + "$TAR" xf prefix.tar -C extract && + check_dir extract foo +' + +test_expect_success UNZIP 'zip archive of empty tree is empty' ' + # Detect the exit code produced when our particular flavor of unzip + # sees an empty archive. Infozip will generate a warning and exit with + # code 1. But in the name of sanity, we do not expect other unzip + # implementations to do the same thing (it would be perfectly + # reasonable to exit 0, for example). + # + # This makes our test less rigorous on some platforms (unzip may not + # handle the empty repo at all, making our later check of its exit code + # a no-op). But we cannot do anything reasonable except skip the test + # on such platforms anyway, and this is the moral equivalent. + "$GIT_UNZIP" "$TEST_DIRECTORY"/t5004/empty.zip + expect_code=$? + + git archive --format=zip HEAD >empty.zip && + make_dir extract && + ( + cd extract && + test_expect_code $expect_code "$GIT_UNZIP" ../empty.zip + ) && + check_dir extract +' + +test_expect_success UNZIP 'zip archive of empty tree with prefix' ' + # We do not have to play exit-code tricks here, because our + # result should not be empty; it has a directory in it. + git archive --format=zip --prefix=foo/ HEAD >prefix.zip && + make_dir extract && + ( + cd extract && + "$GIT_UNZIP" ../prefix.zip + ) && + check_dir extract foo +' + +test_expect_success 'archive complains about pathspec on empty tree' ' + test_must_fail git archive --format=tar HEAD -- foo >/dev/null +' + +test_expect_success 'create a commit with an empty subtree' ' + empty_tree=$(git hash-object -t tree /dev/null) && + root_tree=$(printf "040000 tree $empty_tree\tsub\n" | git mktree) +' + +test_expect_success 'archive empty subtree with no pathspec' ' + git archive --format=tar $root_tree >subtree-all.tar && + make_dir extract && + "$TAR" xf subtree-all.tar -C extract && + check_dir extract sub +' + +test_expect_success 'archive empty subtree by direct pathspec' ' + git archive --format=tar $root_tree -- sub >subtree-path.tar && + make_dir extract && + "$TAR" xf subtree-path.tar -C extract && + check_dir extract sub +' + +test_done diff --git a/t/t5004/empty.zip b/t/t5004/empty.zip new file mode 100644 index 0000000000..1a76bb6005 Binary files /dev/null and b/t/t5004/empty.zip differ diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index d645328609..e4bb3a1457 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -195,4 +195,30 @@ test_expect_success 'gc: prune old objects after local clone' ' ) ' +test_expect_success 'garbage report in count-objects -v' ' + : >.git/objects/pack/foo && + : >.git/objects/pack/foo.bar && + : >.git/objects/pack/foo.keep && + : >.git/objects/pack/foo.pack && + : >.git/objects/pack/fake.bar && + : >.git/objects/pack/fake.keep && + : >.git/objects/pack/fake.pack && + : >.git/objects/pack/fake.idx && + : >.git/objects/pack/fake2.keep && + : >.git/objects/pack/fake3.idx && + git count-objects -v 2>stderr && + grep "index file .git/objects/pack/fake.idx is too small" stderr && + grep "^warning:" stderr | sort >actual && + cat >expected <<\EOF && +warning: garbage found: .git/objects/pack/fake.bar +warning: garbage found: .git/objects/pack/foo +warning: garbage found: .git/objects/pack/foo.bar +warning: no corresponding .idx nor .pack: .git/objects/pack/fake2.keep +warning: no corresponding .idx: .git/objects/pack/foo.keep +warning: no corresponding .idx: .git/objects/pack/foo.pack +warning: no corresponding .pack: .git/objects/pack/fake3.idx +EOF + test_cmp expected actual +' + test_done diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index c31e5c1c52..d3dc5df7b1 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1043,4 +1043,111 @@ do ' done +test_expect_success 'fetch exact SHA1' ' + mk_test heads/master hidden/one && + git push testrepo master:refs/hidden/one && + ( + cd testrepo && + git config transfer.hiderefs refs/hidden + ) && + check_push_result $the_commit hidden/one && + + mk_child child && + ( + cd child && + + # make sure $the_commit does not exist here + git repack -a -d && + git prune && + test_must_fail git cat-file -t $the_commit && + + # fetching the hidden object should fail by default + test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy && + test_must_fail git rev-parse --verify refs/heads/copy && + + # the server side can allow it to succeed + ( + cd ../testrepo && + git config uploadpack.allowtipsha1inwant true + ) && + + git fetch -v ../testrepo $the_commit:refs/heads/copy && + result=$(git rev-parse --verify refs/heads/copy) && + test "$the_commit" = "$result" + ) +' + +test_expect_success 'fetch follows tags by default' ' + mk_test heads/master && + rm -fr src dst && + git init src && + ( + cd src && + git pull ../testrepo master && + git tag -m "annotated" tag && + git for-each-ref >tmp1 && + ( + cat tmp1 + sed -n "s|refs/heads/master$|refs/remotes/origin/master|p" tmp1 + ) | + sort -k 3 >../expect + ) && + git init dst && + ( + cd dst && + git remote add origin ../src && + git config branch.master.remote origin && + git config branch.master.merge refs/heads/master && + git pull && + git for-each-ref >../actual + ) && + test_cmp expect actual +' + +test_expect_success 'push does not follow tags by default' ' + mk_test heads/master && + rm -fr src dst && + git init src && + git init --bare dst && + ( + cd src && + git pull ../testrepo master && + git tag -m "annotated" tag && + git checkout -b another && + git commit --allow-empty -m "future commit" && + git tag -m "future" future && + git checkout master && + git for-each-ref refs/heads/master >../expect && + git push ../dst master + ) && + ( + cd dst && + git for-each-ref >../actual + ) && + test_cmp expect actual +' + +test_expect_success 'push --follow-tag only pushes relevant tags' ' + mk_test heads/master && + rm -fr src dst && + git init src && + git init --bare dst && + ( + cd src && + git pull ../testrepo master && + git tag -m "annotated" tag && + git checkout -b another && + git commit --allow-empty -m "future commit" && + git tag -m "future" future && + git checkout master && + git for-each-ref refs/heads/master refs/tags/tag >../expect + git push --follow-tag ../dst master + ) && + ( + cd dst && + git for-each-ref >../actual + ) && + test_cmp expect actual +' + test_done diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh index 1b06691bb4..aa31abe32b 100755 --- a/t/t5521-pull-options.sh +++ b/t/t5521-pull-options.sh @@ -19,6 +19,17 @@ test_expect_success 'git pull -q' ' test ! -s out) ' +test_expect_success 'git pull -q --rebase' ' + mkdir clonedqrb && + (cd clonedqrb && git init && + git pull -q --rebase "../parent" >out 2>err && + test ! -s err && + test ! -s out && + git pull -q --rebase "../parent" >out 2>err && + test ! -s err && + test ! -s out) +' + test_expect_success 'git pull' ' mkdir cloned && (cd cloned && git init && @@ -27,6 +38,14 @@ test_expect_success 'git pull' ' test ! -s out) ' +test_expect_success 'git pull --rebase' ' + mkdir clonedrb && + (cd clonedrb && git init && + git pull --rebase "../parent" >out 2>err && + test -s err && + test ! -s out) +' + test_expect_success 'git pull -v' ' mkdir clonedv && (cd clonedv && git init && @@ -35,6 +54,14 @@ test_expect_success 'git pull -v' ' test ! -s out) ' +test_expect_success 'git pull -v --rebase' ' + mkdir clonedvrb && + (cd clonedvrb && git init && + git pull -v --rebase "../parent" >out 2>err && + test -s err && + test ! -s out) +' + test_expect_success 'git pull -v -q' ' mkdir clonedvq && (cd clonedvq && git init && diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh index f4f38a5e73..52ef06b000 100755 --- a/t/t7060-wtstatus.sh +++ b/t/t7060-wtstatus.sh @@ -5,6 +5,7 @@ test_description='basic work tree status reporting' . ./test-lib.sh test_expect_success setup ' + git config --global advice.statusuoption false && test_commit A && test_commit B oneside added && git checkout A^0 && diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 2683cba7e3..5030f1f1bc 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -757,4 +757,104 @@ test_expect_success 'submodule add with an existing name fails unless forced' ' ) ' +test_expect_success 'set up a second submodule' ' + git submodule add ./init2 example2 && + git commit -m "submodule example2 added" +' + +test_expect_success 'submodule deinit should remove the whole submodule section from .git/config' ' + git config submodule.example.foo bar && + git config submodule.example2.frotz nitfol && + git submodule deinit init && + test -z "$(git config --get-regexp "submodule\.example\.")" && + test -n "$(git config --get-regexp "submodule\.example2\.")" && + test -f example2/.git && + rmdir init +' + +test_expect_success 'submodule deinit . deinits all initialized submodules' ' + git submodule update --init && + git config submodule.example.foo bar && + git config submodule.example2.frotz nitfol && + test_must_fail git submodule deinit && + git submodule deinit . && + test -z "$(git config --get-regexp "submodule\.example\.")" && + test -z "$(git config --get-regexp "submodule\.example2\.")" && + rmdir init example2 +' + +test_expect_success 'submodule deinit deinits a submodule when its work tree is missing or empty' ' + git submodule update --init && + rm -rf init example2/* example2/.git && + git submodule deinit init example2 && + test -z "$(git config --get-regexp "submodule\.example\.")" && + test -z "$(git config --get-regexp "submodule\.example2\.")" && + rmdir init +' + +test_expect_success 'submodule deinit fails when the submodule contains modifications unless forced' ' + git submodule update --init && + echo X >>init/s && + test_must_fail git submodule deinit init && + test -n "$(git config --get-regexp "submodule\.example\.")" && + test -f example2/.git && + git submodule deinit -f init && + test -z "$(git config --get-regexp "submodule\.example\.")" && + rmdir init +' + +test_expect_success 'submodule deinit fails when the submodule contains untracked files unless forced' ' + git submodule update --init && + echo X >>init/untracked && + test_must_fail git submodule deinit init && + test -n "$(git config --get-regexp "submodule\.example\.")" && + test -f example2/.git && + git submodule deinit -f init && + test -z "$(git config --get-regexp "submodule\.example\.")" && + rmdir init +' + +test_expect_success 'submodule deinit fails when the submodule HEAD does not match unless forced' ' + git submodule update --init && + ( + cd init && + git checkout HEAD^ + ) && + test_must_fail git submodule deinit init && + test -n "$(git config --get-regexp "submodule\.example\.")" && + test -f example2/.git && + git submodule deinit -f init && + test -z "$(git config --get-regexp "submodule\.example\.")" && + rmdir init +' + +test_expect_success 'submodule deinit is silent when used on an uninitialized submodule' ' + git submodule update --init && + git submodule deinit init >actual && + test_i18ngrep "Submodule .example. (.*) unregistered for path .init" actual && + git submodule deinit init >actual && + test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && + git submodule deinit . >actual && + test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && + test_i18ngrep "Submodule .example2. (.*) unregistered for path .example2" actual && + git submodule deinit . >actual && + test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && + test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual && + rmdir init example2 +' + +test_expect_success 'submodule deinit fails when submodule has a .git directory even when forced' ' + git submodule update --init && + ( + cd init && + rm .git && + cp -R ../.git/modules/example .git && + GIT_WORK_TREE=. git config --unset core.worktree + ) && + test_must_fail git submodule deinit init && + test_must_fail git submodule deinit -f init && + test -d init/.git && + test -n "$(git config --get-regexp "submodule\.example\.")" +' + test_done diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 4975ec07ce..1a3d20bdc3 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -643,7 +643,8 @@ test_expect_success 'submodule update places git-dir in superprojects git-dir re rm -rf super_update_r2 && git clone super_update_r super_update_r2 && (cd super_update_r2 && - git submodule update --init --recursive && + git submodule update --init --recursive >actual && + test_i18ngrep "Submodule path .submodule/subsubmodule.: checked out" actual && (cd submodule/subsubmodule && git log > ../../expected ) && diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index cbd7a45927..f9b44b7244 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -177,12 +177,20 @@ test_expect_success 'verbose respects diff config' ' git config --unset color.diff ' +mesg_with_comment_and_newlines=' +# text + +' + +test_expect_success 'prepare file with comment line and trailing newlines' ' + printf "%s" "$mesg_with_comment_and_newlines" >expect +' + test_expect_success 'cleanup commit messages (verbatim option,-t)' ' echo >>negative && - { echo;echo "# text";echo; } >expect && - git commit --cleanup=verbatim -t expect -a && - git cat-file -p HEAD |sed -e "1,/^\$/d" |head -n 3 >actual && + git commit --cleanup=verbatim --no-status -t expect -a && + git cat-file -p HEAD |sed -e "1,/^\$/d" >actual && test_cmp expect actual ' @@ -199,7 +207,7 @@ test_expect_success 'cleanup commit messages (verbatim option,-F)' ' test_expect_success 'cleanup commit messages (verbatim option,-m)' ' echo >>negative && - git commit --cleanup=verbatim -m "$(cat expect)" -a && + git commit --cleanup=verbatim -m "$mesg_with_comment_and_newlines" -a && git cat-file -p HEAD |sed -e "1,/^\$/d">actual && test_cmp expect actual @@ -255,32 +263,40 @@ test_expect_success 'cleanup commit message (fail on invalid cleanup mode config test_expect_success 'cleanup commit message (no config and no option uses default)' ' echo content >>file && git add file && - test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && - git commit --no-status && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && + git commit --no-status + ) && commit_msg_is "commit message" ' test_expect_success 'cleanup commit message (option overrides default)' ' echo content >>file && git add file && - test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && - git commit --cleanup=whitespace --no-status && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && + git commit --cleanup=whitespace --no-status + ) && commit_msg_is "commit message # comment" ' test_expect_success 'cleanup commit message (config overrides default)' ' echo content >>file && git add file && - test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && - git -c commit.cleanup=whitespace commit --no-status && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && + git -c commit.cleanup=whitespace commit --no-status + ) && commit_msg_is "commit message # comment" ' test_expect_success 'cleanup commit message (option overrides config)' ' echo content >>file && git add file && - test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && - git -c commit.cleanup=whitespace commit --cleanup=default && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment && + git -c commit.cleanup=whitespace commit --cleanup=default + ) && commit_msg_is "commit message" ' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index a79c032ffd..aecb4d1e5f 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -8,6 +8,7 @@ test_description='git status' . ./test-lib.sh test_expect_success 'status -h in broken repository' ' + git config --global advice.statusuoption false && mkdir broken && test_when_finished "rm -fr broken" && ( diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index d2da89a5f5..9d4610629d 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -14,6 +14,7 @@ test_description='git status advice' set_fake_editor test_expect_success 'prepare for conflicts' ' + git config --global advice.statusuoption false && test_commit init main.txt init && git branch conflicts && test_commit on_master main.txt on_master && diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index eb1d3f85b5..3aab6e1500 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009, 2010 David Aguilar +# Copyright (c) 2009, 2010, 2012, 2013 David Aguilar # test_description='git-difftool @@ -10,43 +10,25 @@ Testing basic diff tool invocation . ./test-lib.sh -remove_config_vars() +difftool_test_setup () { - # Unset all config variables used by git-difftool - git config --unset diff.tool - git config --unset diff.guitool - git config --unset difftool.test-tool.cmd - git config --unset difftool.prompt - git config --unset merge.tool - git config --unset mergetool.test-tool.cmd - git config --unset mergetool.prompt - return 0 + test_config diff.tool test-tool && + test_config difftool.test-tool.cmd 'cat "$LOCAL"' && + test_config difftool.bogus-tool.cmd false } -restore_test_defaults() -{ - # Restores the test defaults used by several tests - remove_config_vars - unset GIT_DIFF_TOOL - unset GIT_DIFFTOOL_PROMPT - unset GIT_DIFFTOOL_NO_PROMPT - git config diff.tool test-tool && - git config difftool.test-tool.cmd 'cat $LOCAL' - git config difftool.bogus-tool.cmd false -} - -prompt_given() +prompt_given () { prompt="$1" test "$prompt" = "Launch 'test-tool' [Y/n]: branch" } -stdin_contains() +stdin_contains () { grep >/dev/null "$1" } -stdin_doesnot_contain() +stdin_doesnot_contain () { ! stdin_contains "$1" } @@ -65,249 +47,237 @@ test_expect_success PERL 'setup' ' # Configure a custom difftool..cmd and use it test_expect_success PERL 'custom commands' ' - restore_test_defaults && - git config difftool.test-tool.cmd "cat \$REMOTE" && + difftool_test_setup && + test_config difftool.test-tool.cmd "cat \"\$REMOTE\"" && + echo master >expect && + git difftool --no-prompt branch >actual && + test_cmp expect actual && - diff=$(git difftool --no-prompt branch) && - test "$diff" = "master" && - - restore_test_defaults && - diff=$(git difftool --no-prompt branch) && - test "$diff" = "branch" + test_config difftool.test-tool.cmd "cat \"\$LOCAL\"" && + echo branch >expect && + git difftool --no-prompt branch >actual && + test_cmp expect actual ' -# Ensures that a custom difftool..cmd overrides built-ins -test_expect_success PERL 'custom commands override built-ins' ' - restore_test_defaults && - git config difftool.defaults.cmd "cat \$REMOTE" && - - diff=$(git difftool --tool defaults --no-prompt branch) && - test "$diff" = "master" && - - git config --unset difftool.defaults.cmd +test_expect_success PERL 'custom tool commands override built-ins' ' + test_config difftool.vimdiff.cmd "cat \"\$REMOTE\"" && + echo master >expect && + git difftool --tool vimdiff --no-prompt branch >actual && + test_cmp expect actual ' -# Ensures that git-difftool ignores bogus --tool values test_expect_success PERL 'difftool ignores bad --tool values' ' - diff=$(git difftool --no-prompt --tool=bad-tool branch) - test "$?" = 1 && - test "$diff" = "" + : >expect && + test_expect_code 1 \ + git difftool --no-prompt --tool=bad-tool branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool forwards arguments to diff' ' + difftool_test_setup && >for-diff && git add for-diff && echo changes>for-diff && git add for-diff && - diff=$(git difftool --cached --no-prompt -- for-diff) && - test "$diff" = "" && + : >expect && + git difftool --cached --no-prompt -- for-diff >actual && + test_cmp expect actual && git reset -- for-diff && rm for-diff ' test_expect_success PERL 'difftool honors --gui' ' - git config merge.tool bogus-tool && - git config diff.tool bogus-tool && - git config diff.guitool test-tool && - - diff=$(git difftool --no-prompt --gui branch) && - test "$diff" = "branch" && + difftool_test_setup && + test_config merge.tool bogus-tool && + test_config diff.tool bogus-tool && + test_config diff.guitool test-tool && - restore_test_defaults + echo branch >expect && + git difftool --no-prompt --gui branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool --gui last setting wins' ' - git config diff.guitool bogus-tool && - git difftool --no-prompt --gui --no-gui && + difftool_test_setup && + : >expect && + git difftool --no-prompt --gui --no-gui >actual && + test_cmp expect actual && - git config merge.tool bogus-tool && - git config diff.tool bogus-tool && - git config diff.guitool test-tool && - diff=$(git difftool --no-prompt --no-gui --gui branch) && - test "$diff" = "branch" && - - restore_test_defaults + test_config merge.tool bogus-tool && + test_config diff.tool bogus-tool && + test_config diff.guitool test-tool && + echo branch >expect && + git difftool --no-prompt --no-gui --gui branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool --gui works without configured diff.guitool' ' - git config diff.tool test-tool && - - diff=$(git difftool --no-prompt --gui branch) && - test "$diff" = "branch" && - - restore_test_defaults + difftool_test_setup && + echo branch >expect && + git difftool --no-prompt --gui branch >actual && + test_cmp expect actual ' # Specify the diff tool using $GIT_DIFF_TOOL test_expect_success PERL 'GIT_DIFF_TOOL variable' ' - test_might_fail git config --unset diff.tool && - GIT_DIFF_TOOL=test-tool && - export GIT_DIFF_TOOL && - - diff=$(git difftool --no-prompt branch) && - test "$diff" = "branch" && - - restore_test_defaults + difftool_test_setup && + git config --unset diff.tool && + echo branch >expect && + GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual && + test_cmp expect actual ' # Test the $GIT_*_TOOL variables and ensure # that $GIT_DIFF_TOOL always wins unless --tool is specified test_expect_success PERL 'GIT_DIFF_TOOL overrides' ' - git config diff.tool bogus-tool && - git config merge.tool bogus-tool && - - GIT_DIFF_TOOL=test-tool && - export GIT_DIFF_TOOL && - - diff=$(git difftool --no-prompt branch) && - test "$diff" = "branch" && + difftool_test_setup && + test_config diff.tool bogus-tool && + test_config merge.tool bogus-tool && - GIT_DIFF_TOOL=bogus-tool && - export GIT_DIFF_TOOL && + echo branch >expect && + GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual && + test_cmp expect actual && - diff=$(git difftool --no-prompt --tool=test-tool branch) && - test "$diff" = "branch" && - - restore_test_defaults + test_config diff.tool bogus-tool && + test_config merge.tool bogus-tool && + GIT_DIFF_TOOL=bogus-tool \ + git difftool --no-prompt --tool=test-tool branch >actual && + test_cmp expect actual ' # Test that we don't have to pass --no-prompt to difftool # when $GIT_DIFFTOOL_NO_PROMPT is true test_expect_success PERL 'GIT_DIFFTOOL_NO_PROMPT variable' ' - GIT_DIFFTOOL_NO_PROMPT=true && - export GIT_DIFFTOOL_NO_PROMPT && - - diff=$(git difftool branch) && - test "$diff" = "branch" && - - restore_test_defaults + difftool_test_setup && + echo branch >expect && + GIT_DIFFTOOL_NO_PROMPT=true git difftool branch >actual && + test_cmp expect actual ' # git-difftool supports the difftool.prompt variable. # Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false test_expect_success PERL 'GIT_DIFFTOOL_PROMPT variable' ' - git config difftool.prompt false && - GIT_DIFFTOOL_PROMPT=true && - export GIT_DIFFTOOL_PROMPT && - - prompt=$(echo | git difftool branch | tail -1) && - prompt_given "$prompt" && - - restore_test_defaults + difftool_test_setup && + test_config difftool.prompt false && + echo >input && + GIT_DIFFTOOL_PROMPT=true git difftool branch output && + prompt=$(tail -1 expect && + git difftool branch >actual && + test_cmp expect actual ' # Test that we don't have to pass --no-prompt when mergetool.prompt is false test_expect_success PERL 'difftool merge.prompt = false' ' + difftool_test_setup && test_might_fail git config --unset difftool.prompt && - git config mergetool.prompt false && - - diff=$(git difftool branch) && - test "$diff" = "branch" && - - restore_test_defaults + test_config mergetool.prompt false && + echo branch >expect && + git difftool branch >actual && + test_cmp expect actual ' # Test that the -y flag can override difftool.prompt = true test_expect_success PERL 'difftool.prompt can overridden with -y' ' - git config difftool.prompt true && - - diff=$(git difftool -y branch) && - test "$diff" = "branch" && - - restore_test_defaults + difftool_test_setup && + test_config difftool.prompt true && + echo branch >expect && + git difftool -y branch >actual && + test_cmp expect actual ' # Test that the --prompt flag can override difftool.prompt = false test_expect_success PERL 'difftool.prompt can overridden with --prompt' ' - git config difftool.prompt false && - - prompt=$(echo | git difftool --prompt branch | tail -1) && - prompt_given "$prompt" && - - restore_test_defaults + difftool_test_setup && + test_config difftool.prompt false && + echo >input && + git difftool --prompt branch output && + prompt=$(tail -1 expect && + git difftool --prompt --no-prompt branch >actual && + test_cmp expect actual && + echo >input && + git difftool --no-prompt --prompt branch output && + prompt=$(tail -1 expect && + git difftool --no-prompt branch >actual && + test_cmp expect actual && # set merge.tool to something bogus, diff.tool to test-tool - git config merge.tool bogus-tool && - git config diff.tool test-tool && - - diff=$(git difftool --no-prompt branch) && - test "$diff" = "branch" && - - restore_test_defaults + test_config merge.tool bogus-tool && + test_config diff.tool test-tool && + git difftool --no-prompt branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool..path' ' - git config difftool.tkdiff.path echo && - diff=$(git difftool --tool=tkdiff --no-prompt branch) && - git config --unset difftool.tkdiff.path && - lines=$(echo "$diff" | grep file | wc -l) && - test "$lines" -eq 1 && - - restore_test_defaults + test_config difftool.tkdiff.path echo && + git difftool --tool=tkdiff --no-prompt branch >output && + lines=$(grep file output | wc -l) && + test "$lines" -eq 1 ' test_expect_success PERL 'difftool --extcmd=cat' ' - diff=$(git difftool --no-prompt --extcmd=cat branch) && - test "$diff" = branch"$LF"master + echo branch >expect && + echo master >>expect && + git difftool --no-prompt --extcmd=cat branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool --extcmd cat' ' - diff=$(git difftool --no-prompt --extcmd cat branch) && - test "$diff" = branch"$LF"master + echo branch >expect && + echo master >>expect && + git difftool --no-prompt --extcmd=cat branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool -x cat' ' - diff=$(git difftool --no-prompt -x cat branch) && - test "$diff" = branch"$LF"master + echo branch >expect && + echo master >>expect && + git difftool --no-prompt -x cat branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool --extcmd echo arg1' ' - diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"echo\ \$1\" branch) && - test "$diff" = file + echo file >expect && + git difftool --no-prompt \ + --extcmd sh\ -c\ \"echo\ \$1\" branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool --extcmd cat arg1' ' - diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$1\" branch) && - test "$diff" = master + echo master >expect && + git difftool --no-prompt \ + --extcmd sh\ -c\ \"cat\ \$1\" branch >actual && + test_cmp expect actual ' test_expect_success PERL 'difftool --extcmd cat arg2' ' - diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$2\" branch) && - test "$diff" = branch + echo branch >expect && + git difftool --no-prompt \ + --extcmd sh\ -c\ \"cat\ \$2\" branch >actual && + test_cmp expect actual ' # Create a second file on master and a different version on branch @@ -324,26 +294,26 @@ test_expect_success PERL 'setup with 2 files different' ' ' test_expect_success PERL 'say no to the first file' ' - diff=$( (echo n; echo) | git difftool -x cat branch ) && - - echo "$diff" | stdin_contains m2 && - echo "$diff" | stdin_contains br2 && - echo "$diff" | stdin_doesnot_contain master && - echo "$diff" | stdin_doesnot_contain branch + (echo n && echo) >input && + git difftool -x cat branch output && + stdin_contains m2 input && + git difftool -x cat branch output && + stdin_contains master output && + stdin_contains tool output && + stdin_contains sub output && + stdin_contains sub output && + stdin_contains sub output && + stdin_contains sub git/.p4config && + P4CONFIG=.p4config && + export P4CONFIG && + unset P4PORT && + git p4 clone --dest="git" //depot + ) +' + +# When the p4 client Root is a symlink, make sure chdir() does not use +# getcwd() to convert it to a physical path. +test_expect_success SYMLINKS 'p4 client root symlink should stay symbolic' ' + physical="$TRASH_DIRECTORY/physical" && + symbolic="$TRASH_DIRECTORY/symbolic" && + test_when_finished "rm -rf \"$physical\"" && + test_when_finished "rm \"$symbolic\"" && + mkdir -p "$physical" && + ln -s "$physical" "$symbolic" && + test_when_finished cleanup_git && + ( + P4CLIENT=client-sym && + p4 client -i <<-EOF && + Client: $P4CLIENT + Description: $P4CLIENT + Root: $symbolic + LineEnd: unix + View: //depot/... //$P4CLIENT/... + EOF + git p4 clone --dest="$git" //depot && + cd "$git" && + test_commit file2 && + git config git-p4.skipSubmitEdit true && + git p4 submit + ) +' + test_expect_success 'kill p4d' ' kill_p4d ' diff --git a/t/test-lib.sh b/t/test-lib.sh index 9e7f6b424d..1f510252ad 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -760,3 +760,9 @@ test_lazy_prereq AUTOIDENT ' # When the tests are run as root, permission tests will report that # things are writable when they shouldn't be. test -w / || test_set_prereq SANITY + +GIT_UNZIP=${GIT_UNZIP:-unzip} +test_lazy_prereq UNZIP ' + "$GIT_UNZIP" -v + test $? -ne 127 +' diff --git a/templates/hooks--update.sample b/templates/hooks--update.sample index 71ab04edc0..d84758373d 100755 --- a/templates/hooks--update.sample +++ b/templates/hooks--update.sample @@ -38,7 +38,7 @@ if [ -z "$GIT_DIR" ]; then fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "Usage: $0 " >&2 + echo "usage: $0 " >&2 exit 1 fi diff --git a/test-chmtime.c b/test-chmtime.c index 92713d16da..02b42badd5 100644 --- a/test-chmtime.c +++ b/test-chmtime.c @@ -114,6 +114,6 @@ int main(int argc, const char *argv[]) return 0; usage: - fprintf(stderr, "Usage: %s %s\n", argv[0], usage_str); + fprintf(stderr, "usage: %s %s\n", argv[0], usage_str); return -1; } diff --git a/test-delta.c b/test-delta.c index af40a3c49e..4595cd6433 100644 --- a/test-delta.c +++ b/test-delta.c @@ -23,7 +23,7 @@ int main(int argc, char *argv[]) unsigned long from_size, data_size, out_size; if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) { - fprintf(stderr, "Usage: %s\n", usage_str); + fprintf(stderr, "usage: %s\n", usage_str); return 1; } diff --git a/test-genrandom.c b/test-genrandom.c index b3c28d9a1c..54824d0754 100644 --- a/test-genrandom.c +++ b/test-genrandom.c @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) unsigned char *c; if (argc < 2 || argc > 3) { - fprintf(stderr, "Usage: %s []\n", argv[0]); + fprintf(stderr, "usage: %s []\n", argv[0]); return 1; } diff --git a/test-svn-fe.c b/test-svn-fe.c index 0f2d9a4a3d..120ec96b0d 100644 --- a/test-svn-fe.c +++ b/test-svn-fe.c @@ -24,7 +24,7 @@ static int apply_delta(int argc, char *argv[]) die_errno("cannot open preimage"); if (buffer_init(&delta, argv[3])) die_errno("cannot open delta"); - if (svndiff0_apply(&delta, (off_t) strtoull(argv[4], NULL, 0), + if (svndiff0_apply(&delta, (off_t) strtoumax(argv[4], NULL, 0), &preimage_view, stdout)) return 1; if (buffer_deinit(&preimage)) diff --git a/transport.c b/transport.c index 886ffd8b1e..eb9eb33e0f 100644 --- a/transport.c +++ b/transport.c @@ -106,7 +106,8 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list) return; for (;;) { - int cmp = cmp, len; + int cmp = 0; /* assigned before used */ + int len; if (!fgets(buffer, sizeof(buffer), f)) { fclose(f); @@ -518,11 +519,9 @@ static int fetch_refs_via_pack(struct transport *transport, int nr_heads, struct ref **to_fetch) { struct git_transport_data *data = transport->data; - struct string_list sought = STRING_LIST_INIT_DUP; const struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; - int i; struct ref *refs_tmp = NULL; memset(&args, 0, sizeof(args)); @@ -536,9 +535,6 @@ static int fetch_refs_via_pack(struct transport *transport, args.no_progress = !transport->progress; args.depth = data->options.depth; - for (i = 0; i < nr_heads; i++) - string_list_append(&sought, to_fetch[i]->name); - if (!data->got_remote_heads) { connect_setup(transport, 0, 0); get_remote_heads(data->fd[0], &refs_tmp, 0, NULL); @@ -547,7 +543,8 @@ static int fetch_refs_via_pack(struct transport *transport, refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, - dest, &sought, &transport->pack_lockfile); + dest, to_fetch, nr_heads, + &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) @@ -557,7 +554,6 @@ static int fetch_refs_via_pack(struct transport *transport, free_refs(refs_tmp); - string_list_clear(&sought, 0); free(dest); return (refs ? 0 : -1); } @@ -1132,6 +1128,8 @@ int transport_push(struct transport *transport, match_flags |= MATCH_REFS_MIRROR; if (flags & TRANSPORT_PUSH_PRUNE) match_flags |= MATCH_REFS_PRUNE; + if (flags & TRANSPORT_PUSH_FOLLOW_TAGS) + match_flags |= MATCH_REFS_FOLLOW_TAGS; if (match_push_refs(local_refs, &remote_refs, refspec_nr, refspec, match_flags)) { diff --git a/transport.h b/transport.h index a3450e97c0..9354462708 100644 --- a/transport.h +++ b/transport.h @@ -105,6 +105,7 @@ struct transport { #define TRANSPORT_PUSH_PRUNE 128 #define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256 #define TRANSPORT_PUSH_NO_HOOK 512 +#define TRANSPORT_PUSH_FOLLOW_TAGS 1024 #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) #define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x) diff --git a/upload-pack.c b/upload-pack.c index 30146a04f7..35605310d2 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -26,6 +26,7 @@ static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=< #define SHALLOW (1u << 16) #define NOT_SHALLOW (1u << 17) #define CLIENT_SHALLOW (1u << 18) +#define HIDDEN_REF (1u << 19) static unsigned long oldest_have; @@ -33,6 +34,7 @@ static int multi_ack; static int no_done; static int use_thin_pack, use_ofs_delta, use_include_tag; static int no_progress, daemon_mode; +static int allow_tip_sha1_in_want; static int shallow_nr; static struct object_array have_obj; static struct object_array want_obj; @@ -487,6 +489,12 @@ static int get_common_commits(void) } } +static int is_our_ref(struct object *o) +{ + return o->flags & + ((allow_tip_sha1_in_want ? HIDDEN_REF : 0) | OUR_REF); +} + static void check_non_tip(void) { static const char *argv[] = { @@ -523,7 +531,7 @@ static void check_non_tip(void) o = get_indexed_object(--i); if (!o) continue; - if (!(o->flags & OUR_REF)) + if (!is_our_ref(o)) continue; memcpy(namebuf + 1, sha1_to_hex(o->sha1), 40); if (write_in_full(cmd.in, namebuf, 42) < 0) @@ -532,7 +540,7 @@ static void check_non_tip(void) namebuf[40] = '\n'; for (i = 0; i < want_obj.nr; i++) { o = want_obj.objects[i].item; - if (o->flags & OUR_REF) + if (is_our_ref(o)) continue; memcpy(namebuf, sha1_to_hex(o->sha1), 40); if (write_in_full(cmd.in, namebuf, 41) < 0) @@ -566,7 +574,7 @@ static void check_non_tip(void) /* Pick one of them (we know there at least is one) */ for (i = 0; i < want_obj.nr; i++) { o = want_obj.objects[i].item; - if (!(o->flags & OUR_REF)) + if (!is_our_ref(o)) die("git upload-pack: not our ref %s", sha1_to_hex(o->sha1)); } @@ -646,7 +654,7 @@ static void receive_needs(void) sha1_to_hex(sha1_buf)); if (!(o->flags & WANTED)) { o->flags |= WANTED; - if (!(o->flags & OUR_REF)) + if (!is_our_ref(o)) has_non_tip = 1; add_object_array(o, NULL, &want_obj); } @@ -732,8 +740,10 @@ static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag { struct object *o = lookup_unknown_object(sha1); - if (ref_is_hidden(refname)) + if (ref_is_hidden(refname)) { + o->flags |= HIDDEN_REF; return 1; + } if (!o) die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1)); o->flags |= OUR_REF; @@ -752,9 +762,10 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo return 0; if (capabilities) - packet_write(1, "%s %s%c%s%s agent=%s\n", + packet_write(1, "%s %s%c%s%s%s agent=%s\n", sha1_to_hex(sha1), refname_nons, 0, capabilities, + allow_tip_sha1_in_want ? " allow-tip-sha1-in-want" : "", stateless_rpc ? " no-done" : "", git_user_agent_sanitized()); else @@ -788,6 +799,8 @@ static void upload_pack(void) static int upload_pack_config(const char *var, const char *value, void *unused) { + if (!strcmp("uploadpack.allowtipsha1inwant", var)) + allow_tip_sha1_in_want = git_config_bool(var, value); return parse_hide_refs_config(var, value, "uploadpack"); } diff --git a/utf8.c b/utf8.c index 1087870c51..7f648574a5 100644 --- a/utf8.c +++ b/utf8.c @@ -507,11 +507,66 @@ char *reencode_string(const char *in, const char *out_encoding, const char *in_e if (!in_encoding) return NULL; + conv = iconv_open(out_encoding, in_encoding); - if (conv == (iconv_t) -1) - return NULL; + if (conv == (iconv_t) -1) { + /* + * Some platforms do not have the variously spelled variants of + * UTF-8, so let's fall back to trying the most official + * spelling. We do so only as a fallback in case the platform + * does understand the user's spelling, but not our official + * one. + */ + if (is_encoding_utf8(in_encoding)) + in_encoding = "UTF-8"; + if (is_encoding_utf8(out_encoding)) + out_encoding = "UTF-8"; + conv = iconv_open(out_encoding, in_encoding); + if (conv == (iconv_t) -1) + return NULL; + } + out = reencode_string_iconv(in, strlen(in), conv); iconv_close(conv); return out; } #endif + +/* + * Returns first character length in bytes for multi-byte `text` according to + * `encoding`. + * + * - The `text` pointer is updated to point at the next character. + * - When `remainder_p` is not NULL, on entry `*remainder_p` is how much bytes + * we can consume from text, and on exit `*remainder_p` is reduced by returned + * character length. Otherwise `text` is treated as limited by NUL. + */ +int mbs_chrlen(const char **text, size_t *remainder_p, const char *encoding) +{ + int chrlen; + const char *p = *text; + size_t r = (remainder_p ? *remainder_p : SIZE_MAX); + + if (r < 1) + return 0; + + if (is_encoding_utf8(encoding)) { + pick_one_utf8_char(&p, &r); + + chrlen = p ? (p - *text) + : 1 /* not valid UTF-8 -> raw byte sequence */; + } + else { + /* + * TODO use iconv to decode one char and obtain its chrlen + * for now, let's treat encodings != UTF-8 as one-byte + */ + chrlen = 1; + } + + *text += chrlen; + if (remainder_p) + *remainder_p -= chrlen; + + return chrlen; +} diff --git a/utf8.h b/utf8.h index 501b2bd9c4..1f8ecad1e8 100644 --- a/utf8.h +++ b/utf8.h @@ -22,4 +22,6 @@ char *reencode_string(const char *in, const char *out_encoding, const char *in_e #define reencode_string(a,b,c) NULL #endif +int mbs_chrlen(const char **text, size_t *remainder_p, const char *encoding); + #endif diff --git a/wt-status.c b/wt-status.c index ef405d03d9..54f4391f9c 100644 --- a/wt-status.c +++ b/wt-status.c @@ -264,7 +264,7 @@ static void wt_status_print_change_data(struct wt_status *s, { struct wt_status_change_data *d = it->util; const char *c = color(change_type, s); - int status = status; + int status; char *one_name; char *two_name; const char *one, *two; @@ -292,6 +292,9 @@ static void wt_status_print_change_data(struct wt_status *s, } status = d->worktree_status; break; + default: + die("BUG: unhandled change_type %d in wt_status_print_change_data", + change_type); } one = quote_path(one_name, -1, &onebuf, s->prefix); @@ -496,9 +499,14 @@ static void wt_status_collect_untracked(struct wt_status *s) { int i; struct dir_struct dir; + struct timeval t_begin; if (!s->show_untracked_files) return; + + if (advice_status_u_option) + gettimeofday(&t_begin, NULL); + memset(&dir, 0, sizeof(dir)); if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES) dir.flags |= @@ -530,6 +538,14 @@ static void wt_status_collect_untracked(struct wt_status *s) } free(dir.entries); + + if (advice_status_u_option) { + struct timeval t_end; + gettimeofday(&t_end, NULL); + s->untracked_in_ms = + (uint64_t)t_end.tv_sec * 1000 + t_end.tv_usec / 1000 - + ((uint64_t)t_begin.tv_sec * 1000 + t_begin.tv_usec / 1000); + } } void wt_status_collect(struct wt_status *s) @@ -1097,6 +1113,18 @@ void wt_status_print(struct wt_status *s) wt_status_print_other(s, &s->untracked, _("Untracked files"), "add"); if (s->show_ignored_files) wt_status_print_other(s, &s->ignored, _("Ignored files"), "add -f"); + if (advice_status_u_option && 2000 < s->untracked_in_ms) { + status_printf_ln(s, GIT_COLOR_NORMAL, ""); + status_printf_ln(s, GIT_COLOR_NORMAL, + _("It took %.2f seconds to enumerate untracked files." + " 'status -uno'"), + s->untracked_in_ms / 1000.0); + status_printf_ln(s, GIT_COLOR_NORMAL, + _("may speed it up, but you have to be careful not" + " to forget to add")); + status_printf_ln(s, GIT_COLOR_NORMAL, + _("new files yourself (see 'git help status').")); + } } else if (s->commitable) status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"), advice_status_hints diff --git a/wt-status.h b/wt-status.h index 81e1dcf84d..74208c06fd 100644 --- a/wt-status.h +++ b/wt-status.h @@ -69,6 +69,7 @@ struct wt_status { struct string_list change; struct string_list untracked; struct string_list ignored; + uint32_t untracked_in_ms; }; struct wt_status_state {