1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
4
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
5
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
6
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
7
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
8
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
9
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
10
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
11
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
12
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
13
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
14
|
|
|
* |
15
|
|
|
* This software consists of voluntary contributions made by many individuals |
16
|
|
|
* and is licensed under the LGPL. For more information please see |
17
|
|
|
* <http://phing.info>. |
18
|
|
|
*/ |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Writes a build event to the console. |
22
|
|
|
* |
23
|
|
|
* Currently, it only writes which targets are being executed, and |
24
|
|
|
* any messages that get logged. |
25
|
|
|
* |
26
|
|
|
* @author Andreas Aderhold <[email protected]> |
27
|
|
|
* @copyright 2001,2002 THYRELL. All rights reserved |
28
|
|
|
* @see BuildEvent |
29
|
|
|
* @package phing.listener |
30
|
|
|
*/ |
31
|
|
|
class DefaultLogger implements StreamRequiredBuildLogger |
32
|
|
|
{ |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Size of the left column in output. The default char width is 12. |
36
|
|
|
* |
37
|
|
|
* @var int |
38
|
|
|
*/ |
39
|
|
|
public const LEFT_COLUMN_SIZE = 12; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* The message output level that should be used. The default is |
43
|
|
|
* <code>Project::MSG_VERBOSE</code>. |
44
|
|
|
* |
45
|
|
|
* @var int |
46
|
|
|
*/ |
47
|
|
|
protected $msgOutputLevel = Project::MSG_ERR; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Time that the build started |
51
|
|
|
* |
52
|
|
|
* @var int |
53
|
|
|
*/ |
54
|
|
|
protected $startTime; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* @var OutputStream Stream to use for standard output. |
58
|
|
|
*/ |
59
|
|
|
protected $out; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @var OutputStream Stream to use for error output. |
63
|
|
|
*/ |
64
|
|
|
protected $err; |
65
|
|
|
|
66
|
|
|
protected $emacsMode = false; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Construct a new default logger. |
70
|
|
|
*/ |
71
|
5 |
|
public function __construct() |
72
|
|
|
{ |
73
|
5 |
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Set the msgOutputLevel this logger is to respond to. |
77
|
|
|
* |
78
|
|
|
* Only messages with a message level lower than or equal to the given |
79
|
|
|
* level are output to the log. |
80
|
|
|
* |
81
|
|
|
* <p> Constants for the message levels are in Project.php. The order of |
82
|
|
|
* the levels, from least to most verbose, is: |
83
|
|
|
* |
84
|
|
|
* <ul> |
85
|
|
|
* <li>Project::MSG_ERR</li> |
86
|
|
|
* <li>Project::MSG_WARN</li> |
87
|
|
|
* <li>Project::MSG_INFO</li> |
88
|
|
|
* <li>Project::MSG_VERBOSE</li> |
89
|
|
|
* <li>Project::MSG_DEBUG</li> |
90
|
|
|
* </ul> |
91
|
|
|
* |
92
|
|
|
* The default message level for DefaultLogger is Project::MSG_ERR. |
93
|
|
|
* |
94
|
|
|
* @param int $level The logging level for the logger. |
95
|
|
|
* @see BuildLogger#setMessageOutputLevel() |
96
|
|
|
*/ |
97
|
1 |
|
public function setMessageOutputLevel($level) |
98
|
|
|
{ |
99
|
1 |
|
$this->msgOutputLevel = (int) $level; |
100
|
1 |
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Sets the output stream. |
104
|
|
|
* |
105
|
|
|
* @param OutputStream $output |
106
|
|
|
* @see BuildLogger#setOutputStream() |
107
|
|
|
*/ |
108
|
1 |
|
public function setOutputStream(OutputStream $output) |
109
|
|
|
{ |
110
|
1 |
|
$this->out = $output; |
111
|
1 |
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Sets the error stream. |
115
|
|
|
* |
116
|
|
|
* @param OutputStream $err |
117
|
|
|
* @see BuildLogger#setErrorStream() |
118
|
|
|
*/ |
119
|
1 |
|
public function setErrorStream(OutputStream $err) |
120
|
|
|
{ |
121
|
1 |
|
$this->err = $err; |
122
|
1 |
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Sets this logger to produce emacs (and other editor) friendly output. |
126
|
|
|
* |
127
|
|
|
* @param bool $emacsMode <code>true</code> if output is to be unadorned so that |
128
|
|
|
* emacs and other editors can parse files names, etc. |
129
|
|
|
*/ |
130
|
|
|
public function setEmacsMode($emacsMode) |
131
|
|
|
{ |
132
|
|
|
$this->emacsMode = $emacsMode; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Sets the start-time when the build started. Used for calculating |
137
|
|
|
* the build-time. |
138
|
|
|
* |
139
|
|
|
* @param BuildEvent $event |
140
|
|
|
*/ |
141
|
|
|
public function buildStarted(BuildEvent $event) |
142
|
|
|
{ |
143
|
|
|
$this->startTime = Phing::currentTimeMillis(); |
144
|
|
|
if ($this->msgOutputLevel >= Project::MSG_INFO) { |
145
|
|
|
$this->printMessage( |
146
|
|
|
"Buildfile: " . $event->getProject()->getProperty("phing.file"), |
147
|
|
|
$this->out, |
148
|
|
|
Project::MSG_INFO |
149
|
|
|
); |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Prints whether the build succeeded or failed, and any errors that |
155
|
|
|
* occurred during the build. Also outputs the total build-time. |
156
|
|
|
* |
157
|
|
|
* @param BuildEvent $event |
158
|
|
|
* @see BuildEvent::getException() |
159
|
|
|
*/ |
160
|
3 |
|
public function buildFinished(BuildEvent $event) |
161
|
|
|
{ |
162
|
3 |
|
$msg = PHP_EOL . $this->getBuildSuccessfulMessage() . PHP_EOL; |
163
|
3 |
|
$error = $event->getException(); |
164
|
|
|
|
165
|
3 |
|
if ($error !== null) { |
166
|
1 |
|
$msg = PHP_EOL . $this->getBuildFailedMessage() . PHP_EOL; |
167
|
|
|
|
168
|
1 |
|
self::throwableMessage($msg, $error, Project::MSG_VERBOSE <= $this->msgOutputLevel); |
169
|
|
|
} |
170
|
3 |
|
$msg .= PHP_EOL . "Total time: " . static::formatTime(Phing::currentTimeMillis() - $this->startTime) . PHP_EOL; |
171
|
|
|
|
172
|
3 |
|
$error === null |
173
|
2 |
|
? $this->printMessage($msg, $this->out, Project::MSG_VERBOSE) |
174
|
1 |
|
: $this->printMessage($msg, $this->err, Project::MSG_ERR); |
175
|
3 |
|
} |
176
|
|
|
|
177
|
4 |
|
public static function throwableMessage(&$msg, $error, $verbose) |
178
|
|
|
{ |
179
|
4 |
|
while ($error instanceof BuildException) { |
180
|
3 |
|
$cause = $error->getPrevious(); |
181
|
3 |
|
if ($cause === null) { |
182
|
3 |
|
break; |
183
|
|
|
} |
184
|
2 |
|
$msg1 = trim($error); |
185
|
2 |
|
$msg2 = trim($cause); |
186
|
2 |
|
if (StringHelper::endsWith($msg2, $msg1)) { |
187
|
2 |
|
$msg .= StringHelper::substring($msg1, 0, strlen($msg1) - strlen($msg2) - 1); |
188
|
2 |
|
$error = $cause; |
189
|
|
|
} else { |
190
|
|
|
break; |
191
|
|
|
} |
192
|
|
|
} |
193
|
4 |
|
$msg .= $verbose || !$error instanceof BuildException |
194
|
1 |
|
? $error->getMessage() . PHP_EOL . $error->getTraceAsString() . PHP_EOL |
195
|
4 |
|
: $error->getLocation() . ' ' . $error->getMessage() . PHP_EOL; |
196
|
4 |
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Get the message to return when a build failed. |
200
|
|
|
* |
201
|
|
|
* @return string The classic "BUILD FAILED" |
202
|
|
|
*/ |
203
|
1 |
|
protected function getBuildFailedMessage() |
204
|
|
|
{ |
205
|
1 |
|
return "BUILD FAILED"; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Get the message to return when a build succeeded. |
210
|
|
|
* |
211
|
|
|
* @return string The classic "BUILD FINISHED" |
212
|
|
|
*/ |
213
|
3 |
|
protected function getBuildSuccessfulMessage() |
214
|
|
|
{ |
215
|
3 |
|
return "BUILD FINISHED"; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Prints the current target name |
220
|
|
|
* |
221
|
|
|
* @param BuildEvent $event |
222
|
|
|
* @see BuildEvent::getTarget() |
223
|
|
|
*/ |
224
|
1 |
|
public function targetStarted(BuildEvent $event) |
225
|
|
|
{ |
226
|
|
|
if ( |
227
|
1 |
|
Project::MSG_INFO <= $this->msgOutputLevel |
228
|
1 |
|
&& $event->getTarget()->getName() != '' |
229
|
|
|
) { |
230
|
1 |
|
$showLongTargets = $event->getProject()->getProperty("phing.showlongtargets"); |
231
|
1 |
|
$msg = PHP_EOL . $event->getProject()->getName() . ' > ' . $event->getTarget()->getName() . ($showLongTargets ? ' [' . $event->getTarget()->getDescription() . ']' : '') . ':' . PHP_EOL; |
232
|
1 |
|
$this->printMessage($msg, $this->out, $event->getPriority()); |
233
|
|
|
} |
234
|
1 |
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* Fired when a target has finished. We don't need specific action on this |
238
|
|
|
* event. So the methods are empty. |
239
|
|
|
* |
240
|
|
|
* @param BuildEvent $event |
241
|
|
|
* @see BuildEvent::getException() |
242
|
|
|
*/ |
243
|
1 |
|
public function targetFinished(BuildEvent $event) |
244
|
|
|
{ |
245
|
1 |
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Fired when a task is started. We don't need specific action on this |
249
|
|
|
* event. So the methods are empty. |
250
|
|
|
* |
251
|
|
|
* @param BuildEvent $event |
252
|
|
|
* @see BuildEvent::getTask() |
253
|
|
|
*/ |
254
|
1 |
|
public function taskStarted(BuildEvent $event) |
255
|
|
|
{ |
256
|
1 |
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Fired when a task has finished. We don't need specific action on this |
260
|
|
|
* event. So the methods are empty. |
261
|
|
|
* |
262
|
|
|
* @param BuildEvent $event The BuildEvent |
263
|
|
|
* @see BuildEvent::getException() |
264
|
|
|
*/ |
265
|
1 |
|
public function taskFinished(BuildEvent $event) |
266
|
|
|
{ |
267
|
1 |
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* Print a message to the stdout. |
271
|
|
|
* |
272
|
|
|
* @param BuildEvent $event |
273
|
|
|
* @see BuildEvent::getMessage() |
274
|
|
|
*/ |
275
|
1 |
|
public function messageLogged(BuildEvent $event) |
276
|
|
|
{ |
277
|
1 |
|
$priority = $event->getPriority(); |
278
|
1 |
|
if ($priority <= $this->msgOutputLevel) { |
279
|
1 |
|
$msg = ""; |
280
|
1 |
|
if ($event->getTask() !== null && !$this->emacsMode) { |
281
|
1 |
|
$name = $event->getTask(); |
282
|
1 |
|
$name = $name->getTaskName(); |
283
|
1 |
|
$msg = str_pad("[$name] ", self::LEFT_COLUMN_SIZE, " ", STR_PAD_LEFT); |
284
|
|
|
} |
285
|
|
|
|
286
|
1 |
|
$msg .= $event->getMessage(); |
287
|
|
|
|
288
|
1 |
|
if ($priority != Project::MSG_ERR) { |
289
|
1 |
|
$this->printMessage($msg, $this->out, $priority); |
290
|
|
|
} else { |
291
|
|
|
$this->printMessage($msg, $this->err, $priority); |
292
|
|
|
} |
293
|
|
|
} |
294
|
1 |
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Formats a time micro integer to human readable format. |
298
|
|
|
* |
299
|
|
|
* @param integer The time stamp |
300
|
|
|
* @return string |
301
|
|
|
*/ |
302
|
1 |
|
public static function formatTime($micros) |
303
|
|
|
{ |
304
|
1 |
|
$seconds = $micros; |
305
|
1 |
|
$minutes = (int) floor($seconds / 60); |
306
|
1 |
|
if ($minutes >= 1) { |
307
|
|
|
return sprintf( |
308
|
|
|
"%1.0f minute%s %0.2f second%s", |
309
|
|
|
$minutes, |
310
|
|
|
($minutes === 1 ? " " : "s "), |
311
|
|
|
$seconds - floor($seconds / 60) * 60, |
312
|
|
|
($seconds % 60 === 1 ? "" : "s") |
313
|
|
|
); |
314
|
|
|
} |
315
|
|
|
|
316
|
1 |
|
return sprintf("%0.4f second%s", $seconds, ($seconds % 60 === 1 ? "" : "s")); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Prints a message to console. |
321
|
|
|
* |
322
|
|
|
* @param string $message The message to print. |
323
|
|
|
* Should not be |
324
|
|
|
* <code>null</code>. |
325
|
|
|
* @param OutputStream|resource $stream The stream to use for message printing. |
326
|
|
|
* @param int $priority The priority of the message. |
327
|
|
|
* (Ignored in this |
328
|
|
|
* implementation.) |
329
|
|
|
* @throws IOException |
330
|
|
|
* @return void |
331
|
|
|
*/ |
332
|
1 |
|
protected function printMessage($message, OutputStream $stream, $priority) |
|
|
|
|
333
|
|
|
{ |
334
|
1 |
|
$stream->write($message . PHP_EOL); |
335
|
1 |
|
} |
336
|
|
|
} |
337
|
|
|
|
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.