From c2b8b13494f3de6bd9a22162973e4df32665a966 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Fri, 6 Apr 2007 23:58:11 +0200 Subject: gitweb: Allow forks with project list file Make it possible to use the forks feature even when reading the list of projects from a file, by creating a list of known prefixes as we go. Forks have to be listed after the main project in order to be recognised as such. Signed-off-by: Frank Lichtenheld Acked-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e49eb91d69..01a10b320e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -176,8 +176,8 @@ our %feature = ( # projects matching $projname/*.git will not be shown in the main # projects list, instead a '+' mark will be added to $projname # there and a 'forks' view will be enabled for the project, listing - # all the forks. This feature is supported only if project list - # is taken from a directory, not file. + # all the forks. If project list is taken from a file, forks have + # to be listed after the main project. # To enable system wide have in $GITWEB_CONFIG # $feature{'forks'}{'default'} = [1]; @@ -1047,6 +1047,8 @@ sub git_get_projects_list { $filter ||= ''; $filter =~ s/\.git$//; + my ($check_forks) = gitweb_check_feature('forks'); + if (-d $projects_list) { # search in directory my $dir = $projects_list . ($filter ? "/$filter" : ''); @@ -1054,8 +1056,6 @@ sub git_get_projects_list { $dir =~ s!/+$!!; my $pfxlen = length("$dir"); - my ($check_forks) = gitweb_check_feature('forks'); - File::Find::find({ follow_fast => 1, # follow symbolic links dangling_symlinks => 0, # ignore dangling symlinks, silently @@ -1081,7 +1081,9 @@ sub git_get_projects_list { # 'git%2Fgit.git Linus+Torvalds' # 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin' # 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman' + my %paths; open my ($fd), $projects_list or return; + PROJECT: while (my $line = <$fd>) { chomp $line; my ($path, $owner) = split ' ', $line; @@ -1094,11 +1096,27 @@ sub git_get_projects_list { # looking for forks; my $pfx = substr($path, 0, length($filter)); if ($pfx ne $filter) { - next; + next PROJECT; } my $sfx = substr($path, length($filter)); if ($sfx !~ /^\/.*\.git$/) { - next; + next PROJECT; + } + } elsif ($check_forks) { + PATH: + foreach my $filter (keys %paths) { + # looking for forks; + my $pfx = substr($path, 0, length($filter)); + if ($pfx ne $filter) { + next PATH; + } + my $sfx = substr($path, length($filter)); + if ($sfx !~ /^\/.*\.git$/) { + next PATH; + } + # is a fork, don't include it in + # the list + next PROJECT; } } if (check_export_ok("$projectroot/$path")) { @@ -1106,7 +1124,9 @@ sub git_get_projects_list { path => $path, owner => to_utf8($owner), }; - push @list, $pr + push @list, $pr; + (my $forks_path = $path) =~ s/\.git$//; + $paths{$forks_path}++; } } close $fd; -- cgit v1.3 From b06dcf8cb83a9b7655bad5f0f6d84e68fc78beb3 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Fri, 6 Apr 2007 23:58:24 +0200 Subject: gitweb: Allow configuring the default projects order and add order 'none' Introduce new configuration variable $default_projects_order that can be used to specify the default order of projects on the index page if no 'o' parameter is given. Allow a new value 'none' for order that will cause the projects to be in the order we learned about them. In case of reading the list of projects from a file, this should be the order as they are listed in the file. In case of reading the list of projects from a directory this will probably give random results depending on the filesystem in use. Signed-off-by: Frank Lichtenheld Acked-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 01a10b320e..c48b35aa39 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -71,6 +71,10 @@ our $logo_label = "git homepage"; # source of projects list our $projects_list = "++GITWEB_LIST++"; +# default order of projects list +# valid values are none, project, descr, owner, and age +our $default_projects_order = "project"; + # show repository only if this file exists # (only effective if this variable evaluates to true) our $export_ok = "++GITWEB_EXPORT_OK++"; @@ -1131,7 +1135,6 @@ sub git_get_projects_list { } close $fd; } - @list = sort {$a->{'path'} cmp $b->{'path'}} @list; return @list; } @@ -2618,7 +2621,7 @@ sub git_project_list_body { push @projects, $pr; } - $order ||= "project"; + $order ||= $default_projects_order; $from = 0 unless defined $from; $to = $#projects if (!defined $to || $#projects < $to); @@ -2977,7 +2980,7 @@ sub git_search_grep_body { sub git_project_list { my $order = $cgi->param('o'); - if (defined $order && $order !~ m/project|descr|owner|age/) { + if (defined $order && $order !~ m/none|project|descr|owner|age/) { die_error(undef, "Unknown order parameter"); } @@ -3000,7 +3003,7 @@ sub git_project_list { sub git_forks { my $order = $cgi->param('o'); - if (defined $order && $order !~ m/project|descr|owner|age/) { + if (defined $order && $order !~ m/none|project|descr|owner|age/) { die_error(undef, "Unknown order parameter"); } -- cgit v1.3 From 4280cde95fa4e3fb012eb6d0c239a7777baaf60c Mon Sep 17 00:00:00 2001 From: Martin Koegler Date: Sun, 22 Apr 2007 22:49:25 -0700 Subject: gitweb: Show "no difference" message for empty diff Currently, gitweb shows only header and footer, if no differences are found. This patch adds a "No differences found" message for the html output. Signed-off-by: Martin Koegler Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 4 ++++ gitweb/gitweb.perl | 3 +++ 2 files changed, 7 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 5e40292404..2b023bd98a 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -387,6 +387,10 @@ div.diff.incomplete { color: #cccccc; } +div.diff.nodifferences { + font-weight: bold; + color: #600000; +} div.index_include { border: solid #d9d8d1; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c48b35aa39..cbd8d03e64 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2398,6 +2398,7 @@ sub git_patchset_body { my ($fd, $difftree, $hash, $hash_parent) = @_; my $patch_idx = 0; + my $patch_number = 0; my $patch_line; my $diffinfo; my (%from, %to); @@ -2419,6 +2420,7 @@ sub git_patchset_body { # git diff header #assert($patch_line =~ m/^diff /) if DEBUG; #assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed + $patch_number++; push @diff_header, $patch_line; # extended diff header @@ -2581,6 +2583,7 @@ sub git_patchset_body { } continue { print "\n"; # class="patch" } + print "
No differences found
\n" if (!$patch_number); print "\n"; # class="patchset" } -- cgit v1.3 From e3ad95a8be82663d27cb501eaf9bad86a30f9cda Mon Sep 17 00:00:00 2001 From: Ismail Dönmez Date: Wed, 2 May 2007 00:12:13 +0300 Subject: gitweb: use decode_utf8 directly Using decode() tries to decode data that is already UTF-8 and borks, but decode_utf8 from Encode.pm has a built-in safety against that. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 45ac9d7121..12c2e6685e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -560,12 +560,6 @@ sub validate_refname { return $input; } -# very thin wrapper for decode("utf8", $str, Encode::FB_DEFAULT); -sub to_utf8 { - my $str = shift; - return decode("utf8", $str, Encode::FB_DEFAULT); -} - # quote unsafe chars, but keep the slash, even when it's not # correct, but quoted slashes look too horrible in bookmarks sub esc_param { @@ -590,7 +584,7 @@ sub esc_html ($;%) { my $str = shift; my %opts = @_; - $str = to_utf8($str); + $str = decode_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -604,7 +598,7 @@ sub esc_path { my $str = shift; my %opts = @_; - $str = to_utf8($str); + $str = decode_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -887,7 +881,7 @@ sub format_subject_html { if (length($short) < length($long)) { return $cgi->a({-href => $href, -class => "list subject", - -title => to_utf8($long)}, + -title => decode_utf8($long)}, esc_html($short) . $extra); } else { return $cgi->a({-href => $href, -class => "list subject"}, @@ -1104,7 +1098,7 @@ sub git_get_projects_list { if (check_export_ok("$projectroot/$path")) { my $pr = { path => $path, - owner => to_utf8($owner), + owner => decode_utf8($owner), }; push @list, $pr } @@ -1133,7 +1127,7 @@ sub git_get_project_owner { $pr = unescape($pr); $ow = unescape($ow); if ($pr eq $project) { - $owner = to_utf8($ow); + $owner = decode_utf8($ow); last; } } @@ -1607,7 +1601,7 @@ sub get_file_owner { } my $owner = $gcos; $owner =~ s/[,;].*$//; - return to_utf8($owner); + return decode_utf8($owner); } ## ...................................................................... @@ -1690,7 +1684,7 @@ sub git_header_html { my $title = "$site_name"; if (defined $project) { - $title .= " - " . to_utf8($project); + $title .= " - " . decode_utf8($project); if (defined $action) { $title .= "/$action"; if (defined $file_name) { @@ -1963,7 +1957,7 @@ sub git_print_page_path { print "
"; print $cgi->a({-href => href(action=>"tree", hash_base=>$hb), - -title => 'tree root'}, to_utf8("[$project]")); + -title => 'tree root'}, decode_utf8("[$project]")); print " / "; if (defined $name) { my @dirname = split '/', $name; @@ -2578,7 +2572,7 @@ sub git_project_list_body { ($pr->{'age'}, $pr->{'age_string'}) = @aa; if (!defined $pr->{'descr'}) { my $descr = git_get_project_description($pr->{'path'}) || ""; - $pr->{'descr_long'} = to_utf8($descr); + $pr->{'descr_long'} = decode_utf8($descr); $pr->{'descr'} = chop_str($descr, 25, 5); } if (!defined $pr->{'owner'}) { @@ -3610,7 +3604,7 @@ sub git_snapshot { $hash = git_get_head_hash($project); } - my $filename = to_utf8(basename($project)) . "-$hash.tar.$suffix"; + my $filename = decode_utf8(basename($project)) . "-$hash.tar.$suffix"; print $cgi->header( -type => "application/$ctype", -- cgit v1.3 From 78bc403aaffe4dc7854da118e977685b38bdc5b7 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 7 May 2007 01:10:03 +0200 Subject: gitweb: Add parsing of raw combined diff format to parse_difftree_raw_line Add parsing line of raw combined diff ("git diff-tree -c/-cc" output) as described in section "diff format for merges" in diff-format.txt to parse_difftree_raw_line subroutine. Returned hash (or hashref) has for combined diff 'nparents' key which holds number of parents in a merge. At keys 'from_mode' and 'from_id' there are arrayrefs holding modes and ids, respectively. There is no 'similarity' value, and there is only 'to_file' value and no 'from_file' value. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ba5cc43e5b..dfba399d8e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1495,6 +1495,17 @@ sub parse_difftree_raw_line { $res{'file'} = unquote($7); } } + # '::100755 100755 100755 60e79ca1b01bc8b057abe17ddab484699a7f5fdb 94067cc5f73388f33722d52ae02f44692bc07490 94067cc5f73388f33722d52ae02f44692bc07490 MR git-gui/git-gui.sh' + # combined diff (for merge commit) + elsif ($line =~ s/^(::+)((?:[0-7]{6} )+)((?:[0-9a-fA-F]{40} )+)([a-zA-Z]+)\t(.*)$//) { + $res{'nparents'} = length($1); + $res{'from_mode'} = [ split(' ', $2) ]; + $res{'to_mode'} = pop @{$res{'from_mode'}}; + $res{'from_id'} = [ split(' ', $3) ]; + $res{'to_id'} = pop @{$res{'from_id'}}; + $res{'status'} = [ split('', $4) ]; + $res{'to_file'} = unquote($5); + } # 'c512b523472485aef4fff9e57b229d9d243c967f' elsif ($line =~ m/^([0-9a-fA-F]{40})$/) { $res{'commit'} = $1; -- cgit v1.3 From ed224deac9436215f8c0b098baa0aecfcff1c293 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 7 May 2007 01:10:04 +0200 Subject: gitweb: Add combined diff support to git_difftree_body You have to pass all parents as final parameters of git_difftree_body subroutine; the number of parents of a diff must be equal to the number derived from parsing git-diff-tree output, raw combined diff for git_difftree_body to display combined diff correctly (but it is not checked). Currently the possibility of displaying diffree of combined diff is not used in gitweb code; git_difftree_body is always caled for ordinary diff, and with only one parent. Description of output for combined diff: ---------------------------------------- The difftree table for combined diff starts with a cell with pathname of changed blob (changed file), which if possible is hidden link (class="list") to the 'blob' view of final version (if it exists), like for difftree for ordinary diff. If file was deleted in the final commit then filename is not hyperlinked. There is no cell with single file status (new, deleted, mode change, rename), as for combined diff as there is no single status: different parents might have different status. If git_difftree_body was called from git_commitdiff (for 'commitdiff' action) there is inner link to anchor to appropriate fragment (patch) in patchset body; the "patch" link does not replace "diff" link like for ordinary diff. Each of "diff" links is in separate cell, contrary to output for ordinary diff in which all links are (at least for now) in a single cell. For each parent, if file was not present we leave cell empty. If file was deleted in the result, we provide link to 'blob' view. Otherwise we provide link to 'commitdiff' view, even if patch (diff) consist only of extended diff header, and contents is not changed (pure rename, pure mode change). The only difference is that link to "blobdiff" view with no contents change is with 'nochange' class. At last, there is provided link to current version of file as "blob" link, if the file was not deleted in the result, and lik to history of a file, if there exists one. (The link to file history might be confused, at least for now, by renames.) Note that git-diff-tree raw output dor combined diff does not provide filename before change for renames and copies; we use git_get_path_by_hash to get "src" filename for renames (this means additional call to git-ls-tree for a _whole_ tree). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 17 ++++++++ gitweb/gitweb.perl | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 136 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 2b023bd98a..e795b70b2b 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -181,6 +181,23 @@ table.diff_tree { font-family: monospace; } +table.combined.diff_tree td { + padding-right: 24px; +} + +table.combined.diff_tree td.link { + padding: 0px 2px; +} + +table.combined.diff_tree td.nochange a { + color: #6666ff; +} + +table.combined.diff_tree td.nochange a:hover, +table.combined.diff_tree td.nochange a:visited { + color: #d06666; +} + table.blame { border-collapse: collapse; } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index dfba399d8e..c6a2fef823 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1015,6 +1015,30 @@ sub git_get_hash_by_path { return $3; } +# get path of entry with given hash at given tree-ish (ref) +# used to get 'from' filename for combined diff (merge commit) for renames +sub git_get_path_by_hash { + my $base = shift || return; + my $hash = shift || return; + + local $/ = "\0"; + + open my $fd, "-|", git_cmd(), "ls-tree", '-r', '-t', '-z', $base + or return undef; + while (my $line = <$fd>) { + chomp $line; + + #'040000 tree 595596a6a9117ddba9fe379b6b012b558bac8423 gitweb' + #'100644 blob e02e90f0429be0d2a69b76571101f20b8f75530f gitweb/README' + if ($line =~ m/(?:[0-9]+) (?:.+) $hash\t(.+)$/) { + close $fd; + return $1; + } + } + close $fd; + return undef; +} + ## ...................................................................... ## git utility functions, directly accessing git repository @@ -2210,7 +2234,8 @@ sub git_print_tree_entry { ## functions printing large fragments of HTML sub git_difftree_body { - my ($difftree, $hash, $parent) = @_; + my ($difftree, $hash, @parents) = @_; + my ($parent) = $parents[0]; my ($have_blame) = gitweb_check_feature('blame'); print "
\n"; if ($#{$difftree} > 10) { @@ -2218,7 +2243,9 @@ sub git_difftree_body { } print "
\n"; - print "\n"; + print "
1 ? "combined " : "") . + "diff_tree\">\n"; my $alternate = 1; my $patchno = 0; foreach my $line (@{$difftree}) { @@ -2231,6 +2258,96 @@ sub git_difftree_body { } $alternate ^= 1; + if (exists $diff{'nparents'}) { # combined diff + + if ($diff{'to_id'} ne ('0' x 40)) { + # file exists in the result (child) commit + print "\n"; + } else { + print "\n"; + } + + if ($action eq 'commitdiff') { + # link to patch + $patchno++; + print "\n"; + } + + my $has_history = 0; + my $not_deleted = 0; + for (my $i = 0; $i < $diff{'nparents'}; $i++) { + my $hash_parent = $parents[$i]; + my $from_hash = $diff{'from_id'}[$i]; + my $from_path = undef; + my $status = $diff{'status'}[$i]; + + $has_history ||= ($status ne 'A'); + $not_deleted ||= ($status ne 'D'); + + if ($status eq 'R' || $status eq 'C') { + $from_path = git_get_path_by_hash($hash_parent, $from_hash); + } + + if ($status eq 'A') { + print "\n"; + } elsif ($status eq 'D') { + print "\n"; + } else { + if ($diff{'to_id'} eq $from_hash) { + print "\n"; + } + } + + print "\n"; + + print "\n"; + next; # instead of 'else' clause, to avoid extra indent + } + # else ordinary diff + my ($to_mode_oct, $to_mode_str, $to_file_type); my ($from_mode_oct, $from_mode_str, $from_file_type); if ($diff{'to_mode'} ne ('0' x 6)) { -- cgit v1.3 From e72c0eaf9bbdb2a9467f3f026b39b1c1755c1105 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 7 May 2007 01:10:05 +0200 Subject: gitweb: Add combined diff support to git_patchset_body Calling convention for combined diff similar to the one for git_difftree_body subroutine: difftree info (first parameter) must be result of calling git-diff-tree with -c/--cc option, and all parents of a commit must be passed as last parameters. See also description in "gitweb: Add combined diff support to git_difftree_body" This ability is not used yet. Generating "src" file name for renames in combined diff was separated into fill_from_file_info subroutine; git_difftree_body was modified to use it. Currently git_difftree_body and git_patchset_body fills this info separately. The from-file line in two-line from-file/to-file header is not hyperlinked: there can be more than one "from"/"src" file. This differs from HTML output of ordinary (not combined) diff. format_diff_line subroutine needs extra $from/$to parameters to format combined diff patch line correctly. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 221 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 181 insertions(+), 40 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c6a2fef823..53ae0b83f1 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -897,19 +897,34 @@ sub format_subject_html { sub format_diff_line { my $line = shift; my ($from, $to) = @_; - my $char = substr($line, 0, 1); my $diff_class = ""; chomp $line; - if ($char eq '+') { - $diff_class = " add"; - } elsif ($char eq "-") { - $diff_class = " rem"; - } elsif ($char eq "@") { - $diff_class = " chunk_header"; - } elsif ($char eq "\\") { - $diff_class = " incomplete"; + if ($from && $to && ref($from->{'href'}) eq "ARRAY") { + # combined diff + my $prefix = substr($line, 0, scalar @{$from->{'href'}}); + if ($line =~ m/^\@{3}/) { + $diff_class = " chunk_header"; + } elsif ($line =~ m/^\\/) { + $diff_class = " incomplete"; + } elsif ($prefix =~ tr/+/+/) { + $diff_class = " add"; + } elsif ($prefix =~ tr/-/-/) { + $diff_class = " rem"; + } + } else { + # assume ordinary diff + my $char = substr($line, 0, 1); + if ($char eq '+') { + $diff_class = " add"; + } elsif ($char eq '-') { + $diff_class = " rem"; + } elsif ($char eq '@') { + $diff_class = " chunk_header"; + } elsif ($char eq "\\") { + $diff_class = " incomplete"; + } } $line = untabify($line); if ($from && $to && $line =~ m/^\@{2} /) { @@ -930,6 +945,39 @@ sub format_diff_line { $line = "@@ $from_text $to_text @@" . "" . esc_html($section, -nbsp=>1) . ""; return "
$line
\n"; + } elsif ($from && $to && $line =~ m/^\@{3}/) { + my ($prefix, $ranges, $section) = $line =~ m/^(\@+) (.*?) \@+(.*)$/; + my (@from_text, @from_start, @from_nlines, $to_text, $to_start, $to_nlines); + + @from_text = split(' ', $ranges); + for (my $i = 0; $i < @from_text; ++$i) { + ($from_start[$i], $from_nlines[$i]) = + (split(',', substr($from_text[$i], 1)), 0); + } + + $to_text = pop @from_text; + $to_start = pop @from_start; + $to_nlines = pop @from_nlines; + + $line = "$prefix "; + for (my $i = 0; $i < @from_text; ++$i) { + if ($from->{'href'}[$i]) { + $line .= $cgi->a({-href=>"$from->{'href'}[$i]#l$from_start[$i]", + -class=>"list"}, $from_text[$i]); + } else { + $line .= $from_text[$i]; + } + $line .= " "; + } + if ($to->{'href'}) { + $line .= $cgi->a({-href=>"$to->{'href'}#l$to_start", + -class=>"list"}, $to_text); + } else { + $line .= $to_text; + } + $line .= " $prefix" . + "" . esc_html($section, -nbsp=>1) . ""; + return "
$line
\n"; } return "
" . esc_html($line, -nbsp=>1) . "
\n"; } @@ -2233,6 +2281,39 @@ sub git_print_tree_entry { ## ...................................................................... ## functions printing large fragments of HTML +sub fill_from_file_info { + my ($diff, @parents) = @_; + + $diff->{'from_file'} = [ ]; + $diff->{'from_file'}[$diff->{'nparents'} - 1] = undef; + for (my $i = 0; $i < $diff->{'nparents'}; $i++) { + if ($diff->{'status'}[$i] eq 'R' || + $diff->{'status'}[$i] eq 'C') { + $diff->{'from_file'}[$i] = + git_get_path_by_hash($parents[$i], $diff->{'from_id'}[$i]); + } + } + + return $diff; +} + +# parameters can be strings, or references to arrays of strings +sub from_ids_eq { + my ($a, $b) = @_; + + if (ref($a) eq "ARRAY" && ref($b) eq "ARRAY" && @$a == @$b) { + for (my $i = 0; $i < @$a; ++$i) { + return 0 unless ($a->[$i] eq $b->[$i]); + } + return 1; + } elsif (!ref($a) && !ref($b)) { + return $a eq $b; + } else { + return 0; + } +} + + sub git_difftree_body { my ($difftree, $hash, @parents) = @_; my ($parent) = $parents[0]; @@ -2260,6 +2341,8 @@ sub git_difftree_body { if (exists $diff{'nparents'}) { # combined diff + fill_from_file_info(\%diff, @parents); + if ($diff{'to_id'} ne ('0' x 40)) { # file exists in the result (child) commit print "
\n"; } elsif ($status eq 'D') { @@ -2517,7 +2596,8 @@ sub git_difftree_body { } sub git_patchset_body { - my ($fd, $difftree, $hash, $hash_parent) = @_; + my ($fd, $difftree, $hash, @hash_parents) = @_; + my ($hash_parent) = $hash_parents[0]; my $patch_idx = 0; my $patch_number = 0; @@ -2555,6 +2635,9 @@ sub git_patchset_body { if ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) { $from_id = $1; $to_id = $2; + } elsif ($patch_line =~ m/^index ((?:[0-9a-fA-F]{40},)+[0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) { + $from_id = [ split(',', $1) ]; + $to_id = $2; } push @diff_header, $patch_line; @@ -2564,8 +2647,8 @@ sub git_patchset_body { # check if current patch belong to current raw line # and parse raw git-diff line if needed if (defined $diffinfo && - $diffinfo->{'from_id'} eq $from_id && - $diffinfo->{'to_id'} eq $to_id) { + from_ids_eq($diffinfo->{'from_id'}, $from_id) && + $diffinfo->{'to_id'} eq $to_id) { # this is split patch print "
\n"; } else { @@ -2579,15 +2662,34 @@ sub git_patchset_body { } 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->{'nparents'}) { + # combined diff + $from{'file'} = []; + $from{'href'} = []; + fill_from_file_info($diffinfo, @hash_parents) + unless exists $diffinfo->{'from_file'}; + for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { + $from{'file'}[$i] = $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'}; + if ($diffinfo->{'status'}[$i] ne "A") { # not new (added) file + $from{'href'}[$i] = href(action=>"blob", + hash_base=>$hash_parents[$i], + hash=>$diffinfo->{'from_id'}[$i], + file_name=>$from{'file'}[$i]); + } else { + $from{'href'}[$i] = undef; + } + } } else { - delete $from{'href'}; + $from{'file'} = $diffinfo->{'from_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'}); + } else { + delete $from{'href'}; + } } + $to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; if ($diffinfo->{'status'} ne "D") { # not deleted file $to{'href'} = href(action=>"blob", hash_base=>$hash, hash=>$diffinfo->{'to_id'}, @@ -2602,19 +2704,34 @@ sub git_patchset_body { # print "git diff" header $patch_line = shift @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'}); + if ($diffinfo->{'nparents'}) { + + # combined diff + $patch_line =~ s!^(diff (.*?) )"?.*$!$1!; + if ($to{'href'}) { + $patch_line .= $cgi->a({-href => $to{'href'}, -class => "path"}, + esc_path($to{'file'})); + } else { # file was deleted + $patch_line .= esc_path($to{'file'}); + } + + } else { + + $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 "
$patch_line
\n"; @@ -2631,14 +2748,37 @@ sub git_patchset_body { $patch_line .= $cgi->a({-href=>$to{'href'}, -class=>"path"}, esc_path($to{'file'})); } - # match + # match single if ($patch_line =~ m/\s(\d{6})$/) { $patch_line .= ' (' . file_type_long($1) . ')'; } # match - if ($patch_line =~ m/^index/) { + if ($patch_line =~ m/^index [0-9a-fA-F]{40},[0-9a-fA-F]{40}/) { + # can match only for combined diff + $patch_line = 'index '; + for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { + if ($from{'href'}[$i]) { + $patch_line .= $cgi->a({-href=>$from{'href'}[$i], + -class=>"hash"}, + substr($diffinfo->{'from_id'}[$i],0,7)); + } else { + $patch_line .= '0' x 7; + } + # separator + $patch_line .= ',' if ($i < $diffinfo->{'nparents'} - 1); + } + $patch_line .= '..'; + if ($to{'href'}) { + $patch_line .= $cgi->a({-href=>$to{'href'}, -class=>"hash"}, + substr($diffinfo->{'to_id'},0,7)); + } else { + $patch_line .= '0' x 7; + } + + } elsif ($patch_line =~ m/^index [0-9a-fA-F]{40}..[0-9a-fA-F]{40}/) { + # can match only for ordinary diff my ($from_link, $to_link); if ($from{'href'}) { $from_link = $cgi->a({-href=>$from{'href'}, -class=>"hash"}, @@ -2674,7 +2814,8 @@ sub git_patchset_body { } next PATCH if ($patch_line =~ m/^diff /); #assert($patch_line =~ m/^---/) if DEBUG; - if ($from{'href'} && $patch_line =~ m!^--- "?a/!) { + if (!$diffinfo->{'nparents'} && # not from-file line for combined diff + $from{'href'} && $patch_line =~ m!^--- "?a/!) { $patch_line = '--- a/' . $cgi->a({-href=>$from{'href'}, -class=>"path"}, esc_path($from{'file'})); -- cgit v1.3 From 493e01db51ae003255a27dbcc81953fbfdab958a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 7 May 2007 01:10:06 +0200 Subject: gitweb: Make it possible to use pre-parsed info in git_difftree_body Make it possible to use pre-parsed, or generated by hand, difftree info in git_difftree_body, similarly to how was and is it done in git_patchset_body. Use just introduced feature in git_commitdiff to parse difftree info (raw diff output) only once: difftree info is now parsed in git_commitdiff directly, and parsed information is passed to both git_difftree_body and git_patchset_body. (Till now only git_blobdiff made use of git_patchset_body ability to use pre-parsed or hand generated info.) Additionally this makes rename info for combined diff with renames (or copies) calculated only once in git_difftree_body; the $difftree is modified and git_patchset_body makes use of added info. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 139 ++++++++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 66 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 53ae0b83f1..b3e2e07a2b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2330,7 +2330,13 @@ sub git_difftree_body { my $alternate = 1; my $patchno = 0; foreach my $line (@{$difftree}) { - my %diff = parse_difftree_raw_line($line); + my $diff; + if (ref($line) eq "HASH") { + # pre-parsed (or generated by hand) + $diff = $line; + } else { + $diff = parse_difftree_raw_line($line); + } if ($alternate) { print "
\n"; @@ -2339,21 +2345,22 @@ sub git_difftree_body { } $alternate ^= 1; - if (exists $diff{'nparents'}) { # combined diff + if (exists $diff->{'nparents'}) { # combined diff - fill_from_file_info(\%diff, @parents); + fill_from_file_info($diff, @parents) + unless exists $diff->{'from_file'}; - if ($diff{'to_id'} ne ('0' x 40)) { + if ($diff->{'to_id'} ne ('0' x 40)) { # file exists in the result (child) commit print "\n"; } else { print "\n"; } @@ -2368,11 +2375,11 @@ sub git_difftree_body { my $has_history = 0; my $not_deleted = 0; - for (my $i = 0; $i < $diff{'nparents'}; $i++) { + for (my $i = 0; $i < $diff->{'nparents'}; $i++) { my $hash_parent = $parents[$i]; - my $from_hash = $diff{'from_id'}[$i]; - my $from_path = $diff{'from_file'}[$i]; - my $status = $diff{'status'}[$i]; + my $from_hash = $diff->{'from_id'}[$i]; + my $from_path = $diff->{'from_file'}[$i]; + my $status = $diff->{'status'}[$i]; $has_history ||= ($status ne 'A'); $not_deleted ||= ($status ne 'D'); @@ -2388,17 +2395,17 @@ sub git_difftree_body { "blob" . ($i+1)) . " | \n"; } else { - if ($diff{'to_id'} eq $from_hash) { + if ($diff->{'to_id'} eq $from_hash) { print "\n"; @@ -2408,15 +2415,15 @@ sub git_difftree_body { print "\n"; print "\n"; print "\n"; - } elsif ($diff{'status'} eq "D") { # deleted + } elsif ($diff->{'status'} eq "D") { # deleted my $mode_chng = "[deleted $from_file_type]"; print "\n"; print "\n"; print "\n"; - } elsif ($diff{'status'} eq "M" || $diff{'status'} eq "T") { # modified, or type changed + } elsif ($diff->{'status'} eq "M" || $diff->{'status'} eq "T") { # modified, or type changed my $mode_chnge = ""; - if ($diff{'from_mode'} != $diff{'to_mode'}) { + if ($diff->{'from_mode'} != $diff->{'to_mode'}) { $mode_chnge = "[changed"; if ($from_file_type ne $to_file_type) { $mode_chnge .= " from $from_file_type to $to_file_type"; @@ -2511,9 +2518,9 @@ sub git_difftree_body { $mode_chnge .= "]\n"; } print "\n"; print "\n"; print "\n"; - } elsif ($diff{'status'} eq "R" || $diff{'status'} eq "C") { # renamed or copied + } elsif ($diff->{'status'} eq "R" || $diff->{'status'} eq "C") { # renamed or copied my %status_name = ('R' => 'moved', 'C' => 'copied'); - my $nstatus = $status_name{$diff{'status'}}; + my $nstatus = $status_name{$diff->{'status'}}; my $mode_chng = ""; - if ($diff{'from_mode'} != $diff{'to_mode'}) { + if ($diff->{'from_mode'} != $diff->{'to_mode'}) { # mode also for directories, so we cannot use $to_mode_str $mode_chng = sprintf(", mode: %04o", $to_mode_oct & 0777); } print "\n" . + hash=>$diff->{'to_id'}, file_name=>$diff->{'to_file'}), + -class => "list"}, esc_path($diff->{'to_file'})) . "\n" . "\n" . + hash=>$diff->{'from_id'}, file_name=>$diff->{'from_file'}), + -class => "list"}, esc_path($diff->{'from_file'})) . + " with " . (int $diff->{'similarity'}) . "% similarity$mode_chng]\n" . "\n"; @@ -4401,7 +4408,7 @@ sub git_commitdiff { chomp $line; # empty line ends raw part of diff-tree output last unless $line; - push @difftree, $line; + push @difftree, scalar parse_difftree_raw_line($line); } } elsif ($format eq 'plain') { -- cgit v1.3 From fb1dde4a908ddcfaa884f67734a60dc6bd639b59 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 7 May 2007 01:10:07 +0200 Subject: gitweb: Show combined diff for merge commits in 'commitdiff' view When 'commitdiff' action is requested without 'hp' (hash parent) parameter, and commit given by 'h' (hash) parameter is merge commit, show merge as combined diff. Earlier for merge commits without 'hp' parameter diff to first parent was shown. Note that in compact combined (--cc) format 'uninteresting' hunks omission mechanism can make that there is no patch corresponding to line in raw format (difftree) output. That is why (at least for now) we use --combined and not --cc format for showing commitdiff for merge commits. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b3e2e07a2b..c0e2473b40 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4391,8 +4391,10 @@ sub git_commitdiff { } } + my $hash_parent_param = $hash_parent; if (!defined $hash_parent) { - $hash_parent = $co{'parent'} || '--root'; + $hash_parent_param = + @{$co{'parents'}} > 1 ? '-c' : $co{'parent'} || '--root'; } # read commitdiff @@ -4401,7 +4403,7 @@ sub git_commitdiff { if ($format eq 'html') { open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, "--no-commit-id", "--patch-with-raw", "--full-index", - $hash_parent, $hash, "--" + $hash_parent_param, $hash, "--" or die_error(undef, "Open git-diff-tree failed"); while (my $line = <$fd>) { @@ -4413,7 +4415,7 @@ sub git_commitdiff { } elsif ($format eq 'plain') { open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, - '-p', $hash_parent, $hash, "--" + '-p', $hash_parent_param, $hash, "--" or die_error(undef, "Open git-diff-tree failed"); } else { @@ -4469,10 +4471,10 @@ TEXT # write patch if ($format eq 'html') { - git_difftree_body(\@difftree, $hash, $hash_parent); + git_difftree_body(\@difftree, $hash, $hash_parent || @{$co{'parents'}}); print "
\n"; - git_patchset_body($fd, \@difftree, $hash, $hash_parent); + git_patchset_body($fd, \@difftree, $hash, $hash_parent || @{$co{'parents'}}); close $fd; print "\n"; # class="page_body" git_footer_html(); -- cgit v1.3 From 208ecb2e860364aeffb22eb1f644db077b1c5162 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 7 May 2007 01:10:08 +0200 Subject: gitweb: Show combined diff for merge commits in 'commit' view When commit shown is a merge commit (has more than one parent), display combined difftree output (result of git-diff-tree -c). Earlier (since commit 549ab4a30703012ff3a12b5455d319216805a8db) difftree output (against first parent) was not printed for merges. Examples of non-trivial merges: 5bac4a671907604b5fb4e24ff682d5b0e8431931 (includes rename) addafaf92eeb86033da91323d0d3ad7a496dae83 (five parents) 95f97567c1887d77f3a46b42d8622c76414d964d (evil merge) Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c0e2473b40..90243fdf98 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4026,14 +4026,13 @@ sub git_commit { $parent = "--root"; } my @difftree; - if (@$parents <= 1) { - # difftree output is not printed for merges - open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id", - @diff_opts, $parent, $hash, "--" - or die_error(undef, "Open git-diff-tree failed"); - @difftree = map { chomp; $_ } <$fd>; - close $fd or die_error(undef, "Reading git-diff-tree failed"); - } + open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id", + @diff_opts, + (@$parents <= 1 ? $parent : '-c'), + $hash, "--" + or die_error(undef, "Open git-diff-tree failed"); + @difftree = map { chomp; $_ } <$fd>; + close $fd or die_error(undef, "Reading git-diff-tree failed"); # non-textual hash id's can be cached my $expires; @@ -4111,10 +4110,7 @@ sub git_commit { git_print_log($co{'comment'}); print "\n"; - if (@$parents <= 1) { - # do not output difftree/whatchanged for merges - git_difftree_body(\@difftree, $hash, $parent); - } + git_difftree_body(\@difftree, $hash, @$parents); git_footer_html(); } -- cgit v1.3 From 7f9778b19b07601ae8134fc4ff23b7bf7cac28bd Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Thu, 10 May 2007 07:32:07 +0000 Subject: gitweb: choose appropriate view for file type if a= parameter missing gitweb URLs use the a= parameter for the view to use on the given path, such as "blob" or "tree". Currently, if a gitweb URL omits the a= parameter, gitweb just shows the top-level repository summary, regardless of the path given. gitweb could instead choose an appropriate view based on the file type: blob for blobs (files), tree for trees (directories), and summary if no path given (the URL included no f= parameter, or an empty f= parameter). Apart from making gitweb more robust and supporting URL editing more easily, this change would aid the creation of shortcuts to git repositories using simple substitution, such as: http://example.org/git/?p=path/to/repo.git;hb=HEAD;f=%s With this patch, if given the hash through the h= parameter, or the hash base (hb=) and a filename (f=), gitweb uses cat-file -t to automatically set the a= parameter. This feature was requested by Josh Triplett through http://bugs.debian.org/410465 Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 90243fdf98..21864c62a9 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -458,10 +458,16 @@ my %actions = ( "project_index" => \&git_project_index, ); -if (defined $project) { - $action ||= 'summary'; -} else { - $action ||= 'project_list'; +if (!defined $action) { + if (defined $hash) { + $action = git_get_type($hash); + } elsif (defined $hash_base && defined $file_name) { + $action = git_get_type("$hash_base:$file_name"); + } elsif (defined $project) { + $action = 'summary'; + } else { + $action = 'project_list'; + } } if (!defined($actions{$action})) { die_error(undef, "Unknown action"); -- cgit v1.3 From 63fcbe00a66d7cb7d8bce9a36120a19a809a33b8 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Wed, 9 May 2007 03:41:50 +0200 Subject: gitweb: Do not use absolute font sizes Avoid specifying font sizes in pixels, since that is just pure evil. Pointed out by Chris Riddoch. Note that this is pretty much just a proposal; I didn't test if everything fits perfectly right, but things seem to be pretty much okay. repo.or.cz uses it now as a test drive - if you find any visual quirks, please point them out, with a patch if possible since I'm total CSS noob and debugging CSS is an extremely painful experience for me. Note that this patch actually does change visual look of gitweb in Firefox with my resolution and default settings - everything is bigger and I can't explain the joy of actually seeing gitweb text that is in _readable_ size; also, my horizontal screen real estate feels better used now. But judging from the look of most modern webpages on the 'net, most people prefer reading the web with strained eyes and/or a magnifying glass (I wonder what species of scientists should look into this mystifying phenomenon) - so, please tell us what you think. Maybe we might want to get rid of absolute sizes other than font sizes in the CSS file too in the long term. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index e795b70b2b..b57c8beccb 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -1,6 +1,5 @@ body { font-family: sans-serif; - font-size: 12px; border: solid #d9d8d1; border-width: 1px; margin: 10px; @@ -31,7 +30,7 @@ img.logo { div.page_header { height: 25px; padding: 8px; - font-size: 18px; + font-size: 150%; font-weight: bold; background-color: #d9d8d1; } @@ -113,7 +112,7 @@ span.signoff { div.log_link { padding: 0px 8px; - font-size: 10px; + font-size: 70%; font-family: sans-serif; font-style: normal; position: relative; @@ -204,13 +203,13 @@ table.blame { table.blame td { padding: 0px 5px; - font-size: 12px; + font-size: 100%; vertical-align: top; } th { padding: 2px 5px; - font-size: 12px; + font-size: 100%; text-align: left; } @@ -232,14 +231,14 @@ tr.dark:hover { td { padding: 2px 5px; - font-size: 12px; + font-size: 100%; vertical-align: top; } td.link, td.selflink { padding: 2px 5px; font-family: sans-serif; - font-size: 10px; + font-size: 70%; } td.selflink { @@ -416,7 +415,7 @@ div.index_include { } div.search { - font-size: 12px; + font-size: 100%; font-weight: normal; margin: 4px 8px; position: absolute; @@ -444,7 +443,7 @@ a.rss_logo { background-color: #ff6600; font-weight: bold; font-family: sans-serif; - font-size: 10px; + font-size: 70%; text-align: center; text-decoration: none; } @@ -455,7 +454,7 @@ a.rss_logo:hover { span.refs span { padding: 0px 4px; - font-size: 10px; + font-size: 70%; font-weight: normal; border: 1px solid; background-color: #ffaaff; -- cgit v1.3 From 2206537c07973fc2933092313d95340e076440e4 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 12 May 2007 12:42:32 +0200 Subject: gitweb: Test if $from_id and $to_id are defined before comparison Get rid of "Use of uninitialized value in string eq at gitweb/gitweb.perl line 2320" warning caused by the fact that "empty" patches, consisting only of extended git diff header and with patch body empty, such as patch for pure rename, does not have "index" line in extended diff header. For such patches $from_id and $to_id, filled from parsing extended diff header, are undefined. But such patches cannot be continuation patches. Test if $from_id and $to_id are defined before comparing them with $diffinfo. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 21864c62a9..fff01834de 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2660,9 +2660,10 @@ sub git_patchset_body { # check if current patch belong to current raw line # and parse raw git-diff line if needed if (defined $diffinfo && + defined $from_id && defined $to_id && from_ids_eq($diffinfo->{'from_id'}, $from_id) && $diffinfo->{'to_id'} eq $to_id) { - # this is split patch + # this is continuation of a split patch print "
\n"; } else { # advance raw git-diff output if needed -- cgit v1.3 From 198a2a8a69921327513c32512bdac77f52ab95d3 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 12 May 2007 21:16:34 +0200 Subject: gitweb: Check if requested object exists Try to avoid "Use of uninitialized value ..." errors caused by bad revision, incorrect filename, wrong object id, bad file etc. (wrong value of 'h', 'hb', 'f', etc. parameters). This avoids polluting web server errors log. Correct git_get_hash_by_path and parse_commit_text (and, in turn, parse_commit) to return undef if object does not exist. Check in git_tag if requested tag exists. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index fff01834de..d467bf372a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1060,6 +1060,11 @@ sub git_get_hash_by_path { my $line = <$fd>; close $fd or return undef; + if (!defined $line) { + # there is no tree or hash given by $path at $base + return undef; + } + #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c' $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/; if (defined $type && $type ne $2) { @@ -1376,8 +1381,12 @@ sub parse_commit_text { pop @commit_lines; # Remove '\0' + if (! @commit_lines) { + return; + } + my $header = shift @commit_lines; - if (!($header =~ m/^[0-9a-fA-F]{40}/)) { + if ($header !~ m/^[0-9a-fA-F]{40}/) { return; } ($co{'id'}, my @parents) = split ' ', $header; @@ -3409,6 +3418,11 @@ sub git_tag { git_header_html(); git_print_page_nav('','', $head,undef,$head); my %tag = parse_tag($hash); + + if (! %tag) { + die_error(undef, "Unknown tag object"); + } + git_print_header_div('commit', esc_html($tag{'name'}), $hash); print "
\n" . "
" . + $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, + file_name=>$diff{'to_file'}, + hash_base=>$hash), + -class => "list"}, esc_path($diff{'to_file'})) . + "" . + esc_path($diff{'to_file'}) . + "" . + $cgi->a({-href => "#patch$patchno"}, "patch") . + " | " . + " | " . + $cgi->a({-href => href(action=>"blob", + hash_base=>$hash, + hash=>$from_hash, + file_name=>$from_path)}, + "blob" . ($i+1)) . + " | "; + } + print $cgi->a({-href => href(action=>"blobdiff", + hash=>$diff{'to_id'}, + hash_parent=>$from_hash, + hash_base=>$hash, + hash_parent_base=>$hash_parent, + file_name=>$diff{'to_file'}, + file_parent=>$from_path)}, + "diff" . ($i+1)) . + " | "; + if ($not_deleted) { + print $cgi->a({-href => href(action=>"blob", + hash=>$diff{'to_id'}, + file_name=>$diff{'to_file'}, + hash_base=>$hash)}, + "blob"); + print " | " if ($has_history); + } + if ($has_history) { + print $cgi->a({-href => href(action=>"history", + file_name=>$diff{'to_file'}, + hash_base=>$hash)}, + "history"); + } + print "
" . @@ -2288,16 +2371,12 @@ sub git_difftree_body { for (my $i = 0; $i < $diff{'nparents'}; $i++) { my $hash_parent = $parents[$i]; my $from_hash = $diff{'from_id'}[$i]; - my $from_path = undef; + my $from_path = $diff{'from_file'}[$i]; my $status = $diff{'status'}[$i]; $has_history ||= ($status ne 'A'); $not_deleted ||= ($status ne 'D'); - if ($status eq 'R' || $status eq 'C') { - $from_path = git_get_path_by_hash($hash_parent, $from_hash); - } - if ($status eq 'A') { print " |
" . - $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - file_name=>$diff{'to_file'}, + $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + file_name=>$diff->{'to_file'}, hash_base=>$hash), - -class => "list"}, esc_path($diff{'to_file'})) . + -class => "list"}, esc_path($diff->{'to_file'})) . "" . - esc_path($diff{'to_file'}) . + esc_path($diff->{'to_file'}) . ""; } print $cgi->a({-href => href(action=>"blobdiff", - hash=>$diff{'to_id'}, + hash=>$diff->{'to_id'}, hash_parent=>$from_hash, hash_base=>$hash, hash_parent_base=>$hash_parent, - file_name=>$diff{'to_file'}, + file_name=>$diff->{'to_file'}, file_parent=>$from_path)}, "diff" . ($i+1)) . " | "; if ($not_deleted) { print $cgi->a({-href => href(action=>"blob", - hash=>$diff{'to_id'}, - file_name=>$diff{'to_file'}, + hash=>$diff->{'to_id'}, + file_name=>$diff->{'to_file'}, hash_base=>$hash)}, "blob"); print " | " if ($has_history); } if ($has_history) { print $cgi->a({-href => href(action=>"history", - file_name=>$diff{'to_file'}, + file_name=>$diff->{'to_file'}, hash_base=>$hash)}, "history"); } @@ -2429,29 +2436,29 @@ sub git_difftree_body { my ($to_mode_oct, $to_mode_str, $to_file_type); my ($from_mode_oct, $from_mode_str, $from_file_type); - if ($diff{'to_mode'} ne ('0' x 6)) { - $to_mode_oct = oct $diff{'to_mode'}; + if ($diff->{'to_mode'} ne ('0' x 6)) { + $to_mode_oct = oct $diff->{'to_mode'}; if (S_ISREG($to_mode_oct)) { # only for regular file $to_mode_str = sprintf("%04o", $to_mode_oct & 0777); # permission bits } - $to_file_type = file_type($diff{'to_mode'}); + $to_file_type = file_type($diff->{'to_mode'}); } - if ($diff{'from_mode'} ne ('0' x 6)) { - $from_mode_oct = oct $diff{'from_mode'}; + if ($diff->{'from_mode'} ne ('0' x 6)) { + $from_mode_oct = oct $diff->{'from_mode'}; if (S_ISREG($to_mode_oct)) { # only for regular file $from_mode_str = sprintf("%04o", $from_mode_oct & 0777); # permission bits } - $from_file_type = file_type($diff{'from_mode'}); + $from_file_type = file_type($diff->{'from_mode'}); } - if ($diff{'status'} eq "A") { # created + if ($diff->{'status'} eq "A") { # created my $mode_chng = "[new $to_file_type"; $mode_chng .= " with mode: $to_mode_str" if $to_mode_str; $mode_chng .= "]"; print ""; - print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - hash_base=>$hash, file_name=>$diff{'file'}), - -class => "list"}, esc_path($diff{'file'})); + print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + hash_base=>$hash, file_name=>$diff->{'file'}), + -class => "list"}, esc_path($diff->{'file'})); print "$mode_chng"; @@ -2461,17 +2468,17 @@ sub git_difftree_body { print $cgi->a({-href => "#patch$patchno"}, "patch"); print " | "; } - print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - hash_base=>$hash, file_name=>$diff{'file'})}, + print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + hash_base=>$hash, file_name=>$diff->{'file'})}, "blob"); print ""; - print $cgi->a({-href => href(action=>"blob", hash=>$diff{'from_id'}, - hash_base=>$parent, file_name=>$diff{'file'}), - -class => "list"}, esc_path($diff{'file'})); + print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'}, + hash_base=>$parent, file_name=>$diff->{'file'}), + -class => "list"}, esc_path($diff->{'file'})); print "$mode_chng"; @@ -2481,22 +2488,22 @@ sub git_difftree_body { print $cgi->a({-href => "#patch$patchno"}, "patch"); print " | "; } - print $cgi->a({-href => href(action=>"blob", hash=>$diff{'from_id'}, - hash_base=>$parent, file_name=>$diff{'file'})}, + print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'}, + hash_base=>$parent, file_name=>$diff->{'file'})}, "blob") . " | "; if ($have_blame) { print $cgi->a({-href => href(action=>"blame", hash_base=>$parent, - file_name=>$diff{'file'})}, + file_name=>$diff->{'file'})}, "blame") . " | "; } print $cgi->a({-href => href(action=>"history", hash_base=>$parent, - file_name=>$diff{'file'})}, + file_name=>$diff->{'file'})}, "history"); print ""; - print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - hash_base=>$hash, file_name=>$diff{'file'}), - -class => "list"}, esc_path($diff{'file'})); + print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + hash_base=>$hash, file_name=>$diff->{'file'}), + -class => "list"}, esc_path($diff->{'file'})); print "$mode_chnge"; @@ -2522,70 +2529,70 @@ sub git_difftree_body { $patchno++; print $cgi->a({-href => "#patch$patchno"}, "patch") . " | "; - } elsif ($diff{'to_id'} ne $diff{'from_id'}) { + } elsif ($diff->{'to_id'} ne $diff->{'from_id'}) { # "commit" view and modified file (not onlu mode changed) print $cgi->a({-href => href(action=>"blobdiff", - hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'}, + hash=>$diff->{'to_id'}, hash_parent=>$diff->{'from_id'}, hash_base=>$hash, hash_parent_base=>$parent, - file_name=>$diff{'file'})}, + file_name=>$diff->{'file'})}, "diff") . " | "; } - print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - hash_base=>$hash, file_name=>$diff{'file'})}, + print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + hash_base=>$hash, file_name=>$diff->{'file'})}, "blob") . " | "; if ($have_blame) { print $cgi->a({-href => href(action=>"blame", hash_base=>$hash, - file_name=>$diff{'file'})}, + file_name=>$diff->{'file'})}, "blame") . " | "; } print $cgi->a({-href => href(action=>"history", hash_base=>$hash, - file_name=>$diff{'file'})}, + file_name=>$diff->{'file'})}, "history"); print "" . $cgi->a({-href => href(action=>"blob", hash_base=>$hash, - hash=>$diff{'to_id'}, file_name=>$diff{'to_file'}), - -class => "list"}, esc_path($diff{'to_file'})) . "[$nstatus from " . $cgi->a({-href => href(action=>"blob", hash_base=>$parent, - hash=>$diff{'from_id'}, file_name=>$diff{'from_file'}), - -class => "list"}, esc_path($diff{'from_file'})) . - " with " . (int $diff{'similarity'}) . "% similarity$mode_chng]"; if ($action eq 'commitdiff') { # link to patch $patchno++; print $cgi->a({-href => "#patch$patchno"}, "patch") . " | "; - } elsif ($diff{'to_id'} ne $diff{'from_id'}) { + } elsif ($diff->{'to_id'} ne $diff->{'from_id'}) { # "commit" view and modified file (not only pure rename or copy) print $cgi->a({-href => href(action=>"blobdiff", - hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'}, + hash=>$diff->{'to_id'}, hash_parent=>$diff->{'from_id'}, hash_base=>$hash, hash_parent_base=>$parent, - file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})}, + file_name=>$diff->{'to_file'}, file_parent=>$diff->{'from_file'})}, "diff") . " | "; } - print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'}, - hash_base=>$parent, file_name=>$diff{'to_file'})}, + print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, + hash_base=>$parent, file_name=>$diff->{'to_file'})}, "blob") . " | "; if ($have_blame) { print $cgi->a({-href => href(action=>"blame", hash_base=>$hash, - file_name=>$diff{'to_file'})}, + file_name=>$diff->{'to_file'})}, "blame") . " | "; } print $cgi->a({-href => href(action=>"history", hash_base=>$hash, - file_name=>$diff{'to_file'})}, + file_name=>$diff->{'to_file'})}, "history"); print "
\n" . -- cgit v1.3 From 785cdea9befecc63b2b576c8042c5482fbf7bceb Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 13 May 2007 12:39:22 +0200 Subject: gitweb: Fix "Use of unitialized value" warnings in empty repository Fix it so gitweb doesn't write "Use of unitialized value..." warnings (which gets written in web server logs) for empty (no commits) repository. In empty repository "last change" (last activity) doesn't make sense; also there is no sense in parsing commits which aren't there. In projects list for empty repositories gitweb now writes "No commits" using "noage" class, instead of leaving cell empty, in the last change column. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d467bf372a..c2eeca9fa0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -728,7 +728,9 @@ sub chop_str { sub age_class { my $age = shift; - if ($age < 60*60*2) { + if (!defined $age) { + return "noage"; + } elsif ($age < 60*60*2) { return "age0"; } elsif ($age < 60*60*24*2) { return "age1"; @@ -1258,7 +1260,8 @@ sub git_get_last_activity { 'refs/heads') or return; my $most_recent = <$fd>; close $fd or return; - if ($most_recent =~ / (\d+) [-+][01]\d\d\d$/) { + if (defined $most_recent && + $most_recent =~ / (\d+) [-+][01]\d\d\d$/) { my $timestamp = $1; my $age = time - $timestamp; return ($age, age_string($age)); @@ -2983,7 +2986,7 @@ sub git_project_list_body { esc_html($pr->{'descr'})) . "\n" . "\n"; print "\n" . + (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "\n" . "\n" . "\n"; @@ -4132,8 +4201,6 @@ sub git_blob { } sub git_tree { - my $have_snapshot = gitweb_have_snapshot(); - if (!defined $hash_base) { $hash_base = "HEAD"; } @@ -4167,11 +4234,10 @@ sub git_tree { hash_base=>"HEAD", file_name=>$file_name)}, "HEAD"), } - if ($have_snapshot) { + my $snapshot_links = format_snapshot_links($hash); + if (defined $snapshot_links) { # FIXME: Should be available when we have no hash base as well. - push @views_nav, - $cgi->a({-href => href(action=>"snapshot", hash=>$hash)}, - "snapshot"); + push @views_nav, $snapshot_links; } git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav)); git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base); @@ -4235,33 +4301,36 @@ sub git_tree { } sub git_snapshot { - my ($ctype, $suffix, $command) = gitweb_check_feature('snapshot'); - my $have_snapshot = (defined $ctype && defined $suffix); - if (!$have_snapshot) { - die_error('403 Permission denied', "Permission denied"); + my @supported_fmts = gitweb_check_feature('snapshot'); + + my $format = $cgi->param('sf'); + unless ($format =~ m/[a-z0-9]+/ + && exists($known_snapshot_formats{$format}) + && grep($_ eq $format, @supported_fmts)) { + die_error(undef, "Unsupported snapshot format"); } if (!defined $hash) { $hash = git_get_head_hash($project); } - my $git = git_cmd_str(); + my $git_command = git_cmd_str(); my $name = $project; $name =~ s,([^/])/*\.git$,$1,; $name = basename($name); my $filename = to_utf8($name); $name =~ s/\047/\047\\\047\047/g; my $cmd; - if ($suffix eq 'zip') { - $filename .= "-$hash.$suffix"; - $cmd = "$git archive --format=zip --prefix=\'$name\'/ $hash"; - } else { - $filename .= "-$hash.tar.$suffix"; - $cmd = "$git archive --format=tar --prefix=\'$name\'/ $hash | $command"; + $filename .= "-$hash$known_snapshot_formats{$format}{'suffix'}"; + $cmd = "$git_command archive " . + "--format=$known_snapshot_formats{$format}{'format'}" . + "--prefix=\'$name\'/ $hash"; + if (exists $known_snapshot_formats{$format}{'compressor'}) { + $cmd .= ' | ' . join ' ', @{$known_snapshot_formats{$format}{'compressor'}}; } print $cgi->header( - -type => "application/$ctype", + -type => $known_snapshot_formats{$format}{'type'}, -content_disposition => 'inline; filename="' . "$filename" . '"', -status => '200 OK'); @@ -4271,7 +4340,6 @@ sub git_snapshot { print <$fd>; binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi close $fd; - } sub git_log { @@ -4390,8 +4458,6 @@ sub git_commit { my $refs = git_get_references(); my $ref = format_ref_marker($refs, $co{'id'}); - my $have_snapshot = gitweb_have_snapshot(); - git_header_html(undef, $expires); git_print_page_nav('commit', '', $hash, $co{'tree'}, $hash, @@ -4430,9 +4496,9 @@ sub git_commit { "" . "\n"; -- cgit v1.3 From a781785d8f1eb7adf05a24b121104716a086a67a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 22 Jul 2007 23:41:20 +0200 Subject: gitweb: Fix support for legacy gitweb config for snapshots Earlier commit which cleaned up snapshot support and introduced support for multiple snapshot formats changed the format of $feature{'snapshot'}{'default'} (gitweb configuration) and gitweb.snapshot configuration variable (repository configuration). It supported old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip' and tried to support, but failed to do that, old values of $feature{'snapshot'}{'default'}; at least those corresponding to old gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e. ['x-gzip', 'gz', 'gzip'] ['x-bzip2', 'bz2', 'bzip2'] ['x-zip', 'zip', ''] This commit moves legacy configuration support out of feature_snapshot subroutine to separate filter_snapshot_fmts subroutine. The filter_snapshot_fmts is used on result on result of gitweb_check_feature('snapshot'). This way feature_snapshot deals _only_ with repository config. As a byproduct you can now use 'gzip' and 'bzip2' as aliases to 'tgz' and 'tbz2' also in $feature{'snapshot'}{'default'}, not only in gitweb.snapshot. While at it do some whitespace cleanup: use tabs for indent, but spaces for align. Noticed-by: Matt McCutchen Signed-off-by: Jakub Narebski Tested-by: Matt McCutchen Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c4f88245aa..fdfce311fd 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -307,10 +307,6 @@ sub feature_snapshot { if ($val) { @fmts = ($val eq 'none' ? () : split /\s*[,\s]\s*/, $val); - @fmts = grep { defined } map { - exists $known_snapshot_format_aliases{$_} ? - $known_snapshot_format_aliases{$_} : $_ } @fmts; - @fmts = grep(exists $known_snapshot_formats{$_}, @fmts); } return @fmts; @@ -356,6 +352,18 @@ sub check_export_ok { (!$export_ok || -e "$dir/$export_ok")); } +# process alternate names for backward compatibility +# filter out unsupported (unknown) snapshot formats +sub filter_snapshot_fmts { + my @fmts = @_; + + @fmts = map { + exists $known_snapshot_format_aliases{$_} ? + $known_snapshot_format_aliases{$_} : $_} @fmts; + @fmts = grep(exists $known_snapshot_formats{$_}, @fmts); + +} + our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++"; do $GITWEB_CONFIG if -e $GITWEB_CONFIG; @@ -1299,9 +1307,11 @@ sub format_diff_line { sub format_snapshot_links { my ($hash) = @_; my @snapshot_fmts = gitweb_check_feature('snapshot'); + @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts); my $num_fmts = @snapshot_fmts; if ($num_fmts > 1) { # A parenthesized list of links bearing format names. + # e.g. "snapshot (_tar.gz_ _zip_)" return "snapshot (" . join(' ', map $cgi->a({ -href => href( @@ -1313,8 +1323,10 @@ sub format_snapshot_links { , @snapshot_fmts) . ")"; } elsif ($num_fmts == 1) { # A single "snapshot" link whose tooltip bears the format name. + # i.e. "_snapshot_" my ($fmt) = @snapshot_fmts; - return $cgi->a({ + return + $cgi->a({ -href => href( action=>"snapshot", hash=>$hash, @@ -4302,11 +4314,12 @@ sub git_tree { sub git_snapshot { my @supported_fmts = gitweb_check_feature('snapshot'); + @supported_fmts = filter_snapshot_fmts(@supported_fmts); my $format = $cgi->param('sf'); unless ($format =~ m/[a-z0-9]+/ - && exists($known_snapshot_formats{$format}) - && grep($_ eq $format, @supported_fmts)) { + && exists($known_snapshot_formats{$format}) + && grep($_ eq $format, @supported_fmts)) { die_error(undef, "Unsupported snapshot format"); } -- cgit v1.3 From 3473e7df5f8c7f8dc3e2c3f2fdc99a1d1a719c16 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Wed, 25 Jul 2007 01:19:58 +0200 Subject: gitweb: More detailed error messages for snapshot format Improve error messages for snapshot format in git_snapshot: distinguish between situation where snapshots are turned off, where snapshot format ('sf') parameter is invalid, where given snapshot format does not exist in %known_snapshot_formats hash, and where gitweb was given unsupported snapshot format. While at it, use first from all supported snapshots format as default, if no snapshot format was provided. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index fdfce311fd..0acd0cafb3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4317,9 +4317,16 @@ sub git_snapshot { @supported_fmts = filter_snapshot_fmts(@supported_fmts); my $format = $cgi->param('sf'); - unless ($format =~ m/[a-z0-9]+/ - && exists($known_snapshot_formats{$format}) - && grep($_ eq $format, @supported_fmts)) { + if (!@supported_fmts) { + die_error('403 Permission denied', "Permission denied"); + } + # default to first supported snapshot format + $format ||= $supported_fmts[0]; + if ($format !~ m/^[a-z0-9]+$/) { + die_error(undef, "Invalid snapshot format parameter"); + } elsif (!exists($known_snapshot_formats{$format})) { + die_error(undef, "Unknown snapshot format"); + } elsif (!grep($_ eq $format, @supported_fmts)) { die_error(undef, "Unsupported snapshot format"); } -- cgit v1.3 From 887c5266d64e0a724986af1610985bb42af5bd47 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 25 Jul 2007 15:49:55 -0700 Subject: gitweb: fix broken snapshot Recent updates to snapshot code had a typo that broke the command line to invoke underlying "git archive" command. This is a simple typofix for it. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 0acd0cafb3..b381692119 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4343,7 +4343,7 @@ sub git_snapshot { my $cmd; $filename .= "-$hash$known_snapshot_formats{$format}{'suffix'}"; $cmd = "$git_command archive " . - "--format=$known_snapshot_formats{$format}{'format'}" . + "--format=$known_snapshot_formats{$format}{'format'} " . "--prefix=\'$name\'/ $hash"; if (exists $known_snapshot_formats{$format}{'compressor'}) { $cmd .= ' | ' . join ' ', @{$known_snapshot_formats{$format}{'compressor'}}; -- cgit v1.3 From 01ac1e38dbb1ae3ad3c4bbea60a9c0855606ae11 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 28 Jul 2007 16:27:31 +0200 Subject: gitweb: Show submodule entries in the 'tree' view Add S_ISGITLINK subroutine and S_IFGITLINK, S_IFINVALID constants. Add support for "commit" (submodule) entries in the tree object to mode_str ('m---------', following cgit), file_type and file_type_long ('submodule') subroutines. There is only link to the history of submodule entry in the supermodule (current repository) for now, because gitweb doesn't know where to search for submodule repository objects. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b381692119..1aceedec8e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -890,11 +890,25 @@ sub age_string { return $age_str; } +use constant { + S_IFINVALID => 0030000, + S_IFGITLINK => 0160000, +}; + +# submodule/subproject, a commit object reference +sub S_ISGITLINK($) { + my $mode = shift; + + return (($mode & S_IFMT) == S_IFGITLINK) +} + # convert file mode in octal to symbolic file mode string sub mode_str { my $mode = oct shift; - if (S_ISDIR($mode & S_IFMT)) { + if (S_ISGITLINK($mode)) { + return 'm---------'; + } elsif (S_ISDIR($mode & S_IFMT)) { return 'drwxr-xr-x'; } elsif (S_ISLNK($mode)) { return 'lrwxrwxrwx'; @@ -920,7 +934,9 @@ sub file_type { $mode = oct $mode; } - if (S_ISDIR($mode & S_IFMT)) { + if (S_ISGITLINK($mode)) { + return "submodule"; + } elsif (S_ISDIR($mode & S_IFMT)) { return "directory"; } elsif (S_ISLNK($mode)) { return "symlink"; @@ -941,7 +957,9 @@ sub file_type_long { $mode = oct $mode; } - if (S_ISDIR($mode & S_IFMT)) { + if (S_ISGITLINK($mode)) { + return "submodule"; + } elsif (S_ISDIR($mode & S_IFMT)) { return "directory"; } elsif (S_ISLNK($mode)) { return "symlink"; @@ -2707,6 +2725,20 @@ sub git_print_tree_entry { "history"); } print "\n"; + } else { + # unknown object: we can only present history for it + # (this includes 'commit' object, i.e. submodule support) + print "\n"; + print "\n"; } } -- cgit v1.3 From 12075103ddc9a061cf6f3b04feb206123bb78e2f Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 28 Jul 2007 16:27:32 +0200 Subject: gitweb: Simplify 'opt' parameter validation, add "no merges" feeds Simplify and make more readable validation of 'opt' (extra options) parameter, using exists($hash{key}) instead of grepping keys of a hash for value. Move 'opt' parameter to be the last (for now) in the URL. Make use of '--no-merges' extra option ('opt') by adding "no merges" RSS and Atom feeds to the HTML header. Note that alternate format links in the RSS and Atom views do not use '--no-merges' option yet! Adds tests for the 'opt' parameter to t9500-gitweb-standalone-no-errors.sh Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 17 ++++++++++++----- t/t9500-gitweb-standalone-no-errors.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 1aceedec8e..8a32899655 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -436,12 +436,11 @@ my %allowed_options = ( our @extra_options = $cgi->param('opt'); if (defined @extra_options) { - foreach(@extra_options) - { - if (not grep(/^$_$/, keys %allowed_options)) { + foreach my $opt (@extra_options) { + if (not exists $allowed_options{$opt}) { die_error(undef, "Invalid option parameter"); } - if (not grep(/^$action$/, @{$allowed_options{$_}})) { + if (not grep(/^$action$/, @{$allowed_options{$opt}})) { die_error(undef, "Invalid option parameter for this action"); } } @@ -598,7 +597,6 @@ sub href(%) { action => "a", file_name => "f", file_parent => "fp", - extra_options => "opt", hash => "h", hash_parent => "hp", hash_base => "hb", @@ -608,6 +606,7 @@ sub href(%) { searchtext => "s", searchtype => "st", snapshot_format => "sf", + extra_options => "opt", ); my %mapping = @mapping; @@ -2285,9 +2284,17 @@ EOF printf(''."\n", esc_param($project), href(action=>"rss")); + printf(''."\n", + esc_param($project), href(action=>"rss", + extra_options=>"--no-merges")); printf(''."\n", esc_param($project), href(action=>"atom")); + printf(''."\n", + esc_param($project), href(action=>"atom", + extra_options=>"--no-merges")); } else { printf(''."\n", diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index d948724566..fa32598b0c 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -521,4 +521,32 @@ test_expect_success \ 'gitweb_run "p=.git;a=log"' test_debug 'cat gitweb.log' +# ---------------------------------------------------------------------- +# extra options + +test_expect_success \ + 'opt: log --no-merges' \ + 'gitweb_run "p=.git;a=log;opt=--no-merges"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: atom --no-merges' \ + 'gitweb_run "p=.git;a=log;opt=--no-merges"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: "file" history --no-merges' \ + 'gitweb_run "p=.git;a=history;f=file;opt=--no-merges"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: log --no-such-option (invalid option)' \ + 'gitweb_run "p=.git;a=log;opt=--no-such-option"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: tree --no-merges (invalid option for action)' \ + 'gitweb_run "p=.git;a=tree;opt=--no-merges"' +test_debug 'cat gitweb.log' + test_done -- cgit v1.3 From f22cca44ba5022d93bfd895ec08682fbda7efb8c Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 29 Jul 2007 01:04:09 +0200 Subject: gitweb: Allow for multivalued parameters passed to href subroutine Make it possible to generate URLs with multivalued parameters in the href() subroutine, via passing reference to array of values. Example: href(action=>"log", extra_options=>["--no-merges", "--first-parent"]) Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8a32899655..498b936dd4 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -629,7 +629,13 @@ sub href(%) { for (my $i = 0; $i < @mapping; $i += 2) { my ($name, $symbol) = ($mapping[$i], $mapping[$i+1]); if (defined $params{$name}) { - push @result, $symbol . "=" . esc_param($params{$name}); + if (ref($params{$name}) eq "ARRAY") { + foreach my $par (@{$params{$name}}) { + push @result, $symbol . "=" . esc_param($par); + } + } else { + push @result, $symbol . "=" . esc_param($params{$name}); + } } } $href .= "?" . join(';', @result) if scalar @result; -- cgit v1.3 From d20602eec97caa8766820150eff2a07e205c44e1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 27 Jul 2007 01:23:03 -0700 Subject: gitweb: do not choke on recursive symlink If somebody used to advertise his repository that physically resides at /pub/lic.git/ as: git://git.example.com/pub/lic.git/ but now wants to use --base-path to allow: git://git.example.com/lic.git/ she can start git-daemon with --base-path option, like this: git-daemon --base-path=/pub --export-all During the transition, however, she would also want to allow older URL as well. One natural way to achieve that is to create a symlink: ln -s /pub /pub/pub so that a request to git://git.example.com/pub/lic.git/ is first translated by --base-path to a request to /pub/pub/lic.git/ which goes to /pub/lic.git, thanks to the symlink. So far so good. However, gitweb chokes if there is such a symlink (File::Find barfs with "/pub/pub is a recursive symbolic link"). Make the code ignore such a symlink. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 1 + 1 file changed, 1 insertion(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 498b936dd4..077eb2f4ca 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1515,6 +1515,7 @@ sub git_get_projects_list { File::Find::find({ follow_fast => 1, # follow symbolic links + follow_skip => 2, # ignore duplicates dangling_symlinks => 0, # ignore dangling symlinks, silently wanted => sub { # skip project-list toplevel, if we get it. -- cgit v1.3 From 33f243308589120a700f084b54ee597ce6c26069 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 3 Aug 2007 19:50:42 +0200 Subject: gitweb: Fix handling of $file_name in feed generation The commit b6093a5c, by Robert Fitzsimons: "gitweb: Change atom, rss actions to use parse_commits." forgot to pass $file_name parameter to parse_commits subroutine. If git_feed is provided a file name, it ought to show only the history affecting that file or a directory. The title was being set correctly, but all commits from history were being shown. Signed-off-by: Steven Walter Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 077eb2f4ca..f282a677aa 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5366,7 +5366,7 @@ sub git_feed { # log/feed of current (HEAD) branch, log of given branch, history of file/directory my $head = $hash || 'HEAD'; - my @commitlist = parse_commits($head, 150); + my @commitlist = parse_commits($head, 150, 0, undef, $file_name); my %latest_commit; my %latest_date; -- cgit v1.3 From 67aca456a3cfa9ab8420a6e171d8eee7b0ad2209 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sun, 26 Aug 2007 21:31:32 +0200 Subject: gitweb: Fix searchbox positioning Currently, searchbox is CSS'd to have position: absolute, which has the unfortunate consequence that if the viewport is too small and can't fit into the page width together with the navbar, it gets overlapped and part of the navbar gets obscured. This makes searchbox float: right instead, thus the navbar simply gets wrapped. Discovered and fix pointed out by Michael Olson . Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 096313bec0..1b8887987f 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -430,7 +430,7 @@ div.search { font-size: 100%; font-weight: normal; margin: 4px 8px; - position: absolute; + float: right; top: 56px; right: 12px } -- cgit v1.3 From 7d479624d47a3deff1245a70521180c57b4ff3c1 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sun, 26 Aug 2007 00:18:47 +0200 Subject: gitweb: Lift any characters restriction on searched strings Everything is already fully quoted along the way so I believe this to be unnecessary at this point. It would pose trouble for regexp searches. Signed-off-by: Petr Baudis Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 --- 1 file changed, 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f282a677aa..18042843d6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -471,9 +471,6 @@ if (defined $searchtype) { our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { - if ($searchtype ne 'grep' and $searchtype ne 'pickaxe' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { - die_error(undef, "Invalid search parameter"); - } if (length($searchtext) < 2) { die_error(undef, "At least two characters are required for search parameter"); } -- cgit v1.3 From ce312affa1487b2b3857da7de5cca35d35f3baa7 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 28 Aug 2007 16:05:43 +0200 Subject: gitweb: Fix escaping HTML of project owner in 'projects_list' and 'summary' views This for example allows to put email address in the project owner field in the projects index file (when $projects_list points to a file, and not to a directory), in the form of: path/to/repo.git Random+J+Developer+ Noticed-by: Jon Smirl Signed-off-by: Jakub Narebski Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 18042843d6..b2bae1b250 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3419,7 +3419,7 @@ sub git_project_list_body { "\n" . - "\n"; + "\n"; print "\n" . " table row element. It was done to make it easier to manipulate result HTML with DOM, and to be able write 'blame_incremental' view with the same, or nearly the same result. Signed-off-by: Jakub Narebski Acked-by: Luben Tuikov Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 951739210a..e01e1afe95 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4645,7 +4645,7 @@ HTML if ($group_size) { $current_color = ++$current_color % $num_colors; } - print "\n"; + print "\n"; if ($group_size) { print ""; -- cgit v1.3 From d2ce10d7b7d67ff8b50ae749ce4c5b1a2b8d133c Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 9 Dec 2008 23:48:51 +0100 Subject: gitweb: A bit of code cleanup in git_blame() Among others, here are the highlights: * move variable declaration closer to the place it is set and used, if possible, * uniquify and simplify coding style a bit, which includes removing unnecessary '()'. * check type only if $hash was defined, as otherwise from the way git_get_hash_by_path() is called (and works), we know that it is a blob, * use modern calling convention for git-blame, * remove unused variable, * don't use implicit variables ($_), * add some comments Signed-off-by: Jakub Narebski Acked-by: Luben Tuikov Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 67 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 28 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e01e1afe95..ccbf5d4745 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4575,28 +4575,33 @@ sub git_tag { } sub git_blame { - my $fd; - my $ftype; - + # permissions gitweb_check_feature('blame') - or die_error(403, "Blame view not allowed"); + or die_error(403, "Blame view not allowed"); + # error checking die_error(400, "No file name given") unless $file_name; $hash_base ||= git_get_head_hash($project); - die_error(404, "Couldn't find base commit") unless ($hash_base); + die_error(404, "Couldn't find base commit") unless $hash_base; my %co = parse_commit($hash_base) or die_error(404, "Commit not found"); + my $ftype = "blob"; if (!defined $hash) { $hash = git_get_hash_by_path($hash_base, $file_name, "blob") or die_error(404, "Error looking up file"); + } else { + $ftype = git_get_type($hash); + if ($ftype !~ "blob") { + die_error(400, "Object is not a blob"); + } } - $ftype = git_get_type($hash); - if ($ftype !~ "blob") { - die_error(400, "Object is not a blob"); - } - open ($fd, "-|", git_cmd(), "blame", '-p', '--', - $file_name, $hash_base) + + # run git-blame --porcelain + open my $fd, "-|", git_cmd(), "blame", '-p', + $hash_base, '--', $file_name or die_error(500, "Open git-blame failed"); + + # page header git_header_html(); my $formats_nav = $cgi->a({-href => href(action=>"blob", -replay=>1)}, @@ -4610,40 +4615,44 @@ sub git_blame { git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav); git_print_header_div('commit', esc_html($co{'title'}), $hash_base); git_print_page_path($file_name, $ftype, $hash_base); - my @rev_color = (qw(light2 dark2)); + + # page body + my @rev_color = qw(light2 dark2); my $num_colors = scalar(@rev_color); my $current_color = 0; - my $last_rev; + my %metainfo = (); + print <
" . chop_str($pr->{'owner'}, 15) . "{'age'}) . "\">" . - $pr->{'age_string'} . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " . @@ -3335,7 +3338,7 @@ sub git_project_index { sub git_summary { my $descr = git_get_project_description($project) || "none"; my %co = parse_commit("HEAD"); - my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'}); + my %cd = %co ? parse_date($co{'committer_epoch'}, $co{'committer_tz'}) : (); my $head = $co{'id'}; my $owner = git_get_project_owner($project); @@ -3358,8 +3361,11 @@ sub git_summary { print "
 
\n"; print "\n" . "\n" . - "\n" . - "\n"; + "\n"; + if (defined $cd{'rfc2822'}) { + print "\n"; + } + # use per project git URL list in $projectroot/$project/cloneurl # or make project git URL from git base URL and project name my $url_tag = "URL"; @@ -3382,11 +3388,13 @@ sub git_summary { # we need to request one more than 16 (0..15) to check if # those 16 are all - my @commitlist = parse_commits($head, 17); - git_print_header_div('shortlog'); - git_shortlog_body(\@commitlist, 0, 15, $refs, - $#commitlist <= 15 ? undef : - $cgi->a({-href => href(action=>"shortlog")}, "...")); + my @commitlist = $head ? parse_commits($head, 17) : (); + if (@commitlist) { + git_print_header_div('shortlog'); + git_shortlog_body(\@commitlist, 0, 15, $refs, + $#commitlist <= 15 ? undef : + $cgi->a({-href => href(action=>"shortlog")}, "...")); + } if (@taglist) { git_print_header_div('tags'); -- cgit v1.3 From b4b20b2164e433fead84beb526b713a889fc31df Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 15 May 2007 01:55:44 +0200 Subject: gitweb: Add a few comments about %feature hash Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 12c2e6685e..7b520f5fc1 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -98,10 +98,13 @@ our %feature = ( # 'override' => allow-override (boolean), # 'default' => [ default options...] (array reference)} # - # if feature is overridable (it means that allow-override has true value, + # if feature is overridable (it means that allow-override has true value), # then feature-sub will be called with default options as parameters; # return value of feature-sub indicates if to enable specified feature # + # if there is no 'sub' key (no feature-sub), then feature cannot be + # overriden + # # use gitweb_check_feature() to check if is enabled # Enable the 'blame' blob view, showing the last commit that modified @@ -134,6 +137,7 @@ our %feature = ( # Enable text search, which will list the commits which match author, # committer or commit text to a given string. Enabled by default. + # Project specific override is not supported. 'search' => { 'override' => 0, 'default' => [1]}, -- cgit v1.3 From b211c320eb5d753a7a44a03eccb9a15cfbcc563b Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Wed, 16 May 2007 01:59:55 +0200 Subject: gitweb: Do not use absolute font sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit David KÃ¥gedal proposed that gitweb should explicitely request being somewhat smaller than normal, because it has good use for long lines. However gitweb presents a table with several columns, so having wider line is OK for it. Therefore explicit 'font-size: small' would make sense. Apparently many people on the list seem to agree with him. Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 1 + 1 file changed, 1 insertion(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index b57c8beccb..02623cbb6d 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -1,5 +1,6 @@ body { font-family: sans-serif; + font-size: small; border: solid #d9d8d1; border-width: 1px; margin: 10px; -- cgit v1.3 From 7e431ef9ab933d7ff899a999e40627ab49774f3a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Wed, 16 May 2007 01:56:10 +0200 Subject: gitweb: Separate search regexp from search text Separate search text, which is saved in $searchtext global variable, and is used in links, as default value for the textfield in search form, and for pickaxe search, from search regexp, which is saved in $search_regexp global variable, and is used as parameter to --grep, --committer or --author options to git-rev-list, and for searching commit body in gitweb. For now $search_regexp is unconditionallt equal to quotemeta($searchtext), meaning that we always search for fixed string. This fixes bug where 'next page' links for 'search' view didn't work for searchtext containing quotable characters, like `@'. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a13043deea..549e0270b6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -365,6 +365,7 @@ if (defined $page) { } our $searchtext = $cgi->param('s'); +our $search_regexp; if (defined $searchtext) { if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { die_error(undef, "Invalid search parameter"); @@ -372,7 +373,7 @@ if (defined $searchtext) { if (length($searchtext) < 2) { die_error(undef, "At least two characters are required for search parameter"); } - $searchtext = quotemeta $searchtext; + $search_regexp = quotemeta $searchtext; } our $searchtype = $cgi->param('st'); @@ -3244,7 +3245,7 @@ sub git_search_grep_body { esc_html(chop_str($co{'title'}, 50)) . "
"); my $comment = $co{'comment'}; foreach my $line (@$comment) { - if ($line =~ m/^(.*)($searchtext)(.*)$/i) { + if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { my $lead = esc_html($1) || ""; $lead = chop_str($lead, 30, 10); my $match = esc_html($2) || ""; @@ -4626,7 +4627,7 @@ sub git_search { } elsif ($searchtype eq 'committer') { $greptype = "--committer="; } - $greptype .= $searchtext; + $greptype .= $search_regexp; my @commitlist = parse_commits($hash, 101, (100 * $page), $greptype); my $paging_nav = ''; -- cgit v1.3 From d26c4264e584a1a8cbadbc161fa52cf947f5230a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 17 May 2007 00:05:55 +0200 Subject: gitweb: Empty patch for merge means trivial merge, not no differences Earlier commit 4280cde95fa4e3fb012eb6d0c239a7777baaf60c made gitweb show "No differences found" message for empty diff, for the HTML output. But for merge commits, either -c format we use or --cc format, empty diff doesn't mean no differences, but trivial merge. Show "Trivial merge" message instead of "No differences found" for merges. While at it reword conditional in the code for easier reading. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 549e0270b6..8c688be66d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2877,7 +2877,14 @@ sub git_patchset_body { } continue { print "\n"; # class="patch" } - print "
No differences found
\n" if (!$patch_number); + + if ($patch_number == 0) { + if (@hash_parents > 1) { + print "
Trivial merge
\n"; + } else { + print "
No differences found
\n"; + } + } print "\n"; # class="patchset" } -- cgit v1.3 From 2eb54efc6c12cb20403db9a4739bd736c3bfaad1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 16 May 2007 21:04:16 -0700 Subject: gitweb: fix another use of undefined value Pasky and Jakub competed fixing these and in the confusion this ended up not being covered. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8c688be66d..6f5df9174e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1114,7 +1114,9 @@ sub git_get_project_description { open my $fd, "$projectroot/$path/description" or return undef; my $descr = <$fd>; close $fd; - chomp $descr; + if (defined $descr) { + chomp $descr; + } return $descr; } -- cgit v1.3 From 5f85505265601823cc228fdc94d67d3b0ba582e4 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 17 May 2007 22:54:28 +0200 Subject: gitweb: Fix error in git_patchset_body for deletion in merge commit Checking if $diffinfo->{'status'} is equal 'D' is no longer the way to check if the file was deleted in result. For merge commits $diffinfo->{'status'} is reference to array of statuses for each parent. Use the fact that $diffinfo->{'to_id'} is all zeros as sign that file was deleted in result. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6f5df9174e..66f306705f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2722,8 +2722,9 @@ sub git_patchset_body { delete $from{'href'}; } } + $to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; - if ($diffinfo->{'status'} ne "D") { # not deleted file + if ($diffinfo->{'to_id'} ne ('0' x 40)) { # file exists in result $to{'href'} = href(action=>"blob", hash_base=>$hash, hash=>$diffinfo->{'to_id'}, file_name=>$to{'file'}); -- cgit v1.3 From d77b5673e90f47309d6bf87a7653896169945da0 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 17 May 2007 04:24:19 +0200 Subject: gitweb: Normalize searchbar font size Currently, searchbar font was as big as the page heading font, because font-size was made relative - but to the parent element, which was for some reason indeed page_header. Since that seems to be illogical to me, I just moved the div.search outside of div.page_header. I'm no CSS/DOM expert but no adverse effects were observed by me. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 66f306705f..260d79bd78 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1903,6 +1903,8 @@ EOF } print "\n"; } + print "\n"; + my ($have_search) = gitweb_check_feature('search'); if ((defined $project) && ($have_search)) { if (!defined $searchtext) { @@ -1932,7 +1934,6 @@ EOF "" . $cgi->end_form() . "\n"; } - print "\n"; } sub git_footer_html { -- cgit v1.3 From e7738553723dcff0237b1aed2771886c8d87d224 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 17 May 2007 04:31:12 +0200 Subject: gitweb: Add support for grep searches The 'grep' type of search greps the currently selected tree for given regexp and shows the results in a fancy table with links into blob view. The number of shown matches is limited to 1000 and the whole feature can be turned off (grepping linux-2.6.git already makes repo.or.cz a bit unhappy). This second revision makes it in documentation explicit that grep accepts regexps, and makes grep accept extended regexps instead of basic regexps. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 4 ++ gitweb/gitweb.perl | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 125 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 02623cbb6d..9f0822fab3 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -484,3 +484,7 @@ span.atnight { span.match { color: #e00000; } + +div.binary { + font-style: italic; +} diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 260d79bd78..cc16e3137e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -146,6 +146,19 @@ our %feature = ( 'override' => 0, 'default' => [1]}, + # Enable grep search, which will list the files in currently selected + # tree containing the given string. Enabled by default. This can be + # potentially CPU-intensive, of course. + + # To enable system wide have in $GITWEB_CONFIG + # $feature{'grep'}{'default'} = [1]; + # To have project specific config enable override in $GITWEB_CONFIG + # $feature{'grep'}{'override'} = 1; + # and in project config gitweb.grep = 0|1; + 'grep' => { + 'override' => 0, + 'default' => [1]}, + # Enable the pickaxe search, which will list the commits that modified # a given string in a file. This can be practical and quite faster # alternative to 'blame', but still potentially CPU-intensive. @@ -245,6 +258,18 @@ sub gitweb_have_snapshot { return $have_snapshot; } +sub feature_grep { + my ($val) = git_get_project_config('grep', '--bool'); + + if ($val eq 'true') { + return (1); + } elsif ($val eq 'false') { + return (0); + } + + return ($_[0]); +} + sub feature_pickaxe { my ($val) = git_get_project_config('pickaxe', '--bool'); @@ -364,10 +389,17 @@ if (defined $page) { } } +our $searchtype = $cgi->param('st'); +if (defined $searchtype) { + if ($searchtype =~ m/[^a-z]/) { + die_error(undef, "Invalid searchtype parameter"); + } +} + our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { - if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { + if ($searchtype ne 'grep' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { die_error(undef, "Invalid search parameter"); } if (length($searchtext) < 2) { @@ -1927,7 +1959,7 @@ EOF $cgi->hidden(-name => "a") . "\n" . $cgi->hidden(-name => "h") . "\n" . $cgi->popup_menu(-name => 'st', -default => 'commit', - -values => ['commit', 'author', 'committer', 'pickaxe']) . + -values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) . $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) . " search:\n", $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . @@ -4626,6 +4658,12 @@ sub git_search { die_error('403 Permission denied', "Permission denied"); } } + if ($searchtype eq 'grep') { + my ($have_grep) = gitweb_check_feature('grep'); + if (!$have_grep) { + die_error('403 Permission denied', "Permission denied"); + } + } git_header_html(); @@ -4742,6 +4780,73 @@ sub git_search { print "
description" . esc_html($descr) . "
owner$owner
last change$cd{'rfc2822'}
owner$owner
last change$cd{'rfc2822'}
\n"; } + + if ($searchtype eq 'grep') { + git_print_page_nav('','', $hash,$co{'tree'},$hash); + git_print_header_div('commit', esc_html($co{'title'}), $hash); + + print "\n"; + my $alternate = 1; + my $matches = 0; + $/ = "\n"; + open my $fd, "-|", git_cmd(), 'grep', '-n', '-i', '-E', $searchtext, $co{'tree'}; + my $lastfile = ''; + while (my $line = <$fd>) { + chomp $line; + my ($file, $lno, $ltext, $binary); + last if ($matches++ > 1000); + if ($line =~ /^Binary file (.+) matches$/) { + $file = $1; + $binary = 1; + } else { + (undef, $file, $lno, $ltext) = split(/:/, $line, 4); + } + if ($file ne $lastfile) { + $lastfile and print "\n"; + if ($alternate++) { + print "\n"; + } else { + print "\n"; + } + print "\n"; + if ($matches > 1000) { + print "
Too many matches, listing trimmed
\n"; + } + } else { + print "
No matches found
\n"; + } + close $fd; + + print "
". + $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'}, + file_name=>"$file"), + -class => "list"}, esc_path($file)); + print "\n"; + $lastfile = $file; + } + if ($binary) { + print "
Binary file
\n"; + } else { + $ltext = untabify($ltext); + if ($ltext =~ m/^(.*)($searchtext)(.*)$/i) { + $ltext = esc_html($1, -nbsp=>1); + $ltext .= ''; + $ltext .= esc_html($2, -nbsp=>1); + $ltext .= ''; + $ltext .= esc_html($3, -nbsp=>1); + } else { + $ltext = esc_html($ltext, -nbsp=>1); + } + print "
" . + $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'}, + file_name=>"$file").'#l'.$lno, + -class => "linenr"}, sprintf('%4i', $lno)) + . ' ' . $ltext . "
\n"; + } + } + if ($lastfile) { + print "
\n"; + } git_footer_html(); } @@ -4752,6 +4857,20 @@ sub git_search_help {
commit
The commit messages and authorship information will be scanned for the given string.
+EOT + my ($have_grep) = gitweb_check_feature('grep'); + if ($have_grep) { + print <grep +
All files in the currently selected tree (HEAD unless you are explicitly browsing + a different one) are searched for the given +regular expression +(POSIX extended) and the matches are listed. On large +trees, this search can take a while and put some strain on the server, so please use it with +some consideration.
+EOT + } + print <author
Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.
committer
-- cgit v1.3 From 4229aa5141b5d7716d283fa8625209b59398d7ba Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 17 May 2007 04:30:42 +0200 Subject: gitweb: Allow arbitrary strings to be dug with pickaxe Currently, there are rather draconian restrictions on the strings accepted by the pickaxe search, which degrades its usefulness for digging in code significantly. This patch remedies mentioned limitation. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index cc16e3137e..7c136ec0d3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -399,7 +399,7 @@ if (defined $searchtype) { our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { - if ($searchtype ne 'grep' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { + if ($searchtype ne 'grep' and $searchtype ne 'pickaxe' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { die_error(undef, "Invalid search parameter"); } if (length($searchtext) < 2) { @@ -4725,8 +4725,10 @@ sub git_search { my $alternate = 1; $/ = "\n"; my $git_command = git_cmd_str(); + my $searchqtext = $searchtext; + $searchqtext =~ s/'/'\\''/; open my $fd, "-|", "$git_command rev-list $hash | " . - "$git_command diff-tree -r --stdin -S\'$searchtext\'"; + "$git_command diff-tree -r --stdin -S\'$searchqtext\'"; undef %co; my @files; while (my $line = <$fd>) { -- cgit v1.3 From 7f79b0173d2464a31fcb69ff33df9821172b2219 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sat, 19 May 2007 01:12:32 +0200 Subject: gitweb: Remove redundant $searchtype setup Sorry, this was inadverently introduced by my grep search patch. It causes annoying "redefined" warnings. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 ------- 1 file changed, 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7c136ec0d3..17d8efb29c 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -408,13 +408,6 @@ if (defined $searchtext) { $search_regexp = quotemeta $searchtext; } -our $searchtype = $cgi->param('st'); -if (defined $searchtype) { - if ($searchtype =~ m/[^a-z]/) { - die_error(undef, "Invalid searchtype parameter"); - } -} - # now read PATH_INFO and use it as alternative to parameters sub evaluate_path_info { return if defined $project; -- cgit v1.3 From c906b18122af72a8219c76281473490f812e5a40 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 19 May 2007 02:47:51 +0200 Subject: gitweb: Fix "Use of uninitialized value" warning in git_feed Initial (root) commit has no parents, and $co{'parent'} is undefined. Use '--root' for initial commit. This fixes "Use of uninitialized value in open at gitweb/gitweb.perl line 4925." warning. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 17d8efb29c..5c7011a37b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5040,7 +5040,8 @@ XML # get list of changed files open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, - $co{'parent'}, $co{'id'}, "--", (defined $file_name ? $file_name : ()) + $co{'parent'} || "--root", + $co{'id'}, "--", (defined $file_name ? $file_name : ()) or next; my @difftree = map { chomp; $_ } <$fd>; close $fd -- cgit v1.3 From 072570ee2689c5f19513157d654f04f5a7113a24 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sun, 20 May 2007 11:46:46 -0400 Subject: gitweb.perl - Optionally send archives as .zip files git-archive already knows how to generate an archive as a tar or a zip file, but gitweb did not. zip archvies are much more usable in a Windows environment due to native support and this patch allows a site admin the option to deliver zip rather than tar files. The selection is done by inserting $feature{'snapshot'}{'default'} = ['x-zip', 'zip', '']; in gitweb_config.perl. Tar files remain the default option. Signed-off-by: Mark Levedahl Acked-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5c7011a37b..c3921cb0ba 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -132,7 +132,7 @@ our %feature = ( # $feature{'snapshot'}{'default'} = [undef]; # To have project specific config enable override in $GITWEB_CONFIG # $feature{'snapshot'}{'override'} = 1; - # and in project config gitweb.snapshot = none|gzip|bzip2; + # and in project config gitweb.snapshot = none|gzip|bzip2|zip; 'snapshot' => { 'sub' => \&feature_snapshot, 'override' => 0, @@ -244,6 +244,8 @@ sub feature_snapshot { return ('x-gzip', 'gz', 'gzip'); } elsif ($val eq 'bzip2') { return ('x-bzip2', 'bz2', 'bzip2'); + } elsif ($val eq 'zip') { + return ('x-zip', 'zip', ''); } elsif ($val eq 'none') { return (); } @@ -3976,19 +3978,26 @@ sub git_snapshot { $hash = git_get_head_hash($project); } - my $filename = decode_utf8(basename($project)) . "-$hash.tar.$suffix"; + my $git = git_cmd_str(); + my $name = $project; + $name =~ s/\047/\047\\\047\047/g; + my $filename = decode_utf8(basename($project)); + my $cmd; + if ($suffix eq 'zip') { + $filename .= "-$hash.$suffix"; + $cmd = "$git archive --format=zip --prefix=\'$name\'/ $hash"; + } else { + $filename .= "-$hash.tar.$suffix"; + $cmd = "$git archive --format=tar --prefix=\'$name\'/ $hash | $command"; + } print $cgi->header( -type => "application/$ctype", -content_disposition => 'inline; filename="' . "$filename" . '"', -status => '200 OK'); - my $git = git_cmd_str(); - my $name = $project; - $name =~ s/\047/\047\\\047\047/g; - open my $fd, "-|", - "$git archive --format=tar --prefix=\'$name\'/ $hash | $command" - or die_error(undef, "Execute git-tar-tree failed"); + open my $fd, "-|", $cmd + or die_error(undef, "Execute git-archive failed"); binmode STDOUT, ':raw'; print <$fd>; binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi -- cgit v1.3 From 00f429af7bfaa6a9141bc0ac30995d4fae24836a Mon Sep 17 00:00:00 2001 From: Martin Koegler Date: Sun, 3 Jun 2007 17:42:44 +0200 Subject: gitweb: Handle non UTF-8 text better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gitweb assumes that everything is in UTF-8. If a text contains invalid UTF-8 character sequences, the text must be in a different encoding. This commit introduces $fallback_encoding which would be used as input encoding if gitweb encounters text with is not valid UTF-8. Add basic test for this in t/t9500-gitweb-standalone-no-errors.sh Signed-off-by: Martin Koegler Signed-off-by: Jakub Narebski Tested-by: Alexandre Julliard Tested-by: Ismail Dönmez Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 41 +++++++++++++++++++++++++--------- t/t9500-gitweb-standalone-no-errors.sh | 28 +++++++++++++++++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c3921cb0ba..e92596c295 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -94,6 +94,13 @@ our $default_text_plain_charset = undef; # (relative to the current git repository) our $mimetypes_file = undef; +# assume this charset if line contains non-UTF-8 characters; +# it should be valid encoding (see Encoding::Supported(3pm) for list), +# for which encoding all byte sequences are valid, for example +# 'iso-8859-1' aka 'latin1' (it is decoded without checking, so it +# could be even 'utf-8' for the old behavior) +our $fallback_encoding = 'latin1'; + # You define site-wide feature defaults here; override them with # $GITWEB_CONFIG as necessary. our %feature = ( @@ -602,6 +609,20 @@ sub validate_refname { return $input; } +# decode sequences of octets in utf8 into Perl's internal form, +# which is utf-8 with utf8 flag set if needed. gitweb writes out +# in utf-8 thanks to "binmode STDOUT, ':utf8'" at beginning +sub to_utf8 { + my $str = shift; + my $res; + eval { $res = decode_utf8($str, Encode::FB_CROAK); }; + if (defined $res) { + return $res; + } else { + return decode($fallback_encoding, $str, Encode::FB_DEFAULT); + } +} + # quote unsafe chars, but keep the slash, even when it's not # correct, but quoted slashes look too horrible in bookmarks sub esc_param { @@ -626,7 +647,7 @@ sub esc_html ($;%) { my $str = shift; my %opts = @_; - $str = decode_utf8($str); + $str = to_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -640,7 +661,7 @@ sub esc_path { my $str = shift; my %opts = @_; - $str = decode_utf8($str); + $str = to_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -925,7 +946,7 @@ sub format_subject_html { if (length($short) < length($long)) { return $cgi->a({-href => $href, -class => "list subject", - -title => decode_utf8($long)}, + -title => to_utf8($long)}, esc_html($short) . $extra); } else { return $cgi->a({-href => $href, -class => "list subject"}, @@ -1239,7 +1260,7 @@ sub git_get_projects_list { if (check_export_ok("$projectroot/$path")) { my $pr = { path => $path, - owner => decode_utf8($owner), + owner => to_utf8($owner), }; push @list, $pr; (my $forks_path = $path) =~ s/\.git$//; @@ -1269,7 +1290,7 @@ sub git_get_project_owner { $pr = unescape($pr); $ow = unescape($ow); if ($pr eq $project) { - $owner = decode_utf8($ow); + $owner = to_utf8($ow); last; } } @@ -1759,7 +1780,7 @@ sub get_file_owner { } my $owner = $gcos; $owner =~ s/[,;].*$//; - return decode_utf8($owner); + return to_utf8($owner); } ## ...................................................................... @@ -1842,7 +1863,7 @@ sub git_header_html { my $title = "$site_name"; if (defined $project) { - $title .= " - " . decode_utf8($project); + $title .= " - " . to_utf8($project); if (defined $action) { $title .= "/$action"; if (defined $file_name) { @@ -2116,7 +2137,7 @@ sub git_print_page_path { print "
"; print $cgi->a({-href => href(action=>"tree", hash_base=>$hb), - -title => 'tree root'}, decode_utf8("[$project]")); + -title => 'tree root'}, to_utf8("[$project]")); print " / "; if (defined $name) { my @dirname = split '/', $name; @@ -2936,7 +2957,7 @@ sub git_project_list_body { ($pr->{'age'}, $pr->{'age_string'}) = @aa; if (!defined $pr->{'descr'}) { my $descr = git_get_project_description($pr->{'path'}) || ""; - $pr->{'descr_long'} = decode_utf8($descr); + $pr->{'descr_long'} = to_utf8($descr); $pr->{'descr'} = chop_str($descr, 25, 5); } if (!defined $pr->{'owner'}) { @@ -3981,7 +4002,7 @@ sub git_snapshot { my $git = git_cmd_str(); my $name = $project; $name =~ s/\047/\047\\\047\047/g; - my $filename = decode_utf8(basename($project)); + my $filename = to_utf8(basename($project)); my $cmd; if ($suffix eq 'zip') { $filename .= "-$hash.$suffix"; diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index b92ab63312..44ae503b99 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -487,4 +487,32 @@ test_expect_success \ 'gitweb_run "p=.git;a=atom"' test_debug 'cat gitweb.log' +# ---------------------------------------------------------------------- +# encoding/decoding + +test_expect_success \ + 'encode(commit): utf8' \ + '. ../t3901-utf8.txt && + echo "UTF-8" >> file && + git add file && + git commit -F ../t3900/1-UTF-8.txt && + gitweb_run "p=.git;a=commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'encode(commit): iso-8859-1' \ + '. ../t3901-8859-1.txt && + echo "ISO-8859-1" >> file && + git add file && + git config i18n.commitencoding ISO-8859-1 && + git commit -F ../t3900/ISO-8859-1.txt && + git config --unset i18n.commitencoding && + gitweb_run "p=.git;a=commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'encode(log): utf-8 and iso-8859-1' \ + 'gitweb_run "p=.git;a=log"' +test_debug 'cat gitweb.log' + test_done -- cgit v1.3 From a6080a0a44d5ead84db3dabbbc80e82df838533d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 7 Jun 2007 00:04:01 -0700 Subject: War on whitespace This uses "git-apply --whitespace=strip" to fix whitespace errors that have crept in to our source files over time. There are a few files that need to have trailing whitespaces (most notably, test vectors). The results still passes the test, and build result in Documentation/ area is unchanged. Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.0.4.txt | 2 - Documentation/RelNotes-1.5.0.5.txt | 2 - Documentation/RelNotes-1.5.0.6.txt | 1 - Documentation/RelNotes-1.5.1.3.txt | 1 - Documentation/SubmittingPatches | 14 +- Documentation/asciidoc.conf | 2 - Documentation/config.txt | 2 - Documentation/core-tutorial.txt | 46 +- Documentation/diff-format.txt | 21 +- Documentation/diff-options.txt | 4 +- Documentation/diffcore.txt | 3 +- Documentation/docbook-xsl.css | 572 ++++++++++----------- Documentation/fetch-options.txt | 1 - Documentation/git-add.txt | 1 - Documentation/git-am.txt | 1 - Documentation/git-apply.txt | 1 - Documentation/git-archimport.txt | 45 +- Documentation/git-bisect.txt | 3 +- Documentation/git-branch.txt | 1 - Documentation/git-cat-file.txt | 1 - Documentation/git-check-attr.txt | 1 - Documentation/git-checkout-index.txt | 1 - Documentation/git-checkout.txt | 1 - Documentation/git-cherry-pick.txt | 1 - Documentation/git-cherry.txt | 1 - Documentation/git-clone.txt | 1 - Documentation/git-commit-tree.txt | 3 +- Documentation/git-config.txt | 1 - Documentation/git-convert-objects.txt | 1 - Documentation/git-count-objects.txt | 1 - Documentation/git-cvsexportcommit.txt | 15 +- Documentation/git-cvsimport.txt | 13 +- Documentation/git-daemon.txt | 1 - Documentation/git-describe.txt | 1 - Documentation/git-diff-files.txt | 3 +- Documentation/git-diff-index.txt | 3 +- Documentation/git-diff-tree.txt | 1 - Documentation/git-diff.txt | 1 - Documentation/git-fast-import.txt | 1 - Documentation/git-fmt-merge-msg.txt | 1 - Documentation/git-format-patch.txt | 1 - Documentation/git-fsck.txt | 1 - Documentation/git-get-tar-commit-id.txt | 1 - Documentation/git-grep.txt | 1 - Documentation/git-hash-object.txt | 3 +- Documentation/git-http-fetch.txt | 1 - Documentation/git-http-push.txt | 2 +- Documentation/git-index-pack.txt | 1 - Documentation/git-init-db.txt | 1 - Documentation/git-init.txt | 1 - Documentation/git-instaweb.txt | 1 - Documentation/git-local-fetch.txt | 1 - Documentation/git-log.txt | 1 - Documentation/git-ls-files.txt | 1 - Documentation/git-ls-remote.txt | 1 - Documentation/git-ls-tree.txt | 1 - Documentation/git-mailinfo.txt | 1 - Documentation/git-mailsplit.txt | 1 - Documentation/git-merge-base.txt | 1 - Documentation/git-merge-index.txt | 3 +- Documentation/git-merge-one-file.txt | 1 - Documentation/git-merge-tree.txt | 1 - Documentation/git-merge.txt | 2 +- Documentation/git-mergetool.txt | 1 - Documentation/git-mktag.txt | 1 - Documentation/git-mktree.txt | 1 - Documentation/git-mv.txt | 1 - Documentation/git-name-rev.txt | 1 - Documentation/git-p4import.txt | 1 - Documentation/git-pack-objects.txt | 1 - Documentation/git-pack-redundant.txt | 3 +- Documentation/git-patch-id.txt | 1 - Documentation/git-peek-remote.txt | 1 - Documentation/git-prune-packed.txt | 1 - Documentation/git-prune.txt | 1 - Documentation/git-pull.txt | 1 - Documentation/git-push.txt | 1 - Documentation/git-quiltimport.txt | 1 - Documentation/git-read-tree.txt | 1 - Documentation/git-rebase.txt | 1 - Documentation/git-reflog.txt | 1 - Documentation/git-relink.txt | 1 - Documentation/git-remote.txt | 1 - Documentation/git-repack.txt | 1 - Documentation/git-request-pull.txt | 1 - Documentation/git-rev-parse.txt | 1 - Documentation/git-revert.txt | 1 - Documentation/git-rm.txt | 1 - Documentation/git-runstatus.txt | 1 - Documentation/git-send-email.txt | 3 +- Documentation/git-sh-setup.txt | 1 - Documentation/git-shell.txt | 1 - Documentation/git-shortlog.txt | 1 - Documentation/git-show-index.txt | 1 - Documentation/git-show.txt | 1 - Documentation/git-ssh-fetch.txt | 1 - Documentation/git-ssh-upload.txt | 1 - Documentation/git-status.txt | 1 - Documentation/git-stripspace.txt | 1 - Documentation/git-svnimport.txt | 1 - Documentation/git-tar-tree.txt | 1 - Documentation/git-unpack-file.txt | 1 - Documentation/git-unpack-objects.txt | 1 - Documentation/git-update-index.txt | 9 +- Documentation/git-update-server-info.txt | 1 - Documentation/git-var.txt | 1 - Documentation/git-verify-pack.txt | 1 - Documentation/git-verify-tag.txt | 1 - Documentation/git-whatchanged.txt | 1 - Documentation/git-write-tree.txt | 1 - Documentation/git.txt | 1 - Documentation/gitk.txt | 1 - Documentation/howto/rebase-and-edit.txt | 20 +- .../howto/rebase-from-internal-branch.txt | 12 +- Documentation/howto/rebuild-from-update-hook.txt | 1 - Documentation/howto/revert-branch-rebase.txt | 2 +- Documentation/howto/separating-topic-branches.txt | 13 +- Documentation/howto/use-git-daemon.txt | 1 - Documentation/merge-options.txt | 1 - Documentation/pretty-formats.txt | 1 - Documentation/pretty-options.txt | 1 - Documentation/pull-fetch-param.txt | 2 +- Documentation/repository-layout.txt | 1 - Documentation/technical/pack-format.txt | 8 +- Documentation/user-manual.txt | 38 +- GIT-VERSION-GEN | 2 - INSTALL | 3 +- arm/sha1.c | 4 +- arm/sha1_arm.S | 1 - builtin-annotate.c | 1 - builtin-diff-index.c | 2 +- builtin-fmt-merge-msg.c | 1 - builtin-fsck.c | 4 +- builtin-ls-files.c | 2 +- builtin-name-rev.c | 1 - builtin-pack-objects.c | 2 +- builtin-rerere.c | 1 - builtin-shortlog.c | 1 - cache.h | 2 +- commit.c | 14 +- commit.h | 2 +- compat/mmap.c | 1 - config.c | 3 +- config.mak.in | 1 - connect.c | 2 +- contrib/README | 1 - contrib/blameview/README | 1 - contrib/gitview/gitview | 2 - contrib/hooks/post-receive-email | 2 +- contrib/remotes2config.sh | 2 - convert-objects.c | 2 +- copy.c | 1 - ctype.c | 1 - daemon.c | 4 +- date.c | 10 +- diff-lib.c | 2 +- diff.c | 4 +- diffcore-pickaxe.c | 2 +- entry.c | 2 +- environment.c | 2 - fetch-pack.c | 2 +- fetch.c | 4 +- git-archimport.perl | 175 ++++--- git-checkout.sh | 4 +- git-clone.sh | 5 +- git-commit.sh | 2 +- git-cvsexportcommit.perl | 2 +- git-cvsimport.perl | 12 +- git-gui/GIT-VERSION-GEN | 2 - git-gui/lib/class.tcl | 1 - git-merge-one-file.sh | 2 +- git-p4import.py | 1 - git-svnimport.perl | 4 +- git-tag.sh | 5 +- git-verify-tag.sh | 1 - git.spec.in | 2 +- gitk | 2 +- gitweb/README | 1 - help.c | 2 - http-fetch.c | 2 +- http-push.c | 2 +- http.c | 2 +- imap-send.c | 2 +- local-fetch.c | 8 +- lockfile.c | 1 - mailmap.c | 1 - match-trees.c | 1 - merge-index.c | 2 +- mktag.c | 2 +- mozilla-sha1/sha1.c | 19 +- mozilla-sha1/sha1.h | 18 +- object-refs.c | 2 - object.h | 2 +- pack-redundant.c | 4 +- patch-id.c | 2 +- path-list.c | 1 - perl/Makefile | 1 - pkt-line.c | 2 +- ppc/sha1.c | 2 +- read-cache.c | 10 +- rsh.h | 2 +- setup.c | 4 +- sha1_file.c | 8 +- shallow.c | 1 - ssh-upload.c | 10 +- strbuf.c | 1 - t/Makefile | 1 - t/lib-read-tree-m-3way.sh | 2 +- t/t0000-basic.sh | 2 +- t/t1200-tutorial.sh | 1 - t/t1300-repo-config.sh | 1 - t/t2000-checkout-cache-clash.sh | 2 - t/t2001-checkout-cache-clash.sh | 1 - t/t3030-merge-recursive.sh | 1 - t/t3403-rebase-skip.sh | 1 - t/t4006-diff-mode.sh | 1 - t/t4100-apply-stat.sh | 1 - t/t4110-apply-scan.sh | 1 - t/t4112-apply-renames.sh | 16 +- t/t4118-apply-empty-context.sh | 1 - t/t4119-apply-config.sh | 2 +- t/t4121-apply-diffs.sh | 1 - t/t4122-apply-symlink-inside.sh | 1 - t/t4200-rerere.sh | 2 - t/t5400-send-pack.sh | 2 +- t/t5520-pull.sh | 1 - t/t5710-info-alternate.sh | 1 - t/t6000lib.sh | 16 +- t/t6002-rev-list-bisect.sh | 8 +- t/t6021-merge-criss-cross.sh | 2 +- t/t6023-merge-file.sh | 1 - t/t6030-bisect-porcelain.sh | 1 - t/t6101-rev-parse-parents.sh | 1 - t/t9107-git-svn-migrate.sh | 1 - t/t9111/svnsync.dump | 2 - t/test-lib.sh | 2 +- templates/hooks--commit-msg | 1 - templates/hooks--post-receive | 1 - templates/hooks--pre-applypatch | 1 - templates/hooks--pre-commit | 1 - tree-walk.c | 1 - upload-pack.c | 2 +- var.c | 4 +- xdiff-interface.c | 2 - xdiff/xdiff.h | 1 - xdiff/xdiffi.c | 1 - xdiff/xdiffi.h | 1 - xdiff/xemit.c | 1 - xdiff/xemit.h | 1 - xdiff/xinclude.h | 1 - xdiff/xmacros.h | 1 - xdiff/xprepare.c | 1 - xdiff/xprepare.h | 1 - xdiff/xtypes.h | 1 - xdiff/xutils.c | 1 - xdiff/xutils.h | 1 - 256 files changed, 645 insertions(+), 852 deletions(-) (limited to 'gitweb') diff --git a/Documentation/RelNotes-1.5.0.4.txt b/Documentation/RelNotes-1.5.0.4.txt index b727a8d1e5..feefa5dfd4 100644 --- a/Documentation/RelNotes-1.5.0.4.txt +++ b/Documentation/RelNotes-1.5.0.4.txt @@ -20,5 +20,3 @@ Fixes since v1.5.0.3 * Documentation updates * User manual updates - - diff --git a/Documentation/RelNotes-1.5.0.5.txt b/Documentation/RelNotes-1.5.0.5.txt index aa86149d4f..eeec3d73d0 100644 --- a/Documentation/RelNotes-1.5.0.5.txt +++ b/Documentation/RelNotes-1.5.0.5.txt @@ -24,5 +24,3 @@ Fixes since v1.5.0.3 * Documentation updates * User manual updates - - diff --git a/Documentation/RelNotes-1.5.0.6.txt b/Documentation/RelNotes-1.5.0.6.txt index e15447ffdb..c02015ad5f 100644 --- a/Documentation/RelNotes-1.5.0.6.txt +++ b/Documentation/RelNotes-1.5.0.6.txt @@ -19,4 +19,3 @@ Fixes since v1.5.0.5 - user-manual has better cross references. - gitweb installation/deployment procedure is now documented. - diff --git a/Documentation/RelNotes-1.5.1.3.txt b/Documentation/RelNotes-1.5.1.3.txt index 2ddeabd029..876408b65a 100644 --- a/Documentation/RelNotes-1.5.1.3.txt +++ b/Documentation/RelNotes-1.5.1.3.txt @@ -43,4 +43,3 @@ Fixes since v1.5.1.2 description was given by the caller. Also contains various documentation updates. - diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index b9baa1d3b4..01354c2bb5 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -296,15 +296,15 @@ diff --git a/pico/pico.c b/pico/pico.c --- a/pico/pico.c +++ b/pico/pico.c @@ -219,7 +219,9 @@ PICO *pm; - switch(pico_all_done){ /* prepare for/handle final events */ - case COMP_EXIT : /* already confirmed */ - packheader(); + switch(pico_all_done){ /* prepare for/handle final events */ + case COMP_EXIT : /* already confirmed */ + packheader(); +#if 0 - stripwhitespace(); + stripwhitespace(); +#endif - c |= COMP_EXIT; - break; - + c |= COMP_EXIT; + break; + (Daniel Barkalow) diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 60e15ba349..99302c5beb 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -54,5 +54,3 @@ ifdef::backend-xhtml11[] [gitlink-inlinemacro] {target}{0?({0})} endif::backend-xhtml11[] - - diff --git a/Documentation/config.txt b/Documentation/config.txt index 5868d587a9..de408b6571 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -682,5 +682,3 @@ receive.denyNonFastForwards:: transfer.unpackLimit:: When `fetch.unpackLimit` or `receive.unpackLimit` are not set, the value of this variable is used instead. - - diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt index 6b9b9ad7d1..4fb6f4143c 100644 --- a/Documentation/core-tutorial.txt +++ b/Documentation/core-tutorial.txt @@ -9,11 +9,11 @@ repository, mainly because being hands-on and using explicit examples is often the best way of explaining what is going on. In normal life, most people wouldn't use the "core" git programs -directly, but rather script around them to make them more palatable. +directly, but rather script around them to make them more palatable. Understanding the core git stuff may help some people get those scripts done, though, and it may also be instructive in helping people understand what it is that the higher-level helper scripts are actually -doing. +doing. The core git is often called "plumbing", with the prettier user interfaces on top of it called "porcelain". You may not want to use the @@ -41,7 +41,7 @@ Creating a new git repository couldn't be easier: all git repositories start out empty, and the only thing you need to do is find yourself a subdirectory that you want to use as a working tree - either an empty one for a totally new project, or an existing working tree that you want -to import into git. +to import into git. For our first example, we're going to start a totally new repository from scratch, with no pre-existing files, and we'll call it `git-tutorial`. @@ -169,7 +169,7 @@ $ ls .git/objects/??/* and see two files: ---------------- -.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238 +.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238 .git/objects/f2/4c74a2e500f5ee1332c86b94199f52b1d1d962 ---------------- @@ -220,7 +220,7 @@ you have not actually really "checked in" your files into git so far, you've only *told* git about them. However, since git knows about them, you can now start using some of the -most basic git commands to manipulate the files or look at their status. +most basic git commands to manipulate the files or look at their status. In particular, let's not even check in the two files into git yet, we'll start off by adding another line to `hello` first: @@ -350,7 +350,7 @@ Making a change Remember how we did the `git-update-index` on file `hello` and then we changed `hello` afterward, and could compare the new state of `hello` with the -state we saved in the index file? +state we saved in the index file? Further, remember how I said that `git-write-tree` writes the contents of the *index* file to the tree, and thus what we just committed was in @@ -370,7 +370,7 @@ file and the working tree, `git-diff-index` shows the differences between a committed *tree* and either the index file or the working tree. In other words, `git-diff-index` wants a tree to be diffed against, and before we did the commit, we couldn't do that, because we -didn't have anything to diff against. +didn't have anything to diff against. But now we can do @@ -379,7 +379,7 @@ $ git-diff-index -p HEAD ---------------- (where `-p` has the same meaning as it did in `git-diff-files`), and it -will show us the same difference, but for a totally different reason. +will show us the same difference, but for a totally different reason. Now we're comparing the working tree not against the index file, but against the tree we just wrote. It just so happens that those two are obviously the same, so we get the same result. @@ -398,7 +398,7 @@ working tree, but when given the `\--cached` flag, it is told to instead compare against just the index cache contents, and ignore the current working tree state entirely. Since we just wrote the index file to HEAD, doing `git-diff-index \--cached -p HEAD` should thus return -an empty set of differences, and that's exactly what it does. +an empty set of differences, and that's exactly what it does. [NOTE] ================ @@ -549,7 +549,7 @@ $ git-whatchanged -p --root ---------------- and you will see exactly what has changed in the repository over its -short history. +short history. [NOTE] The `\--root` flag is a flag to `git-diff-tree` to tell it to @@ -637,7 +637,7 @@ So the mental model of "the git information is always tied directly to the working tree that it describes" may not be technically 100% accurate, but it's a good model for all normal use. -This has two implications: +This has two implications: - if you grow bored with the tutorial repository you created (or you've made a mistake and want to start all over), you can just do simple @@ -705,7 +705,7 @@ Many (most?) public remote repositories will not contain any of the checked out files or even an index file, and will *only* contain the actual core git files. Such a repository usually doesn't even have the `.git` subdirectory, but has all the git files directly in the -repository. +repository. To create your own local live copy of such a "raw" git repository, you'd first create your own subdirectory for the project, and then copy the @@ -718,7 +718,7 @@ $ cd my-git $ rsync -rL rsync://rsync.kernel.org/pub/scm/git/git.git/ .git ---------------- -followed by +followed by ---------------- $ git-read-tree HEAD @@ -738,7 +738,7 @@ up-to-date (so that you don't have to refresh it afterward), and the `-a` flag means "check out all files" (if you have a stale copy or an older version of a checked out tree you may also need to add the `-f` flag first, to tell git-checkout-index to *force* overwriting of any old -files). +files). Again, this can all be simplified with @@ -751,7 +751,7 @@ $ git checkout which will end up doing all of the above for you. You have now successfully copied somebody else's (mine) remote -repository, and checked it out. +repository, and checked it out. Creating a new branch @@ -760,14 +760,14 @@ Creating a new branch Branches in git are really nothing more than pointers into the git object database from within the `.git/refs/` subdirectory, and as we already discussed, the `HEAD` branch is nothing but a symlink to one of -these object pointers. +these object pointers. You can at any time create a new branch by just picking an arbitrary point in the project history, and just writing the SHA1 name of that object into a file under `.git/refs/heads/`. You can use any filename you want (and indeed, subdirectories), but the convention is that the "normal" branch is called `master`. That's just a convention, though, -and nothing enforces it. +and nothing enforces it. To show that as an example, let's go back to the git-tutorial repository we used earlier, and create a branch in it. You do that by simply just @@ -778,7 +778,7 @@ $ git checkout -b mybranch ------------ will create a new branch based at the current `HEAD` position, and switch -to it. +to it. [NOTE] ================================================ @@ -825,7 +825,7 @@ checking it out and switching to it. If so, just use the command $ git branch [startingpoint] ------------ -which will simply _create_ the branch, but will not do anything further. +which will simply _create_ the branch, but will not do anything further. You can then later -- once you decide that you want to actually develop on that branch -- switch to that branch with a regular `git checkout` with the branchname as the argument. @@ -884,7 +884,7 @@ $ gitk --all will show you graphically both of your branches (that's what the `\--all` means: normally it will just show you your current `HEAD`) and their histories. You can also see exactly how they came to be from a common -source. +source. Anyway, let's exit `gitk` (`^Q` or the File menu), and decide that we want to merge the work we did on the `mybranch` branch into the `master` @@ -905,8 +905,8 @@ of it as it can automatically (which in this case is just merge the `example` file, which had no differences in the `mybranch` branch), and say: ---------------- - Auto-merging hello - CONFLICT (content): Merge conflict in hello + Auto-merging hello + CONFLICT (content): Merge conflict in hello Automatic merge failed; fix up by hand ---------------- @@ -1387,7 +1387,7 @@ repository. Kernel.org mirror network takes care of the propagation to other publicly visible machines: ------------ -$ git push master.kernel.org:/pub/scm/git/git.git/ +$ git push master.kernel.org:/pub/scm/git/git.git/ ------------ diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index e38a1f1405..18d49d2c3b 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -1,7 +1,7 @@ The output format from "git-diff-index", "git-diff-tree" and "git-diff-files" are very similar. -These commands all compare two sets of things; what is +These commands all compare two sets of things; what is compared differs: git-diff-index :: @@ -139,28 +139,28 @@ index fabadb8,cc95eb0..4866510 --- a/describe.c +++ b/describe.c @@@ -98,20 -98,12 +98,20 @@@ - return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; + return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; } - + - static void describe(char *arg) -static void describe(struct commit *cmit, int last_one) ++static void describe(char *arg, int last_one) { + unsigned char sha1[20]; + struct commit *cmit; - struct commit_list *list; - static int initialized = 0; - struct commit_name *n; - + struct commit_list *list; + static int initialized = 0; + struct commit_name *n; + + if (get_sha1(arg, sha1) < 0) + usage(describe_usage); + cmit = lookup_commit_reference(sha1); + if (!cmit) + usage(describe_usage); + - if (!initialized) { - initialized = 1; - for_each_ref(get_name); + if (!initialized) { + initialized = 1; + for_each_ref(get_name); ------------ 1. It is preceded with a "git diff" header, that looks like @@ -233,4 +233,3 @@ parents). When shown by `git diff-files -c`, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version"). - diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 1689c74817..b2a05937f9 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -100,8 +100,8 @@ that matches other criteria, nothing is selected. --find-copies-harder:: - For performance reasons, by default, -C option finds copies only - if the original file of the copy was modified in the same + For performance reasons, by default, -C option finds copies only + if the original file of the copy was modified in the same changeset. This flag makes the command inspect unmodified files as candidates for the source of copy. This is a very expensive operation for large diff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt index 34cd306bb1..c6a983a5d5 100644 --- a/Documentation/diffcore.txt +++ b/Documentation/diffcore.txt @@ -71,7 +71,7 @@ The first transformation in the chain is diffcore-pathspec, and is controlled by giving the pathname parameters to the git-diff-* commands on the command line. The pathspec is used to limit the world diff operates in. It removes the filepairs -outside the specified set of pathnames. E.g. If the input set +outside the specified set of pathnames. E.g. If the input set of filepairs included: ------------------------------------------------ @@ -269,4 +269,3 @@ Documentation *.c t ------------------------------------------------ - diff --git a/Documentation/docbook-xsl.css b/Documentation/docbook-xsl.css index 8821e305dd..b878b385c6 100644 --- a/Documentation/docbook-xsl.css +++ b/Documentation/docbook-xsl.css @@ -1,286 +1,286 @@ -/* - CSS stylesheet for XHTML produced by DocBook XSL stylesheets. - Tested with XSL stylesheets 1.61.2, 1.67.2 -*/ - -span.strong { - font-weight: bold; -} - -body blockquote { - margin-top: .75em; - line-height: 1.5; - margin-bottom: .75em; -} - -html body { - margin: 1em 5% 1em 5%; - line-height: 1.2; -} - -body div { - margin: 0; -} - -h1, h2, h3, h4, h5, h6, -div.toc p b, -div.list-of-figures p b, -div.list-of-tables p b, -div.abstract p.title -{ - color: #527bbd; - font-family: tahoma, verdana, sans-serif; -} - -div.toc p:first-child, -div.list-of-figures p:first-child, -div.list-of-tables p:first-child, -div.example p.title -{ - margin-bottom: 0.2em; -} - -body h1 { - margin: .0em 0 0 -4%; - line-height: 1.3; - border-bottom: 2px solid silver; -} - -body h2 { - margin: 0.5em 0 0 -4%; - line-height: 1.3; - border-bottom: 2px solid silver; -} - -body h3 { - margin: .8em 0 0 -3%; - line-height: 1.3; -} - -body h4 { - margin: .8em 0 0 -3%; - line-height: 1.3; -} - -body h5 { - margin: .8em 0 0 -2%; - line-height: 1.3; -} - -body h6 { - margin: .8em 0 0 -1%; - line-height: 1.3; -} - -body hr { - border: none; /* Broken on IE6 */ -} -div.footnotes hr { - border: 1px solid silver; -} - -div.navheader th, div.navheader td, div.navfooter td { - font-family: sans-serif; - font-size: 0.9em; - font-weight: bold; - color: #527bbd; -} -div.navheader img, div.navfooter img { - border-style: none; -} -div.navheader a, div.navfooter a { - font-weight: normal; -} -div.navfooter hr { - border: 1px solid silver; -} - -body td { - line-height: 1.2 -} - -body th { - line-height: 1.2; -} - -ol { - line-height: 1.2; -} - -ul, body dir, body menu { - line-height: 1.2; -} - -html { - margin: 0; - padding: 0; -} - -body h1, body h2, body h3, body h4, body h5, body h6 { - margin-left: 0 -} - -body pre { - margin: 0.5em 10% 0.5em 1em; - line-height: 1.0; - color: navy; -} - -tt.literal, code.literal { - color: navy; -} - -div.literallayout p { - padding: 0em; - margin: 0em; -} - -div.literallayout { - font-family: monospace; -# margin: 0.5em 10% 0.5em 1em; - margin: 0em; - color: navy; - border: 1px solid silver; - background: #f4f4f4; - padding: 0.5em; -} - -.programlisting, .screen { - border: 1px solid silver; - background: #f4f4f4; - margin: 0.5em 10% 0.5em 0; - padding: 0.5em 1em; -} - -div.sidebar { - background: #ffffee; - margin: 1.0em 10% 0.5em 0; - padding: 0.5em 1em; - border: 1px solid silver; -} -div.sidebar * { padding: 0; } -div.sidebar div { margin: 0; } -div.sidebar p.title { - font-family: sans-serif; - margin-top: 0.5em; - margin-bottom: 0.2em; -} - -div.bibliomixed { - margin: 0.5em 5% 0.5em 1em; -} - -div.glossary dt { - font-weight: bold; -} -div.glossary dd p { - margin-top: 0.2em; -} - -dl { - margin: .8em 0; - line-height: 1.2; -} - -dt { - margin-top: 0.5em; -} - -dt span.term { - font-style: italic; -} - -div.variablelist dd p { - margin-top: 0; -} - -div.itemizedlist li, div.orderedlist li { - margin-left: -0.8em; - margin-top: 0.5em; -} - -ul, ol { - list-style-position: outside; -} - -div.sidebar ul, div.sidebar ol { - margin-left: 2.8em; -} - -div.itemizedlist p.title, -div.orderedlist p.title, -div.variablelist p.title -{ - margin-bottom: -0.8em; -} - -div.revhistory table { - border-collapse: collapse; - border: none; -} -div.revhistory th { - border: none; - color: #527bbd; - font-family: tahoma, verdana, sans-serif; -} -div.revhistory td { - border: 1px solid silver; -} - -/* Keep TOC and index lines close together. */ -div.toc dl, div.toc dt, -div.list-of-figures dl, div.list-of-figures dt, -div.list-of-tables dl, div.list-of-tables dt, -div.indexdiv dl, div.indexdiv dt -{ - line-height: normal; - margin-top: 0; - margin-bottom: 0; -} - -/* - Table styling does not work because of overriding attributes in - generated HTML. -*/ -div.table table, -div.informaltable table -{ - margin-left: 0; - margin-right: 5%; - margin-bottom: 0.8em; -} -div.informaltable table -{ - margin-top: 0.4em -} -div.table thead, -div.table tfoot, -div.table tbody, -div.informaltable thead, -div.informaltable tfoot, -div.informaltable tbody -{ - /* No effect in IE6. */ - border-top: 2px solid #527bbd; - border-bottom: 2px solid #527bbd; -} -div.table thead, div.table tfoot, -div.informaltable thead, div.informaltable tfoot -{ - font-weight: bold; -} - -div.mediaobject img { - border: 1px solid silver; - margin-bottom: 0.8em; -} -div.figure p.title, -div.table p.title -{ - margin-top: 1em; - margin-bottom: 0.4em; -} - -@media print { - div.navheader, div.navfooter { display: none; } -} +/* + CSS stylesheet for XHTML produced by DocBook XSL stylesheets. + Tested with XSL stylesheets 1.61.2, 1.67.2 +*/ + +span.strong { + font-weight: bold; +} + +body blockquote { + margin-top: .75em; + line-height: 1.5; + margin-bottom: .75em; +} + +html body { + margin: 1em 5% 1em 5%; + line-height: 1.2; +} + +body div { + margin: 0; +} + +h1, h2, h3, h4, h5, h6, +div.toc p b, +div.list-of-figures p b, +div.list-of-tables p b, +div.abstract p.title +{ + color: #527bbd; + font-family: tahoma, verdana, sans-serif; +} + +div.toc p:first-child, +div.list-of-figures p:first-child, +div.list-of-tables p:first-child, +div.example p.title +{ + margin-bottom: 0.2em; +} + +body h1 { + margin: .0em 0 0 -4%; + line-height: 1.3; + border-bottom: 2px solid silver; +} + +body h2 { + margin: 0.5em 0 0 -4%; + line-height: 1.3; + border-bottom: 2px solid silver; +} + +body h3 { + margin: .8em 0 0 -3%; + line-height: 1.3; +} + +body h4 { + margin: .8em 0 0 -3%; + line-height: 1.3; +} + +body h5 { + margin: .8em 0 0 -2%; + line-height: 1.3; +} + +body h6 { + margin: .8em 0 0 -1%; + line-height: 1.3; +} + +body hr { + border: none; /* Broken on IE6 */ +} +div.footnotes hr { + border: 1px solid silver; +} + +div.navheader th, div.navheader td, div.navfooter td { + font-family: sans-serif; + font-size: 0.9em; + font-weight: bold; + color: #527bbd; +} +div.navheader img, div.navfooter img { + border-style: none; +} +div.navheader a, div.navfooter a { + font-weight: normal; +} +div.navfooter hr { + border: 1px solid silver; +} + +body td { + line-height: 1.2 +} + +body th { + line-height: 1.2; +} + +ol { + line-height: 1.2; +} + +ul, body dir, body menu { + line-height: 1.2; +} + +html { + margin: 0; + padding: 0; +} + +body h1, body h2, body h3, body h4, body h5, body h6 { + margin-left: 0 +} + +body pre { + margin: 0.5em 10% 0.5em 1em; + line-height: 1.0; + color: navy; +} + +tt.literal, code.literal { + color: navy; +} + +div.literallayout p { + padding: 0em; + margin: 0em; +} + +div.literallayout { + font-family: monospace; +# margin: 0.5em 10% 0.5em 1em; + margin: 0em; + color: navy; + border: 1px solid silver; + background: #f4f4f4; + padding: 0.5em; +} + +.programlisting, .screen { + border: 1px solid silver; + background: #f4f4f4; + margin: 0.5em 10% 0.5em 0; + padding: 0.5em 1em; +} + +div.sidebar { + background: #ffffee; + margin: 1.0em 10% 0.5em 0; + padding: 0.5em 1em; + border: 1px solid silver; +} +div.sidebar * { padding: 0; } +div.sidebar div { margin: 0; } +div.sidebar p.title { + font-family: sans-serif; + margin-top: 0.5em; + margin-bottom: 0.2em; +} + +div.bibliomixed { + margin: 0.5em 5% 0.5em 1em; +} + +div.glossary dt { + font-weight: bold; +} +div.glossary dd p { + margin-top: 0.2em; +} + +dl { + margin: .8em 0; + line-height: 1.2; +} + +dt { + margin-top: 0.5em; +} + +dt span.term { + font-style: italic; +} + +div.variablelist dd p { + margin-top: 0; +} + +div.itemizedlist li, div.orderedlist li { + margin-left: -0.8em; + margin-top: 0.5em; +} + +ul, ol { + list-style-position: outside; +} + +div.sidebar ul, div.sidebar ol { + margin-left: 2.8em; +} + +div.itemizedlist p.title, +div.orderedlist p.title, +div.variablelist p.title +{ + margin-bottom: -0.8em; +} + +div.revhistory table { + border-collapse: collapse; + border: none; +} +div.revhistory th { + border: none; + color: #527bbd; + font-family: tahoma, verdana, sans-serif; +} +div.revhistory td { + border: 1px solid silver; +} + +/* Keep TOC and index lines close together. */ +div.toc dl, div.toc dt, +div.list-of-figures dl, div.list-of-figures dt, +div.list-of-tables dl, div.list-of-tables dt, +div.indexdiv dl, div.indexdiv dt +{ + line-height: normal; + margin-top: 0; + margin-bottom: 0; +} + +/* + Table styling does not work because of overriding attributes in + generated HTML. +*/ +div.table table, +div.informaltable table +{ + margin-left: 0; + margin-right: 5%; + margin-bottom: 0.8em; +} +div.informaltable table +{ + margin-top: 0.4em +} +div.table thead, +div.table tfoot, +div.table tbody, +div.informaltable thead, +div.informaltable tfoot, +div.informaltable tbody +{ + /* No effect in IE6. */ + border-top: 2px solid #527bbd; + border-bottom: 2px solid #527bbd; +} +div.table thead, div.table tfoot, +div.informaltable thead, div.informaltable tfoot +{ + font-weight: bold; +} + +div.mediaobject img { + border: 1px solid silver; + margin-bottom: 0.8em; +} +div.figure p.title, +div.table p.title +{ + margin-top: 1em; + margin-bottom: 0.4em; +} + +@media print { + div.navheader, div.navfooter { display: none; } +} diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index bdc7332c7b..da034223f3 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -52,4 +52,3 @@ Deepen the history of a 'shallow' repository created by `git clone` with `--depth=` option (see gitlink:git-clone[1]) by the specified number of commits. - diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index a0c9f68580..76d2b05854 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -228,4 +228,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index f3387f5d09..e4a6b3a6f0 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -158,4 +158,3 @@ Documentation by Petr Baudis, Junio C Hamano and the git-list parameters supplied. If it cannot find the remote branch a merge comes from -it will just import it as a regular commit. If it can find it, it will mark it -as a merge whenever possible (see discussion below). +it will just import it as a regular commit. If it can find it, it will mark it +as a merge whenever possible (see discussion below). -The script expects you to provide the key roots where it can start the import -from an 'initial import' or 'tag' type of Arch commit. It will follow and -import new branches within the provided roots. +The script expects you to provide the key roots where it can start the import +from an 'initial import' or 'tag' type of Arch commit. It will follow and +import new branches within the provided roots. -It expects to be dealing with one project only. If it sees -branches that have different roots, it will refuse to run. In that case, -edit your parameters to define clearly the scope of the -import. +It expects to be dealing with one project only. If it sees +branches that have different roots, it will refuse to run. In that case, +edit your parameters to define clearly the scope of the +import. -`git-archimport` uses `tla` extensively in the background to access the +`git-archimport` uses `tla` extensively in the background to access the Arch repository. Make sure you have a recent version of `tla` available in the path. `tla` must -know about the repositories you pass to `git-archimport`. +know about the repositories you pass to `git-archimport`. -For the initial import `git-archimport` expects to find itself in an empty -directory. To follow the development of a project that uses Arch, rerun -`git-archimport` with the same parameters as the initial import to perform +For the initial import `git-archimport` expects to find itself in an empty +directory. To follow the development of a project that uses Arch, rerun +`git-archimport` with the same parameters as the initial import to perform incremental imports. While git-archimport will try to create sensible branch names for the @@ -54,15 +54,15 @@ convert Arch repositories that had been rotated periodically. MERGES ------ -Patch merge data from Arch is used to mark merges in git as well. git +Patch merge data from Arch is used to mark merges in git as well. git does not care much about tracking patches, and only considers a merge when a branch incorporates all the commits since the point they forked. The end result -is that git will have a good idea of how far branches have diverged. So the +is that git will have a good idea of how far branches have diverged. So the import process does lose some patch-trading metadata. -Fortunately, when you try and merge branches imported from Arch, -git will find a good merge base, and it has a good chance of identifying -patches that have been traded out-of-sequence between the branches. +Fortunately, when you try and merge branches imported from Arch, +git will find a good merge base, and it has a good chance of identifying +patches that have been traded out-of-sequence between the branches. OPTIONS ------- @@ -71,10 +71,10 @@ OPTIONS Display usage. -v:: - Verbose output. + Verbose output. -T:: - Many tags. Will create a tag for every commit, reflecting the commit + Many tags. Will create a tag for every commit, reflecting the commit name in the Arch repository. -f:: @@ -104,7 +104,7 @@ OPTIONS :: - Archive/branch identifier in a format that `tla log` understands. + Archive/branch identifier in a format that `tla log` understands. Author @@ -118,4 +118,3 @@ Documentation by Junio C Hamano, Martin Langhoff and the git-list +'git bisect' DESCRIPTION ----------- @@ -200,4 +200,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index 8dc5171f5e..8d72bb9368 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -158,4 +158,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 075c0d05ef..afa095c795 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -71,4 +71,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 918d8ee720..ea26da8e21 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -215,4 +215,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 68bba98260..47b1e8c2fc 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -68,4 +68,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt index 27b67b81a5..b62c97097f 100644 --- a/Documentation/git-cherry.txt +++ b/Documentation/git-cherry.txt @@ -64,4 +64,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 644bf126fb..2461c0ec2d 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -175,4 +175,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt index 504a3aa1b4..9586b97291 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.txt @@ -40,7 +40,7 @@ OPTIONS -p :: Each '-p' indicates the id of a parent commit object. - + Commit Information ------------------ @@ -107,4 +107,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index da5c242241..827711c3c9 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -14,19 +14,19 @@ SYNOPSIS DESCRIPTION ----------- Exports a commit from GIT to a CVS checkout, making it easier -to merge patches from a git repository into a CVS repository. +to merge patches from a git repository into a CVS repository. -Execute it from the root of the CVS working copy. GIT_DIR must be defined. +Execute it from the root of the CVS working copy. GIT_DIR must be defined. See examples below. -It does its best to do the safe thing, it will check that the files are -unchanged and up to date in the CVS checkout, and it will not autocommit +It does its best to do the safe thing, it will check that the files are +unchanged and up to date in the CVS checkout, and it will not autocommit by default. Supports file additions, removals, and commits that affect binary files. If the commit is a merge commit, you must tell git-cvsexportcommit what parent -should the changeset be done against. +should the changeset be done against. OPTIONS ------- @@ -55,7 +55,7 @@ OPTIONS Force the parent commit, even if it is not a direct parent. -m:: - Prepend the commit message with the provided prefix. + Prepend the commit message with the provided prefix. Useful for patch series and the like. -u:: @@ -73,7 +73,7 @@ Merge one patch into CVS:: $ export GIT_DIR=~/project/.git $ cd ~/project_cvs_checkout $ git-cvsexportcommit -v -$ cvs commit -F .mgs +$ cvs commit -F .mgs ------------ Merge pending patches into CVS automatically -- only if you really know what you are doing :: @@ -95,4 +95,3 @@ Documentation by Martin Langhoff GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index e0be856546..3985e0164b 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -37,7 +37,7 @@ OPTIONS -d :: The root of the CVS archive. May be local (a simple path) or remote; - currently, only the :local:, :ext: and :pserver: access methods + currently, only the :local:, :ext: and :pserver: access methods are supported. If not given, git-cvsimport will try to read it from `CVS/Root`. If no such file exists, it checks for the `CVSROOT` environment variable. @@ -67,7 +67,7 @@ the old cvs2git tool. -k:: Kill keywords: will extract files with '-kk' from the CVS archive to avoid noisy changesets. Highly recommended, but off by default - to preserve compatibility with early imported trees. + to preserve compatibility with early imported trees. -u:: Convert underscores in tag and branch names to dots. @@ -89,15 +89,15 @@ If you need to pass multiple options, separate them with a comma. Instead of calling cvsps, read the provided cvsps output file. Useful for debugging or when cvsps is being handled outside cvsimport. --m:: +-m:: Attempt to detect merges based on the commit message. This option - will enable default regexes that try to capture the name source - branch name from the commit message. + will enable default regexes that try to capture the name source + branch name from the commit message. -M :: Attempt to detect merges based on the commit message with a custom regex. It can be used with '-m' to also see the default regexes. - You must escape forward slashes. + You must escape forward slashes. -S :: Skip paths matching the regex. @@ -156,4 +156,3 @@ Documentation by Matthias Urlichs . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index 9ddab71203..4b30b18b42 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -235,4 +235,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt index dc47b65ced..ac23e28f27 100644 --- a/Documentation/git-describe.txt +++ b/Documentation/git-describe.txt @@ -124,4 +124,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 8d06775a6b..5eacab08dc 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -908,4 +908,3 @@ Documentation by Shawn O. Pearce . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt index 4913c2552f..6affc5bb4d 100644 --- a/Documentation/git-fmt-merge-msg.txt +++ b/Documentation/git-fmt-merge-msg.txt @@ -60,4 +60,3 @@ Documentation by Petr Baudis, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index ed6413a3c7..234c22f57f 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.txt @@ -145,4 +145,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index c5a5dad1ce..97faaa1d3a 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -144,4 +144,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt index 5edc36f060..616f196d81 100644 --- a/Documentation/git-hash-object.txt +++ b/Documentation/git-hash-object.txt @@ -18,7 +18,7 @@ work tree), and optionally writes the resulting object into the object database. Reports its object ID to its standard output. This is used by "git-cvsimport" to update the index without modifying files in the work tree. When is not -specified, it defaults to "blob". +specified, it defaults to "blob". OPTIONS ------- @@ -43,4 +43,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list ' specification can be either a single pattern, or a pair of such patterns separated by a colon ":" (this means that a ref name -cannot have a colon in it). A single pattern '' is just a +cannot have a colon in it). A single pattern '' is just a shorthand for ':'. Each pattern pair consists of the source side (before the colon) diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt index 226926964e..a8a7f6f04b 100644 --- a/Documentation/git-index-pack.txt +++ b/Documentation/git-index-pack.txt @@ -98,4 +98,3 @@ Documentation by Sergey Vlasov GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt index 5412135d76..ab0201aec2 100644 --- a/Documentation/git-init-db.txt +++ b/Documentation/git-init-db.txt @@ -16,4 +16,3 @@ DESCRIPTION This is a synonym for gitlink:git-init[1]. Please refer to the documentation of that command. - diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt index 1b64d3ab03..413ed65143 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.txt @@ -108,4 +108,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-local-fetch.txt b/Documentation/git-local-fetch.txt index 51389ef37d..19b5f8895c 100644 --- a/Documentation/git-local-fetch.txt +++ b/Documentation/git-local-fetch.txt @@ -62,4 +62,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt index ad7f1b9202..7b78599673 100644 --- a/Documentation/git-ls-tree.txt +++ b/Documentation/git-ls-tree.txt @@ -92,4 +92,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt index 16956951dd..64aa6a1ea6 100644 --- a/Documentation/git-mailinfo.txt +++ b/Documentation/git-mailinfo.txt @@ -67,4 +67,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt index abb0903696..c4f4cabbdc 100644 --- a/Documentation/git-mailsplit.txt +++ b/Documentation/git-mailsplit.txt @@ -56,4 +56,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt index 3190aed108..6b71880ec4 100644 --- a/Documentation/git-merge-base.txt +++ b/Documentation/git-merge-base.txt @@ -40,4 +40,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list git-merge-index cat AA MM cat: : No such file or directory @@ -85,4 +85,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 912ef29efc..d285cba033 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -95,7 +95,7 @@ When things cleanly merge, these things happen: 1. the results are updated both in the index file and in your working tree, 2. index file is written out as a tree, -3. the tree gets committed, and +3. the tree gets committed, and 4. the `HEAD` pointer gets advanced. Because of 2., we require that the original state of the index diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index add01e855a..b89c51c65b 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -43,4 +43,3 @@ Documentation by Theodore Y Ts'o. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt index 2860a3d1ba..0ac3be10c7 100644 --- a/Documentation/git-mktag.txt +++ b/Documentation/git-mktag.txt @@ -44,4 +44,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt index 6756b76bb1..2c9cf743c7 100644 --- a/Documentation/git-mv.txt +++ b/Documentation/git-mv.txt @@ -51,4 +51,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index cfe127ad9e..e3549b5044 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -185,4 +185,3 @@ gitlink:git-prune-packed[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt index 94bbea0db2..f2ceebac4b 100644 --- a/Documentation/git-pack-redundant.txt +++ b/Documentation/git-pack-redundant.txt @@ -17,7 +17,7 @@ are redundant. The output is suitable for piping to 'xargs rm' if you are in the root of the repository. git-pack-redundant accepts a list of objects on standard input. Any objects -given will be ignored when checking which packs are required. This makes the +given will be ignored when checking which packs are required. This makes the following command useful when wanting to remove packs which contain unreachable objects. @@ -55,4 +55,3 @@ gitlink:git-prune-packed[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.txt index a7e9fd021a..ad528a9224 100644 --- a/Documentation/git-patch-id.txt +++ b/Documentation/git-patch-id.txt @@ -40,4 +40,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt index 74f37bd904..abc171266a 100644 --- a/Documentation/git-peek-remote.txt +++ b/Documentation/git-peek-remote.txt @@ -52,4 +52,3 @@ Documentation by Junio C Hamano. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt index 310033e460..3800edb7bb 100644 --- a/Documentation/git-prune-packed.txt +++ b/Documentation/git-prune-packed.txt @@ -50,4 +50,3 @@ gitlink:git-repack[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt index 0b44f3015d..50ee5bddd0 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.txt @@ -58,4 +58,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index e9ad10672a..366c5dbdce 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -110,4 +110,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.txt index 296937a416..1c3ef4c593 100644 --- a/Documentation/git-quiltimport.txt +++ b/Documentation/git-quiltimport.txt @@ -58,4 +58,3 @@ Documentation by Eric Biederman GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index acb57447a8..84184d6294 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -356,4 +356,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 1e343bcdcd..f717e1e30c 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -65,4 +65,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-relink.txt b/Documentation/git-relink.txt index aca60120c8..fe631bb3dd 100644 --- a/Documentation/git-relink.txt +++ b/Documentation/git-relink.txt @@ -34,4 +34,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 3dde7134a5..ab232c2f68 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -128,4 +128,3 @@ Documentation by J. Bruce Fields and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index 2847c9b8d7..c33a512ffb 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -101,4 +101,3 @@ gitlink:git-prune-packed[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.txt index 478a5fd6b7..087eeb7cc2 100644 --- a/Documentation/git-request-pull.txt +++ b/Documentation/git-request-pull.txt @@ -37,4 +37,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 7757abe621..e1cb4ef856 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -286,4 +286,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index 8081bbaffa..69db498447 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -56,4 +56,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt index a65f24a0f6..78f45dca2e 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.txt @@ -95,4 +95,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-runstatus.txt b/Documentation/git-runstatus.txt index 8bb52f4687..dee5d0da9d 100644 --- a/Documentation/git-runstatus.txt +++ b/Documentation/git-runstatus.txt @@ -66,4 +66,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index 228b9f14f3..48f2d57b7b 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -32,4 +32,3 @@ Documentation by Petr Baudis and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt index 15cc6f77c1..2220ef6ea8 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.txt @@ -56,4 +56,3 @@ Documentation by Junio C Hamano. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt index be09b62beb..764d99356b 100644 --- a/Documentation/git-show-index.txt +++ b/Documentation/git-show-index.txt @@ -32,4 +32,3 @@ Documentation by Junio C Hamano GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt index 34c5caf2d0..a42e121150 100644 --- a/Documentation/git-show.txt +++ b/Documentation/git-show.txt @@ -84,4 +84,3 @@ This manual page is a stub. You can help the git documentation by expanding it. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-ssh-fetch.txt b/Documentation/git-ssh-fetch.txt index 192b1f15a9..aaf3db06da 100644 --- a/Documentation/git-ssh-fetch.txt +++ b/Documentation/git-ssh-fetch.txt @@ -48,4 +48,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index bdae7d87dc..e97d15e8f2 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -174,4 +174,3 @@ Documentation by Matthias Urlichs . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index 7bde73b1b8..2d01d9666f 100644 --- a/Documentation/git-tar-tree.txt +++ b/Documentation/git-tar-tree.txt @@ -90,4 +90,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list :: Directly insert the specified info into the index. - + --index-info:: Read index information from stdin. --chmod=(+|-)x:: - Set the execute permissions on the updated files. + Set the execute permissions on the updated files. --assume-unchanged, --no-assume-unchanged:: When these flags are specified, the object name recorded @@ -126,7 +126,7 @@ OPTIONS :: Files to act on. Note that files beginning with '.' are discarded. This includes - `./file` and `dir/./file`. If you don't want this, then use + `./file` and `dir/./file`. If you don't want this, then use cleaner names. The same applies to directories ending '/' and paths with '//' @@ -324,4 +324,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt index 7a6132b016..f4c540f39b 100644 --- a/Documentation/git-verify-pack.txt +++ b/Documentation/git-verify-pack.txt @@ -51,4 +51,3 @@ Documentation by Junio C Hamano GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt index 0f9bdb58dc..48d17fd9c4 100644 --- a/Documentation/git-verify-tag.txt +++ b/Documentation/git-verify-tag.txt @@ -29,4 +29,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.txt index 399bff3bbc..607df48f09 100644 --- a/Documentation/git-whatchanged.txt +++ b/Documentation/git-whatchanged.txt @@ -78,4 +78,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt index 48c5894736..e9f82b97b9 100644 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.txt @@ -99,4 +99,3 @@ Documentation by Junio C Hamano, Jonas Fonseca, and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/howto/rebase-and-edit.txt b/Documentation/howto/rebase-and-edit.txt index 646c55cc69..554909fe08 100644 --- a/Documentation/howto/rebase-and-edit.txt +++ b/Documentation/howto/rebase-and-edit.txt @@ -9,16 +9,16 @@ Abstract: In this article, Linus demonstrates how a broken commit On Sat, 13 Aug 2005, Linus Torvalds wrote: -> That's correct. Same things apply: you can move a patch over, and create a -> new one with a modified comment, but basically the _old_ commit will be +> That's correct. Same things apply: you can move a patch over, and create a +> new one with a modified comment, but basically the _old_ commit will be > immutable. Let me clarify. You can entirely _drop_ old branches, so commits may be immutable, but -nothing forces you to keep them. Of course, when you drop a commit, you'll -always end up dropping all the commits that depended on it, and if you -actually got somebody else to pull that commit you can't drop it from +nothing forces you to keep them. Of course, when you drop a commit, you'll +always end up dropping all the commits that depended on it, and if you +actually got somebody else to pull that commit you can't drop it from _their_ repository, but undoing things is not impossible. For example, let's say that you've made a mess of things: you've committed @@ -29,7 +29,7 @@ want to save "b" and "c". What you can do is # for reference git branch broken - # Reset the main branch to three parents back: this + # Reset the main branch to three parents back: this # effectively undoes the three top commits git reset HEAD^^^ git checkout -f @@ -59,7 +59,7 @@ Finally, check out the end result again: to see that everything looks sensible. -And then, you can just remove the broken branch if you decide you really +And then, you can just remove the broken branch if you decide you really don't want it: # remove 'broken' branch @@ -68,8 +68,8 @@ don't want it: # Prune old objects if you're really really sure git prune -And yeah, I'm sure there are other ways of doing this. And as usual, the -above is totally untested, and I just wrote it down in this email, so if +And yeah, I'm sure there are other ways of doing this. And as usual, the +above is totally untested, and I just wrote it down in this email, so if I've done something wrong, you'll have to figure it out on your own ;) Linus @@ -77,5 +77,3 @@ I've done something wrong, you'll have to figure it out on your own ;) To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html - - diff --git a/Documentation/howto/rebase-from-internal-branch.txt b/Documentation/howto/rebase-from-internal-branch.txt index 3b3a5c2e69..7a76045eb7 100644 --- a/Documentation/howto/rebase-from-internal-branch.txt +++ b/Documentation/howto/rebase-from-internal-branch.txt @@ -14,10 +14,10 @@ Petr Baudis writes: > Dear diary, on Sun, Aug 14, 2005 at 09:57:13AM CEST, I got a letter > where Junio C Hamano told me that... >> Linus Torvalds writes: ->> ->> > Junio, maybe you want to talk about how you move patches from your "pu" +>> +>> > Junio, maybe you want to talk about how you move patches from your "pu" >> > branch to the real branches. ->> +>> > Actually, wouldn't this be also precisely for what StGIT is intended to? Exactly my feeling. I was sort of waiting for Catalin to speak @@ -118,7 +118,7 @@ up your changes, along with other changes. where *your "master" head upstream --> #1 --> #2 --> #3 - used \ + used \ to be \--> #A --> #2' --> #3' --> #B --> #C *upstream head @@ -133,7 +133,7 @@ You fetch from upstream, but not merge. $ git fetch upstream This leaves the updated upstream head in .git/FETCH_HEAD but -does not touch your .git/HEAD nor .git/refs/heads/master. +does not touch your .git/HEAD nor .git/refs/heads/master. You run "git rebase" now. $ git rebase FETCH_HEAD master @@ -161,5 +161,3 @@ the #1' commit. To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html - - diff --git a/Documentation/howto/rebuild-from-update-hook.txt b/Documentation/howto/rebuild-from-update-hook.txt index 02621b54a0..8d55dfbfae 100644 --- a/Documentation/howto/rebuild-from-update-hook.txt +++ b/Documentation/howto/rebuild-from-update-hook.txt @@ -84,4 +84,3 @@ There are four things worth mentioning: - This is still crude and does not protect against simultaneous make invocations stomping on each other. I would need to add some locking mechanism for this. - diff --git a/Documentation/howto/revert-branch-rebase.txt b/Documentation/howto/revert-branch-rebase.txt index d88ec23a97..865a666324 100644 --- a/Documentation/howto/revert-branch-rebase.txt +++ b/Documentation/howto/revert-branch-rebase.txt @@ -146,7 +146,7 @@ Everything is in the good order. I do not need the temporary branch nor tag anymore, so remove them: ------------------------------------------------ -$ rm -f .git/refs/tags/pu-anchor +$ rm -f .git/refs/tags/pu-anchor $ git branch -d revert-c99 ------------------------------------------------ diff --git a/Documentation/howto/separating-topic-branches.txt b/Documentation/howto/separating-topic-branches.txt index 090e2c9b01..0d73b31224 100644 --- a/Documentation/howto/separating-topic-branches.txt +++ b/Documentation/howto/separating-topic-branches.txt @@ -12,7 +12,7 @@ up with a history like this: "master" o---o - \ "topic" + \ "topic" o---o---o---o---o---o At this point, "topic" contains something I know I want, but it @@ -29,11 +29,11 @@ start building on top of "master": $ git checkout -b topicA master ... pick and apply pieces from P.diff to build ... commits on topicA branch. - + o---o---o / "topicA" o---o"master" - \ "topic" + \ "topic" o---o---o---o---o---o Before doing each commit on "topicA" HEAD, I run "diff HEAD" @@ -59,7 +59,7 @@ other topic: /o---o---o |/ "topicA" o---o"master" - \ "topic" + \ "topic" o---o---o---o---o---o After I am done, I'd try a pretend-merge between "topicA" and @@ -73,7 +73,7 @@ After I am done, I'd try a pretend-merge between "topicA" and /o---o---o----------' |/ "topicA" o---o"master" - \ "topic" + \ "topic" o---o---o---o---o---o The last diff better not to show anything other than cleanups @@ -84,8 +84,7 @@ for crufts. Then I can finally clean things up: "topicB" o---o---o---o---o - / + / /o---o---o |/ "topicA" o---o"master" - diff --git a/Documentation/howto/use-git-daemon.txt b/Documentation/howto/use-git-daemon.txt index 1a1eb246bf..4e2f75cb61 100644 --- a/Documentation/howto/use-git-daemon.txt +++ b/Documentation/howto/use-git-daemon.txt @@ -49,4 +49,3 @@ Now, test your daemon with $ git ls-remote git://127.0.0.1/rule-the-world.git If this does not work, find out why, and submit a patch to this document. - diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index 56f1d8d69d..d64c259bb3 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -25,4 +25,3 @@ If there is no `-s` option, a built-in list of strategies is used instead (`git-merge-recursive` when merging a single head, `git-merge-octopus` otherwise). - diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index d922e8e86c..c551ea61d2 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -121,4 +121,3 @@ The placeholders are: - '%Creset': reset color - '%m': left, right or boundary mark - '%n': newline - diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt index 7d515be0fd..6338def5a7 100644 --- a/Documentation/pretty-options.txt +++ b/Documentation/pretty-options.txt @@ -11,4 +11,3 @@ command to re-code the commit log message in the encoding preferred by the user. For non plumbing commands this defaults to UTF-8. - diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt index 8d4e950abc..b6eb7fc618 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.txt @@ -58,7 +58,7 @@ is often useful. + Some short-cut notations are also supported. + -* `tag ` means the same as `refs/tags/:refs/tags/`; +* `tag ` means the same as `refs/tags/:refs/tags/`; it requests fetching everything up to the given tag. * A parameter without a colon is equivalent to : when pulling/fetching, so it merges into the current diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt index 15221b5320..4c92e375fe 100644 --- a/Documentation/repository-layout.txt +++ b/Documentation/repository-layout.txt @@ -177,4 +177,3 @@ shallow:: This is similar to `info/grafts` but is internally used and maintained by shallow clone mechanism. See `--depth` option to gitlink:git-clone[1] and gitlink:git-fetch[1]. - diff --git a/Documentation/technical/pack-format.txt b/Documentation/technical/pack-format.txt index 9ce3c473ae..e5b31c81fa 100644 --- a/Documentation/technical/pack-format.txt +++ b/Documentation/technical/pack-format.txt @@ -80,7 +80,7 @@ Pack Idx file: +--------------------------------+ | main | offset | | index | object name 00XXXXXXXXXXXXXXXX | | -table +--------------------------------+ | +table +--------------------------------+ | | offset | | | object name 00XXXXXXXXXXXXXXXX | | +--------------------------------+ | @@ -97,14 +97,14 @@ trailer | | packfile checksum | | +--------------------------------+ | | idxfile checksum | | +--------------------------------+ - .-------. + .-------. | Pack file entry: <+ packed object header: 1-byte size extension bit (MSB) type (next 3 bit) - size0 (lower 4-bit) + size0 (lower 4-bit) n-byte sizeN (as long as MSB is set, each 7-bit) size0..sizeN form 4+7+7+..+7 bit integer, size0 is the least significant part, and sizeN is the @@ -114,5 +114,5 @@ Pack file entry: <+ is the size before compression). If it is DELTA, then 20-byte base object name SHA1 (the size above is the - size of the delta data that follows). + size of the delta data that follows). delta data, deflated. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 7eaafa80e9..957cd00761 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -154,11 +154,11 @@ Author: Jamal Hadi Salim Date: Sat Dec 2 22:22:25 2006 -0800 [XFRM]: Fix aevent structuring to be more complete. - + aevents can not uniquely identify an SA. We break the ABI with this patch, but consensus is that since it is not yet utilized by any (known) application then it is fine (better do it now than later). - + Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller @@ -167,7 +167,7 @@ index 8be626f..d7aac9d 100644 --- a/Documentation/networking/xfrm_sync.txt +++ b/Documentation/networking/xfrm_sync.txt @@ -47,10 +47,13 @@ aevent_id structure looks like: - + struct xfrm_aevent_id { struct xfrm_usersa_id sa_id; + xfrm_address_t saddr; @@ -1056,7 +1056,7 @@ $ git show ------------------------------------------------- As a special shortcut, - + ------------------------------------------------- $ git commit -a ------------------------------------------------- @@ -1554,7 +1554,7 @@ history. Fortunately, git also keeps a log, called a "reflog", of all the previous values of each branch. So in this case you can still find the -old history using, for example, +old history using, for example, ------------------------------------------------- $ git log master@{1} @@ -1630,7 +1630,7 @@ If you decide you want the history back, you can always create a new reference pointing to it, for example, a new branch: ------------------------------------------------ -$ git branch recovered-branch 7281251ddd +$ git branch recovered-branch 7281251ddd ------------------------------------------------ Other types of dangling objects (blobs and trees) are also possible, and @@ -1793,7 +1793,7 @@ like this: you push your personal repo ------------------> your public repo - ^ | + ^ | | | | you pull | they pull | | @@ -2359,7 +2359,7 @@ the result would create a new merge commit, like this: \ \ a--b--c--m <-- mywork ................................................ - + However, if you prefer to keep the history in mywork a simple series of commits without any merges, you may instead choose to use gitlink:git-rebase[1]: @@ -2735,7 +2735,7 @@ must have at least one root, and while you can tie several different root objects together into one project by creating a commit object which has two or more separate roots as its ultimate parents, that's probably just going to confuse people. So aim for the notion of "one root object -per project", even if git itself does not enforce that. +per project", even if git itself does not enforce that. A <> symbolically identifies and can be used to sign other objects. It contains the identifier and type of @@ -2757,7 +2757,7 @@ independently of the contents or the type of the object: all objects can be validated by verifying that (a) their hashes match the content of the file and (b) the object successfully inflates to a stream of bytes that forms a sequence of + + + + . +size> + + . The structured objects can further have their structure and connectivity to other objects verified. This is generally done with @@ -2954,7 +2954,7 @@ cache, and the normal operation is to re-generate it completely from a known tree object, or update/compare it with a live tree that is being developed. If you blow the directory cache away entirely, you generally haven't lost any information as long as you have the name of the tree -that it described. +that it described. At the same time, the index is at the same time also the staging area for creating new trees, and creating a new tree always @@ -2974,7 +2974,7 @@ Generally, all "git" operations work on the index file. Some operations work *purely* on the index file (showing the current state of the index), but most operations move data to and from the index file. Either from the database or from the working directory. Thus there are four -main combinations: +main combinations: [[working-directory-to-index]] working directory -> index @@ -3437,7 +3437,7 @@ because you interrupted a "git fetch" with ^C or something like that, leaving _some_ of the new objects in the object database, but just dangling and useless. -Anyway, once you are sure that you're not interested in any dangling +Anyway, once you are sure that you're not interested in any dangling state, you can just prune all unreachable objects: ------------------------------------------------ @@ -3448,12 +3448,12 @@ and they'll be gone. But you should only run "git prune" on a quiescent repository - it's kind of like doing a filesystem fsck recovery: you don't want to do that while the filesystem is mounted. -(The same is true of "git-fsck" itself, btw - but since -git-fsck never actually *changes* the repository, it just reports -on what it found, git-fsck itself is never "dangerous" to run. -Running it while somebody is actually changing the repository can cause -confusing and scary messages, but it won't actually do anything bad. In -contrast, running "git prune" while somebody is actively changing the +(The same is true of "git-fsck" itself, btw - but since +git-fsck never actually *changes* the repository, it just reports +on what it found, git-fsck itself is never "dangerous" to run. +Running it while somebody is actually changing the repository can cause +confusing and scary messages, but it won't actually do anything bad. In +contrast, running "git prune" while somebody is actively changing the repository is a *BAD* idea). [[birdview-on-the-source-code]] diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 06c360b267..289c8067b5 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -43,5 +43,3 @@ test "$VN" = "$VC" || { echo >&2 "GIT_VERSION = $VN" echo "GIT_VERSION = $VN" >$GVF } - - diff --git a/INSTALL b/INSTALL index 361c65bacc..95269cc513 100644 --- a/INSTALL +++ b/INSTALL @@ -31,7 +31,7 @@ Issues of note: interactive tools. None of the core git stuff needs the wrapper, it's just a convenient shorthand and while it is documented in some places, you can always replace "git commit" with "git-commit" - instead. + instead. But let's face it, most of us don't have GNU interactive tools, and even if we had it, we wouldn't know what it does. I don't think it @@ -111,4 +111,3 @@ Issues of note: would instead give you a copy of what you see at: http://www.kernel.org/pub/software/scm/git/docs/ - diff --git a/arm/sha1.c b/arm/sha1.c index 11b1a048b4..9e3ae038e8 100644 --- a/arm/sha1.c +++ b/arm/sha1.c @@ -49,7 +49,7 @@ void SHA1_Update(SHA_CTX *c, const void *p, unsigned long n) void SHA1_Final(unsigned char *hash, SHA_CTX *c) { uint64_t bitlen; - uint32_t bitlen_hi, bitlen_lo; + uint32_t bitlen_hi, bitlen_lo; unsigned int i, offset, padlen; unsigned char bits[8]; static const unsigned char padding[64] = { 0x80, }; @@ -69,7 +69,7 @@ void SHA1_Final(unsigned char *hash, SHA_CTX *c) bits[5] = bitlen_lo >> 16; bits[6] = bitlen_lo >> 8; bits[7] = bitlen_lo; - SHA1_Update(c, bits, 8); + SHA1_Update(c, bits, 8); for (i = 0; i < 5; i++) { uint32_t v = c->hash[i]; diff --git a/arm/sha1_arm.S b/arm/sha1_arm.S index a328b73375..8c1cb99fb4 100644 --- a/arm/sha1_arm.S +++ b/arm/sha1_arm.S @@ -181,4 +181,3 @@ sha_transform: .L_sha_K: .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 - diff --git a/builtin-annotate.c b/builtin-annotate.c index 9db7cfe74c..fc43eed36b 100644 --- a/builtin-annotate.c +++ b/builtin-annotate.c @@ -22,4 +22,3 @@ int cmd_annotate(int argc, const char **argv, const char *prefix) return cmd_blame(argc + 1, nargv, prefix); } - diff --git a/builtin-diff-index.c b/builtin-diff-index.c index d90eba95a6..81e7167438 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -23,7 +23,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) argc = setup_revisions(argc, argv, &rev, NULL); for (i = 1; i < argc; i++) { const char *arg = argv[i]; - + if (!strcmp(arg, "--cached")) cached = 1; else diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index 5c145d2165..ae60fccea7 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -357,4 +357,3 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) return 0; } - diff --git a/builtin-fsck.c b/builtin-fsck.c index bacae5dfa6..944a496650 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -351,7 +351,7 @@ static int fsck_commit(struct commit *commit) if (!commit->parents && show_root) printf("root %s\n", sha1_to_hex(commit->object.sha1)); if (!commit->date) - printf("bad commit date in %s\n", + printf("bad commit date in %s\n", sha1_to_hex(commit->object.sha1)); return 0; } @@ -719,7 +719,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix) heads = 0; for (i = 1; i < argc; i++) { - const char *arg = argv[i]; + const char *arg = argv[i]; if (*arg == '-') continue; diff --git a/builtin-ls-files.c b/builtin-ls-files.c index f7c066b24b..5398a41415 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -117,7 +117,7 @@ static void show_other_files(struct dir_struct *dir) if (0 <= pos) continue; /* exact match */ pos = -pos - 1; - if (pos < active_nr) { + if (pos < active_nr) { ce = active_cache[pos]; if (ce_namelen(ce) == len && !memcmp(ce->name, ent->name, len)) diff --git a/builtin-name-rev.c b/builtin-name-rev.c index d3c42ed67e..61eba343ab 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -290,4 +290,3 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) return 0; } - diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 8b9740c277..3d396ca37a 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -252,7 +252,7 @@ static void *delta_against(void *buf, unsigned long size, struct object_entry *e delta_buf = diff_delta(otherbuf, othersize, buf, size, &delta_size, 0); if (!delta_buf || delta_size != entry->delta_size) - die("delta size changed"); + die("delta size changed"); free(buf); free(otherbuf); return delta_buf; diff --git a/builtin-rerere.c b/builtin-rerere.c index 8c2c8bdc18..f6409b93c1 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -434,4 +434,3 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) path_list_clear(&merge_rr, 1); return 0; } - diff --git a/builtin-shortlog.c b/builtin-shortlog.c index 8d3f742d43..16af6199ab 100644 --- a/builtin-shortlog.c +++ b/builtin-shortlog.c @@ -331,4 +331,3 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix) return 0; } - diff --git a/cache.h b/cache.h index 8a9d1f3883..5e7381eb1e 100644 --- a/cache.h +++ b/cache.h @@ -479,7 +479,7 @@ extern void prepare_packed_git(void); extern void reprepare_packed_git(void); extern void install_packed_git(struct packed_git *pack); -extern struct packed_git *find_sha1_pack(const unsigned char *sha1, +extern struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs); extern void pack_report(void); diff --git a/commit.c b/commit.c index 5632e32685..57b69ca7fa 100644 --- a/commit.c +++ b/commit.c @@ -148,7 +148,7 @@ static int commit_graft_pos(const unsigned char *sha1) int register_commit_graft(struct commit_graft *graft, int ignore_dups) { int pos = commit_graft_pos(graft->sha1); - + if (0 <= pos) { if (ignore_dups) free(graft); @@ -406,7 +406,7 @@ struct commit_list * insert_by_date(struct commit *item, struct commit_list **li return commit_list_insert(item, pp); } - + void sort_by_date(struct commit_list **list) { struct commit_list *ret = NULL; @@ -1160,7 +1160,7 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, next = next->next; count++; } - + if (!count) return; /* allocate an array to help sort the list */ @@ -1188,11 +1188,11 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, } next=next->next; } - /* + /* * find the tips * - * tips are nodes not reachable from any other node in the list - * + * tips are nodes not reachable from any other node in the list + * * the tips serve as a starting set for the work queue. */ next=*list; @@ -1220,7 +1220,7 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, if (pn) { /* - * parents are only enqueued for emission + * parents are only enqueued for emission * when all their children have been emitted thereby * guaranteeing topological order. */ diff --git a/commit.h b/commit.h index 86e8dca0c9..75b43a53ed 100644 --- a/commit.h +++ b/commit.h @@ -66,7 +66,7 @@ extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit /** Removes the first commit from a list sorted by date, and adds all * of its parents. **/ -struct commit *pop_most_recent_commit(struct commit_list **list, +struct commit *pop_most_recent_commit(struct commit_list **list, unsigned int mark); struct commit *pop_commit(struct commit_list **stack); diff --git a/compat/mmap.c b/compat/mmap.c index 4cfaee3136..c9d46d1742 100644 --- a/compat/mmap.c +++ b/compat/mmap.c @@ -40,4 +40,3 @@ int git_munmap(void *start, size_t length) free(start); return 0; } - diff --git a/config.c b/config.c index 0614c2b29f..58d3ed5d37 100644 --- a/config.c +++ b/config.c @@ -621,7 +621,7 @@ static ssize_t find_beginning_of_line(const char* contents, size_t size, size_t equal_offset = size, bracket_offset = size; ssize_t offset; - for (offset = offset_-2; offset > 0 + for (offset = offset_-2; offset > 0 && contents[offset] != '\n'; offset--) switch (contents[offset]) { case '=': equal_offset = offset; break; @@ -989,4 +989,3 @@ int git_config_rename_section(const char *old_name, const char *new_name) free(config_filename); return ret; } - diff --git a/config.mak.in b/config.mak.in index eb9d7a5549..a3032e389f 100644 --- a/config.mak.in +++ b/config.mak.in @@ -38,4 +38,3 @@ NO_STRCASESTR=@NO_STRCASESTR@ NO_STRLCPY=@NO_STRLCPY@ NO_SETENV=@NO_SETENV@ NO_ICONV=@NO_ICONV@ - diff --git a/connect.c b/connect.c index 8cbda88dda..7fab9c0fd9 100644 --- a/connect.c +++ b/connect.c @@ -390,7 +390,7 @@ static int git_proxy_command_options(const char *var, const char *value) } if (0 <= matchlen) { /* core.gitproxy = none for kernel.org */ - if (matchlen == 4 && + if (matchlen == 4 && !memcmp(value, "none", 4)) matchlen = 0; git_proxy_command = xmalloc(matchlen + 1); diff --git a/contrib/README b/contrib/README index e1c0a01ff3..05f291c1f1 100644 --- a/contrib/README +++ b/contrib/README @@ -41,4 +41,3 @@ submit a patch to create a subdirectory of contrib/ and put your stuff there. -jc - diff --git a/contrib/blameview/README b/contrib/blameview/README index 50a6f67fd6..fada5ce909 100644 --- a/contrib/blameview/README +++ b/contrib/blameview/README @@ -7,4 +7,3 @@ To: Linus Torvalds Cc: git@vger.kernel.org Date: Sat, 27 Jan 2007 18:52:38 -0500 Message-ID: <20070127235238.GA28706@coredump.intra.peff.net> - diff --git a/contrib/gitview/gitview b/contrib/gitview/gitview index 2d80e2bad2..3dc1ef50c7 100755 --- a/contrib/gitview/gitview +++ b/contrib/gitview/gitview @@ -1277,5 +1277,3 @@ if __name__ == "__main__": view = GitView( without_diff != 1) view.run(sys.argv[without_diff:]) - - diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email index d1bef9125b..c589a39a0c 100644 --- a/contrib/hooks/post-receive-email +++ b/contrib/hooks/post-receive-email @@ -199,7 +199,7 @@ generate_email_footer() hooks/post-receive - -- + -- $projectdesc EOF } diff --git a/contrib/remotes2config.sh b/contrib/remotes2config.sh index dc09eae972..0c8b954490 100644 --- a/contrib/remotes2config.sh +++ b/contrib/remotes2config.sh @@ -31,5 +31,3 @@ if [ -d "$GIT_DIR"/remotes ]; then esac done fi - - diff --git a/convert-objects.c b/convert-objects.c index cefbcebdca..90e7900e6d 100644 --- a/convert-objects.c +++ b/convert-objects.c @@ -194,7 +194,7 @@ static unsigned long parse_oldstyle_date(const char *buf) fmt++; } while (*buf && *fmt); printf("left: %s\n", buf); - return mktime(&tm); + return mktime(&tm); } static int convert_date_line(char *dst, void **buf, unsigned long *sp) diff --git a/copy.c b/copy.c index d340bb253e..c225d1b0ff 100644 --- a/copy.c +++ b/copy.c @@ -34,4 +34,3 @@ int copy_fd(int ifd, int ofd) close(ifd); return 0; } - diff --git a/ctype.c b/ctype.c index 56bdffa636..ee06eb7f48 100644 --- a/ctype.c +++ b/ctype.c @@ -20,4 +20,3 @@ unsigned char sane_ctype[256] = { AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, 0, 0, 0, 0, 0, /* 112-15 */ /* Nothing in the 128.. range */ }; - diff --git a/daemon.c b/daemon.c index 674e30dca3..77792509e3 100644 --- a/daemon.c +++ b/daemon.c @@ -133,7 +133,7 @@ static int avoid_alias(char *p) { int sl, ndot; - /* + /* * This resurrects the belts and suspenders paranoia check by HPA * done in <435560F7.4080006@zytor.com> thread, now enter_repo() * does not do getcwd() based path canonicalizations. @@ -247,7 +247,7 @@ static char *path_ok(struct interp *itable) int pathlen = strlen(path); /* The validation is done on the paths after enter_repo - * appends optional {.git,.git/.git} and friends, but + * appends optional {.git,.git/.git} and friends, but * it does not use getcwd(). So if your /pub is * a symlink to /mnt/pub, you can whitelist /pub and * do not have to say /mnt/pub. diff --git a/date.c b/date.c index 4690371e55..316841e8ad 100644 --- a/date.c +++ b/date.c @@ -403,7 +403,7 @@ static int match_multi_number(unsigned long num, char c, const char *date, char } /* - * We've seen a digit. Time? Year? Date? + * We've seen a digit. Time? Year? Date? */ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt) { @@ -495,7 +495,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt } else if (num > 0 && num < 13) { tm->tm_mon = num-1; } - + return n; } @@ -569,13 +569,13 @@ int parse_date(const char *date, char *result, int maxlen) if (!match) { /* BAD CRAP */ match = 1; - } + } date += match; } /* mktime uses local timezone */ - then = my_mktime(&tm); + then = my_mktime(&tm); if (offset == -1) offset = (then - mktime(&tm)) / 60; @@ -691,7 +691,7 @@ static const struct typelen { { "days", 24*60*60 }, { "weeks", 7*24*60*60 }, { NULL } -}; +}; static const char *approxidate_alpha(const char *date, struct tm *tm, int *num) { diff --git a/diff-lib.c b/diff-lib.c index 07f4e8106a..7fb19c7b87 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -664,7 +664,7 @@ int run_diff_index(struct rev_info *revs, int cached) const char *tree_name; int match_missing = 0; - /* + /* * Backward compatibility wart - "diff-index -m" does * not mean "do not ignore merges", but totally different. */ diff --git a/diff.c b/diff.c index c57ac33414..cafa7debeb 100644 --- a/diff.c +++ b/diff.c @@ -3031,7 +3031,7 @@ void diff_addremove(struct diff_options *options, * entries to the diff-core. They will be prefixed * with something like '=' or '*' (I haven't decided * which but should not make any difference). - * Feeding the same new and old to diff_change() + * Feeding the same new and old to diff_change() * also has the same effect. * Before the final output happens, they are pruned after * merged into rename/copy pairs as appropriate. @@ -3058,7 +3058,7 @@ void diff_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path) + const char *base, const char *path) { char concatpath[PATH_MAX]; struct diff_filespec *one, *two; diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index c4a77d71da..af9fffe6e8 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -102,7 +102,7 @@ void diffcore_pickaxe(const char *needle, int opts) for (i = 0; i < q->nr; i++) diff_free_filepair(q->queue[i]); } - else + else /* Showing only the filepairs that has the needle */ for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; diff --git a/entry.c b/entry.c index ae6476496a..c540ae13e8 100644 --- a/entry.c +++ b/entry.c @@ -31,7 +31,7 @@ static void remove_subtree(const char *path) struct dirent *de; char pathbuf[PATH_MAX]; char *name; - + if (!dir) die("cannot opendir %s (%s)", path, strerror(errno)); strcpy(pathbuf, path); diff --git a/environment.c b/environment.c index 9d3e5eb72f..8b9b89d0a0 100644 --- a/environment.c +++ b/environment.c @@ -105,5 +105,3 @@ char *get_graft_file(void) setup_git_env(); return git_graft_file; } - - diff --git a/fetch-pack.c b/fetch-pack.c index aa59043c03..9c81305be5 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -114,7 +114,7 @@ static const unsigned char* get_rev(void) commit->object.flags |= POPPED; if (!(commit->object.flags & COMMON)) non_common_revs--; - + parents = commit->parents; if (commit->object.flags & COMMON) { diff --git a/fetch.c b/fetch.c index 8e29d313f8..dda33e548b 100644 --- a/fetch.c +++ b/fetch.c @@ -15,7 +15,7 @@ int get_verbosely = 0; int get_recover = 0; static unsigned char current_commit_sha1[20]; -void pull_say(const char *fmt, const char *hex) +void pull_say(const char *fmt, const char *hex) { if (get_verbosely) fprintf(stderr, fmt, hex); @@ -153,7 +153,7 @@ static int process(struct object *obj) return 0; prefetch(obj->sha1); } - + object_list_insert(obj, process_queue_end); process_queue_end = &(*process_queue_end)->next; return 0; diff --git a/git-archimport.perl b/git-archimport.perl index c1e7c1ddcb..b21077206a 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -3,19 +3,19 @@ # This tool is copyright (c) 2005, Martin Langhoff. # It is released under the Gnu Public License, version 2. # -# The basic idea is to walk the output of tla abrowse, -# fetch the changesets and apply them. +# The basic idea is to walk the output of tla abrowse, +# fetch the changesets and apply them. # =head1 Invocation - git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] - [ -D depth] [ -t tempdir ] / [ / ] + git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] + [ -D depth] [ -t tempdir ] / [ / ] Imports a project from one or more Arch repositories. It will follow branches and repositories within the namespaces defined by the parameters supplied. If it cannot find the remote branch a merge comes from -it will just import it as a regular commit. If it can find it, it will mark it +it will just import it as a regular commit. If it can find it, it will mark it as a merge whenever possible. See man (1) git-archimport for more details. @@ -25,14 +25,14 @@ See man (1) git-archimport for more details. - create tag objects instead of ref tags - audit shell-escaping of filenames - hide our private tags somewhere smarter - - find a way to make "cat *patches | patch" safe even when patchfiles are missing newlines + - find a way to make "cat *patches | patch" safe even when patchfiles are missing newlines - sort and apply patches by graphing ancestry relations instead of just relying in dates supplied in the changeset itself. tla ancestry-graph -m could be helpful here... =head1 Devel tricks -Add print in front of the shell commands invoked via backticks. +Add print in front of the shell commands invoked via backticks. =head1 Devel Notes @@ -126,16 +126,16 @@ sub do_abrowse { my $stage = shift; while (my ($limit, $level) = each %arch_branches) { next unless $level == $stage; - - open ABROWSE, "$TLA abrowse -fkD --merges $limit |" + + open ABROWSE, "$TLA abrowse -fkD --merges $limit |" or die "Problems with tla abrowse: $!"; - + my %ps = (); # the current one my $lastseen = ''; - + while () { chomp; - + # first record padded w 8 spaces if (s/^\s{8}\b//) { my ($id, $type) = split(m/\s+/, $_, 2); @@ -147,13 +147,13 @@ sub do_abrowse { push (@psets, \%last_ps); $psets{ $last_ps{id} } = \%last_ps; } - + my $branch = extract_versionname($id); %ps = ( id => $id, branch => $branch ); if (%last_ps && ($last_ps{branch} eq $branch)) { $ps{parent_id} = $last_ps{id}; } - + $arch_branches{$branch} = 1; $lastseen = 'id'; @@ -166,16 +166,16 @@ sub do_abrowse { $ps{type} = 't'; # read which revision we've tagged when we parse the log $ps{tag} = $1; - } else { + } else { warn "Unknown type $type"; } $arch_branches{$branch} = 1; $lastseen = 'id'; - } elsif (s/^\s{10}//) { - # 10 leading spaces or more + } elsif (s/^\s{10}//) { + # 10 leading spaces or more # indicate commit metadata - + # date if ($lastseen eq 'id' && m/^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d)/){ $ps{date} = $1; @@ -186,12 +186,12 @@ sub do_abrowse { } elsif ($lastseen eq 'merges' && s/^\s{2}//) { my $id = $_; push (@{$ps{merges}}, $id); - + # aggressive branch finding: if ($opt_D) { my $branch = extract_versionname($id); my $repo = extract_reponame($branch); - + if (archive_reachable($repo) && !defined $arch_branches{$branch}) { $arch_branches{$branch} = $stage + 1; @@ -208,10 +208,10 @@ sub do_abrowse { if (@psets && $psets[$#psets]{branch} eq $ps{branch}) { $temp{parent_id} = $psets[$#psets]{id}; } - push (@psets, \%temp); + push (@psets, \%temp); $psets{ $temp{id} } = \%temp; - } - + } + close ABROWSE or die "$TLA abrowse failed on $limit\n"; } } # end foreach $root @@ -253,7 +253,7 @@ unless (-d $git_dir) { # initial import while (my $file = readdir(DIR)) { # skip non-interesting-files next unless -f "$ptag_dir/$file"; - + # convert first '--' to '/' from old git-archimport to use # as an archivename/c--b--v private tag if ($file !~ m!,!) { @@ -275,7 +275,7 @@ sub extract_reponame { my $fq_cvbr = shift; # archivename/[[[[category]branch]version]revision] return (split(/\//, $fq_cvbr))[0]; } - + sub extract_versionname { my $name = shift; $name =~ s/--(?:patch|version(?:fix)?|base)-\d+$//; @@ -283,7 +283,7 @@ sub extract_versionname { } # convert a fully-qualified revision or version to a unique dirname: -# normalperson@yhbt.net-05/mpd--uclinux--1--patch-2 +# normalperson@yhbt.net-05/mpd--uclinux--1--patch-2 # becomes: normalperson@yhbt.net-05,mpd--uclinux--1 # # the git notion of a branch is closer to @@ -339,7 +339,7 @@ sub git_branchname { sub process_patchset_accurate { my $ps = shift; - + # switch to that branch if we're not already in that branch: if (-e "$git_dir/refs/heads/$ps->{branch}") { system('git-checkout','-f',$ps->{branch}) == 0 or die "$! $?\n"; @@ -348,7 +348,7 @@ sub process_patchset_accurate { my $rm = safe_pipe_capture('git-ls-files','--others','-z'); rmtree(split(/\0/,$rm)) if $rm; } - + # Apply the import/changeset/merge into the working tree my $dir = sync_to_ps($ps); # read the new log entry: @@ -361,9 +361,9 @@ sub process_patchset_accurate { parselog($ps, \@commitlog); if ($ps->{id} =~ /--base-0$/ && $ps->{id} ne $psets[0]{id}) { - # this should work when importing continuations + # this should work when importing continuations if ($ps->{tag} && (my $branchpoint = eval { ptag($ps->{tag}) })) { - + # find where we are supposed to branch from if (! -e "$git_dir/refs/heads/$ps->{branch}") { system('git-branch',$ps->{branch},$branchpoint) == 0 or die "$! $?\n"; @@ -388,8 +388,8 @@ sub process_patchset_accurate { } # allow multiple bases/imports here since Arch supports cherry-picks # from unrelated trees - } - + } + # update the index with all the changes we got system('git-diff-files --name-only -z | '. 'git-update-index --remove -z --stdin') == 0 or die "$! $?\n"; @@ -402,7 +402,7 @@ sub process_patchset_accurate { # does not handle permissions or any renames involving directories sub process_patchset_fast { my $ps = shift; - # + # # create the branch if needed # if ($ps->{type} eq 'i' && !$import) { @@ -417,9 +417,9 @@ sub process_patchset_fast { # new branch! we need to verify a few things die "Branch on a non-tag!" unless $ps->{type} eq 't'; my $branchpoint = ptag($ps->{tag}); - die "Tagging from unknown id unsupported: $ps->{tag}" + die "Tagging from unknown id unsupported: $ps->{tag}" unless $branchpoint; - + # find where we are supposed to branch from if (! -e "$git_dir/refs/heads/$ps->{branch}") { system('git-branch',$ps->{branch},$branchpoint) == 0 or die "$! $?\n"; @@ -435,13 +435,13 @@ sub process_patchset_fast { } system('git-checkout',$ps->{branch}) == 0 or die "$! $?\n"; return 0; - } + } die $! if $?; - } + } # # Apply the import/changeset/merge into the working tree - # + # if ($ps->{type} eq 'i' || $ps->{type} eq 't') { apply_import($ps) or die $!; $stats{import_or_tag}++; @@ -455,10 +455,10 @@ sub process_patchset_fast { # prepare update git's index, based on what arch knows # about the pset, resolve parents, etc # - - my @commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); + + my @commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); die "Error in cat-archive-log: $!" if $?; - + parselog($ps,\@commitlog); # imports don't give us good info @@ -485,10 +485,10 @@ sub process_patchset_fast { if (@$ren % 2) { die "Odd number of entries in rename!?"; } - + while (@$ren) { my $from = shift @$ren; - my $to = shift @$ren; + my $to = shift @$ren; unless (-d dirname($to)) { mkpath(dirname($to)); # will die on err @@ -529,20 +529,20 @@ if ($opt_f) { "Things may be a bit slow\n"; *process_patchset = *process_patchset_accurate; } - + foreach my $ps (@psets) { # process patchsets $ps->{branch} = git_branchname($ps->{id}); # - # ensure we have a clean state - # + # ensure we have a clean state + # if (my $dirty = `git-diff-files`) { die "Unclean tree when about to process $ps->{id} " . " - did we fail to commit cleanly before?\n$dirty"; } die $! if $?; - + # # skip commits already in repo # @@ -559,7 +559,7 @@ foreach my $ps (@psets) { my $tree = `git-write-tree`; die "cannot write tree $!" if $?; chomp $tree; - + # # Who's your daddy? # @@ -570,18 +570,18 @@ foreach my $ps (@psets) { close HEAD; chomp $p; push @par, '-p', $p; - } else { + } else { if ($ps->{type} eq 's') { warn "Could not find the right head for the branch $ps->{branch}"; } } } - + if ($ps->{merges}) { push @par, find_parents($ps); } - # + # # Commit, tag and clean state # $ENV{TZ} = 'GMT'; @@ -592,14 +592,14 @@ foreach my $ps (@psets) { $ENV{GIT_COMMITTER_EMAIL} = $ps->{email}; $ENV{GIT_COMMITTER_DATE} = $ps->{date}; - my $pid = open2(*READER, *WRITER,'git-commit-tree',$tree,@par) + my $pid = open2(*READER, *WRITER,'git-commit-tree',$tree,@par) or die $!; print WRITER $ps->{summary},"\n\n"; print WRITER $ps->{message},"\n"; - + # make it easy to backtrack and figure out which Arch revision this was: print WRITER 'git-archimport-id: ',$ps->{id},"\n"; - + close WRITER; my $commitid = ; # read chomp $commitid; @@ -611,7 +611,7 @@ foreach my $ps (@psets) { } # # Update the branch - # + # open HEAD, ">","$git_dir/refs/heads/$ps->{branch}"; print HEAD $commitid; close HEAD; @@ -640,7 +640,7 @@ exit 0; sub sync_to_ps { my $ps = shift; my $tree_dir = $tmp.'/'.tree_dirname($ps->{id}); - + $opt_v && print "sync_to_ps($ps->{id}) method: "; if (-d $tree_dir) { @@ -674,7 +674,7 @@ sub sync_to_ps { safe_pipe_capture($TLA,'get','--no-pristine',$ps->{id},$tree_dir); $stats{get_new}++; } - + # added -I flag to rsync since we're going to fast! AIEEEEE!!!! system('rsync','-aI','--delete','--exclude',$git_dir, # '--exclude','.arch-inventory', @@ -691,15 +691,15 @@ sub apply_import { mkpath($tmp); safe_pipe_capture($TLA,'get','-s','--no-pristine',$ps->{id},"$tmp/import"); - die "Cannot get import: $!" if $?; + die "Cannot get import: $!" if $?; system('rsync','-aI','--delete', '--exclude',$git_dir, '--exclude','.arch-ids','--exclude','{arch}', "$tmp/import/", './'); die "Cannot rsync import:$!" if $?; - + rmtree("$tmp/import"); die "Cannot remove tempdir: $!" if $?; - + return 1; } @@ -712,13 +712,13 @@ sub apply_cset { # get the changeset safe_pipe_capture($TLA,'get-changeset',$ps->{id},"$tmp/changeset"); die "Cannot get changeset: $!" if $?; - + # apply patches if (`find $tmp/changeset/patches -type f -name '*.patch'`) { # this can be sped up considerably by doing # (find | xargs cat) | patch # but that can get mucked up by patches - # with missing trailing newlines or the standard + # with missing trailing newlines or the standard # 'missing newline' flag in the patch - possibly # produced with an old/buggy diff. # slow and safe, we invoke patch once per patchfile @@ -741,7 +741,7 @@ sub apply_cset { # bring in new files system('rsync','-aI','--exclude',$git_dir, - '--exclude','.arch-ids', + '--exclude','.arch-ids', '--exclude', '{arch}', "$tmp/changeset/new-files-archive/",'./'); @@ -789,7 +789,7 @@ sub parselog { removed_files => 1, removed_directories => 1, ); - + chomp (@$log); while ($_ = shift @$log) { if (/^Continuation-of:\s*(.*)/) { @@ -828,7 +828,7 @@ sub parselog { } } } - + # drop leading empty lines from the log message while (@$log && $log->[0] eq '') { shift @$log; @@ -842,7 +842,7 @@ sub parselog { $ps->{summary} = $log->[0] . '...'; } $ps->{message} = join("\n",@$log); - + # skip Arch control files, unescape pika-escaped files foreach my $k (keys %want_headers) { next unless (defined $ps->{$k}); @@ -867,7 +867,7 @@ sub parselog { # write/read a tag sub tag { my ($tag, $commit) = @_; - + if ($opt_o) { $tag =~ s|/|--|g; } else { @@ -875,7 +875,7 @@ sub tag { $patchname =~ s/.*--//; $tag = git_branchname ($tag) . '--' . $patchname; } - + if ($commit) { open(C,">","$git_dir/refs/tags/$tag") or die "Cannot create tag $tag: $!\n"; @@ -902,8 +902,8 @@ sub ptag { my ($tag, $commit) = @_; # don't use subdirs for tags yet, it could screw up other porcelains - $tag =~ s|/|,|g; - + $tag =~ s|/|,|g; + my $tag_file = "$ptag_dir/$tag"; my $tag_branch_dir = dirname($tag_file); mkpath($tag_branch_dir) unless (-d $tag_branch_dir); @@ -915,7 +915,7 @@ sub ptag { or die "Cannot write tag $tag: $!\n"; close(C) or die "Cannot write tag $tag: $!\n"; - $rptags{$commit} = $tag + $rptags{$commit} = $tag unless $tag =~ m/--base-0$/; } else { # read # if the tag isn't there, return 0 @@ -941,7 +941,7 @@ sub find_parents { # Identify what branches are merging into me # and whether we are fully merged # git-merge-base should tell - # me what the base of the merge should be + # me what the base of the merge should be # my $ps = shift; @@ -963,14 +963,14 @@ sub find_parents { } # - # foreach branch find a merge base and walk it to the + # foreach branch find a merge base and walk it to the # head where we are, collecting the merged patchsets that # Arch has recorded. Keep that in @have # Compare that with the commits on the other branch # between merge-base and the tip of the branch (@need) # and see if we have a series of consecutive patches # starting from the merge base. The tip of the series - # of consecutive patches merged is our new parent for + # of consecutive patches merged is our new parent for # that branch. # foreach my $branch (keys %branches) { @@ -979,13 +979,13 @@ sub find_parents { next unless -e "$git_dir/refs/heads/$branch"; my $mergebase = `git-merge-base $branch $ps->{branch}`; - if ($?) { - # Don't die here, Arch supports one-way cherry-picking - # between branches with no common base (or any relationship - # at all beforehand) - warn "Cannot find merge base for $branch and $ps->{branch}"; - next; - } + if ($?) { + # Don't die here, Arch supports one-way cherry-picking + # between branches with no common base (or any relationship + # at all beforehand) + warn "Cannot find merge base for $branch and $ps->{branch}"; + next; + } chomp $mergebase; # now walk up to the mergepoint collecting what patches we have @@ -1010,7 +1010,7 @@ sub find_parents { # merge what we have with what ancestors have %have = (%have, %ancestorshave); - # see what the remote branch has - these are the merges we + # see what the remote branch has - these are the merges we # will want to have in a consecutive series from the mergebase my $otherbranchtip = git_rev_parse($branch); my @needraw = `git-rev-list --topo-order $otherbranchtip ^$mergebase`; @@ -1018,7 +1018,7 @@ sub find_parents { foreach my $needps (@needraw) { # get the psets $needps = commitid2pset($needps); # git-rev-list will also - # list commits merged in via earlier + # list commits merged in via earlier # merges. we are only interested in commits # from the branch we're looking at if ($branch eq $needps->{branch}) { @@ -1054,7 +1054,7 @@ sub find_parents { next unless ref $psets{$p}{merges}; my @merges = @{$psets{$p}{merges}}; foreach my $merge (@merges) { - if ($parents{$merge}) { + if ($parents{$merge}) { delete $parents{$merge}; } } @@ -1079,10 +1079,10 @@ sub git_rev_parse { sub commitid2pset { my $commitid = shift; chomp $commitid; - my $name = $rptags{$commitid} + my $name = $rptags{$commitid} || die "Cannot find reverse tag mapping for $commitid"; $name =~ s|,|/|; - my $ps = $psets{$name} + my $ps = $psets{$name} || (print Dumper(sort keys %psets)) && die "Cannot find patchset for $name"; return $ps; } @@ -1112,7 +1112,7 @@ sub archive_reachable { my $archive = shift; return 1 if $reachable{$archive}; return 0 if $unreachable{$archive}; - + if (system "$TLA whereis-archive $archive >/dev/null") { if ($opt_a && (system($TLA,'register-archive', "http://mirrors.sourcecontrol.net/$archive") == 0)) { @@ -1127,4 +1127,3 @@ sub archive_reachable { return 1; } } - diff --git a/git-checkout.sh b/git-checkout.sh index 6b6facfd5a..d561c88dcb 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -210,7 +210,7 @@ else esac # Match the index to the working tree, and do a three-way. - git diff-files --name-only | git update-index --remove --stdin && + git diff-files --name-only | git update-index --remove --stdin && work=`git write-tree` && git read-tree $v --reset -u $new || exit @@ -245,7 +245,7 @@ else (exit $saved_err) fi -# +# # Switch the HEAD pointer to the new branch if we # checked out a branch head, and remove any potential # old MERGE_HEAD's (subsequent commits will clearly not diff --git a/git-clone.sh b/git-clone.sh index fdd354f2da..5bfd8d1556 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -2,7 +2,7 @@ # # Copyright (c) 2005, Linus Torvalds # Copyright (c) 2005, Junio C Hamano -# +# # Clone a repository into a different directory that does not yet exist. # See git-sh-setup why. @@ -98,7 +98,7 @@ while *,--na|*,--nak|*,--nake|*,--naked|\ *,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;; *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;; - *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) + *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) local_shared=yes; use_local=yes ;; 1,--template) usage ;; *,--template) @@ -410,4 +410,3 @@ fi rm -f "$GIT_DIR/CLONE_HEAD" "$GIT_DIR/REMOTE_HEAD" trap - 0 - diff --git a/git-commit.sh b/git-commit.sh index e8b60f7049..5547a02954 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -557,7 +557,7 @@ then } >>"$GIT_DIR"/COMMIT_EDITMSG else # we need to check if there is anything to commit - run_status >/dev/null + run_status >/dev/null fi if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" -a -z "$amend" ] then diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 42060ef6e1..e9832d2bb9 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -197,7 +197,7 @@ if (@canstatusfiles) { # ... validate new files, foreach my $f (@afiles) { if (defined ($cvsstat{$f}) and $cvsstat{$f} ne "Unknown") { - $dirty = 1; + $dirty = 1; warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n"; warn "Status was: $cvsstat{$f}\n"; } diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 4e6c9c6cc7..3225a2a25d 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -145,7 +145,7 @@ my $cvs_tree; if ($#ARGV == 0) { $cvs_tree = $ARGV[0]; } elsif (-f 'CVS/Repository') { - open my $f, '<', 'CVS/Repository' or + open my $f, '<', 'CVS/Repository' or die 'Failed to open CVS/Repository'; $cvs_tree = <$f>; chomp $cvs_tree; @@ -434,7 +434,7 @@ sub file { my ($self,$fn,$rev) = @_; my $res; - my ($fh, $name) = tempfile('gitcvs.XXXXXX', + my ($fh, $name) = tempfile('gitcvs.XXXXXX', DIR => File::Spec->tmpdir(), UNLINK => 1); $self->_file($fn,$rev) and $res = $self->_line($fh); @@ -520,8 +520,8 @@ sub is_sha1 { sub get_headref ($$) { my $name = shift; - my $git_dir = shift; - + my $git_dir = shift; + my $f = "$git_dir/refs/heads/$name"; if (open(my $fh, $f)) { chomp(my $r = <$fh>); @@ -771,7 +771,7 @@ sub commit { $xtag =~ s/\s+\*\*.*$//; # Remove stuff like ** INVALID ** and ** FUNKY ** $xtag =~ tr/_/\./ if ( $opt_u ); $xtag =~ s/[\/]/$opt_s/g; - + my $pid = open2($in, $out, 'git-mktag'); print $out "object $cid\n". "type commit\n". @@ -788,7 +788,7 @@ sub commit { $? != 0 or $tagobj !~ /^[0123456789abcdef]{40}$/ ) { die "Cannot create tag object $xtag: $!\n"; } - + open(C,">$git_dir/refs/tags/$xtag") or die "Cannot create tag $xtag: $!\n"; diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN index 25647c8060..eee495a986 100755 --- a/git-gui/GIT-VERSION-GEN +++ b/git-gui/GIT-VERSION-GEN @@ -78,5 +78,3 @@ test "$VN" = "$VC" || { echo >&2 "GITGUI_VERSION = $VN" echo "GITGUI_VERSION = $VN" >$GVF } - - diff --git a/git-gui/lib/class.tcl b/git-gui/lib/class.tcl index 88b056522a..72494c1a1e 100644 --- a/git-gui/lib/class.tcl +++ b/git-gui/lib/class.tcl @@ -151,4 +151,3 @@ auto_mkindex_parser::command constructor {name args} { [format { [list source [file join $dir %s]]} \ [file split $scriptFile]] "\n" } - diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh index 7d62d7902c..254d210bdc 100755 --- a/git-merge-one-file.sh +++ b/git-merge-one-file.sh @@ -88,7 +88,7 @@ case "${1:-.}${2:-.}${3:-.}" in # remove lines that are unique to ours. orig=`git-unpack-file $2` sz0=`wc -c <"$orig"` - diff -u -La/$orig -Lb/$orig $orig $src2 | git-apply --no-add + diff -u -La/$orig -Lb/$orig $orig $src2 | git-apply --no-add sz1=`wc -c <"$orig"` # If we do not have enough common material, it is not diff --git a/git-p4import.py b/git-p4import.py index 60a758bfe3..0f3d97b67e 100644 --- a/git-p4import.py +++ b/git-p4import.py @@ -358,4 +358,3 @@ for id in changes: if stitch == 1: git.clean_directories() stitch = 0 - diff --git a/git-svnimport.perl b/git-svnimport.perl index 3af8c7e110..f4597626b9 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -542,7 +542,7 @@ sub copy_path($$$$$$$$) { if ($node_kind eq $SVN::Node::dir) { $srcpath =~ s#/*$#/#; } - + my $pid = open my $f,'-|'; die $! unless defined $pid; if (!$pid) { @@ -560,7 +560,7 @@ sub copy_path($$$$$$$$) { } else { $p = $path; } - push(@$new,[$mode,$sha1,$p]); + push(@$new,[$mode,$sha1,$p]); } close($f) or print STDERR "$newrev:$newbranch: could not list files in $oldpath \@ $rev\n"; diff --git a/git-tag.sh b/git-tag.sh index 37cee978d2..c84043902f 100755 --- a/git-tag.sh +++ b/git-tag.sh @@ -64,7 +64,7 @@ do done ;; -m) - annotate=1 + annotate=1 shift message="$1" if test "$#" = "0"; then @@ -90,7 +90,7 @@ do username="$1" ;; -d) - shift + shift had_error=0 for tag do @@ -180,4 +180,3 @@ if [ "$annotate" ]; then fi git update-ref "refs/tags/$name" "$object" "$prev" - diff --git a/git-verify-tag.sh b/git-verify-tag.sh index 8db7dd0b7d..f2d5597dba 100755 --- a/git-verify-tag.sh +++ b/git-verify-tag.sh @@ -42,4 +42,3 @@ cat "$GIT_DIR/.tmp-vtag" | sed '/-----BEGIN PGP/Q' | gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1 rm -f "$GIT_DIR/.tmp-vtag" - diff --git a/git.spec.in b/git.spec.in index 3a45eb8761..b9dc1d59eb 100644 --- a/git.spec.in +++ b/git.spec.in @@ -63,7 +63,7 @@ Git tools for importing Perforce repositories. %package email Summary: Git tools for sending email Group: Development/Tools -Requires: git-core = %{version}-%{release} +Requires: git-core = %{version}-%{release} %description email Git tools for sending email. diff --git a/gitk b/gitk index a57e84cef7..87c3690ff3 100755 --- a/gitk +++ b/gitk @@ -337,7 +337,7 @@ proc readrefs {} { set tagids($name) $commit lappend idtags($commit) $name } - } + } catch { set tagcontents($name) [exec git cat-file tag $id] } diff --git a/gitweb/README b/gitweb/README index e02e90f042..7186cede2f 100644 --- a/gitweb/README +++ b/gitweb/README @@ -79,4 +79,3 @@ Originally written by: Any comment/question/concern to: Git mailing list - diff --git a/help.c b/help.c index 6a9af4d175..1cd33ece6b 100644 --- a/help.c +++ b/help.c @@ -219,5 +219,3 @@ int cmd_help(int argc, const char **argv, const char *prefix) return 0; } - - diff --git a/http-fetch.c b/http-fetch.c index 09baedc18a..202fae0ba8 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -828,7 +828,7 @@ static void abort_object_request(struct object_request *obj_req) } unlink(obj_req->tmpfile); if (obj_req->slot) { - release_active_slot(obj_req->slot); + release_active_slot(obj_req->slot); obj_req->slot = NULL; } release_object_request(obj_req); diff --git a/http-push.c b/http-push.c index 79d2c38608..7c3720f602 100644 --- a/http-push.c +++ b/http-push.c @@ -518,7 +518,7 @@ static void start_put(struct transfer_request *request) request->buffer.size = stream.total_out; request->buffer.posn = 0; - request->url = xmalloc(strlen(remote->url) + + request->url = xmalloc(strlen(remote->url) + strlen(request->lock->token) + 51); strcpy(request->url, remote->url); posn = request->url + strlen(remote->url); diff --git a/http.c b/http.c index ae27e0c940..c6fb8ace9f 100644 --- a/http.c +++ b/http.c @@ -137,7 +137,7 @@ static int http_options(const char *var, const char *value) return 0; } -#ifdef USE_CURL_MULTI +#ifdef USE_CURL_MULTI if (!strcmp("http.maxrequests", var)) { if (max_requests == -1) max_requests = git_config_int(var, value); diff --git a/imap-send.c b/imap-send.c index 4283a4acda..a5a0696084 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1239,7 +1239,7 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs ) msg->data[ msg->len ] = 0; *ofs += msg->len; - return 1; + return 1; } static imap_server_conf_t server = diff --git a/local-fetch.c b/local-fetch.c index 4b650efa8b..bf7ec6c2a3 100644 --- a/local-fetch.c +++ b/local-fetch.c @@ -114,7 +114,7 @@ static int fetch_pack(const unsigned char *sha1) return -1; target = find_sha1_pack(sha1, packs); if (!target) - return error("Couldn't find %s: not separate or in any pack", + return error("Couldn't find %s: not separate or in any pack", sha1_to_hex(sha1)); if (get_verbosely) { fprintf(stderr, "Getting pack %s\n", @@ -122,11 +122,11 @@ static int fetch_pack(const unsigned char *sha1) fprintf(stderr, " which contains %s\n", sha1_to_hex(sha1)); } - sprintf(filename, "%s/objects/pack/pack-%s.pack", + sprintf(filename, "%s/objects/pack/pack-%s.pack", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_name(target->sha1), sha1_to_hex(target->sha1), 1); - sprintf(filename, "%s/objects/pack/pack-%s.idx", + sprintf(filename, "%s/objects/pack/pack-%s.idx", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_index_name(target->sha1), sha1_to_hex(target->sha1), 1); @@ -141,7 +141,7 @@ static int fetch_file(const unsigned char *sha1) char *hex = sha1_to_hex(sha1); char *dest_filename = sha1_file_name(sha1); - if (object_name_start < 0) { + if (object_name_start < 0) { strcpy(filename, path); /* e.g. git.git */ strcat(filename, "/objects/"); object_name_start = strlen(filename); diff --git a/lockfile.c b/lockfile.c index 23db35aff2..5ad2858b48 100644 --- a/lockfile.c +++ b/lockfile.c @@ -97,4 +97,3 @@ void rollback_lock_file(struct lock_file *lk) unlink(lk->filename); lk->filename[0] = 0; } - diff --git a/mailmap.c b/mailmap.c index cb567a2832..8714167059 100644 --- a/mailmap.c +++ b/mailmap.c @@ -89,4 +89,3 @@ int map_email(struct path_list *map, const char *email, char *name, int maxlen) } return 0; } - diff --git a/match-trees.c b/match-trees.c index 23cafe47b4..d7e29c4d1d 100644 --- a/match-trees.c +++ b/match-trees.c @@ -301,4 +301,3 @@ void shift_tree(const unsigned char *hash1, splice_tree(hash1, add_prefix, hash2, shifted); } - diff --git a/merge-index.c b/merge-index.c index 5599fd321b..fa719cb0b1 100644 --- a/merge-index.c +++ b/merge-index.c @@ -25,7 +25,7 @@ static void run_program(void) static int merge_entry(int pos, const char *path) { int found; - + if (pos >= active_nr) die("git-merge-index: %s not in the cache", path); arguments[0] = pgm; diff --git a/mktag.c b/mktag.c index 931011121e..070bc96c0d 100644 --- a/mktag.c +++ b/mktag.c @@ -11,7 +11,7 @@ * The first three lines are guaranteed to be at least 63 bytes: * "object \n" is 48 bytes, "type tag\n" at 9 bytes is the * shortest possible type-line, and "tag .\n" at 6 bytes is the - * shortest single-character-tag line. + * shortest single-character-tag line. * * We also artificially limit the size of the full object to 8kB. * Just because I'm a lazy bastard, and if you can't fit a signature diff --git a/mozilla-sha1/sha1.c b/mozilla-sha1/sha1.c index 847531d19f..3f06b83567 100644 --- a/mozilla-sha1/sha1.c +++ b/mozilla-sha1/sha1.c @@ -1,29 +1,29 @@ -/* +/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * + * * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are + * Cryptography Research. Portions created by Paul Kocher are * Copyright (C) 1995-9 by Cryptography Research, Inc. All * Rights Reserved. - * + * * Contributor(s): * * Paul Kocher - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and @@ -149,4 +149,3 @@ static void shaHashBlock(SHA_CTX *ctx) { ctx->H[3] += D; ctx->H[4] += E; } - diff --git a/mozilla-sha1/sha1.h b/mozilla-sha1/sha1.h index 5d82afa3bd..16f2d3d43c 100644 --- a/mozilla-sha1/sha1.h +++ b/mozilla-sha1/sha1.h @@ -1,29 +1,29 @@ -/* +/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is SHA 180-1 Header File - * + * * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are + * Cryptography Research. Portions created by Paul Kocher are * Copyright (C) 1995-9 by Cryptography Research, Inc. All * Rights Reserved. - * + * * Contributor(s): * * Paul Kocher - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and diff --git a/object-refs.c b/object-refs.c index 022e8d841c..5345671569 100644 --- a/object-refs.c +++ b/object-refs.c @@ -85,5 +85,3 @@ void mark_reachable(struct object *obj, unsigned int mask) mark_reachable(refs->ref[i], mask); } } - - diff --git a/object.h b/object.h index 94f19eed86..397bbfa090 100644 --- a/object.h +++ b/object.h @@ -66,7 +66,7 @@ void set_object_refs(struct object *obj, struct object_refs *refs); void mark_reachable(struct object *obj, unsigned int mask); -struct object_list *object_list_insert(struct object *item, +struct object_list *object_list_insert(struct object *item, struct object_list **list_p); void object_list_append(struct object *item, diff --git a/pack-redundant.c b/pack-redundant.c index 6bc3bdf3f4..f5cd0ac59e 100644 --- a/pack-redundant.c +++ b/pack-redundant.c @@ -81,7 +81,7 @@ static struct llist * llist_copy(struct llist *list) { struct llist *ret; struct llist_item *new, *old, *prev; - + llist_init(&ret); if ((ret->size = list->size) == 0) @@ -100,7 +100,7 @@ static struct llist * llist_copy(struct llist *list) } new->next = NULL; ret->back = new; - + return ret; } diff --git a/patch-id.c b/patch-id.c index 086d2d9c68..9349bc5580 100644 --- a/patch-id.c +++ b/patch-id.c @@ -81,4 +81,4 @@ int main(int argc, char **argv) generate_id_list(); return 0; -} +} diff --git a/path-list.c b/path-list.c index caaa5cc57b..dcb4b3ac13 100644 --- a/path-list.c +++ b/path-list.c @@ -100,4 +100,3 @@ void print_path_list(const char *text, const struct path_list *p) for (i = 0; i < p->nr; i++) printf("%s:%p\n", p->items[i].path, p->items[i].util); } - diff --git a/perl/Makefile b/perl/Makefile index 0d695fd2f3..5e079ad011 100644 --- a/perl/Makefile +++ b/perl/Makefile @@ -40,4 +40,3 @@ endif # (even though GIT-CFLAGS aren't used yet. If ever) ../GIT-CFLAGS: $(MAKE) -C .. GIT-CFLAGS - diff --git a/pkt-line.c b/pkt-line.c index b60526869a..355546a1ad 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -5,7 +5,7 @@ * Write a packetized stream, where each line is preceded by * its length (including the header) as a 4-byte hex number. * A length of 'zero' means end of stream (and a length of 1-3 - * would be an error). + * would be an error). * * This is all pretty stupid, but we use this packetized line * format to make a streaming format possible without ever diff --git a/ppc/sha1.c b/ppc/sha1.c index 0820398b00..738e36c1e8 100644 --- a/ppc/sha1.c +++ b/ppc/sha1.c @@ -50,7 +50,7 @@ int SHA1_Update(SHA_CTX *c, const void *ptr, unsigned long n) p += nb; } return 0; -} +} int SHA1_Final(unsigned char *hash, SHA_CTX *c) { diff --git a/read-cache.c b/read-cache.c index ad4e187537..4362b11f47 100644 --- a/read-cache.c +++ b/read-cache.c @@ -166,7 +166,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) changed |= MTIME_CHANGED; if (ce->ce_ctime.nsec != htonl(st->st_ctim.tv_nsec)) changed |= CTIME_CHANGED; -#endif +#endif if (ce->ce_uid != htonl(st->st_uid) || ce->ce_gid != htonl(st->st_gid)) @@ -597,7 +597,7 @@ static int has_dir_name(struct index_state *istate, * is being added, or we already have path and path/file is being * added. Either one would result in a nonsense tree that has path * twice when git-write-tree tries to write it out. Prevent it. - * + * * If ok-to-replace is specified, we remove the conflicting entries * from the cache so the caller should recompute the insert position. * When this happens, we return non-zero. @@ -970,8 +970,8 @@ static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len) write_buffer_len = buffered; len -= partial; data = (char *) data + partial; - } - return 0; + } + return 0; } static int write_index_ext_header(SHA_CTX *context, int fd, @@ -1037,7 +1037,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce) * size to zero here, then the object name recorded * in index is the 6-byte file but the cached stat information * becomes zero --- which would then match what we would - * obtain from the filesystem next time we stat("frotz"). + * obtain from the filesystem next time we stat("frotz"). * * However, the second update-index, before calling * this function, notices that the cached size is 6 diff --git a/rsh.h b/rsh.h index 3b4194239d..ee2f499291 100644 --- a/rsh.h +++ b/rsh.h @@ -1,7 +1,7 @@ #ifndef RSH_H #define RSH_H -int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, +int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, char *url, int rmt_argc, char **rmt_argv); #endif diff --git a/setup.c b/setup.c index a45ea8309a..14f62c42e3 100644 --- a/setup.c +++ b/setup.c @@ -39,7 +39,7 @@ const char *prefix_path(const char *prefix, int len, const char *path) if (len) { int speclen = strlen(path); char *n = xmalloc(speclen + len + 1); - + memcpy(n, prefix, len); memcpy(n + len, path, speclen+1); path = n; @@ -47,7 +47,7 @@ const char *prefix_path(const char *prefix, int len, const char *path) return path; } -/* +/* * Unlike prefix_path, this should be used if the named file does * not have to interact with index entry; i.e. name of a random file * on the filesystem. diff --git a/sha1_file.c b/sha1_file.c index 30bcd46ceb..2b860868f5 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -193,7 +193,7 @@ char *sha1_pack_name(const unsigned char *sha1) *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } - + return base; } @@ -218,7 +218,7 @@ char *sha1_pack_index_name(const unsigned char *sha1) *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } - + return base; } @@ -1139,7 +1139,7 @@ static int parse_sha1_header(const char *hdr, unsigned long *sizep) unsigned long size; /* - * The type can be at most ten bytes (including the + * The type can be at most ten bytes (including the * terminating '\0' that we add), and is followed by * a space. */ @@ -1738,7 +1738,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons return 0; } -struct packed_git *find_sha1_pack(const unsigned char *sha1, +struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs) { struct packed_git *p; diff --git a/shallow.c b/shallow.c index d17868929c..dbd9f5ad0a 100644 --- a/shallow.c +++ b/shallow.c @@ -101,4 +101,3 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth, return result; } - diff --git a/ssh-upload.c b/ssh-upload.c index 498d41e19b..20c35f03dd 100644 --- a/ssh-upload.c +++ b/ssh-upload.c @@ -29,24 +29,24 @@ static int serve_object(int fd_in, int fd_out) { } if (!size) return -1; - + if (verbose) fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); remote = 0; - + if (!has_sha1_file(sha1)) { fprintf(stderr, "git-ssh-upload: could not find %s\n", sha1_to_hex(sha1)); remote = -1; } - + if (write_in_full(fd_out, &remote, 1) != 1) return 0; - + if (remote < 0) return 0; - + return write_sha1_to_fd(fd_out, sha1); } diff --git a/strbuf.c b/strbuf.c index 7f14b0fb59..e33d06b87c 100644 --- a/strbuf.c +++ b/strbuf.c @@ -39,4 +39,3 @@ void read_line(struct strbuf *sb, FILE *fp, int term) { sb->eof = 1; strbuf_end(sb); } - diff --git a/t/Makefile b/t/Makefile index 19e38508a7..b25caca887 100644 --- a/t/Makefile +++ b/t/Makefile @@ -28,4 +28,3 @@ full-svn-test: .PHONY: $(T) clean .NOTPARALLEL: - diff --git a/t/lib-read-tree-m-3way.sh b/t/lib-read-tree-m-3way.sh index d195603dfa..586df2113f 100644 --- a/t/lib-read-tree-m-3way.sh +++ b/t/lib-read-tree-m-3way.sh @@ -87,7 +87,7 @@ test_expect_success \ test_expect_success \ 'recording branch A tree' \ 'tree_A=$(git-write-tree)' - + ################################################################ # Branch B # Start from O diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 186de70243..8bfe8320ea 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -37,7 +37,7 @@ fi find .git/objects -type f -print >should-be-empty test_expect_success \ '.git/objects should be empty after git-init in an empty repo.' \ - 'cmp -s /dev/null should-be-empty' + 'cmp -s /dev/null should-be-empty' # also it should have 2 subdirectories; no fan-out anymore, pack, and info. # 3 is counting "objects" itself diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh index ca2c30f7af..d3f8358485 100755 --- a/t/t1200-tutorial.sh +++ b/t/t1200-tutorial.sh @@ -159,4 +159,3 @@ test_expect_success 'git prune-packed' 'git prune-packed' test_expect_failure '-> only packed objects' 'find -type f .git/objects/[0-9a-f][0-9a-f]' test_done - diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 3f3fd2d7f7..7731fa72ce 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -514,4 +514,3 @@ git config --list > result test_expect_success 'value continued on next line' 'cmp result expect' test_done - diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh index 03ea4dece4..d556b41f13 100755 --- a/t/t2000-checkout-cache-clash.sh +++ b/t/t2000-checkout-cache-clash.sh @@ -49,5 +49,3 @@ test_expect_success \ 'test -f path0 && test -d path1 && test -f path1/file1' test_done - - diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh index 0dcab8f1de..b895a0fe36 100755 --- a/t/t2001-checkout-cache-clash.sh +++ b/t/t2001-checkout-cache-clash.sh @@ -84,4 +84,3 @@ test_expect_success \ test ! -h path1/file1 && test -f path1/file1' test_done - diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 86ee2b0bd3..607f57ff94 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -525,4 +525,3 @@ test_expect_success 'reset and bind merge' ' ' test_done - diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 977c498f00..9e11ed295d 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -54,4 +54,3 @@ test_expect_success 'merge and reference trees equal' \ test_debug 'gitk --all & sleep 1' test_done - diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh index e72c6fd1b4..b8acca1813 100755 --- a/t/t4006-diff-mode.sh +++ b/t/t4006-diff-mode.sh @@ -41,4 +41,3 @@ test_expect_success \ 'git diff expected check' test_done - diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index 7b81c32e57..c23341feb5 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -44,4 +44,3 @@ test_expect_success \ git diff ../t4100/t-apply-7.expect current' test_done - diff --git a/t/t4110-apply-scan.sh b/t/t4110-apply-scan.sh index 005f744816..9faef0d66e 100755 --- a/t/t4110-apply-scan.sh +++ b/t/t4110-apply-scan.sh @@ -98,4 +98,3 @@ test_expect_success "S = cmp" \ 'cmp apply.txt patch.txt' test_done - diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh index 69e9603c78..9baf810bee 100755 --- a/t/t4112-apply-renames.sh +++ b/t/t4112-apply-renames.sh @@ -49,10 +49,10 @@ copy to include/arch/cris/klibc/archsetjmp.h - * arch/x86_64/include/klibc/archsetjmp.h + * arch/cris/include/klibc/archsetjmp.h */ - + #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H - + struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; @@ -74,9 +74,9 @@ copy to include/arch/cris/klibc/archsetjmp.h + unsigned long __sp; + unsigned long __srp; }; - + typedef struct __jmp_buf jmp_buf[1]; - + -#endif /* _SETJMP_H */ +#endif /* _KLIBC_ARCHSETJMP_H */ diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/m32r/klibc/archsetjmp.h @@ -90,10 +90,10 @@ rename to include/arch/m32r/klibc/archsetjmp.h - * arch/x86_64/include/klibc/archsetjmp.h + * arch/m32r/include/klibc/archsetjmp.h */ - + #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H - + struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; @@ -108,9 +108,9 @@ rename to include/arch/m32r/klibc/archsetjmp.h unsigned long __r15; - unsigned long __rip; }; - + typedef struct __jmp_buf jmp_buf[1]; - + -#endif /* _SETJMP_H */ +#endif /* _KLIBC_ARCHSETJMP_H */ EOF diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index 27cc6f2b88..dd88e81e04 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -53,4 +53,3 @@ test_expect_success 'apply --apply' ' ' test_done - diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh index 620a9207bf..edae7056e4 100755 --- a/t/t4119-apply-config.sh +++ b/t/t4119-apply-config.sh @@ -24,7 +24,7 @@ cat >gpatch.file <<\EOF && +++ file1+ 2007-02-21 01:07:44.000000000 -0800 @@ -1 +1 @@ -A -+B ++B EOF sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file && diff --git a/t/t4121-apply-diffs.sh b/t/t4121-apply-diffs.sh index 2b2f1eda21..b95b89c341 100755 --- a/t/t4121-apply-diffs.sh +++ b/t/t4121-apply-diffs.sh @@ -30,4 +30,3 @@ test_expect_success \ '( git diff test~2 test~1; git diff test~1 test~0 )| git apply' test_done - diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 3ddfe64b02..841773f75f 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -53,4 +53,3 @@ test_expect_success 'check result' ' ' test_done - diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index c64ebbb2e9..a46d7f74be 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -148,5 +148,3 @@ test_expect_success 'old records rest in peace' \ "test ! -f $rr/preimage && test ! -f $rr2/preimage" test_done - - diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 477b267599..4eaea8f336 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -66,7 +66,7 @@ test_expect_success 'pack the destination repository' ' ' test_expect_success \ - 'pushing rewound head should not barf but require --force' ' + 'pushing rewound head should not barf but require --force' ' # should not fail but refuse to update. if git-send-pack ./victim/.git/ master then diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 243212d3da..93eaf2c154 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -54,4 +54,3 @@ test_expect_success 'the default remote . should not break explicit pull' ' ' test_done - diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh index 2f8e97cb7e..699df6ebd8 100755 --- a/t/t5710-info-alternate.sh +++ b/t/t5710-info-alternate.sh @@ -104,4 +104,3 @@ test_valid_repo' cd "$base_dir" test_done - diff --git a/t/t6000lib.sh b/t/t6000lib.sh index d40262159b..d548bf8026 100755 --- a/t/t6000lib.sh +++ b/t/t6000lib.sh @@ -17,17 +17,17 @@ unique_commit() _text=$1 _tree=$2 shift 2 - echo $_text | git-commit-tree $(tag $_tree) "$@" + echo $_text | git-commit-tree $(tag $_tree) "$@" } # Save the output of a command into the tag specified. Prepend # a substitution script for the tag onto the front of sed.script save_tag() { - _tag=$1 + _tag=$1 [ -n "$_tag" ] || error "usage: save_tag tag commit-args ..." shift 1 - "$@" >.git/refs/tags/$_tag + "$@" >.git/refs/tags/$_tag echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp cat sed.script >> sed.script.tmp @@ -35,7 +35,7 @@ save_tag() mv sed.script.tmp sed.script } -# Replace unhelpful sha1 hashses with their symbolic equivalents +# Replace unhelpful sha1 hashses with their symbolic equivalents entag() { sed -f sed.script @@ -62,7 +62,7 @@ as_author() commit_date() { _commit=$1 - git-cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p" + git-cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p" } on_committer_date() @@ -103,14 +103,14 @@ name_from_description() # Execute the test described by the first argument, by eval'ing # command line specified in the 2nd argument. Check the status code -# is zero and that the output matches the stream read from +# is zero and that the output matches the stream read from # stdin. test_output_expect_success() -{ +{ _description=$1 _test=$2 [ $# -eq 2 ] || error "usage: test_output_expect_success description test < $_name.expected - test_expect_success "$_description" "check_output $_name \"$_test\"" + test_expect_success "$_description" "check_output $_name \"$_test\"" } diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index fcb3302764..71cbb72e1b 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -26,7 +26,7 @@ test_bisection_diff() # Test if bisection size is close to half of list size within # tolerance. - # + # _bisect_err=`expr $_list_size - $_bisection_size \* 2` test "$_bisect_err" -lt 0 && _bisect_err=`expr 0 - $_bisect_err` _bisect_err=`expr $_bisect_err / 2` ; # floor @@ -116,8 +116,8 @@ on_committer_date "1971-08-16 00:00:06" save_tag V unique_commit V tree -p u1 -p test_sequence() { - _bisect_option=$1 - + _bisect_option=$1 + test_bisection_diff 0 $_bisect_option l0 ^root test_bisection_diff 0 $_bisect_option l1 ^root test_bisection_diff 0 $_bisect_option l2 ^root @@ -152,7 +152,7 @@ test_sequence() test_bisection_diff 0 $_bisect_option u3 ^U test_bisection_diff 0 $_bisect_option u4 ^U test_bisection_diff 0 $_bisect_option u5 ^U - + # # the following illustrates Linus' binary bug blatt idea. # diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh index 499cafb882..0ab14a6e81 100755 --- a/t/t6021-merge-criss-cross.sh +++ b/t/t6021-merge-criss-cross.sh @@ -20,7 +20,7 @@ test_expect_success 'prepare repository' \ 7 8 9" > file && -git add file && +git add file && git commit -m "Initial commit" file && git branch A && git branch B && diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh index c76fccfb5a..43aa5d033d 100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -135,4 +135,3 @@ EOF test_expect_success "expected conflict markers" "git diff expect out" test_done - diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 30f6ade13f..03cdba5808 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -102,4 +102,3 @@ test_expect_success \ # # test_done - diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh index b0252b9413..dd6cc3a55c 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -40,4 +40,3 @@ test_expect_success 'short SHA-1 works' ' test $start = $abbrv' test_done - diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh index dc2afdaa45..d549665400 100755 --- a/t/t9107-git-svn-migrate.sh +++ b/t/t9107-git-svn-migrate.sh @@ -109,4 +109,3 @@ test_expect_success ".rev_db auto-converted to .rev_db.UUID" " " test_done - diff --git a/t/t9111/svnsync.dump b/t/t9111/svnsync.dump index a9a46eeb29..499fa9594f 100644 --- a/t/t9111/svnsync.dump +++ b/t/t9111/svnsync.dump @@ -558,5 +558,3 @@ Text-content-md5: 7abb78de7f2756ca8b511cbc879fd5e7 Content-length: 4 cba - - diff --git a/t/test-lib.sh b/t/test-lib.sh index dee3ad7621..8bf4cf49a2 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -232,7 +232,7 @@ test_create_repo () { mv .git/hooks .git/hooks-disabled cd "$owd" } - + test_done () { trap - exit case "$test_failure" in diff --git a/templates/hooks--commit-msg b/templates/hooks--commit-msg index 9b04f2d69c..c5cdb9d7ee 100644 --- a/templates/hooks--commit-msg +++ b/templates/hooks--commit-msg @@ -19,4 +19,3 @@ test "" = "$(grep '^Signed-off-by: ' "$1" | echo >&2 Duplicate Signed-off-by lines. exit 1 } - diff --git a/templates/hooks--post-receive b/templates/hooks--post-receive index 190de2688c..b70c8fd364 100644 --- a/templates/hooks--post-receive +++ b/templates/hooks--post-receive @@ -14,4 +14,3 @@ #. /usr/share/doc/git-core/contrib/hooks/post-receive-email - diff --git a/templates/hooks--pre-applypatch b/templates/hooks--pre-applypatch index 5f56ce8053..eeccc934ca 100644 --- a/templates/hooks--pre-applypatch +++ b/templates/hooks--pre-applypatch @@ -12,4 +12,3 @@ test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} : - diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit index 723a9ef210..18b87309f6 100644 --- a/templates/hooks--pre-commit +++ b/templates/hooks--pre-commit @@ -68,4 +68,3 @@ perl -e ' } exit($found_bad); ' - diff --git a/tree-walk.c b/tree-walk.c index cbb24eb3f6..8d4b67317f 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -206,4 +206,3 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch free(tree); return retval; } - diff --git a/upload-pack.c b/upload-pack.c index d3a09e78d5..0e881c85b5 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -678,7 +678,7 @@ int main(int argc, char **argv) break; } } - + if (i != argc-1) usage(upload_pack_usage); dir = argv[i]; diff --git a/var.c b/var.c index e585e59d31..4127031910 100644 --- a/var.c +++ b/var.c @@ -67,8 +67,8 @@ int main(int argc, char **argv) val = read_var(argv[1]); if (!val) usage(var_usage); - + printf("%s\n", val); - + return 0; } diff --git a/xdiff-interface.c b/xdiff-interface.c index 963bb89b08..e407cf11b1 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -129,5 +129,3 @@ int buffer_is_binary(const char *ptr, unsigned long size) size = FIRST_FEW_BYTES; return !!memchr(ptr, 0, size); } - - diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index e874a7c46a..9402bb0799 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -103,4 +103,3 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, #endif /* #ifdef __cplusplus */ #endif /* #if !defined(XDIFF_H) */ - diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index 9aeebc473b..5cb7171a8f 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -565,4 +565,3 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, return 0; } - diff --git a/xdiff/xdiffi.h b/xdiff/xdiffi.h index 472aeaecfa..3e099dc445 100644 --- a/xdiff/xdiffi.h +++ b/xdiff/xdiffi.h @@ -57,4 +57,3 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg); #endif /* #if !defined(XDIFFI_H) */ - diff --git a/xdiff/xemit.c b/xdiff/xemit.c index e291dc7608..78b1d4b8bb 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -194,4 +194,3 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, return 0; } - diff --git a/xdiff/xemit.h b/xdiff/xemit.h index e629417dd2..440a7390fa 100644 --- a/xdiff/xemit.h +++ b/xdiff/xemit.h @@ -31,4 +31,3 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, #endif /* #if !defined(XEMIT_H) */ - diff --git a/xdiff/xinclude.h b/xdiff/xinclude.h index 04a9da82c9..526ccb344d 100644 --- a/xdiff/xinclude.h +++ b/xdiff/xinclude.h @@ -40,4 +40,3 @@ #endif /* #if !defined(XINCLUDE_H) */ - diff --git a/xdiff/xmacros.h b/xdiff/xmacros.h index e2cd2023b3..8ef232cfad 100644 --- a/xdiff/xmacros.h +++ b/xdiff/xmacros.h @@ -51,4 +51,3 @@ do { \ #endif /* #if !defined(XMACROS_H) */ - diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c index 1be7b31950..e87ab57c65 100644 --- a/xdiff/xprepare.c +++ b/xdiff/xprepare.c @@ -466,4 +466,3 @@ static int xdl_optimize_ctxs(xdfile_t *xdf1, xdfile_t *xdf2) { return 0; } - diff --git a/xdiff/xprepare.h b/xdiff/xprepare.h index 344c569e8b..8fb06a5374 100644 --- a/xdiff/xprepare.h +++ b/xdiff/xprepare.h @@ -32,4 +32,3 @@ void xdl_free_env(xdfenv_t *xe); #endif /* #if !defined(XPREPARE_H) */ - diff --git a/xdiff/xtypes.h b/xdiff/xtypes.h index 3593a664fc..2511aef8d8 100644 --- a/xdiff/xtypes.h +++ b/xdiff/xtypes.h @@ -65,4 +65,3 @@ typedef struct s_xdfenv { #endif /* #if !defined(XTYPES_H) */ - diff --git a/xdiff/xutils.c b/xdiff/xutils.c index bf91c0f73c..2ade97b257 100644 --- a/xdiff/xutils.c +++ b/xdiff/xutils.c @@ -380,4 +380,3 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, return 0; } - diff --git a/xdiff/xutils.h b/xdiff/xutils.h index 70d8b9838a..d5de8292e0 100644 --- a/xdiff/xutils.h +++ b/xdiff/xutils.h @@ -45,4 +45,3 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, #endif /* #if !defined(XUTILS_H) */ - -- cgit v1.3 From 47598d7a4920f02c60d7091e7186c50468d83aab Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 8 Jun 2007 13:24:56 +0200 Subject: gitweb: Provide links to commitdiff to each parent in 'commitdiff' view Since commit-fb1dde4a we show combined diff for merges in 'commitdiff' view, and since commit-208ecb2e also in 'commit' view. Sometimes though one would want to see diff to one of merge commit parents. It is easy in 'commit' view: in the commit header part there are "diff" links for each of parent header. This commit adds such links also for 'commitdiff' view. Add to difftree / whatchanged table row with "1", "2", ... links to 'commitdiff' view for diff with n-th parent for merge commits, as a table header. This is visible only in 'comitdiff' view, and only for a merge commit (comit with more than one parent). To save space links are shown as "n", where "n" is number of a parent, and not as for example shortened (to 7 characters) sha1 of a parent commit. To make it easier to discover what links is for, each link has 'title' attribute explaining the link. Note that one would need to remember that difftree table in 'commit' view has one less column (it doesn't have "patch" link column), if one would want to add such table header also in 'commit' view. Example output: 1 2 3 Makefile patch | diff1 | diff2 | diff3 | blob | history cache.h patch | diff1 | diff2 | diff3 | blob | history Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 5 +++++ gitweb/gitweb.perl | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 9f0822fab3..7908fe3b5f 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -181,10 +181,15 @@ table.diff_tree { font-family: monospace; } +table.combined.diff_tree th { + text-align: center; +} + table.combined.diff_tree td { padding-right: 24px; } +table.combined.diff_tree th.link, table.combined.diff_tree td.link { padding: 0px 2px; } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e92596c295..e2d52222bf 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2401,6 +2401,26 @@ sub git_difftree_body { print " 1 ? "combined " : "") . "diff_tree\">\n"; + + # header only for combined diff in 'commitdiff' view + my $has_header = @parents > 1 && $action eq 'commitdiff'; + if ($has_header) { + # table header + print "\n" . + "\n"; # filename, patchN link + for (my $i = 0; $i < @parents; $i++) { + my $par = $parents[$i]; + print "\n"; + } + print "\n\n"; + } + my $alternate = 1; my $patchno = 0; foreach my $line (@{$difftree}) { @@ -2673,6 +2693,7 @@ sub git_difftree_body { } # we should not encounter Unmerged (U) or Unknown (X) status print "\n"; } + print "" if $has_header; print "
" . + $cgi->a({-href => href(action=>"commitdiff", + hash=>$hash, hash_parent=>$par), + -title => 'commitdiff to parent number ' . + ($i+1) . ': ' . substr($par,0,7)}, + $i+1) . + " 
\n"; } -- cgit v1.3 From ada3e1f7334b19c98688bcbd7a24d6b559173dfa Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 8 Jun 2007 13:26:31 +0200 Subject: gitweb: Improve "next" link in commitdiff view Check if 'hp' (hash_parent) parameter to 'commitdiff' view is one of 'h' (hash) commit parents, i.e. if commitdiff is of the form "^ ", and mark it as such in the bottom part of navigation bar. The "next" link in commitdiff view was introduced in commit 151602df00b8e5c5b4a8193f59a94b85f9b5aebc If 'hb' is n-th parent of 'h', show the following at the bottom of navigation bar: (from parent n: _commit_) Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e2d52222bf..4561d4ef11 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4479,7 +4479,14 @@ sub git_commitdiff { $hash_parent_short = substr($hash_parent, 0, 7); } $formats_nav .= - ' (from: ' . + ' (from'; + for (my $i = 0; $i < @{$co{'parents'}}; $i++) { + if ($co{'parents'}[$i] eq $hash_parent) { + $formats_nav .= ' parent ' . ($i+1); + last; + } + } + $formats_nav .= ': ' . $cgi->a({-href => href(action=>"commitdiff", hash=>$hash_parent)}, esc_html($hash_parent_short)) . -- cgit v1.3 From 90921740bd00029708370673fdc537522aa48e6f Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 8 Jun 2007 13:27:42 +0200 Subject: gitweb: Split git_patchset_body into separate subroutines This commit makes git_patchset_body easier to read, and reduces level of nesting and indent level. It adds more lines that it removes because of extra parameter passing in subroutines, and subroutine calls in git_patchset_body. Also because there are few added comments. Below there are descriptions of all split-off subroutines: Separate formatting "git diff" header into format_git_diff_header_line. While at it fix it so it always escapes pathname. It would be even more useful if we decide to use `--cc' for merges, and need to generate by hand empty patches for anchors. Separate formatting extended (git) diff header lines into format_extended_diff_header_line. This one is copied without changes. Separate formatting two-lines from-file/to-file diff header into format_diff_from_to_header subroutine. While at it fix it so it always escapes pathname. Beware calling convention: it takes _two_ lines. Separate generating %from and %to hashes (with info used among others to generate hyperlinks) into parse_from_to_diffinfo subroutine. This one is copied without changes. Separate checking if file was deleted (and among others therefore does not have link to the result file) into is_deleted subroutine. This would allow us to easily change the algotithm to find if file is_deleted in the result. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 313 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 202 insertions(+), 111 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 4561d4ef11..aee4f239ae 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -954,7 +954,149 @@ sub format_subject_html { } } -# format patch (diff) line (rather not to be used for diff headers) +# format git diff header line, i.e. "diff --(git|combined|cc) ..." +sub format_git_diff_header_line { + my $line = shift; + my $diffinfo = shift; + my ($from, $to) = @_; + + if ($diffinfo->{'nparents'}) { + # combined diff + $line =~ s!^(diff (.*?) )"?.*$!$1!; + if ($to->{'href'}) { + $line .= $cgi->a({-href => $to->{'href'}, -class => "path"}, + esc_path($to->{'file'})); + } else { # file was deleted (no href) + $line .= esc_path($to->{'file'}); + } + } else { + # "ordinary" diff + $line =~ s!^(diff (.*?) )"?a/.*$!$1!; + if ($from->{'href'}) { + $line .= $cgi->a({-href => $from->{'href'}, -class => "path"}, + 'a/' . esc_path($from->{'file'})); + } else { # file was added (no href) + $line .= 'a/' . esc_path($from->{'file'}); + } + $line .= ' '; + if ($to->{'href'}) { + $line .= $cgi->a({-href => $to->{'href'}, -class => "path"}, + 'b/' . esc_path($to->{'file'})); + } else { # file was deleted + $line .= 'b/' . esc_path($to->{'file'}); + } + } + + return "
$line
\n"; +} + +# format extended diff header line, before patch itself +sub format_extended_diff_header_line { + my $line = shift; + my $diffinfo = shift; + my ($from, $to) = @_; + + # match + if ($line =~ s!^((copy|rename) from ).*$!$1! && $from->{'href'}) { + $line .= $cgi->a({-href=>$from->{'href'}, -class=>"path"}, + esc_path($from->{'file'})); + } + if ($line =~ s!^((copy|rename) to ).*$!$1! && $to->{'href'}) { + $line .= $cgi->a({-href=>$to->{'href'}, -class=>"path"}, + esc_path($to->{'file'})); + } + # match single + if ($line =~ m/\s(\d{6})$/) { + $line .= ' (' . + file_type_long($1) . + ')'; + } + # match + if ($line =~ m/^index [0-9a-fA-F]{40},[0-9a-fA-F]{40}/) { + # can match only for combined diff + $line = 'index '; + for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { + if ($from->{'href'}[$i]) { + $line .= $cgi->a({-href=>$from->{'href'}[$i], + -class=>"hash"}, + substr($diffinfo->{'from_id'}[$i],0,7)); + } else { + $line .= '0' x 7; + } + # separator + $line .= ',' if ($i < $diffinfo->{'nparents'} - 1); + } + $line .= '..'; + if ($to->{'href'}) { + $line .= $cgi->a({-href=>$to->{'href'}, -class=>"hash"}, + substr($diffinfo->{'to_id'},0,7)); + } else { + $line .= '0' x 7; + } + + } elsif ($line =~ m/^index [0-9a-fA-F]{40}..[0-9a-fA-F]{40}/) { + # can match only for ordinary diff + 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'}); + $line =~ s!$from_id\.\.$to_id!$from_link..$to_link!; + } + + return $line . "
\n"; +} + +# format from-file/to-file diff header +sub format_diff_from_to_header { + my ($from_line, $to_line, $diffinfo, $from, $to) = @_; + my $line; + my $result = ''; + + $line = $from_line; + #assert($line =~ m/^---/) if DEBUG; + # no extra formatting "^--- /dev/null" + if ($line =~ m!^--- "?a/!) { + if (!$diffinfo->{'nparents'} && # multiple 'from' + $from->{'href'}) { + $line = '--- a/' . + $cgi->a({-href=>$from->{'href'}, -class=>"path"}, + esc_path($from->{'file'})); + } else { + $line = '--- a/' . + esc_path($from->{'file'}); + } + } + $result .= qq!
$line
\n!; + + $line = $to_line; + #assert($line =~ m/^\+\+\+/) if DEBUG; + # no extra formatting for "^+++ /dev/null" + if ($line =~ m!^\+\+\+ "?b/!) { + if ($to->{'href'}) { + $line = '+++ b/' . + $cgi->a({-href=>$to->{'href'}, -class=>"path"}, + esc_path($to->{'file'})); + } else { + $line = '+++ b/' . + esc_path($to->{'file'}); + } + } + $result .= qq!
$line
\n!; + + return $result; +} + +# format patch (diff) line (not to be used for diff headers) sub format_diff_line { my $line = shift; my ($from, $to) = @_; @@ -1680,6 +1822,48 @@ sub parse_ls_tree_line ($;%) { return wantarray ? %res : \%res; } +# generates _two_ hashes, references to which are passed as 2 and 3 argument +sub parse_from_to_diffinfo { + my ($diffinfo, $from, $to, @parents) = @_; + + if ($diffinfo->{'nparents'}) { + # combined diff + $from->{'file'} = []; + $from->{'href'} = []; + fill_from_file_info($diffinfo, @parents) + unless exists $diffinfo->{'from_file'}; + for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { + $from->{'file'}[$i] = $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'}; + if ($diffinfo->{'status'}[$i] ne "A") { # not new (added) file + $from->{'href'}[$i] = href(action=>"blob", + hash_base=>$parents[$i], + hash=>$diffinfo->{'from_id'}[$i], + file_name=>$from->{'file'}[$i]); + } else { + $from->{'href'}[$i] = undef; + } + } + } else { + $from->{'file'} = $diffinfo->{'from_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'}); + } else { + delete $from->{'href'}; + } + } + + $to->{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; + if (!is_deleted($diffinfo)) { # file exists in result + $to->{'href'} = href(action=>"blob", hash_base=>$hash, + hash=>$diffinfo->{'to_id'}, + file_name=>$to->{'file'}); + } else { + delete $to->{'href'}; + } +} + ## ...................................................................... ## parse to array of hashes functions @@ -2387,6 +2571,11 @@ sub from_ids_eq { } } +sub is_deleted { + my $diffinfo = shift; + + return $diffinfo->{'to_id'} eq ('0' x 40); +} sub git_difftree_body { my ($difftree, $hash, @parents) = @_; @@ -2444,7 +2633,7 @@ sub git_difftree_body { fill_from_file_info($diff, @parents) unless exists $diff->{'from_file'}; - if ($diff->{'to_id'} ne ('0' x 40)) { + if (!is_deleted($diff)) { # file exists in the result (child) commit print "
" . $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'}, @@ -2765,6 +2954,8 @@ sub git_patchset_body { } else { $diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]); } + # modifies %from, %to hashes + parse_from_to_diffinfo($diffinfo, \%from, \%to, @hash_parents); if ($diffinfo->{'nparents'}) { # combined diff $from{'file'} = []; @@ -2794,7 +2985,7 @@ sub git_patchset_body { } $to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; - if ($diffinfo->{'to_id'} ne ('0' x 40)) { # file exists in result + if (!is_deleted($diffinfo)) { # file exists in result $to{'href'} = href(action=>"blob", hash_base=>$hash, hash=>$diffinfo->{'to_id'}, file_name=>$to{'file'}); @@ -2808,105 +2999,15 @@ sub git_patchset_body { # print "git diff" header $patch_line = shift @diff_header; - if ($diffinfo->{'nparents'}) { - - # combined diff - $patch_line =~ s!^(diff (.*?) )"?.*$!$1!; - if ($to{'href'}) { - $patch_line .= $cgi->a({-href => $to{'href'}, -class => "path"}, - esc_path($to{'file'})); - } else { # file was deleted - $patch_line .= esc_path($to{'file'}); - } - - } else { - - $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 "
$patch_line
\n"; + print format_git_diff_header_line($patch_line, $diffinfo, + \%from, \%to); # print extended diff header print "
\n" if (@diff_header > 0); EXTENDED_HEADER: foreach $patch_line (@diff_header) { - # match - 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 single - if ($patch_line =~ m/\s(\d{6})$/) { - $patch_line .= ' (' . - file_type_long($1) . - ')'; - } - # match - if ($patch_line =~ m/^index [0-9a-fA-F]{40},[0-9a-fA-F]{40}/) { - # can match only for combined diff - $patch_line = 'index '; - for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { - if ($from{'href'}[$i]) { - $patch_line .= $cgi->a({-href=>$from{'href'}[$i], - -class=>"hash"}, - substr($diffinfo->{'from_id'}[$i],0,7)); - } else { - $patch_line .= '0' x 7; - } - # separator - $patch_line .= ',' if ($i < $diffinfo->{'nparents'} - 1); - } - $patch_line .= '..'; - if ($to{'href'}) { - $patch_line .= $cgi->a({-href=>$to{'href'}, -class=>"hash"}, - substr($diffinfo->{'to_id'},0,7)); - } else { - $patch_line .= '0' x 7; - } - - } elsif ($patch_line =~ m/^index [0-9a-fA-F]{40}..[0-9a-fA-F]{40}/) { - # can match only for ordinary diff - 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; - } - #affirm { - # my ($from_hash, $to_hash) = - # ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/); - # my ($from_id, $to_id) = - # ($diffinfo->{'from_id'}, $diffinfo->{'to_id'}); - # ($from_hash eq $from_id) && ($to_hash eq $to_id); - #} if DEBUG; - 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 . "
\n"; + print format_extended_diff_header_line($patch_line, $diffinfo, + \%from, \%to); } print "
\n" if (@diff_header > 0); # class="diff extended_header" @@ -2918,24 +3019,14 @@ sub git_patchset_body { } next PATCH if ($patch_line =~ m/^diff /); #assert($patch_line =~ m/^---/) if DEBUG; - if (!$diffinfo->{'nparents'} && # not from-file line for combined diff - $from{'href'} && $patch_line =~ m!^--- "?a/!) { - $patch_line = '--- a/' . - $cgi->a({-href=>$from{'href'}, -class=>"path"}, - esc_path($from{'file'})); - } - print "
$patch_line
\n"; + #assert($patch_line eq $last_patch_line) if DEBUG; $patch_line = <$fd>; chomp $patch_line; + #assert($patch_line =~ m/^\+\+\+/) if DEBUG; - #assert($patch_line =~ m/^+++/) if DEBUG; - if ($to{'href'} && $patch_line =~ m!^\+\+\+ "?b/!) { - $patch_line = '+++ b/' . - $cgi->a({-href=>$to{'href'}, -class=>"path"}, - esc_path($to{'file'})); - } - print "
$patch_line
\n"; + print format_diff_from_to_header($last_patch_line, $patch_line, + $diffinfo, \%from, \%to); # the patch itself LINE: -- cgit v1.3 From deaa01a9f59875dcfd0c9e08ce48f4168f29cb81 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 8 Jun 2007 13:29:49 +0200 Subject: gitweb: Create special from-file/to-file header for combined diff Instead of using default, diff(1) like from-file/to-file header for combined diff (for a merge commit), which looks like: --- a/git-gui/git-gui.sh +++ b/_git-gui/git-gui.sh_ (where _link_ denotes [hidden] hyperlink), create from-file(n)/to-file header, using "--- /__" for each of parents, e.g.: --- 1/_git-gui/git-gui.sh_ --- 2/_git-gui.sh_ +++ b/_git-gui/git-gui.sh_ Test it on one of merge commits involving rename, e.g. 95f97567c1887d77f3a46b42d8622c76414d964d (rename at top) 5bac4a671907604b5fb4e24ff682d5b0e8431931 (file from one branch) This is mainly meant to easier see renames in a merge commit. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index aee4f239ae..13114bc9c6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1064,19 +1064,35 @@ sub format_diff_from_to_header { $line = $from_line; #assert($line =~ m/^---/) if DEBUG; - # no extra formatting "^--- /dev/null" - if ($line =~ m!^--- "?a/!) { - if (!$diffinfo->{'nparents'} && # multiple 'from' - $from->{'href'}) { - $line = '--- a/' . - $cgi->a({-href=>$from->{'href'}, -class=>"path"}, - esc_path($from->{'file'})); - } else { - $line = '--- a/' . - esc_path($from->{'file'}); + # no extra formatting for "^--- /dev/null" + if (! $diffinfo->{'nparents'}) { + # ordinary (single parent) diff + if ($line =~ m!^--- "?a/!) { + if ($from->{'href'}) { + $line = '--- a/' . + $cgi->a({-href=>$from->{'href'}, -class=>"path"}, + esc_path($from->{'file'})); + } else { + $line = '--- a/' . + esc_path($from->{'file'}); + } + } + $result .= qq!
$line
\n!; + + } else { + # combined diff (merge commit) + for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { + if ($from->{'href'}[$i]) { + $line = '--- ' . + ($i+1) . "/" . + $cgi->a({-href=>$from->{'href'}[$i], -class=>"path"}, + esc_path($from->{'file'}[$i])); + } else { + $line = '--- /dev/null'; + } + $result .= qq!
$line
\n!; } } - $result .= qq!
$line
\n!; $line = $to_line; #assert($line =~ m/^\+\+\+/) if DEBUG; -- cgit v1.3 From 91af4ce4ec3f39e1190ab702f51f141e18cdcc1e Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 8 Jun 2007 13:32:44 +0200 Subject: gitweb: Add links to blobdiffs in from-file/to-file header for merges Add links to diff to file ('blobdiff' view) for each of individual versions of the file in a merge commit to the from-file/to-file header in the patch part of combined 'commitdiff' view for merges. The from-file/to-file header for combined diff now looks like: --- _1_/_git-gui/git-gui.sh_ --- _2_/_git-gui.sh_ +++ b/_git-gui/git-gui.sh_ where __ link is link to appropriate version of a file ('blob' view), and __ is link to respective diff to mentioned version of a file ('blobdiff' view). There is even hint provided in the form of title attribute. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 13114bc9c6..c7acfade60 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1058,7 +1058,7 @@ sub format_extended_diff_header_line { # format from-file/to-file diff header sub format_diff_from_to_header { - my ($from_line, $to_line, $diffinfo, $from, $to) = @_; + my ($from_line, $to_line, $diffinfo, $from, $to, @parents) = @_; my $line; my $result = ''; @@ -1084,7 +1084,17 @@ sub format_diff_from_to_header { for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { if ($from->{'href'}[$i]) { $line = '--- ' . - ($i+1) . "/" . + $cgi->a({-href=>href(action=>"blobdiff", + hash_parent=>$diffinfo->{'from_id'}[$i], + hash_parent_base=>$parents[$i], + file_parent=>$from->{'file'}[$i], + hash=>$diffinfo->{'to_id'}, + hash_base=>$hash, + file_name=>$to->{'file'}), + -class=>"path", + -title=>"diff" . ($i+1)}, + $i+1) . + '/' . $cgi->a({-href=>$from->{'href'}[$i], -class=>"path"}, esc_path($from->{'file'}[$i])); } else { @@ -3042,7 +3052,8 @@ sub git_patchset_body { #assert($patch_line =~ m/^\+\+\+/) if DEBUG; print format_diff_from_to_header($last_patch_line, $patch_line, - $diffinfo, \%from, \%to); + $diffinfo, \%from, \%to, + @hash_parents); # the patch itself LINE: -- cgit v1.3 From cd030c3a7053aec0f9dbf321ef139ce02a821f3b Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 8 Jun 2007 13:33:28 +0200 Subject: gitweb: '--cc' for merges in 'commitdiff' view Allow choosing between '-c' (combined diff) and '--cc' (compact combined) diff format in 'commitdiff' view for merge (multiparent) commits. Default is now '--cc'. In the bottom part of navigation bar there is link allowing to change diff format: "combined" for '-c' (when using '--cc') and "compact" for '--cc' (when using '-c'), just on the right of "raw" link to 'commitdiff_plain" view. About patchset part of diff --cc output: the difftree (whatchanged table) has "patch" links to anchors to individual patches (on the same page). The --cc option further compresses the patch output by omitting some hunks; when this optimization makes all hunks disappear, the patch is not shown (like in any other "empty diff" case). But the fact that patch has been simplified out is not reflected in the raw (difftree) part of diff output; the raw part is the same for '-c' and '--cc' options. As correcting difftree is rather out of the question, as it would require scanning patchset part before writing out difftree, we add "Simple merge" empty diffs as a place to have anchor to in place of those simplified out and removed patches. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 111 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 12 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c7acfade60..a6383dc85b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1122,6 +1122,31 @@ sub format_diff_from_to_header { return $result; } +# create note for patch simplified by combined diff +sub format_diff_cc_simplified { + my ($diffinfo, @parents) = @_; + my $result = ''; + + $result .= "
" . + "diff --cc "; + if (!is_deleted($diffinfo)) { + $result .= $cgi->a({-href => href(action=>"blob", + hash_base=>$hash, + hash=>$diffinfo->{'to_id'}, + file_name=>$diffinfo->{'to_file'}), + -class => "path"}, + esc_path($diffinfo->{'to_file'})); + } else { + $result .= esc_path($diffinfo->{'to_file'}); + } + $result .= "
\n" . # class="diff header" + "
" . + "Simple merge" . + "
\n"; # class="diff nodifferences" + + return $result; +} + # format patch (diff) line (not to be used for diff headers) sub format_diff_line { my $line = shift; @@ -2973,13 +2998,33 @@ sub git_patchset_body { # advance raw git-diff output if needed $patch_idx++ if defined $diffinfo; - # 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]); + # compact combined diff output can have some patches skipped + # find which patch (using pathname of result) we are at now + my $to_name; + if ($diff_header[0] =~ m!^diff --cc "?(.*)"?$!) { + $to_name = $1; } + + do { + # 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]); + } + + # check if current raw line has no patch (it got simplified) + if (defined $to_name && $to_name ne $diffinfo->{'to_file'}) { + print "
\n" . + format_diff_cc_simplified($diffinfo, @hash_parents) . + "
\n"; # class="patch" + + $patch_idx++; + $patch_number++; + } + } until (!defined $to_name || $to_name eq $diffinfo->{'to_file'} || + $patch_idx > $#$difftree); # modifies %from, %to hashes parse_from_to_diffinfo($diffinfo, \%from, \%to, @hash_parents); if ($diffinfo->{'nparents'}) { @@ -3069,6 +3114,27 @@ sub git_patchset_body { print "\n"; # class="patch" } + # for compact combined (--cc) format, with chunk and patch simpliciaction + # patchset might be empty, but there might be unprocessed raw lines + for ($patch_idx++ if $patch_number > 0; + $patch_idx < @$difftree; + $patch_idx++) { + # 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]); + } + + # generate anchor for "patch" links in difftree / whatchanged part + print "
\n" . + format_diff_cc_simplified($diffinfo, @hash_parents) . + "
\n"; # class="patch" + + $patch_number++; + } + if ($patch_number == 0) { if (@hash_parents > 1) { print "
Trivial merge
\n"; @@ -4582,7 +4648,11 @@ sub git_commitdiff { die_error(undef, "Unknown commit object"); } - # we need to prepare $formats_nav before any parameter munging + # choose format for commitdiff for merge + if (! defined $hash_parent && @{$co{'parents'}} > 1) { + $hash_parent = '--cc'; + } + # we need to prepare $formats_nav before almost any parameter munging my $formats_nav; if ($format eq 'html') { $formats_nav = @@ -4590,7 +4660,8 @@ sub git_commitdiff { hash=>$hash, hash_parent=>$hash_parent)}, "raw"); - if (defined $hash_parent) { + if (defined $hash_parent && + $hash_parent ne '-c' && $hash_parent ne '--cc') { # commitdiff with two commits given my $hash_parent_short = $hash_parent; if ($hash_parent =~ m/^[0-9a-fA-F]{40}$/) { @@ -4622,6 +4693,17 @@ sub git_commitdiff { ')'; } else { # merge commit + if ($hash_parent eq '--cc') { + $formats_nav .= ' | ' . + $cgi->a({-href => href(action=>"commitdiff", + hash=>$hash, hash_parent=>'-c')}, + 'combined'); + } else { # $hash_parent eq '-c' + $formats_nav .= ' | ' . + $cgi->a({-href => href(action=>"commitdiff", + hash=>$hash, hash_parent=>'--cc')}, + 'compact'); + } $formats_nav .= ' (merge: ' . join(' ', map { @@ -4634,9 +4716,10 @@ sub git_commitdiff { } my $hash_parent_param = $hash_parent; - if (!defined $hash_parent) { + if (!defined $hash_parent_param) { + # --cc for multiple parents, --root for parentless $hash_parent_param = - @{$co{'parents'}} > 1 ? '-c' : $co{'parent'} || '--root'; + @{$co{'parents'}} > 1 ? '--cc' : $co{'parent'} || '--root'; } # read commitdiff @@ -4713,10 +4796,14 @@ TEXT # write patch if ($format eq 'html') { - git_difftree_body(\@difftree, $hash, $hash_parent || @{$co{'parents'}}); + my $use_parents = !defined $hash_parent || + $hash_parent eq '-c' || $hash_parent eq '--cc'; + git_difftree_body(\@difftree, $hash, + $use_parents ? @{$co{'parents'}} : $hash_parent); print "
\n"; - git_patchset_body($fd, \@difftree, $hash, $hash_parent || @{$co{'parents'}}); + git_patchset_body($fd, \@difftree, $hash, + $use_parents ? @{$co{'parents'}} : $hash_parent); close $fd; print "\n"; # class="page_body" git_footer_html(); -- cgit v1.3 From 9a7d941056fcf6df8324097b73c78353174e4e1b Mon Sep 17 00:00:00 2001 From: Matthias Lederhofer Date: Thu, 7 Jun 2007 11:27:08 +0200 Subject: gitweb: change filename/directory name of snapshots /.git or .git is removed from the project name and the basename of the remaining path is used as the beginning of the filename and as the directory in the archive. The regexp will actually not strip off /.git or .git if there wouldn't be anything left after removing it. Currently the full project name is used as directory in the archive and the basename is used as filename. For example a repository named foo/bar/.git will have a archive named .git-.* and extract to foo/bar/.git. With this patch the file is named bar-.* and extracts to bar. Signed-off-by: Matthias Lederhofer Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a6383dc85b..dbfb0441a6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4206,8 +4206,10 @@ sub git_snapshot { my $git = git_cmd_str(); my $name = $project; + $name =~ s,([^/])/*\.git$,$1,; + $name = basename($name); + my $filename = to_utf8($name); $name =~ s/\047/\047\\\047\047/g; - my $filename = to_utf8(basename($project)); my $cmd; if ($suffix eq 'zip') { $filename .= "-$hash.$suffix"; -- cgit v1.3 From 478524508e2f49af8cc76f2d7294a3b33facf121 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Jul 2007 22:10:42 -0700 Subject: gitweb: make repeated calls to git_get_project_owner() bearable If repeated calls to git_get_project_owner() are made, we would have read the same file over and over again. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index dbfb0441a6..d5b8812a12 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1465,12 +1465,12 @@ sub git_get_projects_list { return @list; } -sub git_get_project_owner { - my $project = shift; - my $owner; +our $gitweb_project_owner = undef; +sub git_get_project_list_from_file { - return undef unless $project; + return if (defined $gitweb_project_owner); + $gitweb_project_owner = {}; # read from file (url-encoded): # 'git%2Fgit.git Linus+Torvalds' # 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin' @@ -1482,13 +1482,25 @@ sub git_get_project_owner { my ($pr, $ow) = split ' ', $line; $pr = unescape($pr); $ow = unescape($ow); - if ($pr eq $project) { - $owner = to_utf8($ow); - last; - } + $gitweb_project_owner->{$pr} = to_utf8($ow); } close $fd; } +} + +sub git_get_project_owner { + my $project = shift; + my $owner; + + return undef unless $project; + + if (!defined $gitweb_project_owner) { + git_get_project_list_from_file(); + } + + if (exists $gitweb_project_owner->{$project}) { + $owner = $gitweb_project_owner->{$project}; + } if (!defined $owner) { $owner = get_file_owner("$projectroot/$project"); } -- cgit v1.3 From 76e4f5d025d80479c3a01ed9c65b024e9b80d931 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Wed, 4 Jul 2007 00:11:23 +0200 Subject: gitweb: prefer git_get_project_owner() over get_file_owner() This way if $projects_list exists, it'll be used, otherwise get_file_owner() will be used as before. Signed-off-by: Miklos Vajna Acked-by: Luben Tuikov Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d5b8812a12..9d728d7738 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3178,7 +3178,7 @@ sub git_project_list_body { $pr->{'descr'} = chop_str($descr, 25, 5); } if (!defined $pr->{'owner'}) { - $pr->{'owner'} = get_file_owner("$projectroot/$pr->{'path'}") || ""; + $pr->{'owner'} = git_get_project_owner("$pr->{'path'}") || ""; } if ($check_forks) { my $pname = $pr->{'path'}; @@ -3602,7 +3602,7 @@ sub git_project_index { foreach my $pr (@projects) { if (!exists $pr->{'owner'}) { - $pr->{'owner'} = get_file_owner("$projectroot/$pr->{'path'}"); + $pr->{'owner'} = git_get_project_owner("$pr->{'path'}"); } my ($path, $owner) = ($pr->{'path'}, $pr->{'owner'}); -- cgit v1.3 From 40375a83d2bc3e2c86f998fe47fef573502a9922 Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Thu, 28 Jun 2007 14:57:07 -0400 Subject: gitweb: make search form generate pathinfo-style URLs The search form generated traditional-style URLs with a "p=" parameter even when the pathinfo feature was on. This patch makes it generate pathinfo-style URLs when appropriate. Signed-off-by: Matt McCutchen Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 9d728d7738..4eb7832b4a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2213,12 +2213,18 @@ EOF } else { $search_hash = "HEAD"; } + my $action = $my_uri; + my ($use_pathinfo) = gitweb_check_feature('pathinfo'); + if ($use_pathinfo) { + $action .= "/$project"; + } else { + $cgi->param("p", $project); + } $cgi->param("a", "search"); $cgi->param("h", $search_hash); - $cgi->param("p", $project); - print $cgi->startform(-method => "get", -action => $my_uri) . + print $cgi->startform(-method => "get", -action => $action) . "
\n" . - $cgi->hidden(-name => "p") . "\n" . + (!$use_pathinfo && $cgi->hidden(-name => "p") . "\n") . $cgi->hidden(-name => "a") . "\n" . $cgi->hidden(-name => "h") . "\n" . $cgi->popup_menu(-name => 'st', -default => 'commit', -- cgit v1.3 From c956395e2bf94a50fe843935605914573f4c7787 Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Thu, 28 Jun 2007 18:15:22 -0400 Subject: gitweb: make "No commits" in project list gray, not bold green A missing return statement in git_get_last_activity made gitweb think a project with no commits was in age class "age0", so the "No commits" appeared in bold green, which was ridiculous. I added the return so those projects get "noage" and added a block to gitweb.css to format the "No commits" text gray. Signed-off-by: Matt McCutchen Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 6 ++++++ gitweb/gitweb.perl | 1 + 2 files changed, 7 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 7908fe3b5f..096313bec0 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -281,6 +281,12 @@ table.diff_tree span.file_status.copied { color: #70a070; } +/* noage: "No commits" */ +table.project_list td.noage { + color: #808080; + font-style: italic; +} + /* age2: 60*60*24*2 <= age */ table.project_list td.age2, table.blame td.age2 { font-style: italic; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 4eb7832b4a..dc609f4f86 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1526,6 +1526,7 @@ sub git_get_last_activity { my $age = time - $timestamp; return ($age, age_string($age)); } + return (undef, undef); } sub git_get_references { -- cgit v1.3 From 55feb1200f0e1a7f6cb8670de0dee97f09d8cb9f Mon Sep 17 00:00:00 2001 From: Michael Hendricks Date: Wed, 4 Jul 2007 18:36:48 -0600 Subject: gitweb: configurable width for the projects list Description column This allows gitweb users to set $projects_list_description_width in their gitweb.conf to determine how many characters of a project description are displayed before being truncated with an ellipsis. Signed-off-by: Michael Hendricks Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index dc609f4f86..27580b5670 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -71,6 +71,9 @@ our $logo_label = "git homepage"; # source of projects list our $projects_list = "++GITWEB_LIST++"; +# the width (in characters) of the projects list "Description" column +our $projects_list_description_width = 25; + # default order of projects list # valid values are none, project, descr, owner, and age our $default_projects_order = "project"; @@ -3182,7 +3185,7 @@ sub git_project_list_body { if (!defined $pr->{'descr'}) { my $descr = git_get_project_description($pr->{'path'}) || ""; $pr->{'descr_long'} = to_utf8($descr); - $pr->{'descr'} = chop_str($descr, 25, 5); + $pr->{'descr'} = chop_str($descr, $projects_list_description_width, 5); } if (!defined $pr->{'owner'}) { $pr->{'owner'} = git_get_project_owner("$pr->{'path'}") || ""; -- cgit v1.3 From 868bc068bb45e3b9d135151f2126ce3dba849426 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Thu, 12 Jul 2007 20:39:27 +0200 Subject: gitweb: new cgi parameter: opt Currently the only supported value is '--no-merges' for the 'rss', 'atom', 'log', 'shortlog' and 'history' actions, but it can be easily extended to allow other parameters for other actions. Signed-off-by: Miklos Vajna Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 27580b5670..c8ba3a27a3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -386,6 +386,23 @@ if (defined $hash_base) { } } +my %allowed_options = ( + "--no-merges" => [ qw(rss atom log shortlog history) ], +); + +our @extra_options = $cgi->param('opt'); +if (defined @extra_options) { + foreach(@extra_options) + { + if (not grep(/^$_$/, keys %allowed_options)) { + die_error(undef, "Invalid option parameter"); + } + if (not grep(/^$action$/, @{$allowed_options{$_}})) { + die_error(undef, "Invalid option parameter for this action"); + } + } +} + our $hash_parent_base = $cgi->param('hpb'); if (defined $hash_parent_base) { if (!validate_refname($hash_parent_base)) { @@ -537,6 +554,7 @@ sub href(%) { action => "a", file_name => "f", file_parent => "fp", + extra_options => "opt", hash => "h", hash_parent => "hp", hash_base => "hb", @@ -1773,6 +1791,7 @@ sub parse_commits { ($arg ? ($arg) : ()), ("--max-count=" . $maxcount), ("--skip=" . $skip), + @extra_options, $commit_id, "--", ($filename ? ($filename) : ()) -- cgit v1.3 From 69a9b41c15f25e1e91df5d9c4d5e3d56706f8f0e Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 20 Jul 2007 02:15:09 +0200 Subject: gitweb cleanup: Move @diff_opts declaration earlier Move @diff_opts declaration earlier, so that all gitweb options are together (and not separated by %feature hash and some subroutines), with the exception of $GITWEB_CONFIG which must be after all option variables including %feature hash. While at it, in the moved comment, note that diff option '-C' implies '-M', instead of suggesting that '-M', '-C' is required. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c8ba3a27a3..6754e26873 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -104,6 +104,16 @@ our $mimetypes_file = undef; # could be even 'utf-8' for the old behavior) our $fallback_encoding = 'latin1'; +# rename detection options for git-diff and git-diff-tree +# - default is '-M', with the cost proportional to +# (number of removed files) * (number of new files). +# - more costly is '-C' (which implies '-M'), with the cost proportional to +# (number of changed files + number of removed files) * (number of new files) +# - even more costly is '-C', '--find-copies-harder' with cost +# (number of files in the original tree) * (number of new files) +# - one might want to include '-B' option, e.g. '-B', '-M' +our @diff_opts = ('-M'); # taken from git_commit + # You define site-wide feature defaults here; override them with # $GITWEB_CONFIG as necessary. our %feature = ( @@ -310,16 +320,6 @@ sub check_export_ok { (!$export_ok || -e "$dir/$export_ok")); } -# rename detection options for git-diff and git-diff-tree -# - default is '-M', with the cost proportional to -# (number of removed files) * (number of new files). -# - more costly is '-C' (or '-C', '-M'), with the cost proportional to -# (number of changed files + number of removed files) * (number of new files) -# - even more costly is '-C', '--find-copies-harder' with cost -# (number of files in the original tree) * (number of new files) -# - one might want to include '-B' option, e.g. '-B', '-M' -our @diff_opts = ('-M'); # taken from git_commit - our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++"; do $GITWEB_CONFIG if -e $GITWEB_CONFIG; -- cgit v1.3 From a3c8ab30a54c30a6a434760bedf04548425416ef Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Sun, 22 Jul 2007 01:30:27 +0200 Subject: gitweb: snapshot cleanups & support for offering multiple formats - Centralize knowledge about snapshot formats (mime types, extensions, commands) in %known_snapshot_formats and improve how some of that information is specified. In particular, zip files are no longer a special case. - Add support for offering multiple snapshot formats to the user so that he/she can download a snapshot in the format he/she prefers. The site-wide or project configuration now gives a list of formats to offer, and if more than one format is offered, the "_snapshot_" link becomes something like "snapshot (_tar.bz2_ _zip_)". - If only one format is offered, a tooltip on the "_snapshot_" link tells the user what it is. - Fix out-of-date "tarball" -> "archive" in comment. Alert for gitweb site administrators: This patch changes the format of $feature{'snapshot'}{'default'} in gitweb_config.perl from a list of three pieces of information about a single format to a list of one or more formats you wish to offer from the set ('tgz', 'tbz2', 'zip'). Update your gitweb_config.perl appropriately. There was taken care for old-style gitweb configuration to work as it used to, but this backward compatibility works only for the values which correspond to gitweb.snapshot values of 'gzip', 'bzip2' and 'zip', i.e. ['x-gzip', 'gz', 'gzip'] ['x-bzip2', 'bz2', 'bzip2'] ['x-zip', 'zip', ''] The preferred names for gitweb.snapshot in repository configuration have also changed from 'gzip' and 'bzip2' to 'tgz' and 'tbz2', but the old names are still recognized for compatibility. Signed-off-by: Matt McCutchen Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 166 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 50 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6754e26873..c4f88245aa 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -114,6 +114,49 @@ our $fallback_encoding = 'latin1'; # - one might want to include '-B' option, e.g. '-B', '-M' our @diff_opts = ('-M'); # taken from git_commit +# information about snapshot formats that gitweb is capable of serving +our %known_snapshot_formats = ( + # name => { + # 'display' => display name, + # 'type' => mime type, + # 'suffix' => filename suffix, + # 'format' => --format for git-archive, + # 'compressor' => [compressor command and arguments] + # (array reference, optional)} + # + 'tgz' => { + 'display' => 'tar.gz', + 'type' => 'application/x-gzip', + 'suffix' => '.tar.gz', + 'format' => 'tar', + 'compressor' => ['gzip']}, + + 'tbz2' => { + 'display' => 'tar.bz2', + 'type' => 'application/x-bzip2', + 'suffix' => '.tar.bz2', + 'format' => 'tar', + 'compressor' => ['bzip2']}, + + 'zip' => { + 'display' => 'zip', + 'type' => 'application/x-zip', + 'suffix' => '.zip', + 'format' => 'zip'}, +); + +# Aliases so we understand old gitweb.snapshot values in repository +# configuration. +our %known_snapshot_format_aliases = ( + 'gzip' => 'tgz', + 'bzip2' => 'tbz2', + + # backward compatibility: legacy gitweb config support + 'x-gzip' => undef, 'gz' => undef, + 'x-bzip2' => undef, 'bz2' => undef, + 'x-zip' => undef, '' => undef, +); + # You define site-wide feature defaults here; override them with # $GITWEB_CONFIG as necessary. our %feature = ( @@ -144,20 +187,22 @@ our %feature = ( 'override' => 0, 'default' => [0]}, - # Enable the 'snapshot' link, providing a compressed tarball of any + # Enable the 'snapshot' link, providing a compressed archive of any # tree. This can potentially generate high traffic if you have large # project. + # Value is a list of formats defined in %known_snapshot_formats that + # you wish to offer. # To disable system wide have in $GITWEB_CONFIG - # $feature{'snapshot'}{'default'} = [undef]; + # $feature{'snapshot'}{'default'} = []; # To have project specific config enable override in $GITWEB_CONFIG # $feature{'snapshot'}{'override'} = 1; - # and in project config gitweb.snapshot = none|gzip|bzip2|zip; + # and in project config, a comma-separated list of formats or "none" + # to disable. Example: gitweb.snapshot = tbz2,zip; 'snapshot' => { 'sub' => \&feature_snapshot, 'override' => 0, - # => [content-encoding, suffix, program] - 'default' => ['x-gzip', 'gz', 'gzip']}, + 'default' => ['tgz']}, # Enable text search, which will list the commits which match author, # committer or commit text to a given string. Enabled by default. @@ -256,28 +301,19 @@ sub feature_blame { } sub feature_snapshot { - my ($ctype, $suffix, $command) = @_; + my (@fmts) = @_; my ($val) = git_get_project_config('snapshot'); - if ($val eq 'gzip') { - return ('x-gzip', 'gz', 'gzip'); - } elsif ($val eq 'bzip2') { - return ('x-bzip2', 'bz2', 'bzip2'); - } elsif ($val eq 'zip') { - return ('x-zip', 'zip', ''); - } elsif ($val eq 'none') { - return (); + if ($val) { + @fmts = ($val eq 'none' ? () : split /\s*[,\s]\s*/, $val); + @fmts = grep { defined } map { + exists $known_snapshot_format_aliases{$_} ? + $known_snapshot_format_aliases{$_} : $_ } @fmts; + @fmts = grep(exists $known_snapshot_formats{$_}, @fmts); } - return ($ctype, $suffix, $command); -} - -sub gitweb_have_snapshot { - my ($ctype, $suffix, $command) = gitweb_check_feature('snapshot'); - my $have_snapshot = (defined $ctype && defined $suffix); - - return $have_snapshot; + return @fmts; } sub feature_grep { @@ -563,6 +599,7 @@ sub href(%) { order => "o", searchtext => "s", searchtype => "st", + snapshot_format => "sf", ); my %mapping = @mapping; @@ -1257,6 +1294,39 @@ sub format_diff_line { return "
" . esc_html($line, -nbsp=>1) . "
\n"; } +# Generates undef or something like "_snapshot_" or "snapshot (_tbz2_ _zip_)", +# linked. Pass the hash of the tree/commit to snapshot. +sub format_snapshot_links { + my ($hash) = @_; + my @snapshot_fmts = gitweb_check_feature('snapshot'); + my $num_fmts = @snapshot_fmts; + if ($num_fmts > 1) { + # A parenthesized list of links bearing format names. + return "snapshot (" . join(' ', map + $cgi->a({ + -href => href( + action=>"snapshot", + hash=>$hash, + snapshot_format=>$_ + ) + }, $known_snapshot_formats{$_}{'display'}) + , @snapshot_fmts) . ")"; + } elsif ($num_fmts == 1) { + # A single "snapshot" link whose tooltip bears the format name. + my ($fmt) = @snapshot_fmts; + return $cgi->a({ + -href => href( + action=>"snapshot", + hash=>$hash, + snapshot_format=>$fmt + ), + -title => "in format: $known_snapshot_formats{$fmt}{'display'}" + }, "snapshot"); + } else { # $num_fmts == 0 + return undef; + } +} + ## ---------------------------------------------------------------------- ## git utility subroutines, invoking git commands @@ -3321,8 +3391,6 @@ sub git_shortlog_body { # uses global variable $project my ($commitlist, $from, $to, $refs, $extra) = @_; - my $have_snapshot = gitweb_have_snapshot(); - $from = 0 unless defined $from; $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to); @@ -3349,8 +3417,9 @@ sub git_shortlog_body { $cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") . " | " . $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") . " | " . $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree"); - if ($have_snapshot) { - print " | " . $cgi->a({-href => href(action=>"snapshot", hash=>$commit)}, "snapshot"); + my $snapshot_links = format_snapshot_links($commit); + if (defined $snapshot_links) { + print " | " . $snapshot_links; } print "
" . $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash)}, "tree"); - if ($have_snapshot) { - print " | " . - $cgi->a({-href => href(action=>"snapshot", hash=>$hash)}, "snapshot"); + my $snapshot_links = format_snapshot_links($hash); + if (defined $snapshot_links) { + print " | " . $snapshot_links; } print "
" . + esc_path($t->{'name'}) . + ""; + if (defined $hash_base) { + print $cgi->a({-href => href(action=>"history", + hash_base=>$hash_base, + file_name=>"$basedir$t->{'name'}")}, + "history"); + } + print "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), -class => "list", -title => $pr->{'descr_long'}}, esc_html($pr->{'descr'})) . "" . chop_str($pr->{'owner'}, 15) . "" . esc_html(chop_str($pr->{'owner'}, 15)) . "{'age'}) . "\">" . (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "" . @@ -3795,7 +3795,7 @@ sub git_summary { print "
 
\n"; print "\n" . "\n" . - "\n"; + "\n"; if (defined $cd{'rfc2822'}) { print "\n"; } -- cgit v1.3 From 711fa74266ebfaf58ee0cd79988748fbaa752538 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 8 Sep 2007 21:49:11 +0200 Subject: gitweb: Remove parse_from_to_diffinfo code from git_patchset_body In commit 90921740bd00029708370673fdc537522aa48e6f "gitweb: Split git_patchset_body into separate subroutines" a part of git_patchset_body code was separated into parse_from_to_diffinfo subroutine. But instead of replacing the separated code by the call to mentioned subroutine, the call to subroutine was placed before the separated code. This patch removes parse_from_to_diffinfo code from git_patchset_body subroutine. Signed-off-by: Jakub Narebski --- gitweb/gitweb.perl | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b2bae1b250..c18339f131 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3191,44 +3191,10 @@ sub git_patchset_body { } } until (!defined $to_name || $to_name eq $diffinfo->{'to_file'} || $patch_idx > $#$difftree); + # modifies %from, %to hashes parse_from_to_diffinfo($diffinfo, \%from, \%to, @hash_parents); - if ($diffinfo->{'nparents'}) { - # combined diff - $from{'file'} = []; - $from{'href'} = []; - fill_from_file_info($diffinfo, @hash_parents) - unless exists $diffinfo->{'from_file'}; - for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { - $from{'file'}[$i] = $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'}; - if ($diffinfo->{'status'}[$i] ne "A") { # not new (added) file - $from{'href'}[$i] = href(action=>"blob", - hash_base=>$hash_parents[$i], - hash=>$diffinfo->{'from_id'}[$i], - file_name=>$from{'file'}[$i]); - } else { - $from{'href'}[$i] = undef; - } - } - } else { - $from{'file'} = $diffinfo->{'from_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'}); - } else { - delete $from{'href'}; - } - } - $to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; - if (!is_deleted($diffinfo)) { # file exists in result - $to{'href'} = href(action=>"blob", hash_base=>$hash, - hash=>$diffinfo->{'to_id'}, - file_name=>$to{'file'}); - } else { - delete $to{'href'}; - } # this is first patch for raw difftree line with $patch_idx index # we index @$difftree array from 0, but number patches from 1 print "
\n"; -- cgit v1.3 From 3ef408aefe937fe76559e9b41602cddc0ac8af8c Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 8 Sep 2007 21:54:28 +0200 Subject: gitweb: No difftree output for trivial merge In 'commitdiff' view, for the merge commit, there is an extra header for the difftree table, with links to commitdiffs to individual parents. Do not show such header when there is nothing to show, for trivial merges. This means that for trivial merge you have to go to 'commit' view to get links to diffs to each parent. Signed-off-by: Jakub Narebski --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c18339f131..3064298f28 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2809,7 +2809,7 @@ sub git_difftree_body { "diff_tree\">\n"; # header only for combined diff in 'commitdiff' view - my $has_header = @parents > 1 && $action eq 'commitdiff'; + my $has_header = @$difftree && @parents > 1 && $action eq 'commitdiff'; if ($has_header) { # table header print "
\n" . -- cgit v1.3 From ca5e9495607c2abb4b665b75d3d96a457fa4c5dd Mon Sep 17 00:00:00 2001 From: Luke Lu Date: Tue, 16 Oct 2007 20:45:25 -0700 Subject: gitweb: speed up project listing on large work trees by limiting find depth Signed-off-by: Luke Lu Signed-off-by: Shawn O. Pearce --- Makefile | 2 ++ gitweb/gitweb.perl | 10 ++++++++++ t/t9500-gitweb-standalone-no-errors.sh | 1 + 3 files changed, 13 insertions(+) (limited to 'gitweb') diff --git a/Makefile b/Makefile index d74ac93c11..9f81c73af7 100644 --- a/Makefile +++ b/Makefile @@ -165,6 +165,7 @@ GITWEB_CONFIG = gitweb_config.perl GITWEB_HOME_LINK_STR = projects GITWEB_SITENAME = GITWEB_PROJECTROOT = /pub/git +GITWEB_PROJECT_MAXDEPTH = 2007 GITWEB_EXPORT_OK = GITWEB_STRICT_EXPORT = GITWEB_BASE_URL = @@ -831,6 +832,7 @@ gitweb/gitweb.cgi: gitweb/gitweb.perl -e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \ -e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \ -e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \ + -e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \ -e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \ -e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \ -e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \ diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3064298f28..48e21dad6c 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -35,6 +35,10 @@ our $GIT = "++GIT_BINDIR++/git"; #our $projectroot = "/pub/scm"; our $projectroot = "++GITWEB_PROJECTROOT++"; +# fs traversing limit for getting project list +# the number is relative to the projectroot +our $project_maxdepth = "++GITWEB_PROJECT_MAXDEPTH++"; + # target of the home link on top of all pages our $home_link = $my_uri || "/"; @@ -1509,6 +1513,7 @@ sub git_get_projects_list { # remove the trailing "/" $dir =~ s!/+$!!; my $pfxlen = length("$dir"); + my $pfxdepth = ($dir =~ tr!/!!); File::Find::find({ follow_fast => 1, # follow symbolic links @@ -1519,6 +1524,11 @@ sub git_get_projects_list { return if (m!^[/.]$!); # only directories can be git repositories return unless (-d $_); + # don't traverse too deep (Find is super slow on os x) + if (($File::Find::name =~ tr!/!!) - $pfxdepth > $project_maxdepth) { + $File::Find::prune = 1; + return; + } my $subdir = substr($File::Find::name, $pfxlen + 1); # we check related file in $projectroot diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 642b836d64..f7bad5bb2f 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -18,6 +18,7 @@ gitweb_init () { our \$version = "current"; our \$GIT = "git"; our \$projectroot = "$(pwd)"; +our \$project_maxdepth = 8; our \$home_link_str = "projects"; our \$site_name = "[localhost]"; our \$site_header = ""; -- cgit v1.3 From e076a0e71f25430205d0437c177fd12a7018e5ad Mon Sep 17 00:00:00 2001 From: David Symonds Date: Mon, 22 Oct 2007 10:28:03 +1000 Subject: gitweb: Provide title attributes for abbreviated author names. Signed-off-by: David Symonds Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 48e21dad6c..0d45769bc3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3437,9 +3437,15 @@ sub git_shortlog_body { print "\n"; } $alternate ^= 1; + my $author = chop_str($co{'author_name'}, 10); + if ($author ne $co{'author_name'}) { + $author = "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } # git_summary() used print "\n" . print "\n" . - "\n" . + "\n" . "\n"; } $alternate ^= 1; + # shortlog uses chop_str($co{'author_name'}, 10) + my $author = chop_str($co{'author_name'}, 15, 3); + if ($author ne $co{'author_name'}) { + "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } print "\n" . - # shortlog uses chop_str($co{'author_name'}, 10) - "\n" . + "\n" . "\n"; } $alternate ^= 1; + my $author = chop_str($co{'author_name'}, 15, 5); + if ($author ne $co{'author_name'}) { + $author = "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } print "\n" . - "\n" . + "\n" . "\n"; } $alternate ^= 1; + my $author = chop_str($co{'author_name'}, 15, 5); + if ($author ne $co{'author_name'}) { + $author = "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } print "\n" . - "\n" . + "\n" . "\n"; } $alternate ^= 1; - my $author = chop_str($co{'author_name'}, 10); - if ($author ne $co{'author_name'}) { - $author = "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 10); # git_summary() used print "\n" . print "\n" . "\n" . @@ -3494,12 +3506,7 @@ sub git_history_body { } $alternate ^= 1; # shortlog uses chop_str($co{'author_name'}, 10) - my $author = chop_str($co{'author_name'}, 15, 3); - if ($author ne $co{'author_name'}) { - "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 15, 3); print "\n" . "\n" . "\n"; } $alternate ^= 1; - my $author = chop_str($co{'author_name'}, 15, 5); - if ($author ne $co{'author_name'}) { - $author = "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 15, 5); print "\n" . "\n" . "\n"; } $alternate ^= 1; - my $author = chop_str($co{'author_name'}, 15, 5); - if ($author ne $co{'author_name'}) { - $author = "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 15, 5); print "\n" . "\n" . "\n" . - "\n"; + "\n"; print "\n" . "\n" . "\n"; @@ -3117,10 +3123,12 @@ sub git_patchset_body { my ($fd, $difftree, $hash, @hash_parents) = @_; my ($hash_parent) = $hash_parents[0]; + my $is_combined = (@hash_parents > 1); my $patch_idx = 0; my $patch_number = 0; my $patch_line; my $diffinfo; + my $to_name; my (%from, %to); print "
\n"; @@ -3134,73 +3142,46 @@ sub git_patchset_body { PATCH: while ($patch_line) { - my @diff_header; - my ($from_id, $to_id); - - # git diff header - #assert($patch_line =~ m/^diff /) if DEBUG; - #assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed - $patch_number++; - push @diff_header, $patch_line; - - # extended diff header - EXTENDED_HEADER: - while ($patch_line = <$fd>) { - chomp $patch_line; - last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /); - - if ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) { - $from_id = $1; - $to_id = $2; - } elsif ($patch_line =~ m/^index ((?:[0-9a-fA-F]{40},)+[0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) { - $from_id = [ split(',', $1) ]; - $to_id = $2; - } - - push @diff_header, $patch_line; + # parse "git diff" header line + if ($patch_line =~ m/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/) { + # $1 is from_name, which we do not use + $to_name = unquote($2); + $to_name =~ s!^b/!!; + } elsif ($patch_line =~ m/^diff --(cc|combined) ("?.*"?)$/) { + # $1 is 'cc' or 'combined', which we do not use + $to_name = unquote($2); + } else { + $to_name = undef; } - my $last_patch_line = $patch_line; # check if current patch belong to current raw line # and parse raw git-diff line if needed - if (defined $diffinfo && - defined $from_id && defined $to_id && - from_ids_eq($diffinfo->{'from_id'}, $from_id) && - $diffinfo->{'to_id'} eq $to_id) { + if (is_patch_split($diffinfo, { 'to_file' => $to_name })) { # this is continuation of a split patch print "
\n"; } else { # advance raw git-diff output if needed $patch_idx++ if defined $diffinfo; - # compact combined diff output can have some patches skipped - # find which patch (using pathname of result) we are at now - my $to_name; - if ($diff_header[0] =~ m!^diff --cc "?(.*)"?$!) { - $to_name = $1; - } - - do { - # 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]); - } + # read and prepare patch information + $diffinfo = parsed_difftree_line($difftree->[$patch_idx]); - # check if current raw line has no patch (it got simplified) - if (defined $to_name && $to_name ne $diffinfo->{'to_file'}) { + # compact combined diff output can have some patches skipped + # find which patch (using pathname of result) we are at now; + if ($is_combined) { + while ($to_name ne $diffinfo->{'to_file'}) { print "
\n" . format_diff_cc_simplified($diffinfo, @hash_parents) . "
\n"; # class="patch" $patch_idx++; $patch_number++; + + last if $patch_idx > $#$difftree; + $diffinfo = parsed_difftree_line($difftree->[$patch_idx]); } - } until (!defined $to_name || $to_name eq $diffinfo->{'to_file'} || - $patch_idx > $#$difftree); + } # modifies %from, %to hashes parse_from_to_diffinfo($diffinfo, \%from, \%to, @hash_parents); @@ -3210,30 +3191,36 @@ sub git_patchset_body { print "
\n"; } + # git diff header + #assert($patch_line =~ m/^diff /) if DEBUG; + #assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed + $patch_number++; # print "git diff" header - $patch_line = shift @diff_header; print format_git_diff_header_line($patch_line, $diffinfo, \%from, \%to); # print extended diff header - print "
\n" if (@diff_header > 0); + print "
\n"; EXTENDED_HEADER: - foreach $patch_line (@diff_header) { + while ($patch_line = <$fd>) { + chomp $patch_line; + + last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /); + print format_extended_diff_header_line($patch_line, $diffinfo, \%from, \%to); } - print "
\n" if (@diff_header > 0); # class="diff extended_header" + print "
\n"; # class="diff extended_header" # from-file/to-file diff header - $patch_line = $last_patch_line; if (! $patch_line) { print "
\n"; # class="patch" last PATCH; } next PATCH if ($patch_line =~ m/^diff /); #assert($patch_line =~ m/^---/) if DEBUG; - #assert($patch_line eq $last_patch_line) if DEBUG; + my $last_patch_line = $patch_line; $patch_line = <$fd>; chomp $patch_line; #assert($patch_line =~ m/^\+\+\+/) if DEBUG; @@ -3258,16 +3245,11 @@ sub git_patchset_body { # for compact combined (--cc) format, with chunk and patch simpliciaction # patchset might be empty, but there might be unprocessed raw lines - for ($patch_idx++ if $patch_number > 0; + for (++$patch_idx if $patch_number > 0; $patch_idx < @$difftree; - $patch_idx++) { + ++$patch_idx) { # 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]); - } + $diffinfo = parsed_difftree_line($difftree->[$patch_idx]); # generate anchor for "patch" links in difftree / whatchanged part print "
\n" . -- cgit v1.3 From 1e3a2eb667256716e101707f4da7179da2ba3c65 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 13:45:33 +0100 Subject: gitweb: Update config file example for snapshot feature in gitweb/INSTALL Commit a3c8ab30a54c30a6a434760bedf04548425416ef by Matt McCutchen "gitweb: snapshot cleanups & support for offering multiple formats" introduced new format of $feature{'snapshot'}{'default'} value. Update "Config file example" in gitweb/INSTALL accordingly. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/INSTALL b/gitweb/INSTALL index 6328e26f56..9cd5b0a2b1 100644 --- a/gitweb/INSTALL +++ b/gitweb/INSTALL @@ -116,7 +116,7 @@ GITWEB_CONFIG file: $feature{'pickaxe'}{'default'} = [1]; $feature{'pickaxe'}{'override'} = 1; - $feature{'snapshot'}{'default'} = ['x-gzip', 'gz', 'gzip']; + $feature{'snapshot'}{'default'} = ['zip', 'tgz']; $feature{'snapshot'}{'override'} = 1; -- cgit v1.3 From 9d3014566302ad0d3d378b0a1653959b3118066d Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 12:38:08 +0100 Subject: gitweb: Always set 'from_file' and 'to_file' in parse_difftree_raw_line Always set 'from_file' and 'to_file' keys when parsing raw diff output format line, even if filename didn't change (file was not renamed). This allows for simpler code. Previously, you would have written: $diffinfo->{'from_file'} || $diffinfo->{'file'} but now you can just use $diffinfo->{'from_file'} as 'from_file' is always defined. While at it, replace (for merge commits) $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'} by defined $diffinfo->{'from_file'}[$i] ? $diffinfo->{'from_file'}[$i] : $diffinfo->{'to_file'}; to have no problems with file named '0'. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 2e00756276..b22f4be152 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1995,7 +1995,7 @@ sub parse_difftree_raw_line { if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied ($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7); } else { - $res{'file'} = unquote($7); + $res{'from_file'} = $res{'to_file'} = $res{'file'} = unquote($7); } } # '::100755 100755 100755 60e79ca1b01bc8b057abe17ddab484699a7f5fdb 94067cc5f73388f33722d52ae02f44692bc07490 94067cc5f73388f33722d52ae02f44692bc07490 MR git-gui/git-gui.sh' @@ -2062,7 +2062,10 @@ sub parse_from_to_diffinfo { fill_from_file_info($diffinfo, @parents) unless exists $diffinfo->{'from_file'}; for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { - $from->{'file'}[$i] = $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'}; + $from->{'file'}[$i] = + defined $diffinfo->{'from_file'}[$i] ? + $diffinfo->{'from_file'}[$i] : + $diffinfo->{'to_file'}; if ($diffinfo->{'status'}[$i] ne "A") { # not new (added) file $from->{'href'}[$i] = href(action=>"blob", hash_base=>$parents[$i], @@ -2074,7 +2077,7 @@ sub parse_from_to_diffinfo { } } else { # ordinary (not combined) diff - $from->{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'}; + $from->{'file'} = $diffinfo->{'from_file'}; if ($diffinfo->{'status'} ne "A") { # not new (added) file $from->{'href'} = href(action=>"blob", hash_base=>$hash_parent, hash=>$diffinfo->{'from_id'}, @@ -2084,7 +2087,7 @@ sub parse_from_to_diffinfo { } } - $to->{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; + $to->{'file'} = $diffinfo->{'to_file'}; if (!is_deleted($diffinfo)) { # file exists in result $to->{'href'} = href(action=>"blob", hash_base=>$hash, hash=>$diffinfo->{'to_id'}, @@ -2829,7 +2832,7 @@ sub is_patch_split { my ($diffinfo, $patchinfo) = @_; return defined $diffinfo && defined $patchinfo - && ($diffinfo->{'to_file'} || $diffinfo->{'file'}) eq $patchinfo->{'to_file'}; + && $diffinfo->{'to_file'} eq $patchinfo->{'to_file'}; } @@ -4667,8 +4670,8 @@ sub git_blobdiff { } %diffinfo = parse_difftree_raw_line($difftree[0]); - $file_parent ||= $diffinfo{'from_file'} || $file_name || $diffinfo{'file'}; - $file_name ||= $diffinfo{'to_file'} || $diffinfo{'file'}; + $file_parent ||= $diffinfo{'from_file'} || $file_name; + $file_name ||= $diffinfo{'to_file'}; $hash_parent ||= $diffinfo{'from_id'}; $hash ||= $diffinfo{'to_id'}; -- cgit v1.3 From 6aa6f92fda47cc4ee5f599895e8a5a327fb6f9ab Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 12:38:09 +0100 Subject: gitweb: Add 'status_str' to parse_difftree_raw_line output Add 'status_str' to diffinfo output, which stores status (also for merge commit) as a string. This allows for easy checking if there is given status among all for merge commit, e.g. $diffinfo->{'status_str'} =~ /D/; Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b22f4be152..abb5a7d39f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1990,7 +1990,7 @@ sub parse_difftree_raw_line { $res{'to_mode'} = $2; $res{'from_id'} = $3; $res{'to_id'} = $4; - $res{'status'} = $5; + $res{'status'} = $res{'status_str'} = $5; $res{'similarity'} = $6; if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied ($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7); @@ -2006,6 +2006,7 @@ sub parse_difftree_raw_line { $res{'to_mode'} = pop @{$res{'from_mode'}}; $res{'from_id'} = [ split(' ', $3) ]; $res{'to_id'} = pop @{$res{'from_id'}}; + $res{'status_str'} = $4; $res{'status'} = [ split('', $4) ]; $res{'to_file'} = unquote($5); } @@ -2821,7 +2822,7 @@ sub fill_from_file_info { sub is_deleted { my $diffinfo = shift; - return $diffinfo->{'to_id'} eq ('0' x 40); + return $diffinfo->{'status_str'} =~ /D/; } # does patch correspond to [previous] difftree raw line -- cgit v1.3 From 1cad283a71d0ade2d86758dac90b51972a7a73c6 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 13:06:27 +0100 Subject: gitweb: Easier adding/changing parameters to current URL Add boolean option '-replay' to href() subroutine, which is used to generate links in gitweb. This option "replays" current URL, overriding it with provided parameters. It means that current value of each CGI parameter is used unless otherwise provided. This change is meant to make it easier to generate links which differ from current page URL only by one parameter, for example the same view but sorted by different column: href(-replay=>1, order=>"age") or view which differs by some option, e.g. in log views href(-replay=>1, extra_options=>"--no-merges") or alternate view of the same object, e.g. in the 'blob' view href(-replay=>1, action=>"blob_plain") Actual use of this functionality is left for later. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index abb5a7d39f..c93c546fbf 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -611,6 +611,15 @@ sub href(%) { ); my %mapping = @mapping; + if ($params{-replay}) { + while (my ($name, $symbol) = each %mapping) { + if (!exists $params{$name}) { + # to allow for multivalued params we use arrayref form + $params{$name} = [ $cgi->param($symbol) ]; + } + } + } + $params{'project'} = $project unless exists $params{'project'}; my ($use_pathinfo) = gitweb_check_feature('pathinfo'); -- cgit v1.3 From 7afd77bfc1b6881fd9e476274d3f08b793c292ed Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 13:06:28 +0100 Subject: gitweb: Use href(-replay=>1, page=>...) to generate pagination links Use href(-replay=>1, page=>$page-1) and href(-replay=>1, page=>$page+1) to generate previous page and next page links. Generate next page link only once. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c93c546fbf..d2adae31c8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2518,7 +2518,7 @@ sub format_paging_nav { if ($page > 0) { $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>$action, hash=>$hash, page=>$page-1), + $cgi->a({-href => href(-replay=>1, page=>$page-1), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { $paging_nav .= " ⋅ prev"; @@ -2526,7 +2526,7 @@ sub format_paging_nav { if ($nrevs >= (100 * ($page+1)-1)) { $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>$action, hash=>$hash, page=>$page+1), + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); } else { $paging_nav .= " ⋅ next"; @@ -4448,7 +4448,7 @@ sub git_log { } if ($#commitlist >= 100) { print "
\n"; - print $cgi->a({-href => href(action=>"log", hash=>$hash, page=>$page+1), + print $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); print "
\n"; } @@ -5015,27 +5015,20 @@ sub git_history { file_name=>$file_name)}, "first"); $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, - file_name=>$file_name, page=>$page-1), + $cgi->a({-href => href(-replay=>1, page=>$page-1), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { $paging_nav .= "first"; $paging_nav .= " ⋅ prev"; } - if ($#commitlist >= 100) { - $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, - file_name=>$file_name, page=>$page+1), - -accesskey => "n", -title => "Alt-n"}, "next"); - } else { - $paging_nav .= " ⋅ next"; - } my $next_link = ''; if ($#commitlist >= 100) { $next_link = - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, - file_name=>$file_name, page=>$page+1), + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); + $paging_nav .= " ⋅ $next_link"; + } else { + $paging_nav .= " ⋅ next"; } git_header_html(); @@ -5105,30 +5098,23 @@ sub git_search { searchtext=>$searchtext, searchtype=>$searchtype)}, "first"); $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"search", hash=>$hash, - searchtext=>$searchtext, searchtype=>$searchtype, - page=>$page-1), + $cgi->a({-href => href(-replay=>1, page=>$page-1), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { $paging_nav .= "first"; $paging_nav .= " ⋅ prev"; } + my $next_link = ''; if ($#commitlist >= 100) { - $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"search", hash=>$hash, - searchtext=>$searchtext, searchtype=>$searchtype, - page=>$page+1), + $next_link = + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); + $paging_nav .= " ⋅ $next_link"; } else { $paging_nav .= " ⋅ next"; } - my $next_link = ''; + if ($#commitlist >= 100) { - $next_link = - $cgi->a({-href => href(action=>"search", hash=>$hash, - searchtext=>$searchtext, searchtype=>$searchtype, - page=>$page+1), - -accesskey => "n", -title => "Alt-n"}, "next"); } git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav); @@ -5327,7 +5313,7 @@ sub git_shortlog { my $next_link = ''; if ($#commitlist >= 100) { $next_link = - $cgi->a({-href => href(action=>"shortlog", hash=>$hash, page=>$page+1), + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); } -- cgit v1.3 From a3823e5ad75498774a32850f44e8254b0e1c0901 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 13:06:29 +0100 Subject: gitweb: Use href(-replay=>1, action=>...) to generate alternate views Use href(action=>..., -replay=>1) to generate links to alternate views of current page in the $formats_nav (bottom) part of page_nav navigation bar. This form is used only when all parameters are repeated, and when the replay form is shorter. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d2adae31c8..ecb0113a79 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3911,11 +3911,11 @@ sub git_blame2 { or die_error(undef, "Open git-blame failed"); git_header_html(); my $formats_nav = - $cgi->a({-href => href(action=>"blob", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"blob", -replay=>1)}, "blob") . " | " . - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)}, - "history") . + $cgi->a({-href => href(action=>"history", -replay=>1)}, + "history") . " | " . $cgi->a({-href => href(action=>"blame", file_name=>$file_name)}, "HEAD"); @@ -4191,18 +4191,15 @@ sub git_blob { if (defined $file_name) { if ($have_blame) { $formats_nav .= - $cgi->a({-href => href(action=>"blame", hash_base=>$hash_base, - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"blame", -replay=>1)}, "blame") . " | "; } $formats_nav .= - $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"history", -replay=>1)}, "history") . " | " . - $cgi->a({-href => href(action=>"blob_plain", - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"blob_plain", -replay=>1)}, "raw") . " | " . $cgi->a({-href => href(action=>"blob", @@ -4210,7 +4207,8 @@ sub git_blob { "HEAD"); } else { $formats_nav .= - $cgi->a({-href => href(action=>"blob_plain", hash=>$hash)}, "raw"); + $cgi->a({-href => href(action=>"blob_plain", -replay=>1)}, + "raw"); } git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav); git_print_header_div('commit', esc_html($co{'title'}), $hash_base); @@ -4273,8 +4271,7 @@ sub git_tree { my @views_nav = (); if (defined $file_name) { push @views_nav, - $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"history", -replay=>1)}, "history"), $cgi->a({-href => href(action=>"tree", hash_base=>"HEAD", file_name=>$file_name)}, @@ -4742,10 +4739,7 @@ sub git_blobdiff { # header if ($format eq 'html') { my $formats_nav = - $cgi->a({-href => href(action=>"blobdiff_plain", - hash=>$hash, hash_parent=>$hash_parent, - hash_base=>$hash_base, hash_parent_base=>$hash_parent_base, - file_name=>$file_name, file_parent=>$file_parent)}, + $cgi->a({-href => href(action=>"blobdiff_plain", -replay=>1)}, "raw"); git_header_html(undef, $expires); if (defined $hash_base && (my %co = parse_commit($hash_base))) { @@ -4819,8 +4813,7 @@ sub git_commitdiff { my $formats_nav; if ($format eq 'html') { $formats_nav = - $cgi->a({-href => href(action=>"commitdiff_plain", - hash=>$hash, hash_parent=>$hash_parent)}, + $cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)}, "raw"); if (defined $hash_parent && -- cgit v1.3 From b201927ac8a4544baa067f5c5c7c7f2d6780e29a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 3 Nov 2007 00:41:19 +0100 Subject: gitweb: Read repo config using 'git config -z -l' Change git_get_project_config to run git-config only once per repository, without changing its signature (its calling convention). This means for example that it returns 'true' or 'false' when called with second argument '--bool', and not true or false value. Instead of calling 'git config [] --get gitweb.' once for each config variable, call 'git config -z -l' only once, parsing and saving its output to %config variable. This makes possible to add new per repository configuration without paying cost of forking once per variable checked. We can now allow repository description and repository URLs to be stored in config file without badly affecting gitweb performance. For now only configuration variables for 'gitweb' section are stored. Multiple values for single configuration variable are stored as anonymous array reference; configuration variable with no value is stored as undef. Converting configuration variable values to boolean or integer value are done in Perl. Results differ from git-config in the fact that no conversion error is ever raised. For boolean values no value, 'true' (any case) and 'false' (any case) are considered true, numbers are true if not zero; all other values (even invalid for bool) are considered false. For integer values value suffix of 'k', 'm', or 'g' following decimal number will cause the value to be multiplied by 1024, 1048576, or 1073741824; other values are returned as-is, only whitespace stripped. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 115 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ecb0113a79..e94ff96337 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1432,20 +1432,121 @@ sub git_get_type { return $type; } +# repository configuration +our $config_file = ''; +our %config; + +# store multiple values for single key as anonymous array reference +# single values stored directly in the hash, not as [ ] +sub hash_set_multi { + my ($hash, $key, $value) = @_; + + if (!exists $hash->{$key}) { + $hash->{$key} = $value; + } elsif (!ref $hash->{$key}) { + $hash->{$key} = [ $hash->{$key}, $value ]; + } else { + push @{$hash->{$key}}, $value; + } +} + +# return hash of git project configuration +# optionally limited to some section, e.g. 'gitweb' +sub git_parse_project_config { + my $section_regexp = shift; + my %config; + + local $/ = "\0"; + + open my $fh, "-|", git_cmd(), "config", '-z', '-l', + or return; + + while (my $keyval = <$fh>) { + chomp $keyval; + my ($key, $value) = split(/\n/, $keyval, 2); + + hash_set_multi(\%config, $key, $value) + if (!defined $section_regexp || $key =~ /^(?:$section_regexp)\./o); + } + close $fh; + + return %config; +} + +# convert config value to boolean, 'true' or 'false' +# no value, number > 0, 'true' and 'yes' values are true +# rest of values are treated as false (never as error) +sub config_to_bool { + my $val = shift; + + # strip leading and trailing whitespace + $val =~ s/^\s+//; + $val =~ s/\s+$//; + + return (!defined $val || # section.key + ($val =~ /^\d+$/ && $val) || # section.key = 1 + ($val =~ /^(?:true|yes)$/i)); # section.key = true +} + +# convert config value to simple decimal number +# an optional value suffix of 'k', 'm', or 'g' will cause the value +# to be multiplied by 1024, 1048576, or 1073741824 +sub config_to_int { + my $val = shift; + + # strip leading and trailing whitespace + $val =~ s/^\s+//; + $val =~ s/\s+$//; + + if (my ($num, $unit) = ($val =~ /^([0-9]*)([kmg])$/i)) { + $unit = lc($unit); + # unknown unit is treated as 1 + return $num * ($unit eq 'g' ? 1073741824 : + $unit eq 'm' ? 1048576 : + $unit eq 'k' ? 1024 : 1); + } + return $val; +} + +# convert config value to array reference, if needed +sub config_to_multi { + my $val = shift; + + return ref($val) ? $val : [ $val ]; +} + sub git_get_project_config { my ($key, $type) = @_; + # key sanity check return unless ($key); $key =~ s/^gitweb\.//; return if ($key =~ m/\W/); - my @x = (git_cmd(), 'config'); - if (defined $type) { push @x, $type; } - push @x, "--get"; - push @x, "gitweb.$key"; - my $val = qx(@x); - chomp $val; - return ($val); + # type sanity check + if (defined $type) { + $type =~ s/^--//; + $type = undef + unless ($type eq 'bool' || $type eq 'int'); + } + + # get config + if (!defined $config_file || + $config_file ne "$git_dir/config") { + %config = git_parse_project_config('gitweb'); + $config_file = "$git_dir/config"; + } + + # ensure given type + if (!defined $type) { + return $config{"gitweb.$key"}; + } elsif ($type eq 'bool') { + # backward compatibility: 'git config --bool' returns true/false + return config_to_bool($config{"gitweb.$key"}) ? 'true' : 'false'; + } elsif ($type eq 'int') { + return config_to_int($config{"gitweb.$key"}); + } + return $config{"gitweb.$key"}; } # get hash of given path at given ref -- cgit v1.3 From 0e121a2cd42d28bc4034feedf8a13c5a91f85bd3 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 3 Nov 2007 00:41:20 +0100 Subject: gitweb: Use config file for repository description and URLs Allow to use configuration variable gitweb.description for repository description if there is no $GIT_DIR/description file, and multivalued configuration variable gitweb.url for URLs of a project (to clone or fetch from) if there is no $GIT_DIR/cloneurl file. While repository description is shown in the projects list page, so it is better to use file and not config variable for performance, it is I think better to use gitweb.url for URLs (as it is shown only on project summary page). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e94ff96337..759dff1cce 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1606,7 +1606,9 @@ sub git_get_path_by_hash { sub git_get_project_description { my $path = shift; - open my $fd, "$projectroot/$path/description" or return undef; + $git_dir = "$projectroot/$path"; + open my $fd, "$projectroot/$path/description" + or return git_get_project_config('description'); my $descr = <$fd>; close $fd; if (defined $descr) { @@ -1618,7 +1620,11 @@ sub git_get_project_description { sub git_get_project_url_list { my $path = shift; - open my $fd, "$projectroot/$path/cloneurl" or return; + $git_dir = "$projectroot/$path"; + open my $fd, "$projectroot/$path/cloneurl" + or return wantarray ? + @{ config_to_multi(git_get_project_config('url')) } : + config_to_multi(git_get_project_config('url')); my @git_project_url_list = map { chomp; $_ } <$fd>; close $fd; -- cgit v1.3 From a62d6d84c67cebd71e8d88171a2ebe0bf3aca8a0 Mon Sep 17 00:00:00 2001 From: Vincent Zanotti Date: Sat, 10 Nov 2007 19:55:27 +0100 Subject: gitweb: correct month in date display for atom feeds Signed-off-by: Vincent Zanotti Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3064298f28..9deefce0a6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1713,7 +1713,7 @@ sub parse_date { $date{'mday-time'} = sprintf "%d %s %02d:%02d", $mday, $months[$mon], $hour ,$min; $date{'iso-8601'} = sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ", - 1900+$year, $mon, $mday, $hour ,$min, $sec; + 1900+$year, 1+$mon, $mday, $hour ,$min, $sec; $tz =~ m/^([+\-][0-9][0-9])([0-9][0-9])$/; my $local = $epoch + ((int $1 + ($2/60)) * 3600); -- cgit v1.3 From 591ebf6595ac7d5e5a21abbfc7501df19a67dc89 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 19 Nov 2007 14:16:11 +0100 Subject: gitweb: Style all tables using CSS Remove all cellspacing="0" attributes from tables in gitweb, replacing it by CSS rule. Add CSS classes for all tables. While at it, change class(es) of table for commit message and commit authorship search from "grep" to "commit_search"; similarly, "grep_search" class is now used for table with results of grep (files) search. Signed-off-by: Jakub Narebski --- gitweb/gitweb.css | 4 ---- gitweb/gitweb.perl | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 1b8887987f..17c60e4cb4 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -170,14 +170,10 @@ a.text:hover { table { padding: 8px 4px; -} - -table.project_list { border-spacing: 0; } table.diff_tree { - border-spacing: 0; font-family: monospace; } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e788ef90c9..3d532dc7d7 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3544,7 +3544,7 @@ sub git_shortlog_body { $from = 0 unless defined $from; $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to); - print "
description" . esc_html($descr) . "
owner$owner
owner" . esc_html($owner) . "
last change$cd{'rfc2822'}
$co{'age_string'}$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 10)) . "" . $author . ""; print format_subject_html($co{'title'}, $co{'title_short'}, href(action=>"commit", hash=>$commit), $ref); @@ -3487,9 +3493,15 @@ sub git_history_body { print "
$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 15, 3)) . "" . $author . ""; # originally git_history used chop_str($co{'title'}, 50) print format_subject_html($co{'title'}, $co{'title_short'}, @@ -3643,8 +3655,14 @@ sub git_search_grep_body { print "
$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "" . $author . "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, esc_html(chop_str($co{'title'}, 50)) . "
"); @@ -5157,8 +5175,14 @@ sub git_search { print "
$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "" . $author . "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, -- cgit v1.3 From ce58ec9158fe398dc7142e34cf575d336f408370 Mon Sep 17 00:00:00 2001 From: David Symonds Date: Tue, 23 Oct 2007 11:31:22 +1000 Subject: gitweb: Refactor abbreviation-with-title-attribute code. Signed-off-by: David Symonds Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 0d45769bc3..818783eba4 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -846,6 +846,23 @@ sub chop_str { return "$body$tail"; } +# takes the same arguments as chop_str, but also wraps a around the +# result with a title attribute if it does get chopped. Additionally, the +# string is HTML-escaped. +sub chop_and_escape_str { + my $str = shift; + my $len = shift; + my $add_len = shift || 10; + + my $chopped = chop_str($str, $len, $add_len); + if ($chopped eq $str) { + return esc_html($chopped); + } else { + return qq{} . + esc_html($chopped) . qq{}; + } +} + ## ---------------------------------------------------------------------- ## functions returning short strings @@ -3437,12 +3454,7 @@ sub git_shortlog_body { print "
$co{'age_string'}$co{'age_string_date'}" . $author . "$co{'age_string_date'}" . $author . ""; @@ -3655,12 +3662,7 @@ sub git_search_grep_body { print "
$co{'age_string_date'}" . $author . "" . @@ -5175,12 +5177,7 @@ sub git_search { print "
$co{'age_string_date'}" . $author . "" . -- cgit v1.3 From d3cd249565b6457d5845e7396530db7685a970bb Mon Sep 17 00:00:00 2001 From: David Symonds Date: Tue, 23 Oct 2007 11:31:23 +1000 Subject: gitweb: Use chop_and_escape_str in more places. Signed-off-by: David Symonds Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 818783eba4..8916950694 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3412,7 +3412,7 @@ sub git_project_list_body { "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), -class => "list", -title => $pr->{'descr_long'}}, esc_html($pr->{'descr'})) . "" . esc_html(chop_str($pr->{'owner'}, 15)) . "" . chop_and_escape_str($pr->{'owner'}, 15) . "{'age'}) . "\">" . (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "" . @@ -3667,7 +3667,7 @@ sub git_search_grep_body { "" . $author . "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, - esc_html(chop_str($co{'title'}, 50)) . "
"); + chop_and_escape_str($co{'title'}, 50) . "
"); my $comment = $co{'comment'}; foreach my $line (@$comment) { if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { @@ -5183,7 +5183,7 @@ sub git_search { "
" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, - esc_html(chop_str($co{'title'}, 50)) . "
"); + chop_and_escape_str($co{'title'}, 50) . "
"); while (my $setref = shift @files) { my %set = %$setref; print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'}, -- cgit v1.3 From 0cec6db5cfbb109eebb3a50b6213cab2dc68f0c8 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 30 Oct 2007 01:35:05 +0100 Subject: gitweb: Fix and simplify "split patch" detection There are some cases when one line from "raw" git-diff output (raw format) corresponds to more than one patch in the patchset git-diff output; we call this situation "split patch". Old code misdetected subsequent patches (for different files) with the same pre-image and post-image as fragments of "split patch", leading to mislabeled from-file/to-file diff header etc. Old code used pre-image and post-image SHA-1 identifier ('from_id' and 'to_id') to check if current patch corresponds to old raw diff format line, to find if one difftree raw line coresponds to more than one patch in the patch format. Now we use post-image filename for that. This assumes that post-image filename alone can be used to identify difftree raw line. In the case this changes (which is unlikely considering current diff engine) we can add 'from_id' and 'to_id' to detect "patch splitting" together with 'to_file'. Because old code got pre-image and post-image SHA-1 identifier for the patch from the "index" line in extended diff header, diff header had to be buffered. New code takes post-image filename from "git diff" header, which is first line of a patch; this allows to simplify git_patchset_body code. A side effect of resigning diff header buffering is that there is always "diff extended_header" div, even if extended diff header is empty. Alternate solution would be to check when git splits patches, and do not check if parsed info from current patch corresponds to current or next raw diff format output line. Git splits patches only for 'T' (typechange) status filepair, and there always two patches corresponding to one raw diff line. It was not used because it would tie gitweb code to minute details of git diff output. While at it, use newly introduced parsed_difftree_line wrapper subroutine in git_difftree_body. Noticed-by: Yann Dirson Diagnosed-by: Petr Baudis Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 152 +++++++++++++++++++++++------------------------------ 1 file changed, 67 insertions(+), 85 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 48e21dad6c..1537b0ec1d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2000,6 +2000,19 @@ sub parse_difftree_raw_line { return wantarray ? %res : \%res; } +# wrapper: return parsed line of git-diff-tree "raw" output +# (the argument might be raw line, or parsed info) +sub parsed_difftree_line { + my $line_or_ref = shift; + + if (ref($line_or_ref) eq "HASH") { + # pre-parsed (or generated by hand) + return $line_or_ref; + } else { + return parse_difftree_raw_line($line_or_ref); + } +} + # parse line of git-ls-tree output sub parse_ls_tree_line ($;%) { my $line = shift; @@ -2043,6 +2056,7 @@ sub parse_from_to_diffinfo { } } } else { + # ordinary (not combined) diff $from->{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'}; if ($diffinfo->{'status'} ne "A") { # not new (added) file $from->{'href'} = href(action=>"blob", hash_base=>$hash_parent, @@ -2766,6 +2780,7 @@ sub git_print_tree_entry { ## ...................................................................... ## functions printing large fragments of HTML +# get pre-image filenames for merge (combined) diff sub fill_from_file_info { my ($diff, @parents) = @_; @@ -2782,28 +2797,25 @@ sub fill_from_file_info { return $diff; } -# parameters can be strings, or references to arrays of strings -sub from_ids_eq { - my ($a, $b) = @_; - - if (ref($a) eq "ARRAY" && ref($b) eq "ARRAY" && @$a == @$b) { - for (my $i = 0; $i < @$a; ++$i) { - return 0 unless ($a->[$i] eq $b->[$i]); - } - return 1; - } elsif (!ref($a) && !ref($b)) { - return $a eq $b; - } else { - return 0; - } -} - +# is current raw difftree line of file deletion sub is_deleted { my $diffinfo = shift; return $diffinfo->{'to_id'} eq ('0' x 40); } +# does patch correspond to [previous] difftree raw line +# $diffinfo - hashref of parsed raw diff format +# $patchinfo - hashref of parsed patch diff format +# (the same keys as in $diffinfo) +sub is_patch_split { + my ($diffinfo, $patchinfo) = @_; + + return defined $diffinfo && defined $patchinfo + && ($diffinfo->{'to_file'} || $diffinfo->{'file'}) eq $patchinfo->{'to_file'}; +} + + sub git_difftree_body { my ($difftree, $hash, @parents) = @_; my ($parent) = $parents[0]; @@ -2840,13 +2852,7 @@ sub git_difftree_body { my $alternate = 1; my $patchno = 0; foreach my $line (@{$difftree}) { - my $diff; - if (ref($line) eq "HASH") { - # pre-parsed (or generated by hand) - $diff = $line; - } else { - $diff = parse_difftree_raw_line($line); - } + my $diff = parsed_difftree_line($line); if ($alternate) { print "
\n"; + print "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my %co = %{$commitlist->[$i]}; @@ -3590,7 +3590,7 @@ sub git_history_body { $from = 0 unless defined $from; $to = $#{$commitlist} unless (defined $to && $to <= $#{$commitlist}); - print "
\n"; + print "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my %co = %{$commitlist->[$i]}; @@ -3650,7 +3650,7 @@ sub git_tags_body { $from = 0 unless defined $from; $to = $#{$taglist} if (!defined $to || $#{$taglist} < $to); - print "
\n"; + print "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my $entry = $taglist->[$i]; @@ -3713,7 +3713,7 @@ sub git_heads_body { $from = 0 unless defined $from; $to = $#{$headlist} if (!defined $to || $#{$headlist} < $to); - print "
\n"; + print "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my $entry = $headlist->[$i]; @@ -3750,7 +3750,7 @@ sub git_search_grep_body { $from = 0 unless defined $from; $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to); - print "
\n"; + print "
\n"; my $alternate = 1; for (my $i = $from; $i <= $to; $i++) { my %co = %{$commitlist->[$i]}; @@ -3891,7 +3891,7 @@ sub git_summary { git_print_page_nav('summary','', $head); print "
 
\n"; - print "
\n" . + print "
\n" . "\n" . "\n"; if (defined $cd{'rfc2822'}) { @@ -3965,7 +3965,7 @@ sub git_tag { git_print_header_div('commit', esc_html($tag{'name'}), $hash); print "
\n" . - "
description" . esc_html($descr) . "
owner" . esc_html($owner) . "
\n" . + "
\n" . "\n" . "\n" . "\n"; + } else { + print "\n"; + } +} + +sub print_sort_th_str { + print_sort_th(1, @_); +} + +sub print_sort_th_num { + print_sort_th(0, @_); +} + sub git_project_list_body { my ($projlist, $order, $from, $to, $extra, $no_header) = @_; @@ -3614,43 +3644,15 @@ sub git_project_list_body { if ($check_forks) { print "\n"; } - if ($order eq "project") { - @projects = sort {$a->{'path'} cmp $b->{'path'}} @projects; - print "\n"; - } else { - print "\n"; - } - if ($order eq "descr") { - @projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects; - print "\n"; - } else { - print "\n"; - } - if ($order eq "owner") { - @projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects; - print "\n"; - } else { - print "\n"; - } - if ($order eq "age") { - @projects = sort {$a->{'age'} <=> $b->{'age'}} @projects; - print "\n"; - } else { - print "\n"; - } - print "\n" . + print_sort_th_str('project', $order, 'path', + 'Project', \@projects); + print_sort_th_str('descr', $order, 'descr_long', + 'Description', \@projects); + print_sort_th_str('owner', $order, 'owner', + 'Owner', \@projects); + print_sort_th_num('age', $order, 'age', + 'Last Change', \@projects); + print "\n" . # for links "\n"; } my $alternate = 1; -- cgit v1.3 From 66115d363a93b9e7c9b937773c0c30f81b766d45 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 14 Jun 2008 20:37:59 +0200 Subject: gitweb: Make it work with $GIT containing spaces This fixes single point where $GIT (which can contain full path to git binary) with embedded spaces gave errors. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 198772c210..4de964792f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -377,7 +377,7 @@ if (-e $GITWEB_CONFIG) { } # version of the core git binary -our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown"; +our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown"; $projects_list ||= $projectroot; -- cgit v1.3 From 516381d50ba7acb66f260461f4d566ab9b6df107 Mon Sep 17 00:00:00 2001 From: Lea Wiemann Date: Tue, 17 Jun 2008 23:46:35 +0200 Subject: gitweb: quote commands properly when calling the shell This eliminates the function git_cmd_str, which was used for composing command lines, and adds a quote_command function, which quotes all of its arguments (as in quote.c). Signed-off-by: Lea Wiemann Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 4de964792f..d7ee2673cb 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1500,9 +1500,13 @@ sub git_cmd { return $GIT, '--git-dir='.$git_dir; } -# returns path to the core git executable and the --git-dir parameter as string -sub git_cmd_str { - return join(' ', git_cmd()); +# quote the given arguments for passing them to the shell +# quote_command("command", "arg 1", "arg with ' and ! characters") +# => "'command' 'arg 1' 'arg with '\'' and '\!' characters'" +# Try to avoid using this function wherever possible. +sub quote_command { + return join(' ', + map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ )); } # get HEAD ref of given project as hash @@ -4633,7 +4637,6 @@ sub git_snapshot { $hash = git_get_head_hash($project); } - my $git_command = git_cmd_str(); my $name = $project; $name =~ s,([^/])/*\.git$,$1,; $name = basename($name); @@ -4641,11 +4644,12 @@ sub git_snapshot { $name =~ s/\047/\047\\\047\047/g; my $cmd; $filename .= "-$hash$known_snapshot_formats{$format}{'suffix'}"; - $cmd = "$git_command archive " . - "--format=$known_snapshot_formats{$format}{'format'} " . - "--prefix=\'$name\'/ $hash"; + $cmd = quote_command( + git_cmd(), 'archive', + "--format=$known_snapshot_formats{$format}{'format'}", + "--prefix=$name/", $hash); if (exists $known_snapshot_formats{$format}{'compressor'}) { - $cmd .= ' | ' . join ' ', @{$known_snapshot_formats{$format}{'compressor'}}; + $cmd .= ' | ' . quote_command(@{$known_snapshot_formats{$format}{'compressor'}}); } print $cgi->header( @@ -4858,8 +4862,8 @@ sub git_object { if ($hash || ($hash_base && !defined $file_name)) { my $object_id = $hash || $hash_base; - my $git_command = git_cmd_str(); - open my $fd, "-|", "$git_command cat-file -t $object_id 2>/dev/null" + open my $fd, "-|", quote_command( + git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null' or die_error('404 Not Found', "Object does not exist"); $type = <$fd>; chomp $type; -- cgit v1.3 From 61fb0b75d138032c7600fe86640897b900f2fd4f Mon Sep 17 00:00:00 2001 From: Lea Wiemann Date: Tue, 17 Jun 2008 08:25:28 +0200 Subject: gitweb: remove unused parse_ref method The parse_ref method became unused in cd1464083c, but the author decided to leave it in. Now it gets in the way of refactoring, so let's remove it. Signed-off-by: Lea Wiemann Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 43 ------------------------------------------- 1 file changed, 43 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d7ee2673cb..49b01d8c25 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2162,49 +2162,6 @@ sub parse_commits { return wantarray ? @cos : \@cos; } -# parse ref from ref_file, given by ref_id, with given type -sub parse_ref { - my $ref_file = shift; - my $ref_id = shift; - my $type = shift || git_get_type($ref_id); - my %ref_item; - - $ref_item{'type'} = $type; - $ref_item{'id'} = $ref_id; - $ref_item{'epoch'} = 0; - $ref_item{'age'} = "unknown"; - if ($type eq "tag") { - my %tag = parse_tag($ref_id); - $ref_item{'comment'} = $tag{'comment'}; - if ($tag{'type'} eq "commit") { - my %co = parse_commit($tag{'object'}); - $ref_item{'epoch'} = $co{'committer_epoch'}; - $ref_item{'age'} = $co{'age_string'}; - } elsif (defined($tag{'epoch'})) { - my $age = time - $tag{'epoch'}; - $ref_item{'epoch'} = $tag{'epoch'}; - $ref_item{'age'} = age_string($age); - } - $ref_item{'reftype'} = $tag{'type'}; - $ref_item{'name'} = $tag{'name'}; - $ref_item{'refid'} = $tag{'object'}; - } elsif ($type eq "commit"){ - my %co = parse_commit($ref_id); - $ref_item{'reftype'} = "commit"; - $ref_item{'name'} = $ref_file; - $ref_item{'title'} = $co{'title'}; - $ref_item{'refid'} = $ref_id; - $ref_item{'epoch'} = $co{'committer_epoch'}; - $ref_item{'age'} = $co{'age_string'}; - } else { - $ref_item{'reftype'} = $type; - $ref_item{'name'} = $ref_file; - $ref_item{'refid'} = $ref_id; - } - - return %ref_item; -} - # parse line of git-diff-tree "raw" output sub parse_difftree_raw_line { my $line = shift; -- cgit v1.3 From 074afaa0cf69e7d49bc00d969f57893c9ddea748 Mon Sep 17 00:00:00 2001 From: Lea Wiemann Date: Thu, 19 Jun 2008 22:03:21 +0200 Subject: gitweb: standarize HTTP status codes Many error status codes simply default to 403 Forbidden, which is not correct in most cases. This patch makes gitweb return semantically correct status codes. For convenience the die_error function now only takes the status code without reason as first parameter (e.g. 404 instead of "404 Not Found"), and it now defaults to 500 (Internal Server Error), even though the default is not used anywhere. Also documented status code conventions in die_error. Signed-off-by: Lea Wiemann Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 211 ++++++++++++++++++++++++++--------------------------- 1 file changed, 105 insertions(+), 106 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 49b01d8c25..5351da2c11 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -386,7 +386,7 @@ $projects_list ||= $projectroot; our $action = $cgi->param('a'); if (defined $action) { if ($action =~ m/[^0-9a-zA-Z\.\-_]/) { - die_error(undef, "Invalid action parameter"); + die_error(400, "Invalid action parameter"); } } @@ -399,21 +399,21 @@ if (defined $project) { ($export_ok && !(-e "$projectroot/$project/$export_ok")) || ($strict_export && !project_in_list($project))) { undef $project; - die_error(undef, "No such project"); + die_error(404, "No such project"); } } our $file_name = $cgi->param('f'); if (defined $file_name) { if (!validate_pathname($file_name)) { - die_error(undef, "Invalid file parameter"); + die_error(400, "Invalid file parameter"); } } our $file_parent = $cgi->param('fp'); if (defined $file_parent) { if (!validate_pathname($file_parent)) { - die_error(undef, "Invalid file parent parameter"); + die_error(400, "Invalid file parent parameter"); } } @@ -421,21 +421,21 @@ if (defined $file_parent) { our $hash = $cgi->param('h'); if (defined $hash) { if (!validate_refname($hash)) { - die_error(undef, "Invalid hash parameter"); + die_error(400, "Invalid hash parameter"); } } our $hash_parent = $cgi->param('hp'); if (defined $hash_parent) { if (!validate_refname($hash_parent)) { - die_error(undef, "Invalid hash parent parameter"); + die_error(400, "Invalid hash parent parameter"); } } our $hash_base = $cgi->param('hb'); if (defined $hash_base) { if (!validate_refname($hash_base)) { - die_error(undef, "Invalid hash base parameter"); + die_error(400, "Invalid hash base parameter"); } } @@ -447,10 +447,10 @@ our @extra_options = $cgi->param('opt'); if (defined @extra_options) { foreach my $opt (@extra_options) { if (not exists $allowed_options{$opt}) { - die_error(undef, "Invalid option parameter"); + die_error(400, "Invalid option parameter"); } if (not grep(/^$action$/, @{$allowed_options{$opt}})) { - die_error(undef, "Invalid option parameter for this action"); + die_error(400, "Invalid option parameter for this action"); } } } @@ -458,7 +458,7 @@ if (defined @extra_options) { our $hash_parent_base = $cgi->param('hpb'); if (defined $hash_parent_base) { if (!validate_refname($hash_parent_base)) { - die_error(undef, "Invalid hash parent base parameter"); + die_error(400, "Invalid hash parent base parameter"); } } @@ -466,14 +466,14 @@ if (defined $hash_parent_base) { our $page = $cgi->param('pg'); if (defined $page) { if ($page =~ m/[^0-9]/) { - die_error(undef, "Invalid page parameter"); + die_error(400, "Invalid page parameter"); } } our $searchtype = $cgi->param('st'); if (defined $searchtype) { if ($searchtype =~ m/[^a-z]/) { - die_error(undef, "Invalid searchtype parameter"); + die_error(400, "Invalid searchtype parameter"); } } @@ -483,7 +483,7 @@ our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { if (length($searchtext) < 2) { - die_error(undef, "At least two characters are required for search parameter"); + die_error(403, "At least two characters are required for search parameter"); } $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext; } @@ -580,11 +580,11 @@ if (!defined $action) { } } if (!defined($actions{$action})) { - die_error(undef, "Unknown action"); + die_error(400, "Unknown action"); } if ($action !~ m/^(opml|project_list|project_index)$/ && !$project) { - die_error(undef, "Project needed"); + die_error(400, "Project needed"); } $actions{$action}->(); exit; @@ -1665,7 +1665,7 @@ sub git_get_hash_by_path { $path =~ s,/+$,,; open my $fd, "-|", git_cmd(), "ls-tree", $base, "--", $path - or die_error(undef, "Open git-ls-tree failed"); + or die_error(500, "Open git-ls-tree failed"); my $line = <$fd>; close $fd or return undef; @@ -2127,7 +2127,7 @@ sub parse_commit { "--max-count=1", $commit_id, "--", - or die_error(undef, "Open git-rev-list failed"); + or die_error(500, "Open git-rev-list failed"); %co = parse_commit_text(<$fd>, 1); close $fd; @@ -2152,7 +2152,7 @@ sub parse_commits { $commit_id, "--", ($filename ? ($filename) : ()) - or die_error(undef, "Open git-rev-list failed"); + or die_error(500, "Open git-rev-list failed"); while (my $line = <$fd>) { my %co = parse_commit_text($line); push @cos, \%co; @@ -2672,11 +2672,26 @@ sub git_footer_html { ""; } +# die_error(, ) +# Example: die_error(404, 'Hash not found') +# By convention, use the following status codes (as defined in RFC 2616): +# 400: Invalid or missing CGI parameters, or +# requested object exists but has wrong type. +# 403: Requested feature (like "pickaxe" or "snapshot") not enabled on +# this server or project. +# 404: Requested object/revision/project doesn't exist. +# 500: The server isn't configured properly, or +# an internal error occurred (e.g. failed assertions caused by bugs), or +# an unknown error occurred (e.g. the git binary died unexpectedly). sub die_error { - my $status = shift || "403 Forbidden"; - my $error = shift || "Malformed query, file missing or permission denied"; - - git_header_html($status); + my $status = shift || 500; + my $error = shift || "Internal server error"; + + my %http_responses = (400 => '400 Bad Request', + 403 => '403 Forbidden', + 404 => '404 Not Found', + 500 => '500 Internal Server Error'); + git_header_html($http_responses{$status}); print <

@@ -3924,12 +3939,12 @@ sub git_search_grep_body { sub git_project_list { my $order = $cgi->param('o'); if (defined $order && $order !~ m/none|project|descr|owner|age/) { - die_error(undef, "Unknown order parameter"); + die_error(400, "Unknown order parameter"); } my @list = git_get_projects_list(); if (!@list) { - die_error(undef, "No projects found"); + die_error(404, "No projects found"); } git_header_html(); @@ -3947,12 +3962,12 @@ sub git_project_list { sub git_forks { my $order = $cgi->param('o'); if (defined $order && $order !~ m/none|project|descr|owner|age/) { - die_error(undef, "Unknown order parameter"); + die_error(400, "Unknown order parameter"); } my @list = git_get_projects_list($project); if (!@list) { - die_error(undef, "No forks found"); + die_error(404, "No forks found"); } git_header_html(); @@ -4081,7 +4096,7 @@ sub git_tag { my %tag = parse_tag($hash); if (! %tag) { - die_error(undef, "Unknown tag object"); + die_error(404, "Unknown tag object"); } git_print_header_div('commit', esc_html($tag{'name'}), $hash); @@ -4117,26 +4132,25 @@ sub git_blame2 { my $fd; my $ftype; - my ($have_blame) = gitweb_check_feature('blame'); - if (!$have_blame) { - die_error('403 Permission denied', "Permission denied"); - } - die_error('404 Not Found', "File name not defined") if (!$file_name); + gitweb_check_feature('blame') + or die_error(403, "Blame view not allowed"); + + die_error(400, "No file name given") unless $file_name; $hash_base ||= git_get_head_hash($project); - die_error(undef, "Couldn't find base commit") unless ($hash_base); + die_error(404, "Couldn't find base commit") unless ($hash_base); my %co = parse_commit($hash_base) - or die_error(undef, "Reading commit failed"); + or die_error(404, "Commit not found"); if (!defined $hash) { $hash = git_get_hash_by_path($hash_base, $file_name, "blob") - or die_error(undef, "Error looking up file"); + or die_error(404, "Error looking up file"); } $ftype = git_get_type($hash); if ($ftype !~ "blob") { - die_error('400 Bad Request', "Object is not a blob"); + die_error(400, "Object is not a blob"); } open ($fd, "-|", git_cmd(), "blame", '-p', '--', $file_name, $hash_base) - or die_error(undef, "Open git-blame failed"); + or die_error(500, "Open git-blame failed"); git_header_html(); my $formats_nav = $cgi->a({-href => href(action=>"blob", -replay=>1)}, @@ -4198,7 +4212,7 @@ HTML print "\n"; } open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^") - or die_error(undef, "Open git-rev-parse failed"); + or die_error(500, "Open git-rev-parse failed"); my $parent_commit = <$dd>; close $dd; chomp($parent_commit); @@ -4352,9 +4366,9 @@ sub git_blob_plain { if (defined $file_name) { my $base = $hash_base || git_get_head_hash($project); $hash = git_get_hash_by_path($base, $file_name, "blob") - or die_error(undef, "Error lookup file"); + or die_error(404, "Cannot find file"); } else { - die_error(undef, "No file name defined"); + die_error(400, "No file name defined"); } } elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) { # blobs defined by non-textual hash id's can be cached @@ -4362,7 +4376,7 @@ sub git_blob_plain { } open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash - or die_error(undef, "Open git-cat-file blob '$hash' failed"); + or die_error(500, "Open git-cat-file blob '$hash' failed"); # content-type (can include charset) $type = blob_contenttype($fd, $file_name, $type); @@ -4394,9 +4408,9 @@ sub git_blob { if (defined $file_name) { my $base = $hash_base || git_get_head_hash($project); $hash = git_get_hash_by_path($base, $file_name, "blob") - or die_error(undef, "Error lookup file"); + or die_error(404, "Cannot find file"); } else { - die_error(undef, "No file name defined"); + die_error(400, "No file name defined"); } } elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) { # blobs defined by non-textual hash id's can be cached @@ -4405,7 +4419,7 @@ sub git_blob { my ($have_blame) = gitweb_check_feature('blame'); open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash - or die_error(undef, "Couldn't cat $file_name, $hash"); + or die_error(500, "Couldn't cat $file_name, $hash"); my $mimetype = blob_mimetype($fd, $file_name); if ($mimetype !~ m!^(?:text/|image/(?:gif|png|jpeg)$)! && -B $fd) { close $fd; @@ -4486,9 +4500,9 @@ sub git_tree { } $/ = "\0"; open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash - or die_error(undef, "Open git-ls-tree failed"); + or die_error(500, "Open git-ls-tree failed"); my @entries = map { chomp; $_ } <$fd>; - close $fd or die_error(undef, "Reading tree failed"); + close $fd or die_error(404, "Reading tree failed"); $/ = "\n"; my $refs = git_get_references(); @@ -4578,16 +4592,16 @@ sub git_snapshot { my $format = $cgi->param('sf'); if (!@supported_fmts) { - die_error('403 Permission denied', "Permission denied"); + die_error(403, "Snapshots not allowed"); } # default to first supported snapshot format $format ||= $supported_fmts[0]; if ($format !~ m/^[a-z0-9]+$/) { - die_error(undef, "Invalid snapshot format parameter"); + die_error(400, "Invalid snapshot format parameter"); } elsif (!exists($known_snapshot_formats{$format})) { - die_error(undef, "Unknown snapshot format"); + die_error(400, "Unknown snapshot format"); } elsif (!grep($_ eq $format, @supported_fmts)) { - die_error(undef, "Unsupported snapshot format"); + die_error(403, "Unsupported snapshot format"); } if (!defined $hash) { @@ -4615,7 +4629,7 @@ sub git_snapshot { -status => '200 OK'); open my $fd, "-|", $cmd - or die_error(undef, "Execute git-archive failed"); + or die_error(500, "Execute git-archive failed"); binmode STDOUT, ':raw'; print <$fd>; binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi @@ -4683,10 +4697,8 @@ sub git_log { sub git_commit { $hash ||= $hash_base || "HEAD"; - my %co = parse_commit($hash); - if (!%co) { - die_error(undef, "Unknown commit object"); - } + my %co = parse_commit($hash) + or die_error(404, "Unknown commit object"); my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'}); my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'}); @@ -4726,9 +4738,9 @@ sub git_commit { @diff_opts, (@$parents <= 1 ? $parent : '-c'), $hash, "--" - or die_error(undef, "Open git-diff-tree failed"); + or die_error(500, "Open git-diff-tree failed"); @difftree = map { chomp; $_ } <$fd>; - close $fd or die_error(undef, "Reading git-diff-tree failed"); + close $fd or die_error(404, "Reading git-diff-tree failed"); # non-textual hash id's can be cached my $expires; @@ -4821,33 +4833,33 @@ sub git_object { open my $fd, "-|", quote_command( git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null' - or die_error('404 Not Found', "Object does not exist"); + or die_error(404, "Object does not exist"); $type = <$fd>; chomp $type; close $fd - or die_error('404 Not Found', "Object does not exist"); + or die_error(404, "Object does not exist"); # - hash_base and file_name } elsif ($hash_base && defined $file_name) { $file_name =~ s,/+$,,; system(git_cmd(), "cat-file", '-e', $hash_base) == 0 - or die_error('404 Not Found', "Base object does not exist"); + or die_error(404, "Base object does not exist"); # here errors should not hapen open my $fd, "-|", git_cmd(), "ls-tree", $hash_base, "--", $file_name - or die_error(undef, "Open git-ls-tree failed"); + or die_error(500, "Open git-ls-tree failed"); my $line = <$fd>; close $fd; #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c' unless ($line && $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/) { - die_error('404 Not Found', "File or directory for given base does not exist"); + die_error(404, "File or directory for given base does not exist"); } $type = $2; $hash = $3; } else { - die_error('404 Not Found', "Not enough information to find object"); + die_error(400, "Not enough information to find object"); } print $cgi->redirect(-uri => href(action=>$type, -full=>1, @@ -4872,12 +4884,12 @@ sub git_blobdiff { open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, $hash_parent_base, $hash_base, "--", (defined $file_parent ? $file_parent : ()), $file_name - or die_error(undef, "Open git-diff-tree failed"); + or die_error(500, "Open git-diff-tree failed"); @difftree = map { chomp; $_ } <$fd>; close $fd - or die_error(undef, "Reading git-diff-tree failed"); + or die_error(404, "Reading git-diff-tree failed"); @difftree - or die_error('404 Not Found', "Blob diff not found"); + or die_error(404, "Blob diff not found"); } elsif (defined $hash && $hash =~ /[0-9a-fA-F]{40}/) { @@ -4886,23 +4898,23 @@ sub git_blobdiff { # read filtered raw output open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, $hash_parent_base, $hash_base, "--" - or die_error(undef, "Open git-diff-tree failed"); + or die_error(500, "Open git-diff-tree failed"); @difftree = # ':100644 100644 03b21826... 3b93d5e7... M ls-files.c' # $hash == to_id grep { /^:[0-7]{6} [0-7]{6} [0-9a-fA-F]{40} $hash/ } map { chomp; $_ } <$fd>; close $fd - or die_error(undef, "Reading git-diff-tree failed"); + or die_error(404, "Reading git-diff-tree failed"); @difftree - or die_error('404 Not Found', "Blob diff not found"); + or die_error(404, "Blob diff not found"); } else { - die_error('404 Not Found', "Missing one of the blob diff parameters"); + die_error(400, "Missing one of the blob diff parameters"); } if (@difftree > 1) { - die_error('404 Not Found', "Ambiguous blob diff specification"); + die_error(400, "Ambiguous blob diff specification"); } %diffinfo = parse_difftree_raw_line($difftree[0]); @@ -4923,7 +4935,7 @@ sub git_blobdiff { '-p', ($format eq 'html' ? "--full-index" : ()), $hash_parent_base, $hash_base, "--", (defined $file_parent ? $file_parent : ()), $file_name - or die_error(undef, "Open git-diff-tree failed"); + or die_error(500, "Open git-diff-tree failed"); } # old/legacy style URI @@ -4959,9 +4971,9 @@ sub git_blobdiff { open $fd, "-|", git_cmd(), "diff", @diff_opts, '-p', ($format eq 'html' ? "--full-index" : ()), $hash_parent, $hash, "--" - or die_error(undef, "Open git-diff failed"); + or die_error(500, "Open git-diff failed"); } else { - die_error('404 Not Found', "Missing one of the blob diff parameters") + die_error(400, "Missing one of the blob diff parameters") unless %diffinfo; } @@ -4994,7 +5006,7 @@ sub git_blobdiff { print "X-Git-Url: " . $cgi->self_url() . "\n\n"; } else { - die_error(undef, "Unknown blobdiff format"); + die_error(400, "Unknown blobdiff format"); } # patch @@ -5029,10 +5041,8 @@ sub git_blobdiff_plain { sub git_commitdiff { my $format = shift || 'html'; $hash ||= $hash_base || "HEAD"; - my %co = parse_commit($hash); - if (!%co) { - die_error(undef, "Unknown commit object"); - } + my %co = parse_commit($hash) + or die_error(404, "Unknown commit object"); # choose format for commitdiff for merge if (! defined $hash_parent && @{$co{'parents'}} > 1) { @@ -5114,7 +5124,7 @@ sub git_commitdiff { open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, "--no-commit-id", "--patch-with-raw", "--full-index", $hash_parent_param, $hash, "--" - or die_error(undef, "Open git-diff-tree failed"); + or die_error(500, "Open git-diff-tree failed"); while (my $line = <$fd>) { chomp $line; @@ -5126,10 +5136,10 @@ sub git_commitdiff { } elsif ($format eq 'plain') { open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, '-p', $hash_parent_param, $hash, "--" - or die_error(undef, "Open git-diff-tree failed"); + or die_error(500, "Open git-diff-tree failed"); } else { - die_error(undef, "Unknown commitdiff format"); + die_error(400, "Unknown commitdiff format"); } # non-textual hash id's can be cached @@ -5212,19 +5222,15 @@ sub git_history { $page = 0; } my $ftype; - my %co = parse_commit($hash_base); - if (!%co) { - die_error(undef, "Unknown commit object"); - } + my %co = parse_commit($hash_base) + or die_error(404, "Unknown commit object"); my $refs = git_get_references(); my $limit = sprintf("--max-count=%i", (100 * ($page+1))); my @commitlist = parse_commits($hash_base, 101, (100 * $page), - $file_name, "--full-history"); - if (!@commitlist) { - die_error('404 Not Found', "No such file or directory on given branch"); - } + $file_name, "--full-history") + or die_error(404, "No such file or directory on given branch"); if (!defined $hash && defined $file_name) { # some commits could have deleted file in question, @@ -5238,7 +5244,7 @@ sub git_history { $ftype = git_get_type($hash); } if (!defined $ftype) { - die_error(undef, "Unknown type of object"); + die_error(500, "Unknown type of object"); } my $paging_nav = ''; @@ -5276,19 +5282,16 @@ sub git_history { } sub git_search { - my ($have_search) = gitweb_check_feature('search'); - if (!$have_search) { - die_error('403 Permission denied', "Permission denied"); - } + gitweb_check_feature('search') or die_error(403, "Search is disabled"); if (!defined $searchtext) { - die_error(undef, "Text field empty"); + die_error(400, "Text field is empty"); } if (!defined $hash) { $hash = git_get_head_hash($project); } my %co = parse_commit($hash); if (!%co) { - die_error(undef, "Unknown commit object"); + die_error(404, "Unknown commit object"); } if (!defined $page) { $page = 0; @@ -5298,16 +5301,12 @@ sub git_search { if ($searchtype eq 'pickaxe') { # pickaxe may take all resources of your box and run for several minutes # with every query - so decide by yourself how public you make this feature - my ($have_pickaxe) = gitweb_check_feature('pickaxe'); - if (!$have_pickaxe) { - die_error('403 Permission denied', "Permission denied"); - } + gitweb_check_feature('pickaxe') + or die_error(403, "Pickaxe is disabled"); } if ($searchtype eq 'grep') { - my ($have_grep) = gitweb_check_feature('grep'); - if (!$have_grep) { - die_error('403 Permission denied', "Permission denied"); - } + gitweb_check_feature('grep') + or die_error(403, "Grep is disabled"); } git_header_html(); @@ -5581,7 +5580,7 @@ sub git_feed { # Atom: http://www.atomenabled.org/developers/syndication/ # RSS: http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ if ($format ne 'rss' && $format ne 'atom') { - die_error(undef, "Unknown web feed format"); + die_error(400, "Unknown web feed format"); } # log/feed of current (HEAD) branch, log of given branch, history of file/directory -- cgit v1.3 From e67c9e3952a60dbf380cead5dae1d13fe9703f3c Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 8 Jul 2008 00:07:53 +0200 Subject: gitweb: Describe projects_index format in more detail Update and extend information about $projects_list file format in gitweb/README and in gitweb/INSTALL. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/INSTALL | 6 ++++++ gitweb/README | 46 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 6 deletions(-) (limited to 'gitweb') diff --git a/gitweb/INSTALL b/gitweb/INSTALL index f7194dbef7..26967e201a 100644 --- a/gitweb/INSTALL +++ b/gitweb/INSTALL @@ -144,6 +144,12 @@ Gitweb repositories Spaces in both project path and project owner have to be encoded as either '%20' or '+'. + Other characters that have to be url-encoded, i.e. replaced by '%' + followed by two-digit character number in octal, are: other whitespace + characters (because they are field separator in a record), plus sign '+' + (because it can be used as replacement for spaces), and percent sign '%' + (which is used for encoding / escaping). + You can generate the projects list index file using the project_index action (the 'TXT' link on projects list page) directly from gitweb. diff --git a/gitweb/README b/gitweb/README index 356ab7b327..6908036402 100644 --- a/gitweb/README +++ b/gitweb/README @@ -156,10 +156,11 @@ not include variables usually directly set during build): set correctly for gitweb to find repositories. * $projects_list Source of projects list, either directory to scan, or text file - with list of repositories (in the " SPC - " format). Set to $GITWEB_LIST - during installation. If empty, $projectroot is used to scan for - repositories. + with list of repositories (in the " SP + " line format; actually there can be + any sequence of whitespace in place of space (SP)). Set to + $GITWEB_LIST during installation. If empty, $projectroot is used + to scan for repositories. * $my_url, $my_uri URL and absolute URL of gitweb script; you might need to set those variables if you are using 'pathinfo' feature: see also below. @@ -214,6 +215,39 @@ not include variables usually directly set during build): ('-M'); set it to ('-C') or ('-C', '-C') to also detect copies, or set it to () if you don't want to have renames detection. + +Projects list file format +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of having gitweb find repositories by scanning filesystem starting +from $projectroot (or $projects_list, if it points to directory), you can +provide list of projects by setting $projects_list to a text file with list +of projects (and some additional info). This file uses the following +format: + +One record (for project / repository) per line, whitespace separated fields; +does not support (at least for now) lines continuation (newline escaping). +Leading and trailing whitespace are ignored, any run of whitespace can be +used as field separator (rules for Perl's "split(' ', $line)"). Keyed by +the first field, which is project name, i.e. path to repository GIT_DIR +relative to $projectroot. Fields use modified URI encoding, defined in +RFC 3986, section 2.1 (Percent-Encoding), or rather "Query string encoding" +(see http://en.wikipedia.org/wiki/Query_string#URL_encoding), the difference +being that SP (' ') can be encoded as '+' (and therefore '+' has to be also +percent-encoded). Reserved characters are: '%' (used for encoding), '+' +(can be used to encode SPACE), all whitespace characters as defined in Perl, +including SP, TAB and LF, (used to separate fields in a record). + +Currently list of fields is + * - path to repository GIT_DIR, relative to $projectroot + * - displayed as repository owner, preferably full name, + or email, or both + +You can additionally use $projects_list file to limit which repositories +are visible, and together with $strict_export to limit access to +repositories (see "Gitweb repositories" section in gitweb/INSTALL). + + Per-repository gitweb configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -225,8 +259,8 @@ You can use the following files in repository: * README.html A .html file (HTML fragment) which is included on the gitweb project summary page inside
block element. You can use it for longer - description of a project, to provide links for example to projects - homepage, etc. + description of a project, to provide links (for example to project's + homepage), etc. * description (or gitweb.description) Short (shortened by default to 25 characters in the projects list page) single line description of a project (of a repository). Plain text file; -- cgit v1.3 From ef115e26f7d6859f679d122d6c2300db09015396 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 27 Jul 2008 01:23:46 +0200 Subject: gitweb: More about how gitweb gets 'owner' of repository Signed-off-by: Jakub Narebski Acked-by: Petr Baudis Signed-off-by: Junio C Hamano --- gitweb/README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index 6908036402..825162a0b6 100644 --- a/gitweb/README +++ b/gitweb/README @@ -277,7 +277,8 @@ You can use the following files in repository: * gitweb.owner You can use the gitweb.owner repository configuration variable to set repository's owner. It is displayed in the project list and summary - page. If it's not set, filesystem directory's owner is used. + page. If it's not set, filesystem directory's owner is used + (via GECOS field / real name field from getpwiud(3)). * various gitweb.* config variables (in config) Read description of %feature hash for detailed list, and some descriptions. -- cgit v1.3 From 4afbaefffa9095fe1391b4b61289a7dc954e9f7b Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 2 Sep 2008 21:47:05 +0200 Subject: gitweb: ref markers link to named shortlogs This patch turns ref markers for tags and heads into links to appropriate views for the ref name, depending on current context. For annotated tags, we link to the tag view, unless that's the current view, in which case we switch to shortlog. For other refs, we prefer the current view if it's history or (short)log, and default to shortlog otherwise. Appropriate changes are made in the CSS to prevent ref markers from being annoyingly blue and underlined, unless hovered. A visual indication of the target view difference is also implemented by making annotated tags show up in italic. Signed-off-by: Giuseppe Bilotta Acked-by: Petr Baudis Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 13 +++++++++++++ gitweb/gitweb.perl | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index aa0eeca247..07f5b53788 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -481,6 +481,19 @@ span.refs span { border-color: #ffccff #ff00ee #ff00ee #ffccff; } +span.refs span a { + text-decoration: none; + color: inherit; +} + +span.refs span a:hover { + text-decoration: underline; +} + +span.refs span.indirect { + font-style: italic; +} + span.refs span.ref { background-color: #aaaaff; border-color: #ccccff #0033cc #0033cc #ccccff; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 90cd99bf91..29e21564c8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1090,13 +1090,23 @@ sub format_log_line_html { } # format marker of refs pointing to given object + +# the destination action is chosen based on object type and current context: +# - for annotated tags, we choose the tag view unless it's the current view +# already, in which case we go to shortlog view +# - for other refs, we keep the current view if we're in history, shortlog or +# log view, and select shortlog otherwise sub format_ref_marker { my ($refs, $id) = @_; my $markers = ''; if (defined $refs->{$id}) { foreach my $ref (@{$refs->{$id}}) { + # this code exploits the fact that non-lightweight tags are the + # only indirect objects, and that they are the only objects for which + # we want to use tag instead of shortlog as action my ($type, $name) = qw(); + my $indirect = ($ref =~ s/\^\{\}$//); # e.g. tags/v2.6.11 or heads/next if ($ref =~ m!^(.*?)s?/(.*)$!) { $type = $1; @@ -1106,8 +1116,29 @@ sub format_ref_marker { $name = $ref; } - $markers .= " " . - esc_html($name) . ""; + my $class = $type; + $class .= " indirect" if $indirect; + + my $dest_action = "shortlog"; + + if ($indirect) { + $dest_action = "tag" unless $action eq "tag"; + } elsif ($action =~ /^(history|(short)?log)$/) { + $dest_action = $action; + } + + my $dest = ""; + $dest .= "refs/" unless $ref =~ m!^refs/!; + $dest .= $ref; + + my $link = $cgi->a({ + -href => href( + action=>$dest_action, + hash=>$dest + )}, $name); + + $markers .= " " . + $link . ""; } } @@ -1918,7 +1949,7 @@ sub git_get_references { while (my $line = <$fd>) { chomp $line; - if ($line =~ m!^([0-9a-fA-F]{40})\srefs/($type/?[^^]+)!) { + if ($line =~ m!^([0-9a-fA-F]{40})\srefs/($type.*)$!) { if (defined $refs{$1}) { push @{$refs{$1}}, $2; } else { -- cgit v1.3 From 53c3967647f79f1563d028d442f81cabba451ca6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 5 Sep 2008 14:26:29 -0400 Subject: gitweb: avoid warnings for commits without body In the unusual case when there is no commit message, gitweb would output an uninitialized value warning. Signed-off-by: Joey Hess Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 90cd99bf91..269f1125d9 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2092,7 +2092,7 @@ sub parse_commit_text { last; } } - if ($co{'title'} eq "") { + if (! defined $co{'title'} || $co{'title'} eq "") { $co{'title'} = $co{'title_short'} = '(no commit message)'; } # remove added spaces -- cgit v1.3 From ec3e97b84e739946413194c563a12779efda2155 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Fri, 8 Aug 2008 16:12:11 +0200 Subject: gitweb: shortlog now also obeys $hash_parent If $hash_parent is defined, shortlog now limits the list of commits at those between $hash_parent (exclusive) and $hash (inclusive). Signed-off-by: Giuseppe Bilotta Acked-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index da474d082c..18e70a3663 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5498,7 +5498,11 @@ sub git_shortlog { } my $refs = git_get_references(); - my @commitlist = parse_commits($hash, 101, (100 * $page)); + my $commit_hash = $hash; + if (defined $hash_parent) { + $commit_hash = "$hash_parent..$hash"; + } + my @commitlist = parse_commits($commit_hash, 101, (100 * $page)); my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, $#commitlist >= 100); my $next_link = ''; -- cgit v1.3 From 6b28da672e8828111a8cf3cda9ed760e03140e11 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 25 Sep 2008 18:48:37 +0200 Subject: gitweb: Clean-up sorting of project list This decouples the sorting of project list and printing the column headers, so that the project list can be easily sorted even when the headers are not shown. Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 18e70a3663..58ffff8be7 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3605,19 +3605,13 @@ sub fill_project_list_info { return @projects; } -# print 'sort by'
\n"; } else { print "\n"; } else { -- cgit v1.3 From 0d1d154dbe4d16a802c2e357de96e349f04d2f2c Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Fri, 3 Oct 2008 09:29:45 +0200 Subject: gitweb: Support for simple project search form This is a trivial patch adding support for searching projects by name and description, making use of the "infrastructure" provided by the tag cloud generation. Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.css | 4 ++++ gitweb/gitweb.perl | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 07f5b53788..a01eac814e 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -435,6 +435,10 @@ div.search { right: 12px } +p.projsearch { + text-align: center; +} + td.linenr { text-align: right; } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 99fdb13f1f..b46af77da0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3767,11 +3767,14 @@ sub git_project_list_body { my $pr = $projects[$i]; next if $tagfilter and $show_ctags and not grep { lc $_ eq lc $tagfilter } keys %{$pr->{'ctags'}}; - # Weed out forks + next if $searchtext and not $pr->{'path'} =~ /$searchtext/ + and not $pr->{'descr_long'} =~ /$searchtext/; + # Weed out forks or non-matching entries of search if ($check_forks) { my $forkbase = $project; $forkbase ||= ''; $forkbase =~ s#\.git$#/#; $forkbase="^$forkbase" if $forkbase; - next if not $tagfilter and $pr->{'path'} =~ m#$forkbase.*/.*#; # regexp-safe + next if not $searchtext and not $tagfilter and $show_ctags + and $pr->{'path'} =~ m#$forkbase.*/.*#; # regexp-safe } if ($alternate) { @@ -4108,6 +4111,11 @@ sub git_project_list { close $fd; print "\n"; } + print $cgi->startform(-method => "get") . + "

Search:\n" . + $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . + "

" . + $cgi->end_form() . "\n"; git_project_list_body(\@list, $order); git_footer_html(); } -- cgit v1.3 From 2b11e059ee55ae7fb9913acf84fcc065e3e33287 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 12 Oct 2008 00:02:32 +0200 Subject: gitweb: Better processing format string in custom links in navbar Make processing format string in custom links in action bar ('actions' feature) more robust. Now there would be no problems if one of expanded values (for example project name, of project filename) contains '%'; additionally format string supports '%' escaping by doubling, i.e. '%%' expands to '%'. Signed-off-by: Jakub Narebski Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 11168006cf..cc6edbede8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -290,10 +290,10 @@ our %feature = ( # The 'default' value consists of a list of triplets in the form # (label, link, position) where position is the label after which - # to inster the link and link is a format string where %n expands + # to insert the link and link is a format string where %n expands # to the project name, %f to the project path within the filesystem, # %h to the current hash (h gitweb parameter) and %b to the current - # hash base (hb gitweb parameter). + # hash base (hb gitweb parameter); %% expands to %. # To enable system wide have in $GITWEB_CONFIG e.g. # $feature{'actions'}{'default'} = [('graphiclog', @@ -2866,14 +2866,19 @@ sub git_print_page_nav { $arg{'tree'}{'hash_base'} = $treebase if defined $treebase; my @actions = gitweb_check_feature('actions'); + my %repl = ( + '%' => '%', + 'n' => $project, # project name + 'f' => $git_dir, # project path within filesystem + 'h' => $treehead || '', # current hash ('h' parameter) + 'b' => $treebase || '', # hash base ('hb' parameter) + ); while (@actions) { - my ($label, $link, $pos) = (shift(@actions), shift(@actions), shift(@actions)); + my ($label, $link, $pos) = splice(@actions,0,3); + # insert @navs = map { $_ eq $pos ? ($_, $label) : $_ } @navs; # munch munch - $link =~ s#%n#$project#g; - $link =~ s#%f#$git_dir#g; - $treehead ? $link =~ s#%h#$treehead#g : $link =~ s#%h##g; - $treebase ? $link =~ s#%b#$treebase#g : $link =~ s#%b##g; + $link =~ s/%([%nfhb])/$repl{$1}/g; $arg{$label}{'_href'} = $link; } -- cgit v1.3 From 1b2d297e41dbd12c56646796c3d3bcf190f0d5d4 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Fri, 10 Oct 2008 20:42:26 +0200 Subject: gitweb: refactor input parameters parse/validation Since input parameters can be obtained both from CGI parameters and PATH_INFO, we would like most of the code to be agnostic about the way parameters were retrieved. We thus collect all the parameters into the new %input_params hash, delaying validation after the collection is completed. Although the kludge removal is minimal at the moment, it makes life much easier for future expansions such as more extensive PATH_INFO use or other form of input such as command-line support. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 315 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 178 insertions(+), 137 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 11168006cf..c5254afa7f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -29,7 +29,9 @@ our $my_uri = $cgi->url(-absolute => 1); # if we're called with PATH_INFO, we have to strip that # from the URL to find our real URL -if (my $path_info = $ENV{"PATH_INFO"}) { +# we make $path_info global because it's also used later on +my $path_info = $ENV{"PATH_INFO"}; +if ($path_info) { $my_url =~ s,\Q$path_info\E$,,; $my_uri =~ s,\Q$path_info\E$,,; } @@ -428,34 +430,155 @@ $projects_list ||= $projectroot; # ====================================================================== # input validation and dispatch -our $action = $cgi->param('a'); + +# input parameters can be collected from a variety of sources (presently, CGI +# and PATH_INFO), so we define an %input_params hash that collects them all +# together during validation: this allows subsequent uses (e.g. href()) to be +# agnostic of the parameter origin + +my %input_params = (); + +# input parameters are stored with the long parameter name as key. This will +# also be used in the href subroutine to convert parameters to their CGI +# equivalent, and since the href() usage is the most frequent one, we store +# the name -> CGI key mapping here, instead of the reverse. +# +# XXX: Warning: If you touch this, check the search form for updating, +# too. + +my @cgi_param_mapping = ( + project => "p", + action => "a", + file_name => "f", + file_parent => "fp", + hash => "h", + hash_parent => "hp", + hash_base => "hb", + hash_parent_base => "hpb", + page => "pg", + order => "o", + searchtext => "s", + searchtype => "st", + snapshot_format => "sf", + extra_options => "opt", + search_use_regexp => "sr", +); +my %cgi_param_mapping = @cgi_param_mapping; + +# we will also need to know the possible actions, for validation +my %actions = ( + "blame" => \&git_blame, + "blobdiff" => \&git_blobdiff, + "blobdiff_plain" => \&git_blobdiff_plain, + "blob" => \&git_blob, + "blob_plain" => \&git_blob_plain, + "commitdiff" => \&git_commitdiff, + "commitdiff_plain" => \&git_commitdiff_plain, + "commit" => \&git_commit, + "forks" => \&git_forks, + "heads" => \&git_heads, + "history" => \&git_history, + "log" => \&git_log, + "rss" => \&git_rss, + "atom" => \&git_atom, + "search" => \&git_search, + "search_help" => \&git_search_help, + "shortlog" => \&git_shortlog, + "summary" => \&git_summary, + "tag" => \&git_tag, + "tags" => \&git_tags, + "tree" => \&git_tree, + "snapshot" => \&git_snapshot, + "object" => \&git_object, + # those below don't need $project + "opml" => \&git_opml, + "project_list" => \&git_project_list, + "project_index" => \&git_project_index, +); + +# finally, we have the hash of allowed extra_options for the commands that +# allow them +my %allowed_options = ( + "--no-merges" => [ qw(rss atom log shortlog history) ], +); + +# fill %input_params with the CGI parameters. All values except for 'opt' +# should be single values, but opt can be an array. We should probably +# build an array of parameters that can be multi-valued, but since for the time +# being it's only this one, we just single it out +while (my ($name, $symbol) = each %cgi_param_mapping) { + if ($symbol eq 'opt') { + $input_params{$name} = [ $cgi->param($symbol) ]; + } else { + $input_params{$name} = $cgi->param($symbol); + } +} + +# now read PATH_INFO and update the parameter list for missing parameters +sub evaluate_path_info { + return if defined $input_params{'project'}; + return if !$path_info; + $path_info =~ s,^/+,,; + return if !$path_info; + + # find which part of PATH_INFO is project + my $project = $path_info; + $project =~ s,/+$,,; + while ($project && !check_head_link("$projectroot/$project")) { + $project =~ s,/*[^/]*$,,; + } + return unless $project; + $input_params{'project'} = $project; + + # do not change any parameters if an action is given using the query string + return if $input_params{'action'}; + $path_info =~ s,^\Q$project\E/*,,; + + my ($refname, $pathname) = split(/:/, $path_info, 2); + if (defined $pathname) { + # we got "project.git/branch:filename" or "project.git/branch:dir/" + # we could use git_get_type(branch:pathname), but it needs $git_dir + $pathname =~ s,^/+,,; + if (!$pathname || substr($pathname, -1) eq "/") { + $input_params{'action'} = "tree"; + $pathname =~ s,/$,,; + } else { + $input_params{'action'} = "blob_plain"; + } + $input_params{'hash_base'} ||= $refname; + $input_params{'file_name'} ||= $pathname; + } elsif (defined $refname) { + # we got "project.git/branch" + $input_params{'action'} = "shortlog"; + $input_params{'hash'} ||= $refname; + } +} +evaluate_path_info(); + +our $action = $input_params{'action'}; if (defined $action) { - if ($action =~ m/[^0-9a-zA-Z\.\-_]/) { + if (!validate_action($action)) { die_error(400, "Invalid action parameter"); } } # parameters which are pathnames -our $project = $cgi->param('p'); +our $project = $input_params{'project'}; if (defined $project) { - if (!validate_pathname($project) || - !(-d "$projectroot/$project") || - !check_head_link("$projectroot/$project") || - ($export_ok && !(-e "$projectroot/$project/$export_ok")) || - ($strict_export && !project_in_list($project))) { + if (!validate_project($project)) { undef $project; die_error(404, "No such project"); } } -our $file_name = $cgi->param('f'); +our $file_name = $input_params{'file_name'}; if (defined $file_name) { if (!validate_pathname($file_name)) { die_error(400, "Invalid file parameter"); } } -our $file_parent = $cgi->param('fp'); +our $file_parent = $input_params{'file_parent'}; if (defined $file_parent) { if (!validate_pathname($file_parent)) { die_error(400, "Invalid file parent parameter"); @@ -463,44 +586,41 @@ if (defined $file_parent) { } # parameters which are refnames -our $hash = $cgi->param('h'); +our $hash = $input_params{'hash'}; if (defined $hash) { if (!validate_refname($hash)) { die_error(400, "Invalid hash parameter"); } } -our $hash_parent = $cgi->param('hp'); +our $hash_parent = $input_params{'hash_parent'}; if (defined $hash_parent) { if (!validate_refname($hash_parent)) { die_error(400, "Invalid hash parent parameter"); } } -our $hash_base = $cgi->param('hb'); +our $hash_base = $input_params{'hash_base'}; if (defined $hash_base) { if (!validate_refname($hash_base)) { die_error(400, "Invalid hash base parameter"); } } -my %allowed_options = ( - "--no-merges" => [ qw(rss atom log shortlog history) ], -); - -our @extra_options = $cgi->param('opt'); -if (defined @extra_options) { - foreach my $opt (@extra_options) { - if (not exists $allowed_options{$opt}) { - die_error(400, "Invalid option parameter"); - } - if (not grep(/^$action$/, @{$allowed_options{$opt}})) { - die_error(400, "Invalid option parameter for this action"); - } +our @extra_options = @{$input_params{'extra_options'}}; +# @extra_options is always defined, since it can only be (currently) set from +# CGI, and $cgi->param() returns the empty array in array context if the param +# is not set +foreach my $opt (@extra_options) { + if (not exists $allowed_options{$opt}) { + die_error(400, "Invalid option parameter"); + } + if (not grep(/^$action$/, @{$allowed_options{$opt}})) { + die_error(400, "Invalid option parameter for this action"); } } -our $hash_parent_base = $cgi->param('hpb'); +our $hash_parent_base = $input_params{'hash_parent_base'}; if (defined $hash_parent_base) { if (!validate_refname($hash_parent_base)) { die_error(400, "Invalid hash parent base parameter"); @@ -508,23 +628,23 @@ if (defined $hash_parent_base) { } # other parameters -our $page = $cgi->param('pg'); +our $page = $input_params{'page'}; if (defined $page) { if ($page =~ m/[^0-9]/) { die_error(400, "Invalid page parameter"); } } -our $searchtype = $cgi->param('st'); +our $searchtype = $input_params{'searchtype'}; if (defined $searchtype) { if ($searchtype =~ m/[^a-z]/) { die_error(400, "Invalid searchtype parameter"); } } -our $search_use_regexp = $cgi->param('sr'); +our $search_use_regexp = $input_params{'search_use_regexp'}; -our $searchtext = $cgi->param('s'); +our $searchtext = $input_params{'searchtext'}; our $search_regexp; if (defined $searchtext) { if (length($searchtext) < 2) { @@ -533,86 +653,11 @@ if (defined $searchtext) { $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext; } -# now read PATH_INFO and use it as alternative to parameters -sub evaluate_path_info { - return if defined $project; - my $path_info = $ENV{"PATH_INFO"}; - return if !$path_info; - $path_info =~ s,^/+,,; - return if !$path_info; - # find which part of PATH_INFO is project - $project = $path_info; - $project =~ s,/+$,,; - while ($project && !check_head_link("$projectroot/$project")) { - $project =~ s,/*[^/]*$,,; - } - # validate project - $project = validate_pathname($project); - if (!$project || - ($export_ok && !-e "$projectroot/$project/$export_ok") || - ($strict_export && !project_in_list($project))) { - undef $project; - return; - } - # do not change any parameters if an action is given using the query string - return if $action; - $path_info =~ s,^\Q$project\E/*,,; - my ($refname, $pathname) = split(/:/, $path_info, 2); - if (defined $pathname) { - # we got "project.git/branch:filename" or "project.git/branch:dir/" - # we could use git_get_type(branch:pathname), but it needs $git_dir - $pathname =~ s,^/+,,; - if (!$pathname || substr($pathname, -1) eq "/") { - $action ||= "tree"; - $pathname =~ s,/$,,; - } else { - $action ||= "blob_plain"; - } - $hash_base ||= validate_refname($refname); - $file_name ||= validate_pathname($pathname); - } elsif (defined $refname) { - # we got "project.git/branch" - $action ||= "shortlog"; - $hash ||= validate_refname($refname); - } -} -evaluate_path_info(); - # path to the current git repository our $git_dir; $git_dir = "$projectroot/$project" if $project; # dispatch -my %actions = ( - "blame" => \&git_blame, - "blobdiff" => \&git_blobdiff, - "blobdiff_plain" => \&git_blobdiff_plain, - "blob" => \&git_blob, - "blob_plain" => \&git_blob_plain, - "commitdiff" => \&git_commitdiff, - "commitdiff_plain" => \&git_commitdiff_plain, - "commit" => \&git_commit, - "forks" => \&git_forks, - "heads" => \&git_heads, - "history" => \&git_history, - "log" => \&git_log, - "rss" => \&git_rss, - "atom" => \&git_atom, - "search" => \&git_search, - "search_help" => \&git_search_help, - "shortlog" => \&git_shortlog, - "summary" => \&git_summary, - "tag" => \&git_tag, - "tags" => \&git_tags, - "tree" => \&git_tree, - "snapshot" => \&git_snapshot, - "object" => \&git_object, - # those below don't need $project - "opml" => \&git_opml, - "project_list" => \&git_project_list, - "project_index" => \&git_project_index, -); - if (!defined $action) { if (defined $hash) { $action = git_get_type($hash); @@ -642,35 +687,12 @@ sub href (%) { # default is to use -absolute url() i.e. $my_uri my $href = $params{-full} ? $my_url : $my_uri; - # XXX: Warning: If you touch this, check the search form for updating, - # too. - - my @mapping = ( - project => "p", - action => "a", - file_name => "f", - file_parent => "fp", - hash => "h", - hash_parent => "hp", - hash_base => "hb", - hash_parent_base => "hpb", - page => "pg", - order => "o", - searchtext => "s", - searchtype => "st", - snapshot_format => "sf", - extra_options => "opt", - search_use_regexp => "sr", - ); - my %mapping = @mapping; - $params{'project'} = $project unless exists $params{'project'}; if ($params{-replay}) { - while (my ($name, $symbol) = each %mapping) { + while (my ($name, $symbol) = each %cgi_param_mapping) { if (!exists $params{$name}) { - # to allow for multivalued params we use arrayref form - $params{$name} = [ $cgi->param($symbol) ]; + $params{$name} = $input_params{$name}; } } } @@ -689,8 +711,8 @@ sub href (%) { # now encode the parameters explicitly my @result = (); - for (my $i = 0; $i < @mapping; $i += 2) { - my ($name, $symbol) = ($mapping[$i], $mapping[$i+1]); + for (my $i = 0; $i < @cgi_param_mapping; $i += 2) { + my ($name, $symbol) = ($cgi_param_mapping[$i], $cgi_param_mapping[$i+1]); if (defined $params{$name}) { if (ref($params{$name}) eq "ARRAY") { foreach my $par (@{$params{$name}}) { @@ -710,6 +732,25 @@ sub href (%) { ## ====================================================================== ## validation, quoting/unquoting and escaping +sub validate_action { + my $input = shift || return undef; + return undef unless exists $actions{$input}; + return $input; +} + +sub validate_project { + my $input = shift || return undef; + if (!validate_pathname($input) || + !(-d "$projectroot/$input") || + !check_head_link("$projectroot/$input") || + ($export_ok && !(-e "$projectroot/$input/$export_ok")) || + ($strict_export && !project_in_list($input))) { + return undef; + } else { + return $input; + } +} + sub validate_pathname { my $input = shift || return undef; @@ -4121,7 +4162,7 @@ sub git_search_grep_body { ## actions sub git_project_list { - my $order = $cgi->param('o'); + my $order = $input_params{'order'}; if (defined $order && $order !~ m/none|project|descr|owner|age/) { die_error(400, "Unknown order parameter"); } @@ -4149,7 +4190,7 @@ sub git_project_list { } sub git_forks { - my $order = $cgi->param('o'); + my $order = $input_params{'order'}; if (defined $order && $order !~ m/none|project|descr|owner|age/) { die_error(400, "Unknown order parameter"); } @@ -4697,7 +4738,7 @@ sub git_snapshot { my @supported_fmts = gitweb_check_feature('snapshot'); @supported_fmts = filter_snapshot_fmts(@supported_fmts); - my $format = $cgi->param('sf'); + my $format = $input_params{'snapshot_format'}; if (!@supported_fmts) { die_error(403, "Snapshots not allowed"); } -- cgit v1.3 From eee0184da8457c1dbd4418f95d158917540da094 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 14 Oct 2008 21:27:12 -0700 Subject: Fix reading of cloud tags The projectroot path could have SP in it, in which case iterating over <$git_dir/ctags/*> does not correctly enumerate the cloud tags files at all. This can be observed by creating an empty t/trash directory and running t9500 test. The $projectroot ends with "trash directory.t9500-gitweb-/" and <$glob> would give "trash", which can be opened and reading from it immediately yields undef, which in turn gives an undef value warning to the standard error stream upon attempt to chomp it. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 11168006cf..41b68668e8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1805,7 +1805,10 @@ sub git_get_project_ctags { my $ctags = {}; $git_dir = "$projectroot/$path"; - foreach (<$git_dir/ctags/*>) { + unless (opendir D, "$git_dir/ctags") { + return $ctags; + } + foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir(D)) { open CT, $_ or next; my $val = ; chomp $val; @@ -1813,6 +1816,7 @@ sub git_get_project_ctags { my $ctag = $_; $ctag =~ s#.*/##; $ctags->{$ctag} = $val; } + closedir D; $ctags; } -- cgit v1.3 From d8c2882254f0f30e4f44de593c3b3db6a8fccef9 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 21 Oct 2008 21:34:50 +0200 Subject: gitweb: parse project/action/hash_base:filename PATH_INFO This patch enables gitweb to parse URLs with more information embedded in PATH_INFO, reducing the need for CGI parameters. The typical gitweb path is now $project/$action/$hash_base:$file_name or $project/$action/$hash This is mostly backwards compatible with the old-style gitweb paths, $project/$branch[:$filename], except when it was used to access a branch whose name matches a gitweb action. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c5254afa7f..d09cf0a520 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -534,23 +534,55 @@ sub evaluate_path_info { return if $input_params{'action'}; $path_info =~ s,^\Q$project\E/*,,; + # next, check if we have an action + my $action = $path_info; + $action =~ s,/.*$,,; + if (exists $actions{$action}) { + $path_info =~ s,^$action/*,,; + $input_params{'action'} = $action; + } + + # list of actions that want hash_base instead of hash, but can have no + # pathname (f) parameter + my @wants_base = ( + 'tree', + 'history', + ); + my ($refname, $pathname) = split(/:/, $path_info, 2); if (defined $pathname) { - # we got "project.git/branch:filename" or "project.git/branch:dir/" - # we could use git_get_type(branch:pathname), but it needs $git_dir + # we got "branch:filename" or "branch:dir/" + # we could use git_get_type(branch:pathname), but: + # - it needs $git_dir + # - it does a git() call + # - the convention of terminating directories with a slash + # makes it superfluous + # - embedding the action in the PATH_INFO would make it even + # more superfluous $pathname =~ s,^/+,,; if (!$pathname || substr($pathname, -1) eq "/") { - $input_params{'action'} = "tree"; + $input_params{'action'} ||= "tree"; $pathname =~ s,/$,,; } else { - $input_params{'action'} = "blob_plain"; + $input_params{'action'} ||= "blob_plain"; } $input_params{'hash_base'} ||= $refname; $input_params{'file_name'} ||= $pathname; } elsif (defined $refname) { - # we got "project.git/branch" - $input_params{'action'} = "shortlog"; - $input_params{'hash'} ||= $refname; + # we got "branch". In this case we have to choose if we have to + # set hash or hash_base. + # + # Most of the actions without a pathname only want hash to be + # set, except for the ones specified in @wants_base that want + # hash_base instead. It should also be noted that hand-crafted + # links having 'history' as an action and no pathname or hash + # set will fail, but that happens regardless of PATH_INFO. + $input_params{'action'} ||= "shortlog"; + if (grep { $_ eq $input_params{'action'} } @wants_base) { + $input_params{'hash_base'} ||= $refname; + } else { + $input_params{'hash'} ||= $refname; + } } } evaluate_path_info(); -- cgit v1.3 From b02bd7a6323a85f9feedd9c8cd7d7401021dfb11 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 21 Oct 2008 21:34:51 +0200 Subject: gitweb: generate project/action/hash URLs When generating path info URLs, reduce the number of CGI parameters by embedding action and hash_parent:filename or hash in the path. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d09cf0a520..50604e0a0c 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -731,14 +731,41 @@ sub href (%) { my ($use_pathinfo) = gitweb_check_feature('pathinfo'); if ($use_pathinfo) { - # use PATH_INFO for project name + # try to put as many parameters as possible in PATH_INFO: + # - project name + # - action + # - hash or hash_base:filename + + # When the script is the root DirectoryIndex for the domain, + # $href here would be something like http://gitweb.example.com/ + # Thus, we strip any trailing / from $href, to spare us double + # slashes in the final URL + $href =~ s,/$,,; + + # Then add the project name, if present $href .= "/".esc_url($params{'project'}) if defined $params{'project'}; delete $params{'project'}; - # Summary just uses the project path URL - if (defined $params{'action'} && $params{'action'} eq 'summary') { + # Summary just uses the project path URL, any other action is + # added to the URL + if (defined $params{'action'}) { + $href .= "/".esc_url($params{'action'}) unless $params{'action'} eq 'summary'; delete $params{'action'}; } + + # Finally, we put either hash_base:file_name or hash + if (defined $params{'hash_base'}) { + $href .= "/".esc_url($params{'hash_base'}); + if (defined $params{'file_name'}) { + $href .= ":".esc_url($params{'file_name'}); + delete $params{'file_name'}; + } + delete $params{'hash'}; + delete $params{'hash_base'}; + } elsif (defined $params{'hash'}) { + $href .= "/".esc_url($params{'hash'}); + delete $params{'hash'}; + } } # now encode the parameters explicitly -- cgit v1.3 From 3550ea71f566b6958ffedf1573806d5fe891f344 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 21 Oct 2008 21:34:52 +0200 Subject: gitweb: use_pathinfo filenames start with / Generate PATH_INFO URLs in the form project/action/hash_base:/filename rather than project/action/hash_base:filename (the latter form is still accepted in input). This minimal change allows relative navigation to work properly when viewing HTML files in raw ('blob_plain') mode. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 50604e0a0c..f8021da967 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -734,7 +734,7 @@ sub href (%) { # try to put as many parameters as possible in PATH_INFO: # - project name # - action - # - hash or hash_base:filename + # - hash or hash_base:/filename # When the script is the root DirectoryIndex for the domain, # $href here would be something like http://gitweb.example.com/ @@ -753,11 +753,11 @@ sub href (%) { delete $params{'action'}; } - # Finally, we put either hash_base:file_name or hash + # Finally, we put either hash_base:/file_name or hash if (defined $params{'hash_base'}) { $href .= "/".esc_url($params{'hash_base'}); if (defined $params{'file_name'}) { - $href .= ":".esc_url($params{'file_name'}); + $href .= ":/".esc_url($params{'file_name'}); delete $params{'file_name'}; } delete $params{'hash'}; -- cgit v1.3 From b0be3838bb75e8b3be04310cc379142c3ef65703 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 21 Oct 2008 21:34:53 +0200 Subject: gitweb: parse parent..current syntax from PATH_INFO This patch makes it possible to use an URL such as project/action/somebranch..otherbranch:/filename to get a diff between different version of a file. Paths like project/action/somebranch:/somefile..otherbranch:/otherfile are parsed as well. All '*diff' actions and in general actions that use $hash_parent[_base] and $file_parent (e.g. 'shortlog') can now get all of their parameters from PATH_INFO Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f8021da967..3d62019e1f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -549,7 +549,12 @@ sub evaluate_path_info { 'history', ); - my ($refname, $pathname) = split(/:/, $path_info, 2); + # we want to catch + # [$hash_parent_base[:$file_parent]..]$hash_parent[:$file_name] + my ($parentrefname, $parentpathname, $refname, $pathname) = + ($path_info =~ /^(?:(.+?)(?::(.+))?\.\.)?(.+?)(?::(.+))?$/); + + # first, analyze the 'current' part if (defined $pathname) { # we got "branch:filename" or "branch:dir/" # we could use git_get_type(branch:pathname), but: @@ -564,7 +569,13 @@ sub evaluate_path_info { $input_params{'action'} ||= "tree"; $pathname =~ s,/$,,; } else { - $input_params{'action'} ||= "blob_plain"; + # the default action depends on whether we had parent info + # or not + if ($parentrefname) { + $input_params{'action'} ||= "blobdiff_plain"; + } else { + $input_params{'action'} ||= "blob_plain"; + } } $input_params{'hash_base'} ||= $refname; $input_params{'file_name'} ||= $pathname; @@ -584,6 +595,27 @@ sub evaluate_path_info { $input_params{'hash'} ||= $refname; } } + + # next, handle the 'parent' part, if present + if (defined $parentrefname) { + # a missing pathspec defaults to the 'current' filename, allowing e.g. + # someproject/blobdiff/oldrev..newrev:/filename + if ($parentpathname) { + $parentpathname =~ s,^/+,,; + $parentpathname =~ s,/$,,; + $input_params{'file_parent'} ||= $parentpathname; + } else { + $input_params{'file_parent'} ||= $input_params{'file_name'}; + } + # we assume that hash_parent_base is wanted if a path was specified, + # or if the action wants hash_base instead of hash + if (defined $input_params{'file_parent'} || + grep { $_ eq $input_params{'action'} } @wants_base) { + $input_params{'hash_parent_base'} ||= $parentrefname; + } else { + $input_params{'hash_parent'} ||= $parentrefname; + } + } } evaluate_path_info(); -- cgit v1.3 From 8db49a7f6f272ecb72c75a172e9753f3981488ce Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 21 Oct 2008 21:34:54 +0200 Subject: gitweb: generate parent..current URLs If use_pathinfo is enabled, href now creates links that contain paths in the form $project/$action/oldhash:/oldname..newhash:/newname for actions that use hash_parent etc. If any of the filename contains two consecutive dots, it's kept as a CGI parameter since the resulting path would otherwise be ambiguous. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3d62019e1f..63c793ec39 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -766,6 +766,7 @@ sub href (%) { # try to put as many parameters as possible in PATH_INFO: # - project name # - action + # - hash_parent or hash_parent_base:/file_parent # - hash or hash_base:/filename # When the script is the root DirectoryIndex for the domain, @@ -785,17 +786,36 @@ sub href (%) { delete $params{'action'}; } - # Finally, we put either hash_base:/file_name or hash + # Next, we put hash_parent_base:/file_parent..hash_base:/file_name, + # stripping nonexistent or useless pieces + $href .= "/" if ($params{'hash_base'} || $params{'hash_parent_base'} + || $params{'hash_parent'} || $params{'hash'}); if (defined $params{'hash_base'}) { - $href .= "/".esc_url($params{'hash_base'}); - if (defined $params{'file_name'}) { + if (defined $params{'hash_parent_base'}) { + $href .= esc_url($params{'hash_parent_base'}); + # skip the file_parent if it's the same as the file_name + delete $params{'file_parent'} if $params{'file_parent'} eq $params{'file_name'}; + if (defined $params{'file_parent'} && $params{'file_parent'} !~ /\.\./) { + $href .= ":/".esc_url($params{'file_parent'}); + delete $params{'file_parent'}; + } + $href .= ".."; + delete $params{'hash_parent'}; + delete $params{'hash_parent_base'}; + } elsif (defined $params{'hash_parent'}) { + $href .= esc_url($params{'hash_parent'}). ".."; + delete $params{'hash_parent'}; + } + + $href .= esc_url($params{'hash_base'}); + if (defined $params{'file_name'} && $params{'file_name'} !~ /\.\./) { $href .= ":/".esc_url($params{'file_name'}); delete $params{'file_name'}; } delete $params{'hash'}; delete $params{'hash_base'}; } elsif (defined $params{'hash'}) { - $href .= "/".esc_url($params{'hash'}); + $href .= esc_url($params{'hash'}); delete $params{'hash'}; } } -- cgit v1.3 From 5e166843f502536df7e940486721057acf37ec23 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sun, 2 Nov 2008 10:21:37 +0100 Subject: gitweb: make the supported snapshot formats array global The array of supported snapshot format is used and defined (with two different names) in two routines, one of which (format_snapshot_links) is often called multiple times per page. Simplify code and speed up page generation by making the array global. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 63c793ec39..b4cd2620ff 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -721,6 +721,10 @@ if (defined $searchtext) { our $git_dir; $git_dir = "$projectroot/$project" if $project; +# list of supported snapshot formats +our @snapshot_fmts = gitweb_check_feature('snapshot'); +@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts); + # dispatch if (!defined $action) { if (defined $hash) { @@ -1647,8 +1651,6 @@ sub format_diff_line { # linked. Pass the hash of the tree/commit to snapshot. sub format_snapshot_links { my ($hash) = @_; - my @snapshot_fmts = gitweb_check_feature('snapshot'); - @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts); my $num_fmts = @snapshot_fmts; if ($num_fmts > 1) { # A parenthesized list of links bearing format names. @@ -4846,20 +4848,17 @@ sub git_tree { } sub git_snapshot { - my @supported_fmts = gitweb_check_feature('snapshot'); - @supported_fmts = filter_snapshot_fmts(@supported_fmts); - my $format = $input_params{'snapshot_format'}; - if (!@supported_fmts) { + if (!@snapshot_fmts) { die_error(403, "Snapshots not allowed"); } # default to first supported snapshot format - $format ||= $supported_fmts[0]; + $format ||= $snapshot_fmts[0]; if ($format !~ m/^[a-z0-9]+$/) { die_error(400, "Invalid snapshot format parameter"); } elsif (!exists($known_snapshot_formats{$format})) { die_error(400, "Unknown snapshot format"); - } elsif (!grep($_ eq $format, @supported_fmts)) { + } elsif (!grep($_ eq $format, @snapshot_fmts)) { die_error(403, "Unsupported snapshot format"); } -- cgit v1.3 From 1ec2fb5fa37d823d02517263f8e2a78930abd1dd Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sun, 2 Nov 2008 10:21:38 +0100 Subject: gitweb: retrieve snapshot format from PATH_INFO We parse requests for $project/snapshot/$head.$sfx as equivalent to $project/snapshot/$head?sf=$sfx, where $sfx is any of the known (although not necessarily supported) snapshot formats (or its default suffix). The filename for the resulting package preserves the requested extensions (so asking for a .tgz gives a .tgz, and asking for a .tar.gz gives a .tar.gz), although for obvious reasons it doesn't preserve the basename (git/snapshot/next.tgz returns a file names git-next.tgz). This introduces a potential case for ambiguity if a project has a head that ends with a snapshot-like suffix (.zip, .tgz, .tar.gz, etc) and the sf CGI parameter is not present; however, gitweb only produces URLs with the sf parameter currently, so this is only a potential issue for hand-coded URLs for extremely unusual project. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b4cd2620ff..a7f35ccc87 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -616,6 +616,45 @@ sub evaluate_path_info { $input_params{'hash_parent'} ||= $parentrefname; } } + + # for the snapshot action, we allow URLs in the form + # $project/snapshot/$hash.ext + # where .ext determines the snapshot and gets removed from the + # passed $refname to provide the $hash. + # + # To be able to tell that $refname includes the format extension, we + # require the following two conditions to be satisfied: + # - the hash input parameter MUST have been set from the $refname part + # of the URL (i.e. they must be equal) + # - the snapshot format MUST NOT have been defined already (e.g. from + # CGI parameter sf) + # It's also useless to try any matching unless $refname has a dot, + # so we check for that too + if (defined $input_params{'action'} && + $input_params{'action'} eq 'snapshot' && + defined $refname && index($refname, '.') != -1 && + $refname eq $input_params{'hash'} && + !defined $input_params{'snapshot_format'}) { + # We loop over the known snapshot formats, checking for + # extensions. Allowed extensions are both the defined suffix + # (which includes the initial dot already) and the snapshot + # format key itself, with a prepended dot + while (my ($fmt, %opt) = each %known_snapshot_formats) { + my $hash = $refname; + my $sfx; + $hash =~ s/(\Q$opt{'suffix'}\E|\Q.$fmt\E)$//; + next unless $sfx = $1; + # a valid suffix was found, so set the snapshot format + # and reset the hash parameter + $input_params{'snapshot_format'} = $fmt; + $input_params{'hash'} = $hash; + # we also set the format suffix to the one requested + # in the URL: this way a request for e.g. .tgz returns + # a .tgz instead of a .tar.gz + $known_snapshot_formats{$fmt}{'suffix'} = $sfx; + last; + } + } } evaluate_path_info(); -- cgit v1.3 From c752a0e00c7f122dbca72552b1bf193e5850a1b1 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sun, 2 Nov 2008 10:21:39 +0100 Subject: gitweb: embed snapshot format parameter in PATH_INFO When PATH_INFO is active, get rid of the sf CGI parameter by embedding the snapshot format information in the PATH_INFO URL, in the form of an appropriate extension. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a7f35ccc87..e2ed1ccab3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -811,6 +811,7 @@ sub href (%) { # - action # - hash_parent or hash_parent_base:/file_parent # - hash or hash_base:/filename + # - the snapshot_format as an appropriate suffix # When the script is the root DirectoryIndex for the domain, # $href here would be something like http://gitweb.example.com/ @@ -822,6 +823,10 @@ sub href (%) { $href .= "/".esc_url($params{'project'}) if defined $params{'project'}; delete $params{'project'}; + # since we destructively absorb parameters, we keep this + # boolean that remembers if we're handling a snapshot + my $is_snapshot = $params{'action'} eq 'snapshot'; + # Summary just uses the project path URL, any other action is # added to the URL if (defined $params{'action'}) { @@ -861,6 +866,18 @@ sub href (%) { $href .= esc_url($params{'hash'}); delete $params{'hash'}; } + + # If the action was a snapshot, we can absorb the + # snapshot_format parameter too + if ($is_snapshot) { + my $fmt = $params{'snapshot_format'}; + # snapshot_format should always be defined when href() + # is called, but just in case some code forgets, we + # fall back to the default + $fmt ||= $snapshot_fmts[0]; + $href .= $known_snapshot_formats{$fmt}{'suffix'}; + delete $params{'snapshot_format'}; + } } # now encode the parameters explicitly -- cgit v1.3 From ec26f098a6593bbd9d396fb7ee74368cdd3eeed3 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 6 Nov 2008 01:15:56 +0300 Subject: gitweb: Use single implementation of export_ok check. GitWeb source contains a special function that implements the export_ok check, but validate_project still uses a separate copy of essentially the same code. This patch makes it use the dedicated function, thus ensuring that all checks are done through a single code path. Signed-off-by: Alexander Gavrilov Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 9d1af7e557..68bdf62657 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -853,8 +853,7 @@ sub validate_project { my $input = shift || return undef; if (!validate_pathname($input) || !(-d "$projectroot/$input") || - !check_head_link("$projectroot/$input") || - ($export_ok && !(-e "$projectroot/$input/$export_ok")) || + !check_export_ok("$projectroot/$input") || ($strict_export && !project_in_list($input))) { return undef; } else { -- cgit v1.3 From dd7f5f105a1d4d094a96c5e3f251854f81106be0 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 6 Nov 2008 01:36:23 +0300 Subject: gitweb: Add a per-repository authorization hook. Add a configuration variable that can be used to specify an arbitrary subroutine that will be called in the same situations where $export_ok is checked, and its return value used to decide whether the repository is to be shown. This allows the user to implement custom authentication schemes, for example by issuing a subrequest through mod_perl and checking if Apache will authorize it. Signed-off-by: Alexander Gavrilov Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/INSTALL | 21 +++++++++++++++++++++ gitweb/gitweb.perl | 8 +++++++- 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/INSTALL b/gitweb/INSTALL index 26967e201a..18c9ce35e8 100644 --- a/gitweb/INSTALL +++ b/gitweb/INSTALL @@ -166,6 +166,27 @@ Gitweb repositories shows repositories only if this file exists in its object database (if directory has the magic file named $export_ok). +- Finally, it is possible to specify an arbitrary perl subroutine that + will be called for each project to determine if it can be exported. + The subroutine receives an absolute path to the project as its only + parameter. + + For example, if you use mod_perl to run the script, and have dumb + http protocol authentication configured for your repositories, you + can use the following hook to allow access only if the user is + authorized to read the files: + + $export_auth_hook = sub { + use Apache2::SubRequest (); + use Apache2::Const -compile => qw(HTTP_OK); + my $path = "$_[0]/HEAD"; + my $r = Apache2::RequestUtil->request; + my $sub = $r->lookup_file($path); + return $sub->filename eq $path + && $sub->status == Apache2::Const::HTTP_OK; + }; + + Generating projects list using gitweb ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 68bdf62657..74672bffd8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -95,6 +95,11 @@ our $default_projects_order = "project"; # (only effective if this variable evaluates to true) our $export_ok = "++GITWEB_EXPORT_OK++"; +# show repository only if this subroutine returns true +# when given the path to the project, for example: +# sub { return -e "$_[0]/git-daemon-export-ok"; } +our $export_auth_hook = undef; + # only allow viewing of repositories also shown on the overview page our $strict_export = "++GITWEB_STRICT_EXPORT++"; @@ -400,7 +405,8 @@ sub check_head_link { sub check_export_ok { my ($dir) = @_; return (check_head_link($dir) && - (!$export_ok || -e "$dir/$export_ok")); + (!$export_ok || -e "$dir/$export_ok") && + (!$export_auth_hook || $export_auth_hook->($dir))); } # process alternate names for backward compatibility -- cgit v1.3 From dde80d9c23e10592817f0c81e32a99a889a9bb8e Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 6 Nov 2008 01:10:07 +0300 Subject: gitweb: Fix mod_perl support. ModPerl::Registry precompiles scripts by wrapping them in a subroutine. This causes ordinary subroutines of the script to become nested, and warnings appear: gitweb.cgi: Variable "$path_info" will not stay shared This warning means that $path_info was declared as 'my', and thus according to the perl evaluation rules all nested subroutines will retain a reference to the instance of the variable used in the first invocation of the master script. When the script (i.e. the master meta-subroutine) is executed the second time, it will use a new instance, so the logic breaks. To avoid this it is necessary to declare all global variables as 'our', which places them at the package level. Signed-off-by: Alexander Gavrilov Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 74672bffd8..06da30c501 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -30,7 +30,7 @@ our $my_uri = $cgi->url(-absolute => 1); # if we're called with PATH_INFO, we have to strip that # from the URL to find our real URL # we make $path_info global because it's also used later on -my $path_info = $ENV{"PATH_INFO"}; +our $path_info = $ENV{"PATH_INFO"}; if ($path_info) { $my_url =~ s,\Q$path_info\E$,,; $my_uri =~ s,\Q$path_info\E$,,; @@ -442,7 +442,7 @@ $projects_list ||= $projectroot; # together during validation: this allows subsequent uses (e.g. href()) to be # agnostic of the parameter origin -my %input_params = (); +our %input_params = (); # input parameters are stored with the long parameter name as key. This will # also be used in the href subroutine to convert parameters to their CGI @@ -452,7 +452,7 @@ my %input_params = (); # XXX: Warning: If you touch this, check the search form for updating, # too. -my @cgi_param_mapping = ( +our @cgi_param_mapping = ( project => "p", action => "a", file_name => "f", @@ -469,10 +469,10 @@ my @cgi_param_mapping = ( extra_options => "opt", search_use_regexp => "sr", ); -my %cgi_param_mapping = @cgi_param_mapping; +our %cgi_param_mapping = @cgi_param_mapping; # we will also need to know the possible actions, for validation -my %actions = ( +our %actions = ( "blame" => \&git_blame, "blobdiff" => \&git_blobdiff, "blobdiff_plain" => \&git_blobdiff_plain, @@ -504,7 +504,7 @@ my %actions = ( # finally, we have the hash of allowed extra_options for the commands that # allow them -my %allowed_options = ( +our %allowed_options = ( "--no-merges" => [ qw(rss atom log shortlog history) ], ); -- cgit v1.3 From 8d2dbbac21bbb76af29133331e2a88870d93899d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 29 Nov 2008 12:53:41 -0800 Subject: gitweb: fix 'ctags' feature check and others gitweb_check_feature() function is to retrieve the configuration parameter list and calling it in the scalar context does not give its first element that tells if the feature is enabled. This fixes all the existing callers to call the function correctly in the list context. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 933e137386..400f5c8e14 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3914,7 +3914,7 @@ sub fill_project_list_info { my ($projlist, $check_forks) = @_; my @projects; - my $show_ctags = gitweb_check_feature('ctags'); + my ($show_ctags) = gitweb_check_feature('ctags'); PROJECT: foreach my $pr (@$projlist) { my (@activity) = git_get_last_activity($pr->{'path'}); @@ -3988,7 +3988,7 @@ sub git_project_list_body { @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @projects; } - my $show_ctags = gitweb_check_feature('ctags'); + my ($show_ctags) = gitweb_check_feature('ctags'); if ($show_ctags) { my %ctags; foreach my $p (@projects) { @@ -4457,7 +4457,7 @@ sub git_summary { } # Tag cloud - my $show_ctags = (gitweb_check_feature('ctags'))[0]; + my ($show_ctags) = gitweb_check_feature('ctags'); if ($show_ctags) { my $ctags = git_get_project_ctags($project); my $cloud = git_populate_project_tagcloud($ctags); @@ -4559,7 +4559,7 @@ sub git_blame { my $fd; my $ftype; - gitweb_check_feature('blame') + gitweb_check_feature('blame')[0] or die_error(403, "Blame view not allowed"); die_error(400, "No file name given") unless $file_name; @@ -5610,7 +5610,7 @@ sub git_history { } sub git_search { - gitweb_check_feature('search') or die_error(403, "Search is disabled"); + gitweb_check_feature('search')[0] or die_error(403, "Search is disabled"); if (!defined $searchtext) { die_error(400, "Text field is empty"); } @@ -5629,11 +5629,11 @@ sub git_search { if ($searchtype eq 'pickaxe') { # pickaxe may take all resources of your box and run for several minutes # with every query - so decide by yourself how public you make this feature - gitweb_check_feature('pickaxe') + gitweb_check_feature('pickaxe')[0] or die_error(403, "Pickaxe is disabled"); } if ($searchtype eq 'grep') { - gitweb_check_feature('grep') + gitweb_check_feature('grep')[0] or die_error(403, "Grep is disabled"); } -- cgit v1.3 From a7c5a283509f6a70753c90393dfad016312b8822 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 29 Nov 2008 13:02:08 -0800 Subject: gitweb: rename gitweb_check_feature to gitweb_get_feature The function is about retrieving the configuration parameter list for the feature. A more robust way to check if a feature is enabled will be introduced in the next patch, and the function will be called gitweb_check_feature. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 400f5c8e14..756b24808d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -190,7 +190,7 @@ our %feature = ( # if there is no 'sub' key (no feature-sub), then feature cannot be # overriden # - # use gitweb_check_feature() to check if is enabled + # # Enable the 'blame' blob view, showing the last commit that modified # each line in the file. This can be very CPU-intensive. @@ -329,7 +329,7 @@ our %feature = ( 'default' => [0]}, ); -sub gitweb_check_feature { +sub gitweb_get_feature { my ($name) = @_; return unless exists $feature{$name}; my ($sub, $override, @defaults) = ( @@ -767,7 +767,7 @@ our $git_dir; $git_dir = "$projectroot/$project" if $project; # list of supported snapshot formats -our @snapshot_fmts = gitweb_check_feature('snapshot'); +our @snapshot_fmts = gitweb_get_feature('snapshot'); @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts); # dispatch @@ -810,7 +810,7 @@ sub href (%) { } } - my ($use_pathinfo) = gitweb_check_feature('pathinfo'); + my ($use_pathinfo) = gitweb_get_feature('pathinfo'); if ($use_pathinfo) { # try to put as many parameters as possible in PATH_INFO: # - project name @@ -2101,7 +2101,7 @@ sub git_get_projects_list { $filter ||= ''; $filter =~ s/\.git$//; - my ($check_forks) = gitweb_check_feature('forks'); + my ($check_forks) = gitweb_get_feature('forks'); if (-d $projects_list) { # search in directory @@ -2947,7 +2947,7 @@ EOF } print "\n"; - my ($have_search) = gitweb_check_feature('search'); + my ($have_search) = gitweb_get_feature('search'); if (defined $project && $have_search) { if (!defined $searchtext) { $searchtext = ""; @@ -2961,7 +2961,7 @@ EOF $search_hash = "HEAD"; } my $action = $my_uri; - my ($use_pathinfo) = gitweb_check_feature('pathinfo'); + my ($use_pathinfo) = gitweb_get_feature('pathinfo'); if ($use_pathinfo) { $action .= "/".esc_url($project); } @@ -3084,7 +3084,7 @@ sub git_print_page_nav { $arg{'tree'}{'hash'} = $treehead if defined $treehead; $arg{'tree'}{'hash_base'} = $treebase if defined $treebase; - my @actions = gitweb_check_feature('actions'); + my @actions = gitweb_get_feature('actions'); my %repl = ( '%' => '%', 'n' => $project, # project name @@ -3454,7 +3454,7 @@ sub is_patch_split { sub git_difftree_body { my ($difftree, $hash, @parents) = @_; my ($parent) = $parents[0]; - my ($have_blame) = gitweb_check_feature('blame'); + my ($have_blame) = gitweb_get_feature('blame'); print "
\n"; if ($#{$difftree} > 10) { print(($#{$difftree} + 1) . " files changed:\n"); @@ -3914,7 +3914,7 @@ sub fill_project_list_info { my ($projlist, $check_forks) = @_; my @projects; - my ($show_ctags) = gitweb_check_feature('ctags'); + my ($show_ctags) = gitweb_get_feature('ctags'); PROJECT: foreach my $pr (@$projlist) { my (@activity) = git_get_last_activity($pr->{'path'}); @@ -3968,7 +3968,7 @@ sub git_project_list_body { # actually uses global variable $project my ($projlist, $order, $from, $to, $extra, $no_header) = @_; - my ($check_forks) = gitweb_check_feature('forks'); + my ($check_forks) = gitweb_get_feature('forks'); my @projects = fill_project_list_info($projlist, $check_forks); $order ||= $default_projects_order; @@ -3988,7 +3988,7 @@ sub git_project_list_body { @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @projects; } - my ($show_ctags) = gitweb_check_feature('ctags'); + my ($show_ctags) = gitweb_get_feature('ctags'); if ($show_ctags) { my %ctags; foreach my $p (@projects) { @@ -4428,7 +4428,7 @@ sub git_summary { my @taglist = git_get_tags_list(16); my @headlist = git_get_heads_list(16); my @forklist; - my ($check_forks) = gitweb_check_feature('forks'); + my ($check_forks) = gitweb_get_feature('forks'); if ($check_forks) { @forklist = git_get_projects_list($project); @@ -4457,7 +4457,7 @@ sub git_summary { } # Tag cloud - my ($show_ctags) = gitweb_check_feature('ctags'); + my ($show_ctags) = gitweb_get_feature('ctags'); if ($show_ctags) { my $ctags = git_get_project_ctags($project); my $cloud = git_populate_project_tagcloud($ctags); @@ -4559,7 +4559,7 @@ sub git_blame { my $fd; my $ftype; - gitweb_check_feature('blame')[0] + gitweb_get_feature('blame')[0] or die_error(403, "Blame view not allowed"); die_error(400, "No file name given") unless $file_name; @@ -4747,7 +4747,7 @@ sub git_blob { $expires = "+1d"; } - my ($have_blame) = gitweb_check_feature('blame'); + my ($have_blame) = gitweb_get_feature('blame'); open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash or die_error(500, "Couldn't cat $file_name, $hash"); my $mimetype = blob_mimetype($fd, $file_name); @@ -4840,7 +4840,7 @@ sub git_tree { my $ref = format_ref_marker($refs, $hash_base); git_header_html(); my $basedir = ''; - my ($have_blame) = gitweb_check_feature('blame'); + my ($have_blame) = gitweb_get_feature('blame'); if (defined $hash_base && (my %co = parse_commit($hash_base))) { my @views_nav = (); if (defined $file_name) { @@ -5610,7 +5610,7 @@ sub git_history { } sub git_search { - gitweb_check_feature('search')[0] or die_error(403, "Search is disabled"); + gitweb_get_feature('search')[0] or die_error(403, "Search is disabled"); if (!defined $searchtext) { die_error(400, "Text field is empty"); } @@ -5629,11 +5629,11 @@ sub git_search { if ($searchtype eq 'pickaxe') { # pickaxe may take all resources of your box and run for several minutes # with every query - so decide by yourself how public you make this feature - gitweb_check_feature('pickaxe')[0] + gitweb_get_feature('pickaxe')[0] or die_error(403, "Pickaxe is disabled"); } if ($searchtype eq 'grep') { - gitweb_check_feature('grep')[0] + gitweb_get_feature('grep')[0] or die_error(403, "Grep is disabled"); } @@ -5838,7 +5838,7 @@ insensitive).

commit
The commit messages and authorship information will be scanned for the given pattern.
EOT - my ($have_grep) = gitweb_check_feature('grep'); + my ($have_grep) = gitweb_get_feature('grep'); if ($have_grep) { print <grep @@ -5855,7 +5855,7 @@ EOT
committer
Name and e-mail of the committer and date of commit will be scanned for the given pattern.
EOT - my ($have_pickaxe) = gitweb_check_feature('pickaxe'); + my ($have_pickaxe) = gitweb_get_feature('pickaxe'); if ($have_pickaxe) { print <pickaxe @@ -5907,7 +5907,7 @@ sub git_shortlog { sub git_feed { my $format = shift || 'atom'; - my ($have_blame) = gitweb_check_feature('blame'); + my ($have_blame) = gitweb_get_feature('blame'); # Atom: http://www.atomenabled.org/developers/syndication/ # RSS: http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ -- cgit v1.3 From 25b2790fff5b7b484f1a2f40fafa4b24db1506a2 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sat, 29 Nov 2008 13:07:29 -0800 Subject: gitweb: make gitweb_check_feature a boolean wrapper The gitweb_get_feature() function retrieves the configuration parameters for the feature (such as the list of snapshot formats or the list of additional actions), but it is very often used to see if feature is enabled (which is returned as the first element in the list). Because accepting the returned list in the scalar context by mistake yields the number of elements in the array, which is non-zero in all cases, such a mistake would result in a bug for the latter use, with disabled features appearing enabled. All existing callers that call the function for this purpose assign the return value in the list context to retrieve the first element, but that is only because we fixed careless callers recently. This adds gitweb_check_feature() as a wrapper to gitweb_get_feature() that can be called safely in the scalar context to see if a feature is enabled to reduce the risk of future bugs. Callers of "get" that use the call only to see if the feature is enabled are updated to call this wrapper. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 56 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 756b24808d..acc4cfdcda 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -190,7 +190,7 @@ our %feature = ( # if there is no 'sub' key (no feature-sub), then feature cannot be # overriden # - # + # use gitweb_check_feature() to check if is enabled # Enable the 'blame' blob view, showing the last commit that modified # each line in the file. This can be very CPU-intensive. @@ -344,6 +344,22 @@ sub gitweb_get_feature { return $sub->(@defaults); } +# A wrapper to check if a given feature is enabled. +# With this, you can say +# +# my $bool_feat = gitweb_check_feature('bool_feat'); +# gitweb_check_feature('bool_feat') or somecode; +# +# instead of +# +# my ($bool_feat) = gitweb_get_feature('bool_feat'); +# (gitweb_get_feature('bool_feat'))[0] or somecode; +# +sub gitweb_check_feature { + return (gitweb_get_feature(@_))[0]; +} + + sub feature_blame { my ($val) = git_get_project_config('blame', '--bool'); @@ -810,7 +826,7 @@ sub href (%) { } } - my ($use_pathinfo) = gitweb_get_feature('pathinfo'); + my $use_pathinfo = gitweb_check_feature('pathinfo'); if ($use_pathinfo) { # try to put as many parameters as possible in PATH_INFO: # - project name @@ -2101,7 +2117,7 @@ sub git_get_projects_list { $filter ||= ''; $filter =~ s/\.git$//; - my ($check_forks) = gitweb_get_feature('forks'); + my $check_forks = gitweb_check_feature('forks'); if (-d $projects_list) { # search in directory @@ -2947,7 +2963,7 @@ EOF } print "
\n"; - my ($have_search) = gitweb_get_feature('search'); + my $have_search = gitweb_check_feature('search'); if (defined $project && $have_search) { if (!defined $searchtext) { $searchtext = ""; @@ -2961,7 +2977,7 @@ EOF $search_hash = "HEAD"; } my $action = $my_uri; - my ($use_pathinfo) = gitweb_get_feature('pathinfo'); + my $use_pathinfo = gitweb_check_feature('pathinfo'); if ($use_pathinfo) { $action .= "/".esc_url($project); } @@ -3454,7 +3470,7 @@ sub is_patch_split { sub git_difftree_body { my ($difftree, $hash, @parents) = @_; my ($parent) = $parents[0]; - my ($have_blame) = gitweb_get_feature('blame'); + my $have_blame = gitweb_check_feature('blame'); print "
\n"; if ($#{$difftree} > 10) { print(($#{$difftree} + 1) . " files changed:\n"); @@ -3914,7 +3930,7 @@ sub fill_project_list_info { my ($projlist, $check_forks) = @_; my @projects; - my ($show_ctags) = gitweb_get_feature('ctags'); + my $show_ctags = gitweb_check_feature('ctags'); PROJECT: foreach my $pr (@$projlist) { my (@activity) = git_get_last_activity($pr->{'path'}); @@ -3968,7 +3984,7 @@ sub git_project_list_body { # actually uses global variable $project my ($projlist, $order, $from, $to, $extra, $no_header) = @_; - my ($check_forks) = gitweb_get_feature('forks'); + my $check_forks = gitweb_check_feature('forks'); my @projects = fill_project_list_info($projlist, $check_forks); $order ||= $default_projects_order; @@ -3988,7 +4004,7 @@ sub git_project_list_body { @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @projects; } - my ($show_ctags) = gitweb_get_feature('ctags'); + my $show_ctags = gitweb_check_feature('ctags'); if ($show_ctags) { my %ctags; foreach my $p (@projects) { @@ -4428,7 +4444,7 @@ sub git_summary { my @taglist = git_get_tags_list(16); my @headlist = git_get_heads_list(16); my @forklist; - my ($check_forks) = gitweb_get_feature('forks'); + my $check_forks = gitweb_check_feature('forks'); if ($check_forks) { @forklist = git_get_projects_list($project); @@ -4457,7 +4473,7 @@ sub git_summary { } # Tag cloud - my ($show_ctags) = gitweb_get_feature('ctags'); + my $show_ctags = gitweb_check_feature('ctags'); if ($show_ctags) { my $ctags = git_get_project_ctags($project); my $cloud = git_populate_project_tagcloud($ctags); @@ -4559,7 +4575,7 @@ sub git_blame { my $fd; my $ftype; - gitweb_get_feature('blame')[0] + gitweb_check_feature('blame') or die_error(403, "Blame view not allowed"); die_error(400, "No file name given") unless $file_name; @@ -4747,7 +4763,7 @@ sub git_blob { $expires = "+1d"; } - my ($have_blame) = gitweb_get_feature('blame'); + my $have_blame = gitweb_check_feature('blame'); open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash or die_error(500, "Couldn't cat $file_name, $hash"); my $mimetype = blob_mimetype($fd, $file_name); @@ -4840,7 +4856,7 @@ sub git_tree { my $ref = format_ref_marker($refs, $hash_base); git_header_html(); my $basedir = ''; - my ($have_blame) = gitweb_get_feature('blame'); + my $have_blame = gitweb_check_feature('blame'); if (defined $hash_base && (my %co = parse_commit($hash_base))) { my @views_nav = (); if (defined $file_name) { @@ -5610,7 +5626,7 @@ sub git_history { } sub git_search { - gitweb_get_feature('search')[0] or die_error(403, "Search is disabled"); + gitweb_check_feature('search') or die_error(403, "Search is disabled"); if (!defined $searchtext) { die_error(400, "Text field is empty"); } @@ -5629,11 +5645,11 @@ sub git_search { if ($searchtype eq 'pickaxe') { # pickaxe may take all resources of your box and run for several minutes # with every query - so decide by yourself how public you make this feature - gitweb_get_feature('pickaxe')[0] + gitweb_check_feature('pickaxe') or die_error(403, "Pickaxe is disabled"); } if ($searchtype eq 'grep') { - gitweb_get_feature('grep')[0] + gitweb_check_feature('grep') or die_error(403, "Grep is disabled"); } @@ -5838,7 +5854,7 @@ insensitive).

commit
The commit messages and authorship information will be scanned for the given pattern.
EOT - my ($have_grep) = gitweb_get_feature('grep'); + my $have_grep = gitweb_check_feature('grep'); if ($have_grep) { print <grep @@ -5855,7 +5871,7 @@ EOT
committer
Name and e-mail of the committer and date of commit will be scanned for the given pattern.
EOT - my ($have_pickaxe) = gitweb_get_feature('pickaxe'); + my $have_pickaxe = gitweb_check_feature('pickaxe'); if ($have_pickaxe) { print <pickaxe @@ -5907,7 +5923,7 @@ sub git_shortlog { sub git_feed { my $format = shift || 'atom'; - my ($have_blame) = gitweb_get_feature('blame'); + my $have_blame = gitweb_check_feature('blame'); # Atom: http://www.atomenabled.org/developers/syndication/ # RSS: http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ -- cgit v1.3 From ff3c0ff20e2c0b2c78d2c2da9ce4eb0739ff6ced Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 2 Dec 2008 14:57:28 -0800 Subject: Update comment on gitweb_check/get_feature This is taken from a patch from Giuseppe but unfortunately it came too late to replace the series that was already on "next". The comment he updated here is better than the version we had previously, so I am cherry-picking this bit not to lose it. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index acc4cfdcda..2738643950 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -190,7 +190,9 @@ our %feature = ( # if there is no 'sub' key (no feature-sub), then feature cannot be # overriden # - # use gitweb_check_feature() to check if is enabled + # use gitweb_get_feature() to retrieve the value + # (an array) or gitweb_check_feature() to check if + # is enabled # Enable the 'blame' blob view, showing the last commit that modified # each line in the file. This can be very CPU-intensive. -- cgit v1.3 From 2dcb5e1ac87330b20962af9199a345eb378d3705 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 1 Dec 2008 19:01:42 +0100 Subject: gitweb: Fix handling of non-ASCII characters in inserted HTML files Use new insert_file() subroutine to insert HTML chunks from external files: $site_header, $home_text (by default indextext.html), $site_footer, and $projectroot/$project/REAME.html. All non-ASCII chars of those files will be broken by Perl IO layer without decoding to utf8, so insert_file() does to_utf8() on each printed line; alternate solution would be to open those files with "binmode $fh, ':utf8'", or even all files with "use open qw(:std :utf8)". Note that inserting README.html lost one of checks for simplicity. Noticed-by: Tatsuki Sugiura Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 933e137386..b92134b1c0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2740,6 +2740,15 @@ sub get_file_owner { return to_utf8($owner); } +# assume that file exists +sub insert_file { + my $filename = shift; + + open my $fd, '<', $filename; + print map(to_utf8, <$fd>); + close $fd; +} + ## ...................................................................... ## mimetype related functions @@ -2928,9 +2937,7 @@ EOF "\n"; if (-f $site_header) { - open (my $fd, $site_header); - print <$fd>; - close $fd; + insert_file($site_header); } print "
\n" . @@ -3017,9 +3024,7 @@ sub git_footer_html { print "
\n"; # class="page_footer" if (-f $site_footer) { - open (my $fd, $site_footer); - print <$fd>; - close $fd; + insert_file($site_footer); } print "\n" . @@ -4358,9 +4363,7 @@ sub git_project_list { git_header_html(); if (-f $home_text) { print "
\n"; - open (my $fd, $home_text); - print <$fd>; - close $fd; + insert_file($home_text); print "
\n"; } print $cgi->startform(-method => "get") . @@ -4472,13 +4475,10 @@ sub git_summary { print "
object" . $cgi->a({-class => "list", -href => href(action=>$tag{'type'}, hash=>$tag{'object'})}, @@ -4405,7 +4405,7 @@ sub git_tree { } git_print_page_path($file_name, 'tree', $hash_base); print "
\n"; - print "\n"; + print "
\n"; my $alternate = 1; # '..' (top directory) link if possible if (defined $hash_base && @@ -4627,7 +4627,7 @@ sub git_commit { git_print_header_div('tree', esc_html($co{'title'}) . $ref, $co{'tree'}, $hash); } print "
\n" . - "
\n"; + "
\n"; print "\n". "" . " - - - - - - -HTML - my @line_class = (qw(light dark)); - my $line_class_len = scalar (@line_class); - my $line_class_num = $#line_class; - while (my $line = <$fd>) { - my $long_rev; - my $short_rev; - my $author; - my $time; - my $lineno; - my $data; - my $age; - my $age_str; - my $age_class; - - chomp $line; - $line_class_num = ($line_class_num + 1) % $line_class_len; - - if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) [+-]\d\d\d\d\t(\d+)\)(.*)$/) { - $long_rev = $1; - $author = $2; - $time = $3; - $lineno = $4; - $data = $5; - } else { - print qq( \n); - next; - } - $short_rev = substr ($long_rev, 0, 8); - $age = time () - $time; - $age_str = age_string ($age); - $age_str =~ s/ / /g; - $age_class = age_class($age); - $author = esc_html ($author); - $author =~ s/ / /g; - - $data = untabify($data); - $data = esc_html ($data); - - print < - - - - - - -HTML - } # while (my $line = <$fd>) - print "
author" . esc_html($co{'author'}) . "
$ad{'rfc2822'}"; @@ -5226,7 +5226,7 @@ sub git_search { git_print_page_nav('','', $hash,$co{'tree'},$hash); git_print_header_div('commit', esc_html($co{'title'}), $hash); - print "\n"; + print "
\n"; my $alternate = 1; $/ = "\n"; my $git_command = git_cmd_str(); @@ -5293,7 +5293,7 @@ sub git_search { git_print_page_nav('','', $hash,$co{'tree'},$hash); git_print_header_div('commit', esc_html($co{'title'}), $hash); - print "
\n"; + print "
\n"; my $alternate = 1; my $matches = 0; $/ = "\n"; -- cgit v1.3 From 9d066745708b77ef917565d699d5d193bfb00fbd Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 19 Nov 2007 14:16:12 +0100 Subject: gitweb: Put project README in div.readme, fix its padding Put (optional) projects README on "summary" page in
element using "readme" class. This allow to style it using CSS. Add padding to project's README to make it line out with the rest of the page. Signed-off-by: Jakub Narebski --- gitweb/gitweb.css | 4 ++++ gitweb/gitweb.perl | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 17c60e4cb4..446a1c333b 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -85,6 +85,10 @@ div.title, a.title { color: #000000; } +div.readme { + padding: 8px; +} + a.title:hover { background-color: #d9d8d1; } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3d532dc7d7..491a3f41d2 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3912,8 +3912,10 @@ sub git_summary { if (-s "$projectroot/$project/README.html") { if (open my $fd, "$projectroot/$project/README.html") { - print "
readme
\n"; + print "
readme
\n" . + "
\n"; print $_ while (<$fd>); + print "\n
\n"; # class="readme" close $fd; } } -- cgit v1.3 From f1fe8f5c1eb30c3b1e13c425216253045f6ba2d1 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Mon, 26 Nov 2007 20:42:06 +0800 Subject: gitweb: the commitdiff is very commonly used, it's needed on search page, too Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 491a3f41d2..ff5daa7901 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3786,6 +3786,8 @@ sub git_search_grep_body { "
\n" . "\n"; -- cgit v1.3 From 61fd2552d89a15b005d36bab99e7172e1c85878b Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 3 Dec 2007 00:22:02 +0100 Subject: gitweb: Update and improve gitweb/README file Update list of build configuration variables, add references to gitweb/INSTALL, add description of runtime and per-repository runtime configuration. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/README | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 197 insertions(+), 18 deletions(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index 7186cede2f..b28f59f574 100644 --- a/gitweb/README +++ b/gitweb/README @@ -10,28 +10,96 @@ From the git version 1.4.0 gitweb is bundled with git. How to configure gitweb for your local system --------------------------------------------- +See also "Build time configuration" section in INSTALL +file for gitweb (in gitweb/INSTALL). + You can specify the following configuration variables when building GIT: + * GIT_BINDIR + Points out where to find git executable. You should set up it to + the place where git binary was installed (usually /usr/bin) if you + don't install git from sources together with gitweb. [Default: $(bindir)] * GITWEB_SITENAME - Shown in the title of all generated pages, defaults to the servers name. + Shown in the title of all generated pages, defaults to the server name + (SERVER_NAME CGI environment variable) if not set. [No default] * GITWEB_PROJECTROOT - The root directory for all projects shown by gitweb. + The root directory for all projects shown by gitweb. Must be set + correctly for gitweb to find repositories to display. See also + "Gitweb repositories" in INSTALL file for gitweb. [Default: /pub/git] + * GITWEB_PROJECT_MAXDEPTH + The filesystem traversing limit for getting projects list; the number + is taken as depth relative to the projectroot. It is used when + GITWEB_LIST is a directory (or is not set; then project root is used). + Is is meant to speed up project listing on large work trees by limiting + find depth. [Default: 2007] * GITWEB_LIST - points to a directory to scan for projects (defaults to project root) - or to a file for explicit listing of projects. + Points to a directory to scan for projects (defaults to project root + if not set / if empty) or to a file with explicit listing of projects + (together with projects' ownership). See "Generating projects list + using gitweb" in INSTALL file for gitweb to find out how to generate + such file from scan of a directory. [No default, which means use root + directory for projects] + * GITWEB_EXPORT_OK + Show repository only if this file exists (in repository). Only + effective if this variable evaluates to true. [No default / Not set] + * GITWEB_STRICT_EXPORT + Only allow viewing of repositories also shown on the overview page. + This for example makes GITWEB_EXPORT_OK to decide if repository is + available and not only if it is shown. If GITWEB_LIST points to + file with list of project, only those repositories listed would be + available for gitweb. [No default] * GITWEB_HOMETEXT - points to an .html file which is included on the gitweb project - overview page. + Points to an .html file which is included on the gitweb project + overview page ('projects_list' view), if it exists. Relative to + gitweb.cgi script. [Default: indextext.html] + * GITWEB_SITE_HEADER + Filename of html text to include at top of each page. Relative to + gitweb.cgi script. [No default] + * GITWEB_SITE_FOOTER + Filename of html text to include at bottom of each page. Relative to + gitweb.cgi script. [No default] + * GITWEB_HOME_LINK_STR + String of the home link on top of all pages, leading to $home_link + (usually main gitweb page, which means projects list). Used as first + part of gitweb view "breadcrumb trail": / / . + [Default: projects] + * GITWEB_SITENAME + Name of your site or organization to appear in page titles. Set it + to something descriptive for clearer bookmarks etc. If not set + (if empty) gitweb uses "$SERVER_NAME Git", or "Untitled Git" if + SERVER_NAME CGI environment variable is not set (e.g. if running + gitweb as standalone script). [No default] + * GITWEB_BASE_URL + Git base URLs used for URL to where fetch project from, i.e. full + URL is "$git_base_url/$project". Shown on projects summary page. + Repository URL for project can be also configured per repository; this + takes precendence over URL composed from base URL and project name. + Note that you can setup multiple base URLs (for example one for + git:// protocol access, one for http:// access) from gitweb config + file. [No default] * GITWEB_CSS - Points to the location where you put gitweb.css on your web server. + Points to the location where you put gitweb.css on your web server + (or to be more generic URI of gitweb stylesheet). Relative to base + URI of gitweb. Note that you can setup multiple stylesheets from + gitweb config file. [Default: gitweb.css] * GITWEB_LOGO - Points to the location where you put git-logo.png on your web server. + Points to the location where you put git-logo.png on your web server + (or to be more generic URI of logo, 72x27 size, displayed in top right + corner of each gitweb page, and used as logo for Atom feed). Relative + to base URI of gitweb. [Default: git-logo.png] + * GITWEB_FAVICON + Points to the location where you put git-favicon.png on your web server + (or to be more generic URI of favicon, assumed to be image/png type; + web browsers that support favicons (website icons) may display them + in the browser's URL bar and next to site name in bookmarks). Relative + to base URI of gitweb. [Default: git-favicon.png] * GITWEB_CONFIG - This file will be loaded using 'require' and can be used to override any - of the options above as well as some other options - see the top of - 'gitweb.cgi' for their full list and description. If the environment - $GITWEB_CONFIG is set when gitweb.cgi is executed the file in the - environment variable will be loaded instead of the file - specified when gitweb.cgi was created. + This Perl file will be loaded using 'do' and can be used to override any + of the options above as well as some other options -- see the "Runtime + gitweb configuration" section below, and top of 'gitweb.cgi' for their + full list and description. If the environment variable GITWEB_CONFIG + is set when gitweb.cgi is executed, then the file specified in the + environment variable will be loaded instead of the file specified + when gitweb.cgi was created. [Default: gitweb_config.perl] Runtime gitweb configuration @@ -39,11 +107,122 @@ Runtime gitweb configuration You can adjust gitweb behaviour using the file specified in `GITWEB_CONFIG` (defaults to 'gitweb_config.perl' in the same directory as the CGI). -See the top of 'gitweb.cgi' for the list of variables and some description. The most notable thing that is not configurable at compile time are the -optional features, stored in the '%features' variable. You can find further -description on how to reconfigure the default features setting in your -`GITWEB_CONFIG` or per-project in `project.git/config` inside 'gitweb.cgi'. +optional features, stored in the '%features' variable. + +Ultimate description on how to reconfigure the default features setting +in your `GITWEB_CONFIG` or per-project in `project.git/config` can be found +as comments inside 'gitweb.cgi'. + +See also "Gitweb config file" (with example of gitweb config file), and +"Gitweb repositories" sections in INSTALL file for gitweb. + + +Gitweb config file is [fragment] of perl code. You can set variables +using "our $variable = value"; text from "#" character until the end +of a line is ignored. See perlsyn(1) man page for details. + +Below there is list of vaiables which you might want to set in gitweb config. +See the top of 'gitweb.cgi' for the full list of variables and their +descriptions. + +Gitweb config file variables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can set, among others, the following variables in gitweb config files: + * $GIT + Cure git executable to use. By default set to "$GIT_BINDIR/git", which + in turn is by default set to "$(bindir)/git". If you use git from binary + package, set this to "/usr/bin/git". This can just be "git" if your + webserver has a sensible PATH. If you have multiple git versions + installed it is / can be used to choose which one to use. + * $version + Gitweb version, set automatically when creating gitweb.cgi from + gitweb.perl. You might want to modify it if you are running modified + gitweb. + * $my_url, $my_uri + URL and absolute URL of gitweb script; you might need to set those + variables if you are using 'pathinfo' feature: see also below. + * $home_link + Target of the home link on top of all pages (the first part of view + "breadcrumbs"). By default set to absolute URI of a page; you might + need to set it up to [base] gitweb URI if you use 'pathinfo' feature + (alternative format of the URLs, with project name embedded directly + in the path part of URL). + * @stylesheets + List of URIs of stylesheets (relative to base URI of a page). You + might specify more than one stylesheet, for example use gitweb.css + as base, with site specific modifications in separate stylesheet + to make it easier to upgrade gitweb. You can add 'site' stylesheet + for example by using + push @stylesheets, "gitweb-site.css"; + in gitweb config file. + * $logo_url, $logo_label + URI and label (title) of GIT logo link (or your site logo, if you choose + to use different logo image). By default they point to git homepage; + in the past they pointed to git documentation at www.kernel.org. + * $projects_list_description_width + The width (in characters) of the projects list "Description" column. + Longer descriptions will be cut (trying to cut at word boundary); + full description is available as 'title' attribute (usually shown on + mouseover). By default set to 25, which might be too small if you + use long project descriptions. + * @git_base_url_list + List of git base URLs used for URL to where fetch project from, shown + in project summary page. Full URL is "$git_base_url/$project". + You can setup multiple base URLs (for example one for git:// protocol + access, and one for http:// "dumb" protocol access). Note that per + repository configuration in 'cloneurl' file, or as values of gitweb.url + project config. + * $default_blob_plain_mimetype + Default mimetype for blob_plain (raw) view, if mimetype checking + doesn't result in some other type; by default 'text/plain'. + * $default_text_plain_charset + Default charset for text files. If not set, web serwer configuration + would be used. + * $mimetypes_file + File to use for (filename extension based) guessing of MIME types before + trying /etc/mime.types. Path, if relative, is taken currently as taken + relative to current git repositoy. + * $fallback_encoding + Gitweb assumes this charset if line contains non-UTF-8 characters. + Fallback decoding is used without error checking, so it can be even + 'utf-8'. Value mist be valid encodig; see Encoding::Supported(3pm) man + page for a list. By default 'latin1', aka. 'iso-8859-1'. + * @diff_opts + Rename detection options for git-diff and git-diff-tree. By default + ('-M'); set it to ('-C') or ('-C', '-C') to also detect copies, or + set it to () if you don't want to have renames detection. + +Per-repository gitweb configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can also configure individual repositories shown in gitweb by creating +file in the GIT_DIR of git repository, or by setting some repo configuration +variable (in GIT_DIR/config). + +You can use the following files in repository: + * README.html + A .html file (HTML fragment) which is included on the gitweb project + summary page inside
block element. You can use it for longer + description of a project, to provide links for example to projects + homepage, etc. + * description (or gitweb.description) + Short (shortened by default to 25 characters in the projects list page) + single line description of a project (of a repository). Plain text file; + HTML will be escaped. By default set to + Unnamed repository; edit this file to name it for gitweb. + from the template during creating repository. You can use + gitweb.description repo configuration variable, but the file takes + precendence. + * cloneurl (or multiple-valued gitweb.url) + File with repository URL (used for clone and fetch), one per line. + Displayed in the project summary page. You can use multiple-valued + gitweb.url repository configuration variable for that, but the file + takes precendence. + * various gitweb.* config variables (in config) + Read description of %feature hash for detailed list, and some + descriptions. Webserver configuration -- cgit v1.3 From e5d3de5c457d1a82c921b9bf2cd9a962970ce30e Mon Sep 17 00:00:00 2001 From: İsmail Dönmez Date: Tue, 4 Dec 2007 10:55:41 +0200 Subject: gitweb: use Perl built-in utf8 function for UTF-8 decoding. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: İsmail Dönmez Tested-by: Martin Koegler Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ff5daa7901..24b31582af 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -695,10 +695,9 @@ sub validate_refname { # in utf-8 thanks to "binmode STDOUT, ':utf8'" at beginning sub to_utf8 { my $str = shift; - my $res; - eval { $res = decode_utf8($str, Encode::FB_CROAK); }; - if (defined $res) { - return $res; + if (utf8::valid($str)) { + utf8::decode($str); + return $str; } else { return decode($fallback_encoding, $str, Encode::FB_DEFAULT); } -- cgit v1.3 From bf901f8e748144a19d057d9d00582417d480c795 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 15 Dec 2007 15:40:28 +0100 Subject: gitweb: disambiguate heads and tags withs the same name Avoid wrong disambiguation that would link logs/trees of tags and heads which share the same name to the same page, leading to a disambiguation that would prefer the tag, thus making it impossible to access the corresponding head log and tree without hacking the url by hand. It does it by using full refname (with 'refs/heads/' or 'refs/tags/' prefix) instead of shortened one in the URLs in 'heads' and 'tags' tables. This makes URLs (and refs) provided by gitweb unambiguous. Signed-off-by: Guillaume Seguin Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 24b31582af..32c1907021 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2233,6 +2233,7 @@ sub git_get_heads_list { my ($hash, $name, $title) = split(' ', $refinfo, 3); my ($committer, $epoch, $tz) = ($committerinfo =~ /^(.*) ([0-9]+) (.*)$/); + $ref_item{'fullname'} = $name; $name =~ s!^refs/heads/!!; $ref_item{'name'} = $name; @@ -2270,6 +2271,7 @@ sub git_get_tags_list { my ($id, $type, $name, $refid, $reftype, $title) = split(' ', $refinfo, 6); my ($creator, $epoch, $tz) = ($creatorinfo =~ /^(.*) ([0-9]+) (.*)$/); + $ref_item{'fullname'} = $name; $name =~ s!^refs/tags/!!; $ref_item{'type'} = $type; @@ -3690,8 +3692,8 @@ sub git_tags_body { "
\n" . ($curr ? "\n" . "\n" . ""; } -- cgit v1.3 From dfa7c7d221d05499063f9bf95f507af8a882bfeb Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 15 Dec 2007 15:41:49 +0100 Subject: gitweb: Teach "a=blob" action to be more lenient about blob/file mime type Since 930cf7dd7cc6b87d173f182230763e1f1913d319 'blob' action knows the file type; if the file type is not "text/*" or one of common network image formats/mimetypes (gif, png, jpeg) then the action "blob" defaulted to "blob_plain". This caused the problem if mimetypes file was not well suited for web, for example returning "application/x-sh" for "*.sh" shell scripts, instead of "text/plain" (or other "text/*"). Now "blob" action defaults to "blob_plain" ('raw' view) only if file is of type which is neither "text/*" nor "image/{gif,png,jpeg}" AND it is binary file. Otherwise it assumes that it can be displayed either in tag ("image/*" mimetype), or can be displayed line by line (otherwise). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 32c1907021..2a0c46c234 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4290,7 +4290,7 @@ sub git_blob { open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash or die_error(undef, "Couldn't cat $file_name, $hash"); my $mimetype = blob_mimetype($fd, $file_name); - if ($mimetype !~ m!^(?:text/|image/(?:gif|png|jpeg)$)!) { + if ($mimetype !~ m!^(?:text/|image/(?:gif|png|jpeg)$)! && -B $fd) { close $fd; return git_blob_plain($mimetype); } @@ -4331,16 +4331,7 @@ sub git_blob { } git_print_page_path($file_name, "blob", $hash_base); print "
\n"; - if ($mimetype =~ m!^text/!) { - my $nr; - while (my $line = <$fd>) { - chomp $line; - $nr++; - $line = untabify($line); - printf "
%4i %s
\n", - $nr, $nr, $nr, esc_html($line, -nbsp=>1); - } - } elsif ($mimetype =~ m!^image/!) { + if ($mimetype =~ m!^image/!) { print qq!$file_name"blob_plain", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name) . qq!" />\n!; + } else { + my $nr; + while (my $line = <$fd>) { + chomp $line; + $nr++; + $line = untabify($line); + printf "
%4i %s
\n", + $nr, $nr, $nr, esc_html($line, -nbsp=>1); + } } close $fd or print "Reading blob failed.\n"; -- cgit v1.3 From bc8b95ae4a4b21753e84bbfd28cbcbf1b3f6e0a8 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sat, 8 Dec 2007 12:30:59 +0100 Subject: gitweb: Make config_to_multi return [] instead of [undef] This is important for the list of clone urls, where if there are no per-repository clone URL configured, the default base URLs are never used for URL construction without this patch. Add tests for different ways of setting project URLs, just in case. Note that those tests in current form wouldn't detect breakage fixed by this patch, as it only checks for errors and not for expected output. Signed-off-by: Petr Baudis Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- t/t9500-gitweb-standalone-no-errors.sh | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 2a0c46c234..28bb8c3933 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1511,7 +1511,7 @@ sub config_to_int { sub config_to_multi { my $val = shift; - return ref($val) ? $val : [ $val ]; + return ref($val) ? $val : (defined($val) ? [ $val ] : []); } sub git_get_project_config { diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 35fff3ddba..796cd7dba0 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -557,6 +557,31 @@ test_expect_success \ 'gitweb_run "p=.git;a=tree;opt=--no-merges"' test_debug 'cat gitweb.log' +# ---------------------------------------------------------------------- +# testing config_to_multi / cloneurl + +test_expect_success \ + 'URL: no project URLs, no base URL' \ + 'gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'URL: project URLs via gitweb.url' \ + 'git config --add gitweb.url git://example.com/git/trash.git && + git config --add gitweb.url http://example.com/git/trash.git && + gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + +cat >.git/cloneurl <<\EOF +git://example.com/git/trash.git +http://example.com/git/trash.git +EOF + +test_expect_success \ + 'URL: project URLs via cloneurl file' \ + 'gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + # ---------------------------------------------------------------------- # gitweb config and repo config -- cgit v1.3 From d76a585d83aeb6910e7eb10d36b406dc27202675 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 20 Dec 2007 10:48:09 +0100 Subject: gitweb: fix whitespace in config_to_multi (indent with tab) Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 28bb8c3933..6256641ace 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1511,7 +1511,7 @@ sub config_to_int { sub config_to_multi { my $val = shift; - return ref($val) ? $val : (defined($val) ? [ $val ] : []); + return ref($val) ? $val : (defined($val) ? [ $val ] : []); } sub git_get_project_config { -- cgit v1.3 From 7720224cebde08186627ab7bdb06018905d84e30 Mon Sep 17 00:00:00 2001 From: Yasushi SHOJI Date: Tue, 29 Jan 2008 21:16:02 +0900 Subject: gitweb: Convert generated contents to utf8 in commitdiff_plain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the commit message, or commit author contains non-ascii, it must be converted from Perl internal representation to utf-8, to follow what got declared in HTTP header. Use to_utf8() to do the conversion. This necessarily replaces here-doc with "print" statements. Signed-off-by: Yasushi SHOJI Acked-by: İsmail Dönmez Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6256641ace..80e3d0ac47 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5048,16 +5048,15 @@ sub git_commitdiff { -expires => $expires, -content_disposition => 'inline; filename="' . "$filename" . '"'); my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'}); - print <self_url() . "\n\n"; foreach my $line (@{$co{'comment'}}) { - print "$line\n"; + print to_utf8($line) . "\n"; } print "---\n\n"; } -- cgit v1.3 From d661146ac2ada526e80dbb6234f8f8da6642ffcb Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 29 Jan 2008 20:52:32 +0100 Subject: gitweb: Add info about $projectroot and $projects_list to gitweb/README Those two configuration variables are important enough that it is worth to explicitely write about them in the "Gitweb config file variables" section even if they are usually set during build by GITWEB_PROJECTROOT and GITWEB_LIST build (Makefile) configuration variables. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/README | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index b28f59f574..4c8bedf744 100644 --- a/gitweb/README +++ b/gitweb/README @@ -129,17 +129,30 @@ descriptions. Gitweb config file variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can set, among others, the following variables in gitweb config files: +You can set, among others, the following variables in gitweb config files +(with the exception of $projectroot and $projects_list this list does +not include variables usually directly set during build): * $GIT Cure git executable to use. By default set to "$GIT_BINDIR/git", which in turn is by default set to "$(bindir)/git". If you use git from binary package, set this to "/usr/bin/git". This can just be "git" if your webserver has a sensible PATH. If you have multiple git versions - installed it is / can be used to choose which one to use. + installed it can be used to choose which one to use. * $version Gitweb version, set automatically when creating gitweb.cgi from gitweb.perl. You might want to modify it if you are running modified gitweb. + * $projectroot + Absolute filesystem path which will be prepended to project path; + the path to repository is $projectroot/$project. Set to + $GITWEB_PROJECTROOT during installation. This variable have to be + set correctly for gitweb to find repositories. + * $projects_list + Source of projects list, either directory to scan, or text file + with list of repositories (in the " SPC + " format). Set to $GITWEB_LIST + during installation. If empty, $projectroot is used to scan for + repositories. * $my_url, $my_uri URL and absolute URL of gitweb script; you might need to set those variables if you are using 'pathinfo' feature: see also below. -- cgit v1.3 From c1dcf7ebf222e7c24b89b40bc00a6ca5e9e2eec6 Mon Sep 17 00:00:00 2001 From: Bruno Ribas Date: Wed, 30 Jan 2008 03:37:56 -0200 Subject: gitweb: Make use of the $git_dir variable at sub git_get_project_description Signed-off-by: Bruno Ribas Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 80e3d0ac47..ae2d05763f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1606,7 +1606,7 @@ sub git_get_project_description { my $path = shift; $git_dir = "$projectroot/$path"; - open my $fd, "$projectroot/$path/description" + open my $fd, "$git_dir/description" or return git_get_project_config('description'); my $descr = <$fd>; close $fd; -- cgit v1.3 From e62a641de17b172ffc4d3a803085c8afbfbec3d1 Mon Sep 17 00:00:00 2001 From: Florian La Roche Date: Sun, 3 Feb 2008 12:38:46 +0100 Subject: gitweb: Make feed entries point to commitdiff view Change feeds entries (feeds items) from pointing (linking) to 'commit' view to pointing to 'commitdiff' view. First, feed entries have whatchanged-like list of files which were modified in a commit, so 'commitdiff' view more naturally reflects feed entry (is more naturally alternate / extended version of a feed item). Second, this way the patches are shown directly and code review is done more easily via watching feeds. [jn: Rewritten commit message] Signed-off-by: Florian La Roche Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ae2d05763f..8ef2735c58 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5565,7 +5565,7 @@ XML or next; # print element (entry, item) - my $co_url = href(-full=>1, action=>"commit", hash=>$commit); + my $co_url = href(-full=>1, action=>"commitdiff", hash=>$commit); if ($format eq 'rss') { print "\n" . "" . esc_html($co{'title'}) . "\n" . -- cgit v1.3 From 201945eeb3b52400e16bb36bf60c56a849c62f32 Mon Sep 17 00:00:00 2001 From: Bruno Ribas Date: Wed, 6 Feb 2008 15:15:12 -0200 Subject: gitweb: Make use of the $git_dir variable at sub git_get_project_url_list Signed-off-by: Bruno Ribas Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8ef2735c58..5e88637b5e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1620,7 +1620,7 @@ sub git_get_project_url_list { my $path = shift; $git_dir = "$projectroot/$path"; - open my $fd, "$projectroot/$path/cloneurl" + open my $fd, "$git_dir/cloneurl" or return wantarray ? @{ config_to_multi(git_get_project_config('url')) } : config_to_multi(git_get_project_config('url')); -- cgit v1.3 From b59012ef4e7dde1895d988736c7df64f68b1e940 Mon Sep 17 00:00:00 2001 From: Bruno Ribas Date: Fri, 8 Feb 2008 14:38:04 -0200 Subject: gitweb: Use the config file to set repository owner's name. Now gitweb checks if gitweb.owner exists before trying to get filesystem's owner. Allow to use configuration variable gitweb.owner set the repository owner, it checks the gitweb.owner, if not set it uses filesystem directory's owner. Useful when we don't want to maintain project list file, and all repository directories have to have the same owner (for example when the same SSH account is shared for all projects, using ssh_acl to control access instead). Signed-off-by: Bruno Ribas Signed-off-by: Junio C Hamano --- gitweb/README | 4 ++++ gitweb/gitweb.perl | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index 4c8bedf744..2163071047 100644 --- a/gitweb/README +++ b/gitweb/README @@ -233,6 +233,10 @@ You can use the following files in repository: Displayed in the project summary page. You can use multiple-valued gitweb.url repository configuration variable for that, but the file takes precendence. + * gitweb.owner + You can use the gitweb.owner repository configuration variable to set + repository's owner. It is displayed in the project list and summary + page. If it's not set, filesystem directory's owner is used. * various gitweb.* config variables (in config) Read description of %feature hash for detailed list, and some descriptions. diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8ef2735c58..c8fe22a961 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1759,6 +1759,7 @@ sub git_get_project_owner { my $owner; return undef unless $project; + $git_dir = "$projectroot/$project"; if (!defined $gitweb_project_owner) { git_get_project_list_from_file(); @@ -1767,8 +1768,11 @@ sub git_get_project_owner { if (exists $gitweb_project_owner->{$project}) { $owner = $gitweb_project_owner->{$project}; } + if (!defined $owner){ + $owner = git_get_project_config('owner'); + } if (!defined $owner) { - $owner = get_file_owner("$projectroot/$project"); + $owner = get_file_owner("$git_dir"); } return $owner; -- cgit v1.3 From 850b90a51d5ed122cee5c2f3ad4c3e513a05259a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 16 Feb 2008 23:07:46 +0100 Subject: gitweb: Fix displaying unchopped argument in chop_and_escape_str Do not use esc_html to escape [title] _attribute_ of a HTML element, and quote unprintable characters. Replace unprintable characters by '?' and use CGI method to generate HTML element and do the escaping. This caused bug noticed by Martin Koegler, Message-ID: <20080216130037.GA14571@auto.tuwien.ac.at> that for bad commit encoding in author name, the title attribute (here to show full, not shortened name) had embedded HTML code in it, result of quoting unprintable characters the gitweb/HTML way. This of course broke the HTML, causing page being not displayed in XML validating web browsers. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5e88637b5e..47e3a41346 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -866,8 +866,8 @@ sub chop_and_escape_str { if ($chopped eq $str) { return esc_html($chopped); } else { - return qq{} . - esc_html($chopped) . qq{}; + $str =~ s/([[:cntrl:]])/?/g; + return $cgi->span({-title=>$str}, esc_html($chopped)); } } -- cgit v1.3 From c84c483ffdfc45d8143fd6f6620361aba91d1080 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 17 Feb 2008 18:48:13 +0100 Subject: gitweb: Add new option -nohtml to quot_xxx subroutines Add support for new option -nohtml to quot_cec and quot_upr subroutines, to have output not wrapped in HTML tags. This makes those subroutines suitable to quoting attributes values, and for plain text output quoting. Currently this API is not used yet. While at it fix whitespace, and use ';' as delimiter, not separator. The option to not wrap quot_cec output in HTML tag were proposed originally in patch: "Don't open a XML tag while another one is already open" Message-ID: <20080216191628.GK30676@schiele.dyndns.org> by Robert Schiele. Originally the parameter was named '-notag', was also supportted by esc_html (but not esc_path) which passed it down to quot_cec. Mentioned patch was meant to fix the bug Martin Koegler reported in his mail "Invalid html output repo.or.cz (alt-git.git)" Message-ID: <20080216130037.GA14571@auto.tuwien.ac.at> which was fixed in different way (do not use esc_html to escape and quote HTML attributes). Signed-off-by: Robert Schiele Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 47e3a41346..8779ca8174 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -753,29 +753,40 @@ sub esc_path { # Make control characters "printable", using character escape codes (CEC) sub quot_cec { my $cntrl = shift; + my %opts = @_; my %es = ( # character escape codes, aka escape sequences - "\t" => '\t', # tab (HT) - "\n" => '\n', # line feed (LF) - "\r" => '\r', # carrige return (CR) - "\f" => '\f', # form feed (FF) - "\b" => '\b', # backspace (BS) - "\a" => '\a', # alarm (bell) (BEL) - "\e" => '\e', # escape (ESC) - "\013" => '\v', # vertical tab (VT) - "\000" => '\0', # nul character (NUL) - ); + "\t" => '\t', # tab (HT) + "\n" => '\n', # line feed (LF) + "\r" => '\r', # carrige return (CR) + "\f" => '\f', # form feed (FF) + "\b" => '\b', # backspace (BS) + "\a" => '\a', # alarm (bell) (BEL) + "\e" => '\e', # escape (ESC) + "\013" => '\v', # vertical tab (VT) + "\000" => '\0', # nul character (NUL) + ); my $chr = ( (exists $es{$cntrl}) ? $es{$cntrl} : sprintf('\%03o', ord($cntrl)) ); - return "$chr"; + if ($opts{-nohtml}) { + return $chr; + } else { + return "$chr"; + } } # Alternatively use unicode control pictures codepoints, # Unicode "printable representation" (PR) sub quot_upr { my $cntrl = shift; + my %opts = @_; + my $chr = sprintf('&#%04d;', 0x2400+ord($cntrl)); - return "$chr"; + if ($opts{-nohtml}) { + return $chr; + } else { + return "$chr"; + } } # git may return quoted and escaped filenames @@ -800,7 +811,7 @@ sub unquote { return chr(oct($seq)); } elsif (exists $es{$seq}) { # C escape sequence, aka character escape code - return $es{$seq} + return $es{$seq}; } # quoted ordinary character return $seq; -- cgit v1.3 From afa9b620f9432491a453d752e8bf62860d7834c0 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 14 Feb 2008 09:22:30 +0100 Subject: gitweb: Fix bug in href(..., -replay=>1) when using 'pathinfo' form URLs generated by href(..., -replay=>1) (which includes 'next page' links and alternate view links) didn't set project info correctly when current page URL is in pathinfo form. This resulted in broken links such like: http://www.example.com/w/ARRAY(0x85a5318)?a=shortlog;pg=1 if the 'pathinfo' feature was used, or http://www.example.com/w/?a=shortlog;pg=1 if it wasn't, instead of correct: http://www.example.com/w/project.git?a=shortlog;pg=1 This was caused by the fact that href() always replays params in the arrayref form, were they multivalued or singlevalued, and the code dealing with 'pathinfo' feature couldn't deal with $params{'project'} being arrayref. Setting $params{'project'} is moved before replaying params; this ensures that 'project' parameter is processed correctly. Noticed-by: Peter Oberndorfer Noticed-by: Wincent Colaiuta Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8008260f6b..8ed6d04417 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -611,6 +611,8 @@ sub href(%) { ); my %mapping = @mapping; + $params{'project'} = $project unless exists $params{'project'}; + if ($params{-replay}) { while (my ($name, $symbol) = each %mapping) { if (!exists $params{$name}) { @@ -620,8 +622,6 @@ sub href(%) { } } - $params{'project'} = $project unless exists $params{'project'}; - my ($use_pathinfo) = gitweb_check_feature('pathinfo'); if ($use_pathinfo) { # use PATH_INFO for project name -- cgit v1.3 From be8b9063810f0c47f825c47045c7ca137f520edb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 22 Feb 2008 17:33:47 +0100 Subject: gitweb: Better chopping in commit search results When searching commit messages (commit search), if matched string is too long, the generated HTML was munged leading to an ill-formed XHTML document. Now gitweb chop leading, trailing and matched parts, HTML escapes those parts, then composes and marks up match info. HTML output is never chopped. Limiting matched info to 80 columns (with slop) is now done by dividing remaining characters after chopping match equally to leading and trailing part, not by chopping composed and HTML marked output. Noticed-by: Jean-Baptiste Quenot Signed-off-by: Junio C Hamano Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8ed6d04417..326e27cf88 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3784,18 +3784,24 @@ sub git_search_grep_body { print "
\n" . "\n" . "\n" . -- cgit v1.3 From 9d561ad324fc8942919981f2c80360e22896989c Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 23 Feb 2008 22:37:08 +0100 Subject: gitweb: Fix bugs in git_search_grep_body: it's length(), not len() Use int(/2) to get integer value for a substring length. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 326e27cf88..e8226b16f4 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3792,7 +3792,7 @@ sub git_search_grep_body { if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { my ($lead, $match, $trail) = ($1, $2, $3); $match = chop_str($match, 70, 5); # in case match is very long - my $contextlen = (80 - len($match))/2; # is left for the remainder + my $contextlen = int((80 - length($match))/2); # for the remainder $contextlen = 30 if ($contextlen > 30); # but not too much $lead = chop_str($lead, $contextlen, 10); $trail = chop_str($trail, $contextlen, 10); -- cgit v1.3 From b8d97d07fd5025232cae74cfc9a555abd9ac390e Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 25 Feb 2008 21:07:57 +0100 Subject: gitweb: Better cutting matched string and its context Improve look of commit search output ('search' view) by better cutting of matched string and its context in match info, as suggested by Junio. For example, if you are looking for "very long search string" in the following line: Could somebody test this with very long search string, and see how you would now see: ...this with <>, and see... instead of: Could som... <>, and see... (where <> denotes emphasized / colored fragment; matched fragment to be more exact). For this feature, support for fourth [optional] parameter to chop_str subroutine was added. This fourth parameter is used to denote where to cut string to make it shorter. chop_str can now cut at the beginning (from the _left_ side of the string), in the middle (_center_ of the string), or at the end (from the _right_ side of the string); cutting from right is the default: chop_str(somestring, len, slop, 'left') -> ' ...string' chop_str(somestring, len, slop, 'center') -> 'som ... ing' chop_str(somestring, len, slop, 'right') -> 'somestr... ' If you want to use default slop (default additional length), use undef as value for third parameter to chop_str. While at it, return from chop_str early if given string is so short that chop_str couldn't shorten it. Simplify also regexp used by chop_str. Make ellipsis (dots) stick to shortened fragment for cutting at ends, to better see which part got shortened. Simplify passing all arguments to chop_str in chop_and_escape_str subroutine. This was needed to pass additional options to chop_str. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 73 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 16 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e8226b16f4..fc95e2ca85 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -848,32 +848,73 @@ sub project_in_list { ## ---------------------------------------------------------------------- ## HTML aware string manipulation +# Try to chop given string on a word boundary between position +# $len and $len+$add_len. If there is no word boundary there, +# chop at $len+$add_len. Do not chop if chopped part plus ellipsis +# (marking chopped part) would be longer than given string. sub chop_str { my $str = shift; my $len = shift; my $add_len = shift || 10; + my $where = shift || 'right'; # 'left' | 'center' | 'right' # allow only $len chars, but don't cut a word if it would fit in $add_len # if it doesn't fit, cut it if it's still longer than the dots we would add - $str =~ m/^(.{0,$len}[^ \/\-_:\.@]{0,$add_len})(.*)/; - my $body = $1; - my $tail = $2; - if (length($tail) > 4) { - $tail = " ..."; - $body =~ s/&[^;]*$//; # remove chopped character entities + # remove chopped character entities entirely + + # when chopping in the middle, distribute $len into left and right part + # return early if chopping wouldn't make string shorter + if ($where eq 'center') { + return $str if ($len + 5 >= length($str)); # filler is length 5 + $len = int($len/2); + } else { + return $str if ($len + 4 >= length($str)); # filler is length 4 + } + + # regexps: ending and beginning with word part up to $add_len + my $endre = qr/.{$len}\w{0,$add_len}/; + my $begre = qr/\w{0,$add_len}.{$len}/; + + if ($where eq 'left') { + $str =~ m/^(.*?)($begre)$/; + my ($lead, $body) = ($1, $2); + if (length($lead) > 4) { + $body =~ s/^[^;]*;// if ($lead =~ m/&[^;]*$/); + $lead = " ..."; + } + return "$lead$body"; + + } elsif ($where eq 'center') { + $str =~ m/^($endre)(.*)$/; + my ($left, $str) = ($1, $2); + $str =~ m/^(.*?)($begre)$/; + my ($mid, $right) = ($1, $2); + if (length($mid) > 5) { + $left =~ s/&[^;]*$//; + $right =~ s/^[^;]*;// if ($mid =~ m/&[^;]*$/); + $mid = " ... "; + } + return "$left$mid$right"; + + } else { + $str =~ m/^($endre)(.*)$/; + my $body = $1; + my $tail = $2; + if (length($tail) > 4) { + $body =~ s/&[^;]*$//; + $tail = "... "; + } + return "$body$tail"; } - return "$body$tail"; } # takes the same arguments as chop_str, but also wraps a around the # result with a title attribute if it does get chopped. Additionally, the # string is HTML-escaped. sub chop_and_escape_str { - my $str = shift; - my $len = shift; - my $add_len = shift || 10; + my ($str) = @_; - my $chopped = chop_str($str, $len, $add_len); + my $chopped = chop_str(@_); if ($chopped eq $str) { return esc_html($chopped); } else { @@ -3791,11 +3832,11 @@ sub git_search_grep_body { foreach my $line (@$comment) { if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { my ($lead, $match, $trail) = ($1, $2, $3); - $match = chop_str($match, 70, 5); # in case match is very long - my $contextlen = int((80 - length($match))/2); # for the remainder - $contextlen = 30 if ($contextlen > 30); # but not too much - $lead = chop_str($lead, $contextlen, 10); - $trail = chop_str($trail, $contextlen, 10); + $match = chop_str($match, 70, 5, 'center'); + my $contextlen = int((80 - length($match))/2); + $contextlen = 30 if ($contextlen > 30); + $lead = chop_str($lead, $contextlen, 10, 'left'); + $trail = chop_str($trail, $contextlen, 10, 'right'); $lead = esc_html($lead); $match = esc_html($match); -- cgit v1.3 From 311e552e7674be620bd930ddada307c15140c6ac Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 26 Feb 2008 13:22:06 +0100 Subject: gitweb: Change parse_commits signature to allow for multiple options Change order of parameters in parse_commits() to have $filename before @args (extra options), to allow for multiple extra options, for example both '--grep=' and '--fixed-strings'. Change all callers to follow new calling convention. Originally by Petr Baudis, in http://repo.or.cz/git/gitweb.git: b98f0a7c gitweb: Clearly distinguish regexp / exact match searches Signed-off-by: Petr Baudis Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index fc95e2ca85..3b4b15a5f0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2079,7 +2079,7 @@ sub parse_commit { } sub parse_commits { - my ($commit_id, $maxcount, $skip, $arg, $filename) = @_; + my ($commit_id, $maxcount, $skip, $filename, @args) = @_; my @cos; $maxcount ||= 1; @@ -2089,7 +2089,7 @@ sub parse_commits { open my $fd, "-|", git_cmd(), "rev-list", "--header", - ($arg ? ($arg) : ()), + @args, ("--max-count=" . $maxcount), ("--skip=" . $skip), @extra_options, @@ -5172,7 +5172,7 @@ sub git_history { $ftype = git_get_type($hash); } - my @commitlist = parse_commits($hash_base, 101, (100 * $page), "--full-history", $file_name); + my @commitlist = parse_commits($hash_base, 101, (100 * $page), $file_name, "--full-history"); my $paging_nav = ''; if ($page > 0) { @@ -5255,7 +5255,7 @@ sub git_search { $greptype = "--committer="; } $greptype .= $search_regexp; - my @commitlist = parse_commits($hash, 101, (100 * $page), $greptype); + my @commitlist = parse_commits($hash, 101, (100 * $page), undef, $greptype); my $paging_nav = ''; if ($page > 0) { @@ -5507,7 +5507,7 @@ sub git_feed { # log/feed of current (HEAD) branch, log of given branch, history of file/directory my $head = $hash || 'HEAD'; - my @commitlist = parse_commits($head, 150, 0, undef, $file_name); + my @commitlist = parse_commits($head, 150, 0, $file_name); my %latest_commit; my %latest_date; -- cgit v1.3 From 0270cd0eeaff06f6bee1b52d5cdffb1a6e69c15a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 26 Feb 2008 13:22:07 +0100 Subject: gitweb: Simplify fixed string search Use '--fixed-strings' option to git-rev-list to simplify and improve searching commit messages (commit search). It allows to search for example for "don't" successfully from gitweb. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3b4b15a5f0..90cf78e436 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5254,14 +5254,16 @@ sub git_search { } elsif ($searchtype eq 'committer') { $greptype = "--committer="; } - $greptype .= $search_regexp; - my @commitlist = parse_commits($hash, 101, (100 * $page), undef, $greptype); + $greptype .= $searchtext; + my @commitlist = parse_commits($hash, 101, (100 * $page), undef, + $greptype, '--fixed-strings'); my $paging_nav = ''; if ($page > 0) { $paging_nav .= $cgi->a({-href => href(action=>"search", hash=>$hash, - searchtext=>$searchtext, searchtype=>$searchtype)}, + searchtext=>$searchtext, + searchtype=>$searchtype)}, "first"); $paging_nav .= " ⋅ " . $cgi->a({-href => href(-replay=>1, page=>$page-1), -- cgit v1.3 From 0e55991987e490a69bc549f6f789b34489c953a7 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 26 Feb 2008 13:22:08 +0100 Subject: gitweb: Clearly distinguish regexp / exact match searches This patch does a couple of things: * Makes commit/author/committer search case insensitive To be consistent with the grep search; I see no convincing reason for the search to be case sensitive, and you might get in trouble especially with contributors e.g. from Japan or France where they sometimes like to uppercase their last name. * Makes grep search by default search for fixed strings. * Introduces 're' checkbox that enables POSIX extended regexp searches This works for all the search types. The idea comes from Jakub. It does not make much sense (and is not easy at all) to untangle most of these changes from each other, thus they all go in a single patch. [jn: Cherry-picked from Pasky's http://repo.or.cz/git/gitweb.git] Signed-off-by: Petr Baudis Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 90cf78e436..20dc5d59c2 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -472,13 +472,15 @@ if (defined $searchtype) { } } +our $search_use_regexp = $cgi->param('sr'); + our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { if (length($searchtext) < 2) { die_error(undef, "At least two characters are required for search parameter"); } - $search_regexp = quotemeta $searchtext; + $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext; } # now read PATH_INFO and use it as alternative to parameters @@ -608,6 +610,7 @@ sub href(%) { searchtype => "st", snapshot_format => "sf", extra_options => "opt", + search_use_regexp => "sr", ); my %mapping = @mapping; @@ -2584,6 +2587,10 @@ EOF $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) . " search:\n", $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . + "" . + $cgi->checkbox(-name => 'sr', -value => 1, -label => 're', + -checked => $search_use_regexp) . + "" . "" . $cgi->end_form() . "\n"; } @@ -5256,7 +5263,8 @@ sub git_search { } $greptype .= $searchtext; my @commitlist = parse_commits($hash, 101, (100 * $page), undef, - $greptype, '--fixed-strings'); + $greptype, '--regexp-ignore-case', + $search_use_regexp ? '--extended-regexp' : '--fixed-strings'); my $paging_nav = ''; if ($page > 0) { @@ -5300,8 +5308,9 @@ sub git_search { my $git_command = git_cmd_str(); my $searchqtext = $searchtext; $searchqtext =~ s/'/'\\''/; + my $pickaxe_flags = $search_use_regexp ? '--pickaxe-regex' : ''; open my $fd, "-|", "$git_command rev-list $hash | " . - "$git_command diff-tree -r --stdin -S\'$searchqtext\'"; + "$git_command diff-tree -r --stdin -S\'$searchqtext\' $pickaxe_flags"; undef %co; my @files; while (my $line = <$fd>) { @@ -5365,7 +5374,9 @@ sub git_search { my $alternate = 1; my $matches = 0; $/ = "\n"; - open my $fd, "-|", git_cmd(), 'grep', '-n', '-i', '-E', $searchtext, $co{'tree'}; + open my $fd, "-|", git_cmd(), 'grep', '-n', + $search_use_regexp ? ('-E', '-i') : '-F', + $searchtext, $co{'tree'}; my $lastfile = ''; while (my $line = <$fd>) { chomp $line; @@ -5395,7 +5406,7 @@ sub git_search { print "
Binary file
\n"; } else { $ltext = untabify($ltext); - if ($ltext =~ m/^(.*)($searchtext)(.*)$/i) { + if ($ltext =~ m/^(.*)($search_regexp)(.*)$/i) { $ltext = esc_html($1, -nbsp=>1); $ltext .= ''; $ltext .= esc_html($2, -nbsp=>1); @@ -5430,27 +5441,31 @@ sub git_search_help { git_header_html(); git_print_page_nav('','', $hash,$hash,$hash); print <Pattern is by default a normal string that is matched precisely (but without +regard to case, except in the case of pickaxe). However, when you check the re checkbox, +the pattern entered is recognized as the POSIX extended +regular expression (also case +insensitive).

commit
-
The commit messages and authorship information will be scanned for the given string.
+
The commit messages and authorship information will be scanned for the given pattern.
EOT my ($have_grep) = gitweb_check_feature('grep'); if ($have_grep) { print <grep
All files in the currently selected tree (HEAD unless you are explicitly browsing - a different one) are searched for the given -regular expression -(POSIX extended) and the matches are listed. On large -trees, this search can take a while and put some strain on the server, so please use it with -some consideration.
+ a different one) are searched for the given pattern. On large trees, this search can take +a while and put some strain on the server, so please use it with some consideration. Note that +due to git-grep peculiarity, currently if regexp mode is turned off, the matches are +case-sensitive. EOT } print <author -
Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.
+
Name and e-mail of the change author and date of birth of the patch will be scanned for the given pattern.
committer
-
Name and e-mail of the committer and date of commit will be scanned for the given string.
+
Name and e-mail of the committer and date of commit will be scanned for the given pattern.
EOT my ($have_pickaxe) = gitweb_check_feature('pickaxe'); if ($have_pickaxe) { @@ -5458,7 +5473,8 @@ EOT
pickaxe
All commits that caused the string to appear or disappear from any file (changes that added, removed or "modified" the string) will be listed. This search can take a while and -takes a lot of strain on the server, so please use it wisely.
+takes a lot of strain on the server, so please use it wisely. Note that since you may be +interested even in changes just changing the case as well, this search is case sensitive. EOT } print "
\n"; -- cgit v1.3 From 6dfbb304be5a5e260321c5f47626582dbe2c62f0 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 2 Mar 2008 16:57:14 +0100 Subject: gitweb: Mark first match when searching commit messages Due to greediness of a pattern, gitweb used to mark (show) last match in line, if there are more than one match in line. Now it shows first. Showing all matches in a line would require further work. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 20dc5d59c2..922dee98b9 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3837,7 +3837,7 @@ sub git_search_grep_body { chop_and_escape_str($co{'title'}, 50) . "
"); my $comment = $co{'comment'}; foreach my $line (@$comment) { - if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { + if ($line =~ m/^(.*?)($search_regexp)(.*)$/i) { my ($lead, $match, $trail) = ($1, $2, $3); $match = chop_str($match, 70, 5, 'center'); my $contextlen = int((80 - length($match))/2); -- cgit v1.3 From c582abae46725504cee9ff91816c979989632f07 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Wed, 5 Mar 2008 09:31:55 +0100 Subject: gitweb: Fix and simplify pickaxe search Instead of using "git-rev-list | git-diff-tree" pipeline for pickaxe search, use git-log with appropriate options. Besides reducing number of forks by one, this allows to use list form of open, which in turn allow to not worry about quoting arguments and to avoid forking shell. The options to git-log were chosen to reduce required changes in pickaxe git command output parsing; gitweb still parses returned commits one by one. Parsing "pickaxe" output is simplified: git_search now reuses parse_difftree_raw_line and writes affected files as they arrive using the fact that commit name goes always before [raw] diff. While at it long bug of pickaxe search was fixed, namely that the last commit found by pickaxe search was never shown. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 85 +++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 42 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 922dee98b9..ec73cb1256 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5305,51 +5305,19 @@ sub git_search { print "
" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") . " | " . + $cgi->a({-href => href(action=>"commitdiff", hash=>$co{'id'})}, "commitdiff") . + " | " . $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree"); print "
" . " | " . $cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'})}, $tag{'reftype'}); if ($tag{'reftype'} eq "commit") { - print " | " . $cgi->a({-href => href(action=>"shortlog", hash=>$tag{'name'})}, "shortlog") . - " | " . $cgi->a({-href => href(action=>"log", hash=>$tag{'name'})}, "log"); + print " | " . $cgi->a({-href => href(action=>"shortlog", hash=>$tag{'fullname'})}, "shortlog") . + " | " . $cgi->a({-href => href(action=>"log", hash=>$tag{'fullname'})}, "log"); } elsif ($tag{'reftype'} eq "blob") { print " | " . $cgi->a({-href => href(action=>"blob_plain", hash=>$tag{'refid'})}, "raw"); } @@ -3726,13 +3728,13 @@ sub git_heads_body { $alternate ^= 1; print "$ref{'age'}" : "") . - $cgi->a({-href => href(action=>"shortlog", hash=>$ref{'name'}), + $cgi->a({-href => href(action=>"shortlog", hash=>$ref{'fullname'}), -class => "list name"},esc_html($ref{'name'})) . "" . - $cgi->a({-href => href(action=>"shortlog", hash=>$ref{'name'})}, "shortlog") . " | " . - $cgi->a({-href => href(action=>"log", hash=>$ref{'name'})}, "log") . " | " . - $cgi->a({-href => href(action=>"tree", hash=>$ref{'name'}, hash_base=>$ref{'name'})}, "tree") . + $cgi->a({-href => href(action=>"shortlog", hash=>$ref{'fullname'})}, "shortlog") . " | " . + $cgi->a({-href => href(action=>"log", hash=>$ref{'fullname'})}, "log") . " | " . + $cgi->a({-href => href(action=>"tree", hash=>$ref{'fullname'}, hash_base=>$ref{'name'})}, "tree") . "
$co{'age_string_date'}" . $author . "" . - $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, - chop_and_escape_str($co{'title'}, 50) . "
"); + $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), + -class => "list subject"}, + chop_and_escape_str($co{'title'}, 50) . "
"); my $comment = $co{'comment'}; foreach my $line (@$comment) { if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { - my $lead = esc_html($1) || ""; - $lead = chop_str($lead, 30, 10); - my $match = esc_html($2) || ""; - my $trail = esc_html($3) || ""; - $trail = chop_str($trail, 30, 10); - my $text = "$lead$match$trail"; - print chop_str($text, 80, 5) . "
\n"; + my ($lead, $match, $trail) = ($1, $2, $3); + $match = chop_str($match, 70, 5); # in case match is very long + my $contextlen = (80 - len($match))/2; # is left for the remainder + $contextlen = 30 if ($contextlen > 30); # but not too much + $lead = chop_str($lead, $contextlen, 10); + $trail = chop_str($trail, $contextlen, 10); + + $lead = esc_html($lead); + $match = esc_html($match); + $trail = esc_html($trail); + + print "$lead$match$trail
"; } } print "
\n"; my $alternate = 1; $/ = "\n"; - my $git_command = git_cmd_str(); - my $searchqtext = $searchtext; - $searchqtext =~ s/'/'\\''/; - my $pickaxe_flags = $search_use_regexp ? '--pickaxe-regex' : ''; - open my $fd, "-|", "$git_command rev-list $hash | " . - "$git_command diff-tree -r --stdin -S\'$searchqtext\' $pickaxe_flags"; + open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts, + '--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext", + ($search_use_regexp ? '--pickaxe-regex' : ()); undef %co; my @files; while (my $line = <$fd>) { - if (%co && $line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/) { - my %set; - $set{'file'} = $6; - $set{'from_id'} = $3; - $set{'to_id'} = $4; - $set{'id'} = $set{'to_id'}; - if ($set{'id'} =~ m/0{40}/) { - $set{'id'} = $set{'from_id'}; - } - if ($set{'id'} =~ m/0{40}/) { - next; - } - push @files, \%set; - } elsif ($line =~ m/^([0-9a-fA-F]{40})$/){ + chomp $line; + next unless $line; + + my %set = parse_difftree_raw_line($line); + if (defined $set{'commit'}) { + # finish previous commit if (%co) { - if ($alternate) { - print "\n"; - } else { - print "\n"; - } - $alternate ^= 1; - my $author = chop_and_escape_str($co{'author_name'}, 15, 5); - print "\n" . - "\n" . - "\n" . "\n" . "\n"; } - %co = parse_commit($1); + + if ($alternate) { + print "\n"; + } else { + print "\n"; + } + $alternate ^= 1; + %co = parse_commit($set{'commit'}); + my $author = chop_and_escape_str($co{'author_name'}, 15, 5); + print "\n" . + "\n" . + "\n" . + "\n" . + "\n"; + } + print "
$co{'age_string_date'}" . $author . "" . - $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), - -class => "list subject"}, - chop_and_escape_str($co{'title'}, 50) . "
"); - while (my $setref = shift @files) { - my %set = %$setref; - print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'}, - hash=>$set{'id'}, file_name=>$set{'file'}), - -class => "list"}, - "" . esc_path($set{'file'}) . "") . - "
\n"; - } print "
" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") . @@ -5358,11 +5326,44 @@ sub git_search { print "
$co{'age_string_date'}$author" . + $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), + -class => "list subject"}, + chop_and_escape_str($co{'title'}, 50) . "
"); + } elsif (defined $set{'to_id'}) { + next if ($set{'to_id'} =~ m/^0{40}$/); + + print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'}, + hash=>$set{'to_id'}, file_name=>$set{'to_file'}), + -class => "list"}, + "" . esc_path($set{'file'}) . "") . + "
\n"; } } close $fd; + # finish last commit (warning: repetition!) + if (%co) { + print "
" . + $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") . + " | " . + $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree"); + print "
\n"; } -- cgit v1.3 From 17a8b25005bb09b03bee7ddac5412c7d29675eef Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Wed, 26 Mar 2008 18:11:19 +0000 Subject: gitweb: fallback to system-wide config file if default config does not exist From a distribution point of view, configuration files for applications should reside in /etc/. On the other hand it's convenient for multiple instances of gitweb (e.g. virtual web servers on a single machine) to have a per-instance configuration file, just as gitweb currently supports through the file gitweb_config.perl next to the cgi. To support both at runtime, this commit introduces GITWEB_CONFIG_SYSTEM as a system-wide configuration file which will be used as a fallback if the config file sprecified throug GITWEB_CONFIG does not exist. See also http://bugs.debian.org/450592 Signed-off-by: Gerrit Pape Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- Makefile | 1 + gitweb/INSTALL | 6 +++++- gitweb/README | 9 ++++++++- gitweb/gitweb.perl | 7 ++++++- 4 files changed, 20 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/Makefile b/Makefile index 7c70b00b82..a88acf6efd 100644 --- a/Makefile +++ b/Makefile @@ -189,6 +189,7 @@ ETC_GITCONFIG = $(sysconfdir)/gitconfig # default configuration for gitweb GITWEB_CONFIG = gitweb_config.perl +GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf GITWEB_HOME_LINK_STR = projects GITWEB_SITENAME = GITWEB_PROJECTROOT = /pub/git diff --git a/gitweb/INSTALL b/gitweb/INSTALL index 9cd5b0a2b1..743f2d4442 100644 --- a/gitweb/INSTALL +++ b/gitweb/INSTALL @@ -95,7 +95,11 @@ for gitweb (in gitweb/README). by default it is file named gitweb_config.perl in the same place as gitweb.cgi script. You can control default place for config file using GITWEB_CONFIG build configuration variable, and you can set it - using GITWEB_CONFIG environmental variable. + using GITWEB_CONFIG environmental variable. If this file does not + exist, gitweb looks for a system-wide configuration file, normally + /etc/gitweb.conf. You can change the default using the + GITWEB_CONFIG_SYSTEM build configuration variable, and override it + through GITWEB_CONFIG_SYSTEM environmental variable. - Gitweb config file is [fragment] of perl code. You can set variables using "our $variable = value"; text from "#" character until the end diff --git a/gitweb/README b/gitweb/README index 2163071047..8dfe335f73 100644 --- a/gitweb/README +++ b/gitweb/README @@ -100,13 +100,20 @@ You can specify the following configuration variables when building GIT: is set when gitweb.cgi is executed, then the file specified in the environment variable will be loaded instead of the file specified when gitweb.cgi was created. [Default: gitweb_config.perl] + * GITWEB_CONFIG_SYSTEM + This Perl file will be loaded using 'do' as a fallback if GITWEB_CONFIG + does not exist. If the environment variable GITWEB_CONFIG_SYSTEM is set + when gitweb.cgi is executed, then the file specified in the environment + variable will be loaded instead of the file specified when gitweb.cgi was + created. [Default: /etc/gitweb.conf] Runtime gitweb configuration ---------------------------- You can adjust gitweb behaviour using the file specified in `GITWEB_CONFIG` -(defaults to 'gitweb_config.perl' in the same directory as the CGI). +(defaults to 'gitweb_config.perl' in the same directory as the CGI), and +as a fallback `GITWEB_CONFIG_SYSTEM` (defaults to /etc/gitweb.conf). The most notable thing that is not configurable at compile time are the optional features, stored in the '%features' variable. diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ec73cb1256..f73cfca539 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -369,7 +369,12 @@ sub filter_snapshot_fmts { } our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++"; -do $GITWEB_CONFIG if -e $GITWEB_CONFIG; +if (-e $GITWEB_CONFIG) { + do $GITWEB_CONFIG; +} else { + our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++"; + do $GITWEB_CONFIG_SYSTEM if -e $GITWEB_CONFIG_SYSTEM; +} # version of the core git binary our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown"; -- cgit v1.3 From 4ed4a347168d6714c6beca7d7702473229c9d8f1 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 5 Apr 2008 21:13:24 +0100 Subject: Revert "gitweb: Add 'status_str' to parse_difftree_raw_line output" This reverts commit 6aa6f92fda47cc4ee5f599895e8a5a327fb6f9ab. It caused is_deleted() subroutine to output warnings when dealing with old, legacy gitweb blobdiff URLs without either 'hb' or 'hpb' parameters. This fixes http://bugs.debian.org/469083 Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ec73cb1256..73d098a433 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2164,7 +2164,7 @@ sub parse_difftree_raw_line { $res{'to_mode'} = $2; $res{'from_id'} = $3; $res{'to_id'} = $4; - $res{'status'} = $res{'status_str'} = $5; + $res{'status'} = $5; $res{'similarity'} = $6; if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied ($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7); @@ -2180,7 +2180,6 @@ sub parse_difftree_raw_line { $res{'to_mode'} = pop @{$res{'from_mode'}}; $res{'from_id'} = [ split(' ', $3) ]; $res{'to_id'} = pop @{$res{'from_id'}}; - $res{'status_str'} = $4; $res{'status'} = [ split('', $4) ]; $res{'to_file'} = unquote($5); } @@ -3002,7 +3001,7 @@ sub fill_from_file_info { sub is_deleted { my $diffinfo = shift; - return $diffinfo->{'status_str'} =~ /D/; + return $diffinfo->{'to_id'} eq ('0' x 40); } # does patch correspond to [previous] difftree raw line -- cgit v1.3 From 5634cf24766f8700804ca55f5e8567c88538a5b0 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 13 Apr 2008 14:12:15 +0200 Subject: gitweb: Fix 'history' view for deleted files with history When asked for history of a file which is not present in given branch ("HEAD", i.e. current branch, or given by transient $hash_hase ('hb') parameter), but is present deeper in the history (meaning that "git rev-list --full-history $hash_base -- $file_name" is not empty), and there is no $hash ('h') parameter set for a file, gitweb would spew multiple of "Use of uninitialized value" warnings, and some links would be missing. This commit fixes this bug. This bug occurs in the rare cases when "git log -- " is empty and "git log --full-history -- " is not, or to be more exact in the cases when full-history starts later than given branch. It can happen if you are using handcrafted gitwb URL, or if you follow generic 'history' link or bookmark for a file which got deleted. Gitweb tried to get file type ('tree', or 'blob', or even 'commit') from the commit we start searching from (where the file was not present), and not among found commits. This was the cause of "Use of uninitialized value" warnings. This commit also add tests for such situation to t9500 test. While we are it, return HTTP error if there is _no_ history; it means that file or directory was not found (for given branch). Also error out if type of item could not be found: it should not happen now, but better be sure. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 18 +++++++++++++++--- t/t9500-gitweb-standalone-no-errors.sh | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 73d098a433..746153ffe8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5171,14 +5171,26 @@ sub git_history { my $refs = git_get_references(); my $limit = sprintf("--max-count=%i", (100 * ($page+1))); + my @commitlist = parse_commits($hash_base, 101, (100 * $page), + $file_name, "--full-history"); + if (!@commitlist) { + die_error('404 Not Found', "No such file or directory on given branch"); + } + if (!defined $hash && defined $file_name) { - $hash = git_get_hash_by_path($hash_base, $file_name); + # some commits could have deleted file in question, + # and not have it in tree, but one of them has to have it + for (my $i = 0; $i <= @commitlist; $i++) { + $hash = git_get_hash_by_path($commitlist[$i]{'id'}, $file_name); + last if defined $hash; + } } if (defined $hash) { $ftype = git_get_type($hash); } - - my @commitlist = parse_commits($hash_base, 101, (100 * $page), $file_name, "--full-history"); + if (!defined $ftype) { + die_error(undef, "Unknown type of object"); + } my $paging_nav = ''; if ($page > 0) { diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 796cd7dba0..061a2596d3 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -483,6 +483,22 @@ test_expect_success \ 'gitweb_run "p=.git;a=history;f=file"' test_debug 'cat gitweb.log' +test_expect_success \ + 'logs: history (implicit HEAD, non-existent file)' \ + 'gitweb_run "p=.git;a=history;f=non-existent"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'logs: history (implicit HEAD, deleted file)' \ + 'git checkout master && + echo "to be deleted" > deleted_file && + git add deleted_file && + git commit -m "Add file to be deleted" && + git rm deleted_file && + git commit -m "Delete file" && + gitweb_run "p=.git;a=history;f=deleted_file"' +test_debug 'cat gitweb.log' + # ---------------------------------------------------------------------- # feed generation -- cgit v1.3 From eae7a75904f9634736ff622be9d1c1e5f5567c27 Mon Sep 17 00:00:00 2001 From: Rafael Garcia-Suarez Date: Thu, 17 Apr 2008 13:45:52 +0200 Subject: Spelling fixes in the gitweb documentation Mostly spelling and grammar nits. Signed-off-by: Rafael Garcia-Suarez Signed-off-by: Junio C Hamano --- gitweb/INSTALL | 79 +++++++++++++++++++++++++++++----------------------------- gitweb/README | 50 ++++++++++++++++++------------------- 2 files changed, 65 insertions(+), 64 deletions(-) (limited to 'gitweb') diff --git a/gitweb/INSTALL b/gitweb/INSTALL index 743f2d4442..f7194dbef7 100644 --- a/gitweb/INSTALL +++ b/gitweb/INSTALL @@ -29,40 +29,40 @@ Build time configuration See also "How to configure gitweb for your local system" in README file for gitweb (in gitweb/README). -- There are many configuration variables which affects building of +- There are many configuration variables which affect building of gitweb.cgi; see "default configuration for gitweb" section in main (top dir) Makefile, and instructions for building gitweb/gitweb.cgi target. - One of most important is where to find git wrapper binary. Gitweb - tries to find git wrapper at $(bindir)/git, so you have to set $bindir + One of the most important is where to find the git wrapper binary. Gitweb + tries to find the git wrapper at $(bindir)/git, so you have to set $bindir when building gitweb.cgi, or $prefix from which $bindir is derived. If - you build and install gitweb together with the rest of git suite, + you build and install gitweb together with the rest of the git suite, there should be no problems. Otherwise, if git was for example installed from a binary package, you have to set $prefix (or $bindir) accordingly. - Another important issue is where are git repositories you want to make - available to gitweb. By default gitweb search for repositories under + available to gitweb. By default gitweb searches for repositories under /pub/git; if you want to have projects somewhere else, like /home/git, use GITWEB_PROJECTROOT build configuration variable. By default all git repositories under projectroot are visible and - available to gitweb. List of projects is generated by default by + available to gitweb. The list of projects is generated by default by scanning the projectroot directory for git repositories. This can be changed (configured) as described in "Gitweb repositories" section below. - Note that gitweb deals directly with object database, and does not - need working directory; the name of the project is the name of its + Note that gitweb deals directly with the object database, and does not + need a working directory; the name of the project is the name of its repository object database, usually projectname.git for bare repositories. If you want to provide gitweb access to non-bare (live) - repository, you can make projectname.git symbolic link under + repositories, you can make projectname.git a symbolic link under projectroot linking to projectname/.git (but it is just a suggestion). - You can control where gitweb tries to find its main CSS style file, - its favicon and logo with GITWEB_CSS, GITWEB_FAVICON and GITWEB_LOGO + its favicon and logo with the GITWEB_CSS, GITWEB_FAVICON and GITWEB_LOGO build configuration variables. By default gitweb tries to find them in the same directory as gitweb.cgi script. @@ -91,17 +91,17 @@ Gitweb config file See also "Runtime gitweb configuration" section in README file for gitweb (in gitweb/README). -- You can configure gitweb further using gitweb configuration file; - by default it is file named gitweb_config.perl in the same place as - gitweb.cgi script. You can control default place for config file - using GITWEB_CONFIG build configuration variable, and you can set it - using GITWEB_CONFIG environmental variable. If this file does not +- You can configure gitweb further using the gitweb configuration file; + by default this is a file named gitweb_config.perl in the same place as + gitweb.cgi script. You can control the default place for the config file + using the GITWEB_CONFIG build configuration variable, and you can set it + using the GITWEB_CONFIG environment variable. If this file does not exist, gitweb looks for a system-wide configuration file, normally /etc/gitweb.conf. You can change the default using the GITWEB_CONFIG_SYSTEM build configuration variable, and override it - through GITWEB_CONFIG_SYSTEM environmental variable. + through the GITWEB_CONFIG_SYSTEM environment variable. -- Gitweb config file is [fragment] of perl code. You can set variables +- The gitweb config file is a fragment of perl code. You can set variables using "our $variable = value"; text from "#" character until the end of a line is ignored. See perlsyn(1) for details. @@ -128,36 +128,37 @@ Gitweb repositories ------------------- - By default all git repositories under projectroot are visible and - available to gitweb. List of projects is generated by default by + available to gitweb. The list of projects is generated by default by scanning the projectroot directory for git repositories (for object databases to be more exact). - You can provide pre-generated list of [visible] repositories, + You can provide a pre-generated list of [visible] repositories, together with information about their owners (the project ownership - is taken from owner of repository directory otherwise), by setting - GITWEB_LIST build configuration variable (or $projects_list variable - in gitweb config file) to point to a plain file. - - Each line of projects list file should consist of url-encoded path - to project repository database (relative to projectroot) separated - by space from url-encoded project owner; spaces in both project path - and project owner have to be encoded as either '%20' or '+'. - - You can generate projects list index file using project_index action - (the 'TXT' link on projects list page) directly from gitweb. - -- By default even if project is not visible on projects list page, you - can view it nevertheless by hand-crafting gitweb URL. You can set - GITWEB_STRICT_EXPORT build configuration variable (or $strict_export - variable in gitweb config file) to only allow viewing of + defaults to the owner of the repository directory otherwise), by setting + the GITWEB_LIST build configuration variable (or the $projects_list + variable in the gitweb config file) to point to a plain file. + + Each line of the projects list file should consist of the url-encoded path + to the project repository database (relative to projectroot), followed + by the url-encoded project owner on the same line (separated by a space). + Spaces in both project path and project owner have to be encoded as either + '%20' or '+'. + + You can generate the projects list index file using the project_index + action (the 'TXT' link on projects list page) directly from gitweb. + +- By default, even if a project is not visible on projects list page, you + can view it nevertheless by hand-crafting a gitweb URL. You can set the + GITWEB_STRICT_EXPORT build configuration variable (or the $strict_export + variable in the gitweb config file) to only allow viewing of repositories also shown on the overview page. - Alternatively, you can configure gitweb to only list and allow - viewing of the explicitly exported repositories, via - GITWEB_EXPORT_OK build configuration variable (or $export_ok + viewing of the explicitly exported repositories, via the + GITWEB_EXPORT_OK build configuration variable (or the $export_ok variable in gitweb config file). If it evaluates to true, gitweb - show repository only if this file exists in its object database - (if directory has the magic file $export_ok). + shows repositories only if this file exists in its object database + (if directory has the magic file named $export_ok). Generating projects list using gitweb ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/gitweb/README b/gitweb/README index 8dfe335f73..8f7ea367ba 100644 --- a/gitweb/README +++ b/gitweb/README @@ -2,7 +2,7 @@ GIT web Interface ================= The one working on: - http://www.kernel.org/git/ + http://git.kernel.org/ From the git version 1.4.0 gitweb is bundled with git. @@ -10,13 +10,13 @@ From the git version 1.4.0 gitweb is bundled with git. How to configure gitweb for your local system --------------------------------------------- -See also "Build time configuration" section in INSTALL +See also the "Build time configuration" section in the INSTALL file for gitweb (in gitweb/INSTALL). You can specify the following configuration variables when building GIT: * GIT_BINDIR - Points out where to find git executable. You should set up it to - the place where git binary was installed (usually /usr/bin) if you + Points where to find the git executable. You should set it up to + the place where the git binary was installed (usually /usr/bin) if you don't install git from sources together with gitweb. [Default: $(bindir)] * GITWEB_SITENAME Shown in the title of all generated pages, defaults to the server name @@ -24,13 +24,13 @@ You can specify the following configuration variables when building GIT: * GITWEB_PROJECTROOT The root directory for all projects shown by gitweb. Must be set correctly for gitweb to find repositories to display. See also - "Gitweb repositories" in INSTALL file for gitweb. [Default: /pub/git] + "Gitweb repositories" in the INSTALL file for gitweb. [Default: /pub/git] * GITWEB_PROJECT_MAXDEPTH - The filesystem traversing limit for getting projects list; the number + The filesystem traversing limit for getting the project list; the number is taken as depth relative to the projectroot. It is used when GITWEB_LIST is a directory (or is not set; then project root is used). Is is meant to speed up project listing on large work trees by limiting - find depth. [Default: 2007] + search depth. [Default: 2007] * GITWEB_LIST Points to a directory to scan for projects (defaults to project root if not set / if empty) or to a file with explicit listing of projects @@ -72,15 +72,15 @@ You can specify the following configuration variables when building GIT: Git base URLs used for URL to where fetch project from, i.e. full URL is "$git_base_url/$project". Shown on projects summary page. Repository URL for project can be also configured per repository; this - takes precendence over URL composed from base URL and project name. + takes precedence over URLs composed from base URL and a project name. Note that you can setup multiple base URLs (for example one for - git:// protocol access, one for http:// access) from gitweb config - file. [No default] + git:// protocol access, another for http:// access) from the gitweb + config file. [No default] * GITWEB_CSS Points to the location where you put gitweb.css on your web server - (or to be more generic URI of gitweb stylesheet). Relative to base - URI of gitweb. Note that you can setup multiple stylesheets from - gitweb config file. [Default: gitweb.css] + (or to be more generic, the URI of gitweb stylesheet). Relative to the + base URI of gitweb. Note that you can setup multiple stylesheets from + the gitweb config file. [Default: gitweb.css] * GITWEB_LOGO Points to the location where you put git-logo.png on your web server (or to be more generic URI of logo, 72x27 size, displayed in top right @@ -121,15 +121,15 @@ Ultimate description on how to reconfigure the default features setting in your `GITWEB_CONFIG` or per-project in `project.git/config` can be found as comments inside 'gitweb.cgi'. -See also "Gitweb config file" (with example of gitweb config file), and -"Gitweb repositories" sections in INSTALL file for gitweb. +See also the "Gitweb config file" (with an example of config file), and +the "Gitweb repositories" sections in INSTALL file for gitweb. -Gitweb config file is [fragment] of perl code. You can set variables +The gitweb config file is a fragment of perl code. You can set variables using "our $variable = value"; text from "#" character until the end of a line is ignored. See perlsyn(1) man page for details. -Below there is list of vaiables which you might want to set in gitweb config. +Below is the list of variables which you might want to set in gitweb config. See the top of 'gitweb.cgi' for the full list of variables and their descriptions. @@ -140,7 +140,7 @@ You can set, among others, the following variables in gitweb config files (with the exception of $projectroot and $projects_list this list does not include variables usually directly set during build): * $GIT - Cure git executable to use. By default set to "$GIT_BINDIR/git", which + Core git executable to use. By default set to "$GIT_BINDIR/git", which in turn is by default set to "$(bindir)/git". If you use git from binary package, set this to "/usr/bin/git". This can just be "git" if your webserver has a sensible PATH. If you have multiple git versions @@ -176,7 +176,7 @@ not include variables usually directly set during build): to make it easier to upgrade gitweb. You can add 'site' stylesheet for example by using push @stylesheets, "gitweb-site.css"; - in gitweb config file. + in the gitweb config file. * $logo_url, $logo_label URI and label (title) of GIT logo link (or your site logo, if you choose to use different logo image). By default they point to git homepage; @@ -198,12 +198,12 @@ not include variables usually directly set during build): Default mimetype for blob_plain (raw) view, if mimetype checking doesn't result in some other type; by default 'text/plain'. * $default_text_plain_charset - Default charset for text files. If not set, web serwer configuration + Default charset for text files. If not set, web server configuration would be used. * $mimetypes_file File to use for (filename extension based) guessing of MIME types before - trying /etc/mime.types. Path, if relative, is taken currently as taken - relative to current git repositoy. + trying /etc/mime.types. Path, if relative, is taken currently as + relative to the current git repository. * $fallback_encoding Gitweb assumes this charset if line contains non-UTF-8 characters. Fallback decoding is used without error checking, so it can be even @@ -232,14 +232,14 @@ You can use the following files in repository: single line description of a project (of a repository). Plain text file; HTML will be escaped. By default set to Unnamed repository; edit this file to name it for gitweb. - from the template during creating repository. You can use + from the template during repository creation. You can use the gitweb.description repo configuration variable, but the file takes - precendence. + precedence. * cloneurl (or multiple-valued gitweb.url) File with repository URL (used for clone and fetch), one per line. Displayed in the project summary page. You can use multiple-valued gitweb.url repository configuration variable for that, but the file - takes precendence. + takes precedence. * gitweb.owner You can use the gitweb.owner repository configuration variable to set repository's owner. It is displayed in the project list and summary -- cgit v1.3 From bbd4c307fc315847c975efd4c9aa32eb0e8470fb Mon Sep 17 00:00:00 2001 From: "martin f. krafft" Date: Sun, 20 Apr 2008 23:03:56 +0200 Subject: Escape project name in regexp The project name, when used in a regular expression, needs to be quoted properly, so that stuff like '++' in the project name does not cause Perl to barf. Related info: http://bugs.debian.org/476076 This is a bug in Perl's CGI.pm, but fixing that exposed a similar bug in gitweb.perl Signed-off-by: martin f. krafft Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 746153ffe8..4abd7ac1ad 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -506,7 +506,7 @@ sub evaluate_path_info { } # do not change any parameters if an action is given using the query string return if $action; - $path_info =~ s,^$project/*,,; + $path_info =~ s,^\Q$project\E/*,,; my ($refname, $pathname) = split(/:/, $path_info, 2); if (defined $pathname) { # we got "project.git/branch:filename" or "project.git/branch:dir/" -- cgit v1.3 From 85d17a123ba59b90744e311e40f80fd8838fbdc5 Mon Sep 17 00:00:00 2001 From: "martin f. krafft" Date: Sun, 20 Apr 2008 23:23:38 +0200 Subject: Escape project names before creating pathinfo URLs If a project name contains special URL characters like +, gitweb's links break in subtle ways. The solution is to pass the project name through esc_url() and using the return value. Signed-off-by: martin f. krafft Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 4abd7ac1ad..12843a4846 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -628,7 +628,7 @@ sub href(%) { my ($use_pathinfo) = gitweb_check_feature('pathinfo'); if ($use_pathinfo) { # use PATH_INFO for project name - $href .= "/$params{'project'}" if defined $params{'project'}; + $href .= "/".esc_url($params{'project'}) if defined $params{'project'}; delete $params{'project'}; # Summary just uses the project path URL @@ -2570,7 +2570,7 @@ EOF my $action = $my_uri; my ($use_pathinfo) = gitweb_check_feature('pathinfo'); if ($use_pathinfo) { - $action .= "/$project"; + $action .= "/".esc_url($project); } else { $cgi->param("p", $project); } -- cgit v1.3 From 3562198b7da7ef6597af27b3a7fcaeee41608999 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 20 Apr 2008 22:09:48 +0200 Subject: gitweb: Use feed link according to current view Michael G. Noll said in comments to the "Switching my code repository from Subversion (SVN) to git" article (http://tinyurl.com/37v67l) in his "My digital moleskine" blog, that one of the things he is missing in gitweb from SVN::Web is an RSS feed with news/information of the current view (including RSS feed for single file or directory). This is not exactly true, as since refactoring feed generation in af6feeb (gitweb: Refactor feed generation, make output prettier, add Atom feed, 2006-11-19), gitweb can generate feeds (RSS or Atom) for history of a given branch, history limited to a given directory, or history of a given file. Nevertheless this required handcrafting the URL to get wanted RSS feed. This commit makes gitweb select feed links in the HTML header and in page footer depending on current view (action). It is more elaborate, and I guess more correct, than simple patch adding $hash ('h') parameter to *all* URLs, including feed links, by Jean-Baptiste Quenot Subject: [PATCH] gitweb: Add hash parameter in feed URL when a hash is specified in the current request Message-ID: If $hash ('h') or $hash_base ('hb') parameter is a branch name (i.e. it starts with 'refs/heads/'; all generated URLs use this form to discriminate between tags and heads), it is used in feed URLs; if $file_name ('f') is defined, it is used in feed URLs. Feed title is set according to the kind of web feed: it is either 'log' for generic feed, 'log of ', 'history of ' for generic history (using implicit or explicit HEAD, i.e. current branch) or 'history of on '. There are special cases: 'heads' and 'forks' views should use OPML providing list of available feeds; 'tags' probably also should use OPML; there is no web feed equivalent to 'search' view. Currently all those cases fallback to (show) default feed. Such feed link uses "generic" class, and is shown in slightly lighter color for distinction. Currently feed can have but one starting point, and does not support negative (exclude) commit arguments. Therefore for now for *diff views it is chosen that feed follow the "to" part: to-name, to-commit for 'blobdiff', 'treediff' and 'commitdiff' views. Generating parameters for href() for feed link was separated (refactored) into get_feed_info() subroutine. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 8 ++++ gitweb/gitweb.perl | 121 ++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 104 insertions(+), 25 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 446a1c333b..aa0eeca247 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -464,6 +464,14 @@ a.rss_logo:hover { background-color: #ee5500; } +a.rss_logo.generic { + background-color: #ff8800; +} + +a.rss_logo.generic:hover { + background-color: #ee7700; +} + span.refs span { padding: 0px 4px; font-size: 70%; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f83567ec39..2facf2db7a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -592,7 +592,7 @@ exit; ## ====================================================================== ## action links -sub href(%) { +sub href (%) { my %params = @_; # default is to use -absolute url() i.e. $my_uri my $href = $params{-full} ? $my_url : $my_uri; @@ -1448,6 +1448,46 @@ sub format_snapshot_links { } } +## ...................................................................... +## functions returning values to be passed, perhaps after some +## transformation, to other functions; e.g. returning arguments to href() + +# returns hash to be passed to href to generate gitweb URL +# in -title key it returns description of link +sub get_feed_info { + my $format = shift || 'Atom'; + my %res = (action => lc($format)); + + # feed links are possible only for project views + return unless (defined $project); + # some views should link to OPML, or to generic project feed, + # or don't have specific feed yet (so they should use generic) + return if ($action =~ /^(?:tags|heads|forks|tag|search)$/x); + + my $branch; + # branches refs uses 'refs/heads/' prefix (fullname) to differentiate + # from tag links; this also makes possible to detect branch links + if ((defined $hash_base && $hash_base =~ m!^refs/heads/(.*)$!) || + (defined $hash && $hash =~ m!^refs/heads/(.*)$!)) { + $branch = $1; + } + # find log type for feed description (title) + my $type = 'log'; + if (defined $file_name) { + $type = "history of $file_name"; + $type .= "/" if ($action eq 'tree'); + $type .= " on '$branch'" if (defined $branch); + } else { + $type = "log of $branch" if (defined $branch); + } + + $res{-title} = $type; + $res{'hash'} = (defined $branch ? "refs/heads/$branch" : undef); + $res{'file_name'} = $file_name; + + return %res; +} + ## ---------------------------------------------------------------------- ## git utility subroutines, invoking git commands @@ -2510,30 +2550,49 @@ EOF } } if (defined $project) { - printf(''."\n", - esc_param($project), href(action=>"rss")); - printf(''."\n", - esc_param($project), href(action=>"rss", - extra_options=>"--no-merges")); - printf(''."\n", - esc_param($project), href(action=>"atom")); - printf(''."\n", - esc_param($project), href(action=>"atom", - extra_options=>"--no-merges")); + my %href_params = get_feed_info(); + if (!exists $href_params{'-title'}) { + $href_params{'-title'} = 'log'; + } + + foreach my $format qw(RSS Atom) { + my $type = lc($format); + my %link_attr = ( + '-rel' => 'alternate', + '-title' => "$project - $href_params{'-title'} - $format feed", + '-type' => "application/$type+xml" + ); + + $href_params{'action'} = $type; + $link_attr{'-href'} = href(%href_params); + print "\n"; + + $href_params{'extra_options'} = '--no-merges'; + $link_attr{'-href'} = href(%href_params); + $link_attr{'-title'} .= ' (no merges)'; + print "\n"; + } + } else { printf(''."\n", + 'href="%s" type="text/plain; charset=utf-8" />'."\n", $site_name, href(project=>undef, action=>"project_index")); printf(''."\n", + 'href="%s" type="text/x-opml" />'."\n", $site_name, href(project=>undef, action=>"opml")); } if (defined $favicon) { - print qq(\n); + print qq(\n); } print "\n" . @@ -2601,23 +2660,35 @@ EOF } sub git_footer_html { + my $feed_class = 'rss_logo'; + print "
\n"; if (defined $project) { my $descr = git_get_project_description($project); if (defined $descr) { print "\n"; } - print $cgi->a({-href => href(action=>"rss"), - -class => "rss_logo"}, "RSS") . " "; - print $cgi->a({-href => href(action=>"atom"), - -class => "rss_logo"}, "Atom") . "\n"; + + my %href_params = get_feed_info(); + if (!%href_params) { + $feed_class .= ' generic'; + } + $href_params{'-title'} ||= 'log'; + + foreach my $format qw(RSS Atom) { + $href_params{'action'} = lc($format); + print $cgi->a({-href => href(%href_params), + -title => "$href_params{'-title'} $format feed", + -class => $feed_class}, $format)."\n"; + } + } else { print $cgi->a({-href => href(project=>undef, action=>"opml"), - -class => "rss_logo"}, "OPML") . " "; + -class => $feed_class}, "OPML") . " "; print $cgi->a({-href => href(project=>undef, action=>"project_index"), - -class => "rss_logo"}, "TXT") . "\n"; + -class => $feed_class}, "TXT") . "\n"; } - print "
\n" ; + print "\n"; # class="page_footer" if (-f $site_footer) { open (my $fd, $site_footer); -- cgit v1.3 From dee2775a29440ca8a52bb5bd09a6de6cd29f69cc Mon Sep 17 00:00:00 2001 From: Anders Waldenborg Date: Wed, 21 May 2008 13:44:43 +0200 Subject: gitweb: Convert string to internal form before chopping in chop_str Fix chop_str not to cut in middle of utf8 multibyte chars. Without this fix at least author name in short log may cut in middle of a multibyte char. When the result comes to esc_html to_utf8 is called again, which doesn't find valid utf8 and decodes using $fallback_encoding making it even worse. This also have the nice side effect that it actually tries to show the first 10 _characters_, not the number of characters that happened to fit into 10 bytes. Signed-off-by: Anders Waldenborg Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 2facf2db7a..8308e2208e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -866,6 +866,10 @@ sub chop_str { my $add_len = shift || 10; my $where = shift || 'right'; # 'left' | 'center' | 'right' + # Make sure perl knows it is utf8 encoded so we don't + # cut in the middle of a utf8 multibyte char. + $str = to_utf8($str); + # allow only $len chars, but don't cut a word if it would fit in $add_len # if it doesn't fit, cut it if it's still longer than the dots we would add # remove chopped character entities entirely -- cgit v1.3 From 1f684dc01c6a45341e8e47d8393f0ef66fdfc398 Mon Sep 17 00:00:00 2001 From: Lea Wiemann Date: Wed, 28 May 2008 01:25:42 +0200 Subject: gitweb: only display "next" links in logs if there is a next page There was a bug in the implementation of the "next" links in format_paging_nav (for log and shortlog), which caused the next links to always be displayed, even if there is no next page. This fixes it. Signed-off-by: Lea Wiemann Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 12843a4846..345acf4520 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2676,7 +2676,7 @@ sub git_print_page_nav { } sub format_paging_nav { - my ($action, $hash, $head, $page, $nrevs) = @_; + my ($action, $hash, $head, $page, $has_next_link) = @_; my $paging_nav; @@ -2694,7 +2694,7 @@ sub format_paging_nav { $paging_nav .= " ⋅ prev"; } - if ($nrevs >= (100 * ($page+1)-1)) { + if ($has_next_link) { $paging_nav .= " ⋅ " . $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); @@ -4585,7 +4585,7 @@ sub git_log { my @commitlist = parse_commits($hash, 101, (100 * $page)); - my $paging_nav = format_paging_nav('log', $hash, $head, $page, (100 * ($page+1))); + my $paging_nav = format_paging_nav('log', $hash, $head, $page, $#commitlist >= 100); git_header_html(); git_print_page_nav('log','', $hash,undef,undef, $paging_nav); @@ -5505,7 +5505,7 @@ sub git_shortlog { my @commitlist = parse_commits($hash, 101, (100 * $page)); - my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, (100 * ($page+1))); + my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, $#commitlist >= 100); my $next_link = ''; if ($#commitlist >= 100) { $next_link = -- cgit v1.3 From 6ab69bf253848d641fb08348eca10b7cf79fd275 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 31 May 2008 20:28:18 +0200 Subject: gitweb: Remove gitweb/test/ directory Testing if gitweb handles filenames with spaces, filenames with plus sign ('+') which encodes spaces in CGI parameters (in URLs), and filenames with Unicode characters should be handled by gitweb tests. Those files are remainder of the time when gitweb was project on its own, not a part of git (with its testsuite). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- "gitweb/test/M\303\244rchen" | 2 -- gitweb/test/file with spaces | 4 ---- gitweb/test/file+plus+sign | 6 ------ 3 files changed, 12 deletions(-) delete mode 100644 "gitweb/test/M\303\244rchen" delete mode 100644 gitweb/test/file with spaces delete mode 100644 gitweb/test/file+plus+sign (limited to 'gitweb') diff --git "a/gitweb/test/M\303\244rchen" "b/gitweb/test/M\303\244rchen" deleted file mode 100644 index 8f7a1d3e9c..0000000000 --- "a/gitweb/test/M\303\244rchen" +++ /dev/null @@ -1,2 +0,0 @@ -Märchen -Märchen diff --git a/gitweb/test/file with spaces b/gitweb/test/file with spaces deleted file mode 100644 index f108543c4e..0000000000 --- a/gitweb/test/file with spaces +++ /dev/null @@ -1,4 +0,0 @@ -This -filename -contains -spaces. diff --git a/gitweb/test/file+plus+sign b/gitweb/test/file+plus+sign deleted file mode 100644 index fd05278808..0000000000 --- a/gitweb/test/file+plus+sign +++ /dev/null @@ -1,6 +0,0 @@ -This -filename -contains -+ -plus -chars. -- cgit v1.3 From f70dda250e33dd17f6fdff17d15287391d8b0952 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 2 Jun 2008 11:54:41 +0200 Subject: gitweb: Fix "next" link on bottom of page Fix search form generation to not modify $cgi->param(...)'s. In git_header_html() we used to use $cgi->hidden(-name => "a") etc. to generate hidden fields; unfortunately to use this form it is required to modify $cgi->param("a") etc., which makes href(-replay,...) use wrong replay values. This for example made the "next" link on the bottom of the page has a=search instead of a=$action, and thus fails to get you to the next page. Because in CGI the value of a hidden field is "sticky", there is no way to modify it short of modifying $cgi->param(...). Therefore it got replaced by generating element [semi] directly. Alternate solution would be for href(-replay,...) to use values saved in global variables, such as $action etc., instead of (re)reading them from $cgi->param($symbol). The bad link was reported by Kai Blin through http://bugs.debian.org/481902 Reported-by: Kai Blin Signed-off-by: Jakub Narebski Tested-by: Gerrit Pape Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 57a19058a4..55fb100534 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2623,7 +2623,7 @@ EOF print "\n"; my ($have_search) = gitweb_check_feature('search'); - if ((defined $project) && ($have_search)) { + if (defined $project && $have_search) { if (!defined $searchtext) { $searchtext = ""; } @@ -2639,16 +2639,13 @@ EOF my ($use_pathinfo) = gitweb_check_feature('pathinfo'); if ($use_pathinfo) { $action .= "/".esc_url($project); - } else { - $cgi->param("p", $project); } - $cgi->param("a", "search"); - $cgi->param("h", $search_hash); print $cgi->startform(-method => "get", -action => $action) . "
\n" . - (!$use_pathinfo && $cgi->hidden(-name => "p") . "\n") . - $cgi->hidden(-name => "a") . "\n" . - $cgi->hidden(-name => "h") . "\n" . + (!$use_pathinfo && + $cgi->input({-name=>"p", -value=>$project, -type=>"hidden"}) . "\n") . + $cgi->input({-name=>"a", -value=>"search", -type=>"hidden"}) . "\n" . + $cgi->input({-name=>"h", -value=>$search_hash, -type=>"hidden"}) . "\n" . $cgi->popup_menu(-name => 'st', -default => 'commit', -values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) . $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) . -- cgit v1.3 From 7f718e8b46b37a9e1caf58a372938817f04885d9 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 3 Jun 2008 16:47:10 +0200 Subject: gitweb: Add charset info to "raw" output of 'text/plain' blobs Earlier "blob_plain" view sent "charset=utf-8" only when gitweb guessed the content type to be text by reading from it, and not when the MIME type was obtained from /etc/mime.types, or when gitweb couldn't guess mimetype and used $default_blob_plain_mimetype. This fixes the bug by always add charset info from $default_text_plain_charset (if it is defined) to "raw" (a=blob_plain) output for 'text/plain' blobs. Generating information for Content-Type: header got separated into blob_contenttype() subroutine; adding charset info in a special case was removed from blob_mimetype(), which now should return mimetype only. While at it cleanup code a bit: put subroutine parameter initialization first, make error message more robust (when $file_name is not defined) if more cryptic, remove unnecessary '"' around variable ("$var" -> $var). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 55fb100534..198772c210 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2481,8 +2481,7 @@ sub blob_mimetype { return $default_blob_plain_mimetype unless $fd; if (-T $fd) { - return 'text/plain' . - ($default_text_plain_charset ? '; charset='.$default_text_plain_charset : ''); + return 'text/plain'; } elsif (! $filename) { return 'application/octet-stream'; } elsif ($filename =~ m/\.png$/i) { @@ -2496,6 +2495,17 @@ sub blob_mimetype { } } +sub blob_contenttype { + my ($fd, $file_name, $type) = @_; + + $type ||= blob_mimetype($fd, $file_name); + if ($type eq 'text/plain' && defined $default_text_plain_charset) { + $type .= "; charset=$default_text_plain_charset"; + } + + return $type; +} + ## ====================================================================== ## functions printing HTML: header, footer, error page @@ -4374,6 +4384,7 @@ sub git_heads { } sub git_blob_plain { + my $type = shift; my $expires; if (!defined $hash) { @@ -4389,13 +4400,13 @@ sub git_blob_plain { $expires = "+1d"; } - my $type = shift; open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash - or die_error(undef, "Couldn't cat $file_name, $hash"); + or die_error(undef, "Open git-cat-file blob '$hash' failed"); - $type ||= blob_mimetype($fd, $file_name); + # content-type (can include charset) + $type = blob_contenttype($fd, $file_name, $type); - # save as filename, even when no $file_name is given + # "save as" filename, even when no $file_name is given my $save_as = "$hash"; if (defined $file_name) { $save_as = $file_name; @@ -4404,9 +4415,9 @@ sub git_blob_plain { } print $cgi->header( - -type => "$type", - -expires=>$expires, - -content_disposition => 'inline; filename="' . "$save_as" . '"'); + -type => $type, + -expires => $expires, + -content_disposition => 'inline; filename="' . $save_as . '"'); undef $/; binmode STDOUT, ':raw'; print <$fd>; -- cgit v1.3 From 55f409a826cbd574333dbc91d6f7e1e9888d696d Mon Sep 17 00:00:00 2001 From: Ask Bjørn Hansen Date: Sat, 7 Jun 2008 00:19:26 -0700 Subject: gitweb setup instruction: rewrite HEAD and root as well Also add a few more hints for how to setup and configure gitweb as described [jc: with a fix from Mike Hommey] Signed-off-by: Junio C Hamano --- gitweb/README | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index 8f7ea367ba..356ab7b327 100644 --- a/gitweb/README +++ b/gitweb/README @@ -255,12 +255,15 @@ Webserver configuration If you want to have one URL for both gitweb and your http:// repositories, you can configure apache like this: - - ServerName git.domain.org + + ServerName git.example.org DocumentRoot /pub/git - RewriteEngine on - RewriteRule ^/(.*\.git/(?!/?(info|objects|refs)).*)?$ /cgi-bin/gitweb.cgi%{REQUEST_URI} [L,PT] SetEnv GITWEB_CONFIG /etc/gitweb.conf + RewriteEngine on + # make the front page an internal rewrite to the gitweb script + RewriteRule ^/$ /cgi-bin/gitweb.cgi + # make access for "dumb clients" work + RewriteRule ^/(.*\.git/(?!/?(HEAD|info|objects|refs)).*)?$ /cgi-bin/gitweb.cgi%{REQUEST_URI} [L,PT] The above configuration expects your public repositories to live under @@ -276,6 +279,13 @@ override the defaults given at the head of the gitweb.perl (or gitweb.cgi). Look at the comments in that file for information on which variables and what they mean. +If you use the rewrite rules from the example you'll likely also need +something like the following in your gitweb.conf (or gitweb_config.perl) file: + + @stylesheets = ("/some/absolute/path/gitweb.css"); + $my_uri = "/"; + $home_link = "/"; + Originally written by: Kay Sievers -- cgit v1.3 From 3a5b919cf220651b681b5f036bf3bd1c61e36ef2 Mon Sep 17 00:00:00 2001 From: Rafael Garcia-Suarez Date: Fri, 6 Jun 2008 09:53:32 +0200 Subject: gitweb: remove git_blame and rename git_blame2 to git_blame git_blame is dead code. It's possible to plug it in place of git_blame2, but I don't know whether anyone does still that, because git_blame2 can now be considered stable enough, I think. Signed-off-by: Rafael Garcia-Suarez Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 101 ++--------------------------------------------------- 1 file changed, 2 insertions(+), 99 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 198772c210..8d1f3e0547 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -539,7 +539,7 @@ $git_dir = "$projectroot/$project" if $project; # dispatch my %actions = ( - "blame" => \&git_blame2, + "blame" => \&git_blame, "blobdiff" => \&git_blobdiff, "blobdiff_plain" => \&git_blobdiff_plain, "blob" => \&git_blob, @@ -4152,7 +4152,7 @@ sub git_tag { git_footer_html(); } -sub git_blame2 { +sub git_blame { my $fd; my $ftype; @@ -4260,103 +4260,6 @@ HTML git_footer_html(); } -sub git_blame { - my $fd; - - my ($have_blame) = gitweb_check_feature('blame'); - if (!$have_blame) { - die_error('403 Permission denied', "Permission denied"); - } - die_error('404 Not Found', "File name not defined") if (!$file_name); - $hash_base ||= git_get_head_hash($project); - die_error(undef, "Couldn't find base commit") unless ($hash_base); - my %co = parse_commit($hash_base) - or die_error(undef, "Reading commit failed"); - if (!defined $hash) { - $hash = git_get_hash_by_path($hash_base, $file_name, "blob") - or die_error(undef, "Error lookup file"); - } - open ($fd, "-|", git_cmd(), "annotate", '-l', '-t', '-r', $file_name, $hash_base) - or die_error(undef, "Open git-annotate failed"); - git_header_html(); - my $formats_nav = - $cgi->a({-href => href(action=>"blob", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)}, - "blob") . - " | " . - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)}, - "history") . - " | " . - $cgi->a({-href => href(action=>"blame", file_name=>$file_name)}, - "HEAD"); - git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav); - git_print_header_div('commit', esc_html($co{'title'}), $hash_base); - git_print_page_path($file_name, 'blob', $hash_base); - print "
\n"; - print < -
CommitAgeAuthorLineData
Unable to parse: $line
$long_rev)}" class="text">$short_rev..$age_str$author$lineno$data
\n\n"; - close $fd - or print "Reading blob failed.\n"; - print "
"; - git_footer_html(); -} - sub git_tags { my $head = git_get_head_hash($project); git_header_html(); -- cgit v1.3 From 69913415655839b3add5d930ebbea1be8a5b60a9 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 10 Jun 2008 19:21:01 +0200 Subject: gitweb: Separate filling list of projects info Extract filling project list info, i.e. adding age, description, owner and forks information, into fill_project_list_info() subroutine. This is preparation for smart pagination and smart searching (to make it possible to calculate/generate info only for those projects which will be shown). Small changes compared to original version to improve readability (comments, names of variables, named loops). Additionally, store both full ('descr_long') and shortened ('descr') project description in Perl's internal form (using to_utf8). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 198772c210..d7a9809027 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3559,21 +3559,24 @@ sub git_patchset_body { # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -sub git_project_list_body { - my ($projlist, $order, $from, $to, $extra, $no_header) = @_; - - my ($check_forks) = gitweb_check_feature('forks'); - +# fills project list info (age, description, owner, forks) for each +# project in the list, removing invalid projects from returned list +# NOTE: modifies $projlist, but does not remove entries from it +sub fill_project_list_info { + my ($projlist, $check_forks) = @_; my @projects; + + PROJECT: foreach my $pr (@$projlist) { - my (@aa) = git_get_last_activity($pr->{'path'}); - unless (@aa) { - next; + my (@activity) = git_get_last_activity($pr->{'path'}); + unless (@activity) { + next PROJECT; } - ($pr->{'age'}, $pr->{'age_string'}) = @aa; + ($pr->{'age'}, $pr->{'age_string'}) = @activity; if (!defined $pr->{'descr'}) { my $descr = git_get_project_description($pr->{'path'}) || ""; - $pr->{'descr_long'} = to_utf8($descr); + $descr = to_utf8($descr); + $pr->{'descr_long'} = $descr; $pr->{'descr'} = chop_str($descr, $projects_list_description_width, 5); } if (!defined $pr->{'owner'}) { @@ -3585,14 +3588,22 @@ sub git_project_list_body { ($pname !~ /\/$/) && (-d "$projectroot/$pname")) { $pr->{'forks'} = "-d $projectroot/$pname"; - } - else { + } else { $pr->{'forks'} = 0; } } push @projects, $pr; } + return @projects; +} + +sub git_project_list_body { + my ($projlist, $order, $from, $to, $extra, $no_header) = @_; + + my ($check_forks) = gitweb_check_feature('forks'); + my @projects = fill_project_list_info($projlist, $check_forks); + $order ||= $default_projects_order; $from = 0 unless defined $from; $to = $#projects if (!defined $to || $#projects < $to); -- cgit v1.3 From 7da0f3a46daac50782a71e8a6eb12355d49c419d Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 10 Jun 2008 19:21:44 +0200 Subject: gitweb: Separate generating 'sort by' table header Extract generating table header cell, for tables which can be sorted by its columns, into print_sort_th_str() and print_sort_th_num() subroutines, and print_sort_th() driver subroutine. This avoids repetition, and should make further improvements (like JavaScript sorting) easier. The subroutine uses now "replay" link, so it is generic enough to be able to use it for other tables which can be sorted by column, like for example 'heads' and 'tags' view (sort by name, or sort by age). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 76 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d7a9809027..c7882f24f7 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3598,6 +3598,36 @@ sub fill_project_list_info { return @projects; } +# print 'sort by'
element, either sorting by $key if $name eq $order +# (changing $list), or generating 'sort by $name' replay link otherwise +sub print_sort_th { + my ($str_sort, $name, $order, $key, $header, $list) = @_; + $key ||= $name; + $header ||= ucfirst($name); + + if ($order eq $name) { + if ($str_sort) { + @$list = sort {$a->{$key} cmp $b->{$key}} @$list; + } else { + @$list = sort {$a->{$key} <=> $b->{$key}} @$list; + } + print "$header" . + $cgi->a({-href => href(-replay=>1, order=>$name), + -class => "header"}, $header) . + "Project" . - $cgi->a({-href => href(project=>undef, order=>'project'), - -class => "header"}, "Project") . - "Description" . - $cgi->a({-href => href(project=>undef, order=>'descr'), - -class => "header"}, "Description") . - "Owner" . - $cgi->a({-href => href(project=>undef, order=>'owner'), - -class => "header"}, "Owner") . - "Last Change" . - $cgi->a({-href => href(project=>undef, order=>'age'), - -class => "header"}, "Last Change") . - "
element, either sorting by $key if $name eq $order -# (changing $list), or generating 'sort by $name' replay link otherwise +# print 'sort by' element, generating 'sort by $name' replay link +# if that order is not selected sub print_sort_th { - my ($str_sort, $name, $order, $key, $header, $list) = @_; - $key ||= $name; + my ($name, $order, $header) = @_; $header ||= ucfirst($name); if ($order eq $name) { - if ($str_sort) { - @$list = sort {$a->{$key} cmp $b->{$key}} @$list; - } else { - @$list = sort {$a->{$key} <=> $b->{$key}} @$list; - } print "$header" . @@ -3627,14 +3621,6 @@ sub print_sort_th { } } -sub print_sort_th_str { - print_sort_th(1, @_); -} - -sub print_sort_th_num { - print_sort_th(0, @_); -} - sub git_project_list_body { my ($projlist, $order, $from, $to, $extra, $no_header) = @_; @@ -3645,20 +3631,29 @@ sub git_project_list_body { $from = 0 unless defined $from; $to = $#projects if (!defined $to || $#projects < $to); + my %order_info = ( + project => { key => 'path', type => 'str' }, + descr => { key => 'descr_long', type => 'str' }, + owner => { key => 'owner', type => 'str' }, + age => { key => 'age', type => 'num' } + ); + my $oi = $order_info{$order}; + if ($oi->{'type'} eq 'str') { + @projects = sort {$a->{$oi->{'key'}} cmp $b->{$oi->{'key'}}} @projects; + } else { + @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @projects; + } + print "\n"; unless ($no_header) { print "\n"; if ($check_forks) { print "\n"; } - print_sort_th_str('project', $order, 'path', - 'Project', \@projects); - print_sort_th_str('descr', $order, 'descr_long', - 'Description', \@projects); - print_sort_th_str('owner', $order, 'owner', - 'Owner', \@projects); - print_sort_th_num('age', $order, 'age', - 'Last Change', \@projects); + print_sort_th('project', $order, 'Project'); + print_sort_th('descr', $order, 'Description'); + print_sort_th('owner', $order, 'Owner'); + print_sort_th('age', $order, 'Last Change'); print "\n" . # for links "\n"; } -- cgit v1.3 From f04f27e8b2a62f62d3ba168f1de4e45265830bff Mon Sep 17 00:00:00 2001 From: Mike Ralphson Date: Thu, 25 Sep 2008 18:48:48 +0200 Subject: gitweb: Sort the list of forks on the summary page by age The list of forks on the summary page was unsorted, this just makes them sorted by age, which seems a fair way to decide which forks are shown before the list size cut-off (15) kicks in. s/noheader/no_header was just to make it obvious what the parameter affects, so all the code can be found with one grep. pb: As suggested by Mike, I have augmented this by an additional patch that refactors the sorting logic so that it is not tied to printing the headers. Signed-off-by: Mike Ralphson Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 58ffff8be7..43da3a7932 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4119,10 +4119,10 @@ sub git_summary { if (@forklist) { git_print_header_div('forks'); - git_project_list_body(\@forklist, undef, 0, 15, + git_project_list_body(\@forklist, 'age', 0, 15, $#forklist <= 15 ? undef : $cgi->a({-href => href(action=>"forks")}, "..."), - 'noheader'); + 'no_header'); } git_footer_html(); -- cgit v1.3 From 25dfd171d646c38f9344d8e3d8ae0fdf179dd281 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Wed, 1 Oct 2008 22:11:54 +0200 Subject: gitweb: Quote non-displayable characters in hex, not octal For the last 30 years, the mankind uses the octal representation of characters only in rare cases and most character codes are hardly recognizable in octal. In contrast, many programmers still know hexadecimal well and that is also the representation of choice e.g. for Unicode codepoints. Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 18e70a3663..eb2943a530 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -775,7 +775,7 @@ sub quot_cec { ); my $chr = ( (exists $es{$cntrl}) ? $es{$cntrl} - : sprintf('\%03o', ord($cntrl)) ); + : sprintf('\%2x', ord($cntrl)) ); if ($opts{-nohtml}) { return $chr; } else { -- cgit v1.3 From b65910fec21db070ac40521e4b375fca76d27c90 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Mon, 29 Sep 2008 15:07:42 +0200 Subject: gitweb: remove PATH_INFO from $my_url and $my_uri This patch fixes PATH_INFO handling by removing the relevant part from $my_url and $my_uri, thus making it unnecessary to specify them by hand in the gitweb configuration. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Acked-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 269f1125d9..f1ab5725c0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -27,6 +27,13 @@ our $version = "++GIT_VERSION++"; our $my_url = $cgi->url(); our $my_uri = $cgi->url(-absolute => 1); +# if we're called with PATH_INFO, we have to strip that +# from the URL to find our real URL +if (my $path_info = $ENV{"PATH_INFO"}) { + $my_url =~ s,\Q$path_info\E$,,; + $my_uri =~ s,\Q$path_info\E$,,; +} + # core git executable to use # this can just be "git" if your webserver has a sensible PATH our $GIT = "++GIT_BINDIR++/git"; -- cgit v1.3 From a476142fe78d4c9b33f07abf3a80bb52f92660b7 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 2 Oct 2008 16:25:05 +0200 Subject: gitweb: Identify all summary metadata table rows In the metadata table of the summary page, all rows have their id (or class in case of URL) set now. This for example lets sites easily disable fields they do not want to show in their custom stylesheet (e.g. they are overly technical or irrelevant for the site). Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index eb2943a530..c2732b3005 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4070,10 +4070,10 @@ sub git_summary { print "
 
\n"; print "
\n" . - "\n" . - "\n"; + "\n" . + "\n"; if (defined $cd{'rfc2822'}) { - print "\n"; + print "\n"; } # use per project git URL list in $projectroot/$project/cloneurl @@ -4083,7 +4083,7 @@ sub git_summary { @url_list = map { "$_/$project" } @git_base_url_list unless @url_list; foreach my $git_url (@url_list) { next unless $git_url; - print "\n"; + print "\n"; $url_tag = ""; } print "
description" . esc_html($descr) . "
owner" . esc_html($owner) . "
description" . esc_html($descr) . "
owner" . esc_html($owner) . "
last change$cd{'rfc2822'}
last change$cd{'rfc2822'}
$url_tag$git_url
\n"; -- cgit v1.3 From 2d7a3532c78bace2f3631ab0e594f713dcab9916 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 2 Oct 2008 16:50:04 +0200 Subject: gitweb: Fix two 'uninitialized value' warnings in git_tree() If we did try to access nonexistent directory or file, which means that git_get_hash_by_path() returns `undef`, uninitialized $hash variable was passed to 'open' call. Now we fail early with "404 Not Found - No such tree" error. (If we try to access something which does not resolve to tree-ish, for example a file / 'blob' object, the error will be caught later, as "404 Not Found - Reading tree failed" error). If we tried to use 'tree' action without $file_name ('f' parameter) set, which means either tree given by hash or a top tree (and we currently cannot distinguish between those two cases), we cannot print path breadcrumbs with git_print_page_path(). Fix this by moving call to git_print_page_path() inside conditional. Signed-off-by: Jakub Narebski Acked-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f1ab5725c0..eae5084c66 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4421,6 +4421,7 @@ sub git_tree { $hash = $hash_base; } } + die_error(404, "No such tree") unless defined($hash); $/ = "\0"; open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash or die_error(500, "Open git-ls-tree failed"); @@ -4461,8 +4462,8 @@ sub git_tree { if ($basedir ne '' && substr($basedir, -1) ne '/') { $basedir .= '/'; } + git_print_page_path($file_name, 'tree', $hash_base); } - git_print_page_path($file_name, 'tree', $hash_base); print "
\n"; print "\n"; my $alternate = 1; -- cgit v1.3 From d627f68fbbe0480337cd56cce442ed8c1efa230e Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 2 Oct 2008 16:36:52 +0200 Subject: gitweb: Add support for extending the action bar with custom links This makes it possible to easily extend gitweb with custom functionality, e.g. git-browser or web-based repository administration system like the repo.or.cz/Girocco duct tape. Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 43da3a7932..453cbac7d8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -275,6 +275,26 @@ our %feature = ( 'forks' => { 'override' => 0, 'default' => [0]}, + + # Insert custom links to the action bar of all project pages. + # This enables you mainly to link to third-party scripts integrating + # into gitweb; e.g. git-browser for graphical history representation + # or custom web-based repository administration interface. + + # The 'default' value consists of a list of triplets in the form + # (label, link, position) where position is the label after which + # to inster the link and link is a format string where %n expands + # to the project name, %f to the project path within the filesystem, + # %h to the current hash (h gitweb parameter) and %b to the current + # hash base (hb gitweb parameter). + + # To enable system wide have in $GITWEB_CONFIG e.g. + # $feature{'actions'}{'default'} = [('graphiclog', + # '/git-browser/by-commit.html?r=%n', 'summary')]; + # Project specific override is not supported. + 'actions' => { + 'override' => 0, + 'default' => []}, ); sub gitweb_check_feature { @@ -2757,13 +2777,26 @@ sub git_print_page_nav { } } } + $arg{'tree'}{'hash'} = $treehead if defined $treehead; $arg{'tree'}{'hash_base'} = $treebase if defined $treebase; + my @actions = gitweb_check_feature('actions'); + while (@actions) { + my ($label, $link, $pos) = (shift(@actions), shift(@actions), shift(@actions)); + @navs = map { $_ eq $pos ? ($_, $label) : $_ } @navs; + # munch munch + $link =~ s#%n#$project#g; + $link =~ s#%f#$git_dir#g; + $treehead ? $link =~ s#%h#$treehead#g : $link =~ s#%h##g; + $treebase ? $link =~ s#%b#$treebase#g : $link =~ s#%b##g; + $arg{$label}{'_href'} = $link; + } + print "
\n" . (join " | ", map { $_ eq $current ? - $_ : $cgi->a({-href => href(%{$arg{$_}})}, "$_") + $_ : $cgi->a({-href => ($arg{$_}{_href} ? $arg{$_}{_href} : href(%{$arg{$_}}))}, "$_") } @navs); print "
\n$extra
\n" . "
\n"; -- cgit v1.3 From aed93de428d7d12ee23d84d27265af1e37eb348f Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 2 Oct 2008 17:13:02 +0200 Subject: gitweb: Support for tag clouds The "Content tags" (nothing to do with usual Git tags!) are free-form strings that are attached to random projects and displayed in the well-known Web2.0-ish tag cloud above project list. The feature will make use of HTML::TagCloud if available, but will still display (less pretty) list of tags in case the module is not installed. The tagging itself is not done by gitweb - user-provided external helper CGI needs to be provided; one example is the tagproj.cgi of Girocco. This functionality might get integrated to gitweb in the future. The tags are stored one-per-file in ctags/ subdirectory. The reason they are not stored in the project config file is that you usually want to give anyone (even CGI scripts) permission to create new tags and they are non-essential information, and thus you would make the ctags/ subdirectory world-writable. Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 83f810ad46..0cb29705b2 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -282,6 +282,24 @@ our %feature = ( 'forks' => { 'override' => 0, 'default' => [0]}, + + # Allow gitweb scan project content tags described in ctags/ + # of project repository, and display the popular Web 2.0-ish + # "tag cloud" near the project list. Note that this is something + # COMPLETELY different from the normal Git tags. + + # gitweb by itself can show existing tags, but it does not handle + # tagging itself; you need an external application for that. + # For an example script, check Girocco's cgi/tagproj.cgi. + # You may want to install the HTML::TagCloud Perl module to get + # a pretty tag cloud instead of just a list of tags. + + # To enable system wide have in $GITWEB_CONFIG + # $feature{'ctags'}{'default'} = ['path_to_tag_script']; + # Project specific override is not supported. + 'ctags' => { + 'override' => 0, + 'default' => [0]}, ); sub gitweb_check_feature { @@ -1762,6 +1780,67 @@ sub git_get_project_description { return $descr; } +sub git_get_project_ctags { + my $path = shift; + my $ctags = {}; + + $git_dir = "$projectroot/$path"; + foreach (<$git_dir/ctags/*>) { + open CT, $_ or next; + my $val = ; + chomp $val; + close CT; + my $ctag = $_; $ctag =~ s#.*/##; + $ctags->{$ctag} = $val; + } + $ctags; +} + +sub git_populate_project_tagcloud { + my $ctags = shift; + + # First, merge different-cased tags; tags vote on casing + my %ctags_lc; + foreach (keys %$ctags) { + $ctags_lc{lc $_}->{count} += $ctags->{$_}; + if (not $ctags_lc{lc $_}->{topcount} + or $ctags_lc{lc $_}->{topcount} < $ctags->{$_}) { + $ctags_lc{lc $_}->{topcount} = $ctags->{$_}; + $ctags_lc{lc $_}->{topname} = $_; + } + } + + my $cloud; + if (eval { require HTML::TagCloud; 1; }) { + $cloud = HTML::TagCloud->new; + foreach (sort keys %ctags_lc) { + # Pad the title with spaces so that the cloud looks + # less crammed. + my $title = $ctags_lc{$_}->{topname}; + $title =~ s/ / /g; + $title =~ s/^/ /g; + $title =~ s/$/ /g; + $cloud->add($title, $home_link."?by_tag=".$_, $ctags_lc{$_}->{count}); + } + } else { + $cloud = \%ctags_lc; + } + $cloud; +} + +sub git_show_project_tagcloud { + my ($cloud, $count) = @_; + print STDERR ref($cloud)."..\n"; + if (ref $cloud eq 'HTML::TagCloud') { + return $cloud->html_and_css($count); + } else { + my @tags = sort { $cloud->{$a}->{count} <=> $cloud->{$b}->{count} } keys %$cloud; + return '

' . join (', ', map { + "$cloud->{$_}->{topname}" + } splice(@tags, 0, $count)) . '

'; + } +} + sub git_get_project_url_list { my $path = shift; @@ -3580,6 +3659,7 @@ sub fill_project_list_info { my ($projlist, $check_forks) = @_; my @projects; + my $show_ctags = gitweb_check_feature('ctags'); PROJECT: foreach my $pr (@$projlist) { my (@activity) = git_get_last_activity($pr->{'path'}); @@ -3606,6 +3686,7 @@ sub fill_project_list_info { $pr->{'forks'} = 0; } } + $show_ctags and $pr->{'ctags'} = git_get_project_ctags($pr->{'path'}); push @projects, $pr; } @@ -3652,6 +3733,18 @@ sub git_project_list_body { $from = 0 unless defined $from; $to = $#projects if (!defined $to || $#projects < $to); + my $show_ctags = gitweb_check_feature('ctags'); + if ($show_ctags) { + my %ctags; + foreach my $p (@projects) { + foreach my $ct (keys %{$p->{'ctags'}}) { + $ctags{$ct} += $p->{'ctags'}->{$ct}; + } + } + my $cloud = git_populate_project_tagcloud(\%ctags); + print git_show_project_tagcloud($cloud, 64); + } + print "
\n"; unless ($no_header) { print "\n"; @@ -3670,8 +3763,10 @@ sub git_project_list_body { "\n"; } my $alternate = 1; + my $tagfilter = $cgi->param('by_tag'); for (my $i = $from; $i <= $to; $i++) { my $pr = $projects[$i]; + next if $tagfilter and $show_ctags and not grep { lc $_ eq lc $tagfilter } keys %{$pr->{'ctags'}}; if ($alternate) { print "\n"; } else { @@ -4093,6 +4188,20 @@ sub git_summary { print "\n"; $url_tag = ""; } + + # Tag cloud + my $show_ctags = (gitweb_check_feature('ctags'))[0]; + if ($show_ctags) { + my $ctags = git_get_project_ctags($project); + my $cloud = git_populate_project_tagcloud($ctags); + print "\n\n"; + } + print "
Content tags:
"; + print "
" unless %$ctags; + print "
Add:
"; + print "
" if %$ctags; + print git_show_project_tagcloud($cloud, 48); + print "
\n"; if (-s "$projectroot/$project/README.html") { -- cgit v1.3 From 42326110b5bb208e0a64e91aeca69a4f0cf5759e Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Thu, 2 Oct 2008 17:17:01 +0200 Subject: gitweb: Make the by_tag filter delve in forks as well This requires us to build a full index including forks and then weed them out only when printing. Signed-off-by: Petr Baudis Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 0cb29705b2..99fdb13f1f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1889,9 +1889,7 @@ sub git_get_projects_list { my $subdir = substr($File::Find::name, $pfxlen + 1); # we check related file in $projectroot - if ($check_forks and $subdir =~ m#/.#) { - $File::Find::prune = 1; - } elsif (check_export_ok("$projectroot/$filter/$subdir")) { + if (check_export_ok("$projectroot/$filter/$subdir")) { push @list, { path => ($filter ? "$filter/" : '') . $subdir }; $File::Find::prune = 1; } @@ -3724,6 +3722,7 @@ sub print_sort_th_num { } sub git_project_list_body { + # actually uses global variable $project my ($projlist, $order, $from, $to, $extra, $no_header) = @_; my ($check_forks) = gitweb_check_feature('forks'); @@ -3766,7 +3765,15 @@ sub git_project_list_body { my $tagfilter = $cgi->param('by_tag'); for (my $i = $from; $i <= $to; $i++) { my $pr = $projects[$i]; + next if $tagfilter and $show_ctags and not grep { lc $_ eq lc $tagfilter } keys %{$pr->{'ctags'}}; + # Weed out forks + if ($check_forks) { + my $forkbase = $project; $forkbase ||= ''; $forkbase =~ s#\.git$#/#; + $forkbase="^$forkbase" if $forkbase; + next if not $tagfilter and $pr->{'path'} =~ m#$forkbase.*/.*#; # regexp-safe + } + if ($alternate) { print "
\n"; if (-s "$projectroot/$project/README.html") { - if (open my $fd, "$projectroot/$project/README.html") { - print "
readme
\n" . - "
\n"; - print $_ while (<$fd>); - print "\n
\n"; # class="readme" - close $fd; - } + print "
readme
\n" . + "
\n"; + insert_file("$projectroot/$project/README.html"); + print "\n
\n"; # class="readme" } # we need to request one more than 16 (0..15) to check if -- cgit v1.3 From bcc6a833032e0830195c1de1b834006a1d0156fe Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 7 Dec 2008 10:36:36 +0100 Subject: gitweb: Make project specific override for 'grep' feature work The 'grep' feature was marked in the comments as having project specific config, but it lacked 'sub' key required for it to work. Kind-of-Noticed-by: Matt Kraai Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 1 + 1 file changed, 1 insertion(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index eae5084c66..ced7bb740f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -232,6 +232,7 @@ our %feature = ( # $feature{'grep'}{'override'} = 1; # and in project config gitweb.grep = 0|1; 'grep' => { + 'sub' => \&feature_grep, 'override' => 0, 'default' => [1]}, -- cgit v1.3 From 4586864afee675eb1c617666f806664aef04a02a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 8 Dec 2008 14:13:21 +0100 Subject: gitweb: Fix bug in insert_file() subroutine In insert_file() subroutine (which is used to insert HTML fragments as custom header, footer, hometext (for projects list view), and per project README.html (for summary view)) we used: map(to_utf8, <$fd>); This doesn't work, and other form has to be used: map { to_utf8($_) } <$fd>; Now with test for t9600 added, for $GIT_DIR/README.html. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- t/t9500-gitweb-standalone-no-errors.sh | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 951739210a..6eb370d8de 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2764,7 +2764,7 @@ sub insert_file { my $filename = shift; open my $fd, '<', $filename; - print map(to_utf8, <$fd>); + print map { to_utf8($_) } <$fd>; close $fd; } diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 64c4cce58b..43cd6eecba 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -673,4 +673,14 @@ test_expect_success \ gitweb_run "p=.git;a=tree"' test_debug 'cat gitweb.log' +# ---------------------------------------------------------------------- +# non-ASCII in README.html + +test_expect_success \ + 'README.html with non-ASCII characters (utf-8)' \ + 'echo "UTF-8 example:
" > .git/README.html && + cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html && + gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + test_done -- cgit v1.3 From 4a24bfc22081a6c2771b62d464222f81c470192c Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 9 Dec 2008 23:46:16 +0100 Subject: gitweb: Move 'lineno' id from link to row element in git_blame Move l ID from link element inside table row (inside cell element for column with line numbers), to encompassing
$parent_commit); print ""; print $cgi->a({ -href => "$blamed#l$orig_lineno", - -id => "l$lineno", -class => "linenr" }, esc_html($lineno)); print "
HTML - my %metainfo = (); - while (1) { - $_ = <$fd>; - last unless defined $_; + LINE: + while (my $line = <$fd>) { + chomp $line; + # the header: [] + # no for subsequent lines in group of lines my ($full_rev, $orig_lineno, $lineno, $group_size) = - /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/; + ($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/); if (!exists $metainfo{$full_rev}) { $metainfo{$full_rev} = {}; } my $meta = $metainfo{$full_rev}; - while (<$fd>) { - last if (s/^\t//); - if (/^(\S+) (.*)$/) { + my $data; + while ($data = <$fd>) { + chomp $data; + last if ($data =~ s/^\t//); # contents of line + if ($data =~ /^(\S+) (.*)$/) { $meta->{$1} = $2; } } - my $data = $_; - chomp $data; - my $rev = substr($full_rev, 0, 8); + my $short_rev = substr($full_rev, 0, 8); my $author = $meta->{'author'}; - my %date = parse_date($meta->{'author-time'}, - $meta->{'author-tz'}); + my %date = + parse_date($meta->{'author-time'}, $meta->{'author-tz'}); my $date = $date{'iso-tz'}; if ($group_size) { - $current_color = ++$current_color % $num_colors; + $current_color = ($current_color + 1) % $num_colors; } print "\n"; if ($group_size) { @@ -4654,7 +4663,7 @@ HTML print $cgi->a({-href => href(action=>"commit", hash=>$full_rev, file_name=>$file_name)}, - esc_html($rev)); + esc_html($short_rev)); print "\n"; } open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^") @@ -4677,6 +4686,8 @@ HTML print ""; close $fd or print "Reading blob failed\n"; + + # page footer git_footer_html(); } -- cgit v1.3 From 39c19ce2755830dd1dfdabf36e2b0166df3546f8 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 11 Dec 2008 01:33:29 +0100 Subject: gitweb: cache $parent_commit info in git_blame() Luben Tuikov changed 'lineno' link from leading to commit which gave current version of given block of lines, to leading to parent of this commit in 244a70e (Blame "linenr" link jumps to previous state at "orig_lineno"). This made possible data mining using 'blame' view. The current implementation calls rev-parse once per each blamed line to find parent revision of blamed commit, even when the same commit appears more than once, which is inefficient. This patch mitigates this issue by caching $parent_commit info in %metainfo, which makes gitweb call rev-parse only once per each unique commit in the output from "git blame". In the tables below you can see simple benchmark comparing gitweb performance before and after this patch File | L[1] | C[2] || Time0[3] | Before[4] | After[4] ==================================================================== blob.h | 18 | 4 || 0m1.727s | 0m2.545s | 0m2.474s GIT-VERSION-GEN | 42 | 13 || 0m2.165s | 0m2.448s | 0m2.071s README | 46 | 6 || 0m1.593s | 0m2.727s | 0m2.242s revision.c | 1923 | 121 || 0m2.357s | 0m30.365s | 0m7.028s gitweb/gitweb.perl | 6291 | 428 || 0m8.080s | 1m37.244s | 0m20.627s File | L/C | Before/After ========================================= blob.h | 4.5 | 1.03 GIT-VERSION-GEN | 3.2 | 1.18 README | 7.7 | 1.22 revision.c | 15.9 | 4.32 gitweb/gitweb.perl | 14.7 | 4.71 As you can see the greater ratio of lines in file to unique commits in blame output, the greater gain from the new implementation. Legend: [1] Number of lines: $ wc -l [2] Number of unique commits in the blame output: $ git blame -p | grep author-time | wc -l [3] Time for running "git blame -p" (user time, single run): $ time git blame -p >/dev/null [4] Time to run gitweb as Perl script from command line: $ gitweb-run.sh "p=.git;a=blame;f=" > /dev/null 2>&1 The gitweb-run.sh script includes slightly modified (with adjusted pathnames) code from gitweb_run() function from the test script t/t9500-gitweb-standalone-no-errors.sh; gitweb config file gitweb_config.perl contents (again up to adjusting pathnames; in particular $projectroot variable should point to top directory of git repository) can be found in the same place. Discussion ~~~~~~~~~~ A possible future improvement would be to open a bidi pipe to "git cat-file --batch-check", (like in Git::Repo in gitweb caching by Lea Wiemann), feed $long_rev^ to it, and parse its output, which is in the following form: 926b07e694599d86cec668475071b32147c95034 commit 637 This would mean one call to git-cat-file for the whole 'blame' view, instead of one call to git-rev-parse per each unique commit in blame output. Yet another solution would be to change use of validate_refname() to validate_revision() when checking script parameters (CGI query or path_info), with validate_revision being something like the following: sub validate_revision { my $rev = shift; return validate_refname(strip_rev_suffixes($rev)); } so we don't need to calculate $long_rev^, but can pass "$long_rev^" as 'hb' parameter. This solution has the advantage that it can be easily adapted to future incremental blame output. Signed-off-by: Jakub Narebski Acked-by: Luben Tuikov Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ccbf5d4745..f992de223d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4666,11 +4666,17 @@ HTML esc_html($short_rev)); print "\n"; } - open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^") - or die_error(500, "Open git-rev-parse failed"); - my $parent_commit = <$dd>; - close $dd; - chomp($parent_commit); + my $parent_commit; + if (!exists $meta->{'parent'}) { + open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^") + or die_error(500, "Open git-rev-parse failed"); + $parent_commit = <$dd>; + close $dd; + chomp($parent_commit); + $meta->{'parent'} = $parent_commit; + } else { + $parent_commit = $meta->{'parent'}; + } my $blamed = href(action => 'blame', file_name => $meta->{'filename'}, hash_base => $parent_commit); -- cgit v1.3 From cdad8170b223a73dc37197d5ba78a3ac7b824406 Mon Sep 17 00:00:00 2001 From: Matt Kraai Date: Mon, 15 Dec 2008 22:16:19 -0800 Subject: gitweb: unify boolean feature subroutines The boolean feature subroutines behaved identically except for the name of the configuration option, so make that a parameter and unify them. Signed-off-by: Matt Kraai Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6eb370d8de..827e5c5137 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -203,7 +203,7 @@ our %feature = ( # $feature{'blame'}{'override'} = 1; # and in project config gitweb.blame = 0|1; 'blame' => { - 'sub' => \&feature_blame, + 'sub' => sub { feature_bool('blame', @_) }, 'override' => 0, 'default' => [0]}, @@ -241,7 +241,7 @@ our %feature = ( # $feature{'grep'}{'override'} = 1; # and in project config gitweb.grep = 0|1; 'grep' => { - 'sub' => \&feature_grep, + 'sub' => sub { feature_bool('grep', @_) }, 'override' => 0, 'default' => [1]}, @@ -255,7 +255,7 @@ our %feature = ( # $feature{'pickaxe'}{'override'} = 1; # and in project config gitweb.pickaxe = 0|1; 'pickaxe' => { - 'sub' => \&feature_pickaxe, + 'sub' => sub { feature_bool('pickaxe', @_) }, 'override' => 0, 'default' => [1]}, @@ -363,16 +363,17 @@ sub gitweb_check_feature { } -sub feature_blame { - my ($val) = git_get_project_config('blame', '--bool'); +sub feature_bool { + my $key = shift; + my ($val) = git_get_project_config($key, '--bool'); if ($val eq 'true') { - return 1; + return (1); } elsif ($val eq 'false') { - return 0; + return (0); } - return $_[0]; + return ($_[0]); } sub feature_snapshot { @@ -387,30 +388,6 @@ sub feature_snapshot { return @fmts; } -sub feature_grep { - my ($val) = git_get_project_config('grep', '--bool'); - - if ($val eq 'true') { - return (1); - } elsif ($val eq 'false') { - return (0); - } - - return ($_[0]); -} - -sub feature_pickaxe { - my ($val) = git_get_project_config('pickaxe', '--bool'); - - if ($val eq 'true') { - return (1); - } elsif ($val eq 'false') { - return (0); - } - - return ($_[0]); -} - # checking HEAD file with -e is fragile if the repository was # initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed # and then pruned. -- cgit v1.3 From b54dc9fdb993a54bba11df3f247e836158b8c1f0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 16 Dec 2008 19:42:02 -0800 Subject: gitweb: do not run "git diff" that is Porcelain Jakub says that legacy-style URI to view two blob differences are never generated since 1.4.3. This codepath runs "git diff" Porcelain from the gitweb, which is a no-no. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 40 +++------------------------------------- 1 file changed, 3 insertions(+), 37 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6eb370d8de..8f574c7b36 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5285,43 +5285,9 @@ sub git_blobdiff { or die_error(500, "Open git-diff-tree failed"); } - # old/legacy style URI - if (!%diffinfo && # if new style URI failed - defined $hash && defined $hash_parent) { - # fake git-diff-tree raw output - $diffinfo{'from_mode'} = $diffinfo{'to_mode'} = "blob"; - $diffinfo{'from_id'} = $hash_parent; - $diffinfo{'to_id'} = $hash; - if (defined $file_name) { - if (defined $file_parent) { - $diffinfo{'status'} = '2'; - $diffinfo{'from_file'} = $file_parent; - $diffinfo{'to_file'} = $file_name; - } else { # assume not renamed - $diffinfo{'status'} = '1'; - $diffinfo{'from_file'} = $file_name; - $diffinfo{'to_file'} = $file_name; - } - } else { # no filename given - $diffinfo{'status'} = '2'; - $diffinfo{'from_file'} = $hash_parent; - $diffinfo{'to_file'} = $hash; - } - - # non-textual hash id's can be cached - if ($hash =~ m/^[0-9a-fA-F]{40}$/ && - $hash_parent =~ m/^[0-9a-fA-F]{40}$/) { - $expires = '+1d'; - } - - # open patch output - open $fd, "-|", git_cmd(), "diff", @diff_opts, - '-p', ($format eq 'html' ? "--full-index" : ()), - $hash_parent, $hash, "--" - or die_error(500, "Open git-diff failed"); - } else { - die_error(400, "Missing one of the blob diff parameters") - unless %diffinfo; + # old/legacy style URI -- not generated anymore since 1.4.3. + if (!%diffinfo) { + die_error('404 Not Found', "Missing one of the blob diff parameters") } # header -- cgit v1.3 From 9872cd6f6c40803db9e784b6287db72e0cb6b5c3 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Thu, 18 Dec 2008 08:13:16 +0100 Subject: gitweb: add patch view The output of commitdiff_plain is not intended for git-am: * when given a range of commits, commitdiff_plain publishes a single patch with the message from the first commit, instead of a patchset * the hand-built email format replicates the commit summary both as email subject and as first line of the email itself, resulting in a duplication if the output is used with git-am. We thus create a new view that can be fed to git-am directly, allowing patch exchange via gitweb. The new view exposes the output of git format-patch directly, limiting it to a single patch in the case of a single commit. A configurable upper limit defaulting to 16 is imposed on the number of commits which will be included in a patchset, to prevent DoS attacks on the server. Setting the limit to 0 will disable the patch view, setting it to a negative number will remove the limit. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 95988fba4a..9a11be3d94 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -329,6 +329,21 @@ our %feature = ( 'ctags' => { 'override' => 0, 'default' => [0]}, + + # The maximum number of patches in a patchset generated in patch + # view. Set this to 0 or undef to disable patch view, or to a + # negative number to remove any limit. + + # To disable system wide have in $GITWEB_CONFIG + # $feature{'patches'}{'default'} = [0]; + # To have project specific config enable override in $GITWEB_CONFIG + # $feature{'patches'}{'override'} = 1; + # and in project config gitweb.patches = 0|n; + # where n is the maximum number of patches allowed in a patchset. + 'patches' => { + 'sub' => \&feature_patches, + 'override' => 0, + 'default' => [16]}, ); sub gitweb_get_feature { @@ -410,6 +425,16 @@ sub feature_pickaxe { return ($_[0]); } +sub feature_patches { + my @val = (git_get_project_config('patches', '--int')); + + if (@val) { + return @val; + } + + return ($_[0]); +} + # checking HEAD file with -e is fragile if the repository was # initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed # and then pruned. @@ -503,6 +528,7 @@ our %actions = ( "heads" => \&git_heads, "history" => \&git_history, "log" => \&git_log, + "patch" => \&git_patch, "rss" => \&git_rss, "atom" => \&git_atom, "search" => \&git_search, @@ -5386,6 +5412,13 @@ sub git_blobdiff_plain { sub git_commitdiff { my $format = shift || 'html'; + + my $patch_max; + if ($format eq 'patch') { + ($patch_max) = gitweb_get_feature('patches'); + die_error(403, "Patch view not allowed") unless $patch_max; + } + $hash ||= $hash_base || "HEAD"; my %co = parse_commit($hash) or die_error(404, "Unknown commit object"); @@ -5483,7 +5516,23 @@ sub git_commitdiff { open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, '-p', $hash_parent_param, $hash, "--" or die_error(500, "Open git-diff-tree failed"); - + } elsif ($format eq 'patch') { + # For commit ranges, we limit the output to the number of + # patches specified in the 'patches' feature. + # For single commits, we limit the output to a single patch, + # diverging from the git-format-patch default. + my @commit_spec = (); + if ($hash_parent) { + if ($patch_max > 0) { + push @commit_spec, "-$patch_max"; + } + push @commit_spec, '-n', "$hash_parent..$hash"; + } else { + push @commit_spec, '-1', '--root', $hash; + } + open $fd, "-|", git_cmd(), "format-patch", '--encoding=utf8', + '--stdout', @commit_spec + or die_error(500, "Open git-format-patch failed"); } else { die_error(400, "Unknown commitdiff format"); } @@ -5532,6 +5581,14 @@ sub git_commitdiff { print to_utf8($line) . "\n"; } print "---\n\n"; + } elsif ($format eq 'patch') { + my $filename = basename($project) . "-$hash.patch"; + + print $cgi->header( + -type => 'text/plain', + -charset => 'utf-8', + -expires => $expires, + -content_disposition => 'inline; filename="' . "$filename" . '"'); } # write patch @@ -5553,6 +5610,11 @@ sub git_commitdiff { print <$fd>; close $fd or print "Reading git-diff-tree failed\n"; + } elsif ($format eq 'patch') { + local $/ = undef; + print <$fd>; + close $fd + or print "Reading git-format-patch failed\n"; } } @@ -5560,6 +5622,11 @@ sub git_commitdiff_plain { git_commitdiff('plain'); } +# format-patch-style patches +sub git_patch { + git_commitdiff('patch'); +} + sub git_history { if (!defined $hash_base) { $hash_base = git_get_head_hash($project); -- cgit v1.3 From 2020985464ba0135f717cd14309ac63a8dfda341 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Thu, 18 Dec 2008 08:13:17 +0100 Subject: gitweb: change call pattern for git_commitdiff Since we are going to introduce an additional parameter for git_commitdiff to tune patch view, we switch to named/hash-based parameter passing for clarity and robustness. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 9a11be3d94..63e93a2736 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5411,7 +5411,8 @@ sub git_blobdiff_plain { } sub git_commitdiff { - my $format = shift || 'html'; + my %params = @_; + my $format = $params{-format} || 'html'; my $patch_max; if ($format eq 'patch') { @@ -5619,12 +5620,12 @@ sub git_commitdiff { } sub git_commitdiff_plain { - git_commitdiff('plain'); + git_commitdiff(-format => 'plain'); } # format-patch-style patches sub git_patch { - git_commitdiff('patch'); + git_commitdiff(-format => 'patch'); } sub git_history { -- cgit v1.3 From a3411f8a2d3acc311991cf2221efa9de81cd03f7 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Thu, 18 Dec 2008 08:13:18 +0100 Subject: gitweb: add patches view The only difference between patch and patches view is in the treatement of single commits: the former only displays a single patch, whereas the latter displays a patchset leading to the specified commit. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 63e93a2736..4b28136ba7 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -529,6 +529,7 @@ our %actions = ( "history" => \&git_history, "log" => \&git_log, "patch" => \&git_patch, + "patches" => \&git_patches, "rss" => \&git_rss, "atom" => \&git_atom, "search" => \&git_search, @@ -5529,7 +5530,15 @@ sub git_commitdiff { } push @commit_spec, '-n', "$hash_parent..$hash"; } else { - push @commit_spec, '-1', '--root', $hash; + if ($params{-single}) { + push @commit_spec, '-1'; + } else { + if ($patch_max > 0) { + push @commit_spec, "-$patch_max"; + } + push @commit_spec, "-n"; + } + push @commit_spec, '--root', $hash; } open $fd, "-|", git_cmd(), "format-patch", '--encoding=utf8', '--stdout', @commit_spec @@ -5625,6 +5634,10 @@ sub git_commitdiff_plain { # format-patch-style patches sub git_patch { + git_commitdiff(-format => 'patch', -single=> 1); +} + +sub git_patches { git_commitdiff(-format => 'patch'); } -- cgit v1.3 From 75bf2cb2983865760464ecec3fa1cd6f9d3719d5 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Thu, 18 Dec 2008 08:13:19 +0100 Subject: gitweb: link to patch(es) view in commit(diff) and (short)log view We link to patch view in commit and commitdiff view, and to patches view in log and shortlog view. In (short)log view, the link is only offered when the number of commits shown is no more than the allowed maximum number of patches. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 4b28136ba7..8a8a32ac15 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5023,6 +5023,15 @@ sub git_log { my $paging_nav = format_paging_nav('log', $hash, $head, $page, $#commitlist >= 100); + my ($patch_max) = gitweb_get_feature('patches'); + if ($patch_max) { + if ($patch_max < 0 || @commitlist <= $patch_max) { + $paging_nav .= " ⋅ " . + $cgi->a({-href => href(action=>"patches", -replay=>1)}, + "patches"); + } + } + git_header_html(); git_print_page_nav('log','', $hash,undef,undef, $paging_nav); @@ -5102,6 +5111,11 @@ sub git_commit { } @$parents ) . ')'; } + if (gitweb_check_feature('patches')) { + $formats_nav .= " | " . + $cgi->a({-href => href(action=>"patch", -replay=>1)}, + "patch"); + } if (!defined $parent) { $parent = "--root"; @@ -5415,9 +5429,8 @@ sub git_commitdiff { my %params = @_; my $format = $params{-format} || 'html'; - my $patch_max; + my ($patch_max) = gitweb_get_feature('patches'); if ($format eq 'patch') { - ($patch_max) = gitweb_get_feature('patches'); die_error(403, "Patch view not allowed") unless $patch_max; } @@ -5435,6 +5448,11 @@ sub git_commitdiff { $formats_nav = $cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)}, "raw"); + if ($patch_max) { + $formats_nav .= " | " . + $cgi->a({-href => href(action=>"patch", -replay=>1)}, + "patch"); + } if (defined $hash_parent && $hash_parent ne '-c' && $hash_parent ne '--cc') { @@ -5991,6 +6009,14 @@ sub git_shortlog { $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); } + my $patch_max = gitweb_check_feature('patches'); + if ($patch_max) { + if ($patch_max < 0 || @commitlist <= $patch_max) { + $paging_nav .= " ⋅ " . + $cgi->a({-href => href(action=>"patches", -replay=>1)}, + "patches"); + } + } git_header_html(); git_print_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav); -- cgit v1.3 From fb3bb3d1325f1d0a8cdc402a596c9a520b0ccbe6 Mon Sep 17 00:00:00 2001 From: Devin Doucette Date: Sat, 27 Dec 2008 02:39:31 -0700 Subject: gitweb: Fix export check in git_get_projects_list When $filter was empty, the path passed to check_export_ok would contain an extra '/', which some implementations of export_auth_hook are sensitive to. It makes more sense to fix this here than to handle the special case in each implementation of export_auth_hook. Signed-off-by: Devin Doucette Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8f574c7b36..99f71b47c2 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2147,8 +2147,9 @@ sub git_get_projects_list { my $subdir = substr($File::Find::name, $pfxlen + 1); # we check related file in $projectroot - if (check_export_ok("$projectroot/$filter/$subdir")) { - push @list, { path => ($filter ? "$filter/" : '') . $subdir }; + my $path = ($filter ? "$filter/" : '') . $subdir; + if (check_export_ok("$projectroot/$path")) { + push @list, { path => $path }; $File::Find::prune = 1; } }, -- cgit v1.3 From df63fbbf46c5ec855132f4c631c32b45f67b42e4 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Fri, 2 Jan 2009 13:15:28 +0100 Subject: gitweb: use href() when generating URLs in OPML Since the OPML project list view was hand-coding the RSS and HTML URLs, it didn't respect global options such as use_pathinfo. Make it use href() to ensure consistency with the rest of the gitweb setup. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 99f71b47c2..7999bb37d3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6146,8 +6146,8 @@ XML } my $path = esc_html(chop_str($proj{'path'}, 25, 5)); - my $rss = "$my_url?p=$proj{'path'};a=rss"; - my $html = "$my_url?p=$proj{'path'};a=summary"; + my $rss = href('project' => $proj{'path'}, 'action' => 'rss', -full => 1); + my $html = href('project' => $proj{'path'}, 'action' => 'summary', -full => 1); print "\n"; } print < Date: Fri, 2 Jan 2009 12:34:40 +0100 Subject: gitweb: don't use pathinfo for global actions With PATH_INFO urls, actions for the projects list (e.g. opml, project_index) were being put in the URL right after the base. The resulting URL is not properly parsed by gitweb itself, since it expects a project name as first component of the URL. Accepting global actions in use_pathinfo is not a very robust solution due to possible present and future conflicts between project names and global actions, therefore we just refuse to create PATH_INFO URLs when the project is not defined. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7999bb37d3..b16400193d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -830,7 +830,7 @@ sub href (%) { } my $use_pathinfo = gitweb_check_feature('pathinfo'); - if ($use_pathinfo) { + if ($use_pathinfo and defined $params{'project'}) { # try to put as many parameters as possible in PATH_INFO: # - project name # - action @@ -845,7 +845,7 @@ sub href (%) { $href =~ s,/$,,; # Then add the project name, if present - $href .= "/".esc_url($params{'project'}) if defined $params{'project'}; + $href .= "/".esc_url($params{'project'}); delete $params{'project'}; # since we destructively absorb parameters, we keep this -- cgit v1.3 From ae35785e3a205cea04d228b00461f4906548fcc3 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Fri, 2 Jan 2009 13:49:30 +0100 Subject: gitweb: suggest name for OPML view Suggest opml.xml as name for OPML view by providing the appropriate header, consistently with similar usage in project_index view. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b16400193d..995bc1a6a9 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6122,7 +6122,11 @@ sub git_atom { sub git_opml { my @list = git_get_projects_list(); - print $cgi->header(-type => 'text/xml', -charset => 'utf-8'); + print $cgi->header( + -type => 'text/xml', + -charset => 'utf-8', + -content_disposition => 'inline; filename="opml.xml"'); + print < -- cgit v1.3 From 1ba68ce23788dfc5cbe3501cb6b1ee95e68cf5a8 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Mon, 26 Jan 2009 12:50:11 +0100 Subject: gitweb: channel image in rss feed Define the channel image for the rss feed when the logo or favicon are defined, preferring the former to the latter. As suggested in the RSS 2.0 specifications, the image's title and link as set to the same as the channel's. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 931db4f7eb..f8a5d2e077 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6075,6 +6075,16 @@ XML "$alt_url\n" . "$descr\n" . "en\n"; + if (defined $logo || defined $favicon) { + # prefer the logo to the favicon, since RSS + # doesn't allow both + my $img = esc_url($logo || $favicon); + print "\n" . + "$img\n" . + "$title\n" . + "$alt_url\n" . + "\n"; + } } elsif ($format eq 'atom') { print < -- cgit v1.3 From ad59a7a359ffa3bf0903f1d35ccfd3910f9bbef2 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Mon, 26 Jan 2009 12:50:12 +0100 Subject: gitweb: feed generator metadata Add tag to RSS and Atom feed. Versioning info (gitweb/git core versions, separated by a literal slash) is stored in the appropriate attribute for the Atom feed, and in the tag content for the RSS feed. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f8a5d2e077..3d94f50cff 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6085,6 +6085,7 @@ XML "$alt_url\n" . "\n"; } + print "gitweb v.$version/$git_version\n"; } elsif ($format eq 'atom') { print < @@ -6111,6 +6112,7 @@ XML } else { print "$latest_date{'iso-8601'}\n"; } + print "gitweb\n"; } # contents -- cgit v1.3 From 3ac109ae4c513b12959f3661b9d8f86b99f150d0 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Mon, 26 Jan 2009 12:50:13 +0100 Subject: gitweb: rss feed managingEditor The RSS 2.0 specification allows an optional managingEditor tag for the channel, containing the "email address for person responsible for editorial content", which is basically the project owner. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3d94f50cff..cc6d0fb79e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6074,7 +6074,9 @@ XML print "$title\n" . "$alt_url\n" . "$descr\n" . - "en\n"; + "en\n" . + # project owner is responsible for 'editorial' content + "$owner\n"; if (defined $logo || defined $favicon) { # prefer the logo to the favicon, since RSS # doesn't allow both -- cgit v1.3 From 0cf31285a0e1a40745eb2a91534f6e6b54df0e2f Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Mon, 26 Jan 2009 12:50:14 +0100 Subject: gitweb: rss channel date The RSS 2.0 specifications defines not one but _two_ dates for its channel element! Woohoo! Luckily, it seems that consensus seems to be that if both are present they should be equal, except for some very obscure and discouraged cases. Since lastBuildDate would make more sense for us and pubDate seems to be the most commonly used, we defined both and make them equal. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index cc6d0fb79e..756868a7f9 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6087,6 +6087,10 @@ XML "$alt_url\n" . "\n"; } + if (%latest_date) { + print "$latest_date{'rfc2822'}\n"; + print "$latest_date{'rfc2822'}\n"; + } print "gitweb v.$version/$git_version\n"; } elsif ($format eq 'atom') { print < Date: Mon, 26 Jan 2009 12:50:15 +0100 Subject: gitweb: last-modified time should be commiter, not author The last-modified time header added by RSS to increase cache hits from readers should be set to the date the repository was last modified. The author time in this respect is not a good guess because the last commit might come from a oldish patch. Use the committer time for the last-modified header to ensure a more correct guess of the last time the repository was modified. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 756868a7f9..8c49c75f10 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6015,7 +6015,7 @@ sub git_feed { } if (defined($commitlist[0])) { %latest_commit = %{$commitlist[0]}; - %latest_date = parse_date($latest_commit{'author_epoch'}); + %latest_date = parse_date($latest_commit{'committer_epoch'}); print $cgi->header( -type => $content_type, -charset => 'utf-8', -- cgit v1.3 From cd956c73a2cce6613a6cd19df6ccb9ff1b08f79a Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Mon, 26 Jan 2009 12:50:16 +0100 Subject: gitweb: check if-modified-since for feeds Offering Last-modified header for feeds is only half the work, even if we bail out early on HEAD requests. We should also check that same date against If-modified-since, and bail out early with 304 Not Modified if that's the case. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8c49c75f10..f4defb01d9 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -6015,7 +6015,25 @@ sub git_feed { } if (defined($commitlist[0])) { %latest_commit = %{$commitlist[0]}; - %latest_date = parse_date($latest_commit{'committer_epoch'}); + my $latest_epoch = $latest_commit{'committer_epoch'}; + %latest_date = parse_date($latest_epoch); + my $if_modified = $cgi->http('IF_MODIFIED_SINCE'); + if (defined $if_modified) { + my $since; + if (eval { require HTTP::Date; 1; }) { + $since = HTTP::Date::str2time($if_modified); + } elsif (eval { require Time::ParseDate; 1; }) { + $since = Time::ParseDate::parsedate($if_modified, GMT => 1); + } + if (defined $since && $latest_epoch <= $since) { + print $cgi->header( + -type => $content_type, + -charset => 'utf-8', + -last_modified => $latest_date{'rfc2822'}, + -status => '304 Not Modified'); + return; + } + } print $cgi->header( -type => $content_type, -charset => 'utf-8', -- cgit v1.3 From c3254aeecf89a620db262480a7c424e7607f1e2a Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sat, 31 Jan 2009 02:31:50 +0100 Subject: gitweb: make static files accessible with PATH_INFO Gitweb links to a number of static files such as CSS stylesheets, favicon or the git logo. When, such as with the default Makefile, the paths to these files are relative (i.e. doesn't start with a "/"), the files become inaccessible in any view other tha project list and summary page if gitweb is invoked with a non-empty PATH_INFO. Fix this by adding a element pointing to the script's own URL, which ensure that all relative paths will be resolved correctly. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f4defb01d9..87948fc422 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2901,6 +2901,11 @@ sub git_header_html { $title EOF +# the stylesheet, favicon etc urls won't work correctly with path_info unless we +# set the appropriate base URL + if ($ENV{'PATH_INFO'}) { + print '\n'; + } # print out each stylesheet that exist if (defined $stylesheet) { #provides backwards capability for those people who define style sheet in a config file -- cgit v1.3 From 0dbf027ad2fc946cb63330146560962fa5d43d2d Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sat, 31 Jan 2009 02:31:51 +0100 Subject: gitweb: webserver config for PATH_INFO Document some possible Apache configurations when the path_info feature is enabled in gitweb. Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/README | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index 825162a0b6..52ad88b34e 100644 --- a/gitweb/README +++ b/gitweb/README @@ -322,6 +322,82 @@ something like the following in your gitweb.conf (or gitweb_config.perl) file: $home_link = "/"; +PATH_INFO usage +----------------------- +If you enable PATH_INFO usage in gitweb by putting + + $feature{'pathinfo'}{'default'} = [1]; + +in your gitweb.conf, it is possible to set up your server so that it +consumes and produces URLs in the form + +http://git.example.com/project.git/shortlog/sometag + +by using a configuration such as the following, that assumes that +/var/www/gitweb is the DocumentRoot of your webserver, and that it +contains the gitweb.cgi script and complementary static files +(stylesheet, favicon): + + + ServerAlias git.example.com + + DocumentRoot /var/www/gitweb + + + Options ExecCGI + AddHandler cgi-script cgi + + DirectoryIndex gitweb.cgi + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^.* /gitweb.cgi/$0 [L,PT] + + + +The rewrite rule guarantees that existing static files will be properly +served, whereas any other URL will be passed to gitweb as PATH_INFO +parameter. + +Notice that in this case you don't need special settings for +@stylesheets, $my_uri and $home_link, but you lose "dumb client" access +to your project .git dirs. A possible workaround for the latter is the +following: in your project root dir (e.g. /pub/git) have the projects +named without a .git extension (e.g. /pub/git/project instead of +/pub/git/project.git) and configure Apache as follows: + + + ServerAlias git.example.com + + DocumentRoot /var/www/gitweb + + AliasMatch ^(/.*?)(\.git)(/.*)? /pub/git$1$3 + + Options ExecCGI + AddHandler cgi-script cgi + + DirectoryIndex gitweb.cgi + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^.* /gitweb.cgi/$0 [L,PT] + + + +The additional AliasMatch makes it so that + +http://git.example.com/project.git + +will give raw access to the project's git dir (so that the project can +be cloned), while + +http://git.example.com/project + +will provide human-friendly gitweb access. + + Originally written by: Kay Sievers -- cgit v1.3 From 41a4d16e200d24b2435148e974b665429931abc9 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sat, 31 Jan 2009 02:31:52 +0100 Subject: gitweb: align comments to code Signed-off-by: Giuseppe Bilotta Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 87948fc422..f27dbb6bf4 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2901,14 +2901,14 @@ sub git_header_html { $title EOF -# the stylesheet, favicon etc urls won't work correctly with path_info unless we -# set the appropriate base URL + # the stylesheet, favicon etc urls won't work correctly with path_info + # unless we set the appropriate base URL if ($ENV{'PATH_INFO'}) { print '\n'; } -# print out each stylesheet that exist + # print out each stylesheet that exist, providing backwards capability + # for those people who defined $stylesheet in a config file if (defined $stylesheet) { -#provides backwards capability for those people who define style sheet in a config file print ''."\n"; } else { foreach my $stylesheet (@stylesheets) { -- cgit v1.3 From e80f97e20c8122f79450e1f40f569df0b52773e9 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 1 Feb 2009 22:37:45 +0100 Subject: gitweb: Update README that gitweb works better with PATH_INFO One had to configure gitweb for it to find static files (stylesheets, images) when using path_info URLs. Now that it is not necessary thanks to adding BASE element to HTML head if needed, update README to reflect this fact. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/README | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index 52ad88b34e..a9dc2e57d9 100644 --- a/gitweb/README +++ b/gitweb/README @@ -162,14 +162,12 @@ not include variables usually directly set during build): $GITWEB_LIST during installation. If empty, $projectroot is used to scan for repositories. * $my_url, $my_uri - URL and absolute URL of gitweb script; you might need to set those - variables if you are using 'pathinfo' feature: see also below. + Full URL and absolute URL of gitweb script; + in earlier versions of gitweb you might have need to set those + variables, now there should be no need to do it. * $home_link Target of the home link on top of all pages (the first part of view - "breadcrumbs"). By default set to absolute URI of a page; you might - need to set it up to [base] gitweb URI if you use 'pathinfo' feature - (alternative format of the URLs, with project name embedded directly - in the path part of URL). + "breadcrumbs"). By default set to absolute URI of a page ($my_uri). * @stylesheets List of URIs of stylesheets (relative to base URI of a page). You might specify more than one stylesheet, for example use gitweb.css -- cgit v1.3 From ccb04f99fe3858bae0f06fc7aeefc4d53fec1352 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 6 Feb 2009 10:12:41 +0100 Subject: gitweb: Better regexp for SHA-1 committag match Make SHA-1 regexp to be turned into hyperlink (the SHA-1 committag) to match word boundary at the beginning and the end. This way we reduce number of false matches, for example we now don't match 0x74a5cd01 which is hex decimal (for example memory address), but is not SHA-1. Suggested-by: Johannes Schindelin Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index f27dbb6bf4..bec1af6b73 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1364,7 +1364,7 @@ sub format_log_line_html { my $line = shift; $line = esc_html($line, -nbsp=>1); - if ($line =~ m/([0-9a-fA-F]{8,40})/) { + if ($line =~ m/\b([0-9a-fA-F]{8,40})\b/) { my $hash_text = $1; my $link = $cgi->a({-href => href(action=>"object", hash=>$hash_text), -- cgit v1.3 From 7e1100e9e939c9178b2aa3969349e9e8d34488bf Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Sat, 7 Feb 2009 19:00:09 -0500 Subject: gitweb: add $prevent_xss option to prevent XSS by repository content Add a gitweb configuration variable $prevent_xss that disables features to prevent content in repositories from launching cross-site scripting (XSS) attacks in the gitweb domain. Currently, this option makes gitweb ignore README.html (a better solution may be worked out in the future) and serve a blob_plain file of an untrusted type with "Content-Disposition: attachment", which tells the browser not to show the file at its original URL. The XSS prevention is currently off by default. Signed-off-by: Matt McCutchen Signed-off-by: Junio C Hamano --- gitweb/README | 9 ++++++++- gitweb/gitweb.perl | 21 +++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index 825162a0b6..19ae28ef9b 100644 --- a/gitweb/README +++ b/gitweb/README @@ -214,6 +214,11 @@ not include variables usually directly set during build): Rename detection options for git-diff and git-diff-tree. By default ('-M'); set it to ('-C') or ('-C', '-C') to also detect copies, or set it to () if you don't want to have renames detection. + * $prevent_xss + If true, some gitweb features are disabled to prevent content in + repositories from launching cross-site scripting (XSS) attacks. Set this + to true if you don't trust the content of your repositories. The default + is false. Projects list file format @@ -260,7 +265,9 @@ You can use the following files in repository: A .html file (HTML fragment) which is included on the gitweb project summary page inside
block element. You can use it for longer description of a project, to provide links (for example to project's - homepage), etc. + homepage), etc. This is recognized only if XSS prevention is off + ($prevent_xss is false); a way to include a readme safely when XSS + prevention is on may be worked out in the future. * description (or gitweb.description) Short (shortened by default to 25 characters in the projects list page) single line description of a project (of a repository). Plain text file; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 99f71b47c2..bdaa4e9463 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -132,6 +132,10 @@ our $fallback_encoding = 'latin1'; # - one might want to include '-B' option, e.g. '-B', '-M' our @diff_opts = ('-M'); # taken from git_commit +# Disables features that would allow repository owners to inject script into +# the gitweb domain. +our $prevent_xss = 0; + # information about snapshot formats that gitweb is capable of serving our %known_snapshot_formats = ( # name => { @@ -4494,7 +4498,9 @@ sub git_summary { print "
CommitLineData
\n"; - if (-s "$projectroot/$project/README.html") { + # If XSS prevention is on, we don't include README.html. + # TODO: Allow a readme in some safe format. + if (!$prevent_xss && -s "$projectroot/$project/README.html") { print "
readme
\n" . "
\n"; insert_file("$projectroot/$project/README.html"); @@ -4739,10 +4745,21 @@ sub git_blob_plain { $save_as .= '.txt'; } + # With XSS prevention on, blobs of all types except a few known safe + # ones are served with "Content-Disposition: attachment" to make sure + # they don't run in our security domain. For certain image types, + # blob view writes an tag referring to blob_plain view, and we + # want to be sure not to break that by serving the image as an + # attachment (though Firefox 3 doesn't seem to care). + my $sandbox = $prevent_xss && + $type !~ m!^(?:text/plain|image/(?:gif|png|jpeg))$!; + print $cgi->header( -type => $type, -expires => $expires, - -content_disposition => 'inline; filename="' . $save_as . '"'); + -content_disposition => + ($sandbox ? 'attachment' : 'inline') + . '; filename="' . $save_as . '"'); undef $/; binmode STDOUT, ':raw'; print <$fd>; -- cgit v1.3 From 81d3fe9f4871e42ebd1af0221fa091fe5476e2f7 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sun, 15 Feb 2009 10:18:36 +0100 Subject: gitweb: fix wrong base URL when non-root DirectoryIndex CGI::url() has some issues when rebuilding the script URL if the script is a DirectoryIndex. One of these issue is the inability to strip PATH_INFO, which is why we had to do it ourselves. Another issue is that the resulting URL cannot be used for the tag: it works if we're the DirectoryIndex at the root level, but not otherwise. We fix this by building the proper base URL ourselves, and improve the comment about the need to strip PATH_INFO manually while we're at it. Additionally t/t9500-gitweb-standalone-no-errors.sh had to be modified to set SCRIPT_NAME variable (CGI standard states that it MUST be set, and now gitweb uses it if PATH_INFO is not empty, as is the case for some of tests in t9500). Signed-off-by: Giuseppe Bilotta Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 28 ++++++++++++++++++++++------ t/t9500-gitweb-standalone-no-errors.sh | 6 ++++-- 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8dffa3fd53..7c481811af 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -27,13 +27,29 @@ our $version = "++GIT_VERSION++"; our $my_url = $cgi->url(); our $my_uri = $cgi->url(-absolute => 1); -# if we're called with PATH_INFO, we have to strip that -# from the URL to find our real URL -# we make $path_info global because it's also used later on +# Base URL for relative URLs in gitweb ($logo, $favicon, ...), +# needed and used only for URLs with nonempty PATH_INFO +our $base_url = $my_url; + +# When the script is used as DirectoryIndex, the URL does not contain the name +# of the script file itself, and $cgi->url() fails to strip PATH_INFO, so we +# have to do it ourselves. We make $path_info global because it's also used +# later on. +# +# Another issue with the script being the DirectoryIndex is that the resulting +# $my_url data is not the full script URL: this is good, because we want +# generated links to keep implying the script name if it wasn't explicitly +# indicated in the URL we're handling, but it means that $my_url cannot be used +# as base URL. +# Therefore, if we needed to strip PATH_INFO, then we know that we have +# to build the base URL ourselves: our $path_info = $ENV{"PATH_INFO"}; if ($path_info) { - $my_url =~ s,\Q$path_info\E$,,; - $my_uri =~ s,\Q$path_info\E$,,; + if ($my_url =~ s,\Q$path_info\E$,, && + $my_uri =~ s,\Q$path_info\E$,, && + defined $ENV{'SCRIPT_NAME'}) { + $base_url = $cgi->url(-base => 1) . $ENV{'SCRIPT_NAME'}; + } } # core git executable to use @@ -2908,7 +2924,7 @@ EOF # the stylesheet, favicon etc urls won't work correctly with path_info # unless we set the appropriate base URL if ($ENV{'PATH_INFO'}) { - print '\n'; + print "\n"; } # print out each stylesheet that exist, providing backwards capability # for those people who defined $stylesheet in a config file diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 43cd6eecba..7c6f70bbd8 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -43,9 +43,11 @@ gitweb_run () { GATEWAY_INTERFACE="CGI/1.1" HTTP_ACCEPT="*/*" REQUEST_METHOD="GET" + SCRIPT_NAME="$TEST_DIRECTORY/../gitweb/gitweb.perl" QUERY_STRING=""$1"" PATH_INFO=""$2"" - export GATEWAY_INTERFACE HTTP_ACCEPT REQUEST_METHOD QUERY_STRING PATH_INFO + export GATEWAY_INTERFACE HTTP_ACCEPT REQUEST_METHOD \ + SCRIPT_NAME QUERY_STRING PATH_INFO GITWEB_CONFIG=$(pwd)/gitweb_config.perl export GITWEB_CONFIG @@ -54,7 +56,7 @@ gitweb_run () { # written to web server logs, so we are not interested in that: # we are interested only in properly formatted errors/warnings rm -f gitweb.log && - perl -- "$TEST_DIRECTORY/../gitweb/gitweb.perl" \ + perl -- "$SCRIPT_NAME" \ >/dev/null 2>gitweb.log && if grep "^[[]" gitweb.log >/dev/null 2>&1; then false; else true; fi -- cgit v1.3 From df5d10a32ebc4f2305e13b70e2c01e4fa2cc73f0 Mon Sep 17 00:00:00 2001 From: "Marcel M. Cary" Date: Wed, 18 Feb 2009 14:09:41 +0100 Subject: gitweb: Fix warnings with override permitted but no repo override When a feature like "blame" is permitted to be overridden in the repository configuration but it is not actually set in the repository, a warning is emitted due to the undefined value of the repository configuration, even though it's a perfectly normal condition. Emitting warning is grounds for test failure in the gitweb test script. This error was caused by rewrite of git_get_project_config from using "git config [] " for each individual configuration variable checked to parsing "git config --list --null" output in commit b201927 (gitweb: Read repo config using 'git config -z -l'). Earlier version of git_get_project_config was returning empty string if variable do not exist in config; newer version is meant to return undef in this case, therefore change in feature_bool was needed. Additionally config_to_* subroutines were meant to be invoked only if configuration variable exists; therefore we added early return to git_get_project_config: it now returns no value if variable does not exists in config. Otherwise config_to_* subroutines (config_to_bool in paryicular) wouldn't be able to distinguish between the case where variable does not exist and the case where variable doesn't have value (the "[section] noval" case, which evaluates to true for boolean). While at it fix bug in config_to_bool, where checking if $val is defined (if config variable has value) was done _after_ stripping leading and trailing whitespace, which lead to 'Use of uninitialized value' warning. Add test case for features overridable but not overriden in repo config, and case for no value boolean configuration variable. Signed-off-by: Marcel M. Cary Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 16 ++++++++++------ t/t9500-gitweb-standalone-no-errors.sh | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7c481811af..83858fb8b9 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -402,13 +402,13 @@ sub feature_bool { my $key = shift; my ($val) = git_get_project_config($key, '--bool'); - if ($val eq 'true') { + if (!defined $val) { + return ($_[0]); + } elsif ($val eq 'true') { return (1); } elsif ($val eq 'false') { return (0); } - - return ($_[0]); } sub feature_snapshot { @@ -1914,18 +1914,19 @@ sub git_parse_project_config { return %config; } -# convert config value to boolean, 'true' or 'false' +# convert config value to boolean: 'true' or 'false' # no value, number > 0, 'true' and 'yes' values are true # rest of values are treated as false (never as error) sub config_to_bool { my $val = shift; + return 1 if !defined $val; # section.key + # strip leading and trailing whitespace $val =~ s/^\s+//; $val =~ s/\s+$//; - return (!defined $val || # section.key - ($val =~ /^\d+$/ && $val) || # section.key = 1 + return (($val =~ /^\d+$/ && $val) || # section.key = 1 ($val =~ /^(?:true|yes)$/i)); # section.key = true } @@ -1978,6 +1979,9 @@ sub git_get_project_config { $config_file = "$git_dir/config"; } + # check if config variable (key) exists + return unless exists $config{"gitweb.$key"}; + # ensure given type if (!defined $type) { return $config{"gitweb.$key"}; diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 7c6f70bbd8..6ed10d0933 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -661,6 +661,11 @@ cat >>gitweb_config.perl <.git/config <<\EOF +# testing noval and alternate separator +[gitweb] + blame + snapshot = zip tgz +EOF +test_expect_success \ + 'config override: tree view, features enabled in repo config (2)' \ + 'gitweb_run "p=.git;a=tree"' +test_debug 'cat gitweb.log' + # ---------------------------------------------------------------------- # non-ASCII in README.html -- cgit v1.3 From 7d233dea5f4e299fdac8d6cfb610bcd4d60a82b7 Mon Sep 17 00:00:00 2001 From: "Marcel M. Cary" Date: Tue, 17 Feb 2009 19:00:43 -0800 Subject: gitweb: Hyperlink multiple git hashes on the same commit message line The current implementation only hyperlinks the first hash on a given line of the commit message. It seems sensible to highlight all of them if there are multiple, and it seems plausible that there would be multiple even with a tidy line length limit, because they can be abbreviated as short as 8 characters. Benchmark: I wanted to make sure that using the 'e' switch to the Perl regex wasn't going to kill performance, since this is called once per commit message line displayed. In all three A/B scenarios I tried, the A and B yielded the same results within 2%, where A is the version of code before this patch and B is the version after. 1: View a commit message containing the last 1000 commit hashes 2: View a commit message containing 1000 lines of 40 dots to avoid hyperlinking at the same message length 3: View a short merge commit message with a few lines of text and no hashes All were run in CGI mode on my sub-production hardware on a recent clone of git.git. Numbers are the average of 10 reqests per second with the first request discarded, since I expect this change to affect primarily CPU usage. Measured with ApacheBench. Note that the web page rendered was the same; while the new code supports multiple hashes per line, there was at most one per line. The primary purpose of scenarios 2 and 3 were to verify that the addition of 1000 commit messages had an impact on how much of the time was spent rendering commit messages. They were all within 2% of 0.80 requests per second (much faster). So I think the patch has no noticeable effect on performance. Signed-off-by: Marcel M. Cary Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 83858fb8b9..33ef190ceb 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1384,13 +1384,11 @@ sub format_log_line_html { my $line = shift; $line = esc_html($line, -nbsp=>1); - if ($line =~ m/\b([0-9a-fA-F]{8,40})\b/) { - my $hash_text = $1; - my $link = - $cgi->a({-href => href(action=>"object", hash=>$hash_text), - -class => "text"}, $hash_text); - $line =~ s/$hash_text/$link/; - } + $line =~ s{\b([0-9a-fA-F]{8,40})\b}{ + $cgi->a({-href => href(action=>"object", hash=>$1), + -class => "text"}, $1); + }eg; + return $line; } -- cgit v1.3 From ccb4b5391382f4cdb5e5be49036e82e7d837b7af Mon Sep 17 00:00:00 2001 From: Holger Weiß Date: Tue, 31 Mar 2009 18:16:36 +0200 Subject: gitweb: Fix snapshots requested via PATH_INFO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the detection of the requested snapshot format, which failed for PATH_INFO URLs since the references to the hashes which describe the supported snapshot formats weren't dereferenced appropriately. Signed-off-by: Holger Weiß Acked-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 33ef190ceb..3f99361ed0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -688,10 +688,10 @@ sub evaluate_path_info { # extensions. Allowed extensions are both the defined suffix # (which includes the initial dot already) and the snapshot # format key itself, with a prepended dot - while (my ($fmt, %opt) = each %known_snapshot_formats) { + while (my ($fmt, $opt) = each %known_snapshot_formats) { my $hash = $refname; my $sfx; - $hash =~ s/(\Q$opt{'suffix'}\E|\Q.$fmt\E)$//; + $hash =~ s/(\Q$opt->{'suffix'}\E|\Q.$fmt\E)$//; next unless $sfx = $1; # a valid suffix was found, so set the snapshot format # and reset the hash parameter -- cgit v1.3 From 680ebc01806187b33cab9093c39102468298350f Mon Sep 17 00:00:00 2001 From: Mike Ralphson Date: Fri, 17 Apr 2009 19:13:28 +0100 Subject: Documentation: fix typos / spelling mistakes Signed-off-by: Mike Ralphson Signed-off-by: Junio C Hamano --- Documentation/git-cvsimport.txt | 2 +- Documentation/git-format-patch.txt | 2 +- contrib/thunderbird-patch-inline/README | 4 ++-- gitweb/README | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'gitweb') diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index d7bab13f6c..614e769f4e 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -196,7 +196,7 @@ Problems related to tags: If you suspect that any of these issues may apply to the repository you want to import consider using these alternative tools which proved to be -more stable in practise: +more stable in practice: * cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org` * parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs` diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index eb2fbcff1a..5eddca92c4 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -194,7 +194,7 @@ CONFIGURATION ------------- You can specify extra mail header lines to be added to each message in the repository configuration, new defaults for the subject prefix -and file suffix, control attachements, and number patches when outputting +and file suffix, control attachments, and number patches when outputting more than one. ------------ diff --git a/contrib/thunderbird-patch-inline/README b/contrib/thunderbird-patch-inline/README index 39f96aa115..000147bbe4 100644 --- a/contrib/thunderbird-patch-inline/README +++ b/contrib/thunderbird-patch-inline/README @@ -1,12 +1,12 @@ appp.sh is a script that is supposed to be used together with ExternalEditor -for Mozilla Thundebird. It will let you include patches inline in e-mails +for Mozilla Thunderbird. It will let you include patches inline in e-mails in an easy way. Usage: - Generate the patch with git format-patch. - Start writing a new e-mail in Thunderbird. - Press the external editor button (or Ctrl-E) to run appp.sh -- Select the previosly generated patch file. +- Select the previously generated patch file. - Finish editing the e-mail. Any text that is entered into the message editor before appp.sh is called diff --git a/gitweb/README b/gitweb/README index 8433dd1d45..ccda890c0e 100644 --- a/gitweb/README +++ b/gitweb/README @@ -206,7 +206,7 @@ not include variables usually directly set during build): * $fallback_encoding Gitweb assumes this charset if line contains non-UTF-8 characters. Fallback decoding is used without error checking, so it can be even - 'utf-8'. Value mist be valid encodig; see Encoding::Supported(3pm) man + 'utf-8'. Value must be valid encoding; see Encoding::Supported(3pm) man page for a list. By default 'latin1', aka. 'iso-8859-1'. * @diff_opts Rename detection options for git-diff and git-diff-tree. By default -- cgit v1.3 From 74fd8728e2abd46a6276f6d48bfc6c9f01d74570 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 7 May 2009 19:11:29 +0200 Subject: gitweb: Remove function prototypes (cleanup) Use of function prototypes is considered bad practice in Perl. The ones used here didn't accomplish anything anyhow, so they've been removed. >From perlsub(1): [...] the intent of this feature [prototypes] is primarily to let you define subroutines that work like built-in functions [...] you can generate new syntax with it [...] We don't want to have subroutines behaving exactly like built-in functions, we don't want to define new syntax / syntactic sugar, so prototypes in gitweb are not needed... and they can have unintended consequences. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3f99361ed0..06e91608fa 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -838,7 +838,7 @@ exit; ## ====================================================================== ## action links -sub href (%) { +sub href { my %params = @_; # default is to use -absolute url() i.e. $my_uri my $href = $params{-full} ? $my_url : $my_uri; @@ -1036,7 +1036,7 @@ sub esc_url { } # replace invalid utf8 character with SUBSTITUTION sequence -sub esc_html ($;%) { +sub esc_html { my $str = shift; my %opts = @_; @@ -1296,7 +1296,7 @@ use constant { }; # submodule/subproject, a commit object reference -sub S_ISGITLINK($) { +sub S_ISGITLINK { my $mode = shift; return (($mode & S_IFMT) == S_IFGITLINK) @@ -2615,7 +2615,7 @@ sub parsed_difftree_line { } # parse line of git-ls-tree output -sub parse_ls_tree_line ($;%) { +sub parse_ls_tree_line { my $line = shift; my %opts = @_; my %res; @@ -3213,7 +3213,6 @@ sub git_print_header_div { "\n
\n"; } -#sub git_print_authorship (\%) { sub git_print_authorship { my $co = shift; @@ -3269,8 +3268,7 @@ sub git_print_page_path { print "
\n"; } -# sub git_print_log (\@;%) { -sub git_print_log ($;%) { +sub git_print_log { my $log = shift; my %opts = @_; -- cgit v1.3 From ad87e4f6f19e78b3f2d7dde3d3ed403db4f79a03 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 11 May 2009 03:21:06 +0200 Subject: gitweb: Do not use bareword filehandles gitweb: Do not use bareword filehandles The script was using bareword filehandles. This is considered a bad practice so they have been changed to indirect filehandles. Changes touch git_get_project_ctags and mimetype_guess_file; while at it rename local variable from $mime to $mimetype (in mimetype_guess_file) to better reflect its value (its contents). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 06e91608fa..584644cbee 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2065,18 +2065,17 @@ sub git_get_project_ctags { my $ctags = {}; $git_dir = "$projectroot/$path"; - unless (opendir D, "$git_dir/ctags") { - return $ctags; - } - foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir(D)) { - open CT, $_ or next; - my $val = ; + opendir my $dh, "$git_dir/ctags" + or return $ctags; + foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir($dh)) { + open my $ct, $_ or next; + my $val = <$ct>; chomp $val; - close CT; + close $ct; my $ctag = $_; $ctag =~ s#.*/##; $ctags->{$ctag} = $val; } - closedir D; + closedir $dh; $ctags; } @@ -2804,18 +2803,18 @@ sub mimetype_guess_file { -r $mimemap or return undef; my %mimemap; - open(MIME, $mimemap) or return undef; - while () { + open(my $mh, $mimemap) or return undef; + while (<$mh>) { next if m/^#/; # skip comments - my ($mime, $exts) = split(/\t+/); + my ($mimetype, $exts) = split(/\t+/); if (defined $exts) { my @exts = split(/\s+/, $exts); foreach my $ext (@exts) { - $mimemap{$ext} = $mime; + $mimemap{$ext} = $mimetype; } } } - close(MIME); + close($mh); $filename =~ /\.([^.]*)$/; return $mimemap{$1}; -- cgit v1.3 From dff2b6d4842eef0a03a3c8b3761f72e2b55b609e Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 10 May 2009 02:38:34 +0200 Subject: gitweb: Always use three argument form of open In most cases (except insert_file() subroutine) we used old two argument form of 'open' to open files for reading. This can cause subtle bugs when $projectroot or $projects_list file starts with mode characters ('>', '<', '+<', '|', etc.) or with leading whitespace; and also when $projects_list file or $mimetypes_file or ctags files end with trailing whitespace or '|'. Additionally it is also more clear to explicitly state that we open those files for reading. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 584644cbee..e7cab9020f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2050,7 +2050,7 @@ sub git_get_project_description { my $path = shift; $git_dir = "$projectroot/$path"; - open my $fd, "$git_dir/description" + open my $fd, '<', "$git_dir/description" or return git_get_project_config('description'); my $descr = <$fd>; close $fd; @@ -2068,7 +2068,7 @@ sub git_get_project_ctags { opendir my $dh, "$git_dir/ctags" or return $ctags; foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir($dh)) { - open my $ct, $_ or next; + open my $ct, '<', $_ or next; my $val = <$ct>; chomp $val; close $ct; @@ -2128,7 +2128,7 @@ sub git_get_project_url_list { my $path = shift; $git_dir = "$projectroot/$path"; - open my $fd, "$git_dir/cloneurl" + open my $fd, '<', "$git_dir/cloneurl" or return wantarray ? @{ config_to_multi(git_get_project_config('url')) } : config_to_multi(git_get_project_config('url')); @@ -2186,7 +2186,7 @@ sub git_get_projects_list { # 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin' # 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman' my %paths; - open my ($fd), $projects_list or return; + open my $fd, '<', $projects_list or return; PROJECT: while (my $line = <$fd>) { chomp $line; @@ -2249,7 +2249,7 @@ sub git_get_project_list_from_file { # 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin' # 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman' if (-f $projects_list) { - open (my $fd , $projects_list); + open(my $fd, '<', $projects_list); while (my $line = <$fd>) { chomp $line; my ($pr, $ow) = split ' ', $line; @@ -2803,7 +2803,7 @@ sub mimetype_guess_file { -r $mimemap or return undef; my %mimemap; - open(my $mh, $mimemap) or return undef; + open(my $mh, '<', $mimemap) or return undef; while (<$mh>) { next if m/^#/; # skip comments my ($mimetype, $exts) = split(/\t+/); -- cgit v1.3 From 34122b57eca747022336f5a3dc1aa80377d1ce56 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 11 May 2009 03:29:40 +0200 Subject: gitweb: Always use three argument form of open From 94638fb6edf3ea693228c680a6a30271ccd77522 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 11 May 2009 03:25:55 +0200 Subject: [PATCH] gitweb: Localize magic variable $/ Instead of undefining and then restoring magic variable $/ (input record separator) for 'slurp mode', localize it. While at it, state explicitely that "local $/;" makes it undefined, by using explicit "local $/ = undef;". Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e7cab9020f..4efeeedccf 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3325,7 +3325,7 @@ sub git_get_link_target { open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash or return; { - local $/; + local $/ = undef; $link_target = <$fd>; } close $fd @@ -4800,11 +4800,10 @@ sub git_blob_plain { -content_disposition => ($sandbox ? 'attachment' : 'inline') . '; filename="' . $save_as . '"'); - undef $/; + local $/ = undef; binmode STDOUT, ':raw'; print <$fd>; binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi - $/ = "\n"; close $fd; } @@ -4906,12 +4905,16 @@ sub git_tree { } } die_error(404, "No such tree") unless defined($hash); - $/ = "\0"; - open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash - or die_error(500, "Open git-ls-tree failed"); - my @entries = map { chomp; $_ } <$fd>; - close $fd or die_error(404, "Reading tree failed"); - $/ = "\n"; + + my @entries = (); + { + local $/ = "\0"; + open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash + or die_error(500, "Open git-ls-tree failed"); + @entries = map { chomp; $_ } <$fd>; + close $fd + or die_error(404, "Reading tree failed"); + } my $refs = git_get_references(); my $ref = format_ref_marker($refs, $hash_base); @@ -5806,7 +5809,7 @@ sub git_search { print "\n"; my $alternate = 1; - $/ = "\n"; + local $/ = "\n"; open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts, '--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext", ($search_use_regexp ? '--pickaxe-regex' : ()); @@ -5876,7 +5879,7 @@ sub git_search { print "
\n"; my $alternate = 1; my $matches = 0; - $/ = "\n"; + local $/ = "\n"; open my $fd, "-|", git_cmd(), 'grep', '-n', $search_use_regexp ? ('-E', '-i') : '-F', $searchtext, $co{'tree'}; -- cgit v1.3 From 68cedb1fea0bbcd5f7c32ce10e3c346bc6db38c5 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 10 May 2009 02:40:37 +0200 Subject: gitweb: Use block form of map/grep in a few cases more Use block form of 'grep' i.e. 'grep {BLOCK} LIST' rather than 'grep(EXPR, LIST)' in filter_snapshot_fmts subroutine. This makes code more readable, as expression is rather long, and statement above there is 'map' with very similar expression also in the block form. Remove unnecessary and misleading parentheses around block form 'map' arguments in quote_command subroutine. The inner "map" in format_snapshot_links was left alone, as it is not clear whether adding parentheses or changing it into block form would improve readibility and clarity of this code. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 4efeeedccf..8c51f3e79e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -458,8 +458,8 @@ sub filter_snapshot_fmts { @fmts = map { exists $known_snapshot_format_aliases{$_} ? $known_snapshot_format_aliases{$_} : $_} @fmts; - @fmts = grep(exists $known_snapshot_formats{$_}, @fmts); - + @fmts = grep { + exists $known_snapshot_formats{$_} } @fmts; } our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++"; @@ -1838,7 +1838,7 @@ sub git_cmd { # Try to avoid using this function wherever possible. sub quote_command { return join(' ', - map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ )); + map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ); } # get HEAD ref of given project as hash -- cgit v1.3 From 3278fbc5ce39e0f7bf095ce99912dccbc347b4d7 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 11 May 2009 19:37:28 +0200 Subject: gitweb: Replace wrongly added tabs with spaces In two places there was hard tab character instead of space. Fix this. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8c51f3e79e..beb79eebd5 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3990,7 +3990,7 @@ sub fill_project_list_info { ($pname !~ /\/$/) && (-d "$projectroot/$pname")) { $pr->{'forks'} = "-d $projectroot/$pname"; - } else { + } else { $pr->{'forks'} = 0; } } @@ -6282,7 +6282,7 @@ XML # end of feed if ($format eq 'rss') { print "\n\n"; - } elsif ($format eq 'atom') { + } elsif ($format eq 'atom') { print "\n"; } } -- cgit v1.3 From e8bb4b38dfcbd5ff02ceb5e925d53c1460887df5 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 11 May 2009 19:39:43 +0200 Subject: gitweb: Use capturing parentheses only when you intend to capture Non-capturing groups are useful because they have better runtime performance and do not copy strings to the magic global capture variables. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index beb79eebd5..097bd18be5 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -828,7 +828,7 @@ if (!defined $action) { if (!defined($actions{$action})) { die_error(400, "Unknown action"); } -if ($action !~ m/^(opml|project_list|project_index)$/ && +if ($action !~ m/^(?:opml|project_list|project_index)$/ && !$project) { die_error(400, "Project needed"); } -- cgit v1.3 From 095e914281395f6c0529ce39939d804eb2ccec02 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 11 May 2009 19:42:47 +0200 Subject: gitweb: Simplify snapshot format detection logic in evaluate_path_info This issue was caught by perlcritic in harsh severity level noticing that catch variable was used outside conditional thanks to the Perl::Critic::Policy::RegularExpressions::ProhibitCaptureWithoutTest policy. See "Perl Best Practices", chapter 12. Regular Expressions, section 12.15. Captured Values: Pattern matches that fail never assign anything to $1, $2, etc., nor do they leave those variables undefined. After an unsuccessful pattern match, the numeric capture variables remain exactly as they were before the match was attempted. New version is in my opinion much easier to understand; previous version worked correctly due to the fact that we returned from loop on first found match. Signed-off-by: Jakub Narebski Acked-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 097bd18be5..c72ae10ef1 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -690,9 +690,10 @@ sub evaluate_path_info { # format key itself, with a prepended dot while (my ($fmt, $opt) = each %known_snapshot_formats) { my $hash = $refname; - my $sfx; - $hash =~ s/(\Q$opt->{'suffix'}\E|\Q.$fmt\E)$//; - next unless $sfx = $1; + unless ($hash =~ s/(\Q$opt->{'suffix'}\E|\Q.$fmt\E)$//) { + next; + } + my $sfx = $1; # a valid suffix was found, so set the snapshot format # and reset the hash parameter $input_params{'snapshot_format'} = $fmt; -- cgit v1.3 From 15c54fe7aa9376de2e03045122723ebde09bfeeb Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 11 May 2009 19:45:11 +0200 Subject: gitweb: Remove unused $hash_base parameter from normalize_link_target ...since it was decided for normalize_link_target to only mangle pathname, and do not try to check if target is present in $hash_base tree, for performance reasons. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c72ae10ef1..05702e4070 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3339,10 +3339,7 @@ sub git_get_link_target { # 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; + my ($link_target, $basedir) = @_; # absolute symlinks (beginning with '/') cannot be normalized return if (substr($link_target, 0, 1) eq '/'); @@ -3398,7 +3395,7 @@ sub git_print_tree_entry { if (S_ISLNK(oct $t->{'mode'})) { my $link_target = git_get_link_target($t->{'hash'}); if ($link_target) { - my $norm_target = normalize_link_target($link_target, $basedir, $hash_base); + my $norm_target = normalize_link_target($link_target, $basedir); if (defined $norm_target) { print " -> " . $cgi->a({-href => href(action=>"object", hash_base=>$hash_base, -- cgit v1.3 From 14afe77486281e411bfadd131e5c8ffc44e22a26 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 22 May 2009 17:35:46 +0200 Subject: gitweb: Sanitize title attribute in format_subject_html Replace control characters with question mark '?' (like in chop_and_esc_str). A little background: some web browsers turn on strict (and unforgiving) XML validating mode for XHTML documents served using application/xhtml+xml content type. This means among others that control characters are forbidden to appear in gitweb output. CGI.pm does by default slight escaping (using simple_escape subroutine from CGI::Util) of all _attribute_ values (depending on the value of autoEscape, by default on). This escaping, at least in CGI.pm version 3.10 (most current version at CPAN is 3.43), is minimal: only '"', '&', '<' and '>' are escaped using named HTML entity references (", &, < and > respectively). But simple_escape does not do escaping of control characters such as ^X which are invalid in XHTML (in strict mode). If by some accident commit message do contain some control character in first 50 characters (more or less) of first line of commit message, and this line is longer than 50 characters (so gitweb shortens it for display), then gitweb would put this control character in title attribute (and CGI.pm would not remove them). The tag _contents_ is safe because it is escaped using esc_html() explicitly, and it replaces control characters by their printable representation. While at it: chop_and_escape_str doesn't need capturing group. Noticed-by: Paul Gortmaker Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 06e91608fa..d143829c5d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1235,7 +1235,7 @@ sub chop_and_escape_str { if ($chopped eq $str) { return esc_html($chopped); } else { - $str =~ s/([[:cntrl:]])/?/g; + $str =~ s/[[:cntrl:]]/?/g; return $cgi->span({-title=>$str}, esc_html($chopped)); } } @@ -1458,6 +1458,7 @@ sub format_subject_html { $extra = '' unless defined($extra); if (length($short) < length($long)) { + $long =~ s/[[:cntrl:]]/?/g; return $cgi->a({-href => $href, -class => "list subject", -title => to_utf8($long)}, esc_html($short) . $extra); -- cgit v1.3 From 1bed73c64a354248d6b342e58df257e8233bcbd2 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sat, 27 Jun 2009 18:24:11 +0200 Subject: gitweb/README: fix AliasMatch in example When combining "dumb client" and human-friendly access by using the '.git' extension to switch between the two, make sure the AliasMatch covers the entire request. Without a full match, a request for http://git.example.com/project/shortlog/branch..gitsomething would result in a 404 because the server would try to access the the project 'project/shortlog/branch.' The solution is still not bulletproof, so document the possible failing case. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/README | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/README b/gitweb/README index ccda890c0e..9056d1e090 100644 --- a/gitweb/README +++ b/gitweb/README @@ -377,7 +377,7 @@ named without a .git extension (e.g. /pub/git/project instead of DocumentRoot /var/www/gitweb - AliasMatch ^(/.*?)(\.git)(/.*)? /pub/git$1$3 + AliasMatch ^(/.*?)(\.git)(/.*)?$ /pub/git$1$3 Options ExecCGI AddHandler cgi-script cgi @@ -402,6 +402,14 @@ http://git.example.com/project will provide human-friendly gitweb access. +This solution is not 100% bulletproof, in the sense that if some project +has a named ref (branch, tag) starting with 'git/', then paths such as + +http://git.example.com/project/command/abranch..git/abranch + +will fail with a 404 error. + + Originally written by: Kay Sievers -- cgit v1.3 From 1c49a4e1f324dcaa000ce92ed44d0e5b9eb16843 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 30 Jun 2009 00:00:48 +0200 Subject: gitweb: refactor author name insertion Collect all author display code in appropriate functions, making it easier to extend these functions on the CGI side. We also move some of the presentation code from hard-coded HTML to CSS, for easier customization. A side effect of the refactoring is that now localtime is always displayed with the 'at night' warning. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 5 ++- gitweb/gitweb.perl | 93 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 59 insertions(+), 39 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index a01eac814e..68b22ffece 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -132,11 +132,14 @@ div.list_head { font-style: italic; } +.author_date, .author { + font-style: italic; +} + div.author_date { padding: 8px; border: solid #d9d8d1; border-width: 0px 0px 1px 0px; - font-style: italic; } a.list { diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 1e7e2d8387..7fd53f68de 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1469,6 +1469,16 @@ sub format_subject_html { } } +# format the author name of the given commit with the given tag +# the author name is chopped and escaped according to the other +# optional parameters (see chop_str). +sub format_author_html { + my $tag = shift; + my $co = shift; + my $author = chop_and_escape_str($co->{'author_name'}, @_); + return "<$tag class=\"author\">" . $author . ""; +} + # format git diff header line, i.e. "diff --(git|combined|cc) ..." sub format_git_diff_header_line { my $line = shift; @@ -3214,21 +3224,50 @@ sub git_print_header_div { "\n\n"; } +sub print_local_time { + my %date = @_; + if ($date{'hour_local'} < 6) { + printf(" (%02d:%02d %s)", + $date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'}); + } else { + printf(" (%02d:%02d %s)", + $date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'}); + } +} + +# Outputs the author name and date in long form sub git_print_authorship { my $co = shift; + my %opts = @_; + my $tag = $opts{-tag} || 'div'; my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'}); - print "
" . + print "<$tag class=\"author_date\">" . esc_html($co->{'author_name'}) . " [$ad{'rfc2822'}"; - if ($ad{'hour_local'} < 6) { - printf(" (%02d:%02d %s)", - $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); - } else { - printf(" (%02d:%02d %s)", - $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); + print_local_time(%ad) if ($opts{-localtime}); + print "]\n"; +} + +# Outputs table rows containing the full author or committer information, +# in the format expected for 'commit' view (& similia). +# Parameters are a commit hash reference, followed by the list of people +# to output information for. If the list is empty it defalts to both +# author and committer. +sub git_print_authorship_rows { + my $co = shift; + # too bad we can't use @people = @_ || ('author', 'committer') + my @people = @_; + @people = ('author', 'committer') unless @people; + foreach my $who (@people) { + my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"}); + print "
\n". + "" . + "" . + "\n"; } - print "]\n"; } sub git_print_page_path { @@ -4142,11 +4181,9 @@ sub git_shortlog_body { print "\n"; } $alternate ^= 1; - my $author = chop_and_escape_str($co{'author_name'}, 10); # git_summary() used print "\n" . print "\n" . - "\n" . - "\n" . @@ -4193,11 +4230,9 @@ sub git_history_body { print "\n"; } $alternate ^= 1; - # shortlog uses chop_str($co{'author_name'}, 10) - my $author = chop_and_escape_str($co{'author_name'}, 15, 3); print "\n" . - "\n" . - "\n"; } $alternate ^= 1; - my $author = chop_and_escape_str($co{'author_name'}, 15, 5); print "\n" . - "\n" . + format_author_html('td', \%co, 15, 5) . "\n" . "\n"; if (defined($tag{'author'})) { - my %ad = parse_date($tag{'epoch'}, $tag{'tz'}); - print "\n"; - print "\n"; + git_print_authorship_rows(\%tag, 'author'); } print "
$who" . esc_html($co->{$who}) . "
$wd{'rfc2822'}"; + print_local_time(%wd); + print "
$co{'age_string'}$co{'age_string_date'}" . $author . ""; + format_author_html('td', \%co, 10) . ""; print format_subject_html($co{'title'}, $co{'title_short'}, href(action=>"commit", hash=>$commit), $ref); print "
$co{'age_string_date'}" . $author . ""; + # shortlog: format_author_html('td', \%co, 10) + format_author_html('td', \%co, 15, 3) . ""; # originally git_history used chop_str($co{'title'}, 50) print format_subject_html($co{'title'}, $co{'title_short'}, href(action=>"commit", hash=>$commit), $ref); @@ -4350,9 +4385,8 @@ sub git_search_grep_body { print "
$co{'age_string_date'}" . $author . "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, @@ -5094,9 +5128,9 @@ sub git_log { " | " . $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree") . "
\n" . - "\n" . - "" . esc_html($co{'author_name'}) . " [$ad{'rfc2822'}]
\n" . "\n"; + git_print_authorship(\%co, -tag => 'span'); + print "
\n\n"; print "
\n"; git_print_log($co{'comment'}, -final_empty_line=> 1); @@ -5115,8 +5149,6 @@ sub git_commit { $hash ||= $hash_base || "HEAD"; my %co = parse_commit($hash) or die_error(404, "Unknown commit object"); - my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'}); - my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'}); my $parent = $co{'parent'}; my $parents = $co{'parents'}; # listref @@ -5183,22 +5215,7 @@ sub git_commit { } print "
\n" . "\n"; - print "\n". - "" . - "" . - "\n"; - print "\n"; - print "\n"; + git_print_authorship_rows(\%co); print "\n"; print "" . "" . @@ -5579,7 +5596,7 @@ sub git_commitdiff { git_header_html(undef, $expires); git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav); git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash); - git_print_authorship(\%co); + git_print_authorship(\%co, -localtime => 1); print "
\n"; if (@{$co{'comment'}} > 1) { print "
\n"; -- cgit v1.3 From f88bafadd9b2562a0cd2500c5a9669d3741243b5 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 30 Jun 2009 00:00:49 +0200 Subject: gitweb: uniform author info for commit and commitdiff Switch from 'log'-like layout A U Thor [date time] to 'commit'-like layout author A U Thor date time committer C O Mitter committer date time Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7fd53f68de..9a8d775ad8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5596,7 +5596,11 @@ sub git_commitdiff { git_header_html(undef, $expires); git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav); git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash); - git_print_authorship(\%co, -localtime => 1); + print "
\n" . + "
author" . esc_html($co{'author'}) . "
$ad{'rfc2822'}"; - if ($ad{'hour_local'} < 6) { - printf(" (%02d:%02d %s)", - $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); - } else { - printf(" (%02d:%02d %s)", - $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); - } - print "
committer" . esc_html($co{'committer'}) . "
$cd{'rfc2822'}" . - sprintf(" (%02d:%02d %s)", $cd{'hour_local'}, $cd{'minute_local'}, $cd{'tz_local'}) . - "
commit$co{'id'}
tree
\n"; + git_print_authorship_rows(\%co); + print "
". + "
\n"; print "
\n"; if (@{$co{'comment'}} > 1) { print "
\n"; -- cgit v1.3 From ba9247339dfbd2c2671603e012d011b4b474fa4b Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 30 Jun 2009 00:00:50 +0200 Subject: gitweb: use git_print_authorship_rows in 'tag' view too parse_tag must be adapted to use the hash keys expected by git_print_authorship_rows. This is not a problem since git_tag is the only user of this sub. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 9a8d775ad8..a393ac6f29 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2409,8 +2409,14 @@ sub parse_tag { $tag{'name'} = $1; } elsif ($line =~ m/^tagger (.*) ([0-9]+) (.*)$/) { $tag{'author'} = $1; - $tag{'epoch'} = $2; - $tag{'tz'} = $3; + $tag{'author_epoch'} = $2; + $tag{'author_tz'} = $3; + if ($tag{'author'} =~ m/^([^<]+) <([^>]*)>/) { + $tag{'author_name'} = $1; + $tag{'author_email'} = $2; + } else { + $tag{'author_name'} = $tag{'author'}; + } } elsif ($line =~ m/--BEGIN/) { push @comment, $line; last; @@ -4620,11 +4626,7 @@ sub git_tag { $tag{'type'}) . "
author" . esc_html($tag{'author'}) . "
" . $ad{'rfc2822'} . - sprintf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}) . - "
\n\n" . "\n"; -- cgit v1.3 From e9fdd74e5374dd1efe1577057d14a2836b4cae78 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 30 Jun 2009 00:00:51 +0200 Subject: gitweb: (gr)avatar support Introduce avatar support: the feature adds the appropriate img tag next to author and committer in commit(diff), history, shortlog, log and tag views. Multiple avatar providers are possible, but only gravatar is implemented at the moment. Gravatar support depends on Digest::MD5, which is a core package since Perl 5.8. If gravatars are activated but Digest::MD5 cannot be found, the feature will be automatically disabled. No avatar provider is selected by default, except in the t9500 test. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 4 ++ gitweb/gitweb.perl | 83 ++++++++++++++++++++++++++++++++-- t/t9500-gitweb-standalone-no-errors.sh | 2 + 3 files changed, 86 insertions(+), 3 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 68b22ffece..d05bc37646 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -28,6 +28,10 @@ img.logo { border-width: 0px; } +img.avatar { + vertical-align: middle; +} + div.page_header { height: 25px; padding: 8px; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a393ac6f29..92695a3ae8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -195,6 +195,14 @@ our %known_snapshot_format_aliases = ( 'x-zip' => undef, '' => undef, ); +# Pixel sizes for icons and avatars. If the default font sizes or lineheights +# are changed, it may be appropriate to change these values too via +# $GITWEB_CONFIG. +our %avatar_size = ( + 'default' => 16, + 'double' => 32 +); + # You define site-wide feature defaults here; override them with # $GITWEB_CONFIG as necessary. our %feature = ( @@ -365,6 +373,24 @@ our %feature = ( 'sub' => \&feature_patches, 'override' => 0, 'default' => [16]}, + + # Avatar support. When this feature is enabled, views such as + # shortlog or commit will display an avatar associated with + # the email of the committer(s) and/or author(s). + + # Currently only the gravatar provider is available, and it + # depends on Digest::MD5. If an unknown provider is specified, + # the feature is disabled. + + # To enable system wide have in $GITWEB_CONFIG + # $feature{'avatar'}{'default'} = ['gravatar']; + # To have project specific config enable override in $GITWEB_CONFIG + # $feature{'avatar'}{'override'} = 1; + # and in project config gitweb.avatar = gravatar; + 'avatar' => { + 'sub' => \&feature_avatar, + 'override' => 0, + 'default' => ['']}, ); sub gitweb_get_feature { @@ -433,6 +459,12 @@ sub feature_patches { return ($_[0]); } +sub feature_avatar { + my @val = (git_get_project_config('avatar')); + + return @val ? @val : @_; +} + # checking HEAD file with -e is fragile if the repository was # initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed # and then pruned. @@ -814,6 +846,17 @@ $git_dir = "$projectroot/$project" if $project; our @snapshot_fmts = gitweb_get_feature('snapshot'); @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts); +# check that the avatar feature is set to a known provider name, +# and for each provider check if the dependencies are satisfied. +# if the provider name is invalid or the dependencies are not met, +# reset $git_avatar to the empty string. +our ($git_avatar) = gitweb_get_feature('avatar'); +if ($git_avatar eq 'gravatar') { + $git_avatar = '' unless (eval { require Digest::MD5; 1; }); +} else { + $git_avatar = ''; +} + # dispatch if (!defined $action) { if (defined $hash) { @@ -1469,6 +1512,34 @@ sub format_subject_html { } } +# Insert an avatar for the given $email at the given $size if the feature +# is enabled. +sub git_get_avatar { + my ($email, %opts) = @_; + my $pre_white = ($opts{-pad_before} ? " " : ""); + my $post_white = ($opts{-pad_after} ? " " : ""); + $opts{-size} ||= 'default'; + my $size = $avatar_size{$opts{-size}} || $avatar_size{'default'}; + my $url = ""; + if ($git_avatar eq 'gravatar') { + $url = "http://www.gravatar.com/avatar/" . + Digest::MD5::md5_hex(lc $email) . "?s=$size"; + } + # Currently only gravatars are supported, but other forms such as + # picons can be added by putting an else up here and defining $url + # as needed. If no variant puts something in $url, we assume avatars + # are completely disabled/unavailable. + if ($url) { + return $pre_white . + "" . $post_white; + } else { + return ""; + } +} + # format the author name of the given commit with the given tag # the author name is chopped and escaped according to the other # optional parameters (see chop_str). @@ -1476,7 +1547,9 @@ sub format_author_html { my $tag = shift; my $co = shift; my $author = chop_and_escape_str($co->{'author_name'}, @_); - return "<$tag class=\"author\">" . $author . ""; + return "<$tag class=\"author\">" . + git_get_avatar($co->{'author_email'}, -pad_after => 1) . + $author . ""; } # format git diff header line, i.e. "diff --(git|combined|cc) ..." @@ -3252,7 +3325,8 @@ sub git_print_authorship { esc_html($co->{'author_name'}) . " [$ad{'rfc2822'}"; print_local_time(%ad) if ($opts{-localtime}); - print "]\n"; + print "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1) + . "\n"; } # Outputs table rows containing the full author or committer information, @@ -3267,7 +3341,10 @@ sub git_print_authorship_rows { @people = ('author', 'committer') unless @people; foreach my $who (@people) { my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"}); - print "$who" . esc_html($co->{$who}) . "\n". + print "$who" . esc_html($co->{$who}) . "" . + "" . + git_get_avatar($co->{"${who}_email"}, -size => 'double') . + "\n" . "" . " $wd{'rfc2822'}"; print_local_time(%wd); diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index d539619e89..627518108a 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -660,6 +660,7 @@ cat >>gitweb_config.perl < Date: Tue, 30 Jun 2009 00:00:52 +0200 Subject: gitweb: gravatar url cache Views which contain many occurrences of the same email address (e.g. shortlog view) benefit from not having to recalculate the MD5 of the email address every time. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 92695a3ae8..4d7e4ff7a0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1512,6 +1512,27 @@ sub format_subject_html { } } +# Rather than recomputing the url for an email multiple times, we cache it +# after the first hit. This gives a visible benefit in views where the avatar +# for the same email is used repeatedly (e.g. shortlog). +# The cache is shared by all avatar engines (currently gravatar only), which +# are free to use it as preferred. Since only one avatar engine is used for any +# given page, there's no risk for cache conflicts. +our %avatar_cache = (); + +# Compute the gravatar url for a given email, if it's not in the cache already. +# Gravatar stores only the part of the URL before the size, since that's the +# one computationally more expensive. This also allows reuse of the cache for +# different sizes (for this particular engine). +sub gravatar_url { + my $email = lc shift; + my $size = shift; + $avatar_cache{$email} ||= + "http://www.gravatar.com/avatar/" . + Digest::MD5::md5_hex($email) . "?s="; + return $avatar_cache{$email} . $size; +} + # Insert an avatar for the given $email at the given $size if the feature # is enabled. sub git_get_avatar { @@ -1522,8 +1543,7 @@ sub git_get_avatar { my $size = $avatar_size{$opts{-size}} || $avatar_size{'default'}; my $url = ""; if ($git_avatar eq 'gravatar') { - $url = "http://www.gravatar.com/avatar/" . - Digest::MD5::md5_hex(lc $email) . "?s=$size"; + $url = gravatar_url($email, $size); } # Currently only gravatars are supported, but other forms such as # picons can be added by putting an else up here and defining $url -- cgit v1.3 From 679a1a1d420616be1647bdf8b2e93f1f86c7bdae Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 30 Jun 2009 00:00:53 +0200 Subject: gitweb: picon avatar provider Simple implementation of picon that only relies on the indiana.edu database. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 4d7e4ff7a0..862ea99f8a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -378,15 +378,18 @@ our %feature = ( # shortlog or commit will display an avatar associated with # the email of the committer(s) and/or author(s). - # Currently only the gravatar provider is available, and it - # depends on Digest::MD5. If an unknown provider is specified, - # the feature is disabled. + # Currently available providers are gravatar and picon. + # If an unknown provider is specified, the feature is disabled. + + # Gravatar depends on Digest::MD5. + # Picon currently relies on the indiana.edu database. # To enable system wide have in $GITWEB_CONFIG - # $feature{'avatar'}{'default'} = ['gravatar']; + # $feature{'avatar'}{'default'} = ['']; + # where is either gravatar or picon. # To have project specific config enable override in $GITWEB_CONFIG # $feature{'avatar'}{'override'} = 1; - # and in project config gitweb.avatar = gravatar; + # and in project config gitweb.avatar = ; 'avatar' => { 'sub' => \&feature_avatar, 'override' => 0, @@ -853,6 +856,8 @@ our @snapshot_fmts = gitweb_get_feature('snapshot'); our ($git_avatar) = gitweb_get_feature('avatar'); if ($git_avatar eq 'gravatar') { $git_avatar = '' unless (eval { require Digest::MD5; 1; }); +} elsif ($git_avatar eq 'picon') { + # no dependencies } else { $git_avatar = ''; } @@ -1520,6 +1525,20 @@ sub format_subject_html { # given page, there's no risk for cache conflicts. our %avatar_cache = (); +# Compute the picon url for a given email, by using the picon search service over at +# http://www.cs.indiana.edu/picons/search.html +sub picon_url { + my $email = lc shift; + if (!$avatar_cache{$email}) { + my ($user, $domain) = split('@', $email); + $avatar_cache{$email} = + "http://www.cs.indiana.edu/cgi-pub/kinzler/piconsearch.cgi/" . + "$domain/$user/" . + "users+domains+unknown/up/single"; + } + return $avatar_cache{$email}; +} + # Compute the gravatar url for a given email, if it's not in the cache already. # Gravatar stores only the part of the URL before the size, since that's the # one computationally more expensive. This also allows reuse of the cache for @@ -1544,9 +1563,10 @@ sub git_get_avatar { my $url = ""; if ($git_avatar eq 'gravatar') { $url = gravatar_url($email, $size); + } elsif ($git_avatar eq 'picon') { + $url = picon_url($email); } - # Currently only gravatars are supported, but other forms such as - # picons can be added by putting an else up here and defining $url + # Other providers can be added by extending the if chain, defining $url # as needed. If no variant puts something in $url, we assume avatars # are completely disabled/unavailable. if ($url) { -- cgit v1.3 From 7d25ef41c84850ec1405400efc95d78fa6523efc Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 30 Jun 2009 00:00:54 +0200 Subject: gitweb: add empty alt text to avatar img The empty alt text optimizes screen estate in text-only browsers. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 1 + 1 file changed, 1 insertion(+) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 862ea99f8a..6a1b5b5b49 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1574,6 +1574,7 @@ sub git_get_avatar { "" . $post_white; } else { return ""; -- cgit v1.3 From 69fb8283937a18a031aeef12ea2a530c8ccf3e83 Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Sun, 12 Jul 2009 14:31:28 +0200 Subject: gitweb: update Git homepage URL git-scm.com is now the "official" Git project page, having taken over from git.or.cz, so update the default link accordingly. This saves a redirect when people hit git.or.cz. Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gitweb') diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6a1b5b5b49..7fbd5ff89e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -94,7 +94,7 @@ our $favicon = "++GITWEB_FAVICON++"; # URI and label (title) of GIT logo link #our $logo_url = "http://www.kernel.org/pub/software/scm/git/docs/"; #our $logo_label = "git documentation"; -our $logo_url = "http://git.or.cz/"; +our $logo_url = "http://git-scm.com/"; our $logo_label = "git homepage"; # source of projects list -- cgit v1.3