Merge branch 'sb/hashmap-customize-comparison' into sb/diff-color-move
* sb/hashmap-customize-comparison: (566 commits) hashmap: migrate documentation from Documentation/technical into header patch-ids.c: use hashmap correctly hashmap.h: compare function has access to a data field Twelfth batch for 2.14 Git 2.13.2 Eleventh batch for 2.14 Revert "split-index: add and use unshare_split_index()" Tenth batch for 2.14 add--interactive: quote commentChar regex add--interactive: handle EOF in prompt_yesno auto-correct: tweak phrasing docs: update 64-bit core.packedGitLimit default t7508: fix a broken indentation grep: fix erroneously copy/pasted variable in check/assert pattern Ninth batch for 2.14 glossary: define 'stash entry' status: add optional stash count information stash: update documentation to use 'stash entry' for_each_bisect_ref(): don't trim refnames mergetools/meld: improve compatibiilty with Meld on macOS X ...maint
commit
2cfb6cec94
|
@ -1,3 +1,9 @@
|
|||
* whitespace=!indent,trail,space
|
||||
*.[ch] whitespace=indent,trail,space diff=cpp
|
||||
*.sh whitespace=indent,trail,space
|
||||
*.sh whitespace=indent,trail,space eol=lf
|
||||
*.perl eol=lf
|
||||
*.pm eol=lf
|
||||
/Documentation/git-*.txt eol=lf
|
||||
/command-list.txt eol=lf
|
||||
/GIT-VERSION-GEN eol=lf
|
||||
/mergetools/* eol=lf
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
## Contributing to Git
|
||||
|
||||
Thanks for taking the time to contribute to Git! Please be advised that the
|
||||
Git community does not use github.com for their contributions. Instead, we use
|
||||
a mailing list (git@vger.kernel.org) for code submissions, code
|
||||
reviews, and bug reports.
|
||||
|
||||
Nevertheless, you can use [submitGit](http://submitgit.herokuapp.com/) to
|
||||
conveniently send your Pull Requests commits to our mailing list.
|
||||
|
||||
Please read ["A note from the maintainer"](https://git.kernel.org/pub/scm/git/git.git/plain/MaintNotes?h=todo)
|
||||
to learn how the Git project is managed, and how you can work with it.
|
||||
In addition, we highly recommend you to read [our submission guidelines](../Documentation/SubmittingPatches).
|
||||
|
||||
If you prefer video, then [this talk](https://www.youtube.com/watch?v=Q7i_qQW__q4&feature=youtu.be&t=6m4s)
|
||||
might be useful to you as the presenter walks you through the contribution
|
||||
process by example.
|
||||
|
||||
Your friendly Git community!
|
|
@ -0,0 +1,7 @@
|
|||
Thanks for taking the time to contribute to Git! Please be advised that the
|
||||
Git community does not use github.com for their contributions. Instead, we use
|
||||
a mailing list (git@vger.kernel.org) for code submissions, code reviews, and
|
||||
bug reports. Nevertheless, you can use submitGit to conveniently send your Pull
|
||||
Requests commits to our mailing list.
|
||||
|
||||
Please read the "guidelines for contributing" linked above!
|
18
.travis.yml
18
.travis.yml
|
@ -39,6 +39,11 @@ env:
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- env: GETTEXT_POISON=YesPlease
|
||||
os: linux
|
||||
compiler:
|
||||
addons:
|
||||
before_install:
|
||||
- env: Windows
|
||||
os: linux
|
||||
compiler:
|
||||
|
@ -52,6 +57,7 @@ matrix:
|
|||
after_failure:
|
||||
- env: Linux32
|
||||
os: linux
|
||||
compiler:
|
||||
services:
|
||||
- docker
|
||||
before_install:
|
||||
|
@ -86,14 +92,14 @@ matrix:
|
|||
after_failure:
|
||||
- env: Documentation
|
||||
os: linux
|
||||
compiler: clang
|
||||
compiler:
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- asciidoc
|
||||
- xmlto
|
||||
before_install:
|
||||
before_script:
|
||||
before_script: gem install asciidoctor
|
||||
script: ci/test-documentation.sh
|
||||
after_failure:
|
||||
|
||||
|
@ -134,12 +140,14 @@ before_install:
|
|||
p4 -V | grep Rev.;
|
||||
echo "$(tput setaf 6)Git-LFS Version$(tput sgr0)";
|
||||
git-lfs version;
|
||||
mkdir -p $HOME/travis-cache;
|
||||
ln -s $HOME/travis-cache/.prove t/.prove;
|
||||
|
||||
before_script: make --jobs=2
|
||||
|
||||
script: make --quiet test
|
||||
script:
|
||||
- >
|
||||
mkdir -p $HOME/travis-cache;
|
||||
ln -s $HOME/travis-cache/.prove t/.prove;
|
||||
make --quiet test;
|
||||
|
||||
after_failure:
|
||||
- >
|
||||
|
|
|
@ -24,7 +24,7 @@ code. For Git in general, a few rough rules are:
|
|||
|
||||
"Once it _is_ in the tree, it's not really worth the patch noise to
|
||||
go and fix it up."
|
||||
Cf. http://article.gmane.org/gmane.linux.kernel/943020
|
||||
Cf. http://lkml.iu.edu/hypermail/linux/kernel/1001.3/01069.html
|
||||
|
||||
Make your code readable and sensible, and don't try to be clever.
|
||||
|
||||
|
@ -256,12 +256,12 @@ For C programs:
|
|||
|
||||
Note however that a comment that explains a translatable string to
|
||||
translators uses a convention of starting with a magic token
|
||||
"TRANSLATORS: " immediately after the opening delimiter, even when
|
||||
it spans multiple lines. We do not add an asterisk at the beginning
|
||||
of each line, either. E.g.
|
||||
"TRANSLATORS: ", e.g.
|
||||
|
||||
/* TRANSLATORS: here is a comment that explains the string
|
||||
to be translated, that follows immediately after it */
|
||||
/*
|
||||
* TRANSLATORS: here is a comment that explains the string to
|
||||
* be translated, that follows immediately after it.
|
||||
*/
|
||||
_("Here is a translatable string explained by the above.");
|
||||
|
||||
- Double negation is often harder to understand than no negation
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
Git v2.13.1 Release Notes
|
||||
=========================
|
||||
|
||||
Fixes since v2.13
|
||||
-----------------
|
||||
|
||||
* The Web interface to gmane news archive is long gone, even though
|
||||
the articles are still accessible via NTTP. Replace the links with
|
||||
ones to public-inbox.org. Because their message identification is
|
||||
based on the actual message-id, it is likely that it will be easier
|
||||
to migrate away from it if/when necessary.
|
||||
|
||||
* Update tests to pass under GETTEXT_POISON (a mechanism to ensure
|
||||
that output strings that should not be translated are not
|
||||
translated by mistake), and tell TravisCI to run them.
|
||||
|
||||
* Setting "log.decorate=false" in the configuration file did not take
|
||||
effect in v2.13, which has been corrected.
|
||||
|
||||
* An earlier update to test 7400 needed to be skipped on CYGWIN.
|
||||
|
||||
* Git sometimes gives an advice in a rhetorical question that does
|
||||
not require an answer, which can confuse new users and non native
|
||||
speakers. Attempt to rephrase them.
|
||||
|
||||
* "git read-tree -m" (no tree-ish) gave a nonsense suggestion "use
|
||||
--empty if you want to clear the index". With "-m", such a request
|
||||
will still fail anyway, as you'd need to name at least one tree-ish
|
||||
to be merged.
|
||||
|
||||
* The codepath in "git am" that is used when running "git rebase"
|
||||
leaked memory held for the log message of the commits being rebased.
|
||||
|
||||
* "pack-objects" can stream a slice of an existing packfile out when
|
||||
the pack bitmap can tell that the reachable objects are all needed
|
||||
in the output, without inspecting individual objects. This
|
||||
strategy however would not work well when "--local" and other
|
||||
options are in use, and need to be disabled.
|
||||
|
||||
* Clarify documentation for include.path and includeIf.<condition>.path
|
||||
configuration variables.
|
||||
|
||||
* Tag objects, which are not reachable from any ref, that point at
|
||||
missing objects were mishandled by "git gc" and friends (they
|
||||
should silently be ignored instead)
|
||||
|
||||
* A few http:// links that are redirected to https:// in the
|
||||
documentation have been updated to https:// links.
|
||||
|
||||
* Make sure our tests would pass when the sources are checked out
|
||||
with "platform native" line ending convention by default on
|
||||
Windows. Some "text" files out tests use and the test scripts
|
||||
themselves that are meant to be run with /bin/sh, ought to be
|
||||
checked out with eol=LF even on Windows.
|
||||
|
||||
* Fix memory leaks pointed out by Coverity (and people).
|
||||
|
||||
* The receive-pack program now makes sure that the push certificate
|
||||
records the same set of push options used for pushing.
|
||||
|
||||
* "git cherry-pick" and other uses of the sequencer machinery
|
||||
mishandled a trailer block whose last line is an incomplete line.
|
||||
This has been fixed so that an additional sign-off etc. are added
|
||||
after completing the existing incomplete line.
|
||||
|
||||
* The shell completion script (in contrib/) learned "git stash" has
|
||||
a new "push" subcommand.
|
||||
|
||||
* Travis CI gained a task to format the documentation with both
|
||||
AsciiDoc and AsciiDoctor.
|
||||
|
||||
* Update the C style recommendation for notes for translators, as
|
||||
recent versions of gettext tools can work with our style of
|
||||
multi-line comments.
|
||||
|
||||
* "git clone --config var=val" is a way to populate the
|
||||
per-repository configuration file of the new repository, but it did
|
||||
not work well when val is an empty string. This has been fixed.
|
||||
|
||||
* A few codepaths in "checkout" and "am" working on an unborn branch
|
||||
tried to access an uninitialized piece of memory.
|
||||
|
||||
* "git for-each-ref --format=..." with %(HEAD) in the format used to
|
||||
resolve the HEAD symref as many times as it had processed refs,
|
||||
which was wasteful, and "git branch" shared the same problem.
|
||||
|
||||
* "git interpret-trailers", when used as GIT_EDITOR for "git commit
|
||||
-v", looked for and appended to a trailer block at the very end,
|
||||
i.e. at the end of the "diff" output. The command has been
|
||||
corrected to pay attention to the cut-mark line "commit -v" adds to
|
||||
the buffer---the real trailer block should appear just before it.
|
||||
|
||||
* A test allowed both "git push" and "git receive-pack" on the other
|
||||
end write their traces into the same file. This is OK on platforms
|
||||
that allows atomically appending to a file opened with O_APPEND,
|
||||
but on other platforms led to a mangled output, causing
|
||||
intermittent test failures. This has been fixed by disabling
|
||||
traces from "receive-pack" in the test.
|
||||
|
||||
* "foo\bar\baz" in "git fetch foo\bar\baz", even though there is no
|
||||
slashes in it, cannot be a nickname for a remote on Windows, as
|
||||
that is likely to be a pathname on a local filesystem.
|
||||
|
||||
* The "collision detecting" SHA-1 implementation shipped with 2.13
|
||||
was quite broken on some big-endian platforms and/or platforms that
|
||||
do not like unaligned fetches. Update to the upstream code which
|
||||
has already fixed these issues.
|
||||
|
||||
* "git am -h" triggered a BUG().
|
||||
|
||||
* The interaction of "url.*.insteadOf" and custom URL scheme's
|
||||
whitelisting is now documented better.
|
||||
|
||||
Also contains various documentation updates and code clean-ups.
|
|
@ -0,0 +1,54 @@
|
|||
Git v2.13.2 Release Notes
|
||||
=========================
|
||||
|
||||
Fixes since v2.13.1
|
||||
-------------------
|
||||
|
||||
* The "collision detecting" SHA-1 implementation shipped with 2.13.1
|
||||
was still broken on some platforms. Update to the upstream code
|
||||
again to take their fix.
|
||||
|
||||
* "git checkout --recurse-submodules" did not quite work with a
|
||||
submodule that itself has submodules.
|
||||
|
||||
* Introduce the BUG() macro to improve die("BUG: ...").
|
||||
|
||||
* The "run-command" API implementation has been made more robust
|
||||
against dead-locking in a threaded environment.
|
||||
|
||||
* A recent update to t5545-push-options.sh started skipping all the
|
||||
tests in the script when a web server testing is disabled or
|
||||
unavailable, not just the ones that require a web server. Non HTTP
|
||||
tests have been salvaged to always run in this script.
|
||||
|
||||
* "git clean -d" used to clean directories that has ignored files,
|
||||
even though the command should not lose ignored ones without "-x".
|
||||
"git status --ignored" did not list ignored and untracked files
|
||||
without "-uall". These have been corrected.
|
||||
|
||||
* The timestamp of the index file is now taken after the file is
|
||||
closed, to help Windows, on which a stale timestamp is reported by
|
||||
fstat() on a file that is opened for writing and data was written
|
||||
but not yet closed.
|
||||
|
||||
* "git pull --rebase --autostash" didn't auto-stash when the local history
|
||||
fast-forwards to the upstream.
|
||||
|
||||
* "git describe --contains" penalized light-weight tags so much that
|
||||
they were almost never considered. Instead, give them about the
|
||||
same chance to be considered as an annotated tag that is the same
|
||||
age as the underlying commit would.
|
||||
|
||||
* The result from "git diff" that compares two blobs, e.g. "git diff
|
||||
$commit1:$path $commit2:$path", used to be shown with the full
|
||||
object name as given on the command line, but it is more natural to
|
||||
use the $path in the output and use it to look up .gitattributes.
|
||||
|
||||
* A flaky test has been corrected.
|
||||
|
||||
* Help contributors that visit us at GitHub.
|
||||
|
||||
* "git stash push <pathspec>" did not work from a subdirectory at all.
|
||||
Bugfix for a topic in v2.13
|
||||
|
||||
Also contains various documentation updates and code clean-ups.
|
|
@ -0,0 +1,399 @@
|
|||
Git 2.14 Release Notes
|
||||
======================
|
||||
|
||||
Backward compatibility notes.
|
||||
|
||||
* Use of an empty string as a pathspec element that is used for
|
||||
'everything matches' is still warned and Git asks users to use a
|
||||
more explicit '.' for that instead. The hope is that existing
|
||||
users will not mind this change, and eventually the warning can be
|
||||
turned into a hard error, upgrading the deprecation into removal of
|
||||
this (mis)feature. That is not scheduled to happen in the upcoming
|
||||
release (yet).
|
||||
|
||||
* Git now avoids blindly falling back to ".git" when the setup
|
||||
sequence said we are _not_ in Git repository. A corner case that
|
||||
happens to work right now may be broken by a call to die("BUG").
|
||||
We've tried hard to locate such cases and fixed them, but there
|
||||
might still be cases that need to be addressed--bug reports are
|
||||
greatly appreciated.
|
||||
|
||||
* The experiment to improve the hunk-boundary selection of textual
|
||||
diff output has finished, and the "indent heuristics" has now
|
||||
become the default.
|
||||
|
||||
|
||||
Updates since v2.13
|
||||
-------------------
|
||||
|
||||
UI, Workflows & Features
|
||||
|
||||
* The colors in which "git status --short --branch" showed the names
|
||||
of the current branch and its remote-tracking branch are now
|
||||
configurable.
|
||||
|
||||
* "git clone" learned the "--no-tags" option not to fetch all tags
|
||||
initially, and also set up the tagopt not to follow any tags in
|
||||
subsequent fetches.
|
||||
|
||||
* "git archive --format=zip" learned to use zip64 extension when
|
||||
necessary to go beyond the 4GB limit.
|
||||
|
||||
* "git reset" learned "--recurse-submodules" option.
|
||||
|
||||
* "git diff --submodule=diff" now recurses into nested submodules.
|
||||
|
||||
* "git repack" learned to accept the --threads=<n> option and pass it
|
||||
to pack-objects.
|
||||
|
||||
* "git send-email" learned to run sendemail-validate hook to inspect
|
||||
and reject a message before sending it out.
|
||||
|
||||
* There is no good reason why "git fetch $there $sha1" should fail
|
||||
when the $sha1 names an object at the tip of an advertised ref,
|
||||
even when the other side hasn't enabled allowTipSHA1InWant.
|
||||
|
||||
* The recently introduced "[includeIf "gitdir:$dir"] path=..."
|
||||
mechansim has further been taught to take symlinks into account.
|
||||
The directory "$dir" specified in "gitdir:$dir" may be a symlink to
|
||||
a real location, not something that $(getcwd) may return. In such
|
||||
a case, a realpath of "$dir" is compared with the real path of the
|
||||
current repository to determine if the contents from the named path
|
||||
should be included.
|
||||
|
||||
* Make the "indent" heuristics the default in "diff" and diff.indentHeuristics
|
||||
configuration variable an escape hatch for those who do no want it.
|
||||
|
||||
* Many commands learned to pay attention to submodule.recurse
|
||||
configuration.
|
||||
|
||||
* The convention for a command line is to follow "git cmdname
|
||||
--options" with revisions followed by an optional "--"
|
||||
disambiguator and then finally pathspecs. When "--" is not there,
|
||||
we make sure early ones are all interpretable as revs (and do not
|
||||
look like paths) and later ones are the other way around. A
|
||||
pathspec with "magic" (e.g. ":/p/a/t/h" that matches p/a/t/h from
|
||||
the top-level of the working tree, no matter what subdirectory you
|
||||
are working from) are conservatively judged as "not a path", which
|
||||
required disambiguation more often. The command line parser
|
||||
learned to say "it's a pathspec" a bit more often when the syntax
|
||||
looks like so.
|
||||
|
||||
* Update "perl-compatible regular expression" support to enable JIT
|
||||
and also allow linking with the newer PCRE v2 library.
|
||||
|
||||
* "filter-branch" learned a pseudo filter "--setup" that can be used
|
||||
to define common functions/variables that can be used by other
|
||||
filters.
|
||||
|
||||
* Using "git add d/i/r" when d/i/r is the top of the working tree of
|
||||
a separate repository would create a gitlink in the index, which
|
||||
would appear as a not-quite-initialized submodule to others. We
|
||||
learned to give warnings when this happens.
|
||||
|
||||
* "git status" learned to optionally give how many stash entries the
|
||||
user has in its output.
|
||||
|
||||
|
||||
Performance, Internal Implementation, Development Support etc.
|
||||
|
||||
* The default packed-git limit value has been raised on larger
|
||||
platforms to save "git fetch" from a (recoverable) failure while
|
||||
"gc" is running in parallel.
|
||||
|
||||
* Code to update the cache-tree has been tightened so that we won't
|
||||
accidentally write out any 0{40} entry in the tree object.
|
||||
|
||||
* Attempt to allow us notice "fishy" situation where we fail to
|
||||
remove the temporary directory used during the test.
|
||||
|
||||
* Travis CI gained a task to format the documentation with both
|
||||
AsciiDoc and AsciiDoctor.
|
||||
|
||||
* Some platforms have ulong that is smaller than time_t, and our
|
||||
historical use of ulong for timestamp would mean they cannot
|
||||
represent some timestamp that the platform allows. Invent a
|
||||
separate and dedicated timestamp_t (so that we can distingiuish
|
||||
timestamps and a vanilla ulongs, which along is already a good
|
||||
move), and then declare uintmax_t is the type to be used as the
|
||||
timestamp_t.
|
||||
|
||||
* We can trigger Windows auto-build tester (credits: Dscho &
|
||||
Microsoft) from our existing Travis CI tester now.
|
||||
|
||||
* Conversion from uchar[20] to struct object_id continues.
|
||||
|
||||
* Simplify parse_pathspec() codepath and stop it from looking at the
|
||||
default in-core index.
|
||||
|
||||
* Add perf-test for wildmatch.
|
||||
|
||||
* Code from "conversion using external process" codepath has been
|
||||
extracted to a separate sub-process.[ch] module.
|
||||
|
||||
* When "git checkout", "git merge", etc. manipulates the in-core
|
||||
index, various pieces of information in the index extensions are
|
||||
discarded from the original state, as it is usually not the case
|
||||
that they are kept up-to-date and in-sync with the operation on the
|
||||
main index. The untracked cache extension is copied across these
|
||||
operations now, which would speed up "git status" (as long as the
|
||||
cache is properly invalidated).
|
||||
|
||||
* The internal implementation of "git grep" has seen some clean-up.
|
||||
|
||||
* Update the C style recommendation for notes for translators, as
|
||||
recent versions of gettext tools can work with our style of
|
||||
multi-line comments.
|
||||
|
||||
* The implementation of "ref" API around the "packed refs" have been
|
||||
cleaned up, in preparation for further changes.
|
||||
|
||||
* The internal logic used in "git blame" has been libified to make it
|
||||
easier to use by cgit.
|
||||
|
||||
* Our code often opens a path to an optional file, to work on its
|
||||
contents when we can successfully open it. We can ignore a failure
|
||||
to open if such an optional file does not exist, but we do want to
|
||||
report a failure in opening for other reasons (e.g. we got an I/O
|
||||
error, or the file is there, but we lack the permission to open).
|
||||
|
||||
The exact errors we need to ignore are ENOENT (obviously) and
|
||||
ENOTDIR (less obvious). Instead of repeating comparison of errno
|
||||
with these two constants, introduce a helper function to do so.
|
||||
|
||||
* We often try to open a file for reading whose existence is
|
||||
optional, and silently ignore errors from open/fopen; report such
|
||||
errors if they are not due to missing files.
|
||||
|
||||
* When an existing repository is used for t/perf testing, we first
|
||||
create bit-for-bit copy of it, which may grab a transient state of
|
||||
the repository and freeze it into the repository used for testing,
|
||||
which then may cause Git operations to fail. Single out "the index
|
||||
being locked" case and forcibly drop the lock from the copy.
|
||||
|
||||
* Three instances of the same helper function have been consolidated
|
||||
to one.
|
||||
|
||||
* "fast-import" uses a default pack chain depth that is consistent
|
||||
with other parts of the system.
|
||||
|
||||
* A new test to show the interaction between the pattern [^a-z]
|
||||
(which matches '/') and a slash in a path has been added. The
|
||||
pattern should not match the slash with "pathmatch", but should
|
||||
with "wildmatch".
|
||||
|
||||
* The 'diff-highlight' program (in contrib/) has been restructured
|
||||
for easier reuse by an external project 'diff-so-fancy'.
|
||||
(merge 0c977dbc81 jk/diff-highlight-module later to maint).
|
||||
|
||||
* A common pattern to free a piece of memory and assign NULL to the
|
||||
pointer that used to point at it has been replaced with a new
|
||||
FREE_AND_NULL() macro.
|
||||
|
||||
|
||||
Also contains various documentation updates and code clean-ups.
|
||||
|
||||
|
||||
Fixes since v2.13
|
||||
-----------------
|
||||
|
||||
Unless otherwise noted, all the fixes since v2.13 in the maintenance
|
||||
track are contained in this release (see the maintenance releases'
|
||||
notes for details).
|
||||
|
||||
* "git gc" did not interact well with "git worktree"-managed
|
||||
per-worktree refs.
|
||||
|
||||
* "git cherry-pick" and other uses of the sequencer machinery
|
||||
mishandled a trailer block whose last line is an incomplete line.
|
||||
This has been fixed so that an additional sign-off etc. are added
|
||||
after completing the existing incomplete line.
|
||||
|
||||
* The codepath in "git am" that is used when running "git rebase"
|
||||
leaked memory held for the log message of the commits being rebased.
|
||||
|
||||
* "git clone --config var=val" is a way to populate the
|
||||
per-repository configuration file of the new repository, but it did
|
||||
not work well when val is an empty string. This has been fixed.
|
||||
|
||||
* Setting "log.decorate=false" in the configuration file did not take
|
||||
effect in v2.13, which has been corrected.
|
||||
|
||||
* A few codepaths in "checkout" and "am" working on an unborn branch
|
||||
tried to access an uninitialized piece of memory.
|
||||
|
||||
* The Web interface to gmane news archive is long gone, even though
|
||||
the articles are still accessible via NTTP. Replace the links with
|
||||
ones to public-inbox.org. Because their message identification is
|
||||
based on the actual message-id, it is likely that it will be easier
|
||||
to migrate away from it if/when necessary.
|
||||
|
||||
* The receive-pack program now makes sure that the push certificate
|
||||
records the same set of push options used for pushing.
|
||||
|
||||
* Tests have been updated to pass under GETTEXT_POISON (a mechanism
|
||||
to ensure that output strings that should not be translated are
|
||||
not translated by mistake), and TravisCI is told to run them.
|
||||
|
||||
* "git checkout --recurse-submodules" did not quite work with a
|
||||
submodule that itself has submodules.
|
||||
|
||||
* "pack-objects" can stream a slice of an existing packfile out when
|
||||
the pack bitmap can tell that the reachable objects are all needed
|
||||
in the output, without inspecting individual objects. This
|
||||
strategy however would not work well when "--local" and other
|
||||
options are in use, and need to be disabled.
|
||||
|
||||
* Fix memory leaks pointed out by Coverity (and people).
|
||||
|
||||
* "git read-tree -m" (no tree-ish) gave a nonsense suggestion "use
|
||||
--empty if you want to clear the index". With "-m", such a request
|
||||
will still fail anyway, as you'd need to name at least one tree-ish
|
||||
to be merged.
|
||||
|
||||
* Make sure our tests would pass when the sources are checked out
|
||||
with "platform native" line ending convention by default on
|
||||
Windows. Some "text" files out tests use and the test scripts
|
||||
themselves that are meant to be run with /bin/sh, ought to be
|
||||
checked out with eol=LF even on Windows.
|
||||
|
||||
* Introduce the BUG() macro to improve die("BUG: ...").
|
||||
|
||||
* Clarify documentation for include.path and includeIf.<condition>.path
|
||||
configuration variables.
|
||||
|
||||
* Git sometimes gives an advice in a rhetorical question that does
|
||||
not require an answer, which can confuse new users and non native
|
||||
speakers. Attempt to rephrase them.
|
||||
|
||||
* A few http:// links that are redirected to https:// in the
|
||||
documentation have been updated to https:// links.
|
||||
|
||||
* "git for-each-ref --format=..." with %(HEAD) in the format used to
|
||||
resolve the HEAD symref as many times as it had processed refs,
|
||||
which was wasteful, and "git branch" shared the same problem.
|
||||
|
||||
* Regression fix to topic recently merged to 'master'.
|
||||
|
||||
* The shell completion script (in contrib/) learned "git stash" has
|
||||
a new "push" subcommand.
|
||||
|
||||
* "git interpret-trailers", when used as GIT_EDITOR for "git commit
|
||||
-v", looked for and appended to a trailer block at the very end,
|
||||
i.e. at the end of the "diff" output. The command has been
|
||||
corrected to pay attention to the cut-mark line "commit -v" adds to
|
||||
the buffer---the real trailer block should appear just before it.
|
||||
|
||||
* A test allowed both "git push" and "git receive-pack" on the other
|
||||
end write their traces into the same file. This is OK on platforms
|
||||
that allows atomically appending to a file opened with O_APPEND,
|
||||
but on other platforms led to a mangled output, causing
|
||||
intermittent test failures. This has been fixed by disabling
|
||||
traces from "receive-pack" in the test.
|
||||
|
||||
* Tag objects, which are not reachable from any ref, that point at
|
||||
missing objects were mishandled by "git gc" and friends (they
|
||||
should silently be ignored instead)
|
||||
|
||||
* "git describe --contains" penalized light-weight tags so much that
|
||||
they were almost never considered. Instead, give them about the
|
||||
same chance to be considered as an annotated tag that is the same
|
||||
age as the underlying commit would.
|
||||
|
||||
* The "run-command" API implementation has been made more robust
|
||||
against dead-locking in a threaded environment.
|
||||
|
||||
* A recent update to t5545-push-options.sh started skipping all the
|
||||
tests in the script when a web server testing is disabled or
|
||||
unavailable, not just the ones that require a web server. Non HTTP
|
||||
tests have been salvaged to always run in this script.
|
||||
|
||||
* "git send-email" now uses Net::SMTP::SSL, which is obsolete, only
|
||||
when needed. Recent versions of Net::SMTP can do TLS natively.
|
||||
|
||||
* "foo\bar\baz" in "git fetch foo\bar\baz", even though there is no
|
||||
slashes in it, cannot be a nickname for a remote on Windows, as
|
||||
that is likely to be a pathname on a local filesystem.
|
||||
|
||||
* "git clean -d" used to clean directories that has ignored files,
|
||||
even though the command should not lose ignored ones without "-x".
|
||||
"git status --ignored" did not list ignored and untracked files
|
||||
without "-uall". These have been corrected.
|
||||
|
||||
* The result from "git diff" that compares two blobs, e.g. "git diff
|
||||
$commit1:$path $commit2:$path", used to be shown with the full
|
||||
object name as given on the command line, but it is more natural to
|
||||
use the $path in the output and use it to look up .gitattributes.
|
||||
|
||||
* The "collision detecting" SHA-1 implementation shipped with 2.13
|
||||
was quite broken on some big-endian platforms and/or platforms that
|
||||
do not like unaligned fetches. Update to the upstream code which
|
||||
has already fixed these issues.
|
||||
|
||||
* "git am -h" triggered a BUG().
|
||||
|
||||
* The interaction of "url.*.insteadOf" and custom URL scheme's
|
||||
whitelisting is now documented better.
|
||||
|
||||
* The timestamp of the index file is now taken after the file is
|
||||
closed, to help Windows, on which a stale timestamp is reported by
|
||||
fstat() on a file that is opened for writing and data was written
|
||||
but not yet closed.
|
||||
|
||||
* "git pull --rebase --autostash" didn't auto-stash when the local history
|
||||
fast-forwards to the upstream.
|
||||
|
||||
* A flaky test has been corrected.
|
||||
|
||||
* "git $cmd -h" for builtin commands calls the implementation of the
|
||||
command (i.e. cmd_$cmd() function) without doing any repository
|
||||
set-up, and the commands that expect RUN_SETUP is done by the Git
|
||||
potty needs to be prepared to show the help text without barfing.
|
||||
(merge d691551192 jk/consistent-h later to maint).
|
||||
|
||||
* Help contributors that visit us at GitHub.
|
||||
|
||||
* "git stash push <pathspec>" did not work from a subdirectory at all.
|
||||
Bugfix for a topic in v2.13
|
||||
|
||||
* As there is no portable way to pass timezone information to
|
||||
strftime, some output format from "git log" and friends are
|
||||
impossible to produce. Teach our own strbuf_addftime to replace %z
|
||||
and %Z with caller-supplied values to help working around this.
|
||||
(merge 6eced3ec5e rs/strbuf-addftime-zZ later to maint).
|
||||
|
||||
* "git mergetool" learned to work around a wrapper MacOS X adds
|
||||
around underlying meld.
|
||||
(merge 0af85f84bd da/mergetools-meld-output-opt-on-macos later to maint).
|
||||
|
||||
* An example in documentation that does not work in multi worktree
|
||||
configuration has been corrected.
|
||||
(merge 773a88914f ah/doc-gitattributes-empty-index later to maint).
|
||||
|
||||
* The pretty-format specifiers like '%h', '%t', etc. had an
|
||||
optimization that no longer works correctly. In preparation/hope
|
||||
of getting it correctly implemented, first discard the optimization
|
||||
that is broken.
|
||||
(merge fe9e2aefd4 rs/pretty-add-again later to maint).
|
||||
|
||||
* The code to pick up and execute command alias definition from the
|
||||
configuration used to switch to the top of the working tree and
|
||||
then come back when the expanded alias was executed, which was
|
||||
unnecessarilyl complex. Attempt to simplify the logic by using the
|
||||
early-config mechanism that does not chdir around.
|
||||
(merge a9bcf6586d js/alias-early-config later to maint).
|
||||
|
||||
* Fix configuration codepath to pay proper attention to commondir
|
||||
that is used in multi-worktree situation, and isolate config API
|
||||
into its own header file.
|
||||
(merge dc8441fdb4 bw/config-h later to maint).
|
||||
|
||||
* "git add -p" were updated in 2.12 timeframe to cope with custom
|
||||
core.commentchar but the implementation was buggy and a
|
||||
metacharacter like $ and * did not work.
|
||||
(merge d85d7ecb80 jk/add-p-commentchar-fix later to maint).
|
||||
|
||||
* Other minor doc, test and build updates and code cleanups.
|
||||
(merge 68241cb9dd sb/t4005-modernize later to maint).
|
||||
(merge 4fced24712 ks/t7508-indent-fix later to maint).
|
||||
(merge 968b1fe263 mb/reword-autocomplete-message later to maint).
|
|
@ -79,14 +79,20 @@ escape sequences) are invalid.
|
|||
Includes
|
||||
~~~~~~~~
|
||||
|
||||
You can include a config file from another by setting the special
|
||||
`include.path` variable to the name of the file to be included. The
|
||||
variable takes a pathname as its value, and is subject to tilde
|
||||
expansion. `include.path` can be given multiple times.
|
||||
The `include` and `includeIf` sections allow you to include config
|
||||
directives from another source. These sections behave identically to
|
||||
each other with the exception that `includeIf` sections may be ignored
|
||||
if their condition does not evaluate to true; see "Conditional includes"
|
||||
below.
|
||||
|
||||
The included file is expanded immediately, as if its contents had been
|
||||
found at the location of the include directive. If the value of the
|
||||
`include.path` variable is a relative path, the path is considered to
|
||||
You can include a config file from another by setting the special
|
||||
`include.path` (or `includeIf.*.path`) variable to the name of the file
|
||||
to be included. The variable takes a pathname as its value, and is
|
||||
subject to tilde expansion. These variables can be given multiple times.
|
||||
|
||||
The contents of the included file are inserted immediately, as if they
|
||||
had been found at the location of the include directive. If the value of the
|
||||
variable is a relative path, the path is considered to
|
||||
be relative to the configuration file in which the include directive
|
||||
was found. See below for examples.
|
||||
|
||||
|
@ -95,8 +101,7 @@ Conditional includes
|
|||
|
||||
You can include a config file from another conditionally by setting a
|
||||
`includeIf.<condition>.path` variable to the name of the file to be
|
||||
included. The variable's value is treated the same way as
|
||||
`include.path`. `includeIf.<condition>.path` can be given multiple times.
|
||||
included.
|
||||
|
||||
The condition starts with a keyword followed by a colon and some data
|
||||
whose format and meaning depends on the keyword. Supported keywords
|
||||
|
@ -140,6 +145,16 @@ A few more notes on matching via `gitdir` and `gitdir/i`:
|
|||
|
||||
* Symlinks in `$GIT_DIR` are not resolved before matching.
|
||||
|
||||
* Both the symlink & realpath versions of paths will be matched
|
||||
outside of `$GIT_DIR`. E.g. if ~/git is a symlink to
|
||||
/mnt/storage/git, both `gitdir:~/git` and `gitdir:/mnt/storage/git`
|
||||
will match.
|
||||
+
|
||||
This was not the case in the initial release of this feature in
|
||||
v2.13.0, which only matched the realpath version. Configuration that
|
||||
wants to be compatible with the initial release of this feature needs
|
||||
to either specify only the realpath version, or both versions.
|
||||
|
||||
* Note that "../" is not special and will match literally, which is
|
||||
unlikely what you want.
|
||||
|
||||
|
@ -167,8 +182,8 @@ Example
|
|||
|
||||
[include]
|
||||
path = /path/to/foo.inc ; include by absolute path
|
||||
path = foo ; expand "foo" relative to the current file
|
||||
path = ~/foo ; expand "foo" in your `$HOME` directory
|
||||
path = foo.inc ; find "foo.inc" relative to the current file
|
||||
path = ~/foo.inc ; find "foo.inc" in your `$HOME` directory
|
||||
|
||||
; include if $GIT_DIR is /path/to/foo/.git
|
||||
[includeIf "gitdir:/path/to/foo/.git"]
|
||||
|
@ -182,6 +197,12 @@ Example
|
|||
[includeIf "gitdir:~/to/group/"]
|
||||
path = /path/to/foo.inc
|
||||
|
||||
; relative paths are always relative to the including
|
||||
; file (if the condition is true); their location is not
|
||||
; affected by the condition
|
||||
[includeIf "gitdir:/path/to/group/"]
|
||||
path = foo.inc
|
||||
|
||||
Values
|
||||
~~~~~~
|
||||
|
||||
|
@ -327,6 +348,9 @@ advice.*::
|
|||
rmHints::
|
||||
In case of failure in the output of linkgit:git-rm[1],
|
||||
show directions on how to proceed from the current state.
|
||||
addEmbeddedRepo::
|
||||
Advice on what to do when you've accidentally added one
|
||||
git repo inside of another.
|
||||
--
|
||||
|
||||
core.fileMode::
|
||||
|
@ -334,7 +358,7 @@ core.fileMode::
|
|||
is to be honored.
|
||||
+
|
||||
Some filesystems lose the executable bit when a file that is
|
||||
marked as executable is checked out, or checks out an
|
||||
marked as executable is checked out, or checks out a
|
||||
non-executable file with executable bit on.
|
||||
linkgit:git-clone[1] or linkgit:git-init[1] probe the filesystem
|
||||
to see if it handles the executable bit correctly
|
||||
|
@ -662,7 +686,8 @@ core.packedGitLimit::
|
|||
bytes at once to complete an operation it will unmap existing
|
||||
regions to reclaim virtual address space within the process.
|
||||
+
|
||||
Default is 256 MiB on 32 bit platforms and 8 GiB on 64 bit platforms.
|
||||
Default is 256 MiB on 32 bit platforms and 32 TiB (effectively
|
||||
unlimited) on 64 bit platforms.
|
||||
This should be reasonable for all users/operating systems, except on
|
||||
the largest projects. You probably do not need to adjust this value.
|
||||
+
|
||||
|
@ -862,6 +887,7 @@ core.abbrev::
|
|||
computed based on the approximate number of packed objects
|
||||
in your repository, which hopefully is enough for
|
||||
abbreviated object names to stay unique for some time.
|
||||
The minimum length is 4.
|
||||
|
||||
add.ignoreErrors::
|
||||
add.ignore-errors (deprecated)::
|
||||
|
@ -1137,7 +1163,10 @@ color.status.<slot>::
|
|||
`untracked` (files which are not tracked by Git),
|
||||
`branch` (the current branch),
|
||||
`nobranch` (the color the 'no branch' warning is shown in, defaulting
|
||||
to red), or
|
||||
to red),
|
||||
`localBranch` or `remoteBranch` (the local and remote branch names,
|
||||
respectively, when branch and tracking information is displayed in the
|
||||
status short-format), or
|
||||
`unmerged` (files which have unmerged changes).
|
||||
|
||||
color.ui::
|
||||
|
@ -2140,6 +2169,10 @@ log.showRoot::
|
|||
Tools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which
|
||||
normally hide the root commit will now show it. True by default.
|
||||
|
||||
log.showSignature::
|
||||
If true, makes linkgit:git-log[1], linkgit:git-show[1], and
|
||||
linkgit:git-whatchanged[1] assume `--show-signature`.
|
||||
|
||||
log.mailmap::
|
||||
If true, makes linkgit:git-log[1], linkgit:git-show[1], and
|
||||
linkgit:git-whatchanged[1] assume `--use-mailmap`.
|
||||
|
@ -2591,7 +2624,7 @@ rebase.autoSquash::
|
|||
If set to true enable `--autosquash` option by default.
|
||||
|
||||
rebase.autoStash::
|
||||
When set to true, automatically create a temporary stash
|
||||
When set to true, automatically create a temporary stash entry
|
||||
before the operation begins, and apply it after the operation
|
||||
ends. This means that you can run rebase on a dirty worktree.
|
||||
However, use with care: the final stash application after a
|
||||
|
@ -2620,9 +2653,8 @@ receive.advertiseAtomic::
|
|||
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.
|
||||
When set to true, git-receive-pack will advertise the push options
|
||||
capability to its clients. False by default.
|
||||
|
||||
receive.autogc::
|
||||
By default, git-receive-pack will run "git-gc --auto" after
|
||||
|
@ -2964,6 +2996,11 @@ status.displayCommentPrefix::
|
|||
behavior of linkgit:git-status[1] in Git 1.8.4 and previous.
|
||||
Defaults to false.
|
||||
|
||||
status.showStash::
|
||||
If set to true, linkgit:git-status[1] will display the number of
|
||||
entries currently stashed away.
|
||||
Defaults to false.
|
||||
|
||||
status.showUntrackedFiles::
|
||||
By default, linkgit:git-status[1] and linkgit:git-commit[1] show
|
||||
files which are not currently tracked by Git. Directories which
|
||||
|
@ -3001,12 +3038,12 @@ status.submoduleSummary::
|
|||
|
||||
stash.showPatch::
|
||||
If this is set to true, the `git stash show` command without an
|
||||
option will show the stash in patch form. Defaults to false.
|
||||
option will show the stash entry in patch form. Defaults to false.
|
||||
See description of 'show' command in linkgit:git-stash[1].
|
||||
|
||||
stash.showStat::
|
||||
If this is set to true, the `git stash show` command without an
|
||||
option will show diffstat of the stash. Defaults to true.
|
||||
option will show diffstat of the stash entry. Defaults to true.
|
||||
See description of 'show' command in linkgit:git-stash[1].
|
||||
|
||||
submodule.<name>.url::
|
||||
|
@ -3063,6 +3100,11 @@ submodule.active::
|
|||
submodule's path to determine if the submodule is of interest to git
|
||||
commands.
|
||||
|
||||
submodule.recurse::
|
||||
Specifies if commands recurse into submodules by default. This
|
||||
applies to all commands that have a `--recurse-submodules` option.
|
||||
Defaults to false.
|
||||
|
||||
submodule.fetchJobs::
|
||||
Specifies how many submodules are fetched/cloned at the same time.
|
||||
A positive integer allows up to that number of submodules fetched
|
||||
|
@ -3208,6 +3250,13 @@ url.<base>.insteadOf::
|
|||
the best alternative for the particular user, even for a
|
||||
never-before-seen repository on the site. When more than one
|
||||
insteadOf strings match a given URL, the longest match is used.
|
||||
+
|
||||
Note that any protocol restrictions will be applied to the rewritten
|
||||
URL. If the rewrite changes the URL to use a custom protocol or remote
|
||||
helper, you may need to adjust the `protocol.*.allow` config to permit
|
||||
the request. In particular, protocols you expect to use for submodules
|
||||
must be set to `always` rather than the default of `user`. See the
|
||||
description of `protocol.allow` above.
|
||||
|
||||
url.<base>.pushInsteadOf::
|
||||
Any URL that starts with this value will not be pushed to;
|
||||
|
|
|
@ -165,6 +165,13 @@ for "git add --no-all <pathspec>...", i.e. ignored removed files.
|
|||
be ignored, no matter if they are already present in the work
|
||||
tree or not.
|
||||
|
||||
--no-warn-embedded-repo::
|
||||
By default, `git add` will warn when adding an embedded
|
||||
repository to the index without using `git submodule add` to
|
||||
create an entry in `.gitmodules`. This option will suppress the
|
||||
warning (e.g., if you are manually performing operations on
|
||||
submodules).
|
||||
|
||||
--chmod=(+|-)x::
|
||||
Override the executable bit of the added files. The executable
|
||||
bit is only changed in the index, the files on disk are left
|
||||
|
|
|
@ -1350,9 +1350,9 @@ References
|
|||
- [[[1]]] https://www.nist.gov/sites/default/files/documents/director/planning/report02-3.pdf['The Economic Impacts of Inadequate Infratructure for Software Testing'. Nist Planning Report 02-3], see Executive Summary and Chapter 8.
|
||||
- [[[2]]] http://www.oracle.com/technetwork/java/codeconvtoc-136057.html['Code Conventions for the Java Programming Language'. Sun Microsystems.]
|
||||
- [[[3]]] https://en.wikipedia.org/wiki/Software_maintenance['Software maintenance'. Wikipedia.]
|
||||
- [[[4]]] http://article.gmane.org/gmane.comp.version-control.git/45195/[Junio C Hamano. 'Automated bisect success story'. Gmane.]
|
||||
- [[[4]]] https://public-inbox.org/git/7vps5xsbwp.fsf_-_@assigned-by-dhcp.cox.net/[Junio C Hamano. 'Automated bisect success story'.]
|
||||
- [[[5]]] https://lwn.net/Articles/317154/[Christian Couder. 'Fully automated bisecting with "git bisect run"'. LWN.net.]
|
||||
- [[[6]]] https://lwn.net/Articles/277872/[Jonathan Corbet. 'Bisection divides users and developers'. LWN.net.]
|
||||
- [[[7]]] http://article.gmane.org/gmane.linux.scsi/36652/[Ingo Molnar. 'Re: BUG 2.6.23-rc3 can't see sd partitions on Alpha'. Gmane.]
|
||||
- [[[7]]] http://marc.info/?l=linux-kernel&m=119702753411680&w=2[Ingo Molnar. 'Re: BUG 2.6.23-rc3 can't see sd partitions on Alpha'. Linux-kernel mailing list.]
|
||||
- [[[8]]] https://www.kernel.org/pub/software/scm/git/docs/git-bisect.html[Junio C Hamano and the git-list. 'git-bisect(1) Manual Page'. Linux Kernel Archives.]
|
||||
- [[[9]]] https://github.com/Ealdwulf/bbchop[Ealdwulf. 'bbchop'. GitHub.]
|
||||
|
|
|
@ -13,7 +13,7 @@ SYNOPSIS
|
|||
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
|
||||
[-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
|
||||
[--dissociate] [--separate-git-dir <git dir>]
|
||||
[--depth <depth>] [--[no-]single-branch]
|
||||
[--depth <depth>] [--[no-]single-branch] [--no-tags]
|
||||
[--recurse-submodules] [--[no-]shallow-submodules]
|
||||
[--jobs <n>] [--] <repository> [<directory>]
|
||||
|
||||
|
@ -215,6 +215,18 @@ objects from the source repository into a pack in the cloned repository.
|
|||
branch when `--single-branch` clone was made, no remote-tracking
|
||||
branch is created.
|
||||
|
||||
--no-tags::
|
||||
Don't clone any tags, and set
|
||||
`remote.<remote>.tagOpt=--no-tags` in the config, ensuring
|
||||
that future `git pull` and `git fetch` operations won't follow
|
||||
any tags. Subsequent explicit tag fetches will still work,
|
||||
(see linkgit:git-fetch[1]).
|
||||
+
|
||||
Can be used in conjunction with `--single-branch` to clone and
|
||||
maintain a branch with no references other than a single cloned
|
||||
branch. This is useful e.g. to maintain minimal clones of the default
|
||||
branch of some repository for search indexing.
|
||||
|
||||
--recurse-submodules[=<pathspec]::
|
||||
After the clone is created, initialize and clone submodules
|
||||
within based on the provided pathspec. If no pathspec is
|
||||
|
|
|
@ -121,7 +121,7 @@ Performance and Compression Tuning
|
|||
|
||||
--depth=<n>::
|
||||
Maximum delta depth, for blob and tree deltification.
|
||||
Default is 10.
|
||||
Default is 50.
|
||||
|
||||
--export-pack-edges=<file>::
|
||||
After creating a packfile, print a line of data to
|
||||
|
|
|
@ -8,11 +8,11 @@ git-filter-branch - Rewrite branches
|
|||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git filter-branch' [--env-filter <command>] [--tree-filter <command>]
|
||||
[--index-filter <command>] [--parent-filter <command>]
|
||||
[--msg-filter <command>] [--commit-filter <command>]
|
||||
[--tag-name-filter <command>] [--subdirectory-filter <directory>]
|
||||
[--prune-empty]
|
||||
'git filter-branch' [--setup <command>] [--env-filter <command>]
|
||||
[--tree-filter <command>] [--index-filter <command>]
|
||||
[--parent-filter <command>] [--msg-filter <command>]
|
||||
[--commit-filter <command>] [--tag-name-filter <command>]
|
||||
[--subdirectory-filter <directory>] [--prune-empty]
|
||||
[--original <namespace>] [-d <directory>] [-f | --force]
|
||||
[--] [<rev-list options>...]
|
||||
|
||||
|
@ -82,12 +82,18 @@ multiple commits.
|
|||
OPTIONS
|
||||
-------
|
||||
|
||||
--setup <command>::
|
||||
This is not a real filter executed for each commit but a one
|
||||
time setup just before the loop. Therefore no commit-specific
|
||||
variables are defined yet. Functions or variables defined here
|
||||
can be used or modified in the following filter steps except
|
||||
the commit filter, for technical reasons.
|
||||
|
||||
--env-filter <command>::
|
||||
This filter may be used if you only need to modify the environment
|
||||
in which the commit will be performed. Specifically, you might
|
||||
want to rewrite the author/committer name/email/time environment
|
||||
variables (see linkgit:git-commit-tree[1] for details). Do not forget
|
||||
to re-export the variables.
|
||||
variables (see linkgit:git-commit-tree[1] for details).
|
||||
|
||||
--tree-filter <command>::
|
||||
This is the filter for rewriting the tree and its contents.
|
||||
|
@ -340,12 +346,10 @@ git filter-branch --env-filter '
|
|||
if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
|
||||
then
|
||||
GIT_AUTHOR_EMAIL=john@example.com
|
||||
export GIT_AUTHOR_EMAIL
|
||||
fi
|
||||
if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
|
||||
then
|
||||
GIT_COMMITTER_EMAIL=john@example.com
|
||||
export GIT_COMMITTER_EMAIL
|
||||
fi
|
||||
' -- --all
|
||||
--------------------------------------------------------
|
||||
|
|
|
@ -161,8 +161,11 @@ OPTIONS
|
|||
|
||||
-P::
|
||||
--perl-regexp::
|
||||
Use Perl-compatible regexp for patterns. Requires libpcre to be
|
||||
compiled in.
|
||||
Use Perl-compatible regular expressions for patterns.
|
||||
+
|
||||
Support for these types of regular expressions is an optional
|
||||
compile-time dependency. If Git wasn't compiled with support for them
|
||||
providing this option will cause it to die.
|
||||
|
||||
-F::
|
||||
--fixed-strings::
|
||||
|
|
|
@ -123,7 +123,7 @@ trailer.ifexists::
|
|||
same <token> in the message.
|
||||
+
|
||||
The valid values for this option are: `addIfDifferentNeighbor` (this
|
||||
is the default), `addIfDifferent`, `add`, `overwrite` or `doNothing`.
|
||||
is the default), `addIfDifferent`, `add`, `replace` or `doNothing`.
|
||||
+
|
||||
With `addIfDifferentNeighbor`, a new trailer will be added only if no
|
||||
trailer with the same (<token>, <value>) pair is above or below the line
|
||||
|
|
|
@ -131,7 +131,7 @@ unless you have read linkgit:git-rebase[1] carefully.
|
|||
--autostash::
|
||||
--no-autostash::
|
||||
Before starting rebase, stash local modifications away (see
|
||||
linkgit:git-stash[1]) if needed, and apply the stash when
|
||||
linkgit:git-stash[1]) if needed, and apply the stash entry when
|
||||
done. `--no-autostash` is useful to override the `rebase.autoStash`
|
||||
configuration variable (see linkgit:git-config[1]).
|
||||
+
|
||||
|
@ -159,15 +159,15 @@ present while on branch `<name>`, that value is used instead of
|
|||
|
||||
In order to determine what URL to use to fetch from, the value
|
||||
of the configuration `remote.<origin>.url` is consulted
|
||||
and if there is not any such variable, the value on `URL: ` line
|
||||
in `$GIT_DIR/remotes/<origin>` file is used.
|
||||
and if there is not any such variable, the value on the `URL:` line
|
||||
in `$GIT_DIR/remotes/<origin>` is used.
|
||||
|
||||
In order to determine what remote branches to fetch (and
|
||||
optionally store in the remote-tracking branches) when the command is
|
||||
run without any refspec parameters on the command line, values
|
||||
of the configuration variable `remote.<origin>.fetch` are
|
||||
consulted, and if there aren't any, `$GIT_DIR/remotes/<origin>`
|
||||
file is consulted and its `Pull: ` lines are used.
|
||||
is consulted and its `Pull:` lines are used.
|
||||
In addition to the refspec formats described in the OPTIONS
|
||||
section, you can have a globbing refspec that looks like this:
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ Merging
|
|||
-------
|
||||
If `-m` is specified, 'git read-tree' can perform 3 kinds of
|
||||
merge, a single tree merge if only 1 tree is given, a
|
||||
fast-forward merge with 2 trees, or a 3-way merge if 3 trees are
|
||||
fast-forward merge with 2 trees, or a 3-way merge if 3 or more trees are
|
||||
provided.
|
||||
|
||||
|
||||
|
|
|
@ -446,7 +446,7 @@ used to override and disable this setting.
|
|||
|
||||
--autostash::
|
||||
--no-autostash::
|
||||
Automatically create a temporary stash before the operation
|
||||
Automatically create a temporary stash entry before the operation
|
||||
begins, and apply it after the operation ends. This means
|
||||
that you can run rebase on a dirty worktree. However, use
|
||||
with care: the final stash application after a successful
|
||||
|
|
|
@ -9,7 +9,7 @@ git-repack - Pack unpacked objects in a repository
|
|||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [--window=<n>] [--depth=<n>]
|
||||
'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [--window=<n>] [--depth=<n>] [--threads=<n>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
@ -92,6 +92,9 @@ other objects in that pack they already have locally.
|
|||
to be applied that many times to get to the necessary object.
|
||||
The default value for --window is 10 and --depth is 50.
|
||||
|
||||
--threads=<n>::
|
||||
This option is passed through to `git pack-objects`.
|
||||
|
||||
--window-memory=<n>::
|
||||
This option provides an additional limit on top of `--window`;
|
||||
the window size will dynamically scale down so as to not take
|
||||
|
|
|
@ -115,7 +115,7 @@ $ git pull git://info.example.com/ nitfol <4>
|
|||
in these files are in good order. You do not want to see them
|
||||
when you run "git diff", because you plan to work on other files
|
||||
and changes with these files are distracting.
|
||||
<2> Somebody asks you to pull, and the changes sounds worthy of merging.
|
||||
<2> Somebody asks you to pull, and the changes sound worthy of merging.
|
||||
<3> However, you already dirtied the index (i.e. your index does
|
||||
not match the HEAD commit). But you know the pull you are going
|
||||
to make does not affect frotz.c or filfre.c, so you revert the
|
||||
|
|
|
@ -126,6 +126,12 @@ can be used.
|
|||
'git diff-{asterisk}'). In contrast to the `--sq-quote` option,
|
||||
the command input is still interpreted as usual.
|
||||
|
||||
--short[=length]::
|
||||
Same as `--verify` but shortens the object name to a unique
|
||||
prefix with at least `length` characters. The minimum length
|
||||
is 4, the default is the effective value of the `core.abbrev`
|
||||
configuration variable (see linkgit:git-config[1]).
|
||||
|
||||
--not::
|
||||
When showing object names, prefix them with '{caret}' and
|
||||
strip '{caret}' prefix from the object names that already have
|
||||
|
@ -136,12 +142,6 @@ can be used.
|
|||
The option core.warnAmbiguousRefs is used to select the strict
|
||||
abbreviation mode.
|
||||
|
||||
--short::
|
||||
--short=number::
|
||||
Instead of outputting the full SHA-1 values of object names try to
|
||||
abbreviate them to a shorter unique name. When no length is specified
|
||||
7 is used. The minimum length is 4.
|
||||
|
||||
--symbolic::
|
||||
Usually the object names are output in SHA-1 form (with
|
||||
possible '{caret}' prefix); this option makes them output in a
|
||||
|
|
|
@ -140,10 +140,11 @@ Only submodules using a gitfile (which means they were cloned
|
|||
with a Git version 1.7.8 or newer) will be removed from the work
|
||||
tree, as their repository lives inside the .git directory of the
|
||||
superproject. If a submodule (or one of those nested inside it)
|
||||
still uses a .git directory, `git rm` will fail - no matter if forced
|
||||
or not - to protect the submodule's history. If it exists the
|
||||
submodule.<name> section in the linkgit:gitmodules[5] file will also
|
||||
be removed and that file will be staged (unless --cached or -n are used).
|
||||
still uses a .git directory, `git rm` will move the submodules
|
||||
git directory into the superprojects git directory to protect
|
||||
the submodule's history. If it exists the submodule.<name> section
|
||||
in the linkgit:gitmodules[5] file will also be removed and that file
|
||||
will be staged (unless --cached or -n are used).
|
||||
|
||||
A submodule is considered up-to-date when the HEAD is the same as
|
||||
recorded in the index, no tracked files are modified and no untracked
|
||||
|
|
|
@ -377,6 +377,7 @@ have been specified, in which case default to 'compose'.
|
|||
Currently, validation means the following:
|
||||
+
|
||||
--
|
||||
* Invoke the sendemail-validate hook if present (see linkgit:githooks[5]).
|
||||
* Warn of patches that contain lines longer than 998 characters; this
|
||||
is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt.
|
||||
--
|
||||
|
|
|
@ -51,18 +51,18 @@ OPTIONS
|
|||
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
|
||||
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
|
||||
|
||||
Save your local modifications to a new 'stash' and roll them
|
||||
Save your local modifications to a new 'stash entry' and roll them
|
||||
back to HEAD (in the working tree and in the index).
|
||||
The <message> part is optional and gives
|
||||
the description along with the stashed state.
|
||||
+
|
||||
For quickly making a snapshot, you can omit "push". In this mode,
|
||||
non-option arguments are not allowed to prevent a misspelled
|
||||
subcommand from making an unwanted stash. The two exceptions to this
|
||||
subcommand from making an unwanted stash entry. The two exceptions to this
|
||||
are `stash -p` which acts as alias for `stash push -p` and pathspecs,
|
||||
which are allowed after a double hyphen `--` for disambiguation.
|
||||
+
|
||||
When pathspec is given to 'git stash push', the new stash records the
|
||||
When pathspec is given to 'git stash push', the new stash entry records the
|
||||
modified states only for the files that match the pathspec. The index
|
||||
entries and working tree files are then rolled back to the state in
|
||||
HEAD only for these files, too, leaving files that do not match the
|
||||
|
@ -89,10 +89,10 @@ The `--patch` option implies `--keep-index`. You can use
|
|||
|
||||
list [<options>]::
|
||||
|
||||
List the stashes that you currently have. Each 'stash' is listed
|
||||
with its name (e.g. `stash@{0}` is the latest stash, `stash@{1}` is
|
||||
List the stash entries that you currently have. Each 'stash entry' is
|
||||
listed with its name (e.g. `stash@{0}` is the latest entry, `stash@{1}` is
|
||||
the one before, etc.), the name of the branch that was current when the
|
||||
stash was made, and a short description of the commit the stash was
|
||||
entry was made, and a short description of the commit the entry was
|
||||
based on.
|
||||
+
|
||||
----------------------------------------------------------------
|
||||
|
@ -105,11 +105,12 @@ command to control what is shown and how. See linkgit:git-log[1].
|
|||
|
||||
show [<stash>]::
|
||||
|
||||
Show the changes recorded in the stash as a diff between the
|
||||
stashed state and its original parent. When no `<stash>` is given,
|
||||
shows the latest one. By default, the command shows the diffstat, but
|
||||
it will accept any format known to 'git diff' (e.g., `git stash show
|
||||
-p stash@{1}` to view the second most recent stash in patch form).
|
||||
Show the changes recorded in the stash entry as a diff between the
|
||||
stashed contents and the commit back when the stash entry was first
|
||||
created. When no `<stash>` is given, it shows the latest one.
|
||||
By default, the command shows the diffstat, but it will accept any
|
||||
format known to 'git diff' (e.g., `git stash show -p stash@{1}`
|
||||
to view the second most recent entry in patch form).
|
||||
You can use stash.showStat and/or stash.showPatch config variables
|
||||
to change the default behavior.
|
||||
|
||||
|
@ -149,26 +150,27 @@ branch <branchname> [<stash>]::
|
|||
+
|
||||
This is useful if the branch on which you ran `git stash save` has
|
||||
changed enough that `git stash apply` fails due to conflicts. Since
|
||||
the stash is applied on top of the commit that was HEAD at the time
|
||||
`git stash` was run, it restores the originally stashed state with
|
||||
no conflicts.
|
||||
the stash entry is applied on top of the commit that was HEAD at the
|
||||
time `git stash` was run, it restores the originally stashed state
|
||||
with no conflicts.
|
||||
|
||||
clear::
|
||||
Remove all the stashed states. Note that those states will then
|
||||
Remove all the stash entries. Note that those entries will then
|
||||
be subject to pruning, and may be impossible to recover (see
|
||||
'Examples' below for a possible strategy).
|
||||
|
||||
drop [-q|--quiet] [<stash>]::
|
||||
|
||||
Remove a single stashed state from the stash list. When no `<stash>`
|
||||
is given, it removes the latest one. i.e. `stash@{0}`, otherwise
|
||||
`<stash>` must be a valid stash log reference of the form
|
||||
`stash@{<revision>}`.
|
||||
Remove a single stash entry from the list of stash entries.
|
||||
When no `<stash>` is given, it removes the latest one.
|
||||
i.e. `stash@{0}`, otherwise `<stash>` must be a valid stash
|
||||
log reference of the form `stash@{<revision>}`.
|
||||
|
||||
create::
|
||||
|
||||
Create a stash (which is a regular commit object) and return its
|
||||
object name, without storing it anywhere in the ref namespace.
|
||||
Create a stash entry (which is a regular commit object) and
|
||||
return its object name, without storing it anywhere in the ref
|
||||
namespace.
|
||||
This is intended to be useful for scripts. It is probably not
|
||||
the command you want to use; see "save" above.
|
||||
|
||||
|
@ -182,10 +184,10 @@ store::
|
|||
DISCUSSION
|
||||
----------
|
||||
|
||||
A stash is represented as a commit whose tree records the state of the
|
||||
working directory, and its first parent is the commit at `HEAD` when
|
||||
the stash was created. The tree of the second parent records the
|
||||
state of the index when the stash is made, and it is made a child of
|
||||
A stash entry is represented as a commit whose tree records the state
|
||||
of the working directory, and its first parent is the commit at `HEAD`
|
||||
when the entry was created. The tree of the second parent records the
|
||||
state of the index when the entry is made, and it is made a child of
|
||||
the `HEAD` commit. The ancestry graph looks like this:
|
||||
|
||||
.----W
|
||||
|
@ -269,12 +271,12 @@ $ edit/build/test remaining parts
|
|||
$ git commit foo -m 'Remaining parts'
|
||||
----------------------------------------------------------------
|
||||
|
||||
Recovering stashes that were cleared/dropped erroneously::
|
||||
Recovering stash entries that were cleared/dropped erroneously::
|
||||
|
||||
If you mistakenly drop or clear stashes, they cannot be recovered
|
||||
If you mistakenly drop or clear stash entries, they cannot be recovered
|
||||
through the normal safety mechanisms. However, you can try the
|
||||
following incantation to get a list of stashes that are still in your
|
||||
repository, but not reachable any more:
|
||||
following incantation to get a list of stash entries that are still in
|
||||
your repository, but not reachable any more:
|
||||
+
|
||||
----------------------------------------------------------------
|
||||
git fsck --unreachable |
|
||||
|
|
|
@ -32,6 +32,9 @@ OPTIONS
|
|||
--branch::
|
||||
Show the branch and tracking info even in short-format.
|
||||
|
||||
--show-stash::
|
||||
Show the number of entries currently stashed away.
|
||||
|
||||
--porcelain[=<version>]::
|
||||
Give the output in an easy-to-parse format for scripts.
|
||||
This is similar to the short output, but will remain stable
|
||||
|
|
|
@ -95,6 +95,10 @@ If you still want the old default, you can get it by passing
|
|||
`--prefix ""` on the command line (`--prefix=""` may not work if
|
||||
your Perl's Getopt::Long is < v2.37).
|
||||
|
||||
--ignore-refs=<regex>;;
|
||||
When passed to 'init' or 'clone' this regular expression will
|
||||
be preserved as a config key. See 'fetch' for a description
|
||||
of `--ignore-refs`.
|
||||
--ignore-paths=<regex>;;
|
||||
When passed to 'init' or 'clone' this regular expression will
|
||||
be preserved as a config key. See 'fetch' for a description
|
||||
|
@ -138,6 +142,18 @@ the same local time zone.
|
|||
--parent;;
|
||||
Fetch only from the SVN parent of the current HEAD.
|
||||
|
||||
--ignore-refs=<regex>;;
|
||||
Ignore refs for branches or tags matching the Perl regular
|
||||
expression. A "negative look-ahead assertion" like
|
||||
`^refs/remotes/origin/(?!tags/wanted-tag|wanted-branch).*$`
|
||||
can be used to allow only certain refs.
|
||||
+
|
||||
[verse]
|
||||
config key: svn-remote.<name>.ignore-refs
|
||||
+
|
||||
If the ignore-refs configuration key is set, and the command-line
|
||||
option is also given, both regular expressions will be used.
|
||||
|
||||
--ignore-paths=<regex>;;
|
||||
This allows one to specify a Perl regular expression that will
|
||||
cause skipping of all matching paths from checkout from SVN.
|
||||
|
@ -443,6 +459,21 @@ Any other arguments are passed directly to 'git log'
|
|||
(URL) may be omitted if you are working from a 'git svn'-aware
|
||||
repository (that has been `init`-ed with 'git svn').
|
||||
The -r<revision> option is required for this.
|
||||
+
|
||||
The commit message is supplied either directly with the `-m` or `-F`
|
||||
option, or indirectly from the tag or commit when the second tree-ish
|
||||
denotes such an object, or it is requested by invoking an editor (see
|
||||
`--edit` option below).
|
||||
|
||||
-m <msg>;;
|
||||
--message=<msg>;;
|
||||
Use the given `msg` as the commit message. This option
|
||||
disables the `--edit` option.
|
||||
|
||||
-F <filename>;;
|
||||
--file=<filename>;;
|
||||
Take the commit message from the given file. This option
|
||||
disables the `--edit` option.
|
||||
|
||||
'info'::
|
||||
Shows information about a file or directory similar to what
|
||||
|
|
|
@ -12,7 +12,7 @@ SYNOPSIS
|
|||
'git tag' [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>]
|
||||
<tagname> [<commit> | <object>]
|
||||
'git tag' -d <tagname>...
|
||||
'git tag' [-n[<num>]] -l [--contains <commit>] [--contains <commit>]
|
||||
'git tag' [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
|
||||
[--points-at <object>] [--column[=<options>] | --no-column]
|
||||
[--create-reflog] [--sort=<key>] [--format=<format>]
|
||||
[--[no-]merged [<commit>]] [<pattern>...]
|
||||
|
|
|
@ -35,516 +35,6 @@ manual page gives you an overview of the command-line command syntax.
|
|||
A formatted and hyperlinked copy of the latest Git documentation
|
||||
can be viewed at `https://git.github.io/htmldocs/git.html`.
|
||||
|
||||
ifdef::stalenotes[]
|
||||
[NOTE]
|
||||
============
|
||||
|
||||
You are reading the documentation for the latest (possibly
|
||||
unreleased) version of Git, that is available from the 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v2.13.0/git.html[documentation for release 2.13]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.13.0.txt[2.13].
|
||||
|
||||
|
||||
* link:v2.12.3/git.html[documentation for release 2.12.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.12.3.txt[2.12.3],
|
||||
link:RelNotes/2.12.2.txt[2.12.2],
|
||||
link:RelNotes/2.12.1.txt[2.12.1],
|
||||
link:RelNotes/2.12.0.txt[2.12].
|
||||
|
||||
* link:v2.11.1/git.html[documentation for release 2.11.1]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.11.2.txt[2.11.2],
|
||||
link:RelNotes/2.11.1.txt[2.11.1],
|
||||
link:RelNotes/2.11.0.txt[2.11].
|
||||
|
||||
* link:v2.10.3/git.html[documentation for release 2.10.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.10.3.txt[2.10.3],
|
||||
link:RelNotes/2.10.2.txt[2.10.2],
|
||||
link:RelNotes/2.10.1.txt[2.10.1],
|
||||
link:RelNotes/2.10.0.txt[2.10].
|
||||
|
||||
* link:v2.9.4/git.html[documentation for release 2.9.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.9.4.txt[2.9.4],
|
||||
link:RelNotes/2.9.3.txt[2.9.3],
|
||||
link:RelNotes/2.9.2.txt[2.9.2],
|
||||
link:RelNotes/2.9.1.txt[2.9.1],
|
||||
link:RelNotes/2.9.0.txt[2.9].
|
||||
|
||||
* link:v2.8.5/git.html[documentation for release 2.8.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.8.5.txt[2.8.5],
|
||||
link:RelNotes/2.8.4.txt[2.8.4],
|
||||
link:RelNotes/2.8.3.txt[2.8.3],
|
||||
link:RelNotes/2.8.2.txt[2.8.2],
|
||||
link:RelNotes/2.8.1.txt[2.8.1],
|
||||
link:RelNotes/2.8.0.txt[2.8].
|
||||
|
||||
* link:v2.7.5/git.html[documentation for release 2.7.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.7.5.txt[2.7.5],
|
||||
link:RelNotes/2.7.4.txt[2.7.4],
|
||||
link:RelNotes/2.7.3.txt[2.7.3],
|
||||
link:RelNotes/2.7.2.txt[2.7.2],
|
||||
link:RelNotes/2.7.1.txt[2.7.1],
|
||||
link:RelNotes/2.7.0.txt[2.7].
|
||||
|
||||
* link:v2.6.7/git.html[documentation for release 2.6.7]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.6.7.txt[2.6.7],
|
||||
link:RelNotes/2.6.6.txt[2.6.6],
|
||||
link:RelNotes/2.6.5.txt[2.6.5],
|
||||
link:RelNotes/2.6.4.txt[2.6.4],
|
||||
link:RelNotes/2.6.3.txt[2.6.3],
|
||||
link:RelNotes/2.6.2.txt[2.6.2],
|
||||
link:RelNotes/2.6.1.txt[2.6.1],
|
||||
link:RelNotes/2.6.0.txt[2.6].
|
||||
|
||||
* link:v2.5.6/git.html[documentation for release 2.5.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.5.6.txt[2.5.6],
|
||||
link:RelNotes/2.5.5.txt[2.5.5],
|
||||
link:RelNotes/2.5.4.txt[2.5.4],
|
||||
link:RelNotes/2.5.3.txt[2.5.3],
|
||||
link:RelNotes/2.5.2.txt[2.5.2],
|
||||
link:RelNotes/2.5.1.txt[2.5.1],
|
||||
link:RelNotes/2.5.0.txt[2.5].
|
||||
|
||||
* link:v2.4.12/git.html[documentation for release 2.4.12]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.4.12.txt[2.4.12],
|
||||
link:RelNotes/2.4.11.txt[2.4.11],
|
||||
link:RelNotes/2.4.10.txt[2.4.10],
|
||||
link:RelNotes/2.4.9.txt[2.4.9],
|
||||
link:RelNotes/2.4.8.txt[2.4.8],
|
||||
link:RelNotes/2.4.7.txt[2.4.7],
|
||||
link:RelNotes/2.4.6.txt[2.4.6],
|
||||
link:RelNotes/2.4.5.txt[2.4.5],
|
||||
link:RelNotes/2.4.4.txt[2.4.4],
|
||||
link:RelNotes/2.4.3.txt[2.4.3],
|
||||
link:RelNotes/2.4.2.txt[2.4.2],
|
||||
link:RelNotes/2.4.1.txt[2.4.1],
|
||||
link:RelNotes/2.4.0.txt[2.4].
|
||||
|
||||
* link:v2.3.10/git.html[documentation for release 2.3.10]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.3.10.txt[2.3.10],
|
||||
link:RelNotes/2.3.9.txt[2.3.9],
|
||||
link:RelNotes/2.3.8.txt[2.3.8],
|
||||
link:RelNotes/2.3.7.txt[2.3.7],
|
||||
link:RelNotes/2.3.6.txt[2.3.6],
|
||||
link:RelNotes/2.3.5.txt[2.3.5],
|
||||
link:RelNotes/2.3.4.txt[2.3.4],
|
||||
link:RelNotes/2.3.3.txt[2.3.3],
|
||||
link:RelNotes/2.3.2.txt[2.3.2],
|
||||
link:RelNotes/2.3.1.txt[2.3.1],
|
||||
link:RelNotes/2.3.0.txt[2.3].
|
||||
|
||||
* link:v2.2.3/git.html[documentation for release 2.2.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.2.3.txt[2.2.3],
|
||||
link:RelNotes/2.2.2.txt[2.2.2],
|
||||
link:RelNotes/2.2.1.txt[2.2.1],
|
||||
link:RelNotes/2.2.0.txt[2.2].
|
||||
|
||||
* link:v2.1.4/git.html[documentation for release 2.1.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.1.4.txt[2.1.4],
|
||||
link:RelNotes/2.1.3.txt[2.1.3],
|
||||
link:RelNotes/2.1.2.txt[2.1.2],
|
||||
link:RelNotes/2.1.1.txt[2.1.1],
|
||||
link:RelNotes/2.1.0.txt[2.1].
|
||||
|
||||
* link:v2.0.5/git.html[documentation for release 2.0.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.0.5.txt[2.0.5],
|
||||
link:RelNotes/2.0.4.txt[2.0.4],
|
||||
link:RelNotes/2.0.3.txt[2.0.3],
|
||||
link:RelNotes/2.0.2.txt[2.0.2],
|
||||
link:RelNotes/2.0.1.txt[2.0.1],
|
||||
link:RelNotes/2.0.0.txt[2.0.0].
|
||||
|
||||
* link:v1.9.5/git.html[documentation for release 1.9.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.9.5.txt[1.9.5],
|
||||
link:RelNotes/1.9.4.txt[1.9.4],
|
||||
link:RelNotes/1.9.3.txt[1.9.3],
|
||||
link:RelNotes/1.9.2.txt[1.9.2],
|
||||
link:RelNotes/1.9.1.txt[1.9.1],
|
||||
link:RelNotes/1.9.0.txt[1.9.0].
|
||||
|
||||
* link:v1.8.5.6/git.html[documentation for release 1.8.5.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.8.5.6.txt[1.8.5.6],
|
||||
link:RelNotes/1.8.5.5.txt[1.8.5.5],
|
||||
link:RelNotes/1.8.5.4.txt[1.8.5.4],
|
||||
link:RelNotes/1.8.5.3.txt[1.8.5.3],
|
||||
link:RelNotes/1.8.5.2.txt[1.8.5.2],
|
||||
link:RelNotes/1.8.5.1.txt[1.8.5.1],
|
||||
link:RelNotes/1.8.5.txt[1.8.5].
|
||||
|
||||
* link:v1.8.4.5/git.html[documentation for release 1.8.4.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.8.4.5.txt[1.8.4.5],
|
||||
link:RelNotes/1.8.4.4.txt[1.8.4.4],
|
||||
link:RelNotes/1.8.4.3.txt[1.8.4.3],
|
||||
link:RelNotes/1.8.4.2.txt[1.8.4.2],
|
||||
link:RelNotes/1.8.4.1.txt[1.8.4.1],
|
||||
link:RelNotes/1.8.4.txt[1.8.4].
|
||||
|
||||
* link:v1.8.3.4/git.html[documentation for release 1.8.3.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.8.3.4.txt[1.8.3.4],
|
||||
link:RelNotes/1.8.3.3.txt[1.8.3.3],
|
||||
link:RelNotes/1.8.3.2.txt[1.8.3.2],
|
||||
link:RelNotes/1.8.3.1.txt[1.8.3.1],
|
||||
link:RelNotes/1.8.3.txt[1.8.3].
|
||||
|
||||
* link:v1.8.2.3/git.html[documentation for release 1.8.2.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.8.2.3.txt[1.8.2.3],
|
||||
link:RelNotes/1.8.2.2.txt[1.8.2.2],
|
||||
link:RelNotes/1.8.2.1.txt[1.8.2.1],
|
||||
link:RelNotes/1.8.2.txt[1.8.2].
|
||||
|
||||
* link:v1.8.1.6/git.html[documentation for release 1.8.1.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.8.1.6.txt[1.8.1.6],
|
||||
link:RelNotes/1.8.1.5.txt[1.8.1.5],
|
||||
link:RelNotes/1.8.1.4.txt[1.8.1.4],
|
||||
link:RelNotes/1.8.1.3.txt[1.8.1.3],
|
||||
link:RelNotes/1.8.1.2.txt[1.8.1.2],
|
||||
link:RelNotes/1.8.1.1.txt[1.8.1.1],
|
||||
link:RelNotes/1.8.1.txt[1.8.1].
|
||||
|
||||
* link:v1.8.0.3/git.html[documentation for release 1.8.0.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.8.0.3.txt[1.8.0.3],
|
||||
link:RelNotes/1.8.0.2.txt[1.8.0.2],
|
||||
link:RelNotes/1.8.0.1.txt[1.8.0.1],
|
||||
link:RelNotes/1.8.0.txt[1.8.0].
|
||||
|
||||
* link:v1.7.12.4/git.html[documentation for release 1.7.12.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.12.4.txt[1.7.12.4],
|
||||
link:RelNotes/1.7.12.3.txt[1.7.12.3],
|
||||
link:RelNotes/1.7.12.2.txt[1.7.12.2],
|
||||
link:RelNotes/1.7.12.1.txt[1.7.12.1],
|
||||
link:RelNotes/1.7.12.txt[1.7.12].
|
||||
|
||||
* link:v1.7.11.7/git.html[documentation for release 1.7.11.7]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.11.7.txt[1.7.11.7],
|
||||
link:RelNotes/1.7.11.6.txt[1.7.11.6],
|
||||
link:RelNotes/1.7.11.5.txt[1.7.11.5],
|
||||
link:RelNotes/1.7.11.4.txt[1.7.11.4],
|
||||
link:RelNotes/1.7.11.3.txt[1.7.11.3],
|
||||
link:RelNotes/1.7.11.2.txt[1.7.11.2],
|
||||
link:RelNotes/1.7.11.1.txt[1.7.11.1],
|
||||
link:RelNotes/1.7.11.txt[1.7.11].
|
||||
|
||||
* link:v1.7.10.5/git.html[documentation for release 1.7.10.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.10.5.txt[1.7.10.5],
|
||||
link:RelNotes/1.7.10.4.txt[1.7.10.4],
|
||||
link:RelNotes/1.7.10.3.txt[1.7.10.3],
|
||||
link:RelNotes/1.7.10.2.txt[1.7.10.2],
|
||||
link:RelNotes/1.7.10.1.txt[1.7.10.1],
|
||||
link:RelNotes/1.7.10.txt[1.7.10].
|
||||
|
||||
* link:v1.7.9.7/git.html[documentation for release 1.7.9.7]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.9.7.txt[1.7.9.7],
|
||||
link:RelNotes/1.7.9.6.txt[1.7.9.6],
|
||||
link:RelNotes/1.7.9.5.txt[1.7.9.5],
|
||||
link:RelNotes/1.7.9.4.txt[1.7.9.4],
|
||||
link:RelNotes/1.7.9.3.txt[1.7.9.3],
|
||||
link:RelNotes/1.7.9.2.txt[1.7.9.2],
|
||||
link:RelNotes/1.7.9.1.txt[1.7.9.1],
|
||||
link:RelNotes/1.7.9.txt[1.7.9].
|
||||
|
||||
* link:v1.7.8.6/git.html[documentation for release 1.7.8.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.8.6.txt[1.7.8.6],
|
||||
link:RelNotes/1.7.8.5.txt[1.7.8.5],
|
||||
link:RelNotes/1.7.8.4.txt[1.7.8.4],
|
||||
link:RelNotes/1.7.8.3.txt[1.7.8.3],
|
||||
link:RelNotes/1.7.8.2.txt[1.7.8.2],
|
||||
link:RelNotes/1.7.8.1.txt[1.7.8.1],
|
||||
link:RelNotes/1.7.8.txt[1.7.8].
|
||||
|
||||
* link:v1.7.7.7/git.html[documentation for release 1.7.7.7]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.7.7.txt[1.7.7.7],
|
||||
link:RelNotes/1.7.7.6.txt[1.7.7.6],
|
||||
link:RelNotes/1.7.7.5.txt[1.7.7.5],
|
||||
link:RelNotes/1.7.7.4.txt[1.7.7.4],
|
||||
link:RelNotes/1.7.7.3.txt[1.7.7.3],
|
||||
link:RelNotes/1.7.7.2.txt[1.7.7.2],
|
||||
link:RelNotes/1.7.7.1.txt[1.7.7.1],
|
||||
link:RelNotes/1.7.7.txt[1.7.7].
|
||||
|
||||
* link:v1.7.6.6/git.html[documentation for release 1.7.6.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.6.6.txt[1.7.6.6],
|
||||
link:RelNotes/1.7.6.5.txt[1.7.6.5],
|
||||
link:RelNotes/1.7.6.4.txt[1.7.6.4],
|
||||
link:RelNotes/1.7.6.3.txt[1.7.6.3],
|
||||
link:RelNotes/1.7.6.2.txt[1.7.6.2],
|
||||
link:RelNotes/1.7.6.1.txt[1.7.6.1],
|
||||
link:RelNotes/1.7.6.txt[1.7.6].
|
||||
|
||||
* link:v1.7.5.4/git.html[documentation for release 1.7.5.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.5.4.txt[1.7.5.4],
|
||||
link:RelNotes/1.7.5.3.txt[1.7.5.3],
|
||||
link:RelNotes/1.7.5.2.txt[1.7.5.2],
|
||||
link:RelNotes/1.7.5.1.txt[1.7.5.1],
|
||||
link:RelNotes/1.7.5.txt[1.7.5].
|
||||
|
||||
* link:v1.7.4.5/git.html[documentation for release 1.7.4.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.4.5.txt[1.7.4.5],
|
||||
link:RelNotes/1.7.4.4.txt[1.7.4.4],
|
||||
link:RelNotes/1.7.4.3.txt[1.7.4.3],
|
||||
link:RelNotes/1.7.4.2.txt[1.7.4.2],
|
||||
link:RelNotes/1.7.4.1.txt[1.7.4.1],
|
||||
link:RelNotes/1.7.4.txt[1.7.4].
|
||||
|
||||
* link:v1.7.3.5/git.html[documentation for release 1.7.3.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.3.5.txt[1.7.3.5],
|
||||
link:RelNotes/1.7.3.4.txt[1.7.3.4],
|
||||
link:RelNotes/1.7.3.3.txt[1.7.3.3],
|
||||
link:RelNotes/1.7.3.2.txt[1.7.3.2],
|
||||
link:RelNotes/1.7.3.1.txt[1.7.3.1],
|
||||
link:RelNotes/1.7.3.txt[1.7.3].
|
||||
|
||||
* link:v1.7.2.5/git.html[documentation for release 1.7.2.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.2.5.txt[1.7.2.5],
|
||||
link:RelNotes/1.7.2.4.txt[1.7.2.4],
|
||||
link:RelNotes/1.7.2.3.txt[1.7.2.3],
|
||||
link:RelNotes/1.7.2.2.txt[1.7.2.2],
|
||||
link:RelNotes/1.7.2.1.txt[1.7.2.1],
|
||||
link:RelNotes/1.7.2.txt[1.7.2].
|
||||
|
||||
* link:v1.7.1.4/git.html[documentation for release 1.7.1.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.1.4.txt[1.7.1.4],
|
||||
link:RelNotes/1.7.1.3.txt[1.7.1.3],
|
||||
link:RelNotes/1.7.1.2.txt[1.7.1.2],
|
||||
link:RelNotes/1.7.1.1.txt[1.7.1.1],
|
||||
link:RelNotes/1.7.1.txt[1.7.1].
|
||||
|
||||
* link:v1.7.0.9/git.html[documentation for release 1.7.0.9]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.7.0.9.txt[1.7.0.9],
|
||||
link:RelNotes/1.7.0.8.txt[1.7.0.8],
|
||||
link:RelNotes/1.7.0.7.txt[1.7.0.7],
|
||||
link:RelNotes/1.7.0.6.txt[1.7.0.6],
|
||||
link:RelNotes/1.7.0.5.txt[1.7.0.5],
|
||||
link:RelNotes/1.7.0.4.txt[1.7.0.4],
|
||||
link:RelNotes/1.7.0.3.txt[1.7.0.3],
|
||||
link:RelNotes/1.7.0.2.txt[1.7.0.2],
|
||||
link:RelNotes/1.7.0.1.txt[1.7.0.1],
|
||||
link:RelNotes/1.7.0.txt[1.7.0].
|
||||
|
||||
* link:v1.6.6.3/git.html[documentation for release 1.6.6.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.6.6.3.txt[1.6.6.3],
|
||||
link:RelNotes/1.6.6.2.txt[1.6.6.2],
|
||||
link:RelNotes/1.6.6.1.txt[1.6.6.1],
|
||||
link:RelNotes/1.6.6.txt[1.6.6].
|
||||
|
||||
* link:v1.6.5.9/git.html[documentation for release 1.6.5.9]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.6.5.9.txt[1.6.5.9],
|
||||
link:RelNotes/1.6.5.8.txt[1.6.5.8],
|
||||
link:RelNotes/1.6.5.7.txt[1.6.5.7],
|
||||
link:RelNotes/1.6.5.6.txt[1.6.5.6],
|
||||
link:RelNotes/1.6.5.5.txt[1.6.5.5],
|
||||
link:RelNotes/1.6.5.4.txt[1.6.5.4],
|
||||
link:RelNotes/1.6.5.3.txt[1.6.5.3],
|
||||
link:RelNotes/1.6.5.2.txt[1.6.5.2],
|
||||
link:RelNotes/1.6.5.1.txt[1.6.5.1],
|
||||
link:RelNotes/1.6.5.txt[1.6.5].
|
||||
|
||||
* link:v1.6.4.5/git.html[documentation for release 1.6.4.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.6.4.5.txt[1.6.4.5],
|
||||
link:RelNotes/1.6.4.4.txt[1.6.4.4],
|
||||
link:RelNotes/1.6.4.3.txt[1.6.4.3],
|
||||
link:RelNotes/1.6.4.2.txt[1.6.4.2],
|
||||
link:RelNotes/1.6.4.1.txt[1.6.4.1],
|
||||
link:RelNotes/1.6.4.txt[1.6.4].
|
||||
|
||||
* link:v1.6.3.4/git.html[documentation for release 1.6.3.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.6.3.4.txt[1.6.3.4],
|
||||
link:RelNotes/1.6.3.3.txt[1.6.3.3],
|
||||
link:RelNotes/1.6.3.2.txt[1.6.3.2],
|
||||
link:RelNotes/1.6.3.1.txt[1.6.3.1],
|
||||
link:RelNotes/1.6.3.txt[1.6.3].
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.6.2.5.txt[1.6.2.5],
|
||||
link:RelNotes/1.6.2.4.txt[1.6.2.4],
|
||||
link:RelNotes/1.6.2.3.txt[1.6.2.3],
|
||||
link:RelNotes/1.6.2.2.txt[1.6.2.2],
|
||||
link:RelNotes/1.6.2.1.txt[1.6.2.1],
|
||||
link:RelNotes/1.6.2.txt[1.6.2].
|
||||
|
||||
* link:v1.6.1.3/git.html[documentation for release 1.6.1.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.6.1.3.txt[1.6.1.3],
|
||||
link:RelNotes/1.6.1.2.txt[1.6.1.2],
|
||||
link:RelNotes/1.6.1.1.txt[1.6.1.1],
|
||||
link:RelNotes/1.6.1.txt[1.6.1].
|
||||
|
||||
* link:v1.6.0.6/git.html[documentation for release 1.6.0.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.6.0.6.txt[1.6.0.6],
|
||||
link:RelNotes/1.6.0.5.txt[1.6.0.5],
|
||||
link:RelNotes/1.6.0.4.txt[1.6.0.4],
|
||||
link:RelNotes/1.6.0.3.txt[1.6.0.3],
|
||||
link:RelNotes/1.6.0.2.txt[1.6.0.2],
|
||||
link:RelNotes/1.6.0.1.txt[1.6.0.1],
|
||||
link:RelNotes/1.6.0.txt[1.6.0].
|
||||
|
||||
* link:v1.5.6.6/git.html[documentation for release 1.5.6.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.5.6.6.txt[1.5.6.6],
|
||||
link:RelNotes/1.5.6.5.txt[1.5.6.5],
|
||||
link:RelNotes/1.5.6.4.txt[1.5.6.4],
|
||||
link:RelNotes/1.5.6.3.txt[1.5.6.3],
|
||||
link:RelNotes/1.5.6.2.txt[1.5.6.2],
|
||||
link:RelNotes/1.5.6.1.txt[1.5.6.1],
|
||||
link:RelNotes/1.5.6.txt[1.5.6].
|
||||
|
||||
* link:v1.5.5.6/git.html[documentation for release 1.5.5.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.5.5.6.txt[1.5.5.6],
|
||||
link:RelNotes/1.5.5.5.txt[1.5.5.5],
|
||||
link:RelNotes/1.5.5.4.txt[1.5.5.4],
|
||||
link:RelNotes/1.5.5.3.txt[1.5.5.3],
|
||||
link:RelNotes/1.5.5.2.txt[1.5.5.2],
|
||||
link:RelNotes/1.5.5.1.txt[1.5.5.1],
|
||||
link:RelNotes/1.5.5.txt[1.5.5].
|
||||
|
||||
* link:v1.5.4.7/git.html[documentation for release 1.5.4.7]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.5.4.7.txt[1.5.4.7],
|
||||
link:RelNotes/1.5.4.6.txt[1.5.4.6],
|
||||
link:RelNotes/1.5.4.5.txt[1.5.4.5],
|
||||
link:RelNotes/1.5.4.4.txt[1.5.4.4],
|
||||
link:RelNotes/1.5.4.3.txt[1.5.4.3],
|
||||
link:RelNotes/1.5.4.2.txt[1.5.4.2],
|
||||
link:RelNotes/1.5.4.1.txt[1.5.4.1],
|
||||
link:RelNotes/1.5.4.txt[1.5.4].
|
||||
|
||||
* link:v1.5.3.8/git.html[documentation for release 1.5.3.8]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.5.3.8.txt[1.5.3.8],
|
||||
link:RelNotes/1.5.3.7.txt[1.5.3.7],
|
||||
link:RelNotes/1.5.3.6.txt[1.5.3.6],
|
||||
link:RelNotes/1.5.3.5.txt[1.5.3.5],
|
||||
link:RelNotes/1.5.3.4.txt[1.5.3.4],
|
||||
link:RelNotes/1.5.3.3.txt[1.5.3.3],
|
||||
link:RelNotes/1.5.3.2.txt[1.5.3.2],
|
||||
link:RelNotes/1.5.3.1.txt[1.5.3.1],
|
||||
link:RelNotes/1.5.3.txt[1.5.3].
|
||||
|
||||
* link:v1.5.2.5/git.html[documentation for release 1.5.2.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.5.2.5.txt[1.5.2.5],
|
||||
link:RelNotes/1.5.2.4.txt[1.5.2.4],
|
||||
link:RelNotes/1.5.2.3.txt[1.5.2.3],
|
||||
link:RelNotes/1.5.2.2.txt[1.5.2.2],
|
||||
link:RelNotes/1.5.2.1.txt[1.5.2.1],
|
||||
link:RelNotes/1.5.2.txt[1.5.2].
|
||||
|
||||
* link:v1.5.1.6/git.html[documentation for release 1.5.1.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.5.1.6.txt[1.5.1.6],
|
||||
link:RelNotes/1.5.1.5.txt[1.5.1.5],
|
||||
link:RelNotes/1.5.1.4.txt[1.5.1.4],
|
||||
link:RelNotes/1.5.1.3.txt[1.5.1.3],
|
||||
link:RelNotes/1.5.1.2.txt[1.5.1.2],
|
||||
link:RelNotes/1.5.1.1.txt[1.5.1.1],
|
||||
link:RelNotes/1.5.1.txt[1.5.1].
|
||||
|
||||
* link:v1.5.0.7/git.html[documentation for release 1.5.0.7]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/1.5.0.7.txt[1.5.0.7],
|
||||
link:RelNotes/1.5.0.6.txt[1.5.0.6],
|
||||
link:RelNotes/1.5.0.5.txt[1.5.0.5],
|
||||
link:RelNotes/1.5.0.3.txt[1.5.0.3],
|
||||
link:RelNotes/1.5.0.2.txt[1.5.0.2],
|
||||
link:RelNotes/1.5.0.1.txt[1.5.0.1],
|
||||
link:RelNotes/1.5.0.txt[1.5.0].
|
||||
|
||||
* documentation for release link:v1.4.4.4/git.html[1.4.4.4],
|
||||
link:v1.3.3/git.html[1.3.3],
|
||||
link:v1.2.6/git.html[1.2.6],
|
||||
link:v1.0.13/git.html[1.0.13].
|
||||
|
||||
============
|
||||
|
||||
endif::stalenotes[]
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
|
|
@ -229,7 +229,7 @@ From a clean working directory:
|
|||
|
||||
-------------------------------------------------
|
||||
$ echo "* text=auto" >.gitattributes
|
||||
$ rm .git/index # Remove the index to re-scan the working directory
|
||||
$ git read-tree --empty # Clean index, force re-scan of working directory
|
||||
$ git add .
|
||||
$ git status # Show files that will be normalized
|
||||
$ git commit -m "Introduce end-of-line normalization"
|
||||
|
|
|
@ -194,7 +194,7 @@ different things.
|
|||
* The `--index` option is used to ask a command that
|
||||
usually works on files in the working tree to *also*
|
||||
affect the index. For example, `git stash apply` usually
|
||||
merges changes recorded in a stash to the working tree,
|
||||
merges changes recorded in a stash entry to the working tree,
|
||||
but with the `--index` option, it also merges changes to
|
||||
the index as well.
|
||||
|
||||
|
|
|
@ -101,16 +101,6 @@ $ git help credential-foo
|
|||
$ git config --global credential.helper foo
|
||||
-------------------------------------------
|
||||
|
||||
If there are multiple instances of the `credential.helper` configuration
|
||||
variable, each helper will be tried in turn, and may provide a username,
|
||||
password, or nothing. Once Git has acquired both a username and a
|
||||
password, no more helpers will be tried.
|
||||
|
||||
If `credential.helper` is configured to the empty string, this resets
|
||||
the helper list to empty (so you may override a helper set by a
|
||||
lower-priority config file by configuring the empty-string helper,
|
||||
followed by whatever set of helpers you would like).
|
||||
|
||||
|
||||
CREDENTIAL CONTEXTS
|
||||
-------------------
|
||||
|
@ -162,6 +152,16 @@ helper::
|
|||
shell (so, for example, setting this to `foo --option=bar` will execute
|
||||
`git credential-foo --option=bar` via the shell. See the manual of
|
||||
specific helpers for examples of their use.
|
||||
+
|
||||
If there are multiple instances of the `credential.helper` configuration
|
||||
variable, each helper will be tried in turn, and may provide a username,
|
||||
password, or nothing. Once Git has acquired both a username and a
|
||||
password, no more helpers will be tried.
|
||||
+
|
||||
If `credential.helper` is configured to the empty string, this resets
|
||||
the helper list to empty (so you may override a helper set by a
|
||||
lower-priority config file by configuring the empty-string helper,
|
||||
followed by whatever set of helpers you would like).
|
||||
|
||||
username::
|
||||
|
||||
|
|
|
@ -447,6 +447,14 @@ rebase::
|
|||
The commits are guaranteed to be listed in the order that they were
|
||||
processed by rebase.
|
||||
|
||||
sendemail-validate
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This hook is invoked by 'git send-email'. It takes a single parameter,
|
||||
the name of the file that holds the e-mail to be sent. Exiting with a
|
||||
non-zero status causes 'git send-email' to abort before sending any
|
||||
e-mails.
|
||||
|
||||
|
||||
GIT
|
||||
---
|
||||
|
|
|
@ -84,7 +84,7 @@ separator (rules for Perl's "`split(" ", $line)`").
|
|||
|
||||
* Fields use modified URI encoding, defined in RFC 3986, section 2.1
|
||||
(Percent-Encoding), or rather "Query string encoding" (see
|
||||
http://en.wikipedia.org/wiki/Query_string#URL_encoding[]), the difference
|
||||
https://en.wikipedia.org/wiki/Query_string#URL_encoding[]), the difference
|
||||
being that SP (" ") can be encoded as "{plus}" (and therefore "{plus}" has to be
|
||||
also percent-encoded).
|
||||
+
|
||||
|
|
|
@ -570,6 +570,10 @@ The most notable example is `HEAD`.
|
|||
is created by giving the `--depth` option to linkgit:git-clone[1], and
|
||||
its history can be later deepened with linkgit:git-fetch[1].
|
||||
|
||||
[[def_stash]]stash entry::
|
||||
An <<def_object,object>> used to temporarily store the contents of a
|
||||
<<def_dirty,dirty>> working directory and the index for future reuse.
|
||||
|
||||
[[def_submodule]]submodule::
|
||||
A <<def_repository,repository>> that holds the history of a
|
||||
separate project inside another repository (the latter of
|
||||
|
|
|
@ -199,7 +199,7 @@ endif::git-rev-list[]
|
|||
than given and there are spaces on its left, use those spaces
|
||||
- '%><(<N>)', '%><|(<N>)': similar to '% <(<N>)', '%<|(<N>)'
|
||||
respectively, but padding both sides (i.e. the text is centered)
|
||||
-%(trailers): display the trailers of the body as interpreted by
|
||||
- %(trailers): display the trailers of the body as interpreted by
|
||||
linkgit:git-interpret-trailers[1]
|
||||
|
||||
NOTE: Some placeholders may depend on other options given to the
|
||||
|
@ -213,8 +213,8 @@ If you add a `+` (plus sign) after '%' of a placeholder, a line-feed
|
|||
is inserted immediately before the expansion if and only if the
|
||||
placeholder expands to a non-empty string.
|
||||
|
||||
If you add a `-` (minus sign) after '%' of a placeholder, line-feeds that
|
||||
immediately precede the expansion are deleted if and only if the
|
||||
If you add a `-` (minus sign) after '%' of a placeholder, all consecutive
|
||||
line-feeds immediately preceding the expansion are deleted if and only if the
|
||||
placeholder expands to an empty string.
|
||||
|
||||
If you add a ` ` (space) after '%' of a placeholder, a space
|
||||
|
|
|
@ -91,9 +91,14 @@ endif::git-rev-list[]
|
|||
Consider the limiting patterns to be fixed strings (don't interpret
|
||||
pattern as a regular expression).
|
||||
|
||||
-P::
|
||||
--perl-regexp::
|
||||
Consider the limiting patterns to be Perl-compatible regular expressions.
|
||||
Requires libpcre to be compiled in.
|
||||
Consider the limiting patterns to be Perl-compatible regular
|
||||
expressions.
|
||||
+
|
||||
Support for these types of regular expressions is an optional
|
||||
compile-time dependency. If Git wasn't compiled with support for them
|
||||
providing this option will cause it to die.
|
||||
|
||||
--remove-empty::
|
||||
Stop when a given path disappears from the tree.
|
||||
|
@ -764,7 +769,8 @@ timezone value.
|
|||
1970). As with `--raw`, this is always in UTC and therefore `-local`
|
||||
has no effect.
|
||||
+
|
||||
`--date=format:...` feeds the format `...` to your system `strftime`.
|
||||
`--date=format:...` feeds the format `...` to your system `strftime`,
|
||||
except for %z and %Z, which are handled internally.
|
||||
Use `--date=format:%c` to show the date in your system locale's
|
||||
preferred format. See the `strftime` manual for a complete list of
|
||||
format placeholders. When using `-local`, the correct syntax is
|
||||
|
|
|
@ -33,6 +33,12 @@ The notable options are:
|
|||
Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]`
|
||||
in addition to untracked files in `entries[]`.
|
||||
|
||||
`DIR_KEEP_UNTRACKED_CONTENTS`:::
|
||||
|
||||
Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is set, the
|
||||
untracked contents of untracked directories are also returned in
|
||||
`entries[]`.
|
||||
|
||||
`DIR_COLLECT_IGNORED`:::
|
||||
|
||||
Special mode for git-add. Return ignored files in `ignored[]` and
|
||||
|
|
|
@ -1,309 +0,0 @@
|
|||
hashmap API
|
||||
===========
|
||||
|
||||
The hashmap API is a generic implementation of hash-based key-value mappings.
|
||||
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct hashmap`::
|
||||
|
||||
The hash table structure. Members can be used as follows, but should
|
||||
not be modified directly:
|
||||
+
|
||||
The `size` member keeps track of the total number of entries (0 means the
|
||||
hashmap is empty).
|
||||
+
|
||||
`tablesize` is the allocated size of the hash table. A non-0 value indicates
|
||||
that the hashmap is initialized. It may also be useful for statistical purposes
|
||||
(i.e. `size / tablesize` is the current load factor).
|
||||
+
|
||||
`cmpfn` stores the comparison function specified in `hashmap_init()`. In
|
||||
advanced scenarios, it may be useful to change this, e.g. to switch between
|
||||
case-sensitive and case-insensitive lookup.
|
||||
+
|
||||
When `disallow_rehash` is set, automatic rehashes are prevented during inserts
|
||||
and deletes.
|
||||
|
||||
`struct hashmap_entry`::
|
||||
|
||||
An opaque structure representing an entry in the hash table, which must
|
||||
be used as first member of user data structures. Ideally it should be
|
||||
followed by an int-sized member to prevent unused memory on 64-bit
|
||||
systems due to alignment.
|
||||
+
|
||||
The `hash` member is the entry's hash code and the `next` member points to the
|
||||
next entry in case of collisions (i.e. if multiple entries map to the same
|
||||
bucket).
|
||||
|
||||
`struct hashmap_iter`::
|
||||
|
||||
An iterator structure, to be used with hashmap_iter_* functions.
|
||||
|
||||
Types
|
||||
-----
|
||||
|
||||
`int (*hashmap_cmp_fn)(const void *entry, const void *entry_or_key, const void *keydata)`::
|
||||
|
||||
User-supplied function to test two hashmap entries for equality. Shall
|
||||
return 0 if the entries are equal.
|
||||
+
|
||||
This function is always called with non-NULL `entry` / `entry_or_key`
|
||||
parameters that have the same hash code. When looking up an entry, the `key`
|
||||
and `keydata` parameters to hashmap_get and hashmap_remove are always passed
|
||||
as second and third argument, respectively. Otherwise, `keydata` is NULL.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`unsigned int strhash(const char *buf)`::
|
||||
`unsigned int strihash(const char *buf)`::
|
||||
`unsigned int memhash(const void *buf, size_t len)`::
|
||||
`unsigned int memihash(const void *buf, size_t len)`::
|
||||
`unsigned int memihash_cont(unsigned int hash_seed, const void *buf, size_t len)`::
|
||||
|
||||
Ready-to-use hash functions for strings, using the FNV-1 algorithm (see
|
||||
http://www.isthe.com/chongo/tech/comp/fnv).
|
||||
+
|
||||
`strhash` and `strihash` take 0-terminated strings, while `memhash` and
|
||||
`memihash` operate on arbitrary-length memory.
|
||||
+
|
||||
`strihash` and `memihash` are case insensitive versions.
|
||||
+
|
||||
`memihash_cont` is a variant of `memihash` that allows a computation to be
|
||||
continued with another chunk of data.
|
||||
|
||||
`unsigned int sha1hash(const unsigned char *sha1)`::
|
||||
|
||||
Converts a cryptographic hash (e.g. SHA-1) into an int-sized hash code
|
||||
for use in hash tables. Cryptographic hashes are supposed to have
|
||||
uniform distribution, so in contrast to `memhash()`, this just copies
|
||||
the first `sizeof(int)` bytes without shuffling any bits. Note that
|
||||
the results will be different on big-endian and little-endian
|
||||
platforms, so they should not be stored or transferred over the net.
|
||||
|
||||
`void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function, size_t initial_size)`::
|
||||
|
||||
Initializes a hashmap structure.
|
||||
+
|
||||
`map` is the hashmap to initialize.
|
||||
+
|
||||
The `equals_function` can be specified to compare two entries for equality.
|
||||
If NULL, entries are considered equal if their hash codes are equal.
|
||||
+
|
||||
If the total number of entries is known in advance, the `initial_size`
|
||||
parameter may be used to preallocate a sufficiently large table and thus
|
||||
prevent expensive resizing. If 0, the table is dynamically resized.
|
||||
|
||||
`void hashmap_free(struct hashmap *map, int free_entries)`::
|
||||
|
||||
Frees a hashmap structure and allocated memory.
|
||||
+
|
||||
`map` is the hashmap to free.
|
||||
+
|
||||
If `free_entries` is true, each hashmap_entry in the map is freed as well
|
||||
(using stdlib's free()).
|
||||
|
||||
`void hashmap_entry_init(void *entry, unsigned int hash)`::
|
||||
|
||||
Initializes a hashmap_entry structure.
|
||||
+
|
||||
`entry` points to the entry to initialize.
|
||||
+
|
||||
`hash` is the hash code of the entry.
|
||||
+
|
||||
The hashmap_entry structure does not hold references to external resources,
|
||||
and it is safe to just discard it once you are done with it (i.e. if
|
||||
your structure was allocated with xmalloc(), you can just free(3) it,
|
||||
and if it is on stack, you can just let it go out of scope).
|
||||
|
||||
`void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata)`::
|
||||
|
||||
Returns the hashmap entry for the specified key, or NULL if not found.
|
||||
+
|
||||
`map` is the hashmap structure.
|
||||
+
|
||||
`key` is a hashmap_entry structure (or user data structure that starts with
|
||||
hashmap_entry) that has at least been initialized with the proper hash code
|
||||
(via `hashmap_entry_init`).
|
||||
+
|
||||
If an entry with matching hash code is found, `key` and `keydata` are passed
|
||||
to `hashmap_cmp_fn` to decide whether the entry matches the key.
|
||||
|
||||
`void *hashmap_get_from_hash(const struct hashmap *map, unsigned int hash, const void *keydata)`::
|
||||
|
||||
Returns the hashmap entry for the specified hash code and key data,
|
||||
or NULL if not found.
|
||||
+
|
||||
`map` is the hashmap structure.
|
||||
+
|
||||
`hash` is the hash code of the entry to look up.
|
||||
+
|
||||
If an entry with matching hash code is found, `keydata` is passed to
|
||||
`hashmap_cmp_fn` to decide whether the entry matches the key. The
|
||||
`entry_or_key` parameter points to a bogus hashmap_entry structure that
|
||||
should not be used in the comparison.
|
||||
|
||||
`void *hashmap_get_next(const struct hashmap *map, const void *entry)`::
|
||||
|
||||
Returns the next equal hashmap entry, or NULL if not found. This can be
|
||||
used to iterate over duplicate entries (see `hashmap_add`).
|
||||
+
|
||||
`map` is the hashmap structure.
|
||||
+
|
||||
`entry` is the hashmap_entry to start the search from, obtained via a previous
|
||||
call to `hashmap_get` or `hashmap_get_next`.
|
||||
|
||||
`void hashmap_add(struct hashmap *map, void *entry)`::
|
||||
|
||||
Adds a hashmap entry. This allows to add duplicate entries (i.e.
|
||||
separate values with the same key according to hashmap_cmp_fn).
|
||||
+
|
||||
`map` is the hashmap structure.
|
||||
+
|
||||
`entry` is the entry to add.
|
||||
|
||||
`void *hashmap_put(struct hashmap *map, void *entry)`::
|
||||
|
||||
Adds or replaces a hashmap entry. If the hashmap contains duplicate
|
||||
entries equal to the specified entry, only one of them will be replaced.
|
||||
+
|
||||
`map` is the hashmap structure.
|
||||
+
|
||||
`entry` is the entry to add or replace.
|
||||
+
|
||||
Returns the replaced entry, or NULL if not found (i.e. the entry was added).
|
||||
|
||||
`void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata)`::
|
||||
|
||||
Removes a hashmap entry matching the specified key. If the hashmap
|
||||
contains duplicate entries equal to the specified key, only one of
|
||||
them will be removed.
|
||||
+
|
||||
`map` is the hashmap structure.
|
||||
+
|
||||
`key` is a hashmap_entry structure (or user data structure that starts with
|
||||
hashmap_entry) that has at least been initialized with the proper hash code
|
||||
(via `hashmap_entry_init`).
|
||||
+
|
||||
If an entry with matching hash code is found, `key` and `keydata` are
|
||||
passed to `hashmap_cmp_fn` to decide whether the entry matches the key.
|
||||
+
|
||||
Returns the removed entry, or NULL if not found.
|
||||
|
||||
`void hashmap_disallow_rehash(struct hashmap *map, unsigned value)`::
|
||||
|
||||
Disallow/allow automatic rehashing of the hashmap during inserts
|
||||
and deletes.
|
||||
+
|
||||
This is useful if the caller knows that the hashmap will be accessed
|
||||
by multiple threads.
|
||||
+
|
||||
The caller is still responsible for any necessary locking; this simply
|
||||
prevents unexpected rehashing. The caller is also responsible for properly
|
||||
sizing the initial hashmap to ensure good performance.
|
||||
+
|
||||
A call to allow rehashing does not force a rehash; that might happen
|
||||
with the next insert or delete.
|
||||
|
||||
`void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter)`::
|
||||
`void *hashmap_iter_next(struct hashmap_iter *iter)`::
|
||||
`void *hashmap_iter_first(struct hashmap *map, struct hashmap_iter *iter)`::
|
||||
|
||||
Used to iterate over all entries of a hashmap. Note that it is
|
||||
not safe to add or remove entries to the hashmap while
|
||||
iterating.
|
||||
+
|
||||
`hashmap_iter_init` initializes a `hashmap_iter` structure.
|
||||
+
|
||||
`hashmap_iter_next` returns the next hashmap_entry, or NULL if there are no
|
||||
more entries.
|
||||
+
|
||||
`hashmap_iter_first` is a combination of both (i.e. initializes the iterator
|
||||
and returns the first entry, if any).
|
||||
|
||||
`const char *strintern(const char *string)`::
|
||||
`const void *memintern(const void *data, size_t len)`::
|
||||
|
||||
Returns the unique, interned version of the specified string or data,
|
||||
similar to the `String.intern` API in Java and .NET, respectively.
|
||||
Interned strings remain valid for the entire lifetime of the process.
|
||||
+
|
||||
Can be used as `[x]strdup()` or `xmemdupz` replacement, except that interned
|
||||
strings / data must not be modified or freed.
|
||||
+
|
||||
Interned strings are best used for short strings with high probability of
|
||||
duplicates.
|
||||
+
|
||||
Uses a hashmap to store the pool of interned strings.
|
||||
|
||||
Usage example
|
||||
-------------
|
||||
|
||||
Here's a simple usage example that maps long keys to double values.
|
||||
------------
|
||||
struct hashmap map;
|
||||
|
||||
struct long2double {
|
||||
struct hashmap_entry ent; /* must be the first member! */
|
||||
long key;
|
||||
double value;
|
||||
};
|
||||
|
||||
static int long2double_cmp(const struct long2double *e1, const struct long2double *e2, const void *unused)
|
||||
{
|
||||
return !(e1->key == e2->key);
|
||||
}
|
||||
|
||||
void long2double_init(void)
|
||||
{
|
||||
hashmap_init(&map, (hashmap_cmp_fn) long2double_cmp, 0);
|
||||
}
|
||||
|
||||
void long2double_free(void)
|
||||
{
|
||||
hashmap_free(&map, 1);
|
||||
}
|
||||
|
||||
static struct long2double *find_entry(long key)
|
||||
{
|
||||
struct long2double k;
|
||||
hashmap_entry_init(&k, memhash(&key, sizeof(long)));
|
||||
k.key = key;
|
||||
return hashmap_get(&map, &k, NULL);
|
||||
}
|
||||
|
||||
double get_value(long key)
|
||||
{
|
||||
struct long2double *e = find_entry(key);
|
||||
return e ? e->value : 0;
|
||||
}
|
||||
|
||||
void set_value(long key, double value)
|
||||
{
|
||||
struct long2double *e = find_entry(key);
|
||||
if (!e) {
|
||||
e = malloc(sizeof(struct long2double));
|
||||
hashmap_entry_init(e, memhash(&key, sizeof(long)));
|
||||
e->key = key;
|
||||
hashmap_add(&map, e);
|
||||
}
|
||||
e->value = value;
|
||||
}
|
||||
------------
|
||||
|
||||
Using variable-sized keys
|
||||
-------------------------
|
||||
|
||||
The `hashmap_entry_get` and `hashmap_entry_remove` functions expect an ordinary
|
||||
`hashmap_entry` structure as key to find the correct entry. If the key data is
|
||||
variable-sized (e.g. a FLEX_ARRAY string) or quite large, it is undesirable
|
||||
to create a full-fledged entry structure on the heap and copy all the key data
|
||||
into the structure.
|
||||
|
||||
In this case, the `keydata` parameter can be used to pass
|
||||
variable-sized key data directly to the comparison function, and the `key`
|
||||
parameter can be a stripped-down, fixed size entry structure allocated on the
|
||||
stack.
|
||||
|
||||
See test-hashmap.c for an example using arbitrary-length strings as keys.
|
|
@ -183,13 +183,13 @@ There are some macros to easily define options:
|
|||
scale the provided value by 1024, 1024^2 or 1024^3 respectively.
|
||||
The scaled value is put into `unsigned_long_var`.
|
||||
|
||||
`OPT_DATE(short, long, &int_var, description)`::
|
||||
`OPT_DATE(short, long, ×tamp_t_var, description)`::
|
||||
Introduce an option with date argument, see `approxidate()`.
|
||||
The timestamp is put into `int_var`.
|
||||
The timestamp is put into `timestamp_t_var`.
|
||||
|
||||
`OPT_EXPIRY_DATE(short, long, &int_var, description)`::
|
||||
`OPT_EXPIRY_DATE(short, long, ×tamp_t_var, description)`::
|
||||
Introduce an option with expiry date argument, see `parse_expiry_date()`.
|
||||
The timestamp is put into `int_var`.
|
||||
The timestamp is put into `timestamp_t_var`.
|
||||
|
||||
`OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`::
|
||||
Introduce an option with argument.
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
sub-process API
|
||||
===============
|
||||
|
||||
The sub-process API makes it possible to run background sub-processes
|
||||
for the entire lifetime of a Git invocation. If Git needs to communicate
|
||||
with an external process multiple times, then this can reduces the process
|
||||
invocation overhead. Git and the sub-process communicate through stdin and
|
||||
stdout.
|
||||
|
||||
The sub-processes are kept in a hashmap by command name and looked up
|
||||
via the subprocess_find_entry function. If an existing instance can not
|
||||
be found then a new process should be created and started. When the
|
||||
parent git command terminates, all sub-processes are also terminated.
|
||||
|
||||
This API is based on the run-command API.
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
* `struct subprocess_entry`
|
||||
|
||||
The sub-process structure. Members should not be accessed directly.
|
||||
|
||||
Types
|
||||
-----
|
||||
|
||||
'int(*subprocess_start_fn)(struct subprocess_entry *entry)'::
|
||||
|
||||
User-supplied function to initialize the sub-process. This is
|
||||
typically used to negotiate the interface version and capabilities.
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`cmd2process_cmp`::
|
||||
|
||||
Function to test two subprocess hashmap entries for equality.
|
||||
|
||||
`subprocess_start`::
|
||||
|
||||
Start a subprocess and add it to the subprocess hashmap.
|
||||
|
||||
`subprocess_stop`::
|
||||
|
||||
Kill a subprocess and remove it from the subprocess hashmap.
|
||||
|
||||
`subprocess_find_entry`::
|
||||
|
||||
Find a subprocess in the subprocess hashmap.
|
||||
|
||||
`subprocess_get_child_process`::
|
||||
|
||||
Get the underlying `struct child_process` from a subprocess.
|
||||
|
||||
`subprocess_read_status`::
|
||||
|
||||
Helper function to read packets looking for the last "status=<foo>"
|
||||
key/value pair.
|
|
@ -473,13 +473,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
|
||||
of the reference.
|
||||
|
||||
This list is followed by a flush-pkt. Then the push options are transmitted
|
||||
one per packet followed by another flush-pkt. After that the packfile that
|
||||
should contain all the objects that the server will need to complete the new
|
||||
references will be sent.
|
||||
This list is followed by a flush-pkt.
|
||||
|
||||
----
|
||||
update-request = *shallow ( command-list | push-cert ) [packfile]
|
||||
update-requests = *shallow ( command-list | push-cert )
|
||||
|
||||
shallow = PKT-LINE("shallow" SP obj-id)
|
||||
|
||||
|
@ -500,12 +497,35 @@ references will be sent.
|
|||
PKT-LINE("pusher" SP ident LF)
|
||||
PKT-LINE("pushee" SP url LF)
|
||||
PKT-LINE("nonce" SP nonce LF)
|
||||
*PKT-LINE("push-option" SP push-option LF)
|
||||
PKT-LINE(LF)
|
||||
*PKT-LINE(command LF)
|
||||
*PKT-LINE(gpg-signature-lines LF)
|
||||
PKT-LINE("push-cert-end" LF)
|
||||
|
||||
packfile = "PACK" 28*(OCTET)
|
||||
push-option = 1*( VCHAR | SP )
|
||||
----
|
||||
|
||||
If the server has advertised the 'push-options' capability and the client has
|
||||
specified 'push-options' as part of the capability list above, the client then
|
||||
sends its push options followed by a flush-pkt.
|
||||
|
||||
----
|
||||
push-options = *PKT-LINE(push-option) flush-pkt
|
||||
----
|
||||
|
||||
For backwards compatibility with older Git servers, if the client sends a push
|
||||
cert and push options, it MUST send its push options both embedded within the
|
||||
push cert and after the push cert. (Note that the push options within the cert
|
||||
are prefixed, but the push options after the cert are not.) Both these lists
|
||||
MUST be the same, modulo the prefix.
|
||||
|
||||
After that the packfile that
|
||||
should contain all the objects that the server will need to complete the new
|
||||
references will be sent.
|
||||
|
||||
----
|
||||
packfile = "PACK" 28*(OCTET)
|
||||
----
|
||||
|
||||
If the receiving end does not support delete-refs, the sending end MUST
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v2.13.0
|
||||
DEF_VER=v2.13.GIT
|
||||
|
||||
LF='
|
||||
'
|
||||
|
|
73
Makefile
73
Makefile
|
@ -19,16 +19,34 @@ all::
|
|||
# have been written to the final string if enough space had been available.
|
||||
#
|
||||
# Define FREAD_READS_DIRECTORIES if you are on a system which succeeds
|
||||
# when attempting to read from an fopen'ed directory.
|
||||
# when attempting to read from an fopen'ed directory (or even to fopen
|
||||
# it at all).
|
||||
#
|
||||
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
|
||||
# This also implies BLK_SHA1.
|
||||
#
|
||||
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
|
||||
# able to use Perl-compatible regular expressions.
|
||||
# Define USE_LIBPCRE if you have and want to use libpcre. Various
|
||||
# commands such as log and grep offer runtime options to use
|
||||
# Perl-compatible regular expressions instead of standard or extended
|
||||
# POSIX regular expressions.
|
||||
#
|
||||
# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
|
||||
# /foo/bar/include and /foo/bar/lib directories.
|
||||
# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
|
||||
# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
|
||||
# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
|
||||
# default in future releases.
|
||||
#
|
||||
# When using USE_LIBPCRE1, define NO_LIBPCRE1_JIT if the PCRE v1
|
||||
# library is compiled without --enable-jit. We will auto-detect
|
||||
# whether the version of the PCRE v1 library in use has JIT support at
|
||||
# all, but we unfortunately can't auto-detect whether JIT support
|
||||
# hasn't been compiled in in an otherwise JIT-supporting version. If
|
||||
# you have link-time errors about a missing `pcre_jit_exec` define
|
||||
# this, or recompile PCRE v1 with --enable-jit.
|
||||
#
|
||||
# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are
|
||||
# in /foo/bar/include and /foo/bar/lib directories. Which version of
|
||||
# PCRE this points to determined by the USE_LIBPCRE1 and USE_LIBPCRE2
|
||||
# variables.
|
||||
#
|
||||
# Define HAVE_ALLOCA_H if you have working alloca(3) defined in that header.
|
||||
#
|
||||
|
@ -718,6 +736,7 @@ LIB_OBJS += argv-array.o
|
|||
LIB_OBJS += attr.o
|
||||
LIB_OBJS += base85.o
|
||||
LIB_OBJS += bisect.o
|
||||
LIB_OBJS += blame.o
|
||||
LIB_OBJS += blob.o
|
||||
LIB_OBJS += branch.o
|
||||
LIB_OBJS += bulk-checkin.o
|
||||
|
@ -842,6 +861,7 @@ LIB_OBJS += streaming.o
|
|||
LIB_OBJS += string-list.o
|
||||
LIB_OBJS += submodule.o
|
||||
LIB_OBJS += submodule-config.o
|
||||
LIB_OBJS += sub-process.o
|
||||
LIB_OBJS += symlinks.o
|
||||
LIB_OBJS += tag.o
|
||||
LIB_OBJS += tempfile.o
|
||||
|
@ -1085,13 +1105,29 @@ ifdef NO_LIBGEN_H
|
|||
COMPAT_OBJS += compat/basename.o
|
||||
endif
|
||||
|
||||
ifdef USE_LIBPCRE
|
||||
BASIC_CFLAGS += -DUSE_LIBPCRE
|
||||
ifdef LIBPCREDIR
|
||||
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
|
||||
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
|
||||
USE_LIBPCRE1 ?= $(USE_LIBPCRE)
|
||||
|
||||
ifneq (,$(USE_LIBPCRE1))
|
||||
ifdef USE_LIBPCRE2
|
||||
$(error Only set USE_LIBPCRE1 (or its alias USE_LIBPCRE) or USE_LIBPCRE2, not both!)
|
||||
endif
|
||||
|
||||
BASIC_CFLAGS += -DUSE_LIBPCRE1
|
||||
EXTLIBS += -lpcre
|
||||
|
||||
ifdef NO_LIBPCRE1_JIT
|
||||
BASIC_CFLAGS += -DNO_LIBPCRE1_JIT
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef USE_LIBPCRE2
|
||||
BASIC_CFLAGS += -DUSE_LIBPCRE2
|
||||
EXTLIBS += -lpcre2-8
|
||||
endif
|
||||
|
||||
ifdef LIBPCREDIR
|
||||
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
|
||||
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
|
||||
endif
|
||||
|
||||
ifdef HAVE_ALLOCA_H
|
||||
|
@ -1414,7 +1450,14 @@ else
|
|||
DC_SHA1 := YesPlease
|
||||
LIB_OBJS += sha1dc/sha1.o
|
||||
LIB_OBJS += sha1dc/ubc_check.o
|
||||
BASIC_CFLAGS += -DSHA1_DC
|
||||
BASIC_CFLAGS += \
|
||||
-DSHA1_DC \
|
||||
-DSHA1DC_NO_STANDARD_INCLUDES \
|
||||
-DSHA1DC_INIT_SAFE_HASH_DEFAULT=0 \
|
||||
-DSHA1DC_CUSTOM_INCLUDE_SHA1_C="\"cache.h\"" \
|
||||
-DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C="\"sha1dc_git.c\"" \
|
||||
-DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H="\"sha1dc_git.h\"" \
|
||||
-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="\"git-compat-util.h\""
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -2238,8 +2281,11 @@ GIT-BUILD-OPTIONS: FORCE
|
|||
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+
|
||||
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+
|
||||
@echo NO_EXPAT=\''$(subst ','\'',$(subst ','\'',$(NO_EXPAT)))'\' >>$@+
|
||||
@echo USE_LIBPCRE=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
|
||||
@echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE1)))'\' >>$@+
|
||||
@echo USE_LIBPCRE2=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE2)))'\' >>$@+
|
||||
@echo NO_LIBPCRE1_JIT=\''$(subst ','\'',$(subst ','\'',$(NO_LIBPCRE1_JIT)))'\' >>$@+
|
||||
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
|
||||
@echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
|
||||
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
|
||||
@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
|
||||
@echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+
|
||||
|
@ -2270,6 +2316,9 @@ endif
|
|||
ifdef GIT_PERF_MAKE_OPTS
|
||||
@echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@+
|
||||
endif
|
||||
ifdef GIT_PERF_MAKE_COMMAND
|
||||
@echo GIT_PERF_MAKE_COMMAND=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_COMMAND)))'\' >>$@+
|
||||
endif
|
||||
ifdef GIT_INTEROP_MAKE_OPTS
|
||||
@echo GIT_INTEROP_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_INTEROP_MAKE_OPTS)))'\' >>$@+
|
||||
endif
|
||||
|
|
3
advice.c
3
advice.c
|
@ -1,4 +1,5 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
|
||||
int advice_push_update_rejected = 1;
|
||||
int advice_push_non_ff_current = 1;
|
||||
|
@ -15,6 +16,7 @@ int advice_detached_head = 1;
|
|||
int advice_set_upstream_failure = 1;
|
||||
int advice_object_name_warning = 1;
|
||||
int advice_rm_hints = 1;
|
||||
int advice_add_embedded_repo = 1;
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
|
@ -35,6 +37,7 @@ static struct {
|
|||
{ "setupstreamfailure", &advice_set_upstream_failure },
|
||||
{ "objectnamewarning", &advice_object_name_warning },
|
||||
{ "rmhints", &advice_rm_hints },
|
||||
{ "addembeddedrepo", &advice_add_embedded_repo },
|
||||
|
||||
/* make this an alias for backward compatibility */
|
||||
{ "pushnonfastforward", &advice_push_update_rejected }
|
||||
|
|
1
advice.h
1
advice.h
|
@ -18,6 +18,7 @@ extern int advice_detached_head;
|
|||
extern int advice_set_upstream_failure;
|
||||
extern int advice_object_name_warning;
|
||||
extern int advice_rm_hints;
|
||||
extern int advice_add_embedded_repo;
|
||||
|
||||
int git_default_advice_config(const char *var, const char *value);
|
||||
__attribute__((format (printf, 1, 2)))
|
||||
|
|
35
alias.c
35
alias.c
|
@ -1,14 +1,29 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
|
||||
struct config_alias_data {
|
||||
const char *alias;
|
||||
char *v;
|
||||
};
|
||||
|
||||
static int config_alias_cb(const char *key, const char *value, void *d)
|
||||
{
|
||||
struct config_alias_data *data = d;
|
||||
const char *p;
|
||||
|
||||
if (skip_prefix(key, "alias.", &p) && !strcmp(p, data->alias))
|
||||
return git_config_string((const char **)&data->v, key, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *alias_lookup(const char *alias)
|
||||
{
|
||||
char *v = NULL;
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
strbuf_addf(&key, "alias.%s", alias);
|
||||
if (git_config_key_is_valid(key.buf))
|
||||
git_config_get_string(key.buf, &v);
|
||||
strbuf_release(&key);
|
||||
return v;
|
||||
struct config_alias_data data = { alias, NULL };
|
||||
|
||||
read_early_config(config_alias_cb, &data);
|
||||
|
||||
return data.v;
|
||||
}
|
||||
|
||||
#define SPLIT_CMDLINE_BAD_ENDING 1
|
||||
|
@ -47,8 +62,7 @@ int split_cmdline(char *cmdline, const char ***argv)
|
|||
src++;
|
||||
c = cmdline[src];
|
||||
if (!c) {
|
||||
free(*argv);
|
||||
*argv = NULL;
|
||||
FREE_AND_NULL(*argv);
|
||||
return -SPLIT_CMDLINE_BAD_ENDING;
|
||||
}
|
||||
}
|
||||
|
@ -60,8 +74,7 @@ int split_cmdline(char *cmdline, const char ***argv)
|
|||
cmdline[dst] = 0;
|
||||
|
||||
if (quoted) {
|
||||
free(*argv);
|
||||
*argv = NULL;
|
||||
FREE_AND_NULL(*argv);
|
||||
return -SPLIT_CMDLINE_UNCLOSED_QUOTE;
|
||||
}
|
||||
|
||||
|
|
331
apply.c
331
apply.c
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "blob.h"
|
||||
#include "delta.h"
|
||||
#include "diff.h"
|
||||
|
@ -762,17 +763,6 @@ static char *find_name_traditional(struct apply_state *state,
|
|||
return find_name_common(state, line, def, p_value, line + len, 0);
|
||||
}
|
||||
|
||||
static int count_slashes(const char *cp)
|
||||
{
|
||||
int cnt = 0;
|
||||
char ch;
|
||||
|
||||
while ((ch = *cp++))
|
||||
if (ch == '/')
|
||||
cnt++;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the string after "--- " or "+++ ", guess the appropriate
|
||||
* p_value for the given patch.
|
||||
|
@ -2267,7 +2257,7 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
|
|||
case S_IFREG:
|
||||
if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
|
||||
return error(_("unable to open or read %s"), path);
|
||||
convert_to_git(path, buf->buf, buf->len, buf, 0);
|
||||
convert_to_git(&the_index, path, buf->buf, buf->len, buf, 0);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
|
@ -3705,8 +3695,7 @@ static int check_preimage(struct apply_state *state,
|
|||
is_new:
|
||||
patch->is_new = 1;
|
||||
patch->is_delete = 0;
|
||||
free(patch->old_name);
|
||||
patch->old_name = NULL;
|
||||
FREE_AND_NULL(patch->old_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3741,7 +3730,7 @@ static int check_to_create(struct apply_state *state,
|
|||
return 0;
|
||||
|
||||
return EXISTS_IN_WORKTREE;
|
||||
} else if ((errno != ENOENT) && (errno != ENOTDIR)) {
|
||||
} else if (!is_missing_file_error(errno)) {
|
||||
return error_errno("%s", new_name);
|
||||
}
|
||||
return 0;
|
||||
|
@ -4091,181 +4080,181 @@ static int build_fake_ancestor(struct apply_state *state, struct patch *list)
|
|||
res = write_locked_index(&result, &lock, COMMIT_LOCK);
|
||||
discard_index(&result);
|
||||
|
||||
if (res)
|
||||
return error(_("could not write temporary index to %s"),
|
||||
state->fake_ancestor);
|
||||
if (res)
|
||||
return error(_("could not write temporary index to %s"),
|
||||
state->fake_ancestor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stat_patch_list(struct apply_state *state, struct patch *patch)
|
||||
{
|
||||
int files, adds, dels;
|
||||
static void stat_patch_list(struct apply_state *state, struct patch *patch)
|
||||
{
|
||||
int files, adds, dels;
|
||||
|
||||
for (files = adds = dels = 0 ; patch ; patch = patch->next) {
|
||||
files++;
|
||||
adds += patch->lines_added;
|
||||
dels += patch->lines_deleted;
|
||||
show_stats(state, patch);
|
||||
}
|
||||
for (files = adds = dels = 0 ; patch ; patch = patch->next) {
|
||||
files++;
|
||||
adds += patch->lines_added;
|
||||
dels += patch->lines_deleted;
|
||||
show_stats(state, patch);
|
||||
}
|
||||
|
||||
print_stat_summary(stdout, files, adds, dels);
|
||||
}
|
||||
print_stat_summary(stdout, files, adds, dels);
|
||||
}
|
||||
|
||||
static void numstat_patch_list(struct apply_state *state,
|
||||
struct patch *patch)
|
||||
{
|
||||
for ( ; patch; patch = patch->next) {
|
||||
const char *name;
|
||||
name = patch->new_name ? patch->new_name : patch->old_name;
|
||||
if (patch->is_binary)
|
||||
printf("-\t-\t");
|
||||
else
|
||||
printf("%d\t%d\t", patch->lines_added, patch->lines_deleted);
|
||||
write_name_quoted(name, stdout, state->line_termination);
|
||||
}
|
||||
}
|
||||
static void numstat_patch_list(struct apply_state *state,
|
||||
struct patch *patch)
|
||||
{
|
||||
for ( ; patch; patch = patch->next) {
|
||||
const char *name;
|
||||
name = patch->new_name ? patch->new_name : patch->old_name;
|
||||
if (patch->is_binary)
|
||||
printf("-\t-\t");
|
||||
else
|
||||
printf("%d\t%d\t", patch->lines_added, patch->lines_deleted);
|
||||
write_name_quoted(name, stdout, state->line_termination);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_file_mode_name(const char *newdelete, unsigned int mode, const char *name)
|
||||
{
|
||||
if (mode)
|
||||
printf(" %s mode %06o %s\n", newdelete, mode, name);
|
||||
else
|
||||
printf(" %s %s\n", newdelete, name);
|
||||
}
|
||||
static void show_file_mode_name(const char *newdelete, unsigned int mode, const char *name)
|
||||
{
|
||||
if (mode)
|
||||
printf(" %s mode %06o %s\n", newdelete, mode, name);
|
||||
else
|
||||
printf(" %s %s\n", newdelete, name);
|
||||
}
|
||||
|
||||
static void show_mode_change(struct patch *p, int show_name)
|
||||
{
|
||||
if (p->old_mode && p->new_mode && p->old_mode != p->new_mode) {
|
||||
if (show_name)
|
||||
printf(" mode change %06o => %06o %s\n",
|
||||
p->old_mode, p->new_mode, p->new_name);
|
||||
else
|
||||
printf(" mode change %06o => %06o\n",
|
||||
p->old_mode, p->new_mode);
|
||||
}
|
||||
}
|
||||
static void show_mode_change(struct patch *p, int show_name)
|
||||
{
|
||||
if (p->old_mode && p->new_mode && p->old_mode != p->new_mode) {
|
||||
if (show_name)
|
||||
printf(" mode change %06o => %06o %s\n",
|
||||
p->old_mode, p->new_mode, p->new_name);
|
||||
else
|
||||
printf(" mode change %06o => %06o\n",
|
||||
p->old_mode, p->new_mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_rename_copy(struct patch *p)
|
||||
{
|
||||
const char *renamecopy = p->is_rename ? "rename" : "copy";
|
||||
const char *old, *new;
|
||||
static void show_rename_copy(struct patch *p)
|
||||
{
|
||||
const char *renamecopy = p->is_rename ? "rename" : "copy";
|
||||
const char *old, *new;
|
||||
|
||||
/* Find common prefix */
|
||||
old = p->old_name;
|
||||
new = p->new_name;
|
||||
while (1) {
|
||||
const char *slash_old, *slash_new;
|
||||
slash_old = strchr(old, '/');
|
||||
slash_new = strchr(new, '/');
|
||||
if (!slash_old ||
|
||||
!slash_new ||
|
||||
slash_old - old != slash_new - new ||
|
||||
memcmp(old, new, slash_new - new))
|
||||
break;
|
||||
old = slash_old + 1;
|
||||
new = slash_new + 1;
|
||||
}
|
||||
/* p->old_name thru old is the common prefix, and old and new
|
||||
* through the end of names are renames
|
||||
*/
|
||||
if (old != p->old_name)
|
||||
printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy,
|
||||
(int)(old - p->old_name), p->old_name,
|
||||
old, new, p->score);
|
||||
else
|
||||
printf(" %s %s => %s (%d%%)\n", renamecopy,
|
||||
p->old_name, p->new_name, p->score);
|
||||
show_mode_change(p, 0);
|
||||
}
|
||||
/* Find common prefix */
|
||||
old = p->old_name;
|
||||
new = p->new_name;
|
||||
while (1) {
|
||||
const char *slash_old, *slash_new;
|
||||
slash_old = strchr(old, '/');
|
||||
slash_new = strchr(new, '/');
|
||||
if (!slash_old ||
|
||||
!slash_new ||
|
||||
slash_old - old != slash_new - new ||
|
||||
memcmp(old, new, slash_new - new))
|
||||
break;
|
||||
old = slash_old + 1;
|
||||
new = slash_new + 1;
|
||||
}
|
||||
/* p->old_name thru old is the common prefix, and old and new
|
||||
* through the end of names are renames
|
||||
*/
|
||||
if (old != p->old_name)
|
||||
printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy,
|
||||
(int)(old - p->old_name), p->old_name,
|
||||
old, new, p->score);
|
||||
else
|
||||
printf(" %s %s => %s (%d%%)\n", renamecopy,
|
||||
p->old_name, p->new_name, p->score);
|
||||
show_mode_change(p, 0);
|
||||
}
|
||||
|
||||
static void summary_patch_list(struct patch *patch)
|
||||
{
|
||||
struct patch *p;
|
||||
static void summary_patch_list(struct patch *patch)
|
||||
{
|
||||
struct patch *p;
|
||||
|
||||
for (p = patch; p; p = p->next) {
|
||||
if (p->is_new)
|
||||
show_file_mode_name("create", p->new_mode, p->new_name);
|
||||
else if (p->is_delete)
|
||||
show_file_mode_name("delete", p->old_mode, p->old_name);
|
||||
else {
|
||||
if (p->is_rename || p->is_copy)
|
||||
show_rename_copy(p);
|
||||
else {
|
||||
if (p->score) {
|
||||
printf(" rewrite %s (%d%%)\n",
|
||||
p->new_name, p->score);
|
||||
show_mode_change(p, 0);
|
||||
}
|
||||
else
|
||||
show_mode_change(p, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (p = patch; p; p = p->next) {
|
||||
if (p->is_new)
|
||||
show_file_mode_name("create", p->new_mode, p->new_name);
|
||||
else if (p->is_delete)
|
||||
show_file_mode_name("delete", p->old_mode, p->old_name);
|
||||
else {
|
||||
if (p->is_rename || p->is_copy)
|
||||
show_rename_copy(p);
|
||||
else {
|
||||
if (p->score) {
|
||||
printf(" rewrite %s (%d%%)\n",
|
||||
p->new_name, p->score);
|
||||
show_mode_change(p, 0);
|
||||
}
|
||||
else
|
||||
show_mode_change(p, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void patch_stats(struct apply_state *state, struct patch *patch)
|
||||
{
|
||||
int lines = patch->lines_added + patch->lines_deleted;
|
||||
static void patch_stats(struct apply_state *state, struct patch *patch)
|
||||
{
|
||||
int lines = patch->lines_added + patch->lines_deleted;
|
||||
|
||||
if (lines > state->max_change)
|
||||
state->max_change = lines;
|
||||
if (patch->old_name) {
|
||||
int len = quote_c_style(patch->old_name, NULL, NULL, 0);
|
||||
if (!len)
|
||||
len = strlen(patch->old_name);
|
||||
if (len > state->max_len)
|
||||
state->max_len = len;
|
||||
}
|
||||
if (patch->new_name) {
|
||||
int len = quote_c_style(patch->new_name, NULL, NULL, 0);
|
||||
if (!len)
|
||||
len = strlen(patch->new_name);
|
||||
if (len > state->max_len)
|
||||
state->max_len = len;
|
||||
}
|
||||
}
|
||||
if (lines > state->max_change)
|
||||
state->max_change = lines;
|
||||
if (patch->old_name) {
|
||||
int len = quote_c_style(patch->old_name, NULL, NULL, 0);
|
||||
if (!len)
|
||||
len = strlen(patch->old_name);
|
||||
if (len > state->max_len)
|
||||
state->max_len = len;
|
||||
}
|
||||
if (patch->new_name) {
|
||||
int len = quote_c_style(patch->new_name, NULL, NULL, 0);
|
||||
if (!len)
|
||||
len = strlen(patch->new_name);
|
||||
if (len > state->max_len)
|
||||
state->max_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty)
|
||||
{
|
||||
if (state->update_index) {
|
||||
if (remove_file_from_cache(patch->old_name) < 0)
|
||||
return error(_("unable to remove %s from index"), patch->old_name);
|
||||
}
|
||||
if (!state->cached) {
|
||||
if (!remove_or_warn(patch->old_mode, patch->old_name) && rmdir_empty) {
|
||||
remove_path(patch->old_name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty)
|
||||
{
|
||||
if (state->update_index) {
|
||||
if (remove_file_from_cache(patch->old_name) < 0)
|
||||
return error(_("unable to remove %s from index"), patch->old_name);
|
||||
}
|
||||
if (!state->cached) {
|
||||
if (!remove_or_warn(patch->old_mode, patch->old_name) && rmdir_empty) {
|
||||
remove_path(patch->old_name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_index_file(struct apply_state *state,
|
||||
const char *path,
|
||||
unsigned mode,
|
||||
void *buf,
|
||||
unsigned long size)
|
||||
{
|
||||
struct stat st;
|
||||
struct cache_entry *ce;
|
||||
int namelen = strlen(path);
|
||||
unsigned ce_size = cache_entry_size(namelen);
|
||||
static int add_index_file(struct apply_state *state,
|
||||
const char *path,
|
||||
unsigned mode,
|
||||
void *buf,
|
||||
unsigned long size)
|
||||
{
|
||||
struct stat st;
|
||||
struct cache_entry *ce;
|
||||
int namelen = strlen(path);
|
||||
unsigned ce_size = cache_entry_size(namelen);
|
||||
|
||||
if (!state->update_index)
|
||||
return 0;
|
||||
if (!state->update_index)
|
||||
return 0;
|
||||
|
||||
ce = xcalloc(1, ce_size);
|
||||
memcpy(ce->name, path, namelen);
|
||||
ce->ce_mode = create_ce_mode(mode);
|
||||
ce->ce_flags = create_ce_flags(0);
|
||||
ce->ce_namelen = namelen;
|
||||
if (S_ISGITLINK(mode)) {
|
||||
const char *s;
|
||||
ce = xcalloc(1, ce_size);
|
||||
memcpy(ce->name, path, namelen);
|
||||
ce->ce_mode = create_ce_mode(mode);
|
||||
ce->ce_flags = create_ce_flags(0);
|
||||
ce->ce_namelen = namelen;
|
||||
if (S_ISGITLINK(mode)) {
|
||||
const char *s;
|
||||
|
||||
if (!skip_prefix(buf, "Subproject commit ", &s) ||
|
||||
get_oid_hex(s, &ce->oid)) {
|
||||
if (!skip_prefix(buf, "Subproject commit ", &s) ||
|
||||
get_oid_hex(s, &ce->oid)) {
|
||||
free(ce);
|
||||
return error(_("corrupt patch for submodule %s"), path);
|
||||
return error(_("corrupt patch for submodule %s"), path);
|
||||
}
|
||||
} else {
|
||||
if (!state->cached) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2005, 2006 Rene Scharfe
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "tar.h"
|
||||
#include "archive.h"
|
||||
#include "streaming.h"
|
||||
|
@ -27,10 +28,13 @@ static int write_tar_filter_archive(const struct archiver *ar,
|
|||
*/
|
||||
#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
|
||||
#if TIME_MAX == 0xFFFFFFFF
|
||||
#define USTAR_MAX_MTIME TIME_MAX
|
||||
#else
|
||||
#define USTAR_MAX_MTIME 077777777777ULL
|
||||
#endif
|
||||
|
||||
/* writes out the whole block, but only if it is full */
|
||||
|
|
228
archive-zip.c
228
archive-zip.c
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2006 Rene Scharfe
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "archive.h"
|
||||
#include "streaming.h"
|
||||
#include "utf8.h"
|
||||
|
@ -11,16 +12,14 @@
|
|||
static int zip_date;
|
||||
static int zip_time;
|
||||
|
||||
static unsigned char *zip_dir;
|
||||
static unsigned int zip_dir_size;
|
||||
/* We only care about the "buf" part here. */
|
||||
static struct strbuf zip_dir;
|
||||
|
||||
static unsigned int zip_offset;
|
||||
static unsigned int zip_dir_offset;
|
||||
static uintmax_t zip_offset;
|
||||
static uint64_t zip_dir_entries;
|
||||
|
||||
static unsigned int max_creator_version;
|
||||
|
||||
#define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
|
||||
#define ZIP_STREAM (1 << 3)
|
||||
#define ZIP_UTF8 (1 << 11)
|
||||
|
||||
|
@ -47,24 +46,11 @@ struct zip_data_desc {
|
|||
unsigned char _end[1];
|
||||
};
|
||||
|
||||
struct zip_dir_header {
|
||||
struct zip64_data_desc {
|
||||
unsigned char magic[4];
|
||||
unsigned char creator_version[2];
|
||||
unsigned char version[2];
|
||||
unsigned char flags[2];
|
||||
unsigned char compression_method[2];
|
||||
unsigned char mtime[2];
|
||||
unsigned char mdate[2];
|
||||
unsigned char crc32[4];
|
||||
unsigned char compressed_size[4];
|
||||
unsigned char size[4];
|
||||
unsigned char filename_length[2];
|
||||
unsigned char extra_length[2];
|
||||
unsigned char comment_length[2];
|
||||
unsigned char disk[2];
|
||||
unsigned char attr1[2];
|
||||
unsigned char attr2[4];
|
||||
unsigned char offset[4];
|
||||
unsigned char compressed_size[8];
|
||||
unsigned char size[8];
|
||||
unsigned char _end[1];
|
||||
};
|
||||
|
||||
|
@ -88,6 +74,14 @@ struct zip_extra_mtime {
|
|||
unsigned char _end[1];
|
||||
};
|
||||
|
||||
struct zip64_extra {
|
||||
unsigned char magic[2];
|
||||
unsigned char extra_size[2];
|
||||
unsigned char size[8];
|
||||
unsigned char compressed_size[8];
|
||||
unsigned char _end[1];
|
||||
};
|
||||
|
||||
struct zip64_dir_trailer {
|
||||
unsigned char magic[4];
|
||||
unsigned char record_size[8];
|
||||
|
@ -117,11 +111,15 @@ struct zip64_dir_trailer_locator {
|
|||
*/
|
||||
#define ZIP_LOCAL_HEADER_SIZE offsetof(struct zip_local_header, _end)
|
||||
#define ZIP_DATA_DESC_SIZE offsetof(struct zip_data_desc, _end)
|
||||
#define ZIP64_DATA_DESC_SIZE offsetof(struct zip64_data_desc, _end)
|
||||
#define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
|
||||
#define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
|
||||
#define ZIP_EXTRA_MTIME_SIZE offsetof(struct zip_extra_mtime, _end)
|
||||
#define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
|
||||
(ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
|
||||
#define ZIP64_EXTRA_SIZE offsetof(struct zip64_extra, _end)
|
||||
#define ZIP64_EXTRA_PAYLOAD_SIZE \
|
||||
(ZIP64_EXTRA_SIZE - offsetof(struct zip64_extra, size))
|
||||
#define ZIP64_DIR_TRAILER_SIZE offsetof(struct zip64_dir_trailer, _end)
|
||||
#define ZIP64_DIR_TRAILER_RECORD_SIZE \
|
||||
(ZIP64_DIR_TRAILER_SIZE - \
|
||||
|
@ -168,6 +166,26 @@ static void copy_le16_clamp(unsigned char *dest, uint64_t n, int *clamped)
|
|||
copy_le16(dest, clamp_max(n, 0xffff, clamped));
|
||||
}
|
||||
|
||||
static void copy_le32_clamp(unsigned char *dest, uint64_t n, int *clamped)
|
||||
{
|
||||
copy_le32(dest, clamp_max(n, 0xffffffff, clamped));
|
||||
}
|
||||
|
||||
static int strbuf_add_le(struct strbuf *sb, size_t size, uintmax_t n)
|
||||
{
|
||||
while (size-- > 0) {
|
||||
strbuf_addch(sb, n & 0xff);
|
||||
n >>= 8;
|
||||
}
|
||||
return -!!n;
|
||||
}
|
||||
|
||||
static uint32_t clamp32(uintmax_t n)
|
||||
{
|
||||
const uintmax_t max = 0xffffffff;
|
||||
return (n < max) ? n : max;
|
||||
}
|
||||
|
||||
static void *zlib_deflate_raw(void *data, unsigned long size,
|
||||
int compression_level,
|
||||
unsigned long *compressed_size)
|
||||
|
@ -205,23 +223,23 @@ static void write_zip_data_desc(unsigned long size,
|
|||
unsigned long compressed_size,
|
||||
unsigned long crc)
|
||||
{
|
||||
struct zip_data_desc trailer;
|
||||
|
||||
copy_le32(trailer.magic, 0x08074b50);
|
||||
copy_le32(trailer.crc32, crc);
|
||||
copy_le32(trailer.compressed_size, compressed_size);
|
||||
copy_le32(trailer.size, size);
|
||||
write_or_die(1, &trailer, ZIP_DATA_DESC_SIZE);
|
||||
}
|
||||
|
||||
static void set_zip_dir_data_desc(struct zip_dir_header *header,
|
||||
unsigned long size,
|
||||
unsigned long compressed_size,
|
||||
unsigned long crc)
|
||||
{
|
||||
copy_le32(header->crc32, crc);
|
||||
copy_le32(header->compressed_size, compressed_size);
|
||||
copy_le32(header->size, size);
|
||||
if (size >= 0xffffffff || compressed_size >= 0xffffffff) {
|
||||
struct zip64_data_desc trailer;
|
||||
copy_le32(trailer.magic, 0x08074b50);
|
||||
copy_le32(trailer.crc32, crc);
|
||||
copy_le64(trailer.compressed_size, compressed_size);
|
||||
copy_le64(trailer.size, size);
|
||||
write_or_die(1, &trailer, ZIP64_DATA_DESC_SIZE);
|
||||
zip_offset += ZIP64_DATA_DESC_SIZE;
|
||||
} else {
|
||||
struct zip_data_desc trailer;
|
||||
copy_le32(trailer.magic, 0x08074b50);
|
||||
copy_le32(trailer.crc32, crc);
|
||||
copy_le32(trailer.compressed_size, compressed_size);
|
||||
copy_le32(trailer.size, size);
|
||||
write_or_die(1, &trailer, ZIP_DATA_DESC_SIZE);
|
||||
zip_offset += ZIP_DATA_DESC_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_zip_header_data_desc(struct zip_local_header *header,
|
||||
|
@ -263,12 +281,14 @@ static int write_zip_entry(struct archiver_args *args,
|
|||
unsigned int mode)
|
||||
{
|
||||
struct zip_local_header header;
|
||||
struct zip_dir_header dirent;
|
||||
uintmax_t offset = zip_offset;
|
||||
struct zip_extra_mtime extra;
|
||||
struct zip64_extra extra64;
|
||||
size_t header_extra_size = ZIP_EXTRA_MTIME_SIZE;
|
||||
int need_zip64_extra = 0;
|
||||
unsigned long attr2;
|
||||
unsigned long compressed_size;
|
||||
unsigned long crc;
|
||||
unsigned long direntsize;
|
||||
int method;
|
||||
unsigned char *out;
|
||||
void *deflated = NULL;
|
||||
|
@ -279,6 +299,9 @@ static int write_zip_entry(struct archiver_args *args,
|
|||
int is_binary = -1;
|
||||
const char *path_without_prefix = path + args->baselen;
|
||||
unsigned int creator_version = 0;
|
||||
unsigned int version_needed = 10;
|
||||
size_t zip_dir_extra_size = ZIP_EXTRA_MTIME_SIZE;
|
||||
size_t zip64_dir_extra_payload_size = 0;
|
||||
|
||||
crc = crc32(0, NULL, 0);
|
||||
|
||||
|
@ -356,43 +379,43 @@ static int write_zip_entry(struct archiver_args *args,
|
|||
extra.flags[0] = 1; /* just mtime */
|
||||
copy_le32(extra.mtime, args->time);
|
||||
|
||||
/* make sure we have enough free space in the dictionary */
|
||||
direntsize = ZIP_DIR_HEADER_SIZE + pathlen + ZIP_EXTRA_MTIME_SIZE;
|
||||
while (zip_dir_size < zip_dir_offset + direntsize) {
|
||||
zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
|
||||
zip_dir = xrealloc(zip_dir, zip_dir_size);
|
||||
}
|
||||
if (size > 0xffffffff || compressed_size > 0xffffffff)
|
||||
need_zip64_extra = 1;
|
||||
if (stream && size > 0x7fffffff)
|
||||
need_zip64_extra = 1;
|
||||
|
||||
copy_le32(dirent.magic, 0x02014b50);
|
||||
copy_le16(dirent.creator_version, creator_version);
|
||||
copy_le16(dirent.version, 10);
|
||||
copy_le16(dirent.flags, flags);
|
||||
copy_le16(dirent.compression_method, method);
|
||||
copy_le16(dirent.mtime, zip_time);
|
||||
copy_le16(dirent.mdate, zip_date);
|
||||
set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
|
||||
copy_le16(dirent.filename_length, pathlen);
|
||||
copy_le16(dirent.extra_length, ZIP_EXTRA_MTIME_SIZE);
|
||||
copy_le16(dirent.comment_length, 0);
|
||||
copy_le16(dirent.disk, 0);
|
||||
copy_le32(dirent.attr2, attr2);
|
||||
copy_le32(dirent.offset, zip_offset);
|
||||
if (need_zip64_extra)
|
||||
version_needed = 45;
|
||||
|
||||
copy_le32(header.magic, 0x04034b50);
|
||||
copy_le16(header.version, 10);
|
||||
copy_le16(header.version, version_needed);
|
||||
copy_le16(header.flags, flags);
|
||||
copy_le16(header.compression_method, method);
|
||||
copy_le16(header.mtime, zip_time);
|
||||
copy_le16(header.mdate, zip_date);
|
||||
set_zip_header_data_desc(&header, size, compressed_size, crc);
|
||||
if (need_zip64_extra) {
|
||||
set_zip_header_data_desc(&header, 0xffffffff, 0xffffffff, crc);
|
||||
header_extra_size += ZIP64_EXTRA_SIZE;
|
||||
} else {
|
||||
set_zip_header_data_desc(&header, size, compressed_size, crc);
|
||||
}
|
||||
copy_le16(header.filename_length, pathlen);
|
||||
copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE);
|
||||
copy_le16(header.extra_length, header_extra_size);
|
||||
write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
|
||||
zip_offset += ZIP_LOCAL_HEADER_SIZE;
|
||||
write_or_die(1, path, pathlen);
|
||||
zip_offset += pathlen;
|
||||
write_or_die(1, &extra, ZIP_EXTRA_MTIME_SIZE);
|
||||
zip_offset += ZIP_EXTRA_MTIME_SIZE;
|
||||
if (need_zip64_extra) {
|
||||
copy_le16(extra64.magic, 0x0001);
|
||||
copy_le16(extra64.extra_size, ZIP64_EXTRA_PAYLOAD_SIZE);
|
||||
copy_le64(extra64.size, size);
|
||||
copy_le64(extra64.compressed_size, compressed_size);
|
||||
write_or_die(1, &extra64, ZIP64_EXTRA_SIZE);
|
||||
zip_offset += ZIP64_EXTRA_SIZE;
|
||||
}
|
||||
|
||||
if (stream && method == 0) {
|
||||
unsigned char buf[STREAM_BUFFER_SIZE];
|
||||
ssize_t readlen;
|
||||
|
@ -415,9 +438,6 @@ static int write_zip_entry(struct archiver_args *args,
|
|||
zip_offset += compressed_size;
|
||||
|
||||
write_zip_data_desc(size, compressed_size, crc);
|
||||
zip_offset += ZIP_DATA_DESC_SIZE;
|
||||
|
||||
set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
|
||||
} else if (stream && method == 8) {
|
||||
unsigned char buf[STREAM_BUFFER_SIZE];
|
||||
ssize_t readlen;
|
||||
|
@ -473,9 +493,6 @@ static int write_zip_entry(struct archiver_args *args,
|
|||
zip_offset += compressed_size;
|
||||
|
||||
write_zip_data_desc(size, compressed_size, crc);
|
||||
zip_offset += ZIP_DATA_DESC_SIZE;
|
||||
|
||||
set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
|
||||
} else if (compressed_size > 0) {
|
||||
write_or_die(1, out, compressed_size);
|
||||
zip_offset += compressed_size;
|
||||
|
@ -484,14 +501,46 @@ static int write_zip_entry(struct archiver_args *args,
|
|||
free(deflated);
|
||||
free(buffer);
|
||||
|
||||
copy_le16(dirent.attr1, !is_binary);
|
||||
if (compressed_size > 0xffffffff || size > 0xffffffff ||
|
||||
offset > 0xffffffff) {
|
||||
if (compressed_size >= 0xffffffff)
|
||||
zip64_dir_extra_payload_size += 8;
|
||||
if (size >= 0xffffffff)
|
||||
zip64_dir_extra_payload_size += 8;
|
||||
if (offset >= 0xffffffff)
|
||||
zip64_dir_extra_payload_size += 8;
|
||||
zip_dir_extra_size += 2 + 2 + zip64_dir_extra_payload_size;
|
||||
}
|
||||
|
||||
memcpy(zip_dir + zip_dir_offset, &dirent, ZIP_DIR_HEADER_SIZE);
|
||||
zip_dir_offset += ZIP_DIR_HEADER_SIZE;
|
||||
memcpy(zip_dir + zip_dir_offset, path, pathlen);
|
||||
zip_dir_offset += pathlen;
|
||||
memcpy(zip_dir + zip_dir_offset, &extra, ZIP_EXTRA_MTIME_SIZE);
|
||||
zip_dir_offset += ZIP_EXTRA_MTIME_SIZE;
|
||||
strbuf_add_le(&zip_dir, 4, 0x02014b50); /* magic */
|
||||
strbuf_add_le(&zip_dir, 2, creator_version);
|
||||
strbuf_add_le(&zip_dir, 2, version_needed);
|
||||
strbuf_add_le(&zip_dir, 2, flags);
|
||||
strbuf_add_le(&zip_dir, 2, method);
|
||||
strbuf_add_le(&zip_dir, 2, zip_time);
|
||||
strbuf_add_le(&zip_dir, 2, zip_date);
|
||||
strbuf_add_le(&zip_dir, 4, crc);
|
||||
strbuf_add_le(&zip_dir, 4, clamp32(compressed_size));
|
||||
strbuf_add_le(&zip_dir, 4, clamp32(size));
|
||||
strbuf_add_le(&zip_dir, 2, pathlen);
|
||||
strbuf_add_le(&zip_dir, 2, zip_dir_extra_size);
|
||||
strbuf_add_le(&zip_dir, 2, 0); /* comment length */
|
||||
strbuf_add_le(&zip_dir, 2, 0); /* disk */
|
||||
strbuf_add_le(&zip_dir, 2, !is_binary);
|
||||
strbuf_add_le(&zip_dir, 4, attr2);
|
||||
strbuf_add_le(&zip_dir, 4, clamp32(offset));
|
||||
strbuf_add(&zip_dir, path, pathlen);
|
||||
strbuf_add(&zip_dir, &extra, ZIP_EXTRA_MTIME_SIZE);
|
||||
if (zip64_dir_extra_payload_size) {
|
||||
strbuf_add_le(&zip_dir, 2, 0x0001); /* magic */
|
||||
strbuf_add_le(&zip_dir, 2, zip64_dir_extra_payload_size);
|
||||
if (size >= 0xffffffff)
|
||||
strbuf_add_le(&zip_dir, 8, size);
|
||||
if (compressed_size >= 0xffffffff)
|
||||
strbuf_add_le(&zip_dir, 8, compressed_size);
|
||||
if (offset >= 0xffffffff)
|
||||
strbuf_add_le(&zip_dir, 8, offset);
|
||||
}
|
||||
zip_dir_entries++;
|
||||
|
||||
return 0;
|
||||
|
@ -510,12 +559,12 @@ static void write_zip64_trailer(void)
|
|||
copy_le32(trailer64.directory_start_disk, 0);
|
||||
copy_le64(trailer64.entries_on_this_disk, zip_dir_entries);
|
||||
copy_le64(trailer64.entries, zip_dir_entries);
|
||||
copy_le64(trailer64.size, zip_dir_offset);
|
||||
copy_le64(trailer64.size, zip_dir.len);
|
||||
copy_le64(trailer64.offset, zip_offset);
|
||||
|
||||
copy_le32(locator64.magic, 0x07064b50);
|
||||
copy_le32(locator64.disk, 0);
|
||||
copy_le64(locator64.offset, zip_offset + zip_dir_offset);
|
||||
copy_le64(locator64.offset, zip_offset + zip_dir.len);
|
||||
copy_le32(locator64.number_of_disks, 1);
|
||||
|
||||
write_or_die(1, &trailer64, ZIP64_DIR_TRAILER_SIZE);
|
||||
|
@ -533,11 +582,11 @@ static void write_zip_trailer(const unsigned char *sha1)
|
|||
copy_le16_clamp(trailer.entries_on_this_disk, zip_dir_entries,
|
||||
&clamped);
|
||||
copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped);
|
||||
copy_le32(trailer.size, zip_dir_offset);
|
||||
copy_le32(trailer.offset, zip_offset);
|
||||
copy_le32(trailer.size, zip_dir.len);
|
||||
copy_le32_clamp(trailer.offset, zip_offset, &clamped);
|
||||
copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0);
|
||||
|
||||
write_or_die(1, zip_dir, zip_dir_offset);
|
||||
write_or_die(1, zip_dir.buf, zip_dir.len);
|
||||
if (clamped)
|
||||
write_zip64_trailer();
|
||||
write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE);
|
||||
|
@ -545,9 +594,17 @@ static void write_zip_trailer(const unsigned char *sha1)
|
|||
write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ);
|
||||
}
|
||||
|
||||
static void dos_time(time_t *time, int *dos_date, int *dos_time)
|
||||
static void dos_time(timestamp_t *timestamp, int *dos_date, int *dos_time)
|
||||
{
|
||||
struct tm *t = localtime(time);
|
||||
time_t time;
|
||||
struct tm *t;
|
||||
|
||||
if (date_overflows(*timestamp))
|
||||
die("timestamp too large for this system: %"PRItime,
|
||||
*timestamp);
|
||||
time = (time_t)*timestamp;
|
||||
t = localtime(&time);
|
||||
*timestamp = time;
|
||||
|
||||
*dos_date = t->tm_mday + (t->tm_mon + 1) * 32 +
|
||||
(t->tm_year + 1900 - 1980) * 512;
|
||||
|
@ -568,14 +625,13 @@ static int write_zip_archive(const struct archiver *ar,
|
|||
|
||||
dos_time(&args->time, &zip_date, &zip_time);
|
||||
|
||||
zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
|
||||
zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
|
||||
strbuf_init(&zip_dir, 0);
|
||||
|
||||
err = write_archive_entries(args, write_zip_entry);
|
||||
if (!err)
|
||||
write_zip_trailer(args->commit_sha1);
|
||||
|
||||
free(zip_dir);
|
||||
strbuf_release(&zip_dir);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "commit.h"
|
||||
#include "tree-walk.h"
|
||||
|
@ -360,7 +361,7 @@ static void parse_treeish_arg(const char **argv,
|
|||
if (get_sha1(name, oid.hash))
|
||||
die("Not a valid object name");
|
||||
|
||||
commit = lookup_commit_reference_gently(oid.hash, 1);
|
||||
commit = lookup_commit_reference_gently(&oid, 1);
|
||||
if (commit) {
|
||||
commit_sha1 = commit->object.oid.hash;
|
||||
archive_time = commit->date;
|
||||
|
@ -369,7 +370,7 @@ static void parse_treeish_arg(const char **argv,
|
|||
archive_time = time(NULL);
|
||||
}
|
||||
|
||||
tree = parse_tree_indirect(oid.hash);
|
||||
tree = parse_tree_indirect(&oid);
|
||||
if (tree == NULL)
|
||||
die("not a tree object");
|
||||
|
||||
|
@ -383,7 +384,7 @@ static void parse_treeish_arg(const char **argv,
|
|||
if (err || !S_ISDIR(mode))
|
||||
die("current working directory is untracked");
|
||||
|
||||
tree = parse_tree_indirect(tree_oid.hash);
|
||||
tree = parse_tree_indirect(&tree_oid);
|
||||
}
|
||||
ar_args->tree = tree;
|
||||
ar_args->commit_sha1 = commit_sha1;
|
||||
|
|
|
@ -9,7 +9,7 @@ struct archiver_args {
|
|||
struct tree *tree;
|
||||
const unsigned char *commit_sha1;
|
||||
const struct commit *commit;
|
||||
time_t time;
|
||||
timestamp_t time;
|
||||
struct pathspec pathspec;
|
||||
unsigned int verbose : 1;
|
||||
unsigned int worktree_attributes : 1;
|
||||
|
|
21
attr.c
21
attr.c
|
@ -9,6 +9,7 @@
|
|||
|
||||
#define NO_THE_INDEX_COMPATIBILITY_MACROS
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "attr.h"
|
||||
#include "dir.h"
|
||||
|
@ -75,9 +76,10 @@ struct attr_hash_entry {
|
|||
};
|
||||
|
||||
/* attr_hashmap comparison function */
|
||||
static int attr_hash_entry_cmp(const struct attr_hash_entry *a,
|
||||
static int attr_hash_entry_cmp(void *unused_cmp_data,
|
||||
const struct attr_hash_entry *a,
|
||||
const struct attr_hash_entry *b,
|
||||
void *unused)
|
||||
void *unused_keydata)
|
||||
{
|
||||
return (a->keylen != b->keylen) || strncmp(a->key, b->key, a->keylen);
|
||||
}
|
||||
|
@ -85,7 +87,7 @@ static int attr_hash_entry_cmp(const struct attr_hash_entry *a,
|
|||
/* Initialize an 'attr_hashmap' object */
|
||||
static void attr_hashmap_init(struct attr_hashmap *map)
|
||||
{
|
||||
hashmap_init(&map->map, (hashmap_cmp_fn) attr_hash_entry_cmp, 0);
|
||||
hashmap_init(&map->map, (hashmap_cmp_fn) attr_hash_entry_cmp, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -638,13 +640,11 @@ void attr_check_reset(struct attr_check *check)
|
|||
|
||||
void attr_check_clear(struct attr_check *check)
|
||||
{
|
||||
free(check->items);
|
||||
check->items = NULL;
|
||||
FREE_AND_NULL(check->items);
|
||||
check->alloc = 0;
|
||||
check->nr = 0;
|
||||
|
||||
free(check->all_attrs);
|
||||
check->all_attrs = NULL;
|
||||
FREE_AND_NULL(check->all_attrs);
|
||||
check->all_attrs_nr = 0;
|
||||
|
||||
drop_attr_stack(&check->stack);
|
||||
|
@ -720,16 +720,13 @@ void git_attr_set_direction(enum git_attr_direction new_direction,
|
|||
|
||||
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
|
||||
{
|
||||
FILE *fp = fopen(path, "r");
|
||||
FILE *fp = fopen_or_warn(path, "r");
|
||||
struct attr_stack *res;
|
||||
char buf[2048];
|
||||
int lineno = 0;
|
||||
|
||||
if (!fp) {
|
||||
if (errno != ENOENT && errno != ENOTDIR)
|
||||
warn_on_inaccessible(path);
|
||||
if (!fp)
|
||||
return NULL;
|
||||
}
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
while (fgets(buf, sizeof(buf), fp)) {
|
||||
char *bufp = buf;
|
||||
|
|
18
bisect.c
18
bisect.c
|
@ -1,4 +1,5 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
|
@ -438,10 +439,7 @@ static void read_bisect_paths(struct argv_array *array)
|
|||
{
|
||||
struct strbuf str = STRBUF_INIT;
|
||||
const char *filename = git_path_bisect_names();
|
||||
FILE *fp = fopen(filename, "r");
|
||||
|
||||
if (!fp)
|
||||
die_errno(_("Could not open file '%s'"), filename);
|
||||
FILE *fp = xfopen(filename, "r");
|
||||
|
||||
while (strbuf_getline_lf(&str, fp) != EOF) {
|
||||
strbuf_trim(&str);
|
||||
|
@ -546,7 +544,7 @@ static unsigned get_prn(unsigned count) {
|
|||
|
||||
/*
|
||||
* Custom integer square root from
|
||||
* http://en.wikipedia.org/wiki/Integer_square_root
|
||||
* https://en.wikipedia.org/wiki/Integer_square_root
|
||||
*/
|
||||
static int sqrti(int val)
|
||||
{
|
||||
|
@ -669,7 +667,7 @@ static int is_expected_rev(const struct object_id *oid)
|
|||
if (stat(filename, &st) || !S_ISREG(st.st_mode))
|
||||
return 0;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
fp = fopen_or_warn(filename, "r");
|
||||
if (!fp)
|
||||
return 0;
|
||||
|
||||
|
@ -705,7 +703,7 @@ static int bisect_checkout(const unsigned char *bisect_rev, int no_checkout)
|
|||
|
||||
static struct commit *get_commit_reference(const struct object_id *oid)
|
||||
{
|
||||
struct commit *r = lookup_commit_reference(oid->hash);
|
||||
struct commit *r = lookup_commit_reference(oid);
|
||||
if (!r)
|
||||
die(_("Not a valid commit name %s"), oid_to_hex(oid));
|
||||
return r;
|
||||
|
@ -995,8 +993,10 @@ int bisect_next_all(const char *prefix, int no_checkout)
|
|||
|
||||
steps_msg = xstrfmt(Q_("(roughly %d step)", "(roughly %d steps)",
|
||||
steps), steps);
|
||||
/* TRANSLATORS: the last %s will be replaced with
|
||||
"(roughly %d steps)" translation */
|
||||
/*
|
||||
* 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);
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
#ifndef BLAME_H
|
||||
#define BLAME_H
|
||||
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "xdiff-interface.h"
|
||||
#include "revision.h"
|
||||
#include "prio-queue.h"
|
||||
#include "diff.h"
|
||||
|
||||
#define PICKAXE_BLAME_MOVE 01
|
||||
#define PICKAXE_BLAME_COPY 02
|
||||
#define PICKAXE_BLAME_COPY_HARDER 04
|
||||
#define PICKAXE_BLAME_COPY_HARDEST 010
|
||||
|
||||
#define BLAME_DEFAULT_MOVE_SCORE 20
|
||||
#define BLAME_DEFAULT_COPY_SCORE 40
|
||||
|
||||
/*
|
||||
* One blob in a commit that is being suspected
|
||||
*/
|
||||
struct blame_origin {
|
||||
int refcnt;
|
||||
/* Record preceding blame record for this blob */
|
||||
struct blame_origin *previous;
|
||||
/* origins are put in a list linked via `next' hanging off the
|
||||
* corresponding commit's util field in order to make finding
|
||||
* them fast. The presence in this chain does not count
|
||||
* towards the origin's reference count. It is tempting to
|
||||
* let it count as long as the commit is pending examination,
|
||||
* but even under circumstances where the commit will be
|
||||
* present multiple times in the priority queue of unexamined
|
||||
* commits, processing the first instance will not leave any
|
||||
* work requiring the origin data for the second instance. An
|
||||
* interspersed commit changing that would have to be
|
||||
* preexisting with a different ancestry and with the same
|
||||
* commit date in order to wedge itself between two instances
|
||||
* of the same commit in the priority queue _and_ produce
|
||||
* blame entries relevant for it. While we don't want to let
|
||||
* us get tripped up by this case, it certainly does not seem
|
||||
* worth optimizing for.
|
||||
*/
|
||||
struct blame_origin *next;
|
||||
struct commit *commit;
|
||||
/* `suspects' contains blame entries that may be attributed to
|
||||
* this origin's commit or to parent commits. When a commit
|
||||
* is being processed, all suspects will be moved, either by
|
||||
* assigning them to an origin in a different commit, or by
|
||||
* shipping them to the scoreboard's ent list because they
|
||||
* cannot be attributed to a different commit.
|
||||
*/
|
||||
struct blame_entry *suspects;
|
||||
mmfile_t file;
|
||||
struct object_id blob_oid;
|
||||
unsigned mode;
|
||||
/* guilty gets set when shipping any suspects to the final
|
||||
* blame list instead of other commits
|
||||
*/
|
||||
char guilty;
|
||||
char path[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
/*
|
||||
* Each group of lines is described by a blame_entry; it can be split
|
||||
* as we pass blame to the parents. They are arranged in linked lists
|
||||
* kept as `suspects' of some unprocessed origin, or entered (when the
|
||||
* blame origin has been finalized) into the scoreboard structure.
|
||||
* While the scoreboard structure is only sorted at the end of
|
||||
* processing (according to final image line number), the lists
|
||||
* attached to an origin are sorted by the target line number.
|
||||
*/
|
||||
struct blame_entry {
|
||||
struct blame_entry *next;
|
||||
|
||||
/* the first line of this group in the final image;
|
||||
* internally all line numbers are 0 based.
|
||||
*/
|
||||
int lno;
|
||||
|
||||
/* how many lines this group has */
|
||||
int num_lines;
|
||||
|
||||
/* the commit that introduced this group into the final image */
|
||||
struct blame_origin *suspect;
|
||||
|
||||
/* the line number of the first line of this group in the
|
||||
* suspect's file; internally all line numbers are 0 based.
|
||||
*/
|
||||
int s_lno;
|
||||
|
||||
/* how significant this entry is -- cached to avoid
|
||||
* scanning the lines over and over.
|
||||
*/
|
||||
unsigned score;
|
||||
};
|
||||
|
||||
/*
|
||||
* The current state of the blame assignment.
|
||||
*/
|
||||
struct blame_scoreboard {
|
||||
/* the final commit (i.e. where we started digging from) */
|
||||
struct commit *final;
|
||||
/* Priority queue for commits with unassigned blame records */
|
||||
struct prio_queue commits;
|
||||
struct rev_info *revs;
|
||||
const char *path;
|
||||
|
||||
/*
|
||||
* The contents in the final image.
|
||||
* Used by many functions to obtain contents of the nth line,
|
||||
* indexed with scoreboard.lineno[blame_entry.lno].
|
||||
*/
|
||||
const char *final_buf;
|
||||
unsigned long final_buf_size;
|
||||
|
||||
/* linked list of blames */
|
||||
struct blame_entry *ent;
|
||||
|
||||
/* look-up a line in the final buffer */
|
||||
int num_lines;
|
||||
int *lineno;
|
||||
|
||||
/* stats */
|
||||
int num_read_blob;
|
||||
int num_get_patch;
|
||||
int num_commits;
|
||||
|
||||
/*
|
||||
* blame for a blame_entry with score lower than these thresholds
|
||||
* is not passed to the parent using move/copy logic.
|
||||
*/
|
||||
unsigned move_score;
|
||||
unsigned copy_score;
|
||||
|
||||
/* use this file's contents as the final image */
|
||||
const char *contents_from;
|
||||
|
||||
/* flags */
|
||||
int reverse;
|
||||
int show_root;
|
||||
int xdl_opts;
|
||||
int no_whole_file_rename;
|
||||
int debug;
|
||||
|
||||
/* callbacks */
|
||||
void(*on_sanity_fail)(struct blame_scoreboard *, int);
|
||||
void(*found_guilty_entry)(struct blame_entry *, void *);
|
||||
|
||||
void *found_guilty_entry_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Origin is refcounted and usually we keep the blob contents to be
|
||||
* reused.
|
||||
*/
|
||||
static inline struct blame_origin *blame_origin_incref(struct blame_origin *o)
|
||||
{
|
||||
if (o)
|
||||
o->refcnt++;
|
||||
return o;
|
||||
}
|
||||
extern void blame_origin_decref(struct blame_origin *o);
|
||||
|
||||
extern void blame_coalesce(struct blame_scoreboard *sb);
|
||||
extern void blame_sort_final(struct blame_scoreboard *sb);
|
||||
extern unsigned blame_entry_score(struct blame_scoreboard *sb, struct blame_entry *e);
|
||||
extern void assign_blame(struct blame_scoreboard *sb, int opt);
|
||||
extern const char *blame_nth_line(struct blame_scoreboard *sb, long lno);
|
||||
|
||||
extern void init_scoreboard(struct blame_scoreboard *sb);
|
||||
extern void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blame_origin **orig);
|
||||
|
||||
extern struct blame_entry *blame_entry_prepend(struct blame_entry *head, long start, long end, struct blame_origin *o);
|
||||
|
||||
#endif /* BLAME_H */
|
6
blob.c
6
blob.c
|
@ -3,11 +3,11 @@
|
|||
|
||||
const char *blob_type = "blob";
|
||||
|
||||
struct blob *lookup_blob(const unsigned char *sha1)
|
||||
struct blob *lookup_blob(const struct object_id *oid)
|
||||
{
|
||||
struct object *obj = lookup_object(sha1);
|
||||
struct object *obj = lookup_object(oid->hash);
|
||||
if (!obj)
|
||||
return create_object(sha1, alloc_blob_node());
|
||||
return create_object(oid->hash, alloc_blob_node());
|
||||
return object_as_type(obj, OBJ_BLOB, 0);
|
||||
}
|
||||
|
||||
|
|
2
blob.h
2
blob.h
|
@ -9,7 +9,7 @@ struct blob {
|
|||
struct object object;
|
||||
};
|
||||
|
||||
struct blob *lookup_blob(const unsigned char *sha1);
|
||||
struct blob *lookup_blob(const struct object_id *oid);
|
||||
|
||||
int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size);
|
||||
|
||||
|
|
35
branch.c
35
branch.c
|
@ -1,5 +1,6 @@
|
|||
#include "git-compat-util.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "branch.h"
|
||||
#include "refs.h"
|
||||
#include "remote.h"
|
||||
|
@ -24,8 +25,7 @@ static int find_tracked_branch(struct remote *remote, void *priv)
|
|||
} else {
|
||||
free(tracking->spec.src);
|
||||
if (tracking->src) {
|
||||
free(tracking->src);
|
||||
tracking->src = NULL;
|
||||
FREE_AND_NULL(tracking->src);
|
||||
}
|
||||
}
|
||||
tracking->spec.src = NULL;
|
||||
|
@ -191,9 +191,9 @@ int validate_new_branchname(const char *name, struct strbuf *ref,
|
|||
|
||||
if (!attr_only) {
|
||||
const char *head;
|
||||
unsigned char sha1[20];
|
||||
struct object_id oid;
|
||||
|
||||
head = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
|
||||
head = resolve_ref_unsafe("HEAD", 0, oid.hash, NULL);
|
||||
if (!is_bare_repository() && head && !strcmp(head, ref->buf))
|
||||
die(_("Cannot force update the current branch."));
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ void create_branch(const char *name, const char *start_name,
|
|||
int quiet, enum branch_track track)
|
||||
{
|
||||
struct commit *commit;
|
||||
unsigned char sha1[20];
|
||||
struct object_id oid;
|
||||
char *real_ref;
|
||||
struct strbuf ref = STRBUF_INIT;
|
||||
int forcing = 0;
|
||||
|
@ -253,7 +253,7 @@ void create_branch(const char *name, const char *start_name,
|
|||
}
|
||||
|
||||
real_ref = NULL;
|
||||
if (get_sha1(start_name, sha1)) {
|
||||
if (get_oid(start_name, &oid)) {
|
||||
if (explicit_tracking) {
|
||||
if (advice_set_upstream_failure) {
|
||||
error(_(upstream_missing), start_name);
|
||||
|
@ -265,7 +265,7 @@ void create_branch(const char *name, const char *start_name,
|
|||
die(_("Not a valid object name: '%s'."), start_name);
|
||||
}
|
||||
|
||||
switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
|
||||
switch (dwim_ref(start_name, strlen(start_name), oid.hash, &real_ref)) {
|
||||
case 0:
|
||||
/* Not branching from any existing branch */
|
||||
if (explicit_tracking)
|
||||
|
@ -286,9 +286,9 @@ void create_branch(const char *name, const char *start_name,
|
|||
break;
|
||||
}
|
||||
|
||||
if ((commit = lookup_commit_reference(sha1)) == NULL)
|
||||
if ((commit = lookup_commit_reference(&oid)) == NULL)
|
||||
die(_("Not a valid branch point: '%s'."), start_name);
|
||||
hashcpy(sha1, commit->object.oid.hash);
|
||||
oidcpy(&oid, &commit->object.oid);
|
||||
|
||||
if (reflog)
|
||||
log_all_ref_updates = LOG_REFS_NORMAL;
|
||||
|
@ -306,7 +306,7 @@ void create_branch(const char *name, const char *start_name,
|
|||
transaction = ref_transaction_begin(&err);
|
||||
if (!transaction ||
|
||||
ref_transaction_update(transaction, ref.buf,
|
||||
sha1, forcing ? NULL : null_sha1,
|
||||
oid.hash, forcing ? NULL : null_sha1,
|
||||
0, msg, &err) ||
|
||||
ref_transaction_commit(transaction, &err))
|
||||
die("%s", err.buf);
|
||||
|
@ -353,17 +353,18 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref,
|
|||
int i;
|
||||
|
||||
for (i = 0; worktrees[i]; i++) {
|
||||
struct ref_store *refs;
|
||||
|
||||
if (worktrees[i]->is_detached)
|
||||
continue;
|
||||
if (strcmp(oldref, worktrees[i]->head_ref))
|
||||
if (worktrees[i]->head_ref &&
|
||||
strcmp(oldref, worktrees[i]->head_ref))
|
||||
continue;
|
||||
|
||||
if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]),
|
||||
newref, logmsg)) {
|
||||
ret = -1;
|
||||
error(_("HEAD of working tree %s is not updated"),
|
||||
worktrees[i]->path);
|
||||
}
|
||||
refs = get_worktree_ref_store(worktrees[i]);
|
||||
if (refs_create_symref(refs, "HEAD", newref, logmsg))
|
||||
ret = error(_("HEAD of working tree %s is not updated"),
|
||||
worktrees[i]->path);
|
||||
}
|
||||
|
||||
free_worktrees(worktrees);
|
||||
|
|
|
@ -25,8 +25,6 @@ struct fmt_merge_msg_opts {
|
|||
extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
|
||||
struct fmt_merge_msg_opts *);
|
||||
|
||||
extern int textconv_object(const char *path, unsigned mode, const struct object_id *oid, int oid_valid, char **buf, unsigned long *buf_size);
|
||||
|
||||
extern int is_builtin(const char *s);
|
||||
|
||||
extern int cmd_add(int argc, const char **argv, const char *prefix);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) 2006 Linus Torvalds
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "builtin.h"
|
||||
#include "lockfile.h"
|
||||
#include "dir.h"
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include "revision.h"
|
||||
#include "bulk-checkin.h"
|
||||
#include "argv-array.h"
|
||||
#include "submodule.h"
|
||||
|
||||
static const char * const builtin_add_usage[] = {
|
||||
N_("git add [<options>] [--] <pathspec>..."),
|
||||
|
@ -135,7 +137,7 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec,
|
|||
*dst++ = entry;
|
||||
}
|
||||
dir->nr = dst - dir->entries;
|
||||
add_pathspec_matches_against_index(pathspec, seen);
|
||||
add_pathspec_matches_against_index(pathspec, &the_index, seen);
|
||||
return seen;
|
||||
}
|
||||
|
||||
|
@ -248,6 +250,7 @@ N_("The following paths are ignored by one of your .gitignore files:\n");
|
|||
|
||||
static int verbose, show_only, ignored_too, refresh_only;
|
||||
static int ignore_add_errors, intent_to_add, ignore_missing;
|
||||
static int warn_on_embedded_repo = 1;
|
||||
|
||||
#define ADDREMOVE_DEFAULT 1
|
||||
static int addremove = ADDREMOVE_DEFAULT;
|
||||
|
@ -281,6 +284,8 @@ static struct option builtin_add_options[] = {
|
|||
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
|
||||
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
|
||||
OPT_STRING( 0 , "chmod", &chmod_arg, N_("(+/-)x"), N_("override the executable bit of the listed files")),
|
||||
OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
|
||||
N_("warn when adding an embedded repository")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
|
@ -294,6 +299,45 @@ static int add_config(const char *var, const char *value, void *cb)
|
|||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static const char embedded_advice[] = N_(
|
||||
"You've added another git repository inside your current repository.\n"
|
||||
"Clones of the outer repository will not contain the contents of\n"
|
||||
"the embedded repository and will not know how to obtain it.\n"
|
||||
"If you meant to add a submodule, use:\n"
|
||||
"\n"
|
||||
" git submodule add <url> %s\n"
|
||||
"\n"
|
||||
"If you added this path by mistake, you can remove it from the\n"
|
||||
"index with:\n"
|
||||
"\n"
|
||||
" git rm --cached %s\n"
|
||||
"\n"
|
||||
"See \"git help submodule\" for more information."
|
||||
);
|
||||
|
||||
static void check_embedded_repo(const char *path)
|
||||
{
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
|
||||
if (!warn_on_embedded_repo)
|
||||
return;
|
||||
if (!ends_with(path, "/"))
|
||||
return;
|
||||
|
||||
/* Drop trailing slash for aesthetics */
|
||||
strbuf_addstr(&name, path);
|
||||
strbuf_strip_suffix(&name, "/");
|
||||
|
||||
warning(_("adding embedded git repository: %s"), name.buf);
|
||||
if (advice_add_embedded_repo) {
|
||||
advise(embedded_advice, name.buf, name.buf);
|
||||
/* there may be multiple entries; advise only once */
|
||||
advice_add_embedded_repo = 0;
|
||||
}
|
||||
|
||||
strbuf_release(&name);
|
||||
}
|
||||
|
||||
static int add_files(struct dir_struct *dir, int flags)
|
||||
{
|
||||
int i, exit_status = 0;
|
||||
|
@ -306,12 +350,14 @@ static int add_files(struct dir_struct *dir, int flags)
|
|||
exit_status = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->nr; i++)
|
||||
for (i = 0; i < dir->nr; i++) {
|
||||
check_embedded_repo(dir->entries[i]->name);
|
||||
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
|
||||
if (!ignore_add_errors)
|
||||
die(_("adding files failed"));
|
||||
exit_status = 1;
|
||||
}
|
||||
}
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
|
@ -379,16 +425,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||
if (read_cache() < 0)
|
||||
die(_("index file corrupt"));
|
||||
|
||||
die_in_unpopulated_submodule(&the_index, prefix);
|
||||
|
||||
/*
|
||||
* Check the "pathspec '%s' did not match any files" block
|
||||
* below before enabling new magic.
|
||||
*/
|
||||
parse_pathspec(&pathspec, 0,
|
||||
PATHSPEC_PREFER_FULL |
|
||||
PATHSPEC_SYMLINK_LEADING_PATH |
|
||||
PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,
|
||||
PATHSPEC_SYMLINK_LEADING_PATH,
|
||||
prefix, argv);
|
||||
|
||||
die_path_inside_submodule(&the_index, &pathspec);
|
||||
|
||||
if (add_new_files) {
|
||||
int baselen;
|
||||
|
||||
|
@ -400,7 +449,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
|
||||
/* This picks up the paths that are not tracked */
|
||||
baselen = fill_directory(&dir, &pathspec);
|
||||
baselen = fill_directory(&dir, &the_index, &pathspec);
|
||||
if (pathspec.nr)
|
||||
seen = prune_directory(&dir, &pathspec, baselen);
|
||||
}
|
||||
|
@ -414,7 +463,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||
int i;
|
||||
|
||||
if (!seen)
|
||||
seen = find_pathspecs_matching_against_index(&pathspec);
|
||||
seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
|
||||
|
||||
/*
|
||||
* file_exists() assumes exact match
|
||||
|
@ -436,8 +485,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
|||
!file_exists(path))) {
|
||||
if (ignore_missing) {
|
||||
int dtype = DT_UNKNOWN;
|
||||
if (is_excluded(&dir, path, &dtype))
|
||||
dir_add_ignored(&dir, path, pathspec.items[i].len);
|
||||
if (is_excluded(&dir, &the_index, path, &dtype))
|
||||
dir_add_ignored(&dir, &the_index,
|
||||
path, pathspec.items[i].len);
|
||||
} else
|
||||
die(_("pathspec '%s' did not match any files"),
|
||||
pathspec.items[i].original);
|
||||
|
|
110
builtin/am.c
110
builtin/am.c
|
@ -4,6 +4,7 @@
|
|||
* Based on git-am.sh by Junio C Hamano.
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "builtin.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "parse-options.h"
|
||||
|
@ -483,8 +484,7 @@ static int run_applypatch_msg_hook(struct am_state *state)
|
|||
ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
|
||||
|
||||
if (!ret) {
|
||||
free(state->msg);
|
||||
state->msg = NULL;
|
||||
FREE_AND_NULL(state->msg);
|
||||
if (read_commit_msg(state) < 0)
|
||||
die(_("'%s' was deleted by the applypatch-msg hook"),
|
||||
am_path(state, "final-commit"));
|
||||
|
@ -563,7 +563,7 @@ static int copy_notes_for_rebase(const struct am_state *state)
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (copy_note_for_rewrite(c, from_obj.hash, to_obj.hash))
|
||||
if (copy_note_for_rewrite(c, &from_obj, &to_obj))
|
||||
ret = error(_("Failed to copy notes from '%s' to '%s'"),
|
||||
oid_to_hex(&from_obj), oid_to_hex(&to_obj));
|
||||
}
|
||||
|
@ -879,12 +879,12 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
|
|||
if (skip_prefix(sb.buf, "# User ", &str))
|
||||
fprintf(out, "From: %s\n", str);
|
||||
else if (skip_prefix(sb.buf, "# Date ", &str)) {
|
||||
unsigned long timestamp;
|
||||
timestamp_t timestamp;
|
||||
long tz, tz2;
|
||||
char *end;
|
||||
|
||||
errno = 0;
|
||||
timestamp = strtoul(str, &end, 10);
|
||||
timestamp = parse_timestamp(str, &end, 10);
|
||||
if (errno)
|
||||
return error(_("invalid timestamp"));
|
||||
|
||||
|
@ -1073,17 +1073,10 @@ static void am_next(struct am_state *state)
|
|||
{
|
||||
struct object_id head;
|
||||
|
||||
free(state->author_name);
|
||||
state->author_name = NULL;
|
||||
|
||||
free(state->author_email);
|
||||
state->author_email = NULL;
|
||||
|
||||
free(state->author_date);
|
||||
state->author_date = NULL;
|
||||
|
||||
free(state->msg);
|
||||
state->msg = NULL;
|
||||
FREE_AND_NULL(state->author_name);
|
||||
FREE_AND_NULL(state->author_email);
|
||||
FREE_AND_NULL(state->author_date);
|
||||
FREE_AND_NULL(state->msg);
|
||||
state->msg_len = 0;
|
||||
|
||||
unlink(am_path(state, "author-script"));
|
||||
|
@ -1145,7 +1138,7 @@ static int index_has_changes(struct strbuf *sb)
|
|||
DIFF_OPT_SET(&opt, EXIT_WITH_STATUS);
|
||||
if (!sb)
|
||||
DIFF_OPT_SET(&opt, QUICK);
|
||||
do_diff_cache(head.hash, &opt);
|
||||
do_diff_cache(&head, &opt);
|
||||
diffcore_std(&opt);
|
||||
for (i = 0; sb && i < diff_queued_diff.nr; i++) {
|
||||
if (i)
|
||||
|
@ -1275,12 +1268,8 @@ static int parse_mail(struct am_state *state, const char *mail)
|
|||
die("BUG: invalid value for state->scissors");
|
||||
}
|
||||
|
||||
mi.input = fopen(mail, "r");
|
||||
if (!mi.input)
|
||||
die("could not open input");
|
||||
mi.output = fopen(am_path(state, "info"), "w");
|
||||
if (!mi.output)
|
||||
die("could not open output 'info'");
|
||||
mi.input = xfopen(mail, "r");
|
||||
mi.output = xfopen(am_path(state, "info"), "w");
|
||||
if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
|
||||
die("could not parse patch");
|
||||
|
||||
|
@ -1312,7 +1301,7 @@ static int parse_mail(struct am_state *state, const char *mail)
|
|||
}
|
||||
|
||||
if (is_empty_file(am_path(state, "patch"))) {
|
||||
printf_ln(_("Patch is empty. Was it split wrong?"));
|
||||
printf_ln(_("Patch is empty."));
|
||||
die_user_resolve(state);
|
||||
}
|
||||
|
||||
|
@ -1351,19 +1340,16 @@ static int get_mail_commit_oid(struct object_id *commit_id, const char *mail)
|
|||
struct strbuf sb = STRBUF_INIT;
|
||||
FILE *fp = xfopen(mail, "r");
|
||||
const char *x;
|
||||
int ret = 0;
|
||||
|
||||
if (strbuf_getline_lf(&sb, fp))
|
||||
return -1;
|
||||
|
||||
if (!skip_prefix(sb.buf, "From ", &x))
|
||||
return -1;
|
||||
|
||||
if (get_oid_hex(x, commit_id) < 0)
|
||||
return -1;
|
||||
if (strbuf_getline_lf(&sb, fp) ||
|
||||
!skip_prefix(sb.buf, "From ", &x) ||
|
||||
get_oid_hex(x, commit_id) < 0)
|
||||
ret = -1;
|
||||
|
||||
strbuf_release(&sb);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1372,40 +1358,33 @@ static int get_mail_commit_oid(struct object_id *commit_id, const char *mail)
|
|||
*/
|
||||
static void get_commit_info(struct am_state *state, struct commit *commit)
|
||||
{
|
||||
const char *buffer, *ident_line, *author_date, *msg;
|
||||
const char *buffer, *ident_line, *msg;
|
||||
size_t ident_len;
|
||||
struct ident_split ident_split;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
struct ident_split id;
|
||||
|
||||
buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding());
|
||||
|
||||
ident_line = find_commit_header(buffer, "author", &ident_len);
|
||||
|
||||
if (split_ident_line(&ident_split, ident_line, ident_len) < 0) {
|
||||
strbuf_add(&sb, ident_line, ident_len);
|
||||
die(_("invalid ident line: %s"), sb.buf);
|
||||
}
|
||||
if (split_ident_line(&id, ident_line, ident_len) < 0)
|
||||
die(_("invalid ident line: %.*s"), (int)ident_len, ident_line);
|
||||
|
||||
assert(!state->author_name);
|
||||
if (ident_split.name_begin) {
|
||||
strbuf_add(&sb, ident_split.name_begin,
|
||||
ident_split.name_end - ident_split.name_begin);
|
||||
state->author_name = strbuf_detach(&sb, NULL);
|
||||
} else
|
||||
if (id.name_begin)
|
||||
state->author_name =
|
||||
xmemdupz(id.name_begin, id.name_end - id.name_begin);
|
||||
else
|
||||
state->author_name = xstrdup("");
|
||||
|
||||
assert(!state->author_email);
|
||||
if (ident_split.mail_begin) {
|
||||
strbuf_add(&sb, ident_split.mail_begin,
|
||||
ident_split.mail_end - ident_split.mail_begin);
|
||||
state->author_email = strbuf_detach(&sb, NULL);
|
||||
} else
|
||||
if (id.mail_begin)
|
||||
state->author_email =
|
||||
xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
|
||||
else
|
||||
state->author_email = xstrdup("");
|
||||
|
||||
author_date = show_ident_date(&ident_split, DATE_MODE(NORMAL));
|
||||
strbuf_addstr(&sb, author_date);
|
||||
assert(!state->author_date);
|
||||
state->author_date = strbuf_detach(&sb, NULL);
|
||||
state->author_date = xstrdup(show_ident_date(&id, DATE_MODE(NORMAL)));
|
||||
|
||||
assert(!state->msg);
|
||||
msg = strstr(buffer, "\n\n");
|
||||
|
@ -1413,6 +1392,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
|
|||
die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid));
|
||||
state->msg = xstrdup(msg + 2);
|
||||
state->msg_len = strlen(state->msg);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1453,9 +1433,9 @@ static void write_index_patch(const struct am_state *state)
|
|||
FILE *fp;
|
||||
|
||||
if (!get_sha1_tree("HEAD", head.hash))
|
||||
tree = lookup_tree(head.hash);
|
||||
tree = lookup_tree(&head);
|
||||
else
|
||||
tree = lookup_tree(EMPTY_TREE_SHA1_BIN);
|
||||
tree = lookup_tree(&empty_tree_oid);
|
||||
|
||||
fp = xfopen(am_path(state, "patch"), "w");
|
||||
init_revisions(&rev_info, NULL);
|
||||
|
@ -1488,7 +1468,7 @@ static int parse_mail_rebase(struct am_state *state, const char *mail)
|
|||
if (get_mail_commit_oid(&commit_oid, mail) < 0)
|
||||
die(_("could not parse %s"), mail);
|
||||
|
||||
commit = lookup_commit_or_die(commit_oid.hash, mail);
|
||||
commit = lookup_commit_or_die(&commit_oid, mail);
|
||||
|
||||
get_commit_info(state, commit);
|
||||
|
||||
|
@ -1618,7 +1598,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
|||
init_revisions(&rev_info, NULL);
|
||||
rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
|
||||
diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
|
||||
add_pending_sha1(&rev_info, "HEAD", our_tree.hash, 0);
|
||||
add_pending_oid(&rev_info, "HEAD", &our_tree, 0);
|
||||
diff_setup_done(&rev_info.diffopt);
|
||||
run_diff_index(&rev_info, 1);
|
||||
}
|
||||
|
@ -1683,7 +1663,7 @@ static void do_commit(const struct am_state *state)
|
|||
|
||||
if (!get_sha1_commit("HEAD", parent.hash)) {
|
||||
old_oid = &parent;
|
||||
commit_list_insert(lookup_commit(parent.hash), &parents);
|
||||
commit_list_insert(lookup_commit(&parent), &parents);
|
||||
} else {
|
||||
old_oid = NULL;
|
||||
say(state, stderr, _("applying to an empty history"));
|
||||
|
@ -1940,7 +1920,8 @@ static void am_resolve(struct am_state *state)
|
|||
|
||||
if (unmerged_cache()) {
|
||||
printf_ln(_("You still have unmerged paths in your index.\n"
|
||||
"Did you forget to use 'git add'?"));
|
||||
"You should 'git add' each file with resolved conflicts to mark them as such.\n"
|
||||
"You might run `git rm` on a file to accept \"deleted by them\" for it."));
|
||||
die_user_resolve(state);
|
||||
}
|
||||
|
||||
|
@ -2045,11 +2026,11 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
|
|||
struct tree *head_tree, *remote_tree, *index_tree;
|
||||
struct object_id index;
|
||||
|
||||
head_tree = parse_tree_indirect(head->hash);
|
||||
head_tree = parse_tree_indirect(head);
|
||||
if (!head_tree)
|
||||
return error(_("Could not parse object '%s'."), oid_to_hex(head));
|
||||
|
||||
remote_tree = parse_tree_indirect(remote->hash);
|
||||
remote_tree = parse_tree_indirect(remote);
|
||||
if (!remote_tree)
|
||||
return error(_("Could not parse object '%s'."), oid_to_hex(remote));
|
||||
|
||||
|
@ -2061,7 +2042,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
|
|||
if (write_cache_as_tree(index.hash, 0, NULL))
|
||||
return -1;
|
||||
|
||||
index_tree = parse_tree_indirect(index.hash);
|
||||
index_tree = parse_tree_indirect(&index);
|
||||
if (!index_tree)
|
||||
return error(_("Could not parse object '%s'."), oid_to_hex(&index));
|
||||
|
||||
|
@ -2156,7 +2137,7 @@ static void am_abort(struct am_state *state)
|
|||
am_rerere_clear();
|
||||
|
||||
curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL);
|
||||
has_curr_head = !is_null_oid(&curr_head);
|
||||
has_curr_head = curr_branch && !is_null_oid(&curr_head);
|
||||
if (!has_curr_head)
|
||||
hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN);
|
||||
|
||||
|
@ -2319,6 +2300,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
|||
OPT_END()
|
||||
};
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage_with_options(usage, options);
|
||||
|
||||
git_config(git_am_config, NULL);
|
||||
|
||||
am_state_init(&state);
|
||||
|
|
2144
builtin/blame.c
2144
builtin/blame.c
File diff suppressed because it is too large
Load Diff
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "color.h"
|
||||
#include "refs.h"
|
||||
#include "commit.h"
|
||||
|
@ -124,7 +125,7 @@ static int branch_merged(int kind, const char *name,
|
|||
(reference_name = reference_name_to_free =
|
||||
resolve_refdup(upstream, RESOLVE_REF_READING,
|
||||
oid.hash, NULL)) != NULL)
|
||||
reference_rev = lookup_commit_reference(oid.hash);
|
||||
reference_rev = lookup_commit_reference(&oid);
|
||||
}
|
||||
if (!reference_rev)
|
||||
reference_rev = head_rev;
|
||||
|
@ -157,7 +158,7 @@ static int check_branch_commit(const char *branchname, const char *refname,
|
|||
const struct object_id *oid, struct commit *head_rev,
|
||||
int kinds, int force)
|
||||
{
|
||||
struct commit *rev = lookup_commit_reference(oid->hash);
|
||||
struct commit *rev = lookup_commit_reference(oid);
|
||||
if (!rev) {
|
||||
error(_("Couldn't look up commit object for '%s'"), refname);
|
||||
return -1;
|
||||
|
@ -211,7 +212,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
|||
}
|
||||
|
||||
if (!force) {
|
||||
head_rev = lookup_commit_reference(head_oid.hash);
|
||||
head_rev = lookup_commit_reference(&head_oid);
|
||||
if (!head_rev)
|
||||
die(_("Couldn't look up commit object for HEAD"));
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
* Copyright (C) Linus Torvalds, 2005
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "builtin.h"
|
||||
#include "diff.h"
|
||||
#include "parse-options.h"
|
||||
#include "userdiff.h"
|
||||
#include "streaming.h"
|
||||
|
@ -61,7 +63,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||
if (unknown_type)
|
||||
flags |= LOOKUP_UNKNOWN_OBJECT;
|
||||
|
||||
if (get_sha1_with_context(obj_name, 0, oid.hash, &obj_context))
|
||||
if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
|
||||
oid.hash, &obj_context))
|
||||
die("Not a valid object name %s", obj_name);
|
||||
|
||||
if (!path)
|
||||
|
@ -165,6 +168,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||
die("git cat-file %s: bad file", obj_name);
|
||||
|
||||
write_or_die(1, buf, size);
|
||||
free(buf);
|
||||
free(obj_context.path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "attr.h"
|
||||
#include "quote.h"
|
||||
#include "parse-options.h"
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "quote.h"
|
||||
#include "pathspec.h"
|
||||
#include "parse-options.h"
|
||||
#include "submodule.h"
|
||||
|
||||
static int quiet, verbose, stdin_paths, show_non_matching, no_index;
|
||||
static const char * const check_ignore_usage[] = {
|
||||
|
@ -87,21 +89,23 @@ static int check_ignore(struct dir_struct *dir,
|
|||
parse_pathspec(&pathspec,
|
||||
PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
|
||||
PATHSPEC_SYMLINK_LEADING_PATH |
|
||||
PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE |
|
||||
PATHSPEC_KEEP_ORDER,
|
||||
prefix, argv);
|
||||
|
||||
die_path_inside_submodule(&the_index, &pathspec);
|
||||
|
||||
/*
|
||||
* look for pathspecs matching entries in the index, since these
|
||||
* should not be ignored, in order to be consistent with
|
||||
* 'git status', 'git add' etc.
|
||||
*/
|
||||
seen = find_pathspecs_matching_against_index(&pathspec);
|
||||
seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
|
||||
for (i = 0; i < pathspec.nr; i++) {
|
||||
full_path = pathspec.items[i].match;
|
||||
exclude = NULL;
|
||||
if (!seen[i]) {
|
||||
exclude = last_exclude_matching(dir, full_path, &dtype);
|
||||
exclude = last_exclude_matching(dir, &the_index,
|
||||
full_path, &dtype);
|
||||
}
|
||||
if (!quiet && (exclude || show_non_matching))
|
||||
output_exclude(pathspec.items[i].original, exclude);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "mailmap.h"
|
||||
#include "parse-options.h"
|
||||
#include "string-list.h"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*
|
||||
*/
|
||||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "lockfile.h"
|
||||
#include "quote.h"
|
||||
#include "cache-tree.h"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "lockfile.h"
|
||||
#include "parse-options.h"
|
||||
#include "refs.h"
|
||||
|
@ -21,31 +22,12 @@
|
|||
#include "submodule-config.h"
|
||||
#include "submodule.h"
|
||||
|
||||
static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
|
||||
|
||||
static const char * const checkout_usage[] = {
|
||||
N_("git checkout [<options>] <branch>"),
|
||||
N_("git checkout [<options>] [<branch>] -- <file>..."),
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int option_parse_recurse_submodules(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
if (unset) {
|
||||
recurse_submodules = RECURSE_SUBMODULES_OFF;
|
||||
return 0;
|
||||
}
|
||||
if (arg)
|
||||
recurse_submodules =
|
||||
parse_update_recurse_submodules_arg(opt->long_name,
|
||||
arg);
|
||||
else
|
||||
recurse_submodules = RECURSE_SUBMODULES_ON;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct checkout_opts {
|
||||
int patch_mode;
|
||||
int quiet;
|
||||
|
@ -235,22 +217,24 @@ static int checkout_merged(int pos, const struct checkout *state)
|
|||
/*
|
||||
* NEEDSWORK:
|
||||
* There is absolutely no reason to write this as a blob object
|
||||
* and create a phony cache entry just to leak. This hack is
|
||||
* primarily to get to the write_entry() machinery that massages
|
||||
* the contents to work-tree format and writes out which only
|
||||
* allows it for a cache entry. The code in write_entry() needs
|
||||
* to be refactored to allow us to feed a <buffer, size, mode>
|
||||
* instead of a cache entry. Such a refactoring would help
|
||||
* merge_recursive as well (it also writes the merge result to the
|
||||
* object database even when it may contain conflicts).
|
||||
* and create a phony cache entry. This hack is primarily to get
|
||||
* to the write_entry() machinery that massages the contents to
|
||||
* work-tree format and writes out which only allows it for a
|
||||
* cache entry. The code in write_entry() needs to be refactored
|
||||
* to allow us to feed a <buffer, size, mode> instead of a cache
|
||||
* entry. Such a refactoring would help merge_recursive as well
|
||||
* (it also writes the merge result to the object database even
|
||||
* when it may contain conflicts).
|
||||
*/
|
||||
if (write_sha1_file(result_buf.ptr, result_buf.size,
|
||||
blob_type, oid.hash))
|
||||
die(_("Unable to add merge result for '%s'"), path);
|
||||
free(result_buf.ptr);
|
||||
ce = make_cache_entry(mode, oid.hash, path, 2, 0);
|
||||
if (!ce)
|
||||
die(_("make_cache_entry failed for path '%s'"), path);
|
||||
status = checkout_entry(ce, state, NULL);
|
||||
free(ce);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -393,7 +377,7 @@ static int checkout_paths(const struct checkout_opts *opts,
|
|||
die(_("unable to write new index file"));
|
||||
|
||||
read_ref_full("HEAD", 0, rev.hash, NULL);
|
||||
head = lookup_commit_reference_gently(rev.hash, 1);
|
||||
head = lookup_commit_reference_gently(&rev, 1);
|
||||
|
||||
errs |= post_checkout_hook(head, head, 0);
|
||||
return errs;
|
||||
|
@ -527,10 +511,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
setup_standard_excludes(topts.dir);
|
||||
}
|
||||
tree = parse_tree_indirect(old->commit ?
|
||||
old->commit->object.oid.hash :
|
||||
EMPTY_TREE_SHA1_BIN);
|
||||
&old->commit->object.oid :
|
||||
&empty_tree_oid);
|
||||
init_tree_desc(&trees[0], tree->buffer, tree->size);
|
||||
tree = parse_tree_indirect(new->commit->object.oid.hash);
|
||||
tree = parse_tree_indirect(&new->commit->object.oid);
|
||||
init_tree_desc(&trees[1], tree->buffer, tree->size);
|
||||
|
||||
ret = unpack_trees(2, trees, &topts);
|
||||
|
@ -721,7 +705,7 @@ static int add_pending_uninteresting_ref(const char *refname,
|
|||
const struct object_id *oid,
|
||||
int flags, void *cb_data)
|
||||
{
|
||||
add_pending_sha1(cb_data, refname, oid->hash, UNINTERESTING);
|
||||
add_pending_oid(cb_data, refname, oid, UNINTERESTING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -807,7 +791,7 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
|
|||
add_pending_object(&revs, object, oid_to_hex(&object->oid));
|
||||
|
||||
for_each_ref(add_pending_uninteresting_ref, &revs);
|
||||
add_pending_sha1(&revs, "HEAD", new->object.oid.hash, UNINTERESTING);
|
||||
add_pending_oid(&revs, "HEAD", &new->object.oid, UNINTERESTING);
|
||||
|
||||
refs = revs.pending;
|
||||
revs.leak_pending = 1;
|
||||
|
@ -833,7 +817,8 @@ static int switch_branches(const struct checkout_opts *opts,
|
|||
int flag, writeout_error = 0;
|
||||
memset(&old, 0, sizeof(old));
|
||||
old.path = path_to_free = resolve_refdup("HEAD", 0, rev.hash, &flag);
|
||||
old.commit = lookup_commit_reference_gently(rev.hash, 1);
|
||||
if (old.path)
|
||||
old.commit = lookup_commit_reference_gently(&rev, 1);
|
||||
if (!(flag & REF_ISSYMREF))
|
||||
old.path = NULL;
|
||||
|
||||
|
@ -873,7 +858,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
|
|||
}
|
||||
|
||||
if (starts_with(var, "submodule."))
|
||||
return parse_submodule_config_option(var, value);
|
||||
return submodule_config(var, value, NULL);
|
||||
|
||||
return git_xmerge_config(var, value, NULL);
|
||||
}
|
||||
|
@ -1047,10 +1032,10 @@ static int parse_branchname_arg(int argc, const char **argv,
|
|||
else
|
||||
new->path = NULL; /* not an existing branch */
|
||||
|
||||
new->commit = lookup_commit_reference_gently(rev->hash, 1);
|
||||
new->commit = lookup_commit_reference_gently(rev, 1);
|
||||
if (!new->commit) {
|
||||
/* not a commit */
|
||||
*source_tree = parse_tree_indirect(rev->hash);
|
||||
*source_tree = parse_tree_indirect(rev);
|
||||
} else {
|
||||
parse_commit_or_die(new->commit);
|
||||
*source_tree = new->commit->tree;
|
||||
|
@ -1181,9 +1166,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||
N_("second guess 'git checkout <no-such-branch>'")),
|
||||
OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
|
||||
N_("do not check if another worktree is holding the given ref")),
|
||||
{ OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
|
||||
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL,
|
||||
"checkout", "control recursive updating of submodules",
|
||||
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
|
||||
PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
|
||||
OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
@ -1214,12 +1199,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||
git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
|
||||
}
|
||||
|
||||
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
|
||||
git_config(submodule_config, NULL);
|
||||
if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
|
||||
set_config_update_recurse_submodules(recurse_submodules);
|
||||
}
|
||||
|
||||
if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
|
||||
die(_("-b, -B and --orphan are mutually exclusive"));
|
||||
|
||||
|
@ -1286,9 +1265,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||
* new_branch && argc > 1 will be caught later.
|
||||
*/
|
||||
if (opts.new_branch && argc == 1)
|
||||
die(_("Cannot update paths and switch to branch '%s' at the same time.\n"
|
||||
"Did you intend to checkout '%s' which can not be resolved as commit?"),
|
||||
opts.new_branch, argv[0]);
|
||||
die(_("'%s' is not a commit and a branch '%s' cannot be created from it"),
|
||||
argv[0], opts.new_branch);
|
||||
|
||||
if (opts.force_detach)
|
||||
die(_("git checkout: --detach does not take a path argument '%s'"),
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "parse-options.h"
|
||||
#include "string-list.h"
|
||||
|
@ -683,7 +684,7 @@ static int filter_by_patterns_cmd(void)
|
|||
for_each_string_list_item(item, &del_list) {
|
||||
int dtype = DT_UNKNOWN;
|
||||
|
||||
if (is_excluded(&dir, item->string, &dtype)) {
|
||||
if (is_excluded(&dir, &the_index, item->string, &dtype)) {
|
||||
*item->string = '\0';
|
||||
changed++;
|
||||
}
|
||||
|
@ -837,8 +838,7 @@ static void interactive_main_loop(void)
|
|||
int ret;
|
||||
ret = menus[*chosen].fn();
|
||||
if (ret != MENU_RETURN_NO_LOOP) {
|
||||
free(chosen);
|
||||
chosen = NULL;
|
||||
FREE_AND_NULL(chosen);
|
||||
if (!del_list.nr) {
|
||||
clean_print_color(CLEAN_COLOR_ERROR);
|
||||
printf_ln(_("No more files to clean, exiting."));
|
||||
|
@ -851,12 +851,43 @@ static void interactive_main_loop(void)
|
|||
quit_cmd();
|
||||
}
|
||||
|
||||
free(chosen);
|
||||
chosen = NULL;
|
||||
FREE_AND_NULL(chosen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void correct_untracked_entries(struct dir_struct *dir)
|
||||
{
|
||||
int src, dst, ign;
|
||||
|
||||
for (src = dst = ign = 0; src < dir->nr; src++) {
|
||||
/* skip paths in ignored[] that cannot be inside entries[src] */
|
||||
while (ign < dir->ignored_nr &&
|
||||
0 <= cmp_dir_entry(&dir->entries[src], &dir->ignored[ign]))
|
||||
ign++;
|
||||
|
||||
if (ign < dir->ignored_nr &&
|
||||
check_dir_entry_contains(dir->entries[src], dir->ignored[ign])) {
|
||||
/* entries[src] contains an ignored path, so we drop it */
|
||||
free(dir->entries[src]);
|
||||
} else {
|
||||
struct dir_entry *ent = dir->entries[src++];
|
||||
|
||||
/* entries[src] does not contain an ignored path, so we keep it */
|
||||
dir->entries[dst++] = ent;
|
||||
|
||||
/* then discard paths in entries[] contained inside entries[src] */
|
||||
while (src < dir->nr &&
|
||||
check_dir_entry_contains(ent, dir->entries[src]))
|
||||
free(dir->entries[src++]);
|
||||
|
||||
/* compensate for the outer loop's loop control */
|
||||
src--;
|
||||
}
|
||||
}
|
||||
dir->nr = dst;
|
||||
}
|
||||
|
||||
int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i, res;
|
||||
|
@ -916,6 +947,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
|||
|
||||
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
|
||||
|
||||
if (remove_directories)
|
||||
dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS;
|
||||
|
||||
if (read_cache() < 0)
|
||||
die(_("index file corrupt"));
|
||||
|
||||
|
@ -930,7 +964,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
|||
PATHSPEC_PREFER_CWD,
|
||||
prefix, argv);
|
||||
|
||||
fill_directory(&dir, &pathspec);
|
||||
fill_directory(&dir, &the_index, &pathspec);
|
||||
correct_untracked_entries(&dir);
|
||||
|
||||
for (i = 0; i < dir.nr; i++) {
|
||||
struct dir_entry *ent = dir.entries[i];
|
||||
|
@ -958,6 +993,12 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
|||
string_list_append(&del_list, rel);
|
||||
}
|
||||
|
||||
for (i = 0; i < dir.nr; i++)
|
||||
free(dir.entries[i]);
|
||||
|
||||
for (i = 0; i < dir.ignored_nr; i++)
|
||||
free(dir.ignored[i]);
|
||||
|
||||
if (interactive && del_list.nr > 0)
|
||||
interactive_main_loop();
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "lockfile.h"
|
||||
#include "parse-options.h"
|
||||
#include "fetch-pack.h"
|
||||
|
@ -40,6 +41,7 @@ static const char * const builtin_clone_usage[] = {
|
|||
|
||||
static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
|
||||
static int option_local = -1, option_no_hardlinks, option_shared;
|
||||
static int option_no_tags;
|
||||
static int option_shallow_submodules;
|
||||
static int deepen;
|
||||
static char *option_template, *option_depth, *option_since;
|
||||
|
@ -120,6 +122,8 @@ static struct option builtin_clone_options[] = {
|
|||
N_("deepen history of shallow clone, excluding rev")),
|
||||
OPT_BOOL(0, "single-branch", &option_single_branch,
|
||||
N_("clone only one branch, HEAD or --branch")),
|
||||
OPT_BOOL(0, "no-tags", &option_no_tags,
|
||||
N_("don't clone any tags, and make later fetches not to follow them")),
|
||||
OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
|
||||
N_("any cloned submodules will be shallow")),
|
||||
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
|
||||
|
@ -357,7 +361,7 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst,
|
|||
* to turn entries with paths relative to the original
|
||||
* absolute, so that they can be used in the new repository.
|
||||
*/
|
||||
FILE *in = fopen(src->buf, "r");
|
||||
FILE *in = xfopen(src->buf, "r");
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
|
||||
while (strbuf_getline(&line, in) != EOF) {
|
||||
|
@ -563,7 +567,7 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
|
|||
} else
|
||||
get_fetch_map(refs, refspec, &tail, 0);
|
||||
|
||||
if (!option_mirror && !option_single_branch)
|
||||
if (!option_mirror && !option_single_branch && !option_no_tags)
|
||||
get_fetch_map(refs, tag_refspec, &tail, 0);
|
||||
|
||||
return local_refs;
|
||||
|
@ -652,7 +656,7 @@ static void update_remote_refs(const struct ref *refs,
|
|||
|
||||
if (refs) {
|
||||
write_remote_refs(mapped_refs);
|
||||
if (option_single_branch)
|
||||
if (option_single_branch && !option_no_tags)
|
||||
write_followtags(refs, msg);
|
||||
}
|
||||
|
||||
|
@ -682,7 +686,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
|
|||
install_branch_config(0, head, option_origin, our->name);
|
||||
}
|
||||
} else if (our) {
|
||||
struct commit *c = lookup_commit_reference(our->old_oid.hash);
|
||||
struct commit *c = lookup_commit_reference(&our->old_oid);
|
||||
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
|
||||
update_ref(msg, "HEAD", c->object.oid.hash,
|
||||
NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
|
||||
|
@ -739,7 +743,7 @@ static int checkout(int submodule_progress)
|
|||
opts.src_index = &the_index;
|
||||
opts.dst_index = &the_index;
|
||||
|
||||
tree = parse_tree_indirect(oid.hash);
|
||||
tree = parse_tree_indirect(&oid);
|
||||
parse_tree(tree);
|
||||
init_tree_desc(&t, tree->buffer, tree->size);
|
||||
if (unpack_trees(1, &t, &opts) < 0)
|
||||
|
@ -773,7 +777,9 @@ static int checkout(int submodule_progress)
|
|||
|
||||
static int write_one_config(const char *key, const char *value, void *data)
|
||||
{
|
||||
return git_config_set_multivar_gently(key, value ? value : "true", "^$", 0);
|
||||
return git_config_set_multivar_gently(key,
|
||||
value ? value : "true",
|
||||
CONFIG_REGEX_NONE, 0);
|
||||
}
|
||||
|
||||
static void write_config(struct string_list *config)
|
||||
|
@ -1035,6 +1041,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
git_config_set(key.buf, repo);
|
||||
strbuf_reset(&key);
|
||||
|
||||
if (option_no_tags) {
|
||||
strbuf_addf(&key, "remote.%s.tagOpt", option_origin);
|
||||
git_config_set(key.buf, "--no-tags");
|
||||
strbuf_reset(&key);
|
||||
}
|
||||
|
||||
if (option_required_reference.nr || option_optional_reference.nr)
|
||||
setup_reference();
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "strbuf.h"
|
||||
#include "parse-options.h"
|
||||
#include "string-list.h"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) Linus Torvalds, 2005
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "commit.h"
|
||||
#include "tree.h"
|
||||
#include "builtin.h"
|
||||
|
@ -58,7 +59,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
|
|||
if (get_sha1_commit(argv[i], oid.hash))
|
||||
die("Not a valid object name %s", argv[i]);
|
||||
assert_sha1_type(oid.hash, OBJ_COMMIT);
|
||||
new_parent(lookup_commit(oid.hash), &parents);
|
||||
new_parent(lookup_commit(&oid), &parents);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "lockfile.h"
|
||||
#include "cache-tree.h"
|
||||
#include "color.h"
|
||||
|
@ -253,7 +254,8 @@ static int list_paths(struct string_list *list, const char *with_tree,
|
|||
|
||||
if (with_tree) {
|
||||
char *max_prefix = common_prefix(pattern);
|
||||
overlay_tree_on_cache(with_tree, max_prefix ? max_prefix : prefix);
|
||||
overlay_tree_on_index(&the_index, with_tree,
|
||||
max_prefix ? max_prefix : prefix);
|
||||
free(max_prefix);
|
||||
}
|
||||
|
||||
|
@ -313,7 +315,7 @@ static void create_base_index(const struct commit *current_head)
|
|||
opts.dst_index = &the_index;
|
||||
|
||||
opts.fn = oneway_merge;
|
||||
tree = parse_tree_indirect(current_head->object.oid.hash);
|
||||
tree = parse_tree_indirect(¤t_head->object.oid);
|
||||
if (!tree)
|
||||
die(_("failed to unpack HEAD tree object"));
|
||||
parse_tree(tree);
|
||||
|
@ -1263,6 +1265,10 @@ static int parse_status_slot(const char *slot)
|
|||
return WT_STATUS_NOBRANCH;
|
||||
if (!strcasecmp(slot, "unmerged"))
|
||||
return WT_STATUS_UNMERGED;
|
||||
if (!strcasecmp(slot, "localBranch"))
|
||||
return WT_STATUS_LOCAL_BRANCH;
|
||||
if (!strcasecmp(slot, "remoteBranch"))
|
||||
return WT_STATUS_REMOTE_BRANCH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1291,6 +1297,10 @@ static int git_status_config(const char *k, const char *v, void *cb)
|
|||
status_deferred_config.show_branch = git_config_bool(k, v);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(k, "status.showstash")) {
|
||||
s->show_stash = git_config_bool(k, v);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
|
||||
s->use_color = git_config_colorbool(k, v);
|
||||
return 0;
|
||||
|
@ -1339,6 +1349,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
|
|||
N_("show status concisely"), STATUS_FORMAT_SHORT),
|
||||
OPT_BOOL('b', "branch", &s.show_branch,
|
||||
N_("show branch information")),
|
||||
OPT_BOOL(0, "show-stash", &s.show_stash,
|
||||
N_("show stash information")),
|
||||
{ OPTION_CALLBACK, 0, "porcelain", &status_format,
|
||||
N_("version"), N_("machine-readable output"),
|
||||
PARSE_OPT_OPTARG, opt_parse_porcelain },
|
||||
|
@ -1430,7 +1442,7 @@ static void print_summary(const char *prefix, const struct object_id *oid,
|
|||
struct strbuf author_ident = STRBUF_INIT;
|
||||
struct strbuf committer_ident = STRBUF_INIT;
|
||||
|
||||
commit = lookup_commit(oid->hash);
|
||||
commit = lookup_commit(oid);
|
||||
if (!commit)
|
||||
die(_("couldn't look up newly created commit"));
|
||||
if (parse_commit(commit))
|
||||
|
@ -1654,7 +1666,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||
if (get_sha1("HEAD", oid.hash))
|
||||
current_head = NULL;
|
||||
else {
|
||||
current_head = lookup_commit_or_die(oid.hash, "HEAD");
|
||||
current_head = lookup_commit_or_die(&oid, "HEAD");
|
||||
if (parse_commit(current_head))
|
||||
die(_("could not parse HEAD commit"));
|
||||
}
|
||||
|
@ -1695,10 +1707,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||
if (!reflog_msg)
|
||||
reflog_msg = "commit (merge)";
|
||||
pptr = commit_list_append(current_head, pptr);
|
||||
fp = fopen(git_path_merge_head(), "r");
|
||||
if (fp == NULL)
|
||||
die_errno(_("could not open '%s' for reading"),
|
||||
git_path_merge_head());
|
||||
fp = xfopen(git_path_merge_head(), "r");
|
||||
while (strbuf_getline_lf(&m, fp) != EOF) {
|
||||
struct commit *parent;
|
||||
|
||||
|
@ -1735,7 +1744,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||
|
||||
if (verbose || /* Truncate the message just before the diff, if any. */
|
||||
cleanup_mode == CLEANUP_SCISSORS)
|
||||
wt_status_truncate_message_at_cut_line(&sb);
|
||||
strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len));
|
||||
|
||||
if (cleanup_mode != CLEANUP_NONE)
|
||||
strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL);
|
||||
|
@ -1758,7 +1767,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||
append_merge_tag_headers(parents, &tail);
|
||||
}
|
||||
|
||||
if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->sha1,
|
||||
if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->oid.hash,
|
||||
parents, oid.hash, author_ident.buf, sign_commit, extra)) {
|
||||
rollback_index_files();
|
||||
die(_("failed to write commit object"));
|
||||
|
@ -1805,7 +1814,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||
cfg = init_copy_notes_for_rewrite("amend");
|
||||
if (cfg) {
|
||||
/* we are amending, so current_head is not NULL */
|
||||
copy_note_for_rewrite(cfg, current_head->object.oid.hash, oid.hash);
|
||||
copy_note_for_rewrite(cfg, ¤t_head->object.oid, &oid);
|
||||
finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
|
||||
}
|
||||
run_rewrite_hook(¤t_head->object.oid, &oid);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "color.h"
|
||||
#include "parse-options.h"
|
||||
#include "urlmatch.h"
|
||||
|
@ -214,8 +215,7 @@ static int get_value(const char *key_, const char *regex_)
|
|||
key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
|
||||
if (regcomp(key_regexp, key, REG_EXTENDED)) {
|
||||
error("invalid key pattern: %s", key_);
|
||||
free(key_regexp);
|
||||
key_regexp = NULL;
|
||||
FREE_AND_NULL(key_regexp);
|
||||
ret = CONFIG_INVALID_PATTERN;
|
||||
goto free_strings;
|
||||
}
|
||||
|
@ -235,15 +235,14 @@ static int get_value(const char *key_, const char *regex_)
|
|||
regexp = (regex_t*)xmalloc(sizeof(regex_t));
|
||||
if (regcomp(regexp, regex_, REG_EXTENDED)) {
|
||||
error("invalid pattern: %s", regex_);
|
||||
free(regexp);
|
||||
regexp = NULL;
|
||||
FREE_AND_NULL(regexp);
|
||||
ret = CONFIG_INVALID_PATTERN;
|
||||
goto free_strings;
|
||||
}
|
||||
}
|
||||
|
||||
git_config_with_options(collect_config, &values,
|
||||
&given_config_source, &config_options);
|
||||
config_with_options(collect_config, &values,
|
||||
&given_config_source, &config_options);
|
||||
|
||||
ret = !values.nr;
|
||||
|
||||
|
@ -320,8 +319,8 @@ static void get_color(const char *var, const char *def_color)
|
|||
get_color_slot = var;
|
||||
get_color_found = 0;
|
||||
parsed_color[0] = '\0';
|
||||
git_config_with_options(git_get_color_config, NULL,
|
||||
&given_config_source, &config_options);
|
||||
config_with_options(git_get_color_config, NULL,
|
||||
&given_config_source, &config_options);
|
||||
|
||||
if (!get_color_found && def_color) {
|
||||
if (color_parse(def_color, parsed_color) < 0)
|
||||
|
@ -352,8 +351,8 @@ static int get_colorbool(const char *var, int print)
|
|||
get_colorbool_found = -1;
|
||||
get_diff_color_found = -1;
|
||||
get_color_ui_found = -1;
|
||||
git_config_with_options(git_get_colorbool_config, NULL,
|
||||
&given_config_source, &config_options);
|
||||
config_with_options(git_get_colorbool_config, NULL,
|
||||
&given_config_source, &config_options);
|
||||
|
||||
if (get_colorbool_found < 0) {
|
||||
if (!strcmp(get_colorbool_slot, "color.diff"))
|
||||
|
@ -441,8 +440,8 @@ static int get_urlmatch(const char *var, const char *url)
|
|||
show_keys = 1;
|
||||
}
|
||||
|
||||
git_config_with_options(urlmatch_config_entry, &config,
|
||||
&given_config_source, &config_options);
|
||||
config_with_options(urlmatch_config_entry, &config,
|
||||
&given_config_source, &config_options);
|
||||
|
||||
ret = !values.nr;
|
||||
|
||||
|
@ -496,6 +495,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
|||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
|
||||
if (use_local_config && nongit)
|
||||
die(_("--local can only be used inside a git repository"));
|
||||
|
||||
if (given_config_source.file &&
|
||||
!strcmp(given_config_source.file, "-")) {
|
||||
given_config_source.file = NULL;
|
||||
|
@ -535,6 +537,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
|||
config_options.respect_includes = !given_config_source.file;
|
||||
else
|
||||
config_options.respect_includes = respect_includes_opt;
|
||||
if (!nongit) {
|
||||
config_options.commondir = get_git_common_dir();
|
||||
config_options.git_dir = get_git_dir();
|
||||
}
|
||||
|
||||
if (end_null) {
|
||||
term = '\0';
|
||||
|
@ -579,9 +585,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
|||
|
||||
if (actions == ACTION_LIST) {
|
||||
check_argc(argc, 0, 0);
|
||||
if (git_config_with_options(show_all_config, NULL,
|
||||
&given_config_source,
|
||||
&config_options) < 0) {
|
||||
if (config_with_options(show_all_config, NULL,
|
||||
&given_config_source,
|
||||
&config_options) < 0) {
|
||||
if (given_config_source.file)
|
||||
die_errno("unable to read config file '%s'",
|
||||
given_config_source.file);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "builtin.h"
|
||||
#include "parse-options.h"
|
||||
|
|
|
@ -10,9 +10,9 @@ int cmd_credential(int argc, const char **argv, const char *prefix)
|
|||
const char *op;
|
||||
struct credential c = CREDENTIAL_INIT;
|
||||
|
||||
op = argv[1];
|
||||
if (!op)
|
||||
if (argc != 2 || !strcmp(argv[1], "-h"))
|
||||
usage(usage_msg);
|
||||
op = argv[1];
|
||||
|
||||
if (credential_read(&c, stdin) < 0)
|
||||
die("unable to read credential from stdin");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "lockfile.h"
|
||||
#include "commit.h"
|
||||
#include "tag.h"
|
||||
|
@ -53,8 +54,10 @@ static const char *prio_names[] = {
|
|||
N_("head"), N_("lightweight"), N_("annotated"),
|
||||
};
|
||||
|
||||
static int commit_name_cmp(const struct commit_name *cn1,
|
||||
const struct commit_name *cn2, const void *peeled)
|
||||
static int commit_name_cmp(const void *unused_cmp_data,
|
||||
const struct commit_name *cn1,
|
||||
const struct commit_name *cn2,
|
||||
const void *peeled)
|
||||
{
|
||||
return oidcmp(&cn1->peeled, peeled ? peeled : &cn2->peeled);
|
||||
}
|
||||
|
@ -79,13 +82,13 @@ static int replace_name(struct commit_name *e,
|
|||
struct tag *t;
|
||||
|
||||
if (!e->tag) {
|
||||
t = lookup_tag(e->oid.hash);
|
||||
t = lookup_tag(&e->oid);
|
||||
if (!t || parse_tag(t))
|
||||
return 1;
|
||||
e->tag = t;
|
||||
}
|
||||
|
||||
t = lookup_tag(oid->hash);
|
||||
t = lookup_tag(oid);
|
||||
if (!t || parse_tag(t))
|
||||
return 0;
|
||||
*tag = t;
|
||||
|
@ -245,7 +248,7 @@ static unsigned long finish_depth_computation(
|
|||
static void display_name(struct commit_name *n)
|
||||
{
|
||||
if (n->prio == 2 && !n->tag) {
|
||||
n->tag = lookup_tag(n->oid.hash);
|
||||
n->tag = lookup_tag(&n->oid);
|
||||
if (!n->tag || parse_tag(n->tag))
|
||||
die(_("annotated tag %s not available"), n->path);
|
||||
}
|
||||
|
@ -281,7 +284,7 @@ static void describe(const char *arg, int last_one)
|
|||
|
||||
if (get_oid(arg, &oid))
|
||||
die(_("Not a valid object name %s"), arg);
|
||||
cmit = lookup_commit_reference(oid.hash);
|
||||
cmit = lookup_commit_reference(&oid);
|
||||
if (!cmit)
|
||||
die(_("%s is not a valid '%s' object"), arg, commit_type);
|
||||
|
||||
|
@ -309,7 +312,7 @@ static void describe(const char *arg, int last_one)
|
|||
struct commit *c;
|
||||
struct commit_name *n = hashmap_iter_first(&names, &iter);
|
||||
for (; n; n = hashmap_iter_next(&iter)) {
|
||||
c = lookup_commit_reference_gently(n->peeled.hash, 1);
|
||||
c = lookup_commit_reference_gently(&n->peeled, 1);
|
||||
if (c)
|
||||
c->util = n;
|
||||
}
|
||||
|
@ -500,7 +503,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
|
|||
return cmd_name_rev(args.argc, args.argv, prefix);
|
||||
}
|
||||
|
||||
hashmap_init(&names, (hashmap_cmp_fn) commit_name_cmp, 0);
|
||||
hashmap_init(&names, (hashmap_cmp_fn) commit_name_cmp, NULL, 0);
|
||||
for_each_rawref(get_name, NULL);
|
||||
if (!names.size && !always)
|
||||
die(_("No names found, cannot describe anything."));
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) Linus Torvalds, 2005
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "diff.h"
|
||||
#include "commit.h"
|
||||
#include "revision.h"
|
||||
|
@ -20,9 +21,12 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
|
|||
int result;
|
||||
unsigned options = 0;
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage(diff_files_usage);
|
||||
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
init_revisions(&rev, prefix);
|
||||
gitmodules_config();
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
rev.abbrev = 0;
|
||||
precompose_argv(argc, argv);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "diff.h"
|
||||
#include "commit.h"
|
||||
#include "revision.h"
|
||||
|
@ -17,9 +18,12 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
|
|||
int i;
|
||||
int result;
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage(diff_cache_usage);
|
||||
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
init_revisions(&rev, prefix);
|
||||
gitmodules_config();
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
rev.abbrev = 0;
|
||||
precompose_argv(argc, argv);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "diff.h"
|
||||
#include "commit.h"
|
||||
#include "log-tree.h"
|
||||
|
@ -7,9 +8,9 @@
|
|||
|
||||
static struct rev_info log_tree_opt;
|
||||
|
||||
static int diff_tree_commit_sha1(const struct object_id *oid)
|
||||
static int diff_tree_commit_oid(const struct object_id *oid)
|
||||
{
|
||||
struct commit *commit = lookup_commit_reference(oid->hash);
|
||||
struct commit *commit = lookup_commit_reference(oid);
|
||||
if (!commit)
|
||||
return -1;
|
||||
return log_tree_commit(&log_tree_opt, commit);
|
||||
|
@ -23,7 +24,7 @@ static int stdin_diff_commit(struct commit *commit, const char *p)
|
|||
|
||||
/* Graft the fake parents locally to the commit */
|
||||
while (isspace(*p++) && !parse_oid_hex(p, &oid, &p)) {
|
||||
struct commit *parent = lookup_commit(oid.hash);
|
||||
struct commit *parent = lookup_commit(&oid);
|
||||
if (!pptr) {
|
||||
/* Free the real parent list */
|
||||
free_commit_list(commit->parents);
|
||||
|
@ -44,13 +45,13 @@ static int stdin_diff_trees(struct tree *tree1, const char *p)
|
|||
struct tree *tree2;
|
||||
if (!isspace(*p++) || parse_oid_hex(p, &oid, &p) || *p)
|
||||
return error("Need exactly two trees, separated by a space");
|
||||
tree2 = lookup_tree(oid.hash);
|
||||
tree2 = lookup_tree(&oid);
|
||||
if (!tree2 || parse_tree(tree2))
|
||||
return -1;
|
||||
printf("%s %s\n", oid_to_hex(&tree1->object.oid),
|
||||
oid_to_hex(&tree2->object.oid));
|
||||
diff_tree_sha1(tree1->object.oid.hash, tree2->object.oid.hash,
|
||||
"", &log_tree_opt.diffopt);
|
||||
diff_tree_oid(&tree1->object.oid, &tree2->object.oid,
|
||||
"", &log_tree_opt.diffopt);
|
||||
log_tree_diff_flush(&log_tree_opt);
|
||||
return 0;
|
||||
}
|
||||
|
@ -67,7 +68,7 @@ static int diff_tree_stdin(char *line)
|
|||
line[len-1] = 0;
|
||||
if (parse_oid_hex(line, &oid, &p))
|
||||
return -1;
|
||||
obj = parse_object(oid.hash);
|
||||
obj = parse_object(&oid);
|
||||
if (!obj)
|
||||
return -1;
|
||||
if (obj->type == OBJ_COMMIT)
|
||||
|
@ -98,16 +99,18 @@ static void diff_tree_tweak_rev(struct rev_info *rev, struct setup_revision_opt
|
|||
|
||||
int cmd_diff_tree(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int nr_sha1;
|
||||
char line[1000];
|
||||
struct object *tree1, *tree2;
|
||||
static struct rev_info *opt = &log_tree_opt;
|
||||
struct setup_revision_opt s_r_opt;
|
||||
int read_stdin = 0;
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage(diff_tree_usage);
|
||||
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
init_revisions(opt, prefix);
|
||||
gitmodules_config();
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
opt->abbrev = 0;
|
||||
opt->diff = 1;
|
||||
opt->disable_stdin = 1;
|
||||
|
@ -128,19 +131,20 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
|
||||
/*
|
||||
* NOTE! We expect "a ^b" to be equal to "a..b", so we
|
||||
* reverse the order of the objects if the second one
|
||||
* is marked UNINTERESTING.
|
||||
* NOTE! We expect "a..b" to expand to "^a b" but it is
|
||||
* perfectly valid for revision range parser to yield "b ^a",
|
||||
* which means the same thing. If we get the latter, i.e. the
|
||||
* second one is marked UNINTERESTING, we recover the original
|
||||
* order the user gave, i.e. "a..b", by swapping the trees.
|
||||
*/
|
||||
nr_sha1 = opt->pending.nr;
|
||||
switch (nr_sha1) {
|
||||
switch (opt->pending.nr) {
|
||||
case 0:
|
||||
if (!read_stdin)
|
||||
usage(diff_tree_usage);
|
||||
break;
|
||||
case 1:
|
||||
tree1 = opt->pending.objects[0].item;
|
||||
diff_tree_commit_sha1(&tree1->oid);
|
||||
diff_tree_commit_oid(&tree1->oid);
|
||||
break;
|
||||
case 2:
|
||||
tree1 = opt->pending.objects[0].item;
|
||||
|
@ -148,9 +152,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
|
|||
if (tree2->flags & UNINTERESTING) {
|
||||
SWAP(tree2, tree1);
|
||||
}
|
||||
diff_tree_sha1(tree1->oid.hash,
|
||||
tree2->oid.hash,
|
||||
"", &opt->diffopt);
|
||||
diff_tree_oid(&tree1->oid, &tree2->oid, "", &opt->diffopt);
|
||||
log_tree_diff_flush(opt);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (c) 2006 Junio C Hamano
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "lockfile.h"
|
||||
#include "color.h"
|
||||
#include "commit.h"
|
||||
|
@ -20,23 +21,22 @@
|
|||
#define DIFF_NO_INDEX_EXPLICIT 1
|
||||
#define DIFF_NO_INDEX_IMPLICIT 2
|
||||
|
||||
struct blobinfo {
|
||||
struct object_id oid;
|
||||
const char *name;
|
||||
unsigned mode;
|
||||
};
|
||||
|
||||
static const char builtin_diff_usage[] =
|
||||
"git diff [<options>] [<commit> [<commit>]] [--] [<path>...]";
|
||||
|
||||
static const char *blob_path(struct object_array_entry *entry)
|
||||
{
|
||||
return entry->path ? entry->path : entry->name;
|
||||
}
|
||||
|
||||
static void stuff_change(struct diff_options *opt,
|
||||
unsigned old_mode, unsigned new_mode,
|
||||
const struct object_id *old_oid,
|
||||
const struct object_id *new_oid,
|
||||
int old_oid_valid,
|
||||
int new_oid_valid,
|
||||
const char *old_name,
|
||||
const char *new_name)
|
||||
const char *old_path,
|
||||
const char *new_path)
|
||||
{
|
||||
struct diff_filespec *one, *two;
|
||||
|
||||
|
@ -47,25 +47,25 @@ static void stuff_change(struct diff_options *opt,
|
|||
if (DIFF_OPT_TST(opt, REVERSE_DIFF)) {
|
||||
SWAP(old_mode, new_mode);
|
||||
SWAP(old_oid, new_oid);
|
||||
SWAP(old_name, new_name);
|
||||
SWAP(old_path, new_path);
|
||||
}
|
||||
|
||||
if (opt->prefix &&
|
||||
(strncmp(old_name, opt->prefix, opt->prefix_length) ||
|
||||
strncmp(new_name, opt->prefix, opt->prefix_length)))
|
||||
(strncmp(old_path, opt->prefix, opt->prefix_length) ||
|
||||
strncmp(new_path, opt->prefix, opt->prefix_length)))
|
||||
return;
|
||||
|
||||
one = alloc_filespec(old_name);
|
||||
two = alloc_filespec(new_name);
|
||||
fill_filespec(one, old_oid->hash, old_oid_valid, old_mode);
|
||||
fill_filespec(two, new_oid->hash, new_oid_valid, new_mode);
|
||||
one = alloc_filespec(old_path);
|
||||
two = alloc_filespec(new_path);
|
||||
fill_filespec(one, old_oid, old_oid_valid, old_mode);
|
||||
fill_filespec(two, new_oid, new_oid_valid, new_mode);
|
||||
|
||||
diff_queue(&diff_queued_diff, one, two);
|
||||
}
|
||||
|
||||
static int builtin_diff_b_f(struct rev_info *revs,
|
||||
int argc, const char **argv,
|
||||
struct blobinfo *blob)
|
||||
struct object_array_entry **blob)
|
||||
{
|
||||
/* Blob vs file in the working tree*/
|
||||
struct stat st;
|
||||
|
@ -84,14 +84,15 @@ static int builtin_diff_b_f(struct rev_info *revs,
|
|||
|
||||
diff_set_mnemonic_prefix(&revs->diffopt, "o/", "w/");
|
||||
|
||||
if (blob[0].mode == S_IFINVALID)
|
||||
blob[0].mode = canon_mode(st.st_mode);
|
||||
if (blob[0]->mode == S_IFINVALID)
|
||||
blob[0]->mode = canon_mode(st.st_mode);
|
||||
|
||||
stuff_change(&revs->diffopt,
|
||||
blob[0].mode, canon_mode(st.st_mode),
|
||||
&blob[0].oid, &null_oid,
|
||||
blob[0]->mode, canon_mode(st.st_mode),
|
||||
&blob[0]->item->oid, &null_oid,
|
||||
1, 0,
|
||||
path, path);
|
||||
blob[0]->path ? blob[0]->path : path,
|
||||
path);
|
||||
diffcore_std(&revs->diffopt);
|
||||
diff_flush(&revs->diffopt);
|
||||
return 0;
|
||||
|
@ -99,24 +100,24 @@ static int builtin_diff_b_f(struct rev_info *revs,
|
|||
|
||||
static int builtin_diff_blobs(struct rev_info *revs,
|
||||
int argc, const char **argv,
|
||||
struct blobinfo *blob)
|
||||
struct object_array_entry **blob)
|
||||
{
|
||||
unsigned mode = canon_mode(S_IFREG | 0644);
|
||||
|
||||
if (argc > 1)
|
||||
usage(builtin_diff_usage);
|
||||
|
||||
if (blob[0].mode == S_IFINVALID)
|
||||
blob[0].mode = mode;
|
||||
if (blob[0]->mode == S_IFINVALID)
|
||||
blob[0]->mode = mode;
|
||||
|
||||
if (blob[1].mode == S_IFINVALID)
|
||||
blob[1].mode = mode;
|
||||
if (blob[1]->mode == S_IFINVALID)
|
||||
blob[1]->mode = mode;
|
||||
|
||||
stuff_change(&revs->diffopt,
|
||||
blob[0].mode, blob[1].mode,
|
||||
&blob[0].oid, &blob[1].oid,
|
||||
blob[0]->mode, blob[1]->mode,
|
||||
&blob[0]->item->oid, &blob[1]->item->oid,
|
||||
1, 1,
|
||||
blob[0].name, blob[1].name);
|
||||
blob_path(blob[0]), blob_path(blob[1]));
|
||||
diffcore_std(&revs->diffopt);
|
||||
diff_flush(&revs->diffopt);
|
||||
return 0;
|
||||
|
@ -174,7 +175,7 @@ static int builtin_diff_tree(struct rev_info *revs,
|
|||
swap = 1;
|
||||
oid[swap] = &ent0->item->oid;
|
||||
oid[1 - swap] = &ent1->item->oid;
|
||||
diff_tree_sha1(oid[0]->hash, oid[1]->hash, "", &revs->diffopt);
|
||||
diff_tree_oid(oid[0], oid[1], "", &revs->diffopt);
|
||||
log_tree_diff_flush(revs);
|
||||
return 0;
|
||||
}
|
||||
|
@ -194,7 +195,7 @@ static int builtin_diff_combined(struct rev_info *revs,
|
|||
revs->dense_combined_merges = revs->combine_merges = 1;
|
||||
for (i = 1; i < ents; i++)
|
||||
oid_array_append(&parents, &ent[i].item->oid);
|
||||
diff_tree_combined(ent[0].item->oid.hash, &parents,
|
||||
diff_tree_combined(&ent[0].item->oid, &parents,
|
||||
revs->dense_combined_merges, revs);
|
||||
oid_array_clear(&parents);
|
||||
return 0;
|
||||
|
@ -259,7 +260,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
|||
struct rev_info rev;
|
||||
struct object_array ent = OBJECT_ARRAY_INIT;
|
||||
int blobs = 0, paths = 0;
|
||||
struct blobinfo blob[2];
|
||||
struct object_array_entry *blob[2];
|
||||
int nongit = 0, no_index = 0;
|
||||
int result = 0;
|
||||
|
||||
|
@ -381,7 +382,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
|||
add_head_to_pending(&rev);
|
||||
if (!rev.pending.nr) {
|
||||
struct tree *tree;
|
||||
tree = lookup_tree(EMPTY_TREE_SHA1_BIN);
|
||||
tree = lookup_tree(&empty_tree_oid);
|
||||
add_pending_object(&rev, &tree->object, "HEAD");
|
||||
}
|
||||
break;
|
||||
|
@ -395,7 +396,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
|||
const char *name = entry->name;
|
||||
int flags = (obj->flags & UNINTERESTING);
|
||||
if (!obj->parsed)
|
||||
obj = parse_object(obj->oid.hash);
|
||||
obj = parse_object(&obj->oid);
|
||||
obj = deref_tag(obj, NULL, 0);
|
||||
if (!obj)
|
||||
die(_("invalid object '%s' given."), name);
|
||||
|
@ -408,9 +409,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
|||
} else if (obj->type == OBJ_BLOB) {
|
||||
if (2 <= blobs)
|
||||
die(_("more than two blobs given: '%s'"), name);
|
||||
hashcpy(blob[blobs].oid.hash, obj->oid.hash);
|
||||
blob[blobs].name = name;
|
||||
blob[blobs].mode = entry->mode;
|
||||
blob[blobs] = entry;
|
||||
blobs++;
|
||||
|
||||
} else {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* Copyright (C) 2016 Johannes Schindelin
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "builtin.h"
|
||||
#include "run-command.h"
|
||||
#include "exec_cmd.h"
|
||||
|
@ -129,8 +130,10 @@ struct working_tree_entry {
|
|||
char path[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
static int working_tree_entry_cmp(struct working_tree_entry *a,
|
||||
struct working_tree_entry *b, void *keydata)
|
||||
static int working_tree_entry_cmp(const void *unused_cmp_data,
|
||||
struct working_tree_entry *a,
|
||||
struct working_tree_entry *b,
|
||||
void *unused_keydata)
|
||||
{
|
||||
return strcmp(a->path, b->path);
|
||||
}
|
||||
|
@ -145,7 +148,9 @@ struct pair_entry {
|
|||
const char path[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
static int pair_cmp(struct pair_entry *a, struct pair_entry *b, void *keydata)
|
||||
static int pair_cmp(const void *unused_cmp_data,
|
||||
struct pair_entry *a, struct pair_entry *b,
|
||||
void *unused_keydata)
|
||||
{
|
||||
return strcmp(a->path, b->path);
|
||||
}
|
||||
|
@ -173,7 +178,9 @@ struct path_entry {
|
|||
char path[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
static int path_entry_cmp(struct path_entry *a, struct path_entry *b, void *key)
|
||||
static int path_entry_cmp(const void *unused_cmp_data,
|
||||
struct path_entry *a, struct path_entry *b,
|
||||
void *key)
|
||||
{
|
||||
return strcmp(a->path, key ? key : b->path);
|
||||
}
|
||||
|
@ -226,6 +233,7 @@ static void changed_files(struct hashmap *result, const char *index_path,
|
|||
hashmap_entry_init(entry, strhash(buf.buf));
|
||||
hashmap_add(result, entry);
|
||||
}
|
||||
fclose(fp);
|
||||
if (finish_command(&diff_files))
|
||||
die("diff-files did not exit properly");
|
||||
strbuf_release(&index_env);
|
||||
|
@ -365,9 +373,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
wtdir_len = wtdir.len;
|
||||
|
||||
hashmap_init(&working_tree_dups,
|
||||
(hashmap_cmp_fn)working_tree_entry_cmp, 0);
|
||||
hashmap_init(&submodules, (hashmap_cmp_fn)pair_cmp, 0);
|
||||
hashmap_init(&symlinks2, (hashmap_cmp_fn)pair_cmp, 0);
|
||||
(hashmap_cmp_fn)working_tree_entry_cmp, NULL, 0);
|
||||
hashmap_init(&submodules, (hashmap_cmp_fn)pair_cmp, NULL, 0);
|
||||
hashmap_init(&symlinks2, (hashmap_cmp_fn)pair_cmp, NULL, 0);
|
||||
|
||||
child.no_stdin = 1;
|
||||
child.git_cmd = 1;
|
||||
|
@ -439,8 +447,10 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
}
|
||||
|
||||
if (lmode && status != 'C') {
|
||||
if (checkout_path(lmode, &loid, src_path, &lstate))
|
||||
return error("could not write '%s'", src_path);
|
||||
if (checkout_path(lmode, &loid, src_path, &lstate)) {
|
||||
ret = error("could not write '%s'", src_path);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
if (rmode && !S_ISLNK(rmode)) {
|
||||
|
@ -456,9 +466,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
hashmap_add(&working_tree_dups, entry);
|
||||
|
||||
if (!use_wt_file(workdir, dst_path, &roid)) {
|
||||
if (checkout_path(rmode, &roid, dst_path, &rstate))
|
||||
return error("could not write '%s'",
|
||||
dst_path);
|
||||
if (checkout_path(rmode, &roid, dst_path,
|
||||
&rstate)) {
|
||||
ret = error("could not write '%s'",
|
||||
dst_path);
|
||||
goto finish;
|
||||
}
|
||||
} else if (!is_null_oid(&roid)) {
|
||||
/*
|
||||
* Changes in the working tree need special
|
||||
|
@ -473,10 +486,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
ADD_CACHE_JUST_APPEND);
|
||||
|
||||
add_path(&rdir, rdir_len, dst_path);
|
||||
if (ensure_leading_directories(rdir.buf))
|
||||
return error("could not create "
|
||||
"directory for '%s'",
|
||||
dst_path);
|
||||
if (ensure_leading_directories(rdir.buf)) {
|
||||
ret = error("could not create "
|
||||
"directory for '%s'",
|
||||
dst_path);
|
||||
goto finish;
|
||||
}
|
||||
add_path(&wtdir, wtdir_len, dst_path);
|
||||
if (symlinks) {
|
||||
if (symlink(wtdir.buf, rdir.buf)) {
|
||||
|
@ -497,13 +512,15 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
if (finish_command(&child)) {
|
||||
ret = error("error occurred running diff --raw");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!i)
|
||||
return 0;
|
||||
goto finish;
|
||||
|
||||
/*
|
||||
* Changes to submodules require special treatment.This loop writes a
|
||||
|
@ -569,9 +586,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
* files through the symlink.
|
||||
*/
|
||||
hashmap_init(&wt_modified, (hashmap_cmp_fn)path_entry_cmp,
|
||||
wtindex.cache_nr);
|
||||
NULL, wtindex.cache_nr);
|
||||
hashmap_init(&tmp_modified, (hashmap_cmp_fn)path_entry_cmp,
|
||||
wtindex.cache_nr);
|
||||
NULL, wtindex.cache_nr);
|
||||
|
||||
for (i = 0; i < wtindex.cache_nr; i++) {
|
||||
struct hashmap_entry dummy;
|
||||
|
@ -626,6 +643,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
exit_cleanup(tmpdir, rc);
|
||||
|
||||
finish:
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
|
||||
free(lbase_dir);
|
||||
free(rbase_dir);
|
||||
strbuf_release(&ldir);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "commit.h"
|
||||
#include "object.h"
|
||||
|
@ -92,8 +93,9 @@ struct anonymized_entry {
|
|||
size_t anon_len;
|
||||
};
|
||||
|
||||
static int anonymized_entry_cmp(const void *va, const void *vb,
|
||||
const void *data)
|
||||
static int anonymized_entry_cmp(const void *unused_cmp_data,
|
||||
const void *va, const void *vb,
|
||||
const void *unused_keydata)
|
||||
{
|
||||
const struct anonymized_entry *a = va, *b = vb;
|
||||
return a->orig_len != b->orig_len ||
|
||||
|
@ -112,7 +114,7 @@ static const void *anonymize_mem(struct hashmap *map,
|
|||
struct anonymized_entry key, *ret;
|
||||
|
||||
if (!map->cmpfn)
|
||||
hashmap_init(map, anonymized_entry_cmp, 0);
|
||||
hashmap_init(map, anonymized_entry_cmp, NULL, 0);
|
||||
|
||||
hashmap_entry_init(&key, memhash(orig, *len));
|
||||
key.orig = orig;
|
||||
|
@ -232,7 +234,7 @@ static void export_blob(const struct object_id *oid)
|
|||
|
||||
if (anonymize) {
|
||||
buf = anonymize_blob(&size);
|
||||
object = (struct object *)lookup_blob(oid->hash);
|
||||
object = (struct object *)lookup_blob(oid);
|
||||
eaten = 0;
|
||||
} else {
|
||||
buf = read_sha1_file(oid->hash, &type, &size);
|
||||
|
@ -240,7 +242,7 @@ static void export_blob(const struct object_id *oid)
|
|||
die ("Could not read blob %s", oid_to_hex(oid));
|
||||
if (check_sha1_signature(oid->hash, buf, size, typename(type)) < 0)
|
||||
die("sha1 mismatch in blob %s", oid_to_hex(oid));
|
||||
object = parse_object_buffer(oid->hash, type, size, buf, &eaten);
|
||||
object = parse_object_buffer(oid, type, size, buf, &eaten);
|
||||
}
|
||||
|
||||
if (!object)
|
||||
|
@ -562,12 +564,12 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
|||
get_object_mark(&commit->parents->item->object) != 0 &&
|
||||
!full_tree) {
|
||||
parse_commit_or_die(commit->parents->item);
|
||||
diff_tree_sha1(commit->parents->item->tree->object.oid.hash,
|
||||
commit->tree->object.oid.hash, "", &rev->diffopt);
|
||||
diff_tree_oid(&commit->parents->item->tree->object.oid,
|
||||
&commit->tree->object.oid, "", &rev->diffopt);
|
||||
}
|
||||
else
|
||||
diff_root_tree_sha1(commit->tree->object.oid.hash,
|
||||
"", &rev->diffopt);
|
||||
diff_root_tree_oid(&commit->tree->object.oid,
|
||||
"", &rev->diffopt);
|
||||
|
||||
/* Export the referenced blobs, and remember the marks. */
|
||||
for (i = 0; i < diff_queued_diff.nr; i++)
|
||||
|
@ -734,6 +736,7 @@ static void handle_tag(const char *name, struct tag *tag)
|
|||
oid_to_hex(&tag->object.oid));
|
||||
case DROP:
|
||||
/* Ignore this tag altogether */
|
||||
free(buf);
|
||||
return;
|
||||
case REWRITE:
|
||||
if (tagged->type != OBJ_COMMIT) {
|
||||
|
@ -765,6 +768,7 @@ static void handle_tag(const char *name, struct tag *tag)
|
|||
(int)(tagger_end - tagger), tagger,
|
||||
tagger == tagger_end ? "" : "\n",
|
||||
(int)message_size, (int)message_size, message ? message : "");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
|
||||
|
@ -777,7 +781,7 @@ static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
|
|||
|
||||
/* handle nested tags */
|
||||
while (tag && tag->object.type == OBJ_TAG) {
|
||||
parse_object(tag->object.oid.hash);
|
||||
parse_object(&tag->object.oid);
|
||||
string_list_append(&extra_refs, full_name)->util = tag;
|
||||
tag = (struct tag *)tag->tagged;
|
||||
}
|
||||
|
@ -905,9 +909,7 @@ static void export_marks(char *file)
|
|||
static void import_marks(char *input_file)
|
||||
{
|
||||
char line[512];
|
||||
FILE *f = fopen(input_file, "r");
|
||||
if (!f)
|
||||
die_errno("cannot read '%s'", input_file);
|
||||
FILE *f = xfopen(input_file, "r");
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
uint32_t mark;
|
||||
|
@ -938,7 +940,7 @@ static void import_marks(char *input_file)
|
|||
/* only commits */
|
||||
continue;
|
||||
|
||||
commit = lookup_commit(oid.hash);
|
||||
commit = lookup_commit(&oid);
|
||||
if (!commit)
|
||||
die("not a commit? can't happen: %s", oid_to_hex(&oid));
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* "git fetch"
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "commit.h"
|
||||
#include "builtin.h"
|
||||
|
@ -73,6 +74,13 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
|
|||
fetch_prune_config = git_config_bool(k, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(k, "submodule.recurse")) {
|
||||
int r = git_config_bool(k, v) ?
|
||||
RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
|
||||
recurse_submodules = r;
|
||||
}
|
||||
|
||||
return git_default_config(k, v, cb);
|
||||
}
|
||||
|
||||
|
@ -636,8 +644,8 @@ static int update_local_ref(struct ref *ref,
|
|||
return r;
|
||||
}
|
||||
|
||||
current = lookup_commit_reference_gently(ref->old_oid.hash, 1);
|
||||
updated = lookup_commit_reference_gently(ref->new_oid.hash, 1);
|
||||
current = lookup_commit_reference_gently(&ref->old_oid, 1);
|
||||
updated = lookup_commit_reference_gently(&ref->new_oid, 1);
|
||||
if (!current || !updated) {
|
||||
const char *msg;
|
||||
const char *what;
|
||||
|
@ -770,7 +778,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
|
|||
continue;
|
||||
}
|
||||
|
||||
commit = lookup_commit_reference_gently(rm->old_oid.hash, 1);
|
||||
commit = lookup_commit_reference_gently(&rm->old_oid,
|
||||
1);
|
||||
if (!commit)
|
||||
rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
|
||||
|
||||
|
@ -940,7 +949,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map,
|
|||
for (ref = stale_refs; ref; ref = ref->next)
|
||||
string_list_append(&refnames, ref->name);
|
||||
|
||||
result = delete_refs(&refnames, 0);
|
||||
result = delete_refs("fetch: prune", &refnames, 0);
|
||||
string_list_clear(&refnames, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
|
@ -341,7 +342,7 @@ static void shortlog(const char *name,
|
|||
const struct object_id *oid = &origin_data->oid;
|
||||
int limit = opts->shortlog_len;
|
||||
|
||||
branch = deref_tag(parse_object(oid->hash), oid_to_hex(oid), GIT_SHA1_HEXSZ);
|
||||
branch = deref_tag(parse_object(oid), oid_to_hex(oid), GIT_SHA1_HEXSZ);
|
||||
if (!branch || branch->type != OBJ_COMMIT)
|
||||
return;
|
||||
|
||||
|
@ -559,14 +560,14 @@ static void find_merge_parents(struct merge_parents *result,
|
|||
* "name" here and we do not want to contaminate its
|
||||
* util field yet.
|
||||
*/
|
||||
obj = parse_object(oid.hash);
|
||||
obj = parse_object(&oid);
|
||||
parent = (struct commit *)peel_to_type(NULL, 0, obj, OBJ_COMMIT);
|
||||
if (!parent)
|
||||
continue;
|
||||
commit_list_insert(parent, &parents);
|
||||
add_merge_parent(result, &obj->oid, &parent->object.oid);
|
||||
}
|
||||
head_commit = lookup_commit(head->hash);
|
||||
head_commit = lookup_commit(head);
|
||||
if (head_commit)
|
||||
commit_list_insert(head_commit, &parents);
|
||||
parents = reduce_heads(parents);
|
||||
|
@ -633,7 +634,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
|
|||
struct commit *head;
|
||||
struct rev_info rev;
|
||||
|
||||
head = lookup_commit_or_die(head_oid.hash, "HEAD");
|
||||
head = lookup_commit_or_die(&head_oid, "HEAD");
|
||||
init_revisions(&rev, NULL);
|
||||
rev.commit_format = CMIT_FMT_ONELINE;
|
||||
rev.ignore_merges = 1;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "object.h"
|
||||
#include "parse-options.h"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "commit.h"
|
||||
#include "tree.h"
|
||||
#include "blob.h"
|
||||
|
@ -280,8 +281,7 @@ static void check_unreachable_object(struct object *obj)
|
|||
free(filename);
|
||||
return;
|
||||
}
|
||||
if (!(f = fopen(filename, "w")))
|
||||
die_errno("Could not open '%s'", filename);
|
||||
f = xfopen(filename, "w");
|
||||
if (obj->type == OBJ_BLOB) {
|
||||
if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))
|
||||
die_errno("Could not write '%s'", filename);
|
||||
|
@ -377,7 +377,7 @@ static int fsck_obj(struct object *obj)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
|
||||
static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
|
||||
unsigned long size, void *buffer, int *eaten)
|
||||
{
|
||||
/*
|
||||
|
@ -385,10 +385,10 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
|
|||
* verify_packfile(), data_valid variable for details.
|
||||
*/
|
||||
struct object *obj;
|
||||
obj = parse_object_buffer(sha1, type, size, buffer, eaten);
|
||||
obj = parse_object_buffer(oid, type, size, buffer, eaten);
|
||||
if (!obj) {
|
||||
errors_found |= ERROR_OBJECT;
|
||||
return error("%s: object corrupt or missing", sha1_to_hex(sha1));
|
||||
return error("%s: object corrupt or missing", oid_to_hex(oid));
|
||||
}
|
||||
obj->flags = HAS_OBJ;
|
||||
return fsck_obj(obj);
|
||||
|
@ -397,7 +397,7 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
|
|||
static int default_refs;
|
||||
|
||||
static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
|
||||
unsigned long timestamp)
|
||||
timestamp_t timestamp)
|
||||
{
|
||||
struct object *obj;
|
||||
|
||||
|
@ -407,7 +407,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
|
|||
if (timestamp && name_objects)
|
||||
add_decoration(fsck_walk_options.object_names,
|
||||
obj,
|
||||
xstrfmt("%s@{%ld}", refname, timestamp));
|
||||
xstrfmt("%s@{%"PRItime"}", refname, timestamp));
|
||||
obj->used = 1;
|
||||
mark_object_reachable(obj);
|
||||
} else {
|
||||
|
@ -418,7 +418,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
|
|||
}
|
||||
|
||||
static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid,
|
||||
const char *email, unsigned long timestamp, int tz,
|
||||
const char *email, timestamp_t timestamp, int tz,
|
||||
const char *message, void *cb_data)
|
||||
{
|
||||
const char *refname = cb_data;
|
||||
|
@ -444,7 +444,7 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,
|
|||
{
|
||||
struct object *obj;
|
||||
|
||||
obj = parse_object(oid->hash);
|
||||
obj = parse_object(oid);
|
||||
if (!obj) {
|
||||
error("%s: invalid sha1 pointer %s", refname, oid_to_hex(oid));
|
||||
errors_found |= ERROR_REACHABLE;
|
||||
|
@ -506,7 +506,7 @@ static struct object *parse_loose_object(const struct object_id *oid,
|
|||
if (!contents && type != OBJ_BLOB)
|
||||
die("BUG: read_loose_object streamed a non-blob");
|
||||
|
||||
obj = parse_object_buffer(oid->hash, type, size, contents, &eaten);
|
||||
obj = parse_object_buffer(oid, type, size, contents, &eaten);
|
||||
|
||||
if (!eaten)
|
||||
free(contents);
|
||||
|
@ -599,10 +599,10 @@ static int fsck_cache_tree(struct cache_tree *it)
|
|||
fprintf(stderr, "Checking cache tree\n");
|
||||
|
||||
if (0 <= it->entry_count) {
|
||||
struct object *obj = parse_object(it->sha1);
|
||||
struct object *obj = parse_object(&it->oid);
|
||||
if (!obj) {
|
||||
error("%s: invalid sha1 pointer in cache-tree",
|
||||
sha1_to_hex(it->sha1));
|
||||
oid_to_hex(&it->oid));
|
||||
errors_found |= ERROR_REFS;
|
||||
return 1;
|
||||
}
|
||||
|
@ -781,7 +781,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||
mode = active_cache[i]->ce_mode;
|
||||
if (S_ISGITLINK(mode))
|
||||
continue;
|
||||
blob = lookup_blob(active_cache[i]->oid.hash);
|
||||
blob = lookup_blob(&active_cache[i]->oid);
|
||||
if (!blob)
|
||||
continue;
|
||||
obj = &blob->object;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "tempfile.h"
|
||||
#include "lockfile.h"
|
||||
#include "parse-options.h"
|
||||
|
@ -33,7 +34,7 @@ static int aggressive_window = 250;
|
|||
static int gc_auto_threshold = 6700;
|
||||
static int gc_auto_pack_limit = 50;
|
||||
static int detach_auto = 1;
|
||||
static unsigned long gc_log_expire_time;
|
||||
static timestamp_t gc_log_expire_time;
|
||||
static const char *gc_log_expire = "1.day.ago";
|
||||
static const char *prune_expire = "2.weeks.ago";
|
||||
static const char *prune_worktrees_expire = "3.months.ago";
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (c) 2006 Junio C Hamano
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "blob.h"
|
||||
#include "tree.h"
|
||||
#include "commit.h"
|
||||
|
@ -73,14 +74,14 @@ static pthread_mutex_t grep_mutex;
|
|||
|
||||
static inline void grep_lock(void)
|
||||
{
|
||||
if (num_threads)
|
||||
pthread_mutex_lock(&grep_mutex);
|
||||
assert(num_threads);
|
||||
pthread_mutex_lock(&grep_mutex);
|
||||
}
|
||||
|
||||
static inline void grep_unlock(void)
|
||||
{
|
||||
if (num_threads)
|
||||
pthread_mutex_unlock(&grep_mutex);
|
||||
assert(num_threads);
|
||||
pthread_mutex_unlock(&grep_mutex);
|
||||
}
|
||||
|
||||
/* Signalled when a new work_item is added to todo. */
|
||||
|
@ -224,7 +225,8 @@ static void start_threads(struct grep_opt *opt)
|
|||
int err;
|
||||
struct grep_opt *o = grep_opt_dup(opt);
|
||||
o->output = strbuf_out;
|
||||
o->debug = 0;
|
||||
if (i)
|
||||
o->debug = 0;
|
||||
compile_grep_patterns(o);
|
||||
err = pthread_create(&threads[i], NULL, run, o);
|
||||
|
||||
|
@ -289,8 +291,22 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
|
|||
if (num_threads < 0)
|
||||
die(_("invalid number of threads specified (%d) for %s"),
|
||||
num_threads, var);
|
||||
#ifdef NO_PTHREADS
|
||||
else if (num_threads && num_threads != 1) {
|
||||
/*
|
||||
* TRANSLATORS: %s is the configuration
|
||||
* variable for tweaking threads, currently
|
||||
* grep.threads
|
||||
*/
|
||||
warning(_("no threads support, ignoring %s"), var);
|
||||
num_threads = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!strcmp(var, "submodule.recurse"))
|
||||
recurse_submodules = git_config_bool(var, value);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
@ -327,7 +343,7 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
|
|||
|
||||
#ifndef NO_PTHREADS
|
||||
if (num_threads) {
|
||||
add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, oid);
|
||||
add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
|
||||
strbuf_release(&pathbuf);
|
||||
return 0;
|
||||
} else
|
||||
|
@ -336,7 +352,7 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
|
|||
struct grep_source gs;
|
||||
int hit;
|
||||
|
||||
grep_source_init(&gs, GREP_SOURCE_SHA1, pathbuf.buf, path, oid);
|
||||
grep_source_init(&gs, GREP_SOURCE_OID, pathbuf.buf, path, oid);
|
||||
strbuf_release(&pathbuf);
|
||||
hit = grep_source(opt, &gs);
|
||||
|
||||
|
@ -495,6 +511,8 @@ static void compile_submodule_options(const struct grep_opt *opt,
|
|||
break;
|
||||
case GREP_PATTERN_TYPE_UNSPECIFIED:
|
||||
break;
|
||||
default:
|
||||
die("BUG: Added a new grep pattern type without updating switch statement");
|
||||
}
|
||||
|
||||
for (pattern = opt->pattern_list; pattern != NULL;
|
||||
|
@ -570,7 +588,7 @@ static int grep_submodule_launch(struct grep_opt *opt,
|
|||
* with the object's name: 'tree-name:filename'. In order to
|
||||
* provide uniformity of output we want to pass the name of the
|
||||
* parent project's object name to the submodule so the submodule can
|
||||
* prefix its output with the parent's name and not its own SHA1.
|
||||
* prefix its output with the parent's name and not its own OID.
|
||||
*/
|
||||
if (gs->identifier && end_of_base)
|
||||
argv_array_pushf(&cp.args, "--parent-basename=%.*s",
|
||||
|
@ -583,12 +601,12 @@ static int grep_submodule_launch(struct grep_opt *opt,
|
|||
* If there is a tree identifier for the submodule, add the
|
||||
* rev after adding the submodule options but before the
|
||||
* pathspecs. To do this we listen for the '--' and insert the
|
||||
* sha1 before pushing the '--' onto the child process argv
|
||||
* oid before pushing the '--' onto the child process argv
|
||||
* array.
|
||||
*/
|
||||
if (gs->identifier &&
|
||||
!strcmp("--", submodule_options.argv[i])) {
|
||||
argv_array_push(&cp.args, sha1_to_hex(gs->identifier));
|
||||
argv_array_push(&cp.args, oid_to_hex(gs->identifier));
|
||||
}
|
||||
|
||||
argv_array_push(&cp.args, submodule_options.argv[i]);
|
||||
|
@ -618,11 +636,11 @@ static int grep_submodule_launch(struct grep_opt *opt,
|
|||
|
||||
/*
|
||||
* Prep grep structures for a submodule grep
|
||||
* sha1: the sha1 of the submodule or NULL if using the working tree
|
||||
* oid: the oid of the submodule or NULL if using the working tree
|
||||
* filename: name of the submodule including tree name of parent
|
||||
* path: location of the submodule
|
||||
*/
|
||||
static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
|
||||
static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
|
||||
const char *filename, const char *path)
|
||||
{
|
||||
if (!is_submodule_initialized(path))
|
||||
|
@ -632,7 +650,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
|
|||
* If searching history, check for the presense of the
|
||||
* submodule's gitdir before skipping the submodule.
|
||||
*/
|
||||
if (sha1) {
|
||||
if (oid) {
|
||||
const struct submodule *sub =
|
||||
submodule_from_path(null_sha1, path);
|
||||
if (sub)
|
||||
|
@ -647,7 +665,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
|
|||
|
||||
#ifndef NO_PTHREADS
|
||||
if (num_threads) {
|
||||
add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, sha1);
|
||||
add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid);
|
||||
return 0;
|
||||
} else
|
||||
#endif
|
||||
|
@ -656,7 +674,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
|
|||
int hit;
|
||||
|
||||
grep_source_init(&gs, GREP_SOURCE_SUBMODULE,
|
||||
filename, path, sha1);
|
||||
filename, path, oid);
|
||||
hit = grep_submodule_launch(opt, &gs);
|
||||
|
||||
grep_source_clear(&gs);
|
||||
|
@ -775,7 +793,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||
check_attr);
|
||||
free(data);
|
||||
} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
|
||||
hit |= grep_submodule(opt, entry.oid->hash, base->buf,
|
||||
hit |= grep_submodule(opt, entry.oid, base->buf,
|
||||
base->buf + tn_len);
|
||||
}
|
||||
|
||||
|
@ -866,7 +884,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||
if (exc_std)
|
||||
setup_standard_excludes(&dir);
|
||||
|
||||
fill_directory(&dir, pathspec);
|
||||
fill_directory(&dir, &the_index, pathspec);
|
||||
for (i = 0; i < dir.nr; i++) {
|
||||
if (!dir_path_match(dir.entries[i], pathspec, 0, NULL))
|
||||
continue;
|
||||
|
@ -1154,8 +1172,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||
if (!opt.fixed && opt.ignore_case)
|
||||
opt.regflags |= REG_ICASE;
|
||||
|
||||
compile_grep_patterns(&opt);
|
||||
|
||||
/*
|
||||
* We have to find "--" in a separate pass, because its presence
|
||||
* influences how we will parse arguments that come before it.
|
||||
|
@ -1190,16 +1206,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||
break;
|
||||
}
|
||||
|
||||
if (get_sha1_with_context(arg, 0, oid.hash, &oc)) {
|
||||
if (get_sha1_with_context(arg, GET_SHA1_RECORD_PATH,
|
||||
oid.hash, &oc)) {
|
||||
if (seen_dashdash)
|
||||
die(_("unable to resolve revision: %s"), arg);
|
||||
break;
|
||||
}
|
||||
|
||||
object = parse_object_or_die(oid.hash, arg);
|
||||
object = parse_object_or_die(&oid, arg);
|
||||
if (!seen_dashdash)
|
||||
verify_non_filename(prefix, arg);
|
||||
add_object_array_with_path(object, arg, &list, oc.mode, oc.path);
|
||||
free(oc.path);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1226,10 +1244,23 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||
num_threads = GREP_NUM_THREADS_DEFAULT;
|
||||
else if (num_threads < 0)
|
||||
die(_("invalid number of threads specified (%d)"), num_threads);
|
||||
if (num_threads == 1)
|
||||
num_threads = 0;
|
||||
#else
|
||||
if (num_threads)
|
||||
warning(_("no threads support, ignoring --threads"));
|
||||
num_threads = 0;
|
||||
#endif
|
||||
|
||||
if (!num_threads)
|
||||
/*
|
||||
* The compiled patterns on the main path are only
|
||||
* used when not using threading. Otherwise
|
||||
* start_threads() below calls compile_grep_patterns()
|
||||
* for each thread.
|
||||
*/
|
||||
compile_grep_patterns(&opt);
|
||||
|
||||
#ifndef NO_PTHREADS
|
||||
if (num_threads) {
|
||||
if (!(opt.name_only || opt.unmatch_name_only || opt.count)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (C) Junio C Hamano, 2005
|
||||
*/
|
||||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "blob.h"
|
||||
#include "quote.h"
|
||||
#include "parse-options.h"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Builtin help command
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "builtin.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "parse-options.h"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "delta.h"
|
||||
#include "pack.h"
|
||||
#include "csum-file.h"
|
||||
|
@ -388,8 +389,7 @@ static struct base_data *alloc_base_data(void)
|
|||
static void free_base_data(struct base_data *c)
|
||||
{
|
||||
if (c->data) {
|
||||
free(c->data);
|
||||
c->data = NULL;
|
||||
FREE_AND_NULL(c->data);
|
||||
get_thread_data()->base_cache_used -= c->size;
|
||||
}
|
||||
}
|
||||
|
@ -605,8 +605,7 @@ static void *unpack_data(struct object_entry *obj,
|
|||
git_inflate_end(&stream);
|
||||
free(inbuf);
|
||||
if (consume) {
|
||||
free(data);
|
||||
data = NULL;
|
||||
FREE_AND_NULL(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -747,13 +746,13 @@ static int compare_objects(const unsigned char *buf, unsigned long size,
|
|||
ssize_t len = read_istream(data->st, data->buf, size);
|
||||
if (len == 0)
|
||||
die(_("SHA1 COLLISION FOUND WITH %s !"),
|
||||
sha1_to_hex(data->entry->idx.sha1));
|
||||
oid_to_hex(&data->entry->idx.oid));
|
||||
if (len < 0)
|
||||
die(_("unable to read %s"),
|
||||
sha1_to_hex(data->entry->idx.sha1));
|
||||
oid_to_hex(&data->entry->idx.oid));
|
||||
if (memcmp(buf, data->buf, len))
|
||||
die(_("SHA1 COLLISION FOUND WITH %s !"),
|
||||
sha1_to_hex(data->entry->idx.sha1));
|
||||
oid_to_hex(&data->entry->idx.oid));
|
||||
size -= len;
|
||||
buf += len;
|
||||
}
|
||||
|
@ -771,12 +770,12 @@ static int check_collison(struct object_entry *entry)
|
|||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.entry = entry;
|
||||
data.st = open_istream(entry->idx.sha1, &type, &size, NULL);
|
||||
data.st = open_istream(entry->idx.oid.hash, &type, &size, NULL);
|
||||
if (!data.st)
|
||||
return -1;
|
||||
if (size != entry->size || type != entry->type)
|
||||
die(_("SHA1 COLLISION FOUND WITH %s !"),
|
||||
sha1_to_hex(entry->idx.sha1));
|
||||
oid_to_hex(&entry->idx.oid));
|
||||
unpack_data(entry, compare_objects, &data);
|
||||
close_istream(data.st);
|
||||
free(data.buf);
|
||||
|
@ -785,7 +784,7 @@ static int check_collison(struct object_entry *entry)
|
|||
|
||||
static void sha1_object(const void *data, struct object_entry *obj_entry,
|
||||
unsigned long size, enum object_type type,
|
||||
const unsigned char *sha1)
|
||||
const struct object_id *oid)
|
||||
{
|
||||
void *new_data = NULL;
|
||||
int collision_test_needed = 0;
|
||||
|
@ -794,7 +793,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
|
|||
|
||||
if (startup_info->have_repository) {
|
||||
read_lock();
|
||||
collision_test_needed = has_sha1_file_with_flags(sha1, HAS_SHA1_QUICK);
|
||||
collision_test_needed = has_sha1_file_with_flags(oid->hash, HAS_SHA1_QUICK);
|
||||
read_unlock();
|
||||
}
|
||||
|
||||
|
@ -809,31 +808,31 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
|
|||
enum object_type has_type;
|
||||
unsigned long has_size;
|
||||
read_lock();
|
||||
has_type = sha1_object_info(sha1, &has_size);
|
||||
has_type = sha1_object_info(oid->hash, &has_size);
|
||||
if (has_type < 0)
|
||||
die(_("cannot read existing object info %s"), sha1_to_hex(sha1));
|
||||
die(_("cannot read existing object info %s"), oid_to_hex(oid));
|
||||
if (has_type != type || has_size != size)
|
||||
die(_("SHA1 COLLISION FOUND WITH %s !"), sha1_to_hex(sha1));
|
||||
has_data = read_sha1_file(sha1, &has_type, &has_size);
|
||||
die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid));
|
||||
has_data = read_sha1_file(oid->hash, &has_type, &has_size);
|
||||
read_unlock();
|
||||
if (!data)
|
||||
data = new_data = get_data_from_pack(obj_entry);
|
||||
if (!has_data)
|
||||
die(_("cannot read existing object %s"), sha1_to_hex(sha1));
|
||||
die(_("cannot read existing object %s"), oid_to_hex(oid));
|
||||
if (size != has_size || type != has_type ||
|
||||
memcmp(data, has_data, size) != 0)
|
||||
die(_("SHA1 COLLISION FOUND WITH %s !"), sha1_to_hex(sha1));
|
||||
die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid));
|
||||
free(has_data);
|
||||
}
|
||||
|
||||
if (strict) {
|
||||
read_lock();
|
||||
if (type == OBJ_BLOB) {
|
||||
struct blob *blob = lookup_blob(sha1);
|
||||
struct blob *blob = lookup_blob(oid);
|
||||
if (blob)
|
||||
blob->object.flags |= FLAG_CHECKED;
|
||||
else
|
||||
die(_("invalid blob object %s"), sha1_to_hex(sha1));
|
||||
die(_("invalid blob object %s"), oid_to_hex(oid));
|
||||
} else {
|
||||
struct object *obj;
|
||||
int eaten;
|
||||
|
@ -845,7 +844,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
|
|||
* we do not need to free the memory here, as the
|
||||
* buf is deleted by the caller.
|
||||
*/
|
||||
obj = parse_object_buffer(sha1, type, size, buf, &eaten);
|
||||
obj = parse_object_buffer(oid, type, size, buf,
|
||||
&eaten);
|
||||
if (!obj)
|
||||
die(_("invalid %s"), typename(type));
|
||||
if (do_fsck_object &&
|
||||
|
@ -957,9 +957,10 @@ static void resolve_delta(struct object_entry *delta_obj,
|
|||
if (!result->data)
|
||||
bad_object(delta_obj->idx.offset, _("failed to apply delta"));
|
||||
hash_sha1_file(result->data, result->size,
|
||||
typename(delta_obj->real_type), delta_obj->idx.sha1);
|
||||
typename(delta_obj->real_type),
|
||||
delta_obj->idx.oid.hash);
|
||||
sha1_object(result->data, NULL, result->size, delta_obj->real_type,
|
||||
delta_obj->idx.sha1);
|
||||
&delta_obj->idx.oid);
|
||||
counter_lock();
|
||||
nr_resolved_deltas++;
|
||||
counter_unlock();
|
||||
|
@ -989,7 +990,7 @@ static struct base_data *find_unresolved_deltas_1(struct base_data *base,
|
|||
struct base_data *prev_base)
|
||||
{
|
||||
if (base->ref_last == -1 && base->ofs_last == -1) {
|
||||
find_ref_delta_children(base->obj->idx.sha1,
|
||||
find_ref_delta_children(base->obj->idx.oid.hash,
|
||||
&base->ref_first, &base->ref_last,
|
||||
OBJ_REF_DELTA);
|
||||
|
||||
|
@ -1130,7 +1131,8 @@ static void parse_pack_objects(unsigned char *sha1)
|
|||
for (i = 0; i < nr_objects; i++) {
|
||||
struct object_entry *obj = &objects[i];
|
||||
void *data = unpack_raw_entry(obj, &ofs_delta->offset,
|
||||
ref_delta_sha1, obj->idx.sha1);
|
||||
ref_delta_sha1,
|
||||
obj->idx.oid.hash);
|
||||
obj->real_type = obj->type;
|
||||
if (obj->type == OBJ_OFS_DELTA) {
|
||||
nr_ofs_deltas++;
|
||||
|
@ -1146,7 +1148,8 @@ static void parse_pack_objects(unsigned char *sha1)
|
|||
obj->real_type = OBJ_BAD;
|
||||
nr_delays++;
|
||||
} else
|
||||
sha1_object(data, NULL, obj->size, obj->type, obj->idx.sha1);
|
||||
sha1_object(data, NULL, obj->size, obj->type,
|
||||
&obj->idx.oid);
|
||||
free(data);
|
||||
display_progress(progress, i+1);
|
||||
}
|
||||
|
@ -1172,7 +1175,8 @@ static void parse_pack_objects(unsigned char *sha1)
|
|||
if (obj->real_type != OBJ_BAD)
|
||||
continue;
|
||||
obj->real_type = obj->type;
|
||||
sha1_object(NULL, obj, obj->size, obj->type, obj->idx.sha1);
|
||||
sha1_object(NULL, obj, obj->size, obj->type,
|
||||
&obj->idx.oid);
|
||||
nr_delays--;
|
||||
}
|
||||
if (nr_delays)
|
||||
|
@ -1330,7 +1334,7 @@ static struct object_entry *append_obj_to_pack(struct sha1file *f,
|
|||
obj[1].idx.offset += write_compressed(f, buf, size);
|
||||
obj[0].idx.crc32 = crc32_end(f);
|
||||
sha1flush(f);
|
||||
hashcpy(obj->idx.sha1, sha1);
|
||||
hashcpy(obj->idx.oid.hash, sha1);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -1581,13 +1585,14 @@ static void show_pack_info(int stat_only)
|
|||
if (stat_only)
|
||||
continue;
|
||||
printf("%s %-6s %lu %lu %"PRIuMAX,
|
||||
sha1_to_hex(obj->idx.sha1),
|
||||
oid_to_hex(&obj->idx.oid),
|
||||
typename(obj->real_type), obj->size,
|
||||
(unsigned long)(obj[1].idx.offset - obj->idx.offset),
|
||||
(uintmax_t)obj->idx.offset);
|
||||
if (is_delta_type(obj->type)) {
|
||||
struct object_entry *bobj = &objects[obj_stat[i].base_object_no];
|
||||
printf(" %u %s", obj_stat[i].delta_depth, sha1_to_hex(bobj->idx.sha1));
|
||||
printf(" %u %s", obj_stat[i].delta_depth,
|
||||
oid_to_hex(&bobj->idx.oid));
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) Linus Torvalds, 2005
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "builtin.h"
|
||||
#include "exec_cmd.h"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2006 Junio Hamano
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "color.h"
|
||||
#include "commit.h"
|
||||
|
@ -110,6 +111,8 @@ static void init_log_defaults(void)
|
|||
{
|
||||
init_grep_defaults();
|
||||
init_diff_ui_defaults();
|
||||
|
||||
decoration_style = auto_decoration_style();
|
||||
}
|
||||
|
||||
static void cmd_log_init_defaults(struct rev_info *rev)
|
||||
|
@ -410,8 +413,6 @@ static int git_log_config(const char *var, const char *value, void *cb)
|
|||
if (decoration_style < 0)
|
||||
decoration_style = 0; /* maybe warn? */
|
||||
return 0;
|
||||
} else {
|
||||
decoration_style = auto_decoration_style();
|
||||
}
|
||||
if (!strcmp(var, "log.showroot")) {
|
||||
default_show_root = git_config_bool(var, value);
|
||||
|
@ -483,16 +484,20 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
|
|||
!DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
|
||||
return stream_blob_to_fd(1, oid, NULL, 0);
|
||||
|
||||
if (get_sha1_with_context(obj_name, 0, oidc.hash, &obj_context))
|
||||
if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
|
||||
oidc.hash, &obj_context))
|
||||
die(_("Not a valid object name %s"), obj_name);
|
||||
if (!obj_context.path[0] ||
|
||||
!textconv_object(obj_context.path, obj_context.mode, &oidc, 1, &buf, &size))
|
||||
if (!obj_context.path ||
|
||||
!textconv_object(obj_context.path, obj_context.mode, &oidc, 1, &buf, &size)) {
|
||||
free(obj_context.path);
|
||||
return stream_blob_to_fd(1, oid, NULL, 0);
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
die(_("git show %s: bad file"), obj_name);
|
||||
|
||||
write_or_die(1, buf, size);
|
||||
free(obj_context.path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -596,7 +601,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
|||
rev.shown_one = 1;
|
||||
if (ret)
|
||||
break;
|
||||
o = parse_object(t->tagged->oid.hash);
|
||||
o = parse_object(&t->tagged->oid);
|
||||
if (!o)
|
||||
ret = error(_("Could not read object %s"),
|
||||
oid_to_hex(&t->tagged->oid));
|
||||
|
@ -842,8 +847,10 @@ static int open_next_file(struct commit *commit, const char *subject,
|
|||
if (output_directory) {
|
||||
strbuf_addstr(&filename, output_directory);
|
||||
if (filename.len >=
|
||||
PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
|
||||
PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len) {
|
||||
strbuf_release(&filename);
|
||||
return error(_("name of output directory is too long"));
|
||||
}
|
||||
strbuf_complete(&filename, '/');
|
||||
}
|
||||
|
||||
|
@ -857,8 +864,11 @@ static int open_next_file(struct commit *commit, const char *subject,
|
|||
if (!quiet)
|
||||
printf("%s\n", filename.buf + outdir_offset);
|
||||
|
||||
if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL)
|
||||
return error(_("Cannot open patch file %s"), filename.buf);
|
||||
if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
|
||||
error_errno(_("Cannot open patch file %s"), filename.buf);
|
||||
strbuf_release(&filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strbuf_release(&filename);
|
||||
return 0;
|
||||
|
@ -878,8 +888,8 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
|
|||
o2 = rev->pending.objects[1].item;
|
||||
flags1 = o1->flags;
|
||||
flags2 = o2->flags;
|
||||
c1 = lookup_commit_reference(o1->oid.hash);
|
||||
c2 = lookup_commit_reference(o2->oid.hash);
|
||||
c1 = lookup_commit_reference(&o1->oid);
|
||||
c2 = lookup_commit_reference(&o2->oid);
|
||||
|
||||
if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
|
||||
die(_("Not a range."));
|
||||
|
@ -910,8 +920,8 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
|
|||
static void gen_message_id(struct rev_info *info, char *base)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
strbuf_addf(&buf, "%s.%lu.git.%s", base,
|
||||
(unsigned long) time(NULL),
|
||||
strbuf_addf(&buf, "%s.%"PRItime".git.%s", base,
|
||||
(timestamp_t) time(NULL),
|
||||
git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
|
||||
info->message_id = strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
@ -1043,9 +1053,9 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||
|
||||
diff_setup_done(&opts);
|
||||
|
||||
diff_tree_sha1(origin->tree->object.oid.hash,
|
||||
head->tree->object.oid.hash,
|
||||
"", &opts);
|
||||
diff_tree_oid(&origin->tree->object.oid,
|
||||
&head->tree->object.oid,
|
||||
"", &opts);
|
||||
diffcore_std(&opts);
|
||||
diff_flush(&opts);
|
||||
|
||||
|
@ -1263,7 +1273,7 @@ static struct commit *get_base_commit(const char *base_commit,
|
|||
|
||||
if (get_oid(upstream, &oid))
|
||||
die(_("Failed to resolve '%s' as a valid ref."), upstream);
|
||||
commit = lookup_commit_or_die(oid.hash, "upstream base");
|
||||
commit = lookup_commit_or_die(&oid, "upstream base");
|
||||
base_list = get_merge_bases_many(commit, total, list);
|
||||
/* There should be one and only one merge base. */
|
||||
if (!base_list || base_list->next)
|
||||
|
@ -1354,7 +1364,7 @@ static void prepare_bases(struct base_tree_info *bases,
|
|||
struct object_id *patch_id;
|
||||
if (commit->util)
|
||||
continue;
|
||||
if (commit_patch_id(commit, &diffopt, oid.hash, 0))
|
||||
if (commit_patch_id(commit, &diffopt, &oid, 0))
|
||||
die(_("cannot get 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;
|
||||
|
@ -1819,7 +1829,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
|
|||
{
|
||||
struct object_id oid;
|
||||
if (get_oid(arg, &oid) == 0) {
|
||||
struct commit *commit = lookup_commit_reference(oid.hash);
|
||||
struct commit *commit = lookup_commit_reference(&oid);
|
||||
if (commit) {
|
||||
commit->object.flags |= flags;
|
||||
add_pending_object(revs, &commit->object, arg);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Copyright (C) Linus Torvalds, 2005
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "quote.h"
|
||||
#include "dir.h"
|
||||
#include "builtin.h"
|
||||
|
@ -53,17 +54,17 @@ static const char *tag_modified = "";
|
|||
static const char *tag_skip_worktree = "";
|
||||
static const char *tag_resolve_undo = "";
|
||||
|
||||
static void write_eolinfo(const struct cache_entry *ce, const char *path)
|
||||
static void write_eolinfo(const struct index_state *istate,
|
||||
const struct cache_entry *ce, const char *path)
|
||||
{
|
||||
if (!show_eol)
|
||||
return;
|
||||
else {
|
||||
if (show_eol) {
|
||||
struct stat st;
|
||||
const char *i_txt = "";
|
||||
const char *w_txt = "";
|
||||
const char *a_txt = get_convert_attr_ascii(path);
|
||||
if (ce && S_ISREG(ce->ce_mode))
|
||||
i_txt = get_cached_convert_stats_ascii(ce->name);
|
||||
i_txt = get_cached_convert_stats_ascii(istate,
|
||||
ce->name);
|
||||
if (!lstat(path, &st) && S_ISREG(st.st_mode))
|
||||
w_txt = get_wt_convert_stats_ascii(path);
|
||||
printf("i/%-5s w/%-5s attr/%-17s\t", i_txt, w_txt, a_txt);
|
||||
|
@ -93,34 +94,73 @@ static void write_name(const char *name)
|
|||
strbuf_release(&full_name);
|
||||
}
|
||||
|
||||
static const char *get_tag(const struct cache_entry *ce, const char *tag)
|
||||
{
|
||||
static char alttag[4];
|
||||
|
||||
if (tag && *tag && show_valid_bit && (ce->ce_flags & CE_VALID)) {
|
||||
memcpy(alttag, tag, 3);
|
||||
|
||||
if (isalpha(tag[0])) {
|
||||
alttag[0] = tolower(tag[0]);
|
||||
} else if (tag[0] == '?') {
|
||||
alttag[0] = '!';
|
||||
} else {
|
||||
alttag[0] = 'v';
|
||||
alttag[1] = tag[0];
|
||||
alttag[2] = ' ';
|
||||
alttag[3] = 0;
|
||||
}
|
||||
|
||||
tag = alttag;
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
static void print_debug(const struct cache_entry *ce)
|
||||
{
|
||||
if (debug_mode) {
|
||||
const struct stat_data *sd = &ce->ce_stat_data;
|
||||
|
||||
printf(" ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
|
||||
printf(" mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
|
||||
printf(" dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
|
||||
printf(" uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
|
||||
printf(" size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_dir_entry(const char *tag, struct dir_entry *ent)
|
||||
{
|
||||
int len = max_prefix_len;
|
||||
|
||||
if (len >= ent->len)
|
||||
if (len > ent->len)
|
||||
die("git ls-files: internal error - directory entry not superset of prefix");
|
||||
|
||||
if (!dir_path_match(ent, &pathspec, len, ps_matched))
|
||||
return;
|
||||
|
||||
fputs(tag, stdout);
|
||||
write_eolinfo(NULL, ent->name);
|
||||
write_eolinfo(NULL, NULL, ent->name);
|
||||
write_name(ent->name);
|
||||
}
|
||||
|
||||
static void show_other_files(struct dir_struct *dir)
|
||||
static void show_other_files(const struct index_state *istate,
|
||||
const struct dir_struct *dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dir->nr; i++) {
|
||||
struct dir_entry *ent = dir->entries[i];
|
||||
if (!cache_name_is_other(ent->name, ent->len))
|
||||
if (!index_name_is_other(istate, ent->name, ent->len))
|
||||
continue;
|
||||
show_dir_entry(tag_other, ent);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_killed_files(struct dir_struct *dir)
|
||||
static void show_killed_files(const struct index_state *istate,
|
||||
const struct dir_struct *dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dir->nr; i++) {
|
||||
|
@ -134,29 +174,29 @@ static void show_killed_files(struct dir_struct *dir)
|
|||
/* If ent->name is prefix of an entry in the
|
||||
* cache, it will be killed.
|
||||
*/
|
||||
pos = cache_name_pos(ent->name, ent->len);
|
||||
pos = index_name_pos(istate, ent->name, ent->len);
|
||||
if (0 <= pos)
|
||||
die("BUG: killed-file %.*s not found",
|
||||
ent->len, ent->name);
|
||||
pos = -pos - 1;
|
||||
while (pos < active_nr &&
|
||||
ce_stage(active_cache[pos]))
|
||||
while (pos < istate->cache_nr &&
|
||||
ce_stage(istate->cache[pos]))
|
||||
pos++; /* skip unmerged */
|
||||
if (active_nr <= pos)
|
||||
if (istate->cache_nr <= pos)
|
||||
break;
|
||||
/* pos points at a name immediately after
|
||||
* ent->name in the cache. Does it expect
|
||||
* ent->name to be a directory?
|
||||
*/
|
||||
len = ce_namelen(active_cache[pos]);
|
||||
len = ce_namelen(istate->cache[pos]);
|
||||
if ((ent->len < len) &&
|
||||
!strncmp(active_cache[pos]->name,
|
||||
!strncmp(istate->cache[pos]->name,
|
||||
ent->name, ent->len) &&
|
||||
active_cache[pos]->name[ent->len] == '/')
|
||||
istate->cache[pos]->name[ent->len] == '/')
|
||||
killed = 1;
|
||||
break;
|
||||
}
|
||||
if (0 <= cache_name_pos(ent->name, sp - ent->name)) {
|
||||
if (0 <= index_name_pos(istate, ent->name, sp - ent->name)) {
|
||||
/* If any of the leading directories in
|
||||
* ent->name is registered in the cache,
|
||||
* ent->name will be killed.
|
||||
|
@ -230,7 +270,8 @@ static void show_gitlink(const struct cache_entry *ce)
|
|||
exit(status);
|
||||
}
|
||||
|
||||
static void show_ce_entry(const char *tag, const struct cache_entry *ce)
|
||||
static void show_ce_entry(const struct index_state *istate,
|
||||
const char *tag, const struct cache_entry *ce)
|
||||
{
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
int len = max_prefix_len;
|
||||
|
@ -238,7 +279,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
|
|||
strbuf_addstr(&name, super_prefix);
|
||||
strbuf_addstr(&name, ce->name);
|
||||
|
||||
if (len >= ce_namelen(ce))
|
||||
if (len > ce_namelen(ce))
|
||||
die("git ls-files: internal error - cache entry not superset of prefix");
|
||||
|
||||
if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
|
||||
|
@ -248,22 +289,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
|
|||
len, ps_matched,
|
||||
S_ISDIR(ce->ce_mode) ||
|
||||
S_ISGITLINK(ce->ce_mode))) {
|
||||
if (tag && *tag && show_valid_bit &&
|
||||
(ce->ce_flags & CE_VALID)) {
|
||||
static char alttag[4];
|
||||
memcpy(alttag, tag, 3);
|
||||
if (isalpha(tag[0]))
|
||||
alttag[0] = tolower(tag[0]);
|
||||
else if (tag[0] == '?')
|
||||
alttag[0] = '!';
|
||||
else {
|
||||
alttag[0] = 'v';
|
||||
alttag[1] = tag[0];
|
||||
alttag[2] = ' ';
|
||||
alttag[3] = 0;
|
||||
}
|
||||
tag = alttag;
|
||||
}
|
||||
tag = get_tag(ce, tag);
|
||||
|
||||
if (!show_stage) {
|
||||
fputs(tag, stdout);
|
||||
|
@ -274,30 +300,22 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
|
|||
find_unique_abbrev(ce->oid.hash, abbrev),
|
||||
ce_stage(ce));
|
||||
}
|
||||
write_eolinfo(ce, ce->name);
|
||||
write_eolinfo(istate, ce, ce->name);
|
||||
write_name(ce->name);
|
||||
if (debug_mode) {
|
||||
const struct stat_data *sd = &ce->ce_stat_data;
|
||||
|
||||
printf(" ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
|
||||
printf(" mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
|
||||
printf(" dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
|
||||
printf(" uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
|
||||
printf(" size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
|
||||
}
|
||||
print_debug(ce);
|
||||
}
|
||||
|
||||
strbuf_release(&name);
|
||||
}
|
||||
|
||||
static void show_ru_info(void)
|
||||
static void show_ru_info(const struct index_state *istate)
|
||||
{
|
||||
struct string_list_item *item;
|
||||
|
||||
if (!the_index.resolve_undo)
|
||||
if (!istate->resolve_undo)
|
||||
return;
|
||||
|
||||
for_each_string_list_item(item, the_index.resolve_undo) {
|
||||
for_each_string_list_item(item, istate->resolve_undo) {
|
||||
const char *path = item->string;
|
||||
struct resolve_undo_info *ui = item->util;
|
||||
int i, len;
|
||||
|
@ -319,13 +337,14 @@ static void show_ru_info(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce)
|
||||
static int ce_excluded(struct dir_struct *dir, struct index_state *istate,
|
||||
const struct cache_entry *ce)
|
||||
{
|
||||
int dtype = ce_to_dtype(ce);
|
||||
return is_excluded(dir, ce->name, &dtype);
|
||||
return is_excluded(dir, istate, ce->name, &dtype);
|
||||
}
|
||||
|
||||
static void show_files(struct dir_struct *dir)
|
||||
static void show_files(struct index_state *istate, struct dir_struct *dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -333,33 +352,33 @@ static void show_files(struct dir_struct *dir)
|
|||
if (show_others || show_killed) {
|
||||
if (!show_others)
|
||||
dir->flags |= DIR_COLLECT_KILLED_ONLY;
|
||||
fill_directory(dir, &pathspec);
|
||||
fill_directory(dir, istate, &pathspec);
|
||||
if (show_others)
|
||||
show_other_files(dir);
|
||||
show_other_files(istate, dir);
|
||||
if (show_killed)
|
||||
show_killed_files(dir);
|
||||
show_killed_files(istate, dir);
|
||||
}
|
||||
if (show_cached || show_stage) {
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
const struct cache_entry *ce = active_cache[i];
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
const struct cache_entry *ce = istate->cache[i];
|
||||
if ((dir->flags & DIR_SHOW_IGNORED) &&
|
||||
!ce_excluded(dir, ce))
|
||||
!ce_excluded(dir, istate, ce))
|
||||
continue;
|
||||
if (show_unmerged && !ce_stage(ce))
|
||||
continue;
|
||||
if (ce->ce_flags & CE_UPDATE)
|
||||
continue;
|
||||
show_ce_entry(ce_stage(ce) ? tag_unmerged :
|
||||
show_ce_entry(istate, ce_stage(ce) ? tag_unmerged :
|
||||
(ce_skip_worktree(ce) ? tag_skip_worktree : tag_cached), ce);
|
||||
}
|
||||
}
|
||||
if (show_deleted || show_modified) {
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
const struct cache_entry *ce = active_cache[i];
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
const struct cache_entry *ce = istate->cache[i];
|
||||
struct stat st;
|
||||
int err;
|
||||
if ((dir->flags & DIR_SHOW_IGNORED) &&
|
||||
!ce_excluded(dir, ce))
|
||||
!ce_excluded(dir, istate, ce))
|
||||
continue;
|
||||
if (ce->ce_flags & CE_UPDATE)
|
||||
continue;
|
||||
|
@ -367,9 +386,9 @@ static void show_files(struct dir_struct *dir)
|
|||
continue;
|
||||
err = lstat(ce->name, &st);
|
||||
if (show_deleted && err)
|
||||
show_ce_entry(tag_removed, ce);
|
||||
if (show_modified && ce_modified(ce, &st, 0))
|
||||
show_ce_entry(tag_modified, ce);
|
||||
show_ce_entry(istate, tag_removed, ce);
|
||||
if (show_modified && ie_modified(istate, ce, &st, 0))
|
||||
show_ce_entry(istate, tag_modified, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -377,30 +396,50 @@ static void show_files(struct dir_struct *dir)
|
|||
/*
|
||||
* Prune the index to only contain stuff starting with "prefix"
|
||||
*/
|
||||
static void prune_cache(const char *prefix, size_t prefixlen)
|
||||
static void prune_index(struct index_state *istate,
|
||||
const char *prefix, size_t prefixlen)
|
||||
{
|
||||
int pos;
|
||||
unsigned int first, last;
|
||||
|
||||
if (!prefix)
|
||||
return;
|
||||
pos = cache_name_pos(prefix, prefixlen);
|
||||
pos = index_name_pos(istate, prefix, prefixlen);
|
||||
if (pos < 0)
|
||||
pos = -pos-1;
|
||||
first = pos;
|
||||
last = active_nr;
|
||||
last = istate->cache_nr;
|
||||
while (last > first) {
|
||||
int next = (last + first) >> 1;
|
||||
const struct cache_entry *ce = active_cache[next];
|
||||
const struct cache_entry *ce = istate->cache[next];
|
||||
if (!strncmp(ce->name, prefix, prefixlen)) {
|
||||
first = next+1;
|
||||
continue;
|
||||
}
|
||||
last = next;
|
||||
}
|
||||
memmove(active_cache, active_cache + pos,
|
||||
memmove(istate->cache, istate->cache + pos,
|
||||
(last - pos) * sizeof(struct cache_entry *));
|
||||
active_nr = last - pos;
|
||||
istate->cache_nr = last - pos;
|
||||
}
|
||||
|
||||
static int get_common_prefix_len(const char *common_prefix)
|
||||
{
|
||||
int common_prefix_len;
|
||||
|
||||
if (!common_prefix)
|
||||
return 0;
|
||||
|
||||
common_prefix_len = strlen(common_prefix);
|
||||
|
||||
/*
|
||||
* If the prefix has a trailing slash, strip it so that submodules wont
|
||||
* be pruned from the index.
|
||||
*/
|
||||
if (common_prefix[common_prefix_len - 1] == '/')
|
||||
common_prefix_len--;
|
||||
|
||||
return common_prefix_len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -411,23 +450,24 @@ static void prune_cache(const char *prefix, size_t prefixlen)
|
|||
* that were given from the command line. We are not
|
||||
* going to write this index out.
|
||||
*/
|
||||
void overlay_tree_on_cache(const char *tree_name, const char *prefix)
|
||||
void overlay_tree_on_index(struct index_state *istate,
|
||||
const char *tree_name, const char *prefix)
|
||||
{
|
||||
struct tree *tree;
|
||||
unsigned char sha1[20];
|
||||
struct object_id oid;
|
||||
struct pathspec pathspec;
|
||||
struct cache_entry *last_stage0 = NULL;
|
||||
int i;
|
||||
|
||||
if (get_sha1(tree_name, sha1))
|
||||
if (get_oid(tree_name, &oid))
|
||||
die("tree-ish %s not found.", tree_name);
|
||||
tree = parse_tree_indirect(sha1);
|
||||
tree = parse_tree_indirect(&oid);
|
||||
if (!tree)
|
||||
die("bad tree-ish %s", tree_name);
|
||||
|
||||
/* Hoist the unmerged entries up to stage #3 to make room */
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
struct cache_entry *ce = istate->cache[i];
|
||||
if (!ce_stage(ce))
|
||||
continue;
|
||||
ce->ce_flags |= CE_STAGEMASK;
|
||||
|
@ -440,11 +480,11 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
|
|||
PATHSPEC_PREFER_CWD, prefix, matchbuf);
|
||||
} else
|
||||
memset(&pathspec, 0, sizeof(pathspec));
|
||||
if (read_tree(tree, 1, &pathspec))
|
||||
if (read_tree(tree, 1, &pathspec, istate))
|
||||
die("unable to read tree entries %s", tree_name);
|
||||
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
struct cache_entry *ce = istate->cache[i];
|
||||
switch (ce_stage(ce)) {
|
||||
case 0:
|
||||
last_stage0 = ce;
|
||||
|
@ -624,8 +664,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
|
|||
"--error-unmatch");
|
||||
|
||||
parse_pathspec(&pathspec, 0,
|
||||
PATHSPEC_PREFER_CWD |
|
||||
PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
|
||||
PATHSPEC_PREFER_CWD,
|
||||
prefix, argv);
|
||||
|
||||
/*
|
||||
|
@ -637,7 +676,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
|
|||
max_prefix = NULL;
|
||||
else
|
||||
max_prefix = common_prefix(&pathspec);
|
||||
max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
|
||||
max_prefix_len = get_common_prefix_len(max_prefix);
|
||||
|
||||
prune_index(&the_index, max_prefix, max_prefix_len);
|
||||
|
||||
/* Treat unmatching pathspec elements as errors */
|
||||
if (pathspec.nr && error_unmatch)
|
||||
|
@ -651,7 +692,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
|
|||
show_killed || show_modified || show_resolve_undo))
|
||||
show_cached = 1;
|
||||
|
||||
prune_cache(max_prefix, max_prefix_len);
|
||||
if (with_tree) {
|
||||
/*
|
||||
* Basic sanity check; show-stages and show-unmerged
|
||||
|
@ -659,11 +699,11 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
|
|||
*/
|
||||
if (show_stage || show_unmerged)
|
||||
die("ls-files --with-tree is incompatible with -s or -u");
|
||||
overlay_tree_on_cache(with_tree, max_prefix);
|
||||
overlay_tree_on_index(&the_index, with_tree, max_prefix);
|
||||
}
|
||||
show_files(&dir);
|
||||
show_files(&the_index, &dir);
|
||||
if (show_resolve_undo)
|
||||
show_ru_info();
|
||||
show_ru_info(&the_index);
|
||||
|
||||
if (ps_matched) {
|
||||
int bad;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) Linus Torvalds, 2005
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "blob.h"
|
||||
#include "tree.h"
|
||||
#include "commit.h"
|
||||
|
@ -119,7 +120,7 @@ static int show_tree(const unsigned char *sha1, struct strbuf *base,
|
|||
|
||||
int cmd_ls_tree(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
struct object_id oid;
|
||||
struct tree *tree;
|
||||
int i, full_tree = 0;
|
||||
const struct option ls_tree_options[] = {
|
||||
|
@ -164,7 +165,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
|
|||
|
||||
if (argc < 1)
|
||||
usage_with_options(ls_tree_usage, ls_tree_options);
|
||||
if (get_sha1(argv[0], sha1))
|
||||
if (get_oid(argv[0], &oid))
|
||||
die("Not a valid object name %s", argv[0]);
|
||||
|
||||
/*
|
||||
|
@ -180,7 +181,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
|
|||
for (i = 0; i < pathspec.nr; i++)
|
||||
pathspec.items[i].nowildcard_len = pathspec.items[i].len;
|
||||
pathspec.has_wildcard = 0;
|
||||
tree = parse_tree_indirect(sha1);
|
||||
tree = parse_tree_indirect(&oid);
|
||||
if (!tree)
|
||||
die("not a tree object");
|
||||
return !!read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL);
|
||||
|
|
|
@ -232,6 +232,16 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
|
|||
|
||||
do {
|
||||
peek = fgetc(f);
|
||||
if (peek == EOF) {
|
||||
if (f == stdin)
|
||||
/* empty stdin is OK */
|
||||
ret = skip;
|
||||
else {
|
||||
fclose(f);
|
||||
error(_("empty mbox: '%s'"), file);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
} while (isspace(peek));
|
||||
ungetc(peek, f);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue