зеркало из https://github.com/microsoft/git.git
Merge branch 'cc/sha1-bsearch' into HEAD
* cc/sha1-bsearch: (95 commits) patch-ids: use the new generic "sha1_pos" function to lookup sha1 sha1-lookup: add new "sha1_pos" function to efficiently lookup sha1 Update draft release notes to 1.6.3 GIT 1.6.2.2 send-email: ensure quoted addresses are rfc2047 encoded send-email: correct two tests which were going interactive Documentation: git-svn: fix trunk/fetch svn-remote key typo Mailmap: Allow empty email addresses to be mapped Cleanup warning about known issues in cvsimport documentation Documentation: Remove an odd "instead" send-email: ask_default should apply to all emails, not just the first send-email: don't attempt to prompt if tty is closed fix portability problem with IS_RUN_COMMAND_ERR Documentation: use "spurious .sp" XSLT if DOCBOOK_SUPPRESS_SP is set mailmap: resurrect lower-casing of email addresses builtin-clone.c: no need to strdup for setenv builtin-clone.c: make junk_pid static git-svn: add a double quiet option to hide git commits Update draft release notes to 1.6.2.2 Documentation: push.default applies to all remotes ...
This commit is contained in:
Коммит
5aaa507b06
|
@ -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
|
||||
|
|
|
@ -7,9 +7,15 @@ 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.
|
||||
|
||||
|
@ -27,9 +33,13 @@ Fixes since v1.6.2.1
|
|||
* '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.
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.2.1-23-g67c176f
|
||||
echo O=$(git describe maint)
|
||||
git shortlog --no-merges $O..maint
|
||||
* 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
|
||||
--------------------
|
||||
|
@ -39,6 +46,9 @@ Updates since v1.6.2
|
|||
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.
|
||||
|
||||
|
@ -52,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
|
||||
|
@ -67,11 +81,17 @@ 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
|
||||
|
@ -85,6 +105,11 @@ Updates since v1.6.2
|
|||
|
||||
* 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.
|
||||
|
||||
|
@ -92,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
|
||||
------------------
|
||||
|
||||
|
@ -104,11 +138,14 @@ release, unless otherwise noted.
|
|||
Here are fixes that this release has, but have not been backported to
|
||||
v1.6.2.X series.
|
||||
|
||||
* 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-213-g7d4e3a7
|
||||
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[]
|
||||
|
|
|
@ -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>
|
|
@ -473,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
|
||||
|
@ -1194,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.
|
||||
|
|
|
@ -81,7 +81,7 @@ will have been left with the first bad kernel revision in "refs/bisect/bad".
|
|||
Bisect reset
|
||||
~~~~~~~~~~~~
|
||||
|
||||
To return to the original head after a bisect session, you issue the
|
||||
To return to the original head after a bisect session, issue the
|
||||
following command:
|
||||
|
||||
------------------------------------------------
|
||||
|
@ -95,8 +95,8 @@ the bisection state).
|
|||
Bisect visualize
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
To see the currently remaining suspects in 'gitk', the following command
|
||||
is issued during the bisection process:
|
||||
To see the currently remaining suspects in 'gitk', issue the following
|
||||
command during the bisection process:
|
||||
|
||||
------------
|
||||
$ git bisect visualize
|
||||
|
@ -115,7 +115,7 @@ $ git bisect view --stat
|
|||
Bisect log and bisect replay
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After having marked revisions as good or bad, you issue the following
|
||||
After having marked revisions as good or bad, issue the following
|
||||
command to show what has been done so far:
|
||||
|
||||
------------
|
||||
|
@ -135,7 +135,7 @@ $ git bisect replay that-file
|
|||
Avoiding testing a commit
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If in the middle of a bisect session, you know that the next suggested
|
||||
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
|
||||
|
@ -151,8 +151,8 @@ $ git reset --hard HEAD~3 # try 3 revisions before what
|
|||
# was suggested
|
||||
------------
|
||||
|
||||
Then compile and test the chosen revision. Afterwards the revision
|
||||
is marked as good or bad in the usual manner.
|
||||
Then compile and test the chosen revision, and afterwards mark
|
||||
the revision as good or bad in the usual manner.
|
||||
|
||||
Bisect skip
|
||||
~~~~~~~~~~~~
|
||||
|
@ -175,8 +175,8 @@ using the "'<commit1>'..'<commit2>'" notation. For example:
|
|||
$ git bisect skip v2.5..v2.6
|
||||
------------
|
||||
|
||||
The effect of this would be that no commit between `v2.5` excluded and
|
||||
`v2.6` included could 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 also want to skip the first commit of the range you
|
||||
would issue the command:
|
||||
|
@ -185,8 +185,8 @@ would issue the command:
|
|||
$ git bisect skip v2.5 v2.5..v2.6
|
||||
------------
|
||||
|
||||
This would cause the commits between `v2.5` included and `v2.6` included
|
||||
to be skipped.
|
||||
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
|
||||
|
|
|
@ -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".
|
||||
|
|
|
@ -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>::
|
||||
|
|
|
@ -65,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
|
||||
|
@ -173,24 +173,26 @@ ISSUES
|
|||
Problems related to timestamps:
|
||||
|
||||
* If timestamps of commits in the cvs repository are not stable enough
|
||||
to be used for ordering commits
|
||||
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)
|
||||
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
|
||||
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
|
||||
* 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
|
||||
* files added to the source branch *after* a daughter branch was
|
||||
created: If previously no commit was made on the daugther branch they
|
||||
will erroneously be added to the daughter branch in git
|
||||
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
|
||||
* 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
|
||||
|
|
|
@ -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
|
||||
|
@ -161,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
|
||||
|
@ -182,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
|
||||
|
|
|
@ -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
|
||||
-------------
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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 \
|
||||
| | | | | * \
|
||||
| | | | | |\ |
|
||||
| | | | * | | |
|
||||
| | | | * | | |
|
||||
|
|
12
Makefile
12
Makefile
|
@ -263,6 +263,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
|
||||
|
|
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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -270,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)
|
||||
{
|
||||
|
@ -406,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);
|
||||
|
|
|
@ -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",
|
||||
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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -918,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];
|
||||
}
|
||||
|
|
|
@ -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,6 +48,71 @@ 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;
|
||||
|
@ -79,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) {
|
||||
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++) {
|
||||
|
|
|
@ -922,6 +922,20 @@ int add_push_to_show_info(struct string_list_item *push_item, void *cb_data)
|
|||
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;
|
||||
|
@ -1032,7 +1046,8 @@ static int show(int argc, const char **argv)
|
|||
|
||||
info.width = info.width2 = 0;
|
||||
for_each_string_list(add_push_to_show_info, &states.push, &info);
|
||||
sort_string_list(info.list);
|
||||
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" : "",
|
||||
|
|
|
@ -10,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)
|
||||
{
|
||||
|
@ -31,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
|
||||
|
@ -49,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;
|
||||
|
@ -83,8 +81,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ref *remote_refs, **remote_tail;
|
||||
|
||||
static int receive_status(int in, struct ref *refs)
|
||||
{
|
||||
struct ref *hint;
|
||||
|
@ -172,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)
|
||||
|
@ -310,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)
|
||||
{
|
||||
struct ref *ref, *local_refs;
|
||||
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);
|
||||
local_refs = get_local_heads();
|
||||
|
||||
/* Does the other end support the reporting? */
|
||||
if (server_supports("report-status"))
|
||||
|
@ -338,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;
|
||||
}
|
||||
|
||||
|
@ -362,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);
|
||||
|
@ -401,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;
|
||||
}
|
||||
|
@ -409,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);
|
||||
|
||||
|
@ -430,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) {
|
||||
|
@ -499,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++) {
|
||||
|
@ -511,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=")) {
|
||||
|
@ -523,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")) {
|
||||
|
@ -552,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)
|
||||
|
@ -562,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) {
|
||||
|
@ -574,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;
|
||||
}
|
||||
|
|
10
cache.h
10
cache.h
|
@ -542,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;
|
||||
|
@ -646,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);
|
||||
|
||||
|
|
28
config.c
28
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);
|
||||
|
||||
|
|
|
@ -1103,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
|
||||
|
@ -1943,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
23
diff.c
23
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.
|
||||
*/
|
||||
|
@ -1946,17 +1954,23 @@ void diff_free_filespec_data(struct diff_filespec *s)
|
|||
s->cnt_data = NULL;
|
||||
}
|
||||
|
||||
static void prep_temp_blob(struct diff_tempfile *temp,
|
||||
static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
|
||||
void *blob,
|
||||
unsigned long size,
|
||||
const unsigned char *sha1,
|
||||
int mode)
|
||||
{
|
||||
int fd;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
|
||||
if (fd < 0)
|
||||
die("unable to create temp-file: %s", strerror(errno));
|
||||
if (convert_to_working_tree(path,
|
||||
(const char *)blob, (size_t)size, &buf)) {
|
||||
blob = buf.buf;
|
||||
size = buf.len;
|
||||
}
|
||||
if (write_in_full(fd, blob, size) != size)
|
||||
die("unable to write temp-file");
|
||||
close(fd);
|
||||
|
@ -1964,6 +1978,7 @@ static void prep_temp_blob(struct diff_tempfile *temp,
|
|||
strcpy(temp->hex, sha1_to_hex(sha1));
|
||||
temp->hex[40] = 0;
|
||||
sprintf(temp->mode, "%06o", mode);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
static struct diff_tempfile *prepare_temp_file(const char *name,
|
||||
|
@ -2004,7 +2019,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
|||
die("readlink(%s)", name);
|
||||
if (ret == sizeof(buf))
|
||||
die("symlink too long: %s", name);
|
||||
prep_temp_blob(temp, buf, ret,
|
||||
prep_temp_blob(name, temp, buf, ret,
|
||||
(one->sha1_valid ?
|
||||
one->sha1 : null_sha1),
|
||||
(one->sha1_valid ?
|
||||
|
@ -2030,7 +2045,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
|||
else {
|
||||
if (diff_populate_filespec(one, 0))
|
||||
die("cannot read data blob for %s", one->path);
|
||||
prep_temp_blob(temp, one->data, one->size,
|
||||
prep_temp_blob(name, temp, one->data, one->size,
|
||||
one->sha1, one->mode);
|
||||
}
|
||||
return temp;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,6 +61,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;
|
||||
|
||||
|
|
|
@ -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
|
||||
"")
|
||||
|
|
|
@ -319,7 +319,7 @@ do
|
|||
--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
|
||||
;;
|
||||
-*)
|
||||
|
|
|
@ -71,11 +71,7 @@ case ",$all_into_one," in
|
|||
existing="$existing $e"
|
||||
fi
|
||||
done
|
||||
if test -n "$existing"
|
||||
then
|
||||
args="--kept-pack-only"
|
||||
fi
|
||||
if test -n "$args" -a -n "$unpack_unreachable" -a \
|
||||
if test -n "$existing" -a -n "$unpack_unreachable" -a \
|
||||
-n "$remove_redundant"
|
||||
then
|
||||
args="$args $unpack_unreachable"
|
||||
|
|
|
@ -606,32 +606,43 @@ EOT
|
|||
do_edit(@files);
|
||||
}
|
||||
|
||||
sub ask {
|
||||
my ($prompt, %arg) = @_;
|
||||
my $valid_re = $arg{valid_re} || ""; # "" matches anything
|
||||
my $default = $arg{default};
|
||||
my $resp;
|
||||
my $i = 0;
|
||||
return defined $default ? $default : undef
|
||||
unless defined $term->IN and defined fileno($term->IN) and
|
||||
defined $term->OUT and defined fileno($term->OUT);
|
||||
while ($i++ < 10) {
|
||||
$resp = $term->readline($prompt);
|
||||
if (!defined $resp) { # EOF
|
||||
print "\n";
|
||||
return defined $default ? $default : undef;
|
||||
}
|
||||
if ($resp eq '' and defined $default) {
|
||||
return $default;
|
||||
}
|
||||
if ($resp =~ /$valid_re/) {
|
||||
return $resp;
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
my $prompting = 0;
|
||||
if (!defined $sender) {
|
||||
$sender = $repoauthor || $repocommitter || '';
|
||||
|
||||
while (1) {
|
||||
$_ = $term->readline("Who should the emails appear to be from? [$sender] ");
|
||||
last if defined $_;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
$sender = $_ if ($_);
|
||||
$sender = ask("Who should the emails appear to be from? [$sender] ",
|
||||
default => $sender);
|
||||
print "Emails will be sent from: ", $sender, "\n";
|
||||
$prompting++;
|
||||
}
|
||||
|
||||
if (!@to) {
|
||||
|
||||
|
||||
while (1) {
|
||||
$_ = $term->readline("Who should the emails be sent to? ", "");
|
||||
last if defined $_;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
my $to = $_;
|
||||
push @to, parse_address_line($to);
|
||||
my $to = ask("Who should the emails be sent to? ");
|
||||
push @to, parse_address_line($to) if defined $to; # sanitized/validated later
|
||||
$prompting++;
|
||||
}
|
||||
|
||||
|
@ -651,13 +662,8 @@ sub expand_aliases {
|
|||
@bcclist = expand_aliases(@bcclist);
|
||||
|
||||
if ($thread && !defined $initial_reply_to && $prompting) {
|
||||
while (1) {
|
||||
$_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to);
|
||||
last if defined $_;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
$initial_reply_to = $_;
|
||||
$initial_reply_to = ask(
|
||||
"Message-ID to be used as In-Reply-To for the first email? ");
|
||||
}
|
||||
if (defined $initial_reply_to) {
|
||||
$initial_reply_to =~ s/^\s*<?//;
|
||||
|
@ -681,7 +687,7 @@ if ($compose && $compose > 0) {
|
|||
|
||||
# Variables we set as part of the loop over files
|
||||
our ($message_id, %mail, $subject, $reply_to, $references, $message,
|
||||
$needs_confirm, $message_num);
|
||||
$needs_confirm, $message_num, $ask_default);
|
||||
|
||||
sub extract_valid_address {
|
||||
my $address = shift;
|
||||
|
@ -770,12 +776,13 @@ sub sanitize_address
|
|||
}
|
||||
|
||||
# if recipient_name is already quoted, do nothing
|
||||
if ($recipient_name =~ /^(".*"|=\?utf-8\?q\?.*\?=)$/) {
|
||||
if ($recipient_name =~ /^("[[:ascii:]]*"|=\?utf-8\?q\?.*\?=)$/) {
|
||||
return $recipient;
|
||||
}
|
||||
|
||||
# rfc2047 is needed if a non-ascii char is included
|
||||
if ($recipient_name =~ /[^[:ascii:]]/) {
|
||||
$recipient_name =~ s/^"(.*)"$/$1/;
|
||||
$recipient_name = quote_rfc2047($recipient_name);
|
||||
}
|
||||
|
||||
|
@ -841,6 +848,7 @@ X-Mailer: git-send-email $gitversion
|
|||
print "\n$header\n";
|
||||
if ($needs_confirm eq "inform") {
|
||||
$confirm_unconfigured = 0; # squelch this message for the rest of this run
|
||||
$ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation
|
||||
print " The Cc list above has been expanded by additional\n";
|
||||
print " addresses found in the patch commit message. By default\n";
|
||||
print " send-email prompts before sending whenever this occurs.\n";
|
||||
|
@ -851,13 +859,10 @@ X-Mailer: git-send-email $gitversion
|
|||
print " To retain the current behavior, but squelch this message,\n";
|
||||
print " run 'git config --global sendemail.confirm auto'.\n\n";
|
||||
}
|
||||
while (1) {
|
||||
chomp ($_ = $term->readline(
|
||||
"Send this email? ([y]es|[n]o|[q]uit|[a]ll): "
|
||||
));
|
||||
last if /^(?:yes|y|no|n|quit|q|all|a)/i;
|
||||
print "\n";
|
||||
}
|
||||
$_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
|
||||
valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
|
||||
default => $ask_default);
|
||||
die "Send this email reply required" unless defined $_;
|
||||
if (/^n/i) {
|
||||
return;
|
||||
} elsif (/^q/i) {
|
||||
|
|
24
git-svn.perl
24
git-svn.perl
|
@ -68,6 +68,7 @@ my ($_stdin, $_help, $_edit,
|
|||
$_prefix, $_no_checkout, $_url, $_verbose,
|
||||
$_git_format, $_commit_url, $_tag);
|
||||
$Git::SVN::_follow_parent = 1;
|
||||
$_q ||= 0;
|
||||
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
|
||||
'config-dir=s' => \$Git::SVN::Ra::config_dir,
|
||||
'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache,
|
||||
|
@ -80,7 +81,7 @@ my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
|
|||
'useSvnsyncProps' => \$Git::SVN::_use_svnsync_props,
|
||||
'log-window-size=i' => \$Git::SVN::Ra::_log_window_size,
|
||||
'no-checkout' => \$_no_checkout,
|
||||
'quiet|q' => \$_q,
|
||||
'quiet|q+' => \$_q,
|
||||
'repack-flags|repack-args|repack-opts=s' =>
|
||||
\$Git::SVN::_repack_flags,
|
||||
'use-log-author' => \$Git::SVN::_use_log_author,
|
||||
|
@ -2331,13 +2332,13 @@ sub do_git_commit {
|
|||
|
||||
$self->{last_rev} = $log_entry->{revision};
|
||||
$self->{last_commit} = $commit;
|
||||
print "r$log_entry->{revision}";
|
||||
print "r$log_entry->{revision}" unless $::_q > 1;
|
||||
if (defined $log_entry->{svm_revision}) {
|
||||
print " (\@$log_entry->{svm_revision})";
|
||||
print " (\@$log_entry->{svm_revision})" unless $::_q > 1;
|
||||
$self->rev_map_set($log_entry->{svm_revision}, $commit,
|
||||
0, $self->svm_uuid);
|
||||
}
|
||||
print " = $commit ($self->{ref_id})\n";
|
||||
print " = $commit ($self->{ref_id})\n" unless $::_q > 1;
|
||||
if (--$_gc_nr == 0) {
|
||||
$_gc_nr = $_gc_period;
|
||||
gc();
|
||||
|
@ -3387,15 +3388,18 @@ sub delete_entry {
|
|||
return undef if ($gpath eq '');
|
||||
|
||||
# remove entire directories.
|
||||
if (command('ls-tree', $self->{c}, '--', $gpath) =~ /^040000 tree/) {
|
||||
my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
|
||||
=~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/);
|
||||
if ($tree) {
|
||||
my ($ls, $ctx) = command_output_pipe(qw/ls-tree
|
||||
-r --name-only -z/,
|
||||
$self->{c}, '--', $gpath);
|
||||
$tree);
|
||||
local $/ = "\0";
|
||||
while (<$ls>) {
|
||||
chomp;
|
||||
$self->{gii}->remove($_);
|
||||
print "\tD\t$_\n" unless $::_q;
|
||||
my $rmpath = "$gpath/$_";
|
||||
$self->{gii}->remove($rmpath);
|
||||
print "\tD\t$rmpath\n" unless $::_q;
|
||||
}
|
||||
print "\tD\t$gpath/\n" unless $::_q;
|
||||
command_close_pipe($ls, $ctx);
|
||||
|
@ -3414,8 +3418,8 @@ sub open_file {
|
|||
goto out if is_path_ignored($path);
|
||||
|
||||
my $gpath = $self->git_path($path);
|
||||
($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath)
|
||||
=~ /^(\d{6}) blob ([a-f\d]{40})\t/);
|
||||
($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
|
||||
=~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/);
|
||||
unless (defined $mode && defined $blob) {
|
||||
die "$path was not found in commit $self->{c} (r$rev)\n";
|
||||
}
|
||||
|
|
162
http-push.c
162
http-push.c
|
@ -97,7 +97,7 @@ struct repo
|
|||
struct remote_lock *locks;
|
||||
};
|
||||
|
||||
static struct repo *remote;
|
||||
static struct repo *repo;
|
||||
|
||||
enum transfer_state {
|
||||
NEED_FETCH,
|
||||
|
@ -324,7 +324,7 @@ static void start_fetch_loose(struct transfer_request *request)
|
|||
|
||||
git_SHA1_Init(&request->c);
|
||||
|
||||
url = get_remote_object_url(remote->url, hex, 0);
|
||||
url = get_remote_object_url(repo->url, hex, 0);
|
||||
request->url = xstrdup(url);
|
||||
|
||||
/* If a previous temp file is present, process what was already
|
||||
|
@ -389,7 +389,7 @@ static void start_fetch_loose(struct transfer_request *request)
|
|||
request->state = RUN_FETCH_LOOSE;
|
||||
if (!start_active_slot(slot)) {
|
||||
fprintf(stderr, "Unable to start GET request\n");
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
release_request(request);
|
||||
}
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ static void start_mkcol(struct transfer_request *request)
|
|||
char *hex = sha1_to_hex(request->obj->sha1);
|
||||
struct active_request_slot *slot;
|
||||
|
||||
request->url = get_remote_object_url(remote->url, hex, 1);
|
||||
request->url = get_remote_object_url(repo->url, hex, 1);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->callback_func = process_response;
|
||||
|
@ -434,10 +434,10 @@ static void start_fetch_packed(struct transfer_request *request)
|
|||
struct transfer_request *check_request = request_queue_head;
|
||||
struct active_request_slot *slot;
|
||||
|
||||
target = find_sha1_pack(request->obj->sha1, remote->packs);
|
||||
target = find_sha1_pack(request->obj->sha1, repo->packs);
|
||||
if (!target) {
|
||||
fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
release_request(request);
|
||||
return;
|
||||
}
|
||||
|
@ -450,9 +450,9 @@ static void start_fetch_packed(struct transfer_request *request)
|
|||
snprintf(request->tmpfile, sizeof(request->tmpfile),
|
||||
"%s.temp", filename);
|
||||
|
||||
url = xmalloc(strlen(remote->url) + 64);
|
||||
url = xmalloc(strlen(repo->url) + 64);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.pack",
|
||||
remote->url, sha1_to_hex(target->sha1));
|
||||
repo->url, sha1_to_hex(target->sha1));
|
||||
|
||||
/* Make sure there isn't another open request for this pack */
|
||||
while (check_request) {
|
||||
|
@ -469,7 +469,7 @@ static void start_fetch_packed(struct transfer_request *request)
|
|||
if (!packfile) {
|
||||
fprintf(stderr, "Unable to open local file %s for pack",
|
||||
request->tmpfile);
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
free(url);
|
||||
return;
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ static void start_fetch_packed(struct transfer_request *request)
|
|||
request->state = RUN_FETCH_PACKED;
|
||||
if (!start_active_slot(slot)) {
|
||||
fprintf(stderr, "Unable to start GET request\n");
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
release_request(request);
|
||||
}
|
||||
}
|
||||
|
@ -554,10 +554,10 @@ static void start_put(struct transfer_request *request)
|
|||
request->buffer.buf.len = stream.total_out;
|
||||
|
||||
strbuf_addstr(&buf, "Destination: ");
|
||||
append_remote_object_url(&buf, remote->url, hex, 0);
|
||||
append_remote_object_url(&buf, repo->url, hex, 0);
|
||||
request->dest = strbuf_detach(&buf, NULL);
|
||||
|
||||
append_remote_object_url(&buf, remote->url, hex, 0);
|
||||
append_remote_object_url(&buf, repo->url, hex, 0);
|
||||
strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
|
||||
request->url = strbuf_detach(&buf, NULL);
|
||||
|
||||
|
@ -648,7 +648,7 @@ static int refresh_lock(struct remote_lock *lock)
|
|||
|
||||
static void check_locks(void)
|
||||
{
|
||||
struct remote_lock *lock = remote->locks;
|
||||
struct remote_lock *lock = repo->locks;
|
||||
time_t current_time = time(NULL);
|
||||
int time_remaining;
|
||||
|
||||
|
@ -788,7 +788,7 @@ static void finish_request(struct transfer_request *request)
|
|||
if (request->curl_result != CURLE_OK) {
|
||||
fprintf(stderr, "Unable to get pack file %s\n%s",
|
||||
request->url, curl_errorstr);
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
} else {
|
||||
off_t pack_size = ftell(request->local_stream);
|
||||
|
||||
|
@ -798,7 +798,7 @@ static void finish_request(struct transfer_request *request)
|
|||
request->filename)) {
|
||||
target = (struct packed_git *)request->userData;
|
||||
target->pack_size = pack_size;
|
||||
lst = &remote->packs;
|
||||
lst = &repo->packs;
|
||||
while (*lst != target)
|
||||
lst = &((*lst)->next);
|
||||
*lst = (*lst)->next;
|
||||
|
@ -806,7 +806,7 @@ static void finish_request(struct transfer_request *request)
|
|||
if (!verify_pack(target))
|
||||
install_packed_git(target);
|
||||
else
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
}
|
||||
}
|
||||
release_request(request);
|
||||
|
@ -889,7 +889,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
|
|||
get_remote_object_list(obj->sha1[0]);
|
||||
if (obj->flags & (REMOTE | PUSHING))
|
||||
return 0;
|
||||
target = find_sha1_pack(obj->sha1, remote->packs);
|
||||
target = find_sha1_pack(obj->sha1, repo->packs);
|
||||
if (target) {
|
||||
obj->flags |= REMOTE;
|
||||
return 0;
|
||||
|
@ -930,8 +930,8 @@ static int fetch_index(unsigned char *sha1)
|
|||
struct slot_results results;
|
||||
|
||||
/* Don't use the index if the pack isn't there */
|
||||
url = xmalloc(strlen(remote->url) + 64);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
|
||||
url = xmalloc(strlen(repo->url) + 64);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
||||
|
@ -956,7 +956,7 @@ static int fetch_index(unsigned char *sha1)
|
|||
if (push_verbosely)
|
||||
fprintf(stderr, "Getting index for pack %s\n", hex);
|
||||
|
||||
sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex);
|
||||
|
||||
filename = sha1_pack_index_name(sha1);
|
||||
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
|
||||
|
@ -1018,8 +1018,8 @@ static int setup_index(unsigned char *sha1)
|
|||
return -1;
|
||||
|
||||
new_pack = parse_pack_index(sha1);
|
||||
new_pack->next = remote->packs;
|
||||
remote->packs = new_pack;
|
||||
new_pack->next = repo->packs;
|
||||
repo->packs = new_pack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1037,8 +1037,8 @@ static int fetch_indices(void)
|
|||
if (push_verbosely)
|
||||
fprintf(stderr, "Getting pack list\n");
|
||||
|
||||
url = xmalloc(strlen(remote->url) + 20);
|
||||
sprintf(url, "%sobjects/info/packs", remote->url);
|
||||
url = xmalloc(strlen(repo->url) + 20);
|
||||
sprintf(url, "%sobjects/info/packs", repo->url);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
|
@ -1223,11 +1223,11 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
|
|||
struct curl_slist *dav_headers = NULL;
|
||||
struct xml_ctx ctx;
|
||||
|
||||
url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
/* Make sure leading directories exist for the remote ref */
|
||||
ep = strchr(url + strlen(remote->url) + 1, '/');
|
||||
ep = strchr(url + strlen(repo->url) + 1, '/');
|
||||
while (ep) {
|
||||
char saved_character = ep[1];
|
||||
ep[1] = '\0';
|
||||
|
@ -1319,8 +1319,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
|
|||
} else {
|
||||
lock->url = url;
|
||||
lock->start_time = time(NULL);
|
||||
lock->next = remote->locks;
|
||||
remote->locks = lock;
|
||||
lock->next = repo->locks;
|
||||
repo->locks = lock;
|
||||
}
|
||||
|
||||
return lock;
|
||||
|
@ -1330,7 +1330,7 @@ static int unlock_remote(struct remote_lock *lock)
|
|||
{
|
||||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
struct remote_lock *prev = remote->locks;
|
||||
struct remote_lock *prev = repo->locks;
|
||||
struct curl_slist *dav_headers;
|
||||
int rc = 0;
|
||||
|
||||
|
@ -1356,8 +1356,8 @@ static int unlock_remote(struct remote_lock *lock)
|
|||
|
||||
curl_slist_free_all(dav_headers);
|
||||
|
||||
if (remote->locks == lock) {
|
||||
remote->locks = lock->next;
|
||||
if (repo->locks == lock) {
|
||||
repo->locks = lock->next;
|
||||
} else {
|
||||
while (prev && prev->next != lock)
|
||||
prev = prev->next;
|
||||
|
@ -1375,7 +1375,7 @@ static int unlock_remote(struct remote_lock *lock)
|
|||
|
||||
static void remove_locks(void)
|
||||
{
|
||||
struct remote_lock *lock = remote->locks;
|
||||
struct remote_lock *lock = repo->locks;
|
||||
|
||||
fprintf(stderr, "Removing remote locks...\n");
|
||||
while (lock) {
|
||||
|
@ -1457,7 +1457,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
|
|||
}
|
||||
}
|
||||
if (path) {
|
||||
path += remote->path_len;
|
||||
path += repo->path_len;
|
||||
ls->dentry_name = xstrdup(path);
|
||||
}
|
||||
} else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
|
||||
|
@ -1480,7 +1480,7 @@ static void remote_ls(const char *path, int flags,
|
|||
void (*userFunc)(struct remote_ls_ctx *ls),
|
||||
void *userData)
|
||||
{
|
||||
char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
struct strbuf in_buffer = STRBUF_INIT;
|
||||
|
@ -1496,7 +1496,7 @@ static void remote_ls(const char *path, int flags,
|
|||
ls.userData = userData;
|
||||
ls.userFunc = userFunc;
|
||||
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST);
|
||||
|
||||
|
@ -1574,7 +1574,7 @@ static int locking_available(void)
|
|||
struct xml_ctx ctx;
|
||||
int lock_flags = 0;
|
||||
|
||||
strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
|
||||
strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, repo->url);
|
||||
|
||||
dav_headers = curl_slist_append(dav_headers, "Depth: 0");
|
||||
dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
|
||||
|
@ -1586,7 +1586,7 @@ static int locking_available(void)
|
|||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
|
||||
|
@ -1617,15 +1617,15 @@ static int locking_available(void)
|
|||
XML_ParserFree(parser);
|
||||
if (!lock_flags)
|
||||
error("no DAV locking support on %s",
|
||||
remote->url);
|
||||
repo->url);
|
||||
|
||||
} else {
|
||||
error("Cannot access URL %s, return code %d",
|
||||
remote->url, results.curl_result);
|
||||
repo->url, results.curl_result);
|
||||
lock_flags = 0;
|
||||
}
|
||||
} else {
|
||||
error("Unable to start PROPFIND request on %s", remote->url);
|
||||
error("Unable to start PROPFIND request on %s", repo->url);
|
||||
}
|
||||
|
||||
strbuf_release(&out_buffer.buf);
|
||||
|
@ -1801,10 +1801,10 @@ static void one_remote_ref(char *refname)
|
|||
|
||||
ref = alloc_ref(refname);
|
||||
|
||||
if (http_fetch_ref(remote->url, ref) != 0) {
|
||||
if (http_fetch_ref(repo->url, ref) != 0) {
|
||||
fprintf(stderr,
|
||||
"Unable to fetch ref %s from %s\n",
|
||||
refname, remote->url);
|
||||
refname, repo->url);
|
||||
free(ref);
|
||||
return;
|
||||
}
|
||||
|
@ -1813,7 +1813,7 @@ static void one_remote_ref(char *refname)
|
|||
* Fetch a copy of the object if it doesn't exist locally - it
|
||||
* may be required for updating server info later.
|
||||
*/
|
||||
if (remote->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
|
||||
if (repo->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
|
||||
obj = lookup_unknown_object(ref->old_sha1);
|
||||
if (obj) {
|
||||
fprintf(stderr, " fetch %s for %s\n",
|
||||
|
@ -1853,10 +1853,10 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
|
|||
|
||||
ref = alloc_ref(ls->dentry_name);
|
||||
|
||||
if (http_fetch_ref(remote->url, ref) != 0) {
|
||||
if (http_fetch_ref(repo->url, ref) != 0) {
|
||||
fprintf(stderr,
|
||||
"Unable to fetch ref %s from %s\n",
|
||||
ls->dentry_name, remote->url);
|
||||
ls->dentry_name, repo->url);
|
||||
aborted = 1;
|
||||
free(ref);
|
||||
return;
|
||||
|
@ -1931,12 +1931,12 @@ static void update_remote_info_refs(struct remote_lock *lock)
|
|||
|
||||
static int remote_exists(const char *path)
|
||||
{
|
||||
char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
int ret = -1;
|
||||
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
|
@ -1966,8 +1966,8 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
|
|||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
|
||||
url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
|
@ -2082,7 +2082,7 @@ static int delete_remote_branch(char *pattern, int force)
|
|||
"of your current HEAD.\n"
|
||||
"If you are sure you want to delete it,"
|
||||
" run:\n\t'git http-push -D %s %s'",
|
||||
remote_ref->name, remote->url, pattern);
|
||||
remote_ref->name, repo->url, pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2090,8 +2090,8 @@ static int delete_remote_branch(char *pattern, int force)
|
|||
fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name);
|
||||
if (dry_run)
|
||||
return 0;
|
||||
url = xmalloc(strlen(remote->url) + strlen(remote_ref->name) + 1);
|
||||
sprintf(url, "%s%s", remote->url, remote_ref->name);
|
||||
url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1);
|
||||
sprintf(url, "%s%s", repo->url, remote_ref->name);
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
|
||||
|
@ -2128,13 +2128,14 @@ int main(int argc, char **argv)
|
|||
int i;
|
||||
int new_refs;
|
||||
struct ref *ref, *local_refs;
|
||||
struct remote *remote;
|
||||
char *rewritten_url = NULL;
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
remote = xcalloc(sizeof(*remote), 1);
|
||||
repo = xcalloc(sizeof(*repo), 1);
|
||||
|
||||
argv++;
|
||||
for (i = 1; i < argc; i++, argv++) {
|
||||
|
@ -2167,14 +2168,14 @@ int main(int argc, char **argv)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (!remote->url) {
|
||||
if (!repo->url) {
|
||||
char *path = strstr(arg, "//");
|
||||
remote->url = arg;
|
||||
remote->path_len = strlen(arg);
|
||||
repo->url = arg;
|
||||
repo->path_len = strlen(arg);
|
||||
if (path) {
|
||||
remote->path = strchr(path+2, '/');
|
||||
if (remote->path)
|
||||
remote->path_len = strlen(remote->path);
|
||||
repo->path = strchr(path+2, '/');
|
||||
if (repo->path)
|
||||
repo->path_len = strlen(repo->path);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -2187,7 +2188,7 @@ int main(int argc, char **argv)
|
|||
die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI");
|
||||
#endif
|
||||
|
||||
if (!remote->url)
|
||||
if (!repo->url)
|
||||
usage(http_push_usage);
|
||||
|
||||
if (delete_branch && nr_refspec != 1)
|
||||
|
@ -2195,17 +2196,24 @@ int main(int argc, char **argv)
|
|||
|
||||
memset(remote_dir_exists, -1, 256);
|
||||
|
||||
http_init(NULL);
|
||||
/*
|
||||
* Create a minimum remote by hand to give to http_init(),
|
||||
* primarily to allow it to look at the URL.
|
||||
*/
|
||||
remote = xcalloc(sizeof(*remote), 1);
|
||||
ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc);
|
||||
remote->url[remote->url_nr++] = repo->url;
|
||||
http_init(remote);
|
||||
|
||||
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
|
||||
|
||||
if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
|
||||
rewritten_url = xmalloc(strlen(remote->url)+2);
|
||||
strcpy(rewritten_url, remote->url);
|
||||
if (repo->url && repo->url[strlen(repo->url)-1] != '/') {
|
||||
rewritten_url = xmalloc(strlen(repo->url)+2);
|
||||
strcpy(rewritten_url, repo->url);
|
||||
strcat(rewritten_url, "/");
|
||||
remote->path = rewritten_url + (remote->path - remote->url);
|
||||
remote->path_len++;
|
||||
remote->url = rewritten_url;
|
||||
repo->path = rewritten_url + (repo->path - repo->url);
|
||||
repo->path_len++;
|
||||
repo->url = rewritten_url;
|
||||
}
|
||||
|
||||
/* Verify DAV compliance/lock support */
|
||||
|
@ -2217,20 +2225,20 @@ int main(int argc, char **argv)
|
|||
sigchain_push_common(remove_locks_on_signal);
|
||||
|
||||
/* Check whether the remote has server info files */
|
||||
remote->can_update_info_refs = 0;
|
||||
remote->has_info_refs = remote_exists("info/refs");
|
||||
remote->has_info_packs = remote_exists("objects/info/packs");
|
||||
if (remote->has_info_refs) {
|
||||
repo->can_update_info_refs = 0;
|
||||
repo->has_info_refs = remote_exists("info/refs");
|
||||
repo->has_info_packs = remote_exists("objects/info/packs");
|
||||
if (repo->has_info_refs) {
|
||||
info_ref_lock = lock_remote("info/refs", LOCK_TIME);
|
||||
if (info_ref_lock)
|
||||
remote->can_update_info_refs = 1;
|
||||
repo->can_update_info_refs = 1;
|
||||
else {
|
||||
error("cannot lock existing info/refs");
|
||||
rc = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (remote->has_info_packs)
|
||||
if (repo->has_info_packs)
|
||||
fetch_indices();
|
||||
|
||||
/* Get a list of all local and remote heads to validate refspecs */
|
||||
|
@ -2388,8 +2396,8 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/* Update remote server info if appropriate */
|
||||
if (remote->has_info_refs && new_refs) {
|
||||
if (info_ref_lock && remote->can_update_info_refs) {
|
||||
if (repo->has_info_refs && new_refs) {
|
||||
if (info_ref_lock && repo->can_update_info_refs) {
|
||||
fprintf(stderr, "Updating remote server info\n");
|
||||
if (!dry_run)
|
||||
update_remote_info_refs(info_ref_lock);
|
||||
|
@ -2402,7 +2410,7 @@ int main(int argc, char **argv)
|
|||
free(rewritten_url);
|
||||
if (info_ref_lock)
|
||||
unlock_remote(info_ref_lock);
|
||||
free(remote);
|
||||
free(repo);
|
||||
|
||||
curl_slist_free_all(no_pragma_header);
|
||||
|
||||
|
|
151
http.c
151
http.c
|
@ -1,7 +1,7 @@
|
|||
#include "http.h"
|
||||
|
||||
int data_received;
|
||||
int active_requests = 0;
|
||||
int active_requests;
|
||||
|
||||
#ifdef USE_CURL_MULTI
|
||||
static int max_requests = -1;
|
||||
|
@ -13,22 +13,23 @@ static CURL *curl_default;
|
|||
char curl_errorstr[CURL_ERROR_SIZE];
|
||||
|
||||
static int curl_ssl_verify = -1;
|
||||
static const char *ssl_cert = NULL;
|
||||
static const char *ssl_cert;
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
static const char *ssl_key = NULL;
|
||||
static const char *ssl_key;
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||
static const char *ssl_capath = NULL;
|
||||
static const char *ssl_capath;
|
||||
#endif
|
||||
static const char *ssl_cainfo = NULL;
|
||||
static const char *ssl_cainfo;
|
||||
static long curl_low_speed_limit = -1;
|
||||
static long curl_low_speed_time = -1;
|
||||
static int curl_ftp_no_epsv = 0;
|
||||
static const char *curl_http_proxy = NULL;
|
||||
static int curl_ftp_no_epsv;
|
||||
static const char *curl_http_proxy;
|
||||
static char *user_name, *user_pass;
|
||||
|
||||
static struct curl_slist *pragma_header;
|
||||
|
||||
static struct active_request_slot *active_queue_head = NULL;
|
||||
static struct active_request_slot *active_queue_head;
|
||||
|
||||
size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
||||
{
|
||||
|
@ -94,52 +95,32 @@ static void process_curl_messages(void)
|
|||
static int http_options(const char *var, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp("http.sslverify", var)) {
|
||||
if (curl_ssl_verify == -1) {
|
||||
curl_ssl_verify = git_config_bool(var, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp("http.sslcert", var)) {
|
||||
if (ssl_cert == NULL)
|
||||
if (!strcmp("http.sslcert", var))
|
||||
return git_config_string(&ssl_cert, var, value);
|
||||
return 0;
|
||||
}
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
if (!strcmp("http.sslkey", var)) {
|
||||
if (ssl_key == NULL)
|
||||
if (!strcmp("http.sslkey", var))
|
||||
return git_config_string(&ssl_key, var, value);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||
if (!strcmp("http.sslcapath", var)) {
|
||||
if (ssl_capath == NULL)
|
||||
if (!strcmp("http.sslcapath", var))
|
||||
return git_config_string(&ssl_capath, var, value);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (!strcmp("http.sslcainfo", var)) {
|
||||
if (ssl_cainfo == NULL)
|
||||
if (!strcmp("http.sslcainfo", var))
|
||||
return git_config_string(&ssl_cainfo, var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_CURL_MULTI
|
||||
if (!strcmp("http.maxrequests", var)) {
|
||||
if (max_requests == -1)
|
||||
max_requests = git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp("http.lowspeedlimit", var)) {
|
||||
if (curl_low_speed_limit == -1)
|
||||
curl_low_speed_limit = (long)git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.lowspeedtime", var)) {
|
||||
if (curl_low_speed_time == -1)
|
||||
curl_low_speed_time = (long)git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
@ -148,19 +129,28 @@ static int http_options(const char *var, const char *value, void *cb)
|
|||
curl_ftp_no_epsv = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.proxy", var)) {
|
||||
if (curl_http_proxy == NULL)
|
||||
if (!strcmp("http.proxy", var))
|
||||
return git_config_string(&curl_http_proxy, var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fall back on the default ones */
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static CURL* get_curl_handle(void)
|
||||
static void init_curl_http_auth(CURL *result)
|
||||
{
|
||||
CURL* result = curl_easy_init();
|
||||
if (user_name) {
|
||||
struct strbuf up = STRBUF_INIT;
|
||||
if (!user_pass)
|
||||
user_pass = xstrdup(getpass("Password: "));
|
||||
strbuf_addf(&up, "%s:%s", user_name, user_pass);
|
||||
curl_easy_setopt(result, CURLOPT_USERPWD,
|
||||
strbuf_detach(&up, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
static CURL *get_curl_handle(void)
|
||||
{
|
||||
CURL *result = curl_easy_init();
|
||||
|
||||
if (!curl_ssl_verify) {
|
||||
curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
|
@ -176,6 +166,8 @@ static CURL* get_curl_handle(void)
|
|||
curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
|
||||
#endif
|
||||
|
||||
init_curl_http_auth(result);
|
||||
|
||||
if (ssl_cert != NULL)
|
||||
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
|
@ -213,11 +205,60 @@ static CURL* get_curl_handle(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void http_auth_init(const char *url)
|
||||
{
|
||||
char *at, *colon, *cp, *slash;
|
||||
int len;
|
||||
|
||||
cp = strstr(url, "://");
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ok, the URL looks like "proto://something". Which one?
|
||||
* "proto://<user>:<pass>@<host>/...",
|
||||
* "proto://<user>@<host>/...", or just
|
||||
* "proto://<host>/..."?
|
||||
*/
|
||||
cp += 3;
|
||||
at = strchr(cp, '@');
|
||||
colon = strchr(cp, ':');
|
||||
slash = strchrnul(cp, '/');
|
||||
if (!at || slash <= at)
|
||||
return; /* No credentials */
|
||||
if (!colon || at <= colon) {
|
||||
/* Only username */
|
||||
len = at - cp;
|
||||
user_name = xmalloc(len + 1);
|
||||
memcpy(user_name, cp, len);
|
||||
user_name[len] = '\0';
|
||||
user_pass = NULL;
|
||||
} else {
|
||||
len = colon - cp;
|
||||
user_name = xmalloc(len + 1);
|
||||
memcpy(user_name, cp, len);
|
||||
user_name[len] = '\0';
|
||||
len = at - (colon + 1);
|
||||
user_pass = xmalloc(len + 1);
|
||||
memcpy(user_pass, colon + 1, len);
|
||||
user_pass[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void set_from_env(const char **var, const char *envname)
|
||||
{
|
||||
const char *val = getenv(envname);
|
||||
if (val)
|
||||
*var = val;
|
||||
}
|
||||
|
||||
void http_init(struct remote *remote)
|
||||
{
|
||||
char *low_speed_limit;
|
||||
char *low_speed_time;
|
||||
|
||||
git_config(http_options, NULL);
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
if (remote && remote->http_proxy)
|
||||
|
@ -242,14 +283,14 @@ void http_init(struct remote *remote)
|
|||
if (getenv("GIT_SSL_NO_VERIFY"))
|
||||
curl_ssl_verify = 0;
|
||||
|
||||
ssl_cert = getenv("GIT_SSL_CERT");
|
||||
set_from_env(&ssl_cert, "GIT_SSL_CERT");
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
ssl_key = getenv("GIT_SSL_KEY");
|
||||
set_from_env(&ssl_key, "GIT_SSL_KEY");
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||
ssl_capath = getenv("GIT_SSL_CAPATH");
|
||||
set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
|
||||
#endif
|
||||
ssl_cainfo = getenv("GIT_SSL_CAINFO");
|
||||
set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
|
||||
|
||||
low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
|
||||
if (low_speed_limit != NULL)
|
||||
|
@ -258,8 +299,6 @@ void http_init(struct remote *remote)
|
|||
if (low_speed_time != NULL)
|
||||
curl_low_speed_time = strtol(low_speed_time, NULL, 10);
|
||||
|
||||
git_config(http_options, NULL);
|
||||
|
||||
if (curl_ssl_verify == -1)
|
||||
curl_ssl_verify = 1;
|
||||
|
||||
|
@ -271,6 +310,9 @@ void http_init(struct remote *remote)
|
|||
if (getenv("GIT_CURL_FTP_NO_EPSV"))
|
||||
curl_ftp_no_epsv = 1;
|
||||
|
||||
if (remote && remote->url && remote->url[0])
|
||||
http_auth_init(remote->url[0]);
|
||||
|
||||
#ifndef NO_CURL_EASY_DUPHANDLE
|
||||
curl_default = get_curl_handle();
|
||||
#endif
|
||||
|
@ -322,15 +364,14 @@ struct active_request_slot *get_active_slot(void)
|
|||
/* Wait for a slot to open up if the queue is full */
|
||||
while (active_requests >= max_requests) {
|
||||
curl_multi_perform(curlm, &num_transfers);
|
||||
if (num_transfers < active_requests) {
|
||||
if (num_transfers < active_requests)
|
||||
process_curl_messages();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (slot != NULL && slot->in_use) {
|
||||
while (slot != NULL && slot->in_use)
|
||||
slot = slot->next;
|
||||
}
|
||||
|
||||
if (slot == NULL) {
|
||||
newslot = xmalloc(sizeof(*newslot));
|
||||
newslot->curl = NULL;
|
||||
|
@ -341,9 +382,8 @@ struct active_request_slot *get_active_slot(void)
|
|||
if (slot == NULL) {
|
||||
active_queue_head = newslot;
|
||||
} else {
|
||||
while (slot->next != NULL) {
|
||||
while (slot->next != NULL)
|
||||
slot = slot->next;
|
||||
}
|
||||
slot->next = newslot;
|
||||
}
|
||||
slot = newslot;
|
||||
|
@ -404,7 +444,7 @@ struct fill_chain {
|
|||
struct fill_chain *next;
|
||||
};
|
||||
|
||||
static struct fill_chain *fill_cfg = NULL;
|
||||
static struct fill_chain *fill_cfg;
|
||||
|
||||
void add_fill_function(void *data, int (*fill)(void *))
|
||||
{
|
||||
|
@ -535,9 +575,8 @@ static void finish_active_slot(struct active_request_slot *slot)
|
|||
}
|
||||
|
||||
/* Run callback if appropriate */
|
||||
if (slot->callback_func != NULL) {
|
||||
if (slot->callback_func != NULL)
|
||||
slot->callback_func(slot->callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void finish_all_active_slots(void)
|
||||
|
@ -567,8 +606,10 @@ static inline int needs_quote(int ch)
|
|||
|
||||
static inline int hex(int v)
|
||||
{
|
||||
if (v < 10) return '0' + v;
|
||||
else return 'A' + v - 10;
|
||||
if (v < 10)
|
||||
return '0' + v;
|
||||
else
|
||||
return 'A' + v - 10;
|
||||
}
|
||||
|
||||
static char *quote_ref_url(const char *base, const char *ref)
|
||||
|
|
18
mailmap.c
18
mailmap.c
|
@ -50,6 +50,15 @@ static void add_mapping(struct string_list *map,
|
|||
{
|
||||
struct mailmap_entry *me;
|
||||
int index;
|
||||
char *p;
|
||||
|
||||
if (old_email)
|
||||
for (p = old_email; *p; p++)
|
||||
*p = tolower(*p);
|
||||
if (new_email)
|
||||
for (p = new_email; *p; p++)
|
||||
*p = tolower(*p);
|
||||
|
||||
if (old_email == NULL) {
|
||||
old_email = new_email;
|
||||
new_email = NULL;
|
||||
|
@ -90,7 +99,8 @@ static void add_mapping(struct string_list *map,
|
|||
old_name, old_email, new_name, new_email);
|
||||
}
|
||||
|
||||
static char *parse_name_and_email(char *buffer, char **name, char **email)
|
||||
static char *parse_name_and_email(char *buffer, char **name,
|
||||
char **email, int allow_empty_email)
|
||||
{
|
||||
char *left, *right, *nstart, *nend;
|
||||
*name = *email = 0;
|
||||
|
@ -99,7 +109,7 @@ static char *parse_name_and_email(char *buffer, char **name, char **email)
|
|||
return NULL;
|
||||
if ((right = strchr(left+1, '>')) == NULL)
|
||||
return NULL;
|
||||
if (left+1 == right)
|
||||
if (!allow_empty_email && (left+1 == right))
|
||||
return NULL;
|
||||
|
||||
/* remove whitespace from beginning and end of name */
|
||||
|
@ -150,8 +160,8 @@ static int read_single_mailmap(struct string_list *map, const char *filename, ch
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if ((name2 = parse_name_and_email(buffer, &name1, &email1)) != NULL)
|
||||
parse_name_and_email(name2, &name2, &email2);
|
||||
if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
|
||||
parse_name_and_email(name2, &name2, &email2, 1);
|
||||
|
||||
if (email1)
|
||||
add_mapping(map, name1, email1, name2, email2);
|
||||
|
|
93
patch-ids.c
93
patch-ids.c
|
@ -1,6 +1,7 @@
|
|||
#include "cache.h"
|
||||
#include "diff.h"
|
||||
#include "commit.h"
|
||||
#include "sha1-lookup.h"
|
||||
#include "patch-ids.h"
|
||||
|
||||
static int commit_patch_id(struct commit *commit, struct diff_options *options,
|
||||
|
@ -15,99 +16,15 @@ static int commit_patch_id(struct commit *commit, struct diff_options *options,
|
|||
return diff_flush_patch_id(options, sha1);
|
||||
}
|
||||
|
||||
static uint32_t take2(const unsigned char *id)
|
||||
static const unsigned char *patch_id_access(size_t index, void *table)
|
||||
{
|
||||
return ((id[0] << 8) | id[1]);
|
||||
struct patch_id **id_table = table;
|
||||
return id_table[index]->patch_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conventional binary search loop looks like this:
|
||||
*
|
||||
* do {
|
||||
* int mi = (lo + hi) / 2;
|
||||
* int cmp = "entry pointed at by mi" minus "target";
|
||||
* if (!cmp)
|
||||
* return (mi is the wanted one)
|
||||
* if (cmp > 0)
|
||||
* hi = mi; "mi is larger than target"
|
||||
* else
|
||||
* lo = mi+1; "mi is smaller than target"
|
||||
* } while (lo < hi);
|
||||
*
|
||||
* The invariants are:
|
||||
*
|
||||
* - When entering the loop, lo points at a slot that is never
|
||||
* above the target (it could be at the target), hi points at a
|
||||
* slot that is guaranteed to be above the target (it can never
|
||||
* be at the target).
|
||||
*
|
||||
* - We find a point 'mi' between lo and hi (mi could be the same
|
||||
* as lo, but never can be the same as hi), and check if it hits
|
||||
* the target. There are three cases:
|
||||
*
|
||||
* - if it is a hit, we are happy.
|
||||
*
|
||||
* - if it is strictly higher than the target, we update hi with
|
||||
* it.
|
||||
*
|
||||
* - if it is strictly lower than the target, we update lo to be
|
||||
* one slot after it, because we allow lo to be at the target.
|
||||
*
|
||||
* When choosing 'mi', we do not have to take the "middle" but
|
||||
* anywhere in between lo and hi, as long as lo <= mi < hi is
|
||||
* satisfied. When we somehow know that the distance between the
|
||||
* target and lo is much shorter than the target and hi, we could
|
||||
* pick mi that is much closer to lo than the midway.
|
||||
*/
|
||||
static int patch_pos(struct patch_id **table, int nr, const unsigned char *id)
|
||||
{
|
||||
int hi = nr;
|
||||
int lo = 0;
|
||||
int mi = 0;
|
||||
|
||||
if (!nr)
|
||||
return -1;
|
||||
|
||||
if (nr != 1) {
|
||||
unsigned lov, hiv, miv, ofs;
|
||||
|
||||
for (ofs = 0; ofs < 18; ofs += 2) {
|
||||
lov = take2(table[0]->patch_id + ofs);
|
||||
hiv = take2(table[nr-1]->patch_id + ofs);
|
||||
miv = take2(id + ofs);
|
||||
if (miv < lov)
|
||||
return -1;
|
||||
if (hiv < miv)
|
||||
return -1 - nr;
|
||||
if (lov != hiv) {
|
||||
/*
|
||||
* At this point miv could be equal
|
||||
* to hiv (but id could still be higher);
|
||||
* the invariant of (mi < hi) should be
|
||||
* kept.
|
||||
*/
|
||||
mi = (nr-1) * (miv - lov) / (hiv - lov);
|
||||
if (lo <= mi && mi < hi)
|
||||
break;
|
||||
die("oops");
|
||||
}
|
||||
}
|
||||
if (18 <= ofs)
|
||||
die("cannot happen -- lo and hi are identical");
|
||||
}
|
||||
|
||||
do {
|
||||
int cmp;
|
||||
cmp = hashcmp(table[mi]->patch_id, id);
|
||||
if (!cmp)
|
||||
return mi;
|
||||
if (cmp > 0)
|
||||
hi = mi;
|
||||
else
|
||||
lo = mi + 1;
|
||||
mi = (hi + lo) / 2;
|
||||
} while (lo < hi);
|
||||
return -lo-1;
|
||||
return sha1_pos(id, table, nr, patch_id_access);
|
||||
}
|
||||
|
||||
#define BUCKET_SIZE 190 /* 190 * 21 = 3990, with slop close enough to 4K */
|
||||
|
|
|
@ -242,7 +242,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
|
|||
}
|
||||
|
||||
void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
||||
int relative_date)
|
||||
enum date_mode dmode)
|
||||
{
|
||||
if (info && info->last_commit_reflog) {
|
||||
struct commit_reflog *commit_reflog = info->last_commit_reflog;
|
||||
|
@ -251,8 +251,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
|||
info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
|
||||
if (oneline) {
|
||||
printf("%s@{", commit_reflog->reflogs->ref);
|
||||
if (commit_reflog->flag || relative_date)
|
||||
printf("%s", show_date(info->timestamp, 0, 1));
|
||||
if (commit_reflog->flag || dmode)
|
||||
printf("%s", show_date(info->timestamp,
|
||||
info->tz,
|
||||
dmode));
|
||||
else
|
||||
printf("%d", commit_reflog->reflogs->nr
|
||||
- 2 - commit_reflog->recno);
|
||||
|
@ -260,10 +262,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
|||
}
|
||||
else {
|
||||
printf("Reflog: %s@{", commit_reflog->reflogs->ref);
|
||||
if (commit_reflog->flag || relative_date)
|
||||
if (commit_reflog->flag || dmode)
|
||||
printf("%s", show_date(info->timestamp,
|
||||
info->tz,
|
||||
relative_date));
|
||||
dmode));
|
||||
else
|
||||
printf("%d", commit_reflog->reflogs->nr
|
||||
- 2 - commit_reflog->recno);
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#ifndef REFLOG_WALK_H
|
||||
#define REFLOG_WALK_H
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
extern void init_reflog_walk(struct reflog_walk_info** info);
|
||||
extern int add_reflog_for_walk(struct reflog_walk_info *info,
|
||||
struct commit *commit, const char *name);
|
||||
extern void fake_reflog_parent(struct reflog_walk_info *info,
|
||||
struct commit *commit);
|
||||
extern void show_reflog_message(struct reflog_walk_info *info, int, int);
|
||||
extern void show_reflog_message(struct reflog_walk_info *info, int,
|
||||
enum date_mode);
|
||||
|
||||
#endif
|
||||
|
|
10
refs.c
10
refs.c
|
@ -742,6 +742,16 @@ int check_ref_format(const char *ref)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const char *ref_rev_parse_rules[] = {
|
||||
"%.*s",
|
||||
"refs/%.*s",
|
||||
|
|
2
refs.h
2
refs.h
|
@ -80,6 +80,8 @@ extern int for_each_reflog(each_ref_fn, void *);
|
|||
#define CHECK_REF_FORMAT_WILDCARD (-3)
|
||||
extern int check_ref_format(const char *target);
|
||||
|
||||
extern const char *prettify_ref(const struct ref *ref);
|
||||
|
||||
/** rename ref, return 0 on success **/
|
||||
extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
|
||||
|
||||
|
|
3
remote.c
3
remote.c
|
@ -1401,9 +1401,10 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
|
|||
if (theirs == ours)
|
||||
return 0;
|
||||
|
||||
/* Run "rev-list --left-right ours...theirs" internally... */
|
||||
/* Run "rev-list --no-merges --left-right ours...theirs" internally... */
|
||||
rev_argc = 0;
|
||||
rev_argv[rev_argc++] = NULL;
|
||||
rev_argv[rev_argc++] = "--no-merges";
|
||||
rev_argv[rev_argc++] = "--left-right";
|
||||
rev_argv[rev_argc++] = symmetric;
|
||||
rev_argv[rev_argc++] = "--";
|
||||
|
|
|
@ -1106,10 +1106,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
|||
revs->edge_hint = 1;
|
||||
} else if (!strcmp(arg, "--unpacked")) {
|
||||
revs->unpacked = 1;
|
||||
revs->kept_pack_only = 0;
|
||||
} else if (!strcmp(arg, "--kept-pack-only")) {
|
||||
revs->unpacked = 1;
|
||||
revs->kept_pack_only = 1;
|
||||
} else if (!prefixcmp(arg, "--unpacked=")) {
|
||||
die("--unpacked=<packfile> no longer supported.");
|
||||
} else if (!strcmp(arg, "-r")) {
|
||||
|
@ -1679,10 +1675,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
|
|||
{
|
||||
if (commit->object.flags & SHOWN)
|
||||
return commit_ignore;
|
||||
if (revs->unpacked &&
|
||||
(revs->kept_pack_only
|
||||
? has_sha1_kept_pack(commit->object.sha1)
|
||||
: has_sha1_pack(commit->object.sha1)))
|
||||
if (revs->unpacked && has_sha1_pack(commit->object.sha1))
|
||||
return commit_ignore;
|
||||
if (revs->show_all)
|
||||
return commit_show;
|
||||
|
|
|
@ -50,7 +50,6 @@ struct rev_info {
|
|||
edge_hint:1,
|
||||
limited:1,
|
||||
unpacked:1,
|
||||
kept_pack_only:1,
|
||||
boundary:2,
|
||||
left_right:1,
|
||||
rewrite_parents:1,
|
||||
|
|
|
@ -10,7 +10,7 @@ enum {
|
|||
ERR_RUN_COMMAND_WAITPID_SIGNAL,
|
||||
ERR_RUN_COMMAND_WAITPID_NOEXIT,
|
||||
};
|
||||
#define IS_RUN_COMMAND_ERR(x) ((x) <= -ERR_RUN_COMMAND_FORK)
|
||||
#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)
|
||||
|
||||
struct child_process {
|
||||
const char **argv;
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
#define SEND_PACK_H
|
||||
|
||||
struct send_pack_args {
|
||||
const char *receivepack;
|
||||
unsigned verbose:1,
|
||||
send_all:1,
|
||||
send_mirror:1,
|
||||
force_update:1,
|
||||
use_thin_pack:1,
|
||||
|
@ -12,7 +10,7 @@ struct send_pack_args {
|
|||
};
|
||||
|
||||
int send_pack(struct send_pack_args *args,
|
||||
const char *dest, struct remote *remote,
|
||||
int nr_heads, const char **heads);
|
||||
int fd[], struct child_process *conn,
|
||||
struct ref *remote_refs, struct extra_have_objects *extra_have);
|
||||
|
||||
#endif
|
||||
|
|
101
sha1-lookup.c
101
sha1-lookup.c
|
@ -1,6 +1,107 @@
|
|||
#include "cache.h"
|
||||
#include "sha1-lookup.h"
|
||||
|
||||
static uint32_t take2(const unsigned char *sha1)
|
||||
{
|
||||
return ((sha1[0] << 8) | sha1[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Conventional binary search loop looks like this:
|
||||
*
|
||||
* do {
|
||||
* int mi = (lo + hi) / 2;
|
||||
* int cmp = "entry pointed at by mi" minus "target";
|
||||
* if (!cmp)
|
||||
* return (mi is the wanted one)
|
||||
* if (cmp > 0)
|
||||
* hi = mi; "mi is larger than target"
|
||||
* else
|
||||
* lo = mi+1; "mi is smaller than target"
|
||||
* } while (lo < hi);
|
||||
*
|
||||
* The invariants are:
|
||||
*
|
||||
* - When entering the loop, lo points at a slot that is never
|
||||
* above the target (it could be at the target), hi points at a
|
||||
* slot that is guaranteed to be above the target (it can never
|
||||
* be at the target).
|
||||
*
|
||||
* - We find a point 'mi' between lo and hi (mi could be the same
|
||||
* as lo, but never can be the same as hi), and check if it hits
|
||||
* the target. There are three cases:
|
||||
*
|
||||
* - if it is a hit, we are happy.
|
||||
*
|
||||
* - if it is strictly higher than the target, we update hi with
|
||||
* it.
|
||||
*
|
||||
* - if it is strictly lower than the target, we update lo to be
|
||||
* one slot after it, because we allow lo to be at the target.
|
||||
*
|
||||
* When choosing 'mi', we do not have to take the "middle" but
|
||||
* anywhere in between lo and hi, as long as lo <= mi < hi is
|
||||
* satisfied. When we somehow know that the distance between the
|
||||
* target and lo is much shorter than the target and hi, we could
|
||||
* pick mi that is much closer to lo than the midway.
|
||||
*/
|
||||
/*
|
||||
* The table should contain "nr" elements.
|
||||
* The sha1 of element i (between 0 and nr - 1) should be returned
|
||||
* by "fn(i, table)".
|
||||
*/
|
||||
int sha1_pos(const unsigned char *sha1, void *table, size_t nr,
|
||||
sha1_access_fn fn)
|
||||
{
|
||||
size_t hi = nr;
|
||||
size_t lo = 0;
|
||||
size_t mi = 0;
|
||||
|
||||
if (!nr)
|
||||
return -1;
|
||||
|
||||
if (nr != 1) {
|
||||
size_t lov, hiv, miv, ofs;
|
||||
|
||||
for (ofs = 0; ofs < 18; ofs += 2) {
|
||||
lov = take2(fn(0, table) + ofs);
|
||||
hiv = take2(fn(nr - 1, table) + ofs);
|
||||
miv = take2(sha1 + ofs);
|
||||
if (miv < lov)
|
||||
return -1;
|
||||
if (hiv < miv)
|
||||
return -1 - nr;
|
||||
if (lov != hiv) {
|
||||
/*
|
||||
* At this point miv could be equal
|
||||
* to hiv (but sha1 could still be higher);
|
||||
* the invariant of (mi < hi) should be
|
||||
* kept.
|
||||
*/
|
||||
mi = (nr - 1) * (miv - lov) / (hiv - lov);
|
||||
if (lo <= mi && mi < hi)
|
||||
break;
|
||||
die("oops");
|
||||
}
|
||||
}
|
||||
if (18 <= ofs)
|
||||
die("cannot happen -- lo and hi are identical");
|
||||
}
|
||||
|
||||
do {
|
||||
int cmp;
|
||||
cmp = hashcmp(fn(mi, table), sha1);
|
||||
if (!cmp)
|
||||
return mi;
|
||||
if (cmp > 0)
|
||||
hi = mi;
|
||||
else
|
||||
lo = mi + 1;
|
||||
mi = (hi + lo) / 2;
|
||||
} while (lo < hi);
|
||||
return -lo-1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conventional binary search loop looks like this:
|
||||
*
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
#ifndef SHA1_LOOKUP_H
|
||||
#define SHA1_LOOKUP_H
|
||||
|
||||
typedef const unsigned char *sha1_access_fn(size_t index, void *table);
|
||||
|
||||
extern int sha1_pos(const unsigned char *sha1,
|
||||
void *table,
|
||||
size_t nr,
|
||||
sha1_access_fn fn);
|
||||
|
||||
extern int sha1_entry_pos(const void *table,
|
||||
size_t elem_size,
|
||||
size_t key_offset,
|
||||
|
|
21
sha1_file.c
21
sha1_file.c
|
@ -1919,8 +1919,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
|
||||
int kept_pack_only)
|
||||
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
|
||||
{
|
||||
static struct packed_git *last_found = (void *)1;
|
||||
struct packed_git *p;
|
||||
|
@ -1932,8 +1931,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
|
|||
p = (last_found == (void *)1) ? packed_git : last_found;
|
||||
|
||||
do {
|
||||
if (kept_pack_only && !p->pack_keep)
|
||||
goto next;
|
||||
if (p->num_bad_objects) {
|
||||
unsigned i;
|
||||
for (i = 0; i < p->num_bad_objects; i++)
|
||||
|
@ -1973,16 +1970,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
|
||||
{
|
||||
return find_pack_ent(sha1, e, 0);
|
||||
}
|
||||
|
||||
static int find_kept_pack_entry(const unsigned char *sha1, struct pack_entry *e)
|
||||
{
|
||||
return find_pack_ent(sha1, e, 1);
|
||||
}
|
||||
|
||||
struct packed_git *find_sha1_pack(const unsigned char *sha1,
|
||||
struct packed_git *packs)
|
||||
{
|
||||
|
@ -2456,12 +2443,6 @@ int has_sha1_pack(const unsigned char *sha1)
|
|||
return find_pack_entry(sha1, &e);
|
||||
}
|
||||
|
||||
int has_sha1_kept_pack(const unsigned char *sha1)
|
||||
{
|
||||
struct pack_entry e;
|
||||
return find_kept_pack_entry(sha1, &e);
|
||||
}
|
||||
|
||||
int has_sha1_file(const unsigned char *sha1)
|
||||
{
|
||||
struct pack_entry e;
|
||||
|
|
|
@ -24,7 +24,7 @@ pre-clean:
|
|||
$(RM) -r test-results
|
||||
|
||||
clean:
|
||||
$(RM) -r 'trash directory' test-results
|
||||
$(RM) -r 'trash directory'.* test-results
|
||||
|
||||
aggregate-results-and-cleanup: $(T)
|
||||
$(MAKE) aggregate-results
|
||||
|
|
|
@ -429,6 +429,37 @@ test_expect_success 'in-tree .gitattributes (4)' '
|
|||
}
|
||||
'
|
||||
|
||||
test_expect_success 'checkout with existing .gitattributes' '
|
||||
|
||||
git config core.autocrlf true &&
|
||||
git config --unset core.safecrlf &&
|
||||
echo ".file2 -crlfQ" | q_to_cr >> .gitattributes &&
|
||||
git add .gitattributes &&
|
||||
git commit -m initial &&
|
||||
echo ".file -crlfQ" | q_to_cr >> .gitattributes &&
|
||||
echo "contents" > .file &&
|
||||
git add .gitattributes .file &&
|
||||
git commit -m second &&
|
||||
|
||||
git checkout master~1 &&
|
||||
git checkout master &&
|
||||
test "$(git diff-files --raw)" = ""
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'checkout when deleting .gitattributes' '
|
||||
|
||||
git rm .gitattributes &&
|
||||
echo "contentsQ" | q_to_cr > .file2 &&
|
||||
git add .file2 &&
|
||||
git commit -m third
|
||||
|
||||
git checkout master~1 &&
|
||||
git checkout master &&
|
||||
remove_cr .file2 >/dev/null
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'invalid .gitattributes (must not crash)' '
|
||||
|
||||
echo "three +crlf" >>.gitattributes &&
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='Test reflog display routines'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
echo content >file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m one
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
|
||||
Reflog message: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'log -g shows reflog headers' '
|
||||
git log -g -1 >tmp &&
|
||||
grep ^Reflog <tmp >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
e46513e HEAD@{0}: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'oneline reflog format' '
|
||||
git log -g -1 --oneline >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>)
|
||||
Reflog message: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using @{now} syntax shows reflog date (multiline)' '
|
||||
git log -g -1 HEAD@{now} >tmp &&
|
||||
grep ^Reflog <tmp >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using @{now} syntax shows reflog date (oneline)' '
|
||||
git log -g -1 --oneline HEAD@{now} >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
Reflog: HEAD@{1112911993 -0700} (C O Mitter <committer@example.com>)
|
||||
Reflog message: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using --date= shows reflog date (multiline)' '
|
||||
git log -g -1 --date=raw >tmp &&
|
||||
grep ^Reflog <tmp >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
e46513e HEAD@{1112911993 -0700}: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using --date= shows reflog date (oneline)' '
|
||||
git log -g -1 --oneline --date=raw >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
|
@ -195,7 +195,7 @@ test_expect_success 'test deleting branch deletes branch config' \
|
|||
test_expect_success 'test deleting branch without config' \
|
||||
'git branch my7 s &&
|
||||
sha1=$(git rev-parse my7 | cut -c 1-7) &&
|
||||
test "$(git branch -d my7 2>&1)" = "Deleted branch my7 ($sha1)."'
|
||||
test "$(git branch -d my7 2>&1)" = "Deleted branch my7 (was $sha1)."'
|
||||
|
||||
test_expect_success 'test --track without .fetch entries' \
|
||||
'git branch --track my8 &&
|
||||
|
|
|
@ -128,6 +128,21 @@ test_expect_success 'additional command line cc' '
|
|||
grep "^ *S. E. Cipient <scipient@example.com>$" patch5
|
||||
'
|
||||
|
||||
test_expect_success 'command line headers' '
|
||||
|
||||
git config --unset-all format.headers &&
|
||||
git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch6 &&
|
||||
grep "^Cc: R. E. Cipient <rcipient@example.com>$" patch6
|
||||
'
|
||||
|
||||
test_expect_success 'configuration headers and command line headers' '
|
||||
|
||||
git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
|
||||
git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch7 &&
|
||||
grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch7 &&
|
||||
grep "^ *S. E. Cipient <scipient@example.com>$" patch7
|
||||
'
|
||||
|
||||
test_expect_success 'multiple files' '
|
||||
|
||||
rm -rf patches/ &&
|
||||
|
|
|
@ -136,4 +136,28 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
|
|||
GIT_EXTERNAL_DIFF=echo git diff
|
||||
'
|
||||
|
||||
echo "#!$SHELL_PATH" >fake-diff.sh
|
||||
cat >> fake-diff.sh <<\EOF
|
||||
cat $2 >> crlfed.txt
|
||||
EOF
|
||||
chmod a+x fake-diff.sh
|
||||
|
||||
keep_only_cr () {
|
||||
tr -dc '\015'
|
||||
}
|
||||
|
||||
test_expect_success 'external diff with autocrlf = true' '
|
||||
git config core.autocrlf true &&
|
||||
GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
|
||||
test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c)
|
||||
'
|
||||
|
||||
test_expect_success 'diff --cached' '
|
||||
git add file &&
|
||||
git update-index --assume-unchanged file &&
|
||||
echo second >file &&
|
||||
git diff --cached >actual &&
|
||||
test_cmp ../t4020/diff.NUL actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
@ -7,6 +7,7 @@ test_description='GIT_EDITOR, core.editor, and stuff'
|
|||
for i in GIT_EDITOR core_editor EDITOR VISUAL vi
|
||||
do
|
||||
cat >e-$i.sh <<-EOF
|
||||
#!$SHELL_PATH
|
||||
echo "Edited by $i" >"\$1"
|
||||
EOF
|
||||
chmod +x e-$i.sh
|
||||
|
|
|
@ -234,7 +234,7 @@ cat >.git/FAKE_EDITOR <<EOF
|
|||
# kill -TERM command added below.
|
||||
EOF
|
||||
|
||||
test_expect_success 'a SIGTERM should break locks' '
|
||||
test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' '
|
||||
echo >>negative &&
|
||||
! "$SHELL_PATH" -c '\''
|
||||
echo kill -TERM $$ >> .git/FAKE_EDITOR
|
||||
|
|
|
@ -88,5 +88,66 @@ test_expect_failure 'packed obs in alt ODB are repacked when local repo has pack
|
|||
done
|
||||
'
|
||||
|
||||
test_expect_success 'packed obs in alternate ODB kept pack are repacked' '
|
||||
# swap the .keep so the commit object is in the pack with .keep
|
||||
for p in alt_objects/pack/*.pack
|
||||
do
|
||||
base_name=$(basename $p .pack)
|
||||
if test -f alt_objects/pack/$base_name.keep
|
||||
then
|
||||
rm alt_objects/pack/$base_name.keep
|
||||
else
|
||||
touch alt_objects/pack/$base_name.keep
|
||||
fi
|
||||
done
|
||||
git repack -a -d &&
|
||||
myidx=$(ls -1 .git/objects/pack/*.idx) &&
|
||||
test -f "$myidx" &&
|
||||
for p in alt_objects/pack/*.idx; do
|
||||
git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
|
||||
done | while read sha1 rest; do
|
||||
if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
|
||||
echo "Missing object in local pack: $sha1"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
'
|
||||
|
||||
test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '
|
||||
rm -f alt_objects/pack/*.keep &&
|
||||
mv .git/objects/pack/* alt_objects/pack/ &&
|
||||
csha1=$(git rev-parse HEAD^{commit}) &&
|
||||
git reset --hard HEAD^ &&
|
||||
sleep 1 &&
|
||||
git reflog expire --expire=now --expire-unreachable=now --all &&
|
||||
# The pack-objects call on the next line is equivalent to
|
||||
# git repack -A -d without the call to prune-packed
|
||||
git pack-objects --honor-pack-keep --non-empty --all --reflog \
|
||||
--unpack-unreachable </dev/null pack &&
|
||||
rm -f .git/objects/pack/* &&
|
||||
mv pack-* .git/objects/pack/ &&
|
||||
test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
|
||||
egrep "^$csha1 " | sort | uniq | wc -l) &&
|
||||
echo > .git/objects/info/alternates &&
|
||||
test_must_fail git show $csha1
|
||||
'
|
||||
|
||||
test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '
|
||||
echo `pwd`/alt_objects > .git/objects/info/alternates &&
|
||||
echo "$csha1" | git pack-objects --non-empty --all --reflog pack &&
|
||||
rm -f .git/objects/pack/* &&
|
||||
mv pack-* .git/objects/pack/ &&
|
||||
# The pack-objects call on the next line is equivalent to
|
||||
# git repack -A -d without the call to prune-packed
|
||||
git pack-objects --honor-pack-keep --non-empty --all --reflog \
|
||||
--unpack-unreachable </dev/null pack &&
|
||||
rm -f .git/objects/pack/* &&
|
||||
mv pack-* .git/objects/pack/ &&
|
||||
test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
|
||||
egrep "^$csha1 " | sort | uniq | wc -l) &&
|
||||
echo > .git/objects/info/alternates &&
|
||||
test_must_fail git show $csha1
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
|
|
|
@ -421,8 +421,8 @@ test_confirm () {
|
|||
--from="Example <nobody@example.com>" \
|
||||
--to=nobody@example.com \
|
||||
--smtp-server="$(pwd)/fake.sendmail" \
|
||||
$@ \
|
||||
$patches | grep "Send this email"
|
||||
$@ $patches > stdout &&
|
||||
grep "Send this email" stdout
|
||||
}
|
||||
|
||||
test_expect_success '--confirm=always' '
|
||||
|
@ -444,8 +444,10 @@ test_expect_success '--confirm=compose' '
|
|||
test_expect_success 'confirm by default (due to cc)' '
|
||||
CONFIRM=$(git config --get sendemail.confirm) &&
|
||||
git config --unset sendemail.confirm &&
|
||||
test_confirm &&
|
||||
git config sendemail.confirm $CONFIRM
|
||||
test_confirm
|
||||
ret="$?"
|
||||
git config sendemail.confirm ${CONFIRM:-never}
|
||||
test $ret = "0"
|
||||
'
|
||||
|
||||
test_expect_success 'confirm by default (due to --compose)' '
|
||||
|
@ -457,6 +459,65 @@ test_expect_success 'confirm by default (due to --compose)' '
|
|||
test $ret = "0"
|
||||
'
|
||||
|
||||
test_expect_success 'confirm detects EOF (inform assumes y)' '
|
||||
CONFIRM=$(git config --get sendemail.confirm) &&
|
||||
git config --unset sendemail.confirm &&
|
||||
rm -fr outdir &&
|
||||
git format-patch -2 -o outdir &&
|
||||
GIT_SEND_EMAIL_NOTTY=1 \
|
||||
git send-email \
|
||||
--from="Example <nobody@example.com>" \
|
||||
--to=nobody@example.com \
|
||||
--smtp-server="$(pwd)/fake.sendmail" \
|
||||
outdir/*.patch < /dev/null
|
||||
ret="$?"
|
||||
git config sendemail.confirm ${CONFIRM:-never}
|
||||
test $ret = "0"
|
||||
'
|
||||
|
||||
test_expect_success 'confirm detects EOF (auto causes failure)' '
|
||||
CONFIRM=$(git config --get sendemail.confirm) &&
|
||||
git config sendemail.confirm auto &&
|
||||
GIT_SEND_EMAIL_NOTTY=1 &&
|
||||
export GIT_SEND_EMAIL_NOTTY &&
|
||||
test_must_fail git send-email \
|
||||
--from="Example <nobody@example.com>" \
|
||||
--to=nobody@example.com \
|
||||
--smtp-server="$(pwd)/fake.sendmail" \
|
||||
$patches < /dev/null
|
||||
ret="$?"
|
||||
git config sendemail.confirm ${CONFIRM:-never}
|
||||
test $ret = "0"
|
||||
'
|
||||
|
||||
test_expect_success 'confirm doesnt loop forever' '
|
||||
CONFIRM=$(git config --get sendemail.confirm) &&
|
||||
git config sendemail.confirm auto &&
|
||||
GIT_SEND_EMAIL_NOTTY=1 &&
|
||||
export GIT_SEND_EMAIL_NOTTY &&
|
||||
yes "bogus" | test_must_fail git send-email \
|
||||
--from="Example <nobody@example.com>" \
|
||||
--to=nobody@example.com \
|
||||
--smtp-server="$(pwd)/fake.sendmail" \
|
||||
$patches
|
||||
ret="$?"
|
||||
git config sendemail.confirm ${CONFIRM:-never}
|
||||
test $ret = "0"
|
||||
'
|
||||
|
||||
test_expect_success 'utf8 Cc is rfc2047 encoded' '
|
||||
clean_fake_sendmail &&
|
||||
rm -fr outdir &&
|
||||
git format-patch -1 -o outdir --cc="àéìöú <utf8@example.com>" &&
|
||||
git send-email \
|
||||
--from="Example <nobody@example.com>" \
|
||||
--to=nobody@example.com \
|
||||
--smtp-server="$(pwd)/fake.sendmail" \
|
||||
outdir/*.patch &&
|
||||
grep "^Cc:" msgtxt1 |
|
||||
grep "=?utf-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
|
||||
'
|
||||
|
||||
test_expect_success '--compose adds MIME for utf8 body' '
|
||||
clean_fake_sendmail &&
|
||||
(echo "#!$SHELL_PATH" &&
|
||||
|
|
|
@ -8,6 +8,9 @@ test_description='git fast-export'
|
|||
|
||||
test_expect_success 'setup' '
|
||||
|
||||
echo break it > file0 &&
|
||||
git add file0 &&
|
||||
test_tick &&
|
||||
echo Wohlauf > file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
|
@ -57,8 +60,8 @@ test_expect_success 'fast-export master~2..master' '
|
|||
(cd new &&
|
||||
git fast-import &&
|
||||
test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
|
||||
git diff master..partial &&
|
||||
git diff master^..partial^ &&
|
||||
git diff --exit-code master partial &&
|
||||
git diff --exit-code master^ partial^ &&
|
||||
test_must_fail git rev-parse partial~2)
|
||||
|
||||
'
|
||||
|
@ -259,4 +262,19 @@ test_expect_success 'cope with tagger-less tags' '
|
|||
|
||||
'
|
||||
|
||||
test_expect_success 'set-up a few more tags for tag export tests' '
|
||||
git checkout -f master &&
|
||||
HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` &&
|
||||
git tag tree_tag -m "tagging a tree" $HEAD_TREE &&
|
||||
git tag -a tree_tag-obj -m "tagging a tree" $HEAD_TREE &&
|
||||
git tag tag-obj_tag -m "tagging a tag" tree_tag-obj &&
|
||||
git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj
|
||||
'
|
||||
|
||||
# NEEDSWORK: not just check return status, but validate the output
|
||||
test_expect_success 'tree_tag' 'git fast-export tree_tag'
|
||||
test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj'
|
||||
test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag'
|
||||
test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
|
||||
|
||||
test_done
|
||||
|
|
|
@ -523,14 +523,6 @@ test_done () {
|
|||
fi
|
||||
case "$test_failure" in
|
||||
0)
|
||||
# We could:
|
||||
# cd .. && rm -fr 'trash directory'
|
||||
# but that means we forbid any tests that use their own
|
||||
# subdirectory from calling test_done without coming back
|
||||
# to where they started from.
|
||||
# The Makefile provided will clean this test area so
|
||||
# we will leave things as they are.
|
||||
|
||||
say_color pass "passed all $msg"
|
||||
|
||||
test -d "$remove_trash" &&
|
||||
|
@ -697,10 +689,12 @@ case $(uname -s) in
|
|||
}
|
||||
# no POSIX permissions
|
||||
# backslashes in pathspec are converted to '/'
|
||||
# exec does not inherit the PID
|
||||
;;
|
||||
*)
|
||||
test_set_prereq POSIXPERM
|
||||
test_set_prereq BSLASHPSPEC
|
||||
test_set_prereq EXECKEEPSPID
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
281
transport.c
281
transport.c
|
@ -143,7 +143,7 @@ static const char *rsync_url(const char *url)
|
|||
return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_rsync(struct transport *transport)
|
||||
static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
|
||||
struct ref dummy, *tail = &dummy;
|
||||
|
@ -151,6 +151,9 @@ static struct ref *get_refs_via_rsync(struct transport *transport)
|
|||
const char *args[5];
|
||||
int temp_dir_len;
|
||||
|
||||
if (for_push)
|
||||
return NULL;
|
||||
|
||||
/* copy the refs to the temporary directory */
|
||||
|
||||
strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
|
||||
|
@ -429,7 +432,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
|
|||
return !!err;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_curl(struct transport *transport)
|
||||
static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
|
||||
{
|
||||
struct strbuf buffer = STRBUF_INIT;
|
||||
char *data, *start, *mid;
|
||||
|
@ -446,6 +449,9 @@ static struct ref *get_refs_via_curl(struct transport *transport)
|
|||
|
||||
struct walker *walker;
|
||||
|
||||
if (for_push)
|
||||
return NULL;
|
||||
|
||||
if (!transport->data)
|
||||
transport->data = get_http_walker(transport->url,
|
||||
transport->remote);
|
||||
|
@ -532,12 +538,15 @@ struct bundle_transport_data {
|
|||
struct bundle_header header;
|
||||
};
|
||||
|
||||
static struct ref *get_refs_from_bundle(struct transport *transport)
|
||||
static struct ref *get_refs_from_bundle(struct transport *transport, int for_push)
|
||||
{
|
||||
struct bundle_transport_data *data = transport->data;
|
||||
struct ref *result = NULL;
|
||||
int i;
|
||||
|
||||
if (for_push)
|
||||
return NULL;
|
||||
|
||||
if (data->fd > 0)
|
||||
close(data->fd);
|
||||
data->fd = read_bundle_header(transport->url, &data->header);
|
||||
|
@ -578,6 +587,7 @@ struct git_transport_data {
|
|||
int fd[2];
|
||||
const char *uploadpack;
|
||||
const char *receivepack;
|
||||
struct extra_have_objects extra_have;
|
||||
};
|
||||
|
||||
static int set_git_option(struct transport *connection,
|
||||
|
@ -609,20 +619,23 @@ static int set_git_option(struct transport *connection,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int connect_setup(struct transport *transport)
|
||||
static int connect_setup(struct transport *transport, int for_push, int verbose)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0);
|
||||
data->conn = git_connect(data->fd, transport->url,
|
||||
for_push ? data->receivepack : data->uploadpack,
|
||||
verbose ? CONNECT_VERBOSE : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_connect(struct transport *transport)
|
||||
static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
struct ref *refs;
|
||||
|
||||
connect_setup(transport);
|
||||
get_remote_heads(data->fd[0], &refs, 0, NULL, 0, NULL);
|
||||
connect_setup(transport, for_push, 0);
|
||||
get_remote_heads(data->fd[0], &refs, 0, NULL,
|
||||
for_push ? REF_NORMAL : 0, &data->extra_have);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
@ -654,7 +667,7 @@ static int fetch_refs_via_pack(struct transport *transport,
|
|||
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
|
||||
|
||||
if (!data->conn) {
|
||||
connect_setup(transport);
|
||||
connect_setup(transport, 0, 0);
|
||||
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
|
@ -677,20 +690,216 @@ static int fetch_refs_via_pack(struct transport *transport,
|
|||
return (refs ? 0 : -1);
|
||||
}
|
||||
|
||||
static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
|
||||
static int refs_pushed(struct ref *ref)
|
||||
{
|
||||
for (; ref; ref = ref->next) {
|
||||
switch(ref->status) {
|
||||
case REF_STATUS_NONE:
|
||||
case REF_STATUS_UPTODATE:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
|
||||
{
|
||||
struct refspec rs;
|
||||
|
||||
if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
|
||||
return;
|
||||
|
||||
rs.src = ref->name;
|
||||
rs.dst = NULL;
|
||||
|
||||
if (!remote_find_tracking(remote, &rs)) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
|
||||
if (ref->deletion) {
|
||||
delete_ref(rs.dst, NULL, 0);
|
||||
} else
|
||||
update_ref("update by push", rs.dst,
|
||||
ref->new_sha1, NULL, 0, 0);
|
||||
free(rs.dst);
|
||||
}
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
|
||||
if (from)
|
||||
fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to));
|
||||
else
|
||||
fputs(prettify_ref(to), stderr);
|
||||
if (msg) {
|
||||
fputs(" (", stderr);
|
||||
fputs(msg, stderr);
|
||||
fputc(')', stderr);
|
||||
}
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
static const char *status_abbrev(unsigned char sha1[20])
|
||||
{
|
||||
return find_unique_abbrev(sha1, DEFAULT_ABBREV);
|
||||
}
|
||||
|
||||
static void print_ok_ref_status(struct ref *ref)
|
||||
{
|
||||
if (ref->deletion)
|
||||
print_ref_status('-', "[deleted]", ref, NULL, NULL);
|
||||
else if (is_null_sha1(ref->old_sha1))
|
||||
print_ref_status('*',
|
||||
(!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
|
||||
"[new branch]"),
|
||||
ref, ref->peer_ref, NULL);
|
||||
else {
|
||||
char quickref[84];
|
||||
char type;
|
||||
const char *msg;
|
||||
|
||||
strcpy(quickref, status_abbrev(ref->old_sha1));
|
||||
if (ref->nonfastforward) {
|
||||
strcat(quickref, "...");
|
||||
type = '+';
|
||||
msg = "forced update";
|
||||
} else {
|
||||
strcat(quickref, "..");
|
||||
type = ' ';
|
||||
msg = NULL;
|
||||
}
|
||||
strcat(quickref, status_abbrev(ref->new_sha1));
|
||||
|
||||
print_ref_status(type, quickref, ref, ref->peer_ref, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static int print_one_push_status(struct ref *ref, const char *dest, int count)
|
||||
{
|
||||
if (!count)
|
||||
fprintf(stderr, "To %s\n", dest);
|
||||
|
||||
switch(ref->status) {
|
||||
case REF_STATUS_NONE:
|
||||
print_ref_status('X', "[no match]", ref, NULL, NULL);
|
||||
break;
|
||||
case REF_STATUS_REJECT_NODELETE:
|
||||
print_ref_status('!', "[rejected]", ref, NULL,
|
||||
"remote does not support deleting refs");
|
||||
break;
|
||||
case REF_STATUS_UPTODATE:
|
||||
print_ref_status('=', "[up to date]", ref,
|
||||
ref->peer_ref, NULL);
|
||||
break;
|
||||
case REF_STATUS_REJECT_NONFASTFORWARD:
|
||||
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
|
||||
"non-fast forward");
|
||||
break;
|
||||
case REF_STATUS_REMOTE_REJECT:
|
||||
print_ref_status('!', "[remote rejected]", ref,
|
||||
ref->deletion ? NULL : ref->peer_ref,
|
||||
ref->remote_status);
|
||||
break;
|
||||
case REF_STATUS_EXPECTING_REPORT:
|
||||
print_ref_status('!', "[remote failure]", ref,
|
||||
ref->deletion ? NULL : ref->peer_ref,
|
||||
"remote failed to report status");
|
||||
break;
|
||||
case REF_STATUS_OK:
|
||||
print_ok_ref_status(ref);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_push_status(const char *dest, struct ref *refs, int verbose)
|
||||
{
|
||||
struct ref *ref;
|
||||
int n = 0;
|
||||
|
||||
if (verbose) {
|
||||
for (ref = refs; ref; ref = ref->next)
|
||||
if (ref->status == REF_STATUS_UPTODATE)
|
||||
n += print_one_push_status(ref, dest, n);
|
||||
}
|
||||
|
||||
for (ref = refs; ref; ref = ref->next)
|
||||
if (ref->status == REF_STATUS_OK)
|
||||
n += print_one_push_status(ref, dest, n);
|
||||
|
||||
for (ref = refs; ref; ref = ref->next) {
|
||||
if (ref->status != REF_STATUS_NONE &&
|
||||
ref->status != REF_STATUS_UPTODATE &&
|
||||
ref->status != REF_STATUS_OK)
|
||||
n += print_one_push_status(ref, dest, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void verify_remote_names(int nr_heads, const char **heads)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_heads; i++) {
|
||||
const char *local = heads[i];
|
||||
const char *remote = strrchr(heads[i], ':');
|
||||
|
||||
if (*local == '+')
|
||||
local++;
|
||||
|
||||
/* A matching refspec is okay. */
|
||||
if (remote == local && remote[1] == '\0')
|
||||
continue;
|
||||
|
||||
remote = remote ? (remote + 1) : local;
|
||||
switch (check_ref_format(remote)) {
|
||||
case 0: /* ok */
|
||||
case CHECK_REF_FORMAT_ONELEVEL:
|
||||
/* ok but a single level -- that is fine for
|
||||
* a match pattern.
|
||||
*/
|
||||
case CHECK_REF_FORMAT_WILDCARD:
|
||||
/* ok but ends with a pattern-match character */
|
||||
continue;
|
||||
}
|
||||
die("remote part of refspec is not a valid name in %s",
|
||||
heads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
struct send_pack_args args;
|
||||
int ret;
|
||||
|
||||
if (!data->conn) {
|
||||
struct ref *tmp_refs;
|
||||
connect_setup(transport, 1, 0);
|
||||
|
||||
get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
args.receivepack = data->receivepack;
|
||||
args.send_all = !!(flags & TRANSPORT_PUSH_ALL);
|
||||
args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
|
||||
args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
|
||||
args.use_thin_pack = data->thin;
|
||||
args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
|
||||
args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
|
||||
|
||||
return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec);
|
||||
ret = send_pack(&args, data->fd, data->conn, remote_refs,
|
||||
&data->extra_have);
|
||||
|
||||
close(data->fd[1]);
|
||||
close(data->fd[0]);
|
||||
ret |= finish_connect(data->conn);
|
||||
data->conn = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int disconnect_git(struct transport *transport)
|
||||
|
@ -760,7 +969,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
|||
ret->set_option = set_git_option;
|
||||
ret->get_refs_list = get_refs_via_connect;
|
||||
ret->fetch = fetch_refs_via_pack;
|
||||
ret->push = git_transport_push;
|
||||
ret->push_refs = git_transport_push;
|
||||
ret->disconnect = disconnect_git;
|
||||
|
||||
data->thin = 1;
|
||||
|
@ -787,15 +996,53 @@ int transport_set_option(struct transport *transport,
|
|||
int transport_push(struct transport *transport,
|
||||
int refspec_nr, const char **refspec, int flags)
|
||||
{
|
||||
if (!transport->push)
|
||||
return 1;
|
||||
verify_remote_names(refspec_nr, refspec);
|
||||
|
||||
if (transport->push)
|
||||
return transport->push(transport, refspec_nr, refspec, flags);
|
||||
if (transport->push_refs) {
|
||||
struct ref *remote_refs =
|
||||
transport->get_refs_list(transport, 1);
|
||||
struct ref **remote_tail;
|
||||
struct ref *local_refs = get_local_heads();
|
||||
int match_flags = MATCH_REFS_NONE;
|
||||
int verbose = flags & TRANSPORT_PUSH_VERBOSE;
|
||||
int ret;
|
||||
|
||||
if (flags & TRANSPORT_PUSH_ALL)
|
||||
match_flags |= MATCH_REFS_ALL;
|
||||
if (flags & TRANSPORT_PUSH_MIRROR)
|
||||
match_flags |= MATCH_REFS_MIRROR;
|
||||
|
||||
remote_tail = &remote_refs;
|
||||
while (*remote_tail)
|
||||
remote_tail = &((*remote_tail)->next);
|
||||
if (match_refs(local_refs, remote_refs, &remote_tail,
|
||||
refspec_nr, refspec, match_flags)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = transport->push_refs(transport, remote_refs, flags);
|
||||
|
||||
print_push_status(transport->url, remote_refs, verbose);
|
||||
|
||||
if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
|
||||
struct ref *ref;
|
||||
for (ref = remote_refs; ref; ref = ref->next)
|
||||
update_tracking_ref(transport->remote, ref, verbose);
|
||||
}
|
||||
|
||||
if (!ret && !refs_pushed(remote_refs))
|
||||
fprintf(stderr, "Everything up-to-date\n");
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct ref *transport_get_remote_refs(struct transport *transport)
|
||||
{
|
||||
if (!transport->remote_refs)
|
||||
transport->remote_refs = transport->get_refs_list(transport);
|
||||
transport->remote_refs = transport->get_refs_list(transport, 0);
|
||||
return transport->remote_refs;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,9 @@ struct transport {
|
|||
int (*set_option)(struct transport *connection, const char *name,
|
||||
const char *value);
|
||||
|
||||
struct ref *(*get_refs_list)(struct transport *transport);
|
||||
struct ref *(*get_refs_list)(struct transport *transport, int for_push);
|
||||
int (*fetch)(struct transport *transport, int refs_nr, const struct ref **refs);
|
||||
int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
|
||||
int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
|
||||
|
||||
int (*disconnect)(struct transport *connection);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "unpack-trees.h"
|
||||
#include "progress.h"
|
||||
#include "refs.h"
|
||||
#include "attr.h"
|
||||
|
||||
/*
|
||||
* Error messages expected by scripts out of plumbing commands such as
|
||||
|
@ -86,6 +87,7 @@ static int check_updates(struct unpack_trees_options *o)
|
|||
cnt = 0;
|
||||
}
|
||||
|
||||
git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
|
||||
for (i = 0; i < index->cache_nr; i++) {
|
||||
struct cache_entry *ce = index->cache[i];
|
||||
|
||||
|
@ -110,6 +112,7 @@ static int check_updates(struct unpack_trees_options *o)
|
|||
}
|
||||
}
|
||||
stop_progress(&progress);
|
||||
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
|
||||
return errs != 0;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче