Skip to content

Commit

Permalink
Detect cycles by default, with an option to run unsafely
Browse files Browse the repository at this point in the history
Instead of requiring the user specify -C/--cycles to run cycle detection, we run detection on every invocation. If any cycles are
detected, they are displayed, an exception is thrown, and the current invocation is aborted.

Should the user want to run Phake without cycle detection, they can specify the -u/--unsafe CLI option.
  • Loading branch information
denzel-morris committed Jul 10, 2014
1 parent 499a67a commit b13cd76
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 16 deletions.
1 change: 1 addition & 0 deletions lib/includes.php
Expand Up @@ -12,5 +12,6 @@
require_once __DIR__ . '/phake/Node.php';
require_once __DIR__ . '/phake/OptionParser.php';
require_once __DIR__ . '/phake/TaskCollisionException.php';
require_once __DIR__ . '/phake/TaskCycleFoundException.php';
require_once __DIR__ . '/phake/TaskNotFoundException.php';
require_once __DIR__ . '/phake/Utils.php';
40 changes: 24 additions & 16 deletions lib/phake/Bin.php
Expand Up @@ -7,6 +7,7 @@
use phake\Utils;
use phake\TaskNotFoundException;
use phake\CycleDetector;
use phake\TaskCycleFoundException;
use Exception;

class Bin
Expand All @@ -21,6 +22,7 @@ public function execute($args) {
$task_names = array('default');
$trace = false;
$runfile = false;
$run_safely = true;

array_shift($args);
$parser = new OptionParser($args);
Expand All @@ -38,9 +40,9 @@ public function execute($args) {
case 'file':
$runfile = $value;
break;
case 'C':
case 'cycles':
$action = 'detect_cycles';
case 'u':
case 'unsafe':
$run_safely = false;
break;
default:
throw new Exception("Unknown command line option '$option'");
Expand Down Expand Up @@ -85,6 +87,13 @@ public function execute($args) {
$application->set_args($cli_args);
$application->reset();

if ($run_safely) {
$does_cycle = $this->detect_and_display_cycles($application);
if ($does_cycle) {
throw new TaskCycleFoundException;
}
}

switch ($action) {
case 'list':
$task_list = $application->get_task_list();
Expand All @@ -100,8 +109,6 @@ public function execute($args) {
$application->invoke($task_name);
}
break;
case 'detect_cycles':
$this->detect_cycles($application);
}

} catch (TaskNotFoundException $tnfe) {
Expand All @@ -111,20 +118,21 @@ public function execute($args) {
}
}

private function detect_cycles($application) {
private function detect_and_display_cycles($application) {
$cycles = (new CycleDetector($application->root()))->get_cycles();
if (empty($cycles)) {
echo "No task cycles found.\n";
} else {
$num_cycles = count($cycles);
$pluralized_cycle_label = ($num_cycles > 1 ? 'cycles' : 'cycle');
echo "$num_cycles $pluralized_cycle_label found:\n";
foreach ($cycles as $cycle) {
$task_names = array_map(function ($task) { return $task->get_name(); }, $cycle);
echo '>> ' . implode(', ', $task_names) . "\n";
}
echo "\nTo ensure proper execution of tasks, please untangle these cyclic dependencies\n";
return false;
}

$num_cycles = count($cycles);
$pluralized_cycle_label = ($num_cycles > 1 ? 'cycles' : 'cycle');
echo "$num_cycles $pluralized_cycle_label found:\n";
foreach ($cycles as $cycle) {
$task_names = array_map(function ($task) { return $task->get_name(); }, $cycle);
echo '>> ' . implode(', ', $task_names) . "\n";
}
echo "\nTo ensure proper execution of tasks, please untangle these cyclic dependencies\n";
return true;
}

private function fatal($exception, $message = null, $trace = false) {
Expand Down
5 changes: 5 additions & 0 deletions lib/phake/TaskCycleFoundException.php
@@ -0,0 +1,5 @@
<?php

namespace phake;

class TaskCycleFoundException extends \Exception {};

0 comments on commit b13cd76

Please sign in to comment.