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
  ...
This commit is contained in:
Junio C Hamano 2017-06-30 13:12:34 -07:00
commit 2cfb6cec94
441 changed files with 13136 additions and 8408 deletions

8
.gitattributes vendored
View file

@ -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

19
.github/CONTRIBUTING.md vendored Normal file
View file

@ -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!

7
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -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!

View file

@ -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:
- >

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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).

View file

@ -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;

View file

@ -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

View file

@ -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.]

View file

@ -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

View file

@ -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

View file

@ -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
--------------------------------------------------------

View file

@ -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::

View file

@ -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

View file

@ -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:

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.
--

View file

@ -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 |

View file

@ -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

View file

@ -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

View file

@ -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>...]

View file

@ -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
-------

View file

@ -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"

View file

@ -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.

View file

@ -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::

View file

@ -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
---

View file

@ -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).
+

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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, &timestamp_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, &timestamp_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.

View file

@ -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.

View file

@ -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

View file

@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v2.13.0
DEF_VER=v2.13.GIT
LF='
'

View file

@ -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

View file

@ -1 +1 @@
Documentation/RelNotes/2.13.0.txt
Documentation/RelNotes/2.14.0.txt

View file

@ -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 }

View file

@ -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
View file

@ -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
View file

@ -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) {

View file

@ -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 */

View file

@ -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;
}

View file

@ -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;

View file

@ -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
View file

@ -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;

View file

@ -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);

1862
blame.c Normal file

File diff suppressed because it is too large Load diff

175
blame.h Normal file
View file

@ -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
View file

@ -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
View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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"));
}

View file

@ -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;
}

View file

@ -1,5 +1,6 @@
#include "builtin.h"
#include "cache.h"
#include "config.h"
#include "attr.h"
#include "quote.h"
#include "parse-options.h"

View file

@ -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);

View file

@ -1,4 +1,5 @@
#include "builtin.h"
#include "config.h"
#include "mailmap.h"
#include "parse-options.h"
#include "string-list.h"

View file

@ -5,6 +5,7 @@
*
*/
#include "builtin.h"
#include "config.h"
#include "lockfile.h"
#include "quote.h"
#include "cache-tree.h"

View file

@ -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'"),

View file

@ -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();

View file

@ -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();

View file

@ -1,5 +1,6 @@
#include "builtin.h"
#include "cache.h"
#include "config.h"
#include "strbuf.h"
#include "parse-options.h"
#include "string-list.h"

View file

@ -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;
}

View file

@ -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(&current_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, &current_head->object.oid, &oid);
finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
}
run_rewrite_hook(&current_head->object.oid, &oid);

View file

@ -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);

View file

@ -5,6 +5,7 @@
*/
#include "cache.h"
#include "config.h"
#include "dir.h"
#include "builtin.h"
#include "parse-options.h"

View file

@ -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");

View file

@ -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."));

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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 {

View file

@ -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);

View file

@ -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));

View file

@ -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);
}

View file

@ -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;

View file

@ -1,5 +1,6 @@
#include "builtin.h"
#include "cache.h"
#include "config.h"
#include "refs.h"
#include "object.h"
#include "parse-options.h"

View file

@ -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;

View file

@ -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";

View file

@ -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)

View file

@ -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"

View file

@ -2,6 +2,7 @@
* Builtin help command
*/
#include "cache.h"
#include "config.h"
#include "builtin.h"
#include "exec_cmd.h"
#include "parse-options.h"

View file

@ -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');
}

View file

@ -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"

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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