{"thread":{"id":"10834","subject":"[RFC PATCH] git-svn info: implement info command","startedAt":"2007-11-12T16:19:09Z","lastAt":"2007-11-21T09:20:28Z","messageCount":10,"participants":["David D. Kilzer","Eric Wong"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"59514","messageId":"1194884349-11504-1-git-send-email-ddkilzer@kilzer.net","threadId":"10834","inReplyTo":null,"subject":"[RFC PATCH] git-svn info: implement info command","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2007-11-12T16:19:09Z","receivedAt":"2007-11-12T16:19:09Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"Implement \"git-svn info\" for files and directories based on the \"svn info\"\ncommand.  Note that the -r/--revision argument is not supported yet.\n\nAdded 18 tests in t/t9117-git-svn-info.sh.\n\nSigned-off-by: David D. Kilzer <ddkilzer@kilzer.net>\n---\n\nLooking for feedback on this patch.  Specifically, I'm looking for insight\nfor the two FIXME comments in the cmd_info() function added to git-svn.\n(I can't help but think I'm missing a plumbing command or a basic concept.\nPointers to code, web pages or man pages are welcome.)\n\nNote that I've tried to cover all the bases that \"svn info\" does (by using\ntests), except supporting the -r/--revision argument.\n\nI've also tried to be aggressive in extracting common code into functions.\n\nDave\n\n Documentation/git-svn.txt |    5 +\n git-svn.perl              |  194 +++++++++++++++++++++++++++++++------\n t/t9117-git-svn-info.sh   |  236 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 403 insertions(+), 32 deletions(-)\n create mode 100644 t/t9117-git-svn-info.sh\n\ndiff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt\nindex 488e4b1..c3fc878 100644\n--- a/Documentation/git-svn.txt\n+++ b/Documentation/git-svn.txt\n@@ -193,6 +193,11 @@ Any other arguments are passed directly to `git log'\n \trepository (that has been init-ed with git-svn).\n \tThe -r<revision> option is required for this.\n \n+'info'::\n+\tShows information about a file or directory similar to what\n+\t`svn info' provides.  Does not currently support a -r/--revision\n+\targument.\n+\n --\n \n OPTIONS\ndiff --git a/git-svn.perl b/git-svn.perl\nindex dd93e32..256a3e0 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -48,7 +48,8 @@ BEGIN {\n \tforeach (qw/command command_oneline command_noisy command_output_pipe\n \t            command_input_pipe command_close_pipe/) {\n \t\tfor my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher\n-\t\t\tGit::SVN::Migration Git::SVN::Log Git::SVN),\n+\t\t\tGit::SVN::Migration Git::SVN::Log Git::SVN\n+\t\t\tGit::SVN::Util),\n \t\t\t__PACKAGE__) {\n \t\t\t*{\"${package}::$_\"} = \\&{\"Git::$_\"};\n \t\t}\n@@ -177,6 +178,8 @@ my %cmd = (\n \t\t\t  'file|F=s' => \\$_file,\n \t\t\t  'revision|r=s' => \\$_revision,\n \t\t\t%cmt_opts } ],\n+\t'info' => [ \\&cmd_info, \"Show info about the latest SVN revision on the current branch\",\n+\t\t\t{ } ],\n );\n \n my $cmd;\n@@ -577,6 +580,23 @@ sub cmd_create_ignore {\n \t});\n }\n \n+sub canonicalize_path {\n+\tmy ($path) = @_;\n+\tmy $dotSlashAdded = 0;\n+\tif (substr($path, 0, 1) ne \"/\") {\n+\t\t$path = \"./\" . $path;\n+\t\t$dotSlashAdded = 1;\n+\t}\n+\t# File::Spec->canonpath doesn't collapse x/../y into y (for a\n+\t# good reason), so let's do this manually.\n+\t$path =~ s#/+#/#g;\n+\t$path =~ s#/\\.(?:/|$)#/#g;\n+\t$path =~ s#/[^/]+/\\.\\.##g;\n+\t$path =~ s#/$##g;\n+\t$path =~ s#^\\./## if $dotSlashAdded;\n+\treturn $path;\n+}\n+\n # get_svnprops(PATH)\n # ------------------\n # Helper for cmd_propget and cmd_proplist below.\n@@ -594,12 +614,7 @@ sub get_svnprops {\n \n \t# canonicalize the path (otherwise libsvn will abort or fail to\n \t# find the file)\n-\t# File::Spec->canonpath doesn't collapse x/../y into y (for a\n-\t# good reason), so let's do this manually.\n-\t$path =~ s#/+#/#g;\n-\t$path =~ s#/\\.(?:/|$)#/#g;\n-\t$path =~ s#/[^/]+/\\.\\.##g;\n-\t$path =~ s#/$##g;\n+\t$path = canonicalize_path($path);\n \n \tmy $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);\n \tmy $props;\n@@ -730,6 +745,96 @@ sub cmd_commit_diff {\n \t}\n }\n \n+sub cmd_info {\n+\tmy $path = canonicalize_path(shift or \".\");\n+\tunless (scalar(@_) == 0) {\n+\t\tdie \"Too many arguments specified\\n\";\n+\t}\n+\n+\t# FIXME: We use a combination of git-diff, git-ls-files and git-cat-file\n+\t# to divine the state and type of object that was passed in as $path.\n+\t# There has to be a better way.  Note that only $diffStatus is used\n+\t# beyond setting $isDirectory below.\n+\n+\tmy $diffStatus = (split(' ', command_oneline(qw(diff --cached --name-status --), $path) || \"\"))[0] || \"\";\n+\tmy $lsFiles = command_oneline(qw(ls-files), $path) || \"\";\n+\tif (!$diffStatus && !$lsFiles) {\n+\t\tprint STDERR \"$path:  (Not a versioned resource)\\n\\n\";\n+\t\treturn;\n+\t}\n+\n+\tmy $catFileType = ($path eq \".\" || $diffStatus eq \"A\") ? \"\" : (command_oneline(qw(cat-file -t), \"HEAD:$path\") || \"\");\n+\tmy $isDirectory = (-e $path && ! -f $path && ! -l $path || $diffStatus eq \"D\" && $catFileType eq \"tree\");\n+\n+\tmy $result = \"Path: $path\\n\";\n+\t$result .= \"Name: \" . basename($path) . \"\\n\" if !$isDirectory;\n+\n+\tmy ($url, $rev, $uuid, $gs) = working_head_info('HEAD');\n+\tunless ($gs) {\n+\t\tdie \"Unable to determine upstream SVN information from \",\n+\t\t    \"working tree history\\n\";\n+\t}\n+\t$result .= \"URL: \" . ($url . ($path eq \".\" ? \"\" : \"/$path\")) . \"\\n\";\n+\n+\tmy $repos_root = $gs->ra->{repos_root};\n+\tGit::SVN::remove_username($repos_root);\n+\t$result .= \"Repository Root: $repos_root\\n\";\n+\t$result .= \"Repository UUID: $uuid\\n\" unless $diffStatus eq \"A\";\n+\t$result .= \"Revision: \" . ($diffStatus eq \"A\" ? 0 : $rev) . \"\\n\";\n+\n+\t$result .= \"Node Kind: \" . ($isDirectory ? \"directory\" : \"file\") . \"\\n\";\n+\n+\tmy $schedule = ($diffStatus eq \"A\" ? \"add\" : ($diffStatus eq \"D\" ? \"delete\" : \"normal\"));\n+\t$result .= \"Schedule: $schedule\\n\";\n+\n+\tif ($diffStatus eq \"A\") {\n+\t\tprint $result, \"\\n\";\n+\t\treturn;\n+\t}\n+\n+\tmy ($lc_author, $lc_rev, $lc_date_utc);\n+\tmy @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, \"--\", $path);\n+\tmy $log = command_output_pipe(@args);\n+\tmy $esc_color = qr/(?:\\033\\[(?:(?:\\d+;)*\\d*)?m)*/;\n+\twhile (<$log>) {\n+\t\tif (/^${esc_color}author (.+) <[^>]+> (\\d+) ([\\-\\+]?\\d+)$/o) {\n+\t\t\t$lc_author = $1;\n+\t\t\t$lc_date_utc = Git::SVN::Log::parse_git_date($2, $3);\n+\t\t} elsif (/^${esc_color}    (git-svn-id:.+)$/o) {\n+\t\t\t(undef, $lc_rev, undef) = ::extract_metadata($1);\n+\t\t}\n+\t}\n+\tclose $log;\n+\n+\tGit::SVN::Log::set_local_timezone();\n+\n+\t$result .= \"Last Changed Author: $lc_author\\n\";\n+\t$result .= \"Last Changed Rev: $lc_rev\\n\";\n+\t$result .= \"Last Changed Date: \" . Git::SVN::Log::format_svn_date($lc_date_utc) . \"\\n\";\n+\n+\tif (!$isDirectory) {\n+\t\tmy $textLastUpdatedDate = ($diffStatus eq \"D\" ? $lc_date_utc : (stat $path)[9]);\n+\t\t$result .= \"Text Last Updated: \" . Git::SVN::Log::format_svn_date($textLastUpdatedDate) . \"\\n\";\n+\t\tmy $checksum;\n+\t\t# FIXME: We fail to generate the correct checksum for deleted\n+\t\t# symlinks here.  How do we know if a deleted file was a symlink?\n+\t\tif ($diffStatus eq \"D\") {\n+\t\t\tmy ($fh, $ctx) = command_output_pipe(qw(cat-file blob), \"HEAD:$path\");\n+\t\t\t$checksum = Git::SVN::Util::md5sum($fh);\n+\t\t\tcommand_close_pipe($fh, $ctx);\n+\t\t} elsif (-l $path) {\n+\t\t\t$checksum = Git::SVN::Util::md5sum(\"link \" . command(qw(cat-file blob), \"HEAD:$path\"));\n+\t\t} else {\n+\t\t\topen FILE, \"<\", $path or die $!;\n+\t\t\t$checksum = Git::SVN::Util::md5sum(\\*FILE);\n+\t\t\tclose FILE or die $!;\n+\t\t}\n+\t\t$result .= \"Checksum: \" . $checksum . \"\\n\";\n+\t}\n+\n+\tprint $result, \"\\n\";\n+}\n+\n ########################### utility functions #########################\n \n sub rebase_cmd {\n@@ -1037,6 +1142,27 @@ sub linearize_history {\n \t(\\@linear_refs, \\%parents);\n }\n \n+package Git::SVN::Util;\n+use strict;\n+use warnings;\n+use Digest::MD5;\n+\n+sub md5sum {\n+\tmy $arg = shift;\n+\tmy $ref = ref $arg;\n+\tmy $md5 = Digest::MD5->new();\n+        if ($ref eq 'GLOB' || $ref eq 'IO::File') {\n+\t\t$md5->addfile($arg) or croak $!;\n+\t} elsif ($ref eq 'SCALAR') {\n+\t\t$md5->add($$arg) or croak $!;\n+\t} elsif (!$ref) {\n+\t\t$md5->add($arg) or croak $!;\n+\t} else {\n+\t\t::fatal \"Can't provide MD5 hash for unknown ref type: '\", $ref, \"'\";\n+\t}\n+\treturn $md5->hexdigest();\n+}\n+\n package Git::SVN;\n use strict;\n use warnings;\n@@ -2582,7 +2708,6 @@ use strict;\n use warnings;\n use Carp qw/croak/;\n use IO::File qw//;\n-use Digest::MD5;\n \n # file baton members: path, mode_a, mode_b, pool, fh, blob, base\n sub new {\n@@ -2734,9 +2859,7 @@ sub apply_textdelta {\n \n \t\tif (defined $exp) {\n \t\t\tseek $base, 0, 0 or croak $!;\n-\t\t\tmy $md5 = Digest::MD5->new;\n-\t\t\t$md5->addfile($base);\n-\t\t\tmy $got = $md5->hexdigest;\n+\t\t\tmy $got = Git::SVN::Util::md5sum($base);\n \t\t\tdie \"Checksum mismatch: $fb->{path} $fb->{blob}\\n\",\n \t\t\t    \"expected: $exp\\n\",\n \t\t\t    \"     got: $got\\n\" if ($got ne $exp);\n@@ -2755,9 +2878,7 @@ sub close_file {\n \tif (my $fh = $fb->{fh}) {\n \t\tif (defined $exp) {\n \t\t\tseek($fh, 0, 0) or croak $!;\n-\t\t\tmy $md5 = Digest::MD5->new;\n-\t\t\t$md5->addfile($fh);\n-\t\t\tmy $got = $md5->hexdigest;\n+\t\t\tmy $got = Git::SVN::Util::md5sum($fh);\n \t\t\tif ($got ne $exp) {\n \t\t\t\tdie \"Checksum mismatch: $path\\n\",\n \t\t\t\t    \"expected: $exp\\n    got: $got\\n\";\n@@ -2809,7 +2930,6 @@ use strict;\n use warnings;\n use Carp qw/croak/;\n use IO::File;\n-use Digest::MD5;\n \n sub new {\n \tmy ($class, $opts) = @_;\n@@ -3113,11 +3233,9 @@ sub chg_file {\n \t$fh->flush == 0 or croak $!;\n \tseek $fh, 0, 0 or croak $!;\n \n-\tmy $md5 = Digest::MD5->new;\n-\t$md5->addfile($fh) or croak $!;\n+\tmy $exp = Git::SVN::Util::md5sum($fh);\n \tseek $fh, 0, 0 or croak $!;\n \n-\tmy $exp = $md5->hexdigest;\n \tmy $pool = SVN::Pool->new;\n \tmy $atd = $self->apply_textdelta($fbat, undef, $pool);\n \tmy $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);\n@@ -3810,6 +3928,29 @@ sub run_pager {\n \texec $pager or ::fatal \"Can't run pager: $! ($pager)\";\n }\n \n+sub format_svn_date {\n+\treturn strftime(\"%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)\", localtime(shift));\n+}\n+\n+sub parse_git_date {\n+\tmy ($t, $tz) = @_;\n+\t# Date::Parse isn't in the standard Perl distro :(\n+\tif ($tz =~ s/^\\+//) {\n+\t\t$t += tz_to_s_offset($tz);\n+\t} elsif ($tz =~ s/^\\-//) {\n+\t\t$t -= tz_to_s_offset($tz);\n+\t}\n+\treturn $t;\n+}\n+\n+sub set_local_timezone {\n+\tif (defined $TZ) {\n+\t\t$ENV{TZ} = $TZ;\n+\t} else {\n+\t\tdelete $ENV{TZ};\n+\t}\n+}\n+\n sub tz_to_s_offset {\n \tmy ($tz) = @_;\n \t$tz =~ s/(\\d\\d)$//;\n@@ -3830,13 +3971,7 @@ sub get_author_info {\n \t$dest->{t} = $t;\n \t$dest->{tz} = $tz;\n \t$dest->{a} = $au;\n-\t# Date::Parse isn't in the standard Perl distro :(\n-\tif ($tz =~ s/^\\+//) {\n-\t\t$t += tz_to_s_offset($tz);\n-\t} elsif ($tz =~ s/^\\-//) {\n-\t\t$t -= tz_to_s_offset($tz);\n-\t}\n-\t$dest->{t_utc} = $t;\n+\t$dest->{t_utc} = parse_git_date($t, $tz);\n }\n \n sub process_commit {\n@@ -3890,8 +4025,7 @@ sub show_commit_normal {\n \tmy ($c) = @_;\n \tprint '-' x72, \"\\nr$c->{r} | \";\n \tprint \"$c->{c} | \" if $show_commit;\n-\tprint \"$c->{a} | \", strftime(\"%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)\",\n-\t\t\t\t localtime($c->{t_utc})), ' | ';\n+\tprint \"$c->{a} | \", format_svn_date($c->{t_utc}), ' | ';\n \tmy $nr_line = 0;\n \n \tif (my $l = $c->{l}) {\n@@ -3931,11 +4065,7 @@ sub cmd_show_log {\n \tmy (@args) = @_;\n \tmy ($r_min, $r_max);\n \tmy $r_last = -1; # prevent dupes\n-\tif (defined $TZ) {\n-\t\t$ENV{TZ} = $TZ;\n-\t} else {\n-\t\tdelete $ENV{TZ};\n-\t}\n+\tset_local_timezone();\n \tif (defined $::_revision) {\n \t\tif ($::_revision =~ /^(\\d+):(\\d+)$/) {\n \t\t\t($r_min, $r_max) = ($1, $2);\ndiff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh\nnew file mode 100644\nindex 0000000..b20db04\n--- /dev/null\n+++ b/t/t9117-git-svn-info.sh\n@@ -0,0 +1,236 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2007 David D. Kilzer\n+\n+test_description='git-svn info'\n+\n+. ./lib-git-svn.sh\n+\n+test_expect_success 'setup repository and import' \"\n+\trm -rf info gitwc svnwc &&\n+\tmkdir info &&\n+\tcd info &&\n+\t\techo one > file &&\n+\t\tln -s file symlink-file &&\n+\t\tmkdir directory &&\n+\t\ttouch directory/.placeholder &&\n+\t\tln -s directory symlink-directory &&\n+\t\tsvn import -m 'initial' . $svnrepo &&\n+\tcd .. &&\n+\tmkdir gitwc &&\n+\tcd gitwc &&\n+\t\tgit-svn init $svnrepo &&\n+\t\tgit-svn fetch &&\n+\tcd .. &&\n+\tsvn co $svnrepo svnwc &&\n+\ttouch -c -r svnwc/file gitwc/file &&\n+\ttouch -c -r svnwc/directory gitwc/directory &&\n+\ttouch -c -r svnwc/symlink-file gitwc/symlink-file &&\n+\ttouch -c -r svnwc/symlink-directory gitwc/symlink-directory\n+\t\"\n+\n+test_expect_success 'info no arguments' \"\n+\t(cd svnwc; svn info) > expected.info-no-arguments &&\n+\t(cd gitwc; git-svn info) > actual.info-no-arguments &&\n+\tdiff -u expected.info-no-arguments actual.info-no-arguments\n+\t\"\n+\n+test_expect_success 'info dot' \"\n+\t(cd svnwc; svn info .) > expected.info-dot &&\n+\t(cd gitwc; git-svn info .) > actual.info-dot &&\n+\tdiff -u expected.info-dot actual.info-dot\n+\t\"\n+\n+test_expect_success 'info file' \"\n+\t(cd svnwc; svn info file) > expected.info-file &&\n+\t(cd gitwc; git-svn info file) > actual.info-file &&\n+\tdiff -u expected.info-file actual.info-file\n+\t\"\n+\n+test_expect_success 'info directory' \"\n+\t(cd svnwc; svn info directory) > expected.info-directory &&\n+\t(cd gitwc; git-svn info directory) > actual.info-directory &&\n+\tdiff -u expected.info-directory actual.info-directory\n+\t\"\n+\n+test_expect_success 'info symlink-file' \"\n+\t(cd svnwc; svn info symlink-file) > expected.info-symlink-file &&\n+\t(cd gitwc; git-svn info symlink-file) > actual.info-symlink-file &&\n+\tdiff -u expected.info-symlink-file actual.info-symlink-file\n+\t\"\n+\n+test_expect_success 'info symlink-directory' \"\n+\t(cd svnwc; svn info symlink-directory) > expected.info-symlink-directory &&\n+\t(cd gitwc; git-svn info symlink-directory) > actual.info-symlink-directory &&\n+\tdiff -u expected.info-symlink-directory actual.info-symlink-directory\n+\t\"\n+\n+test_expect_success 'info added-file' \"\n+\techo two > gitwc/added-file &&\n+\tcd gitwc &&\n+\t\tgit add added-file &&\n+\tcd .. &&\n+\tcp -p gitwc/added-file svnwc/added-file &&\n+\ttouch -r gitwc/added-file svnwc/added-file &&\n+\tcd svnwc &&\n+\t\tsvn add added-file > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info added-file) > expected.info-added-file &&\n+\t(cd gitwc; git-svn info added-file) > actual.info-added-file &&\n+\tdiff -u expected.info-added-file actual.info-added-file\n+\t\"\n+\n+test_expect_success 'info added-directory' \"\n+\tmkdir gitwc/added-directory svnwc/added-directory &&\n+\ttouch -r gitwc/added-directory svnwc/added-directory &&\n+        touch gitwc/added-directory/.placeholder &&\n+\tcd svnwc &&\n+\t\tsvn add added-directory > /dev/null &&\n+\tcd .. &&\n+\tcd gitwc &&\n+\t\tgit add added-directory &&\n+\tcd .. &&\n+\t(cd svnwc; svn info added-directory) > expected.info-added-directory &&\n+\t(cd gitwc; git-svn info added-directory) > actual.info-added-directory &&\n+\tdiff -u expected.info-added-directory actual.info-added-directory\n+\t\"\n+\n+test_expect_success 'info added-symlink-file' \"\n+\tcd gitwc &&\n+\t\tln -s added-file added-symlink-file &&\n+\t\tgit add added-symlink-file &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tln -s added-file added-symlink-file &&\n+\t\tsvn add added-symlink-file > /dev/null &&\n+\tcd .. &&\n+\ttouch -r gitwc/added-symlink-file svnwc/added-symlink-file &&\n+\t(cd svnwc; svn info added-symlink-file) > expected.info-added-symlink-file &&\n+\t(cd gitwc; git-svn info added-symlink-file) > actual.info-added-symlink-file &&\n+\tdiff -u expected.info-added-symlink-file actual.info-added-symlink-file\n+\t\"\n+\n+test_expect_success 'info added-symlink-directory' \"\n+\tcd gitwc &&\n+\t\tln -s added-directory added-symlink-directory &&\n+\t\tgit add added-symlink-directory &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tln -s added-directory added-symlink-directory &&\n+\t\tsvn add added-symlink-directory > /dev/null &&\n+\tcd .. &&\n+\ttouch -r gitwc/added-symlink-directory svnwc/added-symlink-directory &&\n+\t(cd svnwc; svn info added-symlink-directory) > expected.info-added-symlink-directory &&\n+\t(cd gitwc; git-svn info added-symlink-directory) > actual.info-added-symlink-directory &&\n+\tdiff -u expected.info-added-symlink-directory actual.info-added-symlink-directory\n+\t\"\n+\n+replace_Text_Last_Updated_date () {\n+\tREPLACEMENT=`cat $1 | grep '^Last Changed Date:' | sed -e 's/Last Changed Date/Text Last Updated/'` &&\n+\tcat $1 | sed -e \"s/^Text Last Updated: .*\\$/${REPLACEMENT}/\" > $1.$$ &&\n+\tmv -f $1.$$ $1\n+}\n+\n+test_expect_success 'info deleted-file' \"\n+\tcd gitwc &&\n+\t\tgit rm -f file > /dev/null &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tsvn rm --force file > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info file) > expected.info-deleted-file &&\n+\t(cd gitwc; git-svn info file) > actual.info-deleted-file &&\n+\treplace_Text_Last_Updated_date expected.info-deleted-file &&\n+\tdiff -u expected.info-deleted-file actual.info-deleted-file\n+\t\"\n+\n+test_expect_success 'info deleted-directory' \"\n+\tcd gitwc &&\n+\t\tgit rm -r -f directory > /dev/null &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tsvn rm --force directory > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info directory) > expected.info-deleted-directory &&\n+\t(cd gitwc; git-svn info directory) > actual.info-deleted-directory &&\n+\treplace_Text_Last_Updated_date expected.info-deleted-directory &&\n+\tdiff -u expected.info-deleted-directory actual.info-deleted-directory\n+\t\"\n+\n+test_expect_success 'info deleted-symlink-file' \"\n+\tcd gitwc &&\n+\t\tgit rm -f symlink-file > /dev/null &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tsvn rm --force symlink-file > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info symlink-file) > expected.info-deleted-symlink-file &&\n+\t(cd gitwc; git-svn info symlink-file) > actual.info-deleted-symlink-file &&\n+\treplace_Text_Last_Updated_date expected.info-deleted-symlink-file &&\n+\tdiff -u expected.info-deleted-symlink-file actual.info-deleted-symlink-file\n+\t\"\n+\n+test_expect_success 'info deleted-symlink-directory' \"\n+\tcd gitwc &&\n+\t\tgit rm -f symlink-directory > /dev/null &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tsvn rm --force symlink-directory > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info symlink-directory) > expected.info-deleted-symlink-directory &&\n+\t(cd gitwc; git-svn info symlink-directory) > actual.info-deleted-symlink-directory &&\n+\treplace_Text_Last_Updated_date expected.info-deleted-symlink-directory &&\n+\tdiff -u expected.info-deleted-symlink-directory actual.info-deleted-symlink-directory\n+\t\"\n+\n+# NOTE: git does not have the concept of replaced objects, so we can't test for them.\n+#test_expect_success 'info replaced-file' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-directory' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-symlink-file' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-symlink-directory' \"/usr/bin/true\"\n+\n+test_expect_success 'info unknown-file' \"\n+\techo two > gitwc/unknown-file &&\n+\tcp -p gitwc/unknown-file svnwc/unknown-file &&\n+\ttouch -r gitwc/unknown-file svnwc/unknown-file &&\n+\t(cd svnwc; svn info unknown-file) 2> expected.info-unknown-file &&\n+\t(cd gitwc; git-svn info unknown-file) 2> actual.info-unknown-file &&\n+\tdiff -u expected.info-unknown-file actual.info-unknown-file\n+\t\"\n+\n+test_expect_success 'info unknown-directory' \"\n+\tmkdir gitwc/unknown-directory svnwc/unknown-directory &&\n+\ttouch -r gitwc/unknown-directory svnwc/unknown-directory &&\n+        touch gitwc/unknown-directory/.placeholder &&\n+\t(cd svnwc; svn info unknown-directory) 2> expected.info-unknown-directory &&\n+\t(cd gitwc; git-svn info unknown-directory) 2> actual.info-unknown-directory &&\n+\tdiff -u expected.info-unknown-directory actual.info-unknown-directory\n+\t\"\n+\n+test_expect_success 'info unknown-symlink-file' \"\n+\tcd gitwc &&\n+\t\tln -s unknown-file unknown-symlink-file &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tln -s unknown-file unknown-symlink-file &&\n+\tcd .. &&\n+\ttouch -r gitwc/unknown-symlink-file svnwc/unknown-symlink-file &&\n+\t(cd svnwc; svn info unknown-symlink-file) 2> expected.info-unknown-symlink-file &&\n+\t(cd gitwc; git-svn info unknown-symlink-file) 2> actual.info-unknown-symlink-file &&\n+\tdiff -u expected.info-unknown-symlink-file actual.info-unknown-symlink-file\n+\t\"\n+\n+test_expect_success 'info unknown-symlink-directory' \"\n+\tcd gitwc &&\n+\t\tln -s unknown-directory unknown-symlink-directory &&\n+\tcd .. &&\n+\tcd svnwc &&\n+\t\tln -s unknown-directory unknown-symlink-directory &&\n+\tcd .. &&\n+\ttouch -r gitwc/unknown-symlink-directory svnwc/unknown-symlink-directory &&\n+\t(cd svnwc; svn info unknown-symlink-directory) 2> expected.info-unknown-symlink-directory &&\n+\t(cd gitwc; git-svn info unknown-symlink-directory) 2> actual.info-unknown-symlink-directory &&\n+\tdiff -u expected.info-unknown-symlink-directory actual.info-unknown-symlink-directory\n+\t\"\n+\n+test_done\n-- \n1.5.3.4\n"},{"id":"60180","messageId":"20071117225402.GC28755@muzzle","threadId":"10834","inReplyTo":"1194884349-11504-1-git-send-email-ddkilzer@kilzer.net","subject":"Re: [RFC PATCH] git-svn info: implement info command","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-11-17T22:54:02Z","receivedAt":"2007-11-17T22:54:02Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"\"David D. Kilzer\" <ddkilzer@kilzer.net> wrote:\n> Implement \"git-svn info\" for files and directories based on the \"svn info\"\n> command.  Note that the -r/--revision argument is not supported yet.\n> \n> Added 18 tests in t/t9117-git-svn-info.sh.\n> \n> Signed-off-by: David D. Kilzer <ddkilzer@kilzer.net>\n> ---\n> \n> Looking for feedback on this patch.  Specifically, I'm looking for insight\n> for the two FIXME comments in the cmd_info() function added to git-svn.\n> (I can't help but think I'm missing a plumbing command or a basic concept.\n> Pointers to code, web pages or man pages are welcome.)\n> \n> Note that I've tried to cover all the bases that \"svn info\" does (by using\n> tests), except supporting the -r/--revision argument.\n\nHi David,\n\nWow.  I can honestly say I've never even noticed the \"Schedule:\" field\nin `svn info'.  I would've been perfectly happy to accept an\nimplementation of `git svn info' without that :)\n\n> I've also tried to be aggressive in extracting common code into functions.\n\nI like it, but this should be a separate patch.\n\n> +sub canonicalize_path {\n> +\tmy ($path) = @_;\n> +\tmy $dotSlashAdded = 0;\n\ncamelCase variables requires more time for the brain to parse (they're\neasier to write, but take more time to read), please use snake_case like\nthe rest of git-svn (and git).\n\n> +sub cmd_info {\n> +\tmy $path = canonicalize_path(shift or \".\");\n> +\tunless (scalar(@_) == 0) {\n> +\t\tdie \"Too many arguments specified\\n\";\n> +\t}\n> +\n> +\t# FIXME: We use a combination of git-diff, git-ls-files and git-cat-file\n> +\t# to divine the state and type of object that was passed in as $path.\n> +\t# There has to be a better way.  Note that only $diffStatus is used\n> +\t# beyond setting $isDirectory below.\n\nI agree it's pretty ugly.  You can probably expand git-runstatus to do\nthis.  git-commit.sh used to use something like this until git-runstatus\nwas added.  On the other hand, I'd be content if we dropped support\nfor this info entirely since `git-status' is perfectly good.\n\nIMNSHO, \"URL:\" and \"Repository Root:\" and occasionally \"Revision:\" (on the\ntop-level directory) would be the only useful things this command would\nhave to offer.\n\nBeing able to run something like `git svn info --url <path>'\nto get something like http://svn.foo.org/project/trunk/<path> would be\nnice, too.\n\n> +\n> +\tmy $diffStatus = (split(' ', command_oneline(qw(diff --cached --name-status --), $path) || \"\"))[0] || \"\";\n\nPlease wrap lines at 80 characters.  I have a hard time following long\nlines.\n\n> +\t\tmy $checksum;\n> +\t\t# FIXME: We fail to generate the correct checksum for deleted\n> +\t\t# symlinks here.  How do we know if a deleted file was a symlin\n\ngit ls-tree HEAD <filename> will show the mode of a deleted file\n\n> @@ -0,0 +1,236 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2007 David D. Kilzer\n> +\n> +test_description='git-svn info'\n> +\n> +. ./lib-git-svn.sh\n> +\n> +test_expect_success 'setup repository and import' \"\n> +\trm -rf info gitwc svnwc &&\n\nAll git tests should start you off on a clean trash/ directory...\n\n> +\tmkdir info &&\n> +\tcd info &&\n> +\t\techo one > file &&\n> +\t\tln -s file symlink-file &&\n> +\t\tmkdir directory &&\n> +\t\ttouch directory/.placeholder &&\n> +\t\tln -s directory symlink-directory &&\n> +\t\tsvn import -m 'initial' . $svnrepo &&\n> +\tcd .. &&\n> +\tmkdir gitwc &&\n> +\tcd gitwc &&\n> +\t\tgit-svn init $svnrepo &&\n> +\t\tgit-svn fetch &&\n> +\tcd .. &&\n> +\tsvn co $svnrepo svnwc &&\n> +\ttouch -c -r svnwc/file gitwc/file &&\n> +\ttouch -c -r svnwc/directory gitwc/directory &&\n> +\ttouch -c -r svnwc/symlink-file gitwc/symlink-file &&\n> +\ttouch -c -r svnwc/symlink-directory gitwc/symlink-directory\n\nAre -r and -c portable?  I remember writing test-chmtime to workaround\nsome arguments for touch not being portable.\n\n> +test_expect_success 'info no arguments' \"\n> +\t(cd svnwc; svn info) > expected.info-no-arguments &&\n> +\t(cd gitwc; git-svn info) > actual.info-no-arguments &&\n> +\tdiff -u expected.info-no-arguments actual.info-no-arguments\n> +\t\"\n\nCan we expect the output of \"svn info\" to not change between\nversions?  I know \"svn status\" has changed between versions of\nsvn.  I'd prefer if we keep the expected.* files hard-coded\nin a test directory and compare those instead.  Maybe use sed\nto substitute placeholders for timestamps..\n\nAlso, git-diff can be used against arbitrary files nowadays, no\nneed to rely on a working diff command in the system :)\n\n> +test_expect_success 'info added-file' \"\n> +\techo two > gitwc/added-file &&\n> +\tcd gitwc &&\n> +\t\tgit add added-file &&\n> +\tcd .. &&\n> +\tcp -p gitwc/added-file svnwc/added-file &&\n\nI can't remember if cp -p is portable, either...\n\n-- \nEric Wong\n"},{"id":"60459","messageId":"1195627399-25209-1-git-send-email-ddkilzer@kilzer.net","threadId":"10834","inReplyTo":"20071117225402.GC28755@muzzle","subject":"[PATCH 0/3] Implement git-svn: info","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2007-11-21T06:43:16Z","receivedAt":"2007-11-21T06:43:16Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"I've split the original RFC patch into two patches (one for the\nrefactoring changes, and one for implementing the \"git svn info\"\ncommand), and added a third to imlement \"git svn info --url\" per\nEric's request.\n\nEric Wong <normalperson@yhbt.net> wrote:\n> \"David D. Kilzer\" <ddkilzer@kilzer.net> wrote:\n> > Implement \"git-svn info\" for files and directories based on the \"svn info\"\n> > command.  Note that the -r/--revision argument is not supported yet.\n> [...]\n> Wow.  I can honestly say I've never even noticed the \"Schedule:\" field\n> in `svn info'.  I would've been perfectly happy to accept an\n> implementation of `git svn info' without that :)\n\nI never noticed it, either, until I went to implement this feature!\nMy goal is to stay as true to the \"svn info\" output as \"git svn log\"\nhas done for \"svn log\".\n\n> > I've also tried to be aggressive in extracting common code into functions.\n> I like it, but this should be a separate patch.\n\nSee Patch 1/3.\n\n> camelCase variables requires more time for the brain to parse (they're\n> easier to write, but take more time to read), please use snake_case like\n> the rest of git-svn (and git).\n\nI've switched all variables from camelCase to snake_case.  Sorry...old\nhabit.\n\n> > +\t# FIXME: We use a combination of git-diff, git-ls-files and git-cat-file\n> > +\t# to divine the state and type of object that was passed in as $path.\n> > +\t# There has to be a better way.  Note that only $diffStatus is used\n> > +\t# beyond setting $isDirectory below.\n> \n> I agree it's pretty ugly.  You can probably expand git-runstatus to do\n> this.  git-commit.sh used to use something like this until git-runstatus\n> was added.  On the other hand, I'd be content if we dropped support\n> for this info entirely since `git-status' is perfectly good.\n\nI thought I saw a patch on the mailing list to remove git-runstatus\nafter rewriting git-status in C.  Because of that, I extracted this\ncode into a find_file_type_and_diff_status() function in Patch 2/3.\nThe logic in the function is much easier to follow now, and this also\nresulted in cleaning up the cmd_info() function.\n\n> IMNSHO, \"URL:\" and \"Repository Root:\" and occasionally \"Revision:\" (on the\n> top-level directory) would be the only useful things this command would\n> have to offer.\n\nSee above about emulating \"svn info\" as closely as possible.\n\n> Being able to run something like `git svn info --url <path>'\n> to get something like http://svn.foo.org/project/trunk/<path> would be\n> nice, too.\n\nSee Patch 3/3.\n\n> Please wrap lines at 80 characters.  I have a hard time following long\n> lines.\n\nEverything has been rewrapped for 80 columns.\n\n> git ls-tree HEAD <filename> will show the mode of a deleted file\n\nThanks, used this with success in find_file_type_and_diff_status().\n\n> > +\trm -rf info gitwc svnwc &&\n> All git tests should start you off on a clean trash/ directory...\n\nRemoved.\n\n> > +\ttouch -c -r svnwc/symlink-directory gitwc/symlink-directory\n> Are -r and -c portable?  I remember writing test-chmtime to workaround\n> some arguments for touch not being portable.\n\nThe touch and cp commands were removed after restructuring the\nt/t9117-git-svn-info.sh script to use static expected-* files and\nreplacing command output using sed.\n\n> Can we expect the output of \"svn info\" to not change between\n> versions?  I know \"svn status\" has changed between versions of\n> svn.  I'd prefer if we keep the expected.* files hard-coded\n> in a test directory and compare those instead.  Maybe use sed\n> to substitute placeholders for timestamps..\n\nDone.\n\n> Also, git-diff can be used against arbitrary files nowadays, no\n> need to rely on a working diff command in the system :)\n\nDone.\n\n> > +\tcp -p gitwc/added-file svnwc/added-file &&\n> I can't remember if cp -p is portable, either...\n\nFixed (see above).\n\nDave\n"},{"id":"60458","messageId":"1195627399-25209-2-git-send-email-ddkilzer@kilzer.net","threadId":"10834","inReplyTo":"1195627399-25209-1-git-send-email-ddkilzer@kilzer.net","subject":"[PATCH 1/3] git-svn: extract reusable code into utility functions","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2007-11-21T06:43:17Z","receivedAt":"2007-11-21T06:43:17Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"Extacted canonicalize_path() in the main package.\n\nCreated new Git::SVN::Util package with an md5sum() function.  A\nnew package was created so that Digest::MD5 did not have to be\nloaded in the main package.  Replaced code in the SVN::Git::Editor\nand SVN::Git::Fetcher packages with calls to md5sum().\n\nExtracted the format_svn_date(), parse_git_date() and\nset_local_timezone() functions within the Git::SVN::Log package.\n\nSigned-off-by: David D. Kilzer <ddkilzer@kilzer.net>\n---\n git-svn.perl |   96 ++++++++++++++++++++++++++++++++++++++-------------------\n 1 files changed, 64 insertions(+), 32 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex e3e00fd..aff429a 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -48,7 +48,8 @@ BEGIN {\n \tforeach (qw/command command_oneline command_noisy command_output_pipe\n \t            command_input_pipe command_close_pipe/) {\n \t\tfor my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher\n-\t\t\tGit::SVN::Migration Git::SVN::Log Git::SVN),\n+\t\t\tGit::SVN::Migration Git::SVN::Log Git::SVN\n+\t\t\tGit::SVN::Util),\n \t\t\t__PACKAGE__) {\n \t\t\t*{\"${package}::$_\"} = \\&{\"Git::$_\"};\n \t\t}\n@@ -580,6 +581,17 @@ sub cmd_create_ignore {\n \t});\n }\n \n+sub canonicalize_path {\n+\tmy ($path) = @_;\n+\t# File::Spec->canonpath doesn't collapse x/../y into y (for a\n+\t# good reason), so let's do this manually.\n+\t$path =~ s#/+#/#g;\n+\t$path =~ s#/\\.(?:/|$)#/#g;\n+\t$path =~ s#/[^/]+/\\.\\.##g;\n+\t$path =~ s#/$##g;\n+\treturn $path;\n+}\n+\n # get_svnprops(PATH)\n # ------------------\n # Helper for cmd_propget and cmd_proplist below.\n@@ -597,12 +609,7 @@ sub get_svnprops {\n \n \t# canonicalize the path (otherwise libsvn will abort or fail to\n \t# find the file)\n-\t# File::Spec->canonpath doesn't collapse x/../y into y (for a\n-\t# good reason), so let's do this manually.\n-\t$path =~ s#/+#/#g;\n-\t$path =~ s#/\\.(?:/|$)#/#g;\n-\t$path =~ s#/[^/]+/\\.\\.##g;\n-\t$path =~ s#/$##g;\n+\t$path = canonicalize_path($path);\n \n \tmy $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);\n \tmy $props;\n@@ -1040,6 +1047,27 @@ sub linearize_history {\n \t(\\@linear_refs, \\%parents);\n }\n \n+package Git::SVN::Util;\n+use strict;\n+use warnings;\n+use Digest::MD5;\n+\n+sub md5sum {\n+\tmy $arg = shift;\n+\tmy $ref = ref $arg;\n+\tmy $md5 = Digest::MD5->new();\n+        if ($ref eq 'GLOB' || $ref eq 'IO::File') {\n+\t\t$md5->addfile($arg) or croak $!;\n+\t} elsif ($ref eq 'SCALAR') {\n+\t\t$md5->add($$arg) or croak $!;\n+\t} elsif (!$ref) {\n+\t\t$md5->add($arg) or croak $!;\n+\t} else {\n+\t\t::fatal \"Can't provide MD5 hash for unknown ref type: '\", $ref, \"'\";\n+\t}\n+\treturn $md5->hexdigest();\n+}\n+\n package Git::SVN;\n use strict;\n use warnings;\n@@ -2585,7 +2613,6 @@ use strict;\n use warnings;\n use Carp qw/croak/;\n use IO::File qw//;\n-use Digest::MD5;\n \n # file baton members: path, mode_a, mode_b, pool, fh, blob, base\n sub new {\n@@ -2737,9 +2764,7 @@ sub apply_textdelta {\n \n \t\tif (defined $exp) {\n \t\t\tseek $base, 0, 0 or croak $!;\n-\t\t\tmy $md5 = Digest::MD5->new;\n-\t\t\t$md5->addfile($base);\n-\t\t\tmy $got = $md5->hexdigest;\n+\t\t\tmy $got = Git::SVN::Util::md5sum($base);\n \t\t\tdie \"Checksum mismatch: $fb->{path} $fb->{blob}\\n\",\n \t\t\t    \"expected: $exp\\n\",\n \t\t\t    \"     got: $got\\n\" if ($got ne $exp);\n@@ -2758,9 +2783,7 @@ sub close_file {\n \tif (my $fh = $fb->{fh}) {\n \t\tif (defined $exp) {\n \t\t\tseek($fh, 0, 0) or croak $!;\n-\t\t\tmy $md5 = Digest::MD5->new;\n-\t\t\t$md5->addfile($fh);\n-\t\t\tmy $got = $md5->hexdigest;\n+\t\t\tmy $got = Git::SVN::Util::md5sum($fh);\n \t\t\tif ($got ne $exp) {\n \t\t\t\tdie \"Checksum mismatch: $path\\n\",\n \t\t\t\t    \"expected: $exp\\n    got: $got\\n\";\n@@ -2812,7 +2835,6 @@ use strict;\n use warnings;\n use Carp qw/croak/;\n use IO::File;\n-use Digest::MD5;\n \n sub new {\n \tmy ($class, $opts) = @_;\n@@ -3116,11 +3138,9 @@ sub chg_file {\n \t$fh->flush == 0 or croak $!;\n \tseek $fh, 0, 0 or croak $!;\n \n-\tmy $md5 = Digest::MD5->new;\n-\t$md5->addfile($fh) or croak $!;\n+\tmy $exp = Git::SVN::Util::md5sum($fh);\n \tseek $fh, 0, 0 or croak $!;\n \n-\tmy $exp = $md5->hexdigest;\n \tmy $pool = SVN::Pool->new;\n \tmy $atd = $self->apply_textdelta($fbat, undef, $pool);\n \tmy $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);\n@@ -3833,6 +3853,29 @@ sub run_pager {\n \texec $pager or ::fatal \"Can't run pager: $! ($pager)\";\n }\n \n+sub format_svn_date {\n+\treturn strftime(\"%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)\", localtime(shift));\n+}\n+\n+sub parse_git_date {\n+\tmy ($t, $tz) = @_;\n+\t# Date::Parse isn't in the standard Perl distro :(\n+\tif ($tz =~ s/^\\+//) {\n+\t\t$t += tz_to_s_offset($tz);\n+\t} elsif ($tz =~ s/^\\-//) {\n+\t\t$t -= tz_to_s_offset($tz);\n+\t}\n+\treturn $t;\n+}\n+\n+sub set_local_timezone {\n+\tif (defined $TZ) {\n+\t\t$ENV{TZ} = $TZ;\n+\t} else {\n+\t\tdelete $ENV{TZ};\n+\t}\n+}\n+\n sub tz_to_s_offset {\n \tmy ($tz) = @_;\n \t$tz =~ s/(\\d\\d)$//;\n@@ -3853,13 +3896,7 @@ sub get_author_info {\n \t$dest->{t} = $t;\n \t$dest->{tz} = $tz;\n \t$dest->{a} = $au;\n-\t# Date::Parse isn't in the standard Perl distro :(\n-\tif ($tz =~ s/^\\+//) {\n-\t\t$t += tz_to_s_offset($tz);\n-\t} elsif ($tz =~ s/^\\-//) {\n-\t\t$t -= tz_to_s_offset($tz);\n-\t}\n-\t$dest->{t_utc} = $t;\n+\t$dest->{t_utc} = parse_git_date($t, $tz);\n }\n \n sub process_commit {\n@@ -3913,8 +3950,7 @@ sub show_commit_normal {\n \tmy ($c) = @_;\n \tprint '-' x72, \"\\nr$c->{r} | \";\n \tprint \"$c->{c} | \" if $show_commit;\n-\tprint \"$c->{a} | \", strftime(\"%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)\",\n-\t\t\t\t localtime($c->{t_utc})), ' | ';\n+\tprint \"$c->{a} | \", format_svn_date($c->{t_utc}), ' | ';\n \tmy $nr_line = 0;\n \n \tif (my $l = $c->{l}) {\n@@ -3954,11 +3990,7 @@ sub cmd_show_log {\n \tmy (@args) = @_;\n \tmy ($r_min, $r_max);\n \tmy $r_last = -1; # prevent dupes\n-\tif (defined $TZ) {\n-\t\t$ENV{TZ} = $TZ;\n-\t} else {\n-\t\tdelete $ENV{TZ};\n-\t}\n+\tset_local_timezone();\n \tif (defined $::_revision) {\n \t\tif ($::_revision =~ /^(\\d+):(\\d+)$/) {\n \t\t\t($r_min, $r_max) = ($1, $2);\n-- \n1.5.3.4\n"},{"id":"60460","messageId":"1195627399-25209-3-git-send-email-ddkilzer@kilzer.net","threadId":"10834","inReplyTo":"1195627399-25209-2-git-send-email-ddkilzer@kilzer.net","subject":"[PATCH 2/3] git-svn info: implement info command","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2007-11-21T06:43:18Z","receivedAt":"2007-11-21T06:43:18Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"Implement \"git-svn info\" for files and directories based on the\n\"svn info\" command.  Note that the -r/--revision argument is not\nsupported yet.\n\nAdded 18 tests in t/t9117-git-svn-info.sh.\n\nSigned-off-by: David D. Kilzer <ddkilzer@kilzer.net>\n---\n Documentation/git-svn.txt                       |    5 +\n git-svn.perl                                    |  132 ++++++++++++++++\n t/t9117-git-svn-info.sh                         |  186 +++++++++++++++++++++++\n t/t9117/expected.info-added-directory           |    7 +\n t/t9117/expected.info-added-file                |    8 +\n t/t9117/expected.info-added-symlink-directory   |    8 +\n t/t9117/expected.info-added-symlink-file        |    8 +\n t/t9117/expected.info-deleted-directory         |   11 ++\n t/t9117/expected.info-deleted-file              |   14 ++\n t/t9117/expected.info-deleted-symlink-directory |   14 ++\n t/t9117/expected.info-deleted-symlink-file      |   14 ++\n t/t9117/expected.info-directory                 |   11 ++\n t/t9117/expected.info-dot                       |   11 ++\n t/t9117/expected.info-file                      |   14 ++\n t/t9117/expected.info-no-arguments              |   11 ++\n t/t9117/expected.info-symlink-directory         |   14 ++\n t/t9117/expected.info-symlink-file              |   14 ++\n t/t9117/expected.info-unknown-directory         |    2 +\n t/t9117/expected.info-unknown-file              |    2 +\n t/t9117/expected.info-unknown-symlink-directory |    2 +\n t/t9117/expected.info-unknown-symlink-file      |    2 +\n t/t9117/regenerate.sh                           |  186 +++++++++++++++++++++++\n 22 files changed, 676 insertions(+), 0 deletions(-)\n create mode 100644 t/t9117-git-svn-info.sh\n create mode 100644 t/t9117/expected.info-added-directory\n create mode 100644 t/t9117/expected.info-added-file\n create mode 100644 t/t9117/expected.info-added-symlink-directory\n create mode 100644 t/t9117/expected.info-added-symlink-file\n create mode 100644 t/t9117/expected.info-deleted-directory\n create mode 100644 t/t9117/expected.info-deleted-file\n create mode 100644 t/t9117/expected.info-deleted-symlink-directory\n create mode 100644 t/t9117/expected.info-deleted-symlink-file\n create mode 100644 t/t9117/expected.info-directory\n create mode 100644 t/t9117/expected.info-dot\n create mode 100644 t/t9117/expected.info-file\n create mode 100644 t/t9117/expected.info-no-arguments\n create mode 100644 t/t9117/expected.info-symlink-directory\n create mode 100644 t/t9117/expected.info-symlink-file\n create mode 100644 t/t9117/expected.info-unknown-directory\n create mode 100644 t/t9117/expected.info-unknown-file\n create mode 100644 t/t9117/expected.info-unknown-symlink-directory\n create mode 100644 t/t9117/expected.info-unknown-symlink-file\n create mode 100755 t/t9117/regenerate.sh\n\ndiff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt\nindex 488e4b1..c3fc878 100644\n--- a/Documentation/git-svn.txt\n+++ b/Documentation/git-svn.txt\n@@ -193,6 +193,11 @@ Any other arguments are passed directly to `git log'\n \trepository (that has been init-ed with git-svn).\n \tThe -r<revision> option is required for this.\n \n+'info'::\n+\tShows information about a file or directory similar to what\n+\t`svn info' provides.  Does not currently support a -r/--revision\n+\targument.\n+\n --\n \n OPTIONS\ndiff --git a/git-svn.perl b/git-svn.perl\nindex aff429a..406ee6f 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -178,6 +178,10 @@ my %cmd = (\n \t\t\t  'file|F=s' => \\$_file,\n \t\t\t  'revision|r=s' => \\$_revision,\n \t\t\t%cmt_opts } ],\n+\t'info' => [ \\&cmd_info,\n+\t\t    \"Show info about the latest SVN revision\n+\t\t     on the current branch\",\n+\t\t    { } ],\n );\n \n my $cmd;\n@@ -583,12 +587,18 @@ sub cmd_create_ignore {\n \n sub canonicalize_path {\n \tmy ($path) = @_;\n+\tmy $dot_slash_added = 0;\n+\tif (substr($path, 0, 1) ne \"/\") {\n+\t\t$path = \"./\" . $path;\n+\t\t$dot_slash_added = 1;\n+\t}\n \t# File::Spec->canonpath doesn't collapse x/../y into y (for a\n \t# good reason), so let's do this manually.\n \t$path =~ s#/+#/#g;\n \t$path =~ s#/\\.(?:/|$)#/#g;\n \t$path =~ s#/[^/]+/\\.\\.##g;\n \t$path =~ s#/$##g;\n+\t$path =~ s#^\\./## if $dot_slash_added;\n \treturn $path;\n }\n \n@@ -740,6 +750,104 @@ sub cmd_commit_diff {\n \t}\n }\n \n+sub cmd_info {\n+\tmy $path = canonicalize_path(shift or \".\");\n+\tunless (scalar(@_) == 0) {\n+\t\tdie \"Too many arguments specified\\n\";\n+\t}\n+\n+\tmy ($file_type, $diff_status) = find_file_type_and_diff_status($path);\n+\n+\tif (!$file_type && !$diff_status) {\n+\t\tprint STDERR \"$path:  (Not a versioned resource)\\n\\n\";\n+\t\treturn;\n+\t}\n+\n+\tmy ($url, $rev, $uuid, $gs) = working_head_info('HEAD');\n+\tunless ($gs) {\n+\t\tdie \"Unable to determine upstream SVN information from \",\n+\t\t    \"working tree history\\n\";\n+\t}\n+\tmy $full_url = $url . ($path eq \".\" ? \"\" : \"/$path\");\n+\n+\tmy $result = \"Path: $path\\n\";\n+\t$result .= \"Name: \" . basename($path) . \"\\n\" if $file_type ne \"dir\";\n+\t$result .= \"URL: \" . $full_url . \"\\n\";\n+\n+\tmy $repos_root = $gs->ra->{repos_root};\n+\tGit::SVN::remove_username($repos_root);\n+\t$result .= \"Repository Root: $repos_root\\n\";\n+\t$result .= \"Repository UUID: $uuid\\n\" unless $diff_status eq \"A\";\n+\t$result .= \"Revision: \" . ($diff_status eq \"A\" ? 0 : $rev) . \"\\n\";\n+\n+\t$result .= \"Node Kind: \" .\n+\t\t   ($file_type eq \"dir\" ? \"directory\" : \"file\") . \"\\n\";\n+\n+\tmy $schedule = $diff_status eq \"A\"\n+\t\t       ? \"add\"\n+\t\t       : ($diff_status eq \"D\" ? \"delete\" : \"normal\");\n+\t$result .= \"Schedule: $schedule\\n\";\n+\n+\tif ($diff_status eq \"A\") {\n+\t\tprint $result, \"\\n\";\n+\t\treturn;\n+\t}\n+\n+\tmy ($lc_author, $lc_rev, $lc_date_utc);\n+\tmy @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, \"--\", $path);\n+\tmy $log = command_output_pipe(@args);\n+\tmy $esc_color = qr/(?:\\033\\[(?:(?:\\d+;)*\\d*)?m)*/;\n+\twhile (<$log>) {\n+\t\tif (/^${esc_color}author (.+) <[^>]+> (\\d+) ([\\-\\+]?\\d+)$/o) {\n+\t\t\t$lc_author = $1;\n+\t\t\t$lc_date_utc = Git::SVN::Log::parse_git_date($2, $3);\n+\t\t} elsif (/^${esc_color}    (git-svn-id:.+)$/o) {\n+\t\t\t(undef, $lc_rev, undef) = ::extract_metadata($1);\n+\t\t}\n+\t}\n+\tclose $log;\n+\n+\tGit::SVN::Log::set_local_timezone();\n+\n+\t$result .= \"Last Changed Author: $lc_author\\n\";\n+\t$result .= \"Last Changed Rev: $lc_rev\\n\";\n+\t$result .= \"Last Changed Date: \" .\n+\t\t   Git::SVN::Log::format_svn_date($lc_date_utc) . \"\\n\";\n+\n+\tif ($file_type ne \"dir\") {\n+\t\tmy $text_last_updated_date =\n+\t\t    ($diff_status eq \"D\" ? $lc_date_utc : (stat $path)[9]);\n+\t\t$result .=\n+\t\t    \"Text Last Updated: \" .\n+\t\t    Git::SVN::Log::format_svn_date($text_last_updated_date) .\n+\t\t    \"\\n\";\n+\t\tmy $checksum;\n+\t\tif ($diff_status eq \"D\") {\n+\t\t\tmy ($fh, $ctx) =\n+\t\t\t    command_output_pipe(qw(cat-file blob), \"HEAD:$path\");\n+\t\t\tif ($file_type eq \"link\") {\n+\t\t\t\tmy $file_name = <$fh>;\n+\t\t\t\t$checksum = Git::SVN::Util::md5sum(\"link $file_name\");\n+\t\t\t} else {\n+\t\t\t\t$checksum = Git::SVN::Util::md5sum($fh);\n+\t\t\t}\n+\t\t\tcommand_close_pipe($fh, $ctx);\n+\t\t} elsif ($file_type eq \"link\") {\n+\t\t\tmy $file_name =\n+\t\t\t    command(qw(cat-file blob), \"HEAD:$path\");\n+\t\t\t$checksum =\n+\t\t\t    Git::SVN::Util::md5sum(\"link \" . $file_name);\n+\t\t} else {\n+\t\t\topen FILE, \"<\", $path or die $!;\n+\t\t\t$checksum = Git::SVN::Util::md5sum(\\*FILE);\n+\t\t\tclose FILE or die $!;\n+\t\t}\n+\t\t$result .= \"Checksum: \" . $checksum . \"\\n\";\n+\t}\n+\n+\tprint $result, \"\\n\";\n+}\n+\n ########################### utility functions #########################\n \n sub rebase_cmd {\n@@ -1047,6 +1155,30 @@ sub linearize_history {\n \t(\\@linear_refs, \\%parents);\n }\n \n+sub find_file_type_and_diff_status {\n+\tmy ($path) = @_;\n+\n+\tmy $diff_output =\n+\t    command_oneline(qw(diff --cached --name-status --), $path) || \"\";\n+\tmy $diff_status = (split(' ', $diff_output))[0] || \"\";\n+\n+\tmy $ls_tree = command_oneline(qw(ls-tree HEAD), $path) || \"\";\n+\n+\treturn (undef, undef) if !$diff_status && !$ls_tree;\n+\n+\tif ($diff_status eq \"A\") {\n+\t\treturn (\"link\", $diff_status) if -l $path;\n+\t\treturn (\"dir\", $diff_status) if -d $path;\n+\t\treturn (\"file\", $diff_status);\n+\t}\n+\n+\tmy $mode = (split(' ', $ls_tree))[0] || \"\";\n+\n+\treturn (\"link\", $diff_status) if $mode eq \"120000\";\n+\treturn (\"dir\", $diff_status) if $mode eq \"040000\";\n+\treturn (\"file\", $diff_status);\n+}\n+\n package Git::SVN::Util;\n use strict;\n use warnings;\ndiff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh\nnew file mode 100644\nindex 0000000..c7ca006\n--- /dev/null\n+++ b/t/t9117-git-svn-info.sh\n@@ -0,0 +1,186 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2007 David D. Kilzer\n+\n+test_description='git-svn info'\n+\n+. ./lib-git-svn.sh\n+\n+test_expect_success 'setup repository and import' \"\n+\tmkdir info &&\n+\tcd info &&\n+\t\techo one > file &&\n+\t\tln -s file symlink-file &&\n+\t\tmkdir directory &&\n+\t\ttouch directory/.placeholder &&\n+\t\tln -s directory symlink-directory &&\n+\t\tsvn import -m 'initial' . $svnrepo &&\n+\tcd .. &&\n+\tmkdir gitwc &&\n+\tcd gitwc &&\n+\t\tgit-svn init $svnrepo &&\n+\t\tgit-svn fetch &&\n+\tcd ..\n+\t\"\n+\n+test_expect_success 'info no arguments' \"\n+\t(cd gitwc; git-svn info) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' |\n+\tgit-diff ../t9117/expected.info-no-arguments -\n+\t\"\n+\n+test_expect_success 'info dot' \"\n+\t(cd gitwc; git-svn info .) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' |\n+\tgit-diff ../t9117/expected.info-dot -\n+\t\"\n+\n+test_expect_success 'info file' \"\n+\t(cd gitwc; git-svn info file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' |\n+\tgit-diff ../t9117/expected.info-file -\n+\t\"\n+\n+test_expect_success 'info directory' \"\n+\t(cd gitwc; git-svn info directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' |\n+\tgit-diff ../t9117/expected.info-directory -\n+\t\"\n+\n+test_expect_success 'info symlink-file' \"\n+\t(cd gitwc; git-svn info symlink-file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' |\n+\tgit-diff ../t9117/expected.info-symlink-file -\n+\t\"\n+\n+test_expect_success 'info symlink-directory' \"\n+\t(cd gitwc; git-svn info symlink-directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' |\n+\tgit-diff ../t9117/expected.info-symlink-directory -\n+\t\"\n+\n+test_expect_success 'info added-file' \"\n+\techo two > gitwc/added-file &&\n+\tcd gitwc &&\n+\t\tgit add added-file &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info added-file) |\n+\tgit-diff ../t9117/expected.info-added-file -\n+\t\"\n+\n+test_expect_success 'info added-directory' \"\n+\tmkdir gitwc/added-directory &&\n+        touch gitwc/added-directory/.placeholder &&\n+\tcd gitwc &&\n+\t\tgit add added-directory &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info added-directory) |\n+\tgit-diff ../t9117/expected.info-added-directory -\n+\t\"\n+\n+test_expect_success 'info added-symlink-file' \"\n+\tcd gitwc &&\n+\t\tln -s added-file added-symlink-file &&\n+\t\tgit add added-symlink-file &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info added-symlink-file) |\n+\tgit-diff ../t9117/expected.info-added-symlink-file -\n+\t\"\n+\n+test_expect_success 'info added-symlink-directory' \"\n+\tcd gitwc &&\n+\t\tln -s added-directory added-symlink-directory &&\n+\t\tgit add added-symlink-directory &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info added-symlink-directory) |\n+\tgit-diff ../t9117/expected.info-added-symlink-directory -\n+\t\"\n+\n+test_expect_success 'info deleted-file' \"\n+\tcd gitwc &&\n+\t\tgit rm -f file > /dev/null &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' |\n+\tgit-diff ../t9117/expected.info-deleted-file -\n+\t\"\n+\n+test_expect_success 'info deleted-directory' \"\n+\tcd gitwc &&\n+\t\tgit rm -r -f directory > /dev/null &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' |\n+\tgit-diff ../t9117/expected.info-deleted-directory -\n+\t\"\n+\n+test_expect_success 'info deleted-symlink-file' \"\n+\tcd gitwc &&\n+\t\tgit rm -f symlink-file > /dev/null &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info symlink-file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' |\n+\tgit-diff ../t9117/expected.info-deleted-symlink-file -\n+\t\"\n+\n+test_expect_success 'info deleted-symlink-directory' \"\n+\tcd gitwc &&\n+\t\tgit rm -f symlink-directory > /dev/null &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info symlink-directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' |\n+\tgit-diff ../t9117/expected.info-deleted-symlink-directory -\n+\t\"\n+\n+# NOTE: git does not have the concept of replaced objects,\n+# so we can't test for them.\n+#test_expect_success 'info replaced-file' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-directory' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-symlink-file' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-symlink-directory' \"/usr/bin/true\"\n+\n+test_expect_success 'info unknown-file' \"\n+\techo two > gitwc/unknown-file &&\n+\t(cd gitwc; git-svn info unknown-file) 2>&1 |\n+\tgit-diff ../t9117/expected.info-unknown-file -\n+\t\"\n+\n+test_expect_success 'info unknown-directory' \"\n+\tmkdir gitwc/unknown-directory &&\n+\t(cd gitwc; git-svn info unknown-directory) 2>&1 |\n+\tgit-diff ../t9117/expected.info-unknown-directory -\n+\t\"\n+\n+test_expect_success 'info unknown-symlink-file' \"\n+\tcd gitwc &&\n+\t\tln -s unknown-file unknown-symlink-file &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info unknown-symlink-file) 2>&1 |\n+\tgit-diff ../t9117/expected.info-unknown-symlink-file -\n+\t\"\n+\n+test_expect_success 'info unknown-symlink-directory' \"\n+\tcd gitwc &&\n+\t\tln -s unknown-directory unknown-symlink-directory &&\n+\tcd .. &&\n+\t(cd gitwc; git-svn info unknown-symlink-directory) 2>&1 |\n+\tgit-diff ../t9117/expected.info-unknown-symlink-directory -\n+\t\"\n+\n+test_done\ndiff --git a/t/t9117/expected.info-added-directory b/t/t9117/expected.info-added-directory\nnew file mode 100644\nindex 0000000..2622900\n--- /dev/null\n+++ b/t/t9117/expected.info-added-directory\n@@ -0,0 +1,7 @@\n+Path: added-directory\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-directory\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Revision: 0\n+Node Kind: directory\n+Schedule: add\n+\ndiff --git a/t/t9117/expected.info-added-file b/t/t9117/expected.info-added-file\nnew file mode 100644\nindex 0000000..2881f93\n--- /dev/null\n+++ b/t/t9117/expected.info-added-file\n@@ -0,0 +1,8 @@\n+Path: added-file\n+Name: added-file\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-file\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Revision: 0\n+Node Kind: file\n+Schedule: add\n+\ndiff --git a/t/t9117/expected.info-added-symlink-directory b/t/t9117/expected.info-added-symlink-directory\nnew file mode 100644\nindex 0000000..fa3d511\n--- /dev/null\n+++ b/t/t9117/expected.info-added-symlink-directory\n@@ -0,0 +1,8 @@\n+Path: added-symlink-directory\n+Name: added-symlink-directory\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-symlink-directory\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Revision: 0\n+Node Kind: file\n+Schedule: add\n+\ndiff --git a/t/t9117/expected.info-added-symlink-file b/t/t9117/expected.info-added-symlink-file\nnew file mode 100644\nindex 0000000..cd14e62\n--- /dev/null\n+++ b/t/t9117/expected.info-added-symlink-file\n@@ -0,0 +1,8 @@\n+Path: added-symlink-file\n+Name: added-symlink-file\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/added-symlink-file\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Revision: 0\n+Node Kind: file\n+Schedule: add\n+\ndiff --git a/t/t9117/expected.info-deleted-directory b/t/t9117/expected.info-deleted-directory\nnew file mode 100644\nindex 0000000..ec8bda5\n--- /dev/null\n+++ b/t/t9117/expected.info-deleted-directory\n@@ -0,0 +1,11 @@\n+Path: directory\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/directory\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: directory\n+Schedule: delete\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+\ndiff --git a/t/t9117/expected.info-deleted-file b/t/t9117/expected.info-deleted-file\nnew file mode 100644\nindex 0000000..7951183\n--- /dev/null\n+++ b/t/t9117/expected.info-deleted-file\n@@ -0,0 +1,14 @@\n+Path: file\n+Name: file\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/file\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: file\n+Schedule: delete\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+Text Last Updated: TEXT-LAST-UPDATED-STRING\n+Checksum: 5bbf5a52328e7439ae6e719dfe712200\n+\ndiff --git a/t/t9117/expected.info-deleted-symlink-directory b/t/t9117/expected.info-deleted-symlink-directory\nnew file mode 100644\nindex 0000000..2fb452d\n--- /dev/null\n+++ b/t/t9117/expected.info-deleted-symlink-directory\n@@ -0,0 +1,14 @@\n+Path: symlink-directory\n+Name: symlink-directory\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-directory\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: file\n+Schedule: delete\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+Text Last Updated: TEXT-LAST-UPDATED-STRING\n+Checksum: 7f5674b838ad799ab8962413b1f84095\n+\ndiff --git a/t/t9117/expected.info-deleted-symlink-file b/t/t9117/expected.info-deleted-symlink-file\nnew file mode 100644\nindex 0000000..c2945f9\n--- /dev/null\n+++ b/t/t9117/expected.info-deleted-symlink-file\n@@ -0,0 +1,14 @@\n+Path: symlink-file\n+Name: symlink-file\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-file\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: file\n+Schedule: delete\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+Text Last Updated: TEXT-LAST-UPDATED-STRING\n+Checksum: 73f9c467f93002e83dc229a229bbc4cb\n+\ndiff --git a/t/t9117/expected.info-directory b/t/t9117/expected.info-directory\nnew file mode 100644\nindex 0000000..29dfa37\n--- /dev/null\n+++ b/t/t9117/expected.info-directory\n@@ -0,0 +1,11 @@\n+Path: directory\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/directory\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: directory\n+Schedule: normal\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+\ndiff --git a/t/t9117/expected.info-dot b/t/t9117/expected.info-dot\nnew file mode 100644\nindex 0000000..c3bf061\n--- /dev/null\n+++ b/t/t9117/expected.info-dot\n@@ -0,0 +1,11 @@\n+Path: .\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: directory\n+Schedule: normal\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+\ndiff --git a/t/t9117/expected.info-file b/t/t9117/expected.info-file\nnew file mode 100644\nindex 0000000..9350107\n--- /dev/null\n+++ b/t/t9117/expected.info-file\n@@ -0,0 +1,14 @@\n+Path: file\n+Name: file\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/file\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: file\n+Schedule: normal\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+Text Last Updated: TEXT-LAST-UPDATED-STRING\n+Checksum: 5bbf5a52328e7439ae6e719dfe712200\n+\ndiff --git a/t/t9117/expected.info-no-arguments b/t/t9117/expected.info-no-arguments\nnew file mode 100644\nindex 0000000..c3bf061\n--- /dev/null\n+++ b/t/t9117/expected.info-no-arguments\n@@ -0,0 +1,11 @@\n+Path: .\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: directory\n+Schedule: normal\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+\ndiff --git a/t/t9117/expected.info-symlink-directory b/t/t9117/expected.info-symlink-directory\nnew file mode 100644\nindex 0000000..70255ac\n--- /dev/null\n+++ b/t/t9117/expected.info-symlink-directory\n@@ -0,0 +1,14 @@\n+Path: symlink-directory\n+Name: symlink-directory\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-directory\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: file\n+Schedule: normal\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+Text Last Updated: TEXT-LAST-UPDATED-STRING\n+Checksum: 7f5674b838ad799ab8962413b1f84095\n+\ndiff --git a/t/t9117/expected.info-symlink-file b/t/t9117/expected.info-symlink-file\nnew file mode 100644\nindex 0000000..8465c1d\n--- /dev/null\n+++ b/t/t9117/expected.info-symlink-file\n@@ -0,0 +1,14 @@\n+Path: symlink-file\n+Name: symlink-file\n+URL: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo/symlink-file\n+Repository Root: file:///Users/ddkilzer/Projects/C/git/t/trash/svnrepo\n+Repository UUID: REPOSITORY-UUID\n+Revision: 1\n+Node Kind: file\n+Schedule: normal\n+Last Changed Author: ddkilzer\n+Last Changed Rev: 1\n+Last Changed Date: LAST-CHANGED-DATE-STRING\n+Text Last Updated: TEXT-LAST-UPDATED-STRING\n+Checksum: 73f9c467f93002e83dc229a229bbc4cb\n+\ndiff --git a/t/t9117/expected.info-unknown-directory b/t/t9117/expected.info-unknown-directory\nnew file mode 100644\nindex 0000000..b5eef7d\n--- /dev/null\n+++ b/t/t9117/expected.info-unknown-directory\n@@ -0,0 +1,2 @@\n+unknown-directory:  (Not a versioned resource)\n+\ndiff --git a/t/t9117/expected.info-unknown-file b/t/t9117/expected.info-unknown-file\nnew file mode 100644\nindex 0000000..89f102e\n--- /dev/null\n+++ b/t/t9117/expected.info-unknown-file\n@@ -0,0 +1,2 @@\n+unknown-file:  (Not a versioned resource)\n+\ndiff --git a/t/t9117/expected.info-unknown-symlink-directory b/t/t9117/expected.info-unknown-symlink-directory\nnew file mode 100644\nindex 0000000..37d3106\n--- /dev/null\n+++ b/t/t9117/expected.info-unknown-symlink-directory\n@@ -0,0 +1,2 @@\n+unknown-symlink-directory:  (Not a versioned resource)\n+\ndiff --git a/t/t9117/expected.info-unknown-symlink-file b/t/t9117/expected.info-unknown-symlink-file\nnew file mode 100644\nindex 0000000..cae9ab0\n--- /dev/null\n+++ b/t/t9117/expected.info-unknown-symlink-file\n@@ -0,0 +1,2 @@\n+unknown-symlink-file:  (Not a versioned resource)\n+\ndiff --git a/t/t9117/regenerate.sh b/t/t9117/regenerate.sh\nnew file mode 100755\nindex 0000000..16d039d\n--- /dev/null\n+++ b/t/t9117/regenerate.sh\n@@ -0,0 +1,186 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2007 David D. Kilzer\n+\n+test_description='regenerate results for git-svn info'\n+\n+cd `dirname $0`/..\n+. ./lib-git-svn.sh\n+\n+test_expect_success 'setup repository and import' \"\n+\tmkdir info &&\n+\tcd info &&\n+\t\techo one > file &&\n+\t\tln -s file symlink-file &&\n+\t\tmkdir directory &&\n+\t\ttouch directory/.placeholder &&\n+\t\tln -s directory symlink-directory &&\n+\t\tsvn import -m 'initial' . $svnrepo &&\n+\tcd .. &&\n+\tsvn co $svnrepo svnwc\n+\t\"\n+\n+test_expect_success 'info no arguments' \"\n+\t(cd svnwc; svn info) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t>../t9117/expected.info-no-arguments\n+\t\"\n+\n+test_expect_success 'info dot' \"\n+\t(cd svnwc; svn info .) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t>../t9117/expected.info-dot\n+\t\"\n+\n+test_expect_success 'info file' \"\n+\t(cd svnwc; svn info file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' \\\n+\t>../t9117/expected.info-file\n+\t\"\n+\n+test_expect_success 'info directory' \"\n+\t(cd svnwc; svn info directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t>../t9117/expected.info-directory\n+\t\"\n+\n+test_expect_success 'info symlink-file' \"\n+\t(cd svnwc; svn info symlink-file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' \\\n+\t>../t9117/expected.info-symlink-file\n+\t\"\n+\n+test_expect_success 'info symlink-directory' \"\n+\t(cd svnwc; svn info symlink-directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' \\\n+\t>../t9117/expected.info-symlink-directory\n+\t\"\n+\n+test_expect_success 'info added-file' \"\n+\techo two > svnwc/added-file &&\n+\tcd svnwc &&\n+\t\tsvn add added-file > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info added-file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t>../t9117/expected.info-added-file\n+\t\"\n+\n+test_expect_success 'info added-directory' \"\n+\tmkdir svnwc/added-directory &&\n+\tcd svnwc &&\n+\t\tsvn add added-directory > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info added-directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t>../t9117/expected.info-added-directory\n+\t\"\n+\n+test_expect_success 'info added-symlink-file' \"\n+\tcd svnwc &&\n+\t\tln -s added-file added-symlink-file &&\n+\t\tsvn add added-symlink-file > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info added-symlink-file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t>../t9117/expected.info-added-symlink-file\n+\t\"\n+\n+test_expect_success 'info added-symlink-directory' \"\n+\tcd svnwc &&\n+\t\tln -s added-directory added-symlink-directory &&\n+\t\tsvn add added-symlink-directory > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info added-symlink-directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t>../t9117/expected.info-added-symlink-directory\n+\t\"\n+\n+test_expect_success 'info deleted-file' \"\n+\tcd svnwc &&\n+\t\tsvn rm --force file > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' \\\n+\t>../t9117/expected.info-deleted-file\n+\t\"\n+\n+test_expect_success 'info deleted-directory' \"\n+\tcd svnwc &&\n+\t\tsvn rm --force directory > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t>../t9117/expected.info-deleted-directory\n+\t\"\n+\n+test_expect_success 'info deleted-symlink-file' \"\n+\tcd svnwc &&\n+\t\tsvn rm --force symlink-file > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info symlink-file) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' \\\n+\t>../t9117/expected.info-deleted-symlink-file\n+\t\"\n+\n+test_expect_success 'info deleted-symlink-directory' \"\n+\tcd svnwc &&\n+\t\tsvn rm --force symlink-directory > /dev/null &&\n+\tcd .. &&\n+\t(cd svnwc; svn info symlink-directory) |\n+\tsed\t-e 's/^\\(Repository UUID:\\).*/\\1 REPOSITORY-UUID/' \\\n+\t\t-e 's/^\\(Last Changed Date:\\).*/\\1 LAST-CHANGED-DATE-STRING/' \\\n+\t\t-e 's/^\\(Text Last Updated:\\).*/\\1 TEXT-LAST-UPDATED-STRING/' \\\n+\t>../t9117/expected.info-deleted-symlink-directory\n+\t\"\n+\n+# NOTE: git does not have the concept of replaced objects,\n+# so we can't test for them.\n+#test_expect_success 'info replaced-file' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-directory' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-symlink-file' \"/usr/bin/true\"\n+#test_expect_success 'info replaced-symlink-directory' \"/usr/bin/true\"\n+\n+test_expect_success 'info unknown-file' \"\n+\techo two > svnwc/unknown-file &&\n+\t(cd svnwc; svn info unknown-file) \\\n+\t2>../t9117/expected.info-unknown-file\n+\t\"\n+\n+test_expect_success 'info unknown-directory' \"\n+\tmkdir svnwc/unknown-directory &&\n+\t(cd svnwc; svn info unknown-directory) \\\n+\t2>../t9117/expected.info-unknown-directory\n+\t\"\n+\n+test_expect_success 'info unknown-symlink-file' \"\n+\tcd svnwc &&\n+\t\tln -s unknown-file unknown-symlink-file &&\n+\tcd .. &&\n+\t(cd svnwc; svn info unknown-symlink-file) \\\n+\t2>../t9117/expected.info-unknown-symlink-file\n+\t\"\n+\n+test_expect_success 'info unknown-symlink-directory' \"\n+\tcd svnwc &&\n+\t\tln -s unknown-directory unknown-symlink-directory &&\n+\tcd .. &&\n+\t(cd svnwc; svn info unknown-symlink-directory) \\\n+\t2>../t9117/expected.info-unknown-symlink-directory\n+\t\"\n+\n+test_done\n-- \n1.5.3.4\n"},{"id":"60461","messageId":"1195627399-25209-4-git-send-email-ddkilzer@kilzer.net","threadId":"10834","inReplyTo":"1195627399-25209-3-git-send-email-ddkilzer@kilzer.net","subject":"[PATCH 3/3] git-svn: info --url [path]","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2007-11-21T06:43:19Z","receivedAt":"2007-11-21T06:43:19Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"Return the svn URL for the given path, or return the svn\nrepository URL if no path is given.\n\nSigned-off-by: David D. Kilzer <ddkilzer@kilzer.net>\n---\n git-svn.perl            |    9 +++++++--\n t/t9117-git-svn-info.sh |    4 ++++\n 2 files changed, 11 insertions(+), 2 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 406ee6f..eaf2187 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -65,7 +65,7 @@ my ($_stdin, $_help, $_edit,\n \t$_template, $_shared,\n \t$_version, $_fetch_all, $_no_rebase,\n \t$_merge, $_strategy, $_dry_run, $_local,\n-\t$_prefix, $_no_checkout, $_verbose);\n+\t$_prefix, $_no_checkout, $_url, $_verbose);\n $Git::SVN::_follow_parent = 1;\n my %remote_opts = ( 'username=s' => \\$Git::SVN::Prompt::_username,\n                     'config-dir=s' => \\$Git::SVN::Ra::config_dir,\n@@ -181,7 +181,7 @@ my %cmd = (\n \t'info' => [ \\&cmd_info,\n \t\t    \"Show info about the latest SVN revision\n \t\t     on the current branch\",\n-\t\t    { } ],\n+\t\t    { 'url' => \\$_url, } ],\n );\n \n my $cmd;\n@@ -770,6 +770,11 @@ sub cmd_info {\n \t}\n \tmy $full_url = $url . ($path eq \".\" ? \"\" : \"/$path\");\n \n+\tif ($_url) {\n+\t\tprint $full_url, \"\\n\";\n+\t\treturn;\n+\t}\n+\n \tmy $result = \"Path: $path\\n\";\n \t$result .= \"Name: \" . basename($path) . \"\\n\" if $file_type ne \"dir\";\n \t$result .= \"URL: \" . $full_url . \"\\n\";\ndiff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh\nindex c7ca006..800d1c4 100644\n--- a/t/t9117-git-svn-info.sh\n+++ b/t/t9117-git-svn-info.sh\n@@ -183,4 +183,8 @@ test_expect_success 'info unknown-symlink-directory' \"\n \tgit-diff ../t9117/expected.info-unknown-symlink-directory -\n \t\"\n \n+test_expect_success 'info --url' '\n+\ttest $(cd gitwc; git-svn info --url) = $svnrepo\n+\t'\n+\n test_done\n-- \n1.5.3.4\n"},{"id":"60463","messageId":"1195627768-26689-1-git-send-email-ddkilzer@kilzer.net","threadId":"10834","inReplyTo":"1195627399-25209-4-git-send-email-ddkilzer@kilzer.net","subject":"[PATCH 3/3 v2] git-svn: info --url [path]","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2007-11-21T06:49:28Z","receivedAt":"2007-11-21T06:49:28Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"Return the svn URL for the given path, or return the svn\nrepository URL if no path is given.\n\nAdded one test to t/t9117-git-svn-info.sh.\n\nSigned-off-by: David D. Kilzer <ddkilzer@kilzer.net>\n---\n\nAdded missing documentation change, and tweaked commit log.\n\n Documentation/git-svn.txt |    2 +-\n git-svn.perl              |    9 +++++++--\n t/t9117-git-svn-info.sh   |    4 ++++\n 3 files changed, 12 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt\nindex c3fc878..295b14b 100644\n--- a/Documentation/git-svn.txt\n+++ b/Documentation/git-svn.txt\n@@ -196,7 +196,7 @@ Any other arguments are passed directly to `git log'\n 'info'::\n \tShows information about a file or directory similar to what\n \t`svn info' provides.  Does not currently support a -r/--revision\n-\targument.\n+\targument.  Use the --url option to output only the 'URL:' field.\n \n --\n \ndiff --git a/git-svn.perl b/git-svn.perl\nindex 406ee6f..eaf2187 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -65,7 +65,7 @@ my ($_stdin, $_help, $_edit,\n \t$_template, $_shared,\n \t$_version, $_fetch_all, $_no_rebase,\n \t$_merge, $_strategy, $_dry_run, $_local,\n-\t$_prefix, $_no_checkout, $_verbose);\n+\t$_prefix, $_no_checkout, $_url, $_verbose);\n $Git::SVN::_follow_parent = 1;\n my %remote_opts = ( 'username=s' => \\$Git::SVN::Prompt::_username,\n                     'config-dir=s' => \\$Git::SVN::Ra::config_dir,\n@@ -181,7 +181,7 @@ my %cmd = (\n \t'info' => [ \\&cmd_info,\n \t\t    \"Show info about the latest SVN revision\n \t\t     on the current branch\",\n-\t\t    { } ],\n+\t\t    { 'url' => \\$_url, } ],\n );\n \n my $cmd;\n@@ -770,6 +770,11 @@ sub cmd_info {\n \t}\n \tmy $full_url = $url . ($path eq \".\" ? \"\" : \"/$path\");\n \n+\tif ($_url) {\n+\t\tprint $full_url, \"\\n\";\n+\t\treturn;\n+\t}\n+\n \tmy $result = \"Path: $path\\n\";\n \t$result .= \"Name: \" . basename($path) . \"\\n\" if $file_type ne \"dir\";\n \t$result .= \"URL: \" . $full_url . \"\\n\";\ndiff --git a/t/t9117-git-svn-info.sh b/t/t9117-git-svn-info.sh\nindex c7ca006..800d1c4 100644\n--- a/t/t9117-git-svn-info.sh\n+++ b/t/t9117-git-svn-info.sh\n@@ -183,4 +183,8 @@ test_expect_success 'info unknown-symlink-directory' \"\n \tgit-diff ../t9117/expected.info-unknown-symlink-directory -\n \t\"\n \n+test_expect_success 'info --url' '\n+\ttest $(cd gitwc; git-svn info --url) = $svnrepo\n+\t'\n+\n test_done\n-- \n1.5.3.4\n"},{"id":"60468","messageId":"220901.13065.qm@web52408.mail.re2.yahoo.com","threadId":"10834","inReplyTo":"1195627399-25209-1-git-send-email-ddkilzer@kilzer.net","subject":"Re: [PATCH 0/3] Implement git-svn: info","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2007-11-21T06:59:07Z","receivedAt":"2007-11-21T06:59:07Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"\"David D. Kilzer\" <ddkilzer@kilzer.net> wrote:\n> Eric Wong <normalperson@yhbt.net> wrote:\n> > Can we expect the output of \"svn info\" to not change between\n> > versions?  I know \"svn status\" has changed between versions of\n> > svn.  I'd prefer if we keep the expected.* files hard-coded\n> > in a test directory and compare those instead.  Maybe use sed\n> > to substitute placeholders for timestamps..\n> Done.\n\nGrrr.  I remember the reason I didn't do this in the first place.  In Patch\n2/3, there are now hard-coded directory paths and my username in the static\nexpected-* files.\n\nThat means that either I need to replace the \"URL:\", \"Repository Root:\" and\n\"Last Changed Author:\" fields with place-holders (weakening the effectiveness\nof the tests), or switch back to more dynamic tests.\n\nThoughts?\n\nDave\n"},{"id":"60485","messageId":"20071121091809.GB23266@soma","threadId":"10834","inReplyTo":"220901.13065.qm@web52408.mail.re2.yahoo.com","subject":"Re: [PATCH 0/3] Implement git-svn: info","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-11-21T09:18:10Z","receivedAt":"2007-11-21T09:18:10Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"\"David D. Kilzer\" <ddkilzer@kilzer.net> wrote:\n> \"David D. Kilzer\" <ddkilzer@kilzer.net> wrote:\n> > Eric Wong <normalperson@yhbt.net> wrote:\n> > > Can we expect the output of \"svn info\" to not change between\n> > > versions?  I know \"svn status\" has changed between versions of\n> > > svn.  I'd prefer if we keep the expected.* files hard-coded\n> > > in a test directory and compare those instead.  Maybe use sed\n> > > to substitute placeholders for timestamps..\n> > Done.\n> \n> Grrr.  I remember the reason I didn't do this in the first place.  In Patch\n> 2/3, there are now hard-coded directory paths and my username in the static\n> expected-* files.\n> \n> That means that either I need to replace the \"URL:\", \"Repository Root:\" and\n> \"Last Changed Author:\" fields with place-holders (weakening the effectiveness\n> of the tests), or switch back to more dynamic tests.\n> \n> Thoughts?\n\nAh, good point.\n\nOn some of my tests (t9110, t9111, t9115), I get around this by\ngenerating a repository once and dumping it using `svnadmin dump'.\n\n-- \nEric Wong\n"},{"id":"60486","messageId":"20071121092028.GC23266@soma","threadId":"10834","inReplyTo":"20071121091809.GB23266@soma","subject":"Re: [PATCH 0/3] Implement git-svn: info","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-11-21T09:20:28Z","receivedAt":"2007-11-21T09:20:28Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Eric Wong <normalperson@yhbt.net> wrote:\n> \"David D. Kilzer\" <ddkilzer@kilzer.net> wrote:\n> > \"David D. Kilzer\" <ddkilzer@kilzer.net> wrote:\n> > > Eric Wong <normalperson@yhbt.net> wrote:\n> > > > Can we expect the output of \"svn info\" to not change between\n> > > > versions?  I know \"svn status\" has changed between versions of\n> > > > svn.  I'd prefer if we keep the expected.* files hard-coded\n> > > > in a test directory and compare those instead.  Maybe use sed\n> > > > to substitute placeholders for timestamps..\n> > > Done.\n> > \n> > Grrr.  I remember the reason I didn't do this in the first place.  In Patch\n> > 2/3, there are now hard-coded directory paths and my username in the static\n> > expected-* files.\n> > \n> > That means that either I need to replace the \"URL:\", \"Repository Root:\" and\n> > \"Last Changed Author:\" fields with place-holders (weakening the effectiveness\n> > of the tests), or switch back to more dynamic tests.\n> > \n> > Thoughts?\n> \n> Ah, good point.\n> \n> On some of my tests (t9110, t9111, t9115), I get around this by\n> generating a repository once and dumping it using `svnadmin dump'.\n\nWait, the paths/URLs will still be inconsistent, but author will at\nleast be correct...\n\nSorry, I need sleep :/\n\n-- \nEric Wong\n"}]}