Rewrite 'pull-os-versions' script in Javascript to add support for reporting os revis...
[WebKit-https.git] / Websites / perf.webkit.org / public / include / commit-log-fetcher.php
1 <?php
2
3 class CommitLogFetcher {
4
5     function __construct($db) {
6         $this->db = $db;
7     }
8
9     function fetch_for_tasks($task_id_list, $task_by_id)
10     {
11         $commit_rows = $this->db->query_and_fetch_all('SELECT task_commits.*, commits.*, committers.*
12             FROM task_commits, commits LEFT OUTER JOIN committers ON commit_committer = committer_id
13             WHERE taskcommit_commit = commit_id AND taskcommit_task = ANY ($1)', array('{' . implode(', ', $task_id_list) . '}'));
14         if (!is_array($commit_rows))
15             return NULL;
16
17         $commits = array();
18         foreach ($commit_rows as &$commit_row) {
19             $associated_task = &$task_by_id[$commit_row['taskcommit_task']];
20             $commit = $this->format_commit($commit_row, $commit_row);
21             $commit['repository'] = $commit_row['commit_repository'];
22             array_push($commits, $commit);
23             array_push($associated_task[Database::is_true($commit_row['taskcommit_is_fix']) ? 'fixes' : 'causes'], $commit_row['commit_id']);
24         }
25         return $commits;
26     }
27
28     function repository_id_from_name($name)
29     {
30         $repository_row = $this->db->select_first_row('repositories', 'repository', array('name' => $name, 'owner' => NULL));
31         if (!$repository_row)
32             return NULL;
33         return $repository_row['repository_id'];
34     }
35
36     function fetch_between($repository_id, $first, $second, $keyword = NULL)
37     {
38         $statements = 'SELECT commit_id as "id",
39             commit_revision as "revision",
40             commit_previous_commit as "previousCommit",
41             commit_time as "time",
42             committer_name as "authorName",
43             committer_account as "authorEmail",
44             commit_message as "message"
45             FROM commits LEFT OUTER JOIN committers ON commit_committer = committer_id
46             WHERE commit_repository = $1 AND commit_reported = true';
47         $values = array($repository_id);
48
49         if ($first && $second) {
50             $first_commit = $this->commit_for_revision($repository_id, $first);
51             $second_commit = $this->commit_for_revision($repository_id, $second);
52             $first = $first_commit['commit_time'];
53             $second = $second_commit['commit_time'];
54             $column_name = 'commit_time';
55             if (!$first || !$second) {
56                 $first = $first_commit['commit_order'];
57                 $second = $second_commit['commit_order'];
58                 $column_name = 'commit_order';
59             }
60
61             $in_order = $first < $second;
62             array_push($values, $in_order ? $first : $second);
63             $statements .= ' AND ' . $column_name . ' >= $' . count($values);
64             array_push($values, $in_order ? $second : $first);
65             $statements .= ' AND ' . $column_name . ' <= $' . count($values);
66         }
67
68         if ($keyword) {
69             array_push($values, '%' . Database::escape_for_like($keyword) . '%');
70             $keyword_index = '$' . count($values);
71             array_push($values, ltrim($keyword, 'r'));
72             $revision_index = '$' . count($values);
73             $statements .= "
74                 AND ((committer_name LIKE $keyword_index OR committer_account LIKE $keyword_index) OR commit_revision = $revision_index)";
75         }
76
77         $commits = $this->db->query_and_fetch_all($statements . ' ORDER BY commit_time, commit_order', $values);
78         if (!is_array($commits))
79             return NULL;
80
81         foreach ($commits as &$commit)
82             $commit['time'] = Database::to_js_time($commit['time']);
83
84         return $commits;
85     }
86
87     # FIXME: this is not DRY. Ideally, $db should provide the ability to search with criteria that specifies a range.
88     function fetch_last_reported_between_orders($repository_id, $from, $to)
89     {
90         $statements = 'SELECT * FROM commits LEFT OUTER JOIN committers ON commit_committer = committer_id
91             WHERE commit_repository = $1 AND commit_reported = true';
92         $from = intval($from);
93         $to = intval($to);
94         $statements .= ' AND commit_order >= $2 AND commit_order <= $3 ORDER BY commit_order DESC LIMIT 1';
95
96         $commits = $this->db->query_and_fetch_all($statements, array($repository_id, $from, $to));
97         if (!is_array($commits))
98             return NULL;
99
100         foreach ($commits as &$commit)
101             $commit = $this->format_single_commit($commit)[0];
102
103         return $commits;
104     }
105
106     function fetch_oldest($repository_id) {
107         return $this->format_single_commit($this->db->select_first_row('commits', 'commit', array('repository' => $repository_id), array('time', 'order')));
108     }
109
110     function fetch_latest($repository_id) {
111         return $this->format_single_commit($this->db->select_last_row('commits', 'commit', array('repository' => $repository_id), array('time', 'order')));
112     }
113
114     function fetch_last_reported($repository_id) {
115         return $this->format_single_commit($this->db->select_last_row('commits', 'commit', array('repository' => $repository_id, 'reported' => true), array('time', 'order')));
116     }
117
118     function fetch_revision($repository_id, $revision) {
119         return $this->format_single_commit($this->commit_for_revision($repository_id, $revision));
120     }
121
122     private function commit_for_revision($repository_id, $revision) {
123         $all_but_first = substr($revision, 1);
124         if ($revision[0] == 'r' && ctype_digit($all_but_first))
125             $revision = $all_but_first;
126         $commit_info = array('repository' => $repository_id, 'revision' => $revision);
127         $row = $this->db->select_last_row('commits', 'commit', $commit_info);
128         if (!$row)
129             exit_with_error('UnknownCommit', $commit_info);
130         return $row;
131     }
132
133     private function format_single_commit($commit_row) {
134         if (!$commit_row)
135             return array();
136         $committer = $this->db->select_first_row('committers', 'committer', array('id' => $commit_row['commit_committer']));
137         return array($this->format_commit($commit_row, $committer));
138     }
139
140     private function format_commit($commit_row, $committer_row) {
141         return array(
142             'id' => $commit_row['commit_id'],
143             'revision' => $commit_row['commit_revision'],
144             'previousCommit' => $commit_row['commit_previous_commit'],
145             'time' => Database::to_js_time($commit_row['commit_time']),
146             'order' => $commit_row['commit_order'],
147             'authorName' => $committer_row ? $committer_row['committer_name'] : null,
148             'authorEmail' => $committer_row ? $committer_row['committer_account'] : null,
149             'message' => $commit_row['commit_message']
150         );
151     }
152 }
153
154 ?>