1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of the SVN-Buddy library. |
4
|
|
|
* For the full copyright and license information, please view |
5
|
|
|
* the LICENSE file that was distributed with this source code. |
6
|
|
|
* |
7
|
|
|
* @copyright Alexander Obuhovich <[email protected]> |
8
|
|
|
* @link https://github.com/console-helpers/svn-buddy |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace ConsoleHelpers\SVNBuddy\Repository\RevisionLog\Plugin\DatabaseCollectorPlugin; |
12
|
|
|
|
13
|
|
|
|
14
|
|
|
class ProjectsPlugin extends AbstractDatabaseCollectorPlugin |
15
|
|
|
{ |
16
|
|
|
|
17
|
|
|
const STATISTIC_PROJECT_DELETED = 'project_deleted'; |
18
|
|
|
|
19
|
|
|
const STATISTIC_PROJECT_RESTORED = 'project_restored'; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Returns plugin name. |
23
|
|
|
* |
24
|
|
|
* @return string |
25
|
|
|
*/ |
26
|
11 |
|
public function getName() |
27
|
|
|
{ |
28
|
11 |
|
return 'projects'; |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Defines parsing statistic types. |
33
|
|
|
* |
34
|
|
|
* @return array |
35
|
|
|
*/ |
36
|
15 |
|
public function defineStatisticTypes() |
37
|
|
|
{ |
38
|
|
|
return array( |
39
|
15 |
|
self::STATISTIC_PROJECT_DELETED, |
40
|
15 |
|
self::STATISTIC_PROJECT_RESTORED, |
41
|
|
|
); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Processes data. |
46
|
|
|
* |
47
|
|
|
* @param integer $from_revision From revision. |
48
|
|
|
* @param integer $to_revision To revision. |
49
|
|
|
* |
50
|
|
|
* @return void |
51
|
|
|
*/ |
52
|
6 |
|
public function doProcess($from_revision, $to_revision) |
53
|
|
|
{ |
54
|
6 |
|
$projects = $this->getProjects(); |
55
|
6 |
|
$this->setLastRevision($to_revision); |
56
|
|
|
|
57
|
|
|
// When no projects exists and there 20+ commits, then consider repository |
58
|
|
|
// having single project without known structure (trunk/branches/tags) only. |
59
|
6 |
|
if ( !$projects && $to_revision >= 20 ) { |
60
|
2 |
|
$this->createRepositoryWideProject(); |
61
|
|
|
} |
62
|
|
|
|
63
|
6 |
|
foreach ( $projects as $project_data ) { |
64
|
3 |
|
$is_deleted = $project_data['IsDeleted']; |
65
|
|
|
|
66
|
3 |
|
if ( $is_deleted && !is_numeric($project_data['RevisionDeleted']) ) { |
67
|
2 |
|
$this->repositoryFiller->setProjectStatus($project_data['Id'], 0); |
68
|
2 |
|
$this->recordStatistic(self::STATISTIC_PROJECT_RESTORED); |
69
|
|
|
} |
70
|
1 |
|
elseif ( !$is_deleted && is_numeric($project_data['RevisionDeleted']) ) { |
71
|
1 |
|
$this->repositoryFiller->setProjectStatus($project_data['Id'], 1); |
72
|
3 |
|
$this->recordStatistic(self::STATISTIC_PROJECT_DELETED); |
73
|
|
|
} |
74
|
|
|
} |
75
|
|
|
|
76
|
6 |
|
$this->advanceProgressBar(); |
77
|
6 |
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Creates one project per repository and moves all commits into it. |
81
|
|
|
* |
82
|
|
|
* @return void |
83
|
|
|
*/ |
84
|
2 |
|
protected function createRepositoryWideProject() |
85
|
|
|
{ |
86
|
2 |
|
$select_sql = 'SELECT Id FROM Paths WHERE ProjectPath = :project_path LIMIT 100'; |
87
|
|
|
|
88
|
2 |
|
while ( true ) { |
89
|
2 |
|
$path_ids = $this->database->fetchCol($select_sql, array('project_path' => '')); |
90
|
|
|
|
91
|
2 |
|
if ( !$path_ids ) { |
|
|
|
|
92
|
2 |
|
break; |
93
|
|
|
} |
94
|
|
|
|
95
|
1 |
|
$this->repositoryFiller->movePathsIntoProject($path_ids, '/'); |
96
|
|
|
} |
97
|
|
|
|
98
|
2 |
|
$project_id = $this->repositoryFiller->addProject('/'); |
99
|
|
|
|
100
|
2 |
|
$sql = 'SELECT Revision |
101
|
|
|
FROM Commits'; |
102
|
2 |
|
$all_commits = $this->database->yieldCol($sql); |
103
|
|
|
|
104
|
2 |
|
foreach ( $all_commits as $revision ) { |
105
|
1 |
|
$this->repositoryFiller->addCommitToProject($revision, $project_id); |
106
|
|
|
} |
107
|
2 |
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Find revisions by collected data. |
111
|
|
|
* |
112
|
|
|
* @param array $criteria Criteria. |
113
|
|
|
* @param string $project_path Project path. |
114
|
|
|
* |
115
|
|
|
* @return array |
116
|
|
|
* @throws \InvalidArgumentException When some of given project paths are not found. |
117
|
|
|
*/ |
118
|
4 |
|
public function find(array $criteria, $project_path) |
119
|
|
|
{ |
120
|
4 |
|
if ( !$criteria ) { |
|
|
|
|
121
|
1 |
|
return array(); |
122
|
|
|
} |
123
|
|
|
|
124
|
3 |
|
$sql = 'SELECT Path, Id |
125
|
|
|
FROM Projects |
126
|
|
|
WHERE Path IN (:paths)'; |
127
|
3 |
|
$projects = $this->database->fetchPairs($sql, array('paths' => $criteria)); |
128
|
|
|
|
129
|
3 |
|
$missing_projects = array_diff($criteria, array_keys($projects)); |
130
|
|
|
|
131
|
3 |
|
if ( $missing_projects ) { |
|
|
|
|
132
|
1 |
|
throw new \InvalidArgumentException(sprintf( |
133
|
1 |
|
'The "%s" project(-s) not found by "%s" plugin.', |
134
|
1 |
|
implode('", "', $missing_projects), |
135
|
1 |
|
$this->getName() |
136
|
|
|
)); |
137
|
|
|
} |
138
|
|
|
|
139
|
2 |
|
$sql = 'SELECT DISTINCT Revision |
140
|
|
|
FROM CommitProjects |
141
|
|
|
WHERE ProjectId IN (:project_ids)'; |
142
|
2 |
|
$project_revisions = $this->database->fetchCol($sql, array('project_ids' => $projects)); |
143
|
|
|
|
144
|
2 |
|
sort($project_revisions, SORT_NUMERIC); |
145
|
|
|
|
146
|
2 |
|
return $project_revisions; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Returns information about revisions. |
151
|
|
|
* |
152
|
|
|
* @param array $revisions Revisions. |
153
|
|
|
* |
154
|
|
|
* @return array |
155
|
|
|
*/ |
156
|
1 |
|
public function getRevisionsData(array $revisions) |
157
|
|
|
{ |
158
|
1 |
|
$results = array(); |
159
|
1 |
|
$all_projects = $this->getAllProjects(); |
160
|
|
|
|
161
|
1 |
|
$sql = 'SELECT Revision, ProjectId |
162
|
|
|
FROM CommitProjects |
163
|
|
|
WHERE Revision IN (:revisions)'; |
164
|
1 |
|
$revisions_data = $this->getRawRevisionsData($sql, 'revisions', $revisions); |
165
|
|
|
|
166
|
1 |
|
foreach ( $revisions_data as $revision_data ) { |
167
|
1 |
|
$revision = $revision_data['Revision']; |
168
|
1 |
|
$project_path = $all_projects[$revision_data['ProjectId']]; |
169
|
|
|
|
170
|
1 |
|
if ( !isset($results[$revision]) ) { |
171
|
1 |
|
$results[$revision] = array(); |
172
|
|
|
} |
173
|
|
|
|
174
|
1 |
|
$results[$revision][] = $project_path; |
175
|
|
|
} |
176
|
|
|
|
177
|
1 |
|
return $this->addMissingResults($revisions, $results); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Returns all projects. |
182
|
|
|
* |
183
|
|
|
* @return array |
184
|
|
|
*/ |
185
|
1 |
|
protected function getAllProjects() |
186
|
|
|
{ |
187
|
1 |
|
$sql = 'SELECT Id, Path |
188
|
|
|
FROM Projects'; |
189
|
|
|
|
190
|
1 |
|
return $this->database->fetchPairs($sql); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Returns project meta information. |
195
|
|
|
* |
196
|
|
|
* @param string $project_path Project path. |
197
|
|
|
* |
198
|
|
|
* @return array |
199
|
|
|
*/ |
200
|
|
|
public function getMeta($project_path) |
201
|
|
|
{ |
202
|
|
|
$projects = $this->getProjects('Id = :id', array('id' => $this->getProject($project_path))); |
203
|
|
|
|
204
|
|
|
return reset($projects); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
} |
208
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.