mirror of
https://github.com/git/git.git
synced 2026-03-14 10:53:25 +01:00
Merge branch 'pb/diffroot' into next
* pb/diffroot:
config option log.showroot to show the diff of root commits
git-svn: handle authentication without relying on cached tokens on disk
git-cvsimport: add support for CVS pserver method HTTP/1.x proxying
Make git-clone --use-separate-remote the default
refs outside refs/{heads,tags} match less strongly.
Increase length of function name buffer
git-svn: preserve uncommitted changes after dcommit
git-svn: correctly handle revision 0 in SVN repositories
git-svn: error out from dcommit on a parent-less commit
archive-zip: don't use sizeof(struct ...)
This commit is contained in:
@@ -219,6 +219,12 @@ i18n.commitEncoding::
|
||||
browser (and possibly at other places in the future or in other
|
||||
porcelains). See e.g. gitlink:git-mailinfo[1]. Defaults to 'utf-8'.
|
||||
|
||||
log.showroot::
|
||||
If true, the initial commit will be shown as a big creation event.
|
||||
This is equivalent to a diff against an empty tree.
|
||||
Tools like gitlink:git-log[1] or gitlink:git-whatchanged[1], which
|
||||
normally hide the root commit will now show it. True by default.
|
||||
|
||||
merge.summary::
|
||||
Whether to include summaries of merged commits in newly created
|
||||
merge commit messages. False by default.
|
||||
|
||||
@@ -11,7 +11,8 @@ SYNOPSIS
|
||||
[verse]
|
||||
'git-clone' [--template=<template_directory>] [-l [-s]] [-q] [-n] [--bare]
|
||||
[-o <name>] [-u <upload-pack>] [--reference <repository>]
|
||||
[--use-separate-remote] <repository> [<directory>]
|
||||
[--use-separate-remote | --use-immingled-remote] <repository>
|
||||
[<directory>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -71,9 +72,13 @@ OPTIONS
|
||||
Make a 'bare' GIT repository. That is, instead of
|
||||
creating `<directory>` and placing the administrative
|
||||
files in `<directory>/.git`, make the `<directory>`
|
||||
itself the `$GIT_DIR`. This implies `-n` option. When
|
||||
this option is used, neither the `origin` branch nor the
|
||||
default `remotes/origin` file is created.
|
||||
itself the `$GIT_DIR`. This obviously implies the `-n`
|
||||
because there is nowhere to check out the working tree.
|
||||
Also the branch heads at the remote are copied directly
|
||||
to corresponding local branch heads, without mapping
|
||||
them to `refs/remotes/origin/`. When this option is
|
||||
used, neither the `origin` branch nor the default
|
||||
`remotes/origin` file is created.
|
||||
|
||||
--origin <name>::
|
||||
-o <name>::
|
||||
@@ -97,8 +102,15 @@ OPTIONS
|
||||
|
||||
--use-separate-remote::
|
||||
Save remotes heads under `$GIT_DIR/remotes/origin/` instead
|
||||
of `$GIT_DIR/refs/heads/`. Only the master branch is saved
|
||||
in the latter.
|
||||
of `$GIT_DIR/refs/heads/`. Only the local master branch is
|
||||
saved in the latter. This is the default.
|
||||
|
||||
--use-immingled-remote::
|
||||
Save remotes heads in the same namespace as the local
|
||||
heads, `$GIT_DIR/refs/heads/'. In regular repositories,
|
||||
this is a legacy setup git-clone created by default in
|
||||
older Git versions, and will be removed before the next
|
||||
major release.
|
||||
|
||||
<repository>::
|
||||
The (possibly remote) repository to clone from. It can
|
||||
|
||||
@@ -35,6 +35,7 @@ struct zip_local_header {
|
||||
unsigned char size[4];
|
||||
unsigned char filename_length[2];
|
||||
unsigned char extra_length[2];
|
||||
unsigned char _end[1];
|
||||
};
|
||||
|
||||
struct zip_dir_header {
|
||||
@@ -55,6 +56,7 @@ struct zip_dir_header {
|
||||
unsigned char attr1[2];
|
||||
unsigned char attr2[4];
|
||||
unsigned char offset[4];
|
||||
unsigned char _end[1];
|
||||
};
|
||||
|
||||
struct zip_dir_trailer {
|
||||
@@ -66,8 +68,18 @@ struct zip_dir_trailer {
|
||||
unsigned char size[4];
|
||||
unsigned char offset[4];
|
||||
unsigned char comment_length[2];
|
||||
unsigned char _end[1];
|
||||
};
|
||||
|
||||
/*
|
||||
* On ARM, padding is added at the end of the struct, so a simple
|
||||
* sizeof(struct ...) reports two bytes more than the payload size
|
||||
* we're interested in.
|
||||
*/
|
||||
#define ZIP_LOCAL_HEADER_SIZE offsetof(struct zip_local_header, _end)
|
||||
#define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
|
||||
#define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
|
||||
|
||||
static void copy_le16(unsigned char *dest, unsigned int n)
|
||||
{
|
||||
dest[0] = 0xff & n;
|
||||
@@ -211,7 +223,7 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
}
|
||||
|
||||
/* make sure we have enough free space in the dictionary */
|
||||
direntsize = sizeof(struct zip_dir_header) + pathlen;
|
||||
direntsize = ZIP_DIR_HEADER_SIZE + pathlen;
|
||||
while (zip_dir_size < zip_dir_offset + direntsize) {
|
||||
zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
|
||||
zip_dir = xrealloc(zip_dir, zip_dir_size);
|
||||
@@ -234,8 +246,8 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
copy_le16(dirent.attr1, 0);
|
||||
copy_le32(dirent.attr2, attr2);
|
||||
copy_le32(dirent.offset, zip_offset);
|
||||
memcpy(zip_dir + zip_dir_offset, &dirent, sizeof(struct zip_dir_header));
|
||||
zip_dir_offset += sizeof(struct zip_dir_header);
|
||||
memcpy(zip_dir + zip_dir_offset, &dirent, ZIP_DIR_HEADER_SIZE);
|
||||
zip_dir_offset += ZIP_DIR_HEADER_SIZE;
|
||||
memcpy(zip_dir + zip_dir_offset, path, pathlen);
|
||||
zip_dir_offset += pathlen;
|
||||
zip_dir_entries++;
|
||||
@@ -251,8 +263,8 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
copy_le32(header.size, uncompressed_size);
|
||||
copy_le16(header.filename_length, pathlen);
|
||||
copy_le16(header.extra_length, 0);
|
||||
write_or_die(1, &header, sizeof(struct zip_local_header));
|
||||
zip_offset += sizeof(struct zip_local_header);
|
||||
write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
|
||||
zip_offset += ZIP_LOCAL_HEADER_SIZE;
|
||||
write_or_die(1, path, pathlen);
|
||||
zip_offset += pathlen;
|
||||
if (compressed_size > 0) {
|
||||
@@ -282,7 +294,7 @@ static void write_zip_trailer(const unsigned char *sha1)
|
||||
copy_le16(trailer.comment_length, sha1 ? 40 : 0);
|
||||
|
||||
write_or_die(1, zip_dir, zip_dir_offset);
|
||||
write_or_die(1, &trailer, sizeof(struct zip_dir_trailer));
|
||||
write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE);
|
||||
if (sha1)
|
||||
write_or_die(1, sha1_to_hex(sha1), 40);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static int default_show_root = 1;
|
||||
|
||||
/* this is in builtin-diff.c */
|
||||
void add_head(struct rev_info *revs);
|
||||
|
||||
@@ -22,6 +24,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
|
||||
rev->abbrev = DEFAULT_ABBREV;
|
||||
rev->commit_format = CMIT_FMT_DEFAULT;
|
||||
rev->verbose_header = 1;
|
||||
rev->show_root_diff = default_show_root;
|
||||
argc = setup_revisions(argc, argv, rev, "HEAD");
|
||||
if (rev->diffopt.pickaxe || rev->diffopt.filter)
|
||||
rev->always_show_header = 0;
|
||||
@@ -44,11 +47,20 @@ static int cmd_log_walk(struct rev_info *rev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_log_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "log.showroot")) {
|
||||
default_show_root = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
return git_diff_ui_config(var, value);
|
||||
}
|
||||
|
||||
int cmd_whatchanged(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct rev_info rev;
|
||||
|
||||
git_config(git_diff_ui_config);
|
||||
git_config(git_log_config);
|
||||
init_revisions(&rev, prefix);
|
||||
rev.diff = 1;
|
||||
rev.diffopt.recursive = 1;
|
||||
@@ -63,7 +75,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct rev_info rev;
|
||||
|
||||
git_config(git_diff_ui_config);
|
||||
git_config(git_log_config);
|
||||
init_revisions(&rev, prefix);
|
||||
rev.diff = 1;
|
||||
rev.diffopt.recursive = 1;
|
||||
@@ -80,7 +92,7 @@ int cmd_log(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct rev_info rev;
|
||||
|
||||
git_config(git_diff_ui_config);
|
||||
git_config(git_log_config);
|
||||
init_revisions(&rev, prefix);
|
||||
rev.always_show_header = 1;
|
||||
cmd_log_init(argc, argv, prefix, &rev);
|
||||
@@ -109,7 +121,7 @@ static int git_format_config(const char *var, const char *value)
|
||||
if (!strcmp(var, "diff.color")) {
|
||||
return 0;
|
||||
}
|
||||
return git_diff_ui_config(var, value);
|
||||
return git_log_config(var, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
47
connect.c
47
connect.c
@@ -174,21 +174,58 @@ static int count_refspec_match(const char *pattern,
|
||||
struct ref *refs,
|
||||
struct ref **matched_ref)
|
||||
{
|
||||
int match;
|
||||
int patlen = strlen(pattern);
|
||||
struct ref *matched_weak = NULL;
|
||||
struct ref *matched = NULL;
|
||||
int weak_match = 0;
|
||||
int match = 0;
|
||||
|
||||
for (match = 0; refs; refs = refs->next) {
|
||||
for (weak_match = match = 0; refs; refs = refs->next) {
|
||||
char *name = refs->name;
|
||||
int namelen = strlen(name);
|
||||
int weak_match;
|
||||
|
||||
if (namelen < patlen ||
|
||||
memcmp(name + namelen - patlen, pattern, patlen))
|
||||
continue;
|
||||
if (namelen != patlen && name[namelen - patlen - 1] != '/')
|
||||
continue;
|
||||
match++;
|
||||
*matched_ref = refs;
|
||||
|
||||
/* A match is "weak" if it is with refs outside
|
||||
* heads or tags, and did not specify the pattern
|
||||
* in full (e.g. "refs/remotes/origin/master") or at
|
||||
* least from the toplevel (e.g. "remotes/origin/master");
|
||||
* otherwise "git push $URL master" would result in
|
||||
* ambiguity between remotes/origin/master and heads/master
|
||||
* at the remote site.
|
||||
*/
|
||||
if (namelen != patlen &&
|
||||
patlen != namelen - 5 &&
|
||||
strncmp(name, "refs/heads/", 11) &&
|
||||
strncmp(name, "refs/tags/", 10)) {
|
||||
/* We want to catch the case where only weak
|
||||
* matches are found and there are multiple
|
||||
* matches, and where more than one strong
|
||||
* matches are found, as ambiguous. One
|
||||
* strong match with zero or more weak matches
|
||||
* are acceptable as a unique match.
|
||||
*/
|
||||
matched_weak = refs;
|
||||
weak_match++;
|
||||
}
|
||||
else {
|
||||
matched = refs;
|
||||
match++;
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
*matched_ref = matched_weak;
|
||||
return weak_match;
|
||||
}
|
||||
else {
|
||||
*matched_ref = matched;
|
||||
return match;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
static void link_dst_tail(struct ref *ref, struct ref ***tail)
|
||||
|
||||
14
git-clone.sh
14
git-clone.sh
@@ -14,7 +14,7 @@ die() {
|
||||
}
|
||||
|
||||
usage() {
|
||||
die "Usage: $0 [--template=<template_directory>] [--use-separate-remote] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [-n] <repo> [<dir>]"
|
||||
die "Usage: $0 [--template=<template_directory>] [--use-immingled-remote] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [-n] <repo> [<dir>]"
|
||||
}
|
||||
|
||||
get_repo_base() {
|
||||
@@ -115,7 +115,7 @@ bare=
|
||||
reference=
|
||||
origin=
|
||||
origin_override=
|
||||
use_separate_remote=
|
||||
use_separate_remote=t
|
||||
while
|
||||
case "$#,$1" in
|
||||
0,*) break ;;
|
||||
@@ -134,7 +134,10 @@ while
|
||||
template="$1" ;;
|
||||
*,-q|*,--quiet) quiet=-q ;;
|
||||
*,--use-separate-remote)
|
||||
# default
|
||||
use_separate_remote=t ;;
|
||||
*,--use-immingled-remote)
|
||||
use_separate_remote= ;;
|
||||
1,--reference) usage ;;
|
||||
*,--reference)
|
||||
shift; reference="$1" ;;
|
||||
@@ -169,18 +172,15 @@ repo="$1"
|
||||
test -n "$repo" ||
|
||||
die 'you must specify a repository to clone.'
|
||||
|
||||
# --bare implies --no-checkout
|
||||
# --bare implies --no-checkout and --use-immingled-remote
|
||||
if test yes = "$bare"
|
||||
then
|
||||
if test yes = "$origin_override"
|
||||
then
|
||||
die '--bare and --origin $origin options are incompatible.'
|
||||
fi
|
||||
if test t = "$use_separate_remote"
|
||||
then
|
||||
die '--bare and --use-separate-remote options are incompatible.'
|
||||
fi
|
||||
no_checkout=yes
|
||||
use_separate_remote=
|
||||
fi
|
||||
|
||||
if test -z "$origin"
|
||||
|
||||
@@ -161,8 +161,22 @@ sub new {
|
||||
sub conn {
|
||||
my $self = shift;
|
||||
my $repo = $self->{'fullrep'};
|
||||
if($repo =~ s/^:pserver:(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?//) {
|
||||
my($user,$pass,$serv,$port) = ($1,$2,$3,$4);
|
||||
if($repo =~ s/^:pserver(?:([^:]*)):(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?//) {
|
||||
my($param,$user,$pass,$serv,$port) = ($1,$2,$3,$4,$5);
|
||||
|
||||
my($proxyhost,$proxyport);
|
||||
if($param && ($param =~ m/proxy=([^;]+)/)) {
|
||||
$proxyhost = $1;
|
||||
# Default proxyport, if not specified, is 8080.
|
||||
$proxyport = 8080;
|
||||
if($ENV{"CVS_PROXY_PORT"}) {
|
||||
$proxyport = $ENV{"CVS_PROXY_PORT"};
|
||||
}
|
||||
if($param =~ m/proxyport=([^;]+)/){
|
||||
$proxyport = $1;
|
||||
}
|
||||
}
|
||||
|
||||
$user="anonymous" unless defined $user;
|
||||
my $rr2 = "-";
|
||||
unless($port) {
|
||||
@@ -187,13 +201,43 @@ sub conn {
|
||||
}
|
||||
$pass="A" unless $pass;
|
||||
|
||||
my $s = IO::Socket::INET->new(PeerHost => $serv, PeerPort => $port);
|
||||
die "Socket to $serv: $!\n" unless defined $s;
|
||||
my ($s, $rep);
|
||||
if($proxyhost) {
|
||||
|
||||
# Use a HTTP Proxy. Only works for HTTP proxies that
|
||||
# don't require user authentication
|
||||
#
|
||||
# See: http://www.ietf.org/rfc/rfc2817.txt
|
||||
|
||||
$s = IO::Socket::INET->new(PeerHost => $proxyhost, PeerPort => $proxyport);
|
||||
die "Socket to $proxyhost: $!\n" unless defined $s;
|
||||
$s->write("CONNECT $serv:$port HTTP/1.1\r\nHost: $serv:$port\r\n\r\n")
|
||||
or die "Write to $proxyhost: $!\n";
|
||||
$s->flush();
|
||||
|
||||
$rep = <$s>;
|
||||
|
||||
# The answer should look like 'HTTP/1.x 2yy ....'
|
||||
if(!($rep =~ m#^HTTP/1\.. 2[0-9][0-9]#)) {
|
||||
die "Proxy connect: $rep\n";
|
||||
}
|
||||
# Skip up to the empty line of the proxy server output
|
||||
# including the response headers.
|
||||
while ($rep = <$s>) {
|
||||
last if (!defined $rep ||
|
||||
$rep eq "\n" ||
|
||||
$rep eq "\r\n");
|
||||
}
|
||||
} else {
|
||||
$s = IO::Socket::INET->new(PeerHost => $serv, PeerPort => $port);
|
||||
die "Socket to $serv: $!\n" unless defined $s;
|
||||
}
|
||||
|
||||
$s->write("BEGIN AUTH REQUEST\n$repo\n$user\n$pass\nEND AUTH REQUEST\n")
|
||||
or die "Write to $serv: $!\n";
|
||||
$s->flush();
|
||||
|
||||
my $rep = <$s>;
|
||||
$rep = <$s>;
|
||||
|
||||
if($rep ne "I LOVE YOU\n") {
|
||||
$rep="<unknown>" unless $rep;
|
||||
|
||||
179
git-svn.perl
179
git-svn.perl
@@ -39,7 +39,7 @@ memoize('revisions_eq');
|
||||
memoize('cmt_metadata');
|
||||
memoize('get_commit_time');
|
||||
|
||||
my ($SVN_PATH, $SVN, $SVN_LOG, $_use_lib);
|
||||
my ($SVN_PATH, $SVN, $SVN_LOG, $_use_lib, $AUTH_BATON, $AUTH_CALLBACKS);
|
||||
|
||||
sub nag_lib {
|
||||
print STDERR <<EOF;
|
||||
@@ -66,7 +66,8 @@ my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
|
||||
$_template, $_shared, $_no_default_regex, $_no_graft_copy,
|
||||
$_limit, $_verbose, $_incremental, $_oneline, $_l_fmt, $_show_commit,
|
||||
$_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m,
|
||||
$_merge, $_strategy, $_dry_run, $_ignore_nodate, $_non_recursive);
|
||||
$_merge, $_strategy, $_dry_run, $_ignore_nodate, $_non_recursive,
|
||||
$_username, $_config_dir, $_no_auth_cache);
|
||||
my (@_branch_from, %tree_map, %users, %rusers, %equiv);
|
||||
my ($_svn_co_url_revs, $_svn_pg_peg_revs);
|
||||
my @repo_path_split_cache;
|
||||
@@ -79,6 +80,9 @@ my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
|
||||
'repack:i' => \$_repack,
|
||||
'no-metadata' => \$_no_metadata,
|
||||
'quiet|q' => \$_q,
|
||||
'username=s' => \$_username,
|
||||
'config-dir=s' => \$_config_dir,
|
||||
'no-auth-cache' => \$_no_auth_cache,
|
||||
'ignore-nodate' => \$_ignore_nodate,
|
||||
'repack-flags|repack-args|repack-opts=s' => \$_repack_flags);
|
||||
|
||||
@@ -232,7 +236,7 @@ sub rebuild {
|
||||
my @commit = grep(/^git-svn-id: /,`git-cat-file commit $c`);
|
||||
next if (!@commit); # skip merges
|
||||
my ($url, $rev, $uuid) = extract_metadata($commit[$#commit]);
|
||||
if (!$rev || !$uuid) {
|
||||
if (!defined $rev || !$uuid) {
|
||||
croak "Unable to extract revision or UUID from ",
|
||||
"$c, $commit[$#commit]\n";
|
||||
}
|
||||
@@ -589,6 +593,13 @@ sub dcommit {
|
||||
chomp(my @refs = safe_qx(qw/git-rev-list --no-merges/, "$gs..HEAD"));
|
||||
my $last_rev;
|
||||
foreach my $d (reverse @refs) {
|
||||
if (quiet_run('git-rev-parse','--verify',"$d~1") != 0) {
|
||||
die "Commit $d\n",
|
||||
"has no parent commit, and therefore ",
|
||||
"nothing to diff against.\n",
|
||||
"You should be working from a repository ",
|
||||
"originally created by git-svn\n";
|
||||
}
|
||||
unless (defined $last_rev) {
|
||||
(undef, $last_rev, undef) = cmt_metadata("$d~1");
|
||||
unless (defined $last_rev) {
|
||||
@@ -616,7 +627,7 @@ sub dcommit {
|
||||
} else {
|
||||
print "No changes between current HEAD and $gs\n",
|
||||
"Hard resetting to the latest $gs\n";
|
||||
@finish = qw/reset --hard/;
|
||||
@finish = qw/reset --mixed/;
|
||||
}
|
||||
sys('git', @finish, $gs);
|
||||
}
|
||||
@@ -825,8 +836,14 @@ sub commit_diff {
|
||||
print STDERR "Needed URL or usable git-svn id command-line\n";
|
||||
commit_diff_usage();
|
||||
}
|
||||
my $r = shift || $_revision;
|
||||
die "-r|--revision is a required argument\n" unless (defined $r);
|
||||
my $r = shift;
|
||||
unless (defined $r) {
|
||||
if (defined $_revision) {
|
||||
$r = $_revision
|
||||
} else {
|
||||
die "-r|--revision is a required argument\n";
|
||||
}
|
||||
}
|
||||
if (defined $_message && defined $_file) {
|
||||
print STDERR "Both --message/-m and --file/-F specified ",
|
||||
"for the commit message.\n",
|
||||
@@ -2486,7 +2503,7 @@ sub extract_metadata {
|
||||
my $id = shift or return (undef, undef, undef);
|
||||
my ($url, $rev, $uuid) = ($id =~ /^git-svn-id:\s(\S+?)\@(\d+)
|
||||
\s([a-f\d\-]+)$/x);
|
||||
if (!$rev || !$uuid || !$url) {
|
||||
if (!defined $rev || !$uuid || !$url) {
|
||||
# some of the original repositories I made had
|
||||
# identifiers like this:
|
||||
($rev, $uuid) = ($id =~/^git-svn-id:\s(\d+)\@([a-f\d\-]+)/);
|
||||
@@ -2670,18 +2687,154 @@ sub libsvn_load {
|
||||
my $kill_stupid_warnings = $SVN::Node::none.$SVN::Node::file.
|
||||
$SVN::Node::dir.$SVN::Node::unknown.
|
||||
$SVN::Node::none.$SVN::Node::file.
|
||||
$SVN::Node::dir.$SVN::Node::unknown;
|
||||
$SVN::Node::dir.$SVN::Node::unknown.
|
||||
$SVN::Auth::SSL::CNMISMATCH.
|
||||
$SVN::Auth::SSL::NOTYETVALID.
|
||||
$SVN::Auth::SSL::EXPIRED.
|
||||
$SVN::Auth::SSL::UNKNOWNCA.
|
||||
$SVN::Auth::SSL::OTHER;
|
||||
1;
|
||||
};
|
||||
}
|
||||
|
||||
sub _simple_prompt {
|
||||
my ($cred, $realm, $default_username, $may_save, $pool) = @_;
|
||||
$may_save = undef if $_no_auth_cache;
|
||||
$default_username = $_username if defined $_username;
|
||||
if (defined $default_username && length $default_username) {
|
||||
if (defined $realm && length $realm) {
|
||||
print "Authentication realm: $realm\n";
|
||||
}
|
||||
$cred->username($default_username);
|
||||
} else {
|
||||
_username_prompt($cred, $realm, $may_save, $pool);
|
||||
}
|
||||
$cred->password(_read_password("Password for '" .
|
||||
$cred->username . "': ", $realm));
|
||||
$cred->may_save($may_save);
|
||||
$SVN::_Core::SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
sub _ssl_server_trust_prompt {
|
||||
my ($cred, $realm, $failures, $cert_info, $may_save, $pool) = @_;
|
||||
$may_save = undef if $_no_auth_cache;
|
||||
print "Error validating server certificate for '$realm':\n";
|
||||
if ($failures & $SVN::Auth::SSL::UNKNOWNCA) {
|
||||
print " - The certificate is not issued by a trusted ",
|
||||
"authority. Use the\n",
|
||||
" fingerprint to validate the certificate manually!\n";
|
||||
}
|
||||
if ($failures & $SVN::Auth::SSL::CNMISMATCH) {
|
||||
print " - The certificate hostname does not match.\n";
|
||||
}
|
||||
if ($failures & $SVN::Auth::SSL::NOTYETVALID) {
|
||||
print " - The certificate is not yet valid.\n";
|
||||
}
|
||||
if ($failures & $SVN::Auth::SSL::EXPIRED) {
|
||||
print " - The certificate has expired.\n";
|
||||
}
|
||||
if ($failures & $SVN::Auth::SSL::OTHER) {
|
||||
print " - The certificate has an unknown error.\n";
|
||||
}
|
||||
printf( "Certificate information:\n".
|
||||
" - Hostname: %s\n".
|
||||
" - Valid: from %s until %s\n".
|
||||
" - Issuer: %s\n".
|
||||
" - Fingerprint: %s\n",
|
||||
map $cert_info->$_, qw(hostname valid_from valid_until
|
||||
issuer_dname fingerprint) );
|
||||
my $choice;
|
||||
prompt:
|
||||
print $may_save ?
|
||||
"(R)eject, accept (t)emporarily or accept (p)ermanently? " :
|
||||
"(R)eject or accept (t)emporarily? ";
|
||||
$choice = lc(substr(<STDIN> || 'R', 0, 1));
|
||||
if ($choice =~ /^t$/i) {
|
||||
$cred->may_save(undef);
|
||||
} elsif ($choice =~ /^r$/i) {
|
||||
return -1;
|
||||
} elsif ($may_save && $choice =~ /^p$/i) {
|
||||
$cred->may_save($may_save);
|
||||
} else {
|
||||
goto prompt;
|
||||
}
|
||||
$cred->accepted_failures($failures);
|
||||
$SVN::_Core::SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
sub _ssl_client_cert_prompt {
|
||||
my ($cred, $realm, $may_save, $pool) = @_;
|
||||
$may_save = undef if $_no_auth_cache;
|
||||
print "Client certificate filename: ";
|
||||
chomp(my $filename = <STDIN>);
|
||||
$cred->cert_file($filename);
|
||||
$cred->may_save($may_save);
|
||||
$SVN::_Core::SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
sub _ssl_client_cert_pw_prompt {
|
||||
my ($cred, $realm, $may_save, $pool) = @_;
|
||||
$may_save = undef if $_no_auth_cache;
|
||||
$cred->password(_read_password("Password: ", $realm));
|
||||
$cred->may_save($may_save);
|
||||
$SVN::_Core::SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
sub _username_prompt {
|
||||
my ($cred, $realm, $may_save, $pool) = @_;
|
||||
$may_save = undef if $_no_auth_cache;
|
||||
if (defined $realm && length $realm) {
|
||||
print "Authentication realm: $realm\n";
|
||||
}
|
||||
my $username;
|
||||
if (defined $_username) {
|
||||
$username = $_username;
|
||||
} else {
|
||||
print "Username: ";
|
||||
chomp($username = <STDIN>);
|
||||
}
|
||||
$cred->username($username);
|
||||
$cred->may_save($may_save);
|
||||
$SVN::_Core::SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
sub _read_password {
|
||||
my ($prompt, $realm) = @_;
|
||||
print $prompt;
|
||||
require Term::ReadKey;
|
||||
Term::ReadKey::ReadMode('noecho');
|
||||
my $password = '';
|
||||
while (defined(my $key = Term::ReadKey::ReadKey(0))) {
|
||||
last if $key =~ /[\012\015]/; # \n\r
|
||||
$password .= $key;
|
||||
}
|
||||
Term::ReadKey::ReadMode('restore');
|
||||
print "\n";
|
||||
$password;
|
||||
}
|
||||
|
||||
sub libsvn_connect {
|
||||
my ($url) = @_;
|
||||
my $auth = SVN::Core::auth_open([SVN::Client::get_simple_provider(),
|
||||
SVN::Client::get_ssl_server_trust_file_provider(),
|
||||
SVN::Client::get_username_provider()]);
|
||||
my $s = eval { SVN::Ra->new(url => $url, auth => $auth) };
|
||||
return $s;
|
||||
if (!$AUTH_BATON || !$AUTH_CALLBACKS) {
|
||||
SVN::_Core::svn_config_ensure($_config_dir, undef);
|
||||
($AUTH_BATON, $AUTH_CALLBACKS) = SVN::Core::auth_open_helper([
|
||||
SVN::Client::get_simple_provider(),
|
||||
SVN::Client::get_ssl_server_trust_file_provider(),
|
||||
SVN::Client::get_simple_prompt_provider(
|
||||
\&_simple_prompt, 2),
|
||||
SVN::Client::get_ssl_client_cert_prompt_provider(
|
||||
\&_ssl_client_cert_prompt, 2),
|
||||
SVN::Client::get_ssl_client_cert_pw_prompt_provider(
|
||||
\&_ssl_client_cert_pw_prompt, 2),
|
||||
SVN::Client::get_username_provider(),
|
||||
SVN::Client::get_ssl_server_trust_prompt_provider(
|
||||
\&_ssl_server_trust_prompt),
|
||||
SVN::Client::get_username_prompt_provider(
|
||||
\&_username_prompt, 2),
|
||||
]);
|
||||
}
|
||||
SVN::Ra->new(url => $url, auth => $AUTH_BATON,
|
||||
auth_provider_callbacks => $AUTH_CALLBACKS);
|
||||
}
|
||||
|
||||
sub libsvn_get_file {
|
||||
|
||||
@@ -73,6 +73,7 @@ test_expect_success setup '
|
||||
for i in 1 2; do echo $i; done >>dir/sub &&
|
||||
git update-index file0 dir/sub &&
|
||||
|
||||
git repo-config log.showroot false &&
|
||||
git commit --amend &&
|
||||
git show-branch
|
||||
'
|
||||
|
||||
@@ -118,7 +118,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
||||
xdemitconf_t const *xecfg) {
|
||||
long s1, s2, e1, e2, lctx;
|
||||
xdchange_t *xch, *xche;
|
||||
char funcbuf[40];
|
||||
char funcbuf[80];
|
||||
long funclen = 0;
|
||||
|
||||
if (xecfg->flags & XDL_EMIT_COMMON)
|
||||
|
||||
Reference in New Issue
Block a user