requires 'File::Stat::ModeString';
requires 'File::Which';
requires 'HTML::Entities';
-requires 'IO::Capture::Stdout';
requires 'IPC::Run';
requires 'List::MoreUtils';
requires 'Path::Class' => '0.17';
requires 'Sub::Exporter';
requires 'Syntax::Highlight::Engine::Kate';
+requires 'Sys::Hostname';
+requires 'XML::Atom';
+requires 'XML::RSS';
author_requires 'Test::NoTabs';
author_requires 'Test::Pod' => '1.14';
+++ /dev/null
-* Fix git_blob_plain i.e don't use the wrapper.
-* An action to find what branches have been merged, either as a list or through a search mechanism.
-* An action to find which branches a given commit is on.
-* Fix any not text/html bits e.g the patch action.
-* Simplify the creation of links.
sitename "Gitalist presently"
-# URI and label (title) of GIT logo link
-logo_url git-scm.org
-logo_label "git homepage"
-logo_img /git-logo.png
-
-home_link /
-home_link_str "A Gitalist"
-
-# show repository only if this file exists
-# (only effective if this variable evaluates to true)
-# export_ok
-
-# XXX Code in config FAIL
-# 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"; }
-# export_auth_hook
-
-# stylesheet path/to/your/stylesheet.css
-logo /git-logo.png
-favicon /git-favicon.png
-
# $feature{'blame'}{'default'} = [1];
<feature>
- <blame>
- default = 1
- </blame>
+ <blame>
+ default = 1
+ </blame>
</feature>
# fs traversing limit for getting project list
<paging>
log = 50
- summary = 16
+ summary = 17
</paging>
+
+<patches>
+ max = 16
+</patches>
BEGIN { extends 'Catalyst::Controller' }
-#
-# Sets the actions in this controller to be registered with no prefix
-# so they function identically to actions created in MyApp.pm
-#
__PACKAGE__->config->{namespace} = '';
+use Sys::Hostname ();
+use XML::Atom::Feed;
+use XML::Atom::Entry;
+use XML::RSS;
+
=head1 NAME
Gitalist::Controller::Root - Root Controller for Gitalist
=cut
-=head2 index
-
-=cut
-
-use IO::Capture::Stdout;
-
-=head2 run_gitweb
-
-The C<gitweb> shim. It should now only be explicitly accessible by
-modifying the URL.
-
-=cut
-
-sub run_gitweb {
- my ( $self, $c ) = @_;
-
- # XXX A slippery slope to be sure.
- if($c->req->param('a')) {
- my $capture = IO::Capture::Stdout->new();
- $capture->start();
- eval {
- my $action = gitweb::main($c);
- $action->();
- };
- $capture->stop();
-
- use Data::Dumper;
- die Dumper($@)
- if $@;
-
- my $output = join '', $capture->read;
- $c->stash->{gitweb_output} = $output;
- $c->stash->{template} = 'gitweb.tt2';
- }
-}
-
sub _get_object {
my($self, $c, $haveh) = @_;
my $maxitems = Gitalist->config->{paging}{summary} || 10;
$c->stash(
commit => $commit,
-# info => $project->info,
log_lines => [$project->list_revs(
sha1 => $commit->sha1,
count => $maxitems,
);
}
+=head2 tags
+
+The current list of tags in the repo.
+
+=cut
+
+sub tags : Local {
+ my ( $self, $c ) = @_;
+ my $project = $c->stash->{Project};
+ $c->stash(
+ commit => $self->_get_object($c),
+ tags => $project->tags,
+ action => 'tags',
+ );
+}
+
+sub blame : Local {
+ my($self, $c) = @_;
+
+ my $project = $c->stash->{Project};
+ my $h = $c->req->param('h')
+ || $project->hash_by_path($c->req->param('hb'), $c->req->param('f'))
+ || die "No file or sha1 provided.";
+ my $hb = $c->req->param('hb')
+ || $project->head_hash
+ || die "Couldn't discern the corresponding head.";
+ my $filename = $c->req->param('f') || '';
+
+ $c->stash(
+ blame => $project->get_object($hb)->blame($filename),
+ head => $project->get_object($hb),
+ filename => $filename,
+ );
+
+}
+
=head2 blob
The blob action i.e the contents of a file.
action => 'blob',
);
- $c->forward('View::SyntaxHighlight');
+ $c->forward('View::SyntaxHighlight')
+ unless $c->stash->{no_wrapper};
+}
+
+sub blob_plain : Local {
+ my($self, $c) = @_;
+
+ $c->stash(no_wrapper => 1);
+ $c->response->content_type('text/plain; charset=utf-8');
+
+ $c->forward('blob');
+}
+
+sub blobdiff_plain : Local {
+ my($self, $c) = @_;
+
+ $c->stash(no_wrapper => 1);
+ $c->response->content_type('text/plain; charset=utf-8');
+
+ $c->forward('blobdiff');
+
}
=head2 blobdiff
|| croak("No file specified!");
my($tree, $patch) = $c->stash->{Project}->diff(
commit => $commit,
- parent => $c->req->param('hpb') || '',
- file => $filename,
patch => 1,
+ parent => $c->req->param('hpb') || undef,
+ file => $filename,
);
$c->stash(
commit => $commit,
diff => $patch,
+ filename => $filename,
# XXX Hack hack hack, see View::SyntaxHighlight
blobs => [$patch->[0]->{diff}],
language => 'Diff',
action => 'blobdiff',
);
- $c->forward('View::SyntaxHighlight');
+ $c->forward('View::SyntaxHighlight')
+ unless $c->stash->{no_wrapper};
}
=head2 commit
action => 'commitdiff',
);
- $c->forward('View::SyntaxHighlight');
+ $c->forward('View::SyntaxHighlight')
+ unless $c->stash->{no_wrapper};
+}
+
+sub commitdiff_plain : Local {
+ my($self, $c) = @_;
+
+ $c->stash(no_wrapper => 1);
+ $c->response->content_type('text/plain; charset=utf-8');
+
+ $c->forward('commitdiff');
}
=head2 shortlog
sub shortlog : Local {
my ( $self, $c ) = @_;
- my $project = $c->stash->{Project};
- my $commit = $self->_get_object($c);
+
+ my $project = $c->stash->{Project};
+ my $commit = $self->_get_object($c);
+ my $filename = $c->req->param('f') || '';
+
my %logargs = (
sha1 => $commit->sha1,
count => Gitalist->config->{paging}{log} || 25,
- ($c->req->param('f') ? (file => $c->req->param('f')) : ())
+ ($filename ? (file => $filename) : ())
);
my $page = $c->req->param('pg') || 0;
commit => $commit,
log_lines => [$project->list_revs(%logargs)],
refs => $project->references,
- action => 'shortlog',
page => $page,
+ filename => $filename,
+ action => 'shortlog',
);
}
$_[1]->stash->{action} = 'log';
}
+# For legacy support.
+sub history : Local {
+ $_[0]->shortlog(@_[1 .. $#_]);
+}
+
=head2 tree
The tree of a given commit.
);
}
+=head2 search
+
+The action for the search form.
+
+=cut
+
sub search : Local {
my($self, $c) = @_;
$c->stash(current_action => 'GitRepos');
sha1 => $commit->sha1,
count => Gitalist->config->{paging}{log},
($c->req->param('f') ? (file => $c->req->param('f')) : ()),
- search => {
- type => $c->req->param('type'),
- text => $c->req->param('text'),
- regexp => $c->req->param('regexp') || 0,
- }
+ search => {
+ type => $c->req->param('type'),
+ text => $c->req->param('text'),
+ regexp => $c->req->param('regexp') || 0,
+ },
);
$c->stash(
);
}
+=head2 search_help
+
+Provides some help for the search form.
+
+=cut
+
sub search_help : Local {
my ($self, $c) = @_;
$c->stash(template => 'search_help.tt2');
}
+=head2 atom
+
+Provides an atom feed for a given project.
+
+=cut
+
sub atom : Local {
- # FIXME - implement atom
- Carp::croak "Not implemented.";
+ my($self, $c) = @_;
+
+ my $feed = XML::Atom::Feed->new;
+
+ my $host = lc Sys::Hostname::hostname();
+ $feed->title($host . ' - ' . Gitalist->config->{name});
+ $feed->updated(~~DateTime->now);
+
+ my $project = $c->stash->{Project};
+ my %logargs = (
+ sha1 => $project->head_hash,
+ count => Gitalist->config->{paging}{log} || 25,
+ ($c->req->param('f') ? (file => $c->req->param('f')) : ())
+ );
+
+ my $mk_title = $c->stash->{short_cmt};
+ for my $commit ($project->list_revs(%logargs)) {
+ my $entry = XML::Atom::Entry->new;
+ $entry->title( $mk_title->($commit->comment) );
+ $entry->id($c->uri_for('commit', {h=>$commit->sha1}));
+ # XXX Needs work ...
+ $entry->content($commit->comment);
+ $feed->add_entry($entry);
+ }
+
+ $c->response->body($feed->as_xml);
+ $c->response->content_type('application/atom+xml');
+ $c->response->status(200);
}
+=head2 rss
+
+Provides an RSS feed for a given project.
+
+=cut
+
sub rss : Local {
- # FIXME - implement rss
- Carp::croak "Not implemented.";
-}
+ my ($self, $c) = @_;
-sub blobdiff_plain : Local {
- # FIXME - implement blobdiff_plain
- Carp::croak "Not implemented.";
-}
+ my $project = $c->stash->{Project};
-sub blob_plain : Local {
- # FIXME - implement blobdiff_plain
- Carp::croak "Not implemented.";
+ my $rss = XML::RSS->new(version => '2.0');
+ $rss->channel(
+ title => lc(Sys::Hostname::hostname()) . ' - ' . Gitalist->config->{name},
+ link => $c->uri_for('summary', {p=>$project->name}),
+ language => 'en',
+ description => $project->description,
+ pubDate => DateTime->now,
+ lastBuildDate => DateTime->now,
+ );
+
+ my %logargs = (
+ sha1 => $project->head_hash,
+ count => Gitalist->config->{paging}{log} || 25,
+ ($c->req->param('f') ? (file => $c->req->param('f')) : ())
+ );
+ my $mk_title = $c->stash->{short_cmt};
+ for my $commit ($project->list_revs(%logargs)) {
+ # XXX Needs work ....
+ $rss->add_item(
+ title => $mk_title->($commit->comment),
+ permaLink => $c->uri_for(commit => {h=>$commit->sha1}),
+ description => $commit->comment,
+ );
+ }
+
+ $c->response->body($rss->as_string);
+ $c->response->content_type('application/rss+xml');
+ $c->response->status(200);
}
+=head2 patch
+
+A raw patch for a given commit.
+
+=cut
+
sub patch : Local {
- # FIXME - implement patches
- Carp::croak "Not implemented.";
+ my ($self, $c) = @_;
+ $c->detach('patches', [1]);
}
+=head2 patches
+
+The patcheset for a given commit ???
+
+=cut
+
sub patches : Local {
- # FIXME - implement patches
- Carp::croak "Not implemented.";
+ my ($self, $c, $count) = @_;
+ $count ||= Gitalist->config->{patches}{max};
+ my $commit = $self->_get_object($c);
+ my $parent = $c->req->param('hp') || undef;
+ my $patch = $commit->get_patch( $parent, $count );
+ $c->response->body($patch);
+ $c->response->content_type('text/plain');
+ $c->response->status(200);
}
-sub snapshot : Local {
- # FIXME - implement snapshot
- Carp::croak "Not implemented.";
-}
+=head2 snapshot
-sub commitdiff_plain : Local {
- # FIXME - implement commitdiff_plain
- Carp::croak "Not implemented.";
+Provides a snapshot of a given commit.
+
+=cut
+
+sub snapshot : Local {
+ my ($self, $c) = @_;
+ my $format = $c->req->param('sf') || 'tgz';
+ die unless $format;
+ my $sha1 = $c->req->param('h') || $self->_get_object($c)->sha1;
+ my @snap = $c->stash->{Project}->snapshot(
+ sha1 => $sha1,
+ format => $format
+ );
+ $c->response->status(200);
+ $c->response->headers->header( 'Content-Disposition' =>
+ "attachment; filename=$snap[0]");
+ $c->response->body($snap[1]);
}
=head2 auto
sub auto : Private {
my($self, $c) = @_;
- # XXX Move these to a plugin!
+ my $project = $c->req->param('p');
+ if (defined $project) {
+ eval {
+ $c->stash(Project => $c->model('GitRepos')->project($project));
+ };
+ if ($@) {
+ $c->detach('error_404');
+ }
+ }
+
+ my $a_project = $c->stash->{Project} || $c->model()->projects->[0];
$c->stash(
+ git_version => $a_project->run_cmd('--version'),
+ version => $Gitalist::VERSION,
+
+ # XXX Move these to a plugin!
time_since => sub {
return 'never' unless $_[0];
return age_string(time - $_[0]->epoch);
join(' ', grep { defined } (split / /, shift)[0..10]);
},
);
-
- # Yes, this is hideous.
- $self->header($c);
- $self->footer($c);
-}
-
-# XXX This could probably be dropped altogether.
-use Gitalist::Util qw(to_utf8);
-# Formally git_header_html
-sub header {
- my($self, $c) = @_;
-
- my $title = $c->config->{sitename};
-
- my $project = $c->req->param('project') || $c->req->param('p');
- my $action = $c->req->param('action') || $c->req->param('a');
- my $file_name = $c->req->param('filename') || $c->req->param('f');
- if(defined $project) {
- $title .= " - " . to_utf8($project);
- if (defined $action) {
- $title .= "/$action";
- if (defined $file_name) {
- $title .= " - " . $file_name;
- if ($action eq "tree" && $file_name !~ m|/$|) {
- $title .= "/";
- }
- }
- }
- }
-
- $c->stash->{version} = $Gitalist::VERSION;
- # check git's version by running it on the first project in the list.
- $c->stash->{title} = $title;
-
- $c->stash->{stylesheet} = $c->config->{stylesheet} || 'gitweb.css';
-
- $c->stash->{project} = $project;
- my @links;
- if($project) {
- my %href_params = $self->feed_info($c);
- $href_params{'-title'} ||= 'log';
-
- foreach my $format qw(RSS Atom) {
- my $type = lc($format);
- push @links, {
- rel => 'alternate',
- title => "$project - $href_params{'-title'} - $format feed",
-
- # XXX A bit hacky and could do with using gitweb::href() features
- href => "?a=$type;p=$project",
- type => "application/$type+xml"
- }, {
- rel => 'alternate',
-
- # XXX This duplication also feels a bit awkward
- title => "$project - $href_params{'-title'} - $format feed (no merges)",
- href => "?a=$type;p=$project;opt=--no-merges",
- type => "application/$type+xml"
- };
- }
- } else {
- push @links, {
- rel => "alternate",
- title => $c->config->{sitename}." projects list",
- href => '?a=project_index',
- type => "text/plain; charset=utf-8"
- }, {
- rel => "alternate",
- title => $c->config->{sitename}." projects feeds",
- href => '?a=opml',
- type => "text/plain; charset=utf-8"
- };
- }
-
- $c->stash->{favicon} = $c->config->{favicon};
-
- # </head><body>
-
- $c->stash(
- logo_url => $c->config->{logo_url},
- logo_label => $c->config->{logo_label},
- logo_img => $c->config->{logo},
- home_link => $c->config->{home_link},
- home_link_str => $c->config->{home_link_str},
- );
-
- if (defined $project) {
- eval {
- $c->stash(Project => $c->model('GitRepos')->project($project));
- };
- if ($@) {
- $c->detach('error_404');
- }
- $c->stash(
- search_text => ( $c->req->param('s') ||
- $c->req->param('searchtext') || ''),
- search_hash => ( $c->req->param('hb') || $c->req->param('hashbase')
- || $c->req->param('h') || $c->req->param('hash')
- || 'HEAD' ),
- );
- }
- my $a_project = $c->stash->{Project} || $c->model()->projects->[0];
- $c->stash->{git_version} = $a_project->run_cmd('--version');
}
-# Formally git_footer_html
-sub footer {
- my($self, $c) = @_;
-
- my $feed_class = 'rss_logo';
-
- my @feeds;
- my $project = $c->req->param('project') || $c->req->param('p');
- if(defined $project) {
- (my $pstr = $project) =~ s[/?\.git$][];
- my $descr = $c->stash->{project_description}
- = $c->stash->{Project} ? $c->stash->{Project}->description : '';
-
- my %href_params = $self->feed_info($c);
- if (!%href_params) {
- $feed_class .= ' generic';
- }
- $href_params{'-title'} ||= 'log';
-
- @feeds = [
- map +{
- class => $feed_class,
- title => "$href_params{'-title'} $_ feed",
- href => "/?p=$project;a=\L$_",
- name => lc $_,
- }, qw(RSS Atom)
- ];
- } else {
- @feeds = [
- map {
- class => $feed_class,
- title => '',
- href => "/?a=$_->[0]",
- name => $_->[1],
- }, [opml=>'OPML'],[project_index=>'TXT'],
- ];
- }
+sub project_index : Local {
+ # FIXME - implement snapshot
+ Carp::croak "Not implemented.";
}
-
-# XXX This feels wrong here, should probably be refactored.
-# returns hash to be passed to href to generate gitweb URL
-# in -title key it returns description of link
-sub feed_info {
- my($self, $c) = @_;
-
- my $format = shift || 'Atom';
- my %res = (action => lc($format));
-
- # feed links are possible only for project views
- return unless $c->req->param('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 $c->req->param('action') =~ /^(?:tags|heads|forks|tag|search)$/x;
-
- my $branch;
- my $hash = $c->req->param('h') || $c->req->param('hash');
- my $hash_base = $c->req->param('hb') || $c->req->param('hashbase');
-
- # 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';
- my $file_name = $c->req->param('f') || $c->req->param('filename');
- if (defined $file_name) {
- $type = "history of $file_name";
- $type .= "/" if $c->req->param('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;
+sub opml : Local {
+ # FIXME - implement snapshot
+ Carp::croak "Not implemented.";
}
=head2 end
}
sub age_string {
- my $age = shift;
- my $age_str;
-
- if ($age > 60*60*24*365*2) {
- $age_str = (int $age/60/60/24/365);
- $age_str .= " years ago";
- } elsif ($age > 60*60*24*(365/12)*2) {
- $age_str = int $age/60/60/24/(365/12);
- $age_str .= " months ago";
- } elsif ($age > 60*60*24*7*2) {
- $age_str = int $age/60/60/24/7;
- $age_str .= " weeks ago";
- } elsif ($age > 60*60*24*2) {
- $age_str = int $age/60/60/24;
- $age_str .= " days ago";
- } elsif ($age > 60*60*2) {
- $age_str = int $age/60/60;
- $age_str .= " hours ago";
- } elsif ($age > 60*2) {
- $age_str = int $age/60;
- $age_str .= " min ago";
- } elsif ($age > 2) {
- $age_str = int $age;
- $age_str .= " sec ago";
- } else {
- $age_str .= " right now";
- }
- return $age_str;
+ my $age = shift;
+ my $age_str;
+
+ if ( $age > 60 * 60 * 24 * 365 * 2 ) {
+ $age_str = ( int $age / 60 / 60 / 24 / 365 );
+ $age_str .= " years ago";
+ }
+ elsif ( $age > 60 * 60 * 24 * ( 365 / 12 ) * 2 ) {
+ $age_str = int $age / 60 / 60 / 24 / ( 365 / 12 );
+ $age_str .= " months ago";
+ }
+ elsif ( $age > 60 * 60 * 24 * 7 * 2 ) {
+ $age_str = int $age / 60 / 60 / 24 / 7;
+ $age_str .= " weeks ago";
+ }
+ elsif ( $age > 60 * 60 * 24 * 2 ) {
+ $age_str = int $age / 60 / 60 / 24;
+ $age_str .= " days ago";
+ }
+ elsif ( $age > 60 * 60 * 2 ) {
+ $age_str = int $age / 60 / 60;
+ $age_str .= " hours ago";
+ }
+ elsif ( $age > 60 * 2 ) {
+ $age_str = int $age / 60;
+ $age_str .= " min ago";
+ }
+ elsif ( $age > 2 ) {
+ $age_str = int $age;
+ $age_str .= " sec ago";
+ }
+ else {
+ $age_str .= " right now";
+ }
+ return $age_str;
}
+
=head1 AUTHOR
Dan Brook
is => 'ro',
lazy_build => 1,
handles => [ 'run_cmd',
+ 'run_cmd_fh',
'run_cmd_list',
'get_gpp_object',
'gpp',
weak_ref => 1,
handles => {
_run_cmd => 'run_cmd',
+ _run_cmd_fh => 'run_cmd_fh',
_run_cmd_list => 'run_cmd_list',
_get_gpp_object => 'get_gpp_object',
},
use MooseX::Declare;
class Gitalist::Git::Object::Blob extends Gitalist::Git::Object {
- has '+type' => ( default => 'blob' );
+ has '+type' => ( default => 'blob' );
}
with Gitalist::Git::Object::HasTree {
use MooseX::Types::Moose qw/Str Int Bool Maybe ArrayRef/;
use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
+ use Moose::Autobox;
use List::MoreUtils qw/any zip/;
our $SHA1RE = qr/[0-9a-fA-F]{40}/;
],
);
- method diff ( Maybe[Bool] :$patch?,
+ method get_patch ( Maybe[NonEmptySimpleStr] $parent_hash?,
+ Int $patch_count?) {
+ # assembling the git command to execute...
+ my @cmd = qw/format-patch --encoding=utf8 --stdout/;
+
+ # patch, or patch set?
+ push @cmd,
+ defined $patch_count
+ ? "-$patch_count -n" : "-1";
+
+ # refspec
+ if (defined $parent_hash) {
+ # if a parent is specified: hp..h
+ push @cmd, "$parent_hash.." . $self->sha1;
+ } else {
+ # if not, but a merge commit: --cc h
+ # otherwise: --root h
+ push @cmd, $self->parents->length > 1
+ ? '--cc' : '--root';
+ push @cmd, $self->sha1;
+ }
+ return $self->_run_cmd_fh( @cmd );
+ }
+
+ method diff ( Maybe[Bool] :$patch?,
Maybe[NonEmptySimpleStr] :$parent?,
Maybe[NonEmptySimpleStr] :$file?
) {
return @ret;
}
+
+ # XXX A prime candidate for caching.
+ method blame ( NonEmptySimpleStr $filename ) {
+ my @blameout = $self->_run_cmd_list(
+ blame => '-p', $self->sha1, '--', $filename
+ );
+
+ my(%commitdata, @filedata);
+ while(defined(local $_ = shift @blameout)) {
+ my ($sha1, $orig_lineno, $lineno, $group_size) =
+ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/;
+
+ $commitdata{$sha1} = {}
+ unless exists $commitdata{$sha1};
+
+ my $commit = $commitdata{$sha1};
+ my $line;
+ until(($line = shift @blameout) =~ s/^\t//) {
+ $commit->{$1} = $2
+ if $line =~ /^(\S+) (.*)/;
+ }
+
+ unless(exists $commit->{author_dt}) {
+ for my $t (qw/author committer/) {
+ my $dt = DateTime->from_epoch(epoch => $commit->{"$t-time"});
+ $dt->set_time_zone($commit->{"$t-tz"});
+ $commit->{"$t\_dt"} = $dt;
+ }
+ }
+
+ push @filedata, {
+ line => $line,
+ commit => { sha1 => $sha1, %$commit },
+ meta => {
+ orig_lineno => $orig_lineno,
+ lineno => $lineno,
+ ( $group_size ? (group_size => $group_size) : () ),
+ },
+ };
}
+
+ return \@filedata;
+ }
+}
use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
use MooseX::Types::Path::Class qw/Dir/;
use MooseX::Types::Moose qw/Str Maybe Bool HashRef ArrayRef/;
+ use Moose::Autobox;
use List::MoreUtils qw/any zip/;
use DateTime;
use Gitalist::Git::Object::Blob;
has heads => ( isa => ArrayRef[HashRef],
is => 'ro',
lazy_build => 1);
+=head2 tags
+
+ArrayRef of hashes containing the name and sha1 of all tags.
+
+=cut
+ has tags => ( isa => ArrayRef[HashRef],
+ is => 'ro',
+ lazy_build => 1);
=head2 references
return @revs;
}
+=head2 snapshot($sha1, $format)
+
+Generate an archived snapshot of the repository.
+$sha1 should be a commit or tree.
+Returns a filehandle to read from.
+
+=cut
+
+method snapshot (NonEmptySimpleStr :$sha1,
+ NonEmptySimpleStr :$format
+ ) {
+ # TODO - only valid formats are 'tar' and 'zip'
+ my $formats = { tgz => 'tar', zip => 'zip' };
+ unless ($formats->exists($format)) {
+ die("No such format: $format");
+ }
+ $format = $formats->{$format};
+ my $name = $self->name;
+ $name =~ s,([^/])/*\.git$,$1,;
+ my $filename = $name;
+ $filename .= "-$sha1.$format";
+ $name =~ s/\047/\047\\\047\047/g;
+
+ my @cmd = ('archive', "--format=$format", "--prefix=$name/", $sha1);
+ return ($filename, $self->run_cmd_fh(@cmd));
+ # TODO - support compressed archives
+}
+
=head2 diff($commit, $patch?, $parent?, $file?)
Generate a diff from a given L<Gitalist::Git::Object>.
return \@ret;
}
+ method _build_tags {
+ my @revlines = $self->run_cmd_list('for-each-ref',
+ '--sort=-creatordate',
+ '--format=%(objectname) %(objecttype) %(refname) %(*objectname) %(*objecttype) %(subject)%00%(creator)',
+ 'refs/tags'
+ );
+ my @ret;
+ for my $line (@revlines) {
+ my($refinfo, $creatorinfo) = split /\0/, $line;
+ my($rev, $type, $name, $refid, $reftype, $title) = split(' ', $refinfo, 6);
+ my($creator, $epoch, $tz) = ($creatorinfo =~ /^(.*) ([0-9]+) (.*)$/);
+ $name =~ s!^refs/tags/!!;
+
+ push @ret, { sha1 => $rev, name => $name };
+
+ #FIXME: That isn't the time I'm looking for..
+ if($epoch and $tz) {
+ my $dt = DateTime->from_epoch(epoch => $epoch);
+ $dt->set_time_zone($tz);
+ $ret[-1]->{last_change} = $dt;
+ }
+ }
+
+ return \@ret;
+ }
+
method _build_references {
# 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11
# c39ae07f393806ccf406ef966e9a15afc43cc36a refs/tags/v2.6.11^{}
use File::Which;
use Git::PurePerl;
use IPC::Run qw(run);
+ use Symbol qw(geniosym);
use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
has project => (
return $out;
}
+ method run_cmd_fh (@args) {
+ my ($in, $out, $err) = (geniosym, geniosym, geniosym);
+ unshift @args, ('--git-dir' => $self->gitdir)
+ if $self->has_project;
+# print STDERR 'RUNNING: ', $self->_git, qq[ @args], $/;
+ run [$self->_git, @args],
+ '<pipe', $in,
+ '>pipe', $out,
+ '2>pipe', $err
+ or die "cmd returned *?";
+ return ($out, $err);
+ }
+
method run_cmd_list (@args) {
my $cmdout = $self->run_cmd(@args);
return $cmdout ? split(/\n/, $cmdout) : ();
+++ /dev/null
-package Gitalist::Util;
-
-use Sub::Exporter -setup => {
- exports => ['to_utf8']
-};
-
-=pod
-
-=head1 NAME
-
-Gitalist::Util - Your usual catch all utility function package.
-
-=cut
-
-# 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;
- if (utf8::valid($str)) {
- utf8::decode($str);
- return $str;
- } else {
- return decode($fallback_encoding, $str, Encode::FB_DEFAULT);
- }
-}
-
-1;
=cut
__PACKAGE__->config(
- TEMPLATE_EXTENSION => '.tt2',
- WRAPPER => 'default.tt2',
+ TEMPLATE_EXTENSION => '.tt2',
+ WRAPPER => 'default.tt2',
);
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
use FindBin;
binmode STDOUT, ':utf8';
-use Gitalist::Util qw(to_utf8);
-
BEGIN {
CGI->compile();
}
return @list && scalar(grep { $_->{'path'} eq $project } @list);
}
+# 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;
+ if (utf8::valid($str)) {
+ utf8::decode($str);
+ return $str;
+ } else {
+ return decode($fallback_encoding, $str, Encode::FB_DEFAULT);
+ }
+}
+
## ----------------------------------------------------------------------
## HTML aware string manipulation
-[% sha1 = sha1 || HEAD %]
-<span class='chroma-hash'>
- [%
+[%- sha1 = sha1 || HEAD -%]
+<span class='chroma-hash'>[%-
hptr = 0;
WHILE hptr < sha1.length - 6;
sha1part = sha1.substr(hptr, 6);
"<span style='border-bottom: solid 4px #" _ sha1part _ ";'>" _ sha1part _ "</span>";
hptr = hptr + 6;
END;
- %]
-</span>
+-%]</span>
--- /dev/null
+[%- FOREACH item IN diff -%]
+diff --git [% item.a _ ' ' _ item.b %]
+[% item.index %]
+[% blobs.${loop.index} %]
+[%- END -%]
-<table class='diff-tree'>
+<table class='diff-tree listing'>
<thead>
<tr>
<th>file</th>
<tbody>
[% FOREACH line IN diff_tree -%]
<tr>
- <td class='filename'>
+ <td class='file-name'>
[% line.file %]
</td>
<td class='status'>
--- /dev/null
+ [% IF Project %]
+ [%-
+ has_branch = c.req.param('h').match('^(refs/heads/.*)') || c.req.param('hb').match('^(refs/heads/.*)');
+ branch = has_branch.0 || '';
+ feed_title = 'log';
+ feed_fn = c.req.param('f');
+ IF feed_fn;
+ title = 'history of ' _ c.req.param('filename');
+ title = title _ (branch ? ' on ' _ branch : '');
+ ELSE;
+ title = title _ (branch ? ' of ' _ branch : '');
+ END;
+
+ feed_args = { h = branch || c.req.param('h') || c.req.param('hb') || 'HEAD' };
+ IF feed_fn; feed_args.f = feed_fn; END;
+ -%]
+ <a
+ class="rss_logo"
+ title="[% feed_title %]"
+ href="[% c.uri_for('rss', feed_args) %]">RSS</a>
+ <a
+ class="rss_logo"
+ title="[% feed_title %]"
+ href="[% c.uri_for('atom', feed_args) %]">Atom</a>
+ [% ELSE %]
+ <a
+ class="rss_logo"
+ href="[% c.uri_for('opml') %]">OPML</a>
+ <a
+ class="rss_logo"
+ href="[% c.uri_for('project_index') %]">TXT</a>
+ [% END %]
--- /dev/null
+ [% IF Project %]
+ <!-- XXX Missing the no-merges links -->
+ <link
+ rel="alternate"
+ title="[% Project.name %] - [% title %] Atom feed"
+ href="[% c.uri_for('atom') %]"
+ type="application/atom+xml"
+ >
+ <link
+ rel="alternate"
+ title="[% Project.name %] - [% title %] RSS feed"
+ href="[% c.uri_for('rss') %]"
+ type="application/rss+xml"
+ >
+ [% ELSE %]
+ <link
+ rel="alternate"
+ title="[% c.config.sitename %] Git projects list"
+ href="[% c.uri_for('project_index') %]"
+ type="text/plain; charset=utf-8"
+ >
+ <link
+ rel="alternate"
+ title="[% c.config.sitename %] Git projects feeds"
+ href="[% c.uri_for('opml') %]"
+ type="text/x-opml"
+ >
+ [% END %]
-<table class='heads'>
+<table class='[% action %] listing'>
<thead>
<tr>
<th>HEAD</th>
<tbody>
[% FOREACH head IN heads %]
<tr>
- <td>[% INCLUDE '_chroma_hash.tt2' sha1 = head.sha1.substr(0,7) %]</td>
- <td class='time-since'>[% time_since(head.last_change) %]</td>
+ <td class='sha1' title='[% head.sha1 %]'>[% INCLUDE '_chroma_hash.tt2' sha1 = head.sha1.substr(0,7) %]</td>
+ <td class='time-since' title='[% head.last_change %]'>[% time_since(head.last_change) %]</td>
<td class='head[% head.sha1 == HEAD ? ' current' : '' %]'>[% head.name %]</td>
<td class='action-list'>
<a href="[% c.uri_for("shortlog", {h='refs/heads/' _ head.name}) %]">shortlog</a>
-<table class='shortlog'>
+<table class='shortlog listing'>
<thead>
<tr>
<th>sha1</th>
<tbody>
[% FOREACH line IN log_lines %]
<tr>
- <td class='sha1'>[% INCLUDE '_chroma_hash.tt2' sha1 = line.sha1.substr(0, 7) %]</td>
- <td class='time-since'>[% time_since(line.authored_time) %]</td>
+ <td class='sha1' title='[% line.sha1 %]'>[% INCLUDE '_chroma_hash.tt2' sha1 = line.sha1.substr(0, 7) %]</td>
+ <td class='time-since' title='[% line.authored_time %]'>[% time_since(line.authored_time) %]</td>
<td class='author'>[% line.author.name | html %]</td>
<td>
[% short_cmt(line.comment) | html %]
-<table>
+<table class='tree listing'>
<thead>
<tr>
<th>mode</th>
<tbody>
[% FOREACH item IN tree_list %]
<tr>
- <td>[% item.modestr %]</td>
+ <td class='file-mode'>[% item.modestr %]</td>
[% theact = item.type == 'tree' ? 'tree' : 'blob' -%]
- <td class='filename'>
+ <td class='file-name'>
<a href="[% c.uri_for(theact, {h=item.sha1, hb=commit.sha1, f=(path ? path _ '/' _ item.file : item.file)}) %]">[% item.file %]</a>
</td>
<td class='action-list'>
--- /dev/null
+[% PROCESS 'nav/actions.tt2' object = head %]
+[% IF object.type == 'commit' %]
+<div class='commit-message'>
+[% head.comment.substr(0, 85) %] ...
+</div>
+[% END %]
+
+<h3>BLOB PATH</h3>
+
+<div id='blame'>
+<table>
+ <thead>
+ <tr>
+ <th>sha1</th>
+ <th>line</th>
+ <th>data</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr>
+ <td>sha1</td>
+ <td>line</td>
+ <td>data</td>
+ </tr>
+ </tfoot>
+
+ <tbody>
+ [% FOR info IN blame %]
+ <tr class=''>
+ <td class='commit-info'><a title="[% info.commit.author %] on [% info.commit.author_dt %]" href='[% c.uri_for('commit', {h=info.commit.sha1}) %]'>[% INCLUDE '_chroma_hash.tt2' sha1 = info.commit.sha1.substr(0,7) -%]</a></td>
+ <td class='lineno'><tt>[% info.meta.lineno %]</tt></td>
+ <td><pre>[% info.line | html %]</pre></td>
+ </tr>
+ [% END %]
+ </tbody>
+</table>
+</div>
</div>
[% END %]
<div class='path'>
- <a href="[% c.uri_for("tree", {hb=head.sha1}) %]">[% project %]</a>
+ <a href="[% c.uri_for("tree", {hb=head.sha1}) %]">[% Project.name %]</a>
[% # XXX The last part should link to blob_plain (or something) but doesn't ATM
FOREACH part IN filename.split('/') %]
/ <a href="[% c.uri_for("tree", {hb=head.sha1}) %]">[% part %]</a>
--- /dev/null
+[% blob %]
--- /dev/null
+[%- INCLUDE '_diff_plain.tt2' -%]
INCLUDE '_refs.tt2' object = commit;
%]
</div>
-
+<!-- [% USE dumper; dumper.dump(commit.parents) %] -->
<dl class='commit-info'>
<dt>author</dt>
<dd>[% commit.author.name | html %] <[% commit.author.email %]><br/>
<dt>parent</dt>
<dd>[% parent.sha1 %]
<span class='action-list'>
- <a href="[% c.uri_for("commit", {h=parent.sha1}) %]">commit</a>
- <a href="[% c.uri_for("commitdiff", {hp=parent.sha1, h=commit.sha1}) %]">diff</a>
- </span>
+ <a href="[% c.uri_for("commit", {h=parent.sha1}) %]">commit</a>
+ <a href="[% c.uri_for("commitdiff", {hp=parent.sha1, h=commit.sha1}) %]">diff</a>
+ </span>
</dd>
[% END %]
</dl>
--- /dev/null
+[%- INCLUDE '_diff_plain.tt2' -%]
-[%- # git_header_html
--%]
+[%- IF no_wrapper || template.name.match('\.(css|js|txt)'); content; ELSE; -%]
<!DOCTYPE html>
<html lang="en">
<head>
<!-- git web interface version [% version %], (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
<!-- git core binaries version [% git_version %] -->
- <meta charset="utf-8"/>
+ <meta charset="utf-8">
<meta name="generator" content="gitweb/[% version %] git/[% git_version %][% mod_perl_version %]"/>
<meta name="robots" content="index, nofollow"/>
- <title>[% title | html %] (Gitalist)</title>
- [% IF baseurl %]
- <base href="[% baseurl %]" />
- [% END %]
+ <title>[%-
+ title = BLOCK;
+ c.config.sitename;
+ IF Project; ' - ' _ Project.name | html; END;
+ IF action; ' / ' _ action; END;
+ IF filename; ' - ' _ filename | html; END;
+ IF action && action == 'tree'; '/'; END;
+ END;
+ title;
+ -%] (Gitalist)</title>
+ [% INCLUDE '_header_feeds.tt2' %]
<link rel="stylesheet" href="[% c.uri_for('/static/css/blueprint/screen.css') %]" type="text/css" media="screen, projection">
<link rel="stylesheet" href="[% c.uri_for('/static/css/blueprint/print.css') %]" type="text/css" media="print">
<!--[if lt IE 8]>
<link rel="stylesheet" href="[% c.uri_for('/static/css/blueprint/ie.css') %]" type="text/css" media="screen, projection">
<![endif]-->
- <link rel="stylesheet" type="text/css" href="[% c.uri_for('/static/css/site.css') %]"/>
-
- [% FOR link IN links %]
- <link rel="[% link.rel %]"
- title="[% link.title %]"
- href="[% link.href %]"
- type="[% link.type %]"
- />
- [% END %]
- [% IF favicon %]
- <link rel="shortcut icon" href="[% favicon %]" type="image/png" />
- [% END %]
+ <link rel="stylesheet" type="text/css" href="[% c.uri_for('/static/css/site.css') %]">
+ <link rel="shortcut icon" href="[% c.uri_for('git-favicon.png') %]" type="image/png">
</head>
<body>
[% site_header %]
<div id="page-header">
- <a title="[% logo_label | url %]" href="[% logo_url | url %]"><img src="[% logo_img %]" alt="git" class="logo"/></a>
- <a href="[% home_link | url %]">[% home_link_str %]</a>
- [%- IF project %]
- / <a href="[% c.uri_for('summary') %]">[% project %]</a>
+ <a title="git homepage" href="http://git-scm.org">
+ <img src="[% c.uri_for('/logo.png') %]" alt="git" class="logo">
+ </a>
+ <a href="[% c.uri_for('/') %]">A Gitalist</a>
+ [%- IF Project %]
+ / <a href="[% c.uri_for('summary') %]">[% Project.name %]</a>
[% IF action; " / " _ action; END;
END %]
[%
- IF project;
+ IF Project;
INCLUDE 'nav/search.tt2';
END;
# / git_header_html
%]
</div>
-[%- # git_footer_html
--%]
<div id="page-footer">
-[% IF project AND project_description %]
- <div class="page_footer_text">[% project_description | html %]</div>
-[% END %]
-[% FOR feed IN feeds %]
- <a class="[% feed.class %]" title="[% feed.title %]" href="[% feed.href %]">[% feed.name %]</a>
+[% IF Project %]
+ [% Project.description | html %]
[% END %]
+[% INCLUDE '_footer_feeds.tt2' %]
</div>
-[% site_footer %]
-
</body>
</html>
-[%- # / git_footer_html
--%]
+[%- END -%]
[% INCLUDE 'nav/actions.tt2' object = commit %]
<div>
-[% project %]
+[% Project.name %]
</div>
[% INCLUDE '_heads.tt2' %]
</div>
<div class="meta">
<table class='summary' cellspacing='0' cellpadding='0'>
- <tr><td>author</td><td>[% line.author.name | html %]</td></tr>
- <tr><td>authored time</td><td>[% line.authored_time %]</td></tr>
+ <tr><td>author</td><td class='author'>[% line.author.name | html %]</td></tr>
+ <tr><td>authored time</td><td class='time'>[% line.authored_time %]</td></tr>
[% IF line.author.name != line.committer.name %]
- <tr><td>committer</td><td>[% line.committer.name | html %]</td></tr>
- <tr><td>committered time</td><td>[% line.committed_time %]</td></tr>
+ <tr><td>committer</td><td class='author'>[% line.committer.name | html %]</td></tr>
+ <tr><td>committered time</td><td class='time'>[% line.committed_time %]</td></tr>
[% END %]
</table>
<span class="time-since">[% time_since(line.authored_time) %]</span>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="65"
+ height="23"
+ id="svg2404"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="logo.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/dbrook/dev/gitalist/root/logo.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs2406">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 11.502125 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="71.847527 : 11.502125 : 1"
+ inkscape:persp3d-origin="35.923763 : 7.6680832 : 1"
+ id="perspective2400" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.9195959"
+ inkscape:cx="35.923763"
+ inkscape:cy="1.045551"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="1280"
+ inkscape:window-height="950"
+ inkscape:window-x="0"
+ inkscape:window-y="25">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2449"
+ visible="true"
+ enabled="true" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata2409">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-20.793031,-18.938722)">
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="60.946594"
+ y="35.124443"
+ id="text2577"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan2579"
+ x="60.946594"
+ y="35.124443"
+ style="font-size:20px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Candara;-inkscape-font-specification:Candara Italic">git</tspan></text>
+ <path
+ style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3357"
+ d="M 2.9800098,4.6496528 C 3.2880818,4.6583433 3.5963683,4.6566553 3.9045415,4.6581792 C 4.2900822,4.6480495 4.6799534,4.6882469 5.0628669,4.6352919 C 5.3415627,4.5839381 5.6225883,4.5523136 5.9053688,4.5367547 C 6.1586148,4.525911 6.4121605,4.5264303 6.6655841,4.5263393 C 6.9517438,4.5294138 7.2379286,4.5284888 7.5240995,4.5281299 C 7.7848081,4.527744 8.0455169,4.5275665 8.3062258,4.5274685 C 8.558755,4.527395 8.8112843,4.5273988 9.0638136,4.5273983 C 9.3162235,4.5274 9.5686335,4.5274028 9.8210434,4.5274043 C 10.073574,4.5274055 10.326104,4.5274056 10.578634,4.5274057 C 10.785275,4.5093013 11.024398,4.4841054 11.21515,4.3956888 C 11.416398,4.3090351 11.636109,4.2943885 11.852029,4.2819999 C 11.974627,4.276229 12.097361,4.2751928 12.220063,4.2738955 L 10.717011,5.3706722 C 10.596134,5.3743956 10.475147,5.3777149 10.354734,5.3898714 C 10.143057,5.4148447 9.938646,5.4621628 9.739379,5.5391785 C 9.519194,5.5818357 9.300299,5.6371449 9.0738739,5.6206779 C 8.8213422,5.620678 8.5688106,5.6206781 8.3162789,5.6206801 C 8.0638608,5.6206826 7.8114426,5.6206872 7.5590244,5.6206935 C 7.3065562,5.6206971 7.054088,5.6207114 6.8016198,5.6206066 C 6.5416878,5.6204588 6.2817558,5.6202017 6.0218249,5.6194038 C 5.7348811,5.6185593 5.4479171,5.6167199 5.1609836,5.6200676 C 4.9100951,5.6212274 4.6589774,5.6224823 4.4085648,5.6397412 C 4.1302379,5.6620999 3.8546293,5.7044164 3.5772175,5.7351221 C 3.1892034,5.7518431 2.8004601,5.7331854 2.412181,5.7424426 C 2.0961821,5.7439843 1.7800839,5.7424472 1.464178,5.7509691 L 2.9800098,4.6496528 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3359"
+ d="M 15.250399,4.5523455 C 15.590061,4.6402633 15.939932,4.6849319 16.280783,4.7668885 C 16.564174,4.8441138 16.854443,4.8817339 17.146909,4.8990287 C 17.399102,4.9098761 17.651613,4.9082786 17.903977,4.9078487 C 18.196362,4.8994477 18.48183,4.9060295 18.769953,4.954769 C 19.026435,5.0019753 19.286577,5.0188065 19.546736,5.0279525 C 19.798361,5.0344119 20.050099,5.0335836 20.301785,5.033395 C 20.554174,5.0330364 20.806562,5.0327599 21.058951,5.0326104 C 21.363806,5.0344648 21.668672,5.0355902 21.973534,5.0351006 C 22.256547,5.0342111 22.53956,5.0333216 22.822574,5.0328558 C 23.076911,5.0325027 23.331247,5.0324842 23.585583,5.0324647 C 23.837759,5.0324579 24.089935,5.0324695 24.34211,5.0324751 C 24.556292,5.0323195 24.775741,4.98369 24.945116,4.8497032 C 22.230527,6.5415415 23.325761,5.7734246 23.936091,5.386159 C 25.664647,4.3818697 25.018714,4.6323031 25.743129,4.3594463 L 24.285165,5.5176185 C 23.679415,5.8500541 24.148817,5.5935527 25.670884,4.7083218 C 24.971451,5.1881669 24.19828,5.5365941 23.494352,6.0234103 C 23.285581,6.1061415 23.061433,6.1343034 22.837331,6.1257613 C 22.585146,6.1257668 22.332961,6.1257785 22.080776,6.1257712 C 21.8268,6.1257511 21.572824,6.1257319 21.318849,6.1253744 C 21.037899,6.1249056 20.75695,6.1240082 20.476001,6.1231311 C 20.168754,6.1226612 19.861503,6.1238295 19.554265,6.1259938 C 19.301825,6.1262062 19.049385,6.1266353 18.796945,6.1266198 C 18.543601,6.1261977 18.290119,6.1261239 18.037005,6.1139367 C 17.773731,6.0982577 17.511863,6.0695772 17.252032,6.0234681 C 16.968885,5.9867088 16.684036,5.9998178 16.399079,6.0011342 C 16.144185,6.0005097 15.888907,6.0003272 15.634679,5.9794826 C 15.340021,5.9501258 15.050044,5.8949689 14.763813,5.8185376 C 14.417768,5.7462516 14.070072,5.6758601 13.720196,5.6259461 L 15.250399,4.5523455 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3361"
+ d="M 29.263724,4.7095281 C 29.543559,4.8008603 29.827126,4.8860904 30.113393,4.9564493 C 30.34092,5.0605715 30.57723,5.1193953 30.825121,5.1432959 C 31.137783,5.1697008 31.451743,5.1480706 31.763125,5.1862517 C 32.097281,5.2339857 32.433502,5.2624205 32.770587,5.2773118 C 33.034287,5.2866749 33.298197,5.2861541 33.562022,5.2860801 C 33.813967,5.2857484 34.065913,5.2853866 34.317858,5.2851965 C 34.570186,5.2850362 34.822513,5.2850255 35.074841,5.2850147 C 35.352046,5.2851166 35.629234,5.2868659 35.906443,5.2865131 C 36.180245,5.2863591 36.454048,5.2843413 36.727845,5.2864149 C 37.04472,5.2979745 37.355267,5.2922269 37.667843,5.2407986 C 37.96856,5.1837264 38.279499,5.2040028 38.578247,5.1418173 C 38.839416,5.0907446 39.101827,5.0275269 39.35035,4.9310873 C 39.194946,4.9727956 39.826949,4.660365 39.66612,4.7539434 C 36.910653,6.3572034 37.855073,5.8664227 38.350928,5.4796749 L 40.075242,4.7799543 C 39.460002,5.369098 38.652116,5.7191844 37.883509,6.0714455 C 37.623385,6.1466605 37.363086,6.2223438 37.093333,6.255085 C 36.789944,6.2847538 36.484875,6.2995069 36.18379,6.3506077 C 35.865823,6.3867145 35.546458,6.3736197 35.226924,6.376897 C 34.95322,6.3789267 34.67951,6.3769901 34.405801,6.3767916 C 34.127221,6.3764318 33.848662,6.3781783 33.570085,6.3783053 C 33.317768,6.3783415 33.06545,6.3783969 32.813134,6.3786503 C 32.561135,6.3789145 32.309135,6.3794844 32.057136,6.3789155 C 31.792731,6.3776272 31.528163,6.3754747 31.264194,6.358621 C 30.928192,6.3348706 30.59417,6.2935806 30.259243,6.2585132 C 29.9424,6.2411928 29.623899,6.2556697 29.308234,6.216721 C 29.057606,6.1786221 28.823039,6.0968746 28.586692,6.0067869 C 28.293107,5.9246568 27.998707,5.8444301 27.708397,5.7515096 L 29.263724,4.7095281 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#00ff00;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3363"
+ d="M 3.1168348,13.771312 C 3.4871277,13.830242 3.8517342,13.918437 4.2191663,13.993351 C 4.8365888,14.10372 5.4653965,14.120181 6.0908892,14.134004 C 6.6183258,14.131945 7.1429297,14.196644 7.6688677,14.229611 C 8.0515007,14.250739 8.4347714,14.254448 8.8178923,14.254653 C 9.1096113,14.253798 9.4013255,14.251899 9.6930442,14.250937 C 9.9740054,14.249674 10.254968,14.250305 10.535904,14.254183 C 10.982187,14.259328 11.428493,14.259977 11.87479,14.257146 C 12.207864,14.240609 12.545321,14.278998 12.875726,14.230274 C 13.068494,14.196492 13.262384,14.171244 13.457002,14.151266 L 11.967231,15.259246 C 11.774069,15.282733 11.58171,15.312125 11.388239,15.333036 C 11.055505,15.349359 10.72238,15.336526 10.389376,15.336362 C 9.9403422,15.333461 9.4913003,15.334285 9.0422815,15.339402 C 8.7580303,15.343276 8.4737547,15.344192 8.189477,15.343616 C 7.9007121,15.343348 7.611941,15.342724 7.3231966,15.33893 C 6.9406694,15.333468 6.5578076,15.328364 6.1762486,15.298076 C 5.6614564,15.257676 5.1481752,15.190115 4.6309779,15.18897 C 3.9920801,15.170244 3.3496573,15.15468 2.7193715,15.038168 C 2.3411972,14.963105 1.9625517,14.890673 1.5798912,14.842263 L 3.1168348,13.771312 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#00ff00;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3365"
+ d="M 8.6634088,9.7750099 C 8.6458015,10.16178 8.6464925,10.549292 8.6442839,10.93642 C 8.6582983,11.440766 8.6301257,11.942307 8.5881454,12.44451 C 8.5337827,12.858986 8.4688526,13.271539 8.4289363,13.687806 C 8.4021237,14.020874 8.401948,14.355087 8.3983622,14.68895 C 8.3981656,15.018792 8.3983046,15.348617 8.4006285,15.678453 C 8.4028493,15.95185 8.4038991,16.225253 8.4044537,16.498657 C 8.4048478,16.751439 8.40482,17.004221 8.4048186,17.257003 C 8.4298921,17.507752 8.4784656,17.755037 8.5041009,18.005961 C 8.5434103,18.243846 8.5067663,18.474507 8.4645558,18.708057 C 8.4302073,18.897923 8.4195037,19.090656 8.4113731,19.283059 L 6.7503165,20.12233 C 6.7554353,19.923404 6.76162,19.724053 6.7892032,19.526699 C 6.8239609,19.305546 6.8946704,19.092062 6.8549589,18.865832 C 6.8329143,18.608918 6.7901946,18.355593 6.747484,18.101454 C 6.7474896,17.848568 6.7474797,17.595682 6.7478122,17.342797 C 6.7482679,17.068341 6.7491362,16.793887 6.7506446,16.519436 C 6.7520929,16.188741 6.7505754,15.858071 6.7512435,15.527378 C 6.7502863,15.188506 6.7528272,14.849176 6.7774631,14.511059 C 6.8113889,14.090591 6.8881912,13.675821 6.9548568,13.259611 C 6.9964813,12.762612 7.0358084,12.266987 7.0130806,11.767559 C 7.0108963,11.386934 7.0118141,11.005886 6.9939556,10.625639 L 8.6634088,9.7750099 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#00ff00;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3385"
+ d="M 16.418357,13.872083 C 17.620556,13.906529 18.81114,14.095792 20.007704,14.208839 C 21.525842,14.340227 23.049286,14.380783 24.572309,14.397281 L 23.184327,15.399419 C 21.680967,15.324869 20.177069,15.257697 18.675006,15.160028 C 17.424243,15.066311 16.171754,14.895255 14.915705,14.963823 L 16.418357,13.872083 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#00ff00;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3389"
+ d="M 20.665339,9.7587118 C 20.722349,10.222553 20.732976,10.690339 20.742278,11.157055 C 20.752317,11.867666 20.748409,12.578364 20.751788,13.289015 C 20.710129,14.254618 20.729215,15.221865 20.751486,16.187776 C 20.770064,16.589489 20.837044,16.986383 20.87711,17.386039 C 20.897733,17.623421 20.899385,17.86205 20.90283,18.100172 L 19.250272,18.944315 C 19.248893,18.710214 19.246043,18.476078 19.230695,18.242386 C 19.202752,17.829538 19.153408,17.417928 19.150089,17.003664 C 19.172458,16.037771 19.193452,15.070443 19.150914,14.104876 C 19.15304,13.397944 19.150029,12.690864 19.130336,11.984165 C 19.11369,11.535866 19.104462,11.082675 19.013357,10.641937 L 20.665339,9.7587118 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#00ff00;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3395"
+ d="M 27.748495,13.422094 C 28.386624,13.611665 29.070496,13.603923 29.730064,13.632045 C 30.989831,13.655712 32.249313,13.668109 33.508743,13.707449 C 33.974488,13.69315 34.430129,13.792746 34.889985,13.844471 C 35.200366,13.870981 35.509644,13.791535 35.813309,13.73547 C 36.045716,13.691233 36.280557,13.66388 36.515949,13.64216 L 35.029661,14.744938 C 34.799369,14.770068 34.569725,14.800725 34.342514,14.846717 C 34.024589,14.908428 33.699995,14.967203 33.376203,14.914662 C 32.942158,14.850743 32.513228,14.745497 32.071717,14.741097 C 30.826118,14.660344 29.579915,14.646151 28.331923,14.64196 C 27.620099,14.632436 26.882897,14.670449 26.193168,14.464075 L 27.748495,13.422094 z"
+ transform="translate(20.793031,18.938722)" />
+ <path
+ style="fill:#00ff00;fill-opacity:1;stroke:none;stroke-opacity:1"
+ id="path3397"
+ d="M 32.526448,9.4122312 C 32.500107,9.9556963 32.498962,10.500074 32.495247,11.044059 C 32.492249,11.791325 32.489686,12.538611 32.493317,13.285877 C 32.491367,13.826812 32.50501,14.367614 32.514782,14.908416 C 32.513335,15.237763 32.576715,15.561888 32.603737,15.889377 C 32.627479,16.294591 32.622776,16.699633 32.671404,17.102956 C 32.697134,17.385271 32.74629,17.660115 32.815308,17.934389 C 32.864178,18.127769 32.880543,18.326507 32.892246,18.524917 L 31.23792,19.37883 C 31.229282,19.19133 31.217981,19.003211 31.175925,18.819622 C 31.108969,18.53489 31.057669,18.25152 31.039661,17.958523 C 30.993406,17.553538 30.991036,17.14824 30.966344,16.741621 C 30.935983,16.409373 30.868687,16.079151 30.872291,15.745307 C 30.882015,15.197212 30.895594,14.649118 30.893755,14.100895 C 30.897365,13.354284 30.894848,12.607653 30.891825,11.861043 C 30.888157,11.327662 30.887401,10.793844 30.860624,10.261011 L 32.526448,9.4122312 z"
+ transform="translate(20.793031,18.938722)" />
+ </g>
+</svg>
<a href="[% c.uri_for('shortlog', {h=object.sha1}) %]">shortlog</a> •
<a href="[% c.uri_for('log', {h=object.sha1}) %]">log</a> •
<a href="[% c.uri_for('commit', {h=object.sha1}) %]">commit</a> •
- <a href="[% c.uri_for('commitdiff', {h=object.sha1}) %]">commitdiff</a> •
- [% IF object.type == 'commit' %]
+ <a href="[% c.uri_for('commitdiff', {h=object.sha1}) %]">commitdiff</a>
+ [% IF object.type == 'commit' %] •
<a href="[% c.uri_for('tree', {h=object.tree_sha1, hb=object.sha1}) %]">tree</a>
[% END %]
+ [% IF filename %]
+ §
+ <a href="[% c.uri_for('blob', {h=object.sha1,f=filename}) %]">blob</a> •
+ <a href="[% c.uri_for('blame', {h=object.sha1,f=filename}) %]">blame</a> •
+ <a href="[% c.uri_for('shortlog', {h=object.sha1,f=filename}) %]">history</a> •
+ <a href="[% c.uri_for(action, {f=filename}) %]">HEAD</a>
+ [% END %]
<div class='chroma-hash'>[% INCLUDE '_chroma_hash.tt2' sha1 = object.sha1 %]</div>
</div>
<div id="page-search">
<form method="get" action="[% c.uri_for('search') %]" enctype="application/x-www-form-urlencoded">
- <input name="p" type="hidden" value="[% project %]" />
+ <input name="p" type="hidden" value="[% Project.name %]" />
<input name="a" type="hidden" value="search" />
<input name="h" type="hidden" value="[% commit.sha1 %]" />
<input name="f" type="hidden" value="[% c.req.param('f') %]" />
<option value="grep">grep</option>
<option value="pickaxe">pickaxe</option>
-->
- </select><sup><a href="/search_help?p=[% project %]">?</a></sup> search:
- <input type="text" name="text" value="[% search_text %]"/>
+ </select><sup><a href="[% c.uri_for('search_help') %]">?</a></sup> search:
+ <input type="text" name="text" value="[% c.req.param('s') %]"/>
<span title="Extended regular expression"><label><input type="checkbox" name="regexp" value="1" />re</label></span>
</form>
</div>
address {margin:0 0 1.5em;font-style:italic;}
del {color:#666;}
pre {margin:1.5em 0;white-space:pre;}
-pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
+pre, code, tt {font:1.1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
li ul, li ol {margin:0;}
ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;}
ul {list-style-type:disc;}
border-top: solid 1px #777;
}
+.listing tbody tr:nth-child(even) {
+ background-color: #f7f7f7;
+}
+.listing tbody tr:hover {
+ background-color: #fefeaa;
+}
+
span.chroma-hash {
font-family: monospace;
font-size: 1em;
font-family: "Trebuchet MS", "Lucida Grande", serif;
}
+.file-name, .file-mode {
+ font-family: monospace;
+}
+.action-list {
+ font-size: smaller;
+}
+
+.path {
+ border-bottom: solid 1px #ddd;
+ padding: 3px 0;
+ font-weight: bold;
+}
+
+
/* header */
#page-header {
height: 25px;
img.logo {
float: right;
border-width: 0px;
+ margin-top: 4px;
}
/* footer */
/* /commit page */
.commit-message {
font-family: monospace;
+ font-size: 1.2em;
}
div.commit-message {
margin-bottom: 10px;
font-family: monospace;
}
-.filename {
- font-family: monospace;
-}
-.action-list {
- font-size: smaller;
-}
-
-.path {
- border-bottom: solid 1px #ddd;
- padding: 3px 0;
- font-weight: bold;
-}
-
/* /heads */
.heads .head {
font-weight: bold;
width: 75%;
}
+/* /blame */
+#blame pre, #blame tt {
+ margin: 0;
+ font-size: 0.9em;
+}
+#blame .commit-info {
+}
+#blame .lineno {
+ text-align: right;
+ padding: 0 8px;
+}
+#blame a {
+ text-decoration: none;
+}
+#blame tr.alt {
+ background-color: #f7f7f7;
+}
+#blame tbody tr:hover {
+ background-color: #fefeaa;
+}
+
/* /blob */
pre.blob {
background-color: #333;
border-bottom: solid 1px green;
}
+/* /commitdiff */
+.diff-patch {
+ font-size: 0.8em;
+}
+
/* /log */
#log .entry {
border: solid 1px grey;
}
#log .meta {
border-top: dotted 1px #ddd;
- color: #755;
+ color: #311;
}
#log table.summary {
width: 33%;
#log .message {
font-family: monospace;
font-size: 1.15em;
+ /* XXX Need to enforce find the CSS switch to force the chroma-hash below the message box */
}
#log .age {
float: right;
font-style: italic;
}
-/**
- * from gitweb.css
- * XXX These can be rejigged once gitweb.css has gone away.
- */
+/* /summary */
+#stats {
+ float: right;
+}
+
+/* /tree */
+table.tree {
+ width: 65%;
+}
+
+/* Formerly of gitweb.css */
span.refs span {
padding: 0px 4px;
span.refs a {
text-decoration: none;
}
+
+a.rss_logo {
+ float: right;
+ padding: 3px 0px;
+ width: 35px;
+ line-height: 10px;
+ border: 1px solid;
+ border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
+ color: #ffffff;
+ background-color: #ff6600;
+ font-weight: bold;
+ font-family: sans-serif;
+ font-size: 70%;
+ font-style: normal;
+ text-align: center;
+ text-decoration: none;
+}
+
+a.rss_logo:hover {
+ background-color: #ee5500;
+}
[% PROCESS 'nav/actions.tt2' object = head %]
<div class='summary'>
-<dl>
-<dt>description</dt><dd>[% Project.description %]</dd>
-<dt>owner</dt><dd>[% Project.owner %]</dd>
-<dt>last change</dt><dd>[% Project.last_change %]</dd>
-</dl>
+<!-- <div id='stats'>
+ <dt>Number of commits in the last day</dt><dd>N</dd>
+ <dt>Most frequent commiter in the last week</dt><dd>Foo</dd>
+ <dt>Hottest file in the repo</dt><dd>Bar.baz</dd>
+ <dt>Current hue</dt><dd>either HEAD or some arbitrary munging</dd>
+ </div> -->
+
+ <dl>
+ <dt>description</dt><dd>[% Project.description %]</dd>
+ <dt>owner</dt><dd>[% Project.owner %]</dd>
+ <dt>last change</dt><dd>[% Project.last_change %]</dd>
+ </dl>
+
</div>
<h2><a href='[% c.uri_for("shortlog") %]'>shortlog</a></h2>
--- /dev/null
+[% INCLUDE 'nav/actions.tt2' object = commit %]
+
+<div>
+[% Project.name %]
+</div>
+
+[% INCLUDE '_heads.tt2' heads = tags %]
[% IF path -%]
<div>
- <a href='[% c.uri_for("tree", {hb=commit.sha1}) %]'>[% project %]</a>
+ <a href='[% c.uri_for("tree", {hb=commit.sha1}) %]'>[% Project.name %]</a>
[% fullpath = ''-%]
[% FOREACH part IN path.split('/') -%]
/ <a href='[% c.uri_for("tree", {h=tree.sha1, hb=commit.sha1, f=fullpath _ part}) %]'>[% part %]</a>
test('/search', 'h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818&f=&type=commit&text=added');
test('/blobdiff', 'f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=refs/heads/master;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
test('/blob', 'f=dir1/file2;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+ test('/patch');
+ test('/patch', 'h=3f7567c7bdf7e7ebf410926493b92d398333116e');
+ test('/patch', 'h=3f7567c7bdf7e7ebf410926493b92d398333116e;hp=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+ test('/patches');
+ test('/patches', 'h=3f7567c7bdf7e7ebf410926493b92d398333116e');
+ test('/patches', 'h=3f7567c7bdf7e7ebf410926493b92d398333116e;hp=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
}
done_testing;
+bar
', 'patch->{diff} is correct');
is($patch->{dst}, '5716ca5987cbf97d6bb54920bea6adde242d87e6', 'patch->{dst} is correct');
+
+ok(index($commit_obj->get_patch, 'From 3f7567c7bdf7e7ebf410926493b92d398333116e Mon Sep 17 00:00:00 2001
+From: Florian Ragwitz <rafl@debian.org>
+Date: Tue, 6 Mar 2007 20:39:45 +0100
+Subject: [PATCH] bar
+
+---
+ file1 | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/file1 b/file1
+index 257cc56..5716ca5 100644
+--- a/file1
++++ b/file1
+@@ -1 +1 @@
+-foo
++bar
+--') == 0, 'commit_obj->get_patch can return a patch');
+
+like($commit_obj->get_patch(undef, 3), qr!PATCH 2/2!, 'commit_obj->get_patch can return a patchset');
{
my @tree = $proj->list_tree('3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
is(scalar @tree, 1, "tree array contains one entry.");
- isa_ok(@tree[0], 'Gitalist::Git::Object', 'tree element 0');
+ isa_ok($tree[0], 'Gitalist::Git::Object', 'tree element 0');
}
test('/', 'a=blob;f=file1;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
test('/', 'a=blob;f=file1;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
-TODO: {
- local $TODO = "Action: blob_plain is not yet implemented.";
- test('/', 'a=blob_plain;f=dir1/file2;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=blob_plain;f=dir1/file2;hb=HEAD');
- test('/', 'a=blob_plain;f=dir1/file2;hb=master');
- test('/', 'a=blob_plain;f=dir1/file2;hb=refs/heads/master');
- test('/', 'a=blob_plain;f=file1;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=blob_plain;f=file1;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=blob_plain;f=file1;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=blob_plain;f=file1;hb=HEAD');
- test('/', 'a=blob_plain;f=file1;hb=master');
- test('/', 'a=blob_plain;f=file1;hb=refs/heads/master');
-}
+
+test('/', 'a=blob_plain;f=dir1/file2;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=blob_plain;f=dir1/file2;hb=HEAD');
+test('/', 'a=blob_plain;f=dir1/file2;hb=master');
+test('/', 'a=blob_plain;f=dir1/file2;hb=refs/heads/master');
+test('/', 'a=blob_plain;f=file1;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=blob_plain;f=file1;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=blob_plain;f=file1;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=blob_plain;f=file1;hb=HEAD');
+test('/', 'a=blob_plain;f=file1;hb=master');
+test('/', 'a=blob_plain;f=file1;hb=refs/heads/master');
test('/', 'a=blobdiff;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
test('/', 'a=blobdiff;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=3f7567c7bdf7e7ebf410926493b92d398333116e;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
test('/', 'a=blobdiff;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=master;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
test('/', 'a=blobdiff;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=refs/heads/master;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
-TODO: {
- local $TODO = "Action: blobdiff_plain is not yet implemented.";
- test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=3f7567c7bdf7e7ebf410926493b92d398333116e;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=HEAD;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=master;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
-}
+test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=3f7567c7bdf7e7ebf410926493b92d398333116e;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=HEAD;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=blobdiff_plain;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hp=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=master;hpb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
test('/', 'a=commit');
test('/', 'a=commit;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
test('/', 'a=commitdiff;h=refs/heads/master');
test('/', 'a=commitdiff;h=refs/heads/master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
-TODO: {
- local $TODO = "Action: commitdiff_plain is not yet implemented.";
- test('/', 'a=commitdiff_plain');
- test('/', 'a=commitdiff_plain;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=commitdiff_plain;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=commitdiff_plain;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=commitdiff_plain;h=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=commitdiff_plain;h=3f7567c7bdf7e7ebf410926493b92d398333116e;hp=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=commitdiff_plain;h=HEAD');
- test('/', 'a=commitdiff_plain;h=HEAD;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=commitdiff_plain;h=master');
- test('/', 'a=commitdiff_plain;h=master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=commitdiff_plain;h=refs/heads/master');
- test('/', 'a=commitdiff_plain;h=refs/heads/master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
-}
+test('/', 'a=commitdiff_plain');
+test('/', 'a=commitdiff_plain;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=commitdiff_plain;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=commitdiff_plain;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=commitdiff_plain;h=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=commitdiff_plain;h=3f7567c7bdf7e7ebf410926493b92d398333116e;hp=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=commitdiff_plain;h=HEAD');
+test('/', 'a=commitdiff_plain;h=HEAD;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=commitdiff_plain;h=master');
+test('/', 'a=commitdiff_plain;h=master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=commitdiff_plain;h=refs/heads/master');
+test('/', 'a=commitdiff_plain;h=refs/heads/master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
-TODO: {
- local $TODO = "Action: history is not yet implemented.";
- test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=HEAD');
- test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=master');
- test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=refs/heads/master');
- test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=HEAD');
- test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=master');
- test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=refs/heads/master');
- test('/', 'a=history;f=dir1;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=history;f=dir1;hb=HEAD');
- test('/', 'a=history;f=dir1;hb=master');
- test('/', 'a=history;f=dir1;hb=refs/heads/master');
- test('/', 'a=history;f=file1;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=HEAD');
- test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=master');
- test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=refs/heads/master');
- test('/', 'a=history;f=file1;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=history;h=refs/heads/master');
-}
+
+test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=HEAD');
+test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=master');
+test('/', 'a=history;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=refs/heads/master');
+test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=HEAD');
+test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=master');
+test('/', 'a=history;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=refs/heads/master');
+test('/', 'a=history;f=dir1;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=history;f=dir1;hb=HEAD');
+test('/', 'a=history;f=dir1;hb=master');
+test('/', 'a=history;f=dir1;hb=refs/heads/master');
+test('/', 'a=history;f=file1;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=HEAD');
+test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=master');
+test('/', 'a=history;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=refs/heads/master');
+test('/', 'a=history;f=file1;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=history;h=refs/heads/master');
test('/', 'a=log');
test('/', 'a=log;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
test('/', 'a=log;h=master');
test('/', 'a=log;h=refs/heads/master');
-TODO: {
- local $TODO = "Action: patch is not yet implemented.";
- test('/', 'a=patch');
- test('/', 'a=patch;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=patch;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=patch;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=patch;h=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=patch;h=3f7567c7bdf7e7ebf410926493b92d398333116e;hp=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=patch;h=HEAD');
- test('/', 'a=patch;h=HEAD;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=patch;h=master');
- test('/', 'a=patch;h=master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=patch;h=refs/heads/master');
- test('/', 'a=patch;h=refs/heads/master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=patch;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=patch;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=patch;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
-}
+test('/', 'a=patch');
+test('/', 'a=patch;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=patch;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=patch;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=patch;h=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=patch;h=3f7567c7bdf7e7ebf410926493b92d398333116e;hp=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=patch;h=HEAD');
+test('/', 'a=patch;h=HEAD;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=patch;h=master');
+test('/', 'a=patch;h=master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=patch;h=refs/heads/master');
+test('/', 'a=patch;h=refs/heads/master;hp=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=patch;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=patch;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=patch;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
-TODO: {
- local $TODO = "Action: patches is not yet implemented.";
- test('/', 'a=patches');
- test('/', 'a=patches;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
- test('/', 'a=patches;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
- test('/', 'a=patches;h=3f7567c7bdf7e7ebf410926493b92d398333116e');
- test('/', 'a=patches;h=HEAD');
- test('/', 'a=patches;h=master');
- test('/', 'a=patches;h=refs/heads/master');
-}
+test('/', 'a=patches');
+test('/', 'a=patches;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+test('/', 'a=patches;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+test('/', 'a=patches;h=3f7567c7bdf7e7ebf410926493b92d398333116e');
+test('/', 'a=patches;h=HEAD');
+test('/', 'a=patches;h=master');
+test('/', 'a=patches;h=refs/heads/master');
test('/', 'a=search_help');
test('/', 'a=shortlog;h=master');
test('/', 'a=shortlog;h=refs/heads/master');
-TODO: {
- local $TODO = "Action: snapshot is not yet implemented.";
- test('/', 'a=snapshot;h=145dc3ef5d307be84cb9b325d70bd08aeed0eceb;sf=tgz');
- test('/', 'a=snapshot;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;sf=tgz');
- test('/', 'a=snapshot;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac;sf=tgz');
- test('/', 'a=snapshot;h=3f7567c7bdf7e7ebf410926493b92d398333116e;sf=tgz');
- test('/', 'a=snapshot;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;sf=tgz');
- test('/', 'a=snapshot;h=82b5fee28277349b6d46beff5fdf6a7152347ba0;sf=tgz');
- test('/', 'a=snapshot;h=9062594aebb5df0de7fb92413f17a9eced196c22;sf=tgz');
- test('/', 'a=snapshot;h=HEAD;sf=tgz');
- test('/', 'a=snapshot;h=master;sf=tgz');
- test('/', 'a=snapshot;h=refs/heads/master;sf=tgz');
-}
+test('/', 'a=snapshot;h=145dc3ef5d307be84cb9b325d70bd08aeed0eceb;sf=tgz');
+test('/', 'a=snapshot;h=36c6c6708b8360d7023e8a1649c45bcf9b3bd818;sf=tgz');
+test('/', 'a=snapshot;h=3bc0634310b9c62222bb0e724c11ffdfb297b4ac;sf=tgz');
+test('/', 'a=snapshot;h=3f7567c7bdf7e7ebf410926493b92d398333116e;sf=tgz');
+test('/', 'a=snapshot;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;sf=tgz');
+test('/', 'a=snapshot;h=82b5fee28277349b6d46beff5fdf6a7152347ba0;sf=tgz');
+test('/', 'a=snapshot;h=9062594aebb5df0de7fb92413f17a9eced196c22;sf=tgz');
+test('/', 'a=snapshot;h=HEAD;sf=tgz');
+test('/', 'a=snapshot;h=master;sf=tgz');
+test('/', 'a=snapshot;h=refs/heads/master;sf=tgz');
test('/', 'a=tree');
test('/', 'a=tree;f=dir1;h=729a7c3f6ba5453b42d16a43692205f67fb23bc1;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
test('/', 'a=tree;hb=master');
test('/', 'a=tree;hb=refs/heads/master');
+
+test('/', 'a=atom');
+test('/', 'a=atom;f=dir1');
+test('/', 'a=atom;f=dir1/file2');
+test('/', 'a=atom;f=dir1/file2;opt=--no-merges');
+test('/', 'a=atom;f=dir1;h=refs/heads/master');
+test('/', 'a=atom;f=dir1;h=refs/heads/master;opt=--no-merges');
+test('/', 'a=atom;f=dir1;opt=--no-merges');
+test('/', 'a=atom;f=file1');
+test('/', 'a=atom;f=file1;h=refs/heads/master');
+test('/', 'a=atom;f=file1;h=refs/heads/master;opt=--no-merges');
+test('/', 'a=atom;f=file1;opt=--no-merges');
+test('/', 'a=atom;h=refs/heads/master');
+test('/', 'a=atom;h=refs/heads/master;opt=--no-merges');
+test('/', 'a=atom;opt=--no-merges');
+
+test('/', 'a=rss');
+test('/', 'a=rss;f=dir1');
+test('/', 'a=rss;f=dir1/file2');
+test('/', 'a=rss;f=dir1/file2;opt=--no-merges');
+test('/', 'a=rss;f=dir1;h=refs/heads/master');
+test('/', 'a=rss;f=dir1;h=refs/heads/master;opt=--no-merges');
+test('/', 'a=rss;f=dir1;opt=--no-merges');
+test('/', 'a=rss;f=file1');
+test('/', 'a=rss;f=file1;h=refs/heads/master');
+test('/', 'a=rss;f=file1;h=refs/heads/master;opt=--no-merges');
+test('/', 'a=rss;f=file1;opt=--no-merges');
+test('/', 'a=rss;h=refs/heads/master');
+test('/', 'a=rss;h=refs/heads/master;opt=--no-merges');
+test('/', 'a=rss;opt=--no-merges');
+
TODO: {
- local $TODO = "Action: atom is not yet implemented.";
- test('/', 'a=atom');
- test('/', 'a=atom;f=dir1');
- test('/', 'a=atom;f=dir1/file2');
- test('/', 'a=atom;f=dir1/file2;opt=--no-merges');
- test('/', 'a=atom;f=dir1;h=refs/heads/master');
- test('/', 'a=atom;f=dir1;h=refs/heads/master;opt=--no-merges');
- test('/', 'a=atom;f=dir1;opt=--no-merges');
- test('/', 'a=atom;f=file1');
- test('/', 'a=atom;f=file1;h=refs/heads/master');
- test('/', 'a=atom;f=file1;h=refs/heads/master;opt=--no-merges');
- test('/', 'a=atom;f=file1;opt=--no-merges');
- test('/', 'a=atom;h=refs/heads/master');
- test('/', 'a=atom;h=refs/heads/master;opt=--no-merges');
- test('/', 'a=atom;opt=--no-merges');
+ local $TODO = 'The project_index action is yet to be implemented';
+ test('/', 'a=project_index');
+}
+TODO: {
+ local $TODO = 'The opml action is yet to be implemented';
+ test('/', 'a=opml');
}
-
TODO: {
- local $TODO = "Action: rss is not yet implemented.";
- test('/', 'a=rss');
- test('/', 'a=rss;f=dir1');
- test('/', 'a=rss;f=dir1/file2');
- test('/', 'a=rss;f=dir1/file2;opt=--no-merges');
- test('/', 'a=rss;f=dir1;h=refs/heads/master');
- test('/', 'a=rss;f=dir1;h=refs/heads/master;opt=--no-merges');
- test('/', 'a=rss;f=dir1;opt=--no-merges');
- test('/', 'a=rss;f=file1');
- test('/', 'a=rss;f=file1;h=refs/heads/master');
- test('/', 'a=rss;f=file1;h=refs/heads/master;opt=--no-merges');
- test('/', 'a=rss;f=file1;opt=--no-merges');
- test('/', 'a=rss;h=refs/heads/master');
- test('/', 'a=rss;h=refs/heads/master;opt=--no-merges');
- test('/', 'a=rss;opt=--no-merges');
+ local $TODO = 'The tags action is yet to be implemented';
+ test('/', 'a=tags');
+}
+TODO: {
+ local $TODO = 'The blame action is yet to be implemented';
+
+ test('/', 'a=blame;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+ test('/', 'a=blame;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=HEAD');
+ test('/', 'a=blame;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=master');
+ test('/', 'a=blame;f=dir1/file2;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=refs/heads/master');
+ test('/', 'a=blame;f=dir1/file2;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+ test('/', 'a=blame;f=file1;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99');
+ test('/', 'a=blame;f=file1;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=257cc5642cb1a054f08cc83f2d943e56fd3ebe99');
+ test('/', 'a=blame;f=file1;h=257cc5642cb1a054f08cc83f2d943e56fd3ebe99;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+ test('/', 'a=blame;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=36c6c6708b8360d7023e8a1649c45bcf9b3bd818');
+ test('/', 'a=blame;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
+ test('/', 'a=blame;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=5716ca5987cbf97d6bb54920bea6adde242d87e6');
+ test('/', 'a=blame;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=HEAD');
+ test('/', 'a=blame;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=master');
+ test('/', 'a=blame;f=file1;h=5716ca5987cbf97d6bb54920bea6adde242d87e6;hb=refs/heads/master');
+ test('/', 'a=blame;f=file1;hb=3bc0634310b9c62222bb0e724c11ffdfb297b4ac');
+ test('/', 'a=blame;f=file1;hb=3f7567c7bdf7e7ebf410926493b92d398333116e');
}
done_testing;
log = 50
summary = 16
</paging>
+
+<patches>
+ max = 16
+</patches>