Make the version number sane and clean up copyright/license statements everywhere
[catagits/Gitalist.git] / lib / Gitalist / Controller / Root.pm
index d295155..b6ae871 100644 (file)
@@ -4,17 +4,13 @@ use namespace::autoclean;
 
 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 IO::Capture::Stdout;
 use Sys::Hostname ();
 use XML::Atom::Feed;
 use XML::Atom::Entry;
 use XML::RSS;
+use XML::OPML::SimpleGen;
 
 =head1 NAME
 
@@ -28,40 +24,6 @@ Gitalist::Controller::Root - Root Controller for Gitalist
 
 =cut
 
-=head2 index
-
-=cut
-
-=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) = @_;
 
@@ -78,10 +40,10 @@ sub _get_object {
           # XXX This could definitely use more context.
           || Carp::croak("Couldn't find a hash for the commit object!");
 
-  my $commit = $m->get_object($hash)
-    or Carp::croak("Couldn't find a commit object for '$hash' in '$pd'!");
+  my $obj = $m->get_object($hash)
+    or Carp::croak("Couldn't find a object for '$hash' in '$pd'!");
 
-  return $commit;
+  return $obj;
 }
 
 =head2 index
@@ -115,6 +77,20 @@ sub index :Path :Args(0) {
   );
 }
 
+sub project_index : Local {
+  my ( $self, $c ) = @_;
+
+  my @list = @{ $c->model()->projects };
+  die 'No projects found in '. $c->model->repo_dir
+    unless @list;
+
+  $c->response->content_type('text/plain');
+  $c->response->body(
+    join "\n", map $_->name, @list
+  );
+  $c->response->status(200);
+}
+
 =head2 summary
 
 A summary of what's happening in the repo.
@@ -156,28 +132,76 @@ sub heads : Local {
   );
 }
 
-=head2 blob
+=head2 tags
 
-The blob action i.e the contents of a file.
+The current list of tags in the repo.
 
 =cut
 
-sub blob : Local {
+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(
-    blob     => $project->get_object($h)->content,
+    blame    => $project->get_object($hb)->blame($filename),
     head     => $project->get_object($hb),
     filename => $filename,
+  );
+  
+}
+
+sub _blob_objs {
+  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') || '';
+
+  my $blob = $project->get_object($h);
+  $blob = $project->get_object(
+    $project->hash_by_path($h || $hb, $filename)
+  ) if $blob->type ne 'blob';
+
+  return $blob, $project->get_object($hb), $filename;
+}
+
+=head2 blob
+
+The blob action i.e the contents of a file.
+
+=cut
+
+sub blob : Local {
+  my ( $self, $c ) = @_;
+
+  my($blob, $head, $filename) = $self->_blob_objs($c);
+  $c->stash(
+    blob     => $blob->content,
+    head     => $head,
+    filename => $filename,
     # XXX Hack hack hack, see View::SyntaxHighlight
     language => ($filename =~ /\.p[lm]$/ ? 'Perl' : ''),
     action   => 'blob',
@@ -187,15 +211,27 @@ sub blob : Local {
     unless $c->stash->{no_wrapper};
 }
 
+=head2 blob_plain
+
+The plain text version of blob, where file is rendered as is.
+
+=cut
+
 sub blob_plain : Local {
   my($self, $c) = @_;
 
-  $c->stash(no_wrapper => 1);
+  my($blob) = $self->_blob_objs($c);
   $c->response->content_type('text/plain; charset=utf-8');
-
-  $c->forward('blob');
+  $c->response->body($blob->content);
+  $c->response->status(200);
 }
 
+=head2 blobdiff_plain
+
+The plain text version of blobdiff.
+
+=cut
+
 sub blobdiff_plain : Local {
   my($self, $c) = @_;
 
@@ -203,7 +239,6 @@ sub blobdiff_plain : Local {
   $c->response->content_type('text/plain; charset=utf-8');
 
   $c->forward('blobdiff');
-
 }
 
 =head2 blobdiff
@@ -226,6 +261,7 @@ sub blobdiff : Local {
   $c->stash(
     commit    => $commit,
     diff      => $patch,
+    filename  => $filename,
     # XXX Hack hack hack, see View::SyntaxHighlight
     blobs     => [$patch->[0]->{diff}],
     language  => 'Diff',
@@ -299,12 +335,15 @@ Expose an abbreviated log of a given sha1.
 
 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, $c->req->param('hb'));
+  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;
@@ -315,8 +354,9 @@ sub shortlog : Local {
       commit    => $commit,
       log_lines => [$project->list_revs(%logargs)],
       refs      => $project->references,
-      action    => 'shortlog',
       page      => $page,
+      filename  => $filename,
+      action    => 'shortlog',
   );
 }
 
@@ -332,7 +372,7 @@ sub log : Local {
 
 # For legacy support.
 sub history : Local {
-  $_[0]->shortlog(@_[1 .. $#_]);
+  $_[1]->forward('shortlog');
 }
 
 =head2 tree
@@ -345,7 +385,11 @@ sub tree : Local {
   my ( $self, $c ) = @_;
   my $project = $c->stash->{Project};
   my $commit  = $self->_get_object($c, $c->req->param('hb'));
-  my $tree    = $self->_get_object($c, $c->req->param('h') || $commit->tree_sha1);
+  my $filename = $c->req->param('f') || '';
+  my $tree    = $filename
+    ? $project->get_object($project->hash_by_path($commit->sha1, $filename))
+    : $project->get_object($commit->tree_sha1)
+  ;
   $c->stash(
       commit    => $commit,
       tree      => $tree,
@@ -373,6 +417,12 @@ sub reflog : Local {
   );
 }
 
+=head2 search
+
+The action for the search form.
+
+=cut
+
 sub search : Local {
   my($self, $c) = @_;
   $c->stash(current_action => 'GitRepos');
@@ -398,11 +448,23 @@ sub search : Local {
   );
 }
 
+=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 {
   my($self, $c) = @_;
 
@@ -434,6 +496,12 @@ sub atom : Local {
   $c->response->status(200);
 }
 
+=head2 rss
+
+Provides an RSS feed for a given project.
+
+=cut
+
 sub rss : Local {
   my ($self, $c) = @_;
 
@@ -469,11 +537,46 @@ sub rss : Local {
   $c->response->status(200);
 }
 
+sub opml : Local {
+  my($self, $c) = @_;
+
+  my $opml = XML::OPML::SimpleGen->new();
+
+  $opml->head(title => lc(Sys::Hostname::hostname()) . ' - ' . Gitalist->config->{name});
+
+  my @list = @{ $c->model()->projects };
+  die 'No projects found in '. $c->model->repo_dir
+    unless @list;
+
+  for my $proj ( @list ) {
+    $opml->insert_outline(
+      text   => $proj->name. ' - '. $proj->description,
+      xmlUrl => $c->uri_for(rss => {p => $proj->name}),
+    );
+  }
+
+  $c->response->body($opml->as_string);
+  $c->response->content_type('application/rss');
+  $c->response->status(200);
+}
+
+=head2 patch
+
+A raw patch for a given commit.
+
+=cut
+
 sub patch : Local {
     my ($self, $c) = @_;
     $c->detach('patches', [1]);
 }
 
+=head2 patches
+
+The patcheset for a given commit ???
+
+=cut
+
 sub patches : Local {
     my ($self, $c, $count) = @_;
     $count ||= Gitalist->config->{patches}{max};
@@ -485,9 +588,25 @@ sub patches : Local {
     $c->response->status(200);
 }
 
+=head2 snapshot
+
+Provides a snapshot of a given commit.
+
+=cut
+
 sub snapshot : Local {
-    # FIXME - implement snapshot
-    Carp::croak "Not implemented.";
+    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
@@ -522,7 +641,7 @@ sub auto : Private {
     short_cmt => sub {
       my $cmt = shift;
       my($line) = split /\n/, $cmt;
-      $line =~ s/^(.{70,80}\b).*/$1 …/;
+      $line =~ s/^(.{70,80}\b).*/$1 \x{2026}/;
       return $line;
     },
     abridged_description => sub {
@@ -592,16 +711,17 @@ sub age_string {
   return $age_str;
 }
 
+__PACKAGE__->meta->make_immutable;
+
+__END__
+
 
-=head1 AUTHOR
+=head1 AUTHORS
 
-Dan Brook
+See L<Gitalist> for authors.
 
 =head1 LICENSE
 
-This library is free software. You can redistribute it and/or modify
-it under the same terms as Perl itself.
+See L<Gitalist> for the license.
 
 =cut
-
-__PACKAGE__->meta->make_immutable;