From: Jakub Narebski <jnareb@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH 1/2 (amend)] gitweb: New improved patchset view
Date: Wed, 8 Nov 2006 19:41:29 +0100 [thread overview]
Message-ID: <200611081941.30330.jnareb@gmail.com> (raw)
In-Reply-To: <200611081759.41498.jnareb@gmail.com>
Replace "gitweb diff header" with its full sha1 of blobs and replace
it by "git diff" header and extended diff header. Change also somewhat
highlighting of diffs.
Added `file_type_long' subroutine to convert file mode in octal to
file type description (only for file modes which used by git).
Changes:
* "gitweb diff header" which looked for example like below:
file:_<sha1 before>_ -> file:_<sha1 after>_
where 'file' is file type and '<sha1>' is full sha1 of blob is
changed to
diff --git _a/<file before>_ _b/<file after>_
In both cases links are visible and use default link style. If file
is added, a/<file> is not hyperlinked. If file is deleted, b/<file>
is not hyperlinked.
* there is added "extended diff header", with <path> and <hash>
hyperlinked (and <hash> shortened to 7 characters), and <mode>
explained: '<mode>' is extended to '<mode> (<file type description>)',
where added text is slightly lighter to easy distinguish that it
was added (and it is difference from git-diff output).
* from-file/to-file two-line header lines have slightly darker color
than removed/added lines.
* chunk header has now delicate line above for easier finding chunk
boundary, and top margin of 2px, both barely visible.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
I'm sorry for previous version with linewrap.
gitweb/gitweb.css | 66 +++++++++++++++----
gitweb/gitweb.perl | 183 ++++++++++++++++++++++++++++++++++------------------
2 files changed, 173 insertions(+), 76 deletions(-)
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index e19e6bc..974b47f 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -298,40 +298,82 @@ td.mode {
font-family: monospace;
}
-div.diff a.list {
+/* styling of diffs (patchsets): commitdiff and blobdiff views */
+div.diff.header,
+div.diff.extended_header {
+ white-space: normal;
+}
+
+div.diff.header {
+ font-weight: bold;
+
+ background-color: #edece6;
+
+ margin-top: 4px;
+ padding: 4px 0px 2px 0px;
+ border: solid #d9d8d1;
+ border-width: 1px 0px 1px 0px;
+}
+
+div.diff.header a.path {
+ text-decoration: underline;
+}
+
+div.diff.extended_header,
+div.diff.extended_header a.path,
+div.diff.extended_header a.hash {
+ color: #777777;
+}
+
+div.diff.extended_header .info {
+ color: #b0b0b0;
+}
+
+div.diff.extended_header {
+ background-color: #f6f5ee;
+ padding: 2px 0px 2px 0px;
+}
+
+div.diff a.path,
+div.diff a.hash {
text-decoration: none;
}
-div.diff a.list:hover {
+div.diff a.path:hover,
+div.diff a.hash:hover {
text-decoration: underline;
}
-div.diff.to_file a.list,
-div.diff.to_file,
+div.diff.to_file a.path,
+div.diff.to_file {
+ color: #007000;
+}
+
div.diff.add {
color: #008800;
}
-div.diff.from_file a.list,
-div.diff.from_file,
+div.diff.from_file a.path,
+div.diff.from_file {
+ color: #aa0000;
+}
+
div.diff.rem {
color: #cc0000;
}
div.diff.chunk_header {
color: #990099;
+
+ border: dotted #ffe0ff;
+ border-width: 1px 0px 0px 0px;
+ margin-top: 2px;
}
div.diff.incomplete {
color: #cccccc;
}
-div.diff_info {
- font-family: monospace;
- color: #000099;
- background-color: #edece6;
- font-style: italic;
-}
div.index_include {
border: solid #d9d8d1;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index c9b16b5..2cf8e60 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -780,6 +780,32 @@ sub file_type {
}
}
+# convert file mode in octal to file type description string
+sub file_type_long {
+ my $mode = shift;
+
+ if ($mode !~ m/^[0-7]+$/) {
+ return $mode;
+ } else {
+ $mode = oct $mode;
+ }
+
+ if (S_ISDIR($mode & S_IFMT)) {
+ return "directory";
+ } elsif (S_ISLNK($mode)) {
+ return "symlink";
+ } elsif (S_ISREG($mode)) {
+ if ($mode & S_IXUSR) {
+ return "executable";
+ } else {
+ return "file";
+ };
+ } else {
+ return "unknown";
+ }
+}
+
+
## ----------------------------------------------------------------------
## functions returning short HTML fragments, or transforming HTML fragments
## which don't beling to other sections
@@ -2166,6 +2192,7 @@ sub git_patchset_body {
my $in_header = 0;
my $patch_found = 0;
my $diffinfo;
+ my (%from, %to);
print "<div class=\"patchset\">\n";
@@ -2176,6 +2203,10 @@ sub git_patchset_body {
if ($patch_line =~ m/^diff /) { # "git diff" header
# beginning of patch (in patchset)
if ($patch_found) {
+ # close extended header for previous empty patch
+ if ($in_header) {
+ print "</div>\n" # class="diff extended_header"
+ }
# close previous patch
print "</div>\n"; # class="patch"
} else {
@@ -2184,89 +2215,113 @@ sub git_patchset_body {
}
print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n";
+ # read and prepare patch information
if (ref($difftree->[$patch_idx]) eq "HASH") {
+ # pre-parsed (or generated by hand)
$diffinfo = $difftree->[$patch_idx];
} else {
$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);
}
+ $from{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'};
+ $to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'};
+ if ($diffinfo->{'status'} ne "A") { # not new (added) file
+ $from{'href'} = href(action=>"blob", hash_base=>$hash_parent,
+ hash=>$diffinfo->{'from_id'},
+ file_name=>$from{'file'});
+ }
+ if ($diffinfo->{'status'} ne "D") { # not deleted file
+ $to{'href'} = href(action=>"blob", hash_base=>$hash,
+ hash=>$diffinfo->{'to_id'},
+ file_name=>$to{'file'});
+ }
$patch_idx++;
- if ($diffinfo->{'status'} eq "A") { # added
- print "<div class=\"diff_info\">" . file_type($diffinfo->{'to_mode'}) . ":" .
- $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
- hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'file'})},
- $diffinfo->{'to_id'}) . " (new)" .
- "</div>\n"; # class="diff_info"
-
- } elsif ($diffinfo->{'status'} eq "D") { # deleted
- print "<div class=\"diff_info\">" . file_type($diffinfo->{'from_mode'}) . ":" .
- $cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
- hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'file'})},
- $diffinfo->{'from_id'}) . " (deleted)" .
- "</div>\n"; # class="diff_info"
-
- } elsif ($diffinfo->{'status'} eq "R" || # renamed
- $diffinfo->{'status'} eq "C" || # copied
- $diffinfo->{'status'} eq "2") { # with two filenames (from git_blobdiff)
- print "<div class=\"diff_info\">" .
- file_type($diffinfo->{'from_mode'}) . ":" .
- $cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
- hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'from_file'})},
- $diffinfo->{'from_id'}) .
- " -> " .
- file_type($diffinfo->{'to_mode'}) . ":" .
- $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
- hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'to_file'})},
- $diffinfo->{'to_id'});
- print "</div>\n"; # class="diff_info"
-
- } else { # modified, mode changed, ...
- print "<div class=\"diff_info\">" .
- file_type($diffinfo->{'from_mode'}) . ":" .
- $cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
- hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'file'})},
- $diffinfo->{'from_id'}) .
- " -> " .
- file_type($diffinfo->{'to_mode'}) . ":" .
- $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
- hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'file'})},
- $diffinfo->{'to_id'});
- print "</div>\n"; # class="diff_info"
+ # print "git diff" header
+ $patch_line =~ s!^(diff (.*?) )"?a/.*$!$1!;
+ if ($from{'href'}) {
+ $patch_line .= $cgi->a({-href => $from{'href'}, -class => "path"},
+ 'a/' . esc_path($from{'file'}));
+ } else { # file was added
+ $patch_line .= 'a/' . esc_path($from{'file'});
+ }
+ $patch_line .= ' ';
+ if ($to{'href'}) {
+ $patch_line .= $cgi->a({-href => $to{'href'}, -class => "path"},
+ 'b/' . esc_path($to{'file'}));
+ } else { # file was deleted
+ $patch_line .= 'b/' . esc_path($to{'file'});
}
- #print "<div class=\"diff extended_header\">\n";
+ print "<div class=\"diff header\">$patch_line</div>\n";
+ print "<div class=\"diff extended_header\">\n";
$in_header = 1;
next LINE;
- } # start of patch in patchset
+ }
+ if ($in_header) {
+ if ($patch_line !~ m/^---/) {
+ # match <path>
+ if ($patch_line =~ s!^((copy|rename) from ).*$!$1! && $from{'href'}) {
+ $patch_line .= $cgi->a({-href=>$from{'href'}, -class=>"path"},
+ esc_path($from{'file'}));
+ }
+ if ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {
+ $patch_line = $cgi->a({-href=>$to{'href'}, -class=>"path"},
+ esc_path($to{'file'}));
+ }
+ # match <mode>
+ if ($patch_line =~ m/\s(\d{6})$/) {
+ $patch_line .= '<span class="info"> (' .
+ file_type_long($1) .
+ ')</span>';
+ }
+ # match <hash>
+ if ($patch_line =~ m/^index/) {
+ my ($from_link, $to_link);
+ if ($from{'href'}) {
+ $from_link = $cgi->a({-href=>$from{'href'}, -class=>"hash"},
+ substr($diffinfo->{'from_id'},0,7));
+ } else {
+ $from_link = '0' x 7;
+ }
+ if ($to{'href'}) {
+ $to_link = $cgi->a({-href=>$to{'href'}, -class=>"hash"},
+ substr($diffinfo->{'to_id'},0,7));
+ } else {
+ $to_link = '0' x 7;
+ }
+ my ($from_id, $to_id) = ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});
+ $patch_line =~ s!$from_id\.\.$to_id!$from_link..$to_link!;
+ }
+ print $patch_line . "<br/>\n";
- if ($in_header && $patch_line =~ m/^---/) {
- #print "</div>\n"; # class="diff extended_header"
- $in_header = 0;
+ } else {
+ #$in_header && $patch_line =~ m/^---/;
+ print "</div>\n"; # class="diff extended_header"
+ $in_header = 0;
+
+ if ($from{'href'}) {
+ $patch_line = '--- a/' .
+ $cgi->a({-href=>$from{'href'}, -class=>"path"},
+ esc_path($from{'file'}));
+ }
+ print "<div class=\"diff from_file\">$patch_line</div>\n";
- my $file = $diffinfo->{'from_file'};
- $file ||= $diffinfo->{'file'};
- $file = $cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent,
- hash=>$diffinfo->{'from_id'}, file_name=>$file),
- -class => "list"}, esc_path($file));
- $patch_line =~ s|a/.*$|a/$file|g;
- print "<div class=\"diff from_file\">$patch_line</div>\n";
+ $patch_line = <$fd>;
+ chomp $patch_line;
- $patch_line = <$fd>;
- chomp $patch_line;
+ #$patch_line =~ m/^+++/;
+ if ($to{'href'}) {
+ $patch_line = '+++ b/' .
+ $cgi->a({-href=>$to{'href'}, -class=>"path"},
+ esc_path($to{'file'}));
+ }
+ print "<div class=\"diff to_file\">$patch_line</div>\n";
- #$patch_line =~ m/^+++/;
- $file = $diffinfo->{'to_file'};
- $file ||= $diffinfo->{'file'};
- $file = $cgi->a({-href => href(action=>"blob", hash_base=>$hash,
- hash=>$diffinfo->{'to_id'}, file_name=>$file),
- -class => "list"}, esc_path($file));
- $patch_line =~ s|b/.*|b/$file|g;
- print "<div class=\"diff to_file\">$patch_line</div>\n";
+ }
next LINE;
}
- next LINE if $in_header;
print format_diff_line($patch_line);
}
--
1.4.3.4
next prev parent reply other threads:[~2006-11-08 18:41 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-08 10:47 [PATCH 0/2] Better unquoting of git quoted filenames; esc_path to escape pathnames for display Jakub Narebski
2006-11-08 10:48 ` [PATCH 1/2] gitweb: Better git-unquoting and gitweb-quoting of pathnames Jakub Narebski
2006-11-08 10:50 ` [PATCH 2/2] gitweb: Use character or octal escape codes (and add span.cntrl) in esc_path Jakub Narebski
2006-11-08 16:58 ` [PATCH 0/2] gitweb: New improved patchset view Jakub Narebski
2006-11-08 16:59 ` [PATCH 1/2] " Jakub Narebski
2006-11-08 18:27 ` Junio C Hamano
2006-11-08 18:57 ` Junio C Hamano
2006-11-08 19:04 ` Jakub Narebski
2006-11-08 18:41 ` Jakub Narebski [this message]
2006-11-08 17:00 ` [PATCH 2/2] gitweb: New improved formatting of chunk header in diff Jakub Narebski
2006-11-08 20:41 ` Junio C Hamano
2006-11-08 20:58 ` Jakub Narebski
2006-11-08 21:41 ` Junio C Hamano
2006-11-08 21:55 ` Jakub Narebski
2006-11-08 18:24 ` [PATCH 2/2] gitweb: Use character or octal escape codes (and add span.cntrl) in esc_path Junio C Hamano
2006-11-08 18:56 ` Jakub Narebski
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=200611081941.30330.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 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).