mirror of
https://github.com/git/git.git
synced 2026-04-13 18:30:08 +02:00
Start maintenance track for 2.10.x series
This commit is contained in:
1
.mailmap
1
.mailmap
@@ -33,6 +33,7 @@ Cheng Renquan <crquan@gmail.com>
|
|||||||
Chris Shoemaker <c.shoemaker@cox.net>
|
Chris Shoemaker <c.shoemaker@cox.net>
|
||||||
Chris Wright <chrisw@sous-sol.org> <chrisw@osdl.org>
|
Chris Wright <chrisw@sous-sol.org> <chrisw@osdl.org>
|
||||||
Cord Seele <cowose@gmail.com> <cowose@googlemail.com>
|
Cord Seele <cowose@gmail.com> <cowose@googlemail.com>
|
||||||
|
Christian Couder <chriscool@tuxfamily.org> <christian.couder@gmail.com>
|
||||||
Christian Stimming <stimming@tuhh.de> <chs@ckiste.goetheallee>
|
Christian Stimming <stimming@tuhh.de> <chs@ckiste.goetheallee>
|
||||||
Csaba Henk <csaba@gluster.com> <csaba@lowlife.hu>
|
Csaba Henk <csaba@gluster.com> <csaba@lowlife.hu>
|
||||||
Dan Johnson <computerdruid@gmail.com>
|
Dan Johnson <computerdruid@gmail.com>
|
||||||
|
|||||||
675
Documentation/RelNotes/2.10.0.txt
Normal file
675
Documentation/RelNotes/2.10.0.txt
Normal file
@@ -0,0 +1,675 @@
|
|||||||
|
Git 2.10 Release Notes
|
||||||
|
======================
|
||||||
|
|
||||||
|
Backward compatibility notes
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Updates since v2.9
|
||||||
|
------------------
|
||||||
|
|
||||||
|
UI, Workflows & Features
|
||||||
|
|
||||||
|
* "git pull --rebase --verify-signature" learned to warn the user
|
||||||
|
that "--verify-signature" is a no-op when rebasing.
|
||||||
|
|
||||||
|
* An upstream project can make a recommendation to shallowly clone
|
||||||
|
some submodules in the .gitmodules file it ships.
|
||||||
|
|
||||||
|
* "git worktree add" learned that '-' can be used as a short-hand for
|
||||||
|
"@{-1}", the previous branch.
|
||||||
|
|
||||||
|
* Update the funcname definition to support css files.
|
||||||
|
|
||||||
|
* The completion script (in contrib/) learned to complete "git
|
||||||
|
status" options.
|
||||||
|
|
||||||
|
* Messages that are generated by auto gc during "git push" on the
|
||||||
|
receiving end are now passed back to the sending end in such a way
|
||||||
|
that they are shown with "remote: " prefix to avoid confusing the
|
||||||
|
users.
|
||||||
|
|
||||||
|
* "git add -i/-p" learned to honor diff.compactionHeuristic
|
||||||
|
experimental knob, so that the user can work on the same hunk split
|
||||||
|
as "git diff" output.
|
||||||
|
|
||||||
|
* "upload-pack" allows a custom "git pack-objects" replacement when
|
||||||
|
responding to "fetch/clone" via the uploadpack.packObjectsHook.
|
||||||
|
(merge b738396 jk/upload-pack-hook later to maint).
|
||||||
|
|
||||||
|
* Teach format-patch and mailsplit (hence "am") how a line that
|
||||||
|
happens to begin with "From " in the e-mail message is quoted with
|
||||||
|
">", so that these lines can be restored to their original shape.
|
||||||
|
(merge d9925d1 ew/mboxrd-format-am later to maint).
|
||||||
|
|
||||||
|
* "git repack" learned the "--keep-unreachable" option, which sends
|
||||||
|
loose unreachable objects to a pack instead of leaving them loose.
|
||||||
|
This helps heuristics based on the number of loose objects
|
||||||
|
(e.g. "gc --auto").
|
||||||
|
(merge e26a8c4 jk/repack-keep-unreachable later to maint).
|
||||||
|
|
||||||
|
* "log --graph --format=" learned that "%>|(N)" specifies the width
|
||||||
|
relative to the terminal's left edge, not relative to the area to
|
||||||
|
draw text that is to the right of the ancestry-graph section. It
|
||||||
|
also now accepts negative N that means the column limit is relative
|
||||||
|
to the right border.
|
||||||
|
|
||||||
|
* A careless invocation of "git send-email directory/" after editing
|
||||||
|
0001-change.patch with an editor often ends up sending both
|
||||||
|
0001-change.patch and its backup file, 0001-change.patch~, causing
|
||||||
|
embarrassment and a minor confusion. Detect such an input and
|
||||||
|
offer to skip the backup files when sending the patches out.
|
||||||
|
(merge 531220b jc/send-email-skip-backup later to maint).
|
||||||
|
|
||||||
|
* "git submodule update" that drives many "git clone" could
|
||||||
|
eventually hit flaky servers/network conditions on one of the
|
||||||
|
submodules; the command learned to retry the attempt.
|
||||||
|
|
||||||
|
* The output coloring scheme learned two new attributes, italic and
|
||||||
|
strike, in addition to existing bold, reverse, etc.
|
||||||
|
|
||||||
|
* "git log" learns log.showSignature configuration variable, and a
|
||||||
|
command line option "--no-show-signature" to countermand it.
|
||||||
|
(merge fce04c3 mj/log-show-signature-conf later to maint).
|
||||||
|
|
||||||
|
* More markings of messages for i18n, with updates to various tests
|
||||||
|
to pass GETTEXT_POISON tests.
|
||||||
|
|
||||||
|
* "git archive" learned to handle files that are larger than 8GB and
|
||||||
|
commits far in the future than expressible by the traditional US-TAR
|
||||||
|
format.
|
||||||
|
(merge 560b0e8 jk/big-and-future-archive-tar later to maint).
|
||||||
|
|
||||||
|
|
||||||
|
* A new configuration variable core.sshCommand has been added to
|
||||||
|
specify what value for GIT_SSH_COMMAND to use per repository.
|
||||||
|
|
||||||
|
* "git worktree prune" protected worktrees that are marked as
|
||||||
|
"locked" by creating a file in a known location. "git worktree"
|
||||||
|
command learned a dedicated command pair to create and remove such
|
||||||
|
a file, so that the users do not have to do this with editor.
|
||||||
|
|
||||||
|
* A handful of "git svn" updates.
|
||||||
|
|
||||||
|
* "git push" learned to accept and pass extra options to the
|
||||||
|
receiving end so that hooks can read and react to them.
|
||||||
|
|
||||||
|
* "git status" learned to suggest "merge --abort" during a conflicted
|
||||||
|
merge, just like it already suggests "rebase --abort" during a
|
||||||
|
conflicted rebase.
|
||||||
|
|
||||||
|
* "git jump" script (in contrib/) has been updated a bit.
|
||||||
|
(merge a91e692 jk/git-jump later to maint).
|
||||||
|
|
||||||
|
* "git push" and "git clone" learned to give better progress meters
|
||||||
|
to the end user who is waiting on the terminal.
|
||||||
|
|
||||||
|
* An entry "git log --decorate" for the tip of the current branch is
|
||||||
|
shown as "HEAD -> name" (where "name" is the name of the branch);
|
||||||
|
the arrow is now painted in the same color as "HEAD", not in the
|
||||||
|
color for commits.
|
||||||
|
|
||||||
|
* "git format-patch" learned format.from configuration variable to
|
||||||
|
specify the default settings for its "--from" option.
|
||||||
|
|
||||||
|
* "git am -3" calls "git merge-recursive" when it needs to fall back
|
||||||
|
to a three-way merge; this call has been turned into an internal
|
||||||
|
subroutine call instead of spawning a separate subprocess.
|
||||||
|
|
||||||
|
* The command line completion scripts (in contrib/) now knows about
|
||||||
|
"git branch --delete/--move [--remote]".
|
||||||
|
(merge 2703c22 vs/completion-branch-fully-spelled-d-m-r later to maint).
|
||||||
|
|
||||||
|
* "git rev-parse --git-path hooks/<hook>" learned to take
|
||||||
|
core.hooksPath configuration variable (introduced during 2.9 cycle)
|
||||||
|
into account.
|
||||||
|
(merge 9445b49 ab/hooks later to maint).
|
||||||
|
|
||||||
|
* "git log --show-signature" and other commands that display the
|
||||||
|
verification status of PGP signature now shows the longer key-id,
|
||||||
|
as 32-bit key-id is so last century.
|
||||||
|
|
||||||
|
|
||||||
|
Performance, Internal Implementation, Development Support etc.
|
||||||
|
|
||||||
|
* "git fast-import" learned the same performance trick to avoid
|
||||||
|
creating too small a packfile as "git fetch" and "git push" have,
|
||||||
|
using *.unpackLimit configuration.
|
||||||
|
|
||||||
|
* When "git daemon" is run without --[init-]timeout specified, a
|
||||||
|
connection from a client that silently goes offline can hang around
|
||||||
|
for a long time, wasting resources. The socket-level KEEPALIVE has
|
||||||
|
been enabled to allow the OS to notice such failed connections.
|
||||||
|
|
||||||
|
* "git upload-pack" command has been updated to use the parse-options
|
||||||
|
API.
|
||||||
|
|
||||||
|
* The "git apply" standalone program is being libified; the first
|
||||||
|
step to move many state variables into a structure that can be
|
||||||
|
explicitly (re)initialized to make the machinery callable more
|
||||||
|
than once has been merged.
|
||||||
|
|
||||||
|
* HTTP transport gained an option to produce more detailed debugging
|
||||||
|
trace.
|
||||||
|
(merge 73e57aa ep/http-curl-trace later to maint).
|
||||||
|
|
||||||
|
* Instead of taking advantage of the fact that a struct string_list
|
||||||
|
that is allocated with all NULs happens to be the INIT_NODUP kind,
|
||||||
|
the users of string_list structures are taught to initialize them
|
||||||
|
explicitly as such, to document their behaviour better.
|
||||||
|
(merge 2721ce2 jk/string-list-static-init later to maint).
|
||||||
|
|
||||||
|
* HTTPd tests learned to show the server error log to help diagnosing
|
||||||
|
a failing tests.
|
||||||
|
(merge 44f243d nd/test-lib-httpd-show-error-log-in-verbose later to maint).
|
||||||
|
|
||||||
|
* The ownership rule for the piece of memory that hold references to
|
||||||
|
be fetched in "git fetch" was screwy, which has been cleaned up.
|
||||||
|
|
||||||
|
* "git bisect" makes an internal call to "git diff-tree" when
|
||||||
|
bisection finds the culprit, but this call did not initialize the
|
||||||
|
data structure to pass to the diff-tree API correctly.
|
||||||
|
|
||||||
|
* Further preparatory clean-up for "worktree" feature continues.
|
||||||
|
(merge 0409e0b nd/worktree-cleanup-post-head-protection later to maint).
|
||||||
|
|
||||||
|
* Formats of the various data (and how to validate them) where we use
|
||||||
|
GPG signature have been documented.
|
||||||
|
|
||||||
|
* A new run-command API function pipe_command() is introduced to
|
||||||
|
sanely feed data to the standard input while capturing data from
|
||||||
|
the standard output and the standard error of an external process,
|
||||||
|
which is cumbersome to hand-roll correctly without deadlocking.
|
||||||
|
|
||||||
|
* The codepath to sign data in a prepared buffer with GPG has been
|
||||||
|
updated to use this API to read from the status-fd to check for
|
||||||
|
errors (instead of relying on GPG's exit status).
|
||||||
|
(merge efee955 jk/gpg-interface-cleanup later to maint).
|
||||||
|
|
||||||
|
* Allow t/perf framework to use the features from the most recent
|
||||||
|
version of Git even when testing an older installed version.
|
||||||
|
|
||||||
|
* The commands in the "log/diff" family have had an FILE* pointer in the
|
||||||
|
data structure they pass around for a long time, but some codepaths
|
||||||
|
used to always write to the standard output. As a preparatory step
|
||||||
|
to make "git format-patch" available to the internal callers, these
|
||||||
|
codepaths have been updated to consistently write into that FILE*
|
||||||
|
instead.
|
||||||
|
|
||||||
|
* Conversion from unsigned char sha1[20] to struct object_id
|
||||||
|
continues.
|
||||||
|
|
||||||
|
* Improve the look of the way "git fetch" reports what happened to
|
||||||
|
each ref that was fetched.
|
||||||
|
|
||||||
|
* The .c/.h sources are marked as such in our .gitattributes file so
|
||||||
|
that "git diff -W" and friends would work better.
|
||||||
|
|
||||||
|
* Code clean-up to avoid using a variable string that compilers may
|
||||||
|
feel untrustable as printf-style format given to write_file()
|
||||||
|
helper function.
|
||||||
|
|
||||||
|
* "git p4" used a location outside $GIT_DIR/refs/ to place its
|
||||||
|
temporary branches, which has been moved to refs/git-p4-tmp/.
|
||||||
|
|
||||||
|
* Existing autoconf generated test for the need to link with pthread
|
||||||
|
library did not check all the functions from pthread libraries;
|
||||||
|
recent FreeBSD has some functions in libc but not others, and we
|
||||||
|
mistakenly thought linking with libc is enough when it is not.
|
||||||
|
|
||||||
|
* When "git fsck" reports a broken link (e.g. a tree object contains
|
||||||
|
a blob that does not exist), both containing object and the object
|
||||||
|
that is referred to were reported with their 40-hex object names.
|
||||||
|
The command learned the "--name-objects" option to show the path to
|
||||||
|
the containing object from existing refs (e.g. "HEAD~24^2:file.txt").
|
||||||
|
|
||||||
|
* Allow http daemon tests in Travis CI tests.
|
||||||
|
|
||||||
|
* Makefile assumed that -lrt is always available on platforms that
|
||||||
|
want to use clock_gettime() and CLOCK_MONOTONIC, which is not a
|
||||||
|
case for recent Mac OS X. The necessary symbols are often found in
|
||||||
|
libc on many modern systems and having -lrt on the command line, as
|
||||||
|
long as the library exists, had no effect, but when the platform
|
||||||
|
removes librt.a that is a different matter--having -lrt will break
|
||||||
|
the linkage.
|
||||||
|
|
||||||
|
This change could be seen as a regression for those who do need to
|
||||||
|
specify -lrt, as they now specifically ask for NEEDS_LIBRT when
|
||||||
|
building. Hopefully they are in the minority these days.
|
||||||
|
|
||||||
|
* Further preparatory work on the refs API before the pluggable
|
||||||
|
backend series can land.
|
||||||
|
|
||||||
|
* Error handling in the codepaths that updates refs has been
|
||||||
|
improved.
|
||||||
|
|
||||||
|
* The API to iterate over all the refs (i.e. for_each_ref(), etc.)
|
||||||
|
has been revamped.
|
||||||
|
|
||||||
|
* The handling of the "text=auto" attribute has been corrected.
|
||||||
|
$ echo "* text=auto eol=crlf" >.gitattributes
|
||||||
|
used to have the same effect as
|
||||||
|
$ echo "* text eol=crlf" >.gitattributes
|
||||||
|
i.e. declaring all files are text (ignoring "auto"). The
|
||||||
|
combination has been fixed to be equivalent to doing
|
||||||
|
$ git config core.autocrlf true
|
||||||
|
|
||||||
|
* Documentation has been updated to show better example usage
|
||||||
|
of the updated "text=auto" attribute.
|
||||||
|
|
||||||
|
* A few tests that specifically target "git rebase -i" have been
|
||||||
|
added.
|
||||||
|
|
||||||
|
* Dumb http transport on the client side has been optimized.
|
||||||
|
(merge ecba195 ew/http-walker later to maint).
|
||||||
|
|
||||||
|
* Users of the parse_options_concat() API function need to allocate
|
||||||
|
extra slots in advance and fill them with OPT_END() when they want
|
||||||
|
to decide the set of supported options dynamically, which makes the
|
||||||
|
code error-prone and hard to read. This has been corrected by tweaking
|
||||||
|
the API to allocate and return a new copy of "struct option" array.
|
||||||
|
|
||||||
|
* "git fetch" exchanges batched have/ack messages between the sender
|
||||||
|
and the receiver, initially doubling every time and then falling
|
||||||
|
back to enlarge the window size linearly. The "smart http"
|
||||||
|
transport, being an half-duplex protocol, outgrows the preset limit
|
||||||
|
too quickly and becomes inefficient when interacting with a large
|
||||||
|
repository. The internal mechanism learned to grow the window size
|
||||||
|
more aggressively when working with the "smart http" transport.
|
||||||
|
|
||||||
|
* Tests for "git svn" have been taught to reuse the lib-httpd test
|
||||||
|
infrastructure when testing the subversion integration that
|
||||||
|
interacts with subversion repositories served over the http://
|
||||||
|
protocol.
|
||||||
|
(merge a8a5d25 ew/git-svn-http-tests later to maint).
|
||||||
|
|
||||||
|
* "git pack-objects" has a few options that tell it not to pack
|
||||||
|
objects found in certain packfiles, which require it to scan .idx
|
||||||
|
files of all available packs. The codepaths involved in these
|
||||||
|
operations have been optimized for a common case of not having any
|
||||||
|
non-local pack and/or any .kept pack.
|
||||||
|
|
||||||
|
* The t3700 test about "add --chmod=-x" have been made a bit more
|
||||||
|
robust and generally cleaned up.
|
||||||
|
(merge 766cdc4 ib/t3700-add-chmod-x-updates later to maint).
|
||||||
|
|
||||||
|
* The build procedure learned PAGER_ENV knob that lists what default
|
||||||
|
environment variable settings to export for popular pagers. This
|
||||||
|
mechanism is used to tweak the default settings to MORE on FreeBSD.
|
||||||
|
(merge 995bc22 ew/build-time-pager-tweaks later to maint).
|
||||||
|
|
||||||
|
* The http-backend (the server-side component of smart-http
|
||||||
|
transport) used to trickle the HTTP header one at a time. Now
|
||||||
|
these write(2)s are batched.
|
||||||
|
(merge b36045c ew/http-backend-batch-headers later to maint).
|
||||||
|
|
||||||
|
* When "git rebase" tries to compare set of changes on the updated
|
||||||
|
upstream and our own branch, it computes patch-id for all of these
|
||||||
|
changes and attempts to find matches. This has been optimized by
|
||||||
|
lazily computing the full patch-id (which is expensive) to be
|
||||||
|
compared only for changes that touch the same set of paths.
|
||||||
|
(merge ba67504 kw/patch-ids-optim later to maint).
|
||||||
|
|
||||||
|
* A handful of tests that were broken under gettext-poison build have
|
||||||
|
been fixed.
|
||||||
|
|
||||||
|
* The recent i18n patch we added during this cycle did a bit too much
|
||||||
|
refactoring of the messages to avoid word-legos; the repetition has
|
||||||
|
been reduced to help translators.
|
||||||
|
|
||||||
|
|
||||||
|
Also contains various documentation updates and code clean-ups.
|
||||||
|
|
||||||
|
|
||||||
|
Fixes since v2.9
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Unless otherwise noted, all the fixes since v2.8 in the maintenance
|
||||||
|
track are contained in this release (see the maintenance releases'
|
||||||
|
notes for details).
|
||||||
|
|
||||||
|
* The commands in `git log` family take %C(auto) in a custom format
|
||||||
|
string. This unconditionally turned the color on, ignoring
|
||||||
|
--no-color or with --color=auto when the output is not connected to
|
||||||
|
a tty; this was corrected to make the format truly behave as
|
||||||
|
"auto".
|
||||||
|
|
||||||
|
* "git rev-list --count" whose walk-length is limited with "-n"
|
||||||
|
option did not work well with the counting optimized to look at the
|
||||||
|
bitmap index.
|
||||||
|
|
||||||
|
* "git show -W" (extend hunks to cover the entire function, delimited
|
||||||
|
by lines that match the "funcname" pattern) used to show the entire
|
||||||
|
file when a change added an entire function at the end of the file,
|
||||||
|
which has been fixed.
|
||||||
|
|
||||||
|
* The documentation set has been updated so that literal commands,
|
||||||
|
configuration variables and environment variables are consistently
|
||||||
|
typeset in fixed-width font and bold in manpages.
|
||||||
|
|
||||||
|
* "git svn propset" subcommand that was added in 2.3 days is
|
||||||
|
documented now.
|
||||||
|
|
||||||
|
* The documentation tries to consistently spell "GPG"; when
|
||||||
|
referring to the specific program name, "gpg" is used.
|
||||||
|
|
||||||
|
* "git reflog" stopped upon seeing an entry that denotes a branch
|
||||||
|
creation event (aka "unborn"), which made it appear as if the
|
||||||
|
reflog was truncated.
|
||||||
|
|
||||||
|
* The git-prompt scriptlet (in contrib/) was not friendly with those
|
||||||
|
who uses "set -u", which has been fixed.
|
||||||
|
|
||||||
|
* compat/regex code did not cleanly compile.
|
||||||
|
|
||||||
|
* A codepath that used alloca(3) to place an unbounded amount of data
|
||||||
|
on the stack has been updated to avoid doing so.
|
||||||
|
|
||||||
|
* "git update-index --add --chmod=+x file" may be usable as an escape
|
||||||
|
hatch, but not a friendly thing to force for people who do need to
|
||||||
|
use it regularly. "git add --chmod=+x file" can be used instead.
|
||||||
|
|
||||||
|
* Build improvements for gnome-keyring (in contrib/)
|
||||||
|
|
||||||
|
* "git status" used to say "working directory" when it meant "working
|
||||||
|
tree".
|
||||||
|
|
||||||
|
* Comments about misbehaving FreeBSD shells have been clarified with
|
||||||
|
the version number (9.x and before are broken, newer ones are OK).
|
||||||
|
|
||||||
|
* "git cherry-pick A" worked on an unborn branch, but "git
|
||||||
|
cherry-pick A..B" didn't.
|
||||||
|
|
||||||
|
* Fix an unintended regression in v2.9 that breaks "clone --depth"
|
||||||
|
that recurses down to submodules by forcing the submodules to also
|
||||||
|
be cloned shallowly, which many server instances that host upstream
|
||||||
|
of the submodules are not prepared for.
|
||||||
|
|
||||||
|
* Fix unnecessarily waste in the idiomatic use of ': ${VAR=default}'
|
||||||
|
to set the default value, without enclosing it in double quotes.
|
||||||
|
|
||||||
|
* Some platform-specific code had non-ANSI strict declarations of C
|
||||||
|
functions that do not take any parameters, which has been
|
||||||
|
corrected.
|
||||||
|
|
||||||
|
* The internal code used to show local timezone offset is not
|
||||||
|
prepared to handle timestamps beyond year 2100, and gave a
|
||||||
|
bogus offset value to the caller. Use a more benign looking
|
||||||
|
+0000 instead and let "git log" going in such a case, instead
|
||||||
|
of aborting.
|
||||||
|
|
||||||
|
* One among four invocations of readlink(1) in our test suite has
|
||||||
|
been rewritten so that the test can run on systems without the
|
||||||
|
command (others are in valgrind test framework and t9802).
|
||||||
|
|
||||||
|
* t/perf needs /usr/bin/time with GNU extension; the invocation of it
|
||||||
|
is updated to "gtime" on Darwin.
|
||||||
|
|
||||||
|
* A bug, which caused "git p4" while running under verbose mode to
|
||||||
|
report paths that are omitted due to branch prefix incorrectly, has
|
||||||
|
been fixed; the command said "Ignoring file outside of prefix" for
|
||||||
|
paths that are _inside_.
|
||||||
|
|
||||||
|
* The top level documentation "git help git" still pointed at the
|
||||||
|
documentation set hosted at now-defunct google-code repository.
|
||||||
|
Update it to point to https://git.github.io/htmldocs/git.html
|
||||||
|
instead.
|
||||||
|
|
||||||
|
* A helper function that takes the contents of a commit object and
|
||||||
|
finds its subject line did not ignore leading blank lines, as is
|
||||||
|
commonly done by other codepaths. Make it ignore leading blank
|
||||||
|
lines to match.
|
||||||
|
|
||||||
|
* For a long time, we carried an in-code comment that said our
|
||||||
|
colored output would work only when we use fprintf/fputs on
|
||||||
|
Windows, which no longer is the case for the past few years.
|
||||||
|
|
||||||
|
* "gc.autoPackLimit" when set to 1 should not trigger a repacking
|
||||||
|
when there is only one pack, but the code counted poorly and did
|
||||||
|
so.
|
||||||
|
|
||||||
|
* Add a test to specify the desired behaviour that currently is not
|
||||||
|
available in "git rebase -Xsubtree=...".
|
||||||
|
|
||||||
|
* More mark-up updates to typeset strings that are expected to
|
||||||
|
literally typed by the end user in fixed-width font.
|
||||||
|
|
||||||
|
* "git commit --amend --allow-empty-message -S" for a commit without
|
||||||
|
any message body could have misidentified where the header of the
|
||||||
|
commit object ends.
|
||||||
|
|
||||||
|
* "git rebase -i --autostash" did not restore the auto-stashed change
|
||||||
|
when the operation was aborted.
|
||||||
|
|
||||||
|
* Git does not know what the contents in the index should be for a
|
||||||
|
path added with "git add -N" yet, so "git grep --cached" should not
|
||||||
|
show hits (or show lack of hits, with -L) in such a path, but that
|
||||||
|
logic does not apply to "git grep", i.e. searching in the working
|
||||||
|
tree files. But we did so by mistake, which has been corrected.
|
||||||
|
|
||||||
|
* "git blame -M" missed a single line that was moved within the file.
|
||||||
|
|
||||||
|
* Fix recently introduced codepaths that are involved in parallel
|
||||||
|
submodule operations, which gave up on reading too early, and
|
||||||
|
could have wasted CPU while attempting to write under a corner
|
||||||
|
case condition.
|
||||||
|
|
||||||
|
* "git grep -i" has been taught to fold case in non-ascii locales
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
* A test that unconditionally used "mktemp" learned that the command
|
||||||
|
is not necessarily available everywhere.
|
||||||
|
|
||||||
|
* There are certain house-keeping tasks that need to be performed at
|
||||||
|
the very beginning of any Git program, and programs that are not
|
||||||
|
built-in commands had to do them exactly the same way as "git"
|
||||||
|
potty does. It was easy to make mistakes in one-off standalone
|
||||||
|
programs (like test helpers). A common "main()" function that
|
||||||
|
calls cmd_main() of individual program has been introduced to
|
||||||
|
make it harder to make mistakes.
|
||||||
|
(merge de61ceb jk/common-main later to maint).
|
||||||
|
|
||||||
|
* The test framework learned a new helper test_match_signal to
|
||||||
|
check an exit code from getting killed by an expected signal.
|
||||||
|
|
||||||
|
* General code clean-up around a helper function to write a
|
||||||
|
single-liner to a file.
|
||||||
|
(merge 7eb6e10 jk/write-file later to maint).
|
||||||
|
|
||||||
|
* One part of "git am" had an oddball helper function that called
|
||||||
|
stuff from outside "his" as opposed to calling what we have "ours",
|
||||||
|
which was not gender-neutral and also inconsistent with the rest of
|
||||||
|
the system where outside stuff is usuall called "theirs" in
|
||||||
|
contrast to "ours".
|
||||||
|
|
||||||
|
* "git blame file" allowed the lineage of lines in the uncommitted,
|
||||||
|
unadded contents of "file" to be inspected, but it refused when
|
||||||
|
"file" did not appear in the current commit. When "file" was
|
||||||
|
created by renaming an existing file (but the change has not been
|
||||||
|
committed), this restriction was unnecessarily tight.
|
||||||
|
|
||||||
|
* "git add -N dir/file && git write-tree" produced an incorrect tree
|
||||||
|
when there are other paths in the same directory that sorts after
|
||||||
|
"file".
|
||||||
|
|
||||||
|
* "git fetch http://user:pass@host/repo..." scrubbed the userinfo
|
||||||
|
part, but "git push" didn't.
|
||||||
|
|
||||||
|
* "git merge" with renormalization did not work well with
|
||||||
|
merge-recursive, due to "safer crlf" conversion kicking in when it
|
||||||
|
shouldn't.
|
||||||
|
(merge 1335d76 jc/renormalize-merge-kill-safer-crlf later to maint).
|
||||||
|
|
||||||
|
* The use of strbuf in "git rm" to build filename to remove was a bit
|
||||||
|
suboptimal, which has been fixed.
|
||||||
|
|
||||||
|
* An age old bug that caused "git diff --ignore-space-at-eol"
|
||||||
|
misbehave has been fixed.
|
||||||
|
|
||||||
|
* "git notes merge" had a code to see if a path exists (and fails if
|
||||||
|
it does) and then open the path for writing (when it doesn't).
|
||||||
|
Replace it with open with O_EXCL.
|
||||||
|
|
||||||
|
* "git pack-objects" and "git index-pack" mostly operate with off_t
|
||||||
|
when talking about the offset of objects in a packfile, but there
|
||||||
|
were a handful of places that used "unsigned long" to hold that
|
||||||
|
value, leading to an unintended truncation.
|
||||||
|
|
||||||
|
* Recent update to "git daemon" tries to enable the socket-level
|
||||||
|
KEEPALIVE, but when it is spawned via inetd, the standard input
|
||||||
|
file descriptor may not necessarily be connected to a socket.
|
||||||
|
Suppress an ENOTSOCK error from setsockopt().
|
||||||
|
|
||||||
|
* Recent FreeBSD stopped making perl available at /usr/bin/perl;
|
||||||
|
switch the default the built-in path to /usr/local/bin/perl on not
|
||||||
|
too ancient FreeBSD releases.
|
||||||
|
|
||||||
|
* "git commit --help" said "--no-verify" is only about skipping the
|
||||||
|
pre-commit hook, and failed to say that it also skipped the
|
||||||
|
commit-msg hook.
|
||||||
|
|
||||||
|
* "git merge" in Git v2.9 was taught to forbid merging an unrelated
|
||||||
|
lines of history by default, but that is exactly the kind of thing
|
||||||
|
the "--rejoin" mode of "git subtree" (in contrib/) wants to do.
|
||||||
|
"git subtree" has been taught to use the "--allow-unrelated-histories"
|
||||||
|
option to override the default.
|
||||||
|
|
||||||
|
* The build procedure for "git persistent-https" helper (in contrib/)
|
||||||
|
has been updated so that it can be built with more recent versions
|
||||||
|
of Go.
|
||||||
|
|
||||||
|
* There is an optimization used in "git diff $treeA $treeB" to borrow
|
||||||
|
an already checked-out copy in the working tree when it is known to
|
||||||
|
be the same as the blob being compared, expecting that open/mmap of
|
||||||
|
such a file is faster than reading it from the object store, which
|
||||||
|
involves inflating and applying delta. This however kicked in even
|
||||||
|
when the checked-out copy needs to go through the convert-to-git
|
||||||
|
conversion (including the clean filter), which defeats the whole
|
||||||
|
point of the optimization. The optimization has been disabled when
|
||||||
|
the conversion is necessary.
|
||||||
|
|
||||||
|
* "git -c grep.patternType=extended log --basic-regexp" misbehaved
|
||||||
|
because the internal API to access the grep machinery was not
|
||||||
|
designed well.
|
||||||
|
|
||||||
|
* Windows port was failing some tests in t4130, due to the lack of
|
||||||
|
inum in the returned values by its lstat(2) emulation.
|
||||||
|
|
||||||
|
* The reflog output format is documented better, and a new format
|
||||||
|
--date=unix to report the seconds-since-epoch (without timezone)
|
||||||
|
has been added.
|
||||||
|
(merge 442f6fd jk/reflog-date later to maint).
|
||||||
|
|
||||||
|
* "git difftool <paths>..." started in a subdirectory failed to
|
||||||
|
interpret the paths relative to that directory, which has been
|
||||||
|
fixed.
|
||||||
|
|
||||||
|
* The characters in the label shown for tags/refs for commits in
|
||||||
|
"gitweb" output are now properly escaped for proper HTML output.
|
||||||
|
|
||||||
|
* FreeBSD can lie when asked mtime of a directory, which made the
|
||||||
|
untracked cache code to fall back to a slow-path, which in turn
|
||||||
|
caused tests in t7063 to fail because it wanted to verify the
|
||||||
|
behaviour of the fast-path.
|
||||||
|
|
||||||
|
* Squelch compiler warnings for nedmalloc (in compat/) library.
|
||||||
|
|
||||||
|
* A small memory leak in the command line parsing of "git blame"
|
||||||
|
has been plugged.
|
||||||
|
|
||||||
|
* The API documentation for hashmap was unclear if hashmap_entry
|
||||||
|
can be safely discarded without any other consideration. State
|
||||||
|
that it is safe to do so.
|
||||||
|
|
||||||
|
* Not-so-recent rewrite of "git am" that started making internal
|
||||||
|
calls into the commit machinery had an unintended regression, in
|
||||||
|
that no matter how many seconds it took to apply many patches, the
|
||||||
|
resulting committer timestamp for the resulting commits were all
|
||||||
|
the same.
|
||||||
|
|
||||||
|
* "git push --force-with-lease" already had enough logic to allow
|
||||||
|
ensuring that such a push results in creation of a ref (i.e. the
|
||||||
|
receiving end did not have another push from sideways that would be
|
||||||
|
discarded by our force-pushing), but didn't expose this possibility
|
||||||
|
to the users. It does so now.
|
||||||
|
(merge 9eed4f3 jk/push-force-with-lease-creation later to maint).
|
||||||
|
|
||||||
|
* The mechanism to limit the pack window memory size, when packing is
|
||||||
|
done using multiple threads (which is the default), is per-thread,
|
||||||
|
but this was not documented clearly.
|
||||||
|
(merge 954176c ms/document-pack-window-memory-is-per-thread later to maint).
|
||||||
|
|
||||||
|
* "import-tars" fast-import script (in contrib/) used to ignore a
|
||||||
|
hardlink target and replaced it with an empty file, which has been
|
||||||
|
corrected to record the same blob as the other file the hardlink is
|
||||||
|
shared with.
|
||||||
|
(merge 04e0869 js/import-tars-hardlinks later to maint).
|
||||||
|
|
||||||
|
* "git mv dir non-existing-dir/" did not work in some environments
|
||||||
|
the same way as existing mainstream platforms. The code now moves
|
||||||
|
"dir" to "non-existing-dir", without relying on rename("A", "B/")
|
||||||
|
that strips the trailing slash of '/'.
|
||||||
|
(merge 189d035 js/mv-dir-to-new-directory later to maint).
|
||||||
|
|
||||||
|
* The "t/" hierarchy is prone to get an unusual pathname; "make test"
|
||||||
|
has been taught to make sure they do not contain paths that cannot
|
||||||
|
be checked out on Windows (and the mechanism can be reusable to
|
||||||
|
catch pathnames that are not portable to other platforms as need
|
||||||
|
arises).
|
||||||
|
(merge c2cafd3 js/test-lint-pathname later to maint).
|
||||||
|
|
||||||
|
* When "git merge-recursive" works on history with many criss-cross
|
||||||
|
merges in "verbose" mode, the names the command assigns to the
|
||||||
|
virtual merge bases could have overwritten each other by unintended
|
||||||
|
reuse of the same piece of memory.
|
||||||
|
(merge 5447a76 rs/pull-signed-tag later to maint).
|
||||||
|
|
||||||
|
* "git checkout --detach <branch>" used to give the same advice
|
||||||
|
message as that is issued when "git checkout <tag>" (or anything
|
||||||
|
that is not a branch name) is given, but asking with "--detach" is
|
||||||
|
an explicit enough sign that the user knows what is going on. The
|
||||||
|
advice message has been squelched in this case.
|
||||||
|
(merge 779b88a sb/checkout-explit-detach-no-advice later to maint).
|
||||||
|
|
||||||
|
* "git difftool" by default ignores the error exit from the backend
|
||||||
|
commands it spawns, because often they signal that they found
|
||||||
|
differences by exiting with a non-zero status code just like "diff"
|
||||||
|
does; the exit status codes 126 and above however are special in
|
||||||
|
that they are used to signal that the command is not executable,
|
||||||
|
does not exist, or killed by a signal. "git difftool" has been
|
||||||
|
taught to notice these exit status codes.
|
||||||
|
(merge 45a4f5d jk/difftool-command-not-found later to maint).
|
||||||
|
|
||||||
|
* On Windows, help.browser configuration variable used to be ignored,
|
||||||
|
which has been corrected.
|
||||||
|
(merge 6db5967 js/no-html-bypass-on-windows later to maint).
|
||||||
|
|
||||||
|
* The "git -c var[=val] cmd" facility to append a configuration
|
||||||
|
variable definition at the end of the search order was described in
|
||||||
|
git(1) manual page, but not in git-config(1), which was more likely
|
||||||
|
place for people to look for when they ask "can I make a one-shot
|
||||||
|
override, and if so how?"
|
||||||
|
(merge ae1f709 dg/document-git-c-in-git-config-doc later to maint).
|
||||||
|
|
||||||
|
* The tempfile (hence its user lockfile) API lets the caller to open
|
||||||
|
a file descriptor to a temporary file, write into it and then
|
||||||
|
finalize it by first closing the filehandle and then either
|
||||||
|
removing or renaming the temporary file. When the process spawns a
|
||||||
|
subprocess after obtaining the file descriptor, and if the
|
||||||
|
subprocess has not exited when the attempt to remove or rename is
|
||||||
|
made, the last step fails on Windows, because the subprocess has
|
||||||
|
the file descriptor still open. Open tempfile with O_CLOEXEC flag
|
||||||
|
to avoid this (on Windows, this is mapped to O_NOINHERIT).
|
||||||
|
(merge 05d1ed6 bw/mingw-avoid-inheriting-fd-to-lockfile later to maint).
|
||||||
|
|
||||||
|
* Correct an age-old calco (is that a typo-like word for calc)
|
||||||
|
in the documentation.
|
||||||
|
(merge 7841c48 ls/packet-line-protocol-doc-fix later to maint).
|
||||||
|
|
||||||
|
* Other minor clean-ups and documentation updates
|
||||||
|
(merge 02a8cfa rs/merge-add-strategies-simplification later to maint).
|
||||||
|
(merge af4941d rs/merge-recursive-string-list-init later to maint).
|
||||||
|
(merge 1eb47f1 rs/use-strbuf-add-unique-abbrev later to maint).
|
||||||
|
(merge ddd0bfa jk/tighten-alloc later to maint).
|
||||||
|
(merge ecf30b2 rs/mailinfo-lib later to maint).
|
||||||
|
(merge 0eb75ce sg/reflog-past-root later to maint).
|
||||||
|
(merge 4369523 hv/doc-commit-reference-style later to maint).
|
||||||
@@ -7,7 +7,7 @@ Fixes since v2.3.9
|
|||||||
* xdiff code we use to generate diffs is not prepared to handle
|
* xdiff code we use to generate diffs is not prepared to handle
|
||||||
extremely large files. It uses "int" in many places, which can
|
extremely large files. It uses "int" in many places, which can
|
||||||
overflow if we have a very large number of lines or even bytes in
|
overflow if we have a very large number of lines or even bytes in
|
||||||
our input files, for example. Cap the input size to soemwhere
|
our input files, for example. Cap the input size to somewhere
|
||||||
around 1GB for now.
|
around 1GB for now.
|
||||||
|
|
||||||
* Some protocols (like git-remote-ext) can execute arbitrary code
|
* Some protocols (like git-remote-ext) can execute arbitrary code
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Fixes since v2.4.9
|
|||||||
* xdiff code we use to generate diffs is not prepared to handle
|
* xdiff code we use to generate diffs is not prepared to handle
|
||||||
extremely large files. It uses "int" in many places, which can
|
extremely large files. It uses "int" in many places, which can
|
||||||
overflow if we have a very large number of lines or even bytes in
|
overflow if we have a very large number of lines or even bytes in
|
||||||
our input files, for example. Cap the input size to soemwhere
|
our input files, for example. Cap the input size to somewhere
|
||||||
around 1GB for now.
|
around 1GB for now.
|
||||||
|
|
||||||
* Some protocols (like git-remote-ext) can execute arbitrary code
|
* Some protocols (like git-remote-ext) can execute arbitrary code
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Fixes since v2.5.4
|
|||||||
* xdiff code we use to generate diffs is not prepared to handle
|
* xdiff code we use to generate diffs is not prepared to handle
|
||||||
extremely large files. It uses "int" in many places, which can
|
extremely large files. It uses "int" in many places, which can
|
||||||
overflow if we have a very large number of lines or even bytes in
|
overflow if we have a very large number of lines or even bytes in
|
||||||
our input files, for example. Cap the input size to soemwhere
|
our input files, for example. Cap the input size to somewhere
|
||||||
around 1GB for now.
|
around 1GB for now.
|
||||||
|
|
||||||
* Some protocols (like git-remote-ext) can execute arbitrary code
|
* Some protocols (like git-remote-ext) can execute arbitrary code
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Fixes since v2.6
|
|||||||
* xdiff code we use to generate diffs is not prepared to handle
|
* xdiff code we use to generate diffs is not prepared to handle
|
||||||
extremely large files. It uses "int" in many places, which can
|
extremely large files. It uses "int" in many places, which can
|
||||||
overflow if we have a very large number of lines or even bytes in
|
overflow if we have a very large number of lines or even bytes in
|
||||||
our input files, for example. Cap the input size to soemwhere
|
our input files, for example. Cap the input size to somewhere
|
||||||
around 1GB for now.
|
around 1GB for now.
|
||||||
|
|
||||||
* Some protocols (like git-remote-ext) can execute arbitrary code
|
* Some protocols (like git-remote-ext) can execute arbitrary code
|
||||||
|
|||||||
@@ -150,27 +150,34 @@ integer::
|
|||||||
1024", "by 1024x1024", etc.
|
1024", "by 1024x1024", etc.
|
||||||
|
|
||||||
color::
|
color::
|
||||||
The value for a variables that takes a color is a list of
|
The value for a variable that takes a color is a list of
|
||||||
colors (at most two) and attributes (at most one), separated
|
colors (at most two, one for foreground and one for background)
|
||||||
by spaces. The colors accepted are `normal`, `black`,
|
and attributes (as many as you want), separated by spaces.
|
||||||
`red`, `green`, `yellow`, `blue`, `magenta`, `cyan` and
|
|
||||||
`white`; the attributes are `bold`, `dim`, `ul`, `blink` and
|
|
||||||
`reverse`. The first color given is the foreground; the
|
|
||||||
second is the background. The position of the attribute, if
|
|
||||||
any, doesn't matter. Attributes may be turned off specifically
|
|
||||||
by prefixing them with `no` (e.g., `noreverse`, `noul`, etc).
|
|
||||||
+
|
+
|
||||||
Colors (foreground and background) may also be given as numbers between
|
The basic colors accepted are `normal`, `black`, `red`, `green`, `yellow`,
|
||||||
0 and 255; these use ANSI 256-color mode (but note that not all
|
`blue`, `magenta`, `cyan` and `white`. The first color given is the
|
||||||
terminals may support this). If your terminal supports it, you may also
|
foreground; the second is the background.
|
||||||
specify 24-bit RGB values as hex, like `#ff0ab3`.
|
|
||||||
+
|
+
|
||||||
The attributes are meant to be reset at the beginning of each item
|
Colors may also be given as numbers between 0 and 255; these use ANSI
|
||||||
in the colored output, so setting color.decorate.branch to `black`
|
256-color mode (but note that not all terminals may support this). If
|
||||||
will paint that branch name in a plain `black`, even if the previous
|
your terminal supports it, you may also specify 24-bit RGB values as
|
||||||
thing on the same output line (e.g. opening parenthesis before the
|
hex, like `#ff0ab3`.
|
||||||
list of branch names in `log --decorate` output) is set to be
|
+
|
||||||
painted with `bold` or some other attribute.
|
The accepted attributes are `bold`, `dim`, `ul`, `blink`, `reverse`,
|
||||||
|
`italic`, and `strike` (for crossed-out or "strikethrough" letters).
|
||||||
|
The position of any attributes with respect to the colors
|
||||||
|
(before, after, or in between), doesn't matter. Specific attributes may
|
||||||
|
be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`,
|
||||||
|
`no-ul`, etc).
|
||||||
|
+
|
||||||
|
For git's pre-defined color slots, the attributes are meant to be reset
|
||||||
|
at the beginning of each item in the colored output. So setting
|
||||||
|
`color.decorate.branch` to `black` will paint that branch name in a
|
||||||
|
plain `black`, even if the previous thing on the same output line (e.g.
|
||||||
|
opening parenthesis before the list of branch names in `log --decorate`
|
||||||
|
output) is set to be painted with `bold` or some other attribute.
|
||||||
|
However, custom log formats may do more complicated and layered
|
||||||
|
coloring, and the negated forms may be useful there.
|
||||||
|
|
||||||
pathname::
|
pathname::
|
||||||
A variable that takes a pathname value can be given a
|
A variable that takes a pathname value can be given a
|
||||||
@@ -441,6 +448,13 @@ specify that no proxy be used for a given domain pattern.
|
|||||||
This is useful for excluding servers inside a firewall from
|
This is useful for excluding servers inside a firewall from
|
||||||
proxy use, while defaulting to a common proxy for external domains.
|
proxy use, while defaulting to a common proxy for external domains.
|
||||||
|
|
||||||
|
core.sshCommand::
|
||||||
|
If this variable is set, `git fetch` and `git push` will
|
||||||
|
use the specified command instead of `ssh` when they need to
|
||||||
|
connect to a remote system. The command is in the same form as
|
||||||
|
the `GIT_SSH_COMMAND` environment variable and is overridden
|
||||||
|
when the environment variable is set.
|
||||||
|
|
||||||
core.ignoreStat::
|
core.ignoreStat::
|
||||||
If true, Git will avoid using lstat() calls to detect if files have
|
If true, Git will avoid using lstat() calls to detect if files have
|
||||||
changed by setting the "assume-unchanged" bit for those tracked files
|
changed by setting the "assume-unchanged" bit for those tracked files
|
||||||
@@ -1187,6 +1201,15 @@ difftool.<tool>.cmd::
|
|||||||
difftool.prompt::
|
difftool.prompt::
|
||||||
Prompt before each invocation of the diff tool.
|
Prompt before each invocation of the diff tool.
|
||||||
|
|
||||||
|
fastimport.unpackLimit::
|
||||||
|
If the number of objects imported by linkgit:git-fast-import[1]
|
||||||
|
is below this limit, then the objects will be unpacked into
|
||||||
|
loose object files. However if the number of imported objects
|
||||||
|
equals or exceeds this limit then the pack will be stored as a
|
||||||
|
pack. Storing the pack from a fast-import can make the import
|
||||||
|
operation complete faster, especially on slow filesystems. If
|
||||||
|
not set, the value of `transfer.unpackLimit` is used instead.
|
||||||
|
|
||||||
fetch.recurseSubmodules::
|
fetch.recurseSubmodules::
|
||||||
This option can be either set to a boolean value or to 'on-demand'.
|
This option can be either set to a boolean value or to 'on-demand'.
|
||||||
Setting it to a boolean changes the behavior of fetch and pull to
|
Setting it to a boolean changes the behavior of fetch and pull to
|
||||||
@@ -1218,6 +1241,11 @@ fetch.prune::
|
|||||||
If true, fetch will automatically behave as if the `--prune`
|
If true, fetch will automatically behave as if the `--prune`
|
||||||
option was given on the command line. See also `remote.<name>.prune`.
|
option was given on the command line. See also `remote.<name>.prune`.
|
||||||
|
|
||||||
|
fetch.output::
|
||||||
|
Control how ref update status is printed. Valid values are
|
||||||
|
`full` and `compact`. Default value is `full`. See section
|
||||||
|
OUTPUT in linkgit:git-fetch[1] for detail.
|
||||||
|
|
||||||
format.attach::
|
format.attach::
|
||||||
Enable multipart/mixed attachments as the default for
|
Enable multipart/mixed attachments as the default for
|
||||||
'format-patch'. The value can also be a double quoted string
|
'format-patch'. The value can also be a double quoted string
|
||||||
@@ -1225,6 +1253,16 @@ format.attach::
|
|||||||
value as the boundary. See the --attach option in
|
value as the boundary. See the --attach option in
|
||||||
linkgit:git-format-patch[1].
|
linkgit:git-format-patch[1].
|
||||||
|
|
||||||
|
format.from::
|
||||||
|
Provides the default value for the `--from` option to format-patch.
|
||||||
|
Accepts a boolean value, or a name and email address. If false,
|
||||||
|
format-patch defaults to `--no-from`, using commit authors directly in
|
||||||
|
the "From:" field of patch mails. If true, format-patch defaults to
|
||||||
|
`--from`, using your committer identity in the "From:" field of patch
|
||||||
|
mails and including a "From:" field in the body of the patch mail if
|
||||||
|
different. If set to a non-boolean value, format-patch uses that
|
||||||
|
value instead of your committer identity. Defaults to false.
|
||||||
|
|
||||||
format.numbered::
|
format.numbered::
|
||||||
A boolean which can enable or disable sequence numbers in patch
|
A boolean which can enable or disable sequence numbers in patch
|
||||||
subjects. It defaults to "auto" which enables it only if there
|
subjects. It defaults to "auto" which enables it only if there
|
||||||
@@ -2399,8 +2437,13 @@ rebase.instructionFormat
|
|||||||
|
|
||||||
receive.advertiseAtomic::
|
receive.advertiseAtomic::
|
||||||
By default, git-receive-pack will advertise the atomic push
|
By default, git-receive-pack will advertise the atomic push
|
||||||
capability to its clients. If you don't want to this capability
|
capability to its clients. If you don't want to advertise this
|
||||||
to be advertised, set this variable to false.
|
capability, set this variable to false.
|
||||||
|
|
||||||
|
receive.advertisePushOptions::
|
||||||
|
By default, git-receive-pack will advertise the push options
|
||||||
|
capability to its clients. If you don't want to advertise this
|
||||||
|
capability, set this variable to false.
|
||||||
|
|
||||||
receive.autogc::
|
receive.autogc::
|
||||||
By default, git-receive-pack will run "git-gc --auto" after
|
By default, git-receive-pack will run "git-gc --auto" after
|
||||||
@@ -2455,6 +2498,15 @@ receive.fsck.skipList::
|
|||||||
can be safely ignored such as invalid committer email addresses.
|
can be safely ignored such as invalid committer email addresses.
|
||||||
Note: corrupt objects cannot be skipped with this setting.
|
Note: corrupt objects cannot be skipped with this setting.
|
||||||
|
|
||||||
|
receive.keepAlive::
|
||||||
|
After receiving the pack from the client, `receive-pack` may
|
||||||
|
produce no output (if `--quiet` was specified) while processing
|
||||||
|
the pack, causing some networks to drop the TCP connection.
|
||||||
|
With this option set, if `receive-pack` does not transmit
|
||||||
|
any data in this phase for `receive.keepAlive` seconds, it will
|
||||||
|
send a short keepalive packet. The default is 5 seconds; set
|
||||||
|
to 0 to disable keepalives entirely.
|
||||||
|
|
||||||
receive.unpackLimit::
|
receive.unpackLimit::
|
||||||
If the number of objects received in a push is below this
|
If the number of objects received in a push is below this
|
||||||
limit then the objects will be unpacked into loose object
|
limit then the objects will be unpacked into loose object
|
||||||
@@ -2881,6 +2933,21 @@ uploadpack.keepAlive::
|
|||||||
`uploadpack.keepAlive` seconds. Setting this option to 0
|
`uploadpack.keepAlive` seconds. Setting this option to 0
|
||||||
disables keepalive packets entirely. The default is 5 seconds.
|
disables keepalive packets entirely. The default is 5 seconds.
|
||||||
|
|
||||||
|
uploadpack.packObjectsHook::
|
||||||
|
If this option is set, when `upload-pack` would run
|
||||||
|
`git pack-objects` to create a packfile for a client, it will
|
||||||
|
run this shell command instead. The `pack-objects` command and
|
||||||
|
arguments it _would_ have run (including the `git pack-objects`
|
||||||
|
at the beginning) are appended to the shell command. The stdin
|
||||||
|
and stdout of the hook are treated as if `pack-objects` itself
|
||||||
|
was run. I.e., `upload-pack` will feed input intended for
|
||||||
|
`pack-objects` to the hook, and expects a completed packfile on
|
||||||
|
stdout.
|
||||||
|
+
|
||||||
|
Note that this configuration variable is ignored if it is seen in the
|
||||||
|
repository-level config (this is a safety measure against fetching from
|
||||||
|
untrusted repositories).
|
||||||
|
|
||||||
url.<base>.insteadOf::
|
url.<base>.insteadOf::
|
||||||
Any URL that starts with this value will be rewritten to
|
Any URL that starts with this value will be rewritten to
|
||||||
start, instead, with <base>. In cases where some site serves a
|
start, instead, with <base>. In cases where some site serves a
|
||||||
|
|||||||
@@ -116,7 +116,8 @@ default. You can use `--no-utf8` to override this.
|
|||||||
By default the command will try to detect the patch format
|
By default the command will try to detect the patch format
|
||||||
automatically. This option allows the user to bypass the automatic
|
automatically. This option allows the user to bypass the automatic
|
||||||
detection and specify the patch format that the patch(es) should be
|
detection and specify the patch format that the patch(es) should be
|
||||||
interpreted as. Valid formats are mbox, stgit, stgit-series and hg.
|
interpreted as. Valid formats are mbox, mboxrd,
|
||||||
|
stgit, stgit-series and hg.
|
||||||
|
|
||||||
-i::
|
-i::
|
||||||
--interactive::
|
--interactive::
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ Performance and Compression Tuning
|
|||||||
Maximum size of each output packfile.
|
Maximum size of each output packfile.
|
||||||
The default is unlimited.
|
The default is unlimited.
|
||||||
|
|
||||||
|
fastimport.unpackLimit::
|
||||||
|
See linkgit:git-config[1]
|
||||||
|
|
||||||
Performance
|
Performance
|
||||||
-----------
|
-----------
|
||||||
|
|||||||
@@ -99,6 +99,57 @@ The latter use of the `remote.<repository>.fetch` values can be
|
|||||||
overridden by giving the `--refmap=<refspec>` parameter(s) on the
|
overridden by giving the `--refmap=<refspec>` parameter(s) on the
|
||||||
command line.
|
command line.
|
||||||
|
|
||||||
|
OUTPUT
|
||||||
|
------
|
||||||
|
|
||||||
|
The output of "git fetch" depends on the transport method used; this
|
||||||
|
section describes the output when fetching over the Git protocol
|
||||||
|
(either locally or via ssh) and Smart HTTP protocol.
|
||||||
|
|
||||||
|
The status of the fetch is output in tabular form, with each line
|
||||||
|
representing the status of a single ref. Each line is of the form:
|
||||||
|
|
||||||
|
-------------------------------
|
||||||
|
<flag> <summary> <from> -> <to> [<reason>]
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The status of up-to-date refs is shown only if the --verbose option is
|
||||||
|
used.
|
||||||
|
|
||||||
|
In compact output mode, specified with configuration variable
|
||||||
|
fetch.output, if either entire `<from>` or `<to>` is found in the
|
||||||
|
other string, it will be substituted with `*` in the other string. For
|
||||||
|
example, `master -> origin/master` becomes `master -> origin/*`.
|
||||||
|
|
||||||
|
flag::
|
||||||
|
A single character indicating the status of the ref:
|
||||||
|
(space);; for a successfully fetched fast-forward;
|
||||||
|
`+`;; for a successful forced update;
|
||||||
|
`-`;; for a successfully pruned ref;
|
||||||
|
`t`;; for a successful tag update;
|
||||||
|
`*`;; for a successfully fetched new ref;
|
||||||
|
`!`;; for a ref that was rejected or failed to update; and
|
||||||
|
`=`;; for a ref that was up to date and did not need fetching.
|
||||||
|
|
||||||
|
summary::
|
||||||
|
For a successfully fetched ref, the summary shows the old and new
|
||||||
|
values of the ref in a form suitable for using as an argument to
|
||||||
|
`git log` (this is `<old>..<new>` in most cases, and
|
||||||
|
`<old>...<new>` for forced non-fast-forward updates).
|
||||||
|
|
||||||
|
from::
|
||||||
|
The name of the remote ref being fetched from, minus its
|
||||||
|
`refs/<type>/` prefix. In the case of deletion, the name of
|
||||||
|
the remote ref is "(none)".
|
||||||
|
|
||||||
|
to::
|
||||||
|
The name of the local ref being updated, minus its
|
||||||
|
`refs/<type>/` prefix.
|
||||||
|
|
||||||
|
reason::
|
||||||
|
A human-readable explanation. In the case of successfully fetched
|
||||||
|
refs, no explanation is needed. For a failed ref, the reason for
|
||||||
|
failure is described.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ SYNOPSIS
|
|||||||
[verse]
|
[verse]
|
||||||
'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
|
'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
|
||||||
[--[no-]full] [--strict] [--verbose] [--lost-found]
|
[--[no-]full] [--strict] [--verbose] [--lost-found]
|
||||||
[--[no-]dangling] [--[no-]progress] [--connectivity-only] [<object>*]
|
[--[no-]dangling] [--[no-]progress] [--connectivity-only]
|
||||||
|
[--[no-]name-objects] [<object>*]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@@ -82,6 +83,12 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs
|
|||||||
a blob, the contents are written into the file, rather than
|
a blob, the contents are written into the file, rather than
|
||||||
its object name.
|
its object name.
|
||||||
|
|
||||||
|
--name-objects::
|
||||||
|
When displaying names of reachable objects, in addition to the
|
||||||
|
SHA-1 also display a name that describes *how* they are reachable,
|
||||||
|
compatible with linkgit:git-rev-parse[1], e.g.
|
||||||
|
`HEAD@{1234567890}~25^2:src/`.
|
||||||
|
|
||||||
--[no-]progress::
|
--[no-]progress::
|
||||||
Progress status is reported on the standard error stream by
|
Progress status is reported on the standard error stream by
|
||||||
default when it is attached to a terminal, unless
|
default when it is attached to a terminal, unless
|
||||||
|
|||||||
@@ -198,6 +198,10 @@ log.showRoot::
|
|||||||
`git log -p` output would be shown without a diff attached.
|
`git log -p` output would be shown without a diff attached.
|
||||||
The default is `true`.
|
The default is `true`.
|
||||||
|
|
||||||
|
log.showSignature::
|
||||||
|
If `true`, `git log` and related commands will act as if the
|
||||||
|
`--show-signature` option was passed to them.
|
||||||
|
|
||||||
mailmap.*::
|
mailmap.*::
|
||||||
See linkgit:git-shortlog[1].
|
See linkgit:git-shortlog[1].
|
||||||
|
|
||||||
|
|||||||
@@ -159,8 +159,7 @@ not accessible in the working tree.
|
|||||||
+
|
+
|
||||||
<eolattr> is the attribute that is used when checking out or committing,
|
<eolattr> is the attribute that is used when checking out or committing,
|
||||||
it is either "", "-text", "text", "text=auto", "text eol=lf", "text eol=crlf".
|
it is either "", "-text", "text", "text=auto", "text eol=lf", "text eol=crlf".
|
||||||
Note: Currently Git does not support "text=auto eol=lf" or "text=auto eol=crlf",
|
Since Git 2.10 "text=auto eol=lf" and "text=auto eol=crlf" are supported.
|
||||||
that may change in the future.
|
|
||||||
+
|
+
|
||||||
Both the <eolinfo> in the index ("i/<eolinfo>")
|
Both the <eolinfo> in the index ("i/<eolinfo>")
|
||||||
and in the working tree ("w/<eolinfo>") are shown for regular files,
|
and in the working tree ("w/<eolinfo>") are shown for regular files,
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ git-mailsplit - Simple UNIX mbox splitter program
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git mailsplit' [-b] [-f<nn>] [-d<prec>] [--keep-cr] -o<directory> [--] [(<mbox>|<Maildir>)...]
|
'git mailsplit' [-b] [-f<nn>] [-d<prec>] [--keep-cr] [--mboxrd]
|
||||||
|
-o<directory> [--] [(<mbox>|<Maildir>)...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@@ -47,6 +48,10 @@ OPTIONS
|
|||||||
--keep-cr::
|
--keep-cr::
|
||||||
Do not remove `\r` from lines ending with `\r\n`.
|
Do not remove `\r` from lines ending with `\r\n`.
|
||||||
|
|
||||||
|
--mboxrd::
|
||||||
|
Input is of the "mboxrd" format and "^>+From " line escaping is
|
||||||
|
reversed.
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
Part of the linkgit:git[1] suite
|
Part of the linkgit:git[1] suite
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ SYNOPSIS
|
|||||||
[verse]
|
[verse]
|
||||||
'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
|
'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
|
||||||
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
|
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
|
||||||
[-u | --set-upstream]
|
[-u | --set-upstream] [--push-option=<string>]
|
||||||
[--[no-]signed|--sign=(true|false|if-asked)]
|
[--[no-]signed|--sign=(true|false|if-asked)]
|
||||||
[--force-with-lease[=<refname>[:<expect>]]]
|
[--force-with-lease[=<refname>[:<expect>]]]
|
||||||
[--no-verify] [<repository> [<refspec>...]]
|
[--no-verify] [<repository> [<refspec>...]]
|
||||||
@@ -156,6 +156,12 @@ already exists on the remote side.
|
|||||||
Either all refs are updated, or on error, no refs are updated.
|
Either all refs are updated, or on error, no refs are updated.
|
||||||
If the server does not support atomic pushes the push will fail.
|
If the server does not support atomic pushes the push will fail.
|
||||||
|
|
||||||
|
-o::
|
||||||
|
--push-option::
|
||||||
|
Transmit the given string to the server, which passes them to
|
||||||
|
the pre-receive as well as the post-receive hook. The given string
|
||||||
|
must not contain a NUL or LF character.
|
||||||
|
|
||||||
--receive-pack=<git-receive-pack>::
|
--receive-pack=<git-receive-pack>::
|
||||||
--exec=<git-receive-pack>::
|
--exec=<git-receive-pack>::
|
||||||
Path to the 'git-receive-pack' program on the remote
|
Path to the 'git-receive-pack' program on the remote
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ fetch, push or archive.
|
|||||||
|
|
||||||
If only <infd> is given, it is assumed to be a bidirectional socket connected
|
If only <infd> is given, it is assumed to be a bidirectional socket connected
|
||||||
to remote Git server (git-upload-pack, git-receive-pack or
|
to remote Git server (git-upload-pack, git-receive-pack or
|
||||||
git-upload-achive). If both <infd> and <outfd> are given, they are assumed
|
git-upload-archive). If both <infd> and <outfd> are given, they are assumed
|
||||||
to be pipes connected to a remote Git server (<infd> being the inbound pipe
|
to be pipes connected to a remote Git server (<infd> being the inbound pipe
|
||||||
and <outfd> being the outbound pipe.
|
and <outfd> being the outbound pipe.
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,19 @@ other objects in that pack they already have locally.
|
|||||||
with `-b` or `repack.writeBitmaps`, as it ensures that the
|
with `-b` or `repack.writeBitmaps`, as it ensures that the
|
||||||
bitmapped packfile has the necessary objects.
|
bitmapped packfile has the necessary objects.
|
||||||
|
|
||||||
|
--unpack-unreachable=<when>::
|
||||||
|
When loosening unreachable objects, do not bother loosening any
|
||||||
|
objects older than `<when>`. This can be used to optimize out
|
||||||
|
the write of any objects that would be immediately pruned by
|
||||||
|
a follow-up `git prune`.
|
||||||
|
|
||||||
|
-k::
|
||||||
|
--keep-unreachable::
|
||||||
|
When used with `-ad`, any unreachable objects from existing
|
||||||
|
packs will be appended to the end of the packfile instead of
|
||||||
|
being removed. In addition, any unreachable loose objects will
|
||||||
|
be packed (and their loose counterparts removed).
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ SYNOPSIS
|
|||||||
'git submodule' [--quiet] init [--] [<path>...]
|
'git submodule' [--quiet] init [--] [<path>...]
|
||||||
'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
|
'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
|
||||||
'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
|
'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
|
||||||
[-f|--force] [--rebase|--merge] [--reference <repository>]
|
[--[no-]recommend-shallow] [-f|--force] [--rebase|--merge]
|
||||||
[--depth <depth>] [--recursive] [--jobs <n>] [--] [<path>...]
|
[--reference <repository>] [--depth <depth>] [--recursive]
|
||||||
|
[--jobs <n>] [--] [<path>...]
|
||||||
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
|
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
|
||||||
[commit] [--] [<path>...]
|
[commit] [--] [<path>...]
|
||||||
'git submodule' [--quiet] foreach [--recursive] <command>
|
'git submodule' [--quiet] foreach [--recursive] <command>
|
||||||
@@ -384,6 +385,12 @@ for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully.
|
|||||||
clone with a history truncated to the specified number of revisions.
|
clone with a history truncated to the specified number of revisions.
|
||||||
See linkgit:git-clone[1]
|
See linkgit:git-clone[1]
|
||||||
|
|
||||||
|
--[no-]recommend-shallow::
|
||||||
|
This option is only valid for the update command.
|
||||||
|
The initial clone of a submodule will use the recommended
|
||||||
|
`submodule.<name>.shallow` as provided by the .gitmodules file
|
||||||
|
by default. To ignore the suggestions use `--no-recommend-shallow`.
|
||||||
|
|
||||||
-j <n>::
|
-j <n>::
|
||||||
--jobs <n>::
|
--jobs <n>::
|
||||||
This option is only valid for the update command.
|
This option is only valid for the update command.
|
||||||
|
|||||||
@@ -625,6 +625,9 @@ config key: svn.authorsfile
|
|||||||
with the committer name as the first argument. The program is
|
with the committer name as the first argument. The program is
|
||||||
expected to return a single line of the form "Name <email>",
|
expected to return a single line of the form "Name <email>",
|
||||||
which will be treated as if included in the authors file.
|
which will be treated as if included in the authors file.
|
||||||
|
+
|
||||||
|
[verse]
|
||||||
|
config key: svn.authorsProg
|
||||||
|
|
||||||
-q::
|
-q::
|
||||||
--quiet::
|
--quiet::
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ git-upload-pack - Send objects packed back to git-fetch-pack
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git-upload-pack' [--strict] [--timeout=<n>] <directory>
|
'git-upload-pack' [--[no-]strict] [--timeout=<n>] [--stateless-rpc]
|
||||||
|
[--advertise-refs] <directory>
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Invoked by 'git fetch-pack', learns what
|
Invoked by 'git fetch-pack', learns what
|
||||||
@@ -25,12 +25,22 @@ repository. For push operations, see 'git send-pack'.
|
|||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
--strict::
|
--[no-]strict::
|
||||||
Do not try <directory>/.git/ if <directory> is no Git directory.
|
Do not try <directory>/.git/ if <directory> is no Git directory.
|
||||||
|
|
||||||
--timeout=<n>::
|
--timeout=<n>::
|
||||||
Interrupt transfer after <n> seconds of inactivity.
|
Interrupt transfer after <n> seconds of inactivity.
|
||||||
|
|
||||||
|
--stateless-rpc::
|
||||||
|
Perform only a single read-write cycle with stdin and stdout.
|
||||||
|
This fits with the HTTP POST request processing model where
|
||||||
|
a program may read the request, write a response, and must exit.
|
||||||
|
|
||||||
|
--advertise-refs::
|
||||||
|
Only the initial ref advertisement is output, and the program exits
|
||||||
|
immediately. This fits with the HTTP GET request model, where
|
||||||
|
no request content is received but a response must be produced.
|
||||||
|
|
||||||
<directory>::
|
<directory>::
|
||||||
The repository to sync from.
|
The repository to sync from.
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ SYNOPSIS
|
|||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git worktree add' [-f] [--detach] [--checkout] [-b <new-branch>] <path> [<branch>]
|
'git worktree add' [-f] [--detach] [--checkout] [-b <new-branch>] <path> [<branch>]
|
||||||
'git worktree prune' [-n] [-v] [--expire <expire>]
|
|
||||||
'git worktree list' [--porcelain]
|
'git worktree list' [--porcelain]
|
||||||
|
'git worktree lock' [--reason <string>] <worktree>
|
||||||
|
'git worktree prune' [-n] [-v] [--expire <expire>]
|
||||||
|
'git worktree unlock' <worktree>
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@@ -38,9 +40,8 @@ section "DETAILS" for more information.
|
|||||||
|
|
||||||
If a linked working tree is stored on a portable device or network share
|
If a linked working tree is stored on a portable device or network share
|
||||||
which is not always mounted, you can prevent its administrative files from
|
which is not always mounted, you can prevent its administrative files from
|
||||||
being pruned by creating a file named 'locked' alongside the other
|
being pruned by issuing the `git worktree lock` command, optionally
|
||||||
administrative files, optionally containing a plain text reason that
|
specifying `--reason` to explain why the working tree is locked.
|
||||||
pruning should be suppressed. See section "DETAILS" for more information.
|
|
||||||
|
|
||||||
COMMANDS
|
COMMANDS
|
||||||
--------
|
--------
|
||||||
@@ -48,16 +49,13 @@ add <path> [<branch>]::
|
|||||||
|
|
||||||
Create `<path>` and checkout `<branch>` into it. The new working directory
|
Create `<path>` and checkout `<branch>` into it. The new working directory
|
||||||
is linked to the current repository, sharing everything except working
|
is linked to the current repository, sharing everything except working
|
||||||
directory specific files such as HEAD, index, etc.
|
directory specific files such as HEAD, index, etc. `-` may also be
|
||||||
|
specified as `<branch>`; it is synonymous with `@{-1}`.
|
||||||
+
|
+
|
||||||
If `<branch>` is omitted and neither `-b` nor `-B` nor `--detached` used,
|
If `<branch>` is omitted and neither `-b` nor `-B` nor `--detached` used,
|
||||||
then, as a convenience, a new branch based at HEAD is created automatically,
|
then, as a convenience, a new branch based at HEAD is created automatically,
|
||||||
as if `-b $(basename <path>)` was specified.
|
as if `-b $(basename <path>)` was specified.
|
||||||
|
|
||||||
prune::
|
|
||||||
|
|
||||||
Prune working tree information in $GIT_DIR/worktrees.
|
|
||||||
|
|
||||||
list::
|
list::
|
||||||
|
|
||||||
List details of each worktree. The main worktree is listed first, followed by
|
List details of each worktree. The main worktree is listed first, followed by
|
||||||
@@ -65,6 +63,22 @@ each of the linked worktrees. The output details include if the worktree is
|
|||||||
bare, the revision currently checked out, and the branch currently checked out
|
bare, the revision currently checked out, and the branch currently checked out
|
||||||
(or 'detached HEAD' if none).
|
(or 'detached HEAD' if none).
|
||||||
|
|
||||||
|
lock::
|
||||||
|
|
||||||
|
If a working tree is on a portable device or network share which
|
||||||
|
is not always mounted, lock it to prevent its administrative
|
||||||
|
files from being pruned automatically. This also prevents it from
|
||||||
|
being moved or deleted. Optionally, specify a reason for the lock
|
||||||
|
with `--reason`.
|
||||||
|
|
||||||
|
prune::
|
||||||
|
|
||||||
|
Prune working tree information in $GIT_DIR/worktrees.
|
||||||
|
|
||||||
|
unlock::
|
||||||
|
|
||||||
|
Unlock a working tree, allowing it to be pruned, moved or deleted.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@@ -110,6 +124,18 @@ OPTIONS
|
|||||||
--expire <time>::
|
--expire <time>::
|
||||||
With `prune`, only expire unused working trees older than <time>.
|
With `prune`, only expire unused working trees older than <time>.
|
||||||
|
|
||||||
|
--reason <string>::
|
||||||
|
With `lock`, an explanation why the working tree is locked.
|
||||||
|
|
||||||
|
<worktree>::
|
||||||
|
Working trees can be identified by path, either relative or
|
||||||
|
absolute.
|
||||||
|
+
|
||||||
|
If the last path components in the working tree's path is unique among
|
||||||
|
working trees, it can be used to identify worktrees. For example if
|
||||||
|
you only have to working trees at "/abc/def/ghi" and "/abc/def/ggg",
|
||||||
|
then "ghi" or "def/ghi" is enough to point to the former working tree.
|
||||||
|
|
||||||
DETAILS
|
DETAILS
|
||||||
-------
|
-------
|
||||||
Each linked working tree has a private sub-directory in the repository's
|
Each linked working tree has a private sub-directory in the repository's
|
||||||
@@ -150,7 +176,8 @@ instead.
|
|||||||
|
|
||||||
To prevent a $GIT_DIR/worktrees entry from being pruned (which
|
To prevent a $GIT_DIR/worktrees entry from being pruned (which
|
||||||
can be useful in some situations, such as when the
|
can be useful in some situations, such as when the
|
||||||
entry's working tree is stored on a portable device), add a file named
|
entry's working tree is stored on a portable device), use the
|
||||||
|
`git worktree lock` command, which adds a file named
|
||||||
'locked' to the entry's directory. The file contains the reason in
|
'locked' to the entry's directory. The file contains the reason in
|
||||||
plain text. For example, if a linked working tree's `.git` file points
|
plain text. For example, if a linked working tree's `.git` file points
|
||||||
to `/path/main/.git/worktrees/test-next` then a file named
|
to `/path/main/.git/worktrees/test-next` then a file named
|
||||||
@@ -226,8 +253,6 @@ performed manually, such as:
|
|||||||
- `remove` to remove a linked working tree and its administrative files (and
|
- `remove` to remove a linked working tree and its administrative files (and
|
||||||
warn if the working tree is dirty)
|
warn if the working tree is dirty)
|
||||||
- `mv` to move or rename a working tree and update its administrative files
|
- `mv` to move or rename a working tree and update its administrative files
|
||||||
- `lock` to prevent automatic pruning of administrative files (for instance,
|
|
||||||
for a working tree on a portable device)
|
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ unreleased) version of Git, that is available from the 'master'
|
|||||||
branch of the `git.git` repository.
|
branch of the `git.git` repository.
|
||||||
Documentation for older releases are available here:
|
Documentation for older releases are available here:
|
||||||
|
|
||||||
|
* link:v2.10.0/git.html[documentation for release 2.10]
|
||||||
|
|
||||||
|
* release notes for
|
||||||
|
link:RelNotes/2.10.0.txt[2.10].
|
||||||
|
|
||||||
* link:v2.9.3/git.html[documentation for release 2.9.3]
|
* link:v2.9.3/git.html[documentation for release 2.9.3]
|
||||||
|
|
||||||
* release notes for
|
* release notes for
|
||||||
@@ -1086,6 +1091,14 @@ of clones and fetches.
|
|||||||
cloning of shallow repositories.
|
cloning of shallow repositories.
|
||||||
See `GIT_TRACE` for available trace output options.
|
See `GIT_TRACE` for available trace output options.
|
||||||
|
|
||||||
|
`GIT_TRACE_CURL`::
|
||||||
|
Enables a curl full trace dump of all incoming and outgoing data,
|
||||||
|
including descriptive information, of the git transport protocol.
|
||||||
|
This is similar to doing curl `--trace-ascii` on the command line.
|
||||||
|
This option overrides setting the `GIT_CURL_VERBOSE` environment
|
||||||
|
variable.
|
||||||
|
See `GIT_TRACE` for available trace output options.
|
||||||
|
|
||||||
`GIT_LITERAL_PATHSPECS`::
|
`GIT_LITERAL_PATHSPECS`::
|
||||||
Setting this variable to `1` will cause Git to treat all
|
Setting this variable to `1` will cause Git to treat all
|
||||||
pathspecs literally, rather than as glob patterns. For example,
|
pathspecs literally, rather than as glob patterns. For example,
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ Set to string value "auto"::
|
|||||||
When `text` is set to "auto", the path is marked for automatic
|
When `text` is set to "auto", the path is marked for automatic
|
||||||
end-of-line conversion. If Git decides that the content is
|
end-of-line conversion. If Git decides that the content is
|
||||||
text, its line endings are converted to LF on checkin.
|
text, its line endings are converted to LF on checkin.
|
||||||
When the file has been commited with CRLF, no conversion is done.
|
When the file has been committed with CRLF, no conversion is done.
|
||||||
|
|
||||||
Unspecified::
|
Unspecified::
|
||||||
|
|
||||||
@@ -182,6 +182,30 @@ While Git normally leaves file contents alone, it can be configured to
|
|||||||
normalize line endings to LF in the repository and, optionally, to
|
normalize line endings to LF in the repository and, optionally, to
|
||||||
convert them to CRLF when files are checked out.
|
convert them to CRLF when files are checked out.
|
||||||
|
|
||||||
|
If you simply want to have CRLF line endings in your working directory
|
||||||
|
regardless of the repository you are working with, you can set the
|
||||||
|
config variable "core.autocrlf" without using any attributes.
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
[core]
|
||||||
|
autocrlf = true
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This does not force normalization of text files, but does ensure
|
||||||
|
that text files that you introduce to the repository have their line
|
||||||
|
endings normalized to LF when they are added, and that files that are
|
||||||
|
already normalized in the repository stay normalized.
|
||||||
|
|
||||||
|
If you want to ensure that text files that any contributor introduces to
|
||||||
|
the repository have their line endings normalized, you can set the
|
||||||
|
`text` attribute to "auto" for _all_ files.
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
* text=auto
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The attributes allow a fine-grained control, how the line endings
|
||||||
|
are converted.
|
||||||
Here is an example that will make Git normalize .txt, .vcproj and .sh
|
Here is an example that will make Git normalize .txt, .vcproj and .sh
|
||||||
files, ensure that .vcproj files have CRLF and .sh files have LF in
|
files, ensure that .vcproj files have CRLF and .sh files have LF in
|
||||||
the working directory, and prevent .jpg files from being normalized
|
the working directory, and prevent .jpg files from being normalized
|
||||||
@@ -195,48 +219,14 @@ regardless of their content.
|
|||||||
*.jpg -text
|
*.jpg -text
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Other source code management systems normalize all text files in their
|
NOTE: When `text=auto` conversion is enabled in a cross-platform
|
||||||
repositories, and there are two ways to enable similar automatic
|
project using push and pull to a central repository the text files
|
||||||
normalization in Git.
|
containing CRLFs should be normalized.
|
||||||
|
|
||||||
If you simply want to have CRLF line endings in your working directory
|
From a clean working directory:
|
||||||
regardless of the repository you are working with, you can set the
|
|
||||||
config variable "core.autocrlf" without using any attributes.
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
[core]
|
|
||||||
autocrlf = true
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
This does not force normalization of all text files, but does ensure
|
|
||||||
that text files that you introduce to the repository have their line
|
|
||||||
endings normalized to LF when they are added, and that files that are
|
|
||||||
already normalized in the repository stay normalized.
|
|
||||||
|
|
||||||
If you want to interoperate with a source code management system that
|
|
||||||
enforces end-of-line normalization, or you simply want all text files
|
|
||||||
in your repository to be normalized, you should instead set the `text`
|
|
||||||
attribute to "auto" for _all_ files.
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
* text=auto
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
This ensures that all files that Git considers to be text will have
|
|
||||||
normalized (LF) line endings in the repository. The `core.eol`
|
|
||||||
configuration variable controls which line endings Git will use for
|
|
||||||
normalized files in your working directory; the default is to use the
|
|
||||||
native line ending for your platform, or CRLF if `core.autocrlf` is
|
|
||||||
set.
|
|
||||||
|
|
||||||
NOTE: When `text=auto` normalization is enabled in an existing
|
|
||||||
repository, any text files containing CRLFs should be normalized. If
|
|
||||||
they are not they will be normalized the next time someone tries to
|
|
||||||
change them, causing unfortunate misattribution. From a clean working
|
|
||||||
directory:
|
|
||||||
|
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
$ echo "* text=auto" >>.gitattributes
|
$ echo "* text=auto" >.gitattributes
|
||||||
$ rm .git/index # Remove the index to force Git to
|
$ rm .git/index # Remove the index to force Git to
|
||||||
$ git reset # re-scan the working directory
|
$ git reset # re-scan the working directory
|
||||||
$ git status # Show files that will be normalized
|
$ git status # Show files that will be normalized
|
||||||
@@ -533,6 +523,8 @@ patterns are available:
|
|||||||
|
|
||||||
- `csharp` suitable for source code in the C# language.
|
- `csharp` suitable for source code in the C# language.
|
||||||
|
|
||||||
|
- `css` suitable for cascading style sheets.
|
||||||
|
|
||||||
- `fortran` suitable for source code in the Fortran language.
|
- `fortran` suitable for source code in the Fortran language.
|
||||||
|
|
||||||
- `fountain` suitable for Fountain documents.
|
- `fountain` suitable for Fountain documents.
|
||||||
|
|||||||
@@ -247,6 +247,15 @@ Both standard output and standard error output are forwarded to
|
|||||||
'git send-pack' on the other end, so you can simply `echo` messages
|
'git send-pack' on the other end, so you can simply `echo` messages
|
||||||
for the user.
|
for the user.
|
||||||
|
|
||||||
|
The number of push options given on the command line of
|
||||||
|
`git push --push-option=...` can be read from the environment
|
||||||
|
variable `GIT_PUSH_OPTION_COUNT`, and the options themselves are
|
||||||
|
found in `GIT_PUSH_OPTION_0`, `GIT_PUSH_OPTION_1`,...
|
||||||
|
If it is negotiated to not use the push options phase, the
|
||||||
|
environment variables will not be set. If the client selects
|
||||||
|
to use push options, but doesn't transmit any, the count variable
|
||||||
|
will be set to zero, `GIT_PUSH_OPTION_COUNT=0`.
|
||||||
|
|
||||||
[[update]]
|
[[update]]
|
||||||
update
|
update
|
||||||
~~~~~~
|
~~~~~~
|
||||||
@@ -322,6 +331,15 @@ a sample script `post-receive-email` provided in the `contrib/hooks`
|
|||||||
directory in Git distribution, which implements sending commit
|
directory in Git distribution, which implements sending commit
|
||||||
emails.
|
emails.
|
||||||
|
|
||||||
|
The number of push options given on the command line of
|
||||||
|
`git push --push-option=...` can be read from the environment
|
||||||
|
variable `GIT_PUSH_OPTION_COUNT`, and the options themselves are
|
||||||
|
found in `GIT_PUSH_OPTION_0`, `GIT_PUSH_OPTION_1`,...
|
||||||
|
If it is negotiated to not use the push options phase, the
|
||||||
|
environment variables will not be set. If the client selects
|
||||||
|
to use push options, but doesn't transmit any, the count variable
|
||||||
|
will be set to zero, `GIT_PUSH_OPTION_COUNT=0`.
|
||||||
|
|
||||||
[[post-update]]
|
[[post-update]]
|
||||||
post-update
|
post-update
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|||||||
@@ -79,6 +79,11 @@ submodule.<name>.ignore::
|
|||||||
"--ignore-submodule" option. The 'git submodule' commands are not
|
"--ignore-submodule" option. The 'git submodule' commands are not
|
||||||
affected by this setting.
|
affected by this setting.
|
||||||
|
|
||||||
|
submodule.<name>.shallow::
|
||||||
|
When set to true, a clone of this submodule will be performed as a
|
||||||
|
shallow clone unless the user explicitly asks for a non-shallow
|
||||||
|
clone.
|
||||||
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|||||||
@@ -289,6 +289,10 @@ ifdef::git-rev-list[]
|
|||||||
Try to speed up the traversal using the pack bitmap index (if
|
Try to speed up the traversal using the pack bitmap index (if
|
||||||
one is available). Note that when traversing with `--objects`,
|
one is available). Note that when traversing with `--objects`,
|
||||||
trees and blobs will not have their associated path printed.
|
trees and blobs will not have their associated path printed.
|
||||||
|
|
||||||
|
--progress=<header>::
|
||||||
|
Show progress reports on stderr as objects are considered. The
|
||||||
|
`<header>` text will be printed with each progress update.
|
||||||
endif::git-rev-list[]
|
endif::git-rev-list[]
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -454,7 +454,8 @@ The reference discovery phase is done nearly the same way as it is in the
|
|||||||
fetching protocol. Each reference obj-id and name on the server is sent
|
fetching protocol. Each reference obj-id and name on the server is sent
|
||||||
in packet-line format to the client, followed by a flush-pkt. The only
|
in packet-line format to the client, followed by a flush-pkt. The only
|
||||||
real difference is that the capability listing is different - the only
|
real difference is that the capability listing is different - the only
|
||||||
possible values are 'report-status', 'delete-refs' and 'ofs-delta'.
|
possible values are 'report-status', 'delete-refs', 'ofs-delta' and
|
||||||
|
'push-options'.
|
||||||
|
|
||||||
Reference Update Request and Packfile Transfer
|
Reference Update Request and Packfile Transfer
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
@@ -465,9 +466,10 @@ that it wants to update, it sends a line listing the obj-id currently on
|
|||||||
the server, the obj-id the client would like to update it to and the name
|
the server, the obj-id the client would like to update it to and the name
|
||||||
of the reference.
|
of the reference.
|
||||||
|
|
||||||
This list is followed by a flush-pkt and then the packfile that should
|
This list is followed by a flush-pkt. Then the push options are transmitted
|
||||||
contain all the objects that the server will need to complete the new
|
one per packet followed by another flush-pkt. After that the packfile that
|
||||||
references.
|
should contain all the objects that the server will need to complete the new
|
||||||
|
references will be sent.
|
||||||
|
|
||||||
----
|
----
|
||||||
update-request = *shallow ( command-list | push-cert ) [packfile]
|
update-request = *shallow ( command-list | push-cert ) [packfile]
|
||||||
|
|||||||
@@ -253,6 +253,15 @@ atomic pushes. If the pushing client requests this capability, the server
|
|||||||
will update the refs in one atomic transaction. Either all refs are
|
will update the refs in one atomic transaction. Either all refs are
|
||||||
updated or none.
|
updated or none.
|
||||||
|
|
||||||
|
push-options
|
||||||
|
------------
|
||||||
|
|
||||||
|
If the server sends the 'push-options' capability it is able to accept
|
||||||
|
push options after the update commands have been sent, but before the
|
||||||
|
packfile is streamed. If the pushing client requests this capability,
|
||||||
|
the server will pass the options to the pre- and post- receive hooks
|
||||||
|
that process this push request.
|
||||||
|
|
||||||
allow-tip-sha1-in-want
|
allow-tip-sha1-in-want
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
GVF=GIT-VERSION-FILE
|
GVF=GIT-VERSION-FILE
|
||||||
DEF_VER=v2.9.3
|
DEF_VER=v2.10.0
|
||||||
|
|
||||||
LF='
|
LF='
|
||||||
'
|
'
|
||||||
|
|||||||
41
Makefile
41
Makefile
@@ -351,9 +351,12 @@ all::
|
|||||||
# Define GMTIME_UNRELIABLE_ERRORS if your gmtime() function does not
|
# Define GMTIME_UNRELIABLE_ERRORS if your gmtime() function does not
|
||||||
# return NULL when it receives a bogus time_t.
|
# return NULL when it receives a bogus time_t.
|
||||||
#
|
#
|
||||||
# Define HAVE_CLOCK_GETTIME if your platform has clock_gettime in librt.
|
# Define HAVE_CLOCK_GETTIME if your platform has clock_gettime.
|
||||||
#
|
#
|
||||||
# Define HAVE_CLOCK_MONOTONIC if your platform has CLOCK_MONOTONIC in librt.
|
# Define HAVE_CLOCK_MONOTONIC if your platform has CLOCK_MONOTONIC.
|
||||||
|
#
|
||||||
|
# Define NEEDS_LIBRT if your platform requires linking with librt (glibc version
|
||||||
|
# before 2.17) for clock_gettime and CLOCK_MONOTONIC.
|
||||||
#
|
#
|
||||||
# Define USE_PARENS_AROUND_GETTEXT_N to "yes" if your compiler happily
|
# Define USE_PARENS_AROUND_GETTEXT_N to "yes" if your compiler happily
|
||||||
# compiles the following initialization:
|
# compiles the following initialization:
|
||||||
@@ -367,6 +370,14 @@ all::
|
|||||||
# Define HAVE_BSD_SYSCTL if your platform has a BSD-compatible sysctl function.
|
# Define HAVE_BSD_SYSCTL if your platform has a BSD-compatible sysctl function.
|
||||||
#
|
#
|
||||||
# Define HAVE_GETDELIM if your system has the getdelim() function.
|
# Define HAVE_GETDELIM if your system has the getdelim() function.
|
||||||
|
#
|
||||||
|
# Define PAGER_ENV to a SP separated VAR=VAL pairs to define
|
||||||
|
# default environment variables to be passed when a pager is spawned, e.g.
|
||||||
|
#
|
||||||
|
# PAGER_ENV = LESS=FRX LV=-c
|
||||||
|
#
|
||||||
|
# to say "export LESS=FRX (and LV=-c) if the environment variable
|
||||||
|
# LESS (and LV) is not set, respectively".
|
||||||
|
|
||||||
GIT-VERSION-FILE: FORCE
|
GIT-VERSION-FILE: FORCE
|
||||||
@$(SHELL_PATH) ./GIT-VERSION-GEN
|
@$(SHELL_PATH) ./GIT-VERSION-GEN
|
||||||
@@ -718,6 +729,7 @@ LIB_OBJS += diff-lib.o
|
|||||||
LIB_OBJS += diff-no-index.o
|
LIB_OBJS += diff-no-index.o
|
||||||
LIB_OBJS += diff.o
|
LIB_OBJS += diff.o
|
||||||
LIB_OBJS += dir.o
|
LIB_OBJS += dir.o
|
||||||
|
LIB_OBJS += dir-iterator.o
|
||||||
LIB_OBJS += editor.o
|
LIB_OBJS += editor.o
|
||||||
LIB_OBJS += entry.o
|
LIB_OBJS += entry.o
|
||||||
LIB_OBJS += environment.o
|
LIB_OBJS += environment.o
|
||||||
@@ -751,6 +763,7 @@ LIB_OBJS += merge.o
|
|||||||
LIB_OBJS += merge-blobs.o
|
LIB_OBJS += merge-blobs.o
|
||||||
LIB_OBJS += merge-recursive.o
|
LIB_OBJS += merge-recursive.o
|
||||||
LIB_OBJS += mergesort.o
|
LIB_OBJS += mergesort.o
|
||||||
|
LIB_OBJS += mru.o
|
||||||
LIB_OBJS += name-hash.o
|
LIB_OBJS += name-hash.o
|
||||||
LIB_OBJS += notes.o
|
LIB_OBJS += notes.o
|
||||||
LIB_OBJS += notes-cache.o
|
LIB_OBJS += notes-cache.o
|
||||||
@@ -782,6 +795,7 @@ LIB_OBJS += read-cache.o
|
|||||||
LIB_OBJS += reflog-walk.o
|
LIB_OBJS += reflog-walk.o
|
||||||
LIB_OBJS += refs.o
|
LIB_OBJS += refs.o
|
||||||
LIB_OBJS += refs/files-backend.o
|
LIB_OBJS += refs/files-backend.o
|
||||||
|
LIB_OBJS += refs/iterator.o
|
||||||
LIB_OBJS += ref-filter.o
|
LIB_OBJS += ref-filter.o
|
||||||
LIB_OBJS += remote.o
|
LIB_OBJS += remote.o
|
||||||
LIB_OBJS += replace_object.o
|
LIB_OBJS += replace_object.o
|
||||||
@@ -1465,13 +1479,16 @@ endif
|
|||||||
|
|
||||||
ifdef HAVE_CLOCK_GETTIME
|
ifdef HAVE_CLOCK_GETTIME
|
||||||
BASIC_CFLAGS += -DHAVE_CLOCK_GETTIME
|
BASIC_CFLAGS += -DHAVE_CLOCK_GETTIME
|
||||||
EXTLIBS += -lrt
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef HAVE_CLOCK_MONOTONIC
|
ifdef HAVE_CLOCK_MONOTONIC
|
||||||
BASIC_CFLAGS += -DHAVE_CLOCK_MONOTONIC
|
BASIC_CFLAGS += -DHAVE_CLOCK_MONOTONIC
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef NEEDS_LIBRT
|
||||||
|
EXTLIBS += -lrt
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef HAVE_BSD_SYSCTL
|
ifdef HAVE_BSD_SYSCTL
|
||||||
BASIC_CFLAGS += -DHAVE_BSD_SYSCTL
|
BASIC_CFLAGS += -DHAVE_BSD_SYSCTL
|
||||||
endif
|
endif
|
||||||
@@ -1492,6 +1509,10 @@ ifeq ($(PYTHON_PATH),)
|
|||||||
NO_PYTHON = NoThanks
|
NO_PYTHON = NoThanks
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifndef PAGER_ENV
|
||||||
|
PAGER_ENV = LESS=FRX LV=-c
|
||||||
|
endif
|
||||||
|
|
||||||
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
|
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
|
||||||
QUIET_SUBDIR1 =
|
QUIET_SUBDIR1 =
|
||||||
|
|
||||||
@@ -1621,6 +1642,11 @@ ifdef DEFAULT_HELP_FORMAT
|
|||||||
BASIC_CFLAGS += -DDEFAULT_HELP_FORMAT='"$(DEFAULT_HELP_FORMAT)"'
|
BASIC_CFLAGS += -DDEFAULT_HELP_FORMAT='"$(DEFAULT_HELP_FORMAT)"'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
PAGER_ENV_SQ = $(subst ','\'',$(PAGER_ENV))
|
||||||
|
PAGER_ENV_CQ = "$(subst ",\",$(subst \,\\,$(PAGER_ENV)))"
|
||||||
|
PAGER_ENV_CQ_SQ = $(subst ','\'',$(PAGER_ENV_CQ))
|
||||||
|
BASIC_CFLAGS += -DPAGER_ENV='$(PAGER_ENV_CQ_SQ)'
|
||||||
|
|
||||||
ALL_CFLAGS += $(BASIC_CFLAGS)
|
ALL_CFLAGS += $(BASIC_CFLAGS)
|
||||||
ALL_LDFLAGS += $(BASIC_LDFLAGS)
|
ALL_LDFLAGS += $(BASIC_LDFLAGS)
|
||||||
|
|
||||||
@@ -1745,7 +1771,7 @@ common-cmds.h: $(wildcard Documentation/git-*.txt)
|
|||||||
|
|
||||||
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
|
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
|
||||||
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
|
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
|
||||||
$(gitwebdir_SQ):$(PERL_PATH_SQ):$(SANE_TEXT_GREP)
|
$(gitwebdir_SQ):$(PERL_PATH_SQ):$(SANE_TEXT_GREP):$(PAGER_ENV)
|
||||||
define cmd_munge_script
|
define cmd_munge_script
|
||||||
$(RM) $@ $@+ && \
|
$(RM) $@ $@+ && \
|
||||||
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
||||||
@@ -1758,6 +1784,7 @@ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
|||||||
-e 's|@@GITWEBDIR@@|$(gitwebdir_SQ)|g' \
|
-e 's|@@GITWEBDIR@@|$(gitwebdir_SQ)|g' \
|
||||||
-e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
|
-e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
|
||||||
-e 's|@@SANE_TEXT_GREP@@|$(SANE_TEXT_GREP)|g' \
|
-e 's|@@SANE_TEXT_GREP@@|$(SANE_TEXT_GREP)|g' \
|
||||||
|
-e 's|@@PAGER_ENV@@|$(PAGER_ENV_SQ)|g' \
|
||||||
$@.sh >$@+
|
$@.sh >$@+
|
||||||
endef
|
endef
|
||||||
|
|
||||||
@@ -2072,7 +2099,10 @@ XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
|
|||||||
--keyword=gettextln --keyword=eval_gettextln
|
--keyword=gettextln --keyword=eval_gettextln
|
||||||
XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
|
XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
|
||||||
LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
|
LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
|
||||||
LOCALIZED_SH = $(SCRIPT_SH) git-parse-remote.sh
|
LOCALIZED_SH = $(SCRIPT_SH)
|
||||||
|
LOCALIZED_SH += git-parse-remote.sh
|
||||||
|
LOCALIZED_SH += git-rebase--interactive.sh
|
||||||
|
LOCALIZED_SH += git-sh-setup.sh
|
||||||
LOCALIZED_PERL = $(SCRIPT_PERL)
|
LOCALIZED_PERL = $(SCRIPT_PERL)
|
||||||
|
|
||||||
ifdef XGETTEXT_INCLUDE_TESTS
|
ifdef XGETTEXT_INCLUDE_TESTS
|
||||||
@@ -2162,6 +2192,7 @@ GIT-BUILD-OPTIONS: FORCE
|
|||||||
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
|
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
|
||||||
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
|
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
|
||||||
@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
|
@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
|
||||||
|
@echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+
|
||||||
ifdef TEST_OUTPUT_DIRECTORY
|
ifdef TEST_OUTPUT_DIRECTORY
|
||||||
@echo TEST_OUTPUT_DIRECTORY=\''$(subst ','\'',$(subst ','\'',$(TEST_OUTPUT_DIRECTORY)))'\' >>$@+
|
@echo TEST_OUTPUT_DIRECTORY=\''$(subst ','\'',$(subst ','\'',$(TEST_OUTPUT_DIRECTORY)))'\' >>$@+
|
||||||
endif
|
endif
|
||||||
|
|||||||
23
advice.c
23
advice.c
@@ -79,7 +79,20 @@ int git_default_advice_config(const char *var, const char *value)
|
|||||||
|
|
||||||
int error_resolve_conflict(const char *me)
|
int error_resolve_conflict(const char *me)
|
||||||
{
|
{
|
||||||
error("%s is not possible because you have unmerged files.", me);
|
if (!strcmp(me, "cherry-pick"))
|
||||||
|
error(_("Cherry-picking is not possible because you have unmerged files."));
|
||||||
|
else if (!strcmp(me, "commit"))
|
||||||
|
error(_("Committing is not possible because you have unmerged files."));
|
||||||
|
else if (!strcmp(me, "merge"))
|
||||||
|
error(_("Merging is not possible because you have unmerged files."));
|
||||||
|
else if (!strcmp(me, "pull"))
|
||||||
|
error(_("Pulling is not possible because you have unmerged files."));
|
||||||
|
else if (!strcmp(me, "revert"))
|
||||||
|
error(_("Reverting is not possible because you have unmerged files."));
|
||||||
|
else
|
||||||
|
error(_("It is not possible to %s because you have unmerged files."),
|
||||||
|
me);
|
||||||
|
|
||||||
if (advice_resolve_conflict)
|
if (advice_resolve_conflict)
|
||||||
/*
|
/*
|
||||||
* Message used both when 'git commit' fails and when
|
* Message used both when 'git commit' fails and when
|
||||||
@@ -93,7 +106,7 @@ int error_resolve_conflict(const char *me)
|
|||||||
void NORETURN die_resolve_conflict(const char *me)
|
void NORETURN die_resolve_conflict(const char *me)
|
||||||
{
|
{
|
||||||
error_resolve_conflict(me);
|
error_resolve_conflict(me);
|
||||||
die("Exiting because of an unresolved conflict.");
|
die(_("Exiting because of an unresolved conflict."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NORETURN die_conclude_merge(void)
|
void NORETURN die_conclude_merge(void)
|
||||||
@@ -106,14 +119,14 @@ void NORETURN die_conclude_merge(void)
|
|||||||
|
|
||||||
void detach_advice(const char *new_name)
|
void detach_advice(const char *new_name)
|
||||||
{
|
{
|
||||||
const char fmt[] =
|
const char *fmt =
|
||||||
"Note: checking out '%s'.\n\n"
|
_("Note: checking out '%s'.\n\n"
|
||||||
"You are in 'detached HEAD' state. You can look around, make experimental\n"
|
"You are in 'detached HEAD' state. You can look around, make experimental\n"
|
||||||
"changes and commit them, and you can discard any commits you make in this\n"
|
"changes and commit them, and you can discard any commits you make in this\n"
|
||||||
"state without impacting any branches by performing another checkout.\n\n"
|
"state without impacting any branches by performing another checkout.\n\n"
|
||||||
"If you want to create a new branch to retain commits you create, you may\n"
|
"If you want to create a new branch to retain commits you create, you may\n"
|
||||||
"do so (now or later) by using -b with the checkout command again. Example:\n\n"
|
"do so (now or later) by using -b with the checkout command again. Example:\n\n"
|
||||||
" git checkout -b <new-branch-name>\n\n";
|
" git checkout -b <new-branch-name>\n\n");
|
||||||
|
|
||||||
fprintf(stderr, fmt, new_name);
|
fprintf(stderr, fmt, new_name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,21 @@ static int tar_umask = 002;
|
|||||||
static int write_tar_filter_archive(const struct archiver *ar,
|
static int write_tar_filter_archive(const struct archiver *ar,
|
||||||
struct archiver_args *args);
|
struct archiver_args *args);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the max value that a ustar size header can specify, as it is fixed
|
||||||
|
* at 11 octal digits. POSIX specifies that we switch to extended headers at
|
||||||
|
* this size.
|
||||||
|
*
|
||||||
|
* Likewise for the mtime (which happens to use a buffer of the same size).
|
||||||
|
*/
|
||||||
|
#if ULONG_MAX == 0xFFFFFFFF
|
||||||
|
#define USTAR_MAX_SIZE ULONG_MAX
|
||||||
|
#define USTAR_MAX_MTIME ULONG_MAX
|
||||||
|
#else
|
||||||
|
#define USTAR_MAX_SIZE 077777777777UL
|
||||||
|
#define USTAR_MAX_MTIME 077777777777UL
|
||||||
|
#endif
|
||||||
|
|
||||||
/* writes out the whole block, but only if it is full */
|
/* writes out the whole block, but only if it is full */
|
||||||
static void write_if_needed(void)
|
static void write_if_needed(void)
|
||||||
{
|
{
|
||||||
@@ -137,6 +152,20 @@ static void strbuf_append_ext_header(struct strbuf *sb, const char *keyword,
|
|||||||
strbuf_addch(sb, '\n');
|
strbuf_addch(sb, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like strbuf_append_ext_header, but for numeric values.
|
||||||
|
*/
|
||||||
|
static void strbuf_append_ext_header_uint(struct strbuf *sb,
|
||||||
|
const char *keyword,
|
||||||
|
uintmax_t value)
|
||||||
|
{
|
||||||
|
char buf[40]; /* big enough for 2^128 in decimal, plus NUL */
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = xsnprintf(buf, sizeof(buf), "%"PRIuMAX, value);
|
||||||
|
strbuf_append_ext_header(sb, keyword, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int ustar_header_chksum(const struct ustar_header *header)
|
static unsigned int ustar_header_chksum(const struct ustar_header *header)
|
||||||
{
|
{
|
||||||
const unsigned char *p = (const unsigned char *)header;
|
const unsigned char *p = (const unsigned char *)header;
|
||||||
@@ -184,9 +213,9 @@ static void prepare_header(struct archiver_args *args,
|
|||||||
xsnprintf(header->chksum, sizeof(header->chksum), "%07o", ustar_header_chksum(header));
|
xsnprintf(header->chksum, sizeof(header->chksum), "%07o", ustar_header_chksum(header));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_extended_header(struct archiver_args *args,
|
static void write_extended_header(struct archiver_args *args,
|
||||||
const unsigned char *sha1,
|
const unsigned char *sha1,
|
||||||
const void *buffer, unsigned long size)
|
const void *buffer, unsigned long size)
|
||||||
{
|
{
|
||||||
struct ustar_header header;
|
struct ustar_header header;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
@@ -197,7 +226,6 @@ static int write_extended_header(struct archiver_args *args,
|
|||||||
prepare_header(args, &header, mode, size);
|
prepare_header(args, &header, mode, size);
|
||||||
write_blocked(&header, sizeof(header));
|
write_blocked(&header, sizeof(header));
|
||||||
write_blocked(buffer, size);
|
write_blocked(buffer, size);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_tar_entry(struct archiver_args *args,
|
static int write_tar_entry(struct archiver_args *args,
|
||||||
@@ -208,7 +236,7 @@ static int write_tar_entry(struct archiver_args *args,
|
|||||||
struct ustar_header header;
|
struct ustar_header header;
|
||||||
struct strbuf ext_header = STRBUF_INIT;
|
struct strbuf ext_header = STRBUF_INIT;
|
||||||
unsigned int old_mode = mode;
|
unsigned int old_mode = mode;
|
||||||
unsigned long size;
|
unsigned long size, size_in_header;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@@ -267,15 +295,17 @@ static int write_tar_entry(struct archiver_args *args,
|
|||||||
memcpy(header.linkname, buffer, size);
|
memcpy(header.linkname, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_header(args, &header, mode, size);
|
size_in_header = size;
|
||||||
|
if (S_ISREG(mode) && size > USTAR_MAX_SIZE) {
|
||||||
|
size_in_header = 0;
|
||||||
|
strbuf_append_ext_header_uint(&ext_header, "size", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_header(args, &header, mode, size_in_header);
|
||||||
|
|
||||||
if (ext_header.len > 0) {
|
if (ext_header.len > 0) {
|
||||||
err = write_extended_header(args, sha1, ext_header.buf,
|
write_extended_header(args, sha1, ext_header.buf,
|
||||||
ext_header.len);
|
ext_header.len);
|
||||||
if (err) {
|
|
||||||
free(buffer);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
strbuf_release(&ext_header);
|
strbuf_release(&ext_header);
|
||||||
write_blocked(&header, sizeof(header));
|
write_blocked(&header, sizeof(header));
|
||||||
@@ -289,15 +319,25 @@ static int write_tar_entry(struct archiver_args *args,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_global_extended_header(struct archiver_args *args)
|
static void write_global_extended_header(struct archiver_args *args)
|
||||||
{
|
{
|
||||||
const unsigned char *sha1 = args->commit_sha1;
|
const unsigned char *sha1 = args->commit_sha1;
|
||||||
struct strbuf ext_header = STRBUF_INIT;
|
struct strbuf ext_header = STRBUF_INIT;
|
||||||
struct ustar_header header;
|
struct ustar_header header;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
|
if (sha1)
|
||||||
|
strbuf_append_ext_header(&ext_header, "comment",
|
||||||
|
sha1_to_hex(sha1), 40);
|
||||||
|
if (args->time > USTAR_MAX_MTIME) {
|
||||||
|
strbuf_append_ext_header_uint(&ext_header, "mtime",
|
||||||
|
args->time);
|
||||||
|
args->time = USTAR_MAX_MTIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ext_header.len)
|
||||||
|
return;
|
||||||
|
|
||||||
memset(&header, 0, sizeof(header));
|
memset(&header, 0, sizeof(header));
|
||||||
*header.typeflag = TYPEFLAG_GLOBAL_HEADER;
|
*header.typeflag = TYPEFLAG_GLOBAL_HEADER;
|
||||||
mode = 0100666;
|
mode = 0100666;
|
||||||
@@ -306,7 +346,6 @@ static int write_global_extended_header(struct archiver_args *args)
|
|||||||
write_blocked(&header, sizeof(header));
|
write_blocked(&header, sizeof(header));
|
||||||
write_blocked(ext_header.buf, ext_header.len);
|
write_blocked(ext_header.buf, ext_header.len);
|
||||||
strbuf_release(&ext_header);
|
strbuf_release(&ext_header);
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct archiver **tar_filters;
|
static struct archiver **tar_filters;
|
||||||
@@ -382,10 +421,8 @@ static int write_tar_archive(const struct archiver *ar,
|
|||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (args->commit_sha1)
|
write_global_extended_header(args);
|
||||||
err = write_global_extended_header(args);
|
err = write_archive_entries(args, write_tar_entry);
|
||||||
if (!err)
|
|
||||||
err = write_archive_entries(args, write_tar_entry);
|
|
||||||
if (!err)
|
if (!err)
|
||||||
write_trailer();
|
write_trailer();
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
12
archive.c
12
archive.c
@@ -322,7 +322,7 @@ static int path_exists(struct tree *tree, const char *path)
|
|||||||
pathspec.recursive = 1;
|
pathspec.recursive = 1;
|
||||||
ret = read_tree_recursive(tree, "", 0, 0, &pathspec,
|
ret = read_tree_recursive(tree, "", 0, 0, &pathspec,
|
||||||
reject_entry, &pathspec);
|
reject_entry, &pathspec);
|
||||||
free_pathspec(&pathspec);
|
clear_pathspec(&pathspec);
|
||||||
return ret != 0;
|
return ret != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,11 +458,11 @@ static int parse_archive_args(int argc, const char **argv,
|
|||||||
argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
|
argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
|
||||||
|
|
||||||
if (remote)
|
if (remote)
|
||||||
die("Unexpected option --remote");
|
die(_("Unexpected option --remote"));
|
||||||
if (exec)
|
if (exec)
|
||||||
die("Option --exec can only be used together with --remote");
|
die(_("Option --exec can only be used together with --remote"));
|
||||||
if (output)
|
if (output)
|
||||||
die("Unexpected option --output");
|
die(_("Unexpected option --output"));
|
||||||
|
|
||||||
if (!base)
|
if (!base)
|
||||||
base = "";
|
base = "";
|
||||||
@@ -484,14 +484,14 @@ static int parse_archive_args(int argc, const char **argv,
|
|||||||
usage_with_options(archive_usage, opts);
|
usage_with_options(archive_usage, opts);
|
||||||
*ar = lookup_archiver(format);
|
*ar = lookup_archiver(format);
|
||||||
if (!*ar || (is_remote && !((*ar)->flags & ARCHIVER_REMOTE)))
|
if (!*ar || (is_remote && !((*ar)->flags & ARCHIVER_REMOTE)))
|
||||||
die("Unknown archive format '%s'", format);
|
die(_("Unknown archive format '%s'"), format);
|
||||||
|
|
||||||
args->compression_level = Z_DEFAULT_COMPRESSION;
|
args->compression_level = Z_DEFAULT_COMPRESSION;
|
||||||
if (compression_level != -1) {
|
if (compression_level != -1) {
|
||||||
if ((*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS)
|
if ((*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS)
|
||||||
args->compression_level = compression_level;
|
args->compression_level = compression_level;
|
||||||
else {
|
else {
|
||||||
die("Argument not supported for format '%s': -%d",
|
die(_("Argument not supported for format '%s': -%d"),
|
||||||
format, compression_level);
|
format, compression_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
63
bisect.c
63
bisect.c
@@ -438,12 +438,12 @@ static void read_bisect_paths(struct argv_array *array)
|
|||||||
FILE *fp = fopen(filename, "r");
|
FILE *fp = fopen(filename, "r");
|
||||||
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
die_errno("Could not open file '%s'", filename);
|
die_errno(_("Could not open file '%s'"), filename);
|
||||||
|
|
||||||
while (strbuf_getline_lf(&str, fp) != EOF) {
|
while (strbuf_getline_lf(&str, fp) != EOF) {
|
||||||
strbuf_trim(&str);
|
strbuf_trim(&str);
|
||||||
if (sq_dequote_to_argv_array(str.buf, array))
|
if (sq_dequote_to_argv_array(str.buf, array))
|
||||||
die("Badly quoted content in file '%s': %s",
|
die(_("Badly quoted content in file '%s': %s"),
|
||||||
filename, str.buf);
|
filename, str.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,10 +646,13 @@ static void exit_if_skipped_commits(struct commit_list *tried,
|
|||||||
|
|
||||||
printf("There are only 'skip'ped commits left to test.\n"
|
printf("There are only 'skip'ped commits left to test.\n"
|
||||||
"The first %s commit could be any of:\n", term_bad);
|
"The first %s commit could be any of:\n", term_bad);
|
||||||
print_commit_list(tried, "%s\n", "%s\n");
|
|
||||||
|
for ( ; tried; tried = tried->next)
|
||||||
|
printf("%s\n", oid_to_hex(&tried->item->object.oid));
|
||||||
|
|
||||||
if (bad)
|
if (bad)
|
||||||
printf("%s\n", oid_to_hex(bad));
|
printf("%s\n", oid_to_hex(bad));
|
||||||
printf("We cannot bisect more!\n");
|
printf(_("We cannot bisect more!\n"));
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,7 +705,7 @@ static struct commit *get_commit_reference(const unsigned char *sha1)
|
|||||||
{
|
{
|
||||||
struct commit *r = lookup_commit_reference(sha1);
|
struct commit *r = lookup_commit_reference(sha1);
|
||||||
if (!r)
|
if (!r)
|
||||||
die("Not a valid commit name %s", sha1_to_hex(sha1));
|
die(_("Not a valid commit name %s"), sha1_to_hex(sha1));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -726,27 +729,27 @@ static void handle_bad_merge_base(void)
|
|||||||
char *bad_hex = oid_to_hex(current_bad_oid);
|
char *bad_hex = oid_to_hex(current_bad_oid);
|
||||||
char *good_hex = join_sha1_array_hex(&good_revs, ' ');
|
char *good_hex = join_sha1_array_hex(&good_revs, ' ');
|
||||||
if (!strcmp(term_bad, "bad") && !strcmp(term_good, "good")) {
|
if (!strcmp(term_bad, "bad") && !strcmp(term_good, "good")) {
|
||||||
fprintf(stderr, "The merge base %s is bad.\n"
|
fprintf(stderr, _("The merge base %s is bad.\n"
|
||||||
"This means the bug has been fixed "
|
"This means the bug has been fixed "
|
||||||
"between %s and [%s].\n",
|
"between %s and [%s].\n"),
|
||||||
bad_hex, bad_hex, good_hex);
|
bad_hex, bad_hex, good_hex);
|
||||||
} else if (!strcmp(term_bad, "new") && !strcmp(term_good, "old")) {
|
} else if (!strcmp(term_bad, "new") && !strcmp(term_good, "old")) {
|
||||||
fprintf(stderr, "The merge base %s is new.\n"
|
fprintf(stderr, _("The merge base %s is new.\n"
|
||||||
"The property has changed "
|
"The property has changed "
|
||||||
"between %s and [%s].\n",
|
"between %s and [%s].\n"),
|
||||||
bad_hex, bad_hex, good_hex);
|
bad_hex, bad_hex, good_hex);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "The merge base %s is %s.\n"
|
fprintf(stderr, _("The merge base %s is %s.\n"
|
||||||
"This means the first '%s' commit is "
|
"This means the first '%s' commit is "
|
||||||
"between %s and [%s].\n",
|
"between %s and [%s].\n"),
|
||||||
bad_hex, term_bad, term_good, bad_hex, good_hex);
|
bad_hex, term_bad, term_good, bad_hex, good_hex);
|
||||||
}
|
}
|
||||||
exit(3);
|
exit(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Some %s revs are not ancestor of the %s rev.\n"
|
fprintf(stderr, _("Some %s revs are not ancestor of the %s rev.\n"
|
||||||
"git bisect cannot work properly in this case.\n"
|
"git bisect cannot work properly in this case.\n"
|
||||||
"Maybe you mistook %s and %s revs?\n",
|
"Maybe you mistook %s and %s revs?\n"),
|
||||||
term_good, term_bad, term_good, term_bad);
|
term_good, term_bad, term_good, term_bad);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -754,14 +757,14 @@ static void handle_bad_merge_base(void)
|
|||||||
static void handle_skipped_merge_base(const unsigned char *mb)
|
static void handle_skipped_merge_base(const unsigned char *mb)
|
||||||
{
|
{
|
||||||
char *mb_hex = sha1_to_hex(mb);
|
char *mb_hex = sha1_to_hex(mb);
|
||||||
char *bad_hex = sha1_to_hex(current_bad_oid->hash);
|
char *bad_hex = oid_to_hex(current_bad_oid);
|
||||||
char *good_hex = join_sha1_array_hex(&good_revs, ' ');
|
char *good_hex = join_sha1_array_hex(&good_revs, ' ');
|
||||||
|
|
||||||
warning("the merge base between %s and [%s] "
|
warning(_("the merge base between %s and [%s] "
|
||||||
"must be skipped.\n"
|
"must be skipped.\n"
|
||||||
"So we cannot be sure the first %s commit is "
|
"So we cannot be sure the first %s commit is "
|
||||||
"between %s and %s.\n"
|
"between %s and %s.\n"
|
||||||
"We continue anyway.",
|
"We continue anyway."),
|
||||||
bad_hex, good_hex, term_bad, mb_hex, bad_hex);
|
bad_hex, good_hex, term_bad, mb_hex, bad_hex);
|
||||||
free(good_hex);
|
free(good_hex);
|
||||||
}
|
}
|
||||||
@@ -792,7 +795,7 @@ static void check_merge_bases(int no_checkout)
|
|||||||
} else if (0 <= sha1_array_lookup(&skipped_revs, mb)) {
|
} else if (0 <= sha1_array_lookup(&skipped_revs, mb)) {
|
||||||
handle_skipped_merge_base(mb);
|
handle_skipped_merge_base(mb);
|
||||||
} else {
|
} else {
|
||||||
printf("Bisecting: a merge base must be tested\n");
|
printf(_("Bisecting: a merge base must be tested\n"));
|
||||||
exit(bisect_checkout(mb, no_checkout));
|
exit(bisect_checkout(mb, no_checkout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -843,7 +846,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (!current_bad_oid)
|
if (!current_bad_oid)
|
||||||
die("a %s revision is needed", term_bad);
|
die(_("a %s revision is needed"), term_bad);
|
||||||
|
|
||||||
/* Check if file BISECT_ANCESTORS_OK exists. */
|
/* Check if file BISECT_ANCESTORS_OK exists. */
|
||||||
if (!stat(filename, &st) && S_ISREG(st.st_mode))
|
if (!stat(filename, &st) && S_ISREG(st.st_mode))
|
||||||
@@ -860,7 +863,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
|
|||||||
/* Create file BISECT_ANCESTORS_OK. */
|
/* Create file BISECT_ANCESTORS_OK. */
|
||||||
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
warning_errno("could not create file '%s'",
|
warning_errno(_("could not create file '%s'"),
|
||||||
filename);
|
filename);
|
||||||
else
|
else
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -911,7 +914,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good)
|
|||||||
*read_good = "good";
|
*read_good = "good";
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
die_errno("could not read file '%s'", filename);
|
die_errno(_("could not read file '%s'"), filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strbuf_getline_lf(&str, fp);
|
strbuf_getline_lf(&str, fp);
|
||||||
@@ -937,10 +940,11 @@ int bisect_next_all(const char *prefix, int no_checkout)
|
|||||||
struct commit_list *tried;
|
struct commit_list *tried;
|
||||||
int reaches = 0, all = 0, nr, steps;
|
int reaches = 0, all = 0, nr, steps;
|
||||||
const unsigned char *bisect_rev;
|
const unsigned char *bisect_rev;
|
||||||
|
char steps_msg[32];
|
||||||
|
|
||||||
read_bisect_terms(&term_bad, &term_good);
|
read_bisect_terms(&term_bad, &term_good);
|
||||||
if (read_bisect_refs())
|
if (read_bisect_refs())
|
||||||
die("reading bisect refs failed");
|
die(_("reading bisect refs failed"));
|
||||||
|
|
||||||
check_good_are_ancestors_of_bad(prefix, no_checkout);
|
check_good_are_ancestors_of_bad(prefix, no_checkout);
|
||||||
|
|
||||||
@@ -960,7 +964,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
|
|||||||
*/
|
*/
|
||||||
exit_if_skipped_commits(tried, NULL);
|
exit_if_skipped_commits(tried, NULL);
|
||||||
|
|
||||||
printf("%s was both %s and %s\n",
|
printf(_("%s was both %s and %s\n"),
|
||||||
oid_to_hex(current_bad_oid),
|
oid_to_hex(current_bad_oid),
|
||||||
term_good,
|
term_good,
|
||||||
term_bad);
|
term_bad);
|
||||||
@@ -968,8 +972,8 @@ int bisect_next_all(const char *prefix, int no_checkout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!all) {
|
if (!all) {
|
||||||
fprintf(stderr, "No testable commit found.\n"
|
fprintf(stderr, _("No testable commit found.\n"
|
||||||
"Maybe you started with bad path parameters?\n");
|
"Maybe you started with bad path parameters?\n"));
|
||||||
exit(4);
|
exit(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,9 +990,14 @@ int bisect_next_all(const char *prefix, int no_checkout)
|
|||||||
|
|
||||||
nr = all - reaches - 1;
|
nr = all - reaches - 1;
|
||||||
steps = estimate_bisect_steps(all);
|
steps = estimate_bisect_steps(all);
|
||||||
printf("Bisecting: %d revision%s left to test after this "
|
xsnprintf(steps_msg, sizeof(steps_msg),
|
||||||
"(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
|
Q_("(roughly %d step)", "(roughly %d steps)", steps),
|
||||||
steps, (steps == 1 ? "" : "s"));
|
steps);
|
||||||
|
/* TRANSLATORS: the last %s will be replaced with
|
||||||
|
"(roughly %d steps)" translation */
|
||||||
|
printf(Q_("Bisecting: %d revision left to test after this %s\n",
|
||||||
|
"Bisecting: %d revisions left to test after this %s\n",
|
||||||
|
nr), nr, steps_msg);
|
||||||
|
|
||||||
return bisect_checkout(bisect_rev, no_checkout);
|
return bisect_checkout(bisect_rev, no_checkout);
|
||||||
}
|
}
|
||||||
|
|||||||
105
builtin/am.c
105
builtin/am.c
@@ -70,7 +70,8 @@ enum patch_format {
|
|||||||
PATCH_FORMAT_MBOX,
|
PATCH_FORMAT_MBOX,
|
||||||
PATCH_FORMAT_STGIT,
|
PATCH_FORMAT_STGIT,
|
||||||
PATCH_FORMAT_STGIT_SERIES,
|
PATCH_FORMAT_STGIT_SERIES,
|
||||||
PATCH_FORMAT_HG
|
PATCH_FORMAT_HG,
|
||||||
|
PATCH_FORMAT_MBOXRD
|
||||||
};
|
};
|
||||||
|
|
||||||
enum keep_type {
|
enum keep_type {
|
||||||
@@ -183,22 +184,22 @@ static inline const char *am_path(const struct am_state *state, const char *path
|
|||||||
/**
|
/**
|
||||||
* For convenience to call write_file()
|
* For convenience to call write_file()
|
||||||
*/
|
*/
|
||||||
static int write_state_text(const struct am_state *state,
|
static void write_state_text(const struct am_state *state,
|
||||||
const char *name, const char *string)
|
const char *name, const char *string)
|
||||||
{
|
{
|
||||||
return write_file(am_path(state, name), "%s", string);
|
write_file(am_path(state, name), "%s", string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_state_count(const struct am_state *state,
|
static void write_state_count(const struct am_state *state,
|
||||||
|
const char *name, int value)
|
||||||
|
{
|
||||||
|
write_file(am_path(state, name), "%d", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_state_bool(const struct am_state *state,
|
||||||
const char *name, int value)
|
const char *name, int value)
|
||||||
{
|
{
|
||||||
return write_file(am_path(state, name), "%d", value);
|
write_state_text(state, name, value ? "t" : "f");
|
||||||
}
|
|
||||||
|
|
||||||
static int write_state_bool(const struct am_state *state,
|
|
||||||
const char *name, int value)
|
|
||||||
{
|
|
||||||
return write_state_text(state, name, value ? "t" : "f");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,13 +403,8 @@ static int read_commit_msg(struct am_state *state)
|
|||||||
*/
|
*/
|
||||||
static void write_commit_msg(const struct am_state *state)
|
static void write_commit_msg(const struct am_state *state)
|
||||||
{
|
{
|
||||||
int fd;
|
|
||||||
const char *filename = am_path(state, "final-commit");
|
const char *filename = am_path(state, "final-commit");
|
||||||
|
write_file_buf(filename, state->msg, state->msg_len);
|
||||||
fd = xopen(filename, O_WRONLY | O_CREAT, 0666);
|
|
||||||
if (write_in_full(fd, state->msg, state->msg_len) < 0)
|
|
||||||
die_errno(_("could not write to %s"), filename);
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -712,7 +708,8 @@ done:
|
|||||||
* Splits out individual email patches from `paths`, where each path is either
|
* Splits out individual email patches from `paths`, where each path is either
|
||||||
* a mbox file or a Maildir. Returns 0 on success, -1 on failure.
|
* a mbox file or a Maildir. Returns 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
static int split_mail_mbox(struct am_state *state, const char **paths, int keep_cr)
|
static int split_mail_mbox(struct am_state *state, const char **paths,
|
||||||
|
int keep_cr, int mboxrd)
|
||||||
{
|
{
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
struct strbuf last = STRBUF_INIT;
|
struct strbuf last = STRBUF_INIT;
|
||||||
@@ -724,6 +721,8 @@ static int split_mail_mbox(struct am_state *state, const char **paths, int keep_
|
|||||||
argv_array_push(&cp.args, "-b");
|
argv_array_push(&cp.args, "-b");
|
||||||
if (keep_cr)
|
if (keep_cr)
|
||||||
argv_array_push(&cp.args, "--keep-cr");
|
argv_array_push(&cp.args, "--keep-cr");
|
||||||
|
if (mboxrd)
|
||||||
|
argv_array_push(&cp.args, "--mboxrd");
|
||||||
argv_array_push(&cp.args, "--");
|
argv_array_push(&cp.args, "--");
|
||||||
argv_array_pushv(&cp.args, paths);
|
argv_array_pushv(&cp.args, paths);
|
||||||
|
|
||||||
@@ -965,13 +964,15 @@ static int split_mail(struct am_state *state, enum patch_format patch_format,
|
|||||||
|
|
||||||
switch (patch_format) {
|
switch (patch_format) {
|
||||||
case PATCH_FORMAT_MBOX:
|
case PATCH_FORMAT_MBOX:
|
||||||
return split_mail_mbox(state, paths, keep_cr);
|
return split_mail_mbox(state, paths, keep_cr, 0);
|
||||||
case PATCH_FORMAT_STGIT:
|
case PATCH_FORMAT_STGIT:
|
||||||
return split_mail_conv(stgit_patch_to_mail, state, paths, keep_cr);
|
return split_mail_conv(stgit_patch_to_mail, state, paths, keep_cr);
|
||||||
case PATCH_FORMAT_STGIT_SERIES:
|
case PATCH_FORMAT_STGIT_SERIES:
|
||||||
return split_mail_stgit_series(state, paths, keep_cr);
|
return split_mail_stgit_series(state, paths, keep_cr);
|
||||||
case PATCH_FORMAT_HG:
|
case PATCH_FORMAT_HG:
|
||||||
return split_mail_conv(hg_patch_to_mail, state, paths, keep_cr);
|
return split_mail_conv(hg_patch_to_mail, state, paths, keep_cr);
|
||||||
|
case PATCH_FORMAT_MBOXRD:
|
||||||
|
return split_mail_mbox(state, paths, keep_cr, 1);
|
||||||
default:
|
default:
|
||||||
die("BUG: invalid patch_format");
|
die("BUG: invalid patch_format");
|
||||||
}
|
}
|
||||||
@@ -1577,48 +1578,19 @@ static int build_fake_ancestor(const struct am_state *state, const char *index_f
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Do the three-way merge using fake ancestor, their tree constructed
|
|
||||||
* from the fake ancestor and the postimage of the patch, and our
|
|
||||||
* state.
|
|
||||||
*/
|
|
||||||
static int run_fallback_merge_recursive(const struct am_state *state,
|
|
||||||
unsigned char *orig_tree,
|
|
||||||
unsigned char *our_tree,
|
|
||||||
unsigned char *their_tree)
|
|
||||||
{
|
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
cp.git_cmd = 1;
|
|
||||||
|
|
||||||
argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s",
|
|
||||||
sha1_to_hex(their_tree), linelen(state->msg), state->msg);
|
|
||||||
if (state->quiet)
|
|
||||||
argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0");
|
|
||||||
|
|
||||||
argv_array_push(&cp.args, "merge-recursive");
|
|
||||||
argv_array_push(&cp.args, sha1_to_hex(orig_tree));
|
|
||||||
argv_array_push(&cp.args, "--");
|
|
||||||
argv_array_push(&cp.args, sha1_to_hex(our_tree));
|
|
||||||
argv_array_push(&cp.args, sha1_to_hex(their_tree));
|
|
||||||
|
|
||||||
status = run_command(&cp) ? (-1) : 0;
|
|
||||||
discard_cache();
|
|
||||||
read_cache();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt a threeway merge, using index_path as the temporary index.
|
* Attempt a threeway merge, using index_path as the temporary index.
|
||||||
*/
|
*/
|
||||||
static int fall_back_threeway(const struct am_state *state, const char *index_path)
|
static int fall_back_threeway(const struct am_state *state, const char *index_path)
|
||||||
{
|
{
|
||||||
unsigned char orig_tree[GIT_SHA1_RAWSZ], their_tree[GIT_SHA1_RAWSZ],
|
struct object_id orig_tree, their_tree, our_tree;
|
||||||
our_tree[GIT_SHA1_RAWSZ];
|
const struct object_id *bases[1] = { &orig_tree };
|
||||||
|
struct merge_options o;
|
||||||
|
struct commit *result;
|
||||||
|
char *their_tree_name;
|
||||||
|
|
||||||
if (get_sha1("HEAD", our_tree) < 0)
|
if (get_oid("HEAD", &our_tree) < 0)
|
||||||
hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);
|
hashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN);
|
||||||
|
|
||||||
if (build_fake_ancestor(state, index_path))
|
if (build_fake_ancestor(state, index_path))
|
||||||
return error("could not build fake ancestor");
|
return error("could not build fake ancestor");
|
||||||
@@ -1626,7 +1598,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
|||||||
discard_cache();
|
discard_cache();
|
||||||
read_cache_from(index_path);
|
read_cache_from(index_path);
|
||||||
|
|
||||||
if (write_index_as_tree(orig_tree, &the_index, index_path, 0, NULL))
|
if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL))
|
||||||
return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
|
return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
|
||||||
|
|
||||||
say(state, stdout, _("Using index info to reconstruct a base tree..."));
|
say(state, stdout, _("Using index info to reconstruct a base tree..."));
|
||||||
@@ -1642,7 +1614,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
|||||||
init_revisions(&rev_info, NULL);
|
init_revisions(&rev_info, NULL);
|
||||||
rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
|
rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
|
||||||
diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
|
diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
|
||||||
add_pending_sha1(&rev_info, "HEAD", our_tree, 0);
|
add_pending_sha1(&rev_info, "HEAD", our_tree.hash, 0);
|
||||||
diff_setup_done(&rev_info.diffopt);
|
diff_setup_done(&rev_info.diffopt);
|
||||||
run_diff_index(&rev_info, 1);
|
run_diff_index(&rev_info, 1);
|
||||||
}
|
}
|
||||||
@@ -1651,7 +1623,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
|||||||
return error(_("Did you hand edit your patch?\n"
|
return error(_("Did you hand edit your patch?\n"
|
||||||
"It does not apply to blobs recorded in its index."));
|
"It does not apply to blobs recorded in its index."));
|
||||||
|
|
||||||
if (write_index_as_tree(their_tree, &the_index, index_path, 0, NULL))
|
if (write_index_as_tree(their_tree.hash, &the_index, index_path, 0, NULL))
|
||||||
return error("could not write tree");
|
return error("could not write tree");
|
||||||
|
|
||||||
say(state, stdout, _("Falling back to patching base and 3-way merge..."));
|
say(state, stdout, _("Falling back to patching base and 3-way merge..."));
|
||||||
@@ -1667,11 +1639,22 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
|||||||
* changes.
|
* changes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (run_fallback_merge_recursive(state, orig_tree, our_tree, their_tree)) {
|
init_merge_options(&o);
|
||||||
|
|
||||||
|
o.branch1 = "HEAD";
|
||||||
|
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
|
||||||
|
o.branch2 = their_tree_name;
|
||||||
|
|
||||||
|
if (state->quiet)
|
||||||
|
o.verbosity = 0;
|
||||||
|
|
||||||
|
if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) {
|
||||||
rerere(state->allow_rerere_autoupdate);
|
rerere(state->allow_rerere_autoupdate);
|
||||||
|
free(their_tree_name);
|
||||||
return error(_("Failed to merge in the changes."));
|
return error(_("Failed to merge in the changes."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(their_tree_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2203,6 +2186,8 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
|
|||||||
*opt_value = PATCH_FORMAT_STGIT_SERIES;
|
*opt_value = PATCH_FORMAT_STGIT_SERIES;
|
||||||
else if (!strcmp(arg, "hg"))
|
else if (!strcmp(arg, "hg"))
|
||||||
*opt_value = PATCH_FORMAT_HG;
|
*opt_value = PATCH_FORMAT_HG;
|
||||||
|
else if (!strcmp(arg, "mboxrd"))
|
||||||
|
*opt_value = PATCH_FORMAT_MBOXRD;
|
||||||
else
|
else
|
||||||
return error(_("Invalid value for --patch-format: %s"), arg);
|
return error(_("Invalid value for --patch-format: %s"), arg);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
1484
builtin/apply.c
1484
builtin/apply.c
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,7 @@ static int show_progress;
|
|||||||
static struct date_mode blame_date_mode = { DATE_ISO8601 };
|
static struct date_mode blame_date_mode = { DATE_ISO8601 };
|
||||||
static size_t blame_date_width;
|
static size_t blame_date_width;
|
||||||
|
|
||||||
static struct string_list mailmap;
|
static struct string_list mailmap = STRING_LIST_INIT_NODUP;
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
@@ -598,7 +598,7 @@ static struct origin *find_origin(struct scoreboard *sb,
|
|||||||
p->status);
|
p->status);
|
||||||
case 'M':
|
case 'M':
|
||||||
porigin = get_origin(sb, parent, origin->path);
|
porigin = get_origin(sb, parent, origin->path);
|
||||||
hashcpy(porigin->blob_sha1, p->one->sha1);
|
hashcpy(porigin->blob_sha1, p->one->oid.hash);
|
||||||
porigin->mode = p->one->mode;
|
porigin->mode = p->one->mode;
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
@@ -608,7 +608,7 @@ static struct origin *find_origin(struct scoreboard *sb,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff_flush(&diff_opts);
|
diff_flush(&diff_opts);
|
||||||
free_pathspec(&diff_opts.pathspec);
|
clear_pathspec(&diff_opts.pathspec);
|
||||||
return porigin;
|
return porigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,13 +644,13 @@ static struct origin *find_rename(struct scoreboard *sb,
|
|||||||
if ((p->status == 'R' || p->status == 'C') &&
|
if ((p->status == 'R' || p->status == 'C') &&
|
||||||
!strcmp(p->two->path, origin->path)) {
|
!strcmp(p->two->path, origin->path)) {
|
||||||
porigin = get_origin(sb, parent, p->one->path);
|
porigin = get_origin(sb, parent, p->one->path);
|
||||||
hashcpy(porigin->blob_sha1, p->one->sha1);
|
hashcpy(porigin->blob_sha1, p->one->oid.hash);
|
||||||
porigin->mode = p->one->mode;
|
porigin->mode = p->one->mode;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff_flush(&diff_opts);
|
diff_flush(&diff_opts);
|
||||||
free_pathspec(&diff_opts.pathspec);
|
clear_pathspec(&diff_opts.pathspec);
|
||||||
return porigin;
|
return porigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1308,7 +1308,7 @@ static void find_copy_in_parent(struct scoreboard *sb,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
norigin = get_origin(sb, parent, p->one->path);
|
norigin = get_origin(sb, parent, p->one->path);
|
||||||
hashcpy(norigin->blob_sha1, p->one->sha1);
|
hashcpy(norigin->blob_sha1, p->one->oid.hash);
|
||||||
norigin->mode = p->one->mode;
|
norigin->mode = p->one->mode;
|
||||||
fill_origin_blob(&sb->revs->diffopt, norigin, &file_p);
|
fill_origin_blob(&sb->revs->diffopt, norigin, &file_p);
|
||||||
if (!file_p.ptr)
|
if (!file_p.ptr)
|
||||||
@@ -1342,7 +1342,7 @@ static void find_copy_in_parent(struct scoreboard *sb,
|
|||||||
} while (unblamed);
|
} while (unblamed);
|
||||||
target->suspects = reverse_blame(leftover, NULL);
|
target->suspects = reverse_blame(leftover, NULL);
|
||||||
diff_flush(&diff_opts);
|
diff_flush(&diff_opts);
|
||||||
free_pathspec(&diff_opts.pathspec);
|
clear_pathspec(&diff_opts.pathspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2244,7 +2244,8 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path)
|
|||||||
pos = cache_name_pos(path, strlen(path));
|
pos = cache_name_pos(path, strlen(path));
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
; /* path is in the index */
|
; /* path is in the index */
|
||||||
else if (!strcmp(active_cache[-1 - pos]->name, path))
|
else if (-1 - pos < active_nr &&
|
||||||
|
!strcmp(active_cache[-1 - pos]->name, path))
|
||||||
; /* path is in the index, unmerged */
|
; /* path is in the index, unmerged */
|
||||||
else
|
else
|
||||||
die("no such path '%s' in HEAD", path);
|
die("no such path '%s' in HEAD", path);
|
||||||
@@ -2527,12 +2528,12 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
|||||||
enum object_type type;
|
enum object_type type;
|
||||||
struct commit *final_commit = NULL;
|
struct commit *final_commit = NULL;
|
||||||
|
|
||||||
static struct string_list range_list;
|
struct string_list range_list = STRING_LIST_INIT_NODUP;
|
||||||
static int output_option = 0, opt = 0;
|
int output_option = 0, opt = 0;
|
||||||
static int show_stats = 0;
|
int show_stats = 0;
|
||||||
static const char *revs_file = NULL;
|
const char *revs_file = NULL;
|
||||||
static const char *contents_from = NULL;
|
const char *contents_from = NULL;
|
||||||
static const struct option options[] = {
|
const struct option options[] = {
|
||||||
OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
|
OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
|
||||||
OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
|
OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
|
||||||
OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
|
OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
|
||||||
@@ -2808,7 +2809,7 @@ parse_done:
|
|||||||
lno = prepare_lines(&sb);
|
lno = prepare_lines(&sb);
|
||||||
|
|
||||||
if (lno && !range_list.nr)
|
if (lno && !range_list.nr)
|
||||||
string_list_append(&range_list, xstrdup("1"));
|
string_list_append(&range_list, "1");
|
||||||
|
|
||||||
anchor = 1;
|
anchor = 1;
|
||||||
range_set_init(&ranges, range_list.nr);
|
range_set_init(&ranges, range_list.nr);
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
|||||||
die(_("Couldn't look up commit object for HEAD"));
|
die(_("Couldn't look up commit object for HEAD"));
|
||||||
}
|
}
|
||||||
for (i = 0; i < argc; i++, strbuf_release(&bname)) {
|
for (i = 0; i < argc; i++, strbuf_release(&bname)) {
|
||||||
const char *target;
|
char *target = NULL;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
strbuf_branchname(&bname, argv[i]);
|
strbuf_branchname(&bname, argv[i]);
|
||||||
@@ -231,11 +231,11 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target = resolve_ref_unsafe(name,
|
target = resolve_refdup(name,
|
||||||
RESOLVE_REF_READING
|
RESOLVE_REF_READING
|
||||||
| RESOLVE_REF_NO_RECURSE
|
| RESOLVE_REF_NO_RECURSE
|
||||||
| RESOLVE_REF_ALLOW_BAD_NAME,
|
| RESOLVE_REF_ALLOW_BAD_NAME,
|
||||||
sha1, &flags);
|
sha1, &flags);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
error(remote_branch
|
error(remote_branch
|
||||||
? _("remote-tracking branch '%s' not found.")
|
? _("remote-tracking branch '%s' not found.")
|
||||||
@@ -248,7 +248,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
|||||||
check_branch_commit(bname.buf, name, sha1, head_rev, kinds,
|
check_branch_commit(bname.buf, name, sha1, head_rev, kinds,
|
||||||
force)) {
|
force)) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
continue;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delete_ref(name, is_null_sha1(sha1) ? NULL : sha1,
|
if (delete_ref(name, is_null_sha1(sha1) ? NULL : sha1,
|
||||||
@@ -258,7 +258,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
|||||||
: _("Error deleting branch '%s'"),
|
: _("Error deleting branch '%s'"),
|
||||||
bname.buf);
|
bname.buf);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
continue;
|
goto next;
|
||||||
}
|
}
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
printf(remote_branch
|
printf(remote_branch
|
||||||
@@ -270,6 +270,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
|||||||
: find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
: find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||||
}
|
}
|
||||||
delete_branch_config(bname.buf);
|
delete_branch_config(bname.buf);
|
||||||
|
|
||||||
|
next:
|
||||||
|
free(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
@@ -614,14 +617,11 @@ static int edit_branch_description(const char *branch_name)
|
|||||||
if (!buf.len || buf.buf[buf.len-1] != '\n')
|
if (!buf.len || buf.buf[buf.len-1] != '\n')
|
||||||
strbuf_addch(&buf, '\n');
|
strbuf_addch(&buf, '\n');
|
||||||
strbuf_commented_addf(&buf,
|
strbuf_commented_addf(&buf,
|
||||||
"Please edit the description for the branch\n"
|
_("Please edit the description for the branch\n"
|
||||||
" %s\n"
|
" %s\n"
|
||||||
"Lines starting with '%c' will be stripped.\n",
|
"Lines starting with '%c' will be stripped.\n"),
|
||||||
branch_name, comment_line_char);
|
branch_name, comment_line_char);
|
||||||
if (write_file_gently(git_path(edit_description), "%s", buf.buf)) {
|
write_file_buf(git_path(edit_description), buf.buf, buf.len);
|
||||||
strbuf_release(&buf);
|
|
||||||
return error_errno(_("could not write branch description template"));
|
|
||||||
}
|
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
if (launch_editor(git_path(edit_description), &buf, NULL)) {
|
if (launch_editor(git_path(edit_description), &buf, NULL)) {
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ static int checkout_paths(const struct checkout_opts *opts,
|
|||||||
|
|
||||||
hold_locked_index(lock_file, 1);
|
hold_locked_index(lock_file, 1);
|
||||||
if (read_cache_preload(&opts->pathspec) < 0)
|
if (read_cache_preload(&opts->pathspec) < 0)
|
||||||
return error(_("corrupt index file"));
|
return error(_("index file corrupt"));
|
||||||
|
|
||||||
if (opts->source_tree)
|
if (opts->source_tree)
|
||||||
read_tree_some(opts->source_tree, &opts->pathspec);
|
read_tree_some(opts->source_tree, &opts->pathspec);
|
||||||
@@ -470,7 +470,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||||||
|
|
||||||
hold_locked_index(lock_file, 1);
|
hold_locked_index(lock_file, 1);
|
||||||
if (read_cache_preload(NULL) < 0)
|
if (read_cache_preload(NULL) < 0)
|
||||||
return error(_("corrupt index file"));
|
return error(_("index file corrupt"));
|
||||||
|
|
||||||
resolve_undo_clear();
|
resolve_undo_clear();
|
||||||
if (opts->force) {
|
if (opts->force) {
|
||||||
@@ -567,10 +567,13 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||||||
o.ancestor = old->name;
|
o.ancestor = old->name;
|
||||||
o.branch1 = new->name;
|
o.branch1 = new->name;
|
||||||
o.branch2 = "local";
|
o.branch2 = "local";
|
||||||
merge_trees(&o, new->commit->tree, work,
|
ret = merge_trees(&o, new->commit->tree, work,
|
||||||
old->commit->tree, &result);
|
old->commit->tree, &result);
|
||||||
|
if (ret < 0)
|
||||||
|
exit(128);
|
||||||
ret = reset_tree(new->commit->tree, opts, 0,
|
ret = reset_tree(new->commit->tree, opts, 0,
|
||||||
writeout_error);
|
writeout_error);
|
||||||
|
strbuf_release(&o.obuf);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1138,7 +1141,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||||||
OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
|
OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
|
||||||
N_("create/reset and checkout a branch")),
|
N_("create/reset and checkout a branch")),
|
||||||
OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
|
OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
|
||||||
OPT_BOOL(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
|
OPT_BOOL(0, "detach", &opts.force_detach, N_("detach HEAD at named commit")),
|
||||||
OPT_SET_INT('t', "track", &opts.track, N_("set upstream info for new branch"),
|
OPT_SET_INT('t', "track", &opts.track, N_("set upstream info for new branch"),
|
||||||
BRANCH_TRACK_EXPLICIT),
|
BRANCH_TRACK_EXPLICIT),
|
||||||
OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
|
OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ static char *option_upload_pack = "git-upload-pack";
|
|||||||
static int option_verbosity;
|
static int option_verbosity;
|
||||||
static int option_progress = -1;
|
static int option_progress = -1;
|
||||||
static enum transport_family family;
|
static enum transport_family family;
|
||||||
static struct string_list option_config;
|
static struct string_list option_config = STRING_LIST_INIT_NODUP;
|
||||||
static struct string_list option_reference;
|
static struct string_list option_reference = STRING_LIST_INIT_NODUP;
|
||||||
static int option_dissociate;
|
static int option_dissociate;
|
||||||
static int max_jobs = -1;
|
static int max_jobs = -1;
|
||||||
|
|
||||||
@@ -624,13 +624,13 @@ static void update_remote_refs(const struct ref *refs,
|
|||||||
const struct ref *rm = mapped_refs;
|
const struct ref *rm = mapped_refs;
|
||||||
|
|
||||||
if (check_connectivity) {
|
if (check_connectivity) {
|
||||||
if (transport->progress)
|
struct check_connected_options opt = CHECK_CONNECTED_INIT;
|
||||||
fprintf(stderr, _("Checking connectivity... "));
|
|
||||||
if (check_everything_connected_with_transport(iterate_ref_map,
|
opt.transport = transport;
|
||||||
0, &rm, transport))
|
opt.progress = transport->progress;
|
||||||
|
|
||||||
|
if (check_connected(iterate_ref_map, &rm, &opt))
|
||||||
die(_("remote did not send all necessary objects"));
|
die(_("remote did not send all necessary objects"));
|
||||||
if (transport->progress)
|
|
||||||
fprintf(stderr, _("done.\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refs) {
|
if (refs) {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ static char term = '\n';
|
|||||||
static int use_global_config, use_system_config, use_local_config;
|
static int use_global_config, use_system_config, use_local_config;
|
||||||
static struct git_config_source given_config_source;
|
static struct git_config_source given_config_source;
|
||||||
static int actions, types;
|
static int actions, types;
|
||||||
static const char *get_color_slot, *get_colorbool_slot;
|
|
||||||
static int end_null;
|
static int end_null;
|
||||||
static int respect_includes = -1;
|
static int respect_includes = -1;
|
||||||
static int show_origin;
|
static int show_origin;
|
||||||
@@ -604,7 +603,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
|||||||
given_config_source.file : git_path("config"));
|
given_config_source.file : git_path("config"));
|
||||||
if (use_global_config) {
|
if (use_global_config) {
|
||||||
int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
||||||
if (fd) {
|
if (fd >= 0) {
|
||||||
char *content = default_user_config();
|
char *content = default_user_config();
|
||||||
write_str_in_full(fd, content);
|
write_str_in_full(fd, content);
|
||||||
free(content);
|
free(content);
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ static void show_filemodify(struct diff_queue_struct *q,
|
|||||||
print_path(spec->path);
|
print_path(spec->path);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
|
||||||
if (!hashcmp(ospec->sha1, spec->sha1) &&
|
if (!oidcmp(&ospec->oid, &spec->oid) &&
|
||||||
ospec->mode == spec->mode)
|
ospec->mode == spec->mode)
|
||||||
break;
|
break;
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
@@ -383,10 +383,10 @@ static void show_filemodify(struct diff_queue_struct *q,
|
|||||||
if (no_data || S_ISGITLINK(spec->mode))
|
if (no_data || S_ISGITLINK(spec->mode))
|
||||||
printf("M %06o %s ", spec->mode,
|
printf("M %06o %s ", spec->mode,
|
||||||
sha1_to_hex(anonymize ?
|
sha1_to_hex(anonymize ?
|
||||||
anonymize_sha1(spec->sha1) :
|
anonymize_sha1(spec->oid.hash) :
|
||||||
spec->sha1));
|
spec->oid.hash));
|
||||||
else {
|
else {
|
||||||
struct object *object = lookup_object(spec->sha1);
|
struct object *object = lookup_object(spec->oid.hash);
|
||||||
printf("M %06o :%d ", spec->mode,
|
printf("M %06o :%d ", spec->mode,
|
||||||
get_object_mark(object));
|
get_object_mark(object));
|
||||||
}
|
}
|
||||||
@@ -572,7 +572,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
|||||||
/* Export the referenced blobs, and remember the marks. */
|
/* Export the referenced blobs, and remember the marks. */
|
||||||
for (i = 0; i < diff_queued_diff.nr; i++)
|
for (i = 0; i < diff_queued_diff.nr; i++)
|
||||||
if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
|
if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
|
||||||
export_blob(diff_queued_diff.queue[i]->two->sha1);
|
export_blob(diff_queued_diff.queue[i]->two->oid.hash);
|
||||||
|
|
||||||
refname = commit->util;
|
refname = commit->util;
|
||||||
if (anonymize) {
|
if (anonymize) {
|
||||||
|
|||||||
205
builtin/fetch.c
205
builtin/fetch.c
@@ -15,6 +15,7 @@
|
|||||||
#include "submodule.h"
|
#include "submodule.h"
|
||||||
#include "connected.h"
|
#include "connected.h"
|
||||||
#include "argv-array.h"
|
#include "argv-array.h"
|
||||||
|
#include "utf8.h"
|
||||||
|
|
||||||
static const char * const builtin_fetch_usage[] = {
|
static const char * const builtin_fetch_usage[] = {
|
||||||
N_("git fetch [<options>] [<repository> [<refspec>...]]"),
|
N_("git fetch [<options>] [<repository> [<refspec>...]]"),
|
||||||
@@ -449,7 +450,132 @@ fail:
|
|||||||
: STORE_REF_ERROR_OTHER;
|
: STORE_REF_ERROR_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REFCOL_WIDTH 10
|
static int refcol_width = 10;
|
||||||
|
static int compact_format;
|
||||||
|
|
||||||
|
static void adjust_refcol_width(const struct ref *ref)
|
||||||
|
{
|
||||||
|
int max, rlen, llen, len;
|
||||||
|
|
||||||
|
/* uptodate lines are only shown on high verbosity level */
|
||||||
|
if (!verbosity && !oidcmp(&ref->peer_ref->old_oid, &ref->old_oid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
max = term_columns();
|
||||||
|
rlen = utf8_strwidth(prettify_refname(ref->name));
|
||||||
|
|
||||||
|
llen = utf8_strwidth(prettify_refname(ref->peer_ref->name));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rough estimation to see if the output line is too long and
|
||||||
|
* should not be counted (we can't do precise calculation
|
||||||
|
* anyway because we don't know if the error explanation part
|
||||||
|
* will be printed in update_local_ref)
|
||||||
|
*/
|
||||||
|
if (compact_format) {
|
||||||
|
llen = 0;
|
||||||
|
max = max * 2 / 3;
|
||||||
|
}
|
||||||
|
len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen;
|
||||||
|
if (len >= max)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not precise calculation for compact mode because '*' can
|
||||||
|
* appear on the left hand side of '->' and shrink the column
|
||||||
|
* back.
|
||||||
|
*/
|
||||||
|
if (refcol_width < rlen)
|
||||||
|
refcol_width = rlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prepare_format_display(struct ref *ref_map)
|
||||||
|
{
|
||||||
|
struct ref *rm;
|
||||||
|
const char *format = "full";
|
||||||
|
|
||||||
|
git_config_get_string_const("fetch.output", &format);
|
||||||
|
if (!strcasecmp(format, "full"))
|
||||||
|
compact_format = 0;
|
||||||
|
else if (!strcasecmp(format, "compact"))
|
||||||
|
compact_format = 1;
|
||||||
|
else
|
||||||
|
die(_("configuration fetch.output contains invalid value %s"),
|
||||||
|
format);
|
||||||
|
|
||||||
|
for (rm = ref_map; rm; rm = rm->next) {
|
||||||
|
if (rm->status == REF_STATUS_REJECT_SHALLOW ||
|
||||||
|
!rm->peer_ref ||
|
||||||
|
!strcmp(rm->name, "HEAD"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
adjust_refcol_width(rm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_remote_to_local(struct strbuf *display,
|
||||||
|
const char *remote, const char *local)
|
||||||
|
{
|
||||||
|
strbuf_addf(display, "%-*s -> %s", refcol_width, remote, local);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_and_replace(struct strbuf *haystack,
|
||||||
|
const char *needle,
|
||||||
|
const char *placeholder)
|
||||||
|
{
|
||||||
|
const char *p = strstr(haystack->buf, needle);
|
||||||
|
int plen, nlen;
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (p > haystack->buf && p[-1] != '/')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
plen = strlen(p);
|
||||||
|
nlen = strlen(needle);
|
||||||
|
if (plen > nlen && p[nlen] != '/')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
strbuf_splice(haystack, p - haystack->buf, nlen,
|
||||||
|
placeholder, strlen(placeholder));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_compact(struct strbuf *display,
|
||||||
|
const char *remote, const char *local)
|
||||||
|
{
|
||||||
|
struct strbuf r = STRBUF_INIT;
|
||||||
|
struct strbuf l = STRBUF_INIT;
|
||||||
|
|
||||||
|
if (!strcmp(remote, local)) {
|
||||||
|
strbuf_addf(display, "%-*s -> *", refcol_width, remote);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strbuf_addstr(&r, remote);
|
||||||
|
strbuf_addstr(&l, local);
|
||||||
|
|
||||||
|
if (!find_and_replace(&r, local, "*"))
|
||||||
|
find_and_replace(&l, remote, "*");
|
||||||
|
print_remote_to_local(display, r.buf, l.buf);
|
||||||
|
|
||||||
|
strbuf_release(&r);
|
||||||
|
strbuf_release(&l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void format_display(struct strbuf *display, char code,
|
||||||
|
const char *summary, const char *error,
|
||||||
|
const char *remote, const char *local)
|
||||||
|
{
|
||||||
|
strbuf_addf(display, "%c %-*s ", code, TRANSPORT_SUMMARY(summary));
|
||||||
|
if (!compact_format)
|
||||||
|
print_remote_to_local(display, remote, local);
|
||||||
|
else
|
||||||
|
print_compact(display, remote, local);
|
||||||
|
if (error)
|
||||||
|
strbuf_addf(display, " (%s)", error);
|
||||||
|
}
|
||||||
|
|
||||||
static int update_local_ref(struct ref *ref,
|
static int update_local_ref(struct ref *ref,
|
||||||
const char *remote,
|
const char *remote,
|
||||||
@@ -467,9 +593,8 @@ static int update_local_ref(struct ref *ref,
|
|||||||
|
|
||||||
if (!oidcmp(&ref->old_oid, &ref->new_oid)) {
|
if (!oidcmp(&ref->old_oid, &ref->new_oid)) {
|
||||||
if (verbosity > 0)
|
if (verbosity > 0)
|
||||||
strbuf_addf(display, "= %-*s %-*s -> %s",
|
format_display(display, '=', _("[up to date]"), NULL,
|
||||||
TRANSPORT_SUMMARY(_("[up to date]")),
|
remote, pretty_ref);
|
||||||
REFCOL_WIDTH, remote, pretty_ref);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,10 +606,9 @@ static int update_local_ref(struct ref *ref,
|
|||||||
* If this is the head, and it's not okay to update
|
* If this is the head, and it's not okay to update
|
||||||
* the head, and the old value of the head isn't empty...
|
* the head, and the old value of the head isn't empty...
|
||||||
*/
|
*/
|
||||||
strbuf_addf(display,
|
format_display(display, '!', _("[rejected]"),
|
||||||
_("! %-*s %-*s -> %s (can't fetch in current branch)"),
|
_("can't fetch in current branch"),
|
||||||
TRANSPORT_SUMMARY(_("[rejected]")),
|
remote, pretty_ref);
|
||||||
REFCOL_WIDTH, remote, pretty_ref);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,11 +616,9 @@ static int update_local_ref(struct ref *ref,
|
|||||||
starts_with(ref->name, "refs/tags/")) {
|
starts_with(ref->name, "refs/tags/")) {
|
||||||
int r;
|
int r;
|
||||||
r = s_update_ref("updating tag", ref, 0);
|
r = s_update_ref("updating tag", ref, 0);
|
||||||
strbuf_addf(display, "%c %-*s %-*s -> %s%s",
|
format_display(display, r ? '!' : 't', _("[tag update]"),
|
||||||
r ? '!' : '-',
|
r ? _("unable to update local ref") : NULL,
|
||||||
TRANSPORT_SUMMARY(_("[tag update]")),
|
remote, pretty_ref);
|
||||||
REFCOL_WIDTH, remote, pretty_ref,
|
|
||||||
r ? _(" (unable to update local ref)") : "");
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,11 +649,9 @@ static int update_local_ref(struct ref *ref,
|
|||||||
(recurse_submodules != RECURSE_SUBMODULES_ON))
|
(recurse_submodules != RECURSE_SUBMODULES_ON))
|
||||||
check_for_new_submodule_commits(ref->new_oid.hash);
|
check_for_new_submodule_commits(ref->new_oid.hash);
|
||||||
r = s_update_ref(msg, ref, 0);
|
r = s_update_ref(msg, ref, 0);
|
||||||
strbuf_addf(display, "%c %-*s %-*s -> %s%s",
|
format_display(display, r ? '!' : '*', what,
|
||||||
r ? '!' : '*',
|
r ? _("unable to update local ref") : NULL,
|
||||||
TRANSPORT_SUMMARY(what),
|
remote, pretty_ref);
|
||||||
REFCOL_WIDTH, remote, pretty_ref,
|
|
||||||
r ? _(" (unable to update local ref)") : "");
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,11 +665,9 @@ static int update_local_ref(struct ref *ref,
|
|||||||
(recurse_submodules != RECURSE_SUBMODULES_ON))
|
(recurse_submodules != RECURSE_SUBMODULES_ON))
|
||||||
check_for_new_submodule_commits(ref->new_oid.hash);
|
check_for_new_submodule_commits(ref->new_oid.hash);
|
||||||
r = s_update_ref("fast-forward", ref, 1);
|
r = s_update_ref("fast-forward", ref, 1);
|
||||||
strbuf_addf(display, "%c %-*s %-*s -> %s%s",
|
format_display(display, r ? '!' : ' ', quickref.buf,
|
||||||
r ? '!' : ' ',
|
r ? _("unable to update local ref") : NULL,
|
||||||
TRANSPORT_SUMMARY_WIDTH, quickref.buf,
|
remote, pretty_ref);
|
||||||
REFCOL_WIDTH, remote, pretty_ref,
|
|
||||||
r ? _(" (unable to update local ref)") : "");
|
|
||||||
strbuf_release(&quickref);
|
strbuf_release(&quickref);
|
||||||
return r;
|
return r;
|
||||||
} else if (force || ref->force) {
|
} else if (force || ref->force) {
|
||||||
@@ -562,18 +680,14 @@ static int update_local_ref(struct ref *ref,
|
|||||||
(recurse_submodules != RECURSE_SUBMODULES_ON))
|
(recurse_submodules != RECURSE_SUBMODULES_ON))
|
||||||
check_for_new_submodule_commits(ref->new_oid.hash);
|
check_for_new_submodule_commits(ref->new_oid.hash);
|
||||||
r = s_update_ref("forced-update", ref, 1);
|
r = s_update_ref("forced-update", ref, 1);
|
||||||
strbuf_addf(display, "%c %-*s %-*s -> %s (%s)",
|
format_display(display, r ? '!' : '+', quickref.buf,
|
||||||
r ? '!' : '+',
|
r ? _("unable to update local ref") : _("forced update"),
|
||||||
TRANSPORT_SUMMARY_WIDTH, quickref.buf,
|
remote, pretty_ref);
|
||||||
REFCOL_WIDTH, remote, pretty_ref,
|
|
||||||
r ? _("unable to update local ref") : _("forced update"));
|
|
||||||
strbuf_release(&quickref);
|
strbuf_release(&quickref);
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
strbuf_addf(display, "! %-*s %-*s -> %s %s",
|
format_display(display, '!', _("[rejected]"), _("non-fast-forward"),
|
||||||
TRANSPORT_SUMMARY(_("[rejected]")),
|
remote, pretty_ref);
|
||||||
REFCOL_WIDTH, remote, pretty_ref,
|
|
||||||
_("(non-fast-forward)"));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -615,11 +729,13 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
|
|||||||
url = xstrdup("foreign");
|
url = xstrdup("foreign");
|
||||||
|
|
||||||
rm = ref_map;
|
rm = ref_map;
|
||||||
if (check_everything_connected(iterate_ref_map, 0, &rm)) {
|
if (check_connected(iterate_ref_map, &rm, NULL)) {
|
||||||
rc = error(_("%s did not send all necessary objects\n"), url);
|
rc = error(_("%s did not send all necessary objects\n"), url);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepare_format_display(ref_map);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We do a pass for each fetch_head_status type in their enum order, so
|
* We do a pass for each fetch_head_status type in their enum order, so
|
||||||
* merged entries are written before not-for-merge. That lets readers
|
* merged entries are written before not-for-merge. That lets readers
|
||||||
@@ -714,11 +830,10 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
|
|||||||
rc |= update_local_ref(ref, what, rm, ¬e);
|
rc |= update_local_ref(ref, what, rm, ¬e);
|
||||||
free(ref);
|
free(ref);
|
||||||
} else
|
} else
|
||||||
strbuf_addf(¬e, "* %-*s %-*s -> FETCH_HEAD",
|
format_display(¬e, '*',
|
||||||
TRANSPORT_SUMMARY_WIDTH,
|
*kind ? kind : "branch", NULL,
|
||||||
*kind ? kind : "branch",
|
*what ? what : "HEAD",
|
||||||
REFCOL_WIDTH,
|
"FETCH_HEAD");
|
||||||
*what ? what : "HEAD");
|
|
||||||
if (note.len) {
|
if (note.len) {
|
||||||
if (verbosity >= 0 && !shown_url) {
|
if (verbosity >= 0 && !shown_url) {
|
||||||
fprintf(stderr, _("From %.*s\n"),
|
fprintf(stderr, _("From %.*s\n"),
|
||||||
@@ -751,6 +866,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
|
|||||||
static int quickfetch(struct ref *ref_map)
|
static int quickfetch(struct ref *ref_map)
|
||||||
{
|
{
|
||||||
struct ref *rm = ref_map;
|
struct ref *rm = ref_map;
|
||||||
|
struct check_connected_options opt = CHECK_CONNECTED_INIT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are deepening a shallow clone we already have these
|
* If we are deepening a shallow clone we already have these
|
||||||
@@ -761,7 +877,8 @@ static int quickfetch(struct ref *ref_map)
|
|||||||
*/
|
*/
|
||||||
if (depth)
|
if (depth)
|
||||||
return -1;
|
return -1;
|
||||||
return check_everything_connected(iterate_ref_map, 1, &rm);
|
opt.quiet = 1;
|
||||||
|
return check_connected(iterate_ref_map, &rm, &opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fetch_refs(struct transport *transport, struct ref *ref_map)
|
static int fetch_refs(struct transport *transport, struct ref *ref_map)
|
||||||
@@ -806,19 +923,21 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map,
|
|||||||
for (ref = stale_refs; ref; ref = ref->next)
|
for (ref = stale_refs; ref; ref = ref->next)
|
||||||
string_list_append(&refnames, ref->name);
|
string_list_append(&refnames, ref->name);
|
||||||
|
|
||||||
result = delete_refs(&refnames);
|
result = delete_refs(&refnames, 0);
|
||||||
string_list_clear(&refnames, 0);
|
string_list_clear(&refnames, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbosity >= 0) {
|
if (verbosity >= 0) {
|
||||||
for (ref = stale_refs; ref; ref = ref->next) {
|
for (ref = stale_refs; ref; ref = ref->next) {
|
||||||
|
struct strbuf sb = STRBUF_INIT;
|
||||||
if (!shown_url) {
|
if (!shown_url) {
|
||||||
fprintf(stderr, _("From %.*s\n"), url_len, url);
|
fprintf(stderr, _("From %.*s\n"), url_len, url);
|
||||||
shown_url = 1;
|
shown_url = 1;
|
||||||
}
|
}
|
||||||
fprintf(stderr, " x %-*s %-*s -> %s\n",
|
format_display(&sb, '-', _("[deleted]"), NULL,
|
||||||
TRANSPORT_SUMMARY(_("[deleted]")),
|
_("(none)"), prettify_refname(ref->name));
|
||||||
REFCOL_WIDTH, _("(none)"), prettify_refname(ref->name));
|
fprintf(stderr, " %s\n",sb.buf);
|
||||||
|
strbuf_release(&sb);
|
||||||
warn_dangling_symref(stderr, dangling_msg, ref->name);
|
warn_dangling_symref(stderr, dangling_msg, ref->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "streaming.h"
|
#include "streaming.h"
|
||||||
|
#include "decorate.h"
|
||||||
|
|
||||||
#define REACHABLE 0x0001
|
#define REACHABLE 0x0001
|
||||||
#define SEEN 0x0002
|
#define SEEN 0x0002
|
||||||
@@ -35,11 +36,26 @@ static int write_lost_and_found;
|
|||||||
static int verbose;
|
static int verbose;
|
||||||
static int show_progress = -1;
|
static int show_progress = -1;
|
||||||
static int show_dangling = 1;
|
static int show_dangling = 1;
|
||||||
|
static int name_objects;
|
||||||
#define ERROR_OBJECT 01
|
#define ERROR_OBJECT 01
|
||||||
#define ERROR_REACHABLE 02
|
#define ERROR_REACHABLE 02
|
||||||
#define ERROR_PACK 04
|
#define ERROR_PACK 04
|
||||||
#define ERROR_REFS 010
|
#define ERROR_REFS 010
|
||||||
|
|
||||||
|
static const char *describe_object(struct object *obj)
|
||||||
|
{
|
||||||
|
static struct strbuf buf = STRBUF_INIT;
|
||||||
|
char *name = name_objects ?
|
||||||
|
lookup_decoration(fsck_walk_options.object_names, obj) : NULL;
|
||||||
|
|
||||||
|
strbuf_reset(&buf);
|
||||||
|
strbuf_addstr(&buf, oid_to_hex(&obj->oid));
|
||||||
|
if (name)
|
||||||
|
strbuf_addf(&buf, " (%s)", name);
|
||||||
|
|
||||||
|
return buf.buf;
|
||||||
|
}
|
||||||
|
|
||||||
static int fsck_config(const char *var, const char *value, void *cb)
|
static int fsck_config(const char *var, const char *value, void *cb)
|
||||||
{
|
{
|
||||||
if (strcmp(var, "fsck.skiplist") == 0) {
|
if (strcmp(var, "fsck.skiplist") == 0) {
|
||||||
@@ -67,7 +83,7 @@ static void objreport(struct object *obj, const char *msg_type,
|
|||||||
const char *err)
|
const char *err)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s in %s %s: %s\n",
|
fprintf(stderr, "%s in %s %s: %s\n",
|
||||||
msg_type, typename(obj->type), oid_to_hex(&obj->oid), err);
|
msg_type, typename(obj->type), describe_object(obj), err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int objerror(struct object *obj, const char *err)
|
static int objerror(struct object *obj, const char *err)
|
||||||
@@ -77,7 +93,8 @@ static int objerror(struct object *obj, const char *err)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsck_error_func(struct object *obj, int type, const char *message)
|
static int fsck_error_func(struct fsck_options *o,
|
||||||
|
struct object *obj, int type, const char *message)
|
||||||
{
|
{
|
||||||
objreport(obj, (type == FSCK_WARN) ? "warning" : "error", message);
|
objreport(obj, (type == FSCK_WARN) ? "warning" : "error", message);
|
||||||
return (type == FSCK_WARN) ? 0 : 1;
|
return (type == FSCK_WARN) ? 0 : 1;
|
||||||
@@ -97,7 +114,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
|
|||||||
if (!obj) {
|
if (!obj) {
|
||||||
/* ... these references to parent->fld are safe here */
|
/* ... these references to parent->fld are safe here */
|
||||||
printf("broken link from %7s %s\n",
|
printf("broken link from %7s %s\n",
|
||||||
typename(parent->type), oid_to_hex(&parent->oid));
|
typename(parent->type), describe_object(parent));
|
||||||
printf("broken link from %7s %s\n",
|
printf("broken link from %7s %s\n",
|
||||||
(type == OBJ_ANY ? "unknown" : typename(type)), "unknown");
|
(type == OBJ_ANY ? "unknown" : typename(type)), "unknown");
|
||||||
errors_found |= ERROR_REACHABLE;
|
errors_found |= ERROR_REACHABLE;
|
||||||
@@ -114,9 +131,9 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
|
|||||||
if (!(obj->flags & HAS_OBJ)) {
|
if (!(obj->flags & HAS_OBJ)) {
|
||||||
if (parent && !has_object_file(&obj->oid)) {
|
if (parent && !has_object_file(&obj->oid)) {
|
||||||
printf("broken link from %7s %s\n",
|
printf("broken link from %7s %s\n",
|
||||||
typename(parent->type), oid_to_hex(&parent->oid));
|
typename(parent->type), describe_object(parent));
|
||||||
printf(" to %7s %s\n",
|
printf(" to %7s %s\n",
|
||||||
typename(obj->type), oid_to_hex(&obj->oid));
|
typename(obj->type), describe_object(obj));
|
||||||
errors_found |= ERROR_REACHABLE;
|
errors_found |= ERROR_REACHABLE;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -190,7 +207,8 @@ static void check_reachable_object(struct object *obj)
|
|||||||
return; /* it is in pack - forget about it */
|
return; /* it is in pack - forget about it */
|
||||||
if (connectivity_only && has_object_file(&obj->oid))
|
if (connectivity_only && has_object_file(&obj->oid))
|
||||||
return;
|
return;
|
||||||
printf("missing %s %s\n", typename(obj->type), oid_to_hex(&obj->oid));
|
printf("missing %s %s\n", typename(obj->type),
|
||||||
|
describe_object(obj));
|
||||||
errors_found |= ERROR_REACHABLE;
|
errors_found |= ERROR_REACHABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -215,7 +233,8 @@ static void check_unreachable_object(struct object *obj)
|
|||||||
* since this is something that is prunable.
|
* since this is something that is prunable.
|
||||||
*/
|
*/
|
||||||
if (show_unreachable) {
|
if (show_unreachable) {
|
||||||
printf("unreachable %s %s\n", typename(obj->type), oid_to_hex(&obj->oid));
|
printf("unreachable %s %s\n", typename(obj->type),
|
||||||
|
describe_object(obj));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,11 +253,11 @@ static void check_unreachable_object(struct object *obj)
|
|||||||
if (!obj->used) {
|
if (!obj->used) {
|
||||||
if (show_dangling)
|
if (show_dangling)
|
||||||
printf("dangling %s %s\n", typename(obj->type),
|
printf("dangling %s %s\n", typename(obj->type),
|
||||||
oid_to_hex(&obj->oid));
|
describe_object(obj));
|
||||||
if (write_lost_and_found) {
|
if (write_lost_and_found) {
|
||||||
char *filename = git_pathdup("lost-found/%s/%s",
|
char *filename = git_pathdup("lost-found/%s/%s",
|
||||||
obj->type == OBJ_COMMIT ? "commit" : "other",
|
obj->type == OBJ_COMMIT ? "commit" : "other",
|
||||||
oid_to_hex(&obj->oid));
|
describe_object(obj));
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
if (safe_create_leading_directories_const(filename)) {
|
if (safe_create_leading_directories_const(filename)) {
|
||||||
@@ -252,7 +271,7 @@ static void check_unreachable_object(struct object *obj)
|
|||||||
if (stream_blob_to_fd(fileno(f), obj->oid.hash, NULL, 1))
|
if (stream_blob_to_fd(fileno(f), obj->oid.hash, NULL, 1))
|
||||||
die_errno("Could not write '%s'", filename);
|
die_errno("Could not write '%s'", filename);
|
||||||
} else
|
} else
|
||||||
fprintf(f, "%s\n", oid_to_hex(&obj->oid));
|
fprintf(f, "%s\n", describe_object(obj));
|
||||||
if (fclose(f))
|
if (fclose(f))
|
||||||
die_errno("Could not finish '%s'",
|
die_errno("Could not finish '%s'",
|
||||||
filename);
|
filename);
|
||||||
@@ -271,7 +290,7 @@ static void check_unreachable_object(struct object *obj)
|
|||||||
static void check_object(struct object *obj)
|
static void check_object(struct object *obj)
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "Checking %s\n", oid_to_hex(&obj->oid));
|
fprintf(stderr, "Checking %s\n", describe_object(obj));
|
||||||
|
|
||||||
if (obj->flags & REACHABLE)
|
if (obj->flags & REACHABLE)
|
||||||
check_reachable_object(obj);
|
check_reachable_object(obj);
|
||||||
@@ -307,7 +326,7 @@ static int fsck_obj(struct object *obj)
|
|||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "Checking %s %s\n",
|
fprintf(stderr, "Checking %s %s\n",
|
||||||
typename(obj->type), oid_to_hex(&obj->oid));
|
typename(obj->type), describe_object(obj));
|
||||||
|
|
||||||
if (fsck_walk(obj, NULL, &fsck_obj_options))
|
if (fsck_walk(obj, NULL, &fsck_obj_options))
|
||||||
objerror(obj, "broken links");
|
objerror(obj, "broken links");
|
||||||
@@ -326,15 +345,17 @@ static int fsck_obj(struct object *obj)
|
|||||||
free_commit_buffer(commit);
|
free_commit_buffer(commit);
|
||||||
|
|
||||||
if (!commit->parents && show_root)
|
if (!commit->parents && show_root)
|
||||||
printf("root %s\n", oid_to_hex(&commit->object.oid));
|
printf("root %s\n", describe_object(&commit->object));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj->type == OBJ_TAG) {
|
if (obj->type == OBJ_TAG) {
|
||||||
struct tag *tag = (struct tag *) obj;
|
struct tag *tag = (struct tag *) obj;
|
||||||
|
|
||||||
if (show_tags && tag->tagged) {
|
if (show_tags && tag->tagged) {
|
||||||
printf("tagged %s %s", typename(tag->tagged->type), oid_to_hex(&tag->tagged->oid));
|
printf("tagged %s %s", typename(tag->tagged->type),
|
||||||
printf(" (%s) in %s\n", tag->tag, oid_to_hex(&tag->object.oid));
|
describe_object(tag->tagged));
|
||||||
|
printf(" (%s) in %s\n", tag->tag,
|
||||||
|
describe_object(&tag->object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,13 +393,18 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
|
|||||||
|
|
||||||
static int default_refs;
|
static int default_refs;
|
||||||
|
|
||||||
static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1)
|
static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1,
|
||||||
|
unsigned long timestamp)
|
||||||
{
|
{
|
||||||
struct object *obj;
|
struct object *obj;
|
||||||
|
|
||||||
if (!is_null_sha1(sha1)) {
|
if (!is_null_sha1(sha1)) {
|
||||||
obj = lookup_object(sha1);
|
obj = lookup_object(sha1);
|
||||||
if (obj) {
|
if (obj) {
|
||||||
|
if (timestamp && name_objects)
|
||||||
|
add_decoration(fsck_walk_options.object_names,
|
||||||
|
obj,
|
||||||
|
xstrfmt("%s@{%ld}", refname, timestamp));
|
||||||
obj->used = 1;
|
obj->used = 1;
|
||||||
mark_object_reachable(obj);
|
mark_object_reachable(obj);
|
||||||
} else {
|
} else {
|
||||||
@@ -398,8 +424,8 @@ static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
|||||||
fprintf(stderr, "Checking reflog %s->%s\n",
|
fprintf(stderr, "Checking reflog %s->%s\n",
|
||||||
sha1_to_hex(osha1), sha1_to_hex(nsha1));
|
sha1_to_hex(osha1), sha1_to_hex(nsha1));
|
||||||
|
|
||||||
fsck_handle_reflog_sha1(refname, osha1);
|
fsck_handle_reflog_sha1(refname, osha1, 0);
|
||||||
fsck_handle_reflog_sha1(refname, nsha1);
|
fsck_handle_reflog_sha1(refname, nsha1, timestamp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,6 +454,9 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,
|
|||||||
}
|
}
|
||||||
default_refs++;
|
default_refs++;
|
||||||
obj->used = 1;
|
obj->used = 1;
|
||||||
|
if (name_objects)
|
||||||
|
add_decoration(fsck_walk_options.object_names,
|
||||||
|
obj, xstrdup(refname));
|
||||||
mark_object_reachable(obj);
|
mark_object_reachable(obj);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -543,6 +572,9 @@ static int fsck_cache_tree(struct cache_tree *it)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
obj->used = 1;
|
obj->used = 1;
|
||||||
|
if (name_objects)
|
||||||
|
add_decoration(fsck_walk_options.object_names,
|
||||||
|
obj, xstrdup(":"));
|
||||||
mark_object_reachable(obj);
|
mark_object_reachable(obj);
|
||||||
if (obj->type != OBJ_TREE)
|
if (obj->type != OBJ_TREE)
|
||||||
err |= objerror(obj, "non-tree in cache-tree");
|
err |= objerror(obj, "non-tree in cache-tree");
|
||||||
@@ -571,6 +603,7 @@ static struct option fsck_opts[] = {
|
|||||||
OPT_BOOL(0, "lost-found", &write_lost_and_found,
|
OPT_BOOL(0, "lost-found", &write_lost_and_found,
|
||||||
N_("write dangling objects in .git/lost-found")),
|
N_("write dangling objects in .git/lost-found")),
|
||||||
OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
|
OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
|
||||||
|
OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")),
|
||||||
OPT_END(),
|
OPT_END(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -600,6 +633,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
include_reflogs = 0;
|
include_reflogs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name_objects)
|
||||||
|
fsck_walk_options.object_names =
|
||||||
|
xcalloc(1, sizeof(struct decoration));
|
||||||
|
|
||||||
git_config(fsck_config, NULL);
|
git_config(fsck_config, NULL);
|
||||||
|
|
||||||
fsck_head_link();
|
fsck_head_link();
|
||||||
@@ -655,6 +692,9 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
obj->used = 1;
|
obj->used = 1;
|
||||||
|
if (name_objects)
|
||||||
|
add_decoration(fsck_walk_options.object_names,
|
||||||
|
obj, xstrdup(arg));
|
||||||
mark_object_reachable(obj);
|
mark_object_reachable(obj);
|
||||||
heads++;
|
heads++;
|
||||||
continue;
|
continue;
|
||||||
@@ -687,6 +727,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
continue;
|
continue;
|
||||||
obj = &blob->object;
|
obj = &blob->object;
|
||||||
obj->used = 1;
|
obj->used = 1;
|
||||||
|
if (name_objects)
|
||||||
|
add_decoration(fsck_walk_options.object_names,
|
||||||
|
obj,
|
||||||
|
xstrfmt(":%s", active_cache[i]->name));
|
||||||
mark_object_reachable(obj);
|
mark_object_reachable(obj);
|
||||||
}
|
}
|
||||||
if (active_cache_tree)
|
if (active_cache_tree)
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ static int strict;
|
|||||||
static int do_fsck_object;
|
static int do_fsck_object;
|
||||||
static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
|
static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
|
||||||
static int verbose;
|
static int verbose;
|
||||||
|
static int show_resolving_progress;
|
||||||
static int show_stat;
|
static int show_stat;
|
||||||
static int check_self_contained_and_connected;
|
static int check_self_contained_and_connected;
|
||||||
|
|
||||||
@@ -1191,7 +1192,7 @@ static void resolve_deltas(void)
|
|||||||
qsort(ref_deltas, nr_ref_deltas, sizeof(struct ref_delta_entry),
|
qsort(ref_deltas, nr_ref_deltas, sizeof(struct ref_delta_entry),
|
||||||
compare_ref_delta_entry);
|
compare_ref_delta_entry);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose || show_resolving_progress)
|
||||||
progress = start_progress(_("Resolving deltas"),
|
progress = start_progress(_("Resolving deltas"),
|
||||||
nr_ref_deltas + nr_ofs_deltas);
|
nr_ref_deltas + nr_ofs_deltas);
|
||||||
|
|
||||||
@@ -1626,6 +1627,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
struct pack_idx_option opts;
|
struct pack_idx_option opts;
|
||||||
unsigned char pack_sha1[20];
|
unsigned char pack_sha1[20];
|
||||||
unsigned foreign_nr = 1; /* zero is a "good" value, assume bad */
|
unsigned foreign_nr = 1; /* zero is a "good" value, assume bad */
|
||||||
|
int report_end_of_input = 0;
|
||||||
|
|
||||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||||
usage(index_pack_usage);
|
usage(index_pack_usage);
|
||||||
@@ -1695,6 +1697,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
input_len = sizeof(*hdr);
|
input_len = sizeof(*hdr);
|
||||||
} else if (!strcmp(arg, "-v")) {
|
} else if (!strcmp(arg, "-v")) {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
|
} else if (!strcmp(arg, "--show-resolving-progress")) {
|
||||||
|
show_resolving_progress = 1;
|
||||||
|
} else if (!strcmp(arg, "--report-end-of-input")) {
|
||||||
|
report_end_of_input = 1;
|
||||||
} else if (!strcmp(arg, "-o")) {
|
} else if (!strcmp(arg, "-o")) {
|
||||||
if (index_name || (i+1) >= argc)
|
if (index_name || (i+1) >= argc)
|
||||||
usage(index_pack_usage);
|
usage(index_pack_usage);
|
||||||
@@ -1752,6 +1758,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat));
|
obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat));
|
||||||
ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry));
|
ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry));
|
||||||
parse_pack_objects(pack_sha1);
|
parse_pack_objects(pack_sha1);
|
||||||
|
if (report_end_of_input)
|
||||||
|
write_in_full(2, "\0", 1);
|
||||||
resolve_deltas();
|
resolve_deltas();
|
||||||
conclude_pack(fix_thin_pack, curr_pack, pack_sha1);
|
conclude_pack(fix_thin_pack, curr_pack, pack_sha1);
|
||||||
free(ofs_deltas);
|
free(ofs_deltas);
|
||||||
|
|||||||
@@ -397,13 +397,16 @@ int init_db(const char *template_dir, unsigned int flags)
|
|||||||
if (!(flags & INIT_DB_QUIET)) {
|
if (!(flags & INIT_DB_QUIET)) {
|
||||||
int len = strlen(git_dir);
|
int len = strlen(git_dir);
|
||||||
|
|
||||||
/* TRANSLATORS: The first '%s' is either "Reinitialized
|
if (reinit)
|
||||||
existing" or "Initialized empty", the second " shared" or
|
printf(get_shared_repository()
|
||||||
"", and the last '%s%s' is the verbatim directory name. */
|
? _("Reinitialized existing shared Git repository in %s%s\n")
|
||||||
printf(_("%s%s Git repository in %s%s\n"),
|
: _("Reinitialized existing Git repository in %s%s\n"),
|
||||||
reinit ? _("Reinitialized existing") : _("Initialized empty"),
|
git_dir, len && git_dir[len-1] != '/' ? "/" : "");
|
||||||
get_shared_repository() ? _(" shared") : "",
|
else
|
||||||
git_dir, len && git_dir[len-1] != '/' ? "/" : "");
|
printf(get_shared_repository()
|
||||||
|
? _("Initialized empty shared Git repository in %s%s\n")
|
||||||
|
: _("Initialized empty Git repository in %s%s\n"),
|
||||||
|
git_dir, len && git_dir[len-1] != '/' ? "/" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
|
|||||||
{
|
{
|
||||||
int in_place = 0;
|
int in_place = 0;
|
||||||
int trim_empty = 0;
|
int trim_empty = 0;
|
||||||
struct string_list trailers = STRING_LIST_INIT_DUP;
|
struct string_list trailers = STRING_LIST_INIT_NODUP;
|
||||||
|
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")),
|
OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")),
|
||||||
|
|||||||
116
builtin/log.c
116
builtin/log.c
@@ -33,6 +33,7 @@ static const char *default_date_mode = NULL;
|
|||||||
static int default_abbrev_commit;
|
static int default_abbrev_commit;
|
||||||
static int default_show_root = 1;
|
static int default_show_root = 1;
|
||||||
static int default_follow;
|
static int default_follow;
|
||||||
|
static int default_show_signature;
|
||||||
static int decoration_style;
|
static int decoration_style;
|
||||||
static int decoration_given;
|
static int decoration_given;
|
||||||
static int use_mailmap_config;
|
static int use_mailmap_config;
|
||||||
@@ -119,6 +120,7 @@ static void cmd_log_init_defaults(struct rev_info *rev)
|
|||||||
rev->abbrev_commit = default_abbrev_commit;
|
rev->abbrev_commit = default_abbrev_commit;
|
||||||
rev->show_root_diff = default_show_root;
|
rev->show_root_diff = default_show_root;
|
||||||
rev->subject_prefix = fmt_patch_subject_prefix;
|
rev->subject_prefix = fmt_patch_subject_prefix;
|
||||||
|
rev->show_signature = default_show_signature;
|
||||||
DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
|
DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
|
||||||
|
|
||||||
if (default_date_mode)
|
if (default_date_mode)
|
||||||
@@ -236,16 +238,17 @@ static void show_early_header(struct rev_info *rev, const char *stage, int nr)
|
|||||||
if (rev->commit_format != CMIT_FMT_ONELINE)
|
if (rev->commit_format != CMIT_FMT_ONELINE)
|
||||||
putchar(rev->diffopt.line_termination);
|
putchar(rev->diffopt.line_termination);
|
||||||
}
|
}
|
||||||
printf(_("Final output: %d %s\n"), nr, stage);
|
fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct itimerval early_output_timer;
|
static struct itimerval early_output_timer;
|
||||||
|
|
||||||
static void log_show_early(struct rev_info *revs, struct commit_list *list)
|
static void log_show_early(struct rev_info *revs, struct commit_list *list)
|
||||||
{
|
{
|
||||||
int i = revs->early_output;
|
int i = revs->early_output, close_file = revs->diffopt.close_file;
|
||||||
int show_header = 1;
|
int show_header = 1;
|
||||||
|
|
||||||
|
revs->diffopt.close_file = 0;
|
||||||
sort_in_topological_order(&list, revs->sort_order);
|
sort_in_topological_order(&list, revs->sort_order);
|
||||||
while (list && i) {
|
while (list && i) {
|
||||||
struct commit *commit = list->item;
|
struct commit *commit = list->item;
|
||||||
@@ -262,14 +265,19 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
|
|||||||
case commit_ignore:
|
case commit_ignore:
|
||||||
break;
|
break;
|
||||||
case commit_error:
|
case commit_error:
|
||||||
|
if (close_file)
|
||||||
|
fclose(revs->diffopt.file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
list = list->next;
|
list = list->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did we already get enough commits for the early output? */
|
/* Did we already get enough commits for the early output? */
|
||||||
if (!i)
|
if (!i) {
|
||||||
|
if (close_file)
|
||||||
|
fclose(revs->diffopt.file);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ..if no, then repeat it twice a second until we
|
* ..if no, then repeat it twice a second until we
|
||||||
@@ -331,7 +339,7 @@ static int cmd_log_walk(struct rev_info *rev)
|
|||||||
{
|
{
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
int saved_nrl = 0;
|
int saved_nrl = 0;
|
||||||
int saved_dcctc = 0;
|
int saved_dcctc = 0, close_file = rev->diffopt.close_file;
|
||||||
|
|
||||||
if (rev->early_output)
|
if (rev->early_output)
|
||||||
setup_early_output(rev);
|
setup_early_output(rev);
|
||||||
@@ -347,6 +355,7 @@ static int cmd_log_walk(struct rev_info *rev)
|
|||||||
* and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
|
* and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
|
||||||
* retain that state information if replacing rev->diffopt in this loop
|
* retain that state information if replacing rev->diffopt in this loop
|
||||||
*/
|
*/
|
||||||
|
rev->diffopt.close_file = 0;
|
||||||
while ((commit = get_revision(rev)) != NULL) {
|
while ((commit = get_revision(rev)) != NULL) {
|
||||||
if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
|
if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
|
||||||
/*
|
/*
|
||||||
@@ -367,6 +376,8 @@ static int cmd_log_walk(struct rev_info *rev)
|
|||||||
}
|
}
|
||||||
rev->diffopt.degraded_cc_to_c = saved_dcctc;
|
rev->diffopt.degraded_cc_to_c = saved_dcctc;
|
||||||
rev->diffopt.needed_rename_limit = saved_nrl;
|
rev->diffopt.needed_rename_limit = saved_nrl;
|
||||||
|
if (close_file)
|
||||||
|
fclose(rev->diffopt.file);
|
||||||
|
|
||||||
if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
|
if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
|
||||||
DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
|
DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
|
||||||
@@ -409,6 +420,10 @@ static int git_log_config(const char *var, const char *value, void *cb)
|
|||||||
use_mailmap_config = git_config_bool(var, value);
|
use_mailmap_config = git_config_bool(var, value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(var, "log.showsignature")) {
|
||||||
|
default_show_signature = git_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (grep_config(var, value, cb) < 0)
|
if (grep_config(var, value, cb) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -445,7 +460,7 @@ static void show_tagger(char *buf, int len, struct rev_info *rev)
|
|||||||
pp.fmt = rev->commit_format;
|
pp.fmt = rev->commit_format;
|
||||||
pp.date_mode = rev->date_mode;
|
pp.date_mode = rev->date_mode;
|
||||||
pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding());
|
pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding());
|
||||||
printf("%s", out.buf);
|
fprintf(rev->diffopt.file, "%s", out.buf);
|
||||||
strbuf_release(&out);
|
strbuf_release(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +471,7 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con
|
|||||||
char *buf;
|
char *buf;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(rev->diffopt.file);
|
||||||
if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) ||
|
if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) ||
|
||||||
!DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
|
!DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
|
||||||
return stream_blob_to_fd(1, sha1, NULL, 0);
|
return stream_blob_to_fd(1, sha1, NULL, 0);
|
||||||
@@ -496,7 +511,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (offset < size)
|
if (offset < size)
|
||||||
fwrite(buf + offset, size - offset, 1, stdout);
|
fwrite(buf + offset, size - offset, 1, rev->diffopt.file);
|
||||||
free(buf);
|
free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -505,7 +520,8 @@ static int show_tree_object(const unsigned char *sha1,
|
|||||||
struct strbuf *base,
|
struct strbuf *base,
|
||||||
const char *pathname, unsigned mode, int stage, void *context)
|
const char *pathname, unsigned mode, int stage, void *context)
|
||||||
{
|
{
|
||||||
printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
|
FILE *file = context;
|
||||||
|
fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,7 +581,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (rev.shown_one)
|
if (rev.shown_one)
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
printf("%stag %s%s\n",
|
fprintf(rev.diffopt.file, "%stag %s%s\n",
|
||||||
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
||||||
t->tag,
|
t->tag,
|
||||||
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
||||||
@@ -584,12 +600,12 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
|||||||
case OBJ_TREE:
|
case OBJ_TREE:
|
||||||
if (rev.shown_one)
|
if (rev.shown_one)
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
printf("%stree %s%s\n\n",
|
fprintf(rev.diffopt.file, "%stree %s%s\n\n",
|
||||||
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
||||||
name,
|
name,
|
||||||
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
||||||
read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
|
read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
|
||||||
show_tree_object, NULL);
|
show_tree_object, rev.diffopt.file);
|
||||||
rev.shown_one = 1;
|
rev.shown_one = 1;
|
||||||
break;
|
break;
|
||||||
case OBJ_COMMIT:
|
case OBJ_COMMIT:
|
||||||
@@ -674,9 +690,9 @@ static int auto_number = 1;
|
|||||||
|
|
||||||
static char *default_attach = NULL;
|
static char *default_attach = NULL;
|
||||||
|
|
||||||
static struct string_list extra_hdr;
|
static struct string_list extra_hdr = STRING_LIST_INIT_NODUP;
|
||||||
static struct string_list extra_to;
|
static struct string_list extra_to = STRING_LIST_INIT_NODUP;
|
||||||
static struct string_list extra_cc;
|
static struct string_list extra_cc = STRING_LIST_INIT_NODUP;
|
||||||
|
|
||||||
static void add_header(const char *value)
|
static void add_header(const char *value)
|
||||||
{
|
{
|
||||||
@@ -703,6 +719,7 @@ static void add_header(const char *value)
|
|||||||
static int thread;
|
static int thread;
|
||||||
static int do_signoff;
|
static int do_signoff;
|
||||||
static int base_auto;
|
static int base_auto;
|
||||||
|
static char *from;
|
||||||
static const char *signature = git_version_string;
|
static const char *signature = git_version_string;
|
||||||
static const char *signature_file;
|
static const char *signature_file;
|
||||||
static int config_cover_letter;
|
static int config_cover_letter;
|
||||||
@@ -791,15 +808,25 @@ static int git_format_config(const char *var, const char *value, void *cb)
|
|||||||
base_auto = git_config_bool(var, value);
|
base_auto = git_config_bool(var, value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(var, "format.from")) {
|
||||||
|
int b = git_config_maybe_bool(var, value);
|
||||||
|
free(from);
|
||||||
|
if (b < 0)
|
||||||
|
from = xstrdup(value);
|
||||||
|
else if (b)
|
||||||
|
from = xstrdup(git_committer_info(IDENT_NO_DATE));
|
||||||
|
else
|
||||||
|
from = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return git_log_config(var, value, cb);
|
return git_log_config(var, value, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE *realstdout = NULL;
|
|
||||||
static const char *output_directory = NULL;
|
static const char *output_directory = NULL;
|
||||||
static int outdir_offset;
|
static int outdir_offset;
|
||||||
|
|
||||||
static int reopen_stdout(struct commit *commit, const char *subject,
|
static int open_next_file(struct commit *commit, const char *subject,
|
||||||
struct rev_info *rev, int quiet)
|
struct rev_info *rev, int quiet)
|
||||||
{
|
{
|
||||||
struct strbuf filename = STRBUF_INIT;
|
struct strbuf filename = STRBUF_INIT;
|
||||||
@@ -821,9 +848,9 @@ static int reopen_stdout(struct commit *commit, const char *subject,
|
|||||||
fmt_output_subject(&filename, subject, rev);
|
fmt_output_subject(&filename, subject, rev);
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
|
printf("%s\n", filename.buf + outdir_offset);
|
||||||
|
|
||||||
if (freopen(filename.buf, "w", stdout) == NULL)
|
if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL)
|
||||||
return error(_("Cannot open patch file %s"), filename.buf);
|
return error(_("Cannot open patch file %s"), filename.buf);
|
||||||
|
|
||||||
strbuf_release(&filename);
|
strbuf_release(&filename);
|
||||||
@@ -882,15 +909,15 @@ static void gen_message_id(struct rev_info *info, char *base)
|
|||||||
info->message_id = strbuf_detach(&buf, NULL);
|
info->message_id = strbuf_detach(&buf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_signature(void)
|
static void print_signature(FILE *file)
|
||||||
{
|
{
|
||||||
if (!signature || !*signature)
|
if (!signature || !*signature)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("-- \n%s", signature);
|
fprintf(file, "-- \n%s", signature);
|
||||||
if (signature[strlen(signature)-1] != '\n')
|
if (signature[strlen(signature)-1] != '\n')
|
||||||
putchar('\n');
|
putc('\n', file);
|
||||||
putchar('\n');
|
putc('\n', file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_branch_description(struct strbuf *buf, const char *branch_name)
|
static void add_branch_description(struct strbuf *buf, const char *branch_name)
|
||||||
@@ -953,13 +980,13 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||||||
struct pretty_print_context pp = {0};
|
struct pretty_print_context pp = {0};
|
||||||
struct commit *head = list[0];
|
struct commit *head = list[0];
|
||||||
|
|
||||||
if (rev->commit_format != CMIT_FMT_EMAIL)
|
if (!cmit_fmt_is_mail(rev->commit_format))
|
||||||
die(_("Cover letter needs email format"));
|
die(_("Cover letter needs email format"));
|
||||||
|
|
||||||
committer = git_committer_info(0);
|
committer = git_committer_info(0);
|
||||||
|
|
||||||
if (!use_stdout &&
|
if (!use_stdout &&
|
||||||
reopen_stdout(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
|
open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
|
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
|
||||||
@@ -982,7 +1009,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||||||
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
|
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
|
||||||
pp_remainder(&pp, &msg, &sb, 0);
|
pp_remainder(&pp, &msg, &sb, 0);
|
||||||
add_branch_description(&sb, branch_name);
|
add_branch_description(&sb, branch_name);
|
||||||
printf("%s\n", sb.buf);
|
fprintf(rev->diffopt.file, "%s\n", sb.buf);
|
||||||
|
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
|
|
||||||
@@ -991,6 +1018,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||||||
log.wrap = 72;
|
log.wrap = 72;
|
||||||
log.in1 = 2;
|
log.in1 = 2;
|
||||||
log.in2 = 4;
|
log.in2 = 4;
|
||||||
|
log.file = rev->diffopt.file;
|
||||||
for (i = 0; i < nr; i++)
|
for (i = 0; i < nr; i++)
|
||||||
shortlog_add_commit(&log, list[i]);
|
shortlog_add_commit(&log, list[i]);
|
||||||
|
|
||||||
@@ -1013,8 +1041,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||||||
diffcore_std(&opts);
|
diffcore_std(&opts);
|
||||||
diff_flush(&opts);
|
diff_flush(&opts);
|
||||||
|
|
||||||
printf("\n");
|
fprintf(rev->diffopt.file, "\n");
|
||||||
print_signature();
|
print_signature(rev->diffopt.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *clean_message_id(const char *msg_id)
|
static const char *clean_message_id(const char *msg_id)
|
||||||
@@ -1315,7 +1343,7 @@ static void prepare_bases(struct base_tree_info *bases,
|
|||||||
struct object_id *patch_id;
|
struct object_id *patch_id;
|
||||||
if (commit->util)
|
if (commit->util)
|
||||||
continue;
|
continue;
|
||||||
if (commit_patch_id(commit, &diffopt, sha1))
|
if (commit_patch_id(commit, &diffopt, sha1, 0))
|
||||||
die(_("cannot get patch id"));
|
die(_("cannot get patch id"));
|
||||||
ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
|
ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
|
||||||
patch_id = bases->patch_id + bases->nr_patch_id;
|
patch_id = bases->patch_id + bases->nr_patch_id;
|
||||||
@@ -1324,7 +1352,7 @@ static void prepare_bases(struct base_tree_info *bases,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_bases(struct base_tree_info *bases)
|
static void print_bases(struct base_tree_info *bases, FILE *file)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -1333,11 +1361,11 @@ static void print_bases(struct base_tree_info *bases)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Show the base commit */
|
/* Show the base commit */
|
||||||
printf("base-commit: %s\n", oid_to_hex(&bases->base_commit));
|
fprintf(file, "base-commit: %s\n", oid_to_hex(&bases->base_commit));
|
||||||
|
|
||||||
/* Show the prerequisite patches */
|
/* Show the prerequisite patches */
|
||||||
for (i = bases->nr_patch_id - 1; i >= 0; i--)
|
for (i = bases->nr_patch_id - 1; i >= 0; i--)
|
||||||
printf("prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
|
fprintf(file, "prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
|
||||||
|
|
||||||
free(bases->patch_id);
|
free(bases->patch_id);
|
||||||
bases->nr_patch_id = 0;
|
bases->nr_patch_id = 0;
|
||||||
@@ -1368,7 +1396,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
int reroll_count = -1;
|
int reroll_count = -1;
|
||||||
char *branch_name = NULL;
|
char *branch_name = NULL;
|
||||||
char *from = NULL;
|
|
||||||
char *base_commit = NULL;
|
char *base_commit = NULL;
|
||||||
struct base_tree_info bases;
|
struct base_tree_info bases;
|
||||||
|
|
||||||
@@ -1569,6 +1596,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
setup_pager();
|
setup_pager();
|
||||||
|
|
||||||
if (output_directory) {
|
if (output_directory) {
|
||||||
|
if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
|
||||||
|
rev.diffopt.use_color = GIT_COLOR_NEVER;
|
||||||
if (use_stdout)
|
if (use_stdout)
|
||||||
die(_("standard output, or directory, which one?"));
|
die(_("standard output, or directory, which one?"));
|
||||||
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
|
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
|
||||||
@@ -1626,9 +1655,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
get_patch_ids(&rev, &ids);
|
get_patch_ids(&rev, &ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use_stdout)
|
|
||||||
realstdout = xfdopen(xdup(1), "w");
|
|
||||||
|
|
||||||
if (prepare_revision_walk(&rev))
|
if (prepare_revision_walk(&rev))
|
||||||
die(_("revision walk setup failed"));
|
die(_("revision walk setup failed"));
|
||||||
rev.boundary = 1;
|
rev.boundary = 1;
|
||||||
@@ -1693,7 +1719,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
gen_message_id(&rev, "cover");
|
gen_message_id(&rev, "cover");
|
||||||
make_cover_letter(&rev, use_stdout,
|
make_cover_letter(&rev, use_stdout,
|
||||||
origin, nr, list, branch_name, quiet);
|
origin, nr, list, branch_name, quiet);
|
||||||
print_bases(&bases);
|
print_bases(&bases, rev.diffopt.file);
|
||||||
total++;
|
total++;
|
||||||
start_number--;
|
start_number--;
|
||||||
}
|
}
|
||||||
@@ -1739,7 +1765,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!use_stdout &&
|
if (!use_stdout &&
|
||||||
reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
|
open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
|
||||||
die(_("Failed to create output files"));
|
die(_("Failed to create output files"));
|
||||||
shown = log_tree_commit(&rev, commit);
|
shown = log_tree_commit(&rev, commit);
|
||||||
free_commit_buffer(commit);
|
free_commit_buffer(commit);
|
||||||
@@ -1754,15 +1780,15 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
rev.shown_one = 0;
|
rev.shown_one = 0;
|
||||||
if (shown) {
|
if (shown) {
|
||||||
if (rev.mime_boundary)
|
if (rev.mime_boundary)
|
||||||
printf("\n--%s%s--\n\n\n",
|
fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
|
||||||
mime_boundary_leader,
|
mime_boundary_leader,
|
||||||
rev.mime_boundary);
|
rev.mime_boundary);
|
||||||
else
|
else
|
||||||
print_signature();
|
print_signature(rev.diffopt.file);
|
||||||
print_bases(&bases);
|
print_bases(&bases, rev.diffopt.file);
|
||||||
}
|
}
|
||||||
if (!use_stdout)
|
if (!use_stdout)
|
||||||
fclose(stdout);
|
fclose(rev.diffopt.file);
|
||||||
}
|
}
|
||||||
free(list);
|
free(list);
|
||||||
free(branch_name);
|
free(branch_name);
|
||||||
@@ -1794,15 +1820,15 @@ static const char * const cherry_usage[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void print_commit(char sign, struct commit *commit, int verbose,
|
static void print_commit(char sign, struct commit *commit, int verbose,
|
||||||
int abbrev)
|
int abbrev, FILE *file)
|
||||||
{
|
{
|
||||||
if (!verbose) {
|
if (!verbose) {
|
||||||
printf("%c %s\n", sign,
|
fprintf(file, "%c %s\n", sign,
|
||||||
find_unique_abbrev(commit->object.oid.hash, abbrev));
|
find_unique_abbrev(commit->object.oid.hash, abbrev));
|
||||||
} else {
|
} else {
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
|
pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
|
||||||
printf("%c %s %s\n", sign,
|
fprintf(file, "%c %s %s\n", sign,
|
||||||
find_unique_abbrev(commit->object.oid.hash, abbrev),
|
find_unique_abbrev(commit->object.oid.hash, abbrev),
|
||||||
buf.buf);
|
buf.buf);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
@@ -1883,7 +1909,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
|
|||||||
commit = list->item;
|
commit = list->item;
|
||||||
if (has_commit_patch_id(commit, &ids))
|
if (has_commit_patch_id(commit, &ids))
|
||||||
sign = '-';
|
sign = '-';
|
||||||
print_commit(sign, commit, verbose, abbrev);
|
print_commit(sign, commit, verbose, abbrev, revs.diffopt.file);
|
||||||
list = list->next;
|
list = list->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,8 @@ static void show_killed_files(struct dir_struct *dir)
|
|||||||
*/
|
*/
|
||||||
pos = cache_name_pos(ent->name, ent->len);
|
pos = cache_name_pos(ent->name, ent->len);
|
||||||
if (0 <= pos)
|
if (0 <= pos)
|
||||||
die("bug in show-killed-files");
|
die("BUG: killed-file %.*s not found",
|
||||||
|
ent->len, ent->name);
|
||||||
pos = -pos - 1;
|
pos = -pos - 1;
|
||||||
while (pos < active_nr &&
|
while (pos < active_nr &&
|
||||||
ce_stage(active_cache[pos]))
|
ce_stage(active_cache[pos]))
|
||||||
|
|||||||
@@ -45,6 +45,19 @@ static int is_from_line(const char *line, int len)
|
|||||||
|
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
static struct strbuf buf = STRBUF_INIT;
|
||||||
static int keep_cr;
|
static int keep_cr;
|
||||||
|
static int mboxrd;
|
||||||
|
|
||||||
|
static int is_gtfrom(const struct strbuf *buf)
|
||||||
|
{
|
||||||
|
size_t min = strlen(">From ");
|
||||||
|
size_t ngt;
|
||||||
|
|
||||||
|
if (buf->len < min)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ngt = strspn(buf->buf, ">");
|
||||||
|
return ngt && starts_with(buf->buf + ngt, "From ");
|
||||||
|
}
|
||||||
|
|
||||||
/* Called with the first line (potentially partial)
|
/* Called with the first line (potentially partial)
|
||||||
* already in buf[] -- normally that should begin with
|
* already in buf[] -- normally that should begin with
|
||||||
@@ -77,6 +90,9 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
|
|||||||
strbuf_addch(&buf, '\n');
|
strbuf_addch(&buf, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mboxrd && is_gtfrom(&buf))
|
||||||
|
strbuf_remove(&buf, 0, 1);
|
||||||
|
|
||||||
if (fwrite(buf.buf, 1, buf.len, output) != buf.len)
|
if (fwrite(buf.buf, 1, buf.len, output) != buf.len)
|
||||||
die_errno("cannot write output");
|
die_errno("cannot write output");
|
||||||
|
|
||||||
@@ -271,6 +287,8 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
|
|||||||
keep_cr = 1;
|
keep_cr = 1;
|
||||||
} else if ( arg[1] == 'o' && arg[2] ) {
|
} else if ( arg[1] == 'o' && arg[2] ) {
|
||||||
dir = arg+2;
|
dir = arg+2;
|
||||||
|
} else if (!strcmp(arg, "--mboxrd")) {
|
||||||
|
mboxrd = 1;
|
||||||
} else if ( arg[1] == '-' && !arg[2] ) {
|
} else if ( arg[1] == '-' && !arg[2] ) {
|
||||||
argp++; /* -- marks end of options */
|
argp++; /* -- marks end of options */
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ static const char builtin_merge_recursive_usage[] =
|
|||||||
|
|
||||||
static const char *better_branch_name(const char *branch)
|
static const char *better_branch_name(const char *branch)
|
||||||
{
|
{
|
||||||
static char githead_env[8 + 40 + 1];
|
static char githead_env[8 + GIT_SHA1_HEXSZ + 1];
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (strlen(branch) != 40)
|
if (strlen(branch) != GIT_SHA1_HEXSZ)
|
||||||
return branch;
|
return branch;
|
||||||
xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch);
|
xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch);
|
||||||
name = getenv(githead_env);
|
name = getenv(githead_env);
|
||||||
@@ -21,10 +21,10 @@ static const char *better_branch_name(const char *branch)
|
|||||||
|
|
||||||
int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
|
int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
const unsigned char *bases[21];
|
const struct object_id *bases[21];
|
||||||
unsigned bases_count = 0;
|
unsigned bases_count = 0;
|
||||||
int i, failed;
|
int i, failed;
|
||||||
unsigned char h1[20], h2[20];
|
struct object_id h1, h2;
|
||||||
struct merge_options o;
|
struct merge_options o;
|
||||||
struct commit *result;
|
struct commit *result;
|
||||||
|
|
||||||
@@ -46,10 +46,10 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bases_count < ARRAY_SIZE(bases)-1) {
|
if (bases_count < ARRAY_SIZE(bases)-1) {
|
||||||
unsigned char *sha = xmalloc(20);
|
struct object_id *oid = xmalloc(sizeof(struct object_id));
|
||||||
if (get_sha1(argv[i], sha))
|
if (get_oid(argv[i], oid))
|
||||||
die("Could not parse object '%s'", argv[i]);
|
die("Could not parse object '%s'", argv[i]);
|
||||||
bases[bases_count++] = sha;
|
bases[bases_count++] = oid;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
warning("Cannot handle more than %d bases. "
|
warning("Cannot handle more than %d bases. "
|
||||||
@@ -62,9 +62,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
|
|||||||
o.branch1 = argv[++i];
|
o.branch1 = argv[++i];
|
||||||
o.branch2 = argv[++i];
|
o.branch2 = argv[++i];
|
||||||
|
|
||||||
if (get_sha1(o.branch1, h1))
|
if (get_oid(o.branch1, &h1))
|
||||||
die("Could not resolve ref '%s'", o.branch1);
|
die("Could not resolve ref '%s'", o.branch1);
|
||||||
if (get_sha1(o.branch2, h2))
|
if (get_oid(o.branch2, &h2))
|
||||||
die("Could not resolve ref '%s'", o.branch2);
|
die("Could not resolve ref '%s'", o.branch2);
|
||||||
|
|
||||||
o.branch1 = better_branch_name(o.branch1);
|
o.branch1 = better_branch_name(o.branch1);
|
||||||
@@ -73,7 +73,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
|
|||||||
if (o.verbosity >= 3)
|
if (o.verbosity >= 3)
|
||||||
printf("Merging %s with %s\n", o.branch1, o.branch2);
|
printf("Merging %s with %s\n", o.branch1, o.branch2);
|
||||||
|
|
||||||
failed = merge_recursive_generic(&o, h1, h2, bases_count, bases, &result);
|
failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result);
|
||||||
if (failed < 0)
|
if (failed < 0)
|
||||||
return 128; /* die() error code */
|
return 128; /* die() error code */
|
||||||
return failed;
|
return failed;
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ static struct option builtin_merge_options[] = {
|
|||||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, FF_ONLY },
|
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, FF_ONLY },
|
||||||
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
|
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
|
||||||
OPT_BOOL(0, "verify-signatures", &verify_signatures,
|
OPT_BOOL(0, "verify-signatures", &verify_signatures,
|
||||||
N_("Verify that the named commit has a valid GPG signature")),
|
N_("verify that the named commit has a valid GPG signature")),
|
||||||
OPT_CALLBACK('s', "strategy", &use_strategies, N_("strategy"),
|
OPT_CALLBACK('s', "strategy", &use_strategies, N_("strategy"),
|
||||||
N_("merge strategy to use"), option_parse_strategy),
|
N_("merge strategy to use"), option_parse_strategy),
|
||||||
OPT_CALLBACK('X', "strategy-option", &xopts, N_("option=value"),
|
OPT_CALLBACK('X', "strategy-option", &xopts, N_("option=value"),
|
||||||
@@ -337,15 +337,9 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead
|
|||||||
struct rev_info rev;
|
struct rev_info rev;
|
||||||
struct strbuf out = STRBUF_INIT;
|
struct strbuf out = STRBUF_INIT;
|
||||||
struct commit_list *j;
|
struct commit_list *j;
|
||||||
const char *filename;
|
|
||||||
int fd;
|
|
||||||
struct pretty_print_context ctx = {0};
|
struct pretty_print_context ctx = {0};
|
||||||
|
|
||||||
printf(_("Squash commit -- not updating HEAD\n"));
|
printf(_("Squash commit -- not updating HEAD\n"));
|
||||||
filename = git_path_squash_msg();
|
|
||||||
fd = open(filename, O_WRONLY | O_CREAT, 0666);
|
|
||||||
if (fd < 0)
|
|
||||||
die_errno(_("Could not write to '%s'"), filename);
|
|
||||||
|
|
||||||
init_revisions(&rev, NULL);
|
init_revisions(&rev, NULL);
|
||||||
rev.ignore_merges = 1;
|
rev.ignore_merges = 1;
|
||||||
@@ -372,10 +366,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead
|
|||||||
oid_to_hex(&commit->object.oid));
|
oid_to_hex(&commit->object.oid));
|
||||||
pretty_print_commit(&ctx, commit, &out);
|
pretty_print_commit(&ctx, commit, &out);
|
||||||
}
|
}
|
||||||
if (write_in_full(fd, out.buf, out.len) != out.len)
|
write_file_buf(git_path_squash_msg(), out.buf, out.len);
|
||||||
die_errno(_("Writing SQUASH_MSG"));
|
|
||||||
if (close(fd))
|
|
||||||
die_errno(_("Finishing SQUASH_MSG"));
|
|
||||||
strbuf_release(&out);
|
strbuf_release(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +493,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
|||||||
if (ref_exists(truname.buf)) {
|
if (ref_exists(truname.buf)) {
|
||||||
strbuf_addf(msg,
|
strbuf_addf(msg,
|
||||||
"%s\t\tbranch '%s'%s of .\n",
|
"%s\t\tbranch '%s'%s of .\n",
|
||||||
sha1_to_hex(remote_head->object.oid.hash),
|
oid_to_hex(&remote_head->object.oid),
|
||||||
truname.buf + 11,
|
truname.buf + 11,
|
||||||
(early ? " (early part)" : ""));
|
(early ? " (early part)" : ""));
|
||||||
strbuf_release(&truname);
|
strbuf_release(&truname);
|
||||||
@@ -516,7 +507,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
|||||||
desc = merge_remote_util(remote_head);
|
desc = merge_remote_util(remote_head);
|
||||||
if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
|
if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
|
||||||
strbuf_addf(msg, "%s\t\t%s '%s'\n",
|
strbuf_addf(msg, "%s\t\t%s '%s'\n",
|
||||||
sha1_to_hex(desc->obj->oid.hash),
|
oid_to_hex(&desc->obj->oid),
|
||||||
typename(desc->obj->type),
|
typename(desc->obj->type),
|
||||||
remote);
|
remote);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -524,7 +515,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strbuf_addf(msg, "%s\t\tcommit '%s'\n",
|
strbuf_addf(msg, "%s\t\tcommit '%s'\n",
|
||||||
sha1_to_hex(remote_head->object.oid.hash), remote);
|
oid_to_hex(&remote_head->object.oid), remote);
|
||||||
cleanup:
|
cleanup:
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
strbuf_release(&bname);
|
strbuf_release(&bname);
|
||||||
@@ -683,6 +674,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
|
|||||||
hold_locked_index(&lock, 1);
|
hold_locked_index(&lock, 1);
|
||||||
clean = merge_recursive(&o, head,
|
clean = merge_recursive(&o, head,
|
||||||
remoteheads->item, reversed, &result);
|
remoteheads->item, reversed, &result);
|
||||||
|
if (clean < 0)
|
||||||
|
exit(128);
|
||||||
if (active_cache_changed &&
|
if (active_cache_changed &&
|
||||||
write_locked_index(&the_index, &lock, COMMIT_LOCK))
|
write_locked_index(&the_index, &lock, COMMIT_LOCK))
|
||||||
die (_("unable to write %s"), get_index_file());
|
die (_("unable to write %s"), get_index_file());
|
||||||
@@ -732,18 +725,6 @@ static void add_strategies(const char *string, unsigned attr)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_merge_msg(struct strbuf *msg)
|
|
||||||
{
|
|
||||||
const char *filename = git_path_merge_msg();
|
|
||||||
int fd = open(filename, O_WRONLY | O_CREAT, 0666);
|
|
||||||
if (fd < 0)
|
|
||||||
die_errno(_("Could not open '%s' for writing"),
|
|
||||||
filename);
|
|
||||||
if (write_in_full(fd, msg->buf, msg->len) != msg->len)
|
|
||||||
die_errno(_("Could not write to '%s'"), filename);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_merge_msg(struct strbuf *msg)
|
static void read_merge_msg(struct strbuf *msg)
|
||||||
{
|
{
|
||||||
const char *filename = git_path_merge_msg();
|
const char *filename = git_path_merge_msg();
|
||||||
@@ -777,7 +758,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)
|
|||||||
strbuf_addch(&msg, '\n');
|
strbuf_addch(&msg, '\n');
|
||||||
if (0 < option_edit)
|
if (0 < option_edit)
|
||||||
strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
|
strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
|
||||||
write_merge_msg(&msg);
|
write_file_buf(git_path_merge_msg(), msg.buf, msg.len);
|
||||||
if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
|
if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
|
||||||
git_path_merge_msg(), "merge", NULL))
|
git_path_merge_msg(), "merge", NULL))
|
||||||
abort_commit(remoteheads, NULL);
|
abort_commit(remoteheads, NULL);
|
||||||
@@ -940,8 +921,6 @@ static int setup_with_upstream(const char ***argv)
|
|||||||
|
|
||||||
static void write_merge_state(struct commit_list *remoteheads)
|
static void write_merge_state(struct commit_list *remoteheads)
|
||||||
{
|
{
|
||||||
const char *filename;
|
|
||||||
int fd;
|
|
||||||
struct commit_list *j;
|
struct commit_list *j;
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
@@ -955,26 +934,14 @@ static void write_merge_state(struct commit_list *remoteheads)
|
|||||||
}
|
}
|
||||||
strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
|
strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
|
||||||
}
|
}
|
||||||
filename = git_path_merge_head();
|
write_file_buf(git_path_merge_head(), buf.buf, buf.len);
|
||||||
fd = open(filename, O_WRONLY | O_CREAT, 0666);
|
|
||||||
if (fd < 0)
|
|
||||||
die_errno(_("Could not open '%s' for writing"), filename);
|
|
||||||
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
|
|
||||||
die_errno(_("Could not write to '%s'"), filename);
|
|
||||||
close(fd);
|
|
||||||
strbuf_addch(&merge_msg, '\n');
|
strbuf_addch(&merge_msg, '\n');
|
||||||
write_merge_msg(&merge_msg);
|
write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len);
|
||||||
|
|
||||||
filename = git_path_merge_mode();
|
|
||||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0)
|
|
||||||
die_errno(_("Could not open '%s' for writing"), filename);
|
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
if (fast_forward == FF_NO)
|
if (fast_forward == FF_NO)
|
||||||
strbuf_addf(&buf, "no-ff");
|
strbuf_addf(&buf, "no-ff");
|
||||||
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
|
write_file_buf(git_path_merge_mode(), buf.buf, buf.len);
|
||||||
die_errno(_("Could not write to '%s'"), filename);
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int default_edit_option(void)
|
static int default_edit_option(void)
|
||||||
@@ -990,7 +957,7 @@ static int default_edit_option(void)
|
|||||||
if (e) {
|
if (e) {
|
||||||
int v = git_config_maybe_bool(name, e);
|
int v = git_config_maybe_bool(name, e);
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
die("Bad value '%s' in environment '%s'", e, name);
|
die(_("Bad value '%s' in environment '%s'"), e, name);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1091,7 +1058,7 @@ static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge
|
|||||||
if (!commit) {
|
if (!commit) {
|
||||||
if (ptr)
|
if (ptr)
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
die("not something we can merge in %s: %s",
|
die(_("not something we can merge in %s: %s"),
|
||||||
filename, merge_names->buf + pos);
|
filename, merge_names->buf + pos);
|
||||||
}
|
}
|
||||||
remotes = &commit_list_insert(commit, remotes)->next;
|
remotes = &commit_list_insert(commit, remotes)->next;
|
||||||
@@ -1125,7 +1092,7 @@ static struct commit_list *collect_parents(struct commit *head_commit,
|
|||||||
struct commit *commit = get_merge_parent(argv[i]);
|
struct commit *commit = get_merge_parent(argv[i]);
|
||||||
if (!commit)
|
if (!commit)
|
||||||
help_unknown_ref(argv[i], "merge",
|
help_unknown_ref(argv[i], "merge",
|
||||||
"not something we can merge");
|
_("not something we can merge"));
|
||||||
remotes = &commit_list_insert(commit, remotes)->next;
|
remotes = &commit_list_insert(commit, remotes)->next;
|
||||||
}
|
}
|
||||||
remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
|
remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
|
||||||
@@ -1342,7 +1309,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||||||
for (p = remoteheads; p; p = p->next) {
|
for (p = remoteheads; p; p = p->next) {
|
||||||
struct commit *commit = p->item;
|
struct commit *commit = p->item;
|
||||||
strbuf_addf(&buf, "GITHEAD_%s",
|
strbuf_addf(&buf, "GITHEAD_%s",
|
||||||
sha1_to_hex(commit->object.oid.hash));
|
oid_to_hex(&commit->object.oid));
|
||||||
setenv(buf.buf, merge_remote_util(commit)->name, 1);
|
setenv(buf.buf, merge_remote_util(commit)->name, 1);
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
if (fast_forward != FF_ONLY &&
|
if (fast_forward != FF_ONLY &&
|
||||||
@@ -1397,11 +1364,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||||||
* If head can reach all the merge then we are up to date.
|
* If head can reach all the merge then we are up to date.
|
||||||
* but first the most common case of merging one remote.
|
* but first the most common case of merging one remote.
|
||||||
*/
|
*/
|
||||||
finish_up_to_date("Already up-to-date.");
|
finish_up_to_date(_("Already up-to-date."));
|
||||||
goto done;
|
goto done;
|
||||||
} else if (fast_forward != FF_NO && !remoteheads->next &&
|
} else if (fast_forward != FF_NO && !remoteheads->next &&
|
||||||
!common->next &&
|
!common->next &&
|
||||||
!hashcmp(common->item->object.oid.hash, head_commit->object.oid.hash)) {
|
!oidcmp(&common->item->object.oid, &head_commit->object.oid)) {
|
||||||
/* Again the most common case of merging one remote. */
|
/* Again the most common case of merging one remote. */
|
||||||
struct strbuf msg = STRBUF_INIT;
|
struct strbuf msg = STRBUF_INIT;
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
@@ -1475,14 +1442,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||||||
* HEAD^^" would be missed.
|
* HEAD^^" would be missed.
|
||||||
*/
|
*/
|
||||||
common_one = get_merge_bases(head_commit, j->item);
|
common_one = get_merge_bases(head_commit, j->item);
|
||||||
if (hashcmp(common_one->item->object.oid.hash,
|
if (oidcmp(&common_one->item->object.oid, &j->item->object.oid)) {
|
||||||
j->item->object.oid.hash)) {
|
|
||||||
up_to_date = 0;
|
up_to_date = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (up_to_date) {
|
if (up_to_date) {
|
||||||
finish_up_to_date("Already up-to-date. Yeeah!");
|
finish_up_to_date(_("Already up-to-date. Yeeah!"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1506,7 +1472,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||||||
* Stash away the local changes so that we can try more than one.
|
* Stash away the local changes so that we can try more than one.
|
||||||
*/
|
*/
|
||||||
save_state(stash))
|
save_state(stash))
|
||||||
hashcpy(stash, null_sha1);
|
hashclr(stash);
|
||||||
|
|
||||||
for (i = 0; i < use_strategies_nr; i++) {
|
for (i = 0; i < use_strategies_nr; i++) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ static const char * const git_notes_get_ref_usage[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char note_template[] =
|
static const char note_template[] =
|
||||||
"\nWrite/edit the notes for the following object:\n";
|
N_("Write/edit the notes for the following object:");
|
||||||
|
|
||||||
struct note_data {
|
struct note_data {
|
||||||
int given;
|
int given;
|
||||||
@@ -179,7 +179,8 @@ static void prepare_note_data(const unsigned char *object, struct note_data *d,
|
|||||||
copy_obj_to_fd(fd, old_note);
|
copy_obj_to_fd(fd, old_note);
|
||||||
|
|
||||||
strbuf_addch(&buf, '\n');
|
strbuf_addch(&buf, '\n');
|
||||||
strbuf_add_commented_lines(&buf, note_template, strlen(note_template));
|
strbuf_add_commented_lines(&buf, "\n", strlen("\n"));
|
||||||
|
strbuf_add_commented_lines(&buf, _(note_template), strlen(_(note_template)));
|
||||||
strbuf_addch(&buf, '\n');
|
strbuf_addch(&buf, '\n');
|
||||||
write_or_die(fd, buf.buf, buf.len);
|
write_or_die(fd, buf.buf, buf.len);
|
||||||
|
|
||||||
@@ -749,7 +750,7 @@ static int git_config_get_notes_strategy(const char *key,
|
|||||||
if (git_config_get_string(key, &value))
|
if (git_config_get_string(key, &value))
|
||||||
return 1;
|
return 1;
|
||||||
if (parse_notes_merge_strategy(value, strategy))
|
if (parse_notes_merge_strategy(value, strategy))
|
||||||
git_die_config(key, "unknown notes merge strategy %s", value);
|
git_die_config(key, _("unknown notes merge strategy %s"), value);
|
||||||
|
|
||||||
free(value);
|
free(value);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -788,15 +789,15 @@ static int merge(int argc, const char **argv, const char *prefix)
|
|||||||
if (strategy || do_commit + do_abort == 0)
|
if (strategy || do_commit + do_abort == 0)
|
||||||
do_merge = 1;
|
do_merge = 1;
|
||||||
if (do_merge + do_commit + do_abort != 1) {
|
if (do_merge + do_commit + do_abort != 1) {
|
||||||
error("cannot mix --commit, --abort or -s/--strategy");
|
error(_("cannot mix --commit, --abort or -s/--strategy"));
|
||||||
usage_with_options(git_notes_merge_usage, options);
|
usage_with_options(git_notes_merge_usage, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_merge && argc != 1) {
|
if (do_merge && argc != 1) {
|
||||||
error("Must specify a notes ref to merge");
|
error(_("Must specify a notes ref to merge"));
|
||||||
usage_with_options(git_notes_merge_usage, options);
|
usage_with_options(git_notes_merge_usage, options);
|
||||||
} else if (!do_merge && argc) {
|
} else if (!do_merge && argc) {
|
||||||
error("too many parameters");
|
error(_("too many parameters"));
|
||||||
usage_with_options(git_notes_merge_usage, options);
|
usage_with_options(git_notes_merge_usage, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,7 +818,7 @@ static int merge(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (strategy) {
|
if (strategy) {
|
||||||
if (parse_notes_merge_strategy(strategy, &o.strategy)) {
|
if (parse_notes_merge_strategy(strategy, &o.strategy)) {
|
||||||
error("Unknown -s/--strategy: %s", strategy);
|
error(_("Unknown -s/--strategy: %s"), strategy);
|
||||||
usage_with_options(git_notes_merge_usage, options);
|
usage_with_options(git_notes_merge_usage, options);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -857,11 +858,11 @@ static int merge(int argc, const char **argv, const char *prefix)
|
|||||||
die(_("A notes merge into %s is already in-progress at %s"),
|
die(_("A notes merge into %s is already in-progress at %s"),
|
||||||
default_notes_ref(), wt->path);
|
default_notes_ref(), wt->path);
|
||||||
if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
|
if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
|
||||||
die("Failed to store link to current notes ref (%s)",
|
die(_("Failed to store link to current notes ref (%s)"),
|
||||||
default_notes_ref());
|
default_notes_ref());
|
||||||
printf("Automatic notes merge failed. Fix conflicts in %s and "
|
printf(_("Automatic notes merge failed. Fix conflicts in %s and "
|
||||||
"commit the result with 'git notes merge --commit', or "
|
"commit the result with 'git notes merge --commit', or "
|
||||||
"abort the merge with 'git notes merge --abort'.\n",
|
"abort the merge with 'git notes merge --abort'.\n"),
|
||||||
git_path(NOTES_MERGE_WORKTREE));
|
git_path(NOTES_MERGE_WORKTREE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,8 +935,8 @@ static int prune(int argc, const char **argv, const char *prefix)
|
|||||||
struct notes_tree *t;
|
struct notes_tree *t;
|
||||||
int show_only = 0, verbose = 0;
|
int show_only = 0, verbose = 0;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT__DRY_RUN(&show_only, "do not remove, show only"),
|
OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
|
||||||
OPT__VERBOSE(&verbose, "report pruned notes"),
|
OPT__VERBOSE(&verbose, N_("report pruned notes")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -964,7 +965,7 @@ static int get_ref(int argc, const char **argv, const char *prefix)
|
|||||||
git_notes_get_ref_usage, 0);
|
git_notes_get_ref_usage, 0);
|
||||||
|
|
||||||
if (argc) {
|
if (argc) {
|
||||||
error("too many parameters");
|
error(_("too many parameters"));
|
||||||
usage_with_options(git_notes_get_ref_usage, options);
|
usage_with_options(git_notes_get_ref_usage, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ static int non_empty;
|
|||||||
static int reuse_delta = 1, reuse_object = 1;
|
static int reuse_delta = 1, reuse_object = 1;
|
||||||
static int keep_unreachable, unpack_unreachable, include_tag;
|
static int keep_unreachable, unpack_unreachable, include_tag;
|
||||||
static unsigned long unpack_unreachable_expiration;
|
static unsigned long unpack_unreachable_expiration;
|
||||||
|
static int pack_loose_unreachable;
|
||||||
static int local;
|
static int local;
|
||||||
|
static int have_non_local_packs;
|
||||||
static int incremental;
|
static int incremental;
|
||||||
static int ignore_packed_keep;
|
static int ignore_packed_keep;
|
||||||
static int allow_ofs_delta;
|
static int allow_ofs_delta;
|
||||||
@@ -977,6 +979,23 @@ static int want_object_in_pack(const unsigned char *sha1,
|
|||||||
return 1;
|
return 1;
|
||||||
if (incremental)
|
if (incremental)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When asked to do --local (do not include an
|
||||||
|
* object that appears in a pack we borrow
|
||||||
|
* from elsewhere) or --honor-pack-keep (do not
|
||||||
|
* include an object that appears in a pack marked
|
||||||
|
* with .keep), we need to make sure no copy of this
|
||||||
|
* object come from in _any_ pack that causes us to
|
||||||
|
* omit it, and need to complete this loop. When
|
||||||
|
* neither option is in effect, we know the object
|
||||||
|
* we just found is going to be packed, so break
|
||||||
|
* out of the loop to return 1 now.
|
||||||
|
*/
|
||||||
|
if (!ignore_packed_keep &&
|
||||||
|
(!local || !have_non_local_packs))
|
||||||
|
break;
|
||||||
|
|
||||||
if (local && !p->pack_local)
|
if (local && !p->pack_local)
|
||||||
return 0;
|
return 0;
|
||||||
if (ignore_packed_keep && p->pack_local && p->pack_keep)
|
if (ignore_packed_keep && p->pack_local && p->pack_keep)
|
||||||
@@ -2379,6 +2398,32 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
|
|||||||
free(in_pack.array);
|
free(in_pack.array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_loose_object(const unsigned char *sha1, const char *path,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
enum object_type type = sha1_object_info(sha1, NULL);
|
||||||
|
|
||||||
|
if (type < 0) {
|
||||||
|
warning("loose object at %s could not be examined", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_object_entry(sha1, type, "", 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We actually don't even have to worry about reachability here.
|
||||||
|
* add_object_entry will weed out duplicates, so we just add every
|
||||||
|
* loose object we find.
|
||||||
|
*/
|
||||||
|
static void add_unreachable_loose_objects(void)
|
||||||
|
{
|
||||||
|
for_each_loose_file_in_objdir(get_object_directory(),
|
||||||
|
add_loose_object,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
|
static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
static struct packed_git *last_found = (void *)1;
|
static struct packed_git *last_found = (void *)1;
|
||||||
@@ -2548,6 +2593,8 @@ static void get_object_list(int ac, const char **av)
|
|||||||
|
|
||||||
if (keep_unreachable)
|
if (keep_unreachable)
|
||||||
add_objects_in_unpacked_packs(&revs);
|
add_objects_in_unpacked_packs(&revs);
|
||||||
|
if (pack_loose_unreachable)
|
||||||
|
add_unreachable_loose_objects();
|
||||||
if (unpack_unreachable)
|
if (unpack_unreachable)
|
||||||
loosen_unused_packed_objects(&revs);
|
loosen_unused_packed_objects(&revs);
|
||||||
|
|
||||||
@@ -2648,6 +2695,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
|||||||
N_("include tag objects that refer to objects to be packed")),
|
N_("include tag objects that refer to objects to be packed")),
|
||||||
OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
|
OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
|
||||||
N_("keep unreachable objects")),
|
N_("keep unreachable objects")),
|
||||||
|
OPT_BOOL(0, "pack-loose-unreachable", &pack_loose_unreachable,
|
||||||
|
N_("pack loose unreachable objects")),
|
||||||
{ OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"),
|
{ OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"),
|
||||||
N_("unpack unreachable objects newer than <time>"),
|
N_("unpack unreachable objects newer than <time>"),
|
||||||
PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
|
PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
|
||||||
@@ -2753,6 +2802,28 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
|||||||
progress = 2;
|
progress = 2;
|
||||||
|
|
||||||
prepare_packed_git();
|
prepare_packed_git();
|
||||||
|
if (ignore_packed_keep) {
|
||||||
|
struct packed_git *p;
|
||||||
|
for (p = packed_git; p; p = p->next)
|
||||||
|
if (p->pack_local && p->pack_keep)
|
||||||
|
break;
|
||||||
|
if (!p) /* no keep-able packs found */
|
||||||
|
ignore_packed_keep = 0;
|
||||||
|
}
|
||||||
|
if (local) {
|
||||||
|
/*
|
||||||
|
* unlike ignore_packed_keep above, we do not want to
|
||||||
|
* unset "local" based on looking at packs, as it
|
||||||
|
* also covers non-local objects
|
||||||
|
*/
|
||||||
|
struct packed_git *p;
|
||||||
|
for (p = packed_git; p; p = p->next) {
|
||||||
|
if (!p->pack_local) {
|
||||||
|
have_non_local_packs = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (progress)
|
if (progress)
|
||||||
progress_state = start_progress(_("Counting objects"), 0);
|
progress_state = start_progress(_("Counting objects"), 0);
|
||||||
|
|||||||
@@ -815,6 +815,9 @@ static int run_rebase(const unsigned char *curr_head,
|
|||||||
argv_array_push(&args, "--no-autostash");
|
argv_array_push(&args, "--no-autostash");
|
||||||
else if (opt_autostash == 1)
|
else if (opt_autostash == 1)
|
||||||
argv_array_push(&args, "--autostash");
|
argv_array_push(&args, "--autostash");
|
||||||
|
if (opt_verify_signatures &&
|
||||||
|
!strcmp(opt_verify_signatures, "--verify-signatures"))
|
||||||
|
warning(_("ignoring --verify-signatures for rebase"));
|
||||||
|
|
||||||
argv_array_push(&args, "--onto");
|
argv_array_push(&args, "--onto");
|
||||||
argv_array_push(&args, sha1_to_hex(merge_head));
|
argv_array_push(&args, sha1_to_hex(merge_head));
|
||||||
@@ -852,7 +855,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
|
|||||||
git_config(git_pull_config, NULL);
|
git_config(git_pull_config, NULL);
|
||||||
|
|
||||||
if (read_cache_unmerged())
|
if (read_cache_unmerged())
|
||||||
die_resolve_conflict("Pull");
|
die_resolve_conflict("pull");
|
||||||
|
|
||||||
if (file_exists(git_path("MERGE_HEAD")))
|
if (file_exists(git_path("MERGE_HEAD")))
|
||||||
die_conclude_merge();
|
die_conclude_merge();
|
||||||
|
|||||||
@@ -353,7 +353,8 @@ static int push_with_options(struct transport *transport, int flags)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_push(const char *repo, int flags)
|
static int do_push(const char *repo, int flags,
|
||||||
|
const struct string_list *push_options)
|
||||||
{
|
{
|
||||||
int i, errs;
|
int i, errs;
|
||||||
struct remote *remote = pushremote_get(repo);
|
struct remote *remote = pushremote_get(repo);
|
||||||
@@ -376,6 +377,9 @@ static int do_push(const char *repo, int flags)
|
|||||||
if (remote->mirror)
|
if (remote->mirror)
|
||||||
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
|
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
|
||||||
|
|
||||||
|
if (push_options->nr)
|
||||||
|
flags |= TRANSPORT_PUSH_OPTIONS;
|
||||||
|
|
||||||
if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
|
if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
|
||||||
if (!strcmp(*refspec, "refs/tags/*"))
|
if (!strcmp(*refspec, "refs/tags/*"))
|
||||||
return error(_("--all and --tags are incompatible"));
|
return error(_("--all and --tags are incompatible"));
|
||||||
@@ -406,13 +410,16 @@ static int do_push(const char *repo, int flags)
|
|||||||
for (i = 0; i < url_nr; i++) {
|
for (i = 0; i < url_nr; i++) {
|
||||||
struct transport *transport =
|
struct transport *transport =
|
||||||
transport_get(remote, url[i]);
|
transport_get(remote, url[i]);
|
||||||
|
if (flags & TRANSPORT_PUSH_OPTIONS)
|
||||||
|
transport->push_options = push_options;
|
||||||
if (push_with_options(transport, flags))
|
if (push_with_options(transport, flags))
|
||||||
errs++;
|
errs++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct transport *transport =
|
struct transport *transport =
|
||||||
transport_get(remote, NULL);
|
transport_get(remote, NULL);
|
||||||
|
if (flags & TRANSPORT_PUSH_OPTIONS)
|
||||||
|
transport->push_options = push_options;
|
||||||
if (push_with_options(transport, flags))
|
if (push_with_options(transport, flags))
|
||||||
errs++;
|
errs++;
|
||||||
}
|
}
|
||||||
@@ -500,6 +507,9 @@ int cmd_push(int argc, const char **argv, const char *prefix)
|
|||||||
int push_cert = -1;
|
int push_cert = -1;
|
||||||
int rc;
|
int rc;
|
||||||
const char *repo = NULL; /* default repository */
|
const char *repo = NULL; /* default repository */
|
||||||
|
static struct string_list push_options = STRING_LIST_INIT_DUP;
|
||||||
|
static struct string_list_item *item;
|
||||||
|
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT__VERBOSITY(&verbosity),
|
OPT__VERBOSITY(&verbosity),
|
||||||
OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
|
OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
|
||||||
@@ -533,6 +543,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
|
|||||||
0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
|
0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
|
||||||
PARSE_OPT_OPTARG, option_parse_push_signed },
|
PARSE_OPT_OPTARG, option_parse_push_signed },
|
||||||
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
|
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
|
||||||
|
OPT_STRING_LIST('o', "push-option", &push_options, N_("server-specific"), N_("option to transmit")),
|
||||||
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
|
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
|
||||||
TRANSPORT_FAMILY_IPV4),
|
TRANSPORT_FAMILY_IPV4),
|
||||||
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
|
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
|
||||||
@@ -563,7 +574,11 @@ int cmd_push(int argc, const char **argv, const char *prefix)
|
|||||||
set_refspecs(argv + 1, argc - 1, repo);
|
set_refspecs(argv + 1, argc - 1, repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = do_push(repo, flags);
|
for_each_string_list_item(item, &push_options)
|
||||||
|
if (strchr(item->string, '\n'))
|
||||||
|
die(_("push options must not have new line characters"));
|
||||||
|
|
||||||
|
rc = do_push(repo, flags, &push_options);
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
usage_with_options(push_usage, options);
|
usage_with_options(push_usage, options);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -44,10 +44,12 @@ static struct strbuf fsck_msg_types = STRBUF_INIT;
|
|||||||
static int receive_unpack_limit = -1;
|
static int receive_unpack_limit = -1;
|
||||||
static int transfer_unpack_limit = -1;
|
static int transfer_unpack_limit = -1;
|
||||||
static int advertise_atomic_push = 1;
|
static int advertise_atomic_push = 1;
|
||||||
|
static int advertise_push_options;
|
||||||
static int unpack_limit = 100;
|
static int unpack_limit = 100;
|
||||||
static int report_status;
|
static int report_status;
|
||||||
static int use_sideband;
|
static int use_sideband;
|
||||||
static int use_atomic;
|
static int use_atomic;
|
||||||
|
static int use_push_options;
|
||||||
static int quiet;
|
static int quiet;
|
||||||
static int prefer_ofs_delta = 1;
|
static int prefer_ofs_delta = 1;
|
||||||
static int auto_update_server_info;
|
static int auto_update_server_info;
|
||||||
@@ -76,6 +78,13 @@ static long nonce_stamp_slop;
|
|||||||
static unsigned long nonce_stamp_slop_limit;
|
static unsigned long nonce_stamp_slop_limit;
|
||||||
static struct ref_transaction *transaction;
|
static struct ref_transaction *transaction;
|
||||||
|
|
||||||
|
static enum {
|
||||||
|
KEEPALIVE_NEVER = 0,
|
||||||
|
KEEPALIVE_AFTER_NUL,
|
||||||
|
KEEPALIVE_ALWAYS
|
||||||
|
} use_keepalive;
|
||||||
|
static int keepalive_in_sec = 5;
|
||||||
|
|
||||||
static enum deny_action parse_deny_action(const char *var, const char *value)
|
static enum deny_action parse_deny_action(const char *var, const char *value)
|
||||||
{
|
{
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -193,6 +202,16 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(var, "receive.advertisepushoptions") == 0) {
|
||||||
|
advertise_push_options = git_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(var, "receive.keepalive") == 0) {
|
||||||
|
keepalive_in_sec = git_config_int(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return git_default_config(var, value, cb);
|
return git_default_config(var, value, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +230,8 @@ static void show_ref(const char *path, const unsigned char *sha1)
|
|||||||
strbuf_addstr(&cap, " ofs-delta");
|
strbuf_addstr(&cap, " ofs-delta");
|
||||||
if (push_cert_nonce)
|
if (push_cert_nonce)
|
||||||
strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
|
strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
|
||||||
|
if (advertise_push_options)
|
||||||
|
strbuf_addstr(&cap, " push-options");
|
||||||
strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
|
strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
|
||||||
packet_write(1, "%s %s%c%s\n",
|
packet_write(1, "%s %s%c%s\n",
|
||||||
sha1_to_hex(sha1), path, 0, cap.buf);
|
sha1_to_hex(sha1), path, 0, cap.buf);
|
||||||
@@ -319,10 +340,60 @@ static void rp_error(const char *err, ...)
|
|||||||
static int copy_to_sideband(int in, int out, void *arg)
|
static int copy_to_sideband(int in, int out, void *arg)
|
||||||
{
|
{
|
||||||
char data[128];
|
char data[128];
|
||||||
|
int keepalive_active = 0;
|
||||||
|
|
||||||
|
if (keepalive_in_sec <= 0)
|
||||||
|
use_keepalive = KEEPALIVE_NEVER;
|
||||||
|
if (use_keepalive == KEEPALIVE_ALWAYS)
|
||||||
|
keepalive_active = 1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ssize_t sz = xread(in, data, sizeof(data));
|
ssize_t sz;
|
||||||
|
|
||||||
|
if (keepalive_active) {
|
||||||
|
struct pollfd pfd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pfd.fd = in;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
ret = poll(&pfd, 1, 1000 * keepalive_in_sec);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
/* no data; send a keepalive packet */
|
||||||
|
static const char buf[] = "0005\1";
|
||||||
|
write_or_die(1, buf, sizeof(buf) - 1);
|
||||||
|
continue;
|
||||||
|
} /* else there is actual data to read */
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = xread(in, data, sizeof(data));
|
||||||
if (sz <= 0)
|
if (sz <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (use_keepalive == KEEPALIVE_AFTER_NUL && !keepalive_active) {
|
||||||
|
const char *p = memchr(data, '\0', sz);
|
||||||
|
if (p) {
|
||||||
|
/*
|
||||||
|
* The NUL tells us to start sending keepalives. Make
|
||||||
|
* sure we send any other data we read along
|
||||||
|
* with it.
|
||||||
|
*/
|
||||||
|
keepalive_active = 1;
|
||||||
|
send_sideband(1, 2, data, p - data, use_sideband);
|
||||||
|
send_sideband(1, 2, p + 1, sz - (p - data + 1), use_sideband);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Either we're not looking for a NUL signal, or we didn't see
|
||||||
|
* it yet; just pass along the data.
|
||||||
|
*/
|
||||||
send_sideband(1, 2, data, sz, use_sideband);
|
send_sideband(1, 2, data, sz, use_sideband);
|
||||||
}
|
}
|
||||||
close(in);
|
close(in);
|
||||||
@@ -550,8 +621,16 @@ static void prepare_push_cert_sha1(struct child_process *proc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct receive_hook_feed_state {
|
||||||
|
struct command *cmd;
|
||||||
|
int skip_broken;
|
||||||
|
struct strbuf buf;
|
||||||
|
const struct string_list *push_options;
|
||||||
|
};
|
||||||
|
|
||||||
typedef int (*feed_fn)(void *, const char **, size_t *);
|
typedef int (*feed_fn)(void *, const char **, size_t *);
|
||||||
static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state)
|
static int run_and_feed_hook(const char *hook_name, feed_fn feed,
|
||||||
|
struct receive_hook_feed_state *feed_state)
|
||||||
{
|
{
|
||||||
struct child_process proc = CHILD_PROCESS_INIT;
|
struct child_process proc = CHILD_PROCESS_INIT;
|
||||||
struct async muxer;
|
struct async muxer;
|
||||||
@@ -567,6 +646,16 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
|
|||||||
proc.argv = argv;
|
proc.argv = argv;
|
||||||
proc.in = -1;
|
proc.in = -1;
|
||||||
proc.stdout_to_stderr = 1;
|
proc.stdout_to_stderr = 1;
|
||||||
|
if (feed_state->push_options) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < feed_state->push_options->nr; i++)
|
||||||
|
argv_array_pushf(&proc.env_array,
|
||||||
|
"GIT_PUSH_OPTION_%d=%s", i,
|
||||||
|
feed_state->push_options->items[i].string);
|
||||||
|
argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d",
|
||||||
|
feed_state->push_options->nr);
|
||||||
|
} else
|
||||||
|
argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT");
|
||||||
|
|
||||||
if (use_sideband) {
|
if (use_sideband) {
|
||||||
memset(&muxer, 0, sizeof(muxer));
|
memset(&muxer, 0, sizeof(muxer));
|
||||||
@@ -606,12 +695,6 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
|
|||||||
return finish_command(&proc);
|
return finish_command(&proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct receive_hook_feed_state {
|
|
||||||
struct command *cmd;
|
|
||||||
int skip_broken;
|
|
||||||
struct strbuf buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
|
static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
|
||||||
{
|
{
|
||||||
struct receive_hook_feed_state *state = state_;
|
struct receive_hook_feed_state *state = state_;
|
||||||
@@ -634,8 +717,10 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_receive_hook(struct command *commands, const char *hook_name,
|
static int run_receive_hook(struct command *commands,
|
||||||
int skip_broken)
|
const char *hook_name,
|
||||||
|
int skip_broken,
|
||||||
|
const struct string_list *push_options)
|
||||||
{
|
{
|
||||||
struct receive_hook_feed_state state;
|
struct receive_hook_feed_state state;
|
||||||
int status;
|
int status;
|
||||||
@@ -646,6 +731,7 @@ static int run_receive_hook(struct command *commands, const char *hook_name,
|
|||||||
if (feed_receive_hook(&state, NULL, NULL))
|
if (feed_receive_hook(&state, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
state.cmd = commands;
|
state.cmd = commands;
|
||||||
|
state.push_options = push_options;
|
||||||
status = run_and_feed_hook(hook_name, feed_receive_hook, &state);
|
status = run_and_feed_hook(hook_name, feed_receive_hook, &state);
|
||||||
strbuf_release(&state.buf);
|
strbuf_release(&state.buf);
|
||||||
return status;
|
return status;
|
||||||
@@ -737,7 +823,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
|
|||||||
{
|
{
|
||||||
static struct lock_file shallow_lock;
|
static struct lock_file shallow_lock;
|
||||||
struct sha1_array extra = SHA1_ARRAY_INIT;
|
struct sha1_array extra = SHA1_ARRAY_INIT;
|
||||||
const char *alt_file;
|
struct check_connected_options opt = CHECK_CONNECTED_INIT;
|
||||||
uint32_t mask = 1 << (cmd->index % 32);
|
uint32_t mask = 1 << (cmd->index % 32);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -749,9 +835,8 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
|
|||||||
!delayed_reachability_test(si, i))
|
!delayed_reachability_test(si, i))
|
||||||
sha1_array_append(&extra, si->shallow->sha1[i]);
|
sha1_array_append(&extra, si->shallow->sha1[i]);
|
||||||
|
|
||||||
setup_alternate_shallow(&shallow_lock, &alt_file, &extra);
|
setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra);
|
||||||
if (check_shallow_connected(command_singleton_iterator,
|
if (check_connected(command_singleton_iterator, cmd, &opt)) {
|
||||||
0, cmd, alt_file)) {
|
|
||||||
rollback_lock_file(&shallow_lock);
|
rollback_lock_file(&shallow_lock);
|
||||||
sha1_array_clear(&extra);
|
sha1_array_clear(&extra);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1160,8 +1245,8 @@ static void set_connectivity_errors(struct command *commands,
|
|||||||
if (shallow_update && si->shallow_ref[cmd->index])
|
if (shallow_update && si->shallow_ref[cmd->index])
|
||||||
/* to be checked in update_shallow_ref() */
|
/* to be checked in update_shallow_ref() */
|
||||||
continue;
|
continue;
|
||||||
if (!check_everything_connected(command_singleton_iterator,
|
if (!check_connected(command_singleton_iterator, &singleton,
|
||||||
0, &singleton))
|
NULL))
|
||||||
continue;
|
continue;
|
||||||
cmd->error_string = "missing necessary objects";
|
cmd->error_string = "missing necessary objects";
|
||||||
}
|
}
|
||||||
@@ -1316,11 +1401,15 @@ cleanup:
|
|||||||
|
|
||||||
static void execute_commands(struct command *commands,
|
static void execute_commands(struct command *commands,
|
||||||
const char *unpacker_error,
|
const char *unpacker_error,
|
||||||
struct shallow_info *si)
|
struct shallow_info *si,
|
||||||
|
const struct string_list *push_options)
|
||||||
{
|
{
|
||||||
|
struct check_connected_options opt = CHECK_CONNECTED_INIT;
|
||||||
struct command *cmd;
|
struct command *cmd;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
struct iterate_data data;
|
struct iterate_data data;
|
||||||
|
struct async muxer;
|
||||||
|
int err_fd = 0;
|
||||||
|
|
||||||
if (unpacker_error) {
|
if (unpacker_error) {
|
||||||
for (cmd = commands; cmd; cmd = cmd->next)
|
for (cmd = commands; cmd; cmd = cmd->next)
|
||||||
@@ -1328,14 +1417,28 @@ static void execute_commands(struct command *commands,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_sideband) {
|
||||||
|
memset(&muxer, 0, sizeof(muxer));
|
||||||
|
muxer.proc = copy_to_sideband;
|
||||||
|
muxer.in = -1;
|
||||||
|
if (!start_async(&muxer))
|
||||||
|
err_fd = muxer.in;
|
||||||
|
/* ...else, continue without relaying sideband */
|
||||||
|
}
|
||||||
|
|
||||||
data.cmds = commands;
|
data.cmds = commands;
|
||||||
data.si = si;
|
data.si = si;
|
||||||
if (check_everything_connected(iterate_receive_command_list, 0, &data))
|
opt.err_fd = err_fd;
|
||||||
|
opt.progress = err_fd && !quiet;
|
||||||
|
if (check_connected(iterate_receive_command_list, &data, &opt))
|
||||||
set_connectivity_errors(commands, si);
|
set_connectivity_errors(commands, si);
|
||||||
|
|
||||||
|
if (use_sideband)
|
||||||
|
finish_async(&muxer);
|
||||||
|
|
||||||
reject_updates_to_hidden(commands);
|
reject_updates_to_hidden(commands);
|
||||||
|
|
||||||
if (run_receive_hook(commands, "pre-receive", 0)) {
|
if (run_receive_hook(commands, "pre-receive", 0, push_options)) {
|
||||||
for (cmd = commands; cmd; cmd = cmd->next) {
|
for (cmd = commands; cmd; cmd = cmd->next) {
|
||||||
if (!cmd->error_string)
|
if (!cmd->error_string)
|
||||||
cmd->error_string = "pre-receive hook declined";
|
cmd->error_string = "pre-receive hook declined";
|
||||||
@@ -1437,6 +1540,9 @@ static struct command *read_head_info(struct sha1_array *shallow)
|
|||||||
if (advertise_atomic_push
|
if (advertise_atomic_push
|
||||||
&& parse_feature_request(feature_list, "atomic"))
|
&& parse_feature_request(feature_list, "atomic"))
|
||||||
use_atomic = 1;
|
use_atomic = 1;
|
||||||
|
if (advertise_push_options
|
||||||
|
&& parse_feature_request(feature_list, "push-options"))
|
||||||
|
use_push_options = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(line, "push-cert")) {
|
if (!strcmp(line, "push-cert")) {
|
||||||
@@ -1469,6 +1575,21 @@ static struct command *read_head_info(struct sha1_array *shallow)
|
|||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void read_push_options(struct string_list *options)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
char *line;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
line = packet_read_line(0, &len);
|
||||||
|
|
||||||
|
if (!line)
|
||||||
|
break;
|
||||||
|
|
||||||
|
string_list_append(options, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const char *parse_pack_header(struct pack_header *hdr)
|
static const char *parse_pack_header(struct pack_header *hdr)
|
||||||
{
|
{
|
||||||
switch (read_pack_header(0, hdr)) {
|
switch (read_pack_header(0, hdr)) {
|
||||||
@@ -1546,6 +1667,10 @@ static const char *unpack(int err_fd, struct shallow_info *si)
|
|||||||
(uintmax_t)getpid(),
|
(uintmax_t)getpid(),
|
||||||
hostname);
|
hostname);
|
||||||
|
|
||||||
|
if (!quiet && err_fd)
|
||||||
|
argv_array_push(&child.args, "--show-resolving-progress");
|
||||||
|
if (use_sideband)
|
||||||
|
argv_array_push(&child.args, "--report-end-of-input");
|
||||||
if (fsck_objects)
|
if (fsck_objects)
|
||||||
argv_array_pushf(&child.args, "--strict%s",
|
argv_array_pushf(&child.args, "--strict%s",
|
||||||
fsck_msg_types.buf);
|
fsck_msg_types.buf);
|
||||||
@@ -1575,6 +1700,7 @@ static const char *unpack_with_sideband(struct shallow_info *si)
|
|||||||
if (!use_sideband)
|
if (!use_sideband)
|
||||||
return unpack(0, si);
|
return unpack(0, si);
|
||||||
|
|
||||||
|
use_keepalive = KEEPALIVE_AFTER_NUL;
|
||||||
memset(&muxer, 0, sizeof(muxer));
|
memset(&muxer, 0, sizeof(muxer));
|
||||||
muxer.proc = copy_to_sideband;
|
muxer.proc = copy_to_sideband;
|
||||||
muxer.in = -1;
|
muxer.in = -1;
|
||||||
@@ -1754,6 +1880,10 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if ((commands = read_head_info(&shallow)) != NULL) {
|
if ((commands = read_head_info(&shallow)) != NULL) {
|
||||||
const char *unpack_status = NULL;
|
const char *unpack_status = NULL;
|
||||||
|
struct string_list push_options = STRING_LIST_INIT_DUP;
|
||||||
|
|
||||||
|
if (use_push_options)
|
||||||
|
read_push_options(&push_options);
|
||||||
|
|
||||||
prepare_shallow_info(&si, &shallow);
|
prepare_shallow_info(&si, &shallow);
|
||||||
if (!si.nr_ours && !si.nr_theirs)
|
if (!si.nr_ours && !si.nr_theirs)
|
||||||
@@ -1762,20 +1892,36 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
|||||||
unpack_status = unpack_with_sideband(&si);
|
unpack_status = unpack_with_sideband(&si);
|
||||||
update_shallow_info(commands, &si, &ref);
|
update_shallow_info(commands, &si, &ref);
|
||||||
}
|
}
|
||||||
execute_commands(commands, unpack_status, &si);
|
use_keepalive = KEEPALIVE_ALWAYS;
|
||||||
|
execute_commands(commands, unpack_status, &si,
|
||||||
|
&push_options);
|
||||||
if (pack_lockfile)
|
if (pack_lockfile)
|
||||||
unlink_or_warn(pack_lockfile);
|
unlink_or_warn(pack_lockfile);
|
||||||
if (report_status)
|
if (report_status)
|
||||||
report(commands, unpack_status);
|
report(commands, unpack_status);
|
||||||
run_receive_hook(commands, "post-receive", 1);
|
run_receive_hook(commands, "post-receive", 1,
|
||||||
|
&push_options);
|
||||||
run_update_post_hook(commands);
|
run_update_post_hook(commands);
|
||||||
|
if (push_options.nr)
|
||||||
|
string_list_clear(&push_options, 0);
|
||||||
if (auto_gc) {
|
if (auto_gc) {
|
||||||
const char *argv_gc_auto[] = {
|
const char *argv_gc_auto[] = {
|
||||||
"gc", "--auto", "--quiet", NULL,
|
"gc", "--auto", "--quiet", NULL,
|
||||||
};
|
};
|
||||||
int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR;
|
struct child_process proc = CHILD_PROCESS_INIT;
|
||||||
|
|
||||||
|
proc.no_stdin = 1;
|
||||||
|
proc.stdout_to_stderr = 1;
|
||||||
|
proc.err = use_sideband ? -1 : 0;
|
||||||
|
proc.git_cmd = 1;
|
||||||
|
proc.argv = argv_gc_auto;
|
||||||
|
|
||||||
close_all_packs();
|
close_all_packs();
|
||||||
run_command_v_opt(argv_gc_auto, opt);
|
if (!start_command(&proc)) {
|
||||||
|
if (use_sideband)
|
||||||
|
copy_to_sideband(proc.err, -1, NULL);
|
||||||
|
finish_command(&proc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (auto_update_server_info)
|
if (auto_update_server_info)
|
||||||
update_server_info(0);
|
update_server_info(0);
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ struct branch_info {
|
|||||||
enum { NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE } rebase;
|
enum { NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE } rebase;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct string_list branch_list;
|
static struct string_list branch_list = STRING_LIST_INIT_NODUP;
|
||||||
|
|
||||||
static const char *abbrev_ref(const char *name, const char *prefix)
|
static const char *abbrev_ref(const char *name, const char *prefix)
|
||||||
{
|
{
|
||||||
@@ -539,10 +539,6 @@ static int add_branch_for_removal(const char *refname,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure that symrefs are deleted */
|
|
||||||
if (flags & REF_ISSYMREF)
|
|
||||||
return unlink(git_path("%s", refname));
|
|
||||||
|
|
||||||
string_list_append(branches->branches, refname);
|
string_list_append(branches->branches, refname);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -788,7 +784,7 @@ static int rm(int argc, const char **argv)
|
|||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
result = delete_refs(&branches);
|
result = delete_refs(&branches, REF_NODEREF);
|
||||||
string_list_clear(&branches, 0);
|
string_list_clear(&branches, 0);
|
||||||
|
|
||||||
if (skipped.nr) {
|
if (skipped.nr) {
|
||||||
@@ -952,7 +948,7 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
|
|||||||
struct show_info *show_info = cb_data;
|
struct show_info *show_info = cb_data;
|
||||||
struct branch_info *branch_info = item->util;
|
struct branch_info *branch_info = item->util;
|
||||||
struct string_list *merge = &branch_info->merge;
|
struct string_list *merge = &branch_info->merge;
|
||||||
const char *also;
|
int width = show_info->width + 4;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (branch_info->rebase && branch_info->merge.nr > 1) {
|
if (branch_info->rebase && branch_info->merge.nr > 1) {
|
||||||
@@ -963,19 +959,18 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
|
|||||||
|
|
||||||
printf(" %-*s ", show_info->width, item->string);
|
printf(" %-*s ", show_info->width, item->string);
|
||||||
if (branch_info->rebase) {
|
if (branch_info->rebase) {
|
||||||
printf_ln(_(branch_info->rebase == INTERACTIVE_REBASE ?
|
printf_ln(branch_info->rebase == INTERACTIVE_REBASE
|
||||||
"rebases interactively onto remote %s" :
|
? _("rebases interactively onto remote %s")
|
||||||
"rebases onto remote %s"), merge->items[0].string);
|
: _("rebases onto remote %s"), merge->items[0].string);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (show_info->any_rebase) {
|
} else if (show_info->any_rebase) {
|
||||||
printf_ln(_(" merges with remote %s"), merge->items[0].string);
|
printf_ln(_(" merges with remote %s"), merge->items[0].string);
|
||||||
also = _(" and with remote");
|
width++;
|
||||||
} else {
|
} else {
|
||||||
printf_ln(_("merges with remote %s"), merge->items[0].string);
|
printf_ln(_("merges with remote %s"), merge->items[0].string);
|
||||||
also = _(" and with remote");
|
|
||||||
}
|
}
|
||||||
for (i = 1; i < merge->nr; i++)
|
for (i = 1; i < merge->nr; i++)
|
||||||
printf(" %-*s %s %s\n", show_info->width, "", also,
|
printf(_("%-*s and with remote %s\n"), width, "",
|
||||||
merge->items[i].string);
|
merge->items[i].string);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1158,11 +1153,11 @@ static int show(int argc, const char **argv)
|
|||||||
the one in " Fetch URL: %s" translation */
|
the one in " Fetch URL: %s" translation */
|
||||||
printf_ln(_(" Push URL: %s"), url[i]);
|
printf_ln(_(" Push URL: %s"), url[i]);
|
||||||
if (!i)
|
if (!i)
|
||||||
printf_ln(_(" Push URL: %s"), "(no URL)");
|
printf_ln(_(" Push URL: %s"), _("(no URL)"));
|
||||||
if (no_query)
|
if (no_query)
|
||||||
printf_ln(_(" HEAD branch: %s"), "(not queried)");
|
printf_ln(_(" HEAD branch: %s"), _("(not queried)"));
|
||||||
else if (!states.heads.nr)
|
else if (!states.heads.nr)
|
||||||
printf_ln(_(" HEAD branch: %s"), "(unknown)");
|
printf_ln(_(" HEAD branch: %s"), _("(unknown)"));
|
||||||
else if (states.heads.nr == 1)
|
else if (states.heads.nr == 1)
|
||||||
printf_ln(_(" HEAD branch: %s"), states.heads.items[0].string);
|
printf_ln(_(" HEAD branch: %s"), states.heads.items[0].string);
|
||||||
else {
|
else {
|
||||||
@@ -1305,7 +1300,7 @@ static int prune_remote(const char *remote, int dry_run)
|
|||||||
string_list_sort(&refs_to_prune);
|
string_list_sort(&refs_to_prune);
|
||||||
|
|
||||||
if (!dry_run)
|
if (!dry_run)
|
||||||
result |= delete_refs(&refs_to_prune);
|
result |= delete_refs(&refs_to_prune, 0);
|
||||||
|
|
||||||
for_each_string_list_item(item, &states.stale) {
|
for_each_string_list_item(item, &states.stale) {
|
||||||
const char *refname = item->util;
|
const char *refname = item->util;
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
|||||||
int pack_everything = 0;
|
int pack_everything = 0;
|
||||||
int delete_redundant = 0;
|
int delete_redundant = 0;
|
||||||
const char *unpack_unreachable = NULL;
|
const char *unpack_unreachable = NULL;
|
||||||
|
int keep_unreachable = 0;
|
||||||
const char *window = NULL, *window_memory = NULL;
|
const char *window = NULL, *window_memory = NULL;
|
||||||
const char *depth = NULL;
|
const char *depth = NULL;
|
||||||
const char *max_pack_size = NULL;
|
const char *max_pack_size = NULL;
|
||||||
@@ -175,6 +176,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
|||||||
N_("write bitmap index")),
|
N_("write bitmap index")),
|
||||||
OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
|
OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
|
||||||
N_("with -A, do not loosen objects older than this")),
|
N_("with -A, do not loosen objects older than this")),
|
||||||
|
OPT_BOOL('k', "keep-unreachable", &keep_unreachable,
|
||||||
|
N_("with -a, repack unreachable objects")),
|
||||||
OPT_STRING(0, "window", &window, N_("n"),
|
OPT_STRING(0, "window", &window, N_("n"),
|
||||||
N_("size of the window used for delta compression")),
|
N_("size of the window used for delta compression")),
|
||||||
OPT_STRING(0, "window-memory", &window_memory, N_("bytes"),
|
OPT_STRING(0, "window-memory", &window_memory, N_("bytes"),
|
||||||
@@ -196,6 +199,10 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
|||||||
if (delete_redundant && repository_format_precious_objects)
|
if (delete_redundant && repository_format_precious_objects)
|
||||||
die(_("cannot delete packs in a precious-objects repo"));
|
die(_("cannot delete packs in a precious-objects repo"));
|
||||||
|
|
||||||
|
if (keep_unreachable &&
|
||||||
|
(unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
|
||||||
|
die(_("--keep-unreachable and -A are incompatible"));
|
||||||
|
|
||||||
if (pack_kept_objects < 0)
|
if (pack_kept_objects < 0)
|
||||||
pack_kept_objects = write_bitmaps;
|
pack_kept_objects = write_bitmaps;
|
||||||
|
|
||||||
@@ -239,6 +246,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
|||||||
} else if (pack_everything & LOOSEN_UNREACHABLE) {
|
} else if (pack_everything & LOOSEN_UNREACHABLE) {
|
||||||
argv_array_push(&cmd.args,
|
argv_array_push(&cmd.args,
|
||||||
"--unpack-unreachable");
|
"--unpack-unreachable");
|
||||||
|
} else if (keep_unreachable) {
|
||||||
|
argv_array_push(&cmd.args, "--keep-unreachable");
|
||||||
|
argv_array_push(&cmd.args, "--pack-loose-unreachable");
|
||||||
} else {
|
} else {
|
||||||
argv_array_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
|
argv_array_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
|
||||||
}
|
}
|
||||||
@@ -378,7 +388,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
|
|||||||
item->string,
|
item->string,
|
||||||
exts[ext].name);
|
exts[ext].name);
|
||||||
if (remove_path(fname))
|
if (remove_path(fname))
|
||||||
warning(_("removing '%s' failed"), fname);
|
warning(_("failed to remove '%s'"), fname);
|
||||||
free(fname);
|
free(fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
|
|||||||
|
|
||||||
for (i = 0; i < q->nr; i++) {
|
for (i = 0; i < q->nr; i++) {
|
||||||
struct diff_filespec *one = q->queue[i]->one;
|
struct diff_filespec *one = q->queue[i]->one;
|
||||||
int is_missing = !(one->mode && !is_null_sha1(one->sha1));
|
int is_missing = !(one->mode && !is_null_oid(&one->oid));
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
|
|
||||||
if (is_missing && !intent_to_add) {
|
if (is_missing && !intent_to_add) {
|
||||||
@@ -129,7 +129,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ce = make_cache_entry(one->mode, one->sha1, one->path,
|
ce = make_cache_entry(one->mode, one->oid.hash, one->path,
|
||||||
0, 0);
|
0, 0);
|
||||||
if (!ce)
|
if (!ce)
|
||||||
die(_("make_cache_entry failed for path '%s'"),
|
die(_("make_cache_entry failed for path '%s'"),
|
||||||
@@ -158,7 +158,7 @@ static int read_from_tree(const struct pathspec *pathspec,
|
|||||||
return 1;
|
return 1;
|
||||||
diffcore_std(&opt);
|
diffcore_std(&opt);
|
||||||
diff_flush(&opt);
|
diff_flush(&opt);
|
||||||
free_pathspec(&opt.pathspec);
|
clear_pathspec(&opt.pathspec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "log-tree.h"
|
#include "log-tree.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "bisect.h"
|
#include "bisect.h"
|
||||||
|
#include "progress.h"
|
||||||
|
|
||||||
static const char rev_list_usage[] =
|
static const char rev_list_usage[] =
|
||||||
"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
|
"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
|
||||||
@@ -49,12 +50,17 @@ static const char rev_list_usage[] =
|
|||||||
" --bisect-all"
|
" --bisect-all"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
static struct progress *progress;
|
||||||
|
static unsigned progress_counter;
|
||||||
|
|
||||||
static void finish_commit(struct commit *commit, void *data);
|
static void finish_commit(struct commit *commit, void *data);
|
||||||
static void show_commit(struct commit *commit, void *data)
|
static void show_commit(struct commit *commit, void *data)
|
||||||
{
|
{
|
||||||
struct rev_list_info *info = data;
|
struct rev_list_info *info = data;
|
||||||
struct rev_info *revs = info->revs;
|
struct rev_info *revs = info->revs;
|
||||||
|
|
||||||
|
display_progress(progress, ++progress_counter);
|
||||||
|
|
||||||
if (info->flags & REV_LIST_QUIET) {
|
if (info->flags & REV_LIST_QUIET) {
|
||||||
finish_commit(commit, data);
|
finish_commit(commit, data);
|
||||||
return;
|
return;
|
||||||
@@ -190,6 +196,7 @@ static void show_object(struct object *obj, const char *name, void *cb_data)
|
|||||||
{
|
{
|
||||||
struct rev_list_info *info = cb_data;
|
struct rev_list_info *info = cb_data;
|
||||||
finish_object(obj, name, cb_data);
|
finish_object(obj, name, cb_data);
|
||||||
|
display_progress(progress, ++progress_counter);
|
||||||
if (info->flags & REV_LIST_QUIET)
|
if (info->flags & REV_LIST_QUIET)
|
||||||
return;
|
return;
|
||||||
show_object_with_name(stdout, obj, name);
|
show_object_with_name(stdout, obj, name);
|
||||||
@@ -276,6 +283,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||||||
int bisect_show_vars = 0;
|
int bisect_show_vars = 0;
|
||||||
int bisect_find_all = 0;
|
int bisect_find_all = 0;
|
||||||
int use_bitmap_index = 0;
|
int use_bitmap_index = 0;
|
||||||
|
const char *show_progress = NULL;
|
||||||
|
|
||||||
git_config(git_default_config, NULL);
|
git_config(git_default_config, NULL);
|
||||||
init_revisions(&revs, prefix);
|
init_revisions(&revs, prefix);
|
||||||
@@ -325,6 +333,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||||||
test_bitmap_walk(&revs);
|
test_bitmap_walk(&revs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (skip_prefix(arg, "--progress=", &arg)) {
|
||||||
|
show_progress = arg;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
usage(rev_list_usage);
|
usage(rev_list_usage);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -355,6 +367,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||||||
if (bisect_list)
|
if (bisect_list)
|
||||||
revs.limited = 1;
|
revs.limited = 1;
|
||||||
|
|
||||||
|
if (show_progress)
|
||||||
|
progress = start_progress_delay(show_progress, 0, 0, 2);
|
||||||
|
|
||||||
if (use_bitmap_index && !revs.prune) {
|
if (use_bitmap_index && !revs.prune) {
|
||||||
if (revs.count && !revs.left_right && !revs.cherry_mark) {
|
if (revs.count && !revs.left_right && !revs.cherry_mark) {
|
||||||
uint32_t commit_count;
|
uint32_t commit_count;
|
||||||
@@ -392,6 +407,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
traverse_commit_list(&revs, show_commit, show_object, &info);
|
traverse_commit_list(&revs, show_commit, show_object, &info);
|
||||||
|
|
||||||
|
stop_progress(&progress);
|
||||||
|
|
||||||
if (revs.count) {
|
if (revs.count) {
|
||||||
if (revs.left_right && revs.cherry_mark)
|
if (revs.left_right && revs.cherry_mark)
|
||||||
printf("%d\t%d\t%d\n", revs.count_left, revs.count_right, revs.count_same);
|
printf("%d\t%d\t%d\n", revs.count_left, revs.count_right, revs.count_same);
|
||||||
|
|||||||
@@ -233,11 +233,11 @@ void shortlog_init(struct shortlog *log)
|
|||||||
|
|
||||||
int cmd_shortlog(int argc, const char **argv, const char *prefix)
|
int cmd_shortlog(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
static struct shortlog log;
|
struct shortlog log = { STRING_LIST_INIT_NODUP };
|
||||||
static struct rev_info rev;
|
struct rev_info rev;
|
||||||
int nongit = !startup_info->have_repository;
|
int nongit = !startup_info->have_repository;
|
||||||
|
|
||||||
static const struct option options[] = {
|
const struct option options[] = {
|
||||||
OPT_BOOL('n', "numbered", &log.sort_by_number,
|
OPT_BOOL('n', "numbered", &log.sort_by_number,
|
||||||
N_("sort output according to the number of commits per author")),
|
N_("sort output according to the number of commits per author")),
|
||||||
OPT_BOOL('s', "summary", &log.summary,
|
OPT_BOOL('s', "summary", &log.summary,
|
||||||
@@ -276,6 +276,7 @@ parse_done:
|
|||||||
|
|
||||||
log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
|
log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
|
||||||
log.abbrev = rev.abbrev;
|
log.abbrev = rev.abbrev;
|
||||||
|
log.file = rev.diffopt.file;
|
||||||
|
|
||||||
/* assume HEAD if from a tty */
|
/* assume HEAD if from a tty */
|
||||||
if (!nongit && !rev.pending.nr && isatty(0))
|
if (!nongit && !rev.pending.nr && isatty(0))
|
||||||
@@ -289,6 +290,8 @@ parse_done:
|
|||||||
get_from_rev(&rev, &log);
|
get_from_rev(&rev, &log);
|
||||||
|
|
||||||
shortlog_output(&log);
|
shortlog_output(&log);
|
||||||
|
if (log.file != stdout)
|
||||||
|
fclose(log.file);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,22 +313,24 @@ void shortlog_output(struct shortlog *log)
|
|||||||
for (i = 0; i < log->list.nr; i++) {
|
for (i = 0; i < log->list.nr; i++) {
|
||||||
const struct string_list_item *item = &log->list.items[i];
|
const struct string_list_item *item = &log->list.items[i];
|
||||||
if (log->summary) {
|
if (log->summary) {
|
||||||
printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string);
|
fprintf(log->file, "%6d\t%s\n",
|
||||||
|
(int)UTIL_TO_INT(item), item->string);
|
||||||
} else {
|
} else {
|
||||||
struct string_list *onelines = item->util;
|
struct string_list *onelines = item->util;
|
||||||
printf("%s (%d):\n", item->string, onelines->nr);
|
fprintf(log->file, "%s (%d):\n",
|
||||||
|
item->string, onelines->nr);
|
||||||
for (j = onelines->nr - 1; j >= 0; j--) {
|
for (j = onelines->nr - 1; j >= 0; j--) {
|
||||||
const char *msg = onelines->items[j].string;
|
const char *msg = onelines->items[j].string;
|
||||||
|
|
||||||
if (log->wrap_lines) {
|
if (log->wrap_lines) {
|
||||||
strbuf_reset(&sb);
|
strbuf_reset(&sb);
|
||||||
add_wrapped_shortlog_msg(&sb, msg, log);
|
add_wrapped_shortlog_msg(&sb, msg, log);
|
||||||
fwrite(sb.buf, sb.len, 1, stdout);
|
fwrite(sb.buf, sb.len, 1, log->file);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf(" %s\n", msg);
|
fprintf(log->file, " %s\n", msg);
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putc('\n', log->file);
|
||||||
onelines->strdup_strings = 1;
|
onelines->strdup_strings = 1;
|
||||||
string_list_clear(onelines, 0);
|
string_list_clear(onelines, 0);
|
||||||
free(onelines);
|
free(onelines);
|
||||||
|
|||||||
@@ -444,8 +444,7 @@ static int module_name(int argc, const char **argv, const char *prefix)
|
|||||||
static int clone_submodule(const char *path, const char *gitdir, const char *url,
|
static int clone_submodule(const char *path, const char *gitdir, const char *url,
|
||||||
const char *depth, const char *reference, int quiet)
|
const char *depth, const char *reference, int quiet)
|
||||||
{
|
{
|
||||||
struct child_process cp;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
child_process_init(&cp);
|
|
||||||
|
|
||||||
argv_array_push(&cp.args, "clone");
|
argv_array_push(&cp.args, "clone");
|
||||||
argv_array_push(&cp.args, "--no-checkout");
|
argv_array_push(&cp.args, "--no-checkout");
|
||||||
@@ -579,6 +578,7 @@ struct submodule_update_clone {
|
|||||||
|
|
||||||
/* configuration parameters which are passed on to the children */
|
/* configuration parameters which are passed on to the children */
|
||||||
int quiet;
|
int quiet;
|
||||||
|
int recommend_shallow;
|
||||||
const char *reference;
|
const char *reference;
|
||||||
const char *depth;
|
const char *depth;
|
||||||
const char *recursive_prefix;
|
const char *recursive_prefix;
|
||||||
@@ -589,10 +589,14 @@ struct submodule_update_clone {
|
|||||||
|
|
||||||
/* If we want to stop as fast as possible and return an error */
|
/* If we want to stop as fast as possible and return an error */
|
||||||
unsigned quickstop : 1;
|
unsigned quickstop : 1;
|
||||||
|
|
||||||
|
/* failed clones to be retried again */
|
||||||
|
const struct cache_entry **failed_clones;
|
||||||
|
int failed_clones_nr, failed_clones_alloc;
|
||||||
};
|
};
|
||||||
#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
|
#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
|
||||||
SUBMODULE_UPDATE_STRATEGY_INIT, 0, NULL, NULL, NULL, NULL, \
|
SUBMODULE_UPDATE_STRATEGY_INIT, 0, -1, NULL, NULL, NULL, NULL, \
|
||||||
STRING_LIST_INIT_DUP, 0}
|
STRING_LIST_INIT_DUP, 0, NULL, 0, 0}
|
||||||
|
|
||||||
|
|
||||||
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
|
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
|
||||||
@@ -696,6 +700,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
|
|||||||
argv_array_push(&child->args, "--quiet");
|
argv_array_push(&child->args, "--quiet");
|
||||||
if (suc->prefix)
|
if (suc->prefix)
|
||||||
argv_array_pushl(&child->args, "--prefix", suc->prefix, NULL);
|
argv_array_pushl(&child->args, "--prefix", suc->prefix, NULL);
|
||||||
|
if (suc->recommend_shallow && sub->recommend_shallow == 1)
|
||||||
|
argv_array_push(&child->args, "--depth=1");
|
||||||
argv_array_pushl(&child->args, "--path", sub->path, NULL);
|
argv_array_pushl(&child->args, "--path", sub->path, NULL);
|
||||||
argv_array_pushl(&child->args, "--name", sub->name, NULL);
|
argv_array_pushl(&child->args, "--name", sub->name, NULL);
|
||||||
argv_array_pushl(&child->args, "--url", url, NULL);
|
argv_array_pushl(&child->args, "--url", url, NULL);
|
||||||
@@ -715,23 +721,51 @@ cleanup:
|
|||||||
static int update_clone_get_next_task(struct child_process *child,
|
static int update_clone_get_next_task(struct child_process *child,
|
||||||
struct strbuf *err,
|
struct strbuf *err,
|
||||||
void *suc_cb,
|
void *suc_cb,
|
||||||
void **void_task_cb)
|
void **idx_task_cb)
|
||||||
{
|
{
|
||||||
struct submodule_update_clone *suc = suc_cb;
|
struct submodule_update_clone *suc = suc_cb;
|
||||||
|
const struct cache_entry *ce;
|
||||||
|
int index;
|
||||||
|
|
||||||
for (; suc->current < suc->list.nr; suc->current++) {
|
for (; suc->current < suc->list.nr; suc->current++) {
|
||||||
const struct cache_entry *ce = suc->list.entries[suc->current];
|
ce = suc->list.entries[suc->current];
|
||||||
if (prepare_to_clone_next_submodule(ce, child, suc, err)) {
|
if (prepare_to_clone_next_submodule(ce, child, suc, err)) {
|
||||||
|
int *p = xmalloc(sizeof(*p));
|
||||||
|
*p = suc->current;
|
||||||
|
*idx_task_cb = p;
|
||||||
suc->current++;
|
suc->current++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The loop above tried cloning each submodule once, now try the
|
||||||
|
* stragglers again, which we can imagine as an extension of the
|
||||||
|
* entry list.
|
||||||
|
*/
|
||||||
|
index = suc->current - suc->list.nr;
|
||||||
|
if (index < suc->failed_clones_nr) {
|
||||||
|
int *p;
|
||||||
|
ce = suc->failed_clones[index];
|
||||||
|
if (!prepare_to_clone_next_submodule(ce, child, suc, err)) {
|
||||||
|
suc->current ++;
|
||||||
|
strbuf_addf(err, "BUG: submodule considered for cloning,"
|
||||||
|
"doesn't need cloning any more?\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
p = xmalloc(sizeof(*p));
|
||||||
|
*p = suc->current;
|
||||||
|
*idx_task_cb = p;
|
||||||
|
suc->current ++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int update_clone_start_failure(struct strbuf *err,
|
static int update_clone_start_failure(struct strbuf *err,
|
||||||
void *suc_cb,
|
void *suc_cb,
|
||||||
void *void_task_cb)
|
void *idx_task_cb)
|
||||||
{
|
{
|
||||||
struct submodule_update_clone *suc = suc_cb;
|
struct submodule_update_clone *suc = suc_cb;
|
||||||
suc->quickstop = 1;
|
suc->quickstop = 1;
|
||||||
@@ -741,15 +775,39 @@ static int update_clone_start_failure(struct strbuf *err,
|
|||||||
static int update_clone_task_finished(int result,
|
static int update_clone_task_finished(int result,
|
||||||
struct strbuf *err,
|
struct strbuf *err,
|
||||||
void *suc_cb,
|
void *suc_cb,
|
||||||
void *void_task_cb)
|
void *idx_task_cb)
|
||||||
{
|
{
|
||||||
|
const struct cache_entry *ce;
|
||||||
struct submodule_update_clone *suc = suc_cb;
|
struct submodule_update_clone *suc = suc_cb;
|
||||||
|
|
||||||
|
int *idxP = *(int**)idx_task_cb;
|
||||||
|
int idx = *idxP;
|
||||||
|
free(idxP);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
suc->quickstop = 1;
|
if (idx < suc->list.nr) {
|
||||||
return 1;
|
ce = suc->list.entries[idx];
|
||||||
|
strbuf_addf(err, _("Failed to clone '%s'. Retry scheduled"),
|
||||||
|
ce->name);
|
||||||
|
strbuf_addch(err, '\n');
|
||||||
|
ALLOC_GROW(suc->failed_clones,
|
||||||
|
suc->failed_clones_nr + 1,
|
||||||
|
suc->failed_clones_alloc);
|
||||||
|
suc->failed_clones[suc->failed_clones_nr++] = ce;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
idx -= suc->list.nr;
|
||||||
|
ce = suc->failed_clones[idx];
|
||||||
|
strbuf_addf(err, _("Failed to clone '%s' a second time, aborting"),
|
||||||
|
ce->name);
|
||||||
|
strbuf_addch(err, '\n');
|
||||||
|
suc->quickstop = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int update_clone(int argc, const char **argv, const char *prefix)
|
static int update_clone(int argc, const char **argv, const char *prefix)
|
||||||
@@ -778,6 +836,8 @@ static int update_clone(int argc, const char **argv, const char *prefix)
|
|||||||
"specified number of revisions")),
|
"specified number of revisions")),
|
||||||
OPT_INTEGER('j', "jobs", &max_jobs,
|
OPT_INTEGER('j', "jobs", &max_jobs,
|
||||||
N_("parallel jobs")),
|
N_("parallel jobs")),
|
||||||
|
OPT_BOOL(0, "recommend-shallow", &suc.recommend_shallow,
|
||||||
|
N_("whether the initial clone should follow the shallow recommendation")),
|
||||||
OPT__QUIET(&suc.quiet, N_("don't print cloning progress")),
|
OPT__QUIET(&suc.quiet, N_("don't print cloning progress")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
@@ -835,13 +895,64 @@ static int resolve_relative_path(int argc, const char **argv, const char *prefix
|
|||||||
{
|
{
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
if (argc != 3)
|
if (argc != 3)
|
||||||
die("submodule--helper relative_path takes exactly 2 arguments, got %d", argc);
|
die("submodule--helper relative-path takes exactly 2 arguments, got %d", argc);
|
||||||
|
|
||||||
printf("%s", relative_path(argv[1], argv[2], &sb));
|
printf("%s", relative_path(argv[1], argv[2], &sb));
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *remote_submodule_branch(const char *path)
|
||||||
|
{
|
||||||
|
const struct submodule *sub;
|
||||||
|
gitmodules_config();
|
||||||
|
git_config(submodule_config, NULL);
|
||||||
|
|
||||||
|
sub = submodule_from_path(null_sha1, path);
|
||||||
|
if (!sub)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!sub->branch)
|
||||||
|
return "master";
|
||||||
|
|
||||||
|
if (!strcmp(sub->branch, ".")) {
|
||||||
|
unsigned char sha1[20];
|
||||||
|
const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
|
||||||
|
|
||||||
|
if (!refname)
|
||||||
|
die(_("No such ref: %s"), "HEAD");
|
||||||
|
|
||||||
|
/* detached HEAD */
|
||||||
|
if (!strcmp(refname, "HEAD"))
|
||||||
|
die(_("Submodule (%s) branch configured to inherit "
|
||||||
|
"branch from superproject, but the superproject "
|
||||||
|
"is not on any branch"), sub->name);
|
||||||
|
|
||||||
|
if (!skip_prefix(refname, "refs/heads/", &refname))
|
||||||
|
die(_("Expecting a full ref name, got %s"), refname);
|
||||||
|
return refname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sub->branch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int resolve_remote_submodule_branch(int argc, const char **argv,
|
||||||
|
const char *prefix)
|
||||||
|
{
|
||||||
|
const char *ret;
|
||||||
|
struct strbuf sb = STRBUF_INIT;
|
||||||
|
if (argc != 2)
|
||||||
|
die("submodule--helper remote-branch takes exactly one arguments, got %d", argc);
|
||||||
|
|
||||||
|
ret = remote_submodule_branch(argv[1]);
|
||||||
|
if (!ret)
|
||||||
|
die("submodule %s doesn't exist", argv[1]);
|
||||||
|
|
||||||
|
printf("%s", ret);
|
||||||
|
strbuf_release(&sb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct cmd_struct {
|
struct cmd_struct {
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
int (*fn)(int, const char **, const char *);
|
int (*fn)(int, const char **, const char *);
|
||||||
@@ -855,7 +966,8 @@ static struct cmd_struct commands[] = {
|
|||||||
{"relative-path", resolve_relative_path},
|
{"relative-path", resolve_relative_path},
|
||||||
{"resolve-relative-url", resolve_relative_url},
|
{"resolve-relative-url", resolve_relative_url},
|
||||||
{"resolve-relative-url-test", resolve_relative_url_test},
|
{"resolve-relative-url-test", resolve_relative_url_test},
|
||||||
{"init", module_init}
|
{"init", module_init},
|
||||||
|
{"remote-branch", resolve_remote_submodule_branch}
|
||||||
};
|
};
|
||||||
|
|
||||||
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
|
|||||||
return; /* we are done */
|
return; /* we are done */
|
||||||
else {
|
else {
|
||||||
/* cannot resolve yet --- queue it */
|
/* cannot resolve yet --- queue it */
|
||||||
hashcpy(obj_list[nr].sha1, null_sha1);
|
hashclr(obj_list[nr].sha1);
|
||||||
add_delta_to_list(nr, base_sha1, 0, delta_data, delta_size);
|
add_delta_to_list(nr, base_sha1, 0, delta_data, delta_size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -406,7 +406,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
|
|||||||
* The delta base object is itself a delta that
|
* The delta base object is itself a delta that
|
||||||
* has not been resolved yet.
|
* has not been resolved yet.
|
||||||
*/
|
*/
|
||||||
hashcpy(obj_list[nr].sha1, null_sha1);
|
hashclr(obj_list[nr].sha1);
|
||||||
add_delta_to_list(nr, null_sha1, base_offset, delta_data, delta_size);
|
add_delta_to_list(nr, null_sha1, base_offset, delta_data, delta_size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -759,7 +759,7 @@ static int do_reupdate(int ac, const char **av,
|
|||||||
if (save_nr != active_nr)
|
if (save_nr != active_nr)
|
||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
free_pathspec(&pathspec);
|
clear_pathspec(&pathspec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1146,7 +1146,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
|
|||||||
report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
|
report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
die("Bug: bad untracked_cache value: %d", untracked_cache);
|
die("BUG: bad untracked_cache value: %d", untracked_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active_cache_changed) {
|
if (active_cache_changed) {
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
|
|
||||||
static const char * const worktree_usage[] = {
|
static const char * const worktree_usage[] = {
|
||||||
N_("git worktree add [<options>] <path> [<branch>]"),
|
N_("git worktree add [<options>] <path> [<branch>]"),
|
||||||
N_("git worktree prune [<options>]"),
|
|
||||||
N_("git worktree list [<options>]"),
|
N_("git worktree list [<options>]"),
|
||||||
|
N_("git worktree lock [<options>] <path>"),
|
||||||
|
N_("git worktree prune [<options>]"),
|
||||||
|
N_("git worktree unlock <path>"),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,7 +97,7 @@ static void prune_worktrees(void)
|
|||||||
if (!dir)
|
if (!dir)
|
||||||
return;
|
return;
|
||||||
while ((d = readdir(dir)) != NULL) {
|
while ((d = readdir(dir)) != NULL) {
|
||||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
if (is_dot_or_dotdot(d->d_name))
|
||||||
continue;
|
continue;
|
||||||
strbuf_reset(&reason);
|
strbuf_reset(&reason);
|
||||||
if (!prune_worktree(d->d_name, &reason))
|
if (!prune_worktree(d->d_name, &reason))
|
||||||
@@ -192,7 +194,7 @@ static int add_worktree(const char *path, const char *refname,
|
|||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
const char *name;
|
const char *name;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct child_process cp;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
struct argv_array child_env = ARGV_ARRAY_INIT;
|
struct argv_array child_env = ARGV_ARRAY_INIT;
|
||||||
int counter = 0, len, ret;
|
int counter = 0, len, ret;
|
||||||
struct strbuf symref = STRBUF_INIT;
|
struct strbuf symref = STRBUF_INIT;
|
||||||
@@ -262,7 +264,7 @@ static int add_worktree(const char *path, const char *refname,
|
|||||||
*/
|
*/
|
||||||
strbuf_reset(&sb);
|
strbuf_reset(&sb);
|
||||||
strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
|
strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
|
||||||
write_file(sb.buf, "0000000000000000000000000000000000000000");
|
write_file(sb.buf, "%s", sha1_to_hex(null_sha1));
|
||||||
strbuf_reset(&sb);
|
strbuf_reset(&sb);
|
||||||
strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
|
strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
|
||||||
write_file(sb.buf, "../..");
|
write_file(sb.buf, "../..");
|
||||||
@@ -271,7 +273,6 @@ static int add_worktree(const char *path, const char *refname,
|
|||||||
|
|
||||||
argv_array_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
|
argv_array_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
|
||||||
argv_array_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
|
argv_array_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
|
||||||
memset(&cp, 0, sizeof(cp));
|
|
||||||
cp.git_cmd = 1;
|
cp.git_cmd = 1;
|
||||||
|
|
||||||
if (commit)
|
if (commit)
|
||||||
@@ -337,9 +338,12 @@ static int add(int ac, const char **av, const char *prefix)
|
|||||||
if (ac < 1 || ac > 2)
|
if (ac < 1 || ac > 2)
|
||||||
usage_with_options(worktree_usage, options);
|
usage_with_options(worktree_usage, options);
|
||||||
|
|
||||||
path = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0];
|
path = prefix_filename(prefix, strlen(prefix), av[0]);
|
||||||
branch = ac < 2 ? "HEAD" : av[1];
|
branch = ac < 2 ? "HEAD" : av[1];
|
||||||
|
|
||||||
|
if (!strcmp(branch, "-"))
|
||||||
|
branch = "@{-1}";
|
||||||
|
|
||||||
opts.force_new_branch = !!new_branch_force;
|
opts.force_new_branch = !!new_branch_force;
|
||||||
if (opts.force_new_branch) {
|
if (opts.force_new_branch) {
|
||||||
struct strbuf symref = STRBUF_INIT;
|
struct strbuf symref = STRBUF_INIT;
|
||||||
@@ -360,8 +364,7 @@ static int add(int ac, const char **av, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (opts.new_branch) {
|
if (opts.new_branch) {
|
||||||
struct child_process cp;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
memset(&cp, 0, sizeof(cp));
|
|
||||||
cp.git_cmd = 1;
|
cp.git_cmd = 1;
|
||||||
argv_array_push(&cp.args, "branch");
|
argv_array_push(&cp.args, "branch");
|
||||||
if (opts.force_new_branch)
|
if (opts.force_new_branch)
|
||||||
@@ -459,6 +462,66 @@ static int list(int ac, const char **av, const char *prefix)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lock_worktree(int ac, const char **av, const char *prefix)
|
||||||
|
{
|
||||||
|
const char *reason = "", *old_reason;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_STRING(0, "reason", &reason, N_("string"),
|
||||||
|
N_("reason for locking")),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
struct worktree **worktrees, *wt;
|
||||||
|
|
||||||
|
ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
|
||||||
|
if (ac != 1)
|
||||||
|
usage_with_options(worktree_usage, options);
|
||||||
|
|
||||||
|
worktrees = get_worktrees();
|
||||||
|
wt = find_worktree(worktrees, prefix, av[0]);
|
||||||
|
if (!wt)
|
||||||
|
die(_("'%s' is not a working tree"), av[0]);
|
||||||
|
if (is_main_worktree(wt))
|
||||||
|
die(_("The main working tree cannot be locked or unlocked"));
|
||||||
|
|
||||||
|
old_reason = is_worktree_locked(wt);
|
||||||
|
if (old_reason) {
|
||||||
|
if (*old_reason)
|
||||||
|
die(_("'%s' is already locked, reason: %s"),
|
||||||
|
av[0], old_reason);
|
||||||
|
die(_("'%s' is already locked"), av[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_file(git_common_path("worktrees/%s/locked", wt->id),
|
||||||
|
"%s", reason);
|
||||||
|
free_worktrees(worktrees);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int unlock_worktree(int ac, const char **av, const char *prefix)
|
||||||
|
{
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
struct worktree **worktrees, *wt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
|
||||||
|
if (ac != 1)
|
||||||
|
usage_with_options(worktree_usage, options);
|
||||||
|
|
||||||
|
worktrees = get_worktrees();
|
||||||
|
wt = find_worktree(worktrees, prefix, av[0]);
|
||||||
|
if (!wt)
|
||||||
|
die(_("'%s' is not a working tree"), av[0]);
|
||||||
|
if (is_main_worktree(wt))
|
||||||
|
die(_("The main working tree cannot be locked or unlocked"));
|
||||||
|
if (!is_worktree_locked(wt))
|
||||||
|
die(_("'%s' is not locked"), av[0]);
|
||||||
|
ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id));
|
||||||
|
free_worktrees(worktrees);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_worktree(int ac, const char **av, const char *prefix)
|
int cmd_worktree(int ac, const char **av, const char *prefix)
|
||||||
{
|
{
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
@@ -467,11 +530,17 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
|
|||||||
|
|
||||||
if (ac < 2)
|
if (ac < 2)
|
||||||
usage_with_options(worktree_usage, options);
|
usage_with_options(worktree_usage, options);
|
||||||
|
if (!prefix)
|
||||||
|
prefix = "";
|
||||||
if (!strcmp(av[1], "add"))
|
if (!strcmp(av[1], "add"))
|
||||||
return add(ac - 1, av + 1, prefix);
|
return add(ac - 1, av + 1, prefix);
|
||||||
if (!strcmp(av[1], "prune"))
|
if (!strcmp(av[1], "prune"))
|
||||||
return prune(ac - 1, av + 1, prefix);
|
return prune(ac - 1, av + 1, prefix);
|
||||||
if (!strcmp(av[1], "list"))
|
if (!strcmp(av[1], "list"))
|
||||||
return list(ac - 1, av + 1, prefix);
|
return list(ac - 1, av + 1, prefix);
|
||||||
|
if (!strcmp(av[1], "lock"))
|
||||||
|
return lock_worktree(ac - 1, av + 1, prefix);
|
||||||
|
if (!strcmp(av[1], "unlock"))
|
||||||
|
return unlock_worktree(ac - 1, av + 1, prefix);
|
||||||
usage_with_options(worktree_usage, options);
|
usage_with_options(worktree_usage, options);
|
||||||
}
|
}
|
||||||
|
|||||||
54
cache.h
54
cache.h
@@ -1004,6 +1004,11 @@ int adjust_shared_perm(const char *path);
|
|||||||
* directory while we were working. To be robust against this kind of
|
* directory while we were working. To be robust against this kind of
|
||||||
* race, callers might want to try invoking the function again when it
|
* race, callers might want to try invoking the function again when it
|
||||||
* returns SCLD_VANISHED.
|
* returns SCLD_VANISHED.
|
||||||
|
*
|
||||||
|
* safe_create_leading_directories() temporarily changes path while it
|
||||||
|
* is working but restores it before returning.
|
||||||
|
* safe_create_leading_directories_const() doesn't modify path, even
|
||||||
|
* temporarily.
|
||||||
*/
|
*/
|
||||||
enum scld_error {
|
enum scld_error {
|
||||||
SCLD_OK = 0,
|
SCLD_OK = 0,
|
||||||
@@ -1194,6 +1199,7 @@ extern int get_oid_hex(const char *hex, struct object_id *sha1);
|
|||||||
* printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two));
|
* printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two));
|
||||||
*/
|
*/
|
||||||
extern char *sha1_to_hex_r(char *out, const unsigned char *sha1);
|
extern char *sha1_to_hex_r(char *out, const unsigned char *sha1);
|
||||||
|
extern char *oid_to_hex_r(char *out, const struct object_id *oid);
|
||||||
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
|
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
|
||||||
extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */
|
extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */
|
||||||
|
|
||||||
@@ -1373,6 +1379,13 @@ extern struct packed_git {
|
|||||||
char pack_name[FLEX_ARRAY]; /* more */
|
char pack_name[FLEX_ARRAY]; /* more */
|
||||||
} *packed_git;
|
} *packed_git;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A most-recently-used ordered version of the packed_git list, which can
|
||||||
|
* be iterated instead of packed_git (and marked via mru_mark).
|
||||||
|
*/
|
||||||
|
struct mru;
|
||||||
|
extern struct mru *packed_git_mru;
|
||||||
|
|
||||||
struct pack_entry {
|
struct pack_entry {
|
||||||
off_t offset;
|
off_t offset;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
@@ -1412,7 +1425,6 @@ extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t
|
|||||||
extern void close_pack_windows(struct packed_git *);
|
extern void close_pack_windows(struct packed_git *);
|
||||||
extern void close_all_packs(void);
|
extern void close_all_packs(void);
|
||||||
extern void unuse_pack(struct pack_window **);
|
extern void unuse_pack(struct pack_window **);
|
||||||
extern void free_pack_by_name(const char *);
|
|
||||||
extern void clear_delta_base_cache(void);
|
extern void clear_delta_base_cache(void);
|
||||||
extern struct packed_git *add_packed_git(const char *path, size_t path_len, int local);
|
extern struct packed_git *add_packed_git(const char *path, size_t path_len, int local);
|
||||||
|
|
||||||
@@ -1562,10 +1574,18 @@ struct git_config_source {
|
|||||||
const char *blob;
|
const char *blob;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum config_origin_type {
|
||||||
|
CONFIG_ORIGIN_BLOB,
|
||||||
|
CONFIG_ORIGIN_FILE,
|
||||||
|
CONFIG_ORIGIN_STDIN,
|
||||||
|
CONFIG_ORIGIN_SUBMODULE_BLOB,
|
||||||
|
CONFIG_ORIGIN_CMDLINE
|
||||||
|
};
|
||||||
|
|
||||||
typedef int (*config_fn_t)(const char *, const char *, void *);
|
typedef int (*config_fn_t)(const char *, const char *, void *);
|
||||||
extern int git_default_config(const char *, const char *, void *);
|
extern int git_default_config(const char *, const char *, void *);
|
||||||
extern int git_config_from_file(config_fn_t fn, const char *, void *);
|
extern int git_config_from_file(config_fn_t fn, const char *, void *);
|
||||||
extern int git_config_from_mem(config_fn_t fn, const char *origin_type,
|
extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type,
|
||||||
const char *name, const char *buf, size_t len, void *data);
|
const char *name, const char *buf, size_t len, void *data);
|
||||||
extern void git_config_push_parameter(const char *text);
|
extern void git_config_push_parameter(const char *text);
|
||||||
extern int git_config_from_parameters(config_fn_t fn, void *data);
|
extern int git_config_from_parameters(config_fn_t fn, void *data);
|
||||||
@@ -1607,6 +1627,16 @@ extern const char *get_log_output_encoding(void);
|
|||||||
extern const char *get_commit_output_encoding(void);
|
extern const char *get_commit_output_encoding(void);
|
||||||
|
|
||||||
extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
|
extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
|
||||||
|
|
||||||
|
enum config_scope {
|
||||||
|
CONFIG_SCOPE_UNKNOWN = 0,
|
||||||
|
CONFIG_SCOPE_SYSTEM,
|
||||||
|
CONFIG_SCOPE_GLOBAL,
|
||||||
|
CONFIG_SCOPE_REPO,
|
||||||
|
CONFIG_SCOPE_CMDLINE,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern enum config_scope current_config_scope(void);
|
||||||
extern const char *current_config_origin_type(void);
|
extern const char *current_config_origin_type(void);
|
||||||
extern const char *current_config_name(void);
|
extern const char *current_config_name(void);
|
||||||
|
|
||||||
@@ -1699,6 +1729,8 @@ extern int ignore_untracked_cache_config;
|
|||||||
struct key_value_info {
|
struct key_value_info {
|
||||||
const char *filename;
|
const char *filename;
|
||||||
int linenr;
|
int linenr;
|
||||||
|
enum config_origin_type origin_type;
|
||||||
|
enum config_scope scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
|
extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
|
||||||
@@ -1724,7 +1756,6 @@ extern int copy_file(const char *dst, const char *src, int mode);
|
|||||||
extern int copy_file_with_time(const char *dst, const char *src, int mode);
|
extern int copy_file_with_time(const char *dst, const char *src, int mode);
|
||||||
|
|
||||||
extern void write_or_die(int fd, const void *buf, size_t count);
|
extern void write_or_die(int fd, const void *buf, size_t count);
|
||||||
extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
|
|
||||||
extern void fsync_or_die(int fd, const char *);
|
extern void fsync_or_die(int fd, const char *);
|
||||||
|
|
||||||
extern ssize_t read_in_full(int fd, void *buf, size_t count);
|
extern ssize_t read_in_full(int fd, void *buf, size_t count);
|
||||||
@@ -1736,8 +1767,21 @@ static inline ssize_t write_str_in_full(int fd, const char *str)
|
|||||||
return write_in_full(fd, str, strlen(str));
|
return write_in_full(fd, str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int write_file(const char *path, const char *fmt, ...);
|
/**
|
||||||
extern int write_file_gently(const char *path, const char *fmt, ...);
|
* Open (and truncate) the file at path, write the contents of buf to it,
|
||||||
|
* and close it. Dies if any errors are encountered.
|
||||||
|
*/
|
||||||
|
extern void write_file_buf(const char *path, const char *buf, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like write_file_buf(), but format the contents into a buffer first.
|
||||||
|
* Additionally, write_file() will append a newline if one is not already
|
||||||
|
* present, making it convenient to write text files:
|
||||||
|
*
|
||||||
|
* write_file(path, "counter: %d", ctr);
|
||||||
|
*/
|
||||||
|
__attribute__((format (printf, 2, 3)))
|
||||||
|
extern void write_file(const char *path, const char *fmt, ...);
|
||||||
|
|
||||||
/* pager.c */
|
/* pager.c */
|
||||||
extern void setup_pager(void);
|
extern void setup_pager(void);
|
||||||
|
|||||||
35
color.c
35
color.c
@@ -123,19 +123,34 @@ static int parse_color(struct color *out, const char *name, int len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_attr(const char *name, int len)
|
static int parse_attr(const char *name, size_t len)
|
||||||
{
|
{
|
||||||
static const int attr_values[] = { 1, 2, 4, 5, 7,
|
static const struct {
|
||||||
22, 22, 24, 25, 27 };
|
const char *name;
|
||||||
static const char * const attr_names[] = {
|
size_t len;
|
||||||
"bold", "dim", "ul", "blink", "reverse",
|
int val, neg;
|
||||||
"nobold", "nodim", "noul", "noblink", "noreverse"
|
} attrs[] = {
|
||||||
|
#define ATTR(x, val, neg) { (x), sizeof(x)-1, (val), (neg) }
|
||||||
|
ATTR("bold", 1, 22),
|
||||||
|
ATTR("dim", 2, 22),
|
||||||
|
ATTR("italic", 3, 23),
|
||||||
|
ATTR("ul", 4, 24),
|
||||||
|
ATTR("blink", 5, 25),
|
||||||
|
ATTR("reverse", 7, 27),
|
||||||
|
ATTR("strike", 9, 29)
|
||||||
|
#undef ATTR
|
||||||
};
|
};
|
||||||
|
int negate = 0;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
|
|
||||||
const char *str = attr_names[i];
|
if (skip_prefix_mem(name, len, "no", &name, &len)) {
|
||||||
if (!strncasecmp(name, str, len) && !str[len])
|
skip_prefix_mem(name, len, "-", &name, &len);
|
||||||
return attr_values[i];
|
negate = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(attrs); i++) {
|
||||||
|
if (attrs[i].len == len && !memcmp(attrs[i].name, name, len))
|
||||||
|
return negate ? attrs[i].neg : attrs[i].val;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
15
color.h
15
color.h
@@ -3,20 +3,23 @@
|
|||||||
|
|
||||||
struct strbuf;
|
struct strbuf;
|
||||||
|
|
||||||
/* 2 + (2 * num_attrs) + 8 + 1 + 8 + 'm' + NUL */
|
|
||||||
/* "\033[1;2;4;5;7;38;5;2xx;48;5;2xxm\0" */
|
|
||||||
/*
|
/*
|
||||||
* The maximum length of ANSI color sequence we would generate:
|
* The maximum length of ANSI color sequence we would generate:
|
||||||
* - leading ESC '[' 2
|
* - leading ESC '[' 2
|
||||||
* - attr + ';' 3 * 10 (e.g. "1;")
|
* - attr + ';' 2 * num_attr (e.g. "1;")
|
||||||
|
* - no-attr + ';' 3 * num_attr (e.g. "22;")
|
||||||
* - fg color + ';' 17 (e.g. "38;2;255;255;255;")
|
* - fg color + ';' 17 (e.g. "38;2;255;255;255;")
|
||||||
* - bg color + ';' 17 (e.g. "48;2;255;255;255;")
|
* - bg color + ';' 17 (e.g. "48;2;255;255;255;")
|
||||||
* - terminating 'm' NUL 2
|
* - terminating 'm' NUL 2
|
||||||
*
|
*
|
||||||
* The above overcounts attr (we only use 5 not 8) and one semicolon
|
* The above overcounts by one semicolon but it is close enough.
|
||||||
* but it is close enough.
|
*
|
||||||
|
* The space for attributes is also slightly overallocated, as
|
||||||
|
* the negation for some attributes is the same (e.g., nobold and nodim).
|
||||||
|
*
|
||||||
|
* We allocate space for 7 attributes.
|
||||||
*/
|
*/
|
||||||
#define COLOR_MAXLEN 70
|
#define COLOR_MAXLEN 75
|
||||||
|
|
||||||
#define GIT_COLOR_NORMAL ""
|
#define GIT_COLOR_NORMAL ""
|
||||||
#define GIT_COLOR_RESET "\033[m"
|
#define GIT_COLOR_RESET "\033[m"
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
|
|||||||
memset(p->parent, 0,
|
memset(p->parent, 0,
|
||||||
sizeof(p->parent[0]) * num_parent);
|
sizeof(p->parent[0]) * num_parent);
|
||||||
|
|
||||||
hashcpy(p->oid.hash, q->queue[i]->two->sha1);
|
oidcpy(&p->oid, &q->queue[i]->two->oid);
|
||||||
p->mode = q->queue[i]->two->mode;
|
p->mode = q->queue[i]->two->mode;
|
||||||
hashcpy(p->parent[n].oid.hash, q->queue[i]->one->sha1);
|
oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);
|
||||||
p->parent[n].mode = q->queue[i]->one->mode;
|
p->parent[n].mode = q->queue[i]->one->mode;
|
||||||
p->parent[n].status = q->queue[i]->status;
|
p->parent[n].status = q->queue[i]->status;
|
||||||
*tail = p;
|
*tail = p;
|
||||||
@@ -77,7 +77,7 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashcpy(p->parent[n].oid.hash, q->queue[i]->one->sha1);
|
oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);
|
||||||
p->parent[n].mode = q->queue[i]->one->mode;
|
p->parent[n].mode = q->queue[i]->one->mode;
|
||||||
p->parent[n].status = q->queue[i]->status;
|
p->parent[n].status = q->queue[i]->status;
|
||||||
|
|
||||||
@@ -1268,16 +1268,16 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p,
|
|||||||
for (i = 0; i < num_parent; i++) {
|
for (i = 0; i < num_parent; i++) {
|
||||||
pair->one[i].path = p->path;
|
pair->one[i].path = p->path;
|
||||||
pair->one[i].mode = p->parent[i].mode;
|
pair->one[i].mode = p->parent[i].mode;
|
||||||
hashcpy(pair->one[i].sha1, p->parent[i].oid.hash);
|
oidcpy(&pair->one[i].oid, &p->parent[i].oid);
|
||||||
pair->one[i].sha1_valid = !is_null_oid(&p->parent[i].oid);
|
pair->one[i].oid_valid = !is_null_oid(&p->parent[i].oid);
|
||||||
pair->one[i].has_more_entries = 1;
|
pair->one[i].has_more_entries = 1;
|
||||||
}
|
}
|
||||||
pair->one[num_parent - 1].has_more_entries = 0;
|
pair->one[num_parent - 1].has_more_entries = 0;
|
||||||
|
|
||||||
pair->two->path = p->path;
|
pair->two->path = p->path;
|
||||||
pair->two->mode = p->mode;
|
pair->two->mode = p->mode;
|
||||||
hashcpy(pair->two->sha1, p->oid.hash);
|
oidcpy(&pair->two->oid, &p->oid);
|
||||||
pair->two->sha1_valid = !is_null_oid(&p->oid);
|
pair->two->oid_valid = !is_null_oid(&p->oid);
|
||||||
return pair;
|
return pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1525,7 +1525,7 @@ void diff_tree_combined(const unsigned char *sha1,
|
|||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_pathspec(&diffopts.pathspec);
|
clear_pathspec(&diffopts.pathspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void diff_tree_combined_merge(const struct commit *commit, int dense,
|
void diff_tree_combined_merge(const struct commit *commit, int dense,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* After including this header file, using:
|
* After including this header file, using:
|
||||||
*
|
*
|
||||||
* define_commit_slab(indegee, int);
|
* define_commit_slab(indegree, int);
|
||||||
*
|
*
|
||||||
* will let you call the following functions:
|
* will let you call the following functions:
|
||||||
*
|
*
|
||||||
@@ -126,16 +126,16 @@ static MAYBE_UNUSED elemtype *slabname## _peek(struct slabname *s, \
|
|||||||
return slabname##_at_peek(s, c, 0); \
|
return slabname##_at_peek(s, c, 0); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static int stat_ ##slabname## realloc
|
struct slabname
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that this seemingly redundant second declaration is required
|
* Note that this redundant forward declaration is required
|
||||||
* to allow a terminating semicolon, which makes instantiations look
|
* to allow a terminating semicolon, which makes instantiations look
|
||||||
* like function declarations. I.e., the expansion of
|
* like function declarations. I.e., the expansion of
|
||||||
*
|
*
|
||||||
* define_commit_slab(indegree, int);
|
* define_commit_slab(indegree, int);
|
||||||
*
|
*
|
||||||
* ends in 'static int stat_indegreerealloc;'. This would otherwise
|
* ends in 'struct indegree;'. This would otherwise
|
||||||
* be a syntax error according (at least) to ISO C. It's hard to
|
* be a syntax error according (at least) to ISO C. It's hard to
|
||||||
* catch because GCC silently parses it by default.
|
* catch because GCC silently parses it by default.
|
||||||
*/
|
*/
|
||||||
|
|||||||
10
commit.c
10
commit.c
@@ -1626,16 +1626,6 @@ struct commit_list **commit_list_append(struct commit *commit,
|
|||||||
return &new->next;
|
return &new->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_commit_list(struct commit_list *list,
|
|
||||||
const char *format_cur,
|
|
||||||
const char *format_last)
|
|
||||||
{
|
|
||||||
for ( ; list; list = list->next) {
|
|
||||||
const char *format = list->next ? format_cur : format_last;
|
|
||||||
printf(format, oid_to_hex(&list->item->object.oid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *find_commit_header(const char *msg, const char *key, size_t *out_len)
|
const char *find_commit_header(const char *msg, const char *key, size_t *out_len)
|
||||||
{
|
{
|
||||||
int key_len = strlen(key);
|
int key_len = strlen(key);
|
||||||
|
|||||||
10
commit.h
10
commit.h
@@ -131,11 +131,17 @@ enum cmit_fmt {
|
|||||||
CMIT_FMT_FULLER,
|
CMIT_FMT_FULLER,
|
||||||
CMIT_FMT_ONELINE,
|
CMIT_FMT_ONELINE,
|
||||||
CMIT_FMT_EMAIL,
|
CMIT_FMT_EMAIL,
|
||||||
|
CMIT_FMT_MBOXRD,
|
||||||
CMIT_FMT_USERFORMAT,
|
CMIT_FMT_USERFORMAT,
|
||||||
|
|
||||||
CMIT_FMT_UNSPECIFIED
|
CMIT_FMT_UNSPECIFIED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)
|
||||||
|
{
|
||||||
|
return (fmt == CMIT_FMT_EMAIL || fmt == CMIT_FMT_MBOXRD);
|
||||||
|
}
|
||||||
|
|
||||||
struct pretty_print_context {
|
struct pretty_print_context {
|
||||||
/*
|
/*
|
||||||
* Callers should tweak these to change the behavior of pp_* functions.
|
* Callers should tweak these to change the behavior of pp_* functions.
|
||||||
@@ -373,10 +379,6 @@ extern int parse_signed_commit(const struct commit *commit,
|
|||||||
struct strbuf *message, struct strbuf *signature);
|
struct strbuf *message, struct strbuf *signature);
|
||||||
extern int remove_signature(struct strbuf *buf);
|
extern int remove_signature(struct strbuf *buf);
|
||||||
|
|
||||||
extern void print_commit_list(struct commit_list *list,
|
|
||||||
const char *format_cur,
|
|
||||||
const char *format_last);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the signature of the given commit. The result of the check is stored
|
* Check the signature of the given commit. The result of the check is stored
|
||||||
* in sig->check_result, 'G' for a good signature, 'U' for a good signature
|
* in sig->check_result, 'G' for a good signature, 'U' for a good signature
|
||||||
|
|||||||
231
config.c
231
config.c
@@ -24,7 +24,7 @@ struct config_source {
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
} buf;
|
} buf;
|
||||||
} u;
|
} u;
|
||||||
const char *origin_type;
|
enum config_origin_type origin_type;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *path;
|
const char *path;
|
||||||
int die_on_error;
|
int die_on_error;
|
||||||
@@ -38,7 +38,33 @@ struct config_source {
|
|||||||
long (*do_ftell)(struct config_source *c);
|
long (*do_ftell)(struct config_source *c);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These variables record the "current" config source, which
|
||||||
|
* can be accessed by parsing callbacks.
|
||||||
|
*
|
||||||
|
* The "cf" variable will be non-NULL only when we are actually parsing a real
|
||||||
|
* config source (file, blob, cmdline, etc).
|
||||||
|
*
|
||||||
|
* The "current_config_kvi" variable will be non-NULL only when we are feeding
|
||||||
|
* cached config from a configset into a callback.
|
||||||
|
*
|
||||||
|
* They should generally never be non-NULL at the same time. If they are both
|
||||||
|
* NULL, then we aren't parsing anything (and depending on the function looking
|
||||||
|
* at the variables, it's either a bug for it to be called in the first place,
|
||||||
|
* or it's a function which can be reused for non-config purposes, and should
|
||||||
|
* fall back to some sane behavior).
|
||||||
|
*/
|
||||||
static struct config_source *cf;
|
static struct config_source *cf;
|
||||||
|
static struct key_value_info *current_config_kvi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar to the variables above, this gives access to the "scope" of the
|
||||||
|
* current value (repo, global, etc). For cached values, it can be found via
|
||||||
|
* the current_config_kvi as above. During parsing, the current value can be
|
||||||
|
* found in this variable. It's not part of "cf" because it transcends a single
|
||||||
|
* file (i.e., a file included from .git/config is still in "repo" scope).
|
||||||
|
*/
|
||||||
|
static enum config_scope current_parsing_scope;
|
||||||
|
|
||||||
static int zlib_compression_seen;
|
static int zlib_compression_seen;
|
||||||
|
|
||||||
@@ -131,7 +157,9 @@ static int handle_path_include(const char *path, struct config_include_data *inc
|
|||||||
if (!access_or_die(path, R_OK, 0)) {
|
if (!access_or_die(path, R_OK, 0)) {
|
||||||
if (++inc->depth > MAX_INCLUDE_DEPTH)
|
if (++inc->depth > MAX_INCLUDE_DEPTH)
|
||||||
die(include_depth_advice, MAX_INCLUDE_DEPTH, path,
|
die(include_depth_advice, MAX_INCLUDE_DEPTH, path,
|
||||||
cf && cf->name ? cf->name : "the command line");
|
!cf ? "<unknown>" :
|
||||||
|
cf->name ? cf->name :
|
||||||
|
"the command line");
|
||||||
ret = git_config_from_file(git_config_include, path, inc);
|
ret = git_config_from_file(git_config_include, path, inc);
|
||||||
inc->depth--;
|
inc->depth--;
|
||||||
}
|
}
|
||||||
@@ -205,32 +233,41 @@ int git_config_parse_parameter(const char *text,
|
|||||||
int git_config_from_parameters(config_fn_t fn, void *data)
|
int git_config_from_parameters(config_fn_t fn, void *data)
|
||||||
{
|
{
|
||||||
const char *env = getenv(CONFIG_DATA_ENVIRONMENT);
|
const char *env = getenv(CONFIG_DATA_ENVIRONMENT);
|
||||||
|
int ret = 0;
|
||||||
char *envw;
|
char *envw;
|
||||||
const char **argv = NULL;
|
const char **argv = NULL;
|
||||||
int nr = 0, alloc = 0;
|
int nr = 0, alloc = 0;
|
||||||
int i;
|
int i;
|
||||||
|
struct config_source source;
|
||||||
|
|
||||||
if (!env)
|
if (!env)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
memset(&source, 0, sizeof(source));
|
||||||
|
source.prev = cf;
|
||||||
|
source.origin_type = CONFIG_ORIGIN_CMDLINE;
|
||||||
|
cf = &source;
|
||||||
|
|
||||||
/* sq_dequote will write over it */
|
/* sq_dequote will write over it */
|
||||||
envw = xstrdup(env);
|
envw = xstrdup(env);
|
||||||
|
|
||||||
if (sq_dequote_to_argv(envw, &argv, &nr, &alloc) < 0) {
|
if (sq_dequote_to_argv(envw, &argv, &nr, &alloc) < 0) {
|
||||||
free(envw);
|
ret = error("bogus format in " CONFIG_DATA_ENVIRONMENT);
|
||||||
return error("bogus format in " CONFIG_DATA_ENVIRONMENT);
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
if (git_config_parse_parameter(argv[i], fn, data) < 0) {
|
if (git_config_parse_parameter(argv[i], fn, data) < 0) {
|
||||||
free(argv);
|
ret = -1;
|
||||||
free(envw);
|
goto out;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
free(argv);
|
free(argv);
|
||||||
free(envw);
|
free(envw);
|
||||||
return nr > 0;
|
cf = source.prev;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_next_char(void)
|
static int get_next_char(void)
|
||||||
@@ -417,6 +454,8 @@ static int git_parse_source(config_fn_t fn, void *data)
|
|||||||
int comment = 0;
|
int comment = 0;
|
||||||
int baselen = 0;
|
int baselen = 0;
|
||||||
struct strbuf *var = &cf->var;
|
struct strbuf *var = &cf->var;
|
||||||
|
int error_return = 0;
|
||||||
|
char *error_msg = NULL;
|
||||||
|
|
||||||
/* U+FEFF Byte Order Mark in UTF8 */
|
/* U+FEFF Byte Order Mark in UTF8 */
|
||||||
const char *bomptr = utf8_bom;
|
const char *bomptr = utf8_bom;
|
||||||
@@ -471,10 +510,40 @@ static int git_parse_source(config_fn_t fn, void *data)
|
|||||||
if (get_value(fn, data, var) < 0)
|
if (get_value(fn, data, var) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (cf->origin_type) {
|
||||||
|
case CONFIG_ORIGIN_BLOB:
|
||||||
|
error_msg = xstrfmt(_("bad config line %d in blob %s"),
|
||||||
|
cf->linenr, cf->name);
|
||||||
|
break;
|
||||||
|
case CONFIG_ORIGIN_FILE:
|
||||||
|
error_msg = xstrfmt(_("bad config line %d in file %s"),
|
||||||
|
cf->linenr, cf->name);
|
||||||
|
break;
|
||||||
|
case CONFIG_ORIGIN_STDIN:
|
||||||
|
error_msg = xstrfmt(_("bad config line %d in standard input"),
|
||||||
|
cf->linenr);
|
||||||
|
break;
|
||||||
|
case CONFIG_ORIGIN_SUBMODULE_BLOB:
|
||||||
|
error_msg = xstrfmt(_("bad config line %d in submodule-blob %s"),
|
||||||
|
cf->linenr, cf->name);
|
||||||
|
break;
|
||||||
|
case CONFIG_ORIGIN_CMDLINE:
|
||||||
|
error_msg = xstrfmt(_("bad config line %d in command line %s"),
|
||||||
|
cf->linenr, cf->name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error_msg = xstrfmt(_("bad config line %d in %s"),
|
||||||
|
cf->linenr, cf->name);
|
||||||
|
}
|
||||||
|
|
||||||
if (cf->die_on_error)
|
if (cf->die_on_error)
|
||||||
die(_("bad config line %d in %s %s"), cf->linenr, cf->origin_type, cf->name);
|
die("%s", error_msg);
|
||||||
else
|
else
|
||||||
return error(_("bad config line %d in %s %s"), cf->linenr, cf->origin_type, cf->name);
|
error_return = error("%s", error_msg);
|
||||||
|
|
||||||
|
free(error_msg);
|
||||||
|
return error_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_unit_factor(const char *end, uintmax_t *val)
|
static int parse_unit_factor(const char *end, uintmax_t *val)
|
||||||
@@ -583,16 +652,35 @@ int git_parse_ulong(const char *value, unsigned long *ret)
|
|||||||
NORETURN
|
NORETURN
|
||||||
static void die_bad_number(const char *name, const char *value)
|
static void die_bad_number(const char *name, const char *value)
|
||||||
{
|
{
|
||||||
const char *reason = errno == ERANGE ?
|
const char * error_type = (errno == ERANGE)? _("out of range"):_("invalid unit");
|
||||||
"out of range" :
|
|
||||||
"invalid unit";
|
|
||||||
if (!value)
|
if (!value)
|
||||||
value = "";
|
value = "";
|
||||||
|
|
||||||
if (cf && cf->origin_type && cf->name)
|
if (!(cf && cf->name))
|
||||||
die(_("bad numeric config value '%s' for '%s' in %s %s: %s"),
|
die(_("bad numeric config value '%s' for '%s': %s"),
|
||||||
value, name, cf->origin_type, cf->name, reason);
|
value, name, error_type);
|
||||||
die(_("bad numeric config value '%s' for '%s': %s"), value, name, reason);
|
|
||||||
|
switch (cf->origin_type) {
|
||||||
|
case CONFIG_ORIGIN_BLOB:
|
||||||
|
die(_("bad numeric config value '%s' for '%s' in blob %s: %s"),
|
||||||
|
value, name, cf->name, error_type);
|
||||||
|
case CONFIG_ORIGIN_FILE:
|
||||||
|
die(_("bad numeric config value '%s' for '%s' in file %s: %s"),
|
||||||
|
value, name, cf->name, error_type);
|
||||||
|
case CONFIG_ORIGIN_STDIN:
|
||||||
|
die(_("bad numeric config value '%s' for '%s' in standard input: %s"),
|
||||||
|
value, name, error_type);
|
||||||
|
case CONFIG_ORIGIN_SUBMODULE_BLOB:
|
||||||
|
die(_("bad numeric config value '%s' for '%s' in submodule-blob %s: %s"),
|
||||||
|
value, name, cf->name, error_type);
|
||||||
|
case CONFIG_ORIGIN_CMDLINE:
|
||||||
|
die(_("bad numeric config value '%s' for '%s' in command line %s: %s"),
|
||||||
|
value, name, cf->name, error_type);
|
||||||
|
default:
|
||||||
|
die(_("bad numeric config value '%s' for '%s' in %s: %s"),
|
||||||
|
value, name, cf->name, error_type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_int(const char *name, const char *value)
|
int git_config_int(const char *name, const char *value)
|
||||||
@@ -1069,7 +1157,8 @@ static int do_config_from(struct config_source *top, config_fn_t fn, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int do_config_from_file(config_fn_t fn,
|
static int do_config_from_file(config_fn_t fn,
|
||||||
const char *origin_type, const char *name, const char *path, FILE *f,
|
const enum config_origin_type origin_type,
|
||||||
|
const char *name, const char *path, FILE *f,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct config_source top;
|
struct config_source top;
|
||||||
@@ -1088,7 +1177,7 @@ static int do_config_from_file(config_fn_t fn,
|
|||||||
|
|
||||||
static int git_config_from_stdin(config_fn_t fn, void *data)
|
static int git_config_from_stdin(config_fn_t fn, void *data)
|
||||||
{
|
{
|
||||||
return do_config_from_file(fn, "standard input", "", NULL, stdin, data);
|
return do_config_from_file(fn, CONFIG_ORIGIN_STDIN, "", NULL, stdin, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_from_file(config_fn_t fn, const char *filename, void *data)
|
int git_config_from_file(config_fn_t fn, const char *filename, void *data)
|
||||||
@@ -1099,14 +1188,14 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
|
|||||||
f = fopen(filename, "r");
|
f = fopen(filename, "r");
|
||||||
if (f) {
|
if (f) {
|
||||||
flockfile(f);
|
flockfile(f);
|
||||||
ret = do_config_from_file(fn, "file", filename, filename, f, data);
|
ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename, filename, f, data);
|
||||||
funlockfile(f);
|
funlockfile(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_from_mem(config_fn_t fn, const char *origin_type,
|
int git_config_from_mem(config_fn_t fn, const enum config_origin_type origin_type,
|
||||||
const char *name, const char *buf, size_t len, void *data)
|
const char *name, const char *buf, size_t len, void *data)
|
||||||
{
|
{
|
||||||
struct config_source top;
|
struct config_source top;
|
||||||
@@ -1143,7 +1232,7 @@ static int git_config_from_blob_sha1(config_fn_t fn,
|
|||||||
return error("reference '%s' does not point to a blob", name);
|
return error("reference '%s' does not point to a blob", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = git_config_from_mem(fn, "blob", name, buf, size, data);
|
ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size, data);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1197,47 +1286,36 @@ int git_config_system(void)
|
|||||||
|
|
||||||
static int do_git_config_sequence(config_fn_t fn, void *data)
|
static int do_git_config_sequence(config_fn_t fn, void *data)
|
||||||
{
|
{
|
||||||
int ret = 0, found = 0;
|
int ret = 0;
|
||||||
char *xdg_config = xdg_config_home("config");
|
char *xdg_config = xdg_config_home("config");
|
||||||
char *user_config = expand_user_path("~/.gitconfig");
|
char *user_config = expand_user_path("~/.gitconfig");
|
||||||
char *repo_config = git_pathdup("config");
|
char *repo_config = git_pathdup("config");
|
||||||
|
|
||||||
if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) {
|
current_parsing_scope = CONFIG_SCOPE_SYSTEM;
|
||||||
|
if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0))
|
||||||
ret += git_config_from_file(fn, git_etc_gitconfig(),
|
ret += git_config_from_file(fn, git_etc_gitconfig(),
|
||||||
data);
|
data);
|
||||||
found += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK)) {
|
current_parsing_scope = CONFIG_SCOPE_GLOBAL;
|
||||||
|
if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK))
|
||||||
ret += git_config_from_file(fn, xdg_config, data);
|
ret += git_config_from_file(fn, xdg_config, data);
|
||||||
found += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK)) {
|
if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
|
||||||
ret += git_config_from_file(fn, user_config, data);
|
ret += git_config_from_file(fn, user_config, data);
|
||||||
found += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repo_config && !access_or_die(repo_config, R_OK, 0)) {
|
current_parsing_scope = CONFIG_SCOPE_REPO;
|
||||||
|
if (repo_config && !access_or_die(repo_config, R_OK, 0))
|
||||||
ret += git_config_from_file(fn, repo_config, data);
|
ret += git_config_from_file(fn, repo_config, data);
|
||||||
found += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (git_config_from_parameters(fn, data)) {
|
current_parsing_scope = CONFIG_SCOPE_CMDLINE;
|
||||||
case -1: /* error */
|
if (git_config_from_parameters(fn, data) < 0)
|
||||||
die(_("unable to parse command-line config"));
|
die(_("unable to parse command-line config"));
|
||||||
break;
|
|
||||||
case 0: /* found nothing */
|
|
||||||
break;
|
|
||||||
default: /* found at least one item */
|
|
||||||
found++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
|
||||||
free(xdg_config);
|
free(xdg_config);
|
||||||
free(user_config);
|
free(user_config);
|
||||||
free(repo_config);
|
free(repo_config);
|
||||||
return ret == 0 ? found : ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_with_options(config_fn_t fn, void *data,
|
int git_config_with_options(config_fn_t fn, void *data,
|
||||||
@@ -1272,7 +1350,7 @@ static void git_config_raw(config_fn_t fn, void *data)
|
|||||||
if (git_config_with_options(fn, data, NULL, 1) < 0)
|
if (git_config_with_options(fn, data, NULL, 1) < 0)
|
||||||
/*
|
/*
|
||||||
* git_config_with_options() normally returns only
|
* git_config_with_options() normally returns only
|
||||||
* positive values, as most errors are fatal, and
|
* zero, as most errors are fatal, and
|
||||||
* non-fatal potential errors are guarded by "if"
|
* non-fatal potential errors are guarded by "if"
|
||||||
* statements that are entered only when no error is
|
* statements that are entered only when no error is
|
||||||
* possible.
|
* possible.
|
||||||
@@ -1290,16 +1368,20 @@ static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
|
|||||||
struct string_list *values;
|
struct string_list *values;
|
||||||
struct config_set_element *entry;
|
struct config_set_element *entry;
|
||||||
struct configset_list *list = &cs->list;
|
struct configset_list *list = &cs->list;
|
||||||
struct key_value_info *kv_info;
|
|
||||||
|
|
||||||
for (i = 0; i < list->nr; i++) {
|
for (i = 0; i < list->nr; i++) {
|
||||||
entry = list->items[i].e;
|
entry = list->items[i].e;
|
||||||
value_index = list->items[i].value_index;
|
value_index = list->items[i].value_index;
|
||||||
values = &entry->value_list;
|
values = &entry->value_list;
|
||||||
if (fn(entry->key, values->items[value_index].string, data) < 0) {
|
|
||||||
kv_info = values->items[value_index].util;
|
current_config_kvi = values->items[value_index].util;
|
||||||
git_die_config_linenr(entry->key, kv_info->filename, kv_info->linenr);
|
|
||||||
}
|
if (fn(entry->key, values->items[value_index].string, data) < 0)
|
||||||
|
git_die_config_linenr(entry->key,
|
||||||
|
current_config_kvi->filename,
|
||||||
|
current_config_kvi->linenr);
|
||||||
|
|
||||||
|
current_config_kvi = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1356,14 +1438,19 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
|
|||||||
l_item->e = e;
|
l_item->e = e;
|
||||||
l_item->value_index = e->value_list.nr - 1;
|
l_item->value_index = e->value_list.nr - 1;
|
||||||
|
|
||||||
if (cf) {
|
if (!cf)
|
||||||
|
die("BUG: configset_add_value has no source");
|
||||||
|
if (cf->name) {
|
||||||
kv_info->filename = strintern(cf->name);
|
kv_info->filename = strintern(cf->name);
|
||||||
kv_info->linenr = cf->linenr;
|
kv_info->linenr = cf->linenr;
|
||||||
|
kv_info->origin_type = cf->origin_type;
|
||||||
} else {
|
} else {
|
||||||
/* for values read from `git_config_from_parameters()` */
|
/* for values read from `git_config_from_parameters()` */
|
||||||
kv_info->filename = NULL;
|
kv_info->filename = NULL;
|
||||||
kv_info->linenr = -1;
|
kv_info->linenr = -1;
|
||||||
|
kv_info->origin_type = CONFIG_ORIGIN_CMDLINE;
|
||||||
}
|
}
|
||||||
|
kv_info->scope = current_parsing_scope;
|
||||||
si->util = kv_info;
|
si->util = kv_info;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2442,10 +2529,46 @@ int parse_config_key(const char *var,
|
|||||||
|
|
||||||
const char *current_config_origin_type(void)
|
const char *current_config_origin_type(void)
|
||||||
{
|
{
|
||||||
return cf && cf->origin_type ? cf->origin_type : "command line";
|
int type;
|
||||||
|
if (current_config_kvi)
|
||||||
|
type = current_config_kvi->origin_type;
|
||||||
|
else if(cf)
|
||||||
|
type = cf->origin_type;
|
||||||
|
else
|
||||||
|
die("BUG: current_config_origin_type called outside config callback");
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case CONFIG_ORIGIN_BLOB:
|
||||||
|
return "blob";
|
||||||
|
case CONFIG_ORIGIN_FILE:
|
||||||
|
return "file";
|
||||||
|
case CONFIG_ORIGIN_STDIN:
|
||||||
|
return "standard input";
|
||||||
|
case CONFIG_ORIGIN_SUBMODULE_BLOB:
|
||||||
|
return "submodule-blob";
|
||||||
|
case CONFIG_ORIGIN_CMDLINE:
|
||||||
|
return "command line";
|
||||||
|
default:
|
||||||
|
die("BUG: unknown config origin type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *current_config_name(void)
|
const char *current_config_name(void)
|
||||||
{
|
{
|
||||||
return cf && cf->name ? cf->name : "";
|
const char *name;
|
||||||
|
if (current_config_kvi)
|
||||||
|
name = current_config_kvi->filename;
|
||||||
|
else if (cf)
|
||||||
|
name = cf->name;
|
||||||
|
else
|
||||||
|
die("BUG: current_config_name called outside config callback");
|
||||||
|
return name ? name : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
enum config_scope current_config_scope(void)
|
||||||
|
{
|
||||||
|
if (current_config_kvi)
|
||||||
|
return current_config_kvi->scope;
|
||||||
|
else
|
||||||
|
return current_parsing_scope;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ ifeq ($(uname_S),Linux)
|
|||||||
HAVE_DEV_TTY = YesPlease
|
HAVE_DEV_TTY = YesPlease
|
||||||
HAVE_CLOCK_GETTIME = YesPlease
|
HAVE_CLOCK_GETTIME = YesPlease
|
||||||
HAVE_CLOCK_MONOTONIC = YesPlease
|
HAVE_CLOCK_MONOTONIC = YesPlease
|
||||||
|
# -lrt is needed for clock_gettime on glibc <= 2.16
|
||||||
|
NEEDS_LIBRT = YesPlease
|
||||||
HAVE_GETDELIM = YesPlease
|
HAVE_GETDELIM = YesPlease
|
||||||
SANE_TEXT_GREP=-a
|
SANE_TEXT_GREP=-a
|
||||||
endif
|
endif
|
||||||
@@ -207,6 +209,7 @@ ifeq ($(uname_S),FreeBSD)
|
|||||||
HAVE_PATHS_H = YesPlease
|
HAVE_PATHS_H = YesPlease
|
||||||
GMTIME_UNRELIABLE_ERRORS = UnfortunatelyYes
|
GMTIME_UNRELIABLE_ERRORS = UnfortunatelyYes
|
||||||
HAVE_BSD_SYSCTL = YesPlease
|
HAVE_BSD_SYSCTL = YesPlease
|
||||||
|
PAGER_ENV = LESS=FRX LV=-c MORE=FRX
|
||||||
endif
|
endif
|
||||||
ifeq ($(uname_S),OpenBSD)
|
ifeq ($(uname_S),OpenBSD)
|
||||||
NO_STRCASESTR = YesPlease
|
NO_STRCASESTR = YesPlease
|
||||||
|
|||||||
15
connect.c
15
connect.c
@@ -658,6 +658,19 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
|
|||||||
|
|
||||||
static struct child_process no_fork = CHILD_PROCESS_INIT;
|
static struct child_process no_fork = CHILD_PROCESS_INIT;
|
||||||
|
|
||||||
|
static const char *get_ssh_command(void)
|
||||||
|
{
|
||||||
|
const char *ssh;
|
||||||
|
|
||||||
|
if ((ssh = getenv("GIT_SSH_COMMAND")))
|
||||||
|
return ssh;
|
||||||
|
|
||||||
|
if (!git_config_get_string_const("core.sshcommand", &ssh))
|
||||||
|
return ssh;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This returns a dummy child_process if the transport protocol does not
|
* This returns a dummy child_process if the transport protocol does not
|
||||||
* need fork(2), or a struct child_process object if it does. Once done,
|
* need fork(2), or a struct child_process object if it does. Once done,
|
||||||
@@ -758,7 +771,7 @@ struct child_process *git_connect(int fd[2], const char *url,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh = getenv("GIT_SSH_COMMAND");
|
ssh = get_ssh_command();
|
||||||
if (!ssh) {
|
if (!ssh) {
|
||||||
const char *base;
|
const char *base;
|
||||||
char *ssh_dup;
|
char *ssh_dup;
|
||||||
|
|||||||
71
connected.c
71
connected.c
@@ -4,10 +4,6 @@
|
|||||||
#include "connected.h"
|
#include "connected.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
int check_everything_connected(sha1_iterate_fn fn, int quiet, void *cb_data)
|
|
||||||
{
|
|
||||||
return check_everything_connected_with_transport(fn, quiet, cb_data, NULL);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* If we feed all the commits we want to verify to this command
|
* If we feed all the commits we want to verify to this command
|
||||||
*
|
*
|
||||||
@@ -19,22 +15,27 @@ int check_everything_connected(sha1_iterate_fn fn, int quiet, void *cb_data)
|
|||||||
*
|
*
|
||||||
* Returns 0 if everything is connected, non-zero otherwise.
|
* Returns 0 if everything is connected, non-zero otherwise.
|
||||||
*/
|
*/
|
||||||
static int check_everything_connected_real(sha1_iterate_fn fn,
|
int check_connected(sha1_iterate_fn fn, void *cb_data,
|
||||||
int quiet,
|
struct check_connected_options *opt)
|
||||||
void *cb_data,
|
|
||||||
struct transport *transport,
|
|
||||||
const char *shallow_file)
|
|
||||||
{
|
{
|
||||||
struct child_process rev_list = CHILD_PROCESS_INIT;
|
struct child_process rev_list = CHILD_PROCESS_INIT;
|
||||||
const char *argv[9];
|
struct check_connected_options defaults = CHECK_CONNECTED_INIT;
|
||||||
char commit[41];
|
char commit[41];
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
int err = 0, ac = 0;
|
int err = 0;
|
||||||
struct packed_git *new_pack = NULL;
|
struct packed_git *new_pack = NULL;
|
||||||
|
struct transport *transport;
|
||||||
size_t base_len;
|
size_t base_len;
|
||||||
|
|
||||||
if (fn(cb_data, sha1))
|
if (!opt)
|
||||||
|
opt = &defaults;
|
||||||
|
transport = opt->transport;
|
||||||
|
|
||||||
|
if (fn(cb_data, sha1)) {
|
||||||
|
if (opt->err_fd)
|
||||||
|
close(opt->err_fd);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (transport && transport->smart_options &&
|
if (transport && transport->smart_options &&
|
||||||
transport->smart_options->self_contained_and_connected &&
|
transport->smart_options->self_contained_and_connected &&
|
||||||
@@ -47,24 +48,28 @@ static int check_everything_connected_real(sha1_iterate_fn fn,
|
|||||||
strbuf_release(&idx_file);
|
strbuf_release(&idx_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shallow_file) {
|
if (opt->shallow_file) {
|
||||||
argv[ac++] = "--shallow-file";
|
argv_array_push(&rev_list.args, "--shallow-file");
|
||||||
argv[ac++] = shallow_file;
|
argv_array_push(&rev_list.args, opt->shallow_file);
|
||||||
}
|
}
|
||||||
argv[ac++] = "rev-list";
|
argv_array_push(&rev_list.args,"rev-list");
|
||||||
argv[ac++] = "--objects";
|
argv_array_push(&rev_list.args, "--objects");
|
||||||
argv[ac++] = "--stdin";
|
argv_array_push(&rev_list.args, "--stdin");
|
||||||
argv[ac++] = "--not";
|
argv_array_push(&rev_list.args, "--not");
|
||||||
argv[ac++] = "--all";
|
argv_array_push(&rev_list.args, "--all");
|
||||||
if (quiet)
|
argv_array_push(&rev_list.args, "--quiet");
|
||||||
argv[ac++] = "--quiet";
|
if (opt->progress)
|
||||||
argv[ac] = NULL;
|
argv_array_pushf(&rev_list.args, "--progress=%s",
|
||||||
|
_("Checking connectivity"));
|
||||||
|
|
||||||
rev_list.argv = argv;
|
|
||||||
rev_list.git_cmd = 1;
|
rev_list.git_cmd = 1;
|
||||||
rev_list.in = -1;
|
rev_list.in = -1;
|
||||||
rev_list.no_stdout = 1;
|
rev_list.no_stdout = 1;
|
||||||
rev_list.no_stderr = quiet;
|
if (opt->err_fd)
|
||||||
|
rev_list.err = opt->err_fd;
|
||||||
|
else
|
||||||
|
rev_list.no_stderr = opt->quiet;
|
||||||
|
|
||||||
if (start_command(&rev_list))
|
if (start_command(&rev_list))
|
||||||
return error(_("Could not run 'git rev-list'"));
|
return error(_("Could not run 'git rev-list'"));
|
||||||
|
|
||||||
@@ -98,19 +103,3 @@ static int check_everything_connected_real(sha1_iterate_fn fn,
|
|||||||
sigchain_pop(SIGPIPE);
|
sigchain_pop(SIGPIPE);
|
||||||
return finish_command(&rev_list) || err;
|
return finish_command(&rev_list) || err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_everything_connected_with_transport(sha1_iterate_fn fn,
|
|
||||||
int quiet,
|
|
||||||
void *cb_data,
|
|
||||||
struct transport *transport)
|
|
||||||
{
|
|
||||||
return check_everything_connected_real(fn, quiet, cb_data,
|
|
||||||
transport, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int check_shallow_connected(sha1_iterate_fn fn, int quiet, void *cb_data,
|
|
||||||
const char *shallow_file)
|
|
||||||
{
|
|
||||||
return check_everything_connected_real(fn, quiet, cb_data,
|
|
||||||
NULL, shallow_file);
|
|
||||||
}
|
|
||||||
|
|||||||
37
connected.h
37
connected.h
@@ -10,18 +10,43 @@ struct transport;
|
|||||||
*/
|
*/
|
||||||
typedef int (*sha1_iterate_fn)(void *, unsigned char [20]);
|
typedef int (*sha1_iterate_fn)(void *, unsigned char [20]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Named-arguments struct for check_connected. All arguments are
|
||||||
|
* optional, and can be left to defaults as set by CHECK_CONNECTED_INIT.
|
||||||
|
*/
|
||||||
|
struct check_connected_options {
|
||||||
|
/* Avoid printing any errors to stderr. */
|
||||||
|
int quiet;
|
||||||
|
|
||||||
|
/* --shallow-file to pass to rev-list sub-process */
|
||||||
|
const char *shallow_file;
|
||||||
|
|
||||||
|
/* Transport whose objects we are checking, if available. */
|
||||||
|
struct transport *transport;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If non-zero, send error messages to this descriptor rather
|
||||||
|
* than stderr. The descriptor is closed before check_connected
|
||||||
|
* returns.
|
||||||
|
*/
|
||||||
|
int err_fd;
|
||||||
|
|
||||||
|
/* If non-zero, show progress as we traverse the objects. */
|
||||||
|
int progress;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CHECK_CONNECTED_INIT { 0 }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure that our object store has all the commits necessary to
|
* Make sure that our object store has all the commits necessary to
|
||||||
* connect the ancestry chain to some of our existing refs, and all
|
* connect the ancestry chain to some of our existing refs, and all
|
||||||
* the trees and blobs that these commits use.
|
* the trees and blobs that these commits use.
|
||||||
*
|
*
|
||||||
* Return 0 if Ok, non zero otherwise (i.e. some missing objects)
|
* Return 0 if Ok, non zero otherwise (i.e. some missing objects)
|
||||||
|
*
|
||||||
|
* If "opt" is NULL, behaves as if CHECK_CONNECTED_INIT was passed.
|
||||||
*/
|
*/
|
||||||
extern int check_everything_connected(sha1_iterate_fn, int quiet, void *cb_data);
|
int check_connected(sha1_iterate_fn fn, void *cb_data,
|
||||||
extern int check_shallow_connected(sha1_iterate_fn, int quiet, void *cb_data,
|
struct check_connected_options *opt);
|
||||||
const char *shallow_file);
|
|
||||||
extern int check_everything_connected_with_transport(sha1_iterate_fn, int quiet,
|
|
||||||
void *cb_data,
|
|
||||||
struct transport *transport);
|
|
||||||
|
|
||||||
#endif /* CONNECTED_H */
|
#endif /* CONNECTED_H */
|
||||||
|
|||||||
2
contrib/coccinelle/README
Normal file
2
contrib/coccinelle/README
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
This directory provides examples of Coccinelle (http://coccinelle.lip6.fr/)
|
||||||
|
semantic patches that might be useful to developers.
|
||||||
95
contrib/coccinelle/object_id.cocci
Normal file
95
contrib/coccinelle/object_id.cocci
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- is_null_sha1(E1.hash)
|
||||||
|
+ is_null_oid(&E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- is_null_sha1(E1->hash)
|
||||||
|
+ is_null_oid(E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- sha1_to_hex(E1.hash)
|
||||||
|
+ oid_to_hex(&E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- sha1_to_hex(E1->hash)
|
||||||
|
+ oid_to_hex(E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- sha1_to_hex_r(E1.hash)
|
||||||
|
+ oid_to_hex_r(&E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- sha1_to_hex_r(E1->hash)
|
||||||
|
+ oid_to_hex_r(E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- hashclr(E1.hash)
|
||||||
|
+ oidclr(&E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
- hashclr(E1->hash)
|
||||||
|
+ oidclr(E1)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcmp(E1.hash, E2.hash)
|
||||||
|
+ oidcmp(&E1, &E2)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcmp(E1->hash, E2->hash)
|
||||||
|
+ oidcmp(E1, E2)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcmp(E1->hash, E2.hash)
|
||||||
|
+ oidcmp(E1, &E2)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcmp(E1.hash, E2->hash)
|
||||||
|
+ oidcmp(&E1, E2)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcpy(E1.hash, E2.hash)
|
||||||
|
+ oidcpy(&E1, &E2)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcpy(E1->hash, E2->hash)
|
||||||
|
+ oidcpy(E1, E2)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcpy(E1->hash, E2.hash)
|
||||||
|
+ oidcpy(E1, &E2)
|
||||||
|
|
||||||
|
@@
|
||||||
|
expression E1, E2;
|
||||||
|
@@
|
||||||
|
- hashcpy(E1.hash, E2->hash)
|
||||||
|
+ oidcpy(&E1, E2)
|
||||||
@@ -803,6 +803,50 @@ __git_find_on_cmdline ()
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Echo the value of an option set on the command line or config
|
||||||
|
#
|
||||||
|
# $1: short option name
|
||||||
|
# $2: long option name including =
|
||||||
|
# $3: list of possible values
|
||||||
|
# $4: config string (optional)
|
||||||
|
#
|
||||||
|
# example:
|
||||||
|
# result="$(__git_get_option_value "-d" "--do-something=" \
|
||||||
|
# "yes no" "core.doSomething")"
|
||||||
|
#
|
||||||
|
# result is then either empty (no option set) or "yes" or "no"
|
||||||
|
#
|
||||||
|
# __git_get_option_value requires 3 arguments
|
||||||
|
__git_get_option_value ()
|
||||||
|
{
|
||||||
|
local c short_opt long_opt val
|
||||||
|
local result= values config_key word
|
||||||
|
|
||||||
|
short_opt="$1"
|
||||||
|
long_opt="$2"
|
||||||
|
values="$3"
|
||||||
|
config_key="$4"
|
||||||
|
|
||||||
|
((c = $cword - 1))
|
||||||
|
while [ $c -ge 0 ]; do
|
||||||
|
word="${words[c]}"
|
||||||
|
for val in $values; do
|
||||||
|
if [ "$short_opt$val" = "$word" ] ||
|
||||||
|
[ "$long_opt$val" = "$word" ]; then
|
||||||
|
result="$val"
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
((c--))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$config_key" ] && [ -z "$result" ]; then
|
||||||
|
result="$(git --git-dir="$(__gitdir)" config "$config_key")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$result"
|
||||||
|
}
|
||||||
|
|
||||||
__git_has_doubledash ()
|
__git_has_doubledash ()
|
||||||
{
|
{
|
||||||
local c=1
|
local c=1
|
||||||
@@ -964,8 +1008,8 @@ _git_branch ()
|
|||||||
while [ $c -lt $cword ]; do
|
while [ $c -lt $cword ]; do
|
||||||
i="${words[c]}"
|
i="${words[c]}"
|
||||||
case "$i" in
|
case "$i" in
|
||||||
-d|-m) only_local_ref="y" ;;
|
-d|--delete|-m|--move) only_local_ref="y" ;;
|
||||||
-r) has_r="y" ;;
|
-r|--remotes) has_r="y" ;;
|
||||||
esac
|
esac
|
||||||
((c++))
|
((c++))
|
||||||
done
|
done
|
||||||
@@ -979,7 +1023,7 @@ _git_branch ()
|
|||||||
--color --no-color --verbose --abbrev= --no-abbrev
|
--color --no-color --verbose --abbrev= --no-abbrev
|
||||||
--track --no-track --contains --merged --no-merged
|
--track --no-track --contains --merged --no-merged
|
||||||
--set-upstream-to= --edit-description --list
|
--set-upstream-to= --edit-description --list
|
||||||
--unset-upstream
|
--unset-upstream --delete --move --remotes
|
||||||
"
|
"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -1099,6 +1143,8 @@ _git_clone ()
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__git_untracked_file_modes="all no normal"
|
||||||
|
|
||||||
_git_commit ()
|
_git_commit ()
|
||||||
{
|
{
|
||||||
case "$prev" in
|
case "$prev" in
|
||||||
@@ -1120,7 +1166,7 @@ _git_commit ()
|
|||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--untracked-files=*)
|
--untracked-files=*)
|
||||||
__gitcomp "all no normal" "" "${cur##--untracked-files=}"
|
__gitcomp "$__git_untracked_file_modes" "" "${cur##--untracked-files=}"
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--*)
|
--*)
|
||||||
@@ -1159,6 +1205,8 @@ _git_describe ()
|
|||||||
|
|
||||||
__git_diff_algorithms="myers minimal patience histogram"
|
__git_diff_algorithms="myers minimal patience histogram"
|
||||||
|
|
||||||
|
__git_diff_submodule_formats="log short"
|
||||||
|
|
||||||
__git_diff_common_options="--stat --numstat --shortstat --summary
|
__git_diff_common_options="--stat --numstat --shortstat --summary
|
||||||
--patch-with-stat --name-only --name-status --color
|
--patch-with-stat --name-only --name-status --color
|
||||||
--no-color --color-words --no-renames --check
|
--no-color --color-words --no-renames --check
|
||||||
@@ -1174,6 +1222,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
|
|||||||
--dirstat --dirstat= --dirstat-by-file
|
--dirstat --dirstat= --dirstat-by-file
|
||||||
--dirstat-by-file= --cumulative
|
--dirstat-by-file= --cumulative
|
||||||
--diff-algorithm=
|
--diff-algorithm=
|
||||||
|
--submodule --submodule=
|
||||||
"
|
"
|
||||||
|
|
||||||
_git_diff ()
|
_git_diff ()
|
||||||
@@ -1185,6 +1234,10 @@ _git_diff ()
|
|||||||
__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
|
__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--submodule=*)
|
||||||
|
__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
--*)
|
--*)
|
||||||
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
|
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
|
||||||
--base --ours --theirs --no-index
|
--base --ours --theirs --no-index
|
||||||
@@ -1448,6 +1501,14 @@ _git_log ()
|
|||||||
__gitcomp "full short no" "" "${cur##--decorate=}"
|
__gitcomp "full short no" "" "${cur##--decorate=}"
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--diff-algorithm=*)
|
||||||
|
__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--submodule=*)
|
||||||
|
__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
--*)
|
--*)
|
||||||
__gitcomp "
|
__gitcomp "
|
||||||
$__git_log_common_options
|
$__git_log_common_options
|
||||||
@@ -1781,6 +1842,56 @@ _git_stage ()
|
|||||||
_git_add
|
_git_add
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_git_status ()
|
||||||
|
{
|
||||||
|
local complete_opt
|
||||||
|
local untracked_state
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
--ignore-submodules=*)
|
||||||
|
__gitcomp "none untracked dirty all" "" "${cur##--ignore-submodules=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--untracked-files=*)
|
||||||
|
__gitcomp "$__git_untracked_file_modes" "" "${cur##--untracked-files=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--column=*)
|
||||||
|
__gitcomp "
|
||||||
|
always never auto column row plain dense nodense
|
||||||
|
" "" "${cur##--column=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--*)
|
||||||
|
__gitcomp "
|
||||||
|
--short --branch --porcelain --long --verbose
|
||||||
|
--untracked-files= --ignore-submodules= --ignored
|
||||||
|
--column= --no-column
|
||||||
|
"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
untracked_state="$(__git_get_option_value "-u" "--untracked-files=" \
|
||||||
|
"$__git_untracked_file_modes" "status.showUntrackedFiles")"
|
||||||
|
|
||||||
|
case "$untracked_state" in
|
||||||
|
no)
|
||||||
|
# --ignored option does not matter
|
||||||
|
complete_opt=
|
||||||
|
;;
|
||||||
|
all|normal|*)
|
||||||
|
complete_opt="--cached --directory --no-empty-directory --others"
|
||||||
|
|
||||||
|
if [ -n "$(__git_find_on_cmdline "--ignored")" ]; then
|
||||||
|
complete_opt="$complete_opt --ignored --exclude=*"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
__git_complete_index_file "$complete_opt"
|
||||||
|
}
|
||||||
|
|
||||||
__git_config_get_set_variables ()
|
__git_config_get_set_variables ()
|
||||||
{
|
{
|
||||||
local prevword word config_file= c=$cword
|
local prevword word config_file= c=$cword
|
||||||
@@ -2086,6 +2197,7 @@ _git_config ()
|
|||||||
format.attach
|
format.attach
|
||||||
format.cc
|
format.cc
|
||||||
format.coverLetter
|
format.coverLetter
|
||||||
|
format.from
|
||||||
format.headers
|
format.headers
|
||||||
format.numbered
|
format.numbered
|
||||||
format.pretty
|
format.pretty
|
||||||
@@ -2360,6 +2472,10 @@ _git_show ()
|
|||||||
__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
|
__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--submodule=*)
|
||||||
|
__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
--*)
|
--*)
|
||||||
__gitcomp "--pretty= --format= --abbrev-commit --oneline
|
__gitcomp "--pretty= --format= --abbrev-commit --oneline
|
||||||
--show-signature
|
--show-signature
|
||||||
@@ -2596,6 +2712,32 @@ _git_whatchanged ()
|
|||||||
_git_log
|
_git_log
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_git_worktree ()
|
||||||
|
{
|
||||||
|
local subcommands="add list lock prune unlock"
|
||||||
|
local subcommand="$(__git_find_on_cmdline "$subcommands")"
|
||||||
|
if [ -z "$subcommand" ]; then
|
||||||
|
__gitcomp "$subcommands"
|
||||||
|
else
|
||||||
|
case "$subcommand,$cur" in
|
||||||
|
add,--*)
|
||||||
|
__gitcomp "--detach"
|
||||||
|
;;
|
||||||
|
list,--*)
|
||||||
|
__gitcomp "--porcelain"
|
||||||
|
;;
|
||||||
|
lock,--*)
|
||||||
|
__gitcomp "--reason"
|
||||||
|
;;
|
||||||
|
prune,--*)
|
||||||
|
__gitcomp "--dry-run --expire --verbose"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
__git_main ()
|
__git_main ()
|
||||||
{
|
{
|
||||||
local i c=1 command __git_dir
|
local i c=1 command __git_dir
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Obviously this trivial case isn't that interesting; you could just open
|
|||||||
`foo.c` yourself. But when you have many changes scattered across a
|
`foo.c` yourself. But when you have many changes scattered across a
|
||||||
project, you can use the editor's support to "jump" from point to point.
|
project, you can use the editor's support to "jump" from point to point.
|
||||||
|
|
||||||
Git-jump can generate three types of interesting lists:
|
Git-jump can generate four types of interesting lists:
|
||||||
|
|
||||||
1. The beginning of any diff hunks.
|
1. The beginning of any diff hunks.
|
||||||
|
|
||||||
@@ -37,6 +37,8 @@ Git-jump can generate three types of interesting lists:
|
|||||||
|
|
||||||
3. Any grep matches.
|
3. Any grep matches.
|
||||||
|
|
||||||
|
4. Any whitespace errors detected by `git diff --check`.
|
||||||
|
|
||||||
|
|
||||||
Using git-jump
|
Using git-jump
|
||||||
--------------
|
--------------
|
||||||
@@ -83,7 +85,7 @@ complete list of files and line numbers for each match.
|
|||||||
Limitations
|
Limitations
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
This scripts was written and tested with vim. Given that the quickfix
|
This script was written and tested with vim. Given that the quickfix
|
||||||
format is the same as what gcc produces, I expect emacs users have a
|
format is the same as what gcc produces, I expect emacs users have a
|
||||||
similar feature for iterating through the list, but I know nothing about
|
similar feature for iterating through the list, but I know nothing about
|
||||||
how to activate it.
|
how to activate it.
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ diff: elements are diff hunks. Arguments are given to diff.
|
|||||||
merge: elements are merge conflicts. Arguments are ignored.
|
merge: elements are merge conflicts. Arguments are ignored.
|
||||||
|
|
||||||
grep: elements are grep hits. Arguments are given to grep.
|
grep: elements are grep hits. Arguments are given to grep.
|
||||||
|
|
||||||
|
ws: elements are whitespace errors. Arguments are given to diff --check.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +27,7 @@ mode_diff() {
|
|||||||
perl -ne '
|
perl -ne '
|
||||||
if (m{^\+\+\+ (.*)}) { $file = $1; next }
|
if (m{^\+\+\+ (.*)}) { $file = $1; next }
|
||||||
defined($file) or next;
|
defined($file) or next;
|
||||||
if (m/^@@ .*\+(\d+)/) { $line = $1; next }
|
if (m/^@@ .*?\+(\d+)/) { $line = $1; next }
|
||||||
defined($line) or next;
|
defined($line) or next;
|
||||||
if (/^ /) { $line++; next }
|
if (/^ /) { $line++; next }
|
||||||
if (/^[-+]\s*(.*)/) {
|
if (/^[-+]\s*(.*)/) {
|
||||||
@@ -55,6 +57,10 @@ mode_grep() {
|
|||||||
'
|
'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mode_ws() {
|
||||||
|
git diff --check "$@"
|
||||||
|
}
|
||||||
|
|
||||||
if test $# -lt 1; then
|
if test $# -lt 1; then
|
||||||
usage >&2
|
usage >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -1,3 +1,62 @@
|
|||||||
|
Release 1.4.0
|
||||||
|
=============
|
||||||
|
|
||||||
|
New features to troubleshoot a git-multimail installation
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
* One can now perform a basic check of git-multimail's setup by
|
||||||
|
running the hook with the environment variable
|
||||||
|
GIT_MULTIMAIL_CHECK_SETUP set to a non-empty string. See
|
||||||
|
doc/troubleshooting.rst for details.
|
||||||
|
|
||||||
|
* A new log files system was added. See the multimailhook.logFile,
|
||||||
|
multimailhook.errorLogFile and multimailhook.debugLogFile variables.
|
||||||
|
|
||||||
|
* git_multimail.py can now be made more verbose using
|
||||||
|
multimailhook.verbose.
|
||||||
|
|
||||||
|
* A new option --check-ref-filter is now available to help debugging
|
||||||
|
the refFilter* options.
|
||||||
|
|
||||||
|
Formatting emails
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* Formatting of emails was made slightly more compact, to reduce the
|
||||||
|
odds of having long subject lines truncated or wrapped in short list
|
||||||
|
of commits.
|
||||||
|
|
||||||
|
* multimailhook.emailPrefix may now use the '%(repo_shortname)s'
|
||||||
|
placeholder for the repository's short name.
|
||||||
|
|
||||||
|
* A new option multimailhook.subjectMaxLength is available to truncate
|
||||||
|
overly long subject lines.
|
||||||
|
|
||||||
|
Bug fixes and minor changes
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* Options refFilterDoSendRegex and refFilterDontSendRegex were
|
||||||
|
essentially broken. They should work now.
|
||||||
|
|
||||||
|
* The behavior when both refFilter{Do,Dont}SendRegex and
|
||||||
|
refFilter{Exclusion,Inclusion}Regex are set have been slightly
|
||||||
|
changed. Exclusion/Inclusion is now strictly stronger than
|
||||||
|
DoSend/DontSend.
|
||||||
|
|
||||||
|
* The management of precedence when a setting can be computed in
|
||||||
|
multiple ways has been considerably refactored and modified.
|
||||||
|
multimailhook.from and multimailhook.reponame now have precedence
|
||||||
|
over the environment-specific settings ($GL_REPO/$GL_USER for
|
||||||
|
gitolite, --stash-user/repo for Stash, --submitter/--project for
|
||||||
|
Gerrit).
|
||||||
|
|
||||||
|
* The coverage of the testsuite has been considerably improved. All
|
||||||
|
configuration variables now appear at least once in the testsuite.
|
||||||
|
|
||||||
|
This version was tested with Python 2.6 to 3.5. It also mostly works
|
||||||
|
with Python 2.4, but there is one known breakage in the testsuite
|
||||||
|
related to non-ascii characters. It was tested with Git
|
||||||
|
1.7.10.406.gdc801, 1.8.5.6, 2.1.4, and 2.10.0.rc0.1.g07c9292.
|
||||||
|
|
||||||
Release 1.3.1 (bugfix-only release)
|
Release 1.3.1 (bugfix-only release)
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ Contributing
|
|||||||
git-multimail is an open-source project, built by volunteers. We would
|
git-multimail is an open-source project, built by volunteers. We would
|
||||||
welcome your help!
|
welcome your help!
|
||||||
|
|
||||||
The current maintainers are Michael Haggerty <mhagger@alum.mit.edu>
|
The current maintainers are Matthieu Moy
|
||||||
and Matthieu Moy <matthieu.moy@grenoble-inp.fr>.
|
<matthieu.moy@grenoble-inp.fr> and Michael Haggerty
|
||||||
|
<mhagger@alum.mit.edu>.
|
||||||
|
|
||||||
Please note that although a copy of git-multimail is distributed in
|
Please note that although a copy of git-multimail is distributed in
|
||||||
the "contrib" section of the main Git project, development takes place
|
the "contrib" section of the main Git project, development takes place
|
||||||
@@ -22,6 +23,10 @@ to the maintainers). Please sign off your patches as per the `Git
|
|||||||
project practice
|
project practice
|
||||||
<https://github.com/git/git/blob/master/Documentation/SubmittingPatches#L234>`__.
|
<https://github.com/git/git/blob/master/Documentation/SubmittingPatches#L234>`__.
|
||||||
|
|
||||||
|
Please vote for issues you would like to be addressed in priority
|
||||||
|
(click "add your reaction" and then the "+1" thumbs-up button on the
|
||||||
|
GitHub issue).
|
||||||
|
|
||||||
General discussion of git-multimail can take place on the main `Git
|
General discussion of git-multimail can take place on the main `Git
|
||||||
mailing list`_.
|
mailing list`_.
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
git-multimail 1.3.1
|
git-multimail version 1.4.0
|
||||||
===================
|
===========================
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/git-multimail/git-multimail.svg?branch=master
|
.. image:: https://travis-ci.org/git-multimail/git-multimail.svg?branch=master
|
||||||
:target: https://travis-ci.org/git-multimail/git-multimail
|
:target: https://travis-ci.org/git-multimail/git-multimail
|
||||||
|
|
||||||
git-multimail is a tool for sending notification emails on pushes to a
|
git-multimail is a tool for sending notification emails on pushes to a
|
||||||
Git repository. It includes a Python module called git_multimail.py,
|
Git repository. It includes a Python module called ``git_multimail.py``,
|
||||||
which can either be used as a hook script directly or can be imported
|
which can either be used as a hook script directly or can be imported
|
||||||
as a Python module into another script.
|
as a Python module into another script.
|
||||||
|
|
||||||
@@ -93,20 +93,20 @@ Requirements
|
|||||||
Invocation
|
Invocation
|
||||||
----------
|
----------
|
||||||
|
|
||||||
git_multimail.py is designed to be used as a ``post-receive`` hook in a
|
``git_multimail.py`` is designed to be used as a ``post-receive`` hook in a
|
||||||
Git repository (see githooks(5)). Link or copy it to
|
Git repository (see githooks(5)). Link or copy it to
|
||||||
$GIT_DIR/hooks/post-receive within the repository for which email
|
$GIT_DIR/hooks/post-receive within the repository for which email
|
||||||
notifications are desired. Usually it should be installed on the
|
notifications are desired. Usually it should be installed on the
|
||||||
central repository for a project, to which all commits are eventually
|
central repository for a project, to which all commits are eventually
|
||||||
pushed.
|
pushed.
|
||||||
|
|
||||||
For use on pre-v1.5.1 Git servers, git_multimail.py can also work as
|
For use on pre-v1.5.1 Git servers, ``git_multimail.py`` can also work as
|
||||||
an ``update`` hook, taking its arguments on the command line. To use
|
an ``update`` hook, taking its arguments on the command line. To use
|
||||||
this script in this manner, link or copy it to $GIT_DIR/hooks/update.
|
this script in this manner, link or copy it to $GIT_DIR/hooks/update.
|
||||||
Please note that the script is not completely reliable in this mode
|
Please note that the script is not completely reliable in this mode
|
||||||
[2]_.
|
[1]_.
|
||||||
|
|
||||||
Alternatively, git_multimail.py can be imported as a Python module
|
Alternatively, ``git_multimail.py`` can be imported as a Python module
|
||||||
into your own Python post-receive script. This method is a bit more
|
into your own Python post-receive script. This method is a bit more
|
||||||
work, but allows the behavior of the hook to be customized using
|
work, but allows the behavior of the hook to be customized using
|
||||||
arbitrary Python code. For example, you can use a custom environment
|
arbitrary Python code. For example, you can use a custom environment
|
||||||
@@ -122,7 +122,7 @@ arbitrary Python code. For example, you can use a custom environment
|
|||||||
|
|
||||||
Or you can change how emails are sent by writing your own Mailer
|
Or you can change how emails are sent by writing your own Mailer
|
||||||
class. The ``post-receive`` script in this directory demonstrates how
|
class. The ``post-receive`` script in this directory demonstrates how
|
||||||
to use git_multimail.py as a Python module. (If you make interesting
|
to use ``git_multimail.py`` as a Python module. (If you make interesting
|
||||||
changes of this type, please consider sharing them with the
|
changes of this type, please consider sharing them with the
|
||||||
community.)
|
community.)
|
||||||
|
|
||||||
@@ -151,7 +151,10 @@ multimailhook.environment
|
|||||||
the repository name is derived from the repository's path.
|
the repository name is derived from the repository's path.
|
||||||
|
|
||||||
gitolite
|
gitolite
|
||||||
the username of the pusher is read from $GL_USER, the repository
|
Environment to use when ``git-multimail`` is ran as a gitolite_
|
||||||
|
hook.
|
||||||
|
|
||||||
|
The username of the pusher is read from $GL_USER, the repository
|
||||||
name is read from $GL_REPO, and the From: header value is
|
name is read from $GL_REPO, and the From: header value is
|
||||||
optionally read from gitolite.conf (see multimailhook.from).
|
optionally read from gitolite.conf (see multimailhook.from).
|
||||||
|
|
||||||
@@ -294,7 +297,7 @@ multimailhook.htmlInIntro, multimailhook.htmlInFooter
|
|||||||
like ``<a href="foo">link</a>``, the reader will see the HTML
|
like ``<a href="foo">link</a>``, the reader will see the HTML
|
||||||
source code and not a proper link.
|
source code and not a proper link.
|
||||||
|
|
||||||
Set ``multimailhook.htmlInIntro`` to true to allow writting HTML
|
Set ``multimailhook.htmlInIntro`` to true to allow writing HTML
|
||||||
formatting in introduction templates. Similarly, set
|
formatting in introduction templates. Similarly, set
|
||||||
``multimailhook.htmlInFooter`` for HTML in the footer.
|
``multimailhook.htmlInFooter`` for HTML in the footer.
|
||||||
|
|
||||||
@@ -444,7 +447,9 @@ multimailhook.emailPrefix
|
|||||||
email filtering (though filtering based on the X-Git-* email
|
email filtering (though filtering based on the X-Git-* email
|
||||||
headers is probably more robust). Default is the short name of
|
headers is probably more robust). Default is the short name of
|
||||||
the repository in square brackets; e.g., ``[myrepo]``. Set this
|
the repository in square brackets; e.g., ``[myrepo]``. Set this
|
||||||
value to the empty string to suppress the email prefix.
|
value to the empty string to suppress the email prefix. You may
|
||||||
|
use the placeholder ``%(repo_shortname)s`` for the short name of
|
||||||
|
the repository.
|
||||||
|
|
||||||
multimailhook.emailMaxLines
|
multimailhook.emailMaxLines
|
||||||
The maximum number of lines that should be included in the body of
|
The maximum number of lines that should be included in the body of
|
||||||
@@ -461,6 +466,17 @@ multimailhook.emailMaxLineLength
|
|||||||
lines, the diffs are probably unreadable anyway. To disable line
|
lines, the diffs are probably unreadable anyway. To disable line
|
||||||
truncation, set this option to 0.
|
truncation, set this option to 0.
|
||||||
|
|
||||||
|
multimailhook.subjectMaxLength
|
||||||
|
The maximum length of the subject line (i.e. the ``oneline`` field
|
||||||
|
in templates, not including the prefix). Lines longer than this
|
||||||
|
limit are truncated to this length with a trailing ``[...]`` added
|
||||||
|
to indicate the missing text. This option The default is to use
|
||||||
|
``multimailhook.emailMaxLineLength``. This option avoids sending
|
||||||
|
emails with overly long subject lines, but should not be needed if
|
||||||
|
the commit messages follow the Git convention (one short subject
|
||||||
|
line, then a blank line, then the message body). To disable line
|
||||||
|
truncation, set this option to 0.
|
||||||
|
|
||||||
multimailhook.maxCommitEmails
|
multimailhook.maxCommitEmails
|
||||||
The maximum number of commit emails to send for a given change.
|
The maximum number of commit emails to send for a given change.
|
||||||
When the number of patches is larger that this value, only the
|
When the number of patches is larger that this value, only the
|
||||||
@@ -474,12 +490,15 @@ multimailhook.emailStrictUTF8
|
|||||||
not valid UTF-8 are converted to the Unicode replacement
|
not valid UTF-8 are converted to the Unicode replacement
|
||||||
character, U+FFFD. The default is `true`.
|
character, U+FFFD. The default is `true`.
|
||||||
|
|
||||||
|
This option is ineffective with Python 3, where non-UTF-8
|
||||||
|
characters are unconditionally replaced.
|
||||||
|
|
||||||
multimailhook.diffOpts
|
multimailhook.diffOpts
|
||||||
Options passed to ``git diff-tree`` when generating the summary
|
Options passed to ``git diff-tree`` when generating the summary
|
||||||
information for ReferenceChange emails. Default is ``--stat
|
information for ReferenceChange emails. Default is ``--stat
|
||||||
--summary --find-copies-harder``. Add -p to those options to
|
--summary --find-copies-harder``. Add -p to those options to
|
||||||
include a unified diff of changes in addition to the usual summary
|
include a unified diff of changes in addition to the usual summary
|
||||||
output. Shell quoting is allowed; see multimailhook.logOpts for
|
output. Shell quoting is allowed; see ``multimailhook.logOpts`` for
|
||||||
details.
|
details.
|
||||||
|
|
||||||
multimailhook.graphOpts
|
multimailhook.graphOpts
|
||||||
@@ -516,7 +535,7 @@ multimailhook.commitLogOpts
|
|||||||
|
|
||||||
multimailhook.dateSubstitute
|
multimailhook.dateSubstitute
|
||||||
String to use as a substitute for ``Date:`` in the output of ``git
|
String to use as a substitute for ``Date:`` in the output of ``git
|
||||||
log`` while formatting commit messages. This is usefull to avoid
|
log`` while formatting commit messages. This is useful to avoid
|
||||||
emitting a line that can be interpreted by mailers as the start of
|
emitting a line that can be interpreted by mailers as the start of
|
||||||
a cited message (Zimbra webmail in particular). Defaults to
|
a cited message (Zimbra webmail in particular). Defaults to
|
||||||
``CommitDate:``. Set to an empty string or ``none`` to deactivate
|
``CommitDate:``. Set to an empty string or ``none`` to deactivate
|
||||||
@@ -564,6 +583,8 @@ multimailhook.refFilterInclusionRegex, multimailhook.refFilterExclusionRegex, mu
|
|||||||
the user-interface is not stable yet (in particular, the option
|
the user-interface is not stable yet (in particular, the option
|
||||||
names may change). If you want to participate in stabilizing the
|
names may change). If you want to participate in stabilizing the
|
||||||
feature, please contact the maintainers and/or send pull-requests.
|
feature, please contact the maintainers and/or send pull-requests.
|
||||||
|
If you are happy with the current shape of the feature, please
|
||||||
|
report it too.
|
||||||
|
|
||||||
Regular expressions that can be used to limit refs for which email
|
Regular expressions that can be used to limit refs for which email
|
||||||
updates will be sent. It is an error to specify both an inclusion
|
updates will be sent. It is an error to specify both an inclusion
|
||||||
@@ -613,6 +634,32 @@ multimailhook.refFilterInclusionRegex, multimailhook.refFilterExclusionRegex, mu
|
|||||||
[multimailhook]
|
[multimailhook]
|
||||||
refFilterExclusionRegex = ^refs/tags/|^refs/heads/master$
|
refFilterExclusionRegex = ^refs/tags/|^refs/heads/master$
|
||||||
|
|
||||||
|
``refFilterInclusionRegex`` and ``refFilterExclusionRegex`` are
|
||||||
|
strictly stronger than ``refFilterDoSendRegex`` and
|
||||||
|
``refFilterDontSendRegex``. In other words, adding a ref to a
|
||||||
|
DoSend/DontSend regex has no effect if it is already excluded by a
|
||||||
|
Exclusion/Inclusion regex.
|
||||||
|
|
||||||
|
multimailhook.logFile, multimailhook.errorLogFile, multimailhook.debugLogFile
|
||||||
|
|
||||||
|
When set, these variable designate path to files where
|
||||||
|
git-multimail will log some messages. Normal messages and error
|
||||||
|
messages are sent to ``logFile``, and error messages are also sent
|
||||||
|
to ``errorLogFile``. Debug messages and all other messages are
|
||||||
|
sent to ``debugLogFile``. The recommended way is to set only one
|
||||||
|
of these variables, but it is also possible to set several of them
|
||||||
|
(part of the information is then duplicated in several log files,
|
||||||
|
for example errors are duplicated to all log files).
|
||||||
|
|
||||||
|
Relative path are relative to the Git repository where the push is
|
||||||
|
done.
|
||||||
|
|
||||||
|
multimailhook.verbose
|
||||||
|
|
||||||
|
Verbosity level of git-multimail on its standard output. By
|
||||||
|
default, show only error and info messages. If set to true, show
|
||||||
|
also debug messages.
|
||||||
|
|
||||||
Email filtering aids
|
Email filtering aids
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -628,8 +675,8 @@ Customizing email contents
|
|||||||
|
|
||||||
git-multimail mostly generates emails by expanding templates. The
|
git-multimail mostly generates emails by expanding templates. The
|
||||||
templates can be customized. To avoid the need to edit
|
templates can be customized. To avoid the need to edit
|
||||||
git_multimail.py directly, the preferred way to change the templates
|
``git_multimail.py`` directly, the preferred way to change the templates
|
||||||
is to write a separate Python script that imports git_multimail.py as
|
is to write a separate Python script that imports ``git_multimail.py`` as
|
||||||
a module, then replaces the templates in place. See the provided
|
a module, then replaces the templates in place. See the provided
|
||||||
post-receive script for an example of how this is done.
|
post-receive script for an example of how this is done.
|
||||||
|
|
||||||
@@ -645,8 +692,8 @@ GenericEnvironment
|
|||||||
a stand-alone Git repository.
|
a stand-alone Git repository.
|
||||||
|
|
||||||
GitoliteEnvironment
|
GitoliteEnvironment
|
||||||
a Git repository that is managed by gitolite
|
a Git repository that is managed by gitolite_. For such
|
||||||
[3]_. For such repositories, the identity of the pusher is read from
|
repositories, the identity of the pusher is read from
|
||||||
environment variable $GL_USER, the name of the repository is read
|
environment variable $GL_USER, the name of the repository is read
|
||||||
from $GL_REPO (if it is not overridden by multimailhook.reponame),
|
from $GL_REPO (if it is not overridden by multimailhook.reponame),
|
||||||
and the From: header value is optionally read from gitolite.conf
|
and the From: header value is optionally read from gitolite.conf
|
||||||
@@ -662,7 +709,7 @@ option to the script.
|
|||||||
If you need to customize the script in ways that are not supported by
|
If you need to customize the script in ways that are not supported by
|
||||||
the existing environments, you can define your own environment class
|
the existing environments, you can define your own environment class
|
||||||
class using arbitrary Python code. To do so, you need to import
|
class using arbitrary Python code. To do so, you need to import
|
||||||
git_multimail.py as a Python module, as demonstrated by the example
|
``git_multimail.py`` as a Python module, as demonstrated by the example
|
||||||
post-receive script. Then implement your environment class; it should
|
post-receive script. Then implement your environment class; it should
|
||||||
usually inherit from one of the existing Environment classes and
|
usually inherit from one of the existing Environment classes and
|
||||||
possibly one or more of the EnvironmentMixin classes. Then set the
|
possibly one or more of the EnvironmentMixin classes. Then set the
|
||||||
@@ -690,9 +737,7 @@ contribute to git-multimail.
|
|||||||
Footnotes
|
Footnotes
|
||||||
---------
|
---------
|
||||||
|
|
||||||
.. [1] http://www.python.org/dev/peps/pep-0394/
|
.. [1] Because of the way information is passed to update hooks, the
|
||||||
|
|
||||||
.. [2] Because of the way information is passed to update hooks, the
|
|
||||||
script's method of determining whether a commit has already
|
script's method of determining whether a commit has already
|
||||||
been seen does not work when it is used as an ``update`` script.
|
been seen does not work when it is used as an ``update`` script.
|
||||||
In particular, no notification email will be generated for a
|
In particular, no notification email will be generated for a
|
||||||
@@ -700,4 +745,4 @@ Footnotes
|
|||||||
push. A workaround is to use --force-send to force sending the
|
push. A workaround is to use --force-send to force sending the
|
||||||
emails.
|
emails.
|
||||||
|
|
||||||
.. [3] https://github.com/sitaramc/gitolite
|
.. _gitolite: https://github.com/sitaramc/gitolite
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ website:
|
|||||||
https://github.com/git-multimail/git-multimail
|
https://github.com/git-multimail/git-multimail
|
||||||
|
|
||||||
The version in this directory was obtained from the upstream project
|
The version in this directory was obtained from the upstream project
|
||||||
on May 13 2016 and consists of the "git-multimail" subdirectory from
|
on August 17 2016 and consists of the "git-multimail" subdirectory from
|
||||||
revision
|
revision
|
||||||
|
|
||||||
3ce5470d4abf7251604cbf64e73a962e1b617f5e refs/tags/1.3.1
|
07b1cb6bfd7be156c62e1afa17cae13b850a869f refs/tags/1.4.0
|
||||||
|
|
||||||
Please see the README file in this directory for information about how
|
Please see the README file in this directory for information about how
|
||||||
to report bugs or contribute to git-multimail.
|
to report bugs or contribute to git-multimail.
|
||||||
|
|||||||
@@ -1,6 +1,40 @@
|
|||||||
Troubleshooting issues with git-multimail: a FAQ
|
Troubleshooting issues with git-multimail: a FAQ
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
|
How to check that git-multimail is properly set up?
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
Since version 1.4.0, git-multimail allows a simple self-checking of
|
||||||
|
its configuration: run it with the environment variable
|
||||||
|
``GIT_MULTIMAIL_CHECK_SETUP`` set to a non-empty string. You should
|
||||||
|
get something like this::
|
||||||
|
|
||||||
|
$ GIT_MULTIMAIL_CHECK_SETUP=true /home/moy/dev/git-multimail/git-multimail/git_multimail.py
|
||||||
|
Environment values:
|
||||||
|
administrator : 'the administrator of this repository'
|
||||||
|
charset : 'utf-8'
|
||||||
|
emailprefix : '[git-multimail] '
|
||||||
|
fqdn : 'anie'
|
||||||
|
projectdesc : 'UNNAMED PROJECT'
|
||||||
|
pusher : 'moy'
|
||||||
|
repo_path : '/home/moy/dev/git-multimail'
|
||||||
|
repo_shortname : 'git-multimail'
|
||||||
|
|
||||||
|
Now, checking that git-multimail's standard input is properly set ...
|
||||||
|
Please type some text and then press Return
|
||||||
|
foo
|
||||||
|
You have just entered:
|
||||||
|
foo
|
||||||
|
git-multimail seems properly set up.
|
||||||
|
|
||||||
|
If you forgot to set an important variable, you may get instead::
|
||||||
|
|
||||||
|
$ GIT_MULTIMAIL_CHECK_SETUP=true /home/moy/dev/git-multimail/git-multimail/git_multimail.py
|
||||||
|
No email recipients configured!
|
||||||
|
|
||||||
|
Do not set ``$GIT_MULTIMAIL_CHECK_SETUP`` other than for testing your
|
||||||
|
configuration: it would disable the hook completely.
|
||||||
|
|
||||||
Git is not using the right address in the From/To/Reply-To field
|
Git is not using the right address in the From/To/Reply-To field
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
|||||||
[InputOutput::RequireCheckedSyscalls]
|
[InputOutput::RequireCheckedSyscalls]
|
||||||
functions = open say close
|
functions = open say close
|
||||||
|
|
||||||
# This rules demands to add a dependancy for the Readonly module. This is not
|
# This rule demands to add a dependency for the Readonly module. This is not
|
||||||
# wished.
|
# wished.
|
||||||
[-ValuesAndExpressions::ProhibitConstantPragma]
|
[-ValuesAndExpressions::ProhibitConstantPragma]
|
||||||
|
|
||||||
|
|||||||
@@ -963,7 +963,7 @@ sub mw_upload_file {
|
|||||||
print {*STDERR} "Check the configuration of file uploads in your mediawiki.\n";
|
print {*STDERR} "Check the configuration of file uploads in your mediawiki.\n";
|
||||||
return $newrevid;
|
return $newrevid;
|
||||||
}
|
}
|
||||||
# Deleting and uploading a file requires a priviledged user
|
# Deleting and uploading a file requires a privileged user
|
||||||
if ($file_deleted) {
|
if ($file_deleted) {
|
||||||
$mediawiki = connect_maybe($mediawiki, $remotename, $url);
|
$mediawiki = connect_maybe($mediawiki, $remotename, $url);
|
||||||
my $query = {
|
my $query = {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -948,7 +948,7 @@ test_expect_success 'split a new subtree without --onto option' '
|
|||||||
|
|
||||||
# also test that we still can split out an entirely new subtree
|
# also test that we still can split out an entirely new subtree
|
||||||
# if the parent of the first commit in the tree is not empty,
|
# if the parent of the first commit in the tree is not empty,
|
||||||
# then the new subtree has accidently been attached to something
|
# then the new subtree has accidentally been attached to something
|
||||||
git subtree split --prefix="sub dir2" --branch subproj2-br &&
|
git subtree split --prefix="sub dir2" --branch subproj2-br &&
|
||||||
check_equal "$(git log --pretty=format:%P -1 subproj2-br)" ""
|
check_equal "$(git log --pretty=format:%P -1 subproj2-br)" ""
|
||||||
)
|
)
|
||||||
|
|||||||
97
convert.c
97
convert.c
@@ -189,33 +189,25 @@ static enum eol output_eol(enum crlf_action crlf_action)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void check_safe_crlf(const char *path, enum crlf_action crlf_action,
|
static void check_safe_crlf(const char *path, enum crlf_action crlf_action,
|
||||||
struct text_stat *stats, enum safe_crlf checksafe)
|
struct text_stat *old_stats, struct text_stat *new_stats,
|
||||||
|
enum safe_crlf checksafe)
|
||||||
{
|
{
|
||||||
if (!checksafe)
|
if (old_stats->crlf && !new_stats->crlf ) {
|
||||||
return;
|
|
||||||
|
|
||||||
if (output_eol(crlf_action) == EOL_LF) {
|
|
||||||
/*
|
/*
|
||||||
* CRLFs would not be restored by checkout:
|
* CRLFs would not be restored by checkout
|
||||||
* check if we'd remove CRLFs
|
|
||||||
*/
|
*/
|
||||||
if (stats->crlf) {
|
if (checksafe == SAFE_CRLF_WARN)
|
||||||
if (checksafe == SAFE_CRLF_WARN)
|
warning("CRLF will be replaced by LF in %s.\nThe file will have its original line endings in your working directory.", path);
|
||||||
warning("CRLF will be replaced by LF in %s.\nThe file will have its original line endings in your working directory.", path);
|
else /* i.e. SAFE_CRLF_FAIL */
|
||||||
else /* i.e. SAFE_CRLF_FAIL */
|
die("CRLF would be replaced by LF in %s.", path);
|
||||||
die("CRLF would be replaced by LF in %s.", path);
|
} else if (old_stats->lonelf && !new_stats->lonelf ) {
|
||||||
}
|
|
||||||
} else if (output_eol(crlf_action) == EOL_CRLF) {
|
|
||||||
/*
|
/*
|
||||||
* CRLFs would be added by checkout:
|
* CRLFs would be added by checkout
|
||||||
* check if we have "naked" LFs
|
|
||||||
*/
|
*/
|
||||||
if (stats->lonelf) {
|
if (checksafe == SAFE_CRLF_WARN)
|
||||||
if (checksafe == SAFE_CRLF_WARN)
|
warning("LF will be replaced by CRLF in %s.\nThe file will have its original line endings in your working directory.", path);
|
||||||
warning("LF will be replaced by CRLF in %s.\nThe file will have its original line endings in your working directory.", path);
|
else /* i.e. SAFE_CRLF_FAIL */
|
||||||
else /* i.e. SAFE_CRLF_FAIL */
|
die("LF would be replaced by CRLF in %s", path);
|
||||||
die("LF would be replaced by CRLF in %s", path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,12 +225,35 @@ static int has_cr_in_index(const char *path)
|
|||||||
return has_cr;
|
return has_cr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int will_convert_lf_to_crlf(size_t len, struct text_stat *stats,
|
||||||
|
enum crlf_action crlf_action)
|
||||||
|
{
|
||||||
|
if (output_eol(crlf_action) != EOL_CRLF)
|
||||||
|
return 0;
|
||||||
|
/* No "naked" LF? Nothing to convert, regardless. */
|
||||||
|
if (!stats->lonelf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
|
||||||
|
/* If we have any CR or CRLF line endings, we do not touch it */
|
||||||
|
/* This is the new safer autocrlf-handling */
|
||||||
|
if (stats->lonecr || stats->crlf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (convert_is_binary(len, stats))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int crlf_to_git(const char *path, const char *src, size_t len,
|
static int crlf_to_git(const char *path, const char *src, size_t len,
|
||||||
struct strbuf *buf,
|
struct strbuf *buf,
|
||||||
enum crlf_action crlf_action, enum safe_crlf checksafe)
|
enum crlf_action crlf_action, enum safe_crlf checksafe)
|
||||||
{
|
{
|
||||||
struct text_stat stats;
|
struct text_stat stats;
|
||||||
char *dst;
|
char *dst;
|
||||||
|
int convert_crlf_into_lf;
|
||||||
|
|
||||||
if (crlf_action == CRLF_BINARY ||
|
if (crlf_action == CRLF_BINARY ||
|
||||||
(src && !len))
|
(src && !len))
|
||||||
@@ -252,6 +267,8 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
gather_stats(src, len, &stats);
|
gather_stats(src, len, &stats);
|
||||||
|
/* Optimization: No CRLF? Nothing to convert, regardless. */
|
||||||
|
convert_crlf_into_lf = !!stats.crlf;
|
||||||
|
|
||||||
if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
|
if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
|
||||||
if (convert_is_binary(len, &stats))
|
if (convert_is_binary(len, &stats))
|
||||||
@@ -263,12 +280,24 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
|
|||||||
if (checksafe == SAFE_CRLF_RENORMALIZE)
|
if (checksafe == SAFE_CRLF_RENORMALIZE)
|
||||||
checksafe = SAFE_CRLF_FALSE;
|
checksafe = SAFE_CRLF_FALSE;
|
||||||
else if (has_cr_in_index(path))
|
else if (has_cr_in_index(path))
|
||||||
return 0;
|
convert_crlf_into_lf = 0;
|
||||||
}
|
}
|
||||||
check_safe_crlf(path, crlf_action, &stats, checksafe);
|
if (checksafe && len) {
|
||||||
|
struct text_stat new_stats;
|
||||||
/* Optimization: No CRLF? Nothing to convert, regardless. */
|
memcpy(&new_stats, &stats, sizeof(new_stats));
|
||||||
if (!stats.crlf)
|
/* simulate "git add" */
|
||||||
|
if (convert_crlf_into_lf) {
|
||||||
|
new_stats.lonelf += new_stats.crlf;
|
||||||
|
new_stats.crlf = 0;
|
||||||
|
}
|
||||||
|
/* simulate "git checkout" */
|
||||||
|
if (will_convert_lf_to_crlf(len, &new_stats, crlf_action)) {
|
||||||
|
new_stats.crlf += new_stats.lonelf;
|
||||||
|
new_stats.lonelf = 0;
|
||||||
|
}
|
||||||
|
check_safe_crlf(path, crlf_action, &stats, &new_stats, checksafe);
|
||||||
|
}
|
||||||
|
if (!convert_crlf_into_lf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -314,21 +343,9 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gather_stats(src, len, &stats);
|
gather_stats(src, len, &stats);
|
||||||
|
if (!will_convert_lf_to_crlf(len, &stats, crlf_action))
|
||||||
/* No "naked" LF? Nothing to convert, regardless. */
|
|
||||||
if (!stats.lonelf)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
|
|
||||||
/* If we have any CR or CRLF line endings, we do not touch it */
|
|
||||||
/* This is the new safer autocrlf-handling */
|
|
||||||
if (stats.lonecr || stats.crlf )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (convert_is_binary(len, &stats))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* are we "faking" in place editing ? */
|
/* are we "faking" in place editing ? */
|
||||||
if (src == buf->buf)
|
if (src == buf->buf)
|
||||||
to_free = strbuf_detach(buf, NULL);
|
to_free = strbuf_detach(buf, NULL);
|
||||||
|
|||||||
117
diff.c
117
diff.c
@@ -1933,8 +1933,8 @@ static void show_dirstat(struct diff_options *options)
|
|||||||
|
|
||||||
name = p->two->path ? p->two->path : p->one->path;
|
name = p->two->path ? p->two->path : p->one->path;
|
||||||
|
|
||||||
if (p->one->sha1_valid && p->two->sha1_valid)
|
if (p->one->oid_valid && p->two->oid_valid)
|
||||||
content_changed = hashcmp(p->one->sha1, p->two->sha1);
|
content_changed = oidcmp(&p->one->oid, &p->two->oid);
|
||||||
else
|
else
|
||||||
content_changed = 1;
|
content_changed = 1;
|
||||||
|
|
||||||
@@ -2306,7 +2306,8 @@ static void builtin_diff(const char *name_a,
|
|||||||
const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
|
const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
|
||||||
show_submodule_summary(o->file, one->path ? one->path : two->path,
|
show_submodule_summary(o->file, one->path ? one->path : two->path,
|
||||||
line_prefix,
|
line_prefix,
|
||||||
one->sha1, two->sha1, two->dirty_submodule,
|
one->oid.hash, two->oid.hash,
|
||||||
|
two->dirty_submodule,
|
||||||
meta, del, add, reset);
|
meta, del, add, reset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2384,7 +2385,7 @@ static void builtin_diff(const char *name_a,
|
|||||||
if (!one->data && !two->data &&
|
if (!one->data && !two->data &&
|
||||||
S_ISREG(one->mode) && S_ISREG(two->mode) &&
|
S_ISREG(one->mode) && S_ISREG(two->mode) &&
|
||||||
!DIFF_OPT_TST(o, BINARY)) {
|
!DIFF_OPT_TST(o, BINARY)) {
|
||||||
if (!hashcmp(one->sha1, two->sha1)) {
|
if (!oidcmp(&one->oid, &two->oid)) {
|
||||||
if (must_show_header)
|
if (must_show_header)
|
||||||
fprintf(o->file, "%s", header.buf);
|
fprintf(o->file, "%s", header.buf);
|
||||||
goto free_ab_and_return;
|
goto free_ab_and_return;
|
||||||
@@ -2505,7 +2506,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
same_contents = !hashcmp(one->sha1, two->sha1);
|
same_contents = !oidcmp(&one->oid, &two->oid);
|
||||||
|
|
||||||
if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
|
if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
|
||||||
data->is_binary = 1;
|
data->is_binary = 1;
|
||||||
@@ -2638,8 +2639,8 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
|
|||||||
{
|
{
|
||||||
if (mode) {
|
if (mode) {
|
||||||
spec->mode = canon_mode(mode);
|
spec->mode = canon_mode(mode);
|
||||||
hashcpy(spec->sha1, sha1);
|
hashcpy(spec->oid.hash, sha1);
|
||||||
spec->sha1_valid = sha1_valid;
|
spec->oid_valid = sha1_valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2728,7 +2729,8 @@ static int diff_populate_gitlink(struct diff_filespec *s, int size_only)
|
|||||||
if (s->dirty_submodule)
|
if (s->dirty_submodule)
|
||||||
dirty = "-dirty";
|
dirty = "-dirty";
|
||||||
|
|
||||||
strbuf_addf(&buf, "Subproject commit %s%s\n", sha1_to_hex(s->sha1), dirty);
|
strbuf_addf(&buf, "Subproject commit %s%s\n",
|
||||||
|
oid_to_hex(&s->oid), dirty);
|
||||||
s->size = buf.len;
|
s->size = buf.len;
|
||||||
if (size_only) {
|
if (size_only) {
|
||||||
s->data = NULL;
|
s->data = NULL;
|
||||||
@@ -2771,8 +2773,8 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
|
|||||||
if (S_ISGITLINK(s->mode))
|
if (S_ISGITLINK(s->mode))
|
||||||
return diff_populate_gitlink(s, size_only);
|
return diff_populate_gitlink(s, size_only);
|
||||||
|
|
||||||
if (!s->sha1_valid ||
|
if (!s->oid_valid ||
|
||||||
reuse_worktree_file(s->path, s->sha1, 0)) {
|
reuse_worktree_file(s->path, s->oid.hash, 0)) {
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int fd;
|
int fd;
|
||||||
@@ -2829,9 +2831,10 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
|
|||||||
else {
|
else {
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
if (size_only || (flags & CHECK_BINARY)) {
|
if (size_only || (flags & CHECK_BINARY)) {
|
||||||
type = sha1_object_info(s->sha1, &s->size);
|
type = sha1_object_info(s->oid.hash, &s->size);
|
||||||
if (type < 0)
|
if (type < 0)
|
||||||
die("unable to read %s", sha1_to_hex(s->sha1));
|
die("unable to read %s",
|
||||||
|
oid_to_hex(&s->oid));
|
||||||
if (size_only)
|
if (size_only)
|
||||||
return 0;
|
return 0;
|
||||||
if (s->size > big_file_threshold && s->is_binary == -1) {
|
if (s->size > big_file_threshold && s->is_binary == -1) {
|
||||||
@@ -2839,9 +2842,9 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->data = read_sha1_file(s->sha1, &type, &s->size);
|
s->data = read_sha1_file(s->oid.hash, &type, &s->size);
|
||||||
if (!s->data)
|
if (!s->data)
|
||||||
die("unable to read %s", sha1_to_hex(s->sha1));
|
die("unable to read %s", oid_to_hex(&s->oid));
|
||||||
s->should_free = 1;
|
s->should_free = 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2870,7 +2873,7 @@ void diff_free_filespec_data(struct diff_filespec *s)
|
|||||||
static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
|
static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
|
||||||
void *blob,
|
void *blob,
|
||||||
unsigned long size,
|
unsigned long size,
|
||||||
const unsigned char *sha1,
|
const struct object_id *oid,
|
||||||
int mode)
|
int mode)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
@@ -2895,7 +2898,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
|
|||||||
die_errno("unable to write temp-file");
|
die_errno("unable to write temp-file");
|
||||||
close_tempfile(&temp->tempfile);
|
close_tempfile(&temp->tempfile);
|
||||||
temp->name = get_tempfile_path(&temp->tempfile);
|
temp->name = get_tempfile_path(&temp->tempfile);
|
||||||
sha1_to_hex_r(temp->hex, sha1);
|
oid_to_hex_r(temp->hex, oid);
|
||||||
xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
|
xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
strbuf_release(&template);
|
strbuf_release(&template);
|
||||||
@@ -2919,8 +2922,8 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!S_ISGITLINK(one->mode) &&
|
if (!S_ISGITLINK(one->mode) &&
|
||||||
(!one->sha1_valid ||
|
(!one->oid_valid ||
|
||||||
reuse_worktree_file(name, one->sha1, 1))) {
|
reuse_worktree_file(name, one->oid.hash, 1))) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(name, &st) < 0) {
|
if (lstat(name, &st) < 0) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
@@ -2932,19 +2935,19 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
|||||||
if (strbuf_readlink(&sb, name, st.st_size) < 0)
|
if (strbuf_readlink(&sb, name, st.st_size) < 0)
|
||||||
die_errno("readlink(%s)", name);
|
die_errno("readlink(%s)", name);
|
||||||
prep_temp_blob(name, temp, sb.buf, sb.len,
|
prep_temp_blob(name, temp, sb.buf, sb.len,
|
||||||
(one->sha1_valid ?
|
(one->oid_valid ?
|
||||||
one->sha1 : null_sha1),
|
&one->oid : &null_oid),
|
||||||
(one->sha1_valid ?
|
(one->oid_valid ?
|
||||||
one->mode : S_IFLNK));
|
one->mode : S_IFLNK));
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* we can borrow from the file in the work tree */
|
/* we can borrow from the file in the work tree */
|
||||||
temp->name = name;
|
temp->name = name;
|
||||||
if (!one->sha1_valid)
|
if (!one->oid_valid)
|
||||||
sha1_to_hex_r(temp->hex, null_sha1);
|
sha1_to_hex_r(temp->hex, null_sha1);
|
||||||
else
|
else
|
||||||
sha1_to_hex_r(temp->hex, one->sha1);
|
sha1_to_hex_r(temp->hex, one->oid.hash);
|
||||||
/* Even though we may sometimes borrow the
|
/* Even though we may sometimes borrow the
|
||||||
* contents from the work tree, we always want
|
* contents from the work tree, we always want
|
||||||
* one->mode. mode is trustworthy even when
|
* one->mode. mode is trustworthy even when
|
||||||
@@ -2959,7 +2962,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
|||||||
if (diff_populate_filespec(one, 0))
|
if (diff_populate_filespec(one, 0))
|
||||||
die("cannot read data blob for %s", one->path);
|
die("cannot read data blob for %s", one->path);
|
||||||
prep_temp_blob(name, temp, one->data, one->size,
|
prep_temp_blob(name, temp, one->data, one->size,
|
||||||
one->sha1, one->mode);
|
&one->oid, one->mode);
|
||||||
}
|
}
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
@@ -3072,7 +3075,7 @@ static void fill_metainfo(struct strbuf *msg,
|
|||||||
default:
|
default:
|
||||||
*must_show_header = 0;
|
*must_show_header = 0;
|
||||||
}
|
}
|
||||||
if (one && two && hashcmp(one->sha1, two->sha1)) {
|
if (one && two && oidcmp(&one->oid, &two->oid)) {
|
||||||
int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
|
int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
|
||||||
|
|
||||||
if (DIFF_OPT_TST(o, BINARY)) {
|
if (DIFF_OPT_TST(o, BINARY)) {
|
||||||
@@ -3082,8 +3085,8 @@ static void fill_metainfo(struct strbuf *msg,
|
|||||||
abbrev = 40;
|
abbrev = 40;
|
||||||
}
|
}
|
||||||
strbuf_addf(msg, "%s%sindex %s..", line_prefix, set,
|
strbuf_addf(msg, "%s%sindex %s..", line_prefix, set,
|
||||||
find_unique_abbrev(one->sha1, abbrev));
|
find_unique_abbrev(one->oid.hash, abbrev));
|
||||||
strbuf_addstr(msg, find_unique_abbrev(two->sha1, abbrev));
|
strbuf_addstr(msg, find_unique_abbrev(two->oid.hash, abbrev));
|
||||||
if (one->mode == two->mode)
|
if (one->mode == two->mode)
|
||||||
strbuf_addf(msg, " %06o", one->mode);
|
strbuf_addf(msg, " %06o", one->mode);
|
||||||
strbuf_addf(msg, "%s\n", reset);
|
strbuf_addf(msg, "%s\n", reset);
|
||||||
@@ -3138,20 +3141,20 @@ static void run_diff_cmd(const char *pgm,
|
|||||||
static void diff_fill_sha1_info(struct diff_filespec *one)
|
static void diff_fill_sha1_info(struct diff_filespec *one)
|
||||||
{
|
{
|
||||||
if (DIFF_FILE_VALID(one)) {
|
if (DIFF_FILE_VALID(one)) {
|
||||||
if (!one->sha1_valid) {
|
if (!one->oid_valid) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (one->is_stdin) {
|
if (one->is_stdin) {
|
||||||
hashcpy(one->sha1, null_sha1);
|
oidclr(&one->oid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lstat(one->path, &st) < 0)
|
if (lstat(one->path, &st) < 0)
|
||||||
die_errno("stat '%s'", one->path);
|
die_errno("stat '%s'", one->path);
|
||||||
if (index_path(one->sha1, one->path, &st, 0))
|
if (index_path(one->oid.hash, one->path, &st, 0))
|
||||||
die("cannot hash %s", one->path);
|
die("cannot hash %s", one->path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hashclr(one->sha1);
|
oidclr(&one->oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
|
static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
|
||||||
@@ -3984,6 +3987,8 @@ int diff_opt_parse(struct diff_options *options,
|
|||||||
if (!options->file)
|
if (!options->file)
|
||||||
die_errno("Could not open '%s'", path);
|
die_errno("Could not open '%s'", path);
|
||||||
options->close_file = 1;
|
options->close_file = 1;
|
||||||
|
if (options->use_color != GIT_COLOR_ALWAYS)
|
||||||
|
options->use_color = GIT_COLOR_NEVER;
|
||||||
return argcount;
|
return argcount;
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
@@ -4125,8 +4130,9 @@ static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt)
|
|||||||
fprintf(opt->file, "%s", diff_line_prefix(opt));
|
fprintf(opt->file, "%s", diff_line_prefix(opt));
|
||||||
if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) {
|
if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) {
|
||||||
fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode,
|
fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode,
|
||||||
diff_unique_abbrev(p->one->sha1, opt->abbrev));
|
diff_unique_abbrev(p->one->oid.hash, opt->abbrev));
|
||||||
fprintf(opt->file, "%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev));
|
fprintf(opt->file, "%s ",
|
||||||
|
diff_unique_abbrev(p->two->oid.hash, opt->abbrev));
|
||||||
}
|
}
|
||||||
if (p->score) {
|
if (p->score) {
|
||||||
fprintf(opt->file, "%c%03d%c", p->status, similarity_index(p),
|
fprintf(opt->file, "%c%03d%c", p->status, similarity_index(p),
|
||||||
@@ -4175,11 +4181,11 @@ int diff_unmodified_pair(struct diff_filepair *p)
|
|||||||
/* both are valid and point at the same path. that is, we are
|
/* both are valid and point at the same path. that is, we are
|
||||||
* dealing with a change.
|
* dealing with a change.
|
||||||
*/
|
*/
|
||||||
if (one->sha1_valid && two->sha1_valid &&
|
if (one->oid_valid && two->oid_valid &&
|
||||||
!hashcmp(one->sha1, two->sha1) &&
|
!oidcmp(&one->oid, &two->oid) &&
|
||||||
!one->dirty_submodule && !two->dirty_submodule)
|
!one->dirty_submodule && !two->dirty_submodule)
|
||||||
return 1; /* no change */
|
return 1; /* no change */
|
||||||
if (!one->sha1_valid && !two->sha1_valid)
|
if (!one->oid_valid && !two->oid_valid)
|
||||||
return 1; /* both look at the same file on the filesystem. */
|
return 1; /* both look at the same file on the filesystem. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4240,7 +4246,7 @@ void diff_debug_filespec(struct diff_filespec *s, int x, const char *one)
|
|||||||
s->path,
|
s->path,
|
||||||
DIFF_FILE_VALID(s) ? "valid" : "invalid",
|
DIFF_FILE_VALID(s) ? "valid" : "invalid",
|
||||||
s->mode,
|
s->mode,
|
||||||
s->sha1_valid ? sha1_to_hex(s->sha1) : "");
|
s->oid_valid ? oid_to_hex(&s->oid) : "");
|
||||||
fprintf(stderr, "queue[%d] %s size %lu\n",
|
fprintf(stderr, "queue[%d] %s size %lu\n",
|
||||||
x, one ? one : "",
|
x, one ? one : "",
|
||||||
s->size);
|
s->size);
|
||||||
@@ -4310,11 +4316,11 @@ static void diff_resolve_rename_copy(void)
|
|||||||
else
|
else
|
||||||
p->status = DIFF_STATUS_RENAMED;
|
p->status = DIFF_STATUS_RENAMED;
|
||||||
}
|
}
|
||||||
else if (hashcmp(p->one->sha1, p->two->sha1) ||
|
else if (oidcmp(&p->one->oid, &p->two->oid) ||
|
||||||
p->one->mode != p->two->mode ||
|
p->one->mode != p->two->mode ||
|
||||||
p->one->dirty_submodule ||
|
p->one->dirty_submodule ||
|
||||||
p->two->dirty_submodule ||
|
p->two->dirty_submodule ||
|
||||||
is_null_sha1(p->one->sha1))
|
is_null_oid(&p->one->oid))
|
||||||
p->status = DIFF_STATUS_MODIFIED;
|
p->status = DIFF_STATUS_MODIFIED;
|
||||||
else {
|
else {
|
||||||
/* This is a "no-change" entry and should not
|
/* This is a "no-change" entry and should not
|
||||||
@@ -4456,7 +4462,7 @@ static void patch_id_consume(void *priv, char *line, unsigned long len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* returns 0 upon success, and writes result into sha1 */
|
/* returns 0 upon success, and writes result into sha1 */
|
||||||
static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
|
static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
|
||||||
{
|
{
|
||||||
struct diff_queue_struct *q = &diff_queued_diff;
|
struct diff_queue_struct *q = &diff_queued_diff;
|
||||||
int i;
|
int i;
|
||||||
@@ -4491,9 +4497,6 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
|
|||||||
|
|
||||||
diff_fill_sha1_info(p->one);
|
diff_fill_sha1_info(p->one);
|
||||||
diff_fill_sha1_info(p->two);
|
diff_fill_sha1_info(p->two);
|
||||||
if (fill_mmfile(&mf1, p->one) < 0 ||
|
|
||||||
fill_mmfile(&mf2, p->two) < 0)
|
|
||||||
return error("unable to read files to diff");
|
|
||||||
|
|
||||||
len1 = remove_space(p->one->path, strlen(p->one->path));
|
len1 = remove_space(p->one->path, strlen(p->one->path));
|
||||||
len2 = remove_space(p->two->path, strlen(p->two->path));
|
len2 = remove_space(p->two->path, strlen(p->two->path));
|
||||||
@@ -4528,10 +4531,19 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
|
|||||||
len2, p->two->path);
|
len2, p->two->path);
|
||||||
git_SHA1_Update(&ctx, buffer, len1);
|
git_SHA1_Update(&ctx, buffer, len1);
|
||||||
|
|
||||||
|
if (diff_header_only)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fill_mmfile(&mf1, p->one) < 0 ||
|
||||||
|
fill_mmfile(&mf2, p->two) < 0)
|
||||||
|
return error("unable to read files to diff");
|
||||||
|
|
||||||
if (diff_filespec_is_binary(p->one) ||
|
if (diff_filespec_is_binary(p->one) ||
|
||||||
diff_filespec_is_binary(p->two)) {
|
diff_filespec_is_binary(p->two)) {
|
||||||
git_SHA1_Update(&ctx, sha1_to_hex(p->one->sha1), 40);
|
git_SHA1_Update(&ctx, oid_to_hex(&p->one->oid),
|
||||||
git_SHA1_Update(&ctx, sha1_to_hex(p->two->sha1), 40);
|
40);
|
||||||
|
git_SHA1_Update(&ctx, oid_to_hex(&p->two->oid),
|
||||||
|
40);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4548,11 +4560,11 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)
|
int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
|
||||||
{
|
{
|
||||||
struct diff_queue_struct *q = &diff_queued_diff;
|
struct diff_queue_struct *q = &diff_queued_diff;
|
||||||
int i;
|
int i;
|
||||||
int result = diff_get_patch_id(options, sha1);
|
int result = diff_get_patch_id(options, sha1, diff_header_only);
|
||||||
|
|
||||||
for (i = 0; i < q->nr; i++)
|
for (i = 0; i < q->nr; i++)
|
||||||
diff_free_filepair(q->queue[i]);
|
diff_free_filepair(q->queue[i]);
|
||||||
@@ -4823,7 +4835,7 @@ static int diff_filespec_check_stat_unmatch(struct diff_filepair *p)
|
|||||||
*/
|
*/
|
||||||
if (!DIFF_FILE_VALID(p->one) || /* (1) */
|
if (!DIFF_FILE_VALID(p->one) || /* (1) */
|
||||||
!DIFF_FILE_VALID(p->two) ||
|
!DIFF_FILE_VALID(p->two) ||
|
||||||
(p->one->sha1_valid && p->two->sha1_valid) ||
|
(p->one->oid_valid && p->two->oid_valid) ||
|
||||||
(p->one->mode != p->two->mode) ||
|
(p->one->mode != p->two->mode) ||
|
||||||
diff_populate_filespec(p->one, CHECK_SIZE_ONLY) ||
|
diff_populate_filespec(p->one, CHECK_SIZE_ONLY) ||
|
||||||
diff_populate_filespec(p->two, CHECK_SIZE_ONLY) ||
|
diff_populate_filespec(p->two, CHECK_SIZE_ONLY) ||
|
||||||
@@ -5119,8 +5131,9 @@ size_t fill_textconv(struct userdiff_driver *driver,
|
|||||||
if (!driver->textconv)
|
if (!driver->textconv)
|
||||||
die("BUG: fill_textconv called with non-textconv driver");
|
die("BUG: fill_textconv called with non-textconv driver");
|
||||||
|
|
||||||
if (driver->textconv_cache && df->sha1_valid) {
|
if (driver->textconv_cache && df->oid_valid) {
|
||||||
*outbuf = notes_cache_get(driver->textconv_cache, df->sha1,
|
*outbuf = notes_cache_get(driver->textconv_cache,
|
||||||
|
df->oid.hash,
|
||||||
&size);
|
&size);
|
||||||
if (*outbuf)
|
if (*outbuf)
|
||||||
return size;
|
return size;
|
||||||
@@ -5130,9 +5143,9 @@ size_t fill_textconv(struct userdiff_driver *driver,
|
|||||||
if (!*outbuf)
|
if (!*outbuf)
|
||||||
die("unable to read files to diff");
|
die("unable to read files to diff");
|
||||||
|
|
||||||
if (driver->textconv_cache && df->sha1_valid) {
|
if (driver->textconv_cache && df->oid_valid) {
|
||||||
/* ignore errors, as we might be in a readonly repository */
|
/* ignore errors, as we might be in a readonly repository */
|
||||||
notes_cache_put(driver->textconv_cache, df->sha1, *outbuf,
|
notes_cache_put(driver->textconv_cache, df->oid.hash, *outbuf,
|
||||||
size);
|
size);
|
||||||
/*
|
/*
|
||||||
* we could save up changes and flush them all at the end,
|
* we could save up changes and flush them all at the end,
|
||||||
|
|||||||
2
diff.h
2
diff.h
@@ -342,7 +342,7 @@ extern int run_diff_files(struct rev_info *revs, unsigned int option);
|
|||||||
extern int run_diff_index(struct rev_info *revs, int cached);
|
extern int run_diff_index(struct rev_info *revs, int cached);
|
||||||
|
|
||||||
extern int do_diff_cache(const unsigned char *, struct diff_options *);
|
extern int do_diff_cache(const unsigned char *, struct diff_options *);
|
||||||
extern int diff_flush_patch_id(struct diff_options *, unsigned char *);
|
extern int diff_flush_patch_id(struct diff_options *, unsigned char *, int);
|
||||||
|
|
||||||
extern int diff_result_code(struct diff_options *, int);
|
extern int diff_result_code(struct diff_options *, int);
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ static int should_break(struct diff_filespec *src,
|
|||||||
return 1; /* even their types are different */
|
return 1; /* even their types are different */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src->sha1_valid && dst->sha1_valid &&
|
if (src->oid_valid && dst->oid_valid &&
|
||||||
!hashcmp(src->sha1, dst->sha1))
|
!oidcmp(&src->oid, &dst->oid))
|
||||||
return 0; /* they are the same */
|
return 0; /* they are the same */
|
||||||
|
|
||||||
if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
|
if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ static int add_rename_dst(struct diff_filespec *two)
|
|||||||
memmove(rename_dst + first + 1, rename_dst + first,
|
memmove(rename_dst + first + 1, rename_dst + first,
|
||||||
(rename_dst_nr - first - 1) * sizeof(*rename_dst));
|
(rename_dst_nr - first - 1) * sizeof(*rename_dst));
|
||||||
rename_dst[first].two = alloc_filespec(two->path);
|
rename_dst[first].two = alloc_filespec(two->path);
|
||||||
fill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode);
|
fill_filespec(rename_dst[first].two, two->oid.hash, two->oid_valid,
|
||||||
|
two->mode);
|
||||||
rename_dst[first].pair = NULL;
|
rename_dst[first].pair = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -260,12 +261,13 @@ struct file_similarity {
|
|||||||
|
|
||||||
static unsigned int hash_filespec(struct diff_filespec *filespec)
|
static unsigned int hash_filespec(struct diff_filespec *filespec)
|
||||||
{
|
{
|
||||||
if (!filespec->sha1_valid) {
|
if (!filespec->oid_valid) {
|
||||||
if (diff_populate_filespec(filespec, 0))
|
if (diff_populate_filespec(filespec, 0))
|
||||||
return 0;
|
return 0;
|
||||||
hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1);
|
hash_sha1_file(filespec->data, filespec->size, "blob",
|
||||||
|
filespec->oid.hash);
|
||||||
}
|
}
|
||||||
return sha1hash(filespec->sha1);
|
return sha1hash(filespec->oid.hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_identical_files(struct hashmap *srcs,
|
static int find_identical_files(struct hashmap *srcs,
|
||||||
@@ -287,7 +289,7 @@ static int find_identical_files(struct hashmap *srcs,
|
|||||||
struct diff_filespec *source = p->filespec;
|
struct diff_filespec *source = p->filespec;
|
||||||
|
|
||||||
/* False hash collision? */
|
/* False hash collision? */
|
||||||
if (hashcmp(source->sha1, target->sha1))
|
if (oidcmp(&source->oid, &target->oid))
|
||||||
continue;
|
continue;
|
||||||
/* Non-regular files? If so, the modes must match! */
|
/* Non-regular files? If so, the modes must match! */
|
||||||
if (!S_ISREG(source->mode) || !S_ISREG(target->mode)) {
|
if (!S_ISREG(source->mode) || !S_ISREG(target->mode)) {
|
||||||
@@ -466,7 +468,7 @@ void diffcore_rename(struct diff_options *options)
|
|||||||
strcmp(options->single_follow, p->two->path))
|
strcmp(options->single_follow, p->two->path))
|
||||||
continue; /* not interested */
|
continue; /* not interested */
|
||||||
else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
|
else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
|
||||||
is_empty_blob_sha1(p->two->sha1))
|
is_empty_blob_sha1(p->two->oid.hash))
|
||||||
continue;
|
continue;
|
||||||
else if (add_rename_dst(p->two) < 0) {
|
else if (add_rename_dst(p->two) < 0) {
|
||||||
warning("skipping rename detection, detected"
|
warning("skipping rename detection, detected"
|
||||||
@@ -476,7 +478,7 @@ void diffcore_rename(struct diff_options *options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
|
else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
|
||||||
is_empty_blob_sha1(p->one->sha1))
|
is_empty_blob_sha1(p->one->oid.hash))
|
||||||
continue;
|
continue;
|
||||||
else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {
|
else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {
|
||||||
/*
|
/*
|
||||||
@@ -539,7 +541,7 @@ void diffcore_rename(struct diff_options *options)
|
|||||||
rename_dst_nr * rename_src_nr, 50, 1);
|
rename_dst_nr * rename_src_nr, 50, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mx = xcalloc(st_mult(num_create, NUM_CANDIDATE_PER_DST), sizeof(*mx));
|
mx = xcalloc(st_mult(NUM_CANDIDATE_PER_DST, num_create), sizeof(*mx));
|
||||||
for (dst_cnt = i = 0; i < rename_dst_nr; i++) {
|
for (dst_cnt = i = 0; i < rename_dst_nr; i++) {
|
||||||
struct diff_filespec *two = rename_dst[i].two;
|
struct diff_filespec *two = rename_dst[i].two;
|
||||||
struct diff_score *m;
|
struct diff_score *m;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
struct userdiff_driver;
|
struct userdiff_driver;
|
||||||
|
|
||||||
struct diff_filespec {
|
struct diff_filespec {
|
||||||
unsigned char sha1[20];
|
struct object_id oid;
|
||||||
char *path;
|
char *path;
|
||||||
void *data;
|
void *data;
|
||||||
void *cnt_data;
|
void *cnt_data;
|
||||||
@@ -33,7 +33,7 @@ struct diff_filespec {
|
|||||||
int count; /* Reference count */
|
int count; /* Reference count */
|
||||||
int rename_used; /* Count of rename users */
|
int rename_used; /* Count of rename users */
|
||||||
unsigned short mode; /* file mode */
|
unsigned short mode; /* file mode */
|
||||||
unsigned sha1_valid : 1; /* if true, use sha1 and trust mode;
|
unsigned oid_valid : 1; /* if true, use oid and trust mode;
|
||||||
* if false, use the name and read from
|
* if false, use the name and read from
|
||||||
* the filesystem.
|
* the filesystem.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user