Fleshed out reflog action.
broquaint [Fri, 18 Sep 2009 22:16:06 +0000 (23:16 +0100)]
* Also fixed and simplified blob action.
* Added reflog method to the model.
* Moved encode/escape stuff into templates.
* Normalized indenting in legacy header/footer functions.

lib/Gitalist/Controller/Root.pm
lib/Gitalist/Model/Git.pm
templates/blob.tt2
templates/reflog.tt2

index bbe4ceb..10b8cb3 100644 (file)
@@ -76,15 +76,15 @@ sub blob : Local {
 
   my $git      = $c->model('Git');
   my $req      = $c->req;
+  my $proj     = $req->param('p');
   my $filename = $req->param('f')  || $req->param('filename');
-  my $hash     = $req->param('hb') || $req->param('hashbase')
-              || $git->get_head_hash($req->param('p') || $req->param('project'));
-  my $filehash = $git->get_hash_by_path($hash, $filename, 'blob');
+  my $hash     = $req->param('hb') || $git->get_head_hash($proj);
+  my $filehash = $req->param('h')  || $git->get_hash_by_path($proj, $hash, $filename, 'blob');
   
   my $blob = $git->run_cmd('cat-file' => blob => $filehash);
 
   $c->stash(
-      blob   => encode_entities($blob),
+      blob   => $blob,
       action => 'blob',
   );
 }
@@ -92,11 +92,14 @@ sub blob : Local {
 sub reflog : Local {
   my ( $self, $c ) = @_;
 
-  my $log = $c->model('Git')->run_cmd_in($c->req->param('p'),
-      log => '--since=yesterday', '-g'
+  my @log = $c->model('Git')->reflog(
+      # XXX The project parameter should probably be passed into the Model.
+      $c->req->param('p'),
+      '--since=yesterday'
   );
+
   $c->stash(
-      log    => [map encode_entities($_), $log =~ /(^commit.*?^    \S.*?$)/msg],
+      log    => \@log,
       action => 'reflog',
   );
 }
@@ -109,116 +112,117 @@ sub auto : Private {
     $self->footer($c);
 }
 
+# XXX This could probably be dropped altogether.
 use Gitalist::Util qw(to_utf8);
-use HTML::Entities qw(encode_entities);
-use URI::Escape    qw(uri_escape);
 # Formally git_header_html
 sub header {
   my($self, $c) = @_;
 
-       my $title = $c->config->{sitename};
+  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 .= " - " . encode_entities($file_name);
-                               if ($action eq "tree" && $file_name !~ m|/$|) {
-                                       $title .= "/";
-                               }
-                       }
-               }
-       }
-
-       $c->stash->{version}     = $c->config->{version};
-       $c->stash->{git_version} = $c->model('Git')->run_cmd('--version');
-       $c->stash->{title}       = $title;
+  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}     = $c->config->{version};
+  $c->stash->{git_version} = $c->model('Git')->run_cmd('--version');
+  $c->stash->{title}       = $title;
 
   #$c->stash->{baseurl} = $ENV{PATH_INFO} && uri_escape($base_url);
-       $c->stash->{stylesheet} = $c->config->{stylesheet} || 'gitweb.css';
+  $c->stash->{stylesheet} = $c->config->{stylesheet} || 'gitweb.css';
 
-       $c->stash->{project} = $project;
+  $c->stash->{project} = $project;
   my @links;
-       if($project) {
-               my %href_params = $self->feed_info($c);
-               $href_params{'-title'} ||= 'log';
+  if($project) {
+    my %href_params = $self->feed_info($c);
+    $href_params{'-title'} ||= 'log';
 
-               foreach my $format qw(RSS Atom) {
-                       my $type = lc($format);
+    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',
+        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"
+        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 {
+    }
+  } 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"
-    };
-       }
+      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};
+  $c->stash->{favicon} = $c->config->{favicon};
 
-       # </head><body>
+  # </head><body>
 
-       $c->stash(
-    logo_url      => uri_escape($c->config->{logo_url}),
-         logo_label    => encode_entities($c->config->{logo_label}),
-         logo_img      => $c->config->{logo},
-         home_link     => uri_escape($c->config->{home_link}),
+  $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) {
+  if(defined $project) {
     $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' ),
-    );
-       }
+          || $c->req->param('h')  || $c->req->param('hash')
+          || 'HEAD' ),
+      );
+  }
 }
 
 # Formally git_footer_html
 sub footer {
   my($self, $c) = @_;
 
-       my $feed_class = 'rss_logo';
+  my $feed_class = 'rss_logo';
 
   my @feeds;
   my $project = $c->req->param('project')  || $c->req->param('p');
-       if(defined $project) {
+  if(defined $project) {
     (my $pstr = $project) =~ s[/?\.git$][];
-               my $descr = $c->model('Git')->project_info($project)->{description};
-               $c->stash->{project_description} = defined $descr
-                       ? encode_entities($descr)
-                       : '';
+    my $descr = $c->model('Git')->project_info($project)->{description};
+    $c->stash->{project_description} = defined $descr
+      ? $descr
+      : '';
 
-               my %href_params = $self->feed_info($c);
-               if (!%href_params) {
-                       $feed_class .= ' generic';
-               }
-               $href_params{'-title'} ||= 'log';
+    my %href_params = $self->feed_info($c);
+    if (!%href_params) {
+      $feed_class .= ' generic';
+    }
+    $href_params{'-title'} ||= 'log';
 
     @feeds = [
       map +{
@@ -226,18 +230,18 @@ sub footer {
         title => "$href_params{'-title'} $_ feed",
         href  => "/?p=$project;a=\L$_",
         name  => lc $_,
-      }, qw(RSS Atom)
-    ];
-       } else {
+        }, qw(RSS Atom)
+      ];
+  } else {
     @feeds = [
       map {
         class => $feed_class,
-        title => '',
-        href  => "/?a=$_->[0]",
-        name  => $_->[1],
-      }, [opml=>'OPML'],[project_index=>'TXT'],
-    ];
-       }
+          title => '',
+          href  => "/?a=$_->[0]",
+          name  => $_->[1],
+        }, [opml=>'OPML'],[project_index=>'TXT'],
+      ];
+  }
 }
 
 # XXX This feels wrong here, should probably be refactored.
@@ -246,40 +250,43 @@ sub footer {
 sub feed_info {
   my($self, $c) = @_;
 
-       my $format = shift || 'Atom';
-       my %res = (action => lc($format));
+  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;
+  # feed links are possible only for project views
+  return unless $c->req->param('project');
 
-       my $branch;
+  # 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';
+
+  # 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;
+  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;
 }
 =head2 end
 
index d5c3491..a4afd8e 100644 (file)
@@ -120,6 +120,8 @@ sub run_cmd {
         or die "failed to run git command";
     binmode $fh, ':encoding(UTF-8)';
 
+    print STDERR "RAN - git @_[1..$#_]\n"; 
+
     my $output = do { local $/ = undef; <$fh> };
     close $fh;
 
@@ -196,11 +198,11 @@ sub get_object_type {
 }
 
 sub get_hash_by_path {
-       my($self, $base, $path, $type) = @_;
+       my($self, $project, $base, $path, $type) = @_;
 
        $path =~ s{/+$}();
 
-       my $line = $self->run_cmd('ls-tree', $base, '--', $path)
+       my $line = $self->run_cmd_in($project, 'ls-tree', $base, '--', $path)
     or return;
 
        #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa  panic.c'
@@ -324,6 +326,50 @@ sub rev_info {
     return $self->list_revs($project, rev => $rev, count => 1);
 }
 
+sub reflog {
+    my ($self, $project, @logargs) = @_;
+
+    my @entries
+      =  $self->run_cmd_in($project, qw(log -g), @logargs)
+      =~ /(^commit.+?(?:(?=^commit)|(?=\z)))/msg;
+
+=begin
+
+  commit 02526fc15beddf2c64798a947fecdd8d11bf993d
+  Reflog: HEAD@{14} (The Git Server <git@git.dev.venda.com>)
+  Reflog message: push
+  Author: Iain Loasby <iloasby@rowlf.of-2.uk.venda.com>
+  Date:   Thu Sep 17 12:26:05 2009 +0100
+
+      Merge branch 'rt125181
+=cut
+    return map {
+      # XXX Stuff like this makes me want to switch to Git::PurePerl
+      my($sha1, $type, $author, $date)
+        = m{
+          ^ commit \s+ ([0-9a-f]+)$
+          .*?
+          Reflog[ ]message: \s+ (.+?)$ \s+
+          Author: \s+ ([^<]+) <.*?$ \s+
+          Date: \s+ (.+?)$
+        }xms;
+
+      pos($_) = index($_, $date) + length $date;
+      # Yeah, I just did that.
+
+      my($msg) = /\G\s+(\S.*)/sg;
+
+      {
+        hash    => $sha1,
+        type    => $type,
+        author  => $author,
+        # XXX Add DateTime goodness.
+        date    => $date,
+        message => $msg,
+      };
+    } @entries;
+}
+
 sub get_heads {
     my ($self, $project) = @_;
 
index a4ff6c0..6a85d6c 100644 (file)
@@ -1,5 +1,5 @@
 <div>
 <pre>
-[% blob %]
+[% blob | html %]
 </pre>
 </div>
index a8f4db8..4bfb7a3 100644 (file)
@@ -1,5 +1,12 @@
 <ul>
 [% FOR entry IN log %]
-  <li><pre>[% entry %]</pre></li>
+  <li><h3>[% entry.message | html %]</h3>
+    <dl>
+      <dt>Commit</dt>  <dd>[% entry.hash %]</dd>
+      <dt>Type</dt>    <dd>[% entry.type %]</dd>
+      <dt>Author</dt>  <dd>[% entry.author %]</dd>
+      <dt>Date</dt>    <dd>[% entry.date %]</dd>
+    </dl>
+  </li>
 [% END %]
 </ul>