From 0ea865ce7af4b2b6ee85dc52b5fad84260e27871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 23 Nov 2006 23:02:37 +0100 Subject: [PATCH 01/10] archive-zip: don't use sizeof(struct ...) We can't rely on sizeof(struct zip_*) returning the sum of all struct members. At least on ARM padding is added at the end, as Gerrit Pape reported. This fixes the problem but still lets the compiler do the summing by introducing explicit padding at the end of the structs and then taking its offset as the combined size of the preceding members. As Junio correctly notes, the _end[] marker array's size must be greater than zero for compatibility with compilers other than gcc. The space wasted by the markers can safely be neglected because we only have one instance of each struct, i.e. in sum 3 wasted bytes on i386, and 0 on ARM. :) We still rely on the compiler to not add padding between the struct members, but that's reasonable given that all of them are unsigned char arrays. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- archive-zip.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/archive-zip.c b/archive-zip.c index ae5572ae20..36e922a1f2 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -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); } From 48d044b5fe7ae553f05186db46b5cb4708afceb4 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 23 Nov 2006 14:54:03 -0800 Subject: [PATCH 02/10] git-svn: error out from dcommit on a parent-less commit dcommit would unconditionally append "~1" to a commit in order to generate a diff. Now we generate a meaningful error message if we try to generate an impossible diff. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/git-svn.perl b/git-svn.perl index 80b7b87f0f..f0db4af58c 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -589,6 +589,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) { From e70dc780a4325138ddfae6786c1eb3ec06233de6 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 23 Nov 2006 14:54:04 -0800 Subject: [PATCH 03/10] git-svn: correctly handle revision 0 in SVN repositories some SVN repositories have a revision 0 (committed by no author and no date) when created; so when we need to ensure that we check any revision variables are defined, and not just non-zero. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index f0db4af58c..6feae56c0e 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -232,7 +232,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"; } @@ -832,8 +832,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", @@ -2493,7 +2499,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\-]+)/); From 4769489a412fb0decbd73ce59a6756985d0d6bc4 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 23 Nov 2006 14:54:05 -0800 Subject: [PATCH 04/10] git-svn: preserve uncommitted changes after dcommit Using dcommit could cause the user to lose uncommitted changes during the reset --hard operation, so change it to reset --mixed. If dcommit chooses the rebase path, then git-rebase will already error out when local changes are made. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-svn.perl b/git-svn.perl index 6feae56c0e..bb8935afe6 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -623,7 +623,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); } From f73da29fa2be2f4bbda86e006b743b8121bdbf19 Mon Sep 17 00:00:00 2001 From: Andy Parkins Date: Thu, 23 Nov 2006 10:05:17 +0000 Subject: [PATCH 05/10] Increase length of function name buffer In xemit.c:xdl_emit_diff() a buffer for showing the function name as commentary is allocated; this buffer was 40 characters. This is a bit small; particularly for C++ function names where there is often an identical prefix (like void LongNamespace::LongClassName) on multiple functions, which makes the context the same everywhere. In other words the context is useless. This patch increases that buffer to 80 characters - which may still not be enough, but is better Signed-off-by: Andy Parkins Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 07995ec33e..e291dc7608 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -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) From 29561ad0adadf4884858c209bb22b41d8d9a66ba Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 23 Nov 2006 21:52:18 -0800 Subject: [PATCH 06/10] refs outside refs/{heads,tags} match less strongly. This changes the refname matching logic used to decide which ref is updated with git-send-pack. We used to error out when pushing 'master' when the other end has both 'master' branch and a tracking branch 'remotes/$name/master' but with this, 'master' matches only 'refs/heads/master' when both and no other 'master' exist. Pushing 'foo' when both heads/foo and tags/foo exist at the remote end is still considered an error and you would need to disambiguate between them by being more explicit. When neither heads/foo nor tags/foo exists at the remote, pushing 'foo' when there is only remotes/origin/foo is not ambiguous, while it still is ambiguous when there are more than one such weaker match (remotes/origin/foo and remotes/alt/foo, for example). Signed-off-by: Junio C Hamano --- connect.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/connect.c b/connect.c index c55a20a4aa..b9666cc0d8 100644 --- a/connect.c +++ b/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) From 7182135189d1942d8538a0d0c17fc79f5cb82c71 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 23 Nov 2006 23:58:35 +0100 Subject: [PATCH 07/10] Make git-clone --use-separate-remote the default We've talked about this for quite some time on the list, and it is a sane thing to do for a repository with an associcated working tree. For somebody who wants to use the traditional layout, there is a backward compatibility option --use-immingled-remote, but it is expected to be removed before the next major release. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- Documentation/git-clone.txt | 24 ++++++++++++++++++------ git-clone.sh | 14 +++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 86060472ad..4cb42237b5 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -11,7 +11,8 @@ SYNOPSIS [verse] 'git-clone' [--template=] [-l [-s]] [-q] [-n] [--bare] [-o ] [-u ] [--reference ] - [--use-separate-remote] [] + [--use-separate-remote | --use-immingled-remote] + [] DESCRIPTION ----------- @@ -71,9 +72,13 @@ OPTIONS Make a 'bare' GIT repository. That is, instead of creating `` and placing the administrative files in `/.git`, make the `` - 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 :: -o :: @@ -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. :: The (possibly remote) repository to clone from. It can diff --git a/git-clone.sh b/git-clone.sh index 3f006d1a77..9ed4135544 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -14,7 +14,7 @@ die() { } usage() { - die "Usage: $0 [--template=] [--use-separate-remote] [--reference ] [--bare] [-l [-s]] [-q] [-u ] [--origin ] [-n] []" + die "Usage: $0 [--template=] [--use-immingled-remote] [--reference ] [--bare] [-l [-s]] [-q] [-u ] [--origin ] [-n] []" } 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" From 73bcf53342f16a66ae4e02ed50a08bd34d846bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Arenaza?= Date: Wed, 22 Nov 2006 23:26:57 +0100 Subject: [PATCH 08/10] git-cvsimport: add support for CVS pserver method HTTP/1.x proxying MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for 'proxy' and 'proxyport' connection options when using the pserver method for the CVS Root. It has been tested with a Squid 2.5.x proxy server. Quoting from the CVS info manual: The `gserver' and `pserver' connection methods all accept optional method options, specified as part of the METHOD string, like so: :METHOD[;OPTION=ARG...]: Currently, the only two valid connection options are `proxy', which takes a hostname as an argument, and `proxyport', which takes a port number as an argument. These options can be used to connect via an HTTP tunnel style web proxy. For example, to connect pserver via a web proxy at www.myproxy.net and port 8000, you would use a method of: :pserver;proxy=www.myproxy.net;proxyport=8000: *NOTE: The rest of the connection string is required to connect to the server as noted in the upcoming sections on password authentication, gserver and kserver. The example above would only modify the METHOD portion of the repository name.* PROXY must be supplied to connect to a CVS server via a proxy server, but PROXYPORT will default to port 8080 if not supplied. PROXYPORT may also be set via the CVS_PROXY_PORT environment variable. Signed-off-by: IƱaki Arenaza Signed-off-by: Junio C Hamano --- git-cvsimport.perl | 54 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/git-cvsimport.perl b/git-cvsimport.perl index b54a9486d2..4310dea132 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -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="" unless $rep; From 30d055aa1e45b4740edc3bfbff77fa5d65e106ff Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 24 Nov 2006 01:38:04 -0800 Subject: [PATCH 09/10] git-svn: handle authentication without relying on cached tokens on disk This is mostly gleaned off SVN::Mirror, with added support for --no-auth-cache and --config-dir. Even with this patch, git-svn does not yet support repositories where the user only has partial read permissions. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 156 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 8 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index bb8935afe6..47cd3e27fe 100755 --- a/git-svn.perl +++ b/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 < \$_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); @@ -2683,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( || '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 = ); + $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 = ); + } + $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 { From 0f03ca946142bd656c1af9ff811cb9efbc8314da Mon Sep 17 00:00:00 2001 From: Peter Baumann Date: Thu, 23 Nov 2006 10:36:33 +0100 Subject: [PATCH 10/10] config option log.showroot to show the diff of root commits This allows one to see a root commit as a diff in commands like git-log, git-show and git-whatchanged. Signed-off-by: Peter Baumann Signed-off-by: Junio C Hamano --- Documentation/config.txt | 6 ++++++ builtin-log.c | 20 ++++++++++++++++---- t/t4013-diff-various.sh | 1 + 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 9d3c71c3b8..9090762819 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -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. diff --git a/builtin-log.c b/builtin-log.c index fedb0137bc..7acf5d3b0c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -13,6 +13,8 @@ #include #include +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); } diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 71c454356f..ed37141b6e 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -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 '