Skip to content

Commit

Permalink
gitweb: Hyperlink target of symbolic link in "tree" view (if possible)
Browse files Browse the repository at this point in the history
Make symbolic link target in "tree" view into hyperlink to generic
"object" view (as we don't know if the link target is file (blob) or
directory (tree), and if it exist at all).

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)

Full path of symlink target from the root dir is provided in the title
attribute of hyperlink.

Currently symbolic link name uses ordinary file style (hidden
hyperlink), while the hyperlink to symlink target uses default
hyperlink style, so it is underlined while link target which is not
made into hyperlink is not underlined.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Jakub Narebski authored and Junio C Hamano committed Dec 12, 2006
1 parent ca94601 commit 3bf9d57
Showing 1 changed file with 51 additions and 1 deletion.
52 changes: 51 additions & 1 deletion gitweb/gitweb.perl
Original file line number Diff line number Diff line change
Expand Up @@ -2008,6 +2008,48 @@ sub git_get_link_target {
return $link_target;
}

# given link target, and the directory (basedir) the link is in,
# return target of link relative to top directory (top tree);
# return undef if it is not possible (including absolute links).
sub normalize_link_target {
my ($link_target, $basedir, $hash_base) = @_;

# we can normalize symlink target only if $hash_base is provided
return unless $hash_base;

# absolute symlinks (beginning with '/') cannot be normalized
return if (substr($link_target, 0, 1) eq '/');

# normalize link target to path from top (root) tree (dir)
my $path;
if ($basedir) {
$path = $basedir . '/' . $link_target;
} else {
# we are in top (root) tree (dir)
$path = $link_target;
}

# remove //, /./, and /../
my @path_parts;
foreach my $part (split('/', $path)) {
# discard '.' and ''
next if (!$part || $part eq '.');
# handle '..'
if ($part eq '..') {
if (@path_parts) {
pop @path_parts;
} else {
# link leads outside repository (outside top dir)
return;
}
} else {
push @path_parts, $part;
}
}
$path = join('/', @path_parts);

return $path;
}

# print tree entry (row of git_tree), but without encompassing <tr> element
sub git_print_tree_entry {
Expand All @@ -2029,7 +2071,15 @@ sub git_print_tree_entry {
if (S_ISLNK(oct $t->{'mode'})) {
my $link_target = git_get_link_target($t->{'hash'});
if ($link_target) {
print " -> " . esc_path($link_target);
my $norm_target = normalize_link_target($link_target, $basedir, $hash_base);
if (defined $norm_target) {
print " -> " .
$cgi->a({-href => href(action=>"object", hash_base=>$hash_base,
file_name=>$norm_target),
-title => $norm_target}, esc_path($link_target));
} else {
print " -> " . esc_path($link_target);
}
}
}
print "</td>\n";
Expand Down

0 comments on commit 3bf9d57

Please sign in to comment.