From: Jakub Narebsmi <jnareb@gmail.com>
To: git@vger.kernel.org
Cc: Jakub Narebski <jnareb@gmail.com>
Subject: [PATCH] gitweb: Better symbolic link support in "tree" view
Date: Mon, 4 Dec 2006 19:26:20 +0100 [thread overview]
Message-ID: <1165256780505-git-send-email-jnareb@gmail.com> (raw)
From: Jakub Narebski <jnareb@gmail.com>
In "tree" view (git_print_tree_entry subroutine), add for symbolic
links after file name " -> link_target", a la "ls -l". Use
git_get_link_target_html to escape target name and make it into
hyperlink if possible.
Target of link is made into hyperlink when:
* hash_base is provided (otherwise we cannot find hash of link
target)
* link is relative
* in no place link goes out of root tree (top dir)
* target of link exists for hash_base
Full path of symlink target from the root dir is provided in the title
attribute of hyperlink. If symlink target is a directory, '/' is added
to end of path in title attribute.
Currently symbolic link name uses ordinary file style (hidden
hyperlink), while the hyperlink to symlink target uses default
hyperlink style.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/gitweb.perl | 91 +++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 83 insertions(+), 8 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index ffe8ce1..3c1b75d 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1989,12 +1989,83 @@ sub git_print_log ($;%) {
}
}
+# print link tree entry (name of what link points to, possibly hyperlink)
+sub git_get_link_target_html {
+ my ($t, $basedir, $hash_base) = @_;
+
+ my $fd;
+ my %target = ();
+
+ # read link
+ open $fd, "-|", git_cmd(), "cat-file", "blob", $t->{'hash'};
+ {
+ local $/;
+ $target{'orig'} = <$fd>;
+ }
+ close $fd;
+
+ # we can make hyperlink out of link target only if $hash_base is provided
+ return esc_path($target{'orig'})
+ unless $hash_base;
+
+ # absolute links are returned as is, no hyperlink
+ if (substr($target{'orig'}, 0, 1) eq '/') {
+ return esc_path($target{'orig'});
+ }
+
+ # normalize link target to path from top (root) tree (dir)
+ if ($basedir) {
+ $target{'path'} = $basedir . '/' . $target{'orig'};
+ } else {
+ # we are in top (root) tree (dir)
+ $target{'path'} = $target{'orig'};
+ }
+ $target{'parts'} = [ ];
+ foreach my $part (split('/', $target{'path'})) {
+ # discard '.' and ''
+ next if (!$part || $part eq '.');
+ # handle '..'
+ if ($part eq '..') {
+ if (@{$target{'parts'}}) {
+ pop @{$target{'parts'}};
+ } else {
+ # link leads outside repository
+ return esc_path($target{'orig'});
+ }
+ } else {
+ push @{$target{'parts'}}, $part;
+ }
+ }
+ $target{'path'} = join('/', @{$target{'parts'}});
+
+ # check if path exists
+ open $fd, "-|", git_cmd(), "ls-tree", $hash_base, "--", $target{'path'}
+ or return esc_path($target{'orig'});
+ my $line = <$fd>;
+ close $fd
+ or return esc_path($target{'orig'});
+ return esc_path($target{'orig'}) unless $line;
+
+ # parse ls-tree line to get type and hash of target of link
+ (undef, $target{'type'}, $target{'hash'}) =
+ ($line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/);
+
+ # make a link if path exists
+ return $cgi->a({-href => href(action => $target{'type'},
+ hash => $target{'hash'},
+ file_name => $target{'path'},
+ hash_base => $hash_base),
+ -title => $target{'path'} .
+ ($target{'type'} eq "tree" ? '/' : '')},
+ esc_path($target{'orig'}));
+}
+
# print tree entry (row of git_tree), but without encompassing <tr> element
sub git_print_tree_entry {
my ($t, $basedir, $hash_base, $have_blame) = @_;
my %base_key = ();
- $base_key{hash_base} = $hash_base if defined $hash_base;
+ $base_key{'hash_base'} = $hash_base if defined $hash_base;
# The format of a table row is: mode list link. Where mode is
# the mode of the entry, list is the name of the entry, an href,
@@ -2005,16 +2076,20 @@ sub git_print_tree_entry {
print "<td class=\"list\">" .
$cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
file_name=>"$basedir$t->{'name'}", %base_key),
- -class => "list"}, esc_path($t->{'name'})) . "</td>\n";
+ -class => "list"}, esc_path($t->{'name'}));
+ if (S_ISLNK(oct $t->{'mode'})) {
+ print " -> " . git_get_link_target_html($t, $basedir, $hash_base);
+ }
+ print "</td>\n";
print "<td class=\"link\">";
print $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
- "blob");
+ file_name=>"$basedir$t->{'name'}", %base_key)},
+ "blob");
if ($have_blame) {
print " | " .
$cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
- "blame");
+ file_name=>"$basedir$t->{'name'}", %base_key)},
+ "blame");
}
if (defined $hash_base) {
print " | " .
@@ -2036,8 +2111,8 @@ sub git_print_tree_entry {
print "</td>\n";
print "<td class=\"link\">";
print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
- "tree");
+ file_name=>"$basedir$t->{'name'}", %base_key)},
+ "tree");
if (defined $hash_base) {
print " | " .
$cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
--
1.4.4.1
next reply other threads:[~2006-12-04 18:25 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-04 18:26 Jakub Narebsmi [this message]
2006-12-05 1:08 ` [PATCH] gitweb: Better symbolic link support in "tree" view Junio C Hamano
2006-12-05 21:27 ` Jakub Narebski
2006-12-05 22:34 ` Junio C Hamano
2006-12-05 23:06 ` Jakub Narebski
2006-12-10 12:25 ` [PATCH 0/3] " Jakub Narebski
2006-12-10 12:25 ` Jakub Narebski
2006-12-10 12:25 ` [PATCH 1/3] gitweb: Show target of symbolic link " Jakub Narebski
2006-12-10 12:25 ` [PATCH 2/3] gitweb: Add generic git_object subroutine to display object of any type Jakub Narebski
2006-12-10 12:25 ` [PATCH 3/3] gitweb: Hyperlink target of symbolic link in "tree" view (if possible) Jakub Narebski
2006-12-10 12:25 ` [PATCH/RFC 4/3] gitweb: SHA-1 in commit log message links to "object" view Jakub Narebski
2006-12-10 21:29 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1165256780505-git-send-email-jnareb@gmail.com \
--to=jnareb@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.