mirror of
https://github.com/git/git.git
synced 2026-04-02 21:10:10 +02:00
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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
45
Documentation/RelNotes-1.6.2.2.txt
Normal file
45
Documentation/RelNotes-1.6.2.2.txt
Normal 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.
|
||||
@@ -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
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 </xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
<xsl:template match="callout">
|
||||
<xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>.br </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> </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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::
|
||||
|
||||
@@ -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:
|
||||
+
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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".
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>::
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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('▓fB(',substring-after(@id,'-'),')▓fR')"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="calloutlist">
|
||||
<xsl:text>⌂sp </xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
<xsl:template match="callout">
|
||||
<xsl:value-of select="concat('▓fB',substring-after(@arearefs,'-'),'. ▓fR')"/>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>⌂br </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">▓</xsl:param>
|
||||
<xsl:param name="git.docbook.dot" >⌂</xsl:param>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
||||
35
Documentation/manpage-base.xsl
Normal file
35
Documentation/manpage-base.xsl
Normal 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 </xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text> </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 </xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
17
Documentation/manpage-bold-literal.xsl
Normal file
17
Documentation/manpage-bold-literal.xsl
Normal 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>
|
||||
13
Documentation/manpage-normal.xsl
Normal file
13
Documentation/manpage-normal.xsl
Normal 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>
|
||||
21
Documentation/manpage-suppress-sp.xsl
Normal file
21
Documentation/manpage-suppress-sp.xsl
Normal 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> </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
@@ -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
|
||||
|
||||
@@ -148,22 +148,22 @@ outputting that information, if desired.
|
||||
------------
|
||||
*
|
||||
*
|
||||
M
|
||||
*
|
||||
|\
|
||||
* |
|
||||
| | *
|
||||
| \ \
|
||||
| \ \
|
||||
M-. \ \
|
||||
*-. \ \
|
||||
|\ \ \ \
|
||||
| | * | |
|
||||
| | | | | *
|
||||
| | | | | *
|
||||
| | | | | M
|
||||
| | | | | *
|
||||
| | | | | |\
|
||||
| | | | | | *
|
||||
| * | | | | |
|
||||
| | | | | M \
|
||||
| | | | | * \
|
||||
| | | | | |\ |
|
||||
| | | | * | | |
|
||||
| | | | * | | |
|
||||
|
||||
@@ -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:
|
||||
|
||||
37
Makefile
37
Makefile
@@ -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
73
attr.c
@@ -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
6
attr.h
@@ -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 */
|
||||
|
||||
60
branch.c
60
branch.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
7
branch.h
7
branch.h
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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" : "");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
427
builtin-config.c
427
builtin-config.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 *));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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
|
||||
|
||||
569
builtin-remote.c
569
builtin-remote.c
@@ -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"))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
31
cache.h
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
253
compat/mingw.c
253
compat/mingw.c
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
45
config.c
45
config.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
386
configure.ac
386
configure.ac
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
10
diff.c
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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, ®match, 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
19
dir.c
@@ -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
12
dir.h
@@ -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
106
entry.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
11
exec_cmd.c
11
exec_cmd.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
"")
|
||||
|
||||
@@ -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
|
||||
;;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user