mirror of
https://github.com/git/git.git
synced 2026-03-13 02:13:24 +01:00
Merge commit 'mingw/master' into devel
Conflicts: Makefile daemon.c exec_cmd.c exec_cmd.h fast-import.c git.c hash-object.c http-push.c imap-send.c index-pack.c merge-index.c merge-tree.c mktag.c mktree.c pack-redundant.c patch-id.c unpack-file.c update-server-info.c upload-pack.c var.c
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -144,6 +144,7 @@ git-core-*/?*
|
||||
gitk-wish
|
||||
gitweb/gitweb.cgi
|
||||
test-chmtime
|
||||
test-ctype
|
||||
test-date
|
||||
test-delta
|
||||
test-dump-cache-tree
|
||||
|
||||
@@ -21,8 +21,13 @@ code. For git in general, three rough rules are:
|
||||
|
||||
As for more concrete guidelines, just imitate the existing code
|
||||
(this is a good guideline, no matter which project you are
|
||||
contributing to). But if you must have a list of rules,
|
||||
here they are.
|
||||
contributing to). It is always preferable to match the _local_
|
||||
convention. New code added to git suite is expected to match
|
||||
the overall style of existing code. Modifications to existing
|
||||
code is expected to match the style the surrounding code already
|
||||
uses (even if it doesn't match the overall style of existing code).
|
||||
|
||||
But if you must have a list of rules, here they are.
|
||||
|
||||
For shell scripts specifically (not exhaustive):
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
|
||||
prefix?=$(HOME)
|
||||
bindir?=$(prefix)/bin
|
||||
htmldir?=$(prefix)/share/doc/git-doc
|
||||
pdfdir?=$(prefix)/share/doc/git-doc
|
||||
mandir?=$(prefix)/share/man
|
||||
man1dir=$(mandir)/man1
|
||||
man5dir=$(mandir)/man5
|
||||
@@ -50,6 +51,7 @@ infodir?=$(prefix)/share/info
|
||||
MAKEINFO=makeinfo
|
||||
INSTALL_INFO=install-info
|
||||
DOCBOOK2X_TEXI=docbook2x-texi
|
||||
DBLATEX=dblatex
|
||||
ifndef PERL_PATH
|
||||
PERL_PATH = /usr/bin/perl
|
||||
endif
|
||||
@@ -87,6 +89,8 @@ man7: $(DOC_MAN7)
|
||||
|
||||
info: git.info gitman.info
|
||||
|
||||
pdf: user-manual.pdf
|
||||
|
||||
install: install-man
|
||||
|
||||
install-man: man
|
||||
@@ -107,6 +111,10 @@ install-info: info
|
||||
echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
|
||||
fi
|
||||
|
||||
install-pdf: pdf
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir)
|
||||
$(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir)
|
||||
|
||||
install-html: html
|
||||
sh ./install-webdoc.sh $(DESTDIR)$(htmldir)
|
||||
|
||||
@@ -187,17 +195,23 @@ git.info: user-manual.texi
|
||||
|
||||
user-manual.texi: user-manual.xml
|
||||
$(RM) $@+ $@
|
||||
$(DOCBOOK2X_TEXI) user-manual.xml --to-stdout | $(PERL_PATH) fix-texi.perl >$@+
|
||||
$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \
|
||||
$(PERL_PATH) fix-texi.perl >$@+
|
||||
mv $@+ $@
|
||||
|
||||
user-manual.pdf: user-manual.xml
|
||||
$(RM) $@+ $@
|
||||
$(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $<
|
||||
mv $@+ $@
|
||||
|
||||
gitman.texi: $(MAN_XML) cat-texi.perl
|
||||
$(RM) $@+ $@
|
||||
($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --to-stdout $(xml);)) | \
|
||||
$(PERL_PATH) cat-texi.perl $@ >$@+
|
||||
($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
|
||||
--to-stdout $(xml);)) | $(PERL_PATH) cat-texi.perl $@ >$@+
|
||||
mv $@+ $@
|
||||
|
||||
gitman.info: gitman.texi
|
||||
$(MAKEINFO) --no-split $*.texi
|
||||
$(MAKEINFO) --no-split --no-validate $*.texi
|
||||
|
||||
$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
|
||||
$(RM) $@+ $@
|
||||
|
||||
59
Documentation/RelNotes-1.6.1.1.txt
Normal file
59
Documentation/RelNotes-1.6.1.1.txt
Normal file
@@ -0,0 +1,59 @@
|
||||
GIT v1.6.1.1 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.6.1
|
||||
------------------
|
||||
|
||||
* "git add frotz/nitfol" when "frotz" is a submodule should have errored
|
||||
out, but it didn't.
|
||||
|
||||
* "git apply" took file modes from the patch text and updated the mode
|
||||
bits of the target tree even when the patch was not about mode changes.
|
||||
|
||||
* "git bisect view" on Cygwin did not launch gitk
|
||||
|
||||
* "git checkout $tree" did not trigger an error.
|
||||
|
||||
* "git commit" tried to remove COMMIT_EDITMSG from the work tree by mistake.
|
||||
|
||||
* "git describe --all" complained when a commit is described with a tag,
|
||||
which was nonsense.
|
||||
|
||||
* "git diff --no-index --" did not trigger no-index (aka "use git-diff as
|
||||
a replacement of diff on untracked files") behaviour.
|
||||
|
||||
* "git format-patch -1 HEAD" on a root commit failed to produce patch
|
||||
text.
|
||||
|
||||
* "git fsck branch" did not work as advertised; instead it behaved the same
|
||||
way as "git fsck".
|
||||
|
||||
* "git log --pretty=format:%s" did not handle a multi-line subject the
|
||||
same way as built-in log listers (i.e. shortlog, --pretty=oneline, etc.)
|
||||
|
||||
* "git daemon", and "git merge-file" are more careful when freopen fails
|
||||
and barf, instead of going on and writing to unopened filehandle.
|
||||
|
||||
* "git http-push" did not like some RFC 4918 compliant DAV server
|
||||
responses.
|
||||
|
||||
* "git merge -s recursive" mistakenly overwritten an untracked file in the
|
||||
work tree upon delete/modify conflict.
|
||||
|
||||
* "git merge -s recursive" didn't leave the index unmerged for entries with
|
||||
rename/delete conflictd.
|
||||
|
||||
* "git merge -s recursive" clobbered untracked files in the work tree.
|
||||
|
||||
* "git mv -k" with more than one errorneous paths misbehaved.
|
||||
|
||||
* "git read-tree -m -u" hence branch switching incorrectly lost a
|
||||
subdirectory in rare cases.
|
||||
|
||||
* "git rebase -i" issued an unnecessary error message upon a user error of
|
||||
marking the first commit to be "squash"ed.
|
||||
|
||||
* "git shortlog" did not format a commit message with multi-line
|
||||
subject correctly.
|
||||
|
||||
Many documentation updates.
|
||||
65
Documentation/RelNotes-1.6.2.txt
Normal file
65
Documentation/RelNotes-1.6.2.txt
Normal file
@@ -0,0 +1,65 @@
|
||||
GIT v1.6.2 Release Notes
|
||||
========================
|
||||
|
||||
Updates since v1.6.1
|
||||
--------------------
|
||||
|
||||
(subsystems)
|
||||
|
||||
(portability)
|
||||
|
||||
(performance)
|
||||
|
||||
* pack-objects autodetects the number of CPUs available and uses threaded
|
||||
version.
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
* "git-add -p" learned 'g'oto action to jump directly to a hunk.
|
||||
|
||||
* git-cherry defaults to HEAD when the <upstream> argument is not given.
|
||||
|
||||
* git-cvsserver can be told not to add extra "via git-CVS emulator" to the
|
||||
commit log message it serves via gitcvs.commitmsgannotation configuration.
|
||||
|
||||
* git-diff learned a new option --inter-hunk-context to coalesce close
|
||||
hunks together and show context between them.
|
||||
|
||||
* git-filter-branch learned --prune-empty option that discards commits
|
||||
that do not change the contents.
|
||||
|
||||
* git-ls-tree learned --full-tree option that shows the path in full
|
||||
regardless of where in the work tree hierarchy the command was started.
|
||||
|
||||
* git-mergetool learned -y(--no-prompt) option to disable prompting.
|
||||
|
||||
* "git-reset --merge" is a new mode that works similar to the way
|
||||
"git checkout" switches branches, taking the local changes while
|
||||
switching to another commit.
|
||||
|
||||
(internal)
|
||||
|
||||
|
||||
Fixes since v1.6.1
|
||||
------------------
|
||||
|
||||
All of the fixes in v1.6.1.X maintenance series are included in this
|
||||
release, unless otherwise noted.
|
||||
|
||||
* "git-add sub/file" when sub is a submodule incorrectly added the path to
|
||||
the superproject.
|
||||
|
||||
* git-bundle did not exclude annotated tags even when a range given from the
|
||||
command line wanted to.
|
||||
|
||||
* git-grep did not work correctly for index entries with assume-unchanged bit.
|
||||
|
||||
* branch switching and merges had a silly bug that did not validate
|
||||
the correct directory when making sure an existing subdirectory is
|
||||
clean.
|
||||
|
||||
--
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.1-134-ge98c6a1
|
||||
echo O=$(git describe master)
|
||||
git shortlog --no-merges $O..master ^maint
|
||||
@@ -18,8 +18,12 @@ close TMP;
|
||||
|
||||
printf '\input texinfo
|
||||
@setfilename gitman.info
|
||||
@documentencoding us-ascii
|
||||
@node Top,,%s
|
||||
@documentencoding UTF-8
|
||||
@dircategory Development
|
||||
@direntry
|
||||
* Git Man Pages: (gitman). Manual pages for Git revision control system
|
||||
@end direntry
|
||||
@node Top,,, (dir)
|
||||
@top Git Manual Pages
|
||||
@documentlanguage en
|
||||
@menu
|
||||
|
||||
@@ -635,10 +635,16 @@ diff.renames::
|
||||
will enable basic rename detection. If set to "copies" or
|
||||
"copy", it will detect copies, as well.
|
||||
|
||||
diff.suppress-blank-empty::
|
||||
diff.suppressBlankEmpty::
|
||||
A boolean to inhibit the standard behavior of printing a space
|
||||
before each empty output line. Defaults to false.
|
||||
|
||||
diff.wordRegex::
|
||||
A POSIX Extended Regular Expression used to determine what is a "word"
|
||||
when performing word-by-word difference calculations. Character
|
||||
sequences that match the regular expression are "words", all other
|
||||
characters are *ignorable* whitespace.
|
||||
|
||||
fetch.unpackLimit::
|
||||
If the number of objects fetched over the git native
|
||||
transfer is below this
|
||||
@@ -702,7 +708,9 @@ gc.packrefs::
|
||||
|
||||
gc.pruneexpire::
|
||||
When 'git-gc' is run, it will call 'prune --expire 2.weeks.ago'.
|
||||
Override the grace period with this config variable.
|
||||
Override the grace period with this config variable. The value
|
||||
"now" may be used to disable this grace period and always prune
|
||||
unreachable objects immediately.
|
||||
|
||||
gc.reflogexpire::
|
||||
'git-reflog expire' removes reflog entries older than
|
||||
@@ -723,6 +731,10 @@ gc.rerereunresolved::
|
||||
kept for this many days when 'git-rerere gc' is run.
|
||||
The default is 15 days. See linkgit:git-rerere[1].
|
||||
|
||||
gitcvs.commitmsgannotation::
|
||||
Append this string to each commit message. Set to empty string
|
||||
to disable this feature. Defaults to "via git-CVS emulator".
|
||||
|
||||
gitcvs.enabled::
|
||||
Whether the CVS server interface is enabled for this repository.
|
||||
See linkgit:git-cvsserver[1].
|
||||
@@ -1044,6 +1056,16 @@ mergetool.keepBackup::
|
||||
is set to `false` then this file is not preserved. Defaults to
|
||||
`true` (i.e. keep the backup files).
|
||||
|
||||
mergetool.keepTemporaries::
|
||||
When invoking a custom merge tool, git uses a set of temporary
|
||||
files to pass to the tool. If the tool returns an error and this
|
||||
variable is set to `true`, then these temporary files will be
|
||||
preserved, otherwise they will be removed after the tool has
|
||||
exited. Defaults to `false`.
|
||||
|
||||
mergetool.prompt::
|
||||
Prompt before each invocation of the merge resolution program.
|
||||
|
||||
pack.window::
|
||||
The size of the window used by linkgit:git-pack-objects[1] when no
|
||||
window size is given on the command line. Defaults to 10.
|
||||
|
||||
@@ -19,16 +19,12 @@ endif::git-format-patch[]
|
||||
|
||||
ifndef::git-format-patch[]
|
||||
-p::
|
||||
-u::
|
||||
Generate patch (see section on generating patches).
|
||||
{git-diff? This is the default.}
|
||||
endif::git-format-patch[]
|
||||
|
||||
-u::
|
||||
Synonym for "-p".
|
||||
|
||||
-U<n>::
|
||||
Shorthand for "--unified=<n>".
|
||||
|
||||
--unified=<n>::
|
||||
Generate diffs with <n> lines of context instead of
|
||||
the usual three. Implies "-p".
|
||||
@@ -40,6 +36,9 @@ endif::git-format-patch[]
|
||||
--patch-with-raw::
|
||||
Synonym for "-p --raw".
|
||||
|
||||
--patience::
|
||||
Generate a diff using the "patience diff" algorithm.
|
||||
|
||||
--stat[=width[,name-width]]::
|
||||
Generate a diffstat. You can override the default
|
||||
output width for 80-column terminal by "--stat=width".
|
||||
@@ -95,8 +94,22 @@ endif::git-format-patch[]
|
||||
Turn off colored diff, even when the configuration file
|
||||
gives the default to color output.
|
||||
|
||||
--color-words::
|
||||
Show colored word diff, i.e. color words which have changed.
|
||||
--color-words[=<regex>]::
|
||||
Show colored word diff, i.e., color words which have changed.
|
||||
By default, words are separated by whitespace.
|
||||
+
|
||||
When a <regex> is specified, every non-overlapping match of the
|
||||
<regex> is considered a word. Anything between these matches is
|
||||
considered whitespace and ignored(!) for the purposes of finding
|
||||
differences. You may want to append `|[^[:space:]]` to your regular
|
||||
expression to make sure that it matches all non-whitespace characters.
|
||||
A match that contains a newline is silently truncated(!) at the
|
||||
newline.
|
||||
+
|
||||
The regex can also be set via a diff driver or configuration option, see
|
||||
linkgit:gitattributes[1] or linkgit:git-config[1]. Giving it explicitly
|
||||
overrides any diff driver or configuration setting. Diff drivers
|
||||
override configuration settings.
|
||||
|
||||
--no-renames::
|
||||
Turn off rename detection, even when the configuration
|
||||
@@ -120,7 +133,7 @@ endif::git-format-patch[]
|
||||
--abbrev[=<n>]::
|
||||
Instead of showing the full 40-byte hexadecimal object
|
||||
name in diff-raw format output and diff-tree header
|
||||
lines, show only handful hexdigits prefix. This is
|
||||
lines, show only a partial prefix. This is
|
||||
independent of --full-index option above, which controls
|
||||
the diff-patch output format. Non default number of
|
||||
digits can be specified with --abbrev=<n>.
|
||||
@@ -190,30 +203,28 @@ endif::git-format-patch[]
|
||||
can name which subdirectory to make the output relative
|
||||
to by giving a <path> as an argument.
|
||||
|
||||
-a::
|
||||
--text::
|
||||
Treat all files as text.
|
||||
|
||||
-a::
|
||||
Shorthand for "--text".
|
||||
|
||||
--ignore-space-at-eol::
|
||||
Ignore changes in whitespace at EOL.
|
||||
|
||||
-b::
|
||||
--ignore-space-change::
|
||||
Ignore changes in amount of whitespace. This ignores whitespace
|
||||
at line end, and considers all other sequences of one or
|
||||
more whitespace characters to be equivalent.
|
||||
|
||||
-b::
|
||||
Shorthand for "--ignore-space-change".
|
||||
|
||||
-w::
|
||||
--ignore-all-space::
|
||||
Ignore whitespace when comparing lines. This ignores
|
||||
differences even if one line has whitespace where the other
|
||||
line has none.
|
||||
|
||||
-w::
|
||||
Shorthand for "--ignore-all-space".
|
||||
--inter-hunk-context=<lines>::
|
||||
Show the context between diff hunks, up to the specified number
|
||||
of lines, thereby fusing hunks that are close to each other.
|
||||
|
||||
--exit-code::
|
||||
Make the program exit with codes similar to diff(1).
|
||||
|
||||
@@ -11,7 +11,8 @@ SYNOPSIS
|
||||
[verse]
|
||||
'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
|
||||
[--3way] [--interactive]
|
||||
[--whitespace=<option>] [-C<n>] [-p<n>]
|
||||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
||||
[--reject]
|
||||
[<mbox> | <Maildir>...]
|
||||
'git am' (--skip | --resolved | --abort)
|
||||
|
||||
@@ -60,12 +61,10 @@ default. You could use `--no-utf8` to override this.
|
||||
available locally.
|
||||
|
||||
--whitespace=<option>::
|
||||
This flag is passed to the 'git-apply' (see linkgit:git-apply[1])
|
||||
program that applies
|
||||
the patch.
|
||||
|
||||
-C<n>::
|
||||
-p<n>::
|
||||
--directory=<dir>::
|
||||
--reject::
|
||||
These flags are passed to the 'git-apply' (see linkgit:git-apply[1])
|
||||
program that applies
|
||||
the patch.
|
||||
|
||||
@@ -10,7 +10,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git apply' [--stat] [--numstat] [--summary] [--check] [--index]
|
||||
[--apply] [--no-add] [--build-fake-ancestor <file>] [-R | --reverse]
|
||||
[--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
|
||||
[--allow-binary-replacement | --binary] [--reject] [-z]
|
||||
[-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
|
||||
[--whitespace=<nowarn|warn|fix|error|error-all>]
|
||||
@@ -64,7 +64,7 @@ OPTIONS
|
||||
cached data, apply the patch, and store the result in the index,
|
||||
without using the working tree. This implies '--index'.
|
||||
|
||||
--build-fake-ancestor <file>::
|
||||
--build-fake-ancestor=<file>::
|
||||
Newer 'git-diff' output has embedded 'index information'
|
||||
for each blob to help identify the original version that
|
||||
the patch applies to. When this flag is given, and if
|
||||
|
||||
@@ -7,7 +7,7 @@ git-cherry - Find commits not merged upstream
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git cherry' [-v] <upstream> [<head>] [<limit>]
|
||||
'git cherry' [-v] [<upstream> [<head> [<limit>]]]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -51,6 +51,7 @@ OPTIONS
|
||||
|
||||
<upstream>::
|
||||
Upstream branch to compare against.
|
||||
Defaults to the first tracked remote branch, if available.
|
||||
|
||||
<head>::
|
||||
Working branch; defaults to HEAD.
|
||||
|
||||
@@ -43,7 +43,7 @@ OPTIONS
|
||||
Automatically implies --tags.
|
||||
|
||||
--abbrev=<n>::
|
||||
Instead of using the default 8 hexadecimal digits as the
|
||||
Instead of using the default 7 hexadecimal digits as the
|
||||
abbreviated object name, use <n> digits.
|
||||
|
||||
--candidates=<n>::
|
||||
@@ -87,7 +87,7 @@ With something like git.git current tree, I get:
|
||||
v1.0.4-14-g2414721
|
||||
|
||||
i.e. the current head of my "parent" branch is based on v1.0.4,
|
||||
but since it has a handful commits on top of that,
|
||||
but since it has a few commits on top of that,
|
||||
describe has added the number of additional commits ("14") and
|
||||
an abbreviated object name for the commit itself ("2414721")
|
||||
at the end.
|
||||
|
||||
@@ -21,7 +21,10 @@ OPTIONS
|
||||
-------
|
||||
include::diff-options.txt[]
|
||||
|
||||
-1 -2 -3 or --base --ours --theirs, and -0::
|
||||
-1 --base::
|
||||
-2 --ours::
|
||||
-3 --theirs::
|
||||
-0::
|
||||
Diff against the "base" version, "our branch" or "their
|
||||
branch" respectively. With these options, diffs for
|
||||
merged entries are not shown.
|
||||
|
||||
@@ -122,6 +122,10 @@ You can use the 'map' convenience function in this filter, and other
|
||||
convenience functions, too. For example, calling 'skip_commit "$@"'
|
||||
will leave out the current commit (but not its changes! If you want
|
||||
that, use 'git-rebase' instead).
|
||||
+
|
||||
You can also use the 'git_commit_non_empty_tree "$@"' instead of
|
||||
'git commit-tree "$@"' if you don't wish to keep commits with a single parent
|
||||
and that makes no change to the tree.
|
||||
|
||||
--tag-name-filter <command>::
|
||||
This is the filter for rewriting tag names. When passed,
|
||||
@@ -151,6 +155,16 @@ to other tags will be rewritten to point to the underlying commit.
|
||||
The result will contain that directory (and only that) as its
|
||||
project root.
|
||||
|
||||
--prune-empty::
|
||||
Some kind of filters will generate empty commits, that left the tree
|
||||
untouched. This switch allow git-filter-branch to ignore such
|
||||
commits. Though, this switch only applies for commits that have one
|
||||
and only one parent, it will hence keep merges points. Also, this
|
||||
option is not compatible with the use of '--commit-filter'. Though you
|
||||
just need to use the function 'git_commit_non_empty_tree "$@"' instead
|
||||
of the 'git commit-tree "$@"' idiom in your commit filter to make that
|
||||
happen.
|
||||
|
||||
--original <namespace>::
|
||||
Use this option to set the namespace where the original commits
|
||||
will be stored. The default value is 'refs/original'.
|
||||
|
||||
@@ -126,7 +126,7 @@ OPTIONS
|
||||
|
||||
--abbrev[=<n>]::
|
||||
Instead of showing the full 40-byte hexadecimal object
|
||||
lines, show only handful hexdigits prefix.
|
||||
lines, show only a partial prefix.
|
||||
Non default number of digits can be specified with --abbrev=<n>.
|
||||
|
||||
\--::
|
||||
|
||||
@@ -10,7 +10,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git ls-tree' [-d] [-r] [-t] [-l] [-z]
|
||||
[--name-only] [--name-status] [--full-name] [--abbrev=[<n>]]
|
||||
[--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev=[<n>]]
|
||||
<tree-ish> [paths...]
|
||||
|
||||
DESCRIPTION
|
||||
@@ -30,6 +30,8 @@ in the current working directory. Note that:
|
||||
'sub/dir' in 'HEAD'). You don't want to give a tree that is not at the
|
||||
root level (e.g. 'git ls-tree -r HEAD:sub dir') in this case, as that
|
||||
would result in asking for 'sub/sub/dir' in the 'HEAD' commit.
|
||||
However, the current working directory can be ignored by passing
|
||||
--full-tree option.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
@@ -59,13 +61,17 @@ OPTIONS
|
||||
|
||||
--abbrev[=<n>]::
|
||||
Instead of showing the full 40-byte hexadecimal object
|
||||
lines, show only handful hexdigits prefix.
|
||||
lines, show only a partial prefix.
|
||||
Non default number of digits can be specified with --abbrev=<n>.
|
||||
|
||||
--full-name::
|
||||
Instead of showing the path names relative to the current working
|
||||
directory, show the full path names.
|
||||
|
||||
--full-tree::
|
||||
Do not limit the listing to the current working directory.
|
||||
Implies --full-name.
|
||||
|
||||
paths::
|
||||
When paths are given, show them (note that this isn't really raw
|
||||
pathnames, but rather a list of patterns to match). Otherwise
|
||||
|
||||
@@ -7,7 +7,7 @@ git-mergetool - Run merge conflict resolution tools to resolve merge conflicts
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git mergetool' [--tool=<tool>] [<file>]...
|
||||
'git mergetool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<file>]...
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -22,7 +22,8 @@ with merge conflicts.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-t or --tool=<tool>::
|
||||
-t <tool>::
|
||||
--tool=<tool>::
|
||||
Use the merge resolution program specified by <tool>.
|
||||
Valid merge tools are:
|
||||
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
|
||||
@@ -60,6 +61,16 @@ variable `mergetool.<tool>.trustExitCode` can be set to `true`.
|
||||
Otherwise, 'git-mergetool' will prompt the user to indicate the
|
||||
success of the resolution after the custom tool has exited.
|
||||
|
||||
-y::
|
||||
--no-prompt::
|
||||
Don't prompt before each invocation of the merge resolution
|
||||
program.
|
||||
|
||||
--prompt::
|
||||
Prompt before each invocation of the merge resolution program.
|
||||
This is the default behaviour; the option is provided to
|
||||
override any configuration settings.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Theodore Y Ts'o <tytso@mit.edu>
|
||||
|
||||
@@ -28,7 +28,9 @@ OPTIONS
|
||||
-------
|
||||
<repository>::
|
||||
The "remote" repository that is destination of a push
|
||||
operation. See the section <<URLS,GIT URLS>> below.
|
||||
operation. This parameter can be either a URL
|
||||
(see the section <<URLS,GIT URLS>> below) or the name
|
||||
of a remote (see the section <<REMOTES,REMOTES>> below).
|
||||
|
||||
<refspec>...::
|
||||
The canonical format of a <refspec> parameter is
|
||||
@@ -42,22 +44,21 @@ tip of `master` branch); see linkgit:git-rev-parse[1]) that you
|
||||
want to push. The <dst> side represents the destination location.
|
||||
+
|
||||
The local ref that matches <src> is used
|
||||
to fast forward the remote ref that matches <dst> (or, if no <dst> was
|
||||
specified, the same ref that <src> referred to locally). If
|
||||
to fast forward the remote ref that matches <dst>. If
|
||||
the optional leading plus `+` is used, the remote ref is updated
|
||||
even if it does not result in a fast forward update.
|
||||
+
|
||||
`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
|
||||
+
|
||||
A parameter <ref> without a colon pushes the <ref> from the source
|
||||
repository to the destination repository under the same name.
|
||||
A lonely <src> parameter (without a colon and a destination) pushes
|
||||
the <src> to the same name in the destination repository.
|
||||
+
|
||||
Pushing an empty <src> allows you to delete the <dst> ref from
|
||||
the remote repository.
|
||||
+
|
||||
The special refspec `:` (or `+:` to allow non-fast forward updates)
|
||||
directs git to push "matching" heads: for every head that exists on
|
||||
the local side, the remote side is updated if a head of the same name
|
||||
directs git to push "matching" branches: for every branch that exists on
|
||||
the local side, the remote side is updated if a branch of the same name
|
||||
already exists on the remote side. This is the default operation mode
|
||||
if no explicit refspec is found (that is neither on the command line
|
||||
nor in any Push line of the corresponding remotes file---see below).
|
||||
@@ -86,14 +87,12 @@ nor in any Push line of the corresponding remotes file---see below).
|
||||
line.
|
||||
|
||||
--receive-pack=<git-receive-pack>::
|
||||
--exec=<git-receive-pack>::
|
||||
Path to the 'git-receive-pack' program on the remote
|
||||
end. Sometimes useful when pushing to a remote
|
||||
repository over ssh, and you do not have the program in
|
||||
a directory on the default $PATH.
|
||||
|
||||
--exec=<git-receive-pack>::
|
||||
Same as \--receive-pack=<git-receive-pack>.
|
||||
|
||||
-f::
|
||||
--force::
|
||||
Usually, the command refuses to update a remote ref that is
|
||||
|
||||
@@ -8,10 +8,11 @@ git-rebase - Forward-port local commits to the updated upstream head
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
|
||||
[-s <strategy> | --strategy=<strategy>] [--no-verify]
|
||||
[-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
|
||||
[--onto <newbase>] <upstream> [<branch>]
|
||||
'git rebase' [-i | --interactive] [options] [--onto <newbase>]
|
||||
<upstream> [<branch>]
|
||||
'git rebase' [-i | --interactive] [options] --onto <newbase>
|
||||
--root [<branch>]
|
||||
|
||||
'git rebase' --continue | --skip | --abort
|
||||
|
||||
DESCRIPTION
|
||||
@@ -22,7 +23,8 @@ it remains on the current branch.
|
||||
|
||||
All changes made by commits in the current branch but that are not
|
||||
in <upstream> are saved to a temporary area. This is the same set
|
||||
of commits that would be shown by `git log <upstream>..HEAD`.
|
||||
of commits that would be shown by `git log <upstream>..HEAD` (or
|
||||
`git log HEAD`, if --root is specified).
|
||||
|
||||
The current branch is reset to <upstream>, or <newbase> if the
|
||||
--onto option was supplied. This has the exact same effect as
|
||||
@@ -255,6 +257,15 @@ OPTIONS
|
||||
--preserve-merges::
|
||||
Instead of ignoring merges, try to recreate them.
|
||||
|
||||
--root::
|
||||
Rebase all commits reachable from <branch>, instead of
|
||||
limiting them with an <upstream>. This allows you to rebase
|
||||
the root commit(s) on a branch. Must be used with --onto, and
|
||||
will skip changes already contained in <newbase> (instead of
|
||||
<upstream>). When used together with --preserve-merges, 'all'
|
||||
root commits will be rewritten to have <newbase> as parent
|
||||
instead.
|
||||
|
||||
include::merge-strategies.txt[]
|
||||
|
||||
NOTES
|
||||
|
||||
@@ -8,7 +8,7 @@ git-reset - Reset current HEAD to the specified state
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git reset' [--mixed | --soft | --hard] [-q] [<commit>]
|
||||
'git reset' [--mixed | --soft | --hard | --merge] [-q] [<commit>]
|
||||
'git reset' [-q] [<commit>] [--] <paths>...
|
||||
|
||||
DESCRIPTION
|
||||
@@ -45,6 +45,11 @@ OPTIONS
|
||||
switched to. Any changes to tracked files in the working tree
|
||||
since <commit> are lost.
|
||||
|
||||
--merge::
|
||||
Resets the index to match the tree recorded by the named commit,
|
||||
and updates the files that are different between the named commit
|
||||
and the current commit in the working tree.
|
||||
|
||||
-q::
|
||||
Be quiet, only report errors.
|
||||
|
||||
@@ -152,6 +157,28 @@ tip of the current branch in ORIG_HEAD, so resetting hard to it
|
||||
brings your index file and the working tree back to that state,
|
||||
and resets the tip of the branch to that commit.
|
||||
|
||||
Undo a merge or pull inside a dirty work tree::
|
||||
+
|
||||
------------
|
||||
$ git pull <1>
|
||||
Auto-merging nitfol
|
||||
Merge made by recursive.
|
||||
nitfol | 20 +++++----
|
||||
...
|
||||
$ git reset --merge ORIG_HEAD <2>
|
||||
------------
|
||||
+
|
||||
<1> Even if you may have local modifications in your
|
||||
working tree, you can safely say "git pull" when you know
|
||||
that the change in the other branch does not overlap with
|
||||
them.
|
||||
<2> After inspecting the result of the merge, you may find
|
||||
that the change in the other branch is unsatisfactory. Running
|
||||
"git reset --hard ORIG_HEAD" will let you go back to where you
|
||||
were, but it will discard your local changes, which you do not
|
||||
want. "git reset --merge" keeps your local changes.
|
||||
|
||||
|
||||
Interrupted workflow::
|
||||
+
|
||||
Suppose you are interrupted by an urgent fix request while you
|
||||
|
||||
@@ -34,6 +34,7 @@ The --bcc option must be repeated for each user you want on the bcc list.
|
||||
|
||||
--cc::
|
||||
Specify a starting "Cc:" value for each email.
|
||||
Default is the value of 'sendemail.cc'.
|
||||
+
|
||||
The --cc option must be repeated for each user you want on the cc list.
|
||||
|
||||
@@ -197,12 +198,6 @@ Administering
|
||||
--[no-]validate::
|
||||
Perform sanity checks on patches.
|
||||
Currently, validation means the following:
|
||||
|
||||
--[no-]format-patch::
|
||||
When an argument may be understood either as a reference or as a file name,
|
||||
choose to understand it as a format-patch argument ('--format-patch')
|
||||
or as a file name ('--no-format-patch'). By default, when such a conflict
|
||||
occurs, git send-email will fail.
|
||||
+
|
||||
--
|
||||
* Warn of patches that contain lines longer than 998 characters; this
|
||||
@@ -212,6 +207,12 @@ Administering
|
||||
Default is the value of 'sendemail.validate'; if this is not set,
|
||||
default to '--validate'.
|
||||
|
||||
--[no-]format-patch::
|
||||
When an argument may be understood either as a reference or as a file name,
|
||||
choose to understand it as a format-patch argument ('--format-patch')
|
||||
or as a file name ('--no-format-patch'). By default, when such a conflict
|
||||
occurs, git send-email will fail.
|
||||
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
@@ -18,8 +18,9 @@ of server-side GIT commands implementing the pull/push functionality.
|
||||
The commands can be executed only by the '-c' option; the shell is not
|
||||
interactive.
|
||||
|
||||
Currently, only the 'git-receive-pack' and 'git-upload-pack' commands
|
||||
are permitted to be called, with a single required argument.
|
||||
Currently, only three commands are permitted to be called, 'git-receive-pack'
|
||||
'git-upload-pack' with a single required argument or 'cvs server' (to invoke
|
||||
'git-cvsserver').
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
@@ -48,15 +48,41 @@ OPTIONS
|
||||
FILES
|
||||
-----
|
||||
|
||||
If the file `.mailmap` exists, it will be used for mapping author
|
||||
email addresses to a real author name. One mapping per line, first
|
||||
the author name followed by the email address enclosed by
|
||||
'<' and '>'. Use hash '#' for comments. Example:
|
||||
If a file `.mailmap` exists at the toplevel of the repository,
|
||||
it is used to map an author email address to a canonical real name. This
|
||||
can be used to coalesce together commits by the same person where their
|
||||
name was spelled differently (whether with the same email address or
|
||||
not).
|
||||
|
||||
Each line in the file consists, in this order, of the canonical real name
|
||||
of an author, whitespace, and an email address (enclosed by '<' and '>')
|
||||
to map to the name. Use hash '#' for comments, either on their own line,
|
||||
or after the email address.
|
||||
|
||||
A canonical name may appear in more than one line, associated with
|
||||
different email addresses, but it doesn't make sense for a given address
|
||||
to appear more than once (if that happens, a later line overrides the
|
||||
earlier ones).
|
||||
|
||||
So, for example, if your history contains commits by two authors, Jane
|
||||
and Joe, whose names appear in the repository under several forms:
|
||||
|
||||
------------
|
||||
# Keep alphabetized
|
||||
Adam Morrow <adam@localhost.localdomain>
|
||||
Eve Jones <eve@laptop.(none)>
|
||||
Joe Developer <joe@example.com>
|
||||
Joe R. Developer <joe@example.com>
|
||||
Jane Doe <jane@example.com>
|
||||
Jane Doe <jane@laptop.(none)>
|
||||
Jane D. <jane@desktop.(none)>
|
||||
------------
|
||||
|
||||
Then, supposing Joe wants his middle name initial used, and Jane prefers
|
||||
her family name fully spelled out, a proper `.mailmap` file would look like:
|
||||
|
||||
------------
|
||||
# Note how we don't need an entry for <jane@laptop.(none)>, because the
|
||||
# real name of that author is correct already, and coalesced directly.
|
||||
Jane Doe <jane@desktop.(none)>
|
||||
Joe R. Developer <joe@random.com>
|
||||
------------
|
||||
|
||||
Author
|
||||
|
||||
@@ -92,6 +92,30 @@ COMMANDS
|
||||
.git/config file may be specified as an optional command-line
|
||||
argument.
|
||||
|
||||
--localtime;;
|
||||
Store Git commit times in the local timezone instead of UTC. This
|
||||
makes 'git-log' (even without --date=local) show the same times
|
||||
that `svn log` would in the local timezone.
|
||||
|
||||
This doesn't interfere with interoperating with the Subversion
|
||||
repository you cloned from, but if you wish for your local Git
|
||||
repository to be able to interoperate with someone else's local Git
|
||||
repository, either don't use this option or you should both use it in
|
||||
the same local timezone.
|
||||
|
||||
--ignore-paths=<regex>;;
|
||||
This allows one to specify Perl regular expression that will
|
||||
cause skipping of all matching paths from checkout from SVN.
|
||||
Examples:
|
||||
|
||||
--ignore-paths="^doc" - skip "doc*" directory for every fetch.
|
||||
|
||||
--ignore-paths="^[^/]+/(?:branches|tags)" - skip "branches"
|
||||
and "tags" of first level directories.
|
||||
|
||||
Regular expression is not persistent, you should specify
|
||||
it every time when fetching.
|
||||
|
||||
'clone'::
|
||||
Runs 'init' and 'fetch'. It will automatically create a
|
||||
directory based on the basename of the URL passed to it;
|
||||
|
||||
@@ -70,7 +70,7 @@ OPTIONS
|
||||
|
||||
-m <msg>::
|
||||
Use the given tag message (instead of prompting).
|
||||
If multiple `-m` options are given, there values are
|
||||
If multiple `-m` options are given, their values are
|
||||
concatenated as separate paragraphs.
|
||||
Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
|
||||
is given.
|
||||
@@ -207,7 +207,7 @@ determines who are interested in whose tags.
|
||||
|
||||
A one-shot pull is a sign that a commit history is now crossing
|
||||
the boundary between one circle of people (e.g. "people who are
|
||||
primarily interested in networking part of the kernel") who may
|
||||
primarily interested in the networking part of the kernel") who may
|
||||
have their own set of tags (e.g. "this is the third release
|
||||
candidate from the networking group to be proposed for general
|
||||
consumption with 2.6.21 release") to another circle of people
|
||||
|
||||
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.6.1/git.html[documentation for release 1.6.1]
|
||||
* link:v1.6.1.1/git.html[documentation for release 1.6.1.1]
|
||||
|
||||
* release notes for
|
||||
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]
|
||||
|
||||
@@ -317,6 +317,8 @@ patterns are available:
|
||||
|
||||
- `bibtex` suitable for files with BibTeX coded references.
|
||||
|
||||
- `cpp` suitable for source code in the C and C++ languages.
|
||||
|
||||
- `html` suitable for HTML/XHTML documents.
|
||||
|
||||
- `java` suitable for source code in the Java language.
|
||||
@@ -334,6 +336,25 @@ patterns are available:
|
||||
- `tex` suitable for source code for LaTeX documents.
|
||||
|
||||
|
||||
Customizing word diff
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can customize the rules that `git diff --color-words` uses to
|
||||
split words in a line, by specifying an appropriate regular expression
|
||||
in the "diff.*.wordRegex" configuration variable. For example, in TeX
|
||||
a backslash followed by a sequence of letters forms a command, but
|
||||
several such commands can be run together without intervening
|
||||
whitespace. To separate them, use a regular expression such as
|
||||
|
||||
------------------------
|
||||
[diff "tex"]
|
||||
wordRegex = "\\\\[a-zA-Z]+|[{}]|\\\\.|[^\\{}[:space:]]+"
|
||||
------------------------
|
||||
|
||||
A built-in pattern is provided for all languages listed in the
|
||||
previous section.
|
||||
|
||||
|
||||
Performing text diffs of binary files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -1243,10 +1243,10 @@ $ git ls-files --stage
|
||||
------------
|
||||
|
||||
In our example of only two files, we did not have unchanged
|
||||
files so only 'example' resulted in collapsing, but in real-life
|
||||
large projects, only small number of files change in one commit,
|
||||
and this 'collapsing' tends to trivially merge most of the paths
|
||||
fairly quickly, leaving only a handful the real changes in non-zero
|
||||
files so only 'example' resulted in collapsing. But in real-life
|
||||
large projects, when only a small number of files change in one commit,
|
||||
this 'collapsing' tends to trivially merge most of the paths
|
||||
fairly quickly, leaving only a handful of real changes in non-zero
|
||||
stages.
|
||||
|
||||
To look at only non-zero stages, use `\--unmerged` flag:
|
||||
|
||||
@@ -15,7 +15,7 @@ DESCRIPTION
|
||||
|
||||
Hooks are little scripts you can place in `$GIT_DIR/hooks`
|
||||
directory to trigger action at certain points. When
|
||||
'git-init' is run, a handful example hooks are copied in the
|
||||
'git-init' is run, a handful of example hooks are copied into the
|
||||
`hooks` directory of the new repository, but by default they are
|
||||
all disabled. To enable a hook, rename it by removing its `.sample`
|
||||
suffix.
|
||||
@@ -90,7 +90,7 @@ This hook is invoked by 'git-commit' right after preparing the
|
||||
default log message, and before the editor is started.
|
||||
|
||||
It takes one to three parameters. The first is the name of the file
|
||||
that the commit log message. The second is the source of the commit
|
||||
that contains the commit log message. The second is the source of the commit
|
||||
message, and can be: `message` (if a `-m` or `-F` option was
|
||||
given); `template` (if a `-t` option was given or the
|
||||
configuration option `commit.template` is set); `merge` (if the
|
||||
|
||||
@@ -32,12 +32,12 @@ Initialized empty Git repository in .git/
|
||||
$ echo 'hello world' > file.txt
|
||||
$ git add .
|
||||
$ git commit -a -m "initial commit"
|
||||
[master (root-commit)] created 54196cc: "initial commit"
|
||||
[master (root-commit) 54196cc] initial commit
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
create mode 100644 file.txt
|
||||
$ echo 'hello world!' >file.txt
|
||||
$ git commit -a -m "add emphasis"
|
||||
[master] created c4d59f3: "add emphasis"
|
||||
[master c4d59f3] add emphasis
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
@@ -308,9 +308,7 @@ alice$ git pull /home/bob/myrepo master
|
||||
|
||||
This merges the changes from Bob's "master" branch into Alice's
|
||||
current branch. If Alice has made her own changes in the meantime,
|
||||
then she may need to manually fix any conflicts. (Note that the
|
||||
"master" argument in the above command is actually unnecessary, as it
|
||||
is the default.)
|
||||
then she may need to manually fix any conflicts.
|
||||
|
||||
The "pull" command thus performs two operations: it fetches changes
|
||||
from a remote branch, then merges them into the current branch.
|
||||
@@ -590,7 +588,7 @@ list. When the history has lines of development that diverged and
|
||||
then merged back together, the order in which 'git-log' presents
|
||||
those commits is meaningless.
|
||||
|
||||
Most projects with multiple contributors (such as the linux kernel,
|
||||
Most projects with multiple contributors (such as the Linux kernel,
|
||||
or git itself) have frequent merges, and 'gitk' does a better job of
|
||||
visualizing their history. For example,
|
||||
|
||||
@@ -642,7 +640,7 @@ digressions that may be interesting at this point are:
|
||||
|
||||
* linkgit:git-format-patch[1], linkgit:git-am[1]: These convert
|
||||
series of git commits into emailed patches, and vice versa,
|
||||
useful for projects such as the linux kernel which rely heavily
|
||||
useful for projects such as the Linux kernel which rely heavily
|
||||
on emailed patches.
|
||||
|
||||
* linkgit:git-bisect[1]: When there is a regression in your
|
||||
|
||||
@@ -27,7 +27,7 @@ the kind of task StGIT is designed to do.
|
||||
I just have done a simpler one, this time using only the core
|
||||
GIT tools.
|
||||
|
||||
I had a handful commits that were ahead of master in pu, and I
|
||||
I had a handful of commits that were ahead of master in pu, and I
|
||||
wanted to add some documentation bypassing my usual habit of
|
||||
placing new things in pu first. At the beginning, the commit
|
||||
ancestry graph looked like this:
|
||||
|
||||
@@ -124,6 +124,7 @@ The placeholders are:
|
||||
- '%Cgreen': switch color to green
|
||||
- '%Cblue': switch color to blue
|
||||
- '%Creset': reset color
|
||||
- '%C(...)': color specification, as described in color.branch.* config option
|
||||
- '%m': left, right or boundary mark
|
||||
- '%n': newline
|
||||
- '%x00': print a byte from a hex code
|
||||
|
||||
@@ -10,7 +10,7 @@ configuration (see linkgit:git-config[1]).
|
||||
|
||||
--abbrev-commit::
|
||||
Instead of showing the full 40-byte hexadecimal commit object
|
||||
name, show only handful hexdigits prefix. Non default number of
|
||||
name, show only a partial prefix. Non default number of
|
||||
digits can be specified with "--abbrev=<n>" (which also modifies
|
||||
diff output, if it is displayed).
|
||||
+
|
||||
|
||||
@@ -52,6 +52,21 @@ Functions
|
||||
Wait for the completion of an asynchronous function that was
|
||||
started with start_async().
|
||||
|
||||
`run_hook`::
|
||||
|
||||
Run a hook.
|
||||
The first argument is a pathname to an index file, or NULL
|
||||
if the hook uses the default index file or no index is needed.
|
||||
The second argument is the name of the hook.
|
||||
The further arguments correspond to the hook arguments.
|
||||
The last argument has to be NULL to terminate the arguments list.
|
||||
If the hook does not exist or is not executable, the return
|
||||
value will be zero.
|
||||
If it is executable, the hook will be executed and the exit
|
||||
status of the hook is returned.
|
||||
On execution, .stdout_to_stderr and .no_stdin will be set.
|
||||
(See below.)
|
||||
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
@@ -133,8 +133,10 @@ Functions
|
||||
|
||||
* Adding data to the buffer
|
||||
|
||||
NOTE: All of these functions in this section will grow the buffer as
|
||||
necessary.
|
||||
NOTE: All of the functions in this section will grow the buffer as necessary.
|
||||
If they fail for some reason other than memory shortage and the buffer hadn't
|
||||
been allocated before (i.e. the `struct strbuf` was set to `STRBUF_INIT`),
|
||||
then they will free() it.
|
||||
|
||||
`strbuf_addch`::
|
||||
|
||||
@@ -235,6 +237,11 @@ same behaviour as well.
|
||||
Read the contents of a file, specified by its path. The third argument
|
||||
can be used to give a hint about the file size, to avoid reallocs.
|
||||
|
||||
`strbuf_readlink`::
|
||||
|
||||
Read the target of a symbolic link, specified by its path. The third
|
||||
argument can be used to give a hint about the size, to avoid reallocs.
|
||||
|
||||
`strbuf_getline`::
|
||||
|
||||
Read a line from a FILE* pointer. The second argument specifies the line
|
||||
|
||||
@@ -59,7 +59,7 @@ project in mind, here are some interesting examples:
|
||||
------------------------------------------------
|
||||
# git itself (approx. 10MB download):
|
||||
$ git clone git://git.kernel.org/pub/scm/git/git.git
|
||||
# the linux kernel (approx. 150MB download):
|
||||
# the Linux kernel (approx. 150MB download):
|
||||
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
|
||||
------------------------------------------------
|
||||
|
||||
@@ -1009,7 +1009,7 @@ $ git init
|
||||
If you have some initial content (say, a tarball):
|
||||
|
||||
-------------------------------------------------
|
||||
$ tar -xzvf project.tar.gz
|
||||
$ tar xzvf project.tar.gz
|
||||
$ cd project
|
||||
$ git init
|
||||
$ git add . # include everything below ./ in the first commit:
|
||||
@@ -1340,7 +1340,7 @@ These will display all commits which exist only on HEAD or on
|
||||
MERGE_HEAD, and which touch an unmerged file.
|
||||
|
||||
You may also use linkgit:git-mergetool[1], which lets you merge the
|
||||
unmerged files using external tools such as emacs or kdiff3.
|
||||
unmerged files using external tools such as Emacs or kdiff3.
|
||||
|
||||
Each time you resolve the conflicts in a file and update the index:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.6.0.2.GIT
|
||||
DEF_VER=v1.6.1.GIT
|
||||
|
||||
LF='
|
||||
'
|
||||
|
||||
3
INSTALL
3
INSTALL
@@ -101,6 +101,9 @@ Issues of note:
|
||||
Building and installing the info file additionally requires
|
||||
makeinfo and docbook2X. Version 0.8.3 is known to work.
|
||||
|
||||
Building and installing the pdf file additionally requires
|
||||
dblatex. Version 0.2.7 with asciidoc >= 8.2.7 is known to work.
|
||||
|
||||
The documentation is written for AsciiDoc 7, but "make
|
||||
ASCIIDOC8=YesPlease doc" will let you format with AsciiDoc 8.
|
||||
|
||||
|
||||
31
Makefile
31
Makefile
@@ -822,6 +822,7 @@ ifeq ($(uname_S),Darwin)
|
||||
BASIC_LDFLAGS += -L/opt/local/lib
|
||||
endif
|
||||
endif
|
||||
PTHREAD_LIBS =
|
||||
endif
|
||||
|
||||
ifndef CC_LD_DYNPATH
|
||||
@@ -1301,7 +1302,7 @@ $(LIB_FILE): $(LIB_OBJS)
|
||||
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
|
||||
|
||||
XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
|
||||
xdiff/xmerge.o
|
||||
xdiff/xmerge.o xdiff/xpatience.o
|
||||
$(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
|
||||
xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
|
||||
|
||||
@@ -1321,6 +1322,9 @@ html:
|
||||
info:
|
||||
$(MAKE) -C Documentation info
|
||||
|
||||
pdf:
|
||||
$(MAKE) -C Documentation pdf
|
||||
|
||||
TAGS:
|
||||
$(RM) TAGS
|
||||
$(FIND) . -name '*.[hcS]' -print | xargs etags -a
|
||||
@@ -1367,7 +1371,15 @@ endif
|
||||
|
||||
### Testing rules
|
||||
|
||||
TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
|
||||
TEST_PROGRAMS += test-chmtime$X
|
||||
TEST_PROGRAMS += test-ctype$X
|
||||
TEST_PROGRAMS += test-date$X
|
||||
TEST_PROGRAMS += test-delta$X
|
||||
TEST_PROGRAMS += test-genrandom$X
|
||||
TEST_PROGRAMS += test-match-trees$X
|
||||
TEST_PROGRAMS += test-parse-options$X
|
||||
TEST_PROGRAMS += test-path-utils$X
|
||||
TEST_PROGRAMS += test-sha1$X
|
||||
|
||||
all:: $(TEST_PROGRAMS)
|
||||
|
||||
@@ -1380,6 +1392,8 @@ export NO_SVN_TESTS
|
||||
test: all
|
||||
$(MAKE) -C t/ all
|
||||
|
||||
test-ctype$X: ctype.o
|
||||
|
||||
test-date$X: date.o ctype.o
|
||||
|
||||
test-delta$X: diff-delta.o patch-delta.o
|
||||
@@ -1445,10 +1459,12 @@ endif
|
||||
{ $(RM) "$$execdir/git-add$X" && \
|
||||
ln git-add$X "$$execdir/git-add$X" 2>/dev/null || \
|
||||
cp git-add$X "$$execdir/git-add$X"; } && \
|
||||
{ $(foreach p,$(filter-out git-add$X,$(BUILT_INS)), $(RM) "$$execdir/$p" && \
|
||||
ln "$$execdir/git-add$X" "$$execdir/$p" 2>/dev/null || \
|
||||
ln -s "git-add$X" "$$execdir/$p" 2>/dev/null || \
|
||||
cp "$$execdir/git-add$X" "$$execdir/$p" || exit;) } && \
|
||||
{ for p in $(filter-out git-add$X,$(BUILT_INS)); do \
|
||||
$(RM) "$$execdir/$$p" && \
|
||||
ln "$$execdir/git-add$X" "$$execdir/$$p" 2>/dev/null || \
|
||||
ln -s "git-add$X" "$$execdir/$$p" 2>/dev/null || \
|
||||
cp "$$execdir/git-add$X" "$$execdir/$$p" || exit; \
|
||||
done } && \
|
||||
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
|
||||
|
||||
install-doc:
|
||||
@@ -1463,6 +1479,9 @@ install-html:
|
||||
install-info:
|
||||
$(MAKE) -C Documentation install-info
|
||||
|
||||
install-pdf:
|
||||
$(MAKE) -C Documentation install-pdf
|
||||
|
||||
quick-install-doc:
|
||||
$(MAKE) -C Documentation quick-install
|
||||
|
||||
|
||||
2
README
2
README
@@ -24,7 +24,7 @@ It was originally written by Linus Torvalds with help of a group of
|
||||
hackers around the net. It is currently maintained by Junio C Hamano.
|
||||
|
||||
Please read the file INSTALL for installation instructions.
|
||||
See Documentation/tutorial.txt to get started, then see
|
||||
See Documentation/gittutorial.txt to get started, then see
|
||||
Documentation/everyday.txt for a useful minimum set of commands,
|
||||
and "man git-commandname" for documentation of each command.
|
||||
CVS users may also want to read Documentation/cvs-migration.txt.
|
||||
|
||||
@@ -68,6 +68,33 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p
|
||||
free(seen);
|
||||
}
|
||||
|
||||
static void treat_gitlinks(const char **pathspec)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!pathspec || !*pathspec)
|
||||
return;
|
||||
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
if (S_ISGITLINK(ce->ce_mode)) {
|
||||
int len = ce_namelen(ce), j;
|
||||
for (j = 0; pathspec[j]; j++) {
|
||||
int len2 = strlen(pathspec[j]);
|
||||
if (len2 <= len || pathspec[j][len] != '/' ||
|
||||
memcmp(ce->name, pathspec[j], len))
|
||||
continue;
|
||||
if (len2 == len + 1)
|
||||
/* strip trailing slash */
|
||||
pathspec[j] = xstrndup(ce->name, len);
|
||||
else
|
||||
die ("Path '%s' is in submodule '%.*s'",
|
||||
pathspec[j], len, ce->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_directory(struct dir_struct *dir, const char **pathspec,
|
||||
int ignored_too)
|
||||
{
|
||||
@@ -261,6 +288,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
|
||||
if (read_cache() < 0)
|
||||
die("index file corrupt");
|
||||
treat_gitlinks(pathspec);
|
||||
|
||||
if (add_new_files)
|
||||
/* This picks up the paths that are not tracked */
|
||||
|
||||
275
builtin-apply.c
275
builtin-apply.c
@@ -14,6 +14,7 @@
|
||||
#include "builtin.h"
|
||||
#include "string-list.h"
|
||||
#include "dir.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
/*
|
||||
* --check turns on checking that the working tree matches the
|
||||
@@ -45,9 +46,11 @@ static int apply_verbosely;
|
||||
static int no_add;
|
||||
static const char *fake_ancestor;
|
||||
static int line_termination = '\n';
|
||||
static unsigned long p_context = ULONG_MAX;
|
||||
static const char apply_usage[] =
|
||||
"git apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
|
||||
static unsigned int p_context = UINT_MAX;
|
||||
static const char * const apply_usage[] = {
|
||||
"git apply [options] [<patch>...]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static enum ws_error_action {
|
||||
nowarn_ws_error,
|
||||
@@ -61,6 +64,8 @@ static int applied_after_fixing_ws;
|
||||
static const char *patch_input_file;
|
||||
static const char *root;
|
||||
static int root_len;
|
||||
static int read_stdin = 1;
|
||||
static int options;
|
||||
|
||||
static void parse_whitespace_option(const char *option)
|
||||
{
|
||||
@@ -630,7 +635,7 @@ static int gitdiff_index(const char *line, struct patch *patch)
|
||||
memcpy(patch->new_sha1_prefix, line, len);
|
||||
patch->new_sha1_prefix[len] = 0;
|
||||
if (*ptr == ' ')
|
||||
patch->new_mode = patch->old_mode = strtoul(ptr+1, NULL, 8);
|
||||
patch->old_mode = strtoul(ptr+1, NULL, 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1253,8 +1258,9 @@ static char *inflate_it(const void *data, unsigned long size,
|
||||
stream.avail_in = size;
|
||||
stream.next_out = out = xmalloc(inflated_size);
|
||||
stream.avail_out = inflated_size;
|
||||
inflateInit(&stream);
|
||||
st = inflate(&stream, Z_FINISH);
|
||||
git_inflate_init(&stream);
|
||||
st = git_inflate(&stream, Z_FINISH);
|
||||
git_inflate_end(&stream);
|
||||
if ((st != Z_STREAM_END) || stream.total_out != inflated_size) {
|
||||
free(out);
|
||||
return NULL;
|
||||
@@ -2447,6 +2453,8 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
|
||||
if (st_mode != patch->old_mode)
|
||||
fprintf(stderr, "warning: %s has type %o, expected %o\n",
|
||||
old_name, st_mode, patch->old_mode);
|
||||
if (!patch->new_mode)
|
||||
patch->new_mode = st_mode;
|
||||
return 0;
|
||||
|
||||
is_new:
|
||||
@@ -3135,151 +3143,160 @@ static int git_apply_config(const char *var, const char *value, void *cb)
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static int option_parse_exclude(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
add_name_limit(arg, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_include(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
add_name_limit(arg, 0);
|
||||
has_include = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_p(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
p_value = atoi(arg);
|
||||
p_value_known = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_z(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
if (unset)
|
||||
line_termination = '\n';
|
||||
else
|
||||
line_termination = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_whitespace(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
const char **whitespace_option = opt->value;
|
||||
|
||||
*whitespace_option = arg;
|
||||
parse_whitespace_option(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int option_parse_directory(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
{
|
||||
root_len = strlen(arg);
|
||||
if (root_len && arg[root_len - 1] != '/') {
|
||||
char *new_root;
|
||||
root = new_root = xmalloc(root_len + 2);
|
||||
strcpy(new_root, arg);
|
||||
strcpy(new_root + root_len++, "/");
|
||||
} else
|
||||
root = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
{
|
||||
int i;
|
||||
int read_stdin = 1;
|
||||
int options = 0;
|
||||
int errs = 0;
|
||||
int is_not_gitdir;
|
||||
int binary;
|
||||
int force_apply = 0;
|
||||
|
||||
const char *whitespace_option = NULL;
|
||||
|
||||
struct option builtin_apply_options[] = {
|
||||
{ OPTION_CALLBACK, 0, "exclude", NULL, "path",
|
||||
"don´t apply changes matching the given path",
|
||||
0, option_parse_exclude },
|
||||
{ OPTION_CALLBACK, 0, "include", NULL, "path",
|
||||
"apply changes matching the given path",
|
||||
0, option_parse_include },
|
||||
{ OPTION_CALLBACK, 'p', NULL, NULL, "num",
|
||||
"remove <num> leading slashes from traditional diff paths",
|
||||
0, option_parse_p },
|
||||
OPT_BOOLEAN(0, "no-add", &no_add,
|
||||
"ignore additions made by the patch"),
|
||||
OPT_BOOLEAN(0, "stat", &diffstat,
|
||||
"instead of applying the patch, output diffstat for the input"),
|
||||
OPT_BOOLEAN(0, "allow-binary-replacement", &binary,
|
||||
"now no-op"),
|
||||
OPT_BOOLEAN(0, "binary", &binary,
|
||||
"now no-op"),
|
||||
OPT_BOOLEAN(0, "numstat", &numstat,
|
||||
"shows number of added and deleted lines in decimal notation"),
|
||||
OPT_BOOLEAN(0, "summary", &summary,
|
||||
"instead of applying the patch, output a summary for the input"),
|
||||
OPT_BOOLEAN(0, "check", &check,
|
||||
"instead of applying the patch, see if the patch is applicable"),
|
||||
OPT_BOOLEAN(0, "index", &check_index,
|
||||
"make sure the patch is applicable to the current index"),
|
||||
OPT_BOOLEAN(0, "cached", &cached,
|
||||
"apply a patch without touching the working tree"),
|
||||
OPT_BOOLEAN(0, "apply", &force_apply,
|
||||
"also apply the patch (use with --stat/--summary/--check)"),
|
||||
OPT_STRING(0, "build-fake-ancestor", &fake_ancestor, "file",
|
||||
"build a temporary index based on embedded index information"),
|
||||
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
|
||||
"paths are separated with NUL character",
|
||||
PARSE_OPT_NOARG, option_parse_z },
|
||||
OPT_INTEGER('C', NULL, &p_context,
|
||||
"ensure at least <n> lines of context match"),
|
||||
{ OPTION_CALLBACK, 0, "whitespace", &whitespace_option, "action",
|
||||
"detect new or modified lines that have whitespace errors",
|
||||
0, option_parse_whitespace },
|
||||
OPT_BOOLEAN('R', "reverse", &apply_in_reverse,
|
||||
"apply the patch in reverse"),
|
||||
OPT_BOOLEAN(0, "unidiff-zero", &unidiff_zero,
|
||||
"don't expect at least one line of context"),
|
||||
OPT_BOOLEAN(0, "reject", &apply_with_reject,
|
||||
"leave the rejected hunks in corresponding *.rej files"),
|
||||
OPT__VERBOSE(&apply_verbosely),
|
||||
OPT_BIT(0, "inaccurate-eof", &options,
|
||||
"tolerate incorrectly detected missing new-line at the end of file",
|
||||
INACCURATE_EOF),
|
||||
OPT_BIT(0, "recount", &options,
|
||||
"do not trust the line counts in the hunk headers",
|
||||
RECOUNT),
|
||||
{ OPTION_CALLBACK, 0, "directory", NULL, "root",
|
||||
"prepend <root> to all filenames",
|
||||
0, option_parse_directory },
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
prefix = setup_git_directory_gently(&is_not_gitdir);
|
||||
prefix_length = prefix ? strlen(prefix) : 0;
|
||||
git_config(git_apply_config, NULL);
|
||||
if (apply_default_whitespace)
|
||||
parse_whitespace_option(apply_default_whitespace);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
argc = parse_options(argc, argv, builtin_apply_options,
|
||||
apply_usage, 0);
|
||||
if (apply_with_reject)
|
||||
apply = apply_verbosely = 1;
|
||||
if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))
|
||||
apply = 0;
|
||||
if (check_index && is_not_gitdir)
|
||||
die("--index outside a repository");
|
||||
if (cached) {
|
||||
if (is_not_gitdir)
|
||||
die("--cached outside a repository");
|
||||
check_index = 1;
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
char *end;
|
||||
int fd;
|
||||
|
||||
if (!strcmp(arg, "-")) {
|
||||
errs |= apply_patch(0, "<stdin>", options);
|
||||
read_stdin = 0;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--exclude=")) {
|
||||
add_name_limit(arg + 10, 1);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--include=")) {
|
||||
add_name_limit(arg + 10, 0);
|
||||
has_include = 1;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "-p")) {
|
||||
p_value = atoi(arg + 2);
|
||||
p_value_known = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--no-add")) {
|
||||
no_add = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--stat")) {
|
||||
apply = 0;
|
||||
diffstat = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--allow-binary-replacement") ||
|
||||
!strcmp(arg, "--binary")) {
|
||||
continue; /* now no-op */
|
||||
}
|
||||
if (!strcmp(arg, "--numstat")) {
|
||||
apply = 0;
|
||||
numstat = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--summary")) {
|
||||
apply = 0;
|
||||
summary = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--check")) {
|
||||
apply = 0;
|
||||
check = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--index")) {
|
||||
if (is_not_gitdir)
|
||||
die("--index outside a repository");
|
||||
check_index = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--cached")) {
|
||||
if (is_not_gitdir)
|
||||
die("--cached outside a repository");
|
||||
check_index = 1;
|
||||
cached = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--apply")) {
|
||||
apply = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--build-fake-ancestor")) {
|
||||
apply = 0;
|
||||
if (++i >= argc)
|
||||
die ("need a filename");
|
||||
fake_ancestor = argv[i];
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-z")) {
|
||||
line_termination = 0;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "-C")) {
|
||||
p_context = strtoul(arg + 2, &end, 0);
|
||||
if (*end != '\0')
|
||||
die("unrecognized context count '%s'", arg + 2);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--whitespace=")) {
|
||||
whitespace_option = arg + 13;
|
||||
parse_whitespace_option(arg + 13);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-R") || !strcmp(arg, "--reverse")) {
|
||||
apply_in_reverse = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--unidiff-zero")) {
|
||||
unidiff_zero = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--reject")) {
|
||||
apply = apply_with_reject = apply_verbosely = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) {
|
||||
apply_verbosely = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--inaccurate-eof")) {
|
||||
options |= INACCURATE_EOF;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--recount")) {
|
||||
options |= RECOUNT;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--directory=")) {
|
||||
arg += strlen("--directory=");
|
||||
root_len = strlen(arg);
|
||||
if (root_len && arg[root_len - 1] != '/') {
|
||||
char *new_root;
|
||||
root = new_root = xmalloc(root_len + 2);
|
||||
strcpy(new_root, arg);
|
||||
strcpy(new_root + root_len++, "/");
|
||||
} else
|
||||
root = arg;
|
||||
continue;
|
||||
}
|
||||
if (0 < prefix_length)
|
||||
} else if (0 < prefix_length)
|
||||
arg = prefix_filename(prefix, prefix_length, arg);
|
||||
|
||||
fd = open(arg, O_RDONLY);
|
||||
|
||||
@@ -137,7 +137,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
|
||||
break;
|
||||
|
||||
default:
|
||||
die("git cat-file: unknown option: %s\n", exp_type);
|
||||
die("git cat-file: unknown option: %s", exp_type);
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
|
||||
@@ -38,23 +38,13 @@ struct checkout_opts {
|
||||
static int post_checkout_hook(struct commit *old, struct commit *new,
|
||||
int changed)
|
||||
{
|
||||
struct child_process proc;
|
||||
const char *name = git_path("hooks/post-checkout");
|
||||
const char *argv[5];
|
||||
return run_hook(NULL, "post-checkout",
|
||||
sha1_to_hex(old ? old->object.sha1 : null_sha1),
|
||||
sha1_to_hex(new ? new->object.sha1 : null_sha1),
|
||||
changed ? "1" : "0", NULL);
|
||||
/* "new" can be NULL when checking out from the index before
|
||||
a commit exists. */
|
||||
|
||||
if (access(name, X_OK) < 0)
|
||||
return 0;
|
||||
|
||||
memset(&proc, 0, sizeof(proc));
|
||||
argv[0] = name;
|
||||
argv[1] = xstrdup(sha1_to_hex(old ? old->object.sha1 : null_sha1));
|
||||
argv[2] = xstrdup(sha1_to_hex(new->object.sha1));
|
||||
argv[3] = changed ? "1" : "0";
|
||||
argv[4] = NULL;
|
||||
proc.argv = argv;
|
||||
proc.no_stdin = 1;
|
||||
proc.stdout_to_stderr = 1;
|
||||
return run_command(&proc);
|
||||
}
|
||||
|
||||
static int update_some(const unsigned char *sha1, const char *base, int baselen,
|
||||
@@ -240,7 +230,7 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
|
||||
|
||||
for (pos = 0; pos < active_nr; pos++) {
|
||||
struct cache_entry *ce = active_cache[pos];
|
||||
pathspec_match(pathspec, ps_matched, ce->name, 0);
|
||||
match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, ps_matched);
|
||||
}
|
||||
|
||||
if (report_path_error(ps_matched, pathspec, 0))
|
||||
@@ -249,7 +239,7 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
|
||||
/* Any unmerged paths? */
|
||||
for (pos = 0; pos < active_nr; pos++) {
|
||||
struct cache_entry *ce = active_cache[pos];
|
||||
if (pathspec_match(pathspec, NULL, ce->name, 0)) {
|
||||
if (match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
|
||||
if (!ce_stage(ce))
|
||||
continue;
|
||||
if (opts->force) {
|
||||
@@ -274,7 +264,7 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
|
||||
state.refresh_cache = 1;
|
||||
for (pos = 0; pos < active_nr; pos++) {
|
||||
struct cache_entry *ce = active_cache[pos];
|
||||
if (pathspec_match(pathspec, NULL, ce->name, 0)) {
|
||||
if (match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
|
||||
if (!ce_stage(ce)) {
|
||||
errs |= checkout_entry(ce, &state, NULL);
|
||||
continue;
|
||||
@@ -681,8 +671,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
new.name = arg;
|
||||
if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
|
||||
new.name = arg;
|
||||
setup_branch_path(&new);
|
||||
if (resolve_ref(new.path, rev, 1, NULL))
|
||||
new.commit = lookup_commit_reference(rev);
|
||||
|
||||
@@ -192,15 +192,15 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
|
||||
|
||||
dir = opendir(src->buf);
|
||||
if (!dir)
|
||||
die("failed to open %s\n", src->buf);
|
||||
die("failed to open %s", src->buf);
|
||||
|
||||
if (mkdir(dest->buf, 0777)) {
|
||||
if (errno != EEXIST)
|
||||
die("failed to create directory %s\n", dest->buf);
|
||||
die("failed to create directory %s", dest->buf);
|
||||
else if (stat(dest->buf, &buf))
|
||||
die("failed to stat %s\n", dest->buf);
|
||||
die("failed to stat %s", dest->buf);
|
||||
else if (!S_ISDIR(buf.st_mode))
|
||||
die("%s exists and is not a directory\n", dest->buf);
|
||||
die("%s exists and is not a directory", dest->buf);
|
||||
}
|
||||
|
||||
strbuf_addch(src, '/');
|
||||
@@ -224,16 +224,16 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
|
||||
}
|
||||
|
||||
if (unlink(dest->buf) && errno != ENOENT)
|
||||
die("failed to unlink %s\n", dest->buf);
|
||||
die("failed to unlink %s", dest->buf);
|
||||
if (!option_no_hardlinks) {
|
||||
if (!link(src->buf, dest->buf))
|
||||
continue;
|
||||
if (option_local)
|
||||
die("failed to create link %s\n", dest->buf);
|
||||
die("failed to create link %s", dest->buf);
|
||||
option_no_hardlinks = 1;
|
||||
}
|
||||
if (copy_file(dest->buf, src->buf, 0666))
|
||||
die("failed to copy file to %s\n", dest->buf);
|
||||
die("failed to copy file to %s", dest->buf);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
@@ -357,6 +357,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
struct stat buf;
|
||||
const char *repo_name, *repo, *work_tree, *git_dir;
|
||||
char *path, *dir;
|
||||
int dest_exists;
|
||||
const struct ref *refs, *head_points_at, *remote_head, *mapped_refs;
|
||||
struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
|
||||
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
|
||||
@@ -406,8 +407,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
dir = guess_dir_name(repo_name, is_bundle, option_bare);
|
||||
strip_trailing_slashes(dir);
|
||||
|
||||
if (!stat(dir, &buf))
|
||||
die("destination directory '%s' already exists.", dir);
|
||||
dest_exists = !stat(dir, &buf);
|
||||
if (dest_exists && !is_empty_dir(dir))
|
||||
die("destination path '%s' already exists and is not "
|
||||
"an empty directory.", dir);
|
||||
|
||||
strbuf_addf(&reflog_msg, "clone: from %s", repo);
|
||||
|
||||
@@ -431,7 +434,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
if (safe_create_leading_directories_const(work_tree) < 0)
|
||||
die("could not create leading directories of '%s': %s",
|
||||
work_tree, strerror(errno));
|
||||
if (mkdir(work_tree, 0755))
|
||||
if (!dest_exists && mkdir(work_tree, 0755))
|
||||
die("could not create work tree dir '%s': %s.",
|
||||
work_tree, strerror(errno));
|
||||
set_git_work_tree(work_tree);
|
||||
@@ -519,14 +522,23 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
option_upload_pack);
|
||||
|
||||
refs = transport_get_remote_refs(transport);
|
||||
transport_fetch_refs(transport, refs);
|
||||
if(refs)
|
||||
transport_fetch_refs(transport, refs);
|
||||
}
|
||||
|
||||
clear_extra_refs();
|
||||
if (refs) {
|
||||
clear_extra_refs();
|
||||
|
||||
mapped_refs = write_remote_refs(refs, &refspec, reflog_msg.buf);
|
||||
mapped_refs = write_remote_refs(refs, &refspec, reflog_msg.buf);
|
||||
|
||||
head_points_at = locate_head(refs, mapped_refs, &remote_head);
|
||||
head_points_at = locate_head(refs, mapped_refs, &remote_head);
|
||||
}
|
||||
else {
|
||||
warning("You appear to have cloned an empty repository.");
|
||||
head_points_at = NULL;
|
||||
remote_head = NULL;
|
||||
option_no_checkout = 1;
|
||||
}
|
||||
|
||||
if (head_points_at) {
|
||||
/* Local default branch link */
|
||||
|
||||
@@ -166,7 +166,7 @@ static int list_paths(struct string_list *list, const char *with_tree,
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
if (ce->ce_flags & CE_UPDATE)
|
||||
continue;
|
||||
if (!pathspec_match(pattern, m, ce->name, 0))
|
||||
if (!match_pathspec(pattern, ce->name, ce_namelen(ce), 0, m))
|
||||
continue;
|
||||
string_list_insert(ce->name, list);
|
||||
}
|
||||
@@ -361,40 +361,6 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
|
||||
return s.commitable;
|
||||
}
|
||||
|
||||
static int run_hook(const char *index_file, const char *name, ...)
|
||||
{
|
||||
struct child_process hook;
|
||||
const char *argv[10], *env[2];
|
||||
char index[PATH_MAX];
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, name);
|
||||
argv[0] = git_path("hooks/%s", name);
|
||||
i = 0;
|
||||
do {
|
||||
if (++i >= ARRAY_SIZE(argv))
|
||||
die ("run_hook(): too many arguments");
|
||||
argv[i] = va_arg(args, const char *);
|
||||
} while (argv[i]);
|
||||
va_end(args);
|
||||
|
||||
snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
|
||||
env[0] = index;
|
||||
env[1] = NULL;
|
||||
|
||||
if (access(argv[0], X_OK) < 0)
|
||||
return 0;
|
||||
|
||||
memset(&hook, 0, sizeof(hook));
|
||||
hook.argv = argv;
|
||||
hook.no_stdin = 1;
|
||||
hook.stdout_to_stderr = 1;
|
||||
hook.env = env;
|
||||
|
||||
return run_command(&hook);
|
||||
}
|
||||
|
||||
static int is_a_merge(const unsigned char *sha1)
|
||||
{
|
||||
struct commit *commit = lookup_commit(sha1);
|
||||
@@ -624,7 +590,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
|
||||
if (!commitable && !in_merge && !allow_empty &&
|
||||
!(amend && is_a_merge(head_sha1))) {
|
||||
run_status(stdout, index_file, prefix, 0);
|
||||
unlink(commit_editmsg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -866,6 +831,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
|
||||
if (wt_status_use_color == -1)
|
||||
wt_status_use_color = git_use_color_default;
|
||||
|
||||
if (diff_use_color_default == -1)
|
||||
diff_use_color_default = git_use_color_default;
|
||||
|
||||
argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
|
||||
|
||||
index_file = prepare_index(argc, argv, prefix);
|
||||
@@ -881,7 +849,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
|
||||
{
|
||||
struct rev_info rev;
|
||||
struct commit *commit;
|
||||
static const char *format = "format:%h: \"%s\"";
|
||||
static const char *format = "format:%h] %s";
|
||||
unsigned char junk_sha1[20];
|
||||
const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
|
||||
|
||||
@@ -908,7 +876,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
|
||||
rev.diffopt.break_opt = 0;
|
||||
diff_setup_done(&rev.diffopt);
|
||||
|
||||
printf("[%s%s]: created ",
|
||||
printf("[%s%s ",
|
||||
!prefixcmp(head, "refs/heads/") ?
|
||||
head + 11 :
|
||||
!strcmp(head, "HEAD") ?
|
||||
@@ -945,6 +913,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
||||
|
||||
git_config(git_commit_config, NULL);
|
||||
|
||||
if (wt_status_use_color == -1)
|
||||
wt_status_use_color = git_use_color_default;
|
||||
|
||||
argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
|
||||
|
||||
index_file = prepare_index(argc, argv, prefix);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "cache.h"
|
||||
#include "dir.h"
|
||||
#include "builtin.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
@@ -21,9 +22,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
|
||||
const char *cp;
|
||||
int bad = 0;
|
||||
|
||||
if ((ent->d_name[0] == '.') &&
|
||||
(ent->d_name[1] == 0 ||
|
||||
((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))
|
||||
if (is_dot_or_dotdot(ent->d_name))
|
||||
continue;
|
||||
for (cp = ent->d_name; *cp; cp++) {
|
||||
int ch = *cp;
|
||||
|
||||
@@ -158,7 +158,7 @@ static void display_name(struct commit_name *n)
|
||||
n->tag = lookup_tag(n->sha1);
|
||||
if (!n->tag || parse_tag(n->tag) || !n->tag->tag)
|
||||
die("annotated tag %s not available", n->path);
|
||||
if (strcmp(n->tag->tag, n->path))
|
||||
if (strcmp(n->tag->tag, all ? n->path + 5 : n->path))
|
||||
warning("tag '%s' is really '%s' here", n->tag->tag, n->path);
|
||||
}
|
||||
|
||||
|
||||
@@ -497,6 +497,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
if (argc == 1)
|
||||
usage_with_options (fast_export_usage, options);
|
||||
|
||||
/* we handle encodings */
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
|
||||
@@ -607,7 +607,7 @@ static void set_option(const char *name, const char *value)
|
||||
{
|
||||
int r = transport_set_option(transport, name, value);
|
||||
if (r < 0)
|
||||
die("Option \"%s\" value \"%s\" is not valid for %s\n",
|
||||
die("Option \"%s\" value \"%s\" is not valid for %s",
|
||||
name, value, transport->url);
|
||||
if (r > 0)
|
||||
warning("Option \"%s\" is ignored for %s\n",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "tree-walk.h"
|
||||
#include "fsck.h"
|
||||
#include "parse-options.h"
|
||||
#include "dir.h"
|
||||
|
||||
#define REACHABLE 0x0001
|
||||
#define SEEN 0x0002
|
||||
@@ -395,19 +396,12 @@ static void fsck_dir(int i, char *path)
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
char name[100];
|
||||
unsigned char sha1[20];
|
||||
int len = strlen(de->d_name);
|
||||
|
||||
switch (len) {
|
||||
case 2:
|
||||
if (de->d_name[1] != '.')
|
||||
break;
|
||||
case 1:
|
||||
if (de->d_name[0] != '.')
|
||||
break;
|
||||
if (is_dot_or_dotdot(de->d_name))
|
||||
continue;
|
||||
case 38:
|
||||
if (strlen(de->d_name) == 38) {
|
||||
sprintf(name, "%02x", i);
|
||||
memcpy(name+2, de->d_name, len+1);
|
||||
memcpy(name+2, de->d_name, 39);
|
||||
if (get_sha1_hex(name, sha1) < 0)
|
||||
break;
|
||||
add_sha1_list(sha1, DIRENT_SORT_HINT(de));
|
||||
@@ -628,7 +622,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
|
||||
heads = 0;
|
||||
for (i = 1; i < argc; i++) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
if (!get_sha1(arg, head_sha1)) {
|
||||
struct object *obj = lookup_object(head_sha1);
|
||||
|
||||
38
builtin-gc.c
38
builtin-gc.c
@@ -144,34 +144,6 @@ static int too_many_packs(void)
|
||||
return gc_auto_pack_limit <= cnt;
|
||||
}
|
||||
|
||||
static int run_hook(void)
|
||||
{
|
||||
const char *argv[2];
|
||||
struct child_process hook;
|
||||
int ret;
|
||||
|
||||
argv[0] = git_path("hooks/pre-auto-gc");
|
||||
argv[1] = NULL;
|
||||
|
||||
if (access(argv[0], X_OK) < 0)
|
||||
return 0;
|
||||
|
||||
memset(&hook, 0, sizeof(hook));
|
||||
hook.argv = argv;
|
||||
hook.no_stdin = 1;
|
||||
hook.stdout_to_stderr = 1;
|
||||
|
||||
ret = start_command(&hook);
|
||||
if (ret) {
|
||||
warning("Could not spawn %s", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
ret = finish_command(&hook);
|
||||
if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL)
|
||||
warning("%s exited due to uncaught signal", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int need_to_gc(void)
|
||||
{
|
||||
/*
|
||||
@@ -188,11 +160,13 @@ static int need_to_gc(void)
|
||||
* there is no need.
|
||||
*/
|
||||
if (too_many_packs())
|
||||
append_option(argv_repack, "-A", MAX_ADD);
|
||||
append_option(argv_repack,
|
||||
!strcmp(prune_expire, "now") ? "-a" : "-A",
|
||||
MAX_ADD);
|
||||
else if (!too_many_loose_objects())
|
||||
return 0;
|
||||
|
||||
if (run_hook())
|
||||
if (run_hook(NULL, "pre-auto-gc", NULL))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -243,7 +217,9 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
||||
"run \"git gc\" manually. See "
|
||||
"\"git help gc\" for more information.\n");
|
||||
} else
|
||||
append_option(argv_repack, "-A", MAX_ADD);
|
||||
append_option(argv_repack,
|
||||
!strcmp(prune_expire, "now") ? "-a" : "-A",
|
||||
MAX_ADD);
|
||||
|
||||
if (pack_refs && run_command_v_opt(argv_pack_refs, RUN_GIT_CMD))
|
||||
return error(FAILED_RUN, argv_pack_refs[0]);
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int builtin_grep;
|
||||
|
||||
/*
|
||||
* git grep pathspecs are somewhat different from diff-tree pathspecs;
|
||||
* pathname wildcards are allowed.
|
||||
@@ -389,7 +391,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
|
||||
* we grep through the checked-out files. It tends to
|
||||
* be a lot more optimized
|
||||
*/
|
||||
if (!cached) {
|
||||
if (!cached && !builtin_grep) {
|
||||
hit = external_grep(opt, paths, cached);
|
||||
if (hit >= 0)
|
||||
return hit;
|
||||
@@ -402,7 +404,12 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
|
||||
continue;
|
||||
if (!pathspec_matches(paths, ce->name))
|
||||
continue;
|
||||
if (cached) {
|
||||
/*
|
||||
* If CE_VALID is on, we assume worktree file and its cache entry
|
||||
* are identical, even if worktree file has been modified, so use
|
||||
* cache version instead
|
||||
*/
|
||||
if (cached || (ce->ce_flags & CE_VALID)) {
|
||||
if (ce_stage(ce))
|
||||
continue;
|
||||
hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
|
||||
@@ -545,6 +552,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
cached = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--no-ext-grep", arg)) {
|
||||
builtin_grep = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-a", arg) ||
|
||||
!strcmp("--text", arg)) {
|
||||
opt.binary = GREP_BINARY_TEXT;
|
||||
|
||||
@@ -29,7 +29,7 @@ static void safe_create_dir(const char *dir, int share)
|
||||
}
|
||||
}
|
||||
else if (share && adjust_shared_perm(dir))
|
||||
die("Could not make %s writable by group\n", dir);
|
||||
die("Could not make %s writable by group", dir);
|
||||
}
|
||||
|
||||
static void copy_templates_1(char *path, int baselen,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "patch-ids.h"
|
||||
#include "run-command.h"
|
||||
#include "shortlog.h"
|
||||
#include "remote.h"
|
||||
|
||||
/* Set a default date-time format for git log ("log.date" config variable) */
|
||||
static const char *default_date_mode = NULL;
|
||||
@@ -249,22 +250,13 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
|
||||
|
||||
static void show_tagger(char *buf, int len, struct rev_info *rev)
|
||||
{
|
||||
char *email_end, *p;
|
||||
unsigned long date;
|
||||
int tz;
|
||||
struct strbuf out = STRBUF_INIT;
|
||||
|
||||
email_end = memchr(buf, '>', len);
|
||||
if (!email_end)
|
||||
return;
|
||||
p = ++email_end;
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
date = strtoul(p, &p, 10);
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
tz = (int)strtol(p, NULL, 10);
|
||||
printf("Tagger: %.*s\nDate: %s\n", (int)(email_end - buf), buf,
|
||||
show_date(date, tz, rev->date_mode));
|
||||
pp_user_info("Tagger", rev->commit_format, &out, buf, rev->date_mode,
|
||||
git_log_output_encoding ?
|
||||
git_log_output_encoding: git_commit_encoding);
|
||||
printf("%s\n", out.buf);
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
static int show_object(const unsigned char *sha1, int show_tag_object,
|
||||
@@ -553,6 +545,7 @@ static const char *get_oneline_for_filename(struct commit *commit,
|
||||
|
||||
static FILE *realstdout = NULL;
|
||||
static const char *output_directory = NULL;
|
||||
static int outdir_offset;
|
||||
|
||||
static int reopen_stdout(const char *oneline, int nr, int total)
|
||||
{
|
||||
@@ -579,7 +572,7 @@ static int reopen_stdout(const char *oneline, int nr, int total)
|
||||
strcpy(filename + len, fmt_patch_suffix);
|
||||
}
|
||||
|
||||
fprintf(realstdout, "%s\n", filename);
|
||||
fprintf(realstdout, "%s\n", filename + outdir_offset);
|
||||
if (freopen(filename, "w", stdout) == NULL)
|
||||
return error("Cannot open patch file %s",filename);
|
||||
|
||||
@@ -740,6 +733,27 @@ static const char *clean_message_id(const char *msg_id)
|
||||
return xmemdupz(a, z - a);
|
||||
}
|
||||
|
||||
static const char *set_outdir(const char *prefix, const char *output_directory)
|
||||
{
|
||||
if (output_directory && is_absolute_path(output_directory))
|
||||
return output_directory;
|
||||
|
||||
if (!prefix || !*prefix) {
|
||||
if (output_directory)
|
||||
return output_directory;
|
||||
/* The user did not explicitly ask for "./" */
|
||||
outdir_offset = 2;
|
||||
return "./";
|
||||
}
|
||||
|
||||
outdir_offset = strlen(prefix);
|
||||
if (!output_directory)
|
||||
return prefix;
|
||||
|
||||
return xstrdup(prefix_filename(prefix, outdir_offset,
|
||||
output_directory));
|
||||
}
|
||||
|
||||
int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct commit *commit;
|
||||
@@ -824,7 +838,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
||||
endpos = strchr(committer, '>');
|
||||
if (!endpos)
|
||||
die("bogus committer info %s\n", committer);
|
||||
die("bogus committer info %s", committer);
|
||||
add_signoff = xmemdupz(committer, endpos - committer + 1);
|
||||
}
|
||||
else if (!strcmp(argv[i], "--attach")) {
|
||||
@@ -917,8 +931,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
|
||||
DIFF_OPT_SET(&rev.diffopt, BINARY);
|
||||
|
||||
if (!output_directory && !use_stdout)
|
||||
output_directory = prefix;
|
||||
if (!use_stdout)
|
||||
output_directory = set_outdir(prefix, output_directory);
|
||||
|
||||
if (output_directory) {
|
||||
if (use_stdout)
|
||||
@@ -944,6 +958,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
* get_revision() to do the usual traversal.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* We cannot move this anywhere earlier because we do want to
|
||||
* know if --root was given explicitly from the comand line.
|
||||
*/
|
||||
rev.show_root_diff = 1;
|
||||
|
||||
if (cover_letter) {
|
||||
/* remember the range */
|
||||
int i;
|
||||
@@ -1070,13 +1091,14 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
|
||||
}
|
||||
|
||||
static const char cherry_usage[] =
|
||||
"git cherry [-v] <upstream> [<head>] [<limit>]";
|
||||
"git cherry [-v] [<upstream> [<head> [<limit>]]]";
|
||||
int cmd_cherry(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct rev_info revs;
|
||||
struct patch_ids ids;
|
||||
struct commit *commit;
|
||||
struct commit_list *list = NULL;
|
||||
struct branch *current_branch;
|
||||
const char *upstream;
|
||||
const char *head = "HEAD";
|
||||
const char *limit = NULL;
|
||||
@@ -1099,7 +1121,17 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
|
||||
upstream = argv[1];
|
||||
break;
|
||||
default:
|
||||
usage(cherry_usage);
|
||||
current_branch = branch_get(NULL);
|
||||
if (!current_branch || !current_branch->merge
|
||||
|| !current_branch->merge[0]
|
||||
|| !current_branch->merge[0]->dst) {
|
||||
fprintf(stderr, "Could not find a tracked"
|
||||
" remote branch, please"
|
||||
" specify <upstream> manually.\n");
|
||||
usage(cherry_usage);
|
||||
}
|
||||
|
||||
upstream = current_branch->merge[0]->dst;
|
||||
}
|
||||
|
||||
init_revisions(&revs, prefix);
|
||||
|
||||
@@ -36,42 +36,6 @@ static const char *tag_other = "";
|
||||
static const char *tag_killed = "";
|
||||
static const char *tag_modified = "";
|
||||
|
||||
|
||||
/*
|
||||
* Match a pathspec against a filename. The first "skiplen" characters
|
||||
* are the common prefix
|
||||
*/
|
||||
int pathspec_match(const char **spec, char *ps_matched,
|
||||
const char *filename, int skiplen)
|
||||
{
|
||||
const char *m;
|
||||
|
||||
while ((m = *spec++) != NULL) {
|
||||
int matchlen = strlen(m + skiplen);
|
||||
|
||||
if (!matchlen)
|
||||
goto matched;
|
||||
if (!strncmp(m + skiplen, filename + skiplen, matchlen)) {
|
||||
if (m[skiplen + matchlen - 1] == '/')
|
||||
goto matched;
|
||||
switch (filename[skiplen + matchlen]) {
|
||||
case '/': case '\0':
|
||||
goto matched;
|
||||
}
|
||||
}
|
||||
if (!fnmatch(m + skiplen, filename + skiplen, 0))
|
||||
goto matched;
|
||||
if (ps_matched)
|
||||
ps_matched++;
|
||||
continue;
|
||||
matched:
|
||||
if (ps_matched)
|
||||
*ps_matched = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_dir_entry(const char *tag, struct dir_entry *ent)
|
||||
{
|
||||
int len = prefix_len;
|
||||
@@ -80,7 +44,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
|
||||
if (len >= ent->len)
|
||||
die("git ls-files: internal error - directory entry not superset of prefix");
|
||||
|
||||
if (pathspec && !pathspec_match(pathspec, ps_matched, ent->name, len))
|
||||
if (!match_pathspec(pathspec, ent->name, ent->len, len, ps_matched))
|
||||
return;
|
||||
|
||||
fputs(tag, stdout);
|
||||
@@ -156,7 +120,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
|
||||
if (len >= ce_namelen(ce))
|
||||
die("git ls-files: internal error - cache entry not superset of prefix");
|
||||
|
||||
if (pathspec && !pathspec_match(pathspec, ps_matched, ce->name, len))
|
||||
if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), len, ps_matched))
|
||||
return;
|
||||
|
||||
if (tag && *tag && show_valid_bit &&
|
||||
|
||||
@@ -23,7 +23,7 @@ static int chomp_prefix;
|
||||
static const char *ls_tree_prefix;
|
||||
|
||||
static const char ls_tree_usage[] =
|
||||
"git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
|
||||
"git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev[=<n>]] <tree-ish> [path...]";
|
||||
|
||||
static int show_recursive(const char *base, int baselen, const char *pathname)
|
||||
{
|
||||
@@ -156,6 +156,11 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
|
||||
chomp_prefix = 0;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(argv[1]+2, "full-tree")) {
|
||||
ls_tree_prefix = prefix = NULL;
|
||||
chomp_prefix = 0;
|
||||
break;
|
||||
}
|
||||
if (!prefixcmp(argv[1]+2, "abbrev=")) {
|
||||
abbrev = strtoul(argv[1]+9, NULL, 10);
|
||||
if (abbrev && abbrev < MINIMUM_ABBREV)
|
||||
|
||||
@@ -494,7 +494,7 @@ static void convert_to_utf8(struct strbuf *line, const char *charset)
|
||||
return;
|
||||
out = reencode_string(line->buf, metainfo_charset, charset);
|
||||
if (!out)
|
||||
die("cannot convert from %s to %s\n",
|
||||
die("cannot convert from %s to %s",
|
||||
charset, metainfo_charset);
|
||||
strbuf_attach(line, out, strlen(out), strlen(out));
|
||||
}
|
||||
|
||||
@@ -51,8 +51,11 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
||||
argc = parse_options(argc, argv, options, merge_file_usage, 0);
|
||||
if (argc != 3)
|
||||
usage_with_options(merge_file_usage, options);
|
||||
if (quiet)
|
||||
freopen("/dev/null", "w", stderr);
|
||||
if (quiet) {
|
||||
if (!freopen("/dev/null", "w", stderr))
|
||||
return error("failed to redirect stderr to /dev/null: "
|
||||
"%s\n", strerror(errno));
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!names[i])
|
||||
|
||||
@@ -33,7 +33,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
|
||||
if (argc < 4)
|
||||
die("Usage: %s <base>... -- <head> <remote> ...\n", argv[0]);
|
||||
die("Usage: %s <base>... -- <head> <remote> ...", argv[0]);
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (!strcmp(argv[i], "--"))
|
||||
|
||||
@@ -300,35 +300,6 @@ static void squash_message(void)
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
static int run_hook(const char *name)
|
||||
{
|
||||
struct child_process hook;
|
||||
const char *argv[3], *env[2];
|
||||
char index[PATH_MAX];
|
||||
|
||||
argv[0] = git_path("hooks/%s", name);
|
||||
if (access(argv[0], X_OK) < 0)
|
||||
return 0;
|
||||
|
||||
snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", get_index_file());
|
||||
env[0] = index;
|
||||
env[1] = NULL;
|
||||
|
||||
if (squash)
|
||||
argv[1] = "1";
|
||||
else
|
||||
argv[1] = "0";
|
||||
argv[2] = NULL;
|
||||
|
||||
memset(&hook, 0, sizeof(hook));
|
||||
hook.argv = argv;
|
||||
hook.no_stdin = 1;
|
||||
hook.stdout_to_stderr = 1;
|
||||
hook.env = env;
|
||||
|
||||
return run_command(&hook);
|
||||
}
|
||||
|
||||
static void finish(const unsigned char *new_head, const char *msg)
|
||||
{
|
||||
struct strbuf reflog_message = STRBUF_INIT;
|
||||
@@ -374,7 +345,7 @@ static void finish(const unsigned char *new_head, const char *msg)
|
||||
}
|
||||
|
||||
/* Run a post-merge hook */
|
||||
run_hook("post-merge");
|
||||
run_hook(NULL, "post-merge", squash ? "1" : "0", NULL);
|
||||
|
||||
strbuf_release(&reflog_message);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
||||
memmove(destination + i,
|
||||
destination + i + 1,
|
||||
(argc - i) * sizeof(char *));
|
||||
i--;
|
||||
}
|
||||
} else
|
||||
die ("%s, source=%s, destination=%s",
|
||||
|
||||
@@ -78,7 +78,7 @@ static int progress = 1;
|
||||
static int window = 10;
|
||||
static uint32_t pack_size_limit, pack_size_limit_cfg;
|
||||
static int depth = 50;
|
||||
static int delta_search_threads = 1;
|
||||
static int delta_search_threads;
|
||||
static int pack_to_stdout;
|
||||
static int num_preferred_base;
|
||||
static struct progress *progress_state;
|
||||
@@ -195,16 +195,16 @@ static int check_pack_inflate(struct packed_git *p,
|
||||
int st;
|
||||
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
inflateInit(&stream);
|
||||
git_inflate_init(&stream);
|
||||
do {
|
||||
in = use_pack(p, w_curs, offset, &stream.avail_in);
|
||||
stream.next_in = in;
|
||||
stream.next_out = fakebuf;
|
||||
stream.avail_out = sizeof(fakebuf);
|
||||
st = inflate(&stream, Z_FINISH);
|
||||
st = git_inflate(&stream, Z_FINISH);
|
||||
offset += stream.next_in - in;
|
||||
} while (st == Z_OK || st == Z_BUF_ERROR);
|
||||
inflateEnd(&stream);
|
||||
git_inflate_end(&stream);
|
||||
return (st == Z_STREAM_END &&
|
||||
stream.total_out == expect &&
|
||||
stream.total_in == len) ? 0 : -1;
|
||||
@@ -1612,11 +1612,18 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
|
||||
find_deltas(list, &list_size, window, depth, processed);
|
||||
return;
|
||||
}
|
||||
if (progress > pack_to_stdout)
|
||||
fprintf(stderr, "Delta compression using %d threads.\n",
|
||||
delta_search_threads);
|
||||
|
||||
/* Partition the work amongst work threads. */
|
||||
for (i = 0; i < delta_search_threads; i++) {
|
||||
unsigned sub_size = list_size / (delta_search_threads - i);
|
||||
|
||||
/* don't use too small segments or no deltas will be found */
|
||||
if (sub_size < 2*window && i+1 < delta_search_threads)
|
||||
sub_size = 0;
|
||||
|
||||
p[i].window = window;
|
||||
p[i].depth = depth;
|
||||
p[i].processed = processed;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "builtin.h"
|
||||
#include "reachable.h"
|
||||
#include "parse-options.h"
|
||||
#include "dir.h"
|
||||
|
||||
static const char * const prune_usage[] = {
|
||||
"git prune [-n] [-v] [--expire <time>] [--] [<head>...]",
|
||||
@@ -61,19 +62,12 @@ static int prune_dir(int i, char *path)
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
char name[100];
|
||||
unsigned char sha1[20];
|
||||
int len = strlen(de->d_name);
|
||||
|
||||
switch (len) {
|
||||
case 2:
|
||||
if (de->d_name[1] != '.')
|
||||
break;
|
||||
case 1:
|
||||
if (de->d_name[0] != '.')
|
||||
break;
|
||||
if (is_dot_or_dotdot(de->d_name))
|
||||
continue;
|
||||
case 38:
|
||||
if (strlen(de->d_name) == 38) {
|
||||
sprintf(name, "%02x", i);
|
||||
memcpy(name+2, de->d_name, len+1);
|
||||
memcpy(name+2, de->d_name, 39);
|
||||
if (get_sha1_hex(name, sha1) < 0)
|
||||
break;
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ static int hook_status(int code, const char *hook_name)
|
||||
}
|
||||
}
|
||||
|
||||
static int run_hook(const char *hook_name)
|
||||
static int run_receive_hook(const char *hook_name)
|
||||
{
|
||||
static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
|
||||
struct command *cmd;
|
||||
@@ -358,7 +358,7 @@ static void execute_commands(const char *unpacker_error)
|
||||
return;
|
||||
}
|
||||
|
||||
if (run_hook(pre_receive_hook)) {
|
||||
if (run_receive_hook(pre_receive_hook)) {
|
||||
while (cmd) {
|
||||
cmd->error_string = "pre-receive hook declined";
|
||||
cmd = cmd->next;
|
||||
@@ -630,7 +630,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
||||
unlink(pack_lockfile);
|
||||
if (report_status)
|
||||
report(unpack_status);
|
||||
run_hook(post_receive_hook);
|
||||
run_receive_hook(post_receive_hook);
|
||||
run_update_post_hook(commands);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "dir.h"
|
||||
#include "string-list.h"
|
||||
#include "rerere.h"
|
||||
#include "xdiff/xdiff.h"
|
||||
@@ -59,17 +60,15 @@ static void garbage_collect(struct string_list *rr)
|
||||
git_config(git_rerere_gc_config, NULL);
|
||||
dir = opendir(git_path("rr-cache"));
|
||||
while ((e = readdir(dir))) {
|
||||
const char *name = e->d_name;
|
||||
if (name[0] == '.' &&
|
||||
(name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
|
||||
if (is_dot_or_dotdot(e->d_name))
|
||||
continue;
|
||||
then = rerere_created_at(name);
|
||||
then = rerere_created_at(e->d_name);
|
||||
if (!then)
|
||||
continue;
|
||||
cutoff = (has_resolution(name)
|
||||
cutoff = (has_resolution(e->d_name)
|
||||
? cutoff_resolve : cutoff_noresolve);
|
||||
if (then < now - cutoff * 86400)
|
||||
string_list_append(name, &to_remove);
|
||||
string_list_append(e->d_name, &to_remove);
|
||||
}
|
||||
for (i = 0; i < to_remove.nr; i++)
|
||||
unlink_rr_item(to_remove.items[i].string);
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char * const git_reset_usage[] = {
|
||||
"git reset [--mixed | --soft | --hard] [-q] [<commit>]",
|
||||
"git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>]",
|
||||
"git reset [--mixed] <commit> [--] <paths>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
enum reset_type { MIXED, SOFT, HARD, MERGE, NONE };
|
||||
static const char *reset_type_names[] = { "mixed", "soft", "hard", "merge", NULL };
|
||||
|
||||
static char *args_to_str(const char **argv)
|
||||
{
|
||||
char *buf = NULL;
|
||||
@@ -49,7 +52,7 @@ static inline int is_merge(void)
|
||||
return !access(git_path("MERGE_HEAD"), F_OK);
|
||||
}
|
||||
|
||||
static int reset_index_file(const unsigned char *sha1, int is_hard_reset, int quiet)
|
||||
static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)
|
||||
{
|
||||
int i = 0;
|
||||
const char *args[6];
|
||||
@@ -57,9 +60,17 @@ static int reset_index_file(const unsigned char *sha1, int is_hard_reset, int qu
|
||||
args[i++] = "read-tree";
|
||||
if (!quiet)
|
||||
args[i++] = "-v";
|
||||
args[i++] = "--reset";
|
||||
if (is_hard_reset)
|
||||
switch (reset_type) {
|
||||
case MERGE:
|
||||
args[i++] = "-u";
|
||||
args[i++] = "-m";
|
||||
break;
|
||||
case HARD:
|
||||
args[i++] = "-u";
|
||||
/* fallthrough */
|
||||
default:
|
||||
args[i++] = "--reset";
|
||||
}
|
||||
args[i++] = sha1_to_hex(sha1);
|
||||
args[i] = NULL;
|
||||
|
||||
@@ -169,9 +180,6 @@ static void prepend_reflog_action(const char *action, char *buf, size_t size)
|
||||
warning("Reflog action message too long: %.*s...", 50, buf);
|
||||
}
|
||||
|
||||
enum reset_type { MIXED, SOFT, HARD, NONE };
|
||||
static const char *reset_type_names[] = { "mixed", "soft", "hard", NULL };
|
||||
|
||||
int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;
|
||||
@@ -186,6 +194,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
|
||||
OPT_SET_INT(0, "hard", &reset_type,
|
||||
"reset HEAD, index and working tree", HARD),
|
||||
OPT_SET_INT(0, "merge", &reset_type,
|
||||
"reset HEAD, index and working tree", MERGE),
|
||||
OPT_BOOLEAN('q', NULL, &quiet,
|
||||
"disable showing new HEAD in hard reset and progress message"),
|
||||
OPT_END()
|
||||
@@ -266,7 +276,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
if (is_merge() || read_cache() < 0 || unmerged_cache())
|
||||
die("Cannot do a soft reset in the middle of a merge.");
|
||||
}
|
||||
else if (reset_index_file(sha1, (reset_type == HARD), quiet))
|
||||
else if (reset_index_file(sha1, reset_type, quiet))
|
||||
die("Could not reset index file to revision '%s'.", rev);
|
||||
|
||||
/* Any resets update HEAD to the head being switched to,
|
||||
|
||||
@@ -29,6 +29,9 @@ static int compare_by_number(const void *a1, const void *a2)
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *format_subject(struct strbuf *sb, const char *msg,
|
||||
const char *line_separator);
|
||||
|
||||
static void insert_one_record(struct shortlog *log,
|
||||
const char *author,
|
||||
const char *oneline)
|
||||
@@ -36,11 +39,11 @@ static void insert_one_record(struct shortlog *log,
|
||||
const char *dot3 = log->common_repo_prefix;
|
||||
char *buffer, *p;
|
||||
struct string_list_item *item;
|
||||
struct string_list *onelines;
|
||||
char namebuf[1024];
|
||||
size_t len;
|
||||
const char *eol;
|
||||
const char *boemail, *eoemail;
|
||||
struct strbuf subject = STRBUF_INIT;
|
||||
|
||||
boemail = strchr(author, '<');
|
||||
if (!boemail)
|
||||
@@ -68,12 +71,9 @@ static void insert_one_record(struct shortlog *log,
|
||||
snprintf(namebuf + len, room, " %.*s", maillen, boemail);
|
||||
}
|
||||
|
||||
buffer = xstrdup(namebuf);
|
||||
item = string_list_insert(buffer, &log->list);
|
||||
item = string_list_insert(namebuf, &log->list);
|
||||
if (item->util == NULL)
|
||||
item->util = xcalloc(1, sizeof(struct string_list));
|
||||
else
|
||||
free(buffer);
|
||||
|
||||
/* Skip any leading whitespace, including any blank lines. */
|
||||
while (*oneline && isspace(*oneline))
|
||||
@@ -89,9 +89,8 @@ static void insert_one_record(struct shortlog *log,
|
||||
while (*oneline && isspace(*oneline) && *oneline != '\n')
|
||||
oneline++;
|
||||
len = eol - oneline;
|
||||
while (len && isspace(oneline[len-1]))
|
||||
len--;
|
||||
buffer = xmemdupz(oneline, len);
|
||||
format_subject(&subject, oneline, " ");
|
||||
buffer = strbuf_detach(&subject, NULL);
|
||||
|
||||
if (dot3) {
|
||||
int dot3len = strlen(dot3);
|
||||
@@ -104,16 +103,7 @@ static void insert_one_record(struct shortlog *log,
|
||||
}
|
||||
}
|
||||
|
||||
onelines = item->util;
|
||||
if (onelines->nr >= onelines->alloc) {
|
||||
onelines->alloc = alloc_nr(onelines->nr);
|
||||
onelines->items = xrealloc(onelines->items,
|
||||
onelines->alloc
|
||||
* sizeof(struct string_list_item));
|
||||
}
|
||||
|
||||
onelines->items[onelines->nr].util = NULL;
|
||||
onelines->items[onelines->nr++].string = buffer;
|
||||
string_list_append(buffer, item->util);
|
||||
}
|
||||
|
||||
static void read_from_stdin(struct shortlog *log)
|
||||
@@ -323,7 +313,7 @@ void shortlog_output(struct shortlog *log)
|
||||
}
|
||||
|
||||
onelines->strdup_strings = 1;
|
||||
string_list_clear(onelines, 1);
|
||||
string_list_clear(onelines, 0);
|
||||
free(onelines);
|
||||
log->list.items[i].util = NULL;
|
||||
}
|
||||
|
||||
@@ -99,10 +99,10 @@ static void *get_data(unsigned long size)
|
||||
stream.avail_out = size;
|
||||
stream.next_in = fill(1);
|
||||
stream.avail_in = len;
|
||||
inflateInit(&stream);
|
||||
git_inflate_init(&stream);
|
||||
|
||||
for (;;) {
|
||||
int ret = inflate(&stream, 0);
|
||||
int ret = git_inflate(&stream, 0);
|
||||
use(len - stream.avail_in);
|
||||
if (stream.total_out == size && ret == Z_STREAM_END)
|
||||
break;
|
||||
@@ -118,7 +118,7 @@ static void *get_data(unsigned long size)
|
||||
stream.next_in = fill(1);
|
||||
stream.avail_in = len;
|
||||
}
|
||||
inflateEnd(&stream);
|
||||
git_inflate_end(&stream);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
@@ -486,7 +486,7 @@ static int unresolve_one(const char *path)
|
||||
static void read_head_pointers(void)
|
||||
{
|
||||
if (read_ref("HEAD", head_sha1))
|
||||
die("No HEAD -- no initial commit yet?\n");
|
||||
die("No HEAD -- no initial commit yet?");
|
||||
if (read_ref("MERGE_HEAD", merge_head_sha1)) {
|
||||
fprintf(stderr, "Not in the middle of a merge.\n");
|
||||
exit(0);
|
||||
|
||||
34
bundle.c
34
bundle.c
@@ -167,6 +167,32 @@ int list_bundle_refs(struct bundle_header *header, int argc, const char **argv)
|
||||
return list_refs(&header->references, argc, argv);
|
||||
}
|
||||
|
||||
static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
|
||||
{
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
char *buf, *line, *lineend;
|
||||
unsigned long date;
|
||||
|
||||
if (revs->max_age == -1 && revs->min_age == -1)
|
||||
return 1;
|
||||
|
||||
buf = read_sha1_file(tag->sha1, &type, &size);
|
||||
if (!buf)
|
||||
return 1;
|
||||
line = memmem(buf, size, "\ntagger ", 8);
|
||||
if (!line++)
|
||||
return 1;
|
||||
lineend = memchr(line, buf + size - line, '\n');
|
||||
line = memchr(line, lineend ? lineend - line : buf + size - line, '>');
|
||||
if (!line++)
|
||||
return 1;
|
||||
date = strtoul(line, NULL, 10);
|
||||
free(buf);
|
||||
return (revs->max_age == -1 || revs->max_age < date) &&
|
||||
(revs->min_age == -1 || revs->min_age > date);
|
||||
}
|
||||
|
||||
int create_bundle(struct bundle_header *header, const char *path,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
@@ -240,6 +266,8 @@ int create_bundle(struct bundle_header *header, const char *path,
|
||||
return error("unrecognized argument: %s'", argv[i]);
|
||||
}
|
||||
|
||||
object_array_remove_duplicates(&revs.pending);
|
||||
|
||||
for (i = 0; i < revs.pending.nr; i++) {
|
||||
struct object_array_entry *e = revs.pending.objects + i;
|
||||
unsigned char sha1[20];
|
||||
@@ -255,6 +283,12 @@ int create_bundle(struct bundle_header *header, const char *path,
|
||||
flag = 0;
|
||||
display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
|
||||
|
||||
if (e->item->type == OBJ_TAG &&
|
||||
!is_tag_in_date_range(e->item, &revs)) {
|
||||
e->item->flags |= UNINTERESTING;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the refs we wrote out is correct; --max-count and
|
||||
* other limiting options could have prevented all the tips
|
||||
|
||||
12
cache.h
12
cache.h
@@ -18,6 +18,10 @@
|
||||
#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
|
||||
#endif
|
||||
|
||||
void git_inflate_init(z_streamp strm);
|
||||
void git_inflate_end(z_streamp strm);
|
||||
int git_inflate(z_streamp strm, int flush);
|
||||
|
||||
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
|
||||
#define DTYPE(de) ((de)->d_type)
|
||||
#else
|
||||
@@ -631,9 +635,6 @@ extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsig
|
||||
extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
|
||||
extern int force_object_loose(const unsigned char *sha1, time_t mtime);
|
||||
|
||||
/* just like read_sha1_file(), but non fatal in presence of bad objects */
|
||||
extern void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size);
|
||||
|
||||
/* global flag to enable extra checks when accessing packed objects */
|
||||
extern int do_check_packed_object_crc;
|
||||
|
||||
@@ -720,6 +721,10 @@ struct checkout {
|
||||
|
||||
extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
|
||||
extern int has_symlink_leading_path(int len, const char *name);
|
||||
extern int has_symlink_or_noent_leading_path(int len, const char *name);
|
||||
extern int has_dirs_only_path(int len, const char *name, int prefix_len);
|
||||
extern void invalidate_lstat_cache(int len, const char *name);
|
||||
extern void clear_lstat_cache(void);
|
||||
|
||||
extern struct alternate_object_database {
|
||||
struct alternate_object_database *next;
|
||||
@@ -936,7 +941,6 @@ extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
|
||||
extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
|
||||
|
||||
/* ls-files */
|
||||
int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen);
|
||||
int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset);
|
||||
void overlay_tree_on_cache(const char *tree_name, const char *prefix);
|
||||
|
||||
|
||||
59
color.c
59
color.c
@@ -40,30 +40,41 @@ static int parse_attr(const char *name, int len)
|
||||
}
|
||||
|
||||
void color_parse(const char *value, const char *var, char *dst)
|
||||
{
|
||||
color_parse_mem(value, strlen(value), var, dst);
|
||||
}
|
||||
|
||||
void color_parse_mem(const char *value, int value_len, const char *var,
|
||||
char *dst)
|
||||
{
|
||||
const char *ptr = value;
|
||||
int len = value_len;
|
||||
int attr = -1;
|
||||
int fg = -2;
|
||||
int bg = -2;
|
||||
|
||||
if (!strcasecmp(value, "reset")) {
|
||||
if (!strncasecmp(value, "reset", len)) {
|
||||
strcpy(dst, "\033[m");
|
||||
return;
|
||||
}
|
||||
|
||||
/* [fg [bg]] [attr] */
|
||||
while (*ptr) {
|
||||
while (len > 0) {
|
||||
const char *word = ptr;
|
||||
int val, len = 0;
|
||||
int val, wordlen = 0;
|
||||
|
||||
while (word[len] && !isspace(word[len]))
|
||||
len++;
|
||||
while (len > 0 && !isspace(word[wordlen])) {
|
||||
wordlen++;
|
||||
len--;
|
||||
}
|
||||
|
||||
ptr = word + len;
|
||||
while (*ptr && isspace(*ptr))
|
||||
ptr = word + wordlen;
|
||||
while (len > 0 && isspace(*ptr)) {
|
||||
ptr++;
|
||||
len--;
|
||||
}
|
||||
|
||||
val = parse_color(word, len);
|
||||
val = parse_color(word, wordlen);
|
||||
if (val >= -1) {
|
||||
if (fg == -2) {
|
||||
fg = val;
|
||||
@@ -75,7 +86,7 @@ void color_parse(const char *value, const char *var, char *dst)
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
val = parse_attr(word, len);
|
||||
val = parse_attr(word, wordlen);
|
||||
if (val < 0 || attr != -1)
|
||||
goto bad;
|
||||
attr = val;
|
||||
@@ -115,7 +126,7 @@ void color_parse(const char *value, const char *var, char *dst)
|
||||
*dst = 0;
|
||||
return;
|
||||
bad:
|
||||
die("bad config value '%s' for variable '%s'", value, var);
|
||||
die("bad color value '%.*s' for variable '%s'", value_len, value, var);
|
||||
}
|
||||
|
||||
int git_config_colorbool(const char *var, const char *value, int stdout_is_tty)
|
||||
@@ -191,3 +202,31 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
|
||||
va_end(args);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function splits the buffer by newlines and colors the lines individually.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int color_fwrite_lines(FILE *fp, const char *color,
|
||||
size_t count, const char *buf)
|
||||
{
|
||||
if (!*color)
|
||||
return fwrite(buf, count, 1, fp) != 1;
|
||||
while (count) {
|
||||
char *p = memchr(buf, '\n', count);
|
||||
if (p != buf && (fputs(color, fp) < 0 ||
|
||||
fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
|
||||
fputs(COLOR_RESET, fp) < 0))
|
||||
return -1;
|
||||
if (!p)
|
||||
return 0;
|
||||
if (fputc('\n', fp) < 0)
|
||||
return -1;
|
||||
count -= p + 1 - buf;
|
||||
buf = p + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
4
color.h
4
color.h
@@ -16,8 +16,10 @@ extern int git_use_color_default;
|
||||
int git_color_default_config(const char *var, const char *value, void *cb);
|
||||
|
||||
int git_config_colorbool(const char *var, const char *value, int stdout_is_tty);
|
||||
void color_parse(const char *var, const char *value, char *dst);
|
||||
void color_parse(const char *value, const char *var, char *dst);
|
||||
void color_parse_mem(const char *value, int len, const char *var, char *dst);
|
||||
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
|
||||
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
|
||||
int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
|
||||
|
||||
#endif /* COLOR_H */
|
||||
|
||||
@@ -52,4 +52,5 @@ NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
|
||||
FREAD_READS_DIRECTORIES=@FREAD_READS_DIRECTORIES@
|
||||
SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
|
||||
NO_PTHREADS=@NO_PTHREADS@
|
||||
THREADED_DELTA_SEARCH=@THREADED_DELTA_SEARCH@
|
||||
PTHREAD_LIBS=@PTHREAD_LIBS@
|
||||
|
||||
28
configure.ac
28
configure.ac
@@ -114,31 +114,31 @@ AC_MSG_NOTICE([CHECKS for programs])
|
||||
#
|
||||
AC_PROG_CC([cc gcc])
|
||||
# which switch to pass runtime path to dynamic libraries to the linker
|
||||
AC_CACHE_CHECK([if linker supports -R], ld_dashr, [
|
||||
AC_CACHE_CHECK([if linker supports -R], git_cv_ld_dashr, [
|
||||
SAVE_LDFLAGS="${LDFLAGS}"
|
||||
LDFLAGS="${SAVE_LDFLAGS} -R /"
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [ld_dashr=yes], [ld_dashr=no])
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [git_cv_ld_dashr=yes], [git_cv_ld_dashr=no])
|
||||
LDFLAGS="${SAVE_LDFLAGS}"
|
||||
])
|
||||
if test "$ld_dashr" = "yes"; then
|
||||
if test "$git_cv_ld_dashr" = "yes"; then
|
||||
AC_SUBST(CC_LD_DYNPATH, [-R])
|
||||
else
|
||||
AC_CACHE_CHECK([if linker supports -Wl,-rpath,], ld_wl_rpath, [
|
||||
AC_CACHE_CHECK([if linker supports -Wl,-rpath,], git_cv_ld_wl_rpath, [
|
||||
SAVE_LDFLAGS="${LDFLAGS}"
|
||||
LDFLAGS="${SAVE_LDFLAGS} -Wl,-rpath,/"
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [ld_wl_rpath=yes], [ld_wl_rpath=no])
|
||||
LDFLAGS="${SAVE_LD_FLAGS}"
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [git_cv_ld_wl_rpath=yes], [git_cv_ld_wl_rpath=no])
|
||||
LDFLAGS="${SAVE_LDFLAGS}"
|
||||
])
|
||||
if test "$ld_wl_rpath" = "yes"; then
|
||||
if test "$git_cv_ld_wl_rpath" = "yes"; then
|
||||
AC_SUBST(CC_LD_DYNPATH, [-Wl,-rpath,])
|
||||
else
|
||||
AC_CACHE_CHECK([if linker supports -rpath], ld_rpath, [
|
||||
AC_CACHE_CHECK([if linker supports -rpath], git_cv_ld_rpath, [
|
||||
SAVE_LDFLAGS="${LDFLAGS}"
|
||||
LDFLAGS="${SAVE_LDFLAGS} -rpath /"
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [ld_rpath=yes], [ld_rpath=no])
|
||||
LDFLAGS="${SAVE_LD_FLAGS}"
|
||||
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [git_cv_ld_rpath=yes], [git_cv_ld_rpath=no])
|
||||
LDFLAGS="${SAVE_LDFLAGS}"
|
||||
])
|
||||
if test "$ld_rpath" = "yes"; then
|
||||
if test "$git_cv_ld_rpath" = "yes"; then
|
||||
AC_SUBST(CC_LD_DYNPATH, [-rpath])
|
||||
else
|
||||
AC_MSG_WARN([linker does not support runtime path to dynamic libraries])
|
||||
@@ -492,7 +492,8 @@ AC_SUBST(NO_MKDTEMP)
|
||||
#
|
||||
# Define NO_PTHREADS if we do not have pthreads
|
||||
#
|
||||
# Define PTHREAD_LIBS to the linker flag used for Pthread support.
|
||||
# Define PTHREAD_LIBS to the linker flag used for Pthread support and define
|
||||
# THREADED_DELTA_SEARCH if Pthreads are available.
|
||||
AC_LANG_CONFTEST([AC_LANG_PROGRAM(
|
||||
[[#include <pthread.h>]],
|
||||
[[pthread_mutex_t test_mutex;]]
|
||||
@@ -500,16 +501,19 @@ AC_LANG_CONFTEST([AC_LANG_PROGRAM(
|
||||
${CC} -pthread conftest.c -o conftest.o > /dev/null 2>&1
|
||||
if test $? -eq 0;then
|
||||
PTHREAD_LIBS="-pthread"
|
||||
THREADED_DELTA_SEARCH=YesPlease
|
||||
else
|
||||
${CC} -lpthread conftest.c -o conftest.o > /dev/null 2>&1
|
||||
if test $? -eq 0;then
|
||||
PTHREAD_LIBS="-lpthread"
|
||||
THREADED_DELTA_SEARCH=YesPlease
|
||||
else
|
||||
NO_PTHREADS=UnfortunatelyYes
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
AC_SUBST(NO_PTHREADS)
|
||||
AC_SUBST(THREADED_DELTA_SEARCH)
|
||||
|
||||
## Site configuration (override autodetection)
|
||||
## --with-PACKAGE[=ARG] and --without-PACKAGE
|
||||
|
||||
@@ -315,7 +315,7 @@ static int git_tcp_connect_sock(char *host, int flags)
|
||||
/* Not numeric */
|
||||
struct servent *se = getservbyname(port,"tcp");
|
||||
if ( !se )
|
||||
die("Unknown port %s\n", port);
|
||||
die("Unknown port %s", port);
|
||||
nport = se->s_port;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!bash
|
||||
#
|
||||
# bash completion support for core Git.
|
||||
#
|
||||
@@ -50,9 +51,11 @@ case "$COMP_WORDBREAKS" in
|
||||
*) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
|
||||
esac
|
||||
|
||||
# __gitdir accepts 0 or 1 arguments (i.e., location)
|
||||
# returns location of .git repo
|
||||
__gitdir ()
|
||||
{
|
||||
if [ -z "$1" ]; then
|
||||
if [ -z "${1-}" ]; then
|
||||
if [ -n "$__git_dir" ]; then
|
||||
echo "$__git_dir"
|
||||
elif [ -d .git ]; then
|
||||
@@ -67,6 +70,8 @@ __gitdir ()
|
||||
fi
|
||||
}
|
||||
|
||||
# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
|
||||
# returns text to add to bash PS1 prompt (includes branch name)
|
||||
__git_ps1 ()
|
||||
{
|
||||
local g="$(git rev-parse --git-dir 2>/dev/null)"
|
||||
@@ -111,7 +116,7 @@ __git_ps1 ()
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
if [ -n "${1-}" ]; then
|
||||
printf "$1" "${b##refs/heads/}$r"
|
||||
else
|
||||
printf " (%s)" "${b##refs/heads/}$r"
|
||||
@@ -119,6 +124,7 @@ __git_ps1 ()
|
||||
fi
|
||||
}
|
||||
|
||||
# __gitcomp_1 requires 2 arguments
|
||||
__gitcomp_1 ()
|
||||
{
|
||||
local c IFS=' '$'\t'$'\n'
|
||||
@@ -131,6 +137,8 @@ __gitcomp_1 ()
|
||||
done
|
||||
}
|
||||
|
||||
# __gitcomp accepts 1, 2, 3, or 4 arguments
|
||||
# generates completion reply with compgen
|
||||
__gitcomp ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
@@ -143,22 +151,23 @@ __gitcomp ()
|
||||
;;
|
||||
*)
|
||||
local IFS=$'\n'
|
||||
COMPREPLY=($(compgen -P "$2" \
|
||||
-W "$(__gitcomp_1 "$1" "$4")" \
|
||||
COMPREPLY=($(compgen -P "${2-}" \
|
||||
-W "$(__gitcomp_1 "${1-}" "${4-}")" \
|
||||
-- "$cur"))
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# __git_heads accepts 0 or 1 arguments (to pass to __gitdir)
|
||||
__git_heads ()
|
||||
{
|
||||
local cmd i is_hash=y dir="$(__gitdir "$1")"
|
||||
local cmd i is_hash=y dir="$(__gitdir "${1-}")"
|
||||
if [ -d "$dir" ]; then
|
||||
git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
|
||||
refs/heads
|
||||
return
|
||||
fi
|
||||
for i in $(git ls-remote "$1" 2>/dev/null); do
|
||||
for i in $(git ls-remote "${1-}" 2>/dev/null); do
|
||||
case "$is_hash,$i" in
|
||||
y,*) is_hash=n ;;
|
||||
n,*^{}) is_hash=y ;;
|
||||
@@ -168,15 +177,16 @@ __git_heads ()
|
||||
done
|
||||
}
|
||||
|
||||
# __git_tags accepts 0 or 1 arguments (to pass to __gitdir)
|
||||
__git_tags ()
|
||||
{
|
||||
local cmd i is_hash=y dir="$(__gitdir "$1")"
|
||||
local cmd i is_hash=y dir="$(__gitdir "${1-}")"
|
||||
if [ -d "$dir" ]; then
|
||||
git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
|
||||
refs/tags
|
||||
return
|
||||
fi
|
||||
for i in $(git ls-remote "$1" 2>/dev/null); do
|
||||
for i in $(git ls-remote "${1-}" 2>/dev/null); do
|
||||
case "$is_hash,$i" in
|
||||
y,*) is_hash=n ;;
|
||||
n,*^{}) is_hash=y ;;
|
||||
@@ -186,9 +196,10 @@ __git_tags ()
|
||||
done
|
||||
}
|
||||
|
||||
# __git_refs accepts 0 or 1 arguments (to pass to __gitdir)
|
||||
__git_refs ()
|
||||
{
|
||||
local i is_hash=y dir="$(__gitdir "$1")"
|
||||
local i is_hash=y dir="$(__gitdir "${1-}")"
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}" format refs
|
||||
if [ -d "$dir" ]; then
|
||||
case "$cur" in
|
||||
@@ -218,6 +229,7 @@ __git_refs ()
|
||||
done
|
||||
}
|
||||
|
||||
# __git_refs2 requires 1 argument (to pass to __git_refs)
|
||||
__git_refs2 ()
|
||||
{
|
||||
local i
|
||||
@@ -226,6 +238,7 @@ __git_refs2 ()
|
||||
done
|
||||
}
|
||||
|
||||
# __git_refs_remotes requires 1 argument (to pass to ls-remote)
|
||||
__git_refs_remotes ()
|
||||
{
|
||||
local cmd i is_hash=y
|
||||
@@ -470,6 +483,7 @@ __git_aliases ()
|
||||
done
|
||||
}
|
||||
|
||||
# __git_aliased_command requires 1 argument
|
||||
__git_aliased_command ()
|
||||
{
|
||||
local word cmdline=$(git --git-dir="$(__gitdir)" \
|
||||
@@ -482,6 +496,7 @@ __git_aliased_command ()
|
||||
done
|
||||
}
|
||||
|
||||
# __git_find_subcommand requires 1 argument
|
||||
__git_find_subcommand ()
|
||||
{
|
||||
local word subcommand c=1
|
||||
@@ -563,7 +578,7 @@ _git_add ()
|
||||
--*)
|
||||
__gitcomp "
|
||||
--interactive --refresh --patch --update --dry-run
|
||||
--ignore-errors
|
||||
--ignore-errors --intent-to-add
|
||||
"
|
||||
return
|
||||
esac
|
||||
@@ -628,7 +643,6 @@ _git_branch ()
|
||||
done
|
||||
|
||||
case "${COMP_WORDS[COMP_CWORD]}" in
|
||||
--*=*) COMPREPLY=() ;;
|
||||
--*)
|
||||
__gitcomp "
|
||||
--color --no-color --verbose --abbrev= --no-abbrev
|
||||
@@ -759,6 +773,20 @@ _git_describe ()
|
||||
__gitcomp "$(__git_refs)"
|
||||
}
|
||||
|
||||
__git_diff_common_options="--stat --numstat --shortstat --summary
|
||||
--patch-with-stat --name-only --name-status --color
|
||||
--no-color --color-words --no-renames --check
|
||||
--full-index --binary --abbrev --diff-filter=
|
||||
--find-copies-harder
|
||||
--text --ignore-space-at-eol --ignore-space-change
|
||||
--ignore-all-space --exit-code --quiet --ext-diff
|
||||
--no-ext-diff
|
||||
--no-prefix --src-prefix= --dst-prefix=
|
||||
--inter-hunk-context=
|
||||
--patience
|
||||
--raw
|
||||
"
|
||||
|
||||
_git_diff ()
|
||||
{
|
||||
__git_has_doubledash && return
|
||||
@@ -766,16 +794,9 @@ _git_diff ()
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "--cached --stat --numstat --shortstat --summary
|
||||
--patch-with-stat --name-only --name-status --color
|
||||
--no-color --color-words --no-renames --check
|
||||
--full-index --binary --abbrev --diff-filter=
|
||||
--find-copies-harder --pickaxe-all --pickaxe-regex
|
||||
--text --ignore-space-at-eol --ignore-space-change
|
||||
--ignore-all-space --exit-code --quiet --ext-diff
|
||||
--no-ext-diff
|
||||
--no-prefix --src-prefix= --dst-prefix=
|
||||
__gitcomp "--cached --pickaxe-all --pickaxe-regex
|
||||
--base --ours --theirs
|
||||
$__git_diff_common_options
|
||||
"
|
||||
return
|
||||
;;
|
||||
@@ -823,6 +844,8 @@ _git_format_patch ()
|
||||
--not --all
|
||||
--cover-letter
|
||||
--no-prefix --src-prefix= --dst-prefix=
|
||||
--inline --suffix= --ignore-if-in-upstream
|
||||
--subject-prefix=
|
||||
"
|
||||
return
|
||||
;;
|
||||
@@ -930,6 +953,8 @@ _git_ls_tree ()
|
||||
__git_complete_file
|
||||
}
|
||||
|
||||
__git_log_pretty_formats="oneline short medium full fuller email raw format:"
|
||||
|
||||
_git_log ()
|
||||
{
|
||||
__git_has_doubledash && return
|
||||
@@ -937,8 +962,7 @@ _git_log ()
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--pretty=*)
|
||||
__gitcomp "
|
||||
oneline short medium full fuller email raw
|
||||
__gitcomp "$__git_log_pretty_formats
|
||||
" "" "${cur##--pretty=}"
|
||||
return
|
||||
;;
|
||||
@@ -958,15 +982,16 @@ _git_log ()
|
||||
--relative-date --date=
|
||||
--author= --committer= --grep=
|
||||
--all-match
|
||||
--pretty= --name-status --name-only --raw
|
||||
--pretty=
|
||||
--not --all
|
||||
--left-right --cherry-pick
|
||||
--graph
|
||||
--stat --numstat --shortstat
|
||||
--decorate --diff-filter=
|
||||
--color-words --walk-reflogs
|
||||
--decorate
|
||||
--walk-reflogs
|
||||
--parents --children --full-history
|
||||
--merge
|
||||
$__git_diff_common_options
|
||||
--pickaxe-all --pickaxe-regex
|
||||
"
|
||||
return
|
||||
;;
|
||||
@@ -1367,7 +1392,7 @@ _git_config ()
|
||||
|
||||
_git_remote ()
|
||||
{
|
||||
local subcommands="add rm show prune update"
|
||||
local subcommands="add rename rm show prune update"
|
||||
local subcommand="$(__git_find_subcommand "$subcommands")"
|
||||
if [ -z "$subcommand" ]; then
|
||||
__gitcomp "$subcommands"
|
||||
@@ -1375,7 +1400,7 @@ _git_remote ()
|
||||
fi
|
||||
|
||||
case "$subcommand" in
|
||||
rm|show|prune)
|
||||
rename|rm|show|prune)
|
||||
__gitcomp "$(__git_remotes)"
|
||||
;;
|
||||
update)
|
||||
@@ -1403,7 +1428,7 @@ _git_reset ()
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "--mixed --hard --soft"
|
||||
__gitcomp "--merge --mixed --hard --soft"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
@@ -1465,13 +1490,14 @@ _git_show ()
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--pretty=*)
|
||||
__gitcomp "
|
||||
oneline short medium full fuller email raw
|
||||
__gitcomp "$__git_log_pretty_formats
|
||||
" "" "${cur##--pretty=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "--pretty="
|
||||
__gitcomp "--pretty=
|
||||
$__git_diff_common_options
|
||||
"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
@@ -1558,7 +1584,7 @@ _git_svn ()
|
||||
--follow-parent --authors-file= --repack=
|
||||
--no-metadata --use-svm-props --use-svnsync-props
|
||||
--log-window-size= --no-checkout --quiet
|
||||
--repack-flags --user-log-author $remote_opts
|
||||
--repack-flags --user-log-author --localtime $remote_opts
|
||||
"
|
||||
local init_opts="
|
||||
--template= --shared= --trunk= --tags=
|
||||
@@ -1672,7 +1698,6 @@ _git ()
|
||||
|
||||
if [ -z "$command" ]; then
|
||||
case "${COMP_WORDS[COMP_CWORD]}" in
|
||||
--*=*) COMPREPLY=() ;;
|
||||
--*) __gitcomp "
|
||||
--paginate
|
||||
--no-pager
|
||||
@@ -1736,6 +1761,7 @@ _git ()
|
||||
show) _git_show ;;
|
||||
show-branch) _git_show_branch ;;
|
||||
stash) _git_stash ;;
|
||||
stage) _git_add ;;
|
||||
submodule) _git_submodule ;;
|
||||
svn) _git_svn ;;
|
||||
tag) _git_tag ;;
|
||||
@@ -1763,13 +1789,16 @@ _gitk ()
|
||||
__git_complete_revlist
|
||||
}
|
||||
|
||||
complete -o default -o nospace -F _git git
|
||||
complete -o default -o nospace -F _gitk gitk
|
||||
complete -o bashdefault -o default -o nospace -F _git git 2>/dev/null \
|
||||
|| complete -o default -o nospace -F _git git
|
||||
complete -o bashdefault -o default -o nospace -F _gitk gitk 2>/dev/null \
|
||||
|| complete -o default -o nospace -F _gitk gitk
|
||||
|
||||
# The following are necessary only for Cygwin, and only are needed
|
||||
# when the user has tab-completed the executable name and consequently
|
||||
# included the '.exe' suffix.
|
||||
#
|
||||
if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
|
||||
complete -o default -o nospace -F _git git.exe
|
||||
complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
|
||||
|| complete -o default -o nospace -F _git git.exe
|
||||
fi
|
||||
|
||||
73
contrib/difftool/git-difftool
Executable file
73
contrib/difftool/git-difftool
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright (c) 2009 David Aguilar
|
||||
#
|
||||
# This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
|
||||
# git-difftool-helper script. This script exports
|
||||
# GIT_EXTERNAL_DIFF and GIT_PAGER for use by git, and
|
||||
# GIT_DIFFTOOL_NO_PROMPT and GIT_MERGE_TOOL for use by git-difftool-helper.
|
||||
# Any arguments that are unknown to this script are forwarded to 'git diff'.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd qw(abs_path);
|
||||
use File::Basename qw(dirname);
|
||||
|
||||
my $DIR = abs_path(dirname($0));
|
||||
|
||||
|
||||
sub usage
|
||||
{
|
||||
print << 'USAGE';
|
||||
usage: git difftool [--tool=<tool>] [--no-prompt] ["git diff" options]
|
||||
USAGE
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub setup_environment
|
||||
{
|
||||
$ENV{PATH} = "$DIR:$ENV{PATH}";
|
||||
$ENV{GIT_PAGER} = '';
|
||||
$ENV{GIT_EXTERNAL_DIFF} = 'git-difftool-helper';
|
||||
}
|
||||
|
||||
sub exe
|
||||
{
|
||||
my $exe = shift;
|
||||
return defined $ENV{COMSPEC} ? "$exe.exe" : $exe;
|
||||
}
|
||||
|
||||
sub generate_command
|
||||
{
|
||||
my @command = (exe('git'), 'diff');
|
||||
my $skip_next = 0;
|
||||
my $idx = -1;
|
||||
for my $arg (@ARGV) {
|
||||
$idx++;
|
||||
if ($skip_next) {
|
||||
$skip_next = 0;
|
||||
next;
|
||||
}
|
||||
if ($arg eq '-t' or $arg eq '--tool') {
|
||||
usage() if $#ARGV <= $idx;
|
||||
$ENV{GIT_MERGE_TOOL} = $ARGV[$idx + 1];
|
||||
$skip_next = 1;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^--tool=/) {
|
||||
$ENV{GIT_MERGE_TOOL} = substr($arg, 7);
|
||||
next;
|
||||
}
|
||||
if ($arg eq '--no-prompt') {
|
||||
$ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
|
||||
next;
|
||||
}
|
||||
if ($arg eq '-h' or $arg eq '--help') {
|
||||
usage();
|
||||
}
|
||||
push @command, $arg;
|
||||
}
|
||||
return @command
|
||||
}
|
||||
|
||||
setup_environment();
|
||||
exec(generate_command());
|
||||
243
contrib/difftool/git-difftool-helper
Executable file
243
contrib/difftool/git-difftool-helper
Executable file
@@ -0,0 +1,243 @@
|
||||
#!/bin/sh
|
||||
# git-difftool-helper is a GIT_EXTERNAL_DIFF-compatible diff tool launcher.
|
||||
# It supports kdiff3, tkdiff, xxdiff, meld, opendiff, emerge, ecmerge,
|
||||
# vimdiff, gvimdiff, and custom user-configurable tools.
|
||||
# This script is typically launched by using the 'git difftool'
|
||||
# convenience command.
|
||||
#
|
||||
# Copyright (c) 2009 David Aguilar
|
||||
|
||||
# Set GIT_DIFFTOOL_NO_PROMPT to bypass the per-file prompt.
|
||||
should_prompt () {
|
||||
! test -n "$GIT_DIFFTOOL_NO_PROMPT"
|
||||
}
|
||||
|
||||
# Should we keep the backup .orig file?
|
||||
keep_backup_mode="$(git config --bool merge.keepBackup || echo true)"
|
||||
keep_backup () {
|
||||
test "$keep_backup_mode" = "true"
|
||||
}
|
||||
|
||||
# This function manages the backup .orig file.
|
||||
# A backup $MERGED.orig file is created if changes are detected.
|
||||
cleanup_temp_files () {
|
||||
if test -n "$MERGED"; then
|
||||
if keep_backup && test "$MERGED" -nt "$BACKUP"; then
|
||||
test -f "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
|
||||
else
|
||||
rm -f -- "$BACKUP"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# This is called when users Ctrl-C out of git-difftool-helper
|
||||
sigint_handler () {
|
||||
cleanup_temp_files
|
||||
exit 1
|
||||
}
|
||||
|
||||
# This function prepares temporary files and launches the appropriate
|
||||
# merge tool.
|
||||
launch_merge_tool () {
|
||||
# Merged is the filename as it appears in the work tree
|
||||
# Local is the contents of a/filename
|
||||
# Remote is the contents of b/filename
|
||||
# Custom merge tool commands might use $BASE so we provide it
|
||||
MERGED="$1"
|
||||
LOCAL="$2"
|
||||
REMOTE="$3"
|
||||
BASE="$1"
|
||||
ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
|
||||
BACKUP="$MERGED.BACKUP.$ext"
|
||||
|
||||
# Create and ensure that we clean up $BACKUP
|
||||
test -f "$MERGED" && cp -- "$MERGED" "$BACKUP"
|
||||
trap sigint_handler INT
|
||||
|
||||
# $LOCAL and $REMOTE are temporary files so prompt
|
||||
# the user with the real $MERGED name before launching $merge_tool.
|
||||
if should_prompt; then
|
||||
printf "\nViewing: '$MERGED'\n"
|
||||
printf "Hit return to launch '%s': " "$merge_tool"
|
||||
read ans
|
||||
fi
|
||||
|
||||
# Run the appropriate merge tool command
|
||||
case "$merge_tool" in
|
||||
kdiff3)
|
||||
basename=$(basename "$MERGED")
|
||||
"$merge_tool_path" --auto \
|
||||
--L1 "$basename (A)" \
|
||||
--L2 "$basename (B)" \
|
||||
-o "$MERGED" "$LOCAL" "$REMOTE" \
|
||||
> /dev/null 2>&1
|
||||
;;
|
||||
|
||||
tkdiff)
|
||||
"$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
meld)
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
vimdiff)
|
||||
"$merge_tool_path" -c "wincmd l" "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
gvimdiff)
|
||||
"$merge_tool_path" -c "wincmd l" -f "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
xxdiff)
|
||||
"$merge_tool_path" \
|
||||
-X \
|
||||
-R 'Accel.SaveAsMerged: "Ctrl-S"' \
|
||||
-R 'Accel.Search: "Ctrl+F"' \
|
||||
-R 'Accel.SearchForward: "Ctrl-G"' \
|
||||
--merged-file "$MERGED" \
|
||||
"$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
opendiff)
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
-merge "$MERGED" | cat
|
||||
;;
|
||||
|
||||
ecmerge)
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
--default --mode=merge2 --to="$MERGED"
|
||||
;;
|
||||
|
||||
emerge)
|
||||
"$merge_tool_path" -f emerge-files-command \
|
||||
"$LOCAL" "$REMOTE" "$(basename "$MERGED")"
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -n "$merge_tool_cmd"; then
|
||||
( eval $merge_tool_cmd )
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
cleanup_temp_files
|
||||
}
|
||||
|
||||
# Verifies that mergetool.<tool>.cmd exists
|
||||
valid_custom_tool() {
|
||||
merge_tool_cmd="$(git config mergetool.$1.cmd)"
|
||||
test -n "$merge_tool_cmd"
|
||||
}
|
||||
|
||||
# Verifies that the chosen merge tool is properly setup.
|
||||
# Built-in merge tools are always valid.
|
||||
valid_tool() {
|
||||
case "$1" in
|
||||
kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
|
||||
;; # happy
|
||||
*)
|
||||
if ! valid_custom_tool "$1"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Sets up the merge_tool_path variable.
|
||||
# This handles the mergetool.<tool>.path configuration.
|
||||
init_merge_tool_path() {
|
||||
merge_tool_path=$(git config mergetool."$1".path)
|
||||
if test -z "$merge_tool_path"; then
|
||||
case "$1" in
|
||||
emerge)
|
||||
merge_tool_path=emacs
|
||||
;;
|
||||
*)
|
||||
merge_tool_path="$1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# Allow the GIT_MERGE_TOOL variable to provide a default value
|
||||
test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
|
||||
|
||||
# If not merge tool was specified then use the merge.tool
|
||||
# configuration variable. If that's invalid then reset merge_tool.
|
||||
if test -z "$merge_tool"; then
|
||||
merge_tool=$(git config merge.tool)
|
||||
if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
|
||||
echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
|
||||
echo >&2 "Resetting to default..."
|
||||
unset merge_tool
|
||||
fi
|
||||
fi
|
||||
|
||||
# Try to guess an appropriate merge tool if no tool has been set.
|
||||
if test -z "$merge_tool"; then
|
||||
|
||||
# We have a $DISPLAY so try some common UNIX merge tools
|
||||
if test -n "$DISPLAY"; then
|
||||
merge_tool_candidates="kdiff3 tkdiff xxdiff meld gvimdiff"
|
||||
# If gnome then prefer meld
|
||||
if test -n "$GNOME_DESKTOP_SESSION_ID"; then
|
||||
merge_tool_candidates="meld $merge_tool_candidates"
|
||||
fi
|
||||
# If KDE then prefer kdiff3
|
||||
if test "$KDE_FULL_SESSION" = "true"; then
|
||||
merge_tool_candidates="kdiff3 $merge_tool_candidates"
|
||||
fi
|
||||
fi
|
||||
|
||||
# $EDITOR is emacs so add emerge as a candidate
|
||||
if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
|
||||
merge_tool_candidates="$merge_tool_candidates emerge"
|
||||
fi
|
||||
|
||||
# $EDITOR is vim so add vimdiff as a candidate
|
||||
if echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
|
||||
merge_tool_candidates="$merge_tool_candidates vimdiff"
|
||||
fi
|
||||
|
||||
merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
|
||||
echo "merge tool candidates: $merge_tool_candidates"
|
||||
|
||||
# Loop over each candidate and stop when a valid merge tool is found.
|
||||
for i in $merge_tool_candidates
|
||||
do
|
||||
init_merge_tool_path $i
|
||||
if type "$merge_tool_path" > /dev/null 2>&1; then
|
||||
merge_tool=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if test -z "$merge_tool" ; then
|
||||
echo "No known merge resolution program available."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
# A merge tool has been set, so verify that it's valid.
|
||||
if ! valid_tool "$merge_tool"; then
|
||||
echo >&2 "Unknown merge tool $merge_tool"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
init_merge_tool_path "$merge_tool"
|
||||
|
||||
if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
|
||||
echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Launch the merge tool on each path provided by 'git diff'
|
||||
while test $# -gt 6
|
||||
do
|
||||
launch_merge_tool "$1" "$2" "$5"
|
||||
shift 7
|
||||
done
|
||||
104
contrib/difftool/git-difftool.txt
Normal file
104
contrib/difftool/git-difftool.txt
Normal file
@@ -0,0 +1,104 @@
|
||||
git-difftool(1)
|
||||
===============
|
||||
|
||||
NAME
|
||||
----
|
||||
git-difftool - compare changes using common merge tools
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git difftool' [--tool=<tool>] [--no-prompt] ['git diff' options]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
'git-difftool' is a git command that allows you to compare and edit files
|
||||
between revisions using common merge tools. At its most basic level,
|
||||
'git-difftool' does what 'git-mergetool' does but its use is for non-merge
|
||||
situations such as when preparing commits or comparing changes against
|
||||
the index.
|
||||
|
||||
'git difftool' is a frontend to 'git diff' and accepts the same
|
||||
arguments and options.
|
||||
|
||||
See linkgit:git-diff[1] for the full list of supported options.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-t <tool>::
|
||||
--tool=<tool>::
|
||||
Use the merge resolution program specified by <tool>.
|
||||
Valid merge tools are:
|
||||
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
|
||||
+
|
||||
If a merge resolution program is not specified, 'git-difftool'
|
||||
will use the configuration variable `merge.tool`. If the
|
||||
configuration variable `merge.tool` is not set, 'git difftool'
|
||||
will pick a suitable default.
|
||||
+
|
||||
You can explicitly provide a full path to the tool by setting the
|
||||
configuration variable `mergetool.<tool>.path`. For example, you
|
||||
can configure the absolute path to kdiff3 by setting
|
||||
`mergetool.kdiff3.path`. Otherwise, 'git-difftool' assumes the
|
||||
tool is available in PATH.
|
||||
+
|
||||
Instead of running one of the known merge tool programs,
|
||||
'git-difftool' can be customized to run an alternative program
|
||||
by specifying the command line to invoke in a configuration
|
||||
variable `mergetool.<tool>.cmd`.
|
||||
+
|
||||
When 'git-difftool' is invoked with this tool (either through the
|
||||
`-t` or `--tool` option or the `merge.tool` configuration variable)
|
||||
the configured command line will be invoked with the following
|
||||
variables available: `$LOCAL` is set to the name of the temporary
|
||||
file containing the contents of the diff pre-image and `$REMOTE`
|
||||
is set to the name of the temporary file containing the contents
|
||||
of the diff post-image. `$BASE` is provided for compatibility
|
||||
with custom merge tool commands and has the same value as `$LOCAL`.
|
||||
|
||||
--no-prompt::
|
||||
Do not prompt before launching a diff tool.
|
||||
|
||||
CONFIG VARIABLES
|
||||
----------------
|
||||
merge.tool::
|
||||
The default merge tool to use.
|
||||
+
|
||||
See the `--tool=<tool>` option above for more details.
|
||||
|
||||
merge.keepBackup::
|
||||
The original, unedited file content can be saved to a file with
|
||||
a `.orig` extension. Defaults to `true` (i.e. keep the backup files).
|
||||
|
||||
mergetool.<tool>.path::
|
||||
Override the path for the given tool. This is useful in case
|
||||
your tool is not in the PATH.
|
||||
|
||||
mergetool.<tool>.cmd::
|
||||
Specify the command to invoke the specified merge tool.
|
||||
+
|
||||
See the `--tool=<tool>` option above for more details.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-diff[1]::
|
||||
Show changes between commits, commit and working tree, etc
|
||||
|
||||
linkgit:git-mergetool[1]::
|
||||
Run merge conflict resolution tools to resolve merge conflicts
|
||||
|
||||
linkgit:git-config[1]::
|
||||
Get and set repository or global options
|
||||
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
Written by David Aguilar <davvid@gmail.com>.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by David Aguilar and the git-list <git@vger.kernel.org>.
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the linkgit:git[1] suite
|
||||
3
contrib/examples/README
Normal file
3
contrib/examples/README
Normal file
@@ -0,0 +1,3 @@
|
||||
These are original scripted implementations, kept primarily for their
|
||||
reference value to any aspiring plumbing users who want to learn how
|
||||
pieces can be fit together.
|
||||
@@ -5,11 +5,13 @@ automatically.
|
||||
If you have an older version of vim, you can get the latest syntax
|
||||
files from the vim project:
|
||||
|
||||
http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/git.vim
|
||||
http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitcommit.vim
|
||||
http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitconfig.vim
|
||||
http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitrebase.vim
|
||||
http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitsendemail.vim
|
||||
http://ftp.vim.org/pub/vim/runtime/syntax/git.vim
|
||||
http://ftp.vim.org/pub/vim/runtime/syntax/gitcommit.vim
|
||||
http://ftp.vim.org/pub/vim/runtime/syntax/gitconfig.vim
|
||||
http://ftp.vim.org/pub/vim/runtime/syntax/gitrebase.vim
|
||||
http://ftp.vim.org/pub/vim/runtime/syntax/gitsendemail.vim
|
||||
|
||||
These files are also available via FTP at the same location.
|
||||
|
||||
To install:
|
||||
|
||||
|
||||
33
ctype.c
33
ctype.c
@@ -5,25 +5,22 @@
|
||||
*/
|
||||
#include "cache.h"
|
||||
|
||||
/* Just so that no insane platform contaminate namespace with these symbols */
|
||||
#undef SS
|
||||
#undef AA
|
||||
#undef DD
|
||||
#undef GS
|
||||
|
||||
#define SS GIT_SPACE
|
||||
#define AA GIT_ALPHA
|
||||
#define DD GIT_DIGIT
|
||||
#define GS GIT_SPECIAL /* \0, *, ?, [, \\ */
|
||||
enum {
|
||||
S = GIT_SPACE,
|
||||
A = GIT_ALPHA,
|
||||
D = GIT_DIGIT,
|
||||
G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */
|
||||
R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */
|
||||
};
|
||||
|
||||
unsigned char sane_ctype[256] = {
|
||||
GS, 0, 0, 0, 0, 0, 0, 0, 0, SS, SS, 0, 0, SS, 0, 0, /* 0-15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-15 */
|
||||
SS, 0, 0, 0, 0, 0, 0, 0, 0, 0, GS, 0, 0, 0, 0, 0, /* 32-15 */
|
||||
DD, DD, DD, DD, DD, DD, DD, DD, DD, DD, 0, 0, 0, 0, 0, GS, /* 48-15 */
|
||||
0, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, /* 64-15 */
|
||||
AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, GS, GS, 0, 0, 0, /* 80-15 */
|
||||
0, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, /* 96-15 */
|
||||
AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, 0, 0, 0, 0, 0, /* 112-15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */
|
||||
S, 0, 0, 0, R, 0, 0, 0, R, R, G, R, 0, 0, R, 0, /* 32.. 47 */
|
||||
D, D, D, D, D, D, D, D, D, D, 0, 0, 0, 0, 0, G, /* 48.. 63 */
|
||||
0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */
|
||||
A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, 0, /* 80.. 95 */
|
||||
0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */
|
||||
A, A, A, A, A, A, A, A, A, A, A, R, R, 0, 0, 0, /* 112..127 */
|
||||
/* Nothing in the 128.. range */
|
||||
};
|
||||
|
||||
61
daemon.c
61
daemon.c
@@ -150,7 +150,6 @@ static char *path_ok(char *directory)
|
||||
{
|
||||
static char rpath[PATH_MAX];
|
||||
static char interp_path[PATH_MAX];
|
||||
int retried_path = 0;
|
||||
char *path;
|
||||
char *dir;
|
||||
|
||||
@@ -219,22 +218,15 @@ static char *path_ok(char *directory)
|
||||
dir = rpath;
|
||||
}
|
||||
|
||||
do {
|
||||
path = enter_repo(dir, strict_paths);
|
||||
if (path)
|
||||
break;
|
||||
|
||||
path = enter_repo(dir, strict_paths);
|
||||
if (!path && base_path && base_path_relaxed) {
|
||||
/*
|
||||
* if we fail and base_path_relaxed is enabled, try without
|
||||
* prefixing the base path
|
||||
*/
|
||||
if (base_path && base_path_relaxed && !retried_path) {
|
||||
dir = directory;
|
||||
retried_path = 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
dir = directory;
|
||||
path = enter_repo(dir, strict_paths);
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
logerror("'%s': unable to chdir or not a git archive", dir);
|
||||
@@ -405,6 +397,14 @@ static void make_service_overridable(const char *name, int ena)
|
||||
die("No such service %s", name);
|
||||
}
|
||||
|
||||
static char *xstrdup_tolower(const char *str)
|
||||
{
|
||||
char *p, *dup = xstrdup(str);
|
||||
for (p = dup; *p; p++)
|
||||
*p = tolower(*p);
|
||||
return dup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Separate the "extra args" information as supplied by the client connection.
|
||||
*/
|
||||
@@ -413,7 +413,6 @@ static void parse_extra_args(char *extra_args, int buflen)
|
||||
char *val;
|
||||
int vallen;
|
||||
char *end = extra_args + buflen;
|
||||
char *hp;
|
||||
|
||||
while (extra_args < end && *extra_args) {
|
||||
saw_extended_args = 1;
|
||||
@@ -431,7 +430,7 @@ static void parse_extra_args(char *extra_args, int buflen)
|
||||
tcp_port = xstrdup(port);
|
||||
}
|
||||
free(hostname);
|
||||
hostname = xstrdup(host);
|
||||
hostname = xstrdup_tolower(host);
|
||||
}
|
||||
|
||||
/* On to the next one */
|
||||
@@ -439,20 +438,11 @@ static void parse_extra_args(char *extra_args, int buflen)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace literal host with lowercase-ized hostname.
|
||||
*/
|
||||
hp = hostname;
|
||||
if (!hp)
|
||||
return;
|
||||
for ( ; *hp; hp++)
|
||||
*hp = tolower(*hp);
|
||||
|
||||
/*
|
||||
* Locate canonical hostname and its IP address.
|
||||
*/
|
||||
if (hostname) {
|
||||
#ifndef NO_IPV6
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *ai, *ai0;
|
||||
int gai;
|
||||
@@ -476,9 +466,7 @@ static void parse_extra_args(char *extra_args, int buflen)
|
||||
}
|
||||
freeaddrinfo(ai0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct hostent *hent;
|
||||
struct sockaddr_in sa;
|
||||
char **ap;
|
||||
@@ -499,8 +487,8 @@ static void parse_extra_args(char *extra_args, int buflen)
|
||||
canon_hostname = xstrdup(hent->h_name);
|
||||
free(ip_address);
|
||||
ip_address = xstrdup(addrbuf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -728,7 +716,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
|
||||
|
||||
gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
|
||||
if (gai)
|
||||
die("getaddrinfo() failed: %s\n", gai_strerror(gai));
|
||||
die("getaddrinfo() failed: %s", gai_strerror(gai));
|
||||
|
||||
for (ai = ai0; ai; ai = ai->ai_next) {
|
||||
int sockfd;
|
||||
@@ -949,19 +937,14 @@ int main(int argc, char **argv)
|
||||
gid_t gid = 0;
|
||||
int i;
|
||||
|
||||
if (argv[0] && *argv[0])
|
||||
git_extract_argv0_path(argv[0]);
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *arg = argv[i];
|
||||
|
||||
if (!prefixcmp(arg, "--listen=")) {
|
||||
char *p = arg + 9;
|
||||
char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1);
|
||||
while (*p)
|
||||
*ph++ = tolower(*p++);
|
||||
*ph = 0;
|
||||
continue;
|
||||
listen_addr = xstrdup_tolower(arg + 9);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--port=")) {
|
||||
char *end;
|
||||
@@ -1121,7 +1104,9 @@ int main(int argc, char **argv)
|
||||
struct sockaddr *peer = (struct sockaddr *)&ss;
|
||||
socklen_t slen = sizeof(ss);
|
||||
|
||||
freopen("/dev/null", "w", stderr);
|
||||
if (!freopen("/dev/null", "w", stderr))
|
||||
die("failed to redirect stderr to /dev/null: %s",
|
||||
strerror(errno));
|
||||
|
||||
if (getpeername(0, peer, &slen))
|
||||
peer = NULL;
|
||||
|
||||
40
diff-lib.c
40
diff-lib.c
@@ -61,14 +61,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
|
||||
int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
|
||||
unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
|
||||
? CE_MATCH_RACY_IS_DIRTY : 0);
|
||||
char symcache[PATH_MAX];
|
||||
|
||||
diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
|
||||
|
||||
if (diff_unmerged_stage < 0)
|
||||
diff_unmerged_stage = 2;
|
||||
entries = active_nr;
|
||||
symcache[0] = '\0';
|
||||
for (i = 0; i < entries; i++) {
|
||||
struct stat st;
|
||||
unsigned int oldmode, newmode;
|
||||
@@ -198,11 +196,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
|
||||
* diff-index
|
||||
*/
|
||||
|
||||
struct oneway_unpack_data {
|
||||
struct rev_info *revs;
|
||||
char symcache[PATH_MAX];
|
||||
};
|
||||
|
||||
/* A file entry went away or appeared */
|
||||
static void diff_index_show_file(struct rev_info *revs,
|
||||
const char *prefix,
|
||||
@@ -216,8 +209,7 @@ static void diff_index_show_file(struct rev_info *revs,
|
||||
static int get_stat_data(struct cache_entry *ce,
|
||||
const unsigned char **sha1p,
|
||||
unsigned int *modep,
|
||||
int cached, int match_missing,
|
||||
struct oneway_unpack_data *cbdata)
|
||||
int cached, int match_missing)
|
||||
{
|
||||
const unsigned char *sha1 = ce->sha1;
|
||||
unsigned int mode = ce->ce_mode;
|
||||
@@ -248,25 +240,24 @@ static int get_stat_data(struct cache_entry *ce,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_new_file(struct oneway_unpack_data *cbdata,
|
||||
static void show_new_file(struct rev_info *revs,
|
||||
struct cache_entry *new,
|
||||
int cached, int match_missing)
|
||||
{
|
||||
const unsigned char *sha1;
|
||||
unsigned int mode;
|
||||
struct rev_info *revs = cbdata->revs;
|
||||
|
||||
/*
|
||||
* New file in the index: it might actually be different in
|
||||
* the working copy.
|
||||
*/
|
||||
if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0)
|
||||
if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0)
|
||||
return;
|
||||
|
||||
diff_index_show_file(revs, "+", new, sha1, mode);
|
||||
}
|
||||
|
||||
static int show_modified(struct oneway_unpack_data *cbdata,
|
||||
static int show_modified(struct rev_info *revs,
|
||||
struct cache_entry *old,
|
||||
struct cache_entry *new,
|
||||
int report_missing,
|
||||
@@ -274,9 +265,8 @@ static int show_modified(struct oneway_unpack_data *cbdata,
|
||||
{
|
||||
unsigned int mode, oldmode;
|
||||
const unsigned char *sha1;
|
||||
struct rev_info *revs = cbdata->revs;
|
||||
|
||||
if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0) {
|
||||
if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) {
|
||||
if (report_missing)
|
||||
diff_index_show_file(revs, "-", old,
|
||||
old->sha1, old->ce_mode);
|
||||
@@ -344,8 +334,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
|
||||
struct cache_entry *idx,
|
||||
struct cache_entry *tree)
|
||||
{
|
||||
struct oneway_unpack_data *cbdata = o->unpack_data;
|
||||
struct rev_info *revs = cbdata->revs;
|
||||
struct rev_info *revs = o->unpack_data;
|
||||
int match_missing, cached;
|
||||
|
||||
/*
|
||||
@@ -368,7 +357,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
|
||||
* Something added to the tree?
|
||||
*/
|
||||
if (!tree) {
|
||||
show_new_file(cbdata, idx, cached, match_missing);
|
||||
show_new_file(revs, idx, cached, match_missing);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -381,7 +370,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
|
||||
}
|
||||
|
||||
/* Show difference between old and new */
|
||||
show_modified(cbdata, tree, idx, 1, cached, match_missing);
|
||||
show_modified(revs, tree, idx, 1, cached, match_missing);
|
||||
}
|
||||
|
||||
static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
|
||||
@@ -418,8 +407,7 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
|
||||
{
|
||||
struct cache_entry *idx = src[0];
|
||||
struct cache_entry *tree = src[1];
|
||||
struct oneway_unpack_data *cbdata = o->unpack_data;
|
||||
struct rev_info *revs = cbdata->revs;
|
||||
struct rev_info *revs = o->unpack_data;
|
||||
|
||||
if (idx && ce_stage(idx))
|
||||
skip_same_name(idx, o);
|
||||
@@ -446,7 +434,6 @@ int run_diff_index(struct rev_info *revs, int cached)
|
||||
const char *tree_name;
|
||||
struct unpack_trees_options opts;
|
||||
struct tree_desc t;
|
||||
struct oneway_unpack_data unpack_cb;
|
||||
|
||||
mark_merge_entries();
|
||||
|
||||
@@ -456,14 +443,12 @@ int run_diff_index(struct rev_info *revs, int cached)
|
||||
if (!tree)
|
||||
return error("bad tree object %s", tree_name);
|
||||
|
||||
unpack_cb.revs = revs;
|
||||
unpack_cb.symcache[0] = '\0';
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.head_idx = 1;
|
||||
opts.index_only = cached;
|
||||
opts.merge = 1;
|
||||
opts.fn = oneway_diff;
|
||||
opts.unpack_data = &unpack_cb;
|
||||
opts.unpack_data = revs;
|
||||
opts.src_index = &the_index;
|
||||
opts.dst_index = NULL;
|
||||
|
||||
@@ -486,7 +471,6 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
|
||||
struct cache_entry *last = NULL;
|
||||
struct unpack_trees_options opts;
|
||||
struct tree_desc t;
|
||||
struct oneway_unpack_data unpack_cb;
|
||||
|
||||
/*
|
||||
* This is used by git-blame to run diff-cache internally;
|
||||
@@ -515,14 +499,12 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
|
||||
if (!tree)
|
||||
die("bad tree object %s", sha1_to_hex(tree_sha1));
|
||||
|
||||
unpack_cb.revs = &revs;
|
||||
unpack_cb.symcache[0] = '\0';
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.head_idx = 1;
|
||||
opts.index_only = 1;
|
||||
opts.merge = 1;
|
||||
opts.fn = oneway_diff;
|
||||
opts.unpack_data = &unpack_cb;
|
||||
opts.unpack_data = &revs;
|
||||
opts.src_index = &the_index;
|
||||
opts.dst_index = &the_index;
|
||||
|
||||
|
||||
@@ -173,8 +173,10 @@ void diff_no_index(struct rev_info *revs,
|
||||
|
||||
/* Were we asked to do --no-index explicitly? */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--"))
|
||||
return;
|
||||
if (!strcmp(argv[i], "--")) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(argv[i], "--no-index"))
|
||||
no_index = 1;
|
||||
if (argv[i][0] != '-')
|
||||
@@ -198,13 +200,6 @@ void diff_no_index(struct rev_info *revs,
|
||||
die("git diff %s takes two paths",
|
||||
no_index ? "--no-index" : "[--no-index]");
|
||||
|
||||
/*
|
||||
* If the user asked for our exit code then don't start a
|
||||
* pager or we would end up reporting its exit code instead.
|
||||
*/
|
||||
if (!DIFF_OPT_TST(&revs->diffopt, EXIT_WITH_STATUS))
|
||||
setup_pager();
|
||||
|
||||
diff_setup(&revs->diffopt);
|
||||
if (!revs->diffopt.output_format)
|
||||
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
|
||||
@@ -212,8 +207,12 @@ void diff_no_index(struct rev_info *revs,
|
||||
int j;
|
||||
if (!strcmp(argv[i], "--no-index"))
|
||||
i++;
|
||||
else if (!strcmp(argv[1], "-q"))
|
||||
else if (!strcmp(argv[i], "-q")) {
|
||||
options |= DIFF_SILENT_ON_REMOVED;
|
||||
i++;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--"))
|
||||
i++;
|
||||
else {
|
||||
j = diff_opt_parse(&revs->diffopt, argv + i, argc - i);
|
||||
if (!j)
|
||||
@@ -222,6 +221,13 @@ void diff_no_index(struct rev_info *revs,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user asked for our exit code then don't start a
|
||||
* pager or we would end up reporting its exit code instead.
|
||||
*/
|
||||
if (!DIFF_OPT_TST(&revs->diffopt, EXIT_WITH_STATUS))
|
||||
setup_pager();
|
||||
|
||||
if (prefix) {
|
||||
int len = strlen(prefix);
|
||||
|
||||
|
||||
251
diff.c
251
diff.c
@@ -23,6 +23,7 @@ static int diff_detect_rename_default;
|
||||
static int diff_rename_limit_default = 200;
|
||||
static int diff_suppress_blank_empty;
|
||||
int diff_use_color_default = -1;
|
||||
static const char *diff_word_regex_cfg;
|
||||
static const char *external_diff_cmd_cfg;
|
||||
int diff_auto_refresh_index = 1;
|
||||
static int diff_mnemonic_prefix;
|
||||
@@ -92,6 +93,8 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
|
||||
}
|
||||
if (!strcmp(var, "diff.external"))
|
||||
return git_config_string(&external_diff_cmd_cfg, var, value);
|
||||
if (!strcmp(var, "diff.wordregex"))
|
||||
return git_config_string(&diff_word_regex_cfg, var, value);
|
||||
|
||||
return git_diff_basic_config(var, value, cb);
|
||||
}
|
||||
@@ -118,7 +121,9 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
|
||||
}
|
||||
|
||||
/* like GNU diff's --suppress-blank-empty option */
|
||||
if (!strcmp(var, "diff.suppress-blank-empty")) {
|
||||
if (!strcmp(var, "diff.suppressblankempty") ||
|
||||
/* for backwards compatibility */
|
||||
!strcmp(var, "diff.suppress-blank-empty")) {
|
||||
diff_suppress_blank_empty = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
@@ -319,82 +324,138 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
|
||||
struct diff_words_buffer {
|
||||
mmfile_t text;
|
||||
long alloc;
|
||||
long current; /* output pointer */
|
||||
int suppressed_newline;
|
||||
struct diff_words_orig {
|
||||
const char *begin, *end;
|
||||
} *orig;
|
||||
int orig_nr, orig_alloc;
|
||||
};
|
||||
|
||||
static void diff_words_append(char *line, unsigned long len,
|
||||
struct diff_words_buffer *buffer)
|
||||
{
|
||||
if (buffer->text.size + len > buffer->alloc) {
|
||||
buffer->alloc = (buffer->text.size + len) * 3 / 2;
|
||||
buffer->text.ptr = xrealloc(buffer->text.ptr, buffer->alloc);
|
||||
}
|
||||
ALLOC_GROW(buffer->text.ptr, buffer->text.size + len, buffer->alloc);
|
||||
line++;
|
||||
len--;
|
||||
memcpy(buffer->text.ptr + buffer->text.size, line, len);
|
||||
buffer->text.size += len;
|
||||
buffer->text.ptr[buffer->text.size] = '\0';
|
||||
}
|
||||
|
||||
struct diff_words_data {
|
||||
struct diff_words_buffer minus, plus;
|
||||
const char *current_plus;
|
||||
FILE *file;
|
||||
regex_t *word_regex;
|
||||
};
|
||||
|
||||
static void print_word(FILE *file, struct diff_words_buffer *buffer, int len, int color,
|
||||
int suppress_newline)
|
||||
{
|
||||
const char *ptr;
|
||||
int eol = 0;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
ptr = buffer->text.ptr + buffer->current;
|
||||
buffer->current += len;
|
||||
|
||||
if (ptr[len - 1] == '\n') {
|
||||
eol = 1;
|
||||
len--;
|
||||
}
|
||||
|
||||
fputs(diff_get_color(1, color), file);
|
||||
fwrite(ptr, len, 1, file);
|
||||
fputs(diff_get_color(1, DIFF_RESET), file);
|
||||
|
||||
if (eol) {
|
||||
if (suppress_newline)
|
||||
buffer->suppressed_newline = 1;
|
||||
else
|
||||
putc('\n', file);
|
||||
}
|
||||
}
|
||||
|
||||
static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
|
||||
{
|
||||
struct diff_words_data *diff_words = priv;
|
||||
int minus_first, minus_len, plus_first, plus_len;
|
||||
const char *minus_begin, *minus_end, *plus_begin, *plus_end;
|
||||
|
||||
if (diff_words->minus.suppressed_newline) {
|
||||
if (line[0] != '+')
|
||||
putc('\n', diff_words->file);
|
||||
diff_words->minus.suppressed_newline = 0;
|
||||
if (line[0] != '@' || parse_hunk_header(line, len,
|
||||
&minus_first, &minus_len, &plus_first, &plus_len))
|
||||
return;
|
||||
|
||||
/* POSIX requires that first be decremented by one if len == 0... */
|
||||
if (minus_len) {
|
||||
minus_begin = diff_words->minus.orig[minus_first].begin;
|
||||
minus_end =
|
||||
diff_words->minus.orig[minus_first + minus_len - 1].end;
|
||||
} else
|
||||
minus_begin = minus_end =
|
||||
diff_words->minus.orig[minus_first].end;
|
||||
|
||||
if (plus_len) {
|
||||
plus_begin = diff_words->plus.orig[plus_first].begin;
|
||||
plus_end = diff_words->plus.orig[plus_first + plus_len - 1].end;
|
||||
} else
|
||||
plus_begin = plus_end = diff_words->plus.orig[plus_first].end;
|
||||
|
||||
if (diff_words->current_plus != plus_begin)
|
||||
fwrite(diff_words->current_plus,
|
||||
plus_begin - diff_words->current_plus, 1,
|
||||
diff_words->file);
|
||||
if (minus_begin != minus_end)
|
||||
color_fwrite_lines(diff_words->file,
|
||||
diff_get_color(1, DIFF_FILE_OLD),
|
||||
minus_end - minus_begin, minus_begin);
|
||||
if (plus_begin != plus_end)
|
||||
color_fwrite_lines(diff_words->file,
|
||||
diff_get_color(1, DIFF_FILE_NEW),
|
||||
plus_end - plus_begin, plus_begin);
|
||||
|
||||
diff_words->current_plus = plus_end;
|
||||
}
|
||||
|
||||
/* This function starts looking at *begin, and returns 0 iff a word was found. */
|
||||
static int find_word_boundaries(mmfile_t *buffer, regex_t *word_regex,
|
||||
int *begin, int *end)
|
||||
{
|
||||
if (word_regex && *begin < buffer->size) {
|
||||
regmatch_t match[1];
|
||||
if (!regexec(word_regex, buffer->ptr + *begin, 1, match, 0)) {
|
||||
char *p = memchr(buffer->ptr + *begin + match[0].rm_so,
|
||||
'\n', match[0].rm_eo - match[0].rm_so);
|
||||
*end = p ? p - buffer->ptr : match[0].rm_eo + *begin;
|
||||
*begin += match[0].rm_so;
|
||||
return *begin >= *end;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
len--;
|
||||
switch (line[0]) {
|
||||
case '-':
|
||||
print_word(diff_words->file,
|
||||
&diff_words->minus, len, DIFF_FILE_OLD, 1);
|
||||
break;
|
||||
case '+':
|
||||
print_word(diff_words->file,
|
||||
&diff_words->plus, len, DIFF_FILE_NEW, 0);
|
||||
break;
|
||||
case ' ':
|
||||
print_word(diff_words->file,
|
||||
&diff_words->plus, len, DIFF_PLAIN, 0);
|
||||
diff_words->minus.current += len;
|
||||
break;
|
||||
/* find the next word */
|
||||
while (*begin < buffer->size && isspace(buffer->ptr[*begin]))
|
||||
(*begin)++;
|
||||
if (*begin >= buffer->size)
|
||||
return -1;
|
||||
|
||||
/* find the end of the word */
|
||||
*end = *begin + 1;
|
||||
while (*end < buffer->size && !isspace(buffer->ptr[*end]))
|
||||
(*end)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function splits the words in buffer->text, stores the list with
|
||||
* newline separator into out, and saves the offsets of the original words
|
||||
* in buffer->orig.
|
||||
*/
|
||||
static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out,
|
||||
regex_t *word_regex)
|
||||
{
|
||||
int i, j;
|
||||
long alloc = 0;
|
||||
|
||||
out->size = 0;
|
||||
out->ptr = NULL;
|
||||
|
||||
/* fake an empty "0th" word */
|
||||
ALLOC_GROW(buffer->orig, 1, buffer->orig_alloc);
|
||||
buffer->orig[0].begin = buffer->orig[0].end = buffer->text.ptr;
|
||||
buffer->orig_nr = 1;
|
||||
|
||||
for (i = 0; i < buffer->text.size; i++) {
|
||||
if (find_word_boundaries(&buffer->text, word_regex, &i, &j))
|
||||
return;
|
||||
|
||||
/* store original boundaries */
|
||||
ALLOC_GROW(buffer->orig, buffer->orig_nr + 1,
|
||||
buffer->orig_alloc);
|
||||
buffer->orig[buffer->orig_nr].begin = buffer->text.ptr + i;
|
||||
buffer->orig[buffer->orig_nr].end = buffer->text.ptr + j;
|
||||
buffer->orig_nr++;
|
||||
|
||||
/* store one word */
|
||||
ALLOC_GROW(out->ptr, out->size + j - i + 1, alloc);
|
||||
memcpy(out->ptr + out->size, buffer->text.ptr + i, j - i);
|
||||
out->ptr[out->size + j - i] = '\n';
|
||||
out->size += j - i + 1;
|
||||
|
||||
i = j - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,38 +466,36 @@ static void diff_words_show(struct diff_words_data *diff_words)
|
||||
xdemitconf_t xecfg;
|
||||
xdemitcb_t ecb;
|
||||
mmfile_t minus, plus;
|
||||
int i;
|
||||
|
||||
/* special case: only removal */
|
||||
if (!diff_words->plus.text.size) {
|
||||
color_fwrite_lines(diff_words->file,
|
||||
diff_get_color(1, DIFF_FILE_OLD),
|
||||
diff_words->minus.text.size, diff_words->minus.text.ptr);
|
||||
diff_words->minus.text.size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
diff_words->current_plus = diff_words->plus.text.ptr;
|
||||
|
||||
memset(&xpp, 0, sizeof(xpp));
|
||||
memset(&xecfg, 0, sizeof(xecfg));
|
||||
minus.size = diff_words->minus.text.size;
|
||||
minus.ptr = xmalloc(minus.size);
|
||||
memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size);
|
||||
for (i = 0; i < minus.size; i++)
|
||||
if (isspace(minus.ptr[i]))
|
||||
minus.ptr[i] = '\n';
|
||||
diff_words->minus.current = 0;
|
||||
|
||||
plus.size = diff_words->plus.text.size;
|
||||
plus.ptr = xmalloc(plus.size);
|
||||
memcpy(plus.ptr, diff_words->plus.text.ptr, plus.size);
|
||||
for (i = 0; i < plus.size; i++)
|
||||
if (isspace(plus.ptr[i]))
|
||||
plus.ptr[i] = '\n';
|
||||
diff_words->plus.current = 0;
|
||||
|
||||
diff_words_fill(&diff_words->minus, &minus, diff_words->word_regex);
|
||||
diff_words_fill(&diff_words->plus, &plus, diff_words->word_regex);
|
||||
xpp.flags = XDF_NEED_MINIMAL;
|
||||
xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc;
|
||||
/* as only the hunk header will be parsed, we need a 0-context */
|
||||
xecfg.ctxlen = 0;
|
||||
xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
|
||||
&xpp, &xecfg, &ecb);
|
||||
free(minus.ptr);
|
||||
free(plus.ptr);
|
||||
if (diff_words->current_plus != diff_words->plus.text.ptr +
|
||||
diff_words->plus.text.size)
|
||||
fwrite(diff_words->current_plus,
|
||||
diff_words->plus.text.ptr + diff_words->plus.text.size
|
||||
- diff_words->current_plus, 1,
|
||||
diff_words->file);
|
||||
diff_words->minus.text.size = diff_words->plus.text.size = 0;
|
||||
|
||||
if (diff_words->minus.suppressed_newline) {
|
||||
putc('\n', diff_words->file);
|
||||
diff_words->minus.suppressed_newline = 0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
|
||||
@@ -460,7 +519,10 @@ static void free_diff_words_data(struct emit_callback *ecbdata)
|
||||
diff_words_show(ecbdata->diff_words);
|
||||
|
||||
free (ecbdata->diff_words->minus.text.ptr);
|
||||
free (ecbdata->diff_words->minus.orig);
|
||||
free (ecbdata->diff_words->plus.text.ptr);
|
||||
free (ecbdata->diff_words->plus.orig);
|
||||
free(ecbdata->diff_words->word_regex);
|
||||
free(ecbdata->diff_words);
|
||||
ecbdata->diff_words = NULL;
|
||||
}
|
||||
@@ -1323,6 +1385,12 @@ static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespe
|
||||
return one->driver->funcname.pattern ? &one->driver->funcname : NULL;
|
||||
}
|
||||
|
||||
static const char *userdiff_word_regex(struct diff_filespec *one)
|
||||
{
|
||||
diff_filespec_load_driver(one);
|
||||
return one->driver->word_regex;
|
||||
}
|
||||
|
||||
void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b)
|
||||
{
|
||||
if (!options->a_prefix)
|
||||
@@ -1469,6 +1537,7 @@ static void builtin_diff(const char *name_a,
|
||||
ecbdata.file = o->file;
|
||||
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
|
||||
xecfg.ctxlen = o->context;
|
||||
xecfg.interhunkctxlen = o->interhunkcontext;
|
||||
xecfg.flags = XDL_EMIT_FUNCNAMES;
|
||||
if (pe)
|
||||
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
|
||||
@@ -1482,6 +1551,21 @@ static void builtin_diff(const char *name_a,
|
||||
ecbdata.diff_words =
|
||||
xcalloc(1, sizeof(struct diff_words_data));
|
||||
ecbdata.diff_words->file = o->file;
|
||||
if (!o->word_regex)
|
||||
o->word_regex = userdiff_word_regex(one);
|
||||
if (!o->word_regex)
|
||||
o->word_regex = userdiff_word_regex(two);
|
||||
if (!o->word_regex)
|
||||
o->word_regex = diff_word_regex_cfg;
|
||||
if (o->word_regex) {
|
||||
ecbdata.diff_words->word_regex = (regex_t *)
|
||||
xmalloc(sizeof(regex_t));
|
||||
if (regcomp(ecbdata.diff_words->word_regex,
|
||||
o->word_regex,
|
||||
REG_EXTENDED | REG_NEWLINE))
|
||||
die ("Invalid regular expression: %s",
|
||||
o->word_regex);
|
||||
}
|
||||
}
|
||||
xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
|
||||
&xpp, &xecfg, &ecb);
|
||||
@@ -2039,7 +2123,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
|
||||
if (lstat(one->path, &st) < 0)
|
||||
die("stat %s", one->path);
|
||||
if (index_path(one->sha1, one->path, &st, 0))
|
||||
die("cannot hash %s\n", one->path);
|
||||
die("cannot hash %s", one->path);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2471,6 +2555,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||
options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
|
||||
else if (!strcmp(arg, "--ignore-space-at-eol"))
|
||||
options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
|
||||
else if (!strcmp(arg, "--patience"))
|
||||
options->xdl_opts |= XDF_PATIENCE_DIFF;
|
||||
|
||||
/* flags options */
|
||||
else if (!strcmp(arg, "--binary")) {
|
||||
@@ -2493,6 +2579,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||
DIFF_OPT_CLR(options, COLOR_DIFF);
|
||||
else if (!strcmp(arg, "--color-words"))
|
||||
options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS;
|
||||
else if (!prefixcmp(arg, "--color-words=")) {
|
||||
options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS;
|
||||
options->word_regex = arg + 14;
|
||||
}
|
||||
else if (!strcmp(arg, "--exit-code"))
|
||||
DIFF_OPT_SET(options, EXIT_WITH_STATUS);
|
||||
else if (!strcmp(arg, "--quiet"))
|
||||
@@ -2538,6 +2628,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||
options->b_prefix = arg + 13;
|
||||
else if (!strcmp(arg, "--no-prefix"))
|
||||
options->a_prefix = options->b_prefix = "";
|
||||
else if (opt_arg(arg, '\0', "inter-hunk-context",
|
||||
&options->interhunkcontext))
|
||||
;
|
||||
else if (!prefixcmp(arg, "--output=")) {
|
||||
options->file = fopen(arg + strlen("--output="), "w");
|
||||
options->close_file = 1;
|
||||
|
||||
2
diff.h
2
diff.h
@@ -78,6 +78,7 @@ struct diff_options {
|
||||
const char *a_prefix, *b_prefix;
|
||||
unsigned flags;
|
||||
int context;
|
||||
int interhunkcontext;
|
||||
int break_opt;
|
||||
int detect_rename;
|
||||
int skip_stat_unmatch;
|
||||
@@ -97,6 +98,7 @@ struct diff_options {
|
||||
|
||||
int stat_width;
|
||||
int stat_name_width;
|
||||
const char *word_regex;
|
||||
|
||||
/* this is set by diffcore for DIFF_FORMAT_PATCH */
|
||||
int found_changes;
|
||||
|
||||
@@ -153,9 +153,9 @@ static int estimate_similarity(struct diff_filespec *src,
|
||||
* is a possible size - we really should have a flag to
|
||||
* say whether the size is valid or not!)
|
||||
*/
|
||||
if (!src->cnt_data && diff_populate_filespec(src, 0))
|
||||
if (!src->cnt_data && diff_populate_filespec(src, 1))
|
||||
return 0;
|
||||
if (!dst->cnt_data && diff_populate_filespec(dst, 0))
|
||||
if (!dst->cnt_data && diff_populate_filespec(dst, 1))
|
||||
return 0;
|
||||
|
||||
max_size = ((src->size > dst->size) ? src->size : dst->size);
|
||||
@@ -173,6 +173,11 @@ static int estimate_similarity(struct diff_filespec *src,
|
||||
if (base_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
|
||||
return 0;
|
||||
|
||||
if (!src->cnt_data && diff_populate_filespec(src, 0))
|
||||
return 0;
|
||||
if (!dst->cnt_data && diff_populate_filespec(dst, 0))
|
||||
return 0;
|
||||
|
||||
delta_limit = (unsigned long)
|
||||
(base_size * (MAX_SCORE-minimum_score) / MAX_SCORE);
|
||||
if (diffcore_count_changes(src, dst,
|
||||
|
||||
54
dir.c
54
dir.c
@@ -75,7 +75,7 @@ static int match_one(const char *match, const char *name, int namelen)
|
||||
for (;;) {
|
||||
unsigned char c1 = *match;
|
||||
unsigned char c2 = *name;
|
||||
if (isspecial(c1))
|
||||
if (c1 == '\0' || is_glob_special(c1))
|
||||
break;
|
||||
if (c1 != c2)
|
||||
return 0;
|
||||
@@ -108,25 +108,28 @@ static int match_one(const char *match, const char *name, int namelen)
|
||||
* and a mark is left in seen[] array for pathspec element that
|
||||
* actually matched anything.
|
||||
*/
|
||||
int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen)
|
||||
int match_pathspec(const char **pathspec, const char *name, int namelen,
|
||||
int prefix, char *seen)
|
||||
{
|
||||
int retval;
|
||||
const char *match;
|
||||
int i, retval = 0;
|
||||
|
||||
if (!pathspec)
|
||||
return 1;
|
||||
|
||||
name += prefix;
|
||||
namelen -= prefix;
|
||||
|
||||
for (retval = 0; (match = *pathspec++) != NULL; seen++) {
|
||||
for (i = 0; pathspec[i] != NULL; i++) {
|
||||
int how;
|
||||
if (retval && *seen == MATCHED_EXACTLY)
|
||||
const char *match = pathspec[i] + prefix;
|
||||
if (seen && seen[i] == MATCHED_EXACTLY)
|
||||
continue;
|
||||
match += prefix;
|
||||
how = match_one(match, name, namelen);
|
||||
if (how) {
|
||||
if (retval < how)
|
||||
retval = how;
|
||||
if (*seen < how)
|
||||
*seen = how;
|
||||
if (seen && seen[i] < how)
|
||||
seen[i] = how;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
@@ -585,10 +588,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
|
||||
int len, dtype;
|
||||
int exclude;
|
||||
|
||||
if ((de->d_name[0] == '.') &&
|
||||
(de->d_name[1] == 0 ||
|
||||
!strcmp(de->d_name + 1, ".") ||
|
||||
!strcmp(de->d_name + 1, "git")))
|
||||
if (is_dot_or_dotdot(de->d_name) ||
|
||||
!strcmp(de->d_name, ".git"))
|
||||
continue;
|
||||
len = strlen(de->d_name);
|
||||
/* Ignore overly long pathnames! */
|
||||
@@ -680,7 +681,7 @@ static int simple_length(const char *match)
|
||||
for (;;) {
|
||||
unsigned char c = *match++;
|
||||
len++;
|
||||
if (isspecial(c))
|
||||
if (c == '\0' || is_glob_special(c))
|
||||
return len;
|
||||
}
|
||||
}
|
||||
@@ -779,6 +780,25 @@ int is_inside_dir(const char *dir)
|
||||
return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
|
||||
}
|
||||
|
||||
int is_empty_dir(const char *path)
|
||||
{
|
||||
DIR *dir = opendir(path);
|
||||
struct dirent *e;
|
||||
int ret = 1;
|
||||
|
||||
if (!dir)
|
||||
return 0;
|
||||
|
||||
while ((e = readdir(dir)) != NULL)
|
||||
if (!is_dot_or_dotdot(e->d_name)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int remove_dir_recursively(struct strbuf *path, int only_empty)
|
||||
{
|
||||
DIR *dir = opendir(path->buf);
|
||||
@@ -793,10 +813,8 @@ int remove_dir_recursively(struct strbuf *path, int only_empty)
|
||||
len = path->len;
|
||||
while ((e = readdir(dir)) != NULL) {
|
||||
struct stat st;
|
||||
if ((e->d_name[0] == '.') &&
|
||||
((e->d_name[1] == 0) ||
|
||||
((e->d_name[1] == '.') && e->d_name[2] == 0)))
|
||||
continue; /* "." and ".." */
|
||||
if (is_dot_or_dotdot(e->d_name))
|
||||
continue;
|
||||
|
||||
strbuf_setlen(path, len);
|
||||
strbuf_addstr(path, e->d_name);
|
||||
|
||||
9
dir.h
9
dir.h
@@ -77,6 +77,15 @@ extern int file_exists(const char *);
|
||||
extern char *get_relative_cwd(char *buffer, int size, const char *dir);
|
||||
extern int is_inside_dir(const char *dir);
|
||||
|
||||
static inline int is_dot_or_dotdot(const char *name)
|
||||
{
|
||||
return (name[0] == '.' &&
|
||||
(name[1] == '\0' ||
|
||||
(name[1] == '.' && name[2] == '\0')));
|
||||
}
|
||||
|
||||
extern int is_empty_dir(const char *dir);
|
||||
|
||||
extern void setup_standard_excludes(struct dir_struct *dir);
|
||||
extern int remove_dir_recursively(struct strbuf *path, int only_empty);
|
||||
|
||||
|
||||
39
entry.c
39
entry.c
@@ -1,5 +1,6 @@
|
||||
#include "cache.h"
|
||||
#include "blob.h"
|
||||
#include "dir.h"
|
||||
|
||||
static void create_directories(const char *path, const struct checkout *state)
|
||||
{
|
||||
@@ -8,35 +9,25 @@ static void create_directories(const char *path, const struct checkout *state)
|
||||
const char *slash = path;
|
||||
|
||||
while ((slash = strchr(slash+1, '/')) != NULL) {
|
||||
struct stat st;
|
||||
int stat_status;
|
||||
|
||||
len = slash - path;
|
||||
memcpy(buf, path, len);
|
||||
buf[len] = 0;
|
||||
|
||||
if (len <= state->base_dir_len)
|
||||
/*
|
||||
* checkout-index --prefix=<dir>; <dir> is
|
||||
* allowed to be a symlink to an existing
|
||||
* directory.
|
||||
*/
|
||||
stat_status = stat(buf, &st);
|
||||
else
|
||||
/*
|
||||
* if there currently is a symlink, we would
|
||||
* want to replace it with a real directory.
|
||||
*/
|
||||
stat_status = lstat(buf, &st);
|
||||
|
||||
if (!stat_status && S_ISDIR(st.st_mode))
|
||||
/*
|
||||
* For 'checkout-index --prefix=<dir>', <dir> is
|
||||
* allowed to be a symlink to an existing directory,
|
||||
* and we set 'state->base_dir_len' below, such that
|
||||
* we test the path components of the prefix with the
|
||||
* stat() function instead of the lstat() function.
|
||||
*/
|
||||
if (has_dirs_only_path(len, buf, state->base_dir_len))
|
||||
continue; /* ok, it is already a directory. */
|
||||
|
||||
/*
|
||||
* We know stat_status == 0 means something exists
|
||||
* there and this mkdir would fail, but that is an
|
||||
* error codepath; we do not care, as we unlink and
|
||||
* mkdir again in such a case.
|
||||
* If this mkdir() would fail, it could be that there
|
||||
* is already a symlink or something else exists
|
||||
* there, therefore we then try to unlink it and try
|
||||
* one more time to create the directory.
|
||||
*/
|
||||
if (mkdir(buf, 0777)) {
|
||||
if (errno == EEXIST && state->force &&
|
||||
@@ -62,9 +53,7 @@ static void remove_subtree(const char *path)
|
||||
*name++ = '/';
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
struct stat st;
|
||||
if ((de->d_name[0] == '.') &&
|
||||
((de->d_name[1] == 0) ||
|
||||
((de->d_name[1] == '.') && de->d_name[2] == 0)))
|
||||
if (is_dot_or_dotdot(de->d_name))
|
||||
continue;
|
||||
strcpy(name, de->d_name);
|
||||
if (lstat(pathbuf, &st))
|
||||
|
||||
22
exec_cmd.c
22
exec_cmd.c
@@ -9,11 +9,15 @@ static const char *argv0_path;
|
||||
|
||||
const char *system_path(const char *path)
|
||||
{
|
||||
#ifdef RUNTIME_PREFIX
|
||||
static const char *prefix;
|
||||
#else
|
||||
static const char *prefix = PREFIX;
|
||||
#endif
|
||||
struct strbuf d = STRBUF_INIT;
|
||||
|
||||
if (is_absolute_path(path)) {
|
||||
if (is_absolute_path(path))
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifdef RUNTIME_PREFIX
|
||||
assert(argv0_path);
|
||||
@@ -53,11 +57,8 @@ const char *system_path(const char *path)
|
||||
"but prefix computation failed. "
|
||||
"Using static fallback '%s'.\n", prefix);
|
||||
}
|
||||
#else
|
||||
prefix = PREFIX;
|
||||
#endif
|
||||
|
||||
struct strbuf d = STRBUF_INIT;
|
||||
strbuf_addf(&d, "%s/%s", prefix, path);
|
||||
path = strbuf_detach(&d, NULL);
|
||||
return path;
|
||||
@@ -65,11 +66,14 @@ const char *system_path(const char *path)
|
||||
|
||||
const char *git_extract_argv0_path(const char *argv0)
|
||||
{
|
||||
const char *slash = argv0 + strlen(argv0);
|
||||
const char *slash;
|
||||
|
||||
do
|
||||
--slash;
|
||||
while (slash >= argv0 && !is_dir_sep(*slash));
|
||||
if (!argv0 || !*argv0)
|
||||
return NULL;
|
||||
slash = argv0 + strlen(argv0);
|
||||
|
||||
while (argv0 <= slash && !is_dir_sep(*slash))
|
||||
slash--;
|
||||
|
||||
if (slash >= argv0) {
|
||||
argv0_path = xstrndup(argv0, slash - argv0);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define GIT_EXEC_CMD_H
|
||||
|
||||
extern void git_set_argv_exec_path(const char *exec_path);
|
||||
extern const char* git_extract_argv0_path(const char *path);
|
||||
extern const char* git_exec_path(void);
|
||||
extern const char *git_extract_argv0_path(const char *path);
|
||||
extern const char *git_exec_path(void);
|
||||
extern void setup_path(void);
|
||||
extern const char **prepare_git_cmd(const char **argv);
|
||||
extern int execv_git_cmd(const char **argv); /* NULL terminated */
|
||||
|
||||
@@ -1873,12 +1873,13 @@ static void file_change_m(struct branch *b)
|
||||
if (!p)
|
||||
die("Corrupt mode: %s", command_buf.buf);
|
||||
switch (mode) {
|
||||
case 0644:
|
||||
case 0755:
|
||||
mode |= S_IFREG;
|
||||
case S_IFREG | 0644:
|
||||
case S_IFREG | 0755:
|
||||
case S_IFLNK:
|
||||
case S_IFGITLINK:
|
||||
case 0644:
|
||||
case 0755:
|
||||
/* ok */
|
||||
break;
|
||||
default:
|
||||
@@ -1945,7 +1946,7 @@ static void file_change_m(struct branch *b)
|
||||
typename(type), command_buf.buf);
|
||||
}
|
||||
|
||||
tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode, NULL);
|
||||
tree_content_set(&b->branch_tree, p, sha1, mode, NULL);
|
||||
}
|
||||
|
||||
static void file_change_d(struct branch *b)
|
||||
@@ -2406,8 +2407,7 @@ int main(int argc, const char **argv)
|
||||
{
|
||||
unsigned int i, show_stats = 1;
|
||||
|
||||
if (argv[0] && *argv[0])
|
||||
git_extract_argv0_path(argv[0]);
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
setup_git_directory();
|
||||
git_config(git_pack_config, NULL);
|
||||
|
||||
@@ -800,6 +800,7 @@ y - stage this hunk
|
||||
n - do not stage this hunk
|
||||
a - stage this and all the remaining hunks in the file
|
||||
d - do not stage this hunk nor any of the remaining hunks in the file
|
||||
g - select a hunk to go to
|
||||
j - leave this hunk undecided, see next undecided hunk
|
||||
J - leave this hunk undecided, see next hunk
|
||||
k - leave this hunk undecided, see previous undecided hunk
|
||||
@@ -836,6 +837,47 @@ sub patch_update_cmd {
|
||||
}
|
||||
}
|
||||
|
||||
# Generate a one line summary of a hunk.
|
||||
sub summarize_hunk {
|
||||
my $rhunk = shift;
|
||||
my $summary = $rhunk->{TEXT}[0];
|
||||
|
||||
# Keep the line numbers, discard extra context.
|
||||
$summary =~ s/@@(.*?)@@.*/$1 /s;
|
||||
$summary .= " " x (20 - length $summary);
|
||||
|
||||
# Add some user context.
|
||||
for my $line (@{$rhunk->{TEXT}}) {
|
||||
if ($line =~ m/^[+-].*\w/) {
|
||||
$summary .= $line;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
chomp $summary;
|
||||
return substr($summary, 0, 80) . "\n";
|
||||
}
|
||||
|
||||
|
||||
# Print a one-line summary of each hunk in the array ref in
|
||||
# the first argument, starting wih the index in the 2nd.
|
||||
sub display_hunks {
|
||||
my ($hunks, $i) = @_;
|
||||
my $ctr = 0;
|
||||
$i ||= 0;
|
||||
for (; $i < @$hunks && $ctr < 20; $i++, $ctr++) {
|
||||
my $status = " ";
|
||||
if (defined $hunks->[$i]{USE}) {
|
||||
$status = $hunks->[$i]{USE} ? "+" : "-";
|
||||
}
|
||||
printf "%s%2d: %s",
|
||||
$status,
|
||||
$i + 1,
|
||||
summarize_hunk($hunks->[$i]);
|
||||
}
|
||||
return $i;
|
||||
}
|
||||
|
||||
sub patch_update_file {
|
||||
my ($ix, $num);
|
||||
my $path = shift;
|
||||
@@ -904,6 +946,9 @@ sub patch_update_file {
|
||||
if ($ix < $num - 1) {
|
||||
$other .= '/J';
|
||||
}
|
||||
if ($num > 1) {
|
||||
$other .= '/g';
|
||||
}
|
||||
for ($i = 0; $i < $num; $i++) {
|
||||
if (!defined $hunk[$i]{USE}) {
|
||||
$undecided = 1;
|
||||
@@ -937,6 +982,28 @@ sub patch_update_file {
|
||||
}
|
||||
next;
|
||||
}
|
||||
elsif ($other =~ /g/ && $line =~ /^g(.*)/) {
|
||||
my $response = $1;
|
||||
my $no = $ix > 10 ? $ix - 10 : 0;
|
||||
while ($response eq '') {
|
||||
my $extra = "";
|
||||
$no = display_hunks(\@hunk, $no);
|
||||
if ($no < $num) {
|
||||
$extra = " (<ret> to see more)";
|
||||
}
|
||||
print "go to which hunk$extra? ";
|
||||
$response = <STDIN>;
|
||||
chomp $response;
|
||||
}
|
||||
if ($response !~ /^\s*\d+\s*$/) {
|
||||
print STDERR "Invalid number: '$response'\n";
|
||||
} elsif (0 < $response && $response <= $num) {
|
||||
$ix = $response - 1;
|
||||
} else {
|
||||
print STDERR "Sorry, only $num hunks available.\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^d/i) {
|
||||
while ($ix < $num) {
|
||||
if (!defined $hunk[$ix]{USE}) {
|
||||
|
||||
22
git-am.sh
22
git-am.sh
@@ -16,8 +16,10 @@ s,signoff add a Signed-off-by line to the commit message
|
||||
u,utf8 recode into utf8 (default)
|
||||
k,keep pass -k flag to git-mailinfo
|
||||
whitespace= pass it through git-apply
|
||||
directory= pass it through git-apply
|
||||
C= pass it through git-apply
|
||||
p= pass it through git-apply
|
||||
reject pass it through git-apply
|
||||
resolvemsg= override error message when patch failure occurs
|
||||
r,resolved to be used after a patch failure
|
||||
skip skip the current patch
|
||||
@@ -33,6 +35,14 @@ cd_to_toplevel
|
||||
git var GIT_COMMITTER_IDENT >/dev/null ||
|
||||
die "You need to set your committer info first"
|
||||
|
||||
sq () {
|
||||
for sqarg
|
||||
do
|
||||
printf "%s" "$sqarg" |
|
||||
sed -e 's/'\''/'\''\\'\'''\''/g' -e 's/.*/ '\''&'\''/'
|
||||
done
|
||||
}
|
||||
|
||||
stop_here () {
|
||||
echo "$1" >"$dotest/next"
|
||||
exit 1
|
||||
@@ -155,10 +165,12 @@ do
|
||||
;;
|
||||
--resolvemsg)
|
||||
shift; resolvemsg=$1 ;;
|
||||
--whitespace)
|
||||
git_apply_opt="$git_apply_opt $1=$2"; shift ;;
|
||||
--whitespace|--directory)
|
||||
git_apply_opt="$git_apply_opt $(sq "$1=$2")"; shift ;;
|
||||
-C|-p)
|
||||
git_apply_opt="$git_apply_opt $1$2"; shift ;;
|
||||
git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;;
|
||||
--reject)
|
||||
git_apply_opt="$git_apply_opt $1" ;;
|
||||
--)
|
||||
shift; break ;;
|
||||
*)
|
||||
@@ -459,7 +471,7 @@ do
|
||||
|
||||
case "$resolved" in
|
||||
'')
|
||||
git apply $git_apply_opt --index "$dotest/patch"
|
||||
eval 'git apply '"$git_apply_opt"' --index "$dotest/patch"'
|
||||
apply_status=$?
|
||||
;;
|
||||
t)
|
||||
@@ -501,7 +513,7 @@ do
|
||||
fi
|
||||
if test $apply_status != 0
|
||||
then
|
||||
echo Patch failed at $msgnum.
|
||||
printf 'Patch failed at %s %s\n' "$msgnum" "$FIRSTLINE"
|
||||
stop_here_user_resolve $this
|
||||
fi
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user