* [RFC PATCH] git-svn info: implement info command
@ 2007-11-12 16:19 David D. Kilzer
2007-11-17 22:54 ` Eric Wong
0 siblings, 1 reply; 10+ messages in thread
From: David D. Kilzer @ 2007-11-12 16:19 UTC (permalink / raw)
To: git; +Cc: David D. Kilzer
Implement "git-svn info" for files and directories based on the "svn info"
command. Note that the -r/--revision argument is not supported yet.
Added 18 tests in t/t9117-git-svn-info.sh.
Signed-off-by: David D. Kilzer <ddkilzer@kilzer.net>
---
Looking for feedback on this patch. Specifically, I'm looking for insight
for the two FIXME comments in the cmd_info() function added to git-svn.
(I can't help but think I'm missing a plumbing command or a basic concept.
Pointers to code, web pages or man pages are welcome.)
Note that I've tried to cover all the bases that "svn info" does (by using
tests), except supporting the -r/--revision argument.
I've also tried to be aggressive in extracting common code into functions.
Dave
Documentation/git-svn.txt | 5 +
git-svn.perl | 194 +++++++++++++++++++++++++++++++------
t/t9117-git-svn-info.sh | 236 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 403 insertions(+), 32 deletions(-)
create mode 100644 t/t9117-git-svn-info.sh
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 488e4b1..c3fc878 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -193,6 +193,11 @@ Any other arguments are passed directly to `git log'
repository (that has been init-ed with git-svn).
The -r<revision> option is required for this.
+'info'::
+ Shows information about a file or directory similar to what
+ `svn info' provides. Does not currently support a -r/--revision
+ argument.
+
--
OPTIONS
diff --git a/git-svn.perl b/git-svn.perl
index dd93e32..256a3e0 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -48,7 +48,8 @@ BEGIN {
foreach (qw/command command_oneline command_noisy command_output_pipe
command_input_pipe command_close_pipe/) {
for my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher
- Git::SVN::Migration Git::SVN::Log Git::SVN),
+ Git::SVN::Migration Git::SVN::Log Git::SVN
+ Git::SVN::Util),
__PACKAGE__) {
*{"${package}::$_"} = \&{"Git::$_"};
}
@@ -177,6 +178,8 @@ my %cmd = (
'file|F=s' => \$_file,
'revision|r=s' => \$_revision,
%cmt_opts } ],
+ 'info' => [ \&cmd_info, "Show info about the latest SVN revision on the current branch",
+ { } ],
);
my $cmd;
@@ -577,6 +580,23 @@ sub cmd_create_ignore {
});
}
+sub canonicalize_path {
+ my ($path) = @_;
+ my $dotSlashAdded = 0;
+ if (substr($path, 0, 1) ne "/") {
+ $path = "./" . $path;
+ $dotSlashAdded = 1;
+ }
+ # File::Spec->canonpath doesn't collapse x/../y into y (for a
+ # good reason), so let's do this manually.
+ $path =~ s#/+#/#g;
+ $path =~ s#/\.(?:/|$)#/#g;
+ $path =~ s#/[^/]+/\.\.##g;
+ $path =~ s#/$##g;
+ $path =~ s#^\./## if $dotSlashAdded;
+ return $path;
+}
+
# get_svnprops(PATH)
# ------------------
# Helper for cmd_propget and cmd_proplist below.
@@ -594,12 +614,7 @@ sub get_svnprops {
# canonicalize the path (otherwise libsvn will abort or fail to
# find the file)
- # File::Spec->canonpath doesn't collapse x/../y into y (for a
- # good reason), so let's do this manually.
- $path =~ s#/+#/#g;
- $path =~ s#/\.(?:/|$)#/#g;
- $path =~ s#/[^/]+/\.\.##g;
- $path =~ s#/$##g;
+ $path = canonicalize_path($path);
my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
my $props;
@@ -730,6 +745,96 @@ sub cmd_commit_diff {
}
}
+sub cmd_info {
+ my $path = canonicalize_path(shift or ".");
+ unless (scalar(@_) == 0) {
+ die "Too many arguments specified\n";
+ }
+
+ # FIXME: We use a combination of git-diff, git-ls-files and git-cat-file
+ # to divine the state and type of object that was passed in as $path.
+ # There has to be a better way. Note that only $diffStatus is used
+ # beyond setting $isDirectory below.
+
+ my $diffStatus = (split(' ', command_oneline(qw(diff --cached --name-status --), $path) || ""))[0] || "";
+ my $lsFiles = command_oneline(qw(ls-files), $path) || "";
+ if (!$diffStatus && !$lsFiles) {
+ print STDERR "$path: (Not a versioned resource)\n\n";
+ return;
+ }
+
+ my $catFileType = ($path eq "." || $diffStatus eq "A") ? "" : (command_oneline(qw(cat-file -t), "HEAD:$path") || "");
+ my $isDirectory = (-e $path && ! -f $path && ! -l $path || $diffStatus eq "D" && $catFileType eq "tree");
+
+ my $result = "Path: $path\n";
+ $result .= "Name: " . basename($path) . "\n" if !$isDirectory;
+
+ my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+ unless ($gs) {
+ die "Unable to determine upstream SVN information from ",
+ "working tree history\n";
+ }
+ $result .= "URL: " . ($url . ($path eq "." ? "" : "/$path")) . "\n";
+
+ my $repos_root = $gs->ra->{repos_root};
+ Git::SVN::remove_username($repos_root);
+ $result .= "Repository Root: $repos_root\n";
+ $result .= "Repository UUID: $uuid\n" unless $diffStatus eq "A";
+ $result .= "Revision: " . ($diffStatus eq "A" ? 0 : $rev) . "\n";
+
+ $result .= "Node Kind: " . ($isDirectory ? "directory" : "file") . "\n";
+
+ my $schedule = ($diffStatus eq "A" ? "add" : ($diffStatus eq "D" ? "delete" : "normal"));
+ $result .= "Schedule: $schedule\n";
+
+ if ($diffStatus eq "A") {
+ print $result, "\n";
+ return;
+ }
+
+ my ($lc_author, $lc_rev, $lc_date_utc);
+ my @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, "--", $path);
+ my $log = command_output_pipe(@args);
+ my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/;
+ while (<$log>) {
+ if (/^${esc_color}author (.+) <[^>]+> (\d+) ([\-\+]?\d+)$/o) {
+ $lc_author = $1;
+ $lc_date_utc = Git::SVN::Log::parse_git_date($2, $3);
+ } elsif (/^${esc_color} (git-svn-id:.+)$/o) {
+ (undef, $lc_rev, undef) = ::extract_metadata($1);
+ }
+ }
+ close $log;
+
+ Git::SVN::Log::set_local_timezone();
+
+ $result .= "Last Changed Author: $lc_author\n";
+ $result .= "Last Changed Rev: $lc_rev\n";
+ $result .= "Last Changed Date: " . Git::SVN::Log::format_svn_date($lc_date_utc) . "\n";
+
+ if (!$isDirectory) {
+ my $textLastUpdatedDate = ($diffStatus eq "D" ? $lc_date_utc : (stat $path)[9]);
+ $result .= "Text Last Updated: " . Git::SVN::Log::format_svn_date($textLastUpdatedDate) . "\n";
+ my $checksum;
+ # FIXME: We fail to generate the correct checksum for deleted
+ # symlinks here. How do we know if a deleted file was a symlink?
+ if ($diffStatus eq "D") {
+ my ($fh, $ctx) = command_output_pipe(qw(cat-file blob), "HEAD:$path");
+ $checksum = Git::SVN::Util::md5sum($fh);
+ command_close_pipe($fh, $ctx);
+ } elsif (-l $path) {
+ $checksum = Git::SVN::Util::md5sum("link " . command(qw(cat-file blob), "HEAD:$path"));
+ } else {
+ open FILE, "<", $path or die $!;
+ $checksum = Git::SVN::Util::md5sum(\*FILE);
+ close FILE or die $!;
+ }
+ $result .= "Checksum: " . $checksum . "\n";
+ }
+
+ print $result, "\n";
+}
+
########################### utility functions #########################
sub rebase_cmd {
@@ -1037,6 +1142,27 @@ sub linearize_history {
(\@linear_refs, \%parents);
}
+package Git::SVN::Util;
+use strict;
+use warnings;
+use Digest::MD5;
+
+sub md5sum {
+ my $arg = shift;
+ my $ref = ref $arg;
+ my $md5 = Digest::MD5->new();
+ if ($ref eq 'GLOB' || $ref eq 'IO::File') {
+ $md5->addfile($arg) or croak $!;
+ } elsif ($ref eq 'SCALAR') {
+ $md5->add($$arg) or croak $!;
+ } elsif (!$ref) {
+ $md5->add($arg) or croak $!;
+ } else {
+ ::fatal "Can't provide MD5 hash for unknown ref type: '", $ref, "'";
+ }
+ return $md5->hexdigest();
+}
+
package Git::SVN;
use strict;
use warnings;
@@ -2582,7 +2708,6 @@ use strict;
use warnings;
use Carp qw/croak/;
use IO::File qw//;
-use Digest::MD5;
# file baton members: path, mode_a, mode_b, pool, fh, blob, base
sub new {
@@ -2734,9 +2859,7 @@ sub apply_textdelta {
if (defined $exp) {
seek $base, 0, 0 or croak $!;
- my $md5 = Digest::MD5->new;
- $md5->addfile($base);
- my $got = $md5->hexdigest;
+ my $got = Git::SVN::Util::md5sum($base);
die "Checksum mismatch: $fb->{path} $fb->{blob}\n",
"expected: $exp\n",
" got: $got\n" if ($got ne $exp);
@@ -2755,9 +2878,7 @@ sub close_file {
if (my $fh = $fb->{fh}) {
if (defined $exp) {
seek($fh, 0, 0) or croak $!;
- my $md5 = Digest::MD5->new;
- $md5->addfile($fh);
- my $got = $md5->hexdigest;
+ my $got = Git::SVN::Util::md5sum($fh);
if ($got ne $exp) {
die "Checksum mismatch: $path\n",
"expected: $exp\n got: $got\n";
@@ -2809,7 +2930,6 @@ use strict;
use warnings;
use Carp qw/croak/;
use IO::File;
-use Digest::MD5;
sub new {
my ($class, $opts) = @_;
@@ -3113,11 +3233,9 @@ sub chg_file {
$fh->flush == 0 or croak $!;
seek $fh, 0, 0 or croak $!;
- my $md5 = Digest::MD5->new;
- $md5->addfile($fh) or croak $!;
+ my $exp = Git::SVN::Util::md5sum($fh);
seek $fh, 0, 0 or croak $!;
- my $exp = $md5->hexdigest;
my $pool = SVN::Pool->new;
my $atd = $self->apply_textdelta($fbat, undef, $pool);
my $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);
@@ -3810,6 +3928,29 @@ sub run_pager {
exec $pager or ::fatal "Can't run pager: $! ($pager)";
}
+sub format_svn_date {
+ return strftime("%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)", localtime(shift));
+}
+
+sub parse_git_date {
+ my ($t, $tz) = @_;
+ # Date::Parse isn't in the standard Perl distro :(
+ if ($tz =~ s/^\+//) {
+ $t += tz_to_s_offset($tz);
+ } elsif ($tz =~ s/^\-//) {
+ $t -= tz_to_s_offset($tz);
+ }
+ return $t;
+}
+
+sub set_local_timezone {
+ if (defined $TZ) {
+ $ENV{TZ} = $TZ;
+ } else {
+ delete $ENV{TZ};
+ }
+}
+
sub tz_to_s_offset {
my ($tz) = @_;
$tz =~ s/(\d\d)$//;
@@ -3830,13 +3971,7 @@ sub get_author_info {
$dest->{t} = $t;
$dest->{tz} = $tz;
$dest->{a} = $au;
- # Date::Parse isn't in the standard Perl distro :(
- if ($tz =~ s/^\+//) {
- $t += tz_to_s_offset($tz);
- } elsif ($tz =~ s/^\-//) {
- $t -= tz_to_s_offset($tz);
- }
- $dest->{t_utc} = $t;
+ $dest->{t_utc} = parse_git_date($t, $tz);
}
sub process_commit {
@@ -3890,8 +4025,7 @@ sub show_commit_normal {
my ($c) = @_;
print '-' x72, "\nr$c->{r} | ";
print "$c->{c} | " if $show_commit;
- print "$c->{a} | ", strftime("%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)",
- localtime($c->{t_utc})), ' | ';
+ print "$c->{a} | ", format_svn_date($c->{t_utc}), ' | ';
my $nr_line = 0;
if (my $l = $c->{l}) {
@@ -3931,11 +4065,7 @@ sub cmd_show_log {
my (@args) = @_;
my ($r_min, $r_max);
my $r_last = -1; # prevent dupes
- if (defined $TZ) {
- $ENV{TZ} = $TZ;
- } else {
- delete $ENV{TZ};
- }
+ set_local_timezone();
if (defined $::_revision) {
if ($::_revision =~ /^(\d+):(\d+)$/) {
($r_min, $r_max) = ($1, $2);
diff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh
new file mode 100644
index 0000000..b20db04
--- /dev/null
+++ b/t/t9117-git-svn-info.sh
@@ -0,0 +1,236 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 David D. Kilzer
+
+test_description='git-svn info'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'setup repository and import' "
+ rm -rf info gitwc svnwc &&
+ mkdir info &&
+ cd info &&
+ echo one > file &&
+ ln -s file symlink-file &&
+ mkdir directory &&
+ touch directory/.placeholder &&
+ ln -s directory symlink-directory &&
+ svn import -m 'initial' . $svnrepo &&
+ cd .. &&
+ mkdir gitwc &&
+ cd gitwc &&
+ git-svn init $svnrepo &&
+ git-svn fetch &&
+ cd .. &&
+ svn co $svnrepo svnwc &&
+ touch -c -r svnwc/file gitwc/file &&
+ touch -c -r svnwc/directory gitwc/directory &&
+ touch -c -r svnwc/symlink-file gitwc/symlink-file &&
+ touch -c -r svnwc/symlink-directory gitwc/symlink-directory
+ "
+
+test_expect_success 'info no arguments' "
+ (cd svnwc; svn info) > expected.info-no-arguments &&
+ (cd gitwc; git-svn info) > actual.info-no-arguments &&
+ diff -u expected.info-no-arguments actual.info-no-arguments
+ "
+
+test_expect_success 'info dot' "
+ (cd svnwc; svn info .) > expected.info-dot &&
+ (cd gitwc; git-svn info .) > actual.info-dot &&
+ diff -u expected.info-dot actual.info-dot
+ "
+
+test_expect_success 'info file' "
+ (cd svnwc; svn info file) > expected.info-file &&
+ (cd gitwc; git-svn info file) > actual.info-file &&
+ diff -u expected.info-file actual.info-file
+ "
+
+test_expect_success 'info directory' "
+ (cd svnwc; svn info directory) > expected.info-directory &&
+ (cd gitwc; git-svn info directory) > actual.info-directory &&
+ diff -u expected.info-directory actual.info-directory
+ "
+
+test_expect_success 'info symlink-file' "
+ (cd svnwc; svn info symlink-file) > expected.info-symlink-file &&
+ (cd gitwc; git-svn info symlink-file) > actual.info-symlink-file &&
+ diff -u expected.info-symlink-file actual.info-symlink-file
+ "
+
+test_expect_success 'info symlink-directory' "
+ (cd svnwc; svn info symlink-directory) > expected.info-symlink-directory &&
+ (cd gitwc; git-svn info symlink-directory) > actual.info-symlink-directory &&
+ diff -u expected.info-symlink-directory actual.info-symlink-directory
+ "
+
+test_expect_success 'info added-file' "
+ echo two > gitwc/added-file &&
+ cd gitwc &&
+ git add added-file &&
+ cd .. &&
+ cp -p gitwc/added-file svnwc/added-file &&
+ touch -r gitwc/added-file svnwc/added-file &&
+ cd svnwc &&
+ svn add added-file > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info added-file) > expected.info-added-file &&
+ (cd gitwc; git-svn info added-file) > actual.info-added-file &&
+ diff -u expected.info-added-file actual.info-added-file
+ "
+
+test_expect_success 'info added-directory' "
+ mkdir gitwc/added-directory svnwc/added-directory &&
+ touch -r gitwc/added-directory svnwc/added-directory &&
+ touch gitwc/added-directory/.placeholder &&
+ cd svnwc &&
+ svn add added-directory > /dev/null &&
+ cd .. &&
+ cd gitwc &&
+ git add added-directory &&
+ cd .. &&
+ (cd svnwc; svn info added-directory) > expected.info-added-directory &&
+ (cd gitwc; git-svn info added-directory) > actual.info-added-directory &&
+ diff -u expected.info-added-directory actual.info-added-directory
+ "
+
+test_expect_success 'info added-symlink-file' "
+ cd gitwc &&
+ ln -s added-file added-symlink-file &&
+ git add added-symlink-file &&
+ cd .. &&
+ cd svnwc &&
+ ln -s added-file added-symlink-file &&
+ svn add added-symlink-file > /dev/null &&
+ cd .. &&
+ touch -r gitwc/added-symlink-file svnwc/added-symlink-file &&
+ (cd svnwc; svn info added-symlink-file) > expected.info-added-symlink-file &&
+ (cd gitwc; git-svn info added-symlink-file) > actual.info-added-symlink-file &&
+ diff -u expected.info-added-symlink-file actual.info-added-symlink-file
+ "
+
+test_expect_success 'info added-symlink-directory' "
+ cd gitwc &&
+ ln -s added-directory added-symlink-directory &&
+ git add added-symlink-directory &&
+ cd .. &&
+ cd svnwc &&
+ ln -s added-directory added-symlink-directory &&
+ svn add added-symlink-directory > /dev/null &&
+ cd .. &&
+ touch -r gitwc/added-symlink-directory svnwc/added-symlink-directory &&
+ (cd svnwc; svn info added-symlink-directory) > expected.info-added-symlink-directory &&
+ (cd gitwc; git-svn info added-symlink-directory) > actual.info-added-symlink-directory &&
+ diff -u expected.info-added-symlink-directory actual.info-added-symlink-directory
+ "
+
+replace_Text_Last_Updated_date () {
+ REPLACEMENT=`cat $1 | grep '^Last Changed Date:' | sed -e 's/Last Changed Date/Text Last Updated/'` &&
+ cat $1 | sed -e "s/^Text Last Updated: .*\$/${REPLACEMENT}/" > $1.$$ &&
+ mv -f $1.$$ $1
+}
+
+test_expect_success 'info deleted-file' "
+ cd gitwc &&
+ git rm -f file > /dev/null &&
+ cd .. &&
+ cd svnwc &&
+ svn rm --force file > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info file) > expected.info-deleted-file &&
+ (cd gitwc; git-svn info file) > actual.info-deleted-file &&
+ replace_Text_Last_Updated_date expected.info-deleted-file &&
+ diff -u expected.info-deleted-file actual.info-deleted-file
+ "
+
+test_expect_success 'info deleted-directory' "
+ cd gitwc &&
+ git rm -r -f directory > /dev/null &&
+ cd .. &&
+ cd svnwc &&
+ svn rm --force directory > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info directory) > expected.info-deleted-directory &&
+ (cd gitwc; git-svn info directory) > actual.info-deleted-directory &&
+ replace_Text_Last_Updated_date expected.info-deleted-directory &&
+ diff -u expected.info-deleted-directory actual.info-deleted-directory
+ "
+
+test_expect_success 'info deleted-symlink-file' "
+ cd gitwc &&
+ git rm -f symlink-file > /dev/null &&
+ cd .. &&
+ cd svnwc &&
+ svn rm --force symlink-file > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info symlink-file) > expected.info-deleted-symlink-file &&
+ (cd gitwc; git-svn info symlink-file) > actual.info-deleted-symlink-file &&
+ replace_Text_Last_Updated_date expected.info-deleted-symlink-file &&
+ diff -u expected.info-deleted-symlink-file actual.info-deleted-symlink-file
+ "
+
+test_expect_success 'info deleted-symlink-directory' "
+ cd gitwc &&
+ git rm -f symlink-directory > /dev/null &&
+ cd .. &&
+ cd svnwc &&
+ svn rm --force symlink-directory > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info symlink-directory) > expected.info-deleted-symlink-directory &&
+ (cd gitwc; git-svn info symlink-directory) > actual.info-deleted-symlink-directory &&
+ replace_Text_Last_Updated_date expected.info-deleted-symlink-directory &&
+ diff -u expected.info-deleted-symlink-directory actual.info-deleted-symlink-directory
+ "
+
+# NOTE: git does not have the concept of replaced objects, so we can't test for them.
+#test_expect_success 'info replaced-file' "/usr/bin/true"
+#test_expect_success 'info replaced-directory' "/usr/bin/true"
+#test_expect_success 'info replaced-symlink-file' "/usr/bin/true"
+#test_expect_success 'info replaced-symlink-directory' "/usr/bin/true"
+
+test_expect_success 'info unknown-file' "
+ echo two > gitwc/unknown-file &&
+ cp -p gitwc/unknown-file svnwc/unknown-file &&
+ touch -r gitwc/unknown-file svnwc/unknown-file &&
+ (cd svnwc; svn info unknown-file) 2> expected.info-unknown-file &&
+ (cd gitwc; git-svn info unknown-file) 2> actual.info-unknown-file &&
+ diff -u expected.info-unknown-file actual.info-unknown-file
+ "
+
+test_expect_success 'info unknown-directory' "
+ mkdir gitwc/unknown-directory svnwc/unknown-directory &&
+ touch -r gitwc/unknown-directory svnwc/unknown-directory &&
+ touch gitwc/unknown-directory/.placeholder &&
+ (cd svnwc; svn info unknown-directory) 2> expected.info-unknown-directory &&
+ (cd gitwc; git-svn info unknown-directory) 2> actual.info-unknown-directory &&
+ diff -u expected.info-unknown-directory actual.info-unknown-directory
+ "
+
+test_expect_success 'info unknown-symlink-file' "
+ cd gitwc &&
+ ln -s unknown-file unknown-symlink-file &&
+ cd .. &&
+ cd svnwc &&
+ ln -s unknown-file unknown-symlink-file &&
+ cd .. &&
+ touch -r gitwc/unknown-symlink-file svnwc/unknown-symlink-file &&
+ (cd svnwc; svn info unknown-symlink-file) 2> expected.info-unknown-symlink-file &&
+ (cd gitwc; git-svn info unknown-symlink-file) 2> actual.info-unknown-symlink-file &&
+ diff -u expected.info-unknown-symlink-file actual.info-unknown-symlink-file
+ "
+
+test_expect_success 'info unknown-symlink-directory' "
+ cd gitwc &&
+ ln -s unknown-directory unknown-symlink-directory &&
+ cd .. &&
+ cd svnwc &&
+ ln -s unknown-directory unknown-symlink-directory &&
+ cd .. &&
+ touch -r gitwc/unknown-symlink-directory svnwc/unknown-symlink-directory &&
+ (cd svnwc; svn info unknown-symlink-directory) 2> expected.info-unknown-symlink-directory &&
+ (cd gitwc; git-svn info unknown-symlink-directory) 2> actual.info-unknown-symlink-directory &&
+ diff -u expected.info-unknown-symlink-directory actual.info-unknown-symlink-directory
+ "
+
+test_done
--
1.5.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC PATCH] git-svn info: implement info command
2007-11-12 16:19 [RFC PATCH] git-svn info: implement info command David D. Kilzer
@ 2007-11-17 22:54 ` Eric Wong
2007-11-21 6:43 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2007-11-17 22:54 UTC (permalink / raw)
To: David D. Kilzer; +Cc: git
"David D. Kilzer" <ddkilzer@kilzer.net> wrote:
> Implement "git-svn info" for files and directories based on the "svn info"
> command. Note that the -r/--revision argument is not supported yet.
>
> Added 18 tests in t/t9117-git-svn-info.sh.
>
> Signed-off-by: David D. Kilzer <ddkilzer@kilzer.net>
> ---
>
> Looking for feedback on this patch. Specifically, I'm looking for insight
> for the two FIXME comments in the cmd_info() function added to git-svn.
> (I can't help but think I'm missing a plumbing command or a basic concept.
> Pointers to code, web pages or man pages are welcome.)
>
> Note that I've tried to cover all the bases that "svn info" does (by using
> tests), except supporting the -r/--revision argument.
Hi David,
Wow. I can honestly say I've never even noticed the "Schedule:" field
in `svn info'. I would've been perfectly happy to accept an
implementation of `git svn info' without that :)
> I've also tried to be aggressive in extracting common code into functions.
I like it, but this should be a separate patch.
> +sub canonicalize_path {
> + my ($path) = @_;
> + my $dotSlashAdded = 0;
camelCase variables requires more time for the brain to parse (they're
easier to write, but take more time to read), please use snake_case like
the rest of git-svn (and git).
> +sub cmd_info {
> + my $path = canonicalize_path(shift or ".");
> + unless (scalar(@_) == 0) {
> + die "Too many arguments specified\n";
> + }
> +
> + # FIXME: We use a combination of git-diff, git-ls-files and git-cat-file
> + # to divine the state and type of object that was passed in as $path.
> + # There has to be a better way. Note that only $diffStatus is used
> + # beyond setting $isDirectory below.
I agree it's pretty ugly. You can probably expand git-runstatus to do
this. git-commit.sh used to use something like this until git-runstatus
was added. On the other hand, I'd be content if we dropped support
for this info entirely since `git-status' is perfectly good.
IMNSHO, "URL:" and "Repository Root:" and occasionally "Revision:" (on the
top-level directory) would be the only useful things this command would
have to offer.
Being able to run something like `git svn info --url <path>'
to get something like http://svn.foo.org/project/trunk/<path> would be
nice, too.
> +
> + my $diffStatus = (split(' ', command_oneline(qw(diff --cached --name-status --), $path) || ""))[0] || "";
Please wrap lines at 80 characters. I have a hard time following long
lines.
> + my $checksum;
> + # FIXME: We fail to generate the correct checksum for deleted
> + # symlinks here. How do we know if a deleted file was a symlin
git ls-tree HEAD <filename> will show the mode of a deleted file
> @@ -0,0 +1,236 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2007 David D. Kilzer
> +
> +test_description='git-svn info'
> +
> +. ./lib-git-svn.sh
> +
> +test_expect_success 'setup repository and import' "
> + rm -rf info gitwc svnwc &&
All git tests should start you off on a clean trash/ directory...
> + mkdir info &&
> + cd info &&
> + echo one > file &&
> + ln -s file symlink-file &&
> + mkdir directory &&
> + touch directory/.placeholder &&
> + ln -s directory symlink-directory &&
> + svn import -m 'initial' . $svnrepo &&
> + cd .. &&
> + mkdir gitwc &&
> + cd gitwc &&
> + git-svn init $svnrepo &&
> + git-svn fetch &&
> + cd .. &&
> + svn co $svnrepo svnwc &&
> + touch -c -r svnwc/file gitwc/file &&
> + touch -c -r svnwc/directory gitwc/directory &&
> + touch -c -r svnwc/symlink-file gitwc/symlink-file &&
> + touch -c -r svnwc/symlink-directory gitwc/symlink-directory
Are -r and -c portable? I remember writing test-chmtime to workaround
some arguments for touch not being portable.
> +test_expect_success 'info no arguments' "
> + (cd svnwc; svn info) > expected.info-no-arguments &&
> + (cd gitwc; git-svn info) > actual.info-no-arguments &&
> + diff -u expected.info-no-arguments actual.info-no-arguments
> + "
Can we expect the output of "svn info" to not change between
versions? I know "svn status" has changed between versions of
svn. I'd prefer if we keep the expected.* files hard-coded
in a test directory and compare those instead. Maybe use sed
to substitute placeholders for timestamps..
Also, git-diff can be used against arbitrary files nowadays, no
need to rely on a working diff command in the system :)
> +test_expect_success 'info added-file' "
> + echo two > gitwc/added-file &&
> + cd gitwc &&
> + git add added-file &&
> + cd .. &&
> + cp -p gitwc/added-file svnwc/added-file &&
I can't remember if cp -p is portable, either...
--
Eric Wong
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 0/3] Implement git-svn: info
2007-11-17 22:54 ` Eric Wong
@ 2007-11-21 6:43 ` David D. Kilzer
2007-11-21 6:43 ` [PATCH 1/3] git-svn: extract reusable code into utility functions David D. Kilzer
2007-11-21 6:59 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
0 siblings, 2 replies; 10+ messages in thread
From: David D. Kilzer @ 2007-11-21 6:43 UTC (permalink / raw)
To: Eric Wong; +Cc: git, David D. Kilzer
I've split the original RFC patch into two patches (one for the
refactoring changes, and one for implementing the "git svn info"
command), and added a third to imlement "git svn info --url" per
Eric's request.
Eric Wong <normalperson@yhbt.net> wrote:
> "David D. Kilzer" <ddkilzer@kilzer.net> wrote:
> > Implement "git-svn info" for files and directories based on the "svn info"
> > command. Note that the -r/--revision argument is not supported yet.
> [...]
> Wow. I can honestly say I've never even noticed the "Schedule:" field
> in `svn info'. I would've been perfectly happy to accept an
> implementation of `git svn info' without that :)
I never noticed it, either, until I went to implement this feature!
My goal is to stay as true to the "svn info" output as "git svn log"
has done for "svn log".
> > I've also tried to be aggressive in extracting common code into functions.
> I like it, but this should be a separate patch.
See Patch 1/3.
> camelCase variables requires more time for the brain to parse (they're
> easier to write, but take more time to read), please use snake_case like
> the rest of git-svn (and git).
I've switched all variables from camelCase to snake_case. Sorry...old
habit.
> > + # FIXME: We use a combination of git-diff, git-ls-files and git-cat-file
> > + # to divine the state and type of object that was passed in as $path.
> > + # There has to be a better way. Note that only $diffStatus is used
> > + # beyond setting $isDirectory below.
>
> I agree it's pretty ugly. You can probably expand git-runstatus to do
> this. git-commit.sh used to use something like this until git-runstatus
> was added. On the other hand, I'd be content if we dropped support
> for this info entirely since `git-status' is perfectly good.
I thought I saw a patch on the mailing list to remove git-runstatus
after rewriting git-status in C. Because of that, I extracted this
code into a find_file_type_and_diff_status() function in Patch 2/3.
The logic in the function is much easier to follow now, and this also
resulted in cleaning up the cmd_info() function.
> IMNSHO, "URL:" and "Repository Root:" and occasionally "Revision:" (on the
> top-level directory) would be the only useful things this command would
> have to offer.
See above about emulating "svn info" as closely as possible.
> Being able to run something like `git svn info --url <path>'
> to get something like http://svn.foo.org/project/trunk/<path> would be
> nice, too.
See Patch 3/3.
> Please wrap lines at 80 characters. I have a hard time following long
> lines.
Everything has been rewrapped for 80 columns.
> git ls-tree HEAD <filename> will show the mode of a deleted file
Thanks, used this with success in find_file_type_and_diff_status().
> > + rm -rf info gitwc svnwc &&
> All git tests should start you off on a clean trash/ directory...
Removed.
> > + touch -c -r svnwc/symlink-directory gitwc/symlink-directory
> Are -r and -c portable? I remember writing test-chmtime to workaround
> some arguments for touch not being portable.
The touch and cp commands were removed after restructuring the
t/t9117-git-svn-info.sh script to use static expected-* files and
replacing command output using sed.
> Can we expect the output of "svn info" to not change between
> versions? I know "svn status" has changed between versions of
> svn. I'd prefer if we keep the expected.* files hard-coded
> in a test directory and compare those instead. Maybe use sed
> to substitute placeholders for timestamps..
Done.
> Also, git-diff can be used against arbitrary files nowadays, no
> need to rely on a working diff command in the system :)
Done.
> > + cp -p gitwc/added-file svnwc/added-file &&
> I can't remember if cp -p is portable, either...
Fixed (see above).
Dave
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/3] git-svn: extract reusable code into utility functions
2007-11-21 6:43 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
@ 2007-11-21 6:43 ` David D. Kilzer
2007-11-21 6:43 ` [PATCH 2/3] git-svn info: implement info command David D. Kilzer
2007-11-21 6:59 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
1 sibling, 1 reply; 10+ messages in thread
From: David D. Kilzer @ 2007-11-21 6:43 UTC (permalink / raw)
To: Eric Wong; +Cc: git, David D. Kilzer
Extacted canonicalize_path() in the main package.
Created new Git::SVN::Util package with an md5sum() function. A
new package was created so that Digest::MD5 did not have to be
loaded in the main package. Replaced code in the SVN::Git::Editor
and SVN::Git::Fetcher packages with calls to md5sum().
Extracted the format_svn_date(), parse_git_date() and
set_local_timezone() functions within the Git::SVN::Log package.
Signed-off-by: David D. Kilzer <ddkilzer@kilzer.net>
---
git-svn.perl | 96 ++++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 64 insertions(+), 32 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index e3e00fd..aff429a 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -48,7 +48,8 @@ BEGIN {
foreach (qw/command command_oneline command_noisy command_output_pipe
command_input_pipe command_close_pipe/) {
for my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher
- Git::SVN::Migration Git::SVN::Log Git::SVN),
+ Git::SVN::Migration Git::SVN::Log Git::SVN
+ Git::SVN::Util),
__PACKAGE__) {
*{"${package}::$_"} = \&{"Git::$_"};
}
@@ -580,6 +581,17 @@ sub cmd_create_ignore {
});
}
+sub canonicalize_path {
+ my ($path) = @_;
+ # File::Spec->canonpath doesn't collapse x/../y into y (for a
+ # good reason), so let's do this manually.
+ $path =~ s#/+#/#g;
+ $path =~ s#/\.(?:/|$)#/#g;
+ $path =~ s#/[^/]+/\.\.##g;
+ $path =~ s#/$##g;
+ return $path;
+}
+
# get_svnprops(PATH)
# ------------------
# Helper for cmd_propget and cmd_proplist below.
@@ -597,12 +609,7 @@ sub get_svnprops {
# canonicalize the path (otherwise libsvn will abort or fail to
# find the file)
- # File::Spec->canonpath doesn't collapse x/../y into y (for a
- # good reason), so let's do this manually.
- $path =~ s#/+#/#g;
- $path =~ s#/\.(?:/|$)#/#g;
- $path =~ s#/[^/]+/\.\.##g;
- $path =~ s#/$##g;
+ $path = canonicalize_path($path);
my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
my $props;
@@ -1040,6 +1047,27 @@ sub linearize_history {
(\@linear_refs, \%parents);
}
+package Git::SVN::Util;
+use strict;
+use warnings;
+use Digest::MD5;
+
+sub md5sum {
+ my $arg = shift;
+ my $ref = ref $arg;
+ my $md5 = Digest::MD5->new();
+ if ($ref eq 'GLOB' || $ref eq 'IO::File') {
+ $md5->addfile($arg) or croak $!;
+ } elsif ($ref eq 'SCALAR') {
+ $md5->add($$arg) or croak $!;
+ } elsif (!$ref) {
+ $md5->add($arg) or croak $!;
+ } else {
+ ::fatal "Can't provide MD5 hash for unknown ref type: '", $ref, "'";
+ }
+ return $md5->hexdigest();
+}
+
package Git::SVN;
use strict;
use warnings;
@@ -2585,7 +2613,6 @@ use strict;
use warnings;
use Carp qw/croak/;
use IO::File qw//;
-use Digest::MD5;
# file baton members: path, mode_a, mode_b, pool, fh, blob, base
sub new {
@@ -2737,9 +2764,7 @@ sub apply_textdelta {
if (defined $exp) {
seek $base, 0, 0 or croak $!;
- my $md5 = Digest::MD5->new;
- $md5->addfile($base);
- my $got = $md5->hexdigest;
+ my $got = Git::SVN::Util::md5sum($base);
die "Checksum mismatch: $fb->{path} $fb->{blob}\n",
"expected: $exp\n",
" got: $got\n" if ($got ne $exp);
@@ -2758,9 +2783,7 @@ sub close_file {
if (my $fh = $fb->{fh}) {
if (defined $exp) {
seek($fh, 0, 0) or croak $!;
- my $md5 = Digest::MD5->new;
- $md5->addfile($fh);
- my $got = $md5->hexdigest;
+ my $got = Git::SVN::Util::md5sum($fh);
if ($got ne $exp) {
die "Checksum mismatch: $path\n",
"expected: $exp\n got: $got\n";
@@ -2812,7 +2835,6 @@ use strict;
use warnings;
use Carp qw/croak/;
use IO::File;
-use Digest::MD5;
sub new {
my ($class, $opts) = @_;
@@ -3116,11 +3138,9 @@ sub chg_file {
$fh->flush == 0 or croak $!;
seek $fh, 0, 0 or croak $!;
- my $md5 = Digest::MD5->new;
- $md5->addfile($fh) or croak $!;
+ my $exp = Git::SVN::Util::md5sum($fh);
seek $fh, 0, 0 or croak $!;
- my $exp = $md5->hexdigest;
my $pool = SVN::Pool->new;
my $atd = $self->apply_textdelta($fbat, undef, $pool);
my $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);
@@ -3833,6 +3853,29 @@ sub run_pager {
exec $pager or ::fatal "Can't run pager: $! ($pager)";
}
+sub format_svn_date {
+ return strftime("%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)", localtime(shift));
+}
+
+sub parse_git_date {
+ my ($t, $tz) = @_;
+ # Date::Parse isn't in the standard Perl distro :(
+ if ($tz =~ s/^\+//) {
+ $t += tz_to_s_offset($tz);
+ } elsif ($tz =~ s/^\-//) {
+ $t -= tz_to_s_offset($tz);
+ }
+ return $t;
+}
+
+sub set_local_timezone {
+ if (defined $TZ) {
+ $ENV{TZ} = $TZ;
+ } else {
+ delete $ENV{TZ};
+ }
+}
+
sub tz_to_s_offset {
my ($tz) = @_;
$tz =~ s/(\d\d)$//;
@@ -3853,13 +3896,7 @@ sub get_author_info {
$dest->{t} = $t;
$dest->{tz} = $tz;
$dest->{a} = $au;
- # Date::Parse isn't in the standard Perl distro :(
- if ($tz =~ s/^\+//) {
- $t += tz_to_s_offset($tz);
- } elsif ($tz =~ s/^\-//) {
- $t -= tz_to_s_offset($tz);
- }
- $dest->{t_utc} = $t;
+ $dest->{t_utc} = parse_git_date($t, $tz);
}
sub process_commit {
@@ -3913,8 +3950,7 @@ sub show_commit_normal {
my ($c) = @_;
print '-' x72, "\nr$c->{r} | ";
print "$c->{c} | " if $show_commit;
- print "$c->{a} | ", strftime("%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)",
- localtime($c->{t_utc})), ' | ';
+ print "$c->{a} | ", format_svn_date($c->{t_utc}), ' | ';
my $nr_line = 0;
if (my $l = $c->{l}) {
@@ -3954,11 +3990,7 @@ sub cmd_show_log {
my (@args) = @_;
my ($r_min, $r_max);
my $r_last = -1; # prevent dupes
- if (defined $TZ) {
- $ENV{TZ} = $TZ;
- } else {
- delete $ENV{TZ};
- }
+ set_local_timezone();
if (defined $::_revision) {
if ($::_revision =~ /^(\d+):(\d+)$/) {
($r_min, $r_max) = ($1, $2);
--
1.5.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/3] git-svn info: implement info command
2007-11-21 6:43 ` [PATCH 1/3] git-svn: extract reusable code into utility functions David D. Kilzer
@ 2007-11-21 6:43 ` David D. Kilzer
2007-11-21 6:43 ` [PATCH 3/3] git-svn: info --url [path] David D. Kilzer
0 siblings, 1 reply; 10+ messages in thread
From: David D. Kilzer @ 2007-11-21 6:43 UTC (permalink / raw)
To: Eric Wong; +Cc: git, David D. Kilzer
Implement "git-svn info" for files and directories based on the
"svn info" command. Note that the -r/--revision argument is not
supported yet.
Added 18 tests in t/t9117-git-svn-info.sh.
Signed-off-by: David D. Kilzer <ddkilzer@kilzer.net>
---
Documentation/git-svn.txt | 5 +
git-svn.perl | 132 ++++++++++++++++
t/t9117-git-svn-info.sh | 186 +++++++++++++++++++++++
t/t9117/expected.info-added-directory | 7 +
t/t9117/expected.info-added-file | 8 +
t/t9117/expected.info-added-symlink-directory | 8 +
t/t9117/expected.info-added-symlink-file | 8 +
t/t9117/expected.info-deleted-directory | 11 ++
t/t9117/expected.info-deleted-file | 14 ++
t/t9117/expected.info-deleted-symlink-directory | 14 ++
t/t9117/expected.info-deleted-symlink-file | 14 ++
t/t9117/expected.info-directory | 11 ++
t/t9117/expected.info-dot | 11 ++
t/t9117/expected.info-file | 14 ++
t/t9117/expected.info-no-arguments | 11 ++
t/t9117/expected.info-symlink-directory | 14 ++
t/t9117/expected.info-symlink-file | 14 ++
t/t9117/expected.info-unknown-directory | 2 +
t/t9117/expected.info-unknown-file | 2 +
t/t9117/expected.info-unknown-symlink-directory | 2 +
t/t9117/expected.info-unknown-symlink-file | 2 +
t/t9117/regenerate.sh | 186 +++++++++++++++++++++++
22 files changed, 676 insertions(+), 0 deletions(-)
create mode 100644 t/t9117-git-svn-info.sh
create mode 100644 t/t9117/expected.info-added-directory
create mode 100644 t/t9117/expected.info-added-file
create mode 100644 t/t9117/expected.info-added-symlink-directory
create mode 100644 t/t9117/expected.info-added-symlink-file
create mode 100644 t/t9117/expected.info-deleted-directory
create mode 100644 t/t9117/expected.info-deleted-file
create mode 100644 t/t9117/expected.info-deleted-symlink-directory
create mode 100644 t/t9117/expected.info-deleted-symlink-file
create mode 100644 t/t9117/expected.info-directory
create mode 100644 t/t9117/expected.info-dot
create mode 100644 t/t9117/expected.info-file
create mode 100644 t/t9117/expected.info-no-arguments
create mode 100644 t/t9117/expected.info-symlink-directory
create mode 100644 t/t9117/expected.info-symlink-file
create mode 100644 t/t9117/expected.info-unknown-directory
create mode 100644 t/t9117/expected.info-unknown-file
create mode 100644 t/t9117/expected.info-unknown-symlink-directory
create mode 100644 t/t9117/expected.info-unknown-symlink-file
create mode 100755 t/t9117/regenerate.sh
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 488e4b1..c3fc878 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -193,6 +193,11 @@ Any other arguments are passed directly to `git log'
repository (that has been init-ed with git-svn).
The -r<revision> option is required for this.
+'info'::
+ Shows information about a file or directory similar to what
+ `svn info' provides. Does not currently support a -r/--revision
+ argument.
+
--
OPTIONS
diff --git a/git-svn.perl b/git-svn.perl
index aff429a..406ee6f 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -178,6 +178,10 @@ my %cmd = (
'file|F=s' => \$_file,
'revision|r=s' => \$_revision,
%cmt_opts } ],
+ 'info' => [ \&cmd_info,
+ "Show info about the latest SVN revision
+ on the current branch",
+ { } ],
);
my $cmd;
@@ -583,12 +587,18 @@ sub cmd_create_ignore {
sub canonicalize_path {
my ($path) = @_;
+ my $dot_slash_added = 0;
+ if (substr($path, 0, 1) ne "/") {
+ $path = "./" . $path;
+ $dot_slash_added = 1;
+ }
# File::Spec->canonpath doesn't collapse x/../y into y (for a
# good reason), so let's do this manually.
$path =~ s#/+#/#g;
$path =~ s#/\.(?:/|$)#/#g;
$path =~ s#/[^/]+/\.\.##g;
$path =~ s#/$##g;
+ $path =~ s#^\./## if $dot_slash_added;
return $path;
}
@@ -740,6 +750,104 @@ sub cmd_commit_diff {
}
}
+sub cmd_info {
+ my $path = canonicalize_path(shift or ".");
+ unless (scalar(@_) == 0) {
+ die "Too many arguments specified\n";
+ }
+
+ my ($file_type, $diff_status) = find_file_type_and_diff_status($path);
+
+ if (!$file_type && !$diff_status) {
+ print STDERR "$path: (Not a versioned resource)\n\n";
+ return;
+ }
+
+ my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+ unless ($gs) {
+ die "Unable to determine upstream SVN information from ",
+ "working tree history\n";
+ }
+ my $full_url = $url . ($path eq "." ? "" : "/$path");
+
+ my $result = "Path: $path\n";
+ $result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
+ $result .= "URL: " . $full_url . "\n";
+
+ my $repos_root = $gs->ra->{repos_root};
+ Git::SVN::remove_username($repos_root);
+ $result .= "Repository Root: $repos_root\n";
+ $result .= "Repository UUID: $uuid\n" unless $diff_status eq "A";
+ $result .= "Revision: " . ($diff_status eq "A" ? 0 : $rev) . "\n";
+
+ $result .= "Node Kind: " .
+ ($file_type eq "dir" ? "directory" : "file") . "\n";
+
+ my $schedule = $diff_status eq "A"
+ ? "add"
+ : ($diff_status eq "D" ? "delete" : "normal");
+ $result .= "Schedule: $schedule\n";
+
+ if ($diff_status eq "A") {
+ print $result, "\n";
+ return;
+ }
+
+ my ($lc_author, $lc_rev, $lc_date_utc);
+ my @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, "--", $path);
+ my $log = command_output_pipe(@args);
+ my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/;
+ while (<$log>) {
+ if (/^${esc_color}author (.+) <[^>]+> (\d+) ([\-\+]?\d+)$/o) {
+ $lc_author = $1;
+ $lc_date_utc = Git::SVN::Log::parse_git_date($2, $3);
+ } elsif (/^${esc_color} (git-svn-id:.+)$/o) {
+ (undef, $lc_rev, undef) = ::extract_metadata($1);
+ }
+ }
+ close $log;
+
+ Git::SVN::Log::set_local_timezone();
+
+ $result .= "Last Changed Author: $lc_author\n";
+ $result .= "Last Changed Rev: $lc_rev\n";
+ $result .= "Last Changed Date: " .
+ Git::SVN::Log::format_svn_date($lc_date_utc) . "\n";
+
+ if ($file_type ne "dir") {
+ my $text_last_updated_date =
+ ($diff_status eq "D" ? $lc_date_utc : (stat $path)[9]);
+ $result .=
+ "Text Last Updated: " .
+ Git::SVN::Log::format_svn_date($text_last_updated_date) .
+ "\n";
+ my $checksum;
+ if ($diff_status eq "D") {
+ my ($fh, $ctx) =
+ command_output_pipe(qw(cat-file blob), "HEAD:$path");
+ if ($file_type eq "link") {
+ my $file_name = <$fh>;
+ $checksum = Git::SVN::Util::md5sum("link $file_name");
+ } else {
+ $checksum = Git::SVN::Util::md5sum($fh);
+ }
+ command_close_pipe($fh, $ctx);
+ } elsif ($file_type eq "link") {
+ my $file_name =
+ command(qw(cat-file blob), "HEAD:$path");
+ $checksum =
+ Git::SVN::Util::md5sum("link " . $file_name);
+ } else {
+ open FILE, "<", $path or die $!;
+ $checksum = Git::SVN::Util::md5sum(\*FILE);
+ close FILE or die $!;
+ }
+ $result .= "Checksum: " . $checksum . "\n";
+ }
+
+ print $result, "\n";
+}
+
########################### utility functions #########################
sub rebase_cmd {
@@ -1047,6 +1155,30 @@ sub linearize_history {
(\@linear_refs, \%parents);
}
+sub find_file_type_and_diff_status {
+ my ($path) = @_;
+
+ my $diff_output =
+ command_oneline(qw(diff --cached --name-status --), $path) || "";
+ my $diff_status = (split(' ', $diff_output))[0] || "";
+
+ my $ls_tree = command_oneline(qw(ls-tree HEAD), $path) || "";
+
+ return (undef, undef) if !$diff_status && !$ls_tree;
+
+ if ($diff_status eq "A") {
+ return ("link", $diff_status) if -l $path;
+ return ("dir", $diff_status) if -d $path;
+ return ("file", $diff_status);
+ }
+
+ my $mode = (split(' ', $ls_tree))[0] || "";
+
+ return ("link", $diff_status) if $mode eq "120000";
+ return ("dir", $diff_status) if $mode eq "040000";
+ return ("file", $diff_status);
+}
+
package Git::SVN::Util;
use strict;
use warnings;
diff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh
new file mode 100644
index 0000000..c7ca006
--- /dev/null
+++ b/t/t9117-git-svn-info.sh
@@ -0,0 +1,186 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 David D. Kilzer
+
+test_description='git-svn info'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'setup repository and import' "
+ mkdir info &&
+ cd info &&
+ echo one > file &&
+ ln -s file symlink-file &&
+ mkdir directory &&
+ touch directory/.placeholder &&
+ ln -s directory symlink-directory &&
+ svn import -m 'initial' . $svnrepo &&
+ cd .. &&
+ mkdir gitwc &&
+ cd gitwc &&
+ git-svn init $svnrepo &&
+ git-svn fetch &&
+ cd ..
+ "
+
+test_expect_success 'info no arguments' "
+ (cd gitwc; git-svn info) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' |
+ git-diff ../t9117/expected.info-no-arguments -
+ "
+
+test_expect_success 'info dot' "
+ (cd gitwc; git-svn info .) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' |
+ git-diff ../t9117/expected.info-dot -
+ "
+
+test_expect_success 'info file' "
+ (cd gitwc; git-svn info file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' |
+ git-diff ../t9117/expected.info-file -
+ "
+
+test_expect_success 'info directory' "
+ (cd gitwc; git-svn info directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' |
+ git-diff ../t9117/expected.info-directory -
+ "
+
+test_expect_success 'info symlink-file' "
+ (cd gitwc; git-svn info symlink-file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' |
+ git-diff ../t9117/expected.info-symlink-file -
+ "
+
+test_expect_success 'info symlink-directory' "
+ (cd gitwc; git-svn info symlink-directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' |
+ git-diff ../t9117/expected.info-symlink-directory -
+ "
+
+test_expect_success 'info added-file' "
+ echo two > gitwc/added-file &&
+ cd gitwc &&
+ git add added-file &&
+ cd .. &&
+ (cd gitwc; git-svn info added-file) |
+ git-diff ../t9117/expected.info-added-file -
+ "
+
+test_expect_success 'info added-directory' "
+ mkdir gitwc/added-directory &&
+ touch gitwc/added-directory/.placeholder &&
+ cd gitwc &&
+ git add added-directory &&
+ cd .. &&
+ (cd gitwc; git-svn info added-directory) |
+ git-diff ../t9117/expected.info-added-directory -
+ "
+
+test_expect_success 'info added-symlink-file' "
+ cd gitwc &&
+ ln -s added-file added-symlink-file &&
+ git add added-symlink-file &&
+ cd .. &&
+ (cd gitwc; git-svn info added-symlink-file) |
+ git-diff ../t9117/expected.info-added-symlink-file -
+ "
+
+test_expect_success 'info added-symlink-directory' "
+ cd gitwc &&
+ ln -s added-directory added-symlink-directory &&
+ git add added-symlink-directory &&
+ cd .. &&
+ (cd gitwc; git-svn info added-symlink-directory) |
+ git-diff ../t9117/expected.info-added-symlink-directory -
+ "
+
+test_expect_success 'info deleted-file' "
+ cd gitwc &&
+ git rm -f file > /dev/null &&
+ cd .. &&
+ (cd gitwc; git-svn info file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' |
+ git-diff ../t9117/expected.info-deleted-file -
+ "
+
+test_expect_success 'info deleted-directory' "
+ cd gitwc &&
+ git rm -r -f directory > /dev/null &&
+ cd .. &&
+ (cd gitwc; git-svn info directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' |
+ git-diff ../t9117/expected.info-deleted-directory -
+ "
+
+test_expect_success 'info deleted-symlink-file' "
+ cd gitwc &&
+ git rm -f symlink-file > /dev/null &&
+ cd .. &&
+ (cd gitwc; git-svn info symlink-file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' |
+ git-diff ../t9117/expected.info-deleted-symlink-file -
+ "
+
+test_expect_success 'info deleted-symlink-directory' "
+ cd gitwc &&
+ git rm -f symlink-directory > /dev/null &&
+ cd .. &&
+ (cd gitwc; git-svn info symlink-directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' |
+ git-diff ../t9117/expected.info-deleted-symlink-directory -
+ "
+
+# NOTE: git does not have the concept of replaced objects,
+# so we can't test for them.
+#test_expect_success 'info replaced-file' "/usr/bin/true"
+#test_expect_success 'info replaced-directory' "/usr/bin/true"
+#test_expect_success 'info replaced-symlink-file' "/usr/bin/true"
+#test_expect_success 'info replaced-symlink-directory' "/usr/bin/true"
+
+test_expect_success 'info unknown-file' "
+ echo two > gitwc/unknown-file &&
+ (cd gitwc; git-svn info unknown-file) 2>&1 |
+ git-diff ../t9117/expected.info-unknown-file -
+ "
+
+test_expect_success 'info unknown-directory' "
+ mkdir gitwc/unknown-directory &&
+ (cd gitwc; git-svn info unknown-directory) 2>&1 |
+ git-diff ../t9117/expected.info-unknown-directory -
+ "
+
+test_expect_success 'info unknown-symlink-file' "
+ cd gitwc &&
+ ln -s unknown-file unknown-symlink-file &&
+ cd .. &&
+ (cd gitwc; git-svn info unknown-symlink-file) 2>&1 |
+ git-diff ../t9117/expected.info-unknown-symlink-file -
+ "
+
+test_expect_success 'info unknown-symlink-directory' "
+ cd gitwc &&
+ ln -s unknown-directory unknown-symlink-directory &&
+ cd .. &&
+ (cd gitwc; git-svn info unknown-symlink-directory) 2>&1 |
+ git-diff ../t9117/expected.info-unknown-symlink-directory -
+ "
+
+test_done
diff --git a/t/t9117/expected.info-added-directory b/t/t9117/expected.info-added-directory
new file mode 100644
index 0000000..2622900
--- /dev/null
+++ b/t/t9117/expected.info-added-directory
@@ -0,0 +1,7 @@
+Path: added-directory
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-directory
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Revision: 0
+Node Kind: directory
+Schedule: add
+
diff --git a/t/t9117/expected.info-added-file b/t/t9117/expected.info-added-file
new file mode 100644
index 0000000..2881f93
--- /dev/null
+++ b/t/t9117/expected.info-added-file
@@ -0,0 +1,8 @@
+Path: added-file
+Name: added-file
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-file
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Revision: 0
+Node Kind: file
+Schedule: add
+
diff --git a/t/t9117/expected.info-added-symlink-directory b/t/t9117/expected.info-added-symlink-directory
new file mode 100644
index 0000000..fa3d511
--- /dev/null
+++ b/t/t9117/expected.info-added-symlink-directory
@@ -0,0 +1,8 @@
+Path: added-symlink-directory
+Name: added-symlink-directory
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-symlink-directory
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Revision: 0
+Node Kind: file
+Schedule: add
+
diff --git a/t/t9117/expected.info-added-symlink-file b/t/t9117/expected.info-added-symlink-file
new file mode 100644
index 0000000..cd14e62
--- /dev/null
+++ b/t/t9117/expected.info-added-symlink-file
@@ -0,0 +1,8 @@
+Path: added-symlink-file
+Name: added-symlink-file
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-symlink-file
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Revision: 0
+Node Kind: file
+Schedule: add
+
diff --git a/t/t9117/expected.info-deleted-directory b/t/t9117/expected.info-deleted-directory
new file mode 100644
index 0000000..ec8bda5
--- /dev/null
+++ b/t/t9117/expected.info-deleted-directory
@@ -0,0 +1,11 @@
+Path: directory
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/directory
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: directory
+Schedule: delete
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+
diff --git a/t/t9117/expected.info-deleted-file b/t/t9117/expected.info-deleted-file
new file mode 100644
index 0000000..7951183
--- /dev/null
+++ b/t/t9117/expected.info-deleted-file
@@ -0,0 +1,14 @@
+Path: file
+Name: file
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/file
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: file
+Schedule: delete
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+Text Last Updated: TEXT-LAST-UPDATED-STRING
+Checksum: 5bbf5a52328e7439ae6e719dfe712200
+
diff --git a/t/t9117/expected.info-deleted-symlink-directory b/t/t9117/expected.info-deleted-symlink-directory
new file mode 100644
index 0000000..2fb452d
--- /dev/null
+++ b/t/t9117/expected.info-deleted-symlink-directory
@@ -0,0 +1,14 @@
+Path: symlink-directory
+Name: symlink-directory
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-directory
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: file
+Schedule: delete
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+Text Last Updated: TEXT-LAST-UPDATED-STRING
+Checksum: 7f5674b838ad799ab8962413b1f84095
+
diff --git a/t/t9117/expected.info-deleted-symlink-file b/t/t9117/expected.info-deleted-symlink-file
new file mode 100644
index 0000000..c2945f9
--- /dev/null
+++ b/t/t9117/expected.info-deleted-symlink-file
@@ -0,0 +1,14 @@
+Path: symlink-file
+Name: symlink-file
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-file
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: file
+Schedule: delete
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+Text Last Updated: TEXT-LAST-UPDATED-STRING
+Checksum: 73f9c467f93002e83dc229a229bbc4cb
+
diff --git a/t/t9117/expected.info-directory b/t/t9117/expected.info-directory
new file mode 100644
index 0000000..29dfa37
--- /dev/null
+++ b/t/t9117/expected.info-directory
@@ -0,0 +1,11 @@
+Path: directory
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/directory
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: directory
+Schedule: normal
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+
diff --git a/t/t9117/expected.info-dot b/t/t9117/expected.info-dot
new file mode 100644
index 0000000..c3bf061
--- /dev/null
+++ b/t/t9117/expected.info-dot
@@ -0,0 +1,11 @@
+Path: .
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: directory
+Schedule: normal
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+
diff --git a/t/t9117/expected.info-file b/t/t9117/expected.info-file
new file mode 100644
index 0000000..9350107
--- /dev/null
+++ b/t/t9117/expected.info-file
@@ -0,0 +1,14 @@
+Path: file
+Name: file
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/file
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: file
+Schedule: normal
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+Text Last Updated: TEXT-LAST-UPDATED-STRING
+Checksum: 5bbf5a52328e7439ae6e719dfe712200
+
diff --git a/t/t9117/expected.info-no-arguments b/t/t9117/expected.info-no-arguments
new file mode 100644
index 0000000..c3bf061
--- /dev/null
+++ b/t/t9117/expected.info-no-arguments
@@ -0,0 +1,11 @@
+Path: .
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: directory
+Schedule: normal
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+
diff --git a/t/t9117/expected.info-symlink-directory b/t/t9117/expected.info-symlink-directory
new file mode 100644
index 0000000..70255ac
--- /dev/null
+++ b/t/t9117/expected.info-symlink-directory
@@ -0,0 +1,14 @@
+Path: symlink-directory
+Name: symlink-directory
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-directory
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: file
+Schedule: normal
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+Text Last Updated: TEXT-LAST-UPDATED-STRING
+Checksum: 7f5674b838ad799ab8962413b1f84095
+
diff --git a/t/t9117/expected.info-symlink-file b/t/t9117/expected.info-symlink-file
new file mode 100644
index 0000000..8465c1d
--- /dev/null
+++ b/t/t9117/expected.info-symlink-file
@@ -0,0 +1,14 @@
+Path: symlink-file
+Name: symlink-file
+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-file
+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo
+Repository UUID: REPOSITORY-UUID
+Revision: 1
+Node Kind: file
+Schedule: normal
+Last Changed Author: ddkilzer
+Last Changed Rev: 1
+Last Changed Date: LAST-CHANGED-DATE-STRING
+Text Last Updated: TEXT-LAST-UPDATED-STRING
+Checksum: 73f9c467f93002e83dc229a229bbc4cb
+
diff --git a/t/t9117/expected.info-unknown-directory b/t/t9117/expected.info-unknown-directory
new file mode 100644
index 0000000..b5eef7d
--- /dev/null
+++ b/t/t9117/expected.info-unknown-directory
@@ -0,0 +1,2 @@
+unknown-directory: (Not a versioned resource)
+
diff --git a/t/t9117/expected.info-unknown-file b/t/t9117/expected.info-unknown-file
new file mode 100644
index 0000000..89f102e
--- /dev/null
+++ b/t/t9117/expected.info-unknown-file
@@ -0,0 +1,2 @@
+unknown-file: (Not a versioned resource)
+
diff --git a/t/t9117/expected.info-unknown-symlink-directory b/t/t9117/expected.info-unknown-symlink-directory
new file mode 100644
index 0000000..37d3106
--- /dev/null
+++ b/t/t9117/expected.info-unknown-symlink-directory
@@ -0,0 +1,2 @@
+unknown-symlink-directory: (Not a versioned resource)
+
diff --git a/t/t9117/expected.info-unknown-symlink-file b/t/t9117/expected.info-unknown-symlink-file
new file mode 100644
index 0000000..cae9ab0
--- /dev/null
+++ b/t/t9117/expected.info-unknown-symlink-file
@@ -0,0 +1,2 @@
+unknown-symlink-file: (Not a versioned resource)
+
diff --git a/t/t9117/regenerate.sh b/t/t9117/regenerate.sh
new file mode 100755
index 0000000..16d039d
--- /dev/null
+++ b/t/t9117/regenerate.sh
@@ -0,0 +1,186 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 David D. Kilzer
+
+test_description='regenerate results for git-svn info'
+
+cd `dirname $0`/..
+. ./lib-git-svn.sh
+
+test_expect_success 'setup repository and import' "
+ mkdir info &&
+ cd info &&
+ echo one > file &&
+ ln -s file symlink-file &&
+ mkdir directory &&
+ touch directory/.placeholder &&
+ ln -s directory symlink-directory &&
+ svn import -m 'initial' . $svnrepo &&
+ cd .. &&
+ svn co $svnrepo svnwc
+ "
+
+test_expect_success 'info no arguments' "
+ (cd svnwc; svn info) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ >../t9117/expected.info-no-arguments
+ "
+
+test_expect_success 'info dot' "
+ (cd svnwc; svn info .) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ >../t9117/expected.info-dot
+ "
+
+test_expect_success 'info file' "
+ (cd svnwc; svn info file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
+ >../t9117/expected.info-file
+ "
+
+test_expect_success 'info directory' "
+ (cd svnwc; svn info directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ >../t9117/expected.info-directory
+ "
+
+test_expect_success 'info symlink-file' "
+ (cd svnwc; svn info symlink-file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
+ >../t9117/expected.info-symlink-file
+ "
+
+test_expect_success 'info symlink-directory' "
+ (cd svnwc; svn info symlink-directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
+ >../t9117/expected.info-symlink-directory
+ "
+
+test_expect_success 'info added-file' "
+ echo two > svnwc/added-file &&
+ cd svnwc &&
+ svn add added-file > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info added-file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ >../t9117/expected.info-added-file
+ "
+
+test_expect_success 'info added-directory' "
+ mkdir svnwc/added-directory &&
+ cd svnwc &&
+ svn add added-directory > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info added-directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ >../t9117/expected.info-added-directory
+ "
+
+test_expect_success 'info added-symlink-file' "
+ cd svnwc &&
+ ln -s added-file added-symlink-file &&
+ svn add added-symlink-file > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info added-symlink-file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ >../t9117/expected.info-added-symlink-file
+ "
+
+test_expect_success 'info added-symlink-directory' "
+ cd svnwc &&
+ ln -s added-directory added-symlink-directory &&
+ svn add added-symlink-directory > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info added-symlink-directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ >../t9117/expected.info-added-symlink-directory
+ "
+
+test_expect_success 'info deleted-file' "
+ cd svnwc &&
+ svn rm --force file > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
+ >../t9117/expected.info-deleted-file
+ "
+
+test_expect_success 'info deleted-directory' "
+ cd svnwc &&
+ svn rm --force directory > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ >../t9117/expected.info-deleted-directory
+ "
+
+test_expect_success 'info deleted-symlink-file' "
+ cd svnwc &&
+ svn rm --force symlink-file > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info symlink-file) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
+ >../t9117/expected.info-deleted-symlink-file
+ "
+
+test_expect_success 'info deleted-symlink-directory' "
+ cd svnwc &&
+ svn rm --force symlink-directory > /dev/null &&
+ cd .. &&
+ (cd svnwc; svn info symlink-directory) |
+ sed -e 's/^\(Repository UUID:\).*/\1 REPOSITORY-UUID/' \
+ -e 's/^\(Last Changed Date:\).*/\1 LAST-CHANGED-DATE-STRING/' \
+ -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
+ >../t9117/expected.info-deleted-symlink-directory
+ "
+
+# NOTE: git does not have the concept of replaced objects,
+# so we can't test for them.
+#test_expect_success 'info replaced-file' "/usr/bin/true"
+#test_expect_success 'info replaced-directory' "/usr/bin/true"
+#test_expect_success 'info replaced-symlink-file' "/usr/bin/true"
+#test_expect_success 'info replaced-symlink-directory' "/usr/bin/true"
+
+test_expect_success 'info unknown-file' "
+ echo two > svnwc/unknown-file &&
+ (cd svnwc; svn info unknown-file) \
+ 2>../t9117/expected.info-unknown-file
+ "
+
+test_expect_success 'info unknown-directory' "
+ mkdir svnwc/unknown-directory &&
+ (cd svnwc; svn info unknown-directory) \
+ 2>../t9117/expected.info-unknown-directory
+ "
+
+test_expect_success 'info unknown-symlink-file' "
+ cd svnwc &&
+ ln -s unknown-file unknown-symlink-file &&
+ cd .. &&
+ (cd svnwc; svn info unknown-symlink-file) \
+ 2>../t9117/expected.info-unknown-symlink-file
+ "
+
+test_expect_success 'info unknown-symlink-directory' "
+ cd svnwc &&
+ ln -s unknown-directory unknown-symlink-directory &&
+ cd .. &&
+ (cd svnwc; svn info unknown-symlink-directory) \
+ 2>../t9117/expected.info-unknown-symlink-directory
+ "
+
+test_done
--
1.5.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/3] git-svn: info --url [path]
2007-11-21 6:43 ` [PATCH 2/3] git-svn info: implement info command David D. Kilzer
@ 2007-11-21 6:43 ` David D. Kilzer
2007-11-21 6:49 ` [PATCH 3/3 v2] " David D. Kilzer
0 siblings, 1 reply; 10+ messages in thread
From: David D. Kilzer @ 2007-11-21 6:43 UTC (permalink / raw)
To: Eric Wong; +Cc: git, David D. Kilzer
Return the svn URL for the given path, or return the svn
repository URL if no path is given.
Signed-off-by: David D. Kilzer <ddkilzer@kilzer.net>
---
git-svn.perl | 9 +++++++--
t/t9117-git-svn-info.sh | 4 ++++
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 406ee6f..eaf2187 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -65,7 +65,7 @@ my ($_stdin, $_help, $_edit,
$_template, $_shared,
$_version, $_fetch_all, $_no_rebase,
$_merge, $_strategy, $_dry_run, $_local,
- $_prefix, $_no_checkout, $_verbose);
+ $_prefix, $_no_checkout, $_url, $_verbose);
$Git::SVN::_follow_parent = 1;
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -181,7 +181,7 @@ my %cmd = (
'info' => [ \&cmd_info,
"Show info about the latest SVN revision
on the current branch",
- { } ],
+ { 'url' => \$_url, } ],
);
my $cmd;
@@ -770,6 +770,11 @@ sub cmd_info {
}
my $full_url = $url . ($path eq "." ? "" : "/$path");
+ if ($_url) {
+ print $full_url, "\n";
+ return;
+ }
+
my $result = "Path: $path\n";
$result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
$result .= "URL: " . $full_url . "\n";
diff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh
index c7ca006..800d1c4 100644
--- a/t/t9117-git-svn-info.sh
+++ b/t/t9117-git-svn-info.sh
@@ -183,4 +183,8 @@ test_expect_success 'info unknown-symlink-directory' "
git-diff ../t9117/expected.info-unknown-symlink-directory -
"
+test_expect_success 'info --url' '
+ test $(cd gitwc; git-svn info --url) = $svnrepo
+ '
+
test_done
--
1.5.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/3 v2] git-svn: info --url [path]
2007-11-21 6:43 ` [PATCH 3/3] git-svn: info --url [path] David D. Kilzer
@ 2007-11-21 6:49 ` David D. Kilzer
0 siblings, 0 replies; 10+ messages in thread
From: David D. Kilzer @ 2007-11-21 6:49 UTC (permalink / raw)
To: Eric Wong; +Cc: git, David D. Kilzer
Return the svn URL for the given path, or return the svn
repository URL if no path is given.
Added one test to t/t9117-git-svn-info.sh.
Signed-off-by: David D. Kilzer <ddkilzer@kilzer.net>
---
Added missing documentation change, and tweaked commit log.
Documentation/git-svn.txt | 2 +-
git-svn.perl | 9 +++++++--
t/t9117-git-svn-info.sh | 4 ++++
3 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index c3fc878..295b14b 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -196,7 +196,7 @@ Any other arguments are passed directly to `git log'
'info'::
Shows information about a file or directory similar to what
`svn info' provides. Does not currently support a -r/--revision
- argument.
+ argument. Use the --url option to output only the 'URL:' field.
--
diff --git a/git-svn.perl b/git-svn.perl
index 406ee6f..eaf2187 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -65,7 +65,7 @@ my ($_stdin, $_help, $_edit,
$_template, $_shared,
$_version, $_fetch_all, $_no_rebase,
$_merge, $_strategy, $_dry_run, $_local,
- $_prefix, $_no_checkout, $_verbose);
+ $_prefix, $_no_checkout, $_url, $_verbose);
$Git::SVN::_follow_parent = 1;
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -181,7 +181,7 @@ my %cmd = (
'info' => [ \&cmd_info,
"Show info about the latest SVN revision
on the current branch",
- { } ],
+ { 'url' => \$_url, } ],
);
my $cmd;
@@ -770,6 +770,11 @@ sub cmd_info {
}
my $full_url = $url . ($path eq "." ? "" : "/$path");
+ if ($_url) {
+ print $full_url, "\n";
+ return;
+ }
+
my $result = "Path: $path\n";
$result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
$result .= "URL: " . $full_url . "\n";
diff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh
index c7ca006..800d1c4 100644
--- a/t/t9117-git-svn-info.sh
+++ b/t/t9117-git-svn-info.sh
@@ -183,4 +183,8 @@ test_expect_success 'info unknown-symlink-directory' "
git-diff ../t9117/expected.info-unknown-symlink-directory -
"
+test_expect_success 'info --url' '
+ test $(cd gitwc; git-svn info --url) = $svnrepo
+ '
+
test_done
--
1.5.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/3] Implement git-svn: info
2007-11-21 6:43 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
2007-11-21 6:43 ` [PATCH 1/3] git-svn: extract reusable code into utility functions David D. Kilzer
@ 2007-11-21 6:59 ` David D. Kilzer
2007-11-21 9:18 ` Eric Wong
1 sibling, 1 reply; 10+ messages in thread
From: David D. Kilzer @ 2007-11-21 6:59 UTC (permalink / raw)
To: Eric Wong; +Cc: git, David D. Kilzer
"David D. Kilzer" <ddkilzer@kilzer.net> wrote:
> Eric Wong <normalperson@yhbt.net> wrote:
> > Can we expect the output of "svn info" to not change between
> > versions? I know "svn status" has changed between versions of
> > svn. I'd prefer if we keep the expected.* files hard-coded
> > in a test directory and compare those instead. Maybe use sed
> > to substitute placeholders for timestamps..
> Done.
Grrr. I remember the reason I didn't do this in the first place. In Patch
2/3, there are now hard-coded directory paths and my username in the static
expected-* files.
That means that either I need to replace the "URL:", "Repository Root:" and
"Last Changed Author:" fields with place-holders (weakening the effectiveness
of the tests), or switch back to more dynamic tests.
Thoughts?
Dave
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/3] Implement git-svn: info
2007-11-21 6:59 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
@ 2007-11-21 9:18 ` Eric Wong
2007-11-21 9:20 ` Eric Wong
0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2007-11-21 9:18 UTC (permalink / raw)
To: David D. Kilzer; +Cc: git
"David D. Kilzer" <ddkilzer@kilzer.net> wrote:
> "David D. Kilzer" <ddkilzer@kilzer.net> wrote:
> > Eric Wong <normalperson@yhbt.net> wrote:
> > > Can we expect the output of "svn info" to not change between
> > > versions? I know "svn status" has changed between versions of
> > > svn. I'd prefer if we keep the expected.* files hard-coded
> > > in a test directory and compare those instead. Maybe use sed
> > > to substitute placeholders for timestamps..
> > Done.
>
> Grrr. I remember the reason I didn't do this in the first place. In Patch
> 2/3, there are now hard-coded directory paths and my username in the static
> expected-* files.
>
> That means that either I need to replace the "URL:", "Repository Root:" and
> "Last Changed Author:" fields with place-holders (weakening the effectiveness
> of the tests), or switch back to more dynamic tests.
>
> Thoughts?
Ah, good point.
On some of my tests (t9110, t9111, t9115), I get around this by
generating a repository once and dumping it using `svnadmin dump'.
--
Eric Wong
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/3] Implement git-svn: info
2007-11-21 9:18 ` Eric Wong
@ 2007-11-21 9:20 ` Eric Wong
0 siblings, 0 replies; 10+ messages in thread
From: Eric Wong @ 2007-11-21 9:20 UTC (permalink / raw)
To: David D. Kilzer; +Cc: git
Eric Wong <normalperson@yhbt.net> wrote:
> "David D. Kilzer" <ddkilzer@kilzer.net> wrote:
> > "David D. Kilzer" <ddkilzer@kilzer.net> wrote:
> > > Eric Wong <normalperson@yhbt.net> wrote:
> > > > Can we expect the output of "svn info" to not change between
> > > > versions? I know "svn status" has changed between versions of
> > > > svn. I'd prefer if we keep the expected.* files hard-coded
> > > > in a test directory and compare those instead. Maybe use sed
> > > > to substitute placeholders for timestamps..
> > > Done.
> >
> > Grrr. I remember the reason I didn't do this in the first place. In Patch
> > 2/3, there are now hard-coded directory paths and my username in the static
> > expected-* files.
> >
> > That means that either I need to replace the "URL:", "Repository Root:" and
> > "Last Changed Author:" fields with place-holders (weakening the effectiveness
> > of the tests), or switch back to more dynamic tests.
> >
> > Thoughts?
>
> Ah, good point.
>
> On some of my tests (t9110, t9111, t9115), I get around this by
> generating a repository once and dumping it using `svnadmin dump'.
Wait, the paths/URLs will still be inconsistent, but author will at
least be correct...
Sorry, I need sleep :/
--
Eric Wong
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2007-11-21 9:20 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-12 16:19 [RFC PATCH] git-svn info: implement info command David D. Kilzer
2007-11-17 22:54 ` Eric Wong
2007-11-21 6:43 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
2007-11-21 6:43 ` [PATCH 1/3] git-svn: extract reusable code into utility functions David D. Kilzer
2007-11-21 6:43 ` [PATCH 2/3] git-svn info: implement info command David D. Kilzer
2007-11-21 6:43 ` [PATCH 3/3] git-svn: info --url [path] David D. Kilzer
2007-11-21 6:49 ` [PATCH 3/3 v2] " David D. Kilzer
2007-11-21 6:59 ` [PATCH 0/3] Implement git-svn: info David D. Kilzer
2007-11-21 9:18 ` Eric Wong
2007-11-21 9:20 ` Eric Wong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).