Merge branch 'wk/user-manual' into maint
authorJunio C Hamano <gitster@pobox.com>
Fri, 1 Mar 2013 18:37:40 +0000 (10:37 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 1 Mar 2013 18:37:40 +0000 (10:37 -0800)
* wk/user-manual:
user-manual: Flesh out uncommitted changes and submodule updates
user-manual: Use request-pull to generate "please pull" text
user-manual: Reorganize the reroll sections, adding 'git rebase -i'

43 files changed:
Documentation/Makefile
Documentation/RelNotes/1.8.1.4.txt [new file with mode: 0644]
Documentation/RelNotes/1.8.1.5.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-bisect.txt
Documentation/git-remote-helpers.txt [deleted file]
Documentation/git-remote-helpers.txto [new file with mode: 0644]
Documentation/git-remote-testgit.txt
Documentation/git-submodule.txt
Documentation/git.txt
Documentation/githooks.txt
Documentation/gitremote-helpers.txt [new file with mode: 0644]
Documentation/urls.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
builtin/apply.c
builtin/clean.c
builtin/clone.c
combine-diff.c
git-cvsimport.perl
git-difftool--helper.sh
git-mergetool.sh
gitweb/gitweb.perl
http-push.c
http.c
http.h
imap-send.c
mergetools/p4merge
parse-options.c
perl/Git.pm
perl/Git/SVN.pm
perl/Git/SVN/Log.pm
remote-curl.c
t/lib-httpd.sh
t/lib-httpd/apache.conf
t/lib-httpd/broken-smart-http.sh [new file with mode: 0755]
t/t4038-diff-combined.sh
t/t5551-http-fetch.sh
t/t7512-status-help.sh
utf8.c
utf8.h
index 971977b8aa3cfbc97f2f60f1be051d7327c00beb..3c538e3de732f3810e5d18cae5396192b80d3c6c 100644 (file)
@@ -1,7 +1,7 @@
 MAN1_TXT= \
        $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
                $(wildcard git-*.txt)) \
-       gitk.txt gitweb.txt git.txt
+       gitk.txt gitweb.txt git.txt gitremote-helpers.txt
 MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \
        gitrepository-layout.txt gitweb.conf.txt
 MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \
@@ -13,7 +13,8 @@ MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
 MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
 MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT))
 
-DOC_HTML=$(MAN_HTML)
+OBSOLETE_HTML = git-remote-helpers.html
+DOC_HTML=$(MAN_HTML) $(OBSOLETE_HTML)
 
 ARTICLES = howto-index
 ARTICLES += everyday
@@ -261,6 +262,12 @@ $(MAN_HTML): %.html : %.txt asciidoc.conf
                $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
        mv $@+ $@
 
+$(OBSOLETE_HTML): %.html : %.txto asciidoc.conf
+       $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
+       $(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
+               $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
+       mv $@+ $@
+
 manpage-base-url.xsl: manpage-base-url.xsl.in
        sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@
 
diff --git a/Documentation/RelNotes/1.8.1.4.txt b/Documentation/RelNotes/1.8.1.4.txt
new file mode 100644 (file)
index 0000000..22af1d1
--- /dev/null
@@ -0,0 +1,11 @@
+Git 1.8.1.4 Release Notes
+=========================
+
+Fixes since v1.8.1.3
+--------------------
+
+ * "git imap-send" talking over imaps:// did make sure it received a
+   valid certificate from the other end, but did not check if the
+   certificate matched the host it thought it was talking to.
+
+Also contains various documentation fixes.
diff --git a/Documentation/RelNotes/1.8.1.5.txt b/Documentation/RelNotes/1.8.1.5.txt
new file mode 100644 (file)
index 0000000..30d30a1
--- /dev/null
@@ -0,0 +1,41 @@
+Git 1.8.1.5 Release Notes
+=========================
+
+Fixes since v1.8.1.4
+--------------------
+
+ * Given a string with a multi-byte character that begins with '-' on
+   the command line where an option is expected, the option parser
+   used just one byte of the unknown letter when reporting an error.
+
+ * "git apply --summary" has been taught to make sure the similarity
+   value shown in its output is sensible, even when the input had a
+   bogus value.
+
+ * "git clean" showed what it was going to do, but sometimes ended
+   up finding that it was not allowed to do so, which resulted in a
+   confusing output (e.g. after saying that it will remove an
+   untracked directory, it found an embedded git repository there
+   which it is not allowed to remove).  It now performs the actions
+   and then reports the outcome more faithfully.
+
+ * "git clone" used to allow --bare and --separate-git-dir=$there
+   options at the same time, which was nonsensical.
+
+ * "git cvsimport" mishandled timestamps at DST boundary.
+
+ * We used to have an arbitrary 32 limit for combined diff input,
+   resulting in incorrect number of leading colons shown when showing
+   the "--raw --cc" output.
+
+ * The smart HTTP clients forgot to verify the content-type that comes
+   back from the server side to make sure that the request is being
+   handled properly.
+
+ * "git help remote-helpers" failed to find the documentation.
+
+ * "gitweb" pages served over HTTPS, when configured to show picon or
+   gravatar, referred to these external resources to be fetched via
+   HTTP, resulting in mixed contents warning in browsers.
+
+Also contains various documentation fixes.
index e452ff89ba1f2935d6b22d030251b04db48a3cef..e37ba94a723979f5202c13033a8f8e099ec703c1 100644 (file)
@@ -168,7 +168,7 @@ advice.*::
                Advice shown when linkgit:git-merge[1] refuses to
                merge to avoid overwriting local changes.
        resolveConflict::
-               Advices shown by various commands when conflicts
+               Advice shown by various commands when conflicts
                prevent the operation from being performed.
        implicitIdentity::
                Advice on how to set your identity configuration when
@@ -1758,7 +1758,8 @@ push.default::
   +
   This is currently the default, but Git 2.0 will change the default
   to `simple`.
-* `upstream` - push the current branch to its upstream branch.
+* `upstream` - push the current branch to its upstream branch
+  (`tracking` is a deprecated synonym for this).
   With this, `git push` will update the same remote ref as the one which
   is merged by `git pull`, making `push` and `pull` symmetrical.
   See "branch.<name>.merge" for how to configure the upstream branch.
index e4f46bc18dba1e55da83e4af76b8a7f30a7f40be..038514b51e02d4429df7bb517367e63373a59ecb 100644 (file)
@@ -83,7 +83,7 @@ Bisect reset
 ~~~~~~~~~~~~
 
 After a bisect session, to clean up the bisection state and return to
-the original HEAD, issue the following command:
+the original HEAD (i.e., to quit bisecting), issue the following command:
 
 ------------------------------------------------
 $ git bisect reset
@@ -284,6 +284,7 @@ EXAMPLES
 ------------
 $ git bisect start HEAD v1.2 --      # HEAD is bad, v1.2 is good
 $ git bisect run make                # "make" builds the app
+$ git bisect reset                   # quit the bisect session
 ------------
 
 * Automatically bisect a test failure between origin and HEAD:
@@ -291,6 +292,7 @@ $ git bisect run make                # "make" builds the app
 ------------
 $ git bisect start HEAD origin --    # HEAD is bad, origin is good
 $ git bisect run make test           # "make test" builds and tests
+$ git bisect reset                   # quit the bisect session
 ------------
 
 * Automatically bisect a broken test case:
@@ -302,6 +304,7 @@ make || exit 125                     # this skips broken builds
 ~/check_test_case.sh                 # does the test case pass?
 $ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
 $ git bisect run ~/test.sh
+$ git bisect reset                   # quit the bisect session
 ------------
 +
 Here we use a "test.sh" custom script. In this script, if "make"
@@ -351,6 +354,7 @@ use `git cherry-pick` instead of `git merge`.)
 ------------
 $ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
 $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
+$ git bisect reset                   # quit the bisect session
 ------------
 +
 This shows that you can do without a run script if you write the test
@@ -368,6 +372,7 @@ $ git bisect run sh -c '
        rm -f tmp.$$
        test $rc = 0'
 
+$ git bisect reset                   # quit the bisect session
 ------------
 +
 In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit that
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
deleted file mode 100644 (file)
index 6d696e0..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-git-remote-helpers(1)
-=====================
-
-NAME
-----
-git-remote-helpers - Helper programs to interact with remote repositories
-
-SYNOPSIS
---------
-[verse]
-'git remote-<transport>' <repository> [<URL>]
-
-DESCRIPTION
------------
-
-Remote helper programs are normally not used directly by end users,
-but they are invoked by git when it needs to interact with remote
-repositories git does not support natively.  A given helper will
-implement a subset of the capabilities documented here. When git
-needs to interact with a repository using a remote helper, it spawns
-the helper as an independent process, sends commands to the helper's
-standard input, and expects results from the helper's standard
-output. Because a remote helper runs as an independent process from
-git, there is no need to re-link git to add a new helper, nor any
-need to link the helper with the implementation of git.
-
-Every helper must support the "capabilities" command, which git
-uses to determine what other commands the helper will accept.  Those
-other commands can be used to discover and update remote refs,
-transport objects between the object database and the remote repository,
-and update the local object store.
-
-Git comes with a "curl" family of remote helpers, that handle various
-transport protocols, such as 'git-remote-http', 'git-remote-https',
-'git-remote-ftp' and 'git-remote-ftps'. They implement the capabilities
-'fetch', 'option', and 'push'.
-
-INVOCATION
-----------
-
-Remote helper programs are invoked with one or (optionally) two
-arguments. The first argument specifies a remote repository as in git;
-it is either the name of a configured remote or a URL. The second
-argument specifies a URL; it is usually of the form
-'<transport>://<address>', but any arbitrary string is possible.
-The 'GIT_DIR' environment variable is set up for the remote helper
-and can be used to determine where to store additional data or from
-which directory to invoke auxiliary git commands.
-
-When git encounters a URL of the form '<transport>://<address>', where
-'<transport>' is a protocol that it cannot handle natively, it
-automatically invokes 'git remote-<transport>' with the full URL as
-the second argument. If such a URL is encountered directly on the
-command line, the first argument is the same as the second, and if it
-is encountered in a configured remote, the first argument is the name
-of that remote.
-
-A URL of the form '<transport>::<address>' explicitly instructs git to
-invoke 'git remote-<transport>' with '<address>' as the second
-argument. If such a URL is encountered directly on the command line,
-the first argument is '<address>', and if it is encountered in a
-configured remote, the first argument is the name of that remote.
-
-Additionally, when a configured remote has 'remote.<name>.vcs' set to
-'<transport>', git explicitly invokes 'git remote-<transport>' with
-'<name>' as the first argument. If set, the second argument is
-'remote.<name>.url'; otherwise, the second argument is omitted.
-
-INPUT FORMAT
-------------
-
-Git sends the remote helper a list of commands on standard input, one
-per line.  The first command is always the 'capabilities' command, in
-response to which the remote helper must print a list of the
-capabilities it supports (see below) followed by a blank line.  The
-response to the capabilities command determines what commands Git uses
-in the remainder of the command stream.
-
-The command stream is terminated by a blank line.  In some cases
-(indicated in the documentation of the relevant commands), this blank
-line is followed by a payload in some other protocol (e.g., the pack
-protocol), while in others it indicates the end of input.
-
-Capabilities
-~~~~~~~~~~~~
-
-Each remote helper is expected to support only a subset of commands.
-The operations a helper supports are declared to git in the response
-to the `capabilities` command (see COMMANDS, below).
-
-In the following, we list all defined capabilities and for
-each we list which commands a helper with that capability
-must provide.
-
-Capabilities for Pushing
-^^^^^^^^^^^^^^^^^^^^^^^^
-'connect'::
-       Can attempt to connect to 'git receive-pack' (for pushing),
-       'git upload-pack', etc for communication using
-       git's native packfile protocol. This
-       requires a bidirectional, full-duplex connection.
-+
-Supported commands: 'connect'.
-
-'push'::
-       Can discover remote refs and push local commits and the
-       history leading up to them to new or existing remote refs.
-+
-Supported commands: 'list for-push', 'push'.
-
-'export'::
-       Can discover remote refs and push specified objects from a
-       fast-import stream to remote refs.
-+
-Supported commands: 'list for-push', 'export'.
-
-If a helper advertises 'connect', git will use it if possible and
-fall back to another capability if the helper requests so when
-connecting (see the 'connect' command under COMMANDS).
-When choosing between 'push' and 'export', git prefers 'push'.
-Other frontends may have some other order of preference.
-
-
-Capabilities for Fetching
-^^^^^^^^^^^^^^^^^^^^^^^^^
-'connect'::
-       Can try to connect to 'git upload-pack' (for fetching),
-       'git receive-pack', etc for communication using the
-       git's native packfile protocol. This
-       requires a bidirectional, full-duplex connection.
-+
-Supported commands: 'connect'.
-
-'fetch'::
-       Can discover remote refs and transfer objects reachable from
-       them to the local object store.
-+
-Supported commands: 'list', 'fetch'.
-
-'import'::
-       Can discover remote refs and output objects reachable from
-       them as a stream in fast-import format.
-+
-Supported commands: 'list', 'import'.
-
-If a helper advertises 'connect', git will use it if possible and
-fall back to another capability if the helper requests so when
-connecting (see the 'connect' command under COMMANDS).
-When choosing between 'fetch' and 'import', git prefers 'fetch'.
-Other frontends may have some other order of preference.
-
-Miscellaneous capabilities
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-'option'::
-       For specifying settings like `verbosity` (how much output to
-       write to stderr) and `depth` (how much history is wanted in the
-       case of a shallow clone) that affect how other commands are
-       carried out.
-
-'refspec' <refspec>::
-       This modifies the 'import' capability, allowing the produced
-       fast-import stream to modify refs in a private namespace
-       instead of writing to refs/heads or refs/remotes directly.
-       It is recommended that all importers providing the 'import'
-       capability use this.
-+
-A helper advertising the capability
-`refspec refs/heads/*:refs/svn/origin/branches/*`
-is saying that, when it is asked to `import refs/heads/topic`, the
-stream it outputs will update the `refs/svn/origin/branches/topic`
-ref.
-+
-This capability can be advertised multiple times.  The first
-applicable refspec takes precedence.  The left-hand of refspecs
-advertised with this capability must cover all refs reported by
-the list command.  If no 'refspec' capability is advertised,
-there is an implied `refspec *:*`.
-
-'bidi-import'::
-       This modifies the 'import' capability.
-       The fast-import commands 'cat-blob' and 'ls' can be used by remote-helpers
-       to retrieve information about blobs and trees that already exist in
-       fast-import's memory. This requires a channel from fast-import to the
-       remote-helper.
-       If it is advertised in addition to "import", git establishes a pipe from
-       fast-import to the remote-helper's stdin.
-       It follows that git and fast-import are both connected to the
-       remote-helper's stdin. Because git can send multiple commands to
-       the remote-helper it is required that helpers that use 'bidi-import'
-       buffer all 'import' commands of a batch before sending data to fast-import.
-       This is to prevent mixing commands and fast-import responses on the
-       helper's stdin.
-
-'export-marks' <file>::
-       This modifies the 'export' capability, instructing git to dump the
-       internal marks table to <file> when complete. For details,
-       read up on '--export-marks=<file>' in linkgit:git-fast-export[1].
-
-'import-marks' <file>::
-       This modifies the 'export' capability, instructing git to load the
-       marks specified in <file> before processing any input. For details,
-       read up on '--import-marks=<file>' in linkgit:git-fast-export[1].
-
-
-
-
-COMMANDS
---------
-
-Commands are given by the caller on the helper's standard input, one per line.
-
-'capabilities'::
-       Lists the capabilities of the helper, one per line, ending
-       with a blank line. Each capability may be preceded with '*',
-       which marks them mandatory for git versions using the remote
-       helper to understand. Any unknown mandatory capability is a
-       fatal error.
-+
-Support for this command is mandatory.
-
-'list'::
-       Lists the refs, one per line, in the format "<value> <name>
-       [<attr> ...]". The value may be a hex sha1 hash, "@<dest>" for
-       a symref, or "?" to indicate that the helper could not get the
-       value of the ref. A space-separated list of attributes follows
-       the name; unrecognized attributes are ignored. The list ends
-       with a blank line.
-+
-See REF LIST ATTRIBUTES for a list of currently defined attributes.
-+
-Supported if the helper has the "fetch" or "import" capability.
-
-'list for-push'::
-       Similar to 'list', except that it is used if and only if
-       the caller wants to the resulting ref list to prepare
-       push commands.
-       A helper supporting both push and fetch can use this
-       to distinguish for which operation the output of 'list'
-       is going to be used, possibly reducing the amount
-       of work that needs to be performed.
-+
-Supported if the helper has the "push" or "export" capability.
-
-'option' <name> <value>::
-       Sets the transport helper option <name> to <value>.  Outputs a
-       single line containing one of 'ok' (option successfully set),
-       'unsupported' (option not recognized) or 'error <msg>'
-       (option <name> is supported but <value> is not valid
-       for it).  Options should be set before other commands,
-       and may influence the behavior of those commands.
-+
-See OPTIONS for a list of currently defined options.
-+
-Supported if the helper has the "option" capability.
-
-'fetch' <sha1> <name>::
-       Fetches the given object, writing the necessary objects
-       to the database.  Fetch commands are sent in a batch, one
-       per line, terminated with a blank line.
-       Outputs a single blank line when all fetch commands in the
-       same batch are complete. Only objects which were reported
-       in the output of 'list' with a sha1 may be fetched this way.
-+
-Optionally may output a 'lock <file>' line indicating a file under
-GIT_DIR/objects/pack which is keeping a pack until refs can be
-suitably updated.
-+
-Supported if the helper has the "fetch" capability.
-
-'push' +<src>:<dst>::
-       Pushes the given local <src> commit or branch to the
-       remote branch described by <dst>.  A batch sequence of
-       one or more 'push' commands is terminated with a blank line
-       (if there is only one reference to push, a single 'push' command
-       is followed by a blank line). For example, the following would
-       be two batches of 'push', the first asking the remote-helper
-       to push the local ref 'master' to the remote ref 'master' and
-       the local 'HEAD' to the remote 'branch', and the second
-       asking to push ref 'foo' to ref 'bar' (forced update requested
-       by the '+').
-+
-------------
-push refs/heads/master:refs/heads/master
-push HEAD:refs/heads/branch
-\n
-push +refs/heads/foo:refs/heads/bar
-\n
-------------
-+
-Zero or more protocol options may be entered after the last 'push'
-command, before the batch's terminating blank line.
-+
-When the push is complete, outputs one or more 'ok <dst>' or
-'error <dst> <why>?' lines to indicate success or failure of
-each pushed ref.  The status report output is terminated by
-a blank line.  The option field <why> may be quoted in a C
-style string if it contains an LF.
-+
-Supported if the helper has the "push" capability.
-
-'import' <name>::
-       Produces a fast-import stream which imports the current value
-       of the named ref. It may additionally import other refs as
-       needed to construct the history efficiently. The script writes
-       to a helper-specific private namespace. The value of the named
-       ref should be written to a location in this namespace derived
-       by applying the refspecs from the "refspec" capability to the
-       name of the ref.
-+
-Especially useful for interoperability with a foreign versioning
-system.
-+
-Just like 'push', a batch sequence of one or more 'import' is
-terminated with a blank line. For each batch of 'import', the remote
-helper should produce a fast-import stream terminated by a 'done'
-command.
-+
-Note that if the 'bidi-import' capability is used the complete batch
-sequence has to be buffered before starting to send data to fast-import
-to prevent mixing of commands and fast-import responses on the helper's
-stdin.
-+
-Supported if the helper has the "import" capability.
-
-'export'::
-       Instructs the remote helper that any subsequent input is
-       part of a fast-import stream (generated by 'git fast-export')
-       containing objects which should be pushed to the remote.
-+
-Especially useful for interoperability with a foreign versioning
-system.
-+
-The 'export-marks' and 'import-marks' capabilities, if specified,
-affect this command in so far as they are passed on to 'git
-fast-export', which then will load/store a table of marks for
-local objects. This can be used to implement for incremental
-operations.
-+
-Supported if the helper has the "export" capability.
-
-'connect' <service>::
-       Connects to given service. Standard input and standard output
-       of helper are connected to specified service (git prefix is
-       included in service name so e.g. fetching uses 'git-upload-pack'
-       as service) on remote side. Valid replies to this command are
-       empty line (connection established), 'fallback' (no smart
-       transport support, fall back to dumb transports) and just
-       exiting with error message printed (can't connect, don't
-       bother trying to fall back). After line feed terminating the
-       positive (empty) response, the output of service starts. After
-       the connection ends, the remote helper exits.
-+
-Supported if the helper has the "connect" capability.
-
-If a fatal error occurs, the program writes the error message to
-stderr and exits. The caller should expect that a suitable error
-message has been printed if the child closes the connection without
-completing a valid response for the current command.
-
-Additional commands may be supported, as may be determined from
-capabilities reported by the helper.
-
-REF LIST ATTRIBUTES
--------------------
-
-The 'list' command produces a list of refs in which each ref
-may be followed by a list of attributes. The following ref list
-attributes are defined.
-
-'unchanged'::
-       This ref is unchanged since the last import or fetch, although
-       the helper cannot necessarily determine what value that produced.
-
-OPTIONS
--------
-
-The following options are defined and (under suitable circumstances)
-set by git if the remote helper has the 'option' capability.
-
-'option verbosity' <n>::
-       Changes the verbosity of messages displayed by the helper.
-       A value of 0 for <n> means that processes operate
-       quietly, and the helper produces only error output.
-       1 is the default level of verbosity, and higher values
-       of <n> correspond to the number of -v flags passed on the
-       command line.
-
-'option progress' \{'true'|'false'\}::
-       Enables (or disables) progress messages displayed by the
-       transport helper during a command.
-
-'option depth' <depth>::
-       Deepens the history of a shallow repository.
-
-'option followtags' \{'true'|'false'\}::
-       If enabled the helper should automatically fetch annotated
-       tag objects if the object the tag points at was transferred
-       during the fetch command.  If the tag is not fetched by
-       the helper a second fetch command will usually be sent to
-       ask for the tag specifically.  Some helpers may be able to
-       use this option to avoid a second network connection.
-
-'option dry-run' \{'true'|'false'\}:
-       If true, pretend the operation completed successfully,
-       but don't actually change any repository data.  For most
-       helpers this only applies to the 'push', if supported.
-
-'option servpath <c-style-quoted-path>'::
-       Sets service path (--upload-pack, --receive-pack etc.) for
-       next connect. Remote helper may support this option, but
-       must not rely on this option being set before
-       connect request occurs.
-
-SEE ALSO
---------
-linkgit:git-remote[1]
-
-linkgit:git-remote-testgit[1]
-
-GIT
----
-Part of the linkgit:git[1] suite
diff --git a/Documentation/git-remote-helpers.txto b/Documentation/git-remote-helpers.txto
new file mode 100644 (file)
index 0000000..49233f5
--- /dev/null
@@ -0,0 +1,9 @@
+git-remote-helpers
+==================
+
+This document has been moved to linkgit:gitremote-helpers[1].
+
+Please let the owners of the referring site know so that they can update the
+link you clicked to get here.
+
+Thanks.
index 2a67d456a3d2e278d924e792760dfd90f77a680c..4c871b92e99aeb838a0975502e56a7388cad4965 100644 (file)
@@ -23,7 +23,7 @@ The best way to learn more is to read the comments and source code in
 
 SEE ALSO
 --------
-linkgit:git-remote-helpers[1]
+linkgit:gitremote-helpers[1]
 
 GIT
 ---
index b1de3bade751f34b9629e3d4c0d8f654fca86a91..349378448c5099cadf2bd6a5f5deca57fe03b4ca 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
              [--reference <repository>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
+'git submodule' [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase]
              [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
              [commit] [--] [<path>...]
index c7f211e81b6847ba2cc55e486c898f4405049501..cbac7711ea78e961c58954e47503b663e6030930 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.8.1.3/git.html[documentation for release 1.8.1.3]
+* link:v1.8.1.4/git.html[documentation for release 1.8.1.4]
 
 * release notes for
+  link:RelNotes/1.8.1.4.txt[1.8.1.4],
   link:RelNotes/1.8.1.3.txt[1.8.1.3],
   link:RelNotes/1.8.1.2.txt[1.8.1.2],
   link:RelNotes/1.8.1.1.txt[1.8.1.1],
@@ -530,10 +531,9 @@ include::cmds-purehelpers.txt[]
 Configuration Mechanism
 -----------------------
 
-Starting from 0.99.9 (actually mid 0.99.8.GIT), `.git/config` file
-is used to hold per-repository configuration options.  It is a
-simple text file modeled after `.ini` format familiar to some
-people.  Here is an example:
+Git uses a simple text format to store customizations that are per
+repository and are per user.  Such a configuration file may look
+like this:
 
 ------------
 #
@@ -548,13 +548,13 @@ people.  Here is an example:
 ; user identity
 [user]
        name = "Junio C Hamano"
-       email = "junkio@twinsun.com"
+       email = "gitster@pobox.com"
 
 ------------
 
 Various commands read from the configuration file and adjust
 their operation accordingly.  See linkgit:git-config[1] for a
-list.
+list and more details about the configuration mechanism.
 
 
 Identifier Terminology
index b9003fed248651a7783e042c2e3668cf3ff90d0f..4e0d2a08a11a2dd0af3bd77c5fd0041ea7e1d97e 100644 (file)
@@ -336,7 +336,7 @@ preceding SP is also omitted.  Currently, no commands pass any
 'extra-info'.
 
 The hook always runs after the automatic note copying (see
-"notes.rewrite.<command>" in linkgit:git-config.txt) has happened, and
+"notes.rewrite.<command>" in linkgit:git-config.txt[1]) has happened, and
 thus has access to these notes.
 
 The following command-specific comments apply:
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
new file mode 100644 (file)
index 0000000..0f21367
--- /dev/null
@@ -0,0 +1,423 @@
+gitremote-helpers(1)
+====================
+
+NAME
+----
+gitremote-helpers - Helper programs to interact with remote repositories
+
+SYNOPSIS
+--------
+[verse]
+'git remote-<transport>' <repository> [<URL>]
+
+DESCRIPTION
+-----------
+
+Remote helper programs are normally not used directly by end users,
+but they are invoked by git when it needs to interact with remote
+repositories git does not support natively.  A given helper will
+implement a subset of the capabilities documented here. When git
+needs to interact with a repository using a remote helper, it spawns
+the helper as an independent process, sends commands to the helper's
+standard input, and expects results from the helper's standard
+output. Because a remote helper runs as an independent process from
+git, there is no need to re-link git to add a new helper, nor any
+need to link the helper with the implementation of git.
+
+Every helper must support the "capabilities" command, which git
+uses to determine what other commands the helper will accept.  Those
+other commands can be used to discover and update remote refs,
+transport objects between the object database and the remote repository,
+and update the local object store.
+
+Git comes with a "curl" family of remote helpers, that handle various
+transport protocols, such as 'git-remote-http', 'git-remote-https',
+'git-remote-ftp' and 'git-remote-ftps'. They implement the capabilities
+'fetch', 'option', and 'push'.
+
+INVOCATION
+----------
+
+Remote helper programs are invoked with one or (optionally) two
+arguments. The first argument specifies a remote repository as in git;
+it is either the name of a configured remote or a URL. The second
+argument specifies a URL; it is usually of the form
+'<transport>://<address>', but any arbitrary string is possible.
+The 'GIT_DIR' environment variable is set up for the remote helper
+and can be used to determine where to store additional data or from
+which directory to invoke auxiliary git commands.
+
+When git encounters a URL of the form '<transport>://<address>', where
+'<transport>' is a protocol that it cannot handle natively, it
+automatically invokes 'git remote-<transport>' with the full URL as
+the second argument. If such a URL is encountered directly on the
+command line, the first argument is the same as the second, and if it
+is encountered in a configured remote, the first argument is the name
+of that remote.
+
+A URL of the form '<transport>::<address>' explicitly instructs git to
+invoke 'git remote-<transport>' with '<address>' as the second
+argument. If such a URL is encountered directly on the command line,
+the first argument is '<address>', and if it is encountered in a
+configured remote, the first argument is the name of that remote.
+
+Additionally, when a configured remote has 'remote.<name>.vcs' set to
+'<transport>', git explicitly invokes 'git remote-<transport>' with
+'<name>' as the first argument. If set, the second argument is
+'remote.<name>.url'; otherwise, the second argument is omitted.
+
+INPUT FORMAT
+------------
+
+Git sends the remote helper a list of commands on standard input, one
+per line.  The first command is always the 'capabilities' command, in
+response to which the remote helper must print a list of the
+capabilities it supports (see below) followed by a blank line.  The
+response to the capabilities command determines what commands Git uses
+in the remainder of the command stream.
+
+The command stream is terminated by a blank line.  In some cases
+(indicated in the documentation of the relevant commands), this blank
+line is followed by a payload in some other protocol (e.g., the pack
+protocol), while in others it indicates the end of input.
+
+Capabilities
+~~~~~~~~~~~~
+
+Each remote helper is expected to support only a subset of commands.
+The operations a helper supports are declared to git in the response
+to the `capabilities` command (see COMMANDS, below).
+
+In the following, we list all defined capabilities and for
+each we list which commands a helper with that capability
+must provide.
+
+Capabilities for Pushing
+^^^^^^^^^^^^^^^^^^^^^^^^
+'connect'::
+       Can attempt to connect to 'git receive-pack' (for pushing),
+       'git upload-pack', etc for communication using
+       git's native packfile protocol. This
+       requires a bidirectional, full-duplex connection.
++
+Supported commands: 'connect'.
+
+'push'::
+       Can discover remote refs and push local commits and the
+       history leading up to them to new or existing remote refs.
++
+Supported commands: 'list for-push', 'push'.
+
+'export'::
+       Can discover remote refs and push specified objects from a
+       fast-import stream to remote refs.
++
+Supported commands: 'list for-push', 'export'.
+
+If a helper advertises 'connect', git will use it if possible and
+fall back to another capability if the helper requests so when
+connecting (see the 'connect' command under COMMANDS).
+When choosing between 'push' and 'export', git prefers 'push'.
+Other frontends may have some other order of preference.
+
+
+Capabilities for Fetching
+^^^^^^^^^^^^^^^^^^^^^^^^^
+'connect'::
+       Can try to connect to 'git upload-pack' (for fetching),
+       'git receive-pack', etc for communication using the
+       git's native packfile protocol. This
+       requires a bidirectional, full-duplex connection.
++
+Supported commands: 'connect'.
+
+'fetch'::
+       Can discover remote refs and transfer objects reachable from
+       them to the local object store.
++
+Supported commands: 'list', 'fetch'.
+
+'import'::
+       Can discover remote refs and output objects reachable from
+       them as a stream in fast-import format.
++
+Supported commands: 'list', 'import'.
+
+If a helper advertises 'connect', git will use it if possible and
+fall back to another capability if the helper requests so when
+connecting (see the 'connect' command under COMMANDS).
+When choosing between 'fetch' and 'import', git prefers 'fetch'.
+Other frontends may have some other order of preference.
+
+Miscellaneous capabilities
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+'option'::
+       For specifying settings like `verbosity` (how much output to
+       write to stderr) and `depth` (how much history is wanted in the
+       case of a shallow clone) that affect how other commands are
+       carried out.
+
+'refspec' <refspec>::
+       This modifies the 'import' capability, allowing the produced
+       fast-import stream to modify refs in a private namespace
+       instead of writing to refs/heads or refs/remotes directly.
+       It is recommended that all importers providing the 'import'
+       capability use this.
++
+A helper advertising the capability
+`refspec refs/heads/*:refs/svn/origin/branches/*`
+is saying that, when it is asked to `import refs/heads/topic`, the
+stream it outputs will update the `refs/svn/origin/branches/topic`
+ref.
++
+This capability can be advertised multiple times.  The first
+applicable refspec takes precedence.  The left-hand of refspecs
+advertised with this capability must cover all refs reported by
+the list command.  If no 'refspec' capability is advertised,
+there is an implied `refspec *:*`.
+
+'bidi-import'::
+       This modifies the 'import' capability.
+       The fast-import commands 'cat-blob' and 'ls' can be used by remote-helpers
+       to retrieve information about blobs and trees that already exist in
+       fast-import's memory. This requires a channel from fast-import to the
+       remote-helper.
+       If it is advertised in addition to "import", git establishes a pipe from
+       fast-import to the remote-helper's stdin.
+       It follows that git and fast-import are both connected to the
+       remote-helper's stdin. Because git can send multiple commands to
+       the remote-helper it is required that helpers that use 'bidi-import'
+       buffer all 'import' commands of a batch before sending data to fast-import.
+       This is to prevent mixing commands and fast-import responses on the
+       helper's stdin.
+
+'export-marks' <file>::
+       This modifies the 'export' capability, instructing git to dump the
+       internal marks table to <file> when complete. For details,
+       read up on '--export-marks=<file>' in linkgit:git-fast-export[1].
+
+'import-marks' <file>::
+       This modifies the 'export' capability, instructing git to load the
+       marks specified in <file> before processing any input. For details,
+       read up on '--import-marks=<file>' in linkgit:git-fast-export[1].
+
+
+
+
+COMMANDS
+--------
+
+Commands are given by the caller on the helper's standard input, one per line.
+
+'capabilities'::
+       Lists the capabilities of the helper, one per line, ending
+       with a blank line. Each capability may be preceded with '*',
+       which marks them mandatory for git versions using the remote
+       helper to understand. Any unknown mandatory capability is a
+       fatal error.
++
+Support for this command is mandatory.
+
+'list'::
+       Lists the refs, one per line, in the format "<value> <name>
+       [<attr> ...]". The value may be a hex sha1 hash, "@<dest>" for
+       a symref, or "?" to indicate that the helper could not get the
+       value of the ref. A space-separated list of attributes follows
+       the name; unrecognized attributes are ignored. The list ends
+       with a blank line.
++
+See REF LIST ATTRIBUTES for a list of currently defined attributes.
++
+Supported if the helper has the "fetch" or "import" capability.
+
+'list for-push'::
+       Similar to 'list', except that it is used if and only if
+       the caller wants to the resulting ref list to prepare
+       push commands.
+       A helper supporting both push and fetch can use this
+       to distinguish for which operation the output of 'list'
+       is going to be used, possibly reducing the amount
+       of work that needs to be performed.
++
+Supported if the helper has the "push" or "export" capability.
+
+'option' <name> <value>::
+       Sets the transport helper option <name> to <value>.  Outputs a
+       single line containing one of 'ok' (option successfully set),
+       'unsupported' (option not recognized) or 'error <msg>'
+       (option <name> is supported but <value> is not valid
+       for it).  Options should be set before other commands,
+       and may influence the behavior of those commands.
++
+See OPTIONS for a list of currently defined options.
++
+Supported if the helper has the "option" capability.
+
+'fetch' <sha1> <name>::
+       Fetches the given object, writing the necessary objects
+       to the database.  Fetch commands are sent in a batch, one
+       per line, terminated with a blank line.
+       Outputs a single blank line when all fetch commands in the
+       same batch are complete. Only objects which were reported
+       in the output of 'list' with a sha1 may be fetched this way.
++
+Optionally may output a 'lock <file>' line indicating a file under
+GIT_DIR/objects/pack which is keeping a pack until refs can be
+suitably updated.
++
+Supported if the helper has the "fetch" capability.
+
+'push' +<src>:<dst>::
+       Pushes the given local <src> commit or branch to the
+       remote branch described by <dst>.  A batch sequence of
+       one or more 'push' commands is terminated with a blank line
+       (if there is only one reference to push, a single 'push' command
+       is followed by a blank line). For example, the following would
+       be two batches of 'push', the first asking the remote-helper
+       to push the local ref 'master' to the remote ref 'master' and
+       the local 'HEAD' to the remote 'branch', and the second
+       asking to push ref 'foo' to ref 'bar' (forced update requested
+       by the '+').
++
+------------
+push refs/heads/master:refs/heads/master
+push HEAD:refs/heads/branch
+\n
+push +refs/heads/foo:refs/heads/bar
+\n
+------------
++
+Zero or more protocol options may be entered after the last 'push'
+command, before the batch's terminating blank line.
++
+When the push is complete, outputs one or more 'ok <dst>' or
+'error <dst> <why>?' lines to indicate success or failure of
+each pushed ref.  The status report output is terminated by
+a blank line.  The option field <why> may be quoted in a C
+style string if it contains an LF.
++
+Supported if the helper has the "push" capability.
+
+'import' <name>::
+       Produces a fast-import stream which imports the current value
+       of the named ref. It may additionally import other refs as
+       needed to construct the history efficiently. The script writes
+       to a helper-specific private namespace. The value of the named
+       ref should be written to a location in this namespace derived
+       by applying the refspecs from the "refspec" capability to the
+       name of the ref.
++
+Especially useful for interoperability with a foreign versioning
+system.
++
+Just like 'push', a batch sequence of one or more 'import' is
+terminated with a blank line. For each batch of 'import', the remote
+helper should produce a fast-import stream terminated by a 'done'
+command.
++
+Note that if the 'bidi-import' capability is used the complete batch
+sequence has to be buffered before starting to send data to fast-import
+to prevent mixing of commands and fast-import responses on the helper's
+stdin.
++
+Supported if the helper has the "import" capability.
+
+'export'::
+       Instructs the remote helper that any subsequent input is
+       part of a fast-import stream (generated by 'git fast-export')
+       containing objects which should be pushed to the remote.
++
+Especially useful for interoperability with a foreign versioning
+system.
++
+The 'export-marks' and 'import-marks' capabilities, if specified,
+affect this command in so far as they are passed on to 'git
+fast-export', which then will load/store a table of marks for
+local objects. This can be used to implement for incremental
+operations.
++
+Supported if the helper has the "export" capability.
+
+'connect' <service>::
+       Connects to given service. Standard input and standard output
+       of helper are connected to specified service (git prefix is
+       included in service name so e.g. fetching uses 'git-upload-pack'
+       as service) on remote side. Valid replies to this command are
+       empty line (connection established), 'fallback' (no smart
+       transport support, fall back to dumb transports) and just
+       exiting with error message printed (can't connect, don't
+       bother trying to fall back). After line feed terminating the
+       positive (empty) response, the output of service starts. After
+       the connection ends, the remote helper exits.
++
+Supported if the helper has the "connect" capability.
+
+If a fatal error occurs, the program writes the error message to
+stderr and exits. The caller should expect that a suitable error
+message has been printed if the child closes the connection without
+completing a valid response for the current command.
+
+Additional commands may be supported, as may be determined from
+capabilities reported by the helper.
+
+REF LIST ATTRIBUTES
+-------------------
+
+The 'list' command produces a list of refs in which each ref
+may be followed by a list of attributes. The following ref list
+attributes are defined.
+
+'unchanged'::
+       This ref is unchanged since the last import or fetch, although
+       the helper cannot necessarily determine what value that produced.
+
+OPTIONS
+-------
+
+The following options are defined and (under suitable circumstances)
+set by git if the remote helper has the 'option' capability.
+
+'option verbosity' <n>::
+       Changes the verbosity of messages displayed by the helper.
+       A value of 0 for <n> means that processes operate
+       quietly, and the helper produces only error output.
+       1 is the default level of verbosity, and higher values
+       of <n> correspond to the number of -v flags passed on the
+       command line.
+
+'option progress' \{'true'|'false'\}::
+       Enables (or disables) progress messages displayed by the
+       transport helper during a command.
+
+'option depth' <depth>::
+       Deepens the history of a shallow repository.
+
+'option followtags' \{'true'|'false'\}::
+       If enabled the helper should automatically fetch annotated
+       tag objects if the object the tag points at was transferred
+       during the fetch command.  If the tag is not fetched by
+       the helper a second fetch command will usually be sent to
+       ask for the tag specifically.  Some helpers may be able to
+       use this option to avoid a second network connection.
+
+'option dry-run' \{'true'|'false'\}:
+       If true, pretend the operation completed successfully,
+       but don't actually change any repository data.  For most
+       helpers this only applies to the 'push', if supported.
+
+'option servpath <c-style-quoted-path>'::
+       Sets service path (--upload-pack, --receive-pack etc.) for
+       next connect. Remote helper may support this option, but
+       must not rely on this option being set before
+       connect request occurs.
+
+SEE ALSO
+--------
+linkgit:git-remote[1]
+
+linkgit:git-remote-testgit[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
index 1d15ee7e5209f93a387db348dcccd6abd9cb306f..cea5462ff83366dc3307be37162c57f97cb636c4 100644 (file)
@@ -55,7 +55,7 @@ may be used:
 
 where <address> may be a path, a server and path, or an arbitrary
 URL-like string recognized by the specific remote helper being
-invoked. See linkgit:git-remote-helpers[1] for details.
+invoked. See linkgit:gitremote-helpers[1] for details.
 
 If there are a large number of similarly-named remote repositories and
 you want to use a different format for them (such that the URLs you
index bb03bc88b8cd80b98712edc1a6420aeac4c75371..988c13ff4c8f95f2872d72e399d1fb7d6e6f1413 100644 (file)
@@ -2004,9 +2004,10 @@ handling this case.
 
 Note that the target of a "push" is normally a
 <<def_bare_repository,bare>> repository.  You can also push to a
-repository that has a checked-out working tree, but the working tree
-will not be updated by the push.  This may lead to unexpected results if
-the branch you push to is the currently checked-out branch!
+repository that has a checked-out working tree, but a push to update the
+currently checked-out branch is denied by default to prevent confusion.
+See the description of the receive.denyCurrentBranch option
+in linkgit:git-config[1] for details.
 
 As with `git fetch`, you may also set up configuration options to
 save typing; so, for example:
index 07685f469777e13ed7ad67291e82a69920bd42bd..dcd3595f278439c267d8e7f9725efa2147bf1f15 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.8.1.3
+DEF_VER=v1.8.1.4
 
 LF='
 '
index 4bb3cf13673249d893b450352a27e70f837aa7b8..ec58d5c93b9321c0608b97e7fdb3d9bcbf90c9ac 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2272,12 +2272,14 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)): % : unimplemented.sh
        mv $@+ $@
 endif # NO_PYTHON
 
+CONFIGURE_RECIPE = $(RM) configure configure.ac+ && \
+                  sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
+                       configure.ac >configure.ac+ && \
+                  autoconf -o configure configure.ac+ && \
+                  $(RM) configure.ac+
+
 configure: configure.ac GIT-VERSION-FILE
-       $(QUIET_GEN)$(RM) $@ $<+ && \
-       sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-           $< > $<+ && \
-       autoconf -o $@ $<+ && \
-       $(RM) $<+
+       $(QUIET_GEN)$(CONFIGURE_RECIPE)
 
 ifdef AUTOCONFIGURED
 # We avoid depending on 'configure' here, because it gets rebuilt
@@ -2286,7 +2288,7 @@ ifdef AUTOCONFIGURED
 # do want to recheck when the platform/environment detection logic
 # changes, hence this depends on configure.ac.
 config.status: configure.ac
-       $(QUIET_GEN)$(MAKE) configure && \
+       $(QUIET_GEN)$(CONFIGURE_RECIPE) && \
        if test -f config.status; then \
          ./config.status --recheck; \
        else \
index ce97a3befbd82fe61cd9e0847e26ffa454a48f98..3c65929a74433601bc2d271657aa8d0c26974782 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.8.1.3.txt
\ No newline at end of file
+Documentation/RelNotes/1.8.1.5.txt
\ No newline at end of file
index 9706ca73ab0bc2ee4c3cf7ce7ab39591830a1fab..080ce2ea3e4d6290e5db5567c0bdd217725a36c4 100644 (file)
@@ -1041,15 +1041,17 @@ static int gitdiff_renamedst(const char *line, struct patch *patch)
 
 static int gitdiff_similarity(const char *line, struct patch *patch)
 {
-       if ((patch->score = strtoul(line, NULL, 10)) == ULONG_MAX)
-               patch->score = 0;
+       unsigned long val = strtoul(line, NULL, 10);
+       if (val <= 100)
+               patch->score = val;
        return 0;
 }
 
 static int gitdiff_dissimilarity(const char *line, struct patch *patch)
 {
-       if ((patch->score = strtoul(line, NULL, 10)) == ULONG_MAX)
-               patch->score = 0;
+       unsigned long val = strtoul(line, NULL, 10);
+       if (val <= 100)
+               patch->score = val;
        return 0;
 }
 
index 69c1cda9061f248479377d2841a1ddf703ea59ba..f4b760bf3dcb2371da6ae9d77f2f8fb1c0fa9eb9 100644 (file)
@@ -10,6 +10,7 @@
 #include "cache.h"
 #include "dir.h"
 #include "parse-options.h"
+#include "refs.h"
 #include "string-list.h"
 #include "quote.h"
 
@@ -20,6 +21,12 @@ static const char *const builtin_clean_usage[] = {
        NULL
 };
 
+static const char *msg_remove = N_("Removing %s\n");
+static const char *msg_would_remove = N_("Would remove %s\n");
+static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
+static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
+static const char *msg_warn_remove_failed = N_("failed to remove %s");
+
 static int git_clean_config(const char *var, const char *value, void *cb)
 {
        if (!strcmp(var, "clean.requireforce"))
@@ -34,11 +41,112 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset)
        return 0;
 }
 
+static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
+               int dry_run, int quiet, int *dir_gone)
+{
+       DIR *dir;
+       struct strbuf quoted = STRBUF_INIT;
+       struct dirent *e;
+       int res = 0, ret = 0, gone = 1, original_len = path->len, len, i;
+       unsigned char submodule_head[20];
+       struct string_list dels = STRING_LIST_INIT_DUP;
+
+       *dir_gone = 1;
+
+       if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
+                       !resolve_gitlink_ref(path->buf, "HEAD", submodule_head)) {
+               if (!quiet) {
+                       quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+                       printf(dry_run ?  _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
+                                       quoted.buf);
+               }
+
+               *dir_gone = 0;
+               return 0;
+       }
+
+       dir = opendir(path->buf);
+       if (!dir) {
+               /* an empty dir could be removed even if it is unreadble */
+               res = dry_run ? 0 : rmdir(path->buf);
+               if (res) {
+                       quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+                       warning(_(msg_warn_remove_failed), quoted.buf);
+                       *dir_gone = 0;
+               }
+               return res;
+       }
+
+       if (path->buf[original_len - 1] != '/')
+               strbuf_addch(path, '/');
+
+       len = path->len;
+       while ((e = readdir(dir)) != NULL) {
+               struct stat st;
+               if (is_dot_or_dotdot(e->d_name))
+                       continue;
+
+               strbuf_setlen(path, len);
+               strbuf_addstr(path, e->d_name);
+               if (lstat(path->buf, &st))
+                       ; /* fall thru */
+               else if (S_ISDIR(st.st_mode)) {
+                       if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone))
+                               ret = 1;
+                       if (gone) {
+                               quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+                               string_list_append(&dels, quoted.buf);
+                       } else
+                               *dir_gone = 0;
+                       continue;
+               } else {
+                       res = dry_run ? 0 : unlink(path->buf);
+                       if (!res) {
+                               quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+                               string_list_append(&dels, quoted.buf);
+                       } else {
+                               quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+                               warning(_(msg_warn_remove_failed), quoted.buf);
+                               *dir_gone = 0;
+                               ret = 1;
+                       }
+                       continue;
+               }
+
+               /* path too long, stat fails, or non-directory still exists */
+               *dir_gone = 0;
+               ret = 1;
+               break;
+       }
+       closedir(dir);
+
+       strbuf_setlen(path, original_len);
+
+       if (*dir_gone) {
+               res = dry_run ? 0 : rmdir(path->buf);
+               if (!res)
+                       *dir_gone = 1;
+               else {
+                       quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+                       warning(_(msg_warn_remove_failed), quoted.buf);
+                       *dir_gone = 0;
+                       ret = 1;
+               }
+       }
+
+       if (!*dir_gone && !quiet) {
+               for (i = 0; i < dels.nr; i++)
+                       printf(dry_run ?  _(msg_would_remove) : _(msg_remove), dels.items[i].string);
+       }
+       string_list_clear(&dels, 0);
+       return ret;
+}
+
 int cmd_clean(int argc, const char **argv, const char *prefix)
 {
-       int i;
-       int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0;
-       int ignored_only = 0, config_set = 0, errors = 0;
+       int i, res;
+       int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
+       int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
        int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
        struct strbuf directory = STRBUF_INIT;
        struct dir_struct dir;
@@ -49,7 +157,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        char *seen = NULL;
        struct option options[] = {
                OPT__QUIET(&quiet, N_("do not print names of files removed")),
-               OPT__DRY_RUN(&show_only, N_("dry run")),
+               OPT__DRY_RUN(&dry_run, N_("dry run")),
                OPT__FORCE(&force, N_("force")),
                OPT_BOOLEAN('d', NULL, &remove_directories,
                                N_("remove whole directories")),
@@ -77,7 +185,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        if (ignored && ignored_only)
                die(_("-x and -X cannot be used together"));
 
-       if (!show_only && !force) {
+       if (!dry_run && !force) {
                if (config_set)
                        die(_("clean.requireForce set to true and neither -n nor -f given; "
                                  "refusing to clean"));
@@ -149,38 +257,26 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 
                if (S_ISDIR(st.st_mode)) {
                        strbuf_addstr(&directory, ent->name);
-                       qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
-                       if (show_only && (remove_directories ||
-                           (matches == MATCHED_EXACTLY))) {
-                               printf(_("Would remove %s\n"), qname);
-                       } else if (remove_directories ||
-                                  (matches == MATCHED_EXACTLY)) {
-                               if (!quiet)
-                                       printf(_("Removing %s\n"), qname);
-                               if (remove_dir_recursively(&directory,
-                                                          rm_flags) != 0) {
-                                       warning(_("failed to remove %s"), qname);
+                       if (remove_directories || (matches == MATCHED_EXACTLY)) {
+                               if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone))
                                        errors++;
+                               if (gone && !quiet) {
+                                       qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
+                                       printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
                                }
-                       } else if (show_only) {
-                               printf(_("Would not remove %s\n"), qname);
-                       } else {
-                               printf(_("Not removing %s\n"), qname);
                        }
                        strbuf_reset(&directory);
                } else {
                        if (pathspec && !matches)
                                continue;
-                       qname = quote_path_relative(ent->name, -1, &buf, prefix);
-                       if (show_only) {
-                               printf(_("Would remove %s\n"), qname);
-                               continue;
-                       } else if (!quiet) {
-                               printf(_("Removing %s\n"), qname);
-                       }
-                       if (unlink(ent->name) != 0) {
-                               warning(_("failed to remove %s"), qname);
+                       res = dry_run ? 0 : unlink(ent->name);
+                       if (res) {
+                               qname = quote_path_relative(ent->name, -1, &buf, prefix);
+                               warning(_(msg_warn_remove_failed), qname);
                                errors++;
+                       } else if (!quiet) {
+                               qname = quote_path_relative(ent->name, -1, &buf, prefix);
+                               printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
                        }
                }
        }
index 8d23a62e8a1b875f1415f78a4c283f4cdefac011..36ec99db3f5a7dbd59705aa68bcd592c08c773cd 100644 (file)
@@ -704,6 +704,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                if (option_origin)
                        die(_("--bare and --origin %s options are incompatible."),
                            option_origin);
+               if (real_git_dir)
+                       die(_("--bare and --separate-git-dir are incompatible."));
                option_no_checkout = 1;
        }
 
index bb1cc96c4e73c90ee327858aa3b36cf2bfe043a4..7f6187f9cd2fc44540cddbcf4bb853231c57397c 100644 (file)
@@ -982,14 +982,10 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
        free(sline);
 }
 
-#define COLONS "::::::::::::::::::::::::::::::::"
-
 static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct rev_info *rev)
 {
        struct diff_options *opt = &rev->diffopt;
-       int i, offset;
-       const char *prefix;
-       int line_termination, inter_name_termination;
+       int line_termination, inter_name_termination, i;
 
        line_termination = opt->line_termination;
        inter_name_termination = '\t';
@@ -1000,17 +996,14 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
                show_log(rev);
 
        if (opt->output_format & DIFF_FORMAT_RAW) {
-               offset = strlen(COLONS) - num_parent;
-               if (offset < 0)
-                       offset = 0;
-               prefix = COLONS + offset;
+               /* As many colons as there are parents */
+               for (i = 0; i < num_parent; i++)
+                       putchar(':');
 
                /* Show the modes */
-               for (i = 0; i < num_parent; i++) {
-                       printf("%s%06o", prefix, p->parent[i].mode);
-                       prefix = " ";
-               }
-               printf("%s%06o", prefix, p->mode);
+               for (i = 0; i < num_parent; i++)
+                       printf("%06o ", p->parent[i].mode);
+               printf("%06o", p->mode);
 
                /* Show sha1's */
                for (i = 0; i < num_parent; i++)
index 0a31ebd82020f3aca0020d357c2028d5e7b5e37b..344f1206d111a57ec529c34785ff8b1a6537e4d1 100755 (executable)
@@ -26,6 +26,7 @@
 use IO::Pipe;
 use POSIX qw(strftime tzset dup2 ENOENT);
 use IPC::Open2;
+use Git qw(get_tz_offset);
 
 $SIG{'PIPE'}="IGNORE";
 set_timezone('UTC');
@@ -864,7 +865,9 @@ sub commit {
        }
 
        set_timezone($author_tz);
-       my $commit_date = strftime("%s %z", localtime($date));
+       # $date is in the seconds since epoch format
+       my $tz_offset = get_tz_offset($date);
+       my $commit_date = "$date $tz_offset";
        set_timezone('UTC');
        $ENV{GIT_AUTHOR_NAME} = $author_name;
        $ENV{GIT_AUTHOR_EMAIL} = $author_email;
index 3d0fe0cd93b393a5f376aa10505e927fbed37f8f..b00ed95dba9c035ee812d3a2d6db2d13a1944a33 100755 (executable)
@@ -40,7 +40,7 @@ launch_merge_tool () {
        # the user with the real $MERGED name before launching $merge_tool.
        if should_prompt
        then
-               printf "\nViewing: '$MERGED'\n"
+               printf "\nViewing: '%s'\n" "$MERGED"
                if use_ext_cmd
                then
                        printf "Launch '%s' [Y/n]: " \
index c50e18a8998c1f4ca1449e1733f76cb769f501b9..012afa55494cc968831b8115f9e2956f107bbb45 100755 (executable)
@@ -440,7 +440,7 @@ then
 fi
 
 printf "Merging:\n"
-printf "$files\n"
+printf "%s\n" "$files"
 
 IFS='
 '
index c6bafe6ead815ece2e820d303e442270749c5c4b..1309196d27e675013825cdac8afd6d7328e44b1f 100755 (executable)
@@ -2068,7 +2068,7 @@ sub picon_url {
        if (!$avatar_cache{$email}) {
                my ($user, $domain) = split('@', $email);
                $avatar_cache{$email} =
-                       "http://www.cs.indiana.edu/cgi-pub/kinzler/piconsearch.cgi/" .
+                       "//www.cs.indiana.edu/cgi-pub/kinzler/piconsearch.cgi/" .
                        "$domain/$user/" .
                        "users+domains+unknown/up/single";
        }
@@ -2083,7 +2083,7 @@ sub gravatar_url {
        my $email = lc shift;
        my $size = shift;
        $avatar_cache{$email} ||=
-               "http://www.gravatar.com/avatar/" .
+               "//www.gravatar.com/avatar/" .
                        Digest::MD5::md5_hex($email) . "?s=";
        return $avatar_cache{$email} . $size;
 }
index 8701c1215d21cd0413c1d69be91b309984cf6b1f..ba45b7b501b901e39b34cb44b41cb758dc4ad293 100644 (file)
@@ -1560,7 +1560,7 @@ static int remote_exists(const char *path)
 
        sprintf(url, "%s%s", repo->url, path);
 
-       switch (http_get_strbuf(url, NULL, 0)) {
+       switch (http_get_strbuf(url, NULL, NULL, 0)) {
        case HTTP_OK:
                ret = 1;
                break;
@@ -1584,7 +1584,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
        url = xmalloc(strlen(repo->url) + strlen(path) + 1);
        sprintf(url, "%s%s", repo->url, path);
 
-       if (http_get_strbuf(url, &buffer, 0) != HTTP_OK)
+       if (http_get_strbuf(url, NULL, &buffer, 0) != HTTP_OK)
                die("Couldn't get %s for remote symref\n%s", url,
                    curl_errorstr);
        free(url);
diff --git a/http.c b/http.c
index 44f35256e44ffdda2ffb0ce67825008bef89700f..d9d1aad3be468394e39966c0b45e7e101b387b0c 100644 (file)
--- a/http.c
+++ b/http.c
@@ -788,7 +788,8 @@ int handle_curl_result(struct slot_results *results)
 #define HTTP_REQUEST_STRBUF    0
 #define HTTP_REQUEST_FILE      1
 
-static int http_request(const char *url, void *result, int target, int options)
+static int http_request(const char *url, struct strbuf *type,
+                       void *result, int target, int options)
 {
        struct active_request_slot *slot;
        struct slot_results results;
@@ -838,24 +839,37 @@ static int http_request(const char *url, void *result, int target, int options)
                ret = HTTP_START_FAILED;
        }
 
+       if (type) {
+               char *t;
+               strbuf_reset(type);
+               curl_easy_getinfo(slot->curl, CURLINFO_CONTENT_TYPE, &t);
+               if (t)
+                       strbuf_addstr(type, t);
+       }
+
        curl_slist_free_all(headers);
        strbuf_release(&buf);
 
        return ret;
 }
 
-static int http_request_reauth(const char *url, void *result, int target,
+static int http_request_reauth(const char *url,
+                              struct strbuf *type,
+                              void *result, int target,
                               int options)
 {
-       int ret = http_request(url, result, target, options);
+       int ret = http_request(url, type, result, target, options);
        if (ret != HTTP_REAUTH)
                return ret;
-       return http_request(url, result, target, options);
+       return http_request(url, type, result, target, options);
 }
 
-int http_get_strbuf(const char *url, struct strbuf *result, int options)
+int http_get_strbuf(const char *url,
+                   struct strbuf *type,
+                   struct strbuf *result, int options)
 {
-       return http_request_reauth(url, result, HTTP_REQUEST_STRBUF, options);
+       return http_request_reauth(url, type, result,
+                                  HTTP_REQUEST_STRBUF, options);
 }
 
 /*
@@ -878,7 +892,7 @@ static int http_get_file(const char *url, const char *filename, int options)
                goto cleanup;
        }
 
-       ret = http_request_reauth(url, result, HTTP_REQUEST_FILE, options);
+       ret = http_request_reauth(url, NULL, result, HTTP_REQUEST_FILE, options);
        fclose(result);
 
        if ((ret == HTTP_OK) && move_temp_to_file(tmpfile.buf, filename))
@@ -904,7 +918,7 @@ int http_fetch_ref(const char *base, struct ref *ref)
        int ret = -1;
 
        url = quote_ref_url(base, ref->name);
-       if (http_get_strbuf(url, &buffer, HTTP_NO_CACHE) == HTTP_OK) {
+       if (http_get_strbuf(url, NULL, &buffer, HTTP_NO_CACHE) == HTTP_OK) {
                strbuf_rtrim(&buffer);
                if (buffer.len == 40)
                        ret = get_sha1_hex(buffer.buf, ref->old_sha1);
@@ -997,7 +1011,7 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
        strbuf_addstr(&buf, "objects/info/packs");
        url = strbuf_detach(&buf, NULL);
 
-       ret = http_get_strbuf(url, &buf, HTTP_NO_CACHE);
+       ret = http_get_strbuf(url, NULL, &buf, HTTP_NO_CACHE);
        if (ret != HTTP_OK)
                goto cleanup;
 
diff --git a/http.h b/http.h
index 0a80d303e369b4adf77ca131c732ba39a990610d..25d19313983f0d0a11ab50dffbb623b105c8960a 100644 (file)
--- a/http.h
+++ b/http.h
@@ -132,7 +132,7 @@ extern char *get_remote_object_url(const char *url, const char *hex,
  *
  * If the result pointer is NULL, a HTTP HEAD request is made instead of GET.
  */
-int http_get_strbuf(const char *url, struct strbuf *result, int options);
+int http_get_strbuf(const char *url, struct strbuf *content_type, struct strbuf *result, int options);
 
 /*
  * Prints an error message using error() containing url and curl_errorstr,
index d42e4712972794f055aec6630ba86797d7e5343c..ef500111ec0bca6514e519d39e7a269a7342cddf 100644 (file)
@@ -31,6 +31,7 @@ typedef void *SSL;
 #else
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
+#include <openssl/x509v3.h>
 #endif
 
 struct store_conf {
@@ -266,12 +267,64 @@ static void socket_perror(const char *func, struct imap_socket *sock, int ret)
        }
 }
 
+#ifdef NO_OPENSSL
 static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify)
 {
-#ifdef NO_OPENSSL
        fprintf(stderr, "SSL requested but SSL support not compiled in\n");
        return -1;
+}
+
 #else
+
+static int host_matches(const char *host, const char *pattern)
+{
+       if (pattern[0] == '*' && pattern[1] == '.') {
+               pattern += 2;
+               if (!(host = strchr(host, '.')))
+                       return 0;
+               host++;
+       }
+
+       return *host && *pattern && !strcasecmp(host, pattern);
+}
+
+static int verify_hostname(X509 *cert, const char *hostname)
+{
+       int len;
+       X509_NAME *subj;
+       char cname[1000];
+       int i, found;
+       STACK_OF(GENERAL_NAME) *subj_alt_names;
+
+       /* try the DNS subjectAltNames */
+       found = 0;
+       if ((subj_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL))) {
+               int num_subj_alt_names = sk_GENERAL_NAME_num(subj_alt_names);
+               for (i = 0; !found && i < num_subj_alt_names; i++) {
+                       GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);
+                       if (subj_alt_name->type == GEN_DNS &&
+                           strlen((const char *)subj_alt_name->d.ia5->data) == (size_t)subj_alt_name->d.ia5->length &&
+                           host_matches(hostname, (const char *)(subj_alt_name->d.ia5->data)))
+                               found = 1;
+               }
+               sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);
+       }
+       if (found)
+               return 0;
+
+       /* try the common name */
+       if (!(subj = X509_get_subject_name(cert)))
+               return error("cannot get certificate subject");
+       if ((len = X509_NAME_get_text_by_NID(subj, NID_commonName, cname, sizeof(cname))) < 0)
+               return error("cannot get certificate common name");
+       if (strlen(cname) == (size_t)len && host_matches(hostname, cname))
+               return 0;
+       return error("certificate owner '%s' does not match hostname '%s'",
+                    cname, hostname);
+}
+
+static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify)
+{
 #if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
        const SSL_METHOD *meth;
 #else
@@ -279,6 +332,7 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
 #endif
        SSL_CTX *ctx;
        int ret;
+       X509 *cert;
 
        SSL_library_init();
        SSL_load_error_strings();
@@ -322,9 +376,18 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
                return -1;
        }
 
+       if (verify) {
+               /* make sure the hostname matches that of the certificate */
+               cert = SSL_get_peer_certificate(sock->ssl);
+               if (!cert)
+                       return error("unable to get peer certificate.");
+               if (verify_hostname(cert, server.host) < 0)
+                       return -1;
+       }
+
        return 0;
-#endif
 }
+#endif
 
 static int socket_read(struct imap_socket *sock, char *buf, int len)
 {
index 295361a8aa7d075bbb9fdb8173858e37f9a43211..8a36916567a234c354af9994df9c28788749e7fa 100644 (file)
@@ -1,29 +1,21 @@
 diff_cmd () {
+       empty_file=
+
        # p4merge does not like /dev/null
-       rm_local=
-       rm_remote=
        if test "/dev/null" = "$LOCAL"
        then
-               LOCAL="./p4merge-dev-null.LOCAL.$$"
-               >"$LOCAL"
-               rm_local=true
+               LOCAL="$(create_empty_file)"
        fi
        if test "/dev/null" = "$REMOTE"
        then
-               REMOTE="./p4merge-dev-null.REMOTE.$$"
-               >"$REMOTE"
-               rm_remote=true
+               REMOTE="$(create_empty_file)"
        fi
 
        "$merge_tool_path" "$LOCAL" "$REMOTE"
 
-       if test -n "$rm_local"
-       then
-               rm -f "$LOCAL"
-       fi
-       if test -n "$rm_remote"
+       if test -n "$empty_file"
        then
-               rm -f "$REMOTE"
+               rm -f "$empty_file"
        fi
 }
 
@@ -33,3 +25,10 @@ merge_cmd () {
        "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
        check_unchanged
 }
+
+create_empty_file () {
+       empty_file="${TMPDIR:-/tmp}/git-difftool-p4merge-empty-file.$$"
+       >"$empty_file"
+
+       printf "%s" "$empty_file"
+}
index c1c66bd408c50685c06fe7ff1e1c6a78c26be1b1..7ca8f2caef5606cdac98e9a96c0226a53695f763 100644 (file)
@@ -3,6 +3,7 @@
 #include "cache.h"
 #include "commit.h"
 #include "color.h"
+#include "utf8.h"
 
 static int parse_options_usage(struct parse_opt_ctx_t *ctx,
                               const char * const *usagestr,
@@ -470,8 +471,11 @@ int parse_options(int argc, const char **argv, const char *prefix,
        default: /* PARSE_OPT_UNKNOWN */
                if (ctx.argv[0][1] == '-') {
                        error("unknown option `%s'", ctx.argv[0] + 2);
-               } else {
+               } else if (isascii(*ctx.opt)) {
                        error("unknown switch `%c'", *ctx.opt);
+               } else {
+                       error("unknown non-ascii option in string: `%s'",
+                             ctx.argv[0]);
                }
                usage_with_options(usagestr, options);
        }
@@ -491,7 +495,7 @@ static int usage_argh(const struct option *opts, FILE *outfile)
                        s = literal ? "[%s]" : "[<%s>]";
        else
                s = literal ? " %s" : " <%s>";
-       return fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
+       return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
 }
 
 #define USAGE_OPTS_WIDTH 24
@@ -550,7 +554,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
                if (opts->long_name)
                        pos += fprintf(outfile, "--%s", opts->long_name);
                if (opts->type == OPTION_NUMBER)
-                       pos += fprintf(outfile, "-NUM");
+                       pos += utf8_fprintf(outfile, _("-NUM"));
 
                if ((opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||
                    !(opts->flags & PARSE_OPT_NOARG))
index 931047c51da22cddefe0eab08d0fdaa595daefef..a56d1e76f797cdba83510a5488945425f1936c2d 100644 (file)
@@ -59,6 +59,7 @@ =head1 SYNOPSIS
                 command_bidi_pipe command_close_bidi_pipe
                 version exec_path html_path hash_object git_cmd_try
                 remote_refs prompt
+                get_tz_offset
                 temp_acquire temp_release temp_reset temp_path);
 
 
@@ -102,6 +103,7 @@ =head1 DESCRIPTION
 use Cwd qw(abs_path cwd);
 use IPC::Open2 qw(open2);
 use Fcntl qw(SEEK_SET SEEK_CUR);
+use Time::Local qw(timegm);
 }
 
 
@@ -511,6 +513,27 @@ sub version {
 
 sub html_path { command_oneline('--html-path') }
 
+
+=item get_tz_offset ( TIME )
+
+Return the time zone offset from GMT in the form +/-HHMM where HH is
+the number of hours from GMT and MM is the number of minutes.  This is
+the equivalent of what strftime("%z", ...) would provide on a GNU
+platform.
+
+If TIME is not supplied, the current local time is used.
+
+=cut
+
+sub get_tz_offset {
+       # some systmes don't handle or mishandle %z, so be creative.
+       my $t = shift || time;
+       my $gm = timegm(localtime($t));
+       my $sign = qw( + + - )[ $gm <=> $t ];
+       return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
+}
+
+
 =item prompt ( PROMPT , ISPASSWORD  )
 
 Query user C<PROMPT> and return answer from user.
index 59215fa86e2c2902ec97b12bea70736f9c7c02c6..8c84560a495203a47b77faac36e5661aeace5df0 100644 (file)
@@ -11,7 +11,6 @@ package Git::SVN;
 use File::Path qw/mkpath/;
 use File::Copy qw/copy/;
 use IPC::Open3;
-use Time::Local;
 use Memoize;  # core since 5.8.0, Jul 2002
 use Memoize::Storable;
 use POSIX qw(:signal_h);
@@ -22,6 +21,7 @@ package Git::SVN;
     command_noisy
     command_output_pipe
     command_close_pipe
+    get_tz_offset
 );
 use Git::SVN::Utils qw(
        fatal
@@ -1311,14 +1311,6 @@ sub get_untracked {
        \@out;
 }
 
-sub get_tz {
-       # some systmes don't handle or mishandle %z, so be creative.
-       my $t = shift || time;
-       my $gm = timelocal(gmtime($t));
-       my $sign = qw( + + - )[ $t <=> $gm ];
-       return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
-}
-
 # parse_svn_date(DATE)
 # --------------------
 # Given a date (in UTC) from Subversion, return a string in the format
@@ -1351,7 +1343,7 @@ sub parse_svn_date {
                        delete $ENV{TZ};
                }
 
-               my $our_TZ = get_tz();
+               my $our_TZ = get_tz_offset();
 
                # This converts $epoch_in_UTC into our local timezone.
                my ($sec, $min, $hour, $mday, $mon, $year,
index 3cc1c6f0817fe307390852c54a07cb2a07404f7e..3f8350a57d64ca3335d279c6563fad54b56eb22a 100644 (file)
@@ -2,7 +2,11 @@ package Git::SVN::Log;
 use strict;
 use warnings;
 use Git::SVN::Utils qw(fatal);
-use Git qw(command command_oneline command_output_pipe command_close_pipe);
+use Git qw(command
+           command_oneline
+           command_output_pipe
+           command_close_pipe
+           get_tz_offset);
 use POSIX qw/strftime/;
 use constant commit_log_separator => ('-' x 72) . "\n";
 use vars qw/$TZ $limit $color $pager $non_recursive $verbose $oneline
@@ -119,7 +123,7 @@ sub run_pager {
 sub format_svn_date {
        my $t = shift || time;
        require Git::SVN;
-       my $gmoff = Git::SVN::get_tz($t);
+       my $gmoff = get_tz_offset($t);
        return strftime("%Y-%m-%d %H:%M:%S $gmoff (%a, %d %b %Y)", localtime($t));
 }
 
index 9a8b12350712422e660f40fdf5ef9f191d37de99..933c69ac2627c1903276b92b457843e12649f39e 100644 (file)
@@ -92,6 +92,8 @@ static void free_discovery(struct discovery *d)
 
 static struct discovery* discover_refs(const char *service)
 {
+       struct strbuf exp = STRBUF_INIT;
+       struct strbuf type = STRBUF_INIT;
        struct strbuf buffer = STRBUF_INIT;
        struct discovery *last = last_discovery;
        char *refs_url;
@@ -113,7 +115,7 @@ static struct discovery* discover_refs(const char *service)
        }
        refs_url = strbuf_detach(&buffer, NULL);
 
-       http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
+       http_ret = http_get_strbuf(refs_url, &type, &buffer, HTTP_NO_CACHE);
        switch (http_ret) {
        case HTTP_OK:
                break;
@@ -132,17 +134,20 @@ static struct discovery* discover_refs(const char *service)
        last->buf_alloc = strbuf_detach(&buffer, &last->len);
        last->buf = last->buf_alloc;
 
-       if (maybe_smart && 5 <= last->len && last->buf[4] == '#') {
-               /* smart HTTP response; validate that the service
+       strbuf_addf(&exp, "application/x-%s-advertisement", service);
+       if (maybe_smart &&
+           (5 <= last->len && last->buf[4] == '#') &&
+           !strbuf_cmp(&exp, &type)) {
+               /*
+                * smart HTTP response; validate that the service
                 * pkt-line matches our request.
                 */
-               struct strbuf exp = STRBUF_INIT;
-
                if (packet_get_line(&buffer, &last->buf, &last->len) <= 0)
                        die("%s has invalid packet header", refs_url);
                if (buffer.len && buffer.buf[buffer.len - 1] == '\n')
                        strbuf_setlen(&buffer, buffer.len - 1);
 
+               strbuf_reset(&exp);
                strbuf_addf(&exp, "# service=%s", service);
                if (strbuf_cmp(&exp, &buffer))
                        die("invalid server response; got '%s'", buffer.buf);
@@ -160,6 +165,8 @@ static struct discovery* discover_refs(const char *service)
        }
 
        free(refs_url);
+       strbuf_release(&exp);
+       strbuf_release(&type);
        strbuf_release(&buffer);
        last_discovery = last;
        return last;
index 02f442bfadbb1239785a456cddc50223da4f3834..895b9258b07ca65b78ac376023e203f482d8ac16 100644 (file)
@@ -80,6 +80,7 @@ fi
 prepare_httpd() {
        mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH"
        cp "$TEST_PATH"/passwd "$HTTPD_ROOT_PATH"
+       cp "$TEST_PATH"/broken-smart-http.sh "$HTTPD_ROOT_PATH"
 
        ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
 
index fe76e84b74472a431eef59a1f4936cfc69367003..938b4cf803b3b4ea07be20338425f784b80cdf0c 100644 (file)
@@ -62,9 +62,13 @@ Alias /auth/dumb/ www/auth/dumb/
        SetEnv GIT_COMMITTER_EMAIL custom@example.com
 </LocationMatch>
 ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
+ScriptAlias /broken_smart/ broken-smart-http.sh/
 <Directory ${GIT_EXEC_PATH}>
        Options FollowSymlinks
 </Directory>
+<Files broken-smart-http.sh>
+       Options ExecCGI
+</Files>
 <Files ${GIT_EXEC_PATH}/git-http-backend>
        Options ExecCGI
 </Files>
diff --git a/t/lib-httpd/broken-smart-http.sh b/t/lib-httpd/broken-smart-http.sh
new file mode 100755 (executable)
index 0000000..f7ebfff
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+printf "Content-Type: text/%s\n" "html"
+echo
+printf "%s\n" "001e# service=git-upload-pack"
+printf "%s"   "0000"
+printf "%s%c%s%s\n" \
+       "00a58681d9f286a48b08f37b3a095330da16689e3693 HEAD" \
+       0 \
+       " include-tag multi_ack_detailed multi_ack ofs-delta" \
+       " side-band side-band-64k thin-pack no-progress shallow no-done "
+printf "%s"   "0000"
index 40277c77aad5f2d9533e6822da3380bb49621e59..614425adac536d84e6835d9d707b86fe8f5f4d36 100755 (executable)
@@ -89,4 +89,28 @@ test_expect_success 'diagnose truncated file' '
        grep "diff --cc file" out
 '
 
+test_expect_success 'setup for --cc --raw' '
+       blob=$(echo file | git hash-object --stdin -w) &&
+       base_tree=$(echo "100644 blob $blob     file" | git mktree) &&
+       trees= &&
+       for i in `test_seq 1 40`
+       do
+               blob=$(echo file$i | git hash-object --stdin -w) &&
+               trees="$trees$(echo "100644 blob $blob  file" | git mktree)$LF"
+       done
+'
+
+test_expect_success 'check --cc --raw with four trees' '
+       four_trees=$(echo "$trees" | sed -e 4q) &&
+       git diff --cc --raw $four_trees $base_tree >out &&
+       # Check for four leading colons in the output:
+       grep "^::::[^:]" out
+'
+
+test_expect_success 'check --cc --raw with forty trees' '
+       git diff --cc --raw $trees $base_tree >out &&
+       # Check for forty leading colons in the output:
+       grep "^::::::::::::::::::::::::::::::::::::::::[^:]" out
+'
+
 test_done
index c5cd2e348c6fe47af7d94ef6852757c301f8097a..47eb76921ddd53acb63573f9af75e41ab5067f5c 100755 (executable)
@@ -157,6 +157,11 @@ test_expect_success 'GIT_SMART_HTTP can disable smart http' '
         test_must_fail git fetch)
 '
 
+test_expect_success 'invalid Content-Type rejected' '
+       test_must_fail git clone $HTTPD_URL/broken_smart/repo.git 2>actual
+       grep "not valid:" actual
+'
+
 test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
 
 test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
index b3f6eb9c684c406dd896a144caa6afc160b03226..95d651080f05930d0311ff69d3641bad403eecb2 100755 (executable)
@@ -5,7 +5,7 @@
 #                   Grenoble INP Ensimag
 #
 
-test_description='git status advices'
+test_description='git status advice'
 
 . ./test-lib.sh
 
diff --git a/utf8.c b/utf8.c
index a4ee6650ef6c4c487c083aabf0a950b8ec317b09..1087870c51caff3dd86a852ec5e8bf5875f6d797 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -429,6 +429,27 @@ int same_encoding(const char *src, const char *dst)
        return !strcasecmp(src, dst);
 }
 
+/*
+ * Wrapper for fprintf and returns the total number of columns required
+ * for the printed string, assuming that the string is utf8.
+ */
+int utf8_fprintf(FILE *stream, const char *format, ...)
+{
+       struct strbuf buf = STRBUF_INIT;
+       va_list arg;
+       int columns;
+
+       va_start(arg, format);
+       strbuf_vaddf(&buf, format, arg);
+       va_end(arg);
+
+       columns = fputs(buf.buf, stream);
+       if (0 <= columns) /* keep the error from the I/O */
+               columns = utf8_strwidth(buf.buf);
+       strbuf_release(&buf);
+       return columns;
+}
+
 /*
  * Given a buffer and its encoding, return it re-encoded
  * with iconv.  If the conversion fails, returns NULL.
diff --git a/utf8.h b/utf8.h
index a214238bdd70c6b4eb41edf6626c5b396489ab50..501b2bd9c4fd3fdce6dcbba1a3e3f7c0211d6c8f 100644 (file)
--- a/utf8.h
+++ b/utf8.h
@@ -8,6 +8,7 @@ int utf8_strwidth(const char *string);
 int is_utf8(const char *text);
 int is_encoding_utf8(const char *name);
 int same_encoding(const char *, const char *);
+int utf8_fprintf(FILE *, const char *, ...);
 
 void strbuf_add_wrapped_text(struct strbuf *buf,
                const char *text, int indent, int indent2, int width);