зеркало из 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=asciidoc
|
||||||
ASCIIDOC_EXTRA =
|
ASCIIDOC_EXTRA =
|
||||||
MANPAGE_XSL = callouts.xsl
|
MANPAGE_XSL = manpage-normal.xsl
|
||||||
|
XMLTO_EXTRA =
|
||||||
INSTALL?=install
|
INSTALL?=install
|
||||||
RM ?= rm -f
|
RM ?= rm -f
|
||||||
DOC_REF = origin/man
|
DOC_REF = origin/man
|
||||||
|
@ -59,12 +60,47 @@ endif
|
||||||
-include ../config.mak.autogen
|
-include ../config.mak.autogen
|
||||||
-include ../config.mak
|
-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
|
ifdef ASCIIDOC8
|
||||||
ASCIIDOC_EXTRA += -a asciidoc7compatible
|
ASCIIDOC_EXTRA += -a asciidoc7compatible
|
||||||
endif
|
endif
|
||||||
ifdef DOCBOOK_XSL_172
|
ifdef DOCBOOK_XSL_172
|
||||||
ASCIIDOC_EXTRA += -a docbook-xsl-172
|
ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
|
||||||
MANPAGE_XSL = manpage-1.72.xsl
|
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
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -76,6 +112,32 @@ endif
|
||||||
# yourself - yes, all 6 characters of it!
|
# 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
|
all: html man
|
||||||
|
|
||||||
html: $(DOC_HTML)
|
html: $(DOC_HTML)
|
||||||
|
@ -119,7 +181,7 @@ install-html: html
|
||||||
sh ./install-webdoc.sh $(DESTDIR)$(htmldir)
|
sh ./install-webdoc.sh $(DESTDIR)$(htmldir)
|
||||||
|
|
||||||
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
||||||
$(MAKE) -C ../ GIT-VERSION-FILE
|
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
|
||||||
|
|
||||||
-include ../GIT-VERSION-FILE
|
-include ../GIT-VERSION-FILE
|
||||||
|
|
||||||
|
@ -127,8 +189,8 @@ install-html: html
|
||||||
# Determine "include::" file references in asciidoc files.
|
# Determine "include::" file references in asciidoc files.
|
||||||
#
|
#
|
||||||
doc.dep : $(wildcard *.txt) build-docdep.perl
|
doc.dep : $(wildcard *.txt) build-docdep.perl
|
||||||
$(RM) $@+ $@
|
$(QUIET_GEN)$(RM) $@+ $@ && \
|
||||||
$(PERL_PATH) ./build-docdep.perl >$@+
|
$(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
-include doc.dep
|
-include doc.dep
|
||||||
|
@ -146,91 +208,94 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
|
||||||
$(cmds_txt): cmd-list.made
|
$(cmds_txt): cmd-list.made
|
||||||
|
|
||||||
cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
|
cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
|
||||||
$(RM) $@
|
$(QUIET_GEN)$(RM) $@ && \
|
||||||
$(PERL_PATH) ./cmd-list.perl ../command-list.txt
|
$(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
|
||||||
date >$@
|
date >$@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
|
$(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) howto-index.txt howto/*.html doc.dep
|
||||||
$(RM) technical/api-*.html technical/api-index.txt
|
$(RM) technical/api-*.html technical/api-index.txt
|
||||||
$(RM) $(cmds_txt) *.made
|
$(RM) $(cmds_txt) *.made
|
||||||
|
|
||||||
$(MAN_HTML): %.html : %.txt
|
$(MAN_HTML): %.html : %.txt
|
||||||
$(RM) $@+ $@
|
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||||
$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
|
$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
|
||||||
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
|
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
%.1 %.5 %.7 : %.xml
|
%.1 %.5 %.7 : %.xml
|
||||||
$(RM) $@
|
$(QUIET_XMLTO)$(RM) $@ && \
|
||||||
xmlto -m $(MANPAGE_XSL) man $<
|
xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
|
||||||
|
|
||||||
%.xml : %.txt
|
%.xml : %.txt
|
||||||
$(RM) $@+ $@
|
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||||
$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
|
$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
|
||||||
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
|
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
user-manual.xml: user-manual.txt user-manual.conf
|
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.txt: technical/api-index-skel.txt \
|
||||||
technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS))
|
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
|
$(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
|
$(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) $*.txt
|
||||||
|
|
||||||
XSLT = docbook.xsl
|
XSLT = docbook.xsl
|
||||||
XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
|
XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
|
||||||
|
|
||||||
user-manual.html: user-manual.xml
|
user-manual.html: user-manual.xml
|
||||||
xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
|
$(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
|
||||||
|
|
||||||
git.info: user-manual.texi
|
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
|
user-manual.texi: user-manual.xml
|
||||||
$(RM) $@+ $@
|
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
|
||||||
$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \
|
$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \
|
||||||
$(PERL_PATH) fix-texi.perl >$@+
|
$(PERL_PATH) fix-texi.perl <$@++ >$@+ && \
|
||||||
|
rm $@++ && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
user-manual.pdf: user-manual.xml
|
user-manual.pdf: user-manual.xml
|
||||||
$(RM) $@+ $@
|
$(QUIET_DBLATEX)$(RM) $@+ $@ && \
|
||||||
$(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $<
|
$(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
gitman.texi: $(MAN_XML) cat-texi.perl
|
gitman.texi: $(MAN_XML) cat-texi.perl
|
||||||
$(RM) $@+ $@
|
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
|
||||||
($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
|
($(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 $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
gitman.info: gitman.texi
|
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
|
$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
|
||||||
$(RM) $@+ $@
|
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
|
||||||
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+
|
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
|
howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
|
||||||
$(RM) $@+ $@
|
$(QUIET_GEN)$(RM) $@+ $@ && \
|
||||||
sh ./howto-index.sh $(wildcard howto/*.txt) >$@+
|
sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
|
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
|
||||||
$(ASCIIDOC) -b xhtml11 $*.txt
|
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 $*.txt
|
||||||
|
|
||||||
WEBDOC_DEST = /pub/software/scm/git/docs
|
WEBDOC_DEST = /pub/software/scm/git/docs
|
||||||
|
|
||||||
$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
|
$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
|
||||||
$(RM) $@+ $@
|
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||||
sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+
|
sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \
|
||||||
mv $@+ $@
|
mv $@+ $@
|
||||||
|
|
||||||
install-webdoc : html
|
install-webdoc : html
|
||||||
|
|
|
@ -7,9 +7,15 @@ Fixes since v1.6.2.1
|
||||||
* A longstanding confusing description of what --pickaxe option of
|
* A longstanding confusing description of what --pickaxe option of
|
||||||
git-diff does has been clarified in the documentation.
|
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
|
* "git diff --pickaxe-regexp" did not count overlapping matches
|
||||||
correctly.
|
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
|
* "git-fetch" in a repository that was not cloned from anywhere said
|
||||||
it cannot find 'origin', which was hard to understand for new people.
|
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
|
* 'git-submodule add' did not tolerate extra slashes and ./ in the path it
|
||||||
accepted from the command line; it now is more lenient.
|
accepted from the command line; it now is more lenient.
|
||||||
|
|
||||||
|
* git-svn misbehaved when the project contained a path that began with
|
||||||
|
two dashes.
|
||||||
|
|
||||||
---
|
* import-zips script (in contrib) did not compute the common directory
|
||||||
exec >/var/tmp/1
|
prefix correctly.
|
||||||
O=v1.6.2.1-23-g67c176f
|
|
||||||
echo O=$(git describe maint)
|
* miscompilation of negated enum constants by old gcc (2.9) affected the
|
||||||
git shortlog --no-merges $O..maint
|
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
|
should happen upon such a push by setting the configuration variable
|
||||||
receive.denyDeleteCurrent in the receiving repository.
|
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
|
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
|
repositories. It may not be useful in practice; meant primarily for
|
||||||
testing.
|
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
|
* (msysgit) progress output that is sent over the sideband protocol can
|
||||||
be handled appropriately in Windows console.
|
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
|
with the 'edit' action in git-add -i/-p, you can abort the editor to
|
||||||
tell git not to apply it.
|
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-archive learned --output=<file> option.
|
||||||
|
|
||||||
* git-bisect shows not just the number of remaining commits whose goodness
|
* 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-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,
|
* git-format-patch can be told to use attachment with a new configuration,
|
||||||
format.attach.
|
format.attach.
|
||||||
|
|
||||||
* git-format-patch can be told to produce deep or shallow message threads.
|
* 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-grep learned to highlight the found substrings in color.
|
||||||
|
|
||||||
* git-imap-send learned to work around Thunderbird's inability to easily
|
* 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.
|
* 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
|
* git-send-email learned --confirm option to review the Cc: list before
|
||||||
sending the messages out.
|
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 under valgrind.
|
||||||
|
|
||||||
|
* Test scripts can be run with installed git.
|
||||||
|
|
||||||
* Makefile learned 'coverage' option to run the test suites with
|
* Makefile learned 'coverage' option to run the test suites with
|
||||||
coverage tracking enabled.
|
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
|
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
|
Here are fixes that this release has, but have not been backported to
|
||||||
v1.6.2.X series.
|
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
|
* git-gc spent excessive amount of time to decide if an object appears
|
||||||
in a locally existing pack (if needed, backport by merging 69e020a).
|
in a locally existing pack (if needed, backport by merging 69e020a).
|
||||||
|
|
||||||
---
|
---
|
||||||
exec >/var/tmp/1
|
exec >/var/tmp/1
|
||||||
O=v1.6.2.1-213-g7d4e3a7
|
O=v1.6.2.2-403-g8130949
|
||||||
echo O=$(git describe master)
|
echo O=$(git describe master)
|
||||||
git shortlog --no-merges $O..master ^maint
|
git shortlog --no-merges $O..master ^maint
|
||||||
|
|
|
@ -27,7 +27,7 @@ ifdef::backend-docbook[]
|
||||||
endif::backend-docbook[]
|
endif::backend-docbook[]
|
||||||
|
|
||||||
ifdef::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.
|
# "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.
|
# v1.72 breaks with this because it replaces dots not in roff requests.
|
||||||
[listingblock]
|
[listingblock]
|
||||||
|
@ -42,16 +42,16 @@ ifdef::doctype-manpage[]
|
||||||
endif::doctype-manpage[]
|
endif::doctype-manpage[]
|
||||||
</literallayout>
|
</literallayout>
|
||||||
{title#}</example>
|
{title#}</example>
|
||||||
endif::docbook-xsl-172[]
|
endif::git-asciidoc-no-roff[]
|
||||||
|
|
||||||
ifdef::docbook-xsl-172[]
|
ifdef::git-asciidoc-no-roff[]
|
||||||
ifdef::doctype-manpage[]
|
ifdef::doctype-manpage[]
|
||||||
# The following two small workarounds insert a simple paragraph after screen
|
# The following two small workarounds insert a simple paragraph after screen
|
||||||
[listingblock]
|
[listingblock]
|
||||||
<example><title>{title}</title>
|
<example><title>{title}</title>
|
||||||
<screen>
|
<literallayout>
|
||||||
|
|
|
|
||||||
</screen><simpara></simpara>
|
</literallayout><simpara></simpara>
|
||||||
{title#}</example>
|
{title#}</example>
|
||||||
|
|
||||||
[verseblock]
|
[verseblock]
|
||||||
|
@ -59,10 +59,11 @@ ifdef::doctype-manpage[]
|
||||||
{title%}<literallayout{id? id="{id}"}>
|
{title%}<literallayout{id? id="{id}"}>
|
||||||
{title#}<literallayout>
|
{title#}<literallayout>
|
||||||
|
|
|
|
||||||
</literallayout><simpara></simpara>
|
</literallayout>
|
||||||
{title#}</para></formalpara>
|
{title#}</para></formalpara>
|
||||||
|
{title%}<simpara></simpara>
|
||||||
endif::doctype-manpage[]
|
endif::doctype-manpage[]
|
||||||
endif::docbook-xsl-172[]
|
endif::git-asciidoc-no-roff[]
|
||||||
endif::backend-docbook[]
|
endif::backend-docbook[]
|
||||||
|
|
||||||
ifdef::doctype-manpage[]
|
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.
|
This option defaults to never.
|
||||||
|
|
||||||
branch.<name>.remote::
|
branch.<name>.remote::
|
||||||
When in branch <name>, it tells 'git-fetch' which remote to fetch.
|
When in branch <name>, it tells 'git-fetch' and 'git-push' which
|
||||||
If this option is not given, 'git-fetch' defaults to remote "origin".
|
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::
|
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
|
When in branch <name>, it tells 'git-fetch' the default
|
||||||
refspec to be marked for merging in FETCH_HEAD. The value is
|
refspec to be marked for merging in FETCH_HEAD. The value is
|
||||||
handled like the remote part of a refspec, and must match a
|
handled like the remote part of a refspec, and must match a
|
||||||
|
@ -1194,6 +1198,19 @@ pull.octopus::
|
||||||
pull.twohead::
|
pull.twohead::
|
||||||
The default merge strategy to use when pulling a single branch.
|
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::
|
rebase.stat::
|
||||||
Whether to show a diffstat of what changed upstream since the last
|
Whether to show a diffstat of what changed upstream since the last
|
||||||
rebase. False by default.
|
rebase. False by default.
|
||||||
|
|
|
@ -81,7 +81,7 @@ will have been left with the first bad kernel revision in "refs/bisect/bad".
|
||||||
Bisect reset
|
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:
|
following command:
|
||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
@ -95,8 +95,8 @@ the bisection state).
|
||||||
Bisect visualize
|
Bisect visualize
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
To see the currently remaining suspects in 'gitk', the following command
|
To see the currently remaining suspects in 'gitk', issue the following
|
||||||
is issued during the bisection process:
|
command during the bisection process:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
$ git bisect visualize
|
$ git bisect visualize
|
||||||
|
@ -115,7 +115,7 @@ $ git bisect view --stat
|
||||||
Bisect log and bisect replay
|
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:
|
command to show what has been done so far:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
|
@ -135,7 +135,7 @@ $ git bisect replay that-file
|
||||||
Avoiding testing a commit
|
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
|
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
|
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
|
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
|
# was suggested
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Then compile and test the chosen revision. Afterwards the revision
|
Then compile and test the chosen revision, and afterwards mark
|
||||||
is marked as good or bad in the usual manner.
|
the revision as good or bad in the usual manner.
|
||||||
|
|
||||||
Bisect skip
|
Bisect skip
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
@ -175,8 +175,8 @@ using the "'<commit1>'..'<commit2>'" notation. For example:
|
||||||
$ git bisect skip v2.5..v2.6
|
$ git bisect skip v2.5..v2.6
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The effect of this would be that no commit between `v2.5` excluded and
|
This tells the bisect process that no commit after `v2.5`, up to and
|
||||||
`v2.6` included could be tested.
|
including `v2.6`, should be tested.
|
||||||
|
|
||||||
Note that if you also want to skip the first commit of the range you
|
Note that if you also want to skip the first commit of the range you
|
||||||
would issue the command:
|
would issue the command:
|
||||||
|
@ -185,8 +185,8 @@ would issue the command:
|
||||||
$ git bisect skip v2.5 v2.5..v2.6
|
$ git bisect skip v2.5 v2.5..v2.6
|
||||||
------------
|
------------
|
||||||
|
|
||||||
This would cause the commits between `v2.5` included and `v2.6` included
|
This tells the bisect process that the commits between `v2.5` included
|
||||||
to be skipped.
|
and `v2.6` included should be skipped.
|
||||||
|
|
||||||
|
|
||||||
Cutting down bisection by giving more parameters to bisect start
|
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
|
Some workflows require that one or more branches of development on one
|
||||||
machine be replicated on another machine, but the two machines cannot
|
machine be replicated on another machine, but the two machines cannot
|
||||||
be directly connected so the interactive git protocols (git, ssh,
|
be directly connected, and therefore the interactive git protocols (git,
|
||||||
rsync, http) cannot be used. This command provides support for
|
ssh, rsync, http) cannot be used. This command provides support for
|
||||||
'git-fetch' and 'git-pull' to operate by packaging objects and references
|
'git-fetch' and 'git-pull' to operate by packaging objects and references
|
||||||
in an archive at the originating machine, then importing those into
|
in an archive at the originating machine, then importing those into
|
||||||
another repository using 'git-fetch' and 'git-pull'
|
another repository using 'git-fetch' and 'git-pull'
|
||||||
after moving the archive by some means (i.e., by sneakernet). As no
|
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
|
basis for the bundle that is held by the destination repository: the
|
||||||
bundle assumes that all objects in the basis are already in the
|
bundle assumes that all objects in the basis are already in the
|
||||||
destination repository.
|
destination repository.
|
||||||
|
@ -43,7 +43,7 @@ verify <file>::
|
||||||
bundle format itself as well as checking that the prerequisite
|
bundle format itself as well as checking that the prerequisite
|
||||||
commits exist and are fully linked in the current repository.
|
commits exist and are fully linked in the current repository.
|
||||||
'git-bundle' prints a list of missing commits, if any, and exits
|
'git-bundle' prints a list of missing commits, if any, and exits
|
||||||
with non-zero status.
|
with a non-zero status.
|
||||||
|
|
||||||
list-heads <file>::
|
list-heads <file>::
|
||||||
Lists the references defined in the bundle. If followed by a
|
Lists the references defined in the bundle. If followed by a
|
||||||
|
@ -53,14 +53,14 @@ list-heads <file>::
|
||||||
unbundle <file>::
|
unbundle <file>::
|
||||||
Passes the objects in the bundle to 'git-index-pack'
|
Passes the objects in the bundle to 'git-index-pack'
|
||||||
for storage in the repository, then prints the names of all
|
for storage in the repository, then prints the names of all
|
||||||
defined references. If a reflist is given, only references
|
defined references. If a list of references is given, only
|
||||||
matching those in the given list are printed. This command is
|
references matching those in the list are printed. This command is
|
||||||
really plumbing, intended to be called only by 'git-fetch'.
|
really plumbing, intended to be called only by 'git-fetch'.
|
||||||
|
|
||||||
[git-rev-list-args...]::
|
[git-rev-list-args...]::
|
||||||
A list of arguments, acceptable to 'git-rev-parse' and
|
A list of arguments, acceptable to 'git-rev-parse' and
|
||||||
'git-rev-list', that specify the specific objects and references
|
'git-rev-list', that specifies the specific objects and references
|
||||||
to transport. For example, "master~10..master" causes the
|
to transport. For example, `master\~10..master` causes the
|
||||||
current master reference to be packaged along with all objects
|
current master reference to be packaged along with all objects
|
||||||
added since its 10th ancestor commit. There is no explicit
|
added since its 10th ancestor commit. There is no explicit
|
||||||
limit to the number of references and objects that may be
|
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
|
A list of references used to limit the references reported as
|
||||||
available. This is principally of use to 'git-fetch', which
|
available. This is principally of use to 'git-fetch', which
|
||||||
expects to receive only those references asked for and not
|
expects to receive only those references asked for and not
|
||||||
necessarily everything in the pack (in this case, 'git-bundle' is
|
necessarily everything in the pack (in this case, 'git-bundle' acts
|
||||||
acting like 'git-fetch-pack').
|
like 'git-fetch-pack').
|
||||||
|
|
||||||
SPECIFYING REFERENCES
|
SPECIFYING REFERENCES
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
'git-bundle' will only package references that are shown by
|
'git-bundle' will only package references that are shown by
|
||||||
'git-show-ref': this includes heads, tags, and remote heads. References
|
'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
|
defining the basis. More than one reference may be packaged, and more
|
||||||
than one basis can be specified. The objects packaged are those not
|
than one basis can be specified. The objects packaged are those not
|
||||||
contained in the union of the given bases. Each basis can be
|
contained in the union of the given bases. Each basis can be
|
||||||
specified explicitly (e.g., ^master~10), or implicitly (e.g.,
|
specified explicitly (e.g. `^master\~10`), or implicitly (e.g.
|
||||||
master~10..master, --since=10.days.ago master).
|
`master\~10..master`, `--since=10.days.ago master`).
|
||||||
|
|
||||||
It is very important that the basis used be held by the destination.
|
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
|
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
|
to contain objects already in the destination, as these are ignored
|
||||||
when unpacking at the destination.
|
when unpacking at the destination.
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
|
@ -97,13 +97,13 @@ EXAMPLE
|
||||||
Assume you want to transfer the history from a repository R1 on machine A
|
Assume you want to transfer the history from a repository R1 on machine A
|
||||||
to another repository R2 on machine B.
|
to another repository R2 on machine B.
|
||||||
For whatever reason, direct connection between A and B is not allowed,
|
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).
|
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.
|
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
|
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 sent out
|
any basis. You can use a tag to remember up to what commit you last
|
||||||
in order to make it easy to later update the other repository with
|
processed, in order to make it easy to later update the other repository
|
||||||
incremental bundle,
|
with an incremental bundle:
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
machineA$ cd R1
|
machineA$ cd R1
|
||||||
|
@ -111,17 +111,17 @@ machineA$ git bundle create file.bundle master
|
||||||
machineA$ git tag -f lastR2bundle master
|
machineA$ git tag -f lastR2bundle master
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Then you sneakernet file.bundle to the target machine B. Because you don't
|
Then you transfer file.bundle to the target machine B. If you are creating
|
||||||
have to have any object to extract objects from such a bundle, not only
|
the repository on machine B, then you can clone from the bundle as if it
|
||||||
you can fetch/pull from a bundle, you can clone from it as if it was a
|
were a remote repository instead of creating an empty repository and then
|
||||||
remote repository.
|
pulling or fetching objects from the bundle:
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
machineB$ git clone /home/me/tmp/file.bundle R2
|
machineB$ git clone /home/me/tmp/file.bundle R2
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
This will define a remote called "origin" in the resulting repository that
|
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:
|
have an entry like this:
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
|
@ -130,12 +130,12 @@ have an entry like this:
|
||||||
fetch = refs/heads/*:refs/remotes/origin/*
|
fetch = refs/heads/*:refs/remotes/origin/*
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
You can fetch/pull to update the resulting mine.git repository after
|
To update the resulting mine.git repository, you can fetch or pull after
|
||||||
replacing the bundle you store at /home/me/tmp/file.bundle with incremental
|
replacing the bundle stored at /home/me/tmp/file.bundle with incremental
|
||||||
updates from here on.
|
updates.
|
||||||
|
|
||||||
After working more in the original repository, you can create an
|
After working some more in the original repository, you can create an
|
||||||
incremental bundle to update the other:
|
incremental bundle to update the other repository:
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
machineA$ cd R1
|
machineA$ cd R1
|
||||||
|
@ -143,8 +143,8 @@ machineA$ git bundle create file.bundle lastR2bundle..master
|
||||||
machineA$ git tag -f lastR2bundle master
|
machineA$ git tag -f lastR2bundle master
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
and sneakernet it to the other machine to replace /home/me/tmp/file.bundle,
|
You then transfer the bundle to the other machine to replace
|
||||||
and pull from it.
|
/home/me/tmp/file.bundle, and pull from it.
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
machineB$ cd R2
|
machineB$ cd R2
|
||||||
|
@ -152,49 +152,49 @@ machineB$ git pull
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
If you know up to what commit the intended recipient repository should
|
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
|
basis, giving a cut-off point to limit the revisions and objects that go
|
||||||
in the resulting bundle. The previous example used lastR2bundle tag
|
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:
|
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
|
$ 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
|
$ 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
|
$ git bundle create mybundle -10 master
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
You can run `git-bundle verify` to see if you can extract from a bundle
|
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
|
$ git bundle verify mybundle
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
This will list what commits you must have in order to extract from the
|
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
|
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
|
regular repository which it fetches or pulls from. You can, for example, map
|
||||||
refs, like this example, when fetching:
|
references when fetching:
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
$ git fetch mybundle master:localRef
|
$ git fetch mybundle master:localRef
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Or see what refs it offers.
|
You can also see what references it offers.
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
$ git ls-remote mybundle
|
$ git ls-remote mybundle
|
||||||
|
|
|
@ -3,7 +3,7 @@ git-cat-file(1)
|
||||||
|
|
||||||
NAME
|
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
|
SYNOPSIS
|
||||||
|
@ -14,19 +14,19 @@ SYNOPSIS
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
In the first form, provides content or type of objects in the repository. The
|
In its first form, the command provides the content or the type of an object in
|
||||||
type is required unless '-t' or '-p' is used to find the object type, or '-s'
|
the repository. The type is required unless '-t' or '-p' is used to find the
|
||||||
is used to find the object size.
|
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,
|
In the second form, a list of objects (separated by linefeeds) is provided on
|
||||||
and the SHA1, type, and size of each object is printed on stdout.
|
stdin, and the SHA1, type, and size of each object is printed on stdout.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
<object>::
|
<object>::
|
||||||
The name of the object to show.
|
The name of the object to show.
|
||||||
For a more complete list of ways to spell object names, see
|
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::
|
-t::
|
||||||
Instead of the content, show the object type identified by
|
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.
|
stdin. May not be combined with any other options or arguments.
|
||||||
|
|
||||||
--batch-check::
|
--batch-check::
|
||||||
Print the SHA1, type, and size of each object provided on stdin. May not be
|
Print the SHA1, type, and size of each object provided on stdin. May not
|
||||||
combined with any other options or arguments.
|
be combined with any other options or arguments.
|
||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
------
|
------
|
||||||
|
|
|
@ -14,7 +14,7 @@ SYNOPSIS
|
||||||
|
|
||||||
DESCRIPTION
|
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.
|
'set', or 'unset' as a gitattribute on that pathname.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
|
@ -23,11 +23,11 @@ OPTIONS
|
||||||
Read file names from stdin instead of from the command-line.
|
Read file names from stdin instead of from the command-line.
|
||||||
|
|
||||||
-z::
|
-z::
|
||||||
Only meaningful with `--stdin`; paths are separated with
|
Only meaningful with `--stdin`; paths are separated with a
|
||||||
NUL character instead of LF.
|
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
|
arguments as path names. If not supplied, only the first argument will
|
||||||
be treated as an attribute.
|
be treated as an attribute.
|
||||||
|
|
||||||
|
@ -37,12 +37,12 @@ OUTPUT
|
||||||
The output is of the form:
|
The output is of the form:
|
||||||
<path> COLON SP <attribute> COLON SP <info> LF
|
<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:
|
being queried and <info> can be either:
|
||||||
|
|
||||||
'unspecified';; when the attribute is not defined for the path.
|
'unspecified';; when the attribute is not defined for the path.
|
||||||
'unset';; when the attribute is defined to false.
|
'unset';; when the attribute is defined as false.
|
||||||
'set';; when the attribute is defined to true.
|
'set';; when the attribute is defined as true.
|
||||||
<value>;; when a value has been assigned to the attribute.
|
<value>;; when a value has been assigned to the attribute.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
|
@ -69,7 +69,7 @@ org/example/MyClass.java: diff: java
|
||||||
org/example/MyClass.java: myAttr: set
|
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
|
$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
|
||||||
org/example/MyClass.java: myAttr: set
|
org/example/MyClass.java: myAttr: set
|
||||||
|
|
|
@ -3,7 +3,7 @@ git-check-ref-format(1)
|
||||||
|
|
||||||
NAME
|
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
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
|
@ -11,40 +11,40 @@ SYNOPSIS
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Checks if a given 'refname' is acceptable, and exits non-zero if
|
Checks if a given 'refname' is acceptable, and exits with a non-zero
|
||||||
it is not.
|
status if it is not.
|
||||||
|
|
||||||
A reference is used in git to specify branches and tags. A
|
A reference is used in git to specify branches and tags. A
|
||||||
branch head is stored under `$GIT_DIR/refs/heads` directory, and
|
branch head is stored under the `$GIT_DIR/refs/heads` directory, and
|
||||||
a tag is stored under `$GIT_DIR/refs/tags` directory. git
|
a tag is stored under the `$GIT_DIR/refs/tags` directory. git
|
||||||
imposes the following rules on how refs are named:
|
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
|
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 `~`,
|
values are lower than \040, or \177 `DEL`), space, tilde `~`,
|
||||||
caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
|
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
|
These rules make it easy for shell script based tools to parse
|
||||||
refnames, pathname expansion by the shell when a refname is used
|
reference names, pathname expansion by the shell when a reference name is used
|
||||||
unquoted (by mistake), and also avoids ambiguities in certain
|
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
|
. A double-dot `..` is often used as in `ref1..ref2`, and in some
|
||||||
context this notation means `{caret}ref1 ref2` (i.e. not in
|
contexts this notation means `{caret}ref1 ref2` (i.e. not in
|
||||||
ref1 and in ref2).
|
`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.
|
'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.
|
value and store it in dstref" in fetch and push operations.
|
||||||
It may also be used to select a specific object such as with
|
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".
|
'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>::
|
--origin <name>::
|
||||||
-o <name>::
|
-o <name>::
|
||||||
Instead of using the remote name 'origin' to keep track
|
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>::
|
--upload-pack <upload-pack>::
|
||||||
-u <upload-pack>::
|
-u <upload-pack>::
|
||||||
|
|
|
@ -65,7 +65,7 @@ OPTIONS
|
||||||
-r <remote>::
|
-r <remote>::
|
||||||
The git remote to import this CVS repository into.
|
The git remote to import this CVS repository into.
|
||||||
Moves all CVS branches into remotes/<remote>/<branch>
|
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>::
|
-o <branch-for-HEAD>::
|
||||||
When no remote is specified (via -r) the 'HEAD' branch
|
When no remote is specified (via -r) the 'HEAD' branch
|
||||||
|
@ -173,24 +173,26 @@ ISSUES
|
||||||
Problems related to timestamps:
|
Problems related to timestamps:
|
||||||
|
|
||||||
* If timestamps of commits in the cvs repository are not stable enough
|
* 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
|
* 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
|
* 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:
|
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
|
* All files from the branching point are added to a branch even if
|
||||||
never added in cvs
|
never added in cvs.
|
||||||
* files added to the source branch *after* a daughter branch was
|
* This applies to files added to the source branch *after* a daughter
|
||||||
created: If previously no commit was made on the daugther branch they
|
branch was created: if previously no commit was made on the daughter
|
||||||
will erroneously be added to the daughter branch in git
|
branch they will erroneously be added to the daughter branch in git.
|
||||||
|
|
||||||
Problems related to tags:
|
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
|
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
|
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
|
REVISIONS" section in linkgit:git-rev-parse[1]) means the
|
||||||
commits in the specified range.
|
commits in the specified range.
|
||||||
|
|
||||||
A single commit, when interpreted as a <revision range>
|
The first rule takes precedence in the case of a single <commit>. To
|
||||||
expression, means "everything that leads to that commit", but
|
apply the second rule, i.e., format everything since the beginning of
|
||||||
if you write 'git format-patch <commit>', the previous rule
|
history up until <commit>, use the '\--root' option: "git format-patch
|
||||||
applies to that command line and you do not get "everything
|
\--root <commit>". If you want to format only <commit> itself, you
|
||||||
since the beginning of the time". If you want to format
|
can do this with "git format-patch -1 <commit>".
|
||||||
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>".
|
|
||||||
|
|
||||||
By default, each output file is numbered sequentially from 1, and uses the
|
By default, each output file is numbered sequentially from 1, and uses the
|
||||||
first line of the commit message (massaged for pathname safety) as
|
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
|
Add a "Cc:" header to the email headers. This is in addition
|
||||||
to any configured headers, and may be used multiple times.
|
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::
|
--cover-letter::
|
||||||
In addition to the patches, generate a cover letter file
|
In addition to the patches, generate a cover letter file
|
||||||
containing the shortlog and the overall diffstat. You can
|
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
|
applied. By default the contents of changes in those files are
|
||||||
encoded in the patch.
|
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
|
CONFIGURATION
|
||||||
-------------
|
-------------
|
||||||
You can specify extra mail header lines to be added to each message
|
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[]
|
include::merge-strategies.txt[]
|
||||||
|
|
||||||
|
|
||||||
If you tried a merge which resulted in a complex conflicts and
|
If you tried a merge which resulted in complex conflicts and
|
||||||
would want to start over, you can recover with 'git-reset'.
|
want to start over, you can recover with 'git-reset'.
|
||||||
|
|
||||||
CONFIGURATION
|
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
|
When dealing with 'git-diff-tree' output, it takes advantage of
|
||||||
the fact that the patch is prefixed with the object name of the
|
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.
|
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.
|
This can be used to make a mapping from patch ID to commit ID.
|
||||||
|
|
||||||
|
|
|
@ -385,7 +385,8 @@ config key: svn.authorsfile
|
||||||
|
|
||||||
-q::
|
-q::
|
||||||
--quiet::
|
--quiet::
|
||||||
Make 'git-svn' less verbose.
|
Make 'git-svn' less verbose. Specify a second time to make it
|
||||||
|
even less verbose.
|
||||||
|
|
||||||
--repack[=<n>]::
|
--repack[=<n>]::
|
||||||
--repack-flags=<flags>::
|
--repack-flags=<flags>::
|
||||||
|
@ -672,9 +673,9 @@ listed below are allowed:
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
[svn-remote "project-a"]
|
[svn-remote "project-a"]
|
||||||
url = http://server.org/svn
|
url = http://server.org/svn
|
||||||
|
fetch = trunk/project-a:refs/remotes/project-a/trunk
|
||||||
branches = branches/*/project-a:refs/remotes/project-a/branches/*
|
branches = branches/*/project-a:refs/remotes/project-a/branches/*
|
||||||
tags = tags/*/project-a:refs/remotes/project-a/tags/*
|
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
|
Keep in mind that the '*' (asterisk) wildcard of the local ref
|
||||||
|
|
|
@ -63,6 +63,7 @@ OPTIONS
|
||||||
are printed when using -l.
|
are printed when using -l.
|
||||||
The default is not to print any annotation lines.
|
The default is not to print any annotation lines.
|
||||||
If no number is given to `-n`, only the first line is printed.
|
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>::
|
-l <pattern>::
|
||||||
List tags with names that match the given pattern (or all if no pattern is given).
|
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).
|
flag=1) or a file checkout (retrieving a file from the index, flag=0).
|
||||||
This hook cannot affect the outcome of 'git-checkout'.
|
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
|
This hook can be used to perform repository validity checks, auto-display
|
||||||
differences from the previous HEAD if different, or set working dir metadata
|
differences from the previous HEAD if different, or set working dir metadata
|
||||||
properties.
|
properties.
|
||||||
|
|
|
@ -1,21 +1,14 @@
|
||||||
<!-- Based on callouts.xsl. Fixes man page callouts for DocBook 1.72 XSL -->
|
<!-- manpage-1.72.xsl:
|
||||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
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:import href="manpage-base.xsl"/>
|
||||||
<xsl:param name="refentry.meta.get.quietly" select="1"/>
|
|
||||||
|
|
||||||
<xsl:template match="co">
|
<!-- these are the special values for the roff control characters
|
||||||
<xsl:value-of select="concat('▓fB(',substring-after(@id,'-'),')▓fR')"/>
|
needed for docbook-xsl 1.72.0 -->
|
||||||
</xsl:template>
|
<xsl:param name="git.docbook.backslash">▓</xsl:param>
|
||||||
<xsl:template match="calloutlist">
|
<xsl:param name="git.docbook.dot" >⌂</xsl:param>
|
||||||
<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>
|
|
||||||
|
|
||||||
</xsl:stylesheet>
|
</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::
|
resolve::
|
||||||
This can only resolve two heads (i.e. the current branch
|
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
|
algorithm. It tries to carefully detect criss-cross
|
||||||
merge ambiguities and is considered generally safe and
|
merge ambiguities and is considered generally safe and
|
||||||
fast.
|
fast.
|
||||||
|
|
||||||
recursive::
|
recursive::
|
||||||
This can only resolve two heads using 3-way merge
|
This can only resolve two heads using a 3-way merge
|
||||||
algorithm. When there are more than one common
|
algorithm. When there is more than one common
|
||||||
ancestors that can be used for 3-way merge, it creates a
|
ancestor that can be used for 3-way merge, it creates a
|
||||||
merged tree of the common ancestors and uses that as
|
merged tree of the common ancestors and uses that as
|
||||||
the reference tree for the 3-way merge. This has been
|
the reference tree for the 3-way merge. This has been
|
||||||
reported to result in fewer merge conflicts without
|
reported to result in fewer merge conflicts without
|
||||||
|
@ -22,11 +22,11 @@ recursive::
|
||||||
pulling or merging one branch.
|
pulling or merging one branch.
|
||||||
|
|
||||||
octopus::
|
octopus::
|
||||||
This resolves more than two-head case, but refuses to do
|
This resolves cases with more than two heads, but refuses to do
|
||||||
complex merge that needs manual resolution. It is
|
a complex merge that needs manual resolution. It is
|
||||||
primarily meant to be used for bundling topic branch
|
primarily meant to be used for bundling topic branch
|
||||||
heads together. This is the default merge strategy when
|
heads together. This is the default merge strategy when
|
||||||
pulling or merging more than one branches.
|
pulling or merging more than one branch.
|
||||||
|
|
||||||
ours::
|
ours::
|
||||||
This resolves any number of heads, but the result of the
|
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_CFLAGS =
|
||||||
BASIC_LDFLAGS =
|
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-am.sh
|
||||||
SCRIPT_SH += git-bisect.sh
|
SCRIPT_SH += git-bisect.sh
|
||||||
SCRIPT_SH += git-filter-branch.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 "cache.h"
|
||||||
#include "attr.h"
|
#include "attr.h"
|
||||||
|
|
||||||
|
@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
|
||||||
return res;
|
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)
|
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(path, "r");
|
FILE *fp = fopen(path, "r");
|
||||||
|
@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
|
||||||
unsigned long sz;
|
unsigned long sz;
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
void *data;
|
void *data;
|
||||||
|
struct index_state *istate = use_index ? use_index : &the_index;
|
||||||
|
|
||||||
len = strlen(path);
|
len = strlen(path);
|
||||||
pos = cache_name_pos(path, len);
|
pos = index_name_pos(istate, path, len);
|
||||||
if (pos < 0) {
|
if (pos < 0) {
|
||||||
/*
|
/*
|
||||||
* We might be in the middle of a merge, in which
|
* 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;
|
int i;
|
||||||
for (i = -pos - 1;
|
for (i = -pos - 1;
|
||||||
(pos < 0 && i < active_nr &&
|
(pos < 0 && i < istate->cache_nr &&
|
||||||
!strcmp(active_cache[i]->name, path));
|
!strcmp(istate->cache[i]->name, path));
|
||||||
i++)
|
i++)
|
||||||
if (ce_stage(active_cache[i]) == 2)
|
if (ce_stage(istate->cache[i]) == 2)
|
||||||
pos = i;
|
pos = i;
|
||||||
}
|
}
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return NULL;
|
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) {
|
if (!data || type != OBJ_BLOB) {
|
||||||
free(data);
|
free(data);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
|
||||||
return data;
|
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;
|
struct attr_stack *res;
|
||||||
char *buf, *sp;
|
char *buf, *sp;
|
||||||
int lineno = 0;
|
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);
|
buf = read_index_data(path);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return res;
|
return NULL;
|
||||||
|
|
||||||
|
res = xcalloc(1, sizeof(*res));
|
||||||
for (sp = buf; *sp; ) {
|
for (sp = buf; *sp; ) {
|
||||||
char *ep;
|
char *ep;
|
||||||
int more;
|
int more;
|
||||||
|
@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||||
return res;
|
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
|
#if DEBUG_ATTR
|
||||||
static void debug_info(const char *what, struct attr_stack *elem)
|
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)
|
#define debug_set(a,b,c,d) do { ; } while (0)
|
||||||
#endif
|
#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)
|
static void bootstrap_attr_stack(void)
|
||||||
{
|
{
|
||||||
if (!attr_stack) {
|
if (!attr_stack) {
|
||||||
|
@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
|
||||||
|
|
||||||
return 0;
|
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 *);
|
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 */
|
#endif /* ATTR_H */
|
||||||
|
|
|
@ -2250,6 +2250,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
parse_done:
|
parse_done:
|
||||||
argc = parse_options_end(&ctx);
|
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) {
|
if (cmd_is_annotate) {
|
||||||
output_option |= OUTPUT_ANNOTATE_COMPAT;
|
output_option |= OUTPUT_ANNOTATE_COMPAT;
|
||||||
blame_date_mode = DATE_ISO8601;
|
blame_date_mode = DATE_ISO8601;
|
||||||
|
@ -2418,10 +2422,6 @@ parse_done:
|
||||||
sb.ent = ent;
|
sb.ent = ent;
|
||||||
sb.path = path;
|
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);
|
read_mailmap(&mailmap, NULL);
|
||||||
|
|
||||||
if (!incremental)
|
if (!incremental)
|
||||||
|
|
|
@ -171,7 +171,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
printf("Deleted %sbranch %s (%s).\n", remote,
|
printf("Deleted %sbranch %s (was %s).\n", remote,
|
||||||
bname.buf,
|
bname.buf,
|
||||||
find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||||
strbuf_addf(&buf, "branch.%s", bname.buf);
|
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_work_tree;
|
||||||
static const char *junk_git_dir;
|
static const char *junk_git_dir;
|
||||||
pid_t junk_pid;
|
static pid_t junk_pid;
|
||||||
|
|
||||||
static void remove_junk(void)
|
static void remove_junk(void)
|
||||||
{
|
{
|
||||||
|
@ -406,7 +406,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||||
atexit(remove_junk);
|
atexit(remove_junk);
|
||||||
sigchain_push_common(remove_junk_on_signal);
|
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)
|
if (safe_create_leading_directories_const(git_dir) < 0)
|
||||||
die("could not create leading directories of '%s'", git_dir);
|
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)
|
if (message)
|
||||||
message += 2;
|
message += 2;
|
||||||
|
|
||||||
if (commit->parents) {
|
if (commit->parents &&
|
||||||
|
get_object_mark(&commit->parents->item->object) != 0) {
|
||||||
parse_commit(commit->parents->item);
|
parse_commit(commit->parents->item);
|
||||||
diff_tree_sha1(commit->parents->item->tree->object.sha1,
|
diff_tree_sha1(commit->parents->item->tree->object.sha1,
|
||||||
commit->tree->object.sha1, "", &rev->diffopt);
|
commit->tree->object.sha1, "", &rev->diffopt);
|
||||||
|
@ -362,7 +363,10 @@ static void get_tags_and_duplicates(struct object_array *pending,
|
||||||
break;
|
break;
|
||||||
case OBJ_TAG:
|
case OBJ_TAG:
|
||||||
tag = (struct tag *)e->item;
|
tag = (struct tag *)e->item;
|
||||||
|
|
||||||
|
/* handle nested tags */
|
||||||
while (tag && tag->object.type == OBJ_TAG) {
|
while (tag && tag->object.type == OBJ_TAG) {
|
||||||
|
parse_object(tag->object.sha1);
|
||||||
string_list_append(full_name, extra_refs)->util = tag;
|
string_list_append(full_name, extra_refs)->util = tag;
|
||||||
tag = (struct tag *)tag->tagged;
|
tag = (struct tag *)tag->tagged;
|
||||||
}
|
}
|
||||||
|
@ -375,11 +379,17 @@ static void get_tags_and_duplicates(struct object_array *pending,
|
||||||
case OBJ_BLOB:
|
case OBJ_BLOB:
|
||||||
handle_object(tag->object.sha1);
|
handle_object(tag->object.sha1);
|
||||||
continue;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
die ("Unexpected object of type %s",
|
warning("%s: Unexpected object of type %s, skipping.",
|
||||||
typename(e->item->type));
|
e->name,
|
||||||
|
typename(e->item->type));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (commit->util)
|
if (commit->util)
|
||||||
/* more than one name for the same object */
|
/* 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;
|
struct commit *current = NULL, *updated;
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
struct branch *current_branch = branch_get(NULL);
|
struct branch *current_branch = branch_get(NULL);
|
||||||
const char *pretty_ref = ref->name + (
|
const char *pretty_ref = prettify_ref(ref);
|
||||||
!prefixcmp(ref->name, "refs/heads/") ? 11 :
|
|
||||||
!prefixcmp(ref->name, "refs/tags/") ? 10 :
|
|
||||||
!prefixcmp(ref->name, "refs/remotes/") ? 13 :
|
|
||||||
0);
|
|
||||||
|
|
||||||
*display = 0;
|
*display = 0;
|
||||||
type = sha1_object_info(ref->new_sha1, NULL);
|
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;
|
cover_letter = 1;
|
||||||
else if (!strcmp(argv[i], "--no-binary"))
|
else if (!strcmp(argv[i], "--no-binary"))
|
||||||
no_binary_diff = 1;
|
no_binary_diff = 1;
|
||||||
|
else if (!prefixcmp(argv[i], "--add-header="))
|
||||||
|
add_header(argv[i] + 13);
|
||||||
else
|
else
|
||||||
argv[j++] = argv[i];
|
argv[j++] = argv[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1966,7 +1966,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
|
||||||
const unsigned char *sha1;
|
const unsigned char *sha1;
|
||||||
struct object *o;
|
struct object *o;
|
||||||
|
|
||||||
if (p->pack_keep)
|
if (!p->pack_local || p->pack_keep)
|
||||||
continue;
|
continue;
|
||||||
if (open_pack_index(p))
|
if (open_pack_index(p))
|
||||||
die("cannot open pack index");
|
die("cannot open pack index");
|
||||||
|
@ -1995,6 +1995,29 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
|
||||||
free(in_pack.array);
|
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)
|
static void loosen_unused_packed_objects(struct rev_info *revs)
|
||||||
{
|
{
|
||||||
struct packed_git *p;
|
struct packed_git *p;
|
||||||
|
@ -2002,7 +2025,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
|
||||||
const unsigned char *sha1;
|
const unsigned char *sha1;
|
||||||
|
|
||||||
for (p = packed_git; p; p = p->next) {
|
for (p = packed_git; p; p = p->next) {
|
||||||
if (p->pack_keep)
|
if (!p->pack_local || p->pack_keep)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (open_pack_index(p))
|
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++) {
|
for (i = 0; i < p->num_objects; i++) {
|
||||||
sha1 = nth_packed_object_sha1(p, 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))
|
if (force_object_loose(sha1, p->mtime))
|
||||||
die("unable to force loose object");
|
die("unable to force loose object");
|
||||||
}
|
}
|
||||||
|
@ -2200,7 +2224,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp("--unpacked", arg) ||
|
if (!strcmp("--unpacked", arg) ||
|
||||||
!strcmp("--kept-pack-only", arg) ||
|
|
||||||
!strcmp("--reflog", arg) ||
|
!strcmp("--reflog", arg) ||
|
||||||
!strcmp("--all", arg)) {
|
!strcmp("--all", arg)) {
|
||||||
use_internal_rev_list = 1;
|
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)
|
static int do_push(const char *repo, int flags)
|
||||||
{
|
{
|
||||||
int i, errs;
|
int i, errs;
|
||||||
|
@ -79,11 +144,12 @@ static int do_push(const char *repo, int flags)
|
||||||
return error("--all and --mirror are incompatible");
|
return error("--all and --mirror are incompatible");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!refspec
|
if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
|
||||||
&& !(flags & TRANSPORT_PUSH_ALL)
|
if (remote->push_refspec_nr) {
|
||||||
&& remote->push_refspec_nr) {
|
refspec = remote->push_refspec;
|
||||||
refspec = remote->push_refspec;
|
refspec_nr = remote->push_refspec_nr;
|
||||||
refspec_nr = remote->push_refspec_nr;
|
} else if (!(flags & TRANSPORT_PUSH_MIRROR))
|
||||||
|
setup_default_push_refspecs();
|
||||||
}
|
}
|
||||||
errs = 0;
|
errs = 0;
|
||||||
for (i = 0; i < remote->url_nr; i++) {
|
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;
|
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)
|
int show_push_info_item(struct string_list_item *item, void *cb_data)
|
||||||
{
|
{
|
||||||
struct show_info *show_info = 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;
|
info.width = info.width2 = 0;
|
||||||
for_each_string_list(add_push_to_show_info, &states.push, &info);
|
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)
|
if (info.list->nr)
|
||||||
printf(" Local ref%s configured for 'git push'%s:\n",
|
printf(" Local ref%s configured for 'git push'%s:\n",
|
||||||
info.list->nr > 1 ? "s" : "",
|
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"
|
"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.";
|
" --all and explicit <ref> specification are mutually exclusive.";
|
||||||
|
|
||||||
static struct send_pack_args args = {
|
static struct send_pack_args args;
|
||||||
/* .receivepack = */ "git-receive-pack",
|
|
||||||
};
|
|
||||||
|
|
||||||
static int feed_object(const unsigned char *sha1, int fd, int negative)
|
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
|
* 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
|
* 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;
|
struct child_process po;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (args.use_thin_pack)
|
if (args->use_thin_pack)
|
||||||
argv[4] = "--thin";
|
argv[4] = "--thin";
|
||||||
memset(&po, 0, sizeof(po));
|
memset(&po, 0, sizeof(po));
|
||||||
po.argv = argv;
|
po.argv = argv;
|
||||||
|
@ -83,8 +81,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ref *remote_refs, **remote_tail;
|
|
||||||
|
|
||||||
static int receive_status(int in, struct ref *refs)
|
static int receive_status(int in, struct ref *refs)
|
||||||
{
|
{
|
||||||
struct ref *hint;
|
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)
|
#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)
|
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;
|
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 new_refs;
|
||||||
int ask_for_status_report = 0;
|
int ask_for_status_report = 0;
|
||||||
int allow_deleting_refs = 0;
|
int allow_deleting_refs = 0;
|
||||||
int expect_status_report = 0;
|
int expect_status_report = 0;
|
||||||
int flags = MATCH_REFS_NONE;
|
|
||||||
int ret;
|
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? */
|
/* Does the other end support the reporting? */
|
||||||
if (server_supports("report-status"))
|
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"))
|
if (server_supports("delete-refs"))
|
||||||
allow_deleting_refs = 1;
|
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) {
|
if (!remote_refs) {
|
||||||
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
|
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
|
||||||
"Perhaps you should specify a branch such as 'master'.\n");
|
"Perhaps you should specify a branch such as 'master'.\n");
|
||||||
close(out);
|
|
||||||
return 0;
|
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)
|
if (ref->peer_ref)
|
||||||
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
|
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
|
||||||
else if (!args.send_mirror)
|
else if (!args->send_mirror)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ref->deletion = is_null_sha1(ref->new_sha1);
|
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)
|
(!has_sha1_file(ref->old_sha1)
|
||||||
|| !ref_newer(ref->new_sha1, 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;
|
ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -409,7 +377,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||||
if (!ref->deletion)
|
if (!ref->deletion)
|
||||||
new_refs++;
|
new_refs++;
|
||||||
|
|
||||||
if (!args.dry_run) {
|
if (!args->dry_run) {
|
||||||
char *old_hex = sha1_to_hex(ref->old_sha1);
|
char *old_hex = sha1_to_hex(ref->old_sha1);
|
||||||
char *new_hex = sha1_to_hex(ref->new_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);
|
packet_flush(out);
|
||||||
if (new_refs && !args.dry_run) {
|
if (new_refs && !args->dry_run) {
|
||||||
if (pack_objects(out, remote_refs, &extra_have) < 0)
|
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;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
close(out);
|
|
||||||
|
|
||||||
if (expect_status_report)
|
if (expect_status_report)
|
||||||
ret = receive_status(in, remote_refs);
|
ret = receive_status(in, remote_refs);
|
||||||
else
|
else
|
||||||
ret = 0;
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
for (ref = remote_refs; ref; ref = ref->next) {
|
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 cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i, nr_heads = 0;
|
int i, nr_refspecs = 0;
|
||||||
const char **heads = NULL;
|
const char **refspecs = NULL;
|
||||||
const char *remote_name = NULL;
|
const char *remote_name = NULL;
|
||||||
struct remote *remote = NULL;
|
struct remote *remote = NULL;
|
||||||
const char *dest = 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++;
|
argv++;
|
||||||
for (i = 1; i < argc; i++, 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 (*arg == '-') {
|
||||||
if (!prefixcmp(arg, "--receive-pack=")) {
|
if (!prefixcmp(arg, "--receive-pack=")) {
|
||||||
args.receivepack = arg + 15;
|
receivepack = arg + 15;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!prefixcmp(arg, "--exec=")) {
|
if (!prefixcmp(arg, "--exec=")) {
|
||||||
args.receivepack = arg + 7;
|
receivepack = arg + 7;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!prefixcmp(arg, "--remote=")) {
|
if (!prefixcmp(arg, "--remote=")) {
|
||||||
|
@ -523,7 +491,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--all")) {
|
if (!strcmp(arg, "--all")) {
|
||||||
args.send_all = 1;
|
send_all = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--dry-run")) {
|
if (!strcmp(arg, "--dry-run")) {
|
||||||
|
@ -552,8 +520,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||||
dest = arg;
|
dest = arg;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
heads = (const char **) argv;
|
refspecs = (const char **) argv;
|
||||||
nr_heads = argc - i;
|
nr_refspecs = argc - i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!dest)
|
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
|
* --all and --mirror are incompatible; neither makes sense
|
||||||
* with any refspecs.
|
* with any refspecs.
|
||||||
*/
|
*/
|
||||||
if ((heads && (args.send_all || args.send_mirror)) ||
|
if ((refspecs && (send_all || args.send_mirror)) ||
|
||||||
(args.send_all && args.send_mirror))
|
(send_all && args.send_mirror))
|
||||||
usage(send_pack_usage);
|
usage(send_pack_usage);
|
||||||
|
|
||||||
if (remote_name) {
|
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,
|
memset(&extra_have, 0, sizeof(extra_have));
|
||||||
const char *dest, struct remote *remote,
|
|
||||||
int nr_heads, const char **heads)
|
|
||||||
{
|
|
||||||
int fd[2], ret;
|
|
||||||
struct child_process *conn;
|
|
||||||
|
|
||||||
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);
|
local_refs = get_local_heads();
|
||||||
ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, 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]);
|
close(fd[0]);
|
||||||
/* do_send_pack always closes fd[1] */
|
|
||||||
ret |= finish_connect(conn);
|
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,
|
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 branch_track git_branch_track;
|
||||||
extern enum rebase_setup_type autorebase;
|
extern enum rebase_setup_type autorebase;
|
||||||
|
extern enum push_default_type push_default;
|
||||||
|
|
||||||
#define GIT_REPO_VERSION 0
|
#define GIT_REPO_VERSION 0
|
||||||
extern int repository_format_version;
|
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 move_temp_to_file(const char *tmpfile, const char *filename);
|
||||||
|
|
||||||
extern int has_sha1_pack(const unsigned char *sha1);
|
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_sha1_file(const unsigned char *sha1);
|
||||||
extern int has_loose_object_nonlocal(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;
|
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)
|
static int git_default_mailmap_config(const char *var, const char *value)
|
||||||
{
|
{
|
||||||
if (!strcmp(var, "mailmap.file"))
|
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."))
|
if (!prefixcmp(var, "branch."))
|
||||||
return git_default_branch_config(var, value);
|
return git_default_branch_config(var, value);
|
||||||
|
|
||||||
|
if (!prefixcmp(var, "push."))
|
||||||
|
return git_default_push_config(var, value);
|
||||||
|
|
||||||
if (!prefixcmp(var, "mailmap."))
|
if (!prefixcmp(var, "mailmap."))
|
||||||
return git_default_mailmap_config(var, value);
|
return git_default_mailmap_config(var, value);
|
||||||
|
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ _git_log ()
|
||||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
local g="$(git rev-parse --git-dir 2>/dev/null)"
|
local g="$(git rev-parse --git-dir 2>/dev/null)"
|
||||||
local merge=""
|
local merge=""
|
||||||
if [ -f $g/MERGE_HEAD ]; then
|
if [ -f "$g/MERGE_HEAD" ]; then
|
||||||
merge="--merge"
|
merge="--merge"
|
||||||
fi
|
fi
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
|
@ -1943,7 +1943,7 @@ _gitk ()
|
||||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
local g="$(__gitdir)"
|
local g="$(__gitdir)"
|
||||||
local merge=""
|
local merge=""
|
||||||
if [ -f $g/MERGE_HEAD ]; then
|
if [ -f "$g/MERGE_HEAD" ]; then
|
||||||
merge="--merge"
|
merge="--merge"
|
||||||
fi
|
fi
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
|
|
|
@ -44,7 +44,8 @@ for zipfile in argv[1:]:
|
||||||
common_prefix = name[:name.rfind('/') + 1]
|
common_prefix = name[:name.rfind('/') + 1]
|
||||||
else:
|
else:
|
||||||
while not name.startswith(common_prefix):
|
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)
|
mark[name] = ':' + str(next_mark)
|
||||||
next_mark += 1
|
next_mark += 1
|
||||||
|
|
|
@ -205,8 +205,6 @@ void diff_no_index(struct rev_info *revs,
|
||||||
no_index ? "--no-index" : "[--no-index]");
|
no_index ? "--no-index" : "[--no-index]");
|
||||||
|
|
||||||
diff_setup(&revs->diffopt);
|
diff_setup(&revs->diffopt);
|
||||||
if (!revs->diffopt.output_format)
|
|
||||||
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
|
|
||||||
for (i = 1; i < argc - 2; ) {
|
for (i = 1; i < argc - 2; ) {
|
||||||
int j;
|
int j;
|
||||||
if (!strcmp(argv[i], "--no-index"))
|
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.paths = argv + argc - 2;
|
||||||
revs->diffopt.nr_paths = 2;
|
revs->diffopt.nr_paths = 2;
|
||||||
revs->diffopt.skip_stat_unmatch = 1;
|
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, EXIT_WITH_STATUS);
|
||||||
DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
|
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;
|
struct stat st;
|
||||||
int pos, len;
|
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
|
* benchmark with my previous version that always reads cache
|
||||||
* shows that it makes things worse for diff-tree comparing
|
* shows that it makes things worse for diff-tree comparing
|
||||||
* two linux-2.6 kernel trees in an already checked out work
|
* 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))
|
if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
|
||||||
return 0;
|
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.
|
* 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;
|
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,
|
void *blob,
|
||||||
unsigned long size,
|
unsigned long size,
|
||||||
const unsigned char *sha1,
|
const unsigned char *sha1,
|
||||||
int mode)
|
int mode)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
|
fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
die("unable to create temp-file: %s", strerror(errno));
|
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)
|
if (write_in_full(fd, blob, size) != size)
|
||||||
die("unable to write temp-file");
|
die("unable to write temp-file");
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -1964,6 +1978,7 @@ static void prep_temp_blob(struct diff_tempfile *temp,
|
||||||
strcpy(temp->hex, sha1_to_hex(sha1));
|
strcpy(temp->hex, sha1_to_hex(sha1));
|
||||||
temp->hex[40] = 0;
|
temp->hex[40] = 0;
|
||||||
sprintf(temp->mode, "%06o", mode);
|
sprintf(temp->mode, "%06o", mode);
|
||||||
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct diff_tempfile *prepare_temp_file(const char *name,
|
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);
|
die("readlink(%s)", name);
|
||||||
if (ret == sizeof(buf))
|
if (ret == sizeof(buf))
|
||||||
die("symlink too long: %s", name);
|
die("symlink too long: %s", name);
|
||||||
prep_temp_blob(temp, buf, ret,
|
prep_temp_blob(name, temp, buf, ret,
|
||||||
(one->sha1_valid ?
|
(one->sha1_valid ?
|
||||||
one->sha1 : null_sha1),
|
one->sha1 : null_sha1),
|
||||||
(one->sha1_valid ?
|
(one->sha1_valid ?
|
||||||
|
@ -2030,7 +2045,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
||||||
else {
|
else {
|
||||||
if (diff_populate_filespec(one, 0))
|
if (diff_populate_filespec(one, 0))
|
||||||
die("cannot read data blob for %s", one->path);
|
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);
|
one->sha1, one->mode);
|
||||||
}
|
}
|
||||||
return temp;
|
return temp;
|
||||||
|
|
|
@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
|
||||||
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
|
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
|
||||||
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
|
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
|
||||||
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
|
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
|
||||||
|
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
|
||||||
|
|
||||||
/* Parallel index stat data preload? */
|
/* Parallel index stat data preload? */
|
||||||
int core_preload_index = 0;
|
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)
|
void git_set_argv_exec_path(const char *exec_path)
|
||||||
{
|
{
|
||||||
argv_exec_path = 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:
|
Format of STDIN stream:
|
||||||
|
|
||||||
stream ::= cmd*;
|
stream ::= cmd*;
|
||||||
|
@ -18,8 +19,8 @@ Format of STDIN stream:
|
||||||
|
|
||||||
new_commit ::= 'commit' sp ref_str lf
|
new_commit ::= 'commit' sp ref_str lf
|
||||||
mark?
|
mark?
|
||||||
('author' sp name '<' email '>' when lf)?
|
('author' sp name sp '<' email '>' sp when lf)?
|
||||||
'committer' sp name '<' email '>' when lf
|
'committer' sp name sp '<' email '>' sp when lf
|
||||||
commit_msg
|
commit_msg
|
||||||
('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
|
('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
|
||||||
('merge' 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
|
new_tag ::= 'tag' sp tag_str lf
|
||||||
'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) 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;
|
||||||
tag_msg ::= data;
|
tag_msg ::= data;
|
||||||
|
|
||||||
|
|
|
@ -272,10 +272,10 @@ test $commits -eq 0 && die "Found nothing to rewrite"
|
||||||
|
|
||||||
# Rewrite the commits
|
# Rewrite the commits
|
||||||
|
|
||||||
i=0
|
git_filter_branch__commit_count=0
|
||||||
while read commit parents; do
|
while read commit parents; do
|
||||||
i=$(($i+1))
|
git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
|
||||||
printf "\rRewrite $commit ($i/$commits)"
|
printf "\rRewrite $commit ($git_filter_branch__commit_count/$commits)"
|
||||||
|
|
||||||
case "$filter_subdir" in
|
case "$filter_subdir" in
|
||||||
"")
|
"")
|
||||||
|
|
|
@ -319,7 +319,7 @@ do
|
||||||
--root)
|
--root)
|
||||||
rebase_root=t
|
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
|
force_rebase=t
|
||||||
;;
|
;;
|
||||||
-*)
|
-*)
|
||||||
|
|
|
@ -71,11 +71,7 @@ case ",$all_into_one," in
|
||||||
existing="$existing $e"
|
existing="$existing $e"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if test -n "$existing"
|
if test -n "$existing" -a -n "$unpack_unreachable" -a \
|
||||||
then
|
|
||||||
args="--kept-pack-only"
|
|
||||||
fi
|
|
||||||
if test -n "$args" -a -n "$unpack_unreachable" -a \
|
|
||||||
-n "$remove_redundant"
|
-n "$remove_redundant"
|
||||||
then
|
then
|
||||||
args="$args $unpack_unreachable"
|
args="$args $unpack_unreachable"
|
||||||
|
|
|
@ -606,32 +606,43 @@ EOT
|
||||||
do_edit(@files);
|
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;
|
my $prompting = 0;
|
||||||
if (!defined $sender) {
|
if (!defined $sender) {
|
||||||
$sender = $repoauthor || $repocommitter || '';
|
$sender = $repoauthor || $repocommitter || '';
|
||||||
|
$sender = ask("Who should the emails appear to be from? [$sender] ",
|
||||||
while (1) {
|
default => $sender);
|
||||||
$_ = $term->readline("Who should the emails appear to be from? [$sender] ");
|
|
||||||
last if defined $_;
|
|
||||||
print "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$sender = $_ if ($_);
|
|
||||||
print "Emails will be sent from: ", $sender, "\n";
|
print "Emails will be sent from: ", $sender, "\n";
|
||||||
$prompting++;
|
$prompting++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!@to) {
|
if (!@to) {
|
||||||
|
my $to = ask("Who should the emails be sent to? ");
|
||||||
|
push @to, parse_address_line($to) if defined $to; # sanitized/validated later
|
||||||
while (1) {
|
|
||||||
$_ = $term->readline("Who should the emails be sent to? ", "");
|
|
||||||
last if defined $_;
|
|
||||||
print "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $to = $_;
|
|
||||||
push @to, parse_address_line($to);
|
|
||||||
$prompting++;
|
$prompting++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,13 +662,8 @@ sub expand_aliases {
|
||||||
@bcclist = expand_aliases(@bcclist);
|
@bcclist = expand_aliases(@bcclist);
|
||||||
|
|
||||||
if ($thread && !defined $initial_reply_to && $prompting) {
|
if ($thread && !defined $initial_reply_to && $prompting) {
|
||||||
while (1) {
|
$initial_reply_to = ask(
|
||||||
$_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to);
|
"Message-ID to be used as In-Reply-To for the first email? ");
|
||||||
last if defined $_;
|
|
||||||
print "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$initial_reply_to = $_;
|
|
||||||
}
|
}
|
||||||
if (defined $initial_reply_to) {
|
if (defined $initial_reply_to) {
|
||||||
$initial_reply_to =~ s/^\s*<?//;
|
$initial_reply_to =~ s/^\s*<?//;
|
||||||
|
@ -681,7 +687,7 @@ if ($compose && $compose > 0) {
|
||||||
|
|
||||||
# Variables we set as part of the loop over files
|
# Variables we set as part of the loop over files
|
||||||
our ($message_id, %mail, $subject, $reply_to, $references, $message,
|
our ($message_id, %mail, $subject, $reply_to, $references, $message,
|
||||||
$needs_confirm, $message_num);
|
$needs_confirm, $message_num, $ask_default);
|
||||||
|
|
||||||
sub extract_valid_address {
|
sub extract_valid_address {
|
||||||
my $address = shift;
|
my $address = shift;
|
||||||
|
@ -770,12 +776,13 @@ sub sanitize_address
|
||||||
}
|
}
|
||||||
|
|
||||||
# if recipient_name is already quoted, do nothing
|
# if recipient_name is already quoted, do nothing
|
||||||
if ($recipient_name =~ /^(".*"|=\?utf-8\?q\?.*\?=)$/) {
|
if ($recipient_name =~ /^("[[:ascii:]]*"|=\?utf-8\?q\?.*\?=)$/) {
|
||||||
return $recipient;
|
return $recipient;
|
||||||
}
|
}
|
||||||
|
|
||||||
# rfc2047 is needed if a non-ascii char is included
|
# rfc2047 is needed if a non-ascii char is included
|
||||||
if ($recipient_name =~ /[^[:ascii:]]/) {
|
if ($recipient_name =~ /[^[:ascii:]]/) {
|
||||||
|
$recipient_name =~ s/^"(.*)"$/$1/;
|
||||||
$recipient_name = quote_rfc2047($recipient_name);
|
$recipient_name = quote_rfc2047($recipient_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,6 +848,7 @@ X-Mailer: git-send-email $gitversion
|
||||||
print "\n$header\n";
|
print "\n$header\n";
|
||||||
if ($needs_confirm eq "inform") {
|
if ($needs_confirm eq "inform") {
|
||||||
$confirm_unconfigured = 0; # squelch this message for the rest of this run
|
$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 " The Cc list above has been expanded by additional\n";
|
||||||
print " addresses found in the patch commit message. By default\n";
|
print " addresses found in the patch commit message. By default\n";
|
||||||
print " send-email prompts before sending whenever this occurs.\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 " To retain the current behavior, but squelch this message,\n";
|
||||||
print " run 'git config --global sendemail.confirm auto'.\n\n";
|
print " run 'git config --global sendemail.confirm auto'.\n\n";
|
||||||
}
|
}
|
||||||
while (1) {
|
$_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
|
||||||
chomp ($_ = $term->readline(
|
valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
|
||||||
"Send this email? ([y]es|[n]o|[q]uit|[a]ll): "
|
default => $ask_default);
|
||||||
));
|
die "Send this email reply required" unless defined $_;
|
||||||
last if /^(?:yes|y|no|n|quit|q|all|a)/i;
|
|
||||||
print "\n";
|
|
||||||
}
|
|
||||||
if (/^n/i) {
|
if (/^n/i) {
|
||||||
return;
|
return;
|
||||||
} elsif (/^q/i) {
|
} elsif (/^q/i) {
|
||||||
|
|
24
git-svn.perl
24
git-svn.perl
|
@ -68,6 +68,7 @@ my ($_stdin, $_help, $_edit,
|
||||||
$_prefix, $_no_checkout, $_url, $_verbose,
|
$_prefix, $_no_checkout, $_url, $_verbose,
|
||||||
$_git_format, $_commit_url, $_tag);
|
$_git_format, $_commit_url, $_tag);
|
||||||
$Git::SVN::_follow_parent = 1;
|
$Git::SVN::_follow_parent = 1;
|
||||||
|
$_q ||= 0;
|
||||||
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
|
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
|
||||||
'config-dir=s' => \$Git::SVN::Ra::config_dir,
|
'config-dir=s' => \$Git::SVN::Ra::config_dir,
|
||||||
'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache,
|
'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,
|
'useSvnsyncProps' => \$Git::SVN::_use_svnsync_props,
|
||||||
'log-window-size=i' => \$Git::SVN::Ra::_log_window_size,
|
'log-window-size=i' => \$Git::SVN::Ra::_log_window_size,
|
||||||
'no-checkout' => \$_no_checkout,
|
'no-checkout' => \$_no_checkout,
|
||||||
'quiet|q' => \$_q,
|
'quiet|q+' => \$_q,
|
||||||
'repack-flags|repack-args|repack-opts=s' =>
|
'repack-flags|repack-args|repack-opts=s' =>
|
||||||
\$Git::SVN::_repack_flags,
|
\$Git::SVN::_repack_flags,
|
||||||
'use-log-author' => \$Git::SVN::_use_log_author,
|
'use-log-author' => \$Git::SVN::_use_log_author,
|
||||||
|
@ -2331,13 +2332,13 @@ sub do_git_commit {
|
||||||
|
|
||||||
$self->{last_rev} = $log_entry->{revision};
|
$self->{last_rev} = $log_entry->{revision};
|
||||||
$self->{last_commit} = $commit;
|
$self->{last_commit} = $commit;
|
||||||
print "r$log_entry->{revision}";
|
print "r$log_entry->{revision}" unless $::_q > 1;
|
||||||
if (defined $log_entry->{svm_revision}) {
|
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,
|
$self->rev_map_set($log_entry->{svm_revision}, $commit,
|
||||||
0, $self->svm_uuid);
|
0, $self->svm_uuid);
|
||||||
}
|
}
|
||||||
print " = $commit ($self->{ref_id})\n";
|
print " = $commit ($self->{ref_id})\n" unless $::_q > 1;
|
||||||
if (--$_gc_nr == 0) {
|
if (--$_gc_nr == 0) {
|
||||||
$_gc_nr = $_gc_period;
|
$_gc_nr = $_gc_period;
|
||||||
gc();
|
gc();
|
||||||
|
@ -3387,15 +3388,18 @@ sub delete_entry {
|
||||||
return undef if ($gpath eq '');
|
return undef if ($gpath eq '');
|
||||||
|
|
||||||
# remove entire directories.
|
# 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
|
my ($ls, $ctx) = command_output_pipe(qw/ls-tree
|
||||||
-r --name-only -z/,
|
-r --name-only -z/,
|
||||||
$self->{c}, '--', $gpath);
|
$tree);
|
||||||
local $/ = "\0";
|
local $/ = "\0";
|
||||||
while (<$ls>) {
|
while (<$ls>) {
|
||||||
chomp;
|
chomp;
|
||||||
$self->{gii}->remove($_);
|
my $rmpath = "$gpath/$_";
|
||||||
print "\tD\t$_\n" unless $::_q;
|
$self->{gii}->remove($rmpath);
|
||||||
|
print "\tD\t$rmpath\n" unless $::_q;
|
||||||
}
|
}
|
||||||
print "\tD\t$gpath/\n" unless $::_q;
|
print "\tD\t$gpath/\n" unless $::_q;
|
||||||
command_close_pipe($ls, $ctx);
|
command_close_pipe($ls, $ctx);
|
||||||
|
@ -3414,8 +3418,8 @@ sub open_file {
|
||||||
goto out if is_path_ignored($path);
|
goto out if is_path_ignored($path);
|
||||||
|
|
||||||
my $gpath = $self->git_path($path);
|
my $gpath = $self->git_path($path);
|
||||||
($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath)
|
($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
|
||||||
=~ /^(\d{6}) blob ([a-f\d]{40})\t/);
|
=~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/);
|
||||||
unless (defined $mode && defined $blob) {
|
unless (defined $mode && defined $blob) {
|
||||||
die "$path was not found in commit $self->{c} (r$rev)\n";
|
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;
|
struct remote_lock *locks;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct repo *remote;
|
static struct repo *repo;
|
||||||
|
|
||||||
enum transfer_state {
|
enum transfer_state {
|
||||||
NEED_FETCH,
|
NEED_FETCH,
|
||||||
|
@ -324,7 +324,7 @@ static void start_fetch_loose(struct transfer_request *request)
|
||||||
|
|
||||||
git_SHA1_Init(&request->c);
|
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);
|
request->url = xstrdup(url);
|
||||||
|
|
||||||
/* If a previous temp file is present, process what was already
|
/* 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;
|
request->state = RUN_FETCH_LOOSE;
|
||||||
if (!start_active_slot(slot)) {
|
if (!start_active_slot(slot)) {
|
||||||
fprintf(stderr, "Unable to start GET request\n");
|
fprintf(stderr, "Unable to start GET request\n");
|
||||||
remote->can_update_info_refs = 0;
|
repo->can_update_info_refs = 0;
|
||||||
release_request(request);
|
release_request(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,7 @@ static void start_mkcol(struct transfer_request *request)
|
||||||
char *hex = sha1_to_hex(request->obj->sha1);
|
char *hex = sha1_to_hex(request->obj->sha1);
|
||||||
struct active_request_slot *slot;
|
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 = get_active_slot();
|
||||||
slot->callback_func = process_response;
|
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 transfer_request *check_request = request_queue_head;
|
||||||
struct active_request_slot *slot;
|
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) {
|
if (!target) {
|
||||||
fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
|
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);
|
release_request(request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -450,9 +450,9 @@ static void start_fetch_packed(struct transfer_request *request)
|
||||||
snprintf(request->tmpfile, sizeof(request->tmpfile),
|
snprintf(request->tmpfile, sizeof(request->tmpfile),
|
||||||
"%s.temp", filename);
|
"%s.temp", filename);
|
||||||
|
|
||||||
url = xmalloc(strlen(remote->url) + 64);
|
url = xmalloc(strlen(repo->url) + 64);
|
||||||
sprintf(url, "%sobjects/pack/pack-%s.pack",
|
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 */
|
/* Make sure there isn't another open request for this pack */
|
||||||
while (check_request) {
|
while (check_request) {
|
||||||
|
@ -469,7 +469,7 @@ static void start_fetch_packed(struct transfer_request *request)
|
||||||
if (!packfile) {
|
if (!packfile) {
|
||||||
fprintf(stderr, "Unable to open local file %s for pack",
|
fprintf(stderr, "Unable to open local file %s for pack",
|
||||||
request->tmpfile);
|
request->tmpfile);
|
||||||
remote->can_update_info_refs = 0;
|
repo->can_update_info_refs = 0;
|
||||||
free(url);
|
free(url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -505,7 +505,7 @@ static void start_fetch_packed(struct transfer_request *request)
|
||||||
request->state = RUN_FETCH_PACKED;
|
request->state = RUN_FETCH_PACKED;
|
||||||
if (!start_active_slot(slot)) {
|
if (!start_active_slot(slot)) {
|
||||||
fprintf(stderr, "Unable to start GET request\n");
|
fprintf(stderr, "Unable to start GET request\n");
|
||||||
remote->can_update_info_refs = 0;
|
repo->can_update_info_refs = 0;
|
||||||
release_request(request);
|
release_request(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -554,10 +554,10 @@ static void start_put(struct transfer_request *request)
|
||||||
request->buffer.buf.len = stream.total_out;
|
request->buffer.buf.len = stream.total_out;
|
||||||
|
|
||||||
strbuf_addstr(&buf, "Destination: ");
|
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);
|
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);
|
strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
|
||||||
request->url = strbuf_detach(&buf, NULL);
|
request->url = strbuf_detach(&buf, NULL);
|
||||||
|
|
||||||
|
@ -648,7 +648,7 @@ static int refresh_lock(struct remote_lock *lock)
|
||||||
|
|
||||||
static void check_locks(void)
|
static void check_locks(void)
|
||||||
{
|
{
|
||||||
struct remote_lock *lock = remote->locks;
|
struct remote_lock *lock = repo->locks;
|
||||||
time_t current_time = time(NULL);
|
time_t current_time = time(NULL);
|
||||||
int time_remaining;
|
int time_remaining;
|
||||||
|
|
||||||
|
@ -788,7 +788,7 @@ static void finish_request(struct transfer_request *request)
|
||||||
if (request->curl_result != CURLE_OK) {
|
if (request->curl_result != CURLE_OK) {
|
||||||
fprintf(stderr, "Unable to get pack file %s\n%s",
|
fprintf(stderr, "Unable to get pack file %s\n%s",
|
||||||
request->url, curl_errorstr);
|
request->url, curl_errorstr);
|
||||||
remote->can_update_info_refs = 0;
|
repo->can_update_info_refs = 0;
|
||||||
} else {
|
} else {
|
||||||
off_t pack_size = ftell(request->local_stream);
|
off_t pack_size = ftell(request->local_stream);
|
||||||
|
|
||||||
|
@ -798,7 +798,7 @@ static void finish_request(struct transfer_request *request)
|
||||||
request->filename)) {
|
request->filename)) {
|
||||||
target = (struct packed_git *)request->userData;
|
target = (struct packed_git *)request->userData;
|
||||||
target->pack_size = pack_size;
|
target->pack_size = pack_size;
|
||||||
lst = &remote->packs;
|
lst = &repo->packs;
|
||||||
while (*lst != target)
|
while (*lst != target)
|
||||||
lst = &((*lst)->next);
|
lst = &((*lst)->next);
|
||||||
*lst = (*lst)->next;
|
*lst = (*lst)->next;
|
||||||
|
@ -806,7 +806,7 @@ static void finish_request(struct transfer_request *request)
|
||||||
if (!verify_pack(target))
|
if (!verify_pack(target))
|
||||||
install_packed_git(target);
|
install_packed_git(target);
|
||||||
else
|
else
|
||||||
remote->can_update_info_refs = 0;
|
repo->can_update_info_refs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
release_request(request);
|
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]);
|
get_remote_object_list(obj->sha1[0]);
|
||||||
if (obj->flags & (REMOTE | PUSHING))
|
if (obj->flags & (REMOTE | PUSHING))
|
||||||
return 0;
|
return 0;
|
||||||
target = find_sha1_pack(obj->sha1, remote->packs);
|
target = find_sha1_pack(obj->sha1, repo->packs);
|
||||||
if (target) {
|
if (target) {
|
||||||
obj->flags |= REMOTE;
|
obj->flags |= REMOTE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -930,8 +930,8 @@ static int fetch_index(unsigned char *sha1)
|
||||||
struct slot_results results;
|
struct slot_results results;
|
||||||
|
|
||||||
/* Don't use the index if the pack isn't there */
|
/* Don't use the index if the pack isn't there */
|
||||||
url = xmalloc(strlen(remote->url) + 64);
|
url = xmalloc(strlen(repo->url) + 64);
|
||||||
sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
|
sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
|
||||||
slot = get_active_slot();
|
slot = get_active_slot();
|
||||||
slot->results = &results;
|
slot->results = &results;
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
||||||
|
@ -956,7 +956,7 @@ static int fetch_index(unsigned char *sha1)
|
||||||
if (push_verbosely)
|
if (push_verbosely)
|
||||||
fprintf(stderr, "Getting index for pack %s\n", hex);
|
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);
|
filename = sha1_pack_index_name(sha1);
|
||||||
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
|
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
|
||||||
|
@ -1018,8 +1018,8 @@ static int setup_index(unsigned char *sha1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
new_pack = parse_pack_index(sha1);
|
new_pack = parse_pack_index(sha1);
|
||||||
new_pack->next = remote->packs;
|
new_pack->next = repo->packs;
|
||||||
remote->packs = new_pack;
|
repo->packs = new_pack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,8 +1037,8 @@ static int fetch_indices(void)
|
||||||
if (push_verbosely)
|
if (push_verbosely)
|
||||||
fprintf(stderr, "Getting pack list\n");
|
fprintf(stderr, "Getting pack list\n");
|
||||||
|
|
||||||
url = xmalloc(strlen(remote->url) + 20);
|
url = xmalloc(strlen(repo->url) + 20);
|
||||||
sprintf(url, "%sobjects/info/packs", remote->url);
|
sprintf(url, "%sobjects/info/packs", repo->url);
|
||||||
|
|
||||||
slot = get_active_slot();
|
slot = get_active_slot();
|
||||||
slot->results = &results;
|
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 curl_slist *dav_headers = NULL;
|
||||||
struct xml_ctx ctx;
|
struct xml_ctx ctx;
|
||||||
|
|
||||||
url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||||
sprintf(url, "%s%s", remote->url, path);
|
sprintf(url, "%s%s", repo->url, path);
|
||||||
|
|
||||||
/* Make sure leading directories exist for the remote ref */
|
/* 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) {
|
while (ep) {
|
||||||
char saved_character = ep[1];
|
char saved_character = ep[1];
|
||||||
ep[1] = '\0';
|
ep[1] = '\0';
|
||||||
|
@ -1319,8 +1319,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
|
||||||
} else {
|
} else {
|
||||||
lock->url = url;
|
lock->url = url;
|
||||||
lock->start_time = time(NULL);
|
lock->start_time = time(NULL);
|
||||||
lock->next = remote->locks;
|
lock->next = repo->locks;
|
||||||
remote->locks = lock;
|
repo->locks = lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lock;
|
return lock;
|
||||||
|
@ -1330,7 +1330,7 @@ static int unlock_remote(struct remote_lock *lock)
|
||||||
{
|
{
|
||||||
struct active_request_slot *slot;
|
struct active_request_slot *slot;
|
||||||
struct slot_results results;
|
struct slot_results results;
|
||||||
struct remote_lock *prev = remote->locks;
|
struct remote_lock *prev = repo->locks;
|
||||||
struct curl_slist *dav_headers;
|
struct curl_slist *dav_headers;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
@ -1356,8 +1356,8 @@ static int unlock_remote(struct remote_lock *lock)
|
||||||
|
|
||||||
curl_slist_free_all(dav_headers);
|
curl_slist_free_all(dav_headers);
|
||||||
|
|
||||||
if (remote->locks == lock) {
|
if (repo->locks == lock) {
|
||||||
remote->locks = lock->next;
|
repo->locks = lock->next;
|
||||||
} else {
|
} else {
|
||||||
while (prev && prev->next != lock)
|
while (prev && prev->next != lock)
|
||||||
prev = prev->next;
|
prev = prev->next;
|
||||||
|
@ -1375,7 +1375,7 @@ static int unlock_remote(struct remote_lock *lock)
|
||||||
|
|
||||||
static void remove_locks(void)
|
static void remove_locks(void)
|
||||||
{
|
{
|
||||||
struct remote_lock *lock = remote->locks;
|
struct remote_lock *lock = repo->locks;
|
||||||
|
|
||||||
fprintf(stderr, "Removing remote locks...\n");
|
fprintf(stderr, "Removing remote locks...\n");
|
||||||
while (lock) {
|
while (lock) {
|
||||||
|
@ -1457,7 +1457,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
path += remote->path_len;
|
path += repo->path_len;
|
||||||
ls->dentry_name = xstrdup(path);
|
ls->dentry_name = xstrdup(path);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
|
} 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 (*userFunc)(struct remote_ls_ctx *ls),
|
||||||
void *userData)
|
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 active_request_slot *slot;
|
||||||
struct slot_results results;
|
struct slot_results results;
|
||||||
struct strbuf in_buffer = STRBUF_INIT;
|
struct strbuf in_buffer = STRBUF_INIT;
|
||||||
|
@ -1496,7 +1496,7 @@ static void remote_ls(const char *path, int flags,
|
||||||
ls.userData = userData;
|
ls.userData = userData;
|
||||||
ls.userFunc = userFunc;
|
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);
|
strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST);
|
||||||
|
|
||||||
|
@ -1574,7 +1574,7 @@ static int locking_available(void)
|
||||||
struct xml_ctx ctx;
|
struct xml_ctx ctx;
|
||||||
int lock_flags = 0;
|
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, "Depth: 0");
|
||||||
dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
|
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_READFUNCTION, fread_buffer);
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_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_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_UPLOAD, 1);
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
|
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
|
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
|
||||||
|
@ -1617,15 +1617,15 @@ static int locking_available(void)
|
||||||
XML_ParserFree(parser);
|
XML_ParserFree(parser);
|
||||||
if (!lock_flags)
|
if (!lock_flags)
|
||||||
error("no DAV locking support on %s",
|
error("no DAV locking support on %s",
|
||||||
remote->url);
|
repo->url);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
error("Cannot access URL %s, return code %d",
|
error("Cannot access URL %s, return code %d",
|
||||||
remote->url, results.curl_result);
|
repo->url, results.curl_result);
|
||||||
lock_flags = 0;
|
lock_flags = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
strbuf_release(&out_buffer.buf);
|
||||||
|
@ -1801,10 +1801,10 @@ static void one_remote_ref(char *refname)
|
||||||
|
|
||||||
ref = alloc_ref(refname);
|
ref = alloc_ref(refname);
|
||||||
|
|
||||||
if (http_fetch_ref(remote->url, ref) != 0) {
|
if (http_fetch_ref(repo->url, ref) != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Unable to fetch ref %s from %s\n",
|
"Unable to fetch ref %s from %s\n",
|
||||||
refname, remote->url);
|
refname, repo->url);
|
||||||
free(ref);
|
free(ref);
|
||||||
return;
|
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
|
* Fetch a copy of the object if it doesn't exist locally - it
|
||||||
* may be required for updating server info later.
|
* 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);
|
obj = lookup_unknown_object(ref->old_sha1);
|
||||||
if (obj) {
|
if (obj) {
|
||||||
fprintf(stderr, " fetch %s for %s\n",
|
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);
|
ref = alloc_ref(ls->dentry_name);
|
||||||
|
|
||||||
if (http_fetch_ref(remote->url, ref) != 0) {
|
if (http_fetch_ref(repo->url, ref) != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Unable to fetch ref %s from %s\n",
|
"Unable to fetch ref %s from %s\n",
|
||||||
ls->dentry_name, remote->url);
|
ls->dentry_name, repo->url);
|
||||||
aborted = 1;
|
aborted = 1;
|
||||||
free(ref);
|
free(ref);
|
||||||
return;
|
return;
|
||||||
|
@ -1931,12 +1931,12 @@ static void update_remote_info_refs(struct remote_lock *lock)
|
||||||
|
|
||||||
static int remote_exists(const char *path)
|
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 active_request_slot *slot;
|
||||||
struct slot_results results;
|
struct slot_results results;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
sprintf(url, "%s%s", remote->url, path);
|
sprintf(url, "%s%s", repo->url, path);
|
||||||
|
|
||||||
slot = get_active_slot();
|
slot = get_active_slot();
|
||||||
slot->results = &results;
|
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 active_request_slot *slot;
|
||||||
struct slot_results results;
|
struct slot_results results;
|
||||||
|
|
||||||
url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||||
sprintf(url, "%s%s", remote->url, path);
|
sprintf(url, "%s%s", repo->url, path);
|
||||||
|
|
||||||
slot = get_active_slot();
|
slot = get_active_slot();
|
||||||
slot->results = &results;
|
slot->results = &results;
|
||||||
|
@ -2082,7 +2082,7 @@ static int delete_remote_branch(char *pattern, int force)
|
||||||
"of your current HEAD.\n"
|
"of your current HEAD.\n"
|
||||||
"If you are sure you want to delete it,"
|
"If you are sure you want to delete it,"
|
||||||
" run:\n\t'git http-push -D %s %s'",
|
" 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);
|
fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name);
|
||||||
if (dry_run)
|
if (dry_run)
|
||||||
return 0;
|
return 0;
|
||||||
url = xmalloc(strlen(remote->url) + strlen(remote_ref->name) + 1);
|
url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1);
|
||||||
sprintf(url, "%s%s", remote->url, remote_ref->name);
|
sprintf(url, "%s%s", repo->url, remote_ref->name);
|
||||||
slot = get_active_slot();
|
slot = get_active_slot();
|
||||||
slot->results = &results;
|
slot->results = &results;
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
|
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
|
||||||
|
@ -2128,13 +2128,14 @@ int main(int argc, char **argv)
|
||||||
int i;
|
int i;
|
||||||
int new_refs;
|
int new_refs;
|
||||||
struct ref *ref, *local_refs;
|
struct ref *ref, *local_refs;
|
||||||
|
struct remote *remote;
|
||||||
char *rewritten_url = NULL;
|
char *rewritten_url = NULL;
|
||||||
|
|
||||||
git_extract_argv0_path(argv[0]);
|
git_extract_argv0_path(argv[0]);
|
||||||
|
|
||||||
setup_git_directory();
|
setup_git_directory();
|
||||||
|
|
||||||
remote = xcalloc(sizeof(*remote), 1);
|
repo = xcalloc(sizeof(*repo), 1);
|
||||||
|
|
||||||
argv++;
|
argv++;
|
||||||
for (i = 1; i < argc; i++, argv++) {
|
for (i = 1; i < argc; i++, argv++) {
|
||||||
|
@ -2167,14 +2168,14 @@ int main(int argc, char **argv)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!remote->url) {
|
if (!repo->url) {
|
||||||
char *path = strstr(arg, "//");
|
char *path = strstr(arg, "//");
|
||||||
remote->url = arg;
|
repo->url = arg;
|
||||||
remote->path_len = strlen(arg);
|
repo->path_len = strlen(arg);
|
||||||
if (path) {
|
if (path) {
|
||||||
remote->path = strchr(path+2, '/');
|
repo->path = strchr(path+2, '/');
|
||||||
if (remote->path)
|
if (repo->path)
|
||||||
remote->path_len = strlen(remote->path);
|
repo->path_len = strlen(repo->path);
|
||||||
}
|
}
|
||||||
continue;
|
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");
|
die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!remote->url)
|
if (!repo->url)
|
||||||
usage(http_push_usage);
|
usage(http_push_usage);
|
||||||
|
|
||||||
if (delete_branch && nr_refspec != 1)
|
if (delete_branch && nr_refspec != 1)
|
||||||
|
@ -2195,17 +2196,24 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
memset(remote_dir_exists, -1, 256);
|
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:");
|
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
|
||||||
|
|
||||||
if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
|
if (repo->url && repo->url[strlen(repo->url)-1] != '/') {
|
||||||
rewritten_url = xmalloc(strlen(remote->url)+2);
|
rewritten_url = xmalloc(strlen(repo->url)+2);
|
||||||
strcpy(rewritten_url, remote->url);
|
strcpy(rewritten_url, repo->url);
|
||||||
strcat(rewritten_url, "/");
|
strcat(rewritten_url, "/");
|
||||||
remote->path = rewritten_url + (remote->path - remote->url);
|
repo->path = rewritten_url + (repo->path - repo->url);
|
||||||
remote->path_len++;
|
repo->path_len++;
|
||||||
remote->url = rewritten_url;
|
repo->url = rewritten_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify DAV compliance/lock support */
|
/* Verify DAV compliance/lock support */
|
||||||
|
@ -2217,20 +2225,20 @@ int main(int argc, char **argv)
|
||||||
sigchain_push_common(remove_locks_on_signal);
|
sigchain_push_common(remove_locks_on_signal);
|
||||||
|
|
||||||
/* Check whether the remote has server info files */
|
/* Check whether the remote has server info files */
|
||||||
remote->can_update_info_refs = 0;
|
repo->can_update_info_refs = 0;
|
||||||
remote->has_info_refs = remote_exists("info/refs");
|
repo->has_info_refs = remote_exists("info/refs");
|
||||||
remote->has_info_packs = remote_exists("objects/info/packs");
|
repo->has_info_packs = remote_exists("objects/info/packs");
|
||||||
if (remote->has_info_refs) {
|
if (repo->has_info_refs) {
|
||||||
info_ref_lock = lock_remote("info/refs", LOCK_TIME);
|
info_ref_lock = lock_remote("info/refs", LOCK_TIME);
|
||||||
if (info_ref_lock)
|
if (info_ref_lock)
|
||||||
remote->can_update_info_refs = 1;
|
repo->can_update_info_refs = 1;
|
||||||
else {
|
else {
|
||||||
error("cannot lock existing info/refs");
|
error("cannot lock existing info/refs");
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (remote->has_info_packs)
|
if (repo->has_info_packs)
|
||||||
fetch_indices();
|
fetch_indices();
|
||||||
|
|
||||||
/* Get a list of all local and remote heads to validate refspecs */
|
/* 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 */
|
/* Update remote server info if appropriate */
|
||||||
if (remote->has_info_refs && new_refs) {
|
if (repo->has_info_refs && new_refs) {
|
||||||
if (info_ref_lock && remote->can_update_info_refs) {
|
if (info_ref_lock && repo->can_update_info_refs) {
|
||||||
fprintf(stderr, "Updating remote server info\n");
|
fprintf(stderr, "Updating remote server info\n");
|
||||||
if (!dry_run)
|
if (!dry_run)
|
||||||
update_remote_info_refs(info_ref_lock);
|
update_remote_info_refs(info_ref_lock);
|
||||||
|
@ -2402,7 +2410,7 @@ int main(int argc, char **argv)
|
||||||
free(rewritten_url);
|
free(rewritten_url);
|
||||||
if (info_ref_lock)
|
if (info_ref_lock)
|
||||||
unlock_remote(info_ref_lock);
|
unlock_remote(info_ref_lock);
|
||||||
free(remote);
|
free(repo);
|
||||||
|
|
||||||
curl_slist_free_all(no_pragma_header);
|
curl_slist_free_all(no_pragma_header);
|
||||||
|
|
||||||
|
|
169
http.c
169
http.c
|
@ -1,7 +1,7 @@
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
|
|
||||||
int data_received;
|
int data_received;
|
||||||
int active_requests = 0;
|
int active_requests;
|
||||||
|
|
||||||
#ifdef USE_CURL_MULTI
|
#ifdef USE_CURL_MULTI
|
||||||
static int max_requests = -1;
|
static int max_requests = -1;
|
||||||
|
@ -13,22 +13,23 @@ static CURL *curl_default;
|
||||||
char curl_errorstr[CURL_ERROR_SIZE];
|
char curl_errorstr[CURL_ERROR_SIZE];
|
||||||
|
|
||||||
static int curl_ssl_verify = -1;
|
static int curl_ssl_verify = -1;
|
||||||
static const char *ssl_cert = NULL;
|
static const char *ssl_cert;
|
||||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||||
static const char *ssl_key = NULL;
|
static const char *ssl_key;
|
||||||
#endif
|
#endif
|
||||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||||
static const char *ssl_capath = NULL;
|
static const char *ssl_capath;
|
||||||
#endif
|
#endif
|
||||||
static const char *ssl_cainfo = NULL;
|
static const char *ssl_cainfo;
|
||||||
static long curl_low_speed_limit = -1;
|
static long curl_low_speed_limit = -1;
|
||||||
static long curl_low_speed_time = -1;
|
static long curl_low_speed_time = -1;
|
||||||
static int curl_ftp_no_epsv = 0;
|
static int curl_ftp_no_epsv;
|
||||||
static const char *curl_http_proxy = NULL;
|
static const char *curl_http_proxy;
|
||||||
|
static char *user_name, *user_pass;
|
||||||
|
|
||||||
static struct curl_slist *pragma_header;
|
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_)
|
size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
||||||
{
|
{
|
||||||
|
@ -94,53 +95,33 @@ static void process_curl_messages(void)
|
||||||
static int http_options(const char *var, const char *value, void *cb)
|
static int http_options(const char *var, const char *value, void *cb)
|
||||||
{
|
{
|
||||||
if (!strcmp("http.sslverify", var)) {
|
if (!strcmp("http.sslverify", var)) {
|
||||||
if (curl_ssl_verify == -1) {
|
curl_ssl_verify = git_config_bool(var, value);
|
||||||
curl_ssl_verify = git_config_bool(var, value);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp("http.sslcert", var)) {
|
|
||||||
if (ssl_cert == NULL)
|
|
||||||
return git_config_string(&ssl_cert, var, value);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp("http.sslcert", var))
|
||||||
|
return git_config_string(&ssl_cert, var, value);
|
||||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||||
if (!strcmp("http.sslkey", var)) {
|
if (!strcmp("http.sslkey", var))
|
||||||
if (ssl_key == NULL)
|
return git_config_string(&ssl_key, var, value);
|
||||||
return git_config_string(&ssl_key, var, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||||
if (!strcmp("http.sslcapath", var)) {
|
if (!strcmp("http.sslcapath", var))
|
||||||
if (ssl_capath == NULL)
|
return git_config_string(&ssl_capath, var, value);
|
||||||
return git_config_string(&ssl_capath, var, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (!strcmp("http.sslcainfo", var)) {
|
if (!strcmp("http.sslcainfo", var))
|
||||||
if (ssl_cainfo == NULL)
|
return git_config_string(&ssl_cainfo, var, value);
|
||||||
return git_config_string(&ssl_cainfo, var, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_CURL_MULTI
|
#ifdef USE_CURL_MULTI
|
||||||
if (!strcmp("http.maxrequests", var)) {
|
if (!strcmp("http.maxrequests", var)) {
|
||||||
if (max_requests == -1)
|
max_requests = git_config_int(var, value);
|
||||||
max_requests = git_config_int(var, value);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!strcmp("http.lowspeedlimit", var)) {
|
if (!strcmp("http.lowspeedlimit", var)) {
|
||||||
if (curl_low_speed_limit == -1)
|
curl_low_speed_limit = (long)git_config_int(var, value);
|
||||||
curl_low_speed_limit = (long)git_config_int(var, value);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!strcmp("http.lowspeedtime", var)) {
|
if (!strcmp("http.lowspeedtime", var)) {
|
||||||
if (curl_low_speed_time == -1)
|
curl_low_speed_time = (long)git_config_int(var, value);
|
||||||
curl_low_speed_time = (long)git_config_int(var, value);
|
|
||||||
return 0;
|
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);
|
curl_ftp_no_epsv = git_config_bool(var, value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!strcmp("http.proxy", var)) {
|
if (!strcmp("http.proxy", var))
|
||||||
if (curl_http_proxy == NULL)
|
return git_config_string(&curl_http_proxy, var, value);
|
||||||
return git_config_string(&curl_http_proxy, var, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fall back on the default ones */
|
/* Fall back on the default ones */
|
||||||
return git_default_config(var, value, cb);
|
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) {
|
if (!curl_ssl_verify) {
|
||||||
curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
|
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);
|
curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
init_curl_http_auth(result);
|
||||||
|
|
||||||
if (ssl_cert != NULL)
|
if (ssl_cert != NULL)
|
||||||
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
|
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
|
||||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||||
|
@ -213,11 +205,60 @@ static CURL* get_curl_handle(void)
|
||||||
return result;
|
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)
|
void http_init(struct remote *remote)
|
||||||
{
|
{
|
||||||
char *low_speed_limit;
|
char *low_speed_limit;
|
||||||
char *low_speed_time;
|
char *low_speed_time;
|
||||||
|
|
||||||
|
git_config(http_options, NULL);
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
|
||||||
if (remote && remote->http_proxy)
|
if (remote && remote->http_proxy)
|
||||||
|
@ -242,14 +283,14 @@ void http_init(struct remote *remote)
|
||||||
if (getenv("GIT_SSL_NO_VERIFY"))
|
if (getenv("GIT_SSL_NO_VERIFY"))
|
||||||
curl_ssl_verify = 0;
|
curl_ssl_verify = 0;
|
||||||
|
|
||||||
ssl_cert = getenv("GIT_SSL_CERT");
|
set_from_env(&ssl_cert, "GIT_SSL_CERT");
|
||||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||||
ssl_key = getenv("GIT_SSL_KEY");
|
set_from_env(&ssl_key, "GIT_SSL_KEY");
|
||||||
#endif
|
#endif
|
||||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||||
ssl_capath = getenv("GIT_SSL_CAPATH");
|
set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
|
||||||
#endif
|
#endif
|
||||||
ssl_cainfo = getenv("GIT_SSL_CAINFO");
|
set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
|
||||||
|
|
||||||
low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
|
low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
|
||||||
if (low_speed_limit != NULL)
|
if (low_speed_limit != NULL)
|
||||||
|
@ -258,8 +299,6 @@ void http_init(struct remote *remote)
|
||||||
if (low_speed_time != NULL)
|
if (low_speed_time != NULL)
|
||||||
curl_low_speed_time = strtol(low_speed_time, NULL, 10);
|
curl_low_speed_time = strtol(low_speed_time, NULL, 10);
|
||||||
|
|
||||||
git_config(http_options, NULL);
|
|
||||||
|
|
||||||
if (curl_ssl_verify == -1)
|
if (curl_ssl_verify == -1)
|
||||||
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"))
|
if (getenv("GIT_CURL_FTP_NO_EPSV"))
|
||||||
curl_ftp_no_epsv = 1;
|
curl_ftp_no_epsv = 1;
|
||||||
|
|
||||||
|
if (remote && remote->url && remote->url[0])
|
||||||
|
http_auth_init(remote->url[0]);
|
||||||
|
|
||||||
#ifndef NO_CURL_EASY_DUPHANDLE
|
#ifndef NO_CURL_EASY_DUPHANDLE
|
||||||
curl_default = get_curl_handle();
|
curl_default = get_curl_handle();
|
||||||
#endif
|
#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 */
|
/* Wait for a slot to open up if the queue is full */
|
||||||
while (active_requests >= max_requests) {
|
while (active_requests >= max_requests) {
|
||||||
curl_multi_perform(curlm, &num_transfers);
|
curl_multi_perform(curlm, &num_transfers);
|
||||||
if (num_transfers < active_requests) {
|
if (num_transfers < active_requests)
|
||||||
process_curl_messages();
|
process_curl_messages();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (slot != NULL && slot->in_use) {
|
while (slot != NULL && slot->in_use)
|
||||||
slot = slot->next;
|
slot = slot->next;
|
||||||
}
|
|
||||||
if (slot == NULL) {
|
if (slot == NULL) {
|
||||||
newslot = xmalloc(sizeof(*newslot));
|
newslot = xmalloc(sizeof(*newslot));
|
||||||
newslot->curl = NULL;
|
newslot->curl = NULL;
|
||||||
|
@ -341,9 +382,8 @@ struct active_request_slot *get_active_slot(void)
|
||||||
if (slot == NULL) {
|
if (slot == NULL) {
|
||||||
active_queue_head = newslot;
|
active_queue_head = newslot;
|
||||||
} else {
|
} else {
|
||||||
while (slot->next != NULL) {
|
while (slot->next != NULL)
|
||||||
slot = slot->next;
|
slot = slot->next;
|
||||||
}
|
|
||||||
slot->next = newslot;
|
slot->next = newslot;
|
||||||
}
|
}
|
||||||
slot = newslot;
|
slot = newslot;
|
||||||
|
@ -404,7 +444,7 @@ struct fill_chain {
|
||||||
struct fill_chain *next;
|
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 *))
|
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 */
|
/* Run callback if appropriate */
|
||||||
if (slot->callback_func != NULL) {
|
if (slot->callback_func != NULL)
|
||||||
slot->callback_func(slot->callback_data);
|
slot->callback_func(slot->callback_data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish_all_active_slots(void)
|
void finish_all_active_slots(void)
|
||||||
|
@ -567,8 +606,10 @@ static inline int needs_quote(int ch)
|
||||||
|
|
||||||
static inline int hex(int v)
|
static inline int hex(int v)
|
||||||
{
|
{
|
||||||
if (v < 10) return '0' + v;
|
if (v < 10)
|
||||||
else return 'A' + v - 10;
|
return '0' + v;
|
||||||
|
else
|
||||||
|
return 'A' + v - 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *quote_ref_url(const char *base, const char *ref)
|
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;
|
struct mailmap_entry *me;
|
||||||
int index;
|
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) {
|
if (old_email == NULL) {
|
||||||
old_email = new_email;
|
old_email = new_email;
|
||||||
new_email = NULL;
|
new_email = NULL;
|
||||||
|
@ -90,7 +99,8 @@ static void add_mapping(struct string_list *map,
|
||||||
old_name, old_email, new_name, new_email);
|
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;
|
char *left, *right, *nstart, *nend;
|
||||||
*name = *email = 0;
|
*name = *email = 0;
|
||||||
|
@ -99,7 +109,7 @@ static char *parse_name_and_email(char *buffer, char **name, char **email)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((right = strchr(left+1, '>')) == NULL)
|
if ((right = strchr(left+1, '>')) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (left+1 == right)
|
if (!allow_empty_email && (left+1 == right))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* remove whitespace from beginning and end of name */
|
/* 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;
|
continue;
|
||||||
}
|
}
|
||||||
if ((name2 = parse_name_and_email(buffer, &name1, &email1)) != NULL)
|
if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
|
||||||
parse_name_and_email(name2, &name2, &email2);
|
parse_name_and_email(name2, &name2, &email2, 1);
|
||||||
|
|
||||||
if (email1)
|
if (email1)
|
||||||
add_mapping(map, name1, email1, name2, email2);
|
add_mapping(map, name1, email1, name2, email2);
|
||||||
|
|
93
patch-ids.c
93
patch-ids.c
|
@ -1,6 +1,7 @@
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "diff.h"
|
#include "diff.h"
|
||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
|
#include "sha1-lookup.h"
|
||||||
#include "patch-ids.h"
|
#include "patch-ids.h"
|
||||||
|
|
||||||
static int commit_patch_id(struct commit *commit, struct diff_options *options,
|
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);
|
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)
|
static int patch_pos(struct patch_id **table, int nr, const unsigned char *id)
|
||||||
{
|
{
|
||||||
int hi = nr;
|
return sha1_pos(id, table, nr, patch_id_access);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BUCKET_SIZE 190 /* 190 * 21 = 3990, with slop close enough to 4K */
|
#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,
|
void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
||||||
int relative_date)
|
enum date_mode dmode)
|
||||||
{
|
{
|
||||||
if (info && info->last_commit_reflog) {
|
if (info && info->last_commit_reflog) {
|
||||||
struct commit_reflog *commit_reflog = 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];
|
info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
|
||||||
if (oneline) {
|
if (oneline) {
|
||||||
printf("%s@{", commit_reflog->reflogs->ref);
|
printf("%s@{", commit_reflog->reflogs->ref);
|
||||||
if (commit_reflog->flag || relative_date)
|
if (commit_reflog->flag || dmode)
|
||||||
printf("%s", show_date(info->timestamp, 0, 1));
|
printf("%s", show_date(info->timestamp,
|
||||||
|
info->tz,
|
||||||
|
dmode));
|
||||||
else
|
else
|
||||||
printf("%d", commit_reflog->reflogs->nr
|
printf("%d", commit_reflog->reflogs->nr
|
||||||
- 2 - commit_reflog->recno);
|
- 2 - commit_reflog->recno);
|
||||||
|
@ -260,10 +262,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Reflog: %s@{", commit_reflog->reflogs->ref);
|
printf("Reflog: %s@{", commit_reflog->reflogs->ref);
|
||||||
if (commit_reflog->flag || relative_date)
|
if (commit_reflog->flag || dmode)
|
||||||
printf("%s", show_date(info->timestamp,
|
printf("%s", show_date(info->timestamp,
|
||||||
info->tz,
|
info->tz,
|
||||||
relative_date));
|
dmode));
|
||||||
else
|
else
|
||||||
printf("%d", commit_reflog->reflogs->nr
|
printf("%d", commit_reflog->reflogs->nr
|
||||||
- 2 - commit_reflog->recno);
|
- 2 - commit_reflog->recno);
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#ifndef REFLOG_WALK_H
|
#ifndef REFLOG_WALK_H
|
||||||
#define REFLOG_WALK_H
|
#define REFLOG_WALK_H
|
||||||
|
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
extern void init_reflog_walk(struct reflog_walk_info** info);
|
extern void init_reflog_walk(struct reflog_walk_info** info);
|
||||||
extern int add_reflog_for_walk(struct reflog_walk_info *info,
|
extern int add_reflog_for_walk(struct reflog_walk_info *info,
|
||||||
struct commit *commit, const char *name);
|
struct commit *commit, const char *name);
|
||||||
extern void fake_reflog_parent(struct reflog_walk_info *info,
|
extern void fake_reflog_parent(struct reflog_walk_info *info,
|
||||||
struct commit *commit);
|
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
|
#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[] = {
|
const char *ref_rev_parse_rules[] = {
|
||||||
"%.*s",
|
"%.*s",
|
||||||
"refs/%.*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)
|
#define CHECK_REF_FORMAT_WILDCARD (-3)
|
||||||
extern int check_ref_format(const char *target);
|
extern int check_ref_format(const char *target);
|
||||||
|
|
||||||
|
extern const char *prettify_ref(const struct ref *ref);
|
||||||
|
|
||||||
/** rename ref, return 0 on success **/
|
/** rename ref, return 0 on success **/
|
||||||
extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
|
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)
|
if (theirs == ours)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run "rev-list --left-right ours...theirs" internally... */
|
/* Run "rev-list --no-merges --left-right ours...theirs" internally... */
|
||||||
rev_argc = 0;
|
rev_argc = 0;
|
||||||
rev_argv[rev_argc++] = NULL;
|
rev_argv[rev_argc++] = NULL;
|
||||||
|
rev_argv[rev_argc++] = "--no-merges";
|
||||||
rev_argv[rev_argc++] = "--left-right";
|
rev_argv[rev_argc++] = "--left-right";
|
||||||
rev_argv[rev_argc++] = symmetric;
|
rev_argv[rev_argc++] = symmetric;
|
||||||
rev_argv[rev_argc++] = "--";
|
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;
|
revs->edge_hint = 1;
|
||||||
} else if (!strcmp(arg, "--unpacked")) {
|
} else if (!strcmp(arg, "--unpacked")) {
|
||||||
revs->unpacked = 1;
|
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=")) {
|
} else if (!prefixcmp(arg, "--unpacked=")) {
|
||||||
die("--unpacked=<packfile> no longer supported.");
|
die("--unpacked=<packfile> no longer supported.");
|
||||||
} else if (!strcmp(arg, "-r")) {
|
} 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)
|
if (commit->object.flags & SHOWN)
|
||||||
return commit_ignore;
|
return commit_ignore;
|
||||||
if (revs->unpacked &&
|
if (revs->unpacked && has_sha1_pack(commit->object.sha1))
|
||||||
(revs->kept_pack_only
|
|
||||||
? has_sha1_kept_pack(commit->object.sha1)
|
|
||||||
: has_sha1_pack(commit->object.sha1)))
|
|
||||||
return commit_ignore;
|
return commit_ignore;
|
||||||
if (revs->show_all)
|
if (revs->show_all)
|
||||||
return commit_show;
|
return commit_show;
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct rev_info {
|
||||||
edge_hint:1,
|
edge_hint:1,
|
||||||
limited:1,
|
limited:1,
|
||||||
unpacked:1,
|
unpacked:1,
|
||||||
kept_pack_only:1,
|
|
||||||
boundary:2,
|
boundary:2,
|
||||||
left_right:1,
|
left_right:1,
|
||||||
rewrite_parents:1,
|
rewrite_parents:1,
|
||||||
|
|
|
@ -10,7 +10,7 @@ enum {
|
||||||
ERR_RUN_COMMAND_WAITPID_SIGNAL,
|
ERR_RUN_COMMAND_WAITPID_SIGNAL,
|
||||||
ERR_RUN_COMMAND_WAITPID_NOEXIT,
|
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 {
|
struct child_process {
|
||||||
const char **argv;
|
const char **argv;
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
#define SEND_PACK_H
|
#define SEND_PACK_H
|
||||||
|
|
||||||
struct send_pack_args {
|
struct send_pack_args {
|
||||||
const char *receivepack;
|
|
||||||
unsigned verbose:1,
|
unsigned verbose:1,
|
||||||
send_all:1,
|
|
||||||
send_mirror:1,
|
send_mirror:1,
|
||||||
force_update:1,
|
force_update:1,
|
||||||
use_thin_pack:1,
|
use_thin_pack:1,
|
||||||
|
@ -12,7 +10,7 @@ struct send_pack_args {
|
||||||
};
|
};
|
||||||
|
|
||||||
int send_pack(struct send_pack_args *args,
|
int send_pack(struct send_pack_args *args,
|
||||||
const char *dest, struct remote *remote,
|
int fd[], struct child_process *conn,
|
||||||
int nr_heads, const char **heads);
|
struct ref *remote_refs, struct extra_have_objects *extra_have);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
101
sha1-lookup.c
101
sha1-lookup.c
|
@ -1,6 +1,107 @@
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "sha1-lookup.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:
|
* Conventional binary search loop looks like this:
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
#ifndef SHA1_LOOKUP_H
|
#ifndef SHA1_LOOKUP_H
|
||||||
#define 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,
|
extern int sha1_entry_pos(const void *table,
|
||||||
size_t elem_size,
|
size_t elem_size,
|
||||||
size_t key_offset,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
|
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
|
||||||
int kept_pack_only)
|
|
||||||
{
|
{
|
||||||
static struct packed_git *last_found = (void *)1;
|
static struct packed_git *last_found = (void *)1;
|
||||||
struct packed_git *p;
|
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;
|
p = (last_found == (void *)1) ? packed_git : last_found;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (kept_pack_only && !p->pack_keep)
|
|
||||||
goto next;
|
|
||||||
if (p->num_bad_objects) {
|
if (p->num_bad_objects) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < p->num_bad_objects; 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;
|
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 *find_sha1_pack(const unsigned char *sha1,
|
||||||
struct packed_git *packs)
|
struct packed_git *packs)
|
||||||
{
|
{
|
||||||
|
@ -2456,12 +2443,6 @@ int has_sha1_pack(const unsigned char *sha1)
|
||||||
return find_pack_entry(sha1, &e);
|
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)
|
int has_sha1_file(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
struct pack_entry e;
|
struct pack_entry e;
|
||||||
|
|
|
@ -24,7 +24,7 @@ pre-clean:
|
||||||
$(RM) -r test-results
|
$(RM) -r test-results
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) -r 'trash directory' test-results
|
$(RM) -r 'trash directory'.* test-results
|
||||||
|
|
||||||
aggregate-results-and-cleanup: $(T)
|
aggregate-results-and-cleanup: $(T)
|
||||||
$(MAKE) aggregate-results
|
$(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)' '
|
test_expect_success 'invalid .gitattributes (must not crash)' '
|
||||||
|
|
||||||
echo "three +crlf" >>.gitattributes &&
|
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' \
|
test_expect_success 'test deleting branch without config' \
|
||||||
'git branch my7 s &&
|
'git branch my7 s &&
|
||||||
sha1=$(git rev-parse my7 | cut -c 1-7) &&
|
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' \
|
test_expect_success 'test --track without .fetch entries' \
|
||||||
'git branch --track my8 &&
|
'git branch --track my8 &&
|
||||||
|
|
|
@ -128,6 +128,21 @@ test_expect_success 'additional command line cc' '
|
||||||
grep "^ *S. E. Cipient <scipient@example.com>$" patch5
|
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' '
|
test_expect_success 'multiple files' '
|
||||||
|
|
||||||
rm -rf patches/ &&
|
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
|
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
|
test_done
|
||||||
|
|
|
@ -7,6 +7,7 @@ test_description='GIT_EDITOR, core.editor, and stuff'
|
||||||
for i in GIT_EDITOR core_editor EDITOR VISUAL vi
|
for i in GIT_EDITOR core_editor EDITOR VISUAL vi
|
||||||
do
|
do
|
||||||
cat >e-$i.sh <<-EOF
|
cat >e-$i.sh <<-EOF
|
||||||
|
#!$SHELL_PATH
|
||||||
echo "Edited by $i" >"\$1"
|
echo "Edited by $i" >"\$1"
|
||||||
EOF
|
EOF
|
||||||
chmod +x e-$i.sh
|
chmod +x e-$i.sh
|
||||||
|
|
|
@ -234,7 +234,7 @@ cat >.git/FAKE_EDITOR <<EOF
|
||||||
# kill -TERM command added below.
|
# kill -TERM command added below.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
test_expect_success 'a SIGTERM should break locks' '
|
test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' '
|
||||||
echo >>negative &&
|
echo >>negative &&
|
||||||
! "$SHELL_PATH" -c '\''
|
! "$SHELL_PATH" -c '\''
|
||||||
echo kill -TERM $$ >> .git/FAKE_EDITOR
|
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
|
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
|
test_done
|
||||||
|
|
||||||
|
|
|
@ -421,8 +421,8 @@ test_confirm () {
|
||||||
--from="Example <nobody@example.com>" \
|
--from="Example <nobody@example.com>" \
|
||||||
--to=nobody@example.com \
|
--to=nobody@example.com \
|
||||||
--smtp-server="$(pwd)/fake.sendmail" \
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
$@ \
|
$@ $patches > stdout &&
|
||||||
$patches | grep "Send this email"
|
grep "Send this email" stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
test_expect_success '--confirm=always' '
|
test_expect_success '--confirm=always' '
|
||||||
|
@ -444,8 +444,10 @@ test_expect_success '--confirm=compose' '
|
||||||
test_expect_success 'confirm by default (due to cc)' '
|
test_expect_success 'confirm by default (due to cc)' '
|
||||||
CONFIRM=$(git config --get sendemail.confirm) &&
|
CONFIRM=$(git config --get sendemail.confirm) &&
|
||||||
git config --unset sendemail.confirm &&
|
git config --unset sendemail.confirm &&
|
||||||
test_confirm &&
|
test_confirm
|
||||||
git config sendemail.confirm $CONFIRM
|
ret="$?"
|
||||||
|
git config sendemail.confirm ${CONFIRM:-never}
|
||||||
|
test $ret = "0"
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'confirm by default (due to --compose)' '
|
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 $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' '
|
test_expect_success '--compose adds MIME for utf8 body' '
|
||||||
clean_fake_sendmail &&
|
clean_fake_sendmail &&
|
||||||
(echo "#!$SHELL_PATH" &&
|
(echo "#!$SHELL_PATH" &&
|
||||||
|
|
|
@ -8,6 +8,9 @@ test_description='git fast-export'
|
||||||
|
|
||||||
test_expect_success 'setup' '
|
test_expect_success 'setup' '
|
||||||
|
|
||||||
|
echo break it > file0 &&
|
||||||
|
git add file0 &&
|
||||||
|
test_tick &&
|
||||||
echo Wohlauf > file &&
|
echo Wohlauf > file &&
|
||||||
git add file &&
|
git add file &&
|
||||||
test_tick &&
|
test_tick &&
|
||||||
|
@ -57,8 +60,8 @@ test_expect_success 'fast-export master~2..master' '
|
||||||
(cd new &&
|
(cd new &&
|
||||||
git fast-import &&
|
git fast-import &&
|
||||||
test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
|
test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
|
||||||
git diff master..partial &&
|
git diff --exit-code master partial &&
|
||||||
git diff master^..partial^ &&
|
git diff --exit-code master^ partial^ &&
|
||||||
test_must_fail git rev-parse partial~2)
|
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
|
test_done
|
||||||
|
|
|
@ -523,14 +523,6 @@ test_done () {
|
||||||
fi
|
fi
|
||||||
case "$test_failure" in
|
case "$test_failure" in
|
||||||
0)
|
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"
|
say_color pass "passed all $msg"
|
||||||
|
|
||||||
test -d "$remove_trash" &&
|
test -d "$remove_trash" &&
|
||||||
|
@ -697,10 +689,12 @@ case $(uname -s) in
|
||||||
}
|
}
|
||||||
# no POSIX permissions
|
# no POSIX permissions
|
||||||
# backslashes in pathspec are converted to '/'
|
# backslashes in pathspec are converted to '/'
|
||||||
|
# exec does not inherit the PID
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
test_set_prereq POSIXPERM
|
test_set_prereq POSIXPERM
|
||||||
test_set_prereq BSLASHPSPEC
|
test_set_prereq BSLASHPSPEC
|
||||||
|
test_set_prereq EXECKEEPSPID
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
283
transport.c
283
transport.c
|
@ -143,7 +143,7 @@ static const char *rsync_url(const char *url)
|
||||||
return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : 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 strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
|
||||||
struct ref dummy, *tail = &dummy;
|
struct ref dummy, *tail = &dummy;
|
||||||
|
@ -151,6 +151,9 @@ static struct ref *get_refs_via_rsync(struct transport *transport)
|
||||||
const char *args[5];
|
const char *args[5];
|
||||||
int temp_dir_len;
|
int temp_dir_len;
|
||||||
|
|
||||||
|
if (for_push)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* copy the refs to the temporary directory */
|
/* copy the refs to the temporary directory */
|
||||||
|
|
||||||
strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
|
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;
|
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;
|
struct strbuf buffer = STRBUF_INIT;
|
||||||
char *data, *start, *mid;
|
char *data, *start, *mid;
|
||||||
|
@ -446,6 +449,9 @@ static struct ref *get_refs_via_curl(struct transport *transport)
|
||||||
|
|
||||||
struct walker *walker;
|
struct walker *walker;
|
||||||
|
|
||||||
|
if (for_push)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (!transport->data)
|
if (!transport->data)
|
||||||
transport->data = get_http_walker(transport->url,
|
transport->data = get_http_walker(transport->url,
|
||||||
transport->remote);
|
transport->remote);
|
||||||
|
@ -532,12 +538,15 @@ struct bundle_transport_data {
|
||||||
struct bundle_header header;
|
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 bundle_transport_data *data = transport->data;
|
||||||
struct ref *result = NULL;
|
struct ref *result = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (for_push)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (data->fd > 0)
|
if (data->fd > 0)
|
||||||
close(data->fd);
|
close(data->fd);
|
||||||
data->fd = read_bundle_header(transport->url, &data->header);
|
data->fd = read_bundle_header(transport->url, &data->header);
|
||||||
|
@ -578,6 +587,7 @@ struct git_transport_data {
|
||||||
int fd[2];
|
int fd[2];
|
||||||
const char *uploadpack;
|
const char *uploadpack;
|
||||||
const char *receivepack;
|
const char *receivepack;
|
||||||
|
struct extra_have_objects extra_have;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int set_git_option(struct transport *connection,
|
static int set_git_option(struct transport *connection,
|
||||||
|
@ -609,20 +619,23 @@ static int set_git_option(struct transport *connection,
|
||||||
return 1;
|
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;
|
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;
|
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 git_transport_data *data = transport->data;
|
||||||
struct ref *refs;
|
struct ref *refs;
|
||||||
|
|
||||||
connect_setup(transport);
|
connect_setup(transport, for_push, 0);
|
||||||
get_remote_heads(data->fd[0], &refs, 0, NULL, 0, NULL);
|
get_remote_heads(data->fd[0], &refs, 0, NULL,
|
||||||
|
for_push ? REF_NORMAL : 0, &data->extra_have);
|
||||||
|
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
@ -654,7 +667,7 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||||
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
|
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
|
||||||
|
|
||||||
if (!data->conn) {
|
if (!data->conn) {
|
||||||
connect_setup(transport);
|
connect_setup(transport, 0, 0);
|
||||||
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
|
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);
|
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 git_transport_data *data = transport->data;
|
||||||
struct send_pack_args args;
|
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.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
|
||||||
args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
|
args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
|
||||||
args.use_thin_pack = data->thin;
|
args.use_thin_pack = data->thin;
|
||||||
args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
|
args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
|
||||||
args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
|
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)
|
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->set_option = set_git_option;
|
||||||
ret->get_refs_list = get_refs_via_connect;
|
ret->get_refs_list = get_refs_via_connect;
|
||||||
ret->fetch = fetch_refs_via_pack;
|
ret->fetch = fetch_refs_via_pack;
|
||||||
ret->push = git_transport_push;
|
ret->push_refs = git_transport_push;
|
||||||
ret->disconnect = disconnect_git;
|
ret->disconnect = disconnect_git;
|
||||||
|
|
||||||
data->thin = 1;
|
data->thin = 1;
|
||||||
|
@ -787,15 +996,53 @@ int transport_set_option(struct transport *transport,
|
||||||
int transport_push(struct transport *transport,
|
int transport_push(struct transport *transport,
|
||||||
int refspec_nr, const char **refspec, int flags)
|
int refspec_nr, const char **refspec, int flags)
|
||||||
{
|
{
|
||||||
if (!transport->push)
|
verify_remote_names(refspec_nr, refspec);
|
||||||
return 1;
|
|
||||||
return transport->push(transport, refspec_nr, refspec, flags);
|
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)
|
const struct ref *transport_get_remote_refs(struct transport *transport)
|
||||||
{
|
{
|
||||||
if (!transport->remote_refs)
|
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;
|
return transport->remote_refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@ struct transport {
|
||||||
int (*set_option)(struct transport *connection, const char *name,
|
int (*set_option)(struct transport *connection, const char *name,
|
||||||
const char *value);
|
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 (*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 (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
|
||||||
|
|
||||||
int (*disconnect)(struct transport *connection);
|
int (*disconnect)(struct transport *connection);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "unpack-trees.h"
|
#include "unpack-trees.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
|
#include "attr.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error messages expected by scripts out of plumbing commands such as
|
* 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;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
|
||||||
for (i = 0; i < index->cache_nr; i++) {
|
for (i = 0; i < index->cache_nr; i++) {
|
||||||
struct cache_entry *ce = index->cache[i];
|
struct cache_entry *ce = index->cache[i];
|
||||||
|
|
||||||
|
@ -110,6 +112,7 @@ static int check_updates(struct unpack_trees_options *o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stop_progress(&progress);
|
stop_progress(&progress);
|
||||||
|
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
|
||||||
return errs != 0;
|
return errs != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче