builtin/push.c: use strbuf instead of manual allocation

The command line arguments given to "git push" are massaged into
a list of refspecs in set_refspecs() function. This was implemented
using xmalloc, strcpy and friends, but it is much easier to read if
done using strbuf.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
send-email: pass Debug to Net::SMTP::SSL::new

We forgot to pass the Debug option through to Net::SMTP::SSL->new --
which is the same as Net::SMTP->new.  This meant that with security
set to SSL, we would never enable debug output.

Pass through the flag.

Signed-off-by: Thomas Rast <tr@thomasrast.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
send-email: --smtp-ssl-cert-path takes an argument

35035bb (send-email: be explicit with SSL certificate verification,
2013-07-18) forgot to specify that --smtp-ssl-cert-path takes a string
argument.  This means that the option could not actually be used as
intended.  Presumably noone noticed because it's much easier to set it
through configs anyway.

Add the required "=s".

Signed-off-by: Thomas Rast <tr@thomasrast.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
send-email: set SSL options through IO::Socket::SSL::set_client_defaults

When --smtp-encryption=ssl, we use a Net::SMTP::SSL connection,
passing its ->new all the options that would otherwise go to
Net::SMTP->new (most options) and IO::Socket::SSL->start_SSL (for the
SSL options).

However, while Net::SMTP::SSL replaces the underlying socket class
with an SSL socket, it does nothing to allow passing options to that
socket.  So the SSL-relevant options are lost.

Fortunately there is an escape hatch: we can directly set the options
with IO::Socket::SSL::set_client_defaults.  They will then persist
within the IO::Socket::SSL module.

Signed-off-by: Thomas Rast <tr@thomasrast.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
mv: let 'git mv file no-such-dir/' error out

Git used to trim the trailing slash, and make the command equivalent
to 'git mv file no-such-dir', which created the file no-such-dir
(while the trailing slash explicitly stated that it could only be a
directory).

This patch skips the trailing slash removal for the destination
path.  The path with its trailing slash is passed to rename(2),
which errors out with the appropriate message:

  $ git mv file no-such-dir/
  fatal: renaming 'file' failed: Not a directory

Original-patch-by: Duy Nguyen <pclouds@gmail.com>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
gitweb: Move check-ref-format code into separate function

This check will be used in more than one place later.

Signed-off-by: Krzesimir Nowak <krzesimir@endocode.com>
Reviewed-by: Jakub Narębski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
gitweb: Return plain booleans in validation methods

Users of validate_* passing "0" might get failures on correct name
because of coercion of "0" to false in code like:
die_error(500, "invalid ref") unless (check_ref_format ("0"));

Signed-off-by: Krzesimir Nowak <krzesimir@endocode.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
gitweb: Add a feature for adding more branch refs

Allow extra-branch-refs feature to tell gitweb to show refs from
additional hierarchies in addition to branches in the list-of-branches
view.

Signed-off-by: Krzesimir Nowak <krzesimir@endocode.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
gitweb: Denote non-heads, non-remotes branches

Given two branches residing in refs/heads/master and refs/wip/feature
the list-of-branches view will present them in following way:
master
feature (wip)

When getting a snapshot of a 'feature' branch, the tarball is going to
have name like 'project-wip-feature-<short hash>.tgz'.

Signed-off-by: Krzesimir Nowak <krzesimir@endocode.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
push: use remote.$name.push as a refmap

Since f2690487 (fetch: opportunistically update tracking refs,
2013-05-11), we stopped taking a non-storing refspec given on the
command line of "git fetch" literally, and instead started mapping
it via remote.$name.fetch refspecs.  This allows

    $ git fetch origin master

from the 'origin' repository, which is configured with

    [remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*

to update refs/remotes/origin/master with the result, as if the
command line were

    $ git fetch origin +master:refs/remotes/origin/master

to reduce surprises and improve usability.  Before that change, a
refspec on the command line without a colon was only to fetch the
history and leave the result in FETCH_HEAD, without updating the
remote-tracking branches.

When you are simulating a fetch from you by your mothership with a
push by you into your mothership, instead of having:

    [remote "satellite"]
        fetch = +refs/heads/*:refs/remotes/satellite/*

on the mothership repository and running:

    mothership$ git fetch satellite

you would have:

    [remote "mothership"]
        push = +refs/heads/*:refs/remotes/satellite/*

on your satellite machine, and run:

    satellite$ git push mothership

Because we so far did not make the corresponding change to the push
side, this command:

    satellite$ git push mothership master

does _not_ allow you on the satellite to only push 'master' out but
still to the usual destination (i.e. refs/remotes/satellite/master).

Implement the logic to map an unqualified refspec given on the
command line via the remote.$name.push refspec.  This will bring a
bit more symmetry between "fetch" and "push".

Signed-off-by: Junio C Hamano <gitster@pobox.com>
push: also use "upstream" mapping when pushing a single ref

When the user is using the 'upstream' mode, these commands:

    $ git push
    $ git push origin

would find the 'upstream' branch for the current branch, and then
push the current branch to update it.  However, pushing a single
branch explicitly, i.e.

    $ git push origin $(git symbolic-ref --short HEAD)

would not go through the same ref mapping process, and ends up
updating the branch at 'origin' of the same name, which may not
necessarily be the upstream of the branch being pushed.

In the spirit similar to the previous one, map a colon-less refspec
using the upstream mapping logic.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
t5601: remove clear_ssh, refactor setup_ssh_wrapper

Commit 8d3d28f5 added test cases for URLs which should be ssh.
Remove the function clear_ssh, use test_when_finished to clean up.

Introduce the function setup_ssh_wrapper, which could be factored
out together with expect_ssh.

Tighten one test and use "foo:bar" instead of "./foo:bar",

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
t5601: add tests for ssh

Add more tests testing all the combinations:

 -IPv4 or IPv6
 -path starting with "/" or with "/~"
 -with and without the ssh:// scheme

Some tests fail; they need updates in connect.c

Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git_connect: remove artificial limit of a remote command

Since day one, function git_connect() had a limit on the command line of
the command that is invoked to make a connection. 7a33bcbe converted the
code that constructs the command to strbuf. This would have been the
right time to remove the limit, but it did not happen. Remove it now.

git_connect() uses start_command() to invoke the command; consequently,
the limits of the system still apply, but are diagnosed only at execve()
time. But these limits are more lenient than the 1K that git_connect()
imposed.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git_connect: factor out discovery of the protocol and its parts

git_connect has grown large due to the many different protocols syntaxes
that are supported. Move the part of the function that parses the URL to
connect to into a separate function for readability.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git fetch-pack: add --diag-url

The main purpose is to trace the URL parser called by git_connect() in
connect.c

The main features of the parser can be listed as this:

- parse out host and path for URLs with a scheme (git:// file:// ssh://)
- parse host names embedded by [] correctly
- extract the port number, if present
- separate URLs like "file" (which are local)
  from URLs like "host:repo" which should use ssh

Add the new parameter "--diag-url" to "git fetch-pack", which prints
the value for protocol, host and path to stderr and exits.

Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
t5500: add test cases for diag-url

Add test cases using git fetch-pack --diag-url:

- parse out host and path for URLs with a scheme (git:// file:// ssh://)
- parse host names embedded by [] correctly
- extract the port number, if present
- separate URLs like "file" (which are local)
  from URLs like "host:repo" which should use ssh

Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git fetch: support host:/~repo

The documentation (in urls.txt) says that

    "ssh://host:/~repo",
    "host:/~repo" or
    "host:~repo"

specify the repository "repo" in the home directory at "host".

This has not been working for "host:/~repo".

Before commit 356bec "Support [address] in URLs", the comparison
"url != hostname" could be used to determine if the URL had a scheme
or not: "ssh://host/host" != "host".

However, after 356bec "[::1]" was converted into "::1", yielding
url != hostname as well.  To fix this regression, don't use
"if (url != hostname)", but look at the separator instead.

Rename the variable "c" into "separator" to make it easier to read.

Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git_connect(): refactor the port handling for ssh

Use get_host_and_port() even for ssh.
Remove the variable port git_connect(), and simplify parse_connect_url()
Use only one return point in git_connect(), doing the free() and return conn.

t5601 had 2 corner test cases which now pass.

Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
connect.c: refactor url parsing

Make the function is_local() in transport.c public, rename it into
url_is_local_not_ssh() and use it in both transport.c and connect.c

Use a protocol "local" for URLs for the local file system.

One note about using file:// under Windows:

The (absolute) path on Unix like system typically starts with "/".
When the host is empty, it can be omitted, so that a shell scriptlet
url=file://$pwd
will give a URL like "file:///home/user/repo".

Windows does not have the same concept of a root directory located in "/".
When parsing the URL allow "file://C:/user/repo"
(even if RFC1738 indicates that "file:///C:/user/repo" should be used).

Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>