New perf dashboard should have an ability to search commits by a keyword
[WebKit-https.git] / Websites / perf.webkit.org / public / api / commits.php
1 <?php
2
3 require_once('../include/json-header.php');
4
5 function main($paths) {
6     if (count($paths) < 1 || count($paths) > 2)
7         exit_with_error('InvalidRequest');
8
9     $db = new Database;
10     if (!$db->connect())
11         exit_with_error('DatabaseConnectionFailure');
12
13     $repository_name = $paths[0];
14     $repository_row = $db->select_first_row('repositories', 'repository', array('name' => $repository_name));
15     if (!$repository_row)
16         exit_with_error('RepositoryNotFound', array('repositoryName' => $repository_name));
17     $repository_id = $repository_row['repository_id'];
18
19     $filter = array_get($paths, 1);
20     $single_commit = NULL;
21     $commits = array();
22     if (!$filter) {
23         $keyword = array_get($_GET, 'keyword');
24         $from = array_get($_GET, 'from');
25         $to = array_get($_GET, 'to');
26         $commits = fetch_commits_between($db, $repository_id, $from, $to, $keyword);
27     } else if ($filter == 'oldest') {
28         $single_commit = $db->select_first_row('commits', 'commit', array('repository' => $repository_id), 'time');
29     } else if ($filter == 'latest') {
30         $single_commit = $db->select_last_row('commits', 'commit', array('repository' => $repository_id), 'time');
31     } else if ($filter == 'last-reported') {
32         $single_commit = $db->select_last_row('commits', 'commit', array('repository' => $repository_id, 'reported' => true), 'time');
33     } else if (ctype_alnum($filter)) {
34         $single_commit = commit_from_revision($db, $repository_id, $filter);
35     } else {
36         $matches = array();
37         if (!preg_match('/([A-Za-z0-9]+)[\:\-]([A-Za-z0-9]+)/', $filter, $matches))
38             exit_with_error('UnknownFilter', array('repositoryName' => $repository_name, 'filter' => $filter));
39
40         $commits = fetch_commits_between($db, $repository_id, $matches[1], $matches[2]);
41     }
42
43     exit_with_success(array('commits' => $single_commit ? format_commit($single_commit) : $commits));
44 }
45
46 function commit_from_revision($db, $repository_id, $revision) {
47     $all_but_first = substr($revision, 1);
48     if ($revision[0] == 'r' && ctype_digit($all_but_first))
49         $revision = $all_but_first;
50     $commit_info = array('repository' => $repository_id, 'revision' => $revision);
51     $row = $db->select_last_row('commits', 'commit', $commit_info);
52     if (!$row)
53         exit_with_error('UnknownCommit', $commit_info);
54     return $row;
55 }
56
57 function fetch_commits_between($db, $repository_id, $first, $second, $keyword = NULL) {
58     $statements = 'SELECT commit_id as "id",
59         commit_revision as "revision",
60         commit_parent as "parent",
61         commit_time as "time",
62         commit_author_name as "authorName",
63         commit_author_email as "authorEmail",
64         commit_message as "message"
65         FROM commits WHERE commit_repository = $1 AND commit_reported = true';
66     $values = array($repository_id);
67
68     if ($first && $second) {
69         $first = commit_from_revision($db, $repository_id, $first)['commit_time'];
70         $second = commit_from_revision($db, $repository_id, $second)['commit_time'];
71         $in_order = $first < $second;
72         array_push($values, $in_order ? $first : $second);
73         $statements .= ' AND commit_time >= $' . count($values);
74         array_push($values, $in_order ? $second : $first);
75         $statements .= ' AND commit_time <= $' . count($values);
76     }
77
78     if ($keyword) {
79         array_push($values, '%' . str_replace(array('\\', '_', '@'), array('\\\\', '\\_', '\\%'), $keyword) . '%');
80         $index = '$' . count($values);
81         $statements .= " AND (commit_author_name LIKE $index OR commit_author_email LIKE $index";
82         array_push($values, ltrim($keyword, 'r'));
83         $statements .= ' OR commit_revision = $' . count($values) . ')';
84     }
85
86     $commits = $db->query_and_fetch_all($statements . ' ORDER BY commit_time', $values);
87     if (!is_array($commits))
88         exit_with_error('FailedToFetchCommits', array('repository' => $repository_id, 'first' => $first, 'second' => $second));
89     return $commits;
90 }
91
92 function format_commit($commit_row) {
93     return array(array(
94         'id' => $commit_row['commit_id'],
95         'revision' => $commit_row['commit_revision'],
96         'parent' => $commit_row['commit_parent'],
97         'time' => $commit_row['commit_time'],
98         'authorName' => $commit_row['commit_author_name'],
99         'authorEmail' => $commit_row['commit_author_email'],
100         'message' => $commit_row['commit_message']
101     ));
102 }
103
104 main(array_key_exists('PATH_INFO', $_SERVER) ? explode('/', trim($_SERVER['PATH_INFO'], '/')) : array());
105
106 ?>