diff --git a/src/GitList/Controller/CommitController.php b/src/GitList/Controller/CommitController.php
index 658df9a..ee60e12 100644
--- a/src/GitList/Controller/CommitController.php
+++ b/src/GitList/Controller/CommitController.php
@@ -6,6 +6,7 @@ use Silex\Application;
use Silex\ControllerProviderInterface;
use Silex\ControllerCollection;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\Request;
class CommitController implements ControllerProviderInterface
{
@@ -43,6 +44,27 @@ class CommitController implements ControllerProviderInterface
->value('file', '')
->bind('commits');
+ $route->post('{repo}/commits/search', function(Request $request, $repo) use ($app) {
+ $repository = $app['git']->getRepository($app['git.repos'] . $repo);
+ $commits = $repository->searchCommitLog($request->get('query'));
+
+ foreach ($commits as $commit) {
+ $date = $commit->getDate();
+ $date = $date->format('m/d/Y');
+ $categorized[$date][] = $commit;
+ }
+
+ return $app['twig']->render('searchcommits.twig', array(
+ 'repo' => $repo,
+ 'branch' => 'master',
+ 'file' => '',
+ 'commits' => $categorized,
+ 'branches' => $repository->getBranches(),
+ 'tags' => $repository->getTags(),
+ ));
+ })->assert('repo', '[\w-._]+')
+ ->bind('searchcommits');
+
$route->get('{repo}/commit/{commit}/', function($repo, $commit) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$commit = $repository->getCommit($commit);
diff --git a/src/GitList/Controller/TreeController.php b/src/GitList/Controller/TreeController.php
index c8a9708..4abe17f 100644
--- a/src/GitList/Controller/TreeController.php
+++ b/src/GitList/Controller/TreeController.php
@@ -7,6 +7,7 @@ use Silex\ControllerProviderInterface;
use Silex\ControllerCollection;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\HttpFoundation\Request;
class TreeController implements ControllerProviderInterface
{
@@ -45,6 +46,29 @@ class TreeController implements ControllerProviderInterface
->assert('tree', '.+')
->bind('tree');
+ $route->post('{repo}/tree/{branch}/search', function(Request $request, $repo, $branch = '', $tree = '') use ($app) {
+ $repository = $app['git']->getRepository($app['git.repos'] . $repo);
+
+ if (!$branch) {
+ $branch = $repository->getHead();
+ }
+
+ $breadcrumbs = $app['util.view']->getBreadcrumbs($tree);
+ $results = $repository->searchTree($request->get('query'), $branch);
+
+ return $app['twig']->render('search.twig', array(
+ 'results' => $results,
+ 'repo' => $repo,
+ 'branch' => $branch,
+ 'path' => $tree,
+ 'breadcrumbs' => $breadcrumbs,
+ 'branches' => $repository->getBranches(),
+ 'tags' => $repository->getTags(),
+ ));
+ })->assert('repo', '[\w-._]+')
+ ->assert('branch', '[\w-._]+')
+ ->bind('search');
+
$route->get('{repo}/{branch}/', function($repo, $branch) use ($app, $treeController) {
return $treeController($repo, $branch);
})->assert('repo', '[\w-._]+')
diff --git a/src/GitList/Git/Repository.php b/src/GitList/Git/Repository.php
index c146602..2c6202b 100644
--- a/src/GitList/Git/Repository.php
+++ b/src/GitList/Git/Repository.php
@@ -35,6 +35,47 @@ class Repository extends BaseRepository
return $commits;
}
+ public function searchCommitLog($query)
+ {
+ $command = "log --grep='$query' --pretty=format:'- %H%h%T%P%an%ae%at%cn%ce%ct
'";
+
+ $logs = $this->getPrettyFormat($command);
+
+ foreach ($logs as $log) {
+ $commit = new Commit;
+ $commit->importData($log);
+ $commits[] = $commit;
+ }
+
+ return $commits;
+ }
+
+ public function searchTree($query, $branch)
+ {
+ try {
+ $results = $this->getClient()->run($this, "grep --line-number '$query' $branch");
+ } catch (\RuntimeException $e) {
+ return false;
+ }
+
+ $results = explode("\n", $results);
+
+ foreach ($results as $result) {
+ if ($result == '') {
+ continue;
+ }
+
+ preg_match_all('/([\w-._]+):(.+):([0-9]+):(.+)/', $result, $matches, PREG_SET_ORDER);
+ $data['branch'] = $matches[0][1];
+ $data['file'] = $matches[0][2];
+ $data['line'] = $matches[0][3];
+ $data['match'] = $matches[0][4];
+ $searchResults[] = $data;
+ }
+
+ return $searchResults;
+ }
+
public function getAuthorStatistics()
{
$logs = $this->getClient()->run($this, 'log --pretty=format:"%an||%ae" ' . $this->getHead());
diff --git a/views/commits_list.twig b/views/commits_list.twig
index e0ec786..959d9ff 100644
--- a/views/commits_list.twig
+++ b/views/commits_list.twig
@@ -20,6 +20,7 @@
{% endfor %}
+{% if page != 'searchcommits' %}
+{% endif %}
\ No newline at end of file
diff --git a/views/layout_page.twig b/views/layout_page.twig
index 370fb0b..97f51f3 100644
--- a/views/layout_page.twig
+++ b/views/layout_page.twig
@@ -6,9 +6,20 @@
+ {% if page == 'commits' %}
+
+ {% else %}
+
+ {% endif %}
+
{% if branches is defined %}
{% include 'branch_menu.twig' %}
{% endif %}
+
{% include 'menu.twig' %}
diff --git a/views/search.twig b/views/search.twig
new file mode 100644
index 0000000..d7804d3
--- /dev/null
+++ b/views/search.twig
@@ -0,0 +1,42 @@
+{% extends 'layout_page.twig' %}
+
+{% set page = 'files' %}
+
+{% block title %}GitList{% endblock %}
+
+{% block content %}
+ {% embed 'breadcrumb.twig' with {breadcrumbs: breadcrumbs} %}
+ {% block extra %}
+
+ {% endblock %}
+ {% endembed %}
+
+ {% if results %}
+
+
+
+ | name |
+ match |
+
+
+
+ {% for result in results %}
+
+ | {{ result.file }} |
+ {{ result.match }} |
+
+ {% endfor %}
+
+
+ {% else %}
+
No results found.
+ {% endif %}
+
+
+{% endblock %}
diff --git a/views/searchcommits.twig b/views/searchcommits.twig
new file mode 100644
index 0000000..8b2969b
--- /dev/null
+++ b/views/searchcommits.twig
@@ -0,0 +1,13 @@
+{% extends 'layout_page.twig' %}
+
+{% set page = 'searchcommits' %}
+
+{% block title %}GitList{% endblock %}
+
+{% block content %}
+ {% include 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Commits search results', path:''}]} %}
+
+ {% include 'commits_list.twig' %}
+
+
+{% endblock %}
diff --git a/web/css/style.css b/web/css/style.css
index a8b5fcf..f2fe4b0 100644
--- a/web/css/style.css
+++ b/web/css/style.css
@@ -193,7 +193,8 @@ input:focus:required:invalid,textarea:focus:required:invalid,select:focus:requir
.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
-.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;}
+.form-search{margin:3px 0 0 0;padding:0;}
+.search-query{padding:3px;margin-bottom:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;font-size:11px;}
.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;*zoom:1;margin-bottom:0;}
.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none;}
.form-search label,.form-inline label{display:inline-block;}
diff --git a/web/less/forms.less b/web/less/forms.less
index 7d967c6..3d0185d 100755
--- a/web/less/forms.less
+++ b/web/less/forms.less
@@ -466,13 +466,16 @@ select:focus:required:invalid {
// SEARCH FORM
// -----------
+.form-search {
+ margin: 3px 0 0 0;
+ padding: 0;
+}
+
.search-query {
- padding-right: 14px;
- padding-right: 4px \9;
- padding-left: 14px;
- padding-left: 4px \9; /* IE7-8 doesn't have border-radius, so don't indent the padding */
+ padding: 3px;
margin-bottom: 0; // remove the default margin on all inputs
- .border-radius(14px);
+ .border-radius(4px);
+ font-size: 11px;
}