A rough cut of the /search action.
broquaint [Sun, 1 Nov 2009 20:42:00 +0000 (20:42 +0000)]
ISSUES
lib/Gitalist.pm
lib/Gitalist/Controller/Root.pm
lib/Gitalist/Model/Git.pm
templates/default.tt2
templates/nav/search.tt2 [new file with mode: 0644]
templates/page_nav.tt2 [deleted file]
templates/search.tt2 [new file with mode: 0644]

diff --git a/ISSUES b/ISSUES
index ee3bb08..64a0187 100644 (file)
--- a/ISSUES
+++ b/ISSUES
@@ -1 +1,2 @@
 * Sort out commitdiff so conflicted merges have an equivalent display to gitweb (d7f39bebabeb31ce9a7b4f1b6f3db9f391b78c3e as a reference)
+* Need to sanitise the input ...
index 5213ef7..9b48cb5 100644 (file)
@@ -11,8 +11,6 @@ use Catalyst qw/-Debug
                 Static::Simple
                 StackTrace/;
 
-use Class::C3::Adopt::NEXT -no_warn;
-
 our $VERSION = '0.01';
 
 # Bring in the libified gitweb.cgi.
@@ -26,17 +24,16 @@ __PACKAGE__->config(
 # Start the application
 __PACKAGE__->setup();
 
-sub uri_for {
-    my $p = ref $_[-1] eq 'HASH'
-          ? $_[-1]
-          : push(@_, {}) && $_[-1];
-    $p->{p} = $_[0]->model('Git')->project;
-
-    (my $uri = $_[0]->NEXT::uri_for(@_[1 .. $#_]))
-      # Ampersand! What is this, the 90s?
-      =~ s/&/;/g;
-    return $uri;
-}
+around uri_for => sub {
+  my ($orig, $c) = (shift, shift);
+  my $params = Catalyst::Utils::merge_hashes(
+    { p => $c->model('Git')->project },
+    ref($_[-1]) eq 'HASH' ? pop @_ : {}
+  );
+  (my $uri = $c->$orig(@_, $params))
+    =~ tr[&][;];
+  return $uri;
+};
 
 =head1 NAME
 
index da1a9cd..4405ba4 100644 (file)
@@ -328,7 +328,27 @@ sub reflog : Local {
 }
 
 sub search : Local {
-    Carp::croak "Not implemented.";
+  my($self, $c) = @_;
+
+  my $commit  = $self->_get_commit($c);
+  # Lifted from /shortlog.
+  my %logargs = (
+    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,
+    }
+  );
+
+  $c->stash(
+      commit  => $commit,
+      results => [$c->model('Git')->list_revs(%logargs)],
+      action  => 'search',
+         # This could be added - page      => $page,
+  );
 }
 
 sub search_help : Local {
index f923604..1d9328f 100644 (file)
@@ -570,22 +570,11 @@ Given the output of the C<rev-list> command return a list of hashes.
 
 sub parse_rev_list {
   my ($self, $output) = @_;
-  my @ret;
-
-  my @revs = split /\0/, $output;
-
-  for my $rev (split /\0/, $output) {
-    for my $line (split /\n/, $rev, 6) {
-      chomp $line;
-      next unless $line;
 
-      if ($self->valid_rev($line)) {
-        push @ret, $self->get_object($line);
-      }
-    }
-  }
-
-  return @ret;
+  return
+    map  $self->get_object($_),
+    grep $self->valid_rev($_),
+    map  split(/\n/, $_, 6), split /\0/, $output;
 }
 
 =head2 list_revs
@@ -598,12 +587,28 @@ array of hashes.
 sub list_revs {
   my ($self, %args) = @_;
 
-  $args{sha1} ||= $self->head_hash($args{project});
+  $args{sha1} = $self->head_hash($args{sha1})
+    if !$args{sha1} || $args{sha1} !~ $SHA1RE;
+
+       my @search_opts;
+  if($args{search}) {
+    my $sargs = $args{search};
+    $sargs->{type} = 'grep'
+      if $sargs->{type} eq 'commit';
+    @search_opts = (
+       # This seems a little fragile ...
+       qq[--$sargs->{type}=$sargs->{text}],
+       '--regexp-ignore-case',
+       $sargs->{regexp} ? '--extended-regexp' : '--fixed-strings'
+    );
+  }
 
+  $DB::single=1;
   my $output = $self->run_cmd_in($args{project} || $self->project, 'rev-list',
     '--header',
-    (defined $args{ count } ? "--max-count=$args{count}" : ()),
-    (defined $args{ skip  } ? "--skip=$args{skip}"       : ()),
+    (defined $args{ count  } ? "--max-count=$args{count}" : ()),
+    (defined $args{ skip   } ? "--skip=$args{skip}"       : ()),
+    @search_opts,
     $args{sha1},
     '--',
     ($args{file} ? $args{file} : ()),
index a119460..b8618e8 100644 (file)
   END %]
 </div>
 
-[% IF project AND have_search %]
-<div class="search">
-  <form method="get" action="/" enctype="application/x-www-form-urlencoded">
-  <input name="p" type="hidden" value="[% project %]" />
-  <input name="a" type="hidden" value="search" />
-  <input name="h" type="hidden" value="[% search_hash %]" />
-  <select name="st" >
-      <option value="commit">commit</option>
-      <option value="grep">grep</option>
-      <option value="author">author</option>
-      <option value="committer">committer</option>
-      <option value="pickaxe">pickaxe</option>
-  </select><sup><a href="/search_help?p=[% project %]">?</a></sup> search:
-  <input type="text" name="s" value="[% search_text %]"/>
-  <span title="Extended regular expression"><label><input type="checkbox" name="sr" value="1" />re</label></span>
-  </form>
-</div>
-[% END %]
-
-[%- # / git_header_html
--%]
 [%
-  IF page_nav;
-    INCLUDE "page_nav.tt2";
+  IF project;
+    INCLUDE 'nav/search.tt2';
   END;
+# / git_header_html
 %]
 <div id='body'>
 [%
diff --git a/templates/nav/search.tt2 b/templates/nav/search.tt2
new file mode 100644 (file)
index 0000000..a86a935
--- /dev/null
@@ -0,0 +1,19 @@
+<div class="search">
+  <form method="get" action="[% c.uri_for('search') %]" enctype="application/x-www-form-urlencoded">
+  <input name="p" type="hidden" value="[% project %]" />
+  <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') %]" />
+  <select name="type" >
+      <option value="commit">commit</option>
+      <option value="author">author</option>
+      <option value="committer">committer</option>
+      <!-- Not supported, maybe later.
+      <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 %]"/>
+  <span title="Extended regular expression"><label><input type="checkbox" name="regexp" value="1" />re</label></span>
+  </form>
+</div>
diff --git a/templates/page_nav.tt2 b/templates/page_nav.tt2
deleted file mode 100644 (file)
index c3d0e41..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<div class="page_nav">
-       [% nav_links %]
-       <br/>[% extra %]<br/>
-</div>
diff --git a/templates/search.tt2 b/templates/search.tt2
new file mode 100644 (file)
index 0000000..d1a5654
--- /dev/null
@@ -0,0 +1,34 @@
+[% INCLUDE 'nav/actions.tt2' object = commit %]
+
+[%# INCLUDE '_log_pager.tt2' %]
+
+[%# XXX Nabbed the HTML below from gitweb's log action. %]
+[% FOREACH result IN results %]
+<div class="header">
+ <a class="title" href="[% c.uri_for('commit', {h=result.sha1}) %]">
+  <span class="age">[% result.authored_time %]</span>
+  [% result.comment.substr(0, 50) | html %]
+ </a>
+</div>
+
+<div class="title_text">
+ <div class="log_link">
+   <a href="[% c.uri_for('commit', {h=result.sha1}) %]">commit</a>
+ | <a href="[% c.uri_for('commitdiff', {h=result.sha1}) %]">commitdiff</a>
+ | <a href="[% c.uri_for('tree', {h=result.tree_sha1, hb=line.sha1}) %]">tree</a>
+ </div>
+ <i>[% result.author.name | html %] [% line.authored_time %]</i>
+</div>
+
+<div class="log_body">
+ [%
+   # XXX This is fragile at best.
+   html_comment = result.comment | html;
+   html_comment.replace(
+     c.req.param('text'), '<span class="match">' _ c.req.param('text') _ '</span>'
+   );
+ %]
+</div>
+[% END %]
+
+[%# INCLUDE '_log_pager.tt2' %]