Merge commit 'j6t/master' into devel

Conflicts:
	Makefile
	compat/mingw.c
	compat/win32mmap.c
	t/t1301-shared-repo.sh
	t/t4020-diff-external.sh
	t/t4129-apply-samemode.sh
	t/t7005-editor.sh
	t/test-lib.sh

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin
2009-04-07 17:39:50 +02:00
231 changed files with 5490 additions and 3066 deletions

View File

@@ -129,3 +129,6 @@ For C programs:
used in the git core command set (unless your command is clearly
separate from it, such as an importer to convert random-scm-X
repositories to git).
- When we pass <string, length> pair to functions, we should try to
pass them in that order.

View File

@@ -41,7 +41,8 @@ man7dir=$(mandir)/man7
ASCIIDOC=asciidoc
ASCIIDOC_EXTRA =
MANPAGE_XSL = callouts.xsl
MANPAGE_XSL = manpage-normal.xsl
XMLTO_EXTRA =
INSTALL?=install
RM ?= rm -f
DOC_REF = origin/man
@@ -59,12 +60,47 @@ endif
-include ../config.mak.autogen
-include ../config.mak
#
# For asciidoc ...
# -7.1.2, no extra settings are needed.
# 8.0-, set ASCIIDOC8.
#
#
# For docbook-xsl ...
# -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0)
# 1.69.0, no extra settings are needed?
# 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP?
# 1.71.1, no extra settings are needed?
# 1.72.0, set DOCBOOK_XSL_172.
# 1.73.0-, set ASCIIDOC_NO_ROFF
#
#
# If you had been using DOCBOOK_XSL_172 in an attempt to get rid
# of 'the ".ft C" problem' in your generated manpages, and you
# instead ended up with weird characters around callouts, try
# using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8).
#
ifdef ASCIIDOC8
ASCIIDOC_EXTRA += -a asciidoc7compatible
endif
ifdef DOCBOOK_XSL_172
ASCIIDOC_EXTRA += -a docbook-xsl-172
ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
MANPAGE_XSL = manpage-1.72.xsl
else
ifdef ASCIIDOC_NO_ROFF
# docbook-xsl after 1.72 needs the regular XSL, but will not
# pass-thru raw roff codes from asciidoc.conf, so turn them off.
ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
endif
endif
ifdef MAN_BOLD_LITERAL
XMLTO_EXTRA += -m manpage-bold-literal.xsl
endif
ifdef DOCBOOK_SUPPRESS_SP
XMLTO_EXTRA += -m manpage-suppress-sp.xsl
endif
#
@@ -76,6 +112,32 @@ endif
# yourself - yes, all 6 characters of it!
#
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
QUIET_SUBDIR1 =
ifneq ($(findstring $(MAKEFLAGS),w),w)
PRINT_DIR = --no-print-directory
else # "make -w"
NO_SUBDIR = :
endif
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@;
QUIET_XMLTO = @echo ' ' XMLTO $@;
QUIET_DB2TEXI = @echo ' ' DB2TEXI $@;
QUIET_MAKEINFO = @echo ' ' MAKEINFO $@;
QUIET_DBLATEX = @echo ' ' DBLATEX $@;
QUIET_XSLTPROC = @echo ' ' XSLTPROC $@;
QUIET_GEN = @echo ' ' GEN $@;
QUIET_STDERR = 2> /dev/null
QUIET_SUBDIR0 = +@subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
$(MAKE) $(PRINT_DIR) -C $$subdir
export V
endif
endif
all: html man
html: $(DOC_HTML)
@@ -119,7 +181,7 @@ install-html: html
sh ./install-webdoc.sh $(DESTDIR)$(htmldir)
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
$(MAKE) -C ../ GIT-VERSION-FILE
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
-include ../GIT-VERSION-FILE
@@ -127,8 +189,8 @@ install-html: html
# Determine "include::" file references in asciidoc files.
#
doc.dep : $(wildcard *.txt) build-docdep.perl
$(RM) $@+ $@
$(PERL_PATH) ./build-docdep.perl >$@+
$(QUIET_GEN)$(RM) $@+ $@ && \
$(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
mv $@+ $@
-include doc.dep
@@ -146,91 +208,94 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
$(cmds_txt): cmd-list.made
cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
$(RM) $@
$(PERL_PATH) ./cmd-list.perl ../command-list.txt
$(QUIET_GEN)$(RM) $@ && \
$(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
date >$@
clean:
$(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
$(RM) *.texi *.texi+ git.info gitman.info
$(RM) *.texi *.texi+ *.texi++ git.info gitman.info
$(RM) howto-index.txt howto/*.html doc.dep
$(RM) technical/api-*.html technical/api-index.txt
$(RM) $(cmds_txt) *.made
$(MAN_HTML): %.html : %.txt
$(RM) $@+ $@
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
mv $@+ $@
%.1 %.5 %.7 : %.xml
$(RM) $@
xmlto -m $(MANPAGE_XSL) man $<
$(QUIET_XMLTO)$(RM) $@ && \
xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
%.xml : %.txt
$(RM) $@+ $@
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
mv $@+ $@
user-manual.xml: user-manual.txt user-manual.conf
$(ASCIIDOC) -b docbook -d book $<
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b docbook -d book $<
technical/api-index.txt: technical/api-index-skel.txt \
technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS))
cd technical && sh ./api-index.sh
$(QUIET_GEN)cd technical && sh ./api-index.sh
$(patsubst %,%.html,$(API_DOCS) technical/api-index): %.html : %.txt
$(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) $*.txt
XSLT = docbook.xsl
XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
user-manual.html: user-manual.xml
xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
$(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
git.info: user-manual.texi
$(MAKEINFO) --no-split -o $@ user-manual.texi
$(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi
user-manual.texi: user-manual.xml
$(RM) $@+ $@
$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \
$(PERL_PATH) fix-texi.perl >$@+
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \
$(PERL_PATH) fix-texi.perl <$@++ >$@+ && \
rm $@++ && \
mv $@+ $@
user-manual.pdf: user-manual.xml
$(RM) $@+ $@
$(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $<
$(QUIET_DBLATEX)$(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) $@+ $@
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
--to-stdout $(xml);)) | $(PERL_PATH) cat-texi.perl $@ >$@+
--to-stdout $(xml) &&) true) > $@++ && \
$(PERL_PATH) cat-texi.perl $@ <$@++ >$@+ && \
rm $@++ && \
mv $@+ $@
gitman.info: gitman.texi
$(MAKEINFO) --no-split --no-validate $*.texi
$(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi
$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
$(RM) $@+ $@
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \
mv $@+ $@
howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
$(RM) $@+ $@
sh ./howto-index.sh $(wildcard howto/*.txt) >$@+
$(QUIET_GEN)$(RM) $@+ $@ && \
sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \
mv $@+ $@
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
$(ASCIIDOC) -b xhtml11 $*.txt
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 $*.txt
WEBDOC_DEST = /pub/software/scm/git/docs
$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
$(RM) $@+ $@
sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \
mv $@+ $@
install-webdoc : html

View File

@@ -0,0 +1,45 @@
GIT v1.6.2.2 Release Notes
==========================
Fixes since v1.6.2.1
--------------------
* A longstanding confusing description of what --pickaxe option of
git-diff does has been clarified in the documentation.
* "git-blame -S" did not quite work near the commits that were given
on the command line correctly.
* "git diff --pickaxe-regexp" did not count overlapping matches
correctly.
* "git diff" did not feed files in work-tree representation to external
diff and textconv.
* "git-fetch" in a repository that was not cloned from anywhere said
it cannot find 'origin', which was hard to understand for new people.
* "git-format-patch --numbered-files --stdout" did not have to die of
incompatible options; it now simply ignores --numbered-files as no files
are produced anyway.
* "git-ls-files --deleted" did not work well with GIT_DIR&GIT_WORK_TREE.
* "git-read-tree A B C..." without -m option has been broken for a long
time.
* git-send-email ignored --in-reply-to when --no-thread was given.
* 'git-submodule add' did not tolerate extra slashes and ./ in the path it
accepted from the command line; it now is more lenient.
* git-svn misbehaved when the project contained a path that began with
two dashes.
* import-zips script (in contrib) did not compute the common directory
prefix correctly.
* miscompilation of negated enum constants by old gcc (2.9) affected the
codepaths to spawn subprocesses.
Many small documentation updates are included as well.

View File

@@ -22,6 +22,13 @@ branch pointed at by its HEAD, gets a large warning. You can choose what
should happen upon such a push by setting the configuration variable
receive.denyDeleteCurrent in the receiving repository.
When the user does not tell "git push" what to push, it has always
pushed matching refs. For some people it is unexpected, and a new
configuration variable push.default has been introduced to allow
changing a different default behaviour. To advertise the new feature,
a big warning is issued if this is not configured and a git push without
arguments is attempted.
Updates since v1.6.2
--------------------
@@ -30,8 +37,21 @@ Updates since v1.6.2
(performance)
* many uses of lstat(2) in the codepath for "git checkout" have been
optimized out.
(usability, bells and whistles)
* rsync:/path/to/repo can be used to run git over rsync for local
repositories. It may not be useful in practice; meant primarily for
testing.
* http transport learned to prompt and use password when fetching from or
pushing to http://user@host.xz/ URL.
* (msysgit) progress output that is sent over the sideband protocol can
be handled appropriately in Windows console.
* "--pretty=<style>" option to the log family of commands can now be
spelled as "--format=<style>". In addition, --format=%formatstring
is a short-hand for --pretty=tformat:%formatstring.
@@ -42,6 +62,10 @@ Updates since v1.6.2
with the 'edit' action in git-add -i/-p, you can abort the editor to
tell git not to apply it.
* The number of commits shown in "you are ahead/behind your upstream"
messages given by "git checkout" and "git status" used to count merge
commits; now it doesn't.
* git-archive learned --output=<file> option.
* git-bisect shows not just the number of remaining commits whose goodness
@@ -57,11 +81,19 @@ Updates since v1.6.2
* git-clone runs post-checkout hook when run without --no-checkout.
* git-fast-export choked when seeing a tag that does not point at commit.
* git-format-patch can be told to use attachment with a new configuration,
format.attach.
* git-format-patch can be told to produce deep or shallow message threads.
* git-format-patch learned format.headers configuration to add extra
header fields to the output. This behaviour is similar to the existing
--add-header=<header> option of the command.
* git-grep learned to highlight the found substrings in color.
* git-imap-send learned to work around Thunderbird's inability to easily
disable format=flowed with a new configuration, imap.preformattedHTML.
@@ -71,6 +103,13 @@ Updates since v1.6.2
* git-rebase can be told to report diffstat with the --stat option.
* Output from git-remote command has been vastly improved.
* git-repack (invoked from git-gc) did not work as nicely as it should in
a repository that borrows objects from neighbours via alternates
mechanism especially when some packs are marked with the ".keep" flag
to prevent them from being repacked.
* git-send-email learned --confirm option to review the Cc: list before
sending the messages out.
@@ -78,9 +117,18 @@ Updates since v1.6.2
* Test scripts can be run under valgrind.
* Test scripts can be run with installed git.
* Makefile learned 'coverage' option to run the test suites with
coverage tracking enabled.
* Building the manpages with docbook-xsl between 1.69.1 and 1.71.1 now
requires setting DOCBOOK_SUPPRESS_SP to work around a docbook-xsl bug.
This workaround used to be enabled by default, but causes problems
with newer versions of docbook-xsl. In addition, there are a few more
knobs you can tweak to work around issues with various versions of the
docbook-xsl package. See comments in Documentation/Makefile for details.
Fixes since v1.6.2
------------------
@@ -90,15 +138,14 @@ release, unless otherwise noted.
Here are fixes that this release has, but have not been backported to
v1.6.2.X series.
* 'git-submodule add' did not tolerate extra slashes and ./ in the
path it accepted from the command line; it now is more lenient
(if needed, backport by merging db75ada).
* The initial checkout did not read the attributes from the .gitattribute
file that is being checked out.
* git-gc spent excessive amount of time to decide if an object appears
in a locally existing pack (if needed, backport by merging 69e020a).
---
exec >/var/tmp/1
O=v1.6.2.1-135-g7d65c21
O=v1.6.2.2-403-g8130949
echo O=$(git describe master)
git shortlog --no-merges $O..master ^maint

View File

@@ -27,7 +27,7 @@ ifdef::backend-docbook[]
endif::backend-docbook[]
ifdef::backend-docbook[]
ifndef::docbook-xsl-172[]
ifndef::git-asciidoc-no-roff[]
# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
# v1.72 breaks with this because it replaces dots not in roff requests.
[listingblock]
@@ -42,16 +42,16 @@ ifdef::doctype-manpage[]
endif::doctype-manpage[]
</literallayout>
{title#}</example>
endif::docbook-xsl-172[]
endif::git-asciidoc-no-roff[]
ifdef::docbook-xsl-172[]
ifdef::git-asciidoc-no-roff[]
ifdef::doctype-manpage[]
# The following two small workarounds insert a simple paragraph after screen
[listingblock]
<example><title>{title}</title>
<screen>
<literallayout>
|
</screen><simpara></simpara>
</literallayout><simpara></simpara>
{title#}</example>
[verseblock]
@@ -59,10 +59,11 @@ ifdef::doctype-manpage[]
{title%}<literallayout{id? id="{id}"}>
{title#}<literallayout>
|
</literallayout><simpara></simpara>
</literallayout>
{title#}</para></formalpara>
{title%}<simpara></simpara>
endif::doctype-manpage[]
endif::docbook-xsl-172[]
endif::git-asciidoc-no-roff[]
endif::backend-docbook[]
ifdef::doctype-manpage[]

View File

@@ -39,7 +39,7 @@ of lines before or after the line given by <start>.
Show raw timestamp (Default: off).
-S <revs-file>::
Use revs from revs-file instead of calling linkgit:git-rev-list[1].
Use revisions from revs-file instead of calling linkgit:git-rev-list[1].
--reverse::
Walk history forward instead of backward. Instead of showing

View File

@@ -1,30 +0,0 @@
<!-- callout.xsl: converts asciidoc callouts to man page format -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="co">
<xsl:value-of select="concat('\fB(',substring-after(@id,'-'),')\fR')"/>
</xsl:template>
<xsl:template match="calloutlist">
<xsl:text>.sp&#10;</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="callout">
<xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/>
<xsl:apply-templates/>
<xsl:text>.br&#10;</xsl:text>
</xsl:template>
<!-- sorry, this is not about callouts, but attempts to work around
spurious .sp at the tail of the line docbook stylesheets seem to add -->
<xsl:template match="simpara">
<xsl:variable name="content">
<xsl:apply-templates/>
</xsl:variable>
<xsl:value-of select="normalize-space($content)"/>
<xsl:if test="not(ancestor::authorblurb) and
not(ancestor::personblurb)">
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

View File

@@ -25,7 +25,7 @@ blank lines are ignored.
The file consists of sections and variables. A section begins with
the name of the section in square brackets and continues until the next
section begins. Section names are not case sensitive. Only alphanumeric
characters, '`-`' and '`.`' are allowed in section names. Each variable
characters, `-` and `.` are allowed in section names. Each variable
must belong to some section, which means that there must be section
header before first setting of a variable.
@@ -39,7 +39,7 @@ in the section header, like in example below:
--------
Subsection names can contain any characters except newline (doublequote
'`"`' and backslash have to be escaped as '`\"`' and '`\\`',
`"` and backslash have to be escaped as `\"` and `\\`,
respectively) and are case sensitive. Section header cannot span multiple
lines. Variables may belong directly to a section or to a given subsection.
You can have `[section]` if you have `[section "subsection"]`, but you
@@ -53,7 +53,7 @@ All the other lines are recognized as setting variables, in the form
'name = value'. If there is no equal sign on the line, the entire line
is taken as 'name' and the variable is recognized as boolean "true".
The variable names are case-insensitive and only alphanumeric
characters and '`-`' are allowed. There can be more than one value
characters and `-` are allowed. There can be more than one value
for a given variable; we say then that variable is multivalued.
Leading and trailing whitespace in a variable value is discarded.
@@ -69,15 +69,15 @@ String values may be entirely or partially enclosed in double quotes.
You need to enclose variable value in double quotes if you want to
preserve leading or trailing whitespace, or if variable value contains
beginning of comment characters (if it contains '#' or ';').
Double quote '`"`' and backslash '`\`' characters in variable value must
be escaped: use '`\"`' for '`"`' and '`\\`' for '`\`'.
Double quote `"` and backslash `\` characters in variable value must
be escaped: use `\"` for `"` and `\\` for `\`.
The following escape sequences (beside '`\"`' and '`\\`') are recognized:
'`\n`' for newline character (NL), '`\t`' for horizontal tabulation (HT, TAB)
and '`\b`' for backspace (BS). No other char escape sequence, nor octal
The following escape sequences (beside `\"` and `\\`) are recognized:
`\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)
and `\b` for backspace (BS). No other char escape sequence, nor octal
char sequences are valid.
Variable value ending in a '`\`' is continued on the next line in the
Variable value ending in a `\` is continued on the next line in the
customary UNIX fashion.
Some variables may require special value format.
@@ -221,6 +221,11 @@ core.gitProxy::
Can be overridden by the 'GIT_PROXY_COMMAND' environment variable
(which always applies universally, without the special "for"
handling).
+
The special string `none` can be used as the proxy command to
specify that no proxy be used for a given domain pattern.
This is useful for excluding servers inside a firewall from
proxy use, while defaulting to a common proxy for external domains.
core.ignoreStat::
If true, commands which modify both the working tree and the index
@@ -382,9 +387,9 @@ core.pager::
to override git's default settings this way, you need
to be explicit. For example, to disable the S option
in a backward compatible manner, set `core.pager`
to "`less -+$LESS -FRX`". This will be passed to the
to `less -+$LESS -FRX`. This will be passed to the
shell by git, which will translate the final command to
"`LESS=FRSX less -+FRSX -FRX`".
`LESS=FRSX less -+FRSX -FRX`.
core.whitespace::
A comma separated list of common whitespace problems to
@@ -468,10 +473,14 @@ branch.autosetuprebase::
This option defaults to never.
branch.<name>.remote::
When in branch <name>, it tells 'git-fetch' which remote to fetch.
If this option is not given, 'git-fetch' defaults to remote "origin".
When in branch <name>, it tells 'git-fetch' and 'git-push' which
remote to fetch from/push to. It defaults to `origin` if no remote is
configured. `origin` is also used if you are not on any branch.
branch.<name>.merge::
Defines, together with branch.<name>.remote, the upstream branch
for the given branch. It tells 'git-fetch'/'git-pull' which
branch to merge from.
When in branch <name>, it tells 'git-fetch' the default
refspec to be marked for merging in FETCH_HEAD. The value is
handled like the remote part of a refspec, and must match a
@@ -548,6 +557,25 @@ color.diff.<slot>::
whitespace errors). The values of these variables may be specified as
in color.branch.<slot>.
color.grep::
When set to `always`, always highlight matches. When `false` (or
`never`), never. When set to `true` or `auto`, use color only
when the output is written to the terminal. Defaults to `false`.
color.grep.external::
The string value of this variable is passed to an external 'grep'
command as a command line option if match highlighting is turned
on. If set to an empty string, no option is passed at all,
turning off coloring for external 'grep' calls; this is the default.
For GNU grep, set it to `--color=always` to highlight matches even
when a pager is used.
color.grep.match::
Use customized color for matches. The value of this variable
may be specified as in color.branch.<slot>. It is passed using
the environment variables 'GREP_COLOR' and 'GREP_COLORS' when
calling an external 'grep'.
color.interactive::
When set to `always`, always use colors for interactive prompts
and displays (such as those used by "git-add --interactive").
@@ -1161,7 +1189,7 @@ pager.<cmd>::
particular git subcommand when writing to a tty. If
`\--paginate` or `\--no-pager` is specified on the command line,
it takes precedence over this option. To disable pagination for
all commands, set `core.pager` or 'GIT_PAGER' to "`cat`".
all commands, set `core.pager` or `GIT_PAGER` to `cat`.
pull.octopus::
The default merge strategy to use when pulling multiple branches
@@ -1170,6 +1198,19 @@ pull.octopus::
pull.twohead::
The default merge strategy to use when pulling a single branch.
push.default::
Defines the action git push should take if no refspec is given
on the command line, no refspec is configured in the remote, and
no refspec is implied by any of the options given on the command
line. Possible values are:
+
* `nothing` do not push anything.
* `matching` push all matching branches.
All branches having the same name in both ends are considered to be
matching. This is the default.
* `tracking` push the current branch to the branch it is tracking.
* `current` push the current branch to a branch of the same name.
rebase.stat::
Whether to show a diffstat of what changed upstream since the last
rebase. False by default.

View File

@@ -176,7 +176,10 @@ override configuration settings.
number.
-S<string>::
Look for differences that contain the change in <string>.
Look for differences that introduce or remove an instance of
<string>. Note that this is different than the string simply
appearing in diff output; see the 'pickaxe' entry in
linkgit:gitdiffcore[7] for more details.
--pickaxe-all::
When -S finds a change, show all the changes in that

View File

@@ -98,7 +98,7 @@ Use a tarball as a starting point for a new repository.::
------------
$ tar zxf frotz.tar.gz
$ cd frotz
$ git-init
$ git init
$ git add . <1>
$ git commit -m "import of frotz source tree."
$ git tag v2.43 <2>

View File

@@ -23,7 +23,7 @@ prepended to the filenames in the archive.
'git-archive' behaves differently when given a tree ID versus when
given a commit ID or tag ID. In the first case the current time is
used as modification time of each file in the archive. In the latter
used as the modification time of each file in the archive. In the latter
case the commit time as recorded in the referenced commit object is
used instead. Additionally the commit ID is stored in a global
extended pax header if the tar format is used; it can be extracted
@@ -52,11 +52,11 @@ OPTIONS
Write the archive to <file> instead of stdout.
<extra>::
This can be any options that the archiver backend understand.
This can be any options that the archiver backend understands.
See next section.
--remote=<repo>::
Instead of making a tar archive from local repository,
Instead of making a tar archive from the local repository,
retrieve a tar archive from a remote repository.
--exec=<git-upload-archive>::
@@ -109,7 +109,7 @@ EXAMPLES
git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)::
Create a tar archive that contains the contents of the
latest commit on the current branch, and extracts it in
latest commit on the current branch, and extract it in the
`/var/tmp/junk` directory.
git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::

View File

@@ -3,7 +3,7 @@ git-bisect(1)
NAME
----
git-bisect - Find the change that introduced a bug by binary search
git-bisect - Find by binary search the change that introduced a bug
SYNOPSIS
@@ -39,7 +39,8 @@ help" or "git bisect -h" to get a long usage description.
Basic bisect commands: start, bad, good
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The way you use it is:
Using the Linux kernel tree as an example, basic use of the bisect
command is as follows:
------------------------------------------------
$ git bisect start
@@ -48,61 +49,63 @@ $ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version
# tested that was good
------------------------------------------------
When you give at least one bad and one good versions, it will bisect
the revision tree and say something like:
When you have specified at least one bad and one good version, the
command bisects the revision tree and outputs something similar to
the following:
------------------------------------------------
Bisecting: 675 revisions left to test after this
------------------------------------------------
and check out the state in the middle. Now, compile that kernel, and
boot it. Now, let's say that this booted kernel works fine, then just
do
The state in the middle of the set of revisions is then checked out.
You would now compile that kernel and boot it. If the booted kernel
works correctly, you would then issue the following command:
------------------------------------------------
$ git bisect good # this one is good
------------------------------------------------
which will now say
The output of this command would be something similar to the following:
------------------------------------------------
Bisecting: 337 revisions left to test after this
------------------------------------------------
and you continue along, compiling that one, testing it, and depending
on whether it is good or bad, you say "git bisect good" or "git bisect
bad", and ask for the next bisection.
You keep repeating this process, compiling the tree, testing it, and
depending on whether it is good or bad issuing the command "git bisect good"
or "git bisect bad" to ask for the next bisection.
Until you have no more left, and you'll have been left with the first
bad kernel rev in "refs/bisect/bad".
Eventually there will be no more revisions left to bisect, and you
will have been left with the first bad kernel revision in "refs/bisect/bad".
Bisect reset
~~~~~~~~~~~~
Oh, and then after you want to reset to the original head, do a
To return to the original head after a bisect session, issue the
following command:
------------------------------------------------
$ git bisect reset
------------------------------------------------
to get back to the original branch, instead of being on the bisection
commit ("git bisect start" will do that for you too, actually: it will
reset the bisection state).
This resets the tree to the original branch instead of being on the
bisection commit ("git bisect start" will also do that, as it resets
the bisection state).
Bisect visualize
~~~~~~~~~~~~~~~~
During the bisection process, you can say
To see the currently remaining suspects in 'gitk', issue the following
command during the bisection process:
------------
$ git bisect visualize
------------
to see the currently remaining suspects in 'gitk'. `visualize` is a bit
too long to type and `view` is provided as a synonym.
`view` may also be used as a synonym for `visualize`.
If 'DISPLAY' environment variable is not set, 'git log' is used
instead. You can even give command line options such as `-p` and
If the 'DISPLAY' environment variable is not set, 'git log' is used
instead. You can also give command line options such as `-p` and
`--stat`.
------------
@@ -112,57 +115,58 @@ $ git bisect view --stat
Bisect log and bisect replay
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The good/bad input is logged, and
After having marked revisions as good or bad, issue the following
command to show what has been done so far:
------------
$ git bisect log
------------
shows what you have done so far. You can truncate its output somewhere
and save it in a file, and run
If you discover that you made a mistake in specifying the status of a
revision, you can save the output of this command to a file, edit it to
remove the incorrect entries, and then issue the following commands to
return to a corrected state:
------------
$ git bisect reset
$ git bisect replay that-file
------------
if you find later you made a mistake telling good/bad about a
revision.
Avoiding to test a commit
Avoiding testing a commit
~~~~~~~~~~~~~~~~~~~~~~~~~
If in a middle of bisect session, you know what the bisect suggested
to try next is not a good one to test (e.g. the change the commit
If, in the middle of a bisect session, you know that the next suggested
revision is not a good one to test (e.g. the change the commit
introduces is known not to work in your environment and you know it
does not have anything to do with the bug you are chasing), you may
want to find a near-by commit and try that instead.
want to find a nearby commit and try that instead.
It goes something like this:
For example:
------------
$ git bisect good/bad # previous round was good/bad.
$ git bisect good/bad # previous round was good or bad.
Bisecting: 337 revisions left to test after this
$ git bisect visualize # oops, that is uninteresting.
$ git reset --hard HEAD~3 # try 3 revs before what
$ git reset --hard HEAD~3 # try 3 revisions before what
# was suggested
------------
Then compile and test the one you chose to try. After that, tell
bisect what the result was as usual.
Then compile and test the chosen revision, and afterwards mark
the revision as good or bad in the usual manner.
Bisect skip
~~~~~~~~~~~~
Instead of choosing by yourself a nearby commit, you may just want git
to do it for you using:
Instead of choosing by yourself a nearby commit, you can ask git
to do it for you by issuing the command:
------------
$ git bisect skip # Current version cannot be tested
------------
But computing the commit to test may be slower afterwards and git may
eventually not be able to tell the first bad among a bad and one or
more "skip"ped commits.
eventually not be able to tell the first bad commit among a bad commit
and one or more skipped commits.
You can even skip a range of commits, instead of just one commit,
using the "'<commit1>'..'<commit2>'" notation. For example:
@@ -171,33 +175,34 @@ using the "'<commit1>'..'<commit2>'" notation. For example:
$ git bisect skip v2.5..v2.6
------------
would mean that no commit between `v2.5` excluded and `v2.6` included
can be tested.
This tells the bisect process that no commit after `v2.5`, up to and
including `v2.6`, should be tested.
Note that if you want to also skip the first commit of a range you can
use something like:
Note that if you also want to skip the first commit of the range you
would issue the command:
------------
$ git bisect skip v2.5 v2.5..v2.6
------------
and the commit pointed to by `v2.5` will be skipped too.
This tells the bisect process that the commits between `v2.5` included
and `v2.6` included should be skipped.
Cutting down bisection by giving more parameters to bisect start
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can further cut down the number of trials if you know what part of
the tree is involved in the problem you are tracking down, by giving
paths parameters when you say `bisect start`, like this:
You can further cut down the number of trials, if you know what part of
the tree is involved in the problem you are tracking down, by specifying
path parameters when issuing the `bisect start` command:
------------
$ git bisect start -- arch/i386 include/asm-i386
------------
If you know beforehand more than one good commits, you can narrow the
bisect space down without doing the whole tree checkout every time you
give good commits. You give the bad revision immediately after `start`
and then you give all the good revisions you have:
If you know beforehand more than one good commit, you can narrow the
bisect space down by specifying all of the good commits immediately after
the bad commit when issuing the `bisect start` command:
------------
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 --
@@ -209,38 +214,38 @@ Bisect run
~~~~~~~~~~
If you have a script that can tell if the current source code is good
or bad, you can automatically bisect using:
or bad, you can bisect by issuing the command:
------------
$ git bisect run my_script arguments
------------
Note that the "run" script (`my_script` in the above example) should
exit with code 0 in case the current source code is good. Exit with a
Note that the script (`my_script` in the above example) should
exit with code 0 if the current source code is good, and exit with a
code between 1 and 127 (inclusive), except 125, if the current
source code is bad.
Any other exit code will abort the automatic bisect process. (A
program that does "exit(-1)" leaves $? = 255, see exit(3) manual page,
the value is chopped with "& 0377".)
Any other exit code will abort the bisect process. It should be noted
that a program that terminates via "exit(-1)" leaves $? = 255, (see the
exit(3) manual page), as the value is chopped with "& 0377".
The special exit code 125 should be used when the current source code
cannot be tested. If the "run" script exits with this code, the current
revision will be skipped, see `git bisect skip` above.
cannot be tested. If the script exits with this code, the current
revision will be skipped (see `git bisect skip` above).
You may often find that during bisect you want to have near-constant
tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
"revision that does not have this commit needs this patch applied to
work around other problem this bisection is not interested in")
applied to the revision being tested.
You may often find that during a bisect session you want to have
temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a
header file, or "revision that does not have this commit needs this
patch applied to work around another problem this bisection is not
interested in") applied to the revision being tested.
To cope with such a situation, after the inner 'git bisect' finds the
next revision to test, with the "run" script, you can apply that tweak
before compiling, run the real test, and after the test decides if the
revision (possibly with the needed tweaks) passed the test, rewind the
tree to the pristine state. Finally the "run" script can exit with
the status of the real test to let the "git bisect run" command loop to
determine the outcome.
next revision to test, the script can apply the patch
before compiling, run the real test, and afterwards decide if the
revision (possibly with the needed patch) passed the test and then
rewind the tree to the pristine state. Finally the script should exit
with the status of the real test to let the "git bisect run" command loop
determine the eventual outcome of the bisect session.
EXAMPLES
--------
@@ -264,39 +269,39 @@ $ git bisect run make test # "make test" builds and tests
------------
$ cat ~/test.sh
#!/bin/sh
make || exit 125 # this "skip"s broken builds
make || exit 125 # this skips broken builds
make test # "make test" runs the test suite
$ git bisect start v1.3 v1.1 -- # v1.3 is bad, v1.1 is good
$ git bisect run ~/test.sh
------------
+
Here we use a "test.sh" custom script. In this script, if "make"
fails, we "skip" the current commit.
fails, we skip the current commit.
+
It's safer to use a custom script outside the repo to prevent
It is safer to use a custom script outside the repository to prevent
interactions between the bisect, make and test processes and the
script.
+
And "make test" should "exit 0", if the test suite passes, and
"exit 1" (for example) otherwise.
"make test" should "exit 0", if the test suite passes, and
"exit 1" otherwise.
* Automatically bisect a broken test case:
+
------------
$ cat ~/test.sh
#!/bin/sh
make || exit 125 # this "skip"s broken builds
make || exit 125 # this skips broken builds
~/check_test_case.sh # does the test case passes ?
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10
$ git bisect run ~/test.sh
------------
+
Here "check_test_case.sh" should "exit 0", if the test case passes,
and "exit 1" (for example) otherwise.
Here "check_test_case.sh" should "exit 0" if the test case passes,
and "exit 1" otherwise.
+
It's safer if both "test.sh" and "check_test_case.sh" scripts are
outside the repo to prevent interactions between the bisect, make and
test processes and the scripts.
It is safer if both "test.sh" and "check_test_case.sh" scripts are
outside the repository to prevent interactions between the bisect,
make and test processes and the scripts.
* Automatically bisect a broken test suite:
+

View File

@@ -18,9 +18,9 @@ DESCRIPTION
Annotates each line in the given file with information from the revision which
last modified the line. Optionally, start annotating from the given revision.
Also it can limit the range of lines annotated.
The command can also limit the range of lines annotated.
This report doesn't tell you anything about lines which have been deleted or
The report does not tell you anything about lines which have been deleted or
replaced; you need to use a tool such as 'git-diff' or the "pickaxe"
interface briefly mentioned in the following paragraph.
@@ -48,26 +48,26 @@ include::blame-options.txt[]
lines between files (see `-C`) and lines moved within a
file (see `-M`). The first number listed is the score.
This is the number of alphanumeric characters detected
to be moved between or within files. This must be above
as having been moved between or within files. This must be above
a certain threshold for 'git-blame' to consider those lines
of code to have been moved.
-f::
--show-name::
Show filename in the original commit. By default
filename is shown if there is any line that came from a
file with different name, due to rename detection.
Show the filename in the original commit. By default
the filename is shown if there is any line that came from a
file with a different name, due to rename detection.
-n::
--show-number::
Show line number in the original commit (Default: off).
Show the line number in the original commit (Default: off).
-s::
Suppress author name and timestamp from the output.
Suppress the author name and timestamp from the output.
-w::
Ignore whitespace when comparing parent's version and
child's to find where the lines came from.
Ignore whitespace when comparing the parent's version and
the child's to find where the lines came from.
THE PORCELAIN FORMAT
@@ -79,17 +79,17 @@ header at the minimum has the first line which has:
- 40-byte SHA-1 of the commit the line is attributed to;
- the line number of the line in the original file;
- the line number of the line in the final file;
- on a line that starts a group of line from a different
- on a line that starts a group of lines from a different
commit than the previous one, the number of lines in this
group. On subsequent lines this field is absent.
This header line is followed by the following information
at least once for each commit:
- author name ("author"), email ("author-mail"), time
- the author name ("author"), email ("author-mail"), time
("author-time"), and timezone ("author-tz"); similarly
for committer.
- filename in the commit the line is attributed to.
- the filename in the commit that the line is attributed to.
- the first line of the commit log message ("summary").
The contents of the actual line is output after the above
@@ -100,23 +100,23 @@ header elements later.
SPECIFYING RANGES
-----------------
Unlike 'git-blame' and 'git-annotate' in older git, the extent
of annotation can be limited to both line ranges and revision
Unlike 'git-blame' and 'git-annotate' in older versions of git, the extent
of the annotation can be limited to both line ranges and revision
ranges. When you are interested in finding the origin for
ll. 40-60 for file `foo`, you can use `-L` option like these
lines 40-60 for file `foo`, you can use the `-L` option like so
(they mean the same thing -- both ask for 21 lines starting at
line 40):
git blame -L 40,60 foo
git blame -L 40,+21 foo
Also you can use regular expression to specify the line range.
Also you can use a regular expression to specify the line range:
git blame -L '/^sub hello {/,/^}$/' foo
would limit the annotation to the body of `hello` subroutine.
which limits the annotation to the body of the `hello` subroutine.
When you are not interested in changes older than the version
When you are not interested in changes older than version
v2.6.18, or changes older than 3 weeks, you can use revision
range specifiers similar to 'git-rev-list':
@@ -129,7 +129,7 @@ commit v2.6.18 or the most recent commit that is more than 3
weeks old in the above example) are blamed for that range
boundary commit.
A particularly useful way is to see if an added file have lines
A particularly useful way is to see if an added file has lines
created by copy-and-paste from existing files. Sometimes this
indicates that the developer was being sloppy and did not
refactor the code properly. You can first find the commit that
@@ -162,26 +162,26 @@ annotated.
+
Line numbers count from 1.
. The first time that commit shows up in the stream, it has various
. The first time that a commit shows up in the stream, it has various
other information about it printed out with a one-word tag at the
beginning of each line about that "extended commit info" (author,
email, committer, dates, summary etc).
beginning of each line describing the extra commit information (author,
email, committer, dates, summary, etc.).
. Unlike Porcelain format, the filename information is always
. Unlike the Porcelain format, the filename information is always
given and terminates the entry:
"filename" <whitespace-quoted-filename-goes-here>
+
and thus it's really quite easy to parse for some line- and word-oriented
and thus it is really quite easy to parse for some line- and word-oriented
parser (which should be quite natural for most scripting languages).
+
[NOTE]
For people who do parsing: to make it more robust, just ignore any
lines in between the first and last one ("<sha1>" and "filename" lines)
where you don't recognize the tag-words (or care about that particular
lines between the first and last one ("<sha1>" and "filename" lines)
where you do not recognize the tag words (or care about that particular
one) at the beginning of the "extended information" lines. That way, if
there is ever added information (like the commit encoding or extended
commit commentary), a blame viewer won't ever care.
commit commentary), a blame viewer will not care.
MAPPING AUTHORS

View File

@@ -18,19 +18,19 @@ SYNOPSIS
DESCRIPTION
-----------
With no arguments, existing branches are listed, the current branch will
With no arguments, existing branches are listed and the current branch will
be highlighted with an asterisk. Option `-r` causes the remote-tracking
branches to be listed, and option `-a` shows both.
With `--contains`, shows only the branches that contains the named commit
(in other words, the branches whose tip commits are descendant of the
With `--contains`, shows only the branches that contain the named commit
(in other words, the branches whose tip commits are descendants of the
named commit). With `--merged`, only branches merged into the named
commit (i.e. the branches whose tip commits are reachable from the named
commit) will be listed. With `--no-merged` only branches not merged into
the named commit will be listed. Missing <commit> argument defaults to
'HEAD' (i.e. the tip of the current branch).
the named commit will be listed. If the <commit> argument is missing it
defaults to 'HEAD' (i.e. the tip of the current branch).
In its second form, a new branch named <branchname> will be created.
In the command's second form, a new branch named <branchname> will be created.
It will start out with a head equal to the one given as <start-point>.
If no <start-point> is given, the branch will be created with a head
equal to that of the currently checked out branch.
@@ -57,9 +57,9 @@ has a reflog then the reflog will also be deleted.
Use -r together with -d to delete remote-tracking branches. Note, that it
only makes sense to delete remote-tracking branches if they no longer exist
in remote repository or if 'git-fetch' was configured not to fetch
them again. See also 'prune' subcommand of linkgit:git-remote[1] for way to
clean up all obsolete remote-tracking branches.
in the remote repository or if 'git-fetch' was configured not to fetch
them again. See also the 'prune' subcommand of linkgit:git-remote[1] for a
way to clean up all obsolete remote-tracking branches.
OPTIONS
@@ -76,14 +76,14 @@ OPTIONS
based sha1 expressions such as "<branchname>@\{yesterday}".
-f::
Force the creation of a new branch even if it means deleting
a branch that already exists with the same name.
Reset <branchname> to <startpoint> if <branchname> exists
already. Without `-f` 'git-branch' refuses to change an existing branch.
-m::
Move/rename a branch and the corresponding reflog.
-M::
Move/rename a branch even if the new branchname already exists.
Move/rename a branch even if the new branch name already exists.
--color::
Color branches to highlight current, local, and remote branches.
@@ -103,17 +103,17 @@ OPTIONS
Show sha1 and commit subject line for each head.
--abbrev=<length>::
Alter minimum display length for sha1 in output listing,
default value is 7.
Alter the sha1's minimum display length in the output listing.
The default value is 7.
--no-abbrev::
Display the full sha1s in output listing rather than abbreviating them.
Display the full sha1s in the output listing rather than abbreviating them.
--track::
When creating a new branch, set up configuration so that 'git-pull'
When creating a new branch, set up the configuration so that 'git-pull'
will automatically retrieve data from the start point, which must be
a branch. Use this if you always pull from the same upstream branch
into the new branch, and if you don't want to use "git pull
into the new branch, and if you do not want to use "git pull
<repository> <refspec>" explicitly. This behavior is the default
when the start point is a remote branch. Set the
branch.autosetupmerge configuration variable to `false` if you want
@@ -149,13 +149,13 @@ OPTIONS
<newbranch>::
The new name for an existing branch. The same restrictions as for
<branchname> applies.
<branchname> apply.
Examples
--------
Start development off of a known tag::
Start development from a known tag::
+
------------
$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
@@ -167,7 +167,7 @@ $ git checkout my2.6.14
<1> This step and the next one could be combined into a single step with
"checkout -b my2.6.14 v2.6.14".
Delete unneeded branch::
Delete an unneeded branch::
+
------------
$ git clone git://git.kernel.org/.../git.git my.git
@@ -176,21 +176,21 @@ $ git branch -d -r origin/todo origin/html origin/man <1>
$ git branch -D test <2>
------------
+
<1> Delete remote-tracking branches "todo", "html", "man". Next 'fetch' or
'pull' will create them again unless you configure them not to. See
linkgit:git-fetch[1].
<2> Delete "test" branch even if the "master" branch (or whichever branch is
currently checked out) does not have all commits from test branch.
<1> Delete the remote-tracking branches "todo", "html" and "man". The next
'fetch' or 'pull' will create them again unless you configure them not to.
See linkgit:git-fetch[1].
<2> Delete the "test" branch even if the "master" branch (or whichever branch
is currently checked out) does not have all commits from the test branch.
Notes
-----
If you are creating a branch that you want to immediately checkout, it's
If you are creating a branch that you want to checkout immediately, it is
easier to use the git checkout command with its `-b` option to create
a branch and check it out with a single command.
The options `--contains`, `--merged` and `--no-merged` serves three related
The options `--contains`, `--merged` and `--no-merged` serve three related
but different purposes:
- `--contains <commit>` is used to find all branches which will need

View File

@@ -19,13 +19,13 @@ DESCRIPTION
Some workflows require that one or more branches of development on one
machine be replicated on another machine, but the two machines cannot
be directly connected so the interactive git protocols (git, ssh,
rsync, http) cannot be used. This command provides support for
be directly connected, and therefore the interactive git protocols (git,
ssh, rsync, http) cannot be used. This command provides support for
'git-fetch' and 'git-pull' to operate by packaging objects and references
in an archive at the originating machine, then importing those into
another repository using 'git-fetch' and 'git-pull'
after moving the archive by some means (i.e., by sneakernet). As no
direct connection between repositories exists, the user must specify a
direct connection between the repositories exists, the user must specify a
basis for the bundle that is held by the destination repository: the
bundle assumes that all objects in the basis are already in the
destination repository.
@@ -43,7 +43,7 @@ verify <file>::
bundle format itself as well as checking that the prerequisite
commits exist and are fully linked in the current repository.
'git-bundle' prints a list of missing commits, if any, and exits
with non-zero status.
with a non-zero status.
list-heads <file>::
Lists the references defined in the bundle. If followed by a
@@ -53,14 +53,14 @@ list-heads <file>::
unbundle <file>::
Passes the objects in the bundle to 'git-index-pack'
for storage in the repository, then prints the names of all
defined references. If a reflist is given, only references
matching those in the given list are printed. This command is
defined references. If a list of references is given, only
references matching those in the list are printed. This command is
really plumbing, intended to be called only by 'git-fetch'.
[git-rev-list-args...]::
A list of arguments, acceptable to 'git-rev-parse' and
'git-rev-list', that specify the specific objects and references
to transport. For example, "master~10..master" causes the
'git-rev-list', that specifies the specific objects and references
to transport. For example, `master\~10..master` causes the
current master reference to be packaged along with all objects
added since its 10th ancestor commit. There is no explicit
limit to the number of references and objects that may be
@@ -71,24 +71,24 @@ unbundle <file>::
A list of references used to limit the references reported as
available. This is principally of use to 'git-fetch', which
expects to receive only those references asked for and not
necessarily everything in the pack (in this case, 'git-bundle' is
acting like 'git-fetch-pack').
necessarily everything in the pack (in this case, 'git-bundle' acts
like 'git-fetch-pack').
SPECIFYING REFERENCES
---------------------
'git-bundle' will only package references that are shown by
'git-show-ref': this includes heads, tags, and remote heads. References
such as master~1 cannot be packaged, but are perfectly suitable for
such as `master\~1` cannot be packaged, but are perfectly suitable for
defining the basis. More than one reference may be packaged, and more
than one basis can be specified. The objects packaged are those not
contained in the union of the given bases. Each basis can be
specified explicitly (e.g., ^master~10), or implicitly (e.g.,
master~10..master, --since=10.days.ago master).
specified explicitly (e.g. `^master\~10`), or implicitly (e.g.
`master\~10..master`, `--since=10.days.ago master`).
It is very important that the basis used be held by the destination.
It is okay to err on the side of conservatism, causing the bundle file
to contain objects already in the destination as these are ignored
It is okay to err on the side of caution, causing the bundle file
to contain objects already in the destination, as these are ignored
when unpacking at the destination.
EXAMPLE
@@ -97,13 +97,13 @@ EXAMPLE
Assume you want to transfer the history from a repository R1 on machine A
to another repository R2 on machine B.
For whatever reason, direct connection between A and B is not allowed,
but we can move data from A to B via some mechanism (CD, email, etc).
We want to update R2 with developments made on branch master in R1.
but we can move data from A to B via some mechanism (CD, email, etc.).
We want to update R2 with development made on the branch master in R1.
To bootstrap the process, you can first create a bundle that doesn't have
any basis. You can use a tag to remember up to what commit you sent out
in order to make it easy to later update the other repository with
incremental bundle,
To bootstrap the process, you can first create a bundle that does not have
any basis. You can use a tag to remember up to what commit you last
processed, in order to make it easy to later update the other repository
with an incremental bundle:
----------------
machineA$ cd R1
@@ -111,17 +111,17 @@ machineA$ git bundle create file.bundle master
machineA$ git tag -f lastR2bundle master
----------------
Then you sneakernet file.bundle to the target machine B. Because you don't
have to have any object to extract objects from such a bundle, not only
you can fetch/pull from a bundle, you can clone from it as if it was a
remote repository.
Then you transfer file.bundle to the target machine B. If you are creating
the repository on machine B, then you can clone from the bundle as if it
were a remote repository instead of creating an empty repository and then
pulling or fetching objects from the bundle:
----------------
machineB$ git clone /home/me/tmp/file.bundle R2
----------------
This will define a remote called "origin" in the resulting repository that
lets you fetch and pull from the bundle. $GIT_DIR/config file in R2 may
lets you fetch and pull from the bundle. The $GIT_DIR/config file in R2 will
have an entry like this:
------------------------
@@ -130,12 +130,12 @@ have an entry like this:
fetch = refs/heads/*:refs/remotes/origin/*
------------------------
You can fetch/pull to update the resulting mine.git repository after
replacing the bundle you store at /home/me/tmp/file.bundle with incremental
updates from here on.
To update the resulting mine.git repository, you can fetch or pull after
replacing the bundle stored at /home/me/tmp/file.bundle with incremental
updates.
After working more in the original repository, you can create an
incremental bundle to update the other:
After working some more in the original repository, you can create an
incremental bundle to update the other repository:
----------------
machineA$ cd R1
@@ -143,8 +143,8 @@ machineA$ git bundle create file.bundle lastR2bundle..master
machineA$ git tag -f lastR2bundle master
----------------
and sneakernet it to the other machine to replace /home/me/tmp/file.bundle,
and pull from it.
You then transfer the bundle to the other machine to replace
/home/me/tmp/file.bundle, and pull from it.
----------------
machineB$ cd R2
@@ -152,49 +152,49 @@ machineB$ git pull
----------------
If you know up to what commit the intended recipient repository should
have the necessary objects for, you can use that knowledge to specify the
have the necessary objects, you can use that knowledge to specify the
basis, giving a cut-off point to limit the revisions and objects that go
in the resulting bundle. The previous example used lastR2bundle tag
for this purpose, but you can use other options you would give to
for this purpose, but you can use any other options that you would give to
the linkgit:git-log[1] command. Here are more examples:
You can use a tag that is present in both.
You can use a tag that is present in both:
----------------
$ git bundle create mybundle v1.0.0..master
----------------
You can use a basis based on time.
You can use a basis based on time:
----------------
$ git bundle create mybundle --since=10.days master
----------------
Or you can use the number of commits.
You can use the number of commits:
----------------
$ git bundle create mybundle -10 master
----------------
You can run `git-bundle verify` to see if you can extract from a bundle
that was created with a basis.
that was created with a basis:
----------------
$ git bundle verify mybundle
----------------
This will list what commits you must have in order to extract from the
bundle and will error out if you don't have them.
bundle and will error out if you do not have them.
A bundle from a recipient repository's point of view is just like a
regular repository it fetches/pulls from. You can for example map
refs, like this example, when fetching:
regular repository which it fetches or pulls from. You can, for example, map
references when fetching:
----------------
$ git fetch mybundle master:localRef
----------------
Or see what refs it offers.
You can also see what references it offers.
----------------
$ git ls-remote mybundle

View File

@@ -3,7 +3,7 @@ git-cat-file(1)
NAME
----
git-cat-file - Provide content or type/size information for repository objects
git-cat-file - Provide content or type and size information for repository objects
SYNOPSIS
@@ -14,19 +14,19 @@ SYNOPSIS
DESCRIPTION
-----------
In the first form, provides content or type of objects in the repository. The
type is required unless '-t' or '-p' is used to find the object type, or '-s'
is used to find the object size.
In its first form, the command provides the content or the type of an object in
the repository. The type is required unless '-t' or '-p' is used to find the
object type, or '-s' is used to find the object size.
In the second form, a list of object (separated by LFs) is provided on stdin,
and the SHA1, type, and size of each object is printed on stdout.
In the second form, a list of objects (separated by linefeeds) is provided on
stdin, and the SHA1, type, and size of each object is printed on stdout.
OPTIONS
-------
<object>::
The name of the object to show.
For a more complete list of ways to spell object names, see
"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
the "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
-t::
Instead of the content, show the object type identified by
@@ -56,8 +56,8 @@ OPTIONS
stdin. May not be combined with any other options or arguments.
--batch-check::
Print the SHA1, type, and size of each object provided on stdin. May not be
combined with any other options or arguments.
Print the SHA1, type, and size of each object provided on stdin. May not
be combined with any other options or arguments.
OUTPUT
------

View File

@@ -14,7 +14,7 @@ SYNOPSIS
DESCRIPTION
-----------
For every pathname, this command will list if each attr is 'unspecified',
For every pathname, this command will list if each attribute is 'unspecified',
'set', or 'unset' as a gitattribute on that pathname.
OPTIONS
@@ -23,11 +23,11 @@ OPTIONS
Read file names from stdin instead of from the command-line.
-z::
Only meaningful with `--stdin`; paths are separated with
NUL character instead of LF.
Only meaningful with `--stdin`; paths are separated with a
NUL character instead of a linefeed character.
\--::
Interpret all preceding arguments as attributes, and all following
Interpret all preceding arguments as attributes and all following
arguments as path names. If not supplied, only the first argument will
be treated as an attribute.
@@ -37,12 +37,12 @@ OUTPUT
The output is of the form:
<path> COLON SP <attribute> COLON SP <info> LF
Where <path> is the path of a file being queried, <attribute> is an attribute
<path> is the path of a file being queried, <attribute> is an attribute
being queried and <info> can be either:
'unspecified';; when the attribute is not defined for the path.
'unset';; when the attribute is defined to false.
'set';; when the attribute is defined to true.
'unset';; when the attribute is defined as false.
'set';; when the attribute is defined as true.
<value>;; when a value has been assigned to the attribute.
EXAMPLES
@@ -69,7 +69,7 @@ org/example/MyClass.java: diff: java
org/example/MyClass.java: myAttr: set
---------------
* Listing attribute for multiple files:
* Listing an attribute for multiple files:
---------------
$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
org/example/MyClass.java: myAttr: set

View File

@@ -3,7 +3,7 @@ git-check-ref-format(1)
NAME
----
git-check-ref-format - Make sure ref name is well formed
git-check-ref-format - Ensures that a reference name is well formed
SYNOPSIS
--------
@@ -11,40 +11,40 @@ SYNOPSIS
DESCRIPTION
-----------
Checks if a given 'refname' is acceptable, and exits non-zero if
it is not.
Checks if a given 'refname' is acceptable, and exits with a non-zero
status if it is not.
A reference is used in git to specify branches and tags. A
branch head is stored under `$GIT_DIR/refs/heads` directory, and
a tag is stored under `$GIT_DIR/refs/tags` directory. git
imposes the following rules on how refs are named:
branch head is stored under the `$GIT_DIR/refs/heads` directory, and
a tag is stored under the `$GIT_DIR/refs/tags` directory. git
imposes the following rules on how references are named:
. It can include slash `/` for hierarchical (directory)
. They can include slash `/` for hierarchical (directory)
grouping, but no slash-separated component can begin with a
dot `.`;
dot `.`.
. It cannot have two consecutive dots `..` anywhere;
. They cannot have two consecutive dots `..` anywhere.
. It cannot have ASCII control character (i.e. bytes whose
. They cannot have ASCII control characters (i.e. bytes whose
values are lower than \040, or \177 `DEL`), space, tilde `~`,
caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
or open bracket `[` anywhere;
or open bracket `[` anywhere.
. It cannot end with a slash `/`.
. They cannot end with a slash `/`.
These rules makes it easy for shell script based tools to parse
refnames, pathname expansion by the shell when a refname is used
These rules make it easy for shell script based tools to parse
reference names, pathname expansion by the shell when a reference name is used
unquoted (by mistake), and also avoids ambiguities in certain
refname expressions (see linkgit:git-rev-parse[1]). Namely:
reference name expressions (see linkgit:git-rev-parse[1]):
. double-dot `..` are often used as in `ref1..ref2`, and in some
context this notation means `{caret}ref1 ref2` (i.e. not in
ref1 and in ref2).
. A double-dot `..` is often used as in `ref1..ref2`, and in some
contexts this notation means `{caret}ref1 ref2` (i.e. not in
`ref1` and in `ref2`).
. tilde `~` and caret `{caret}` are used to introduce postfix
. A tilde `~` and caret `{caret}` are used to introduce the postfix
'nth parent' and 'peel onion' operation.
. colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
. A colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
value and store it in dstref" in fetch and push operations.
It may also be used to select a specific object such as with
'git-cat-file': "git cat-file blob v1.3.3:refs.c".

View File

@@ -133,9 +133,9 @@ the conflicted merge in the specified paths.
When this parameter names a non-branch (but still a valid commit object),
your HEAD becomes 'detached'.
+
As a special case, the "`@\{-N\}`" syntax for the N-th last branch
As a special case, the `"@\{-N\}"` syntax for the N-th last branch
checks out the branch (instead of detaching). You may also specify
"`-`" which is synonymous with "`@\{-1\}`".
`-` which is synonymous with `"@\{-1\}"`.
Detached HEAD

View File

@@ -117,7 +117,7 @@ then the cloned repository will become corrupt.
--origin <name>::
-o <name>::
Instead of using the remote name 'origin' to keep track
of the upstream repository, use <name> instead.
of the upstream repository, use <name>.
--upload-pack <upload-pack>::
-u <upload-pack>::

View File

@@ -11,7 +11,7 @@ SYNOPSIS
[verse]
'git config' [<file-option>] [type] [-z|--null] name [value [value_regex]]
'git config' [<file-option>] [type] --add name value
'git config' [<file-option>] [type] --replace-all name [value [value_regex]]
'git config' [<file-option>] [type] --replace-all name value [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get name [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex]

View File

@@ -24,6 +24,9 @@ repository, or incrementally import into an existing one.
Splitting the CVS log into patch sets is done by 'cvsps'.
At least version 2.1 is required.
*WARNING:* for certain situations the import leads to incorrect results.
Please see the section <<issues,ISSUES>> for further reference.
You should *never* do any work of your own on the branches that are
created by 'git-cvsimport'. By default initial import will create and populate a
"master" branch from the CVS repository's main branch which you're free
@@ -62,7 +65,7 @@ OPTIONS
-r <remote>::
The git remote to import this CVS repository into.
Moves all CVS branches into remotes/<remote>/<branch>
akin to the 'git-clone' "--use-separate-remote" option.
akin to the way 'git-clone' uses 'origin' by default.
-o <branch-for-HEAD>::
When no remote is specified (via -r) the 'HEAD' branch
@@ -164,6 +167,39 @@ If '-v' is specified, the script reports what it is doing.
Otherwise, success is indicated the Unix way, i.e. by simply exiting with
a zero exit status.
[[issues]]
ISSUES
------
Problems related to timestamps:
* If timestamps of commits in the cvs repository are not stable enough
to be used for ordering commits changes may show up in the wrong
order.
* If any files were ever "cvs import"ed more than once (e.g., import of
more than one vendor release) the HEAD contains the wrong content.
* If the timestamp order of different files cross the revision order
within the commit matching time window the order of commits may be
wrong.
Problems related to branches:
* Branches on which no commits have been made are not imported.
* All files from the branching point are added to a branch even if
never added in cvs.
* This applies to files added to the source branch *after* a daughter
branch was created: if previously no commit was made on the daughter
branch they will erroneously be added to the daughter branch in git.
Problems related to tags:
* Multiple tags on the same revision are not imported.
If you suspect that any of these issues may apply to the repository you
want to import consider using these alternative tools which proved to be
more stable in practise:
* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
Author
------

View File

@@ -40,15 +40,11 @@ There are two ways to specify which commits to operate on.
REVISIONS" section in linkgit:git-rev-parse[1]) means the
commits in the specified range.
A single commit, when interpreted as a <revision range>
expression, means "everything that leads to that commit", but
if you write 'git format-patch <commit>', the previous rule
applies to that command line and you do not get "everything
since the beginning of the time". If you want to format
everything since project inception to one commit, say "git
format-patch \--root <commit>" to make it clear that it is the
latter case. If you want to format a single commit, you can do
this with "git format-patch -1 <commit>".
The first rule takes precedence in the case of a single <commit>. To
apply the second rule, i.e., format everything since the beginning of
history up until <commit>, use the '\--root' option: "git format-patch
\--root <commit>". If you want to format only <commit> itself, you
can do this with "git format-patch -1 <commit>".
By default, each output file is numbered sequentially from 1, and uses the
first line of the commit message (massaged for pathname safety) as
@@ -97,7 +93,6 @@ include::diff-options.txt[]
--numbered-files::
Output file names will be a simple number sequence
without the default first line of the commit appended.
Mutually exclusive with the --stdout option.
-k::
--keep-subject::
@@ -162,6 +157,11 @@ if that is not set.
Add a "Cc:" header to the email headers. This is in addition
to any configured headers, and may be used multiple times.
--add-header=<header>::
Add an arbitrary header to the email headers. This is in addition
to any configured headers, and may be used multiple times.
For example, --add-header="Organization: git-foo"
--cover-letter::
In addition to the patches, generate a cover letter file
containing the shortlog and the overall diffstat. You can
@@ -183,6 +183,13 @@ not add any suffix.
applied. By default the contents of changes in those files are
encoded in the patch.
--root::
Treat the revision argument as a <revision range>, even if it
is just a single commit (that would normally be treated as a
<since>). Note that root commits included in the specified
range are always formatted as creation patches, independently
of this flag.
CONFIGURATION
-------------
You can specify extra mail header lines to be added to each message

View File

@@ -17,6 +17,7 @@ SYNOPSIS
[-l | --files-with-matches] [-L | --files-without-match]
[-z | --null]
[-c | --count] [--all-match]
[--color | --no-color]
[-A <post-context>] [-B <pre-context>] [-C <context>]
[-f <file>] [-e] <pattern>
[--and|--or|--not|(|)|-e <pattern>...] [<tree>...]
@@ -105,6 +106,13 @@ OPTIONS
Instead of showing every matched line, show the number of
lines that match.
--color::
Show colored matches.
--no-color::
Turn off match highlighting, even when the configuration file
gives the default to color output.
-[ABC] <context>::
Show `context` trailing (`A` -- after), or leading (`B`
-- before), or both (`C` -- context) lines, and place a

View File

@@ -40,8 +40,8 @@ include::merge-options.txt[]
include::merge-strategies.txt[]
If you tried a merge which resulted in a complex conflicts and
would want to start over, you can recover with 'git-reset'.
If you tried a merge which resulted in complex conflicts and
want to start over, you can recover with 'git-reset'.
CONFIGURATION
-------------
@@ -146,7 +146,7 @@ And here is another line that is cleanly resolved or unmodified.
------------
The area where a pair of conflicting changes happened is marked with markers
"`<<<<<<<`", "`=======`", and "`>>>>>>>`". The part before the "`=======`"
`<<<<<<<`, `=======`, and `>>>>>>>`. The part before the `=======`
is typically your side, and the part afterwards is typically their side.
The default format does not show what the original said in the conflicting
@@ -173,8 +173,8 @@ Git makes conflict resolution easy.
And here is another line that is cleanly resolved or unmodified.
------------
In addition to the "`<<<<<<<`", "`=======`", and "`>>>>>>>`" markers, it uses
another "`|||||||`" marker that is followed by the original text. You can
In addition to the `<<<<<<<`, `=======`, and `>>>>>>>` markers, it uses
another `|||||||` marker that is followed by the original text. You can
tell that the original just stated a fact, and your side simply gave in to
that statement and gave up, while the other side tried to have a more
positive attitude. You can sometimes come up with a better resolution by

View File

@@ -20,7 +20,7 @@ IOW, you can use this thing to look for likely duplicate commits.
When dealing with 'git-diff-tree' output, it takes advantage of
the fact that the patch is prefixed with the object name of the
commit, and outputs two 40-byte hexadecimal string. The first
commit, and outputs two 40-byte hexadecimal strings. The first
string is the patch ID, and the second string is the commit ID.
This can be used to make a mapping from patch ID to commit ID.

View File

@@ -24,8 +24,8 @@ every time you push into it, by setting up 'hooks' there. See
documentation for linkgit:git-receive-pack[1].
OPTIONS
-------
OPTIONS[[OPTIONS]]
------------------
<repository>::
The "remote" repository that is destination of a push
operation. This parameter can be either a URL
@@ -187,6 +187,28 @@ reason::
Examples
--------
git push::
Works like `git push <remote>`, where <remote> is the
current branch's remote (or `origin`, if no remote is
configured for the current branch).
git push origin::
Without additional configuration, works like
`git push origin :`.
+
The default behavior of this command when no <refspec> is given can be
configured by setting the `push` option of the remote.
+
For example, to default to pushing only the current branch to `origin`
use `git config remote.origin.push HEAD`. Any valid <refspec> (like
the ones in the examples below) can be configured as the default for
`git push origin`.
git push origin :::
Push "matching" branches to `origin`. See
<refspec> in the <<OPTIONS,OPTIONS>> section above for a
description of "matching" branches.
git push origin master::
Find a ref that matches `master` in the source repository
(most likely, it would find `refs/heads/master`), and update

View File

@@ -258,11 +258,23 @@ OPTIONS
context exist they all must match. By default no context is
ever ignored.
-f::
--force-rebase::
Force the rebase even if the current branch is a descendant
of the commit you are rebasing onto. Normally the command will
exit with the message "Current branch is up to date" in such a
situation.
--whitespace=<option>::
This flag is passed to the 'git-apply' program
(see linkgit:git-apply[1]) that applies the patch.
Incompatible with the --interactive option.
--committer-date-is-author-date::
--ignore-date::
These flags are passed to 'git-am' to easily change the dates
of the rebased commits (see linkgit:git-am[1]).
-i::
--interactive::
Make a list of the commits which are about to be rebased. Let the

View File

@@ -13,6 +13,7 @@ SYNOPSIS
'git remote add' [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
'git remote rename' <old> <new>
'git remote rm' <name>
'git remote set-head' <name> [-a | -d | <branch>]
'git remote show' [-n] <name>
'git remote prune' [-n | --dry-run] <name>
'git remote update' [group]
@@ -53,8 +54,7 @@ is created. You can give more than one `-t <branch>` to track
multiple branches without grabbing all branches.
+
With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
up to point at remote's `<master>` branch instead of whatever
branch the `HEAD` at the remote repository actually points at.
up to point at remote's `<master>` branch. See also the set-head command.
+
In mirror mode, enabled with `\--mirror`, the refs will not be stored
in the 'refs/remotes/' namespace, but in 'refs/heads/'. This option
@@ -76,6 +76,30 @@ the configuration file format.
Remove the remote named <name>. All remote tracking branches and
configuration settings for the remote are removed.
'set-head'::
Sets or deletes the default branch (`$GIT_DIR/remotes/<name>/HEAD`) for
the named remote. Having a default branch for a remote is not required,
but allows the name of the remote to be specified in lieu of a specific
branch. For example, if the default branch for `origin` is set to
`master`, then `origin` may be specified wherever you would normally
specify `origin/master`.
+
With `-d`, `$GIT_DIR/remotes/<name>/HEAD` is deleted.
+
With `-a`, the remote is queried to determine its `HEAD`, then
`$GIT_DIR/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote
`HEAD` is pointed at `next`, "`git remote set-head origin -a`" will set
`$GIT_DIR/refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will
only work if `refs/remotes/origin/next` already exists; if not it must be
fetched first.
+
Use `<branch>` to set `$GIT_DIR/remotes/<name>/HEAD` explicitly. e.g., "git
remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to
`refs/remotes/origin/master`. This will only work if
`refs/remotes/origin/master` already exists; if not it must be fetched first.
+
'show'::
Gives some information about the remote <name>.

View File

@@ -299,18 +299,18 @@ previous section means the set of commits reachable from that
commit, following the commit ancestry chain.
To exclude commits reachable from a commit, a prefix `{caret}`
notation is used. E.g. "`{caret}r1 r2`" means commits reachable
notation is used. E.g. `{caret}r1 r2` means commits reachable
from `r2` but exclude the ones reachable from `r1`.
This set operation appears so often that there is a shorthand
for it. When you have two commits `r1` and `r2` (named according
to the syntax explained in SPECIFYING REVISIONS above), you can ask
for commits that are reachable from r2 excluding those that are reachable
from r1 by "`{caret}r1 r2`" and it can be written as "`r1..r2`".
from r1 by `{caret}r1 r2` and it can be written as `r1..r2`.
A similar notation "`r1\...r2`" is called symmetric difference
A similar notation `r1\...r2` is called symmetric difference
of `r1` and `r2` and is defined as
"`r1 r2 --not $(git merge-base --all r1 r2)`".
`r1 r2 --not $(git merge-base --all r1 r2)`.
It is the set of commits that are reachable from either one of
`r1` or `r2` but not from both.

View File

@@ -60,14 +60,13 @@ The --cc option must be repeated for each user you want on the cc list.
Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
introductory message for the patch series.
+
When '--compose' is used, git send-email gets less interactive will use the
values of the headers you set there. If the body of the email (what you type
after the headers and a blank line) only contains blank (or GIT: prefixed)
lines, the summary won't be sent, but git-send-email will still use the
Headers values if you don't removed them.
When '--compose' is used, git send-email will use the From, Subject, and
In-Reply-To headers specified in the message. If the body of the message
(what you type after the headers and a blank line) only contains blank
(or GIT: prefixed) lines the summary won't be sent, but From, Subject,
and In-Reply-To headers will be used unless they are removed.
+
If it wasn't able to see a header in the summary it will ask you about it
interactively after quitting your editor.
Missing From or In-Reply-To headers will be prompted for.
--from::
Specify the sender of the emails. This will default to

View File

@@ -385,7 +385,8 @@ config key: svn.authorsfile
-q::
--quiet::
Make 'git-svn' less verbose.
Make 'git-svn' less verbose. Specify a second time to make it
even less verbose.
--repack[=<n>]::
--repack-flags=<flags>::
@@ -672,9 +673,9 @@ listed below are allowed:
------------------------------------------------------------------------
[svn-remote "project-a"]
url = http://server.org/svn
fetch = trunk/project-a:refs/remotes/project-a/trunk
branches = branches/*/project-a:refs/remotes/project-a/branches/*
tags = tags/*/project-a:refs/remotes/project-a/tags/*
trunk = trunk/project-a:refs/remotes/project-a/trunk
------------------------------------------------------------------------
Keep in mind that the '*' (asterisk) wildcard of the local ref

View File

@@ -63,6 +63,7 @@ OPTIONS
are printed when using -l.
The default is not to print any annotation lines.
If no number is given to `-n`, only the first line is printed.
If the tag is not annotated, the commit message is displayed instead.
-l <pattern>::
List tags with names that match the given pattern (or all if no pattern is given).

View File

@@ -46,20 +46,20 @@ Here are the rules regarding the "flags" that you should follow when you are
scripting git:
* it's preferred to use the non dashed form of git commands, which means that
you should prefer `"git foo"` to `"git-foo"`.
you should prefer `git foo` to `git-foo`.
* splitting short options to separate words (prefer `"git foo -a -b"`
to `"git foo -ab"`, the latter may not even work).
* splitting short options to separate words (prefer `git foo -a -b`
to `git foo -ab`, the latter may not even work).
* when a command line option takes an argument, use the 'sticked' form. In
other words, write `"git foo -oArg"` instead of `"git foo -o Arg"` for short
options, and `"git foo --long-opt=Arg"` instead of `"git foo --long-opt Arg"`
other words, write `git foo -oArg` instead of `git foo -o Arg` for short
options, and `git foo --long-opt=Arg` instead of `git foo --long-opt Arg`
for long options. An option that takes optional option-argument must be
written in the 'sticked' form.
* when you give a revision parameter to a command, make sure the parameter is
not ambiguous with a name of a file in the work tree. E.g. do not write
`"git log -1 HEAD"` but write `"git log -1 HEAD --"`; the former will not work
`git log -1 HEAD` but write `git log -1 HEAD --`; the former will not work
if you happen to have a file called `HEAD` in the work tree.
@@ -99,17 +99,17 @@ usage: git-describe [options] <committish>*
Negating options
~~~~~~~~~~~~~~~~
Options with long option names can be negated by prefixing `"--no-"`. For
example, `"git branch"` has the option `"--track"` which is 'on' by default. You
can use `"--no-track"` to override that behaviour. The same goes for `"--color"`
and `"--no-color"`.
Options with long option names can be negated by prefixing `--no-`. For
example, `git branch` has the option `--track` which is 'on' by default. You
can use `--no-track` to override that behaviour. The same goes for `--color`
and `--no-color`.
Aggregating short options
~~~~~~~~~~~~~~~~~~~~~~~~~
Commands that support the enhanced option parser allow you to aggregate short
options. This means that you can for example use `"git rm -rf"` or
`"git clean -fdx"`.
options. This means that you can for example use `git rm -rf` or
`git clean -fdx`.
Separating argument from the option

View File

@@ -151,6 +151,10 @@ indicating whether the checkout was a branch checkout (changing branches,
flag=1) or a file checkout (retrieving a file from the index, flag=0).
This hook cannot affect the outcome of 'git-checkout'.
It is also run after 'git-clone', unless the --no-checkout (-n) option is
used. The first parameter given to the hook is the null-ref, the second the
ref of the new HEAD and the flag is always 1.
This hook can be used to perform repository validity checks, auto-display
differences from the previous HEAD if different, or set working dir metadata
properties.

View File

@@ -262,7 +262,7 @@ This commit is referred to as a "merge commit", or sometimes just a
'origin' is used for that purpose. New upstream updates
will be fetched into remote <<def_tracking_branch,tracking branches>> named
origin/name-of-upstream-branch, which you can see using
"`git branch -r`".
`git branch -r`.
[[def_pack]]pack::
A set of objects which have been compressed into one file (to save space

View File

@@ -5,22 +5,21 @@ canonical real names and email addresses.
In the simple form, each line in the file consists of the canonical
real name of an author, whitespace, and an email address used in the
commit (enclosed by '<' and '>') to map to the name. Thus, looks like
this
commit (enclosed by '<' and '>') to map to the name. For example:
--
Proper Name <commit@email.xx>
--
The more complex forms are
The more complex forms are:
--
<proper@email.xx> <commit@email.xx>
--
which allows mailmap to replace only the email part of a commit, and
which allows mailmap to replace only the email part of a commit, and:
--
Proper Name <proper@email.xx> <commit@email.xx>
--
which allows mailmap to replace both the name and the email of a
commit matching the specified commit email address, and
commit matching the specified commit email address, and:
--
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
--
@@ -47,8 +46,8 @@ Jane Doe <jane@desktop.(none)>
Joe R. Developer <joe@example.com>
------------
Note how we don't need an entry for <jane@laptop.(none)>, because the
real name of that author is correct already.
Note how there is no need for an entry for <jane@laptop.(none)>, because the
real name of that author is already correct.
Example 2: Your repository contains commits from the following
authors:
@@ -62,7 +61,7 @@ claus <me@company.xx>
CTO <cto@coompany.xx>
------------
Then, you might want a `.mailmap` file looking like:
Then you might want a `.mailmap` file that looks like:
------------
<cto@company.xx> <cto@coompany.xx>
Some Dude <some@dude.xx> nick1 <bugs@company.xx>
@@ -72,4 +71,4 @@ Santa Claus <santa.claus@northpole.xx> <me@company.xx>
------------
Use hash '#' for comments that are either on their own line, or after
the email address.
the email address.

View File

@@ -1,21 +1,14 @@
<!-- Based on callouts.xsl. Fixes man page callouts for DocBook 1.72 XSL -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- manpage-1.72.xsl:
special settings for manpages rendered from asciidoc+docbook
handles peculiarities in docbook-xsl 1.72.0 -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="man.output.quietly" select="1"/>
<xsl:param name="refentry.meta.get.quietly" select="1"/>
<xsl:import href="manpage-base.xsl"/>
<xsl:template match="co">
<xsl:value-of select="concat('&#x2593;fB(',substring-after(@id,'-'),')&#x2593;fR')"/>
</xsl:template>
<xsl:template match="calloutlist">
<xsl:text>&#x2302;sp&#10;</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="callout">
<xsl:value-of select="concat('&#x2593;fB',substring-after(@arearefs,'-'),'. &#x2593;fR')"/>
<xsl:apply-templates/>
<xsl:text>&#x2302;br&#10;</xsl:text>
</xsl:template>
<!-- these are the special values for the roff control characters
needed for docbook-xsl 1.72.0 -->
<xsl:param name="git.docbook.backslash">&#x2593;</xsl:param>
<xsl:param name="git.docbook.dot" >&#x2302;</xsl:param>
</xsl:stylesheet>

View File

@@ -0,0 +1,35 @@
<!-- manpage-base.xsl:
special formatting for manpages rendered from asciidoc+docbook -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- these params silence some output from xmlto -->
<xsl:param name="man.output.quietly" select="1"/>
<xsl:param name="refentry.meta.get.quietly" select="1"/>
<!-- convert asciidoc callouts to man page format;
git.docbook.backslash and git.docbook.dot params
must be supplied by another XSL file or other means -->
<xsl:template match="co">
<xsl:value-of select="concat(
$git.docbook.backslash,'fB(',
substring-after(@id,'-'),')',
$git.docbook.backslash,'fR')"/>
</xsl:template>
<xsl:template match="calloutlist">
<xsl:value-of select="$git.docbook.dot"/>
<xsl:text>sp&#10;</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="callout">
<xsl:value-of select="concat(
$git.docbook.backslash,'fB',
substring-after(@arearefs,'-'),
'. ',$git.docbook.backslash,'fR')"/>
<xsl:apply-templates/>
<xsl:value-of select="$git.docbook.dot"/>
<xsl:text>br&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,17 @@
<!-- manpage-bold-literal.xsl:
special formatting for manpages rendered from asciidoc+docbook -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- render literal text as bold (instead of plain or monospace);
this makes literal text easier to distinguish in manpages
viewed on a tty -->
<xsl:template match="literal">
<xsl:value-of select="$git.docbook.backslash"/>
<xsl:text>fB</xsl:text>
<xsl:apply-templates/>
<xsl:value-of select="$git.docbook.backslash"/>
<xsl:text>fR</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,13 @@
<!-- manpage-normal.xsl:
special settings for manpages rendered from asciidoc+docbook
handles anything we want to keep away from docbook-xsl 1.72.0 -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="manpage-base.xsl"/>
<!-- these are the normal values for the roff control characters -->
<xsl:param name="git.docbook.backslash">\</xsl:param>
<xsl:param name="git.docbook.dot" >.</xsl:param>
</xsl:stylesheet>

View File

@@ -0,0 +1,21 @@
<!-- manpage-suppress-sp.xsl:
special settings for manpages rendered from asciidoc+docbook
handles erroneous, inline .sp in manpage output of some
versions of docbook-xsl -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- attempt to work around spurious .sp at the tail of the line
that some versions of docbook stylesheets seem to add -->
<xsl:template match="simpara">
<xsl:variable name="content">
<xsl:apply-templates/>
</xsl:variable>
<xsl:value-of select="normalize-space($content)"/>
<xsl:if test="not(ancestor::authorblurb) and
not(ancestor::personblurb)">
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

View File

@@ -3,15 +3,15 @@ MERGE STRATEGIES
resolve::
This can only resolve two heads (i.e. the current branch
and another branch you pulled from) using 3-way merge
and another branch you pulled from) using a 3-way merge
algorithm. It tries to carefully detect criss-cross
merge ambiguities and is considered generally safe and
fast.
recursive::
This can only resolve two heads using 3-way merge
algorithm. When there are more than one common
ancestors that can be used for 3-way merge, it creates a
This can only resolve two heads using a 3-way merge
algorithm. When there is more than one common
ancestor that can be used for 3-way merge, it creates a
merged tree of the common ancestors and uses that as
the reference tree for the 3-way merge. This has been
reported to result in fewer merge conflicts without
@@ -22,11 +22,11 @@ recursive::
pulling or merging one branch.
octopus::
This resolves more than two-head case, but refuses to do
complex merge that needs manual resolution. It is
This resolves cases with more than two heads, but refuses to do
a complex merge that needs manual resolution. It is
primarily meant to be used for bundling topic branch
heads together. This is the default merge strategy when
pulling or merging more than one branches.
pulling or merging more than one branch.
ours::
This resolves any number of heads, but the result of the

View File

@@ -148,22 +148,22 @@ outputting that information, if desired.
------------
*
*
M
*
|\
* |
| | *
| \ \
| \ \
M-. \ \
*-. \ \
|\ \ \ \
| | * | |
| | | | | *
| | | | | *
| | | | | M
| | | | | *
| | | | | |\
| | | | | | *
| * | | | | |
| | | | | M \
| | | | | * \
| | | | | |\ |
| | | | * | | |
| | | | * | | |

View File

@@ -1136,10 +1136,10 @@ Ignoring files
A project will often generate files that you do 'not' want to track with git.
This typically includes files generated by a build process or temporary
backup files made by your editor. Of course, 'not' tracking files with git
is just a matter of 'not' calling "`git-add`" on them. But it quickly becomes
is just a matter of 'not' calling `git-add` on them. But it quickly becomes
annoying to have these untracked files lying around; e.g. they make
"`git add .`" practically useless, and they keep showing up in the output of
"`git status`".
`git add .` practically useless, and they keep showing up in the output of
`git status`.
You can tell git to ignore certain files by creating a file called .gitignore
in the top level of your working directory, with contents such as:

View File

@@ -126,6 +126,12 @@ all::
# randomly break unless your underlying filesystem supports those sub-second
# times (my ext3 doesn't).
#
# Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
# "st_ctim"
#
# Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec"
# available. This automatically turns USE_NSEC off.
#
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-index perspective.
#
@@ -258,6 +264,18 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
BASIC_CFLAGS =
BASIC_LDFLAGS =
# Guard against environment variables
BUILTIN_OBJS =
BUILT_INS =
COMPAT_CFLAGS =
COMPAT_OBJS =
LIB_H =
LIB_OBJS =
PROGRAMS =
SCRIPT_PERL =
SCRIPT_SH =
TEST_PROGRAMS =
SCRIPT_SH += git-am.sh
SCRIPT_SH += git-bisect.sh
SCRIPT_SH += git-filter-branch.sh
@@ -658,6 +676,7 @@ ifeq ($(uname_S),Darwin)
endif
NO_MEMMEM = YesPlease
THREADED_DELTA_SEARCH = YesPlease
USE_ST_TIMESPEC = YesPlease
endif
ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
@@ -707,6 +726,7 @@ ifeq ($(uname_S),FreeBSD)
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
USE_ST_TIMESPEC = YesPlease
THREADED_DELTA_SEARCH = YesPlease
ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
PTHREAD_LIBS = -pthread
@@ -735,6 +755,7 @@ ifeq ($(uname_S),AIX)
NO_MEMMEM = YesPlease
NO_MKDTEMP = YesPlease
NO_STRLCPY = YesPlease
NO_NSEC = YesPlease
FREAD_READS_DIRECTORIES = UnfortunatelyYes
INTERNAL_QSORT = UnfortunatelyYes
NEEDS_LIBICONV=YesPlease
@@ -804,6 +825,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
RUNTIME_PREFIX = YesPlease
NO_POSIX_ONLY_PROGRAMS = YesPlease
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
NO_NSEC = YesPlease
USE_WIN32_MMAP = YesPlease
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
@@ -926,6 +948,15 @@ endif
ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
endif
ifdef USE_NSEC
BASIC_CFLAGS += -DUSE_NSEC
endif
ifdef USE_ST_TIMESPEC
BASIC_CFLAGS += -DUSE_ST_TIMESPEC
endif
ifdef NO_NSEC
BASIC_CFLAGS += -DNO_NSEC
endif
ifdef NO_C99_FORMAT
BASIC_CFLAGS += -DNO_C99_FORMAT
endif
@@ -973,6 +1004,11 @@ endif
ifdef NO_MMAP
COMPAT_CFLAGS += -DNO_MMAP
COMPAT_OBJS += compat/mmap.o
else
ifdef USE_WIN32_MMAP
COMPAT_CFLAGS += -DUSE_WIN32_MMAP
COMPAT_OBJS += compat/win32mmap.o
endif
endif
ifdef USE_WIN32_MMAP
COMPAT_CFLAGS += -DUSE_WIN32_MMAP
@@ -1373,6 +1409,7 @@ GIT-CFLAGS: .FORCE-GIT-CFLAGS
GIT-BUILD-OPTIONS: .FORCE-GIT-BUILD-OPTIONS
@echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
### Detect Tck/Tk interpreter path changes
ifndef NO_TCLTK

73
attr.c
View File

@@ -1,3 +1,4 @@
#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"
#include "attr.h"
@@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
return res;
}
static enum git_attr_direction direction;
static struct index_state *use_index;
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
{
FILE *fp = fopen(path, "r");
@@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
unsigned long sz;
enum object_type type;
void *data;
struct index_state *istate = use_index ? use_index : &the_index;
len = strlen(path);
pos = cache_name_pos(path, len);
pos = index_name_pos(istate, path, len);
if (pos < 0) {
/*
* We might be in the middle of a merge, in which
@@ -350,15 +355,15 @@ static void *read_index_data(const char *path)
*/
int i;
for (i = -pos - 1;
(pos < 0 && i < active_nr &&
!strcmp(active_cache[i]->name, path));
(pos < 0 && i < istate->cache_nr &&
!strcmp(istate->cache[i]->name, path));
i++)
if (ce_stage(active_cache[i]) == 2)
if (ce_stage(istate->cache[i]) == 2)
pos = i;
}
if (pos < 0)
return NULL;
data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
if (!data || type != OBJ_BLOB) {
free(data);
return NULL;
@@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
return data;
}
static struct attr_stack *read_attr(const char *path, int macro_ok)
static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
{
struct attr_stack *res;
char *buf, *sp;
int lineno = 0;
res = read_attr_from_file(path, macro_ok);
if (res)
return res;
res = xcalloc(1, sizeof(*res));
/*
* There is no checked out .gitattributes file there, but
* we might have it in the index. We allow operation in a
* sparsely checked out work tree, so read from it.
*/
buf = read_index_data(path);
if (!buf)
return res;
return NULL;
res = xcalloc(1, sizeof(*res));
for (sp = buf; *sp; ) {
char *ep;
int more;
@@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
return res;
}
static struct attr_stack *read_attr(const char *path, int macro_ok)
{
struct attr_stack *res;
if (direction == GIT_ATTR_CHECKOUT) {
res = read_attr_from_index(path, macro_ok);
if (!res)
res = read_attr_from_file(path, macro_ok);
}
else {
res = read_attr_from_file(path, macro_ok);
if (!res)
/*
* There is no checked out .gitattributes file there, but
* we might have it in the index. We allow operation in a
* sparsely checked out work tree, so read from it.
*/
res = read_attr_from_index(path, macro_ok);
}
if (!res)
res = xcalloc(1, sizeof(*res));
return res;
}
#if DEBUG_ATTR
static void debug_info(const char *what, struct attr_stack *elem)
{
@@ -428,6 +447,15 @@ static void debug_set(const char *what, const char *match, struct git_attr *attr
#define debug_set(a,b,c,d) do { ; } while (0)
#endif
static void drop_attr_stack(void)
{
while (attr_stack) {
struct attr_stack *elem = attr_stack;
attr_stack = elem->prev;
free_attr_elem(elem);
}
}
static void bootstrap_attr_stack(void)
{
if (!attr_stack) {
@@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
return 0;
}
void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
{
enum git_attr_direction old = direction;
direction = new;
if (new != old)
drop_attr_stack();
use_index = istate;
}

6
attr.h
View File

@@ -31,4 +31,10 @@ struct git_attr_check {
int git_checkattr(const char *path, int, struct git_attr_check *);
enum git_attr_direction {
GIT_ATTR_CHECKIN,
GIT_ATTR_CHECKOUT
};
void git_attr_set_direction(enum git_attr_direction, struct index_state *);
#endif /* ATTR_H */

View File

@@ -32,21 +32,59 @@ static int find_tracked_branch(struct remote *remote, void *priv)
return 0;
}
static int should_setup_rebase(const struct tracking *tracking)
static int should_setup_rebase(const char *origin)
{
switch (autorebase) {
case AUTOREBASE_NEVER:
return 0;
case AUTOREBASE_LOCAL:
return tracking->remote == NULL;
return origin == NULL;
case AUTOREBASE_REMOTE:
return tracking->remote != NULL;
return origin != NULL;
case AUTOREBASE_ALWAYS:
return 1;
}
return 0;
}
void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
{
struct strbuf key = STRBUF_INIT;
int rebasing = should_setup_rebase(origin);
strbuf_addf(&key, "branch.%s.remote", local);
git_config_set(key.buf, origin ? origin : ".");
strbuf_reset(&key);
strbuf_addf(&key, "branch.%s.merge", local);
git_config_set(key.buf, remote);
if (rebasing) {
strbuf_reset(&key);
strbuf_addf(&key, "branch.%s.rebase", local);
git_config_set(key.buf, "true");
}
if (flag & BRANCH_CONFIG_VERBOSE) {
strbuf_reset(&key);
strbuf_addstr(&key, origin ? "remote" : "local");
/* Are we tracking a proper "branch"? */
if (!prefixcmp(remote, "refs/heads/")) {
strbuf_addf(&key, " branch %s", remote + 11);
if (origin)
strbuf_addf(&key, " from %s", origin);
}
else
strbuf_addf(&key, " ref %s", remote);
printf("Branch %s set up to track %s%s.\n",
local, key.buf,
rebasing ? " by rebasing" : "");
}
strbuf_release(&key);
}
/*
* This is called when new_ref is branched off of orig_ref, and tries
* to infer the settings for branch.<new_ref>.{remote,merge} from the
@@ -55,7 +93,6 @@ static int should_setup_rebase(const struct tracking *tracking)
static int setup_tracking(const char *new_ref, const char *orig_ref,
enum branch_track track)
{
char key[1024];
struct tracking tracking;
if (strlen(new_ref) > 1024 - 7 - 7 - 1)
@@ -80,19 +117,10 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
return error("Not tracking: ambiguous information for ref %s",
orig_ref);
sprintf(key, "branch.%s.remote", new_ref);
git_config_set(key, tracking.remote ? tracking.remote : ".");
sprintf(key, "branch.%s.merge", new_ref);
git_config_set(key, tracking.src ? tracking.src : orig_ref);
printf("Branch %s set up to track %s branch %s.\n", new_ref,
tracking.remote ? "remote" : "local", orig_ref);
if (should_setup_rebase(&tracking)) {
sprintf(key, "branch.%s.rebase", new_ref);
git_config_set(key, "true");
printf("This branch will rebase on pull.\n");
}
free(tracking.src);
install_branch_config(BRANCH_CONFIG_VERBOSE, new_ref, tracking.remote,
tracking.src ? tracking.src : orig_ref);
free(tracking.src);
return 0;
}

View File

@@ -21,4 +21,11 @@ void create_branch(const char *head, const char *name, const char *start_name,
*/
void remove_branch_state(void);
/*
* Configure local branch "local" to merge remote branch "remote"
* taken from origin "origin".
*/
#define BRANCH_CONFIG_VERBOSE 01
extern void install_branch_config(int flag, const char *local, const char *origin, const char *remote);
#endif

View File

@@ -104,7 +104,7 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,
/* Set up the default git porcelain excludes */
memset(dir, 0, sizeof(*dir));
if (!ignored_too) {
dir->collect_ignored = 1;
dir->flags |= DIR_COLLECT_IGNORED;
setup_standard_excludes(dir);
}
@@ -148,7 +148,7 @@ static const char **validate_pathspec(int argc, const char **argv, const char *p
if (pathspec) {
const char **p;
for (p = pathspec; *p; p++) {
if (has_symlink_leading_path(strlen(*p), *p)) {
if (has_symlink_leading_path(*p, strlen(*p))) {
int len = prefix ? strlen(prefix) : 0;
die("'%s' is beyond a symbolic link", *p + len);
}

View File

@@ -2360,7 +2360,7 @@ static int check_to_create_blob(const char *new_name, int ok_if_exists)
* In such a case, path "new_name" does not exist as
* far as git is concerned.
*/
if (has_symlink_leading_path(strlen(new_name), new_name))
if (has_symlink_leading_path(new_name, strlen(new_name)))
return 0;
return error("%s: already exists in working directory", new_name);
@@ -2451,7 +2451,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
if ((st_mode ^ patch->old_mode) & S_IFMT)
return error("%s: wrong type", old_name);
if (st_mode != patch->old_mode)
fprintf(stderr, "warning: %s has type %o, expected %o\n",
warning("%s has type %o, expected %o",
old_name, st_mode, patch->old_mode);
if (!patch->new_mode && !patch->is_delete)
patch->new_mode = st_mode;
@@ -2932,8 +2932,7 @@ static int write_out_one_reject(struct patch *patch)
cnt = strlen(patch->new_name);
if (ARRAY_SIZE(namebuf) <= cnt + 5) {
cnt = ARRAY_SIZE(namebuf) - 5;
fprintf(stderr,
"warning: truncating .rej filename to %.*s.rej",
warning("truncating .rej filename to %.*s.rej",
cnt - 1, patch->new_name);
}
memcpy(namebuf, patch->new_name, cnt);
@@ -3212,7 +3211,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
struct option builtin_apply_options[] = {
{ OPTION_CALLBACK, 0, "exclude", NULL, "path",
"don´t apply changes matching the given 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",
@@ -3224,10 +3223,10 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
"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"),
{ OPTION_BOOLEAN, 0, "allow-binary-replacement", &binary,
NULL, "old option, now no-op", PARSE_OPT_HIDDEN },
{ OPTION_BOOLEAN, 0, "binary", &binary,
NULL, "old option, now no-op", PARSE_OPT_HIDDEN },
OPT_BOOLEAN(0, "numstat", &numstat,
"shows number of added and deleted lines in decimal notation"),
OPT_BOOLEAN(0, "summary", &summary,
@@ -3315,8 +3314,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
squelch_whitespace_errors < whitespace_error) {
int squelched =
whitespace_error - squelch_whitespace_errors;
fprintf(stderr, "warning: squelched %d "
"whitespace error%s\n",
warning("squelched %d "
"whitespace error%s",
squelched,
squelched == 1 ? "" : "s");
}
@@ -3326,12 +3325,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
whitespace_error == 1 ? "" : "s",
whitespace_error == 1 ? "s" : "");
if (applied_after_fixing_ws && apply)
fprintf(stderr, "warning: %d line%s applied after"
" fixing whitespace errors.\n",
warning("%d line%s applied after"
" fixing whitespace errors.",
applied_after_fixing_ws,
applied_after_fixing_ws == 1 ? "" : "s");
else if (whitespace_error)
fprintf(stderr, "warning: %d line%s add%s whitespace errors.\n",
warning("%d line%s add%s whitespace errors.",
whitespace_error,
whitespace_error == 1 ? "" : "s",
whitespace_error == 1 ? "s" : "");

View File

@@ -2250,6 +2250,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
parse_done:
argc = parse_options_end(&ctx);
if (revs_file && read_ancestry(revs_file))
die("reading graft file %s failed: %s",
revs_file, strerror(errno));
if (cmd_is_annotate) {
output_option |= OUTPUT_ANNOTATE_COMPAT;
blame_date_mode = DATE_ISO8601;
@@ -2418,10 +2422,6 @@ parse_done:
sb.ent = ent;
sb.path = path;
if (revs_file && read_ancestry(revs_file))
die("reading graft file %s failed: %s",
revs_file, strerror(errno));
read_mailmap(&mailmap, NULL);
if (!incremental)

View File

@@ -171,7 +171,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
ret = 1;
} else {
struct strbuf buf = STRBUF_INIT;
printf("Deleted %sbranch %s (%s).\n", remote,
printf("Deleted %sbranch %s (was %s).\n", remote,
bname.buf,
find_unique_abbrev(sha1, DEFAULT_ABBREV));
strbuf_addf(&buf, "branch.%s", bname.buf);

View File

@@ -407,7 +407,7 @@ static int merge_working_tree(struct checkout_opts *opts,
topts.verbose_update = !opts->quiet;
topts.fn = twoway_merge;
topts.dir = xcalloc(1, sizeof(*topts.dir));
topts.dir->show_ignored = 1;
topts.dir->flags |= DIR_SHOW_IGNORED;
topts.dir->exclude_per_dir = ".gitignore";
tree = parse_tree_indirect(old->commit->object.sha1);
init_tree_desc(&trees[0], tree->buffer, tree->size);
@@ -558,8 +558,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
if (!old.commit && !opts->force) {
if (!opts->quiet) {
fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
warning("You appear to be on a branch yet to be born.");
warning("Forcing checkout of %s.", new->name);
}
opts->force = 1;
}

View File

@@ -60,7 +60,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
memset(&dir, 0, sizeof(dir));
if (ignored_only)
dir.show_ignored = 1;
dir.flags |= DIR_SHOW_IGNORED;
if (ignored && ignored_only)
die("-x and -X cannot be used together");
@@ -69,7 +69,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
die("clean.requireForce%s set and -n or -f not given; "
"refusing to clean", config_set ? "" : " not");
dir.show_other_directories = 1;
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
if (!ignored)
setup_standard_excludes(&dir);

View File

@@ -20,6 +20,8 @@
#include "dir.h"
#include "pack-refs.h"
#include "sigchain.h"
#include "branch.h"
#include "remote.h"
#include "run-command.h"
/*
@@ -268,7 +270,7 @@ static const struct ref *clone_local(const char *src_repo,
static const char *junk_work_tree;
static const char *junk_git_dir;
pid_t junk_pid;
static pid_t junk_pid;
static void remove_junk(void)
{
@@ -294,43 +296,6 @@ static void remove_junk_on_signal(int signo)
raise(signo);
}
static const struct ref *locate_head(const struct ref *refs,
const struct ref *mapped_refs,
const struct ref **remote_head_p)
{
const struct ref *remote_head = NULL;
const struct ref *remote_master = NULL;
const struct ref *r;
for (r = refs; r; r = r->next)
if (!strcmp(r->name, "HEAD"))
remote_head = r;
for (r = mapped_refs; r; r = r->next)
if (!strcmp(r->name, "refs/heads/master"))
remote_master = r;
if (remote_head_p)
*remote_head_p = remote_head;
/* If there's no HEAD value at all, never mind. */
if (!remote_head)
return NULL;
/* If refs/heads/master could be right, it is. */
if (remote_master && !hashcmp(remote_master->old_sha1,
remote_head->old_sha1))
return remote_master;
/* Look for another ref that points there */
for (r = mapped_refs; r; r = r->next)
if (r != remote_head &&
!hashcmp(r->old_sha1, remote_head->old_sha1))
return r;
/* Nothing is the same */
return NULL;
}
static struct ref *write_remote_refs(const struct ref *refs,
struct refspec *refspec, const char *reflog)
{
@@ -351,19 +316,6 @@ static struct ref *write_remote_refs(const struct ref *refs,
return local_refs;
}
static void install_branch_config(const char *local,
const char *origin,
const char *remote)
{
struct strbuf key = STRBUF_INIT;
strbuf_addf(&key, "branch.%s.remote", local);
git_config_set(key.buf, origin);
strbuf_reset(&key);
strbuf_addf(&key, "branch.%s.merge", local);
git_config_set(key.buf, remote);
strbuf_release(&key);
}
int cmd_clone(int argc, const char **argv, const char *prefix)
{
int is_bundle = 0;
@@ -378,7 +330,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
char *src_ref_prefix = "refs/heads/";
int err = 0;
struct refspec refspec;
struct refspec *refspec;
const char *fetch_pattern;
junk_pid = getpid();
@@ -453,7 +406,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
atexit(remove_junk);
sigchain_push_common(remove_junk_on_signal);
setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1);
setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
if (safe_create_leading_directories_const(git_dir) < 0)
die("could not create leading directories of '%s'", git_dir);
@@ -483,8 +436,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
}
strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
if (option_mirror || !option_bare) {
/* Configure the remote */
strbuf_addf(&key, "remote.%s.fetch", option_origin);
git_config_set_multivar(key.buf, value.buf, "^$", 0);
strbuf_reset(&key);
if (option_mirror) {
strbuf_addf(&key, "remote.%s.mirror", option_origin);
git_config_set(key.buf, "true");
@@ -493,19 +452,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_addf(&key, "remote.%s.url", option_origin);
git_config_set(key.buf, repo);
strbuf_reset(&key);
strbuf_addf(&key, "remote.%s.fetch", option_origin);
strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
git_config_set_multivar(key.buf, value.buf, "^$", 0);
strbuf_reset(&key);
strbuf_reset(&value);
}
refspec.force = 0;
refspec.pattern = 1;
refspec.src = src_ref_prefix;
refspec.dst = branch_top.buf;
fetch_pattern = value.buf;
refspec = parse_fetch_refspec(1, &fetch_pattern);
strbuf_reset(&value);
if (path && !is_bundle)
refs = clone_local(path, git_dir);
@@ -539,9 +492,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
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);
remote_head = find_ref_by_name(refs, "HEAD");
head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
}
else {
warning("You appear to have cloned an empty repository.");
@@ -549,7 +503,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
remote_head = NULL;
option_no_checkout = 1;
if (!option_bare)
install_branch_config("master", option_origin,
install_branch_config(0, "master", option_origin,
"refs/heads/master");
}
@@ -579,7 +533,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
head_points_at->peer_ref->name,
reflog_msg.buf);
install_branch_config(head, option_origin,
install_branch_config(0, head, option_origin,
head_points_at->name);
}
} else if (remote_head) {

View File

@@ -1,9 +1,12 @@
#include "builtin.h"
#include "cache.h"
#include "color.h"
#include "parse-options.h"
static const char git_config_set_usage[] =
"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty] | --edit | -e ]";
static const char *const builtin_config_usage[] = {
"git config [options]",
NULL
};
static char *key;
static regex_t *key_regexp;
@@ -16,7 +19,67 @@ static int seen;
static char delim = '=';
static char key_delim = ' ';
static char term = '\n';
static enum { T_RAW, T_INT, T_BOOL, T_BOOL_OR_INT } type = T_RAW;
static int use_global_config, use_system_config;
static const char *given_config_file;
static int actions, types;
static const char *get_color_slot, *get_colorbool_slot;
static int end_null;
#define ACTION_GET (1<<0)
#define ACTION_GET_ALL (1<<1)
#define ACTION_GET_REGEXP (1<<2)
#define ACTION_REPLACE_ALL (1<<3)
#define ACTION_ADD (1<<4)
#define ACTION_UNSET (1<<5)
#define ACTION_UNSET_ALL (1<<6)
#define ACTION_RENAME_SECTION (1<<7)
#define ACTION_REMOVE_SECTION (1<<8)
#define ACTION_LIST (1<<9)
#define ACTION_EDIT (1<<10)
#define ACTION_SET (1<<11)
#define ACTION_SET_ALL (1<<12)
#define ACTION_GET_COLOR (1<<13)
#define ACTION_GET_COLORBOOL (1<<14)
#define TYPE_BOOL (1<<0)
#define TYPE_INT (1<<1)
#define TYPE_BOOL_OR_INT (1<<2)
static struct option builtin_config_options[] = {
OPT_GROUP("Config file location"),
OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"),
OPT_GROUP("Action"),
OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL),
OPT_BIT(0, "get-regexp", &actions, "get values for regexp: name-regex [value-regex]", ACTION_GET_REGEXP),
OPT_BIT(0, "replace-all", &actions, "replace all matching variables: name value [value_regex]", ACTION_REPLACE_ALL),
OPT_BIT(0, "add", &actions, "adds a new variable: name value", ACTION_ADD),
OPT_BIT(0, "unset", &actions, "removes a variable: name [value-regex]", ACTION_UNSET),
OPT_BIT(0, "unset-all", &actions, "removes all matches: name [value-regex]", ACTION_UNSET_ALL),
OPT_BIT(0, "rename-section", &actions, "rename section: old-name new-name", ACTION_RENAME_SECTION),
OPT_BIT(0, "remove-section", &actions, "remove a section: name", ACTION_REMOVE_SECTION),
OPT_BIT('l', "list", &actions, "list all", ACTION_LIST),
OPT_BIT('e', "edit", &actions, "opens an editor", ACTION_EDIT),
OPT_STRING(0, "get-color", &get_color_slot, "slot", "find the color configured: [default]"),
OPT_STRING(0, "get-colorbool", &get_colorbool_slot, "slot", "find the color setting: [stdout-is-tty]"),
OPT_GROUP("Type"),
OPT_BIT(0, "bool", &types, "value is \"true\" or \"false\"", TYPE_BOOL),
OPT_BIT(0, "int", &types, "value is decimal number", TYPE_INT),
OPT_BIT(0, "bool-or-int", &types, "value is --bool or --int", TYPE_BOOL_OR_INT),
OPT_GROUP("Other"),
OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"),
OPT_END(),
};
static void check_argc(int argc, int min, int max) {
if (argc >= min && argc <= max)
return;
error("wrong number of arguments");
usage_with_options(builtin_config_usage, builtin_config_options);
}
static int show_all_config(const char *key_, const char *value_, void *cb)
{
@@ -49,11 +112,11 @@ static int show_config(const char *key_, const char *value_, void *cb)
}
if (seen && !do_all)
dup_error = 1;
if (type == T_INT)
if (types == TYPE_INT)
sprintf(value, "%d", git_config_int(key_, value_?value_:""));
else if (type == T_BOOL)
else if (types == TYPE_BOOL)
vptr = git_config_bool(key_, value_) ? "true" : "false";
else if (type == T_BOOL_OR_INT) {
else if (types == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key_, value_, &is_bool);
if (is_bool)
@@ -152,18 +215,18 @@ static char *normalize_value(const char *key, const char *value)
if (!value)
return NULL;
if (type == T_RAW)
if (types == 0)
normalized = xstrdup(value);
else {
normalized = xmalloc(64);
if (type == T_INT) {
if (types == TYPE_INT) {
int v = git_config_int(key, value);
sprintf(normalized, "%d", v);
}
else if (type == T_BOOL)
else if (types == TYPE_BOOL)
sprintf(normalized, "%s",
git_config_bool(key, value) ? "true" : "false");
else if (type == T_BOOL_OR_INT) {
else if (types == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key, value, &is_bool);
if (!is_bool)
@@ -178,6 +241,7 @@ static char *normalize_value(const char *key, const char *value)
static int get_color_found;
static const char *get_color_slot;
static const char *get_colorbool_slot;
static char parsed_color[COLOR_MAXLEN];
static int git_get_color_config(const char *var, const char *value, void *cb)
@@ -191,29 +255,8 @@ static int git_get_color_config(const char *var, const char *value, void *cb)
return 0;
}
static int get_color(int argc, const char **argv)
static void get_color(const char *def_color)
{
/*
* grab the color setting for the given slot from the configuration,
* or parse the default value if missing, and return ANSI color
* escape sequence.
*
* e.g.
* git config --get-color color.diff.whitespace "blue reverse"
*/
const char *def_color = NULL;
switch (argc) {
default:
usage(git_config_set_usage);
case 2:
def_color = argv[1];
/* fallthru */
case 1:
get_color_slot = argv[0];
break;
}
get_color_found = 0;
parsed_color[0] = '\0';
git_config(git_get_color_config, NULL);
@@ -222,7 +265,6 @@ static int get_color(int argc, const char **argv)
color_parse(def_color, "command line", parsed_color);
fputs(parsed_color, stdout);
return 0;
}
static int stdout_is_tty;
@@ -231,7 +273,7 @@ static int get_diff_color_found;
static int git_get_colorbool_config(const char *var, const char *value,
void *cb)
{
if (!strcmp(var, get_color_slot)) {
if (!strcmp(var, get_colorbool_slot)) {
get_colorbool_found =
git_config_colorbool(var, value, stdout_is_tty);
}
@@ -246,191 +288,188 @@ static int git_get_colorbool_config(const char *var, const char *value,
return 0;
}
static int get_colorbool(int argc, const char **argv)
static int get_colorbool(int print)
{
/*
* git config --get-colorbool <slot> [<stdout-is-tty>]
*
* returns "true" or "false" depending on how <slot>
* is configured.
*/
if (argc == 2)
stdout_is_tty = git_config_bool("command line", argv[1]);
else if (argc == 1)
stdout_is_tty = isatty(1);
else
usage(git_config_set_usage);
get_colorbool_found = -1;
get_diff_color_found = -1;
get_color_slot = argv[0];
git_config(git_get_colorbool_config, NULL);
if (get_colorbool_found < 0) {
if (!strcmp(get_color_slot, "color.diff"))
if (!strcmp(get_colorbool_slot, "color.diff"))
get_colorbool_found = get_diff_color_found;
if (get_colorbool_found < 0)
get_colorbool_found = git_use_color_default;
}
if (argc == 1) {
return get_colorbool_found ? 0 : 1;
} else {
if (print) {
printf("%s\n", get_colorbool_found ? "true" : "false");
return 0;
}
} else
return get_colorbool_found ? 0 : 1;
}
int cmd_config(int argc, const char **argv, const char *prefix)
int cmd_config(int argc, const char **argv, const char *unused_prefix)
{
int nongit;
char *value;
const char *file = setup_git_directory_gently(&nongit);
const char *prefix = setup_git_directory_gently(&nongit);
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
while (1 < argc) {
if (!strcmp(argv[1], "--int"))
type = T_INT;
else if (!strcmp(argv[1], "--bool"))
type = T_BOOL;
else if (!strcmp(argv[1], "--bool-or-int"))
type = T_BOOL_OR_INT;
else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) {
if (argc != 2)
usage(git_config_set_usage);
if (git_config(show_all_config, NULL) < 0 &&
file && errno)
die("unable to read config file %s: %s", file,
strerror(errno));
return 0;
}
else if (!strcmp(argv[1], "--global")) {
char *home = getenv("HOME");
if (home) {
char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
config_exclusive_filename = user_config;
} else {
die("$HOME not set");
}
}
else if (!strcmp(argv[1], "--system"))
config_exclusive_filename = git_etc_gitconfig();
else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) {
if (argc < 3)
usage(git_config_set_usage);
if (!is_absolute_path(argv[2]) && file)
file = prefix_filename(file, strlen(file),
argv[2]);
else
file = argv[2];
config_exclusive_filename = file;
argc--;
argv++;
}
else if (!strcmp(argv[1], "--null") || !strcmp(argv[1], "-z")) {
term = '\0';
delim = '\n';
key_delim = '\n';
}
else if (!strcmp(argv[1], "--rename-section")) {
int ret;
if (argc != 4)
usage(git_config_set_usage);
ret = git_config_rename_section(argv[2], argv[3]);
if (ret < 0)
return ret;
if (ret == 0) {
fprintf(stderr, "No such section!\n");
return 1;
}
return 0;
}
else if (!strcmp(argv[1], "--remove-section")) {
int ret;
if (argc != 3)
usage(git_config_set_usage);
ret = git_config_rename_section(argv[2], NULL);
if (ret < 0)
return ret;
if (ret == 0) {
fprintf(stderr, "No such section!\n");
return 1;
}
return 0;
} else if (!strcmp(argv[1], "--get-color")) {
return get_color(argc-2, argv+2);
} else if (!strcmp(argv[1], "--get-colorbool")) {
return get_colorbool(argc-2, argv+2);
} else if (!strcmp(argv[1], "--edit") || !strcmp(argv[1], "-e")) {
if (argc != 2)
usage(git_config_set_usage);
git_config(git_default_config, NULL);
launch_editor(config_exclusive_filename ?
config_exclusive_filename : git_path("config"),
NULL, NULL);
return 0;
} else
break;
argc--;
argv++;
argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (use_global_config + use_system_config + !!given_config_file > 1) {
error("only one config file at a time.");
usage_with_options(builtin_config_usage, builtin_config_options);
}
switch (argc) {
case 2:
return get_value(argv[1], NULL);
case 3:
if (!strcmp(argv[1], "--unset"))
return git_config_set(argv[2], NULL);
else if (!strcmp(argv[1], "--unset-all"))
return git_config_set_multivar(argv[2], NULL, NULL, 1);
else if (!strcmp(argv[1], "--get"))
return get_value(argv[2], NULL);
else if (!strcmp(argv[1], "--get-all")) {
do_all = 1;
return get_value(argv[2], NULL);
} else if (!strcmp(argv[1], "--get-regexp")) {
show_keys = 1;
use_key_regexp = 1;
do_all = 1;
return get_value(argv[2], NULL);
if (use_global_config) {
char *home = getenv("HOME");
if (home) {
char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
config_exclusive_filename = user_config;
} else {
value = normalize_value(argv[1], argv[2]);
return git_config_set(argv[1], value);
die("$HOME not set");
}
case 4:
if (!strcmp(argv[1], "--unset"))
return git_config_set_multivar(argv[2], NULL, argv[3], 0);
else if (!strcmp(argv[1], "--unset-all"))
return git_config_set_multivar(argv[2], NULL, argv[3], 1);
else if (!strcmp(argv[1], "--get"))
return get_value(argv[2], argv[3]);
else if (!strcmp(argv[1], "--get-all")) {
do_all = 1;
return get_value(argv[2], argv[3]);
} else if (!strcmp(argv[1], "--get-regexp")) {
show_keys = 1;
use_key_regexp = 1;
do_all = 1;
return get_value(argv[2], argv[3]);
} else if (!strcmp(argv[1], "--add")) {
value = normalize_value(argv[2], argv[3]);
return git_config_set_multivar(argv[2], value, "^$", 0);
} else if (!strcmp(argv[1], "--replace-all")) {
value = normalize_value(argv[2], argv[3]);
return git_config_set_multivar(argv[2], value, NULL, 1);
} else {
value = normalize_value(argv[1], argv[2]);
return git_config_set_multivar(argv[1], value, argv[3], 0);
}
case 5:
if (!strcmp(argv[1], "--replace-all")) {
value = normalize_value(argv[2], argv[3]);
return git_config_set_multivar(argv[2], value, argv[4], 1);
}
case 1:
default:
usage(git_config_set_usage);
}
else if (use_system_config)
config_exclusive_filename = git_etc_gitconfig();
else if (given_config_file) {
if (!is_absolute_path(given_config_file) && prefix)
config_exclusive_filename = prefix_filename(prefix,
strlen(prefix),
argv[2]);
else
config_exclusive_filename = given_config_file;
}
if (end_null) {
term = '\0';
delim = '\n';
key_delim = '\n';
}
if (HAS_MULTI_BITS(types)) {
error("only one type at a time.");
usage_with_options(builtin_config_usage, builtin_config_options);
}
if (get_color_slot)
actions |= ACTION_GET_COLOR;
if (get_colorbool_slot)
actions |= ACTION_GET_COLORBOOL;
if ((get_color_slot || get_colorbool_slot) && types) {
error("--get-color and variable type are incoherent");
usage_with_options(builtin_config_usage, builtin_config_options);
}
if (HAS_MULTI_BITS(actions)) {
error("only one action at a time.");
usage_with_options(builtin_config_usage, builtin_config_options);
}
if (actions == 0)
switch (argc) {
case 1: actions = ACTION_GET; break;
case 2: actions = ACTION_SET; break;
case 3: actions = ACTION_SET_ALL; break;
default:
usage_with_options(builtin_config_usage, builtin_config_options);
}
if (actions == ACTION_LIST) {
check_argc(argc, 0, 0);
if (git_config(show_all_config, NULL) < 0) {
if (config_exclusive_filename)
die("unable to read config file %s: %s",
config_exclusive_filename, strerror(errno));
else
die("error processing config file(s)");
}
}
else if (actions == ACTION_EDIT) {
check_argc(argc, 0, 0);
git_config(git_default_config, NULL);
launch_editor(config_exclusive_filename ?
config_exclusive_filename : git_path("config"),
NULL, NULL);
}
else if (actions == ACTION_SET) {
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
return git_config_set(argv[0], value);
}
else if (actions == ACTION_SET_ALL) {
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
return git_config_set_multivar(argv[0], value, argv[2], 0);
}
else if (actions == ACTION_ADD) {
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
return git_config_set_multivar(argv[0], value, "^$", 0);
}
else if (actions == ACTION_REPLACE_ALL) {
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
return git_config_set_multivar(argv[0], value, argv[2], 1);
}
else if (actions == ACTION_GET) {
check_argc(argc, 1, 2);
return get_value(argv[0], argv[1]);
}
else if (actions == ACTION_GET_ALL) {
do_all = 1;
check_argc(argc, 1, 2);
return get_value(argv[0], argv[1]);
}
else if (actions == ACTION_GET_REGEXP) {
show_keys = 1;
use_key_regexp = 1;
do_all = 1;
check_argc(argc, 1, 2);
return get_value(argv[0], argv[1]);
}
else if (actions == ACTION_UNSET) {
check_argc(argc, 1, 2);
if (argc == 2)
return git_config_set_multivar(argv[0], NULL, argv[1], 0);
else
return git_config_set(argv[0], NULL);
}
else if (actions == ACTION_UNSET_ALL) {
check_argc(argc, 1, 2);
return git_config_set_multivar(argv[0], NULL, argv[1], 1);
}
else if (actions == ACTION_RENAME_SECTION) {
int ret;
check_argc(argc, 2, 2);
ret = git_config_rename_section(argv[0], argv[1]);
if (ret < 0)
return ret;
if (ret == 0)
die("No such section!");
}
else if (actions == ACTION_REMOVE_SECTION) {
int ret;
check_argc(argc, 1, 1);
ret = git_config_rename_section(argv[0], NULL);
if (ret < 0)
return ret;
if (ret == 0)
die("No such section!");
}
else if (actions == ACTION_GET_COLOR) {
get_color(argv[0]);
}
else if (actions == ACTION_GET_COLORBOOL) {
if (argc == 1)
stdout_is_tty = git_config_bool("command line", argv[0]);
else if (argc == 0)
stdout_is_tty = isatty(1);
return get_colorbool(argc != 0);
}
return 0;
}

View File

@@ -221,7 +221,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
if (message)
message += 2;
if (commit->parents) {
if (commit->parents &&
get_object_mark(&commit->parents->item->object) != 0) {
parse_commit(commit->parents->item);
diff_tree_sha1(commit->parents->item->tree->object.sha1,
commit->tree->object.sha1, "", &rev->diffopt);
@@ -362,7 +363,10 @@ static void get_tags_and_duplicates(struct object_array *pending,
break;
case OBJ_TAG:
tag = (struct tag *)e->item;
/* handle nested tags */
while (tag && tag->object.type == OBJ_TAG) {
parse_object(tag->object.sha1);
string_list_append(full_name, extra_refs)->util = tag;
tag = (struct tag *)tag->tagged;
}
@@ -375,11 +379,17 @@ static void get_tags_and_duplicates(struct object_array *pending,
case OBJ_BLOB:
handle_object(tag->object.sha1);
continue;
default: /* OBJ_TAG (nested tags) is already handled */
warning("Tag points to object of unexpected type %s, skipping.",
typename(tag->object.type));
continue;
}
break;
default:
die ("Unexpected object of type %s",
typename(e->item->type));
warning("%s: Unexpected object of type %s, skipping.",
e->name,
typename(e->item->type));
continue;
}
if (commit->util)
/* more than one name for the same object */

View File

@@ -605,7 +605,7 @@ static struct ref *do_fetch_pack(int fd[2],
/* When cloning, it is not unusual to have
* no common commit.
*/
fprintf(stderr, "warning: no common commits\n");
warning("no common commits");
if (get_pack(fd, pack_lockfile))
die("git fetch-pack: fetch failed.");
@@ -800,15 +800,13 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
int fd;
mtime.sec = st.st_mtime;
#ifdef USE_NSEC
mtime.usec = st.st_mtim.usec;
#endif
mtime.nsec = ST_MTIME_NSEC(st);
if (stat(shallow, &st)) {
if (mtime.sec)
die("shallow file was removed during fetch");
} else if (st.st_mtime != mtime.sec
#ifdef USE_NSEC
|| st.st_mtim.usec != mtime.usec
|| ST_MTIME_NSEC(st) != mtime.nsec
#endif
)
die("shallow file was changed during fetch");

View File

@@ -197,11 +197,7 @@ static int update_local_ref(struct ref *ref,
struct commit *current = NULL, *updated;
enum object_type type;
struct branch *current_branch = branch_get(NULL);
const char *pretty_ref = ref->name + (
!prefixcmp(ref->name, "refs/heads/") ? 11 :
!prefixcmp(ref->name, "refs/tags/") ? 10 :
!prefixcmp(ref->name, "refs/remotes/") ? 13 :
0);
const char *pretty_ref = prettify_ref(ref);
*display = 0;
type = sha1_object_info(ref->new_sha1, NULL);
@@ -544,7 +540,8 @@ static void check_not_current_branch(struct ref *ref_map)
for (; ref_map; ref_map = ref_map->next)
if (ref_map->peer_ref && !strcmp(current_branch->refname,
ref_map->peer_ref->name))
die("Refusing to fetch into current branch");
die("Refusing to fetch into current branch %s "
"of non-bare repository", current_branch->refname);
}
static int do_fetch(struct transport *transport,
@@ -636,6 +633,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
else
remote = remote_get(argv[0]);
if (!remote)
die("Where do you want to fetch from today?");
transport = transport_get(remote, remote->url[0]);
if (verbosity >= 2)
transport->verbose = 1;
@@ -648,9 +648,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
if (depth)
set_option(TRANS_OPT_DEPTH, depth);
if (!transport->url)
die("Where do you want to fetch from today?");
if (argc > 1) {
int j = 0;
refs = xcalloc(argc + 1, sizeof(const char *));

View File

@@ -23,7 +23,7 @@ static const char * const builtin_gc_usage[] = {
};
static int pack_refs = 1;
static int aggressive_window = -1;
static int aggressive_window = 250;
static int gc_auto_threshold = 6700;
static int gc_auto_pack_limit = 50;
static const char *prune_expire = "2.weeks.ago";
@@ -200,6 +200,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (aggressive) {
append_option(argv_repack, "-f", MAX_ADD);
append_option(argv_repack, "--depth=250", MAX_ADD);
if (aggressive_window > 0) {
sprintf(buf, "--window=%d", aggressive_window);
append_option(argv_repack, buf, MAX_ADD);

View File

@@ -22,6 +22,28 @@
static int builtin_grep;
static int grep_config(const char *var, const char *value, void *cb)
{
struct grep_opt *opt = cb;
if (!strcmp(var, "grep.color") || !strcmp(var, "color.grep")) {
opt->color = git_config_colorbool(var, value, -1);
return 0;
}
if (!strcmp(var, "grep.color.external") ||
!strcmp(var, "color.grep.external")) {
return git_config_string(&(opt->color_external), var, value);
}
if (!strcmp(var, "grep.color.match") ||
!strcmp(var, "color.grep.match")) {
if (!value)
return config_error_nonbool(var);
color_parse(value, var, opt->color_match);
return 0;
}
return git_color_default_config(var, value, cb);
}
/*
* git grep pathspecs are somewhat different from diff-tree pathspecs;
* pathname wildcards are allowed.
@@ -269,6 +291,21 @@ static int flush_grep(struct grep_opt *opt,
return status;
}
static void grep_add_color(struct strbuf *sb, const char *escape_seq)
{
size_t orig_len = sb->len;
while (*escape_seq) {
if (*escape_seq == 'm')
strbuf_addch(sb, ';');
else if (*escape_seq != '\033' && *escape_seq != '[')
strbuf_addch(sb, *escape_seq);
escape_seq++;
}
if (sb->len > orig_len && sb->buf[sb->len - 1] == ';')
strbuf_setlen(sb, sb->len - 1);
}
static int external_grep(struct grep_opt *opt, const char **paths, int cached)
{
int i, nr, argc, hit, len, status;
@@ -339,6 +376,23 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
push_arg("-e");
push_arg(p->pattern);
}
if (opt->color) {
struct strbuf sb = STRBUF_INIT;
grep_add_color(&sb, opt->color_match);
setenv("GREP_COLOR", sb.buf, 1);
strbuf_reset(&sb);
strbuf_addstr(&sb, "mt=");
grep_add_color(&sb, opt->color_match);
strbuf_addstr(&sb, ":sl=:cx=:fn=:ln=:bn=:se=");
setenv("GREP_COLORS", sb.buf, 1);
strbuf_release(&sb);
if (opt->color_external && strlen(opt->color_external) > 0)
push_arg(opt->color_external);
}
hit = 0;
argc = nr;
@@ -536,6 +590,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.pattern_tail = &opt.pattern_list;
opt.regflags = REG_NEWLINE;
strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD);
opt.color = -1;
git_config(grep_config, &opt);
if (opt.color == -1)
opt.color = git_use_color_default;
/*
* If there is no -- then the paths must exist in the working
* tree. If there is no explicit pattern specified with -e or
@@ -732,6 +792,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.relative = 0;
continue;
}
if (!strcmp("--color", arg)) {
opt.color = 1;
continue;
}
if (!strcmp("--no-color", arg)) {
opt.color = 0;
continue;
}
if (!strcmp("--", arg)) {
/* later processing wants to have this at argv[1] */
argv--;
@@ -757,6 +825,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
}
if (opt.color && !opt.color_external)
builtin_grep = 1;
if (!opt.pattern_list)
die("no pattern given.");
if ((opt.regflags != REG_NEWLINE) && opt.fixed)

View File

@@ -130,8 +130,7 @@ static void copy_templates(const char *template_dir)
}
dir = opendir(template_path);
if (!dir) {
fprintf(stderr, "warning: templates not found %s\n",
template_dir);
warning("templates not found %s", template_dir);
return;
}
@@ -144,8 +143,8 @@ static void copy_templates(const char *template_dir)
if (repository_format_version &&
repository_format_version != GIT_REPO_VERSION) {
fprintf(stderr, "warning: not copying templates of "
"a wrong format version %d from '%s'\n",
warning("not copying templates of "
"a wrong format version %d from '%s'",
repository_format_version,
template_dir);
closedir(dir);

View File

@@ -573,7 +573,7 @@ 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)
static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev)
{
char filename[PATH_MAX];
int len = 0;
@@ -598,7 +598,9 @@ static int reopen_stdout(const char *oneline, int nr, int total)
strcpy(filename + len, fmt_patch_suffix);
}
fprintf(realstdout, "%s\n", filename + outdir_offset);
if (!DIFF_OPT_TST(&rev->diffopt, QUIET))
fprintf(realstdout, "%s\n", filename + outdir_offset);
if (freopen(filename, "w", stdout) == NULL)
return error("Cannot open patch file %s",filename);
@@ -687,7 +689,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
die("Cover letter needs email format");
if (!use_stdout && reopen_stdout(numbered_files ?
NULL : "cover-letter", 0, rev->total))
NULL : "cover-letter", 0, rev))
return;
head_sha1 = sha1_to_hex(head->object.sha1);
@@ -916,6 +918,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
cover_letter = 1;
else if (!strcmp(argv[i], "--no-binary"))
no_binary_diff = 1;
else if (!prefixcmp(argv[i], "--add-header="))
add_header(argv[i] + 13);
else
argv[j++] = argv[i];
}
@@ -956,8 +960,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
die ("-n and -k are mutually exclusive.");
if (keep_subject && subject_prefix)
die ("--subject-prefix and -k are mutually exclusive.");
if (numbered_files && use_stdout)
die ("--numbered-files and --stdout are mutually exclusive.");
argc = setup_revisions(argc, argv, &rev, "HEAD");
if (argc > 1)
@@ -1106,7 +1108,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
}
if (!use_stdout && reopen_stdout(numbered_files ? NULL :
get_oneline_for_filename(commit, keep_subject),
rev.nr, rev.total))
rev.nr, &rev))
die("Failed to create output files");
shown = log_tree_commit(&rev, commit);
free(commit->buffer);

View File

@@ -10,6 +10,7 @@
#include "dir.h"
#include "builtin.h"
#include "tree.h"
#include "parse-options.h"
static int abbrev;
static int show_deleted;
@@ -28,6 +29,7 @@ static const char **pathspec;
static int error_unmatch;
static char *ps_matched;
static const char *with_tree;
static int exc_given;
static const char *tag_cached = "";
static const char *tag_unmerged = "";
@@ -174,7 +176,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
int dtype = ce_to_dtype(ce);
if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
if (excluded(dir, ce->name, &dtype) !=
!!(dir->flags & DIR_SHOW_IGNORED))
continue;
if (show_unmerged && !ce_stage(ce))
continue;
@@ -189,7 +192,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
struct stat st;
int err;
int dtype = ce_to_dtype(ce);
if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
if (excluded(dir, ce->name, &dtype) !=
!!(dir->flags & DIR_SHOW_IGNORED))
continue;
if (ce->ce_flags & CE_UPDATE)
continue;
@@ -374,156 +378,139 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_
return errors;
}
static const char ls_files_usage[] =
"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
"[ --exclude-per-directory=<filename> ] [--exclude-standard] "
"[--full-name] [--abbrev] [--] [<file>]*";
static const char * const ls_files_usage[] = {
"git ls-files [options] [<file>]*",
NULL
};
static int option_parse_z(const struct option *opt,
const char *arg, int unset)
{
line_terminator = unset ? '\n' : '\0';
return 0;
}
static int option_parse_exclude(const struct option *opt,
const char *arg, int unset)
{
struct exclude_list *list = opt->value;
exc_given = 1;
add_exclude(arg, "", 0, list);
return 0;
}
static int option_parse_exclude_from(const struct option *opt,
const char *arg, int unset)
{
struct dir_struct *dir = opt->value;
exc_given = 1;
add_excludes_from_file(dir, arg);
return 0;
}
static int option_parse_exclude_standard(const struct option *opt,
const char *arg, int unset)
{
struct dir_struct *dir = opt->value;
exc_given = 1;
setup_standard_excludes(dir);
return 0;
}
int cmd_ls_files(int argc, const char **argv, const char *prefix)
{
int i;
int exc_given = 0, require_work_tree = 0;
int require_work_tree = 0, show_tag = 0;
struct dir_struct dir;
struct option builtin_ls_files_options[] = {
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
"paths are separated with NUL character",
PARSE_OPT_NOARG, option_parse_z },
OPT_BOOLEAN('t', NULL, &show_tag,
"identify the file status with tags"),
OPT_BOOLEAN('v', NULL, &show_valid_bit,
"use lowercase letters for 'assume unchanged' files"),
OPT_BOOLEAN('c', "cached", &show_cached,
"show cached files in the output (default)"),
OPT_BOOLEAN('d', "deleted", &show_deleted,
"show deleted files in the output"),
OPT_BOOLEAN('m', "modified", &show_modified,
"show modified files in the output"),
OPT_BOOLEAN('o', "others", &show_others,
"show other files in the output"),
OPT_BIT('i', "ignored", &dir.flags,
"show ignored files in the output",
DIR_SHOW_IGNORED),
OPT_BOOLEAN('s', "stage", &show_stage,
"show staged contents' object name in the output"),
OPT_BOOLEAN('k', "killed", &show_killed,
"show files on the filesystem that need to be removed"),
OPT_BIT(0, "directory", &dir.flags,
"show 'other' directories' name only",
DIR_SHOW_OTHER_DIRECTORIES),
OPT_BIT(0, "no-empty-directory", &dir.flags,
"don't show empty directories",
DIR_HIDE_EMPTY_DIRECTORIES),
OPT_BOOLEAN('u', "unmerged", &show_unmerged,
"show unmerged files in the output"),
{ OPTION_CALLBACK, 'x', "exclude", &dir.exclude_list[EXC_CMDL], "pattern",
"skip files matching pattern",
0, option_parse_exclude },
{ OPTION_CALLBACK, 'X', "exclude-from", &dir, "file",
"exclude patterns are read from <file>",
0, option_parse_exclude_from },
OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, "file",
"read additional per-directory exclude patterns in <file>"),
{ OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
"add the standard git exclusions",
PARSE_OPT_NOARG, option_parse_exclude_standard },
{ OPTION_SET_INT, 0, "full-name", &prefix_offset, NULL,
"make the output relative to the project top directory",
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
OPT_BOOLEAN(0, "error-unmatch", &error_unmatch,
"if any <file> is not in the index, treat this as an error"),
OPT_STRING(0, "with-tree", &with_tree, "tree-ish",
"pretend that paths removed since <tree-ish> are still present"),
OPT__ABBREV(&abbrev),
OPT_END()
};
memset(&dir, 0, sizeof(dir));
if (prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config, NULL);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!strcmp(arg, "-z")) {
line_terminator = 0;
continue;
}
if (!strcmp(arg, "-t") || !strcmp(arg, "-v")) {
tag_cached = "H ";
tag_unmerged = "M ";
tag_removed = "R ";
tag_modified = "C ";
tag_other = "? ";
tag_killed = "K ";
if (arg[1] == 'v')
show_valid_bit = 1;
continue;
}
if (!strcmp(arg, "-c") || !strcmp(arg, "--cached")) {
show_cached = 1;
continue;
}
if (!strcmp(arg, "-d") || !strcmp(arg, "--deleted")) {
show_deleted = 1;
continue;
}
if (!strcmp(arg, "-m") || !strcmp(arg, "--modified")) {
show_modified = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-o") || !strcmp(arg, "--others")) {
show_others = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-i") || !strcmp(arg, "--ignored")) {
dir.show_ignored = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-s") || !strcmp(arg, "--stage")) {
show_stage = 1;
continue;
}
if (!strcmp(arg, "-k") || !strcmp(arg, "--killed")) {
show_killed = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "--directory")) {
dir.show_other_directories = 1;
continue;
}
if (!strcmp(arg, "--no-empty-directory")) {
dir.hide_empty_directories = 1;
continue;
}
if (!strcmp(arg, "-u") || !strcmp(arg, "--unmerged")) {
/* There's no point in showing unmerged unless
* you also show the stage information.
*/
show_stage = 1;
show_unmerged = 1;
continue;
}
if (!strcmp(arg, "-x") && i+1 < argc) {
exc_given = 1;
add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
}
if (!prefixcmp(arg, "--exclude=")) {
exc_given = 1;
add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
}
if (!strcmp(arg, "-X") && i+1 < argc) {
exc_given = 1;
add_excludes_from_file(&dir, argv[++i]);
continue;
}
if (!prefixcmp(arg, "--exclude-from=")) {
exc_given = 1;
add_excludes_from_file(&dir, arg+15);
continue;
}
if (!prefixcmp(arg, "--exclude-per-directory=")) {
exc_given = 1;
dir.exclude_per_dir = arg + 24;
continue;
}
if (!strcmp(arg, "--exclude-standard")) {
exc_given = 1;
setup_standard_excludes(&dir);
continue;
}
if (!strcmp(arg, "--full-name")) {
prefix_offset = 0;
continue;
}
if (!strcmp(arg, "--error-unmatch")) {
error_unmatch = 1;
continue;
}
if (!prefixcmp(arg, "--with-tree=")) {
with_tree = arg + 12;
continue;
}
if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
else if (abbrev > 40)
abbrev = 40;
continue;
}
if (!strcmp(arg, "--abbrev")) {
abbrev = DEFAULT_ABBREV;
continue;
}
if (*arg == '-')
usage(ls_files_usage);
break;
argc = parse_options(argc, argv, builtin_ls_files_options,
ls_files_usage, 0);
if (show_tag || show_valid_bit) {
tag_cached = "H ";
tag_unmerged = "M ";
tag_removed = "R ";
tag_modified = "C ";
tag_other = "? ";
tag_killed = "K ";
}
if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
require_work_tree = 1;
if (show_unmerged)
/*
* There's no point in showing unmerged unless
* you also show the stage information.
*/
show_stage = 1;
if (dir.exclude_per_dir)
exc_given = 1;
if (require_work_tree && !is_inside_work_tree())
setup_work_tree();
pathspec = get_pathspec(prefix, argv + i);
pathspec = get_pathspec(prefix, argv);
/* be nice with submodule patsh ending in a slash */
read_cache();
@@ -542,7 +529,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
ps_matched = xcalloc(1, num);
}
if (dir.show_ignored && !exc_given) {
if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) {
fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
argv[0]);
exit(1);

View File

@@ -60,7 +60,6 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
{
int retval = 0;
const char *type = blob_type;
unsigned long size;
if (S_ISGITLINK(mode)) {
/*
@@ -90,17 +89,20 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
if (!(ls_options & LS_NAME_ONLY)) {
if (ls_options & LS_SHOW_SIZE) {
char size_text[24];
if (!strcmp(type, blob_type)) {
sha1_object_info(sha1, &size);
printf("%06o %s %s %7lu\t", mode, type,
abbrev ? find_unique_abbrev(sha1, abbrev)
: sha1_to_hex(sha1),
size);
unsigned long size;
if (sha1_object_info(sha1, &size) == OBJ_BAD)
strcpy(size_text, "BAD");
else
snprintf(size_text, sizeof(size_text),
"%lu", size);
} else
printf("%06o %s %s %7c\t", mode, type,
abbrev ? find_unique_abbrev(sha1, abbrev)
: sha1_to_hex(sha1),
'-');
strcpy(size_text, "-");
printf("%06o %s %s %7s\t", mode, type,
abbrev ? find_unique_abbrev(sha1, abbrev)
: sha1_to_hex(sha1),
size_text);
} else
printf("%06o %s %s\t", mode, type,
abbrev ? find_unique_abbrev(sha1, abbrev)

View File

@@ -636,7 +636,7 @@ static int checkout_fast_forward(unsigned char *head, unsigned char *remote)
memset(&opts, 0, sizeof(opts));
memset(&t, 0, sizeof(t));
memset(&dir, 0, sizeof(dir));
dir.show_ignored = 1;
dir.flags |= DIR_SHOW_IGNORED;
dir.exclude_per_dir = ".gitignore";
opts.dir = &dir;

View File

@@ -1293,7 +1293,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
max_size = trg_entry->delta_size;
ref_depth = trg->depth;
}
max_size = max_size * (max_depth - src->depth) /
max_size = (uint64_t)max_size * (max_depth - src->depth) /
(max_depth - ref_depth + 1);
if (max_size == 0)
return 0;
@@ -1966,7 +1966,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
const unsigned char *sha1;
struct object *o;
if (p->pack_keep)
if (!p->pack_local || p->pack_keep)
continue;
if (open_pack_index(p))
die("cannot open pack index");
@@ -1995,6 +1995,29 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
free(in_pack.array);
}
static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
{
static struct packed_git *last_found = (void *)1;
struct packed_git *p;
p = (last_found != (void *)1) ? last_found : packed_git;
while (p) {
if ((!p->pack_local || p->pack_keep) &&
find_pack_entry_one(sha1, p)) {
last_found = p;
return 1;
}
if (p == last_found)
p = packed_git;
else
p = p->next;
if (p == last_found)
p = p->next;
}
return 0;
}
static void loosen_unused_packed_objects(struct rev_info *revs)
{
struct packed_git *p;
@@ -2002,7 +2025,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
const unsigned char *sha1;
for (p = packed_git; p; p = p->next) {
if (p->pack_keep)
if (!p->pack_local || p->pack_keep)
continue;
if (open_pack_index(p))
@@ -2010,7 +2033,8 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
for (i = 0; i < p->num_objects; i++) {
sha1 = nth_packed_object_sha1(p, i);
if (!locate_object_entry(sha1))
if (!locate_object_entry(sha1) &&
!has_sha1_pack_kept_or_nonlocal(sha1))
if (force_object_loose(sha1, p->mtime))
die("unable to force loose object");
}
@@ -2200,7 +2224,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp("--unpacked", arg) ||
!strcmp("--kept-pack-only", arg) ||
!strcmp("--reflog", arg) ||
!strcmp("--all", arg)) {
use_internal_rev_list = 1;

View File

@@ -48,13 +48,81 @@ static void set_refspecs(const char **refs, int nr)
}
}
static void setup_push_tracking(void)
{
struct strbuf refspec = STRBUF_INIT;
struct branch *branch = branch_get(NULL);
if (!branch)
die("You are not currently on a branch.");
if (!branch->merge_nr)
die("The current branch %s is not tracking anything.",
branch->name);
if (branch->merge_nr != 1)
die("The current branch %s is tracking multiple branches, "
"refusing to push.", branch->name);
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
add_refspec(refspec.buf);
}
static const char *warn_unconfigured_push_msg[] = {
"You did not specify any refspecs to push, and the current remote",
"has not configured any push refspecs. The default action in this",
"case is to push all matching refspecs, that is, all branches",
"that exist both locally and remotely will be updated. This may",
"not necessarily be what you want to happen.",
"",
"You can specify what action you want to take in this case, and",
"avoid seeing this message again, by configuring 'push.default' to:",
" 'nothing' : Do not push anything",
" 'matching' : Push all matching branches (default)",
" 'tracking' : Push the current branch to whatever it is tracking",
" 'current' : Push the current branch"
};
static void warn_unconfigured_push(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++)
warning("%s", warn_unconfigured_push_msg[i]);
}
static void setup_default_push_refspecs(void)
{
git_config(git_default_config, NULL);
switch (push_default) {
case PUSH_DEFAULT_UNSPECIFIED:
warn_unconfigured_push();
/* fallthrough */
case PUSH_DEFAULT_MATCHING:
add_refspec(":");
break;
case PUSH_DEFAULT_TRACKING:
setup_push_tracking();
break;
case PUSH_DEFAULT_CURRENT:
add_refspec("HEAD");
break;
case PUSH_DEFAULT_NOTHING:
die("You didn't specify any refspecs to push, and "
"push.default is \"nothing\".");
break;
}
}
static int do_push(const char *repo, int flags)
{
int i, errs;
struct remote *remote = remote_get(repo);
if (!remote)
die("bad repository '%s'", repo);
if (!remote) {
if (repo)
die("bad repository '%s'", repo);
die("No destination configured to push to.");
}
if (remote->mirror)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
@@ -76,11 +144,12 @@ static int do_push(const char *repo, int flags)
return error("--all and --mirror are incompatible");
}
if (!refspec
&& !(flags & TRANSPORT_PUSH_ALL)
&& remote->push_refspec_nr) {
refspec = remote->push_refspec;
refspec_nr = remote->push_refspec_nr;
if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
if (remote->push_refspec_nr) {
refspec = remote->push_refspec;
refspec_nr = remote->push_refspec_nr;
} else if (!(flags & TRANSPORT_PUSH_MIRROR))
setup_default_push_refspecs();
}
errs = 0;
for (i = 0; i < remote->url_nr; i++) {

View File

@@ -170,7 +170,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
die("more than one --exclude-per-directory are given.");
dir = xcalloc(1, sizeof(*opts.dir));
dir->show_ignored = 1;
dir->flags |= DIR_SHOW_IGNORED;
dir->exclude_per_dir = arg + 24;
opts.dir = dir;
/* We do not need to nor want to do read-directory

View File

@@ -12,12 +12,17 @@ static const char * const builtin_remote_usage[] = {
"git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>",
"git remote rename <old> <new>",
"git remote rm <name>",
"git remote set-head <name> [-a | -d | <branch>]",
"git remote show [-n] <name>",
"git remote prune [-n | --dry-run] <name>",
"git remote [-v | --verbose] update [group]",
NULL
};
#define GET_REF_STATES (1<<0)
#define GET_HEAD_NAMES (1<<1)
#define GET_PUSH_REF_STATES (1<<2)
static int verbose;
static int show_all(void);
@@ -143,8 +148,9 @@ static int add(int argc, const char **argv)
}
struct branch_info {
char *remote;
char *remote_name;
struct string_list merge;
int rebase;
};
static struct string_list branch_list;
@@ -161,10 +167,11 @@ static const char *abbrev_ref(const char *name, const char *prefix)
static int config_read_branches(const char *key, const char *value, void *cb)
{
if (!prefixcmp(key, "branch.")) {
const char *orig_key = key;
char *name;
struct string_list_item *item;
struct branch_info *info;
enum { REMOTE, MERGE } type;
enum { REMOTE, MERGE, REBASE } type;
key += 7;
if (!postfixcmp(key, ".remote")) {
@@ -173,6 +180,9 @@ static int config_read_branches(const char *key, const char *value, void *cb)
} else if (!postfixcmp(key, ".merge")) {
name = xstrndup(key, strlen(key) - 6);
type = MERGE;
} else if (!postfixcmp(key, ".rebase")) {
name = xstrndup(key, strlen(key) - 7);
type = REBASE;
} else
return 0;
@@ -182,10 +192,10 @@ static int config_read_branches(const char *key, const char *value, void *cb)
item->util = xcalloc(sizeof(struct branch_info), 1);
info = item->util;
if (type == REMOTE) {
if (info->remote)
warning("more than one branch.%s", key);
info->remote = xstrdup(value);
} else {
if (info->remote_name)
warning("more than one %s", orig_key);
info->remote_name = xstrdup(value);
} else if (type == MERGE) {
char *space = strchr(value, ' ');
value = abbrev_branch(value);
while (space) {
@@ -196,7 +206,8 @@ static int config_read_branches(const char *key, const char *value, void *cb)
space = strchr(value, ' ');
}
string_list_append(xstrdup(value), &info->merge);
}
} else
info->rebase = git_config_bool(orig_key, value);
}
return 0;
}
@@ -206,12 +217,12 @@ static void read_branches(void)
if (branch_list.nr)
return;
git_config(config_read_branches, NULL);
sort_string_list(&branch_list);
}
struct ref_states {
struct remote *remote;
struct string_list new, stale, tracked;
struct string_list new, stale, tracked, heads, push;
int queried;
};
static int handle_one_branch(const char *refname,
@@ -227,10 +238,8 @@ static int handle_one_branch(const char *refname,
const char *name = abbrev_branch(refspec.src);
/* symbolic refs pointing nowhere were handled already */
if ((flags & REF_ISSYMREF) ||
unsorted_string_list_has_string(&states->tracked,
name) ||
unsorted_string_list_has_string(&states->new,
name))
string_list_has_string(&states->tracked, name) ||
string_list_has_string(&states->new, name))
return 0;
item = string_list_append(name, &states->stale);
item->util = xstrdup(refname);
@@ -238,39 +247,154 @@ static int handle_one_branch(const char *refname,
return 0;
}
static int get_ref_states(const struct ref *ref, struct ref_states *states)
static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
{
struct ref *fetch_map = NULL, **tail = &fetch_map;
struct ref *ref;
int i;
for (i = 0; i < states->remote->fetch_refspec_nr; i++)
if (get_fetch_map(ref, states->remote->fetch + i, &tail, 1))
if (get_fetch_map(remote_refs, states->remote->fetch + i, &tail, 1))
die("Could not get fetch map for refspec %s",
states->remote->fetch_refspec[i]);
states->new.strdup_strings = states->tracked.strdup_strings = 1;
for (ref = fetch_map; ref; ref = ref->next) {
struct string_list *target = &states->tracked;
unsigned char sha1[20];
void *util = NULL;
if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))
target = &states->new;
else {
target = &states->tracked;
if (hashcmp(sha1, ref->new_sha1))
util = &states;
}
string_list_append(abbrev_branch(ref->name), target)->util = util;
string_list_append(abbrev_branch(ref->name), &states->new);
else
string_list_append(abbrev_branch(ref->name), &states->tracked);
}
free_refs(fetch_map);
sort_string_list(&states->new);
sort_string_list(&states->tracked);
for_each_ref(handle_one_branch, states);
sort_string_list(&states->stale);
return 0;
}
struct push_info {
char *dest;
int forced;
enum {
PUSH_STATUS_CREATE = 0,
PUSH_STATUS_DELETE,
PUSH_STATUS_UPTODATE,
PUSH_STATUS_FASTFORWARD,
PUSH_STATUS_OUTOFDATE,
PUSH_STATUS_NOTQUERIED,
} status;
};
static int get_push_ref_states(const struct ref *remote_refs,
struct ref_states *states)
{
struct remote *remote = states->remote;
struct ref *ref, *local_refs, *push_map, **push_tail;
if (remote->mirror)
return 0;
local_refs = get_local_heads();
ref = push_map = copy_ref_list(remote_refs);
while (ref->next)
ref = ref->next;
push_tail = &ref->next;
match_refs(local_refs, push_map, &push_tail, remote->push_refspec_nr,
remote->push_refspec, MATCH_REFS_NONE);
states->push.strdup_strings = 1;
for (ref = push_map; ref; ref = ref->next) {
struct string_list_item *item;
struct push_info *info;
if (!ref->peer_ref)
continue;
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
item = string_list_append(abbrev_branch(ref->peer_ref->name),
&states->push);
item->util = xcalloc(sizeof(struct push_info), 1);
info = item->util;
info->forced = ref->force;
info->dest = xstrdup(abbrev_branch(ref->name));
if (is_null_sha1(ref->new_sha1)) {
info->status = PUSH_STATUS_DELETE;
} else if (!hashcmp(ref->old_sha1, ref->new_sha1))
info->status = PUSH_STATUS_UPTODATE;
else if (is_null_sha1(ref->old_sha1))
info->status = PUSH_STATUS_CREATE;
else if (has_sha1_file(ref->old_sha1) &&
ref_newer(ref->new_sha1, ref->old_sha1))
info->status = PUSH_STATUS_FASTFORWARD;
else
info->status = PUSH_STATUS_OUTOFDATE;
}
free_refs(local_refs);
free_refs(push_map);
return 0;
}
static int get_push_ref_states_noquery(struct ref_states *states)
{
int i;
struct remote *remote = states->remote;
struct string_list_item *item;
struct push_info *info;
if (remote->mirror)
return 0;
states->push.strdup_strings = 1;
if (!remote->push_refspec_nr) {
item = string_list_append("(matching)", &states->push);
info = item->util = xcalloc(sizeof(struct push_info), 1);
info->status = PUSH_STATUS_NOTQUERIED;
info->dest = xstrdup(item->string);
}
for (i = 0; i < remote->push_refspec_nr; i++) {
struct refspec *spec = remote->push + i;
if (spec->matching)
item = string_list_append("(matching)", &states->push);
else if (strlen(spec->src))
item = string_list_append(spec->src, &states->push);
else
item = string_list_append("(delete)", &states->push);
info = item->util = xcalloc(sizeof(struct push_info), 1);
info->forced = spec->force;
info->status = PUSH_STATUS_NOTQUERIED;
info->dest = xstrdup(spec->dst ? spec->dst : item->string);
}
return 0;
}
static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
{
struct ref *ref, *matches;
struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
struct refspec refspec;
refspec.force = 0;
refspec.pattern = 1;
refspec.src = refspec.dst = "refs/heads/*";
states->heads.strdup_strings = 1;
get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
fetch_map, 1);
for(ref = matches; ref; ref = ref->next)
string_list_append(abbrev_branch(ref->name), &states->heads);
free_refs(fetch_map);
free_refs(matches);
return 0;
}
struct known_remote {
struct known_remote *next;
struct remote *remote;
@@ -466,7 +590,7 @@ static int mv(int argc, const char **argv)
for (i = 0; i < branch_list.nr; i++) {
struct string_list_item *item = branch_list.items + i;
struct branch_info *info = item->util;
if (info->remote && !strcmp(info->remote, rename.old)) {
if (info->remote_name && !strcmp(info->remote_name, rename.old)) {
strbuf_reset(&buf);
strbuf_addf(&buf, "branch.%s.remote", item->string);
if (git_config_set(buf.buf, rename.new)) {
@@ -575,7 +699,7 @@ static int rm(int argc, const char **argv)
for (i = 0; i < branch_list.nr; i++) {
struct string_list_item *item = branch_list.items + i;
struct branch_info *info = item->util;
if (info->remote && !strcmp(info->remote, remote->name)) {
if (info->remote_name && !strcmp(info->remote_name, remote->name)) {
const char *keys[] = { "remote", "merge", NULL }, **k;
for (k = keys; *k; k++) {
strbuf_reset(&buf);
@@ -617,18 +741,37 @@ static int rm(int argc, const char **argv)
return result;
}
static void show_list(const char *title, struct string_list *list,
const char *extra_arg)
void clear_push_info(void *util, const char *string)
{
int i;
struct push_info *info = util;
free(info->dest);
free(info);
}
if (!list->nr)
return;
static void free_remote_ref_states(struct ref_states *states)
{
string_list_clear(&states->new, 0);
string_list_clear(&states->stale, 0);
string_list_clear(&states->tracked, 0);
string_list_clear(&states->heads, 0);
string_list_clear_func(&states->push, clear_push_info);
}
printf(title, list->nr > 1 ? "es" : "", extra_arg);
printf("\n");
for (i = 0; i < list->nr; i++)
printf(" %s\n", list->items[i].string);
static int append_ref_to_tracked_list(const char *refname,
const unsigned char *sha1, int flags, void *cb_data)
{
struct ref_states *states = cb_data;
struct refspec refspec;
if (flags & REF_ISSYMREF)
return 0;
memset(&refspec, 0, sizeof(refspec));
refspec.dst = (char *)refname;
if (!remote_find_tracking(states->remote, &refspec))
string_list_append(abbrev_branch(refspec.src), &states->tracked);
return 0;
}
static int get_remote_ref_states(const char *name,
@@ -636,7 +779,7 @@ static int get_remote_ref_states(const char *name,
int query)
{
struct transport *transport;
const struct ref *ref;
const struct ref *remote_refs;
states->remote = remote_get(name);
if (!states->remote)
@@ -647,105 +790,336 @@ static int get_remote_ref_states(const char *name,
if (query) {
transport = transport_get(NULL, states->remote->url_nr > 0 ?
states->remote->url[0] : NULL);
ref = transport_get_remote_refs(transport);
remote_refs = transport_get_remote_refs(transport);
transport_disconnect(transport);
get_ref_states(ref, states);
states->queried = 1;
if (query & GET_REF_STATES)
get_ref_states(remote_refs, states);
if (query & GET_HEAD_NAMES)
get_head_names(remote_refs, states);
if (query & GET_PUSH_REF_STATES)
get_push_ref_states(remote_refs, states);
} else {
for_each_ref(append_ref_to_tracked_list, states);
sort_string_list(&states->tracked);
get_push_ref_states_noquery(states);
}
return 0;
}
static int append_ref_to_tracked_list(const char *refname,
const unsigned char *sha1, int flags, void *cb_data)
struct show_info {
struct string_list *list;
struct ref_states *states;
int width, width2;
int any_rebase;
};
int add_remote_to_show_info(struct string_list_item *item, void *cb_data)
{
struct ref_states *states = cb_data;
struct refspec refspec;
struct show_info *info = cb_data;
int n = strlen(item->string);
if (n > info->width)
info->width = n;
string_list_insert(item->string, info->list);
return 0;
}
memset(&refspec, 0, sizeof(refspec));
refspec.dst = (char *)refname;
if (!remote_find_tracking(states->remote, &refspec))
string_list_append(abbrev_branch(refspec.src), &states->tracked);
int show_remote_info_item(struct string_list_item *item, void *cb_data)
{
struct show_info *info = cb_data;
struct ref_states *states = info->states;
const char *name = item->string;
if (states->queried) {
const char *fmt = "%s";
const char *arg = "";
if (string_list_has_string(&states->new, name)) {
fmt = " new (next fetch will store in remotes/%s)";
arg = states->remote->name;
} else if (string_list_has_string(&states->tracked, name))
arg = " tracked";
else if (string_list_has_string(&states->stale, name))
arg = " stale (use 'git remote prune' to remove)";
else
arg = " ???";
printf(" %-*s", info->width, name);
printf(fmt, arg);
printf("\n");
} else
printf(" %s\n", name);
return 0;
}
int add_local_to_show_info(struct string_list_item *branch_item, void *cb_data)
{
struct show_info *show_info = cb_data;
struct ref_states *states = show_info->states;
struct branch_info *branch_info = branch_item->util;
struct string_list_item *item;
int n;
if (!branch_info->merge.nr || !branch_info->remote_name ||
strcmp(states->remote->name, branch_info->remote_name))
return 0;
if ((n = strlen(branch_item->string)) > show_info->width)
show_info->width = n;
if (branch_info->rebase)
show_info->any_rebase = 1;
item = string_list_insert(branch_item->string, show_info->list);
item->util = branch_info;
return 0;
}
int show_local_info_item(struct string_list_item *item, void *cb_data)
{
struct show_info *show_info = cb_data;
struct branch_info *branch_info = item->util;
struct string_list *merge = &branch_info->merge;
const char *also;
int i;
if (branch_info->rebase && branch_info->merge.nr > 1) {
error("invalid branch.%s.merge; cannot rebase onto > 1 branch",
item->string);
return 0;
}
printf(" %-*s ", show_info->width, item->string);
if (branch_info->rebase) {
printf("rebases onto remote %s\n", merge->items[0].string);
return 0;
} else if (show_info->any_rebase) {
printf(" merges with remote %s\n", merge->items[0].string);
also = " and with remote";
} else {
printf("merges with remote %s\n", merge->items[0].string);
also = " and with remote";
}
for (i = 1; i < merge->nr; i++)
printf(" %-*s %s %s\n", show_info->width, "", also,
merge->items[i].string);
return 0;
}
int add_push_to_show_info(struct string_list_item *push_item, void *cb_data)
{
struct show_info *show_info = cb_data;
struct push_info *push_info = push_item->util;
struct string_list_item *item;
int n;
if ((n = strlen(push_item->string)) > show_info->width)
show_info->width = n;
if ((n = strlen(push_info->dest)) > show_info->width2)
show_info->width2 = n;
item = string_list_append(push_item->string, show_info->list);
item->util = push_item->util;
return 0;
}
/*
* Sorting comparison for a string list that has push_info
* structs in its util field
*/
static int cmp_string_with_push(const void *va, const void *vb)
{
const struct string_list_item *a = va;
const struct string_list_item *b = vb;
const struct push_info *a_push = a->util;
const struct push_info *b_push = b->util;
int cmp = strcmp(a->string, b->string);
return cmp ? cmp : strcmp(a_push->dest, b_push->dest);
}
int show_push_info_item(struct string_list_item *item, void *cb_data)
{
struct show_info *show_info = cb_data;
struct push_info *push_info = item->util;
char *src = item->string, *status = NULL;
switch (push_info->status) {
case PUSH_STATUS_CREATE:
status = "create";
break;
case PUSH_STATUS_DELETE:
status = "delete";
src = "(none)";
break;
case PUSH_STATUS_UPTODATE:
status = "up to date";
break;
case PUSH_STATUS_FASTFORWARD:
status = "fast forwardable";
break;
case PUSH_STATUS_OUTOFDATE:
status = "local out of date";
break;
case PUSH_STATUS_NOTQUERIED:
break;
}
if (status)
printf(" %-*s %s to %-*s (%s)\n", show_info->width, src,
push_info->forced ? "forces" : "pushes",
show_info->width2, push_info->dest, status);
else
printf(" %-*s %s to %s\n", show_info->width, src,
push_info->forced ? "forces" : "pushes",
push_info->dest);
return 0;
}
static int show(int argc, const char **argv)
{
int no_query = 0, result = 0;
int no_query = 0, result = 0, query_flag = 0;
struct option options[] = {
OPT_GROUP("show specific options"),
OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"),
OPT_END()
};
struct ref_states states;
struct string_list info_list = { NULL, 0, 0, 0 };
struct show_info info;
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
if (argc < 1)
return show_all();
if (!no_query)
query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES);
memset(&states, 0, sizeof(states));
memset(&info, 0, sizeof(info));
info.states = &states;
info.list = &info_list;
for (; argc; argc--, argv++) {
int i;
get_remote_ref_states(*argv, &states, !no_query);
get_remote_ref_states(*argv, &states, query_flag);
printf("* remote %s\n URL: %s\n", *argv,
states.remote->url_nr > 0 ?
states.remote->url[0] : "(no URL)");
for (i = 0; i < branch_list.nr; i++) {
struct string_list_item *branch = branch_list.items + i;
struct branch_info *info = branch->util;
int j;
if (!info->merge.nr || strcmp(*argv, info->remote))
continue;
printf(" Remote branch%s merged with 'git pull' "
"while on branch %s\n ",
info->merge.nr > 1 ? "es" : "",
branch->string);
for (j = 0; j < info->merge.nr; j++)
printf(" %s", info->merge.items[j].string);
printf("\n");
}
if (!no_query) {
show_list(" New remote branch%s (next fetch "
"will store in remotes/%s)",
&states.new, states.remote->name);
show_list(" Stale tracking branch%s (use 'git remote "
"prune')", &states.stale, "");
}
if (no_query)
for_each_ref(append_ref_to_tracked_list, &states);
show_list(" Tracked remote branch%s", &states.tracked, "");
if (states.remote->push_refspec_nr) {
printf(" Local branch%s pushed with 'git push'\n",
states.remote->push_refspec_nr > 1 ?
"es" : "");
for (i = 0; i < states.remote->push_refspec_nr; i++) {
struct refspec *spec = states.remote->push + i;
printf(" %s%s%s%s\n",
spec->force ? "+" : "",
abbrev_branch(spec->src),
spec->dst ? ":" : "",
spec->dst ? abbrev_branch(spec->dst) : "");
}
printf(" HEAD branch: (not queried)\n");
else if (!states.heads.nr)
printf(" HEAD branch: (unknown)\n");
else if (states.heads.nr == 1)
printf(" HEAD branch: %s\n", states.heads.items[0].string);
else {
printf(" HEAD branch (remote HEAD is ambiguous,"
" may be one of the following):\n");
for (i = 0; i < states.heads.nr; i++)
printf(" %s\n", states.heads.items[i].string);
}
/* NEEDSWORK: free remote */
string_list_clear(&states.new, 0);
string_list_clear(&states.stale, 0);
string_list_clear(&states.tracked, 0);
/* remote branch info */
info.width = 0;
for_each_string_list(add_remote_to_show_info, &states.new, &info);
for_each_string_list(add_remote_to_show_info, &states.tracked, &info);
for_each_string_list(add_remote_to_show_info, &states.stale, &info);
if (info.list->nr)
printf(" Remote branch%s:%s\n",
info.list->nr > 1 ? "es" : "",
no_query ? " (status not queried)" : "");
for_each_string_list(show_remote_info_item, info.list, &info);
string_list_clear(info.list, 0);
/* git pull info */
info.width = 0;
info.any_rebase = 0;
for_each_string_list(add_local_to_show_info, &branch_list, &info);
if (info.list->nr)
printf(" Local branch%s configured for 'git pull':\n",
info.list->nr > 1 ? "es" : "");
for_each_string_list(show_local_info_item, info.list, &info);
string_list_clear(info.list, 0);
/* git push info */
if (states.remote->mirror)
printf(" Local refs will be mirrored by 'git push'\n");
info.width = info.width2 = 0;
for_each_string_list(add_push_to_show_info, &states.push, &info);
qsort(info.list->items, info.list->nr,
sizeof(*info.list->items), cmp_string_with_push);
if (info.list->nr)
printf(" Local ref%s configured for 'git push'%s:\n",
info.list->nr > 1 ? "s" : "",
no_query ? " (status not queried)" : "");
for_each_string_list(show_push_info_item, info.list, &info);
string_list_clear(info.list, 0);
free_remote_ref_states(&states);
}
return result;
}
static int set_head(int argc, const char **argv)
{
int i, opt_a = 0, opt_d = 0, result = 0;
struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
char *head_name = NULL;
struct option options[] = {
OPT_GROUP("set-head specific options"),
OPT_BOOLEAN('a', "auto", &opt_a,
"set refs/remotes/<name>/HEAD according to remote"),
OPT_BOOLEAN('d', "delete", &opt_d,
"delete refs/remotes/<name>/HEAD"),
OPT_END()
};
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
if (argc)
strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
if (!opt_a && !opt_d && argc == 2) {
head_name = xstrdup(argv[1]);
} else if (opt_a && !opt_d && argc == 1) {
struct ref_states states;
memset(&states, 0, sizeof(states));
get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
if (!states.heads.nr)
result |= error("Cannot determine remote HEAD");
else if (states.heads.nr > 1) {
result |= error("Multiple remote HEAD branches. "
"Please choose one explicitly with:");
for (i = 0; i < states.heads.nr; i++)
fprintf(stderr, " git remote set-head %s %s\n",
argv[0], states.heads.items[i].string);
} else
head_name = xstrdup(states.heads.items[0].string);
free_remote_ref_states(&states);
} else if (opt_d && !opt_a && argc == 1) {
if (delete_ref(buf.buf, NULL, REF_NODEREF))
result |= error("Could not delete %s", buf.buf);
} else
usage_with_options(builtin_remote_usage, options);
if (head_name) {
unsigned char sha1[20];
strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
/* make sure it's valid */
if (!resolve_ref(buf2.buf, sha1, 1, NULL))
result |= error("Not a valid ref: %s", buf2.buf);
else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
result |= error("Could not setup %s", buf.buf);
if (opt_a)
printf("%s/HEAD set to %s\n", argv[0], head_name);
free(head_name);
}
strbuf_release(&buf);
strbuf_release(&buf2);
return result;
}
static int prune(int argc, const char **argv)
{
int dry_run = 0, result = 0;
@@ -770,7 +1144,7 @@ static int prune(int argc, const char **argv)
for (; argc; argc--, argv++) {
int i;
get_remote_ref_states(*argv, &states, 1);
get_remote_ref_states(*argv, &states, GET_REF_STATES);
if (states.stale.nr) {
printf("Pruning %s\n", *argv);
@@ -791,10 +1165,7 @@ static int prune(int argc, const char **argv)
warn_dangling_symref(dangling_msg, refname);
}
/* NEEDSWORK: free remote */
string_list_clear(&states.new, 0);
string_list_clear(&states.stale, 0);
string_list_clear(&states.tracked, 0);
free_remote_ref_states(&states);
}
return result;
@@ -919,6 +1290,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
result = mv(argc, argv);
else if (!strcmp(argv[0], "rm"))
result = rm(argc, argv);
else if (!strcmp(argv[0], "set-head"))
result = set_head(argc, argv);
else if (!strcmp(argv[0], "show"))
result = show(argc, argv);
else if (!strcmp(argv[0], "prune"))

View File

@@ -59,8 +59,7 @@ static int check_local_mod(unsigned char *head, int index_only)
if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT)
fprintf(stderr, "warning: '%s': %s",
ce->name, strerror(errno));
warning("'%s': %s", ce->name, strerror(errno));
/* It already vanished from the working tree */
continue;
}

View File

@@ -1,6 +1,5 @@
#include "cache.h"
#include "commit.h"
#include "tag.h"
#include "refs.h"
#include "pkt-line.h"
#include "run-command.h"
@@ -11,9 +10,7 @@ static const char send_pack_usage[] =
"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
" --all and explicit <ref> specification are mutually exclusive.";
static struct send_pack_args args = {
/* .receivepack = */ "git-receive-pack",
};
static struct send_pack_args args;
static int feed_object(const unsigned char *sha1, int fd, int negative)
{
@@ -32,7 +29,7 @@ static int feed_object(const unsigned char *sha1, int fd, int negative)
/*
* Make a pack stream and spit it out into file descriptor fd
*/
static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra)
static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
{
/*
* The child becomes pack-objects --revs; we feed
@@ -50,7 +47,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
struct child_process po;
int i;
if (args.use_thin_pack)
if (args->use_thin_pack)
argv[4] = "--thin";
memset(&po, 0, sizeof(po));
po.argv = argv;
@@ -84,82 +81,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
return 0;
}
static void unmark_and_free(struct commit_list *list, unsigned int mark)
{
while (list) {
struct commit_list *temp = list;
temp->item->object.flags &= ~mark;
list = temp->next;
free(temp);
}
}
static int ref_newer(const unsigned char *new_sha1,
const unsigned char *old_sha1)
{
struct object *o;
struct commit *old, *new;
struct commit_list *list, *used;
int found = 0;
/* Both new and old must be commit-ish and new is descendant of
* old. Otherwise we require --force.
*/
o = deref_tag(parse_object(old_sha1), NULL, 0);
if (!o || o->type != OBJ_COMMIT)
return 0;
old = (struct commit *) o;
o = deref_tag(parse_object(new_sha1), NULL, 0);
if (!o || o->type != OBJ_COMMIT)
return 0;
new = (struct commit *) o;
if (parse_commit(new) < 0)
return 0;
used = list = NULL;
commit_list_insert(new, &list);
while (list) {
new = pop_most_recent_commit(&list, 1);
commit_list_insert(new, &used);
if (new == old) {
found = 1;
break;
}
}
unmark_and_free(list, 1);
unmark_and_free(used, 1);
return found;
}
static struct ref *local_refs, **local_tail;
static struct ref *remote_refs, **remote_tail;
static int one_local_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
struct ref *ref;
int len;
/* we already know it starts with refs/ to get here */
if (check_ref_format(refname + 5))
return 0;
len = strlen(refname) + 1;
ref = xcalloc(1, sizeof(*ref) + len);
hashcpy(ref->new_sha1, sha1);
memcpy(ref->name, refname, len);
*local_tail = ref;
local_tail = &ref->next;
return 0;
}
static void get_local_heads(void)
{
local_tail = &local_refs;
for_each_ref(one_local_ref, NULL);
}
static int receive_status(int in, struct ref *refs)
{
struct ref *hint;
@@ -247,16 +168,6 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
}
}
static const char *prettify_ref(const struct ref *ref)
{
const char *name = ref->name;
return name + (
!prefixcmp(name, "refs/heads/") ? 11 :
!prefixcmp(name, "refs/tags/") ? 10 :
!prefixcmp(name, "refs/remotes/") ? 13 :
0);
}
#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
@@ -385,27 +296,19 @@ static int refs_pushed(struct ref *ref)
return 0;
}
static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec)
int send_pack(struct send_pack_args *args,
int fd[], struct child_process *conn,
struct ref *remote_refs,
struct extra_have_objects *extra_have)
{
int in = fd[0];
int out = fd[1];
struct ref *ref;
int new_refs;
int ask_for_status_report = 0;
int allow_deleting_refs = 0;
int expect_status_report = 0;
int flags = MATCH_REFS_NONE;
int ret;
struct extra_have_objects extra_have;
memset(&extra_have, 0, sizeof(extra_have));
if (args.send_all)
flags |= MATCH_REFS_ALL;
if (args.send_mirror)
flags |= MATCH_REFS_MIRROR;
/* No funny business with the matcher */
remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL,
&extra_have);
get_local_heads();
/* Does the other end support the reporting? */
if (server_supports("report-status"))
@@ -413,19 +316,9 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
if (server_supports("delete-refs"))
allow_deleting_refs = 1;
/* match them up */
if (!remote_tail)
remote_tail = &remote_refs;
if (match_refs(local_refs, remote_refs, &remote_tail,
nr_refspec, refspec, flags)) {
close(out);
return -1;
}
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
"Perhaps you should specify a branch such as 'master'.\n");
close(out);
return 0;
}
@@ -437,7 +330,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
if (ref->peer_ref)
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
else if (!args.send_mirror)
else if (!args->send_mirror)
continue;
ref->deletion = is_null_sha1(ref->new_sha1);
@@ -476,7 +369,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
(!has_sha1_file(ref->old_sha1)
|| !ref_newer(ref->new_sha1, ref->old_sha1));
if (ref->nonfastforward && !ref->force && !args.force_update) {
if (ref->nonfastforward && !ref->force && !args->force_update) {
ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
continue;
}
@@ -484,7 +377,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
if (!ref->deletion)
new_refs++;
if (!args.dry_run) {
if (!args->dry_run) {
char *old_hex = sha1_to_hex(ref->old_sha1);
char *new_hex = sha1_to_hex(ref->new_sha1);
@@ -505,27 +398,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
}
packet_flush(out);
if (new_refs && !args.dry_run) {
if (pack_objects(out, remote_refs, &extra_have) < 0)
if (new_refs && !args->dry_run) {
if (pack_objects(out, remote_refs, extra_have, args) < 0) {
for (ref = remote_refs; ref; ref = ref->next)
ref->status = REF_STATUS_NONE;
return -1;
}
}
else
close(out);
if (expect_status_report)
ret = receive_status(in, remote_refs);
else
ret = 0;
print_push_status(dest, remote_refs);
if (!args.dry_run && remote) {
for (ref = remote_refs; ref; ref = ref->next)
update_tracking_ref(remote, ref);
}
if (!refs_pushed(remote_refs))
fprintf(stderr, "Everything up-to-date\n");
if (ret < 0)
return ret;
for (ref = remote_refs; ref; ref = ref->next) {
@@ -574,11 +459,19 @@ static void verify_remote_names(int nr_heads, const char **heads)
int cmd_send_pack(int argc, const char **argv, const char *prefix)
{
int i, nr_heads = 0;
const char **heads = NULL;
int i, nr_refspecs = 0;
const char **refspecs = NULL;
const char *remote_name = NULL;
struct remote *remote = NULL;
const char *dest = NULL;
int fd[2];
struct child_process *conn;
struct extra_have_objects extra_have;
struct ref *remote_refs, **remote_tail, *local_refs;
int ret;
int send_all = 0;
const char *receivepack = "git-receive-pack";
int flags;
argv++;
for (i = 1; i < argc; i++, argv++) {
@@ -586,11 +479,11 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
if (*arg == '-') {
if (!prefixcmp(arg, "--receive-pack=")) {
args.receivepack = arg + 15;
receivepack = arg + 15;
continue;
}
if (!prefixcmp(arg, "--exec=")) {
args.receivepack = arg + 7;
receivepack = arg + 7;
continue;
}
if (!prefixcmp(arg, "--remote=")) {
@@ -598,7 +491,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--all")) {
args.send_all = 1;
send_all = 1;
continue;
}
if (!strcmp(arg, "--dry-run")) {
@@ -627,8 +520,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
dest = arg;
continue;
}
heads = (const char **) argv;
nr_heads = argc - i;
refspecs = (const char **) argv;
nr_refspecs = argc - i;
break;
}
if (!dest)
@@ -637,8 +530,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
* --all and --mirror are incompatible; neither makes sense
* with any refspecs.
*/
if ((heads && (args.send_all || args.send_mirror)) ||
(args.send_all && args.send_mirror))
if ((refspecs && (send_all || args.send_mirror)) ||
(send_all && args.send_mirror))
usage(send_pack_usage);
if (remote_name) {
@@ -649,24 +542,50 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
}
}
return send_pack(&args, dest, remote, nr_heads, heads);
}
conn = git_connect(fd, dest, receivepack, args.verbose ? CONNECT_VERBOSE : 0);
int send_pack(struct send_pack_args *my_args,
const char *dest, struct remote *remote,
int nr_heads, const char **heads)
{
int fd[2], ret;
struct child_process *conn;
memset(&extra_have, 0, sizeof(extra_have));
memcpy(&args, my_args, sizeof(args));
get_remote_heads(fd[0], &remote_refs, 0, NULL, REF_NORMAL,
&extra_have);
verify_remote_names(nr_heads, heads);
verify_remote_names(nr_refspecs, refspecs);
conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
local_refs = get_local_heads();
flags = MATCH_REFS_NONE;
if (send_all)
flags |= MATCH_REFS_ALL;
if (args.send_mirror)
flags |= MATCH_REFS_MIRROR;
/* match them up */
remote_tail = &remote_refs;
while (*remote_tail)
remote_tail = &((*remote_tail)->next);
if (match_refs(local_refs, remote_refs, &remote_tail,
nr_refspecs, refspecs, flags)) {
return -1;
}
ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
close(fd[1]);
close(fd[0]);
/* do_send_pack always closes fd[1] */
ret |= finish_connect(conn);
return !!ret;
print_push_status(dest, remote_refs);
if (!args.dry_run && remote) {
struct ref *ref;
for (ref = remote_refs; ref; ref = ref->next)
update_tracking_ref(remote, ref);
}
if (!ret && !refs_pushed(remote_refs))
fprintf(stderr, "Everything up-to-date\n");
return ret;
}

View File

@@ -365,8 +365,7 @@ static int append_ref(const char *refname, const unsigned char *sha1,
return 0;
}
if (MAX_REVS <= ref_name_cnt) {
fprintf(stderr, "warning: ignoring %s; "
"cannot handle more than %d refs\n",
warning("ignoring %s; cannot handle more than %d refs",
refname, MAX_REVS);
return 0;
}

View File

@@ -140,7 +140,7 @@ static int exclude_existing(const char *match)
continue;
}
if (check_ref_format(ref)) {
fprintf(stderr, "warning: ref '%s' ignored\n", ref);
warning("ref '%s' ignored", ref);
continue;
}
if (!string_list_has_string(&existing_refs, ref)) {

View File

@@ -195,7 +195,7 @@ static int process_path(const char *path)
struct stat st;
len = strlen(path);
if (has_symlink_leading_path(len, path))
if (has_symlink_leading_path(path, len))
return error("'%s' is beyond a symbolic link", path);
/*

31
cache.h
View File

@@ -140,8 +140,8 @@ struct ondisk_cache_entry_extended {
};
struct cache_entry {
unsigned int ce_ctime;
unsigned int ce_mtime;
struct cache_time ce_ctime;
struct cache_time ce_mtime;
unsigned int ce_dev;
unsigned int ce_ino;
unsigned int ce_mode;
@@ -282,7 +282,7 @@ struct index_state {
struct cache_entry **cache;
unsigned int cache_nr, cache_alloc, cache_changed;
struct cache_tree *cache_tree;
time_t timestamp;
struct cache_time timestamp;
void *alloc;
unsigned name_hash_initialized : 1,
initialized : 1;
@@ -428,7 +428,7 @@ extern int read_index_preload(struct index_state *, const char **pathspec);
extern int read_index_from(struct index_state *, const char *path);
extern int is_index_unborn(struct index_state *);
extern int read_index_unmerged(struct index_state *);
extern int write_index(const struct index_state *, int newfd);
extern int write_index(struct index_state *, int newfd);
extern int discard_index(struct index_state *);
extern int unmerged_index(const struct index_state *);
extern int verify_path(const char *path);
@@ -443,6 +443,7 @@ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int opt
extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
extern int remove_index_entry_at(struct index_state *, int pos);
extern void remove_marked_cache_entries(struct index_state *istate);
extern int remove_file_from_index(struct index_state *, const char *path);
#define ADD_CACHE_VERBOSE 1
#define ADD_CACHE_PRETEND 2
@@ -541,8 +542,17 @@ enum rebase_setup_type {
AUTOREBASE_ALWAYS,
};
enum push_default_type {
PUSH_DEFAULT_UNSPECIFIED = -1,
PUSH_DEFAULT_NOTHING = 0,
PUSH_DEFAULT_MATCHING,
PUSH_DEFAULT_TRACKING,
PUSH_DEFAULT_CURRENT,
};
extern enum branch_track git_branch_track;
extern enum rebase_setup_type autorebase;
extern enum push_default_type push_default;
#define GIT_REPO_VERSION 0
extern int repository_format_version;
@@ -645,7 +655,6 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l
extern int move_temp_to_file(const char *tmpfile, const char *filename);
extern int has_sha1_pack(const unsigned char *sha1);
extern int has_sha1_kept_pack(const unsigned char *sha1);
extern int has_sha1_file(const unsigned char *sha1);
extern int has_loose_object_nonlocal(const unsigned char *sha1);
@@ -725,11 +734,13 @@ 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 int has_symlink_leading_path(const char *name, int len);
extern int has_symlink_or_noent_leading_path(const char *name, int len);
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
extern void invalidate_lstat_cache(const char *name, int len);
extern void clear_lstat_cache(void);
extern void schedule_dir_for_removal(const char *name, int len);
extern void remove_scheduled_dirs(void);
extern struct alternate_object_database {
struct alternate_object_database *next;
@@ -802,7 +813,7 @@ struct ref {
#define REF_HEADS (1u << 1)
#define REF_TAGS (1u << 2)
extern struct ref *find_ref_by_name(struct ref *list, const char *name);
extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
#define CONNECT_VERBOSE (1u << 0)
extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);

View File

@@ -712,9 +712,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
result_size = buf.len;
result = strbuf_detach(&buf, NULL);
elem->mode = canon_mode(st.st_mode);
}
else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
!fstat(fd, &st)) {
} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
size_t len = xsize_t(st.st_size);
ssize_t done;
int is_file, i;

View File

@@ -4,6 +4,119 @@
unsigned int _CRT_fmode = _O_BINARY;
static int err_win_to_posix(DWORD winerr)
{
int error = ENOSYS;
switch(winerr) {
case ERROR_ACCESS_DENIED: error = EACCES; break;
case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
case ERROR_ALREADY_EXISTS: error = EEXIST; break;
case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
case ERROR_BAD_COMMAND: error = EIO; break;
case ERROR_BAD_DEVICE: error = ENODEV; break;
case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_LENGTH: error = EINVAL; break;
case ERROR_BAD_PATHNAME: error = ENOENT; break;
case ERROR_BAD_PIPE: error = EPIPE; break;
case ERROR_BAD_UNIT: error = ENODEV; break;
case ERROR_BAD_USERNAME: error = EINVAL; break;
case ERROR_BROKEN_PIPE: error = EPIPE; break;
case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
case ERROR_BUSY: error = EBUSY; break;
case ERROR_BUSY_DRIVE: error = EBUSY; break;
case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
case ERROR_CANNOT_MAKE: error = EACCES; break;
case ERROR_CANTOPEN: error = EIO; break;
case ERROR_CANTREAD: error = EIO; break;
case ERROR_CANTWRITE: error = EIO; break;
case ERROR_CRC: error = EIO; break;
case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
case ERROR_DEVICE_IN_USE: error = EBUSY; break;
case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
case ERROR_DIRECTORY: error = EINVAL; break;
case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
case ERROR_DISK_CHANGE: error = EIO; break;
case ERROR_DISK_FULL: error = ENOSPC; break;
case ERROR_DRIVE_LOCKED: error = EBUSY; break;
case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
case ERROR_FILE_EXISTS: error = EEXIST; break;
case ERROR_FILE_INVALID: error = ENODEV; break;
case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
case ERROR_GEN_FAILURE: error = EIO; break;
case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
case ERROR_INVALID_ACCESS: error = EACCES; break;
case ERROR_INVALID_ADDRESS: error = EFAULT; break;
case ERROR_INVALID_BLOCK: error = EFAULT; break;
case ERROR_INVALID_DATA: error = EINVAL; break;
case ERROR_INVALID_DRIVE: error = ENODEV; break;
case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
case ERROR_INVALID_FLAGS: error = EINVAL; break;
case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
case ERROR_INVALID_HANDLE: error = EBADF; break;
case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
case ERROR_INVALID_NAME: error = EINVAL; break;
case ERROR_INVALID_OWNER: error = EINVAL; break;
case ERROR_INVALID_PARAMETER: error = EINVAL; break;
case ERROR_INVALID_PASSWORD: error = EPERM; break;
case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
case ERROR_INVALID_WORKSTATION: error = EACCES; break;
case ERROR_IO_DEVICE: error = EIO; break;
case ERROR_IO_INCOMPLETE: error = EINTR; break;
case ERROR_LOCKED: error = EBUSY; break;
case ERROR_LOCK_VIOLATION: error = EACCES; break;
case ERROR_LOGON_FAILURE: error = EACCES; break;
case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
case ERROR_MORE_DATA: error = EPIPE; break;
case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
case ERROR_NOACCESS: error = EFAULT; break;
case ERROR_NONE_MAPPED: error = EINVAL; break;
case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
case ERROR_NOT_READY: error = EAGAIN; break;
case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
case ERROR_NO_DATA: error = EPIPE; break;
case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
case ERROR_OPEN_FAILED: error = EIO; break;
case ERROR_OPEN_FILES: error = EBUSY; break;
case ERROR_OPERATION_ABORTED: error = EINTR; break;
case ERROR_OUTOFMEMORY: error = ENOMEM; break;
case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
case ERROR_PATH_BUSY: error = EBUSY; break;
case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
case ERROR_PIPE_BUSY: error = EBUSY; break;
case ERROR_PIPE_CONNECTED: error = EPIPE; break;
case ERROR_PIPE_LISTENING: error = EPIPE; break;
case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
case ERROR_READ_FAULT: error = EIO; break;
case ERROR_SEEK: error = EIO; break;
case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
case ERROR_SHARING_VIOLATION: error = EACCES; break;
case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
case ERROR_SWAPERROR: error = ENOENT; break;
case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
case ERROR_WRITE_FAULT: error = EIO; break;
case ERROR_WRITE_PROTECT: error = EROFS; break;
}
return error;
}
#undef open
int mingw_open (const char *filename, int oflags, ...)
{
@@ -344,7 +457,7 @@ static const char *quote_arg(const char *arg)
const char *p = arg;
if (!*p) force_quotes = 1;
while (*p) {
if (isspace(*p) || *p == '*' || *p == '?' || *p == '{')
if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
force_quotes = 1;
else if (*p == '"')
n++;
@@ -821,7 +934,9 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
#undef rename
int mingw_rename(const char *pold, const char *pnew)
{
DWORD attrs;
DWORD attrs, gle;
int tries = 0;
static const int delay[] = { 0, 1, 10, 20, 40 };
/*
* Try native rename() first to get errno right.
@@ -831,10 +946,12 @@ int mingw_rename(const char *pold, const char *pnew)
return 0;
if (errno != EEXIST)
return -1;
repeat:
if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
return 0;
/* TODO: translate more errors */
if (GetLastError() == ERROR_ACCESS_DENIED &&
gle = GetLastError();
if (gle == ERROR_ACCESS_DENIED &&
(attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
errno = EISDIR;
@@ -844,10 +961,24 @@ int mingw_rename(const char *pold, const char *pnew)
SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
return 0;
gle = GetLastError();
/* revert file attributes on failure */
SetFileAttributes(pnew, attrs);
}
}
if (tries < ARRAY_SIZE(delay) && gle == ERROR_ACCESS_DENIED) {
/*
* We assume that some other process had the source or
* destination file open at the wrong moment and retry.
* In order to give the other process a higher chance to
* complete its operation, we give up our time slice now.
* If we have to retry again, we do sleep a bit.
*/
Sleep(delay[tries]);
tries++;
warning("rename retry #%d %s -> %s", tries, pold, pnew);
goto repeat;
}
errno = EACCES;
return -1;
}
@@ -1006,123 +1137,9 @@ void mingw_open_html(const char *unixpath)
ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);
}
static int err_win_to_posix(DWORD winerr)
{
int error = ENOSYS;
switch(winerr) {
case ERROR_ACCESS_DENIED: error = EACCES; break;
case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
case ERROR_ALREADY_EXISTS: error = EEXIST; break;
case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
case ERROR_BAD_COMMAND: error = EIO; break;
case ERROR_BAD_DEVICE: error = ENODEV; break;
case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_LENGTH: error = EINVAL; break;
case ERROR_BAD_PATHNAME: error = ENOENT; break;
case ERROR_BAD_PIPE: error = EPIPE; break;
case ERROR_BAD_UNIT: error = ENODEV; break;
case ERROR_BAD_USERNAME: error = EINVAL; break;
case ERROR_BROKEN_PIPE: error = EPIPE; break;
case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
case ERROR_BUSY: error = EBUSY; break;
case ERROR_BUSY_DRIVE: error = EBUSY; break;
case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
case ERROR_CANNOT_MAKE: error = EACCES; break;
case ERROR_CANTOPEN: error = EIO; break;
case ERROR_CANTREAD: error = EIO; break;
case ERROR_CANTWRITE: error = EIO; break;
case ERROR_CRC: error = EIO; break;
case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
case ERROR_DEVICE_IN_USE: error = EBUSY; break;
case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
case ERROR_DIRECTORY: error = EINVAL; break;
case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
case ERROR_DISK_CHANGE: error = EIO; break;
case ERROR_DISK_FULL: error = ENOSPC; break;
case ERROR_DRIVE_LOCKED: error = EBUSY; break;
case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
case ERROR_FILE_EXISTS: error = EEXIST; break;
case ERROR_FILE_INVALID: error = ENODEV; break;
case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
case ERROR_GEN_FAILURE: error = EIO; break;
case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
case ERROR_INVALID_ACCESS: error = EACCES; break;
case ERROR_INVALID_ADDRESS: error = EFAULT; break;
case ERROR_INVALID_BLOCK: error = EFAULT; break;
case ERROR_INVALID_DATA: error = EINVAL; break;
case ERROR_INVALID_DRIVE: error = ENODEV; break;
case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
case ERROR_INVALID_FLAGS: error = EINVAL; break;
case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
case ERROR_INVALID_HANDLE: error = EBADF; break;
case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
case ERROR_INVALID_NAME: error = EINVAL; break;
case ERROR_INVALID_OWNER: error = EINVAL; break;
case ERROR_INVALID_PARAMETER: error = EINVAL; break;
case ERROR_INVALID_PASSWORD: error = EPERM; break;
case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
case ERROR_INVALID_WORKSTATION: error = EACCES; break;
case ERROR_IO_DEVICE: error = EIO; break;
case ERROR_IO_INCOMPLETE: error = EINTR; break;
case ERROR_LOCKED: error = EBUSY; break;
case ERROR_LOCK_VIOLATION: error = EACCES; break;
case ERROR_LOGON_FAILURE: error = EACCES; break;
case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
case ERROR_MORE_DATA: error = EPIPE; break;
case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
case ERROR_NOACCESS: error = EFAULT; break;
case ERROR_NONE_MAPPED: error = EINVAL; break;
case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
case ERROR_NOT_READY: error = EAGAIN; break;
case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
case ERROR_NO_DATA: error = EPIPE; break;
case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
case ERROR_OPEN_FAILED: error = EIO; break;
case ERROR_OPEN_FILES: error = EBUSY; break;
case ERROR_OPERATION_ABORTED: error = EINTR; break;
case ERROR_OUTOFMEMORY: error = ENOMEM; break;
case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
case ERROR_PATH_BUSY: error = EBUSY; break;
case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
case ERROR_PIPE_BUSY: error = EBUSY; break;
case ERROR_PIPE_CONNECTED: error = EPIPE; break;
case ERROR_PIPE_LISTENING: error = EPIPE; break;
case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
case ERROR_READ_FAULT: error = EIO; break;
case ERROR_SEEK: error = EIO; break;
case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
case ERROR_SHARING_VIOLATION: error = EACCES; break;
case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
case ERROR_SWAPERROR: error = ENOENT; break;
case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
case ERROR_WRITE_FAULT: error = EIO; break;
case ERROR_WRITE_PROTECT: error = EROFS; break;
}
return error;
}
int link(const char *oldpath, const char *newpath)
{
typedef BOOL WINAPI (*T)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES);
typedef BOOL WINAPI (*T)(const char*, const char*, LPSECURITY_ATTRIBUTES);
static T create_hard_link = NULL;
if (!create_hard_link) {
create_hard_link = (T) GetProcAddress(

View File

@@ -1,6 +1,7 @@
#include "../git-compat-util.h"
/* Note that this doesn't return the actual pagesize, but
/*
* Note that this doesn't return the actual pagesize, but
* the allocation granularity. If future Windows specific git code
* needs the real getpagesize function, we need to find another solution.
*/
@@ -11,8 +12,7 @@ int mingw_getpagesize(void)
return si.dwAllocationGranularity;
}
void *git_mmap
(void *start, size_t length, int prot, int flags, int fd, off_t offset)
void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
HANDLE hmap;
void *temp;

View File

@@ -565,6 +565,31 @@ static int git_default_branch_config(const char *var, const char *value)
return 0;
}
static int git_default_push_config(const char *var, const char *value)
{
if (!strcmp(var, "push.default")) {
if (!value)
return config_error_nonbool(var);
else if (!strcmp(value, "nothing"))
push_default = PUSH_DEFAULT_NOTHING;
else if (!strcmp(value, "matching"))
push_default = PUSH_DEFAULT_MATCHING;
else if (!strcmp(value, "tracking"))
push_default = PUSH_DEFAULT_TRACKING;
else if (!strcmp(value, "current"))
push_default = PUSH_DEFAULT_CURRENT;
else {
error("Malformed value for %s: %s", var, value);
return error("Must be one of nothing, matching, "
"tracking or current.");
}
return 0;
}
/* Add other config variables here and to Documentation/config.txt. */
return 0;
}
static int git_default_mailmap_config(const char *var, const char *value)
{
if (!strcmp(var, "mailmap.file"))
@@ -588,6 +613,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
if (!prefixcmp(var, "branch."))
return git_default_branch_config(var, value);
if (!prefixcmp(var, "push."))
return git_default_push_config(var, value);
if (!prefixcmp(var, "mailmap."))
return git_default_mailmap_config(var, value);
@@ -644,28 +672,37 @@ int git_config_global(void)
int git_config(config_fn_t fn, void *data)
{
int ret = 0;
int ret = 0, found = 0;
char *repo_config = NULL;
const char *home = NULL;
/* Setting $GIT_CONFIG makes git read _only_ the given config file. */
if (config_exclusive_filename)
return git_config_from_file(fn, config_exclusive_filename, data);
if (git_config_system() && !access(git_etc_gitconfig(), R_OK))
if (git_config_system() && !access(git_etc_gitconfig(), R_OK)) {
ret += git_config_from_file(fn, git_etc_gitconfig(),
data);
found += 1;
}
home = getenv("HOME");
if (git_config_global() && home) {
char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
if (!access(user_config, R_OK))
if (!access(user_config, R_OK)) {
ret += git_config_from_file(fn, user_config, data);
found += 1;
}
free(user_config);
}
repo_config = git_pathdup("config");
ret += git_config_from_file(fn, repo_config, data);
if (!access(repo_config, R_OK)) {
ret += git_config_from_file(fn, repo_config, data);
found += 1;
}
free(repo_config);
if (found == 0)
return -1;
return ret;
}

View File

@@ -42,6 +42,8 @@ else \
if test "$withval" = "yes"; then \
AC_MSG_WARN([You should provide path for --with-$1=PATH]); \
else \
m4_toupper($1)_PATH=$withval; \
AC_MSG_NOTICE([Setting m4_toupper($1)_PATH to $withval]); \
GIT_CONF_APPEND_LINE(${PROGRAM}_PATH=$withval); \
fi; \
fi; \
@@ -61,6 +63,8 @@ elif test "$withval" = "yes"; then \
m4_toupper(NO_$1)=; \
else \
m4_toupper(NO_$1)=; \
m4_toupper($1)DIR=$withval; \
AC_MSG_NOTICE([Setting m4_toupper($1)DIR to $withval]); \
GIT_CONF_APPEND_LINE(${PACKAGE}DIR=$withval); \
fi \
])# GIT_PARSE_WITH
@@ -76,6 +80,32 @@ AC_DEFUN([GIT_CHECK_FUNC],[AC_CHECK_FUNC([$1],[
AC_SEARCH_LIBS([$1],,
[$2],[$3])
],[$3])])
dnl
dnl GIT_STASH_FLAGS(BASEPATH_VAR)
dnl -----------------------------
dnl Allow for easy stashing of LDFLAGS and CPPFLAGS before running
dnl tests that may want to take user settings into account.
AC_DEFUN([GIT_STASH_FLAGS],[
if test -n "$1"; then
old_CPPFLAGS="$CPPFLAGS"
old_LDFLAGS="$LDFLAGS"
CPPFLAGS="-I$1/include $CPPFLAGS"
LDFLAGS="-L$1/$lib $LDFLAGS"
fi
])
dnl
dnl GIT_UNSTASH_FLAGS(BASEPATH_VAR)
dnl -----------------------------
dnl Restore the stashed *FLAGS values.
AC_DEFUN([GIT_UNSTASH_FLAGS],[
if test -n "$1"; then
CPPFLAGS="$old_CPPFLAGS"
LDFLAGS="$old_LDFLAGS"
fi
])
## Site configuration related to programs (before tests)
## --with-PACKAGE[=ARG] and --without-PACKAGE
#
@@ -86,9 +116,124 @@ AC_ARG_WITH([lib],
[if test "$withval" = "no" || test "$withval" = "yes"; then \
AC_MSG_WARN([You should provide name for --with-lib=ARG]); \
else \
lib=$withval; \
AC_MSG_NOTICE([Setting lib to '$lib']); \
GIT_CONF_APPEND_LINE(lib=$withval); \
fi; \
],[])
if test -z "$lib"; then
AC_MSG_NOTICE([Setting lib to 'lib' (the default)])
lib=lib
fi
AC_ARG_ENABLE([pthreads],
[AS_HELP_STRING([--enable-pthreads=FLAGS],
[FLAGS is the value to pass to the compiler to enable POSIX Threads.]
[The default if FLAGS is not specified is to try first -pthread]
[and then -lpthread.]
[--without-pthreads will disable threading.])],
[
if test "x$enableval" = "xyes"; then
AC_MSG_NOTICE([Will try -pthread then -lpthread to enable POSIX Threads])
elif test "x$enableval" != "xno"; then
PTHREAD_CFLAGS=$enableval
AC_MSG_NOTICE([Setting '$PTHREAD_CFLAGS' as the FLAGS to enable POSIX Threads])
else
AC_MSG_NOTICE([POSIX Threads will be disabled.])
NO_PTHREADS=YesPlease
USER_NOPTHREAD=1
fi],
[
AC_MSG_NOTICE([Will try -pthread then -lpthread to enable POSIX Threads.])
])
## Site configuration (override autodetection)
## --with-PACKAGE[=ARG] and --without-PACKAGE
AC_MSG_NOTICE([CHECKS for site configuration])
#
# Define NO_SVN_TESTS if you want to skip time-consuming SVN interoperability
# tests. These tests take up a significant amount of the total test time
# but are not needed unless you plan to talk to SVN repos.
#
# Define MOZILLA_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
# choice) has very fast version optimized for i586.
#
# Define PPC_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for PowerPC.
#
# Define ARM_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for ARM.
#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# This also implies MOZILLA_SHA1.
#
# Define OPENSSLDIR=/foo/bar if your openssl header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
AC_ARG_WITH(openssl,
AS_HELP_STRING([--with-openssl],[use OpenSSL library (default is YES)])
AS_HELP_STRING([], [ARG can be prefix for openssl library and headers]),\
GIT_PARSE_WITH(openssl))
#
# Define NO_CURL if you do not have curl installed. git-http-pull and
# git-http-push are not built, and you cannot use http:// and https://
# transports.
#
# Define CURLDIR=/foo/bar if your curl header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
AC_ARG_WITH(curl,
AS_HELP_STRING([--with-curl],[support http(s):// transports (default is YES)])
AS_HELP_STRING([], [ARG can be also prefix for curl library and headers]),
GIT_PARSE_WITH(curl))
#
# Define NO_EXPAT if you do not have expat installed. git-http-push is
# not built, and you cannot push using http:// and https:// transports.
#
# Define EXPATDIR=/foo/bar if your expat header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
AC_ARG_WITH(expat,
AS_HELP_STRING([--with-expat],
[support git-push using http:// and https:// transports via WebDAV (default is YES)])
AS_HELP_STRING([], [ARG can be also prefix for expat library and headers]),
GIT_PARSE_WITH(expat))
#
# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink
# installed in /sw, but don't want GIT to link against any libraries
# installed there. If defined you may specify your own (or Fink's)
# include directories and library directories by defining CFLAGS
# and LDFLAGS appropriately.
#
# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X,
# have DarwinPorts installed in /opt/local, but don't want GIT to
# link against any libraries installed there. If defined you may
# specify your own (or DarwinPort's) include directories and
# library directories by defining CFLAGS and LDFLAGS appropriately.
#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_ICONV if your libc does not properly support iconv.
AC_ARG_WITH(iconv,
AS_HELP_STRING([--without-iconv],
[if your architecture doesn't properly support iconv])
AS_HELP_STRING([--with-iconv=PATH],
[PATH is prefix for libiconv library and headers])
AS_HELP_STRING([],
[used only if you need linking with libiconv]),
GIT_PARSE_WITH(iconv))
## --enable-FEATURE[=ARG] and --disable-FEATURE
#
# Define USE_NSEC below if you want git to care about sub-second file mtimes
# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
# randomly break unless your underlying filesystem supports those sub-second
# times (my ext3 doesn't).
#
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-index perspective.
#
# Define SHELL_PATH to provide path to shell.
GIT_ARG_SET_PATH(shell)
@@ -167,7 +312,7 @@ fi
AC_CHECK_PROGS(ASCIIDOC, [asciidoc])
if test -n "$ASCIIDOC"; then
AC_MSG_CHECKING([for asciidoc version])
asciidoc_version=`$ASCIIDOC --version 2>&1`
asciidoc_version=`$ASCIIDOC --version 2>/dev/null`
case "${asciidoc_version}" in
asciidoc' '8*)
ASCIIDOC8=YesPlease
@@ -191,33 +336,57 @@ AC_MSG_NOTICE([CHECKS for libraries])
#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
GIT_STASH_FLAGS($OPENSSLDIR)
AC_CHECK_LIB([crypto], [SHA1_Init],
[NEEDS_SSL_WITH_CRYPTO=],
[AC_CHECK_LIB([ssl], [SHA1_Init],
[NEEDS_SSL_WITH_CRYPTO=YesPlease
NEEDS_SSL_WITH_CRYPTO=],
[NO_OPENSSL=YesPlease])])
GIT_UNSTASH_FLAGS($OPENSSLDIR)
AC_SUBST(NEEDS_SSL_WITH_CRYPTO)
AC_SUBST(NO_OPENSSL)
#
# Define NO_CURL if you do not have libcurl installed. git-http-pull and
# git-http-push are not built, and you cannot use http:// and https://
# transports.
GIT_STASH_FLAGS($CURLDIR)
AC_CHECK_LIB([curl], [curl_global_init],
[NO_CURL=],
[NO_CURL=YesPlease])
GIT_UNSTASH_FLAGS($CURLDIR)
AC_SUBST(NO_CURL)
#
# Define NO_EXPAT if you do not have expat installed. git-http-push is
# not built, and you cannot push using http:// and https:// transports.
GIT_STASH_FLAGS($EXPATDIR)
AC_CHECK_LIB([expat], [XML_ParserCreate],
[NO_EXPAT=],
[NO_EXPAT=YesPlease])
GIT_UNSTASH_FLAGS($EXPATDIR)
AC_SUBST(NO_EXPAT)
#
# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin and
# some Solaris installations).
# Define NO_ICONV if neither libc nor libiconv support iconv.
GIT_STASH_FLAGS($ICONVDIR)
AC_DEFUN([ICONVTEST_SRC], [
#include <iconv.h>
@@ -227,25 +396,46 @@ int main(void)
return 0;
}
])
AC_MSG_CHECKING([for iconv in -lc])
AC_LINK_IFELSE(ICONVTEST_SRC,
if test -n "$ICONVDIR"; then
lib_order="-liconv -lc"
else
lib_order="-lc -liconv"
fi
NO_ICONV=YesPlease
for l in $lib_order; do
if test "$l" = "-liconv"; then
NEEDS_LIBICONV=YesPlease
else
NEEDS_LIBICONV=
fi
old_LIBS="$LIBS"
LIBS="$LIBS $l"
AC_MSG_CHECKING([for iconv in $l])
AC_LINK_IFELSE(ICONVTEST_SRC,
[AC_MSG_RESULT([yes])
NEEDS_LIBICONV=],
[AC_MSG_RESULT([no])
old_LIBS="$LIBS"
LIBS="$LIBS -liconv"
AC_MSG_CHECKING([for iconv in -liconv])
AC_LINK_IFELSE(ICONVTEST_SRC,
[AC_MSG_RESULT([yes])
NEEDS_LIBICONV=YesPlease],
[AC_MSG_RESULT([no])
NO_ICONV=YesPlease])
LIBS="$old_LIBS"])
NO_ICONV=
break],
[AC_MSG_RESULT([no])])
LIBS="$old_LIBS"
done
#in case of break
LIBS="$old_LIBS"
GIT_UNSTASH_FLAGS($ICONVDIR)
AC_SUBST(NEEDS_LIBICONV)
AC_SUBST(NO_ICONV)
test -n "$NEEDS_LIBICONV" && LIBS="$LIBS -liconv"
#
# Define NO_DEFLATE_BOUND if deflateBound is missing from zlib.
GIT_STASH_FLAGS($ZLIB_PATH)
AC_DEFUN([ZLIBTEST_SRC], [
#include <zlib.h>
@@ -263,7 +453,11 @@ AC_LINK_IFELSE(ZLIBTEST_SRC,
[AC_MSG_RESULT([no])
NO_DEFLATE_BOUND=yes])
LIBS="$old_LIBS"
GIT_UNSTASH_FLAGS($ZLIB_PATH)
AC_SUBST(NO_DEFLATE_BOUND)
#
# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
# Patrick Mauritz).
@@ -297,13 +491,18 @@ int main(void)
return 0;
}
]])
GIT_STASH_FLAGS($ICONVDIR)
AC_MSG_CHECKING([for old iconv()])
AC_COMPILE_IFELSE(OLDICONVTEST_SRC,
[AC_MSG_RESULT([no])],
[AC_MSG_RESULT([yes])
OLD_ICONV=UnfortunatelyYes])
AC_SUBST(OLD_ICONV)
GIT_UNSTASH_FLAGS($ICONVDIR)
AC_SUBST(OLD_ICONV)
## Checks for typedefs, structures, and compiler characteristics.
AC_MSG_NOTICE([CHECKS for typedefs, structures, and compiler characteristics])
@@ -494,114 +693,65 @@ AC_SUBST(NO_MKDTEMP)
#
# 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;]]
)])
${CC} -pthread conftest.c -o conftest.o > /dev/null 2>&1
if test $? -eq 0;then
PTHREAD_LIBS="-pthread"
THREADED_DELTA_SEARCH=YesPlease
AC_DEFUN([PTHREADTEST_SRC], [
#include <pthread.h>
int main(void)
{
pthread_mutex_t test_mutex;
return (0);
}
])
dnl AC_LANG_CONFTEST([AC_LANG_PROGRAM(
dnl [[#include <pthread.h>]],
dnl [[pthread_mutex_t test_mutex;]]
dnl )])
NO_PTHREADS=UnfortunatelyYes
THREADED_DELTA_SEARCH=
PTHREAD_LIBS=
if test -n "$USER_NOPTHREAD"; then
AC_MSG_NOTICE([Skipping POSIX Threads at user request.])
# handle these separately since PTHREAD_CFLAGS could be '-lpthreads
# -D_REENTRANT' or some such.
elif test -z "$PTHREAD_CFLAGS"; then
for opt in -pthread -lpthread; do
old_CFLAGS="$CFLAGS"
CFLAGS="$opt $CFLAGS"
AC_MSG_CHECKING([Checking for POSIX Threads with '$opt'])
AC_LINK_IFELSE(PTHREADTEST_SRC,
[AC_MSG_RESULT([yes])
NO_PTHREADS=
PTHREAD_LIBS="$opt"
THREADED_DELTA_SEARCH=YesPlease
break
],
[AC_MSG_RESULT([no])])
CFLAGS="$old_CFLAGS"
done
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
old_CFLAGS="$CFLAGS"
CFLAGS="$PTHREAD_CFLAGS $CFLAGS"
AC_MSG_CHECKING([Checking for POSIX Threads with '$PTHREAD_CFLAGS'])
AC_LINK_IFELSE(PTHREADTEST_SRC,
[AC_MSG_RESULT([yes])
NO_PTHREADS=
PTHREAD_LIBS="$PTHREAD_CFLAGS"
THREADED_DELTA_SEARCH=YesPlease
],
[AC_MSG_RESULT([no])])
CFLAGS="$old_CFLAGS"
fi
CFLAGS="$old_CFLAGS"
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(NO_PTHREADS)
AC_SUBST(THREADED_DELTA_SEARCH)
## Site configuration (override autodetection)
## --with-PACKAGE[=ARG] and --without-PACKAGE
AC_MSG_NOTICE([CHECKS for site configuration])
#
# Define NO_SVN_TESTS if you want to skip time-consuming SVN interoperability
# tests. These tests take up a significant amount of the total test time
# but are not needed unless you plan to talk to SVN repos.
#
# Define MOZILLA_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
# choice) has very fast version optimized for i586.
#
# Define PPC_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for PowerPC.
#
# Define ARM_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for ARM.
#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# This also implies MOZILLA_SHA1.
#
# Define OPENSSLDIR=/foo/bar if your openssl header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
AC_ARG_WITH(openssl,
AS_HELP_STRING([--with-openssl],[use OpenSSL library (default is YES)])
AS_HELP_STRING([], [ARG can be prefix for openssl library and headers]),\
GIT_PARSE_WITH(openssl))
#
# Define NO_CURL if you do not have curl installed. git-http-pull and
# git-http-push are not built, and you cannot use http:// and https://
# transports.
#
# Define CURLDIR=/foo/bar if your curl header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
AC_ARG_WITH(curl,
AS_HELP_STRING([--with-curl],[support http(s):// transports (default is YES)])
AS_HELP_STRING([], [ARG can be also prefix for curl library and headers]),
GIT_PARSE_WITH(curl))
#
# Define NO_EXPAT if you do not have expat installed. git-http-push is
# not built, and you cannot push using http:// and https:// transports.
#
# Define EXPATDIR=/foo/bar if your expat header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
AC_ARG_WITH(expat,
AS_HELP_STRING([--with-expat],
[support git-push using http:// and https:// transports via WebDAV (default is YES)])
AS_HELP_STRING([], [ARG can be also prefix for expat library and headers]),
GIT_PARSE_WITH(expat))
#
# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink
# installed in /sw, but don't want GIT to link against any libraries
# installed there. If defined you may specify your own (or Fink's)
# include directories and library directories by defining CFLAGS
# and LDFLAGS appropriately.
#
# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X,
# have DarwinPorts installed in /opt/local, but don't want GIT to
# link against any libraries installed there. If defined you may
# specify your own (or DarwinPort's) include directories and
# library directories by defining CFLAGS and LDFLAGS appropriately.
#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_ICONV if your libc does not properly support iconv.
AC_ARG_WITH(iconv,
AS_HELP_STRING([--without-iconv],
[if your architecture doesn't properly support iconv])
AS_HELP_STRING([--with-iconv=PATH],
[PATH is prefix for libiconv library and headers])
AS_HELP_STRING([],
[used only if you need linking with libiconv]),
GIT_PARSE_WITH(iconv))
## --enable-FEATURE[=ARG] and --disable-FEATURE
#
# Define USE_NSEC below if you want git to care about sub-second file mtimes
# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
# randomly break unless your underlying filesystem supports those sub-second
# times (my ext3 doesn't).
#
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-index perspective.
## Output files
AC_CONFIG_FILES(["${config_file}":"${config_in}":"${config_append}"])
AC_OUTPUT

View File

@@ -899,7 +899,7 @@ _git_diff ()
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--*)
__gitcomp "--cached --pickaxe-all --pickaxe-regex
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
--base --ours --theirs
$__git_diff_common_options
"
@@ -930,15 +930,21 @@ _git_format_patch ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--thread=*)
__gitcomp "
deep shallow
" "" "${cur##--thread=}"
return
;;
--*)
__gitcomp "
--stdout --attach --thread
--stdout --attach --no-attach --thread --thread=
--output-directory
--numbered --start-number
--numbered-files
--keep-subject
--signoff
--in-reply-to=
--in-reply-to= --cc=
--full-index --binary
--not --all
--cover-letter
@@ -952,6 +958,21 @@ _git_format_patch ()
__git_complete_revlist
}
_git_fsck ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--*)
__gitcomp "
--tags --root --unreachable --cache --no-reflogs --full
--strict --verbose --lost-found
"
return
;;
esac
COMPREPLY=()
}
_git_gc ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1082,7 +1103,7 @@ _git_log ()
local cur="${COMP_WORDS[COMP_CWORD]}"
local g="$(git rev-parse --git-dir 2>/dev/null)"
local merge=""
if [ -f $g/MERGE_HEAD ]; then
if [ -f "$g/MERGE_HEAD" ]; then
merge="--merge"
fi
case "$cur" in
@@ -1249,8 +1270,8 @@ _git_send_email ()
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--*)
__gitcomp "--bcc --cc --cc-cmd --chain-reply-to --compose
--dry-run --envelope-sender --from --identity
__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
--compose --dry-run --envelope-sender --from --identity
--in-reply-to --no-chain-reply-to --no-signed-off-by-cc
--no-suppress-from --no-thread --quiet
--signed-off-by-cc --smtp-pass --smtp-server
@@ -1516,7 +1537,7 @@ _git_config ()
_git_remote ()
{
local subcommands="add rename rm show prune update"
local subcommands="add rename rm show prune update set-head"
local subcommand="$(__git_find_subcommand "$subcommands")"
if [ -z "$subcommand" ]; then
__gitcomp "$subcommands"
@@ -1880,6 +1901,7 @@ _git ()
diff) _git_diff ;;
fetch) _git_fetch ;;
format-patch) _git_format_patch ;;
fsck) _git_fsck ;;
gc) _git_gc ;;
grep) _git_grep ;;
help) _git_help ;;
@@ -1921,7 +1943,7 @@ _gitk ()
local cur="${COMP_WORDS[COMP_CWORD]}"
local g="$(__gitdir)"
local merge=""
if [ -f $g/MERGE_HEAD ]; then
if [ -f "$g/MERGE_HEAD" ]; then
merge="--merge"
fi
case "$cur" in

View File

@@ -14,13 +14,18 @@ die "usage: import-tars *.tar.{gz,bz2,Z}\n" unless @ARGV;
my $branch_name = 'import-tars';
my $branch_ref = "refs/heads/$branch_name";
my $committer_name = 'T Ar Creator';
my $committer_email = 'tar@example.com';
my $author_name = $ENV{'GIT_AUTHOR_NAME'} || 'T Ar Creator';
my $author_email = $ENV{'GIT_AUTHOR_EMAIL'} || 'tar@example.com';
my $committer_name = $ENV{'GIT_COMMITTER_NAME'} || `git config --get user.name`;
my $committer_email = $ENV{'GIT_COMMITTER_EMAIL'} || `git config --get user.email`;
chomp($committer_name, $committer_email);
open(FI, '|-', 'git', 'fast-import', '--quiet')
or die "Unable to start git fast-import: $!\n";
foreach my $tar_file (@ARGV)
{
my $commit_time = time;
$tar_file =~ m,([^/]+)$,;
my $tar_name = $1;
@@ -39,7 +44,7 @@ foreach my $tar_file (@ARGV)
die "Unrecognized compression format: $tar_file\n";
}
my $commit_time = 0;
my $author_time = 0;
my $next_mark = 1;
my $have_top_dir = 1;
my ($top_dir, %files);
@@ -92,7 +97,7 @@ foreach my $tar_file (@ARGV)
}
$files{$path} = [$next_mark++, $mode];
$commit_time = $mtime if $mtime > $commit_time;
$author_time = $mtime if $mtime > $author_time;
$path =~ m,^([^/]+)/,;
$top_dir = $1 unless $top_dir;
$have_top_dir = 0 if $top_dir ne $1;
@@ -100,6 +105,7 @@ foreach my $tar_file (@ARGV)
print FI <<EOF;
commit $branch_ref
author $author_name <$author_email> $author_time +0000
committer $committer_name <$committer_email> $commit_time +0000
data <<END_OF_COMMIT_MESSAGE
Imported from $tar_file.
@@ -119,7 +125,7 @@ EOF
print FI <<EOF;
tag $tar_name
from $branch_ref
tagger $committer_name <$committer_email> $commit_time +0000
tagger $author_name <$author_email> $author_time +0000
data <<END_OF_TAG_MESSAGE
Package $tar_name
END_OF_TAG_MESSAGE

View File

@@ -44,7 +44,8 @@ for zipfile in argv[1:]:
common_prefix = name[:name.rfind('/') + 1]
else:
while not name.startswith(common_prefix):
common_prefix = name[:name.rfind('/') + 1]
last_slash = common_prefix[:-1].rfind('/') + 1
common_prefix = common_prefix[:last_slash]
mark[name] = ':' + str(next_mark)
next_mark += 1

View File

@@ -31,7 +31,7 @@ static int check_removed(const struct cache_entry *ce, struct stat *st)
return -1;
return 1;
}
if (has_symlink_leading_path(ce_namelen(ce), ce->name))
if (has_symlink_leading_path(ce->name, ce_namelen(ce)))
return 1;
if (S_ISDIR(st->st_mode)) {
unsigned char sub[20];

View File

@@ -205,8 +205,6 @@ void diff_no_index(struct rev_info *revs,
no_index ? "--no-index" : "[--no-index]");
diff_setup(&revs->diffopt);
if (!revs->diffopt.output_format)
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
for (i = 1; i < argc - 2; ) {
int j;
if (!strcmp(argv[i], "--no-index"))
@@ -252,6 +250,8 @@ void diff_no_index(struct rev_info *revs,
revs->diffopt.paths = argv + argc - 2;
revs->diffopt.nr_paths = 2;
revs->diffopt.skip_stat_unmatch = 1;
if (!revs->diffopt.output_format)
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
DIFF_OPT_SET(&revs->diffopt, NO_INDEX);

10
diff.c
View File

@@ -1757,7 +1757,8 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
struct stat st;
int pos, len;
/* We do not read the cache ourselves here, because the
/*
* We do not read the cache ourselves here, because the
* benchmark with my previous version that always reads cache
* shows that it makes things worse for diff-tree comparing
* two linux-2.6 kernel trees in an already checked out work
@@ -1797,6 +1798,13 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
return 0;
/*
* If ce is marked as "assume unchanged", there is no
* guarantee that work tree matches what we are looking for.
*/
if (ce->ce_flags & CE_VALID)
return 0;
/*
* If ce matches the file in the work tree, we can reuse it.
*/

View File

@@ -25,10 +25,12 @@ static unsigned int contains(struct diff_filespec *one,
regmatch_t regmatch;
int flags = 0;
assert(data[sz] == '\0');
while (*data && !regexec(regexp, data, 1, &regmatch, flags)) {
flags |= REG_NOTBOL;
data += regmatch.rm_so;
if (*data) data++;
data += regmatch.rm_eo;
if (*data && regmatch.rm_so == regmatch.rm_eo)
data++;
cnt++;
}

19
dir.c
View File

@@ -487,14 +487,14 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
return recurse_into_directory;
case index_gitdir:
if (dir->show_other_directories)
if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
return ignore_directory;
return show_directory;
case index_nonexistent:
if (dir->show_other_directories)
if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
break;
if (!dir->no_gitlinks) {
if (!(dir->flags & DIR_NO_GITLINKS)) {
unsigned char sha1[20];
if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0)
return show_directory;
@@ -503,7 +503,7 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
}
/* This is the "show_other_directories" case */
if (!dir->hide_empty_directories)
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
return show_directory;
if (!read_directory_recursive(dir, dirname, dirname, len, 1, simplify))
return ignore_directory;
@@ -601,7 +601,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
dtype = DTYPE(de);
exclude = excluded(dir, fullname, &dtype);
if (exclude && dir->collect_ignored
if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
&& in_pathspec(fullname, baselen + len, simplify))
dir_add_ignored(dir, fullname, baselen + len);
@@ -609,7 +609,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
* Excluded? If we don't explicitly want to show
* ignored files, ignore it
*/
if (exclude && !dir->show_ignored)
if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
continue;
if (dtype == DT_UNKNOWN)
@@ -621,7 +621,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
* even if we don't ignore them, since the
* directory may contain files that we do..
*/
if (!exclude && dir->show_ignored) {
if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
if (dtype != DT_DIR)
continue;
}
@@ -634,7 +634,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
len++;
switch (treat_directory(dir, fullname, baselen + len, simplify)) {
case show_directory:
if (exclude != dir->show_ignored)
if (exclude != !!(dir->flags
& DIR_SHOW_IGNORED))
continue;
break;
case recurse_into_directory:
@@ -720,7 +721,7 @@ int read_directory(struct dir_struct *dir, const char *path, const char *base, i
{
struct path_simplify *simplify;
if (has_symlink_leading_path(strlen(path), path))
if (has_symlink_leading_path(path, strlen(path)))
return dir->nr;
simplify = create_simplify(pathspec);

12
dir.h
View File

@@ -34,11 +34,13 @@ struct exclude_stack {
struct dir_struct {
int nr, alloc;
int ignored_nr, ignored_alloc;
unsigned int show_ignored:1,
show_other_directories:1,
hide_empty_directories:1,
no_gitlinks:1,
collect_ignored:1;
enum {
DIR_SHOW_IGNORED = 1<<0,
DIR_SHOW_OTHER_DIRECTORIES = 1<<1,
DIR_HIDE_EMPTY_DIRECTORIES = 1<<2,
DIR_NO_GITLINKS = 1<<3,
DIR_COLLECT_IGNORED = 1<<4
} flags;
struct dir_entry **entries;
struct dir_entry **ignored;

106
entry.c
View File

@@ -2,15 +2,19 @@
#include "blob.h"
#include "dir.h"
static void create_directories(const char *path, const struct checkout *state)
static void create_directories(const char *path, int path_len,
const struct checkout *state)
{
int len = strlen(path);
char *buf = xmalloc(len + 1);
const char *slash = path;
char *buf = xmalloc(path_len + 1);
int len = 0;
while ((slash = strchr(slash+1, '/')) != NULL) {
len = slash - path;
memcpy(buf, path, len);
while (len < path_len) {
do {
buf[len] = path[len];
len++;
} while (len < path_len && path[len] != '/');
if (len >= path_len)
break;
buf[len] = 0;
/*
@@ -20,7 +24,7 @@ static void create_directories(const char *path, const struct checkout *state)
* 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))
if (has_dirs_only_path(buf, len, state->base_dir_len))
continue; /* ok, it is already a directory. */
/*
@@ -74,7 +78,7 @@ static int create_file(const char *path, unsigned int mode)
return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
}
static void *read_blob_entry(struct cache_entry *ce, const char *path, unsigned long *size)
static void *read_blob_entry(struct cache_entry *ce, unsigned long *size)
{
enum object_type type;
void *new = read_sha1_file(ce->sha1, &type, size);
@@ -89,36 +93,52 @@ static void *read_blob_entry(struct cache_entry *ce, const char *path, unsigned
static int write_entry(struct cache_entry *ce, char *path, const struct checkout *state, int to_tempfile)
{
int fd;
long wrote;
switch (ce->ce_mode & S_IFMT) {
char *new;
struct strbuf buf;
unsigned long size;
unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT;
int fd, ret, fstat_done = 0;
char *new;
struct strbuf buf = STRBUF_INIT;
unsigned long size;
size_t wrote, newsize = 0;
struct stat st;
switch (ce_mode_s_ifmt) {
case S_IFREG:
new = read_blob_entry(ce, path, &size);
case S_IFLNK:
new = read_blob_entry(ce, &size);
if (!new)
return error("git checkout-index: unable to read sha1 file of %s (%s)",
path, sha1_to_hex(ce->sha1));
if (ce_mode_s_ifmt == S_IFLNK && has_symlinks && !to_tempfile) {
ret = symlink(new, path);
free(new);
if (ret)
return error("git checkout-index: unable to create symlink %s (%s)",
path, strerror(errno));
break;
}
/*
* Convert from git internal format to working tree format
*/
strbuf_init(&buf, 0);
if (convert_to_working_tree(ce->name, new, size, &buf)) {
size_t newsize = 0;
if (ce_mode_s_ifmt == S_IFREG &&
convert_to_working_tree(ce->name, new, size, &buf)) {
free(new);
new = strbuf_detach(&buf, &newsize);
size = newsize;
}
if (to_tempfile) {
strcpy(path, ".merge_file_XXXXXX");
if (ce_mode_s_ifmt == S_IFREG)
strcpy(path, ".merge_file_XXXXXX");
else
strcpy(path, ".merge_link_XXXXXX");
fd = mkstemp(path);
} else
} else if (ce_mode_s_ifmt == S_IFREG) {
fd = create_file(path, ce->ce_mode);
} else {
fd = create_file(path, 0666);
}
if (fd < 0) {
free(new);
return error("git checkout-index: unable to create file %s (%s)",
@@ -126,41 +146,16 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
}
wrote = write_in_full(fd, new, size);
/* use fstat() only when path == ce->name */
if (state->refresh_cache && !to_tempfile && !state->base_dir_len) {
fstat(fd, &st);
fstat_done = 1;
}
close(fd);
free(new);
if (wrote != size)
return error("git checkout-index: unable to write file %s", path);
break;
case S_IFLNK:
new = read_blob_entry(ce, path, &size);
if (!new)
return error("git checkout-index: unable to read sha1 file of %s (%s)",
path, sha1_to_hex(ce->sha1));
if (to_tempfile || !has_symlinks) {
if (to_tempfile) {
strcpy(path, ".merge_link_XXXXXX");
fd = mkstemp(path);
} else
fd = create_file(path, 0666);
if (fd < 0) {
free(new);
return error("git checkout-index: unable to create "
"file %s (%s)", path, strerror(errno));
}
wrote = write_in_full(fd, new, size);
close(fd);
free(new);
if (wrote != size)
return error("git checkout-index: unable to write file %s",
path);
} else {
wrote = symlink(new, path);
free(new);
if (wrote)
return error("git checkout-index: unable to create "
"symlink %s (%s)", path, strerror(errno));
}
break;
case S_IFGITLINK:
if (to_tempfile)
return error("git checkout-index: cannot create temporary subproject %s", path);
@@ -172,8 +167,8 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
}
if (state->refresh_cache) {
struct stat st;
lstat(ce->name, &st);
if (!fstat_done)
lstat(ce->name, &st);
fill_stat_cache_info(ce, &st);
}
return 0;
@@ -190,6 +185,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
memcpy(path, state->base_dir, len);
strcpy(path + len, ce->name);
len += ce_namelen(ce);
if (!lstat(path, &st)) {
unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID);
@@ -218,6 +214,6 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
return error("unable to unlink old '%s' (%s)", path, strerror(errno));
} else if (state->not_new)
return 0;
create_directories(path, state);
create_directories(path, len, state);
return write_entry(ce, path, state, 0);
}

View File

@@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
/* Parallel index stat data preload? */
int core_preload_index = 0;

View File

@@ -28,9 +28,10 @@ const char *system_path(const char *path)
!(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
!(prefix = strip_path_suffix(argv0_path, "git"))) {
prefix = PREFIX;
fprintf(stderr, "RUNTIME_PREFIX requested, "
"but prefix computation failed. "
"Using static fallback '%s'.\n", prefix);
/*
* RUNTIME_PREFIX requested, but prefix computation failed.
* Using static fallback.
*/
}
#endif
@@ -61,6 +62,10 @@ const char *git_extract_argv0_path(const char *argv0)
void git_set_argv_exec_path(const char *exec_path)
{
argv_exec_path = exec_path;
/*
* Propagate this setting to external programs.
*/
setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
}

View File

@@ -1,4 +1,5 @@
/*
(See Documentation/git-fast-import.txt for maintained documentation.)
Format of STDIN stream:
stream ::= cmd*;
@@ -18,8 +19,8 @@ Format of STDIN stream:
new_commit ::= 'commit' sp ref_str lf
mark?
('author' sp name '<' email '>' when lf)?
'committer' sp name '<' email '>' when lf
('author' sp name sp '<' email '>' sp when lf)?
'committer' sp name sp '<' email '>' sp when lf
commit_msg
('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*
@@ -43,7 +44,7 @@ Format of STDIN stream:
new_tag ::= 'tag' sp tag_str lf
'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
('tagger' sp name '<' email '>' when lf)?
('tagger' sp name sp '<' email '>' sp when lf)?
tag_msg;
tag_msg ::= data;

View File

@@ -150,6 +150,7 @@
#endif
/* General helper functions */
extern void vreport(const char *prefix, const char *err, va_list params);
extern void usage(const char *err) NORETURN;
extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
@@ -394,4 +395,18 @@ void git_qsort(void *base, size_t nmemb, size_t size,
# define FORCE_DIR_SET_GID 0
#endif
#ifdef NO_NSEC
#undef USE_NSEC
#define ST_CTIME_NSEC(st) 0
#define ST_MTIME_NSEC(st) 0
#else
#ifdef USE_ST_TIMESPEC
#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
#else
#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
#endif
#endif
#endif

View File

@@ -272,10 +272,10 @@ test $commits -eq 0 && die "Found nothing to rewrite"
# Rewrite the commits
i=0
git_filter_branch__commit_count=0
while read commit parents; do
i=$(($i+1))
printf "\rRewrite $commit ($i/$commits)"
git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
printf "\rRewrite $commit ($git_filter_branch__commit_count/$commits)"
case "$filter_subdir" in
"")

View File

@@ -442,6 +442,30 @@ do_rest () {
done
}
# skip picking commits whose parents are unchanged
skip_unnecessary_picks () {
fd=3
while read command sha1 rest
do
# fd=3 means we skip the command
case "$fd,$command,$(git rev-parse --verify --quiet $sha1^)" in
3,pick,"$ONTO"*|3,p,"$ONTO"*)
# pick a commit whose parent is current $ONTO -> skip
ONTO=$sha1
;;
3,#*|3,,*)
# copy comments
;;
*)
fd=1
;;
esac
echo "$command${sha1:+ }$sha1${rest:+ }$rest" >&$fd
done <"$TODO" >"$TODO.new" 3>>"$DONE" &&
mv -f "$TODO".new "$TODO" ||
die "Could not skip unnecessary pick commands"
}
# check if no other options are set
is_standalone () {
test $# -eq 2 -a "$2" = '--' &&
@@ -746,6 +770,8 @@ EOF
has_action "$TODO" ||
die_abort "Nothing to do"
test -d "$REWRITTEN" || skip_unnecessary_picks
git update-ref ORIG_HEAD $HEAD
output git checkout $ONTO && do_rest
;;

View File

@@ -309,13 +309,17 @@ do
;;
esac
;;
--committer-date-is-author-date|--ignore-date)
git_am_opt="$git_am_opt $1"
force_rebase=t
;;
-C*)
git_am_opt="$git_am_opt $1"
;;
--root)
rebase_root=t
;;
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force_rebas|--force-rebase)
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
force_rebase=t
;;
-*)

Some files were not shown because too many files have changed in this diff Show More