Skip to content

Commit

Permalink
Added osfamily attribute to ExecTask (#755)
Browse files Browse the repository at this point in the history
  • Loading branch information
siad007 authored and mrook committed Oct 19, 2017
1 parent 54824d4 commit 57b5e3b
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 52 deletions.
117 changes: 78 additions & 39 deletions classes/phing/tasks/system/ExecTask.php
Expand Up @@ -131,6 +131,8 @@ class ExecTask extends Task
*/
protected $checkreturn = false;

private $osFamily;

/**
*
*/
Expand All @@ -146,7 +148,7 @@ public function __construct()
*/
public function main()
{
if (!$this->isApplicable()) {
if (!$this->isValidOs()) {
return;
}

Expand All @@ -156,38 +158,6 @@ public function main()
$this->cleanup($return, $output);
}

/**
* Checks whether the command shall be executed
*
* @return boolean False if the exec command shall not be run
*/
protected function isApplicable()
{
if ($this->os === null) {
return true;
}

$myos = Phing::getProperty('os.name');
$this->log('Myos = ' . $myos, Project::MSG_VERBOSE);

if (strpos($this->os, $myos) !== false) {
// this command will be executed only on the specified OS
// OS matches
return true;
}

$this->log(
sprintf(
'Operating system %s not found in %s',
$myos,
$this->os
),
Project::MSG_VERBOSE
);

return false;
}

/**
* Prepares the command building and execution, i.e.
* changes to the specified directory.
Expand All @@ -202,9 +172,15 @@ protected function prepare()
}

// expand any symbolic links first
if (!$this->dir->getCanonicalFile()->isDirectory()) {
try {
if (!$this->dir->getCanonicalFile()->isDirectory()) {
throw new BuildException(
"'" . (string) $this->dir . "' is not a valid directory"
);
}
} catch (IOException $e) {
throw new BuildException(
"'" . (string) $this->dir . "' is not a valid directory"
"'" . (string) $this->dir . "' is not a readable directory"
);
}
$this->currdir = getcwd();
Expand Down Expand Up @@ -420,6 +396,31 @@ public function setOs($os)
$this->os = (string) $os;
}

/**
* List of operating systems on which the command may be executed.
*/
public function getOs()
{
return $this->os;
}

/**
* Restrict this execution to a single OS Family
* @param string $osFamily the family to restrict to.
*/
public function setOsFamily($osFamily)
{
$this->osFamily = strtolower($osFamily);
}

/**
* Restrict this execution to a single OS Family
*/
public function getOsFamily()
{
return $this->osFamily;
}

/**
* File to which output should be written.
*
Expand Down Expand Up @@ -453,7 +454,7 @@ public function setError(PhingFile $f)
*/
public function setPassthru($passthru)
{
$this->passthru = (bool) $passthru;
$this->passthru = $passthru;
}

/**
Expand All @@ -465,7 +466,7 @@ public function setPassthru($passthru)
*/
public function setLogoutput($logOutput)
{
$this->logOutput = (bool) $logOutput;
$this->logOutput = $logOutput;
}

/**
Expand All @@ -477,7 +478,7 @@ public function setLogoutput($logOutput)
*/
public function setSpawn($spawn)
{
$this->spawn = (bool) $spawn;
$this->spawn = $spawn;
}

/**
Expand All @@ -489,7 +490,7 @@ public function setSpawn($spawn)
*/
public function setCheckreturn($checkreturn)
{
$this->checkreturn = (bool) $checkreturn;
$this->checkreturn = $checkreturn;
}

/**
Expand Down Expand Up @@ -558,4 +559,42 @@ public function createArg()
{
return $this->commandline->createArgument();
}

/**
* Is this the OS the user wanted?
* @return boolean.
* <ul>
* <li>
* <li><code>true</code> if the os and osfamily attributes are null.</li>
* <li><code>true</code> if osfamily is set, and the os family and must match
* that of the current OS, according to the logic of
* {@link Os#isOs(String, String, String, String)}, and the result of the
* <code>os</code> attribute must also evaluate true.
* </li>
* <li>
* <code>true</code> if os is set, and the system.property os.name
* is found in the os attribute,</li>
* <li><code>false</code> otherwise.</li>
* </ul>
*/
protected function isValidOs()
{
//hand osfamily off to Os class, if set
if ($this->osFamily !== null && !OsCondition::isFamily($this->osFamily)) {
return false;
}
//the Exec OS check is different from Os.isOs(), which
//probes for a specific OS. Instead it searches the os field
//for the current os.name
$myos = Phing::getProperty("os.name");
$this->log("Current OS is " . $myos, Project::MSG_VERBOSE);
if (($this->os !== null) && (strpos($this->os, $myos) === false)) {
// this command will be executed only on the specified OS
$this->log("This OS, " . $myos
. " was not found in the specified list of valid OSes: " . $this->os,
Project::MSG_VERBOSE);
return false;
}
return true;
}
}
34 changes: 27 additions & 7 deletions classes/phing/tasks/system/condition/OsCondition.php
Expand Up @@ -41,20 +41,40 @@ public function setFamily($f)
$this->family = strtolower($f);
}

public function evaluate()
{
return self::isOS($this->family);
}

/**
* Determines if the OS on which Ant is executing matches the
* given OS family.
* @param string $family the family to check for
* @return true if the OS matches
*/
public static function isFamily($family)
{
return self::isOS($family);
}

/**
* @param string $family
* @return bool
* @throws BuildException
*/
public function evaluate()
public static function isOS($family)
{
$osName = strtolower(Phing::getProperty("os.name"));

if ($this->family !== null) {
if ($this->family === "windows") {
if ($family !== null) {
if ($family === "windows") {
return StringHelper::startsWith("win", $osName);
} elseif ($this->family === "mac") {
}

if ($family === "mac") {
return (strpos($osName, "mac") !== false || strpos($osName, "darwin") !== false);
} elseif ($this->family === ("unix")) {
}

if ($family === ("unix")) {
return (
StringHelper::endsWith("ix", $osName) ||
StringHelper::endsWith("ux", $osName) ||
Expand All @@ -63,7 +83,7 @@ public function evaluate()
StringHelper::startsWith("darwin", $osName)
);
}
throw new BuildException("Don't know how to detect os family '" . $this->family . "'");
throw new BuildException("Don't know how to detect os family '" . $family . "'");
}

return false;
Expand Down
7 changes: 7 additions & 0 deletions docs/docbook5/en/source/appendixes/coretasks.xml
Expand Up @@ -1696,6 +1696,13 @@ verbose="true" failonerror="false" /></programlisting>
<entry>n/a</entry>
<entry>No</entry>
</row>
<row>
<entry><literal>osfamily</literal></entry>
<entry><literal role="type">String</literal></entry>
<entry>OS family as used in the &lt;os> condition.</entry>
<entry>n/a</entry>
<entry>No</entry>
</row>
<row>
<entry><literal>escape</literal></entry>
<entry><literal role="type">Boolean</literal></entry>
Expand Down
20 changes: 15 additions & 5 deletions etc/phing-grammar.rng
Expand Up @@ -1096,12 +1096,12 @@
</choice>
</oneOrMore>
<optional>
<attribute name="passthru">
<attribute name="passthru" a:defaultValue="false">
<data type="boolean"/>
</attribute>
</optional>
<optional>
<attribute name="checkreturn">
<attribute name="checkreturn" a:defaultValue="false">
<data type="boolean"/>
</attribute>
</optional>
Expand All @@ -1112,12 +1112,15 @@
<attribute name="os"/>
</optional>
<optional>
<attribute name="escape">
<attribute name="osfamily"/>
</optional>
<optional>
<attribute name="escape" a:defaultValue="false">
<data type="boolean"/>
</attribute>
</optional>
<optional>
<attribute name="spawn">
<attribute name="spawn" a:defaultValue="false">
<data type="boolean"/>
</attribute>
</optional>
Expand All @@ -1128,7 +1131,7 @@
<attribute name="outputProperty"/>
</optional>
<optional>
<attribute name="logoutput"/>
<attribute name="logoutput" a:defaultValue="false"/>
</optional>
<optional>
<attribute name="output"/>
Expand Down Expand Up @@ -6511,9 +6514,16 @@
<ref name="available_cond"/>
<ref name="http"/>
<ref name="matches_cond"/>
<ref name="os_cond"/>
</choice>
</define>

<define name="os_cond">
<element name="os">
<attribute name="family"/>
</element>
</define>

<define name="or">
<element name="or">
<oneOrMore>
Expand Down
13 changes: 12 additions & 1 deletion test/classes/phing/tasks/system/ExecTaskTest.php
Expand Up @@ -212,19 +212,30 @@ public function testPropertySetLevelUnknown()
public function testDoNotExecuteOnWrongOs()
{
$this->executeTarget(__FUNCTION__);
$this->assertInLogs('Not found in unknownos');
$this->assertInLogs('not found in the specified list of valid OSes: unknownos');
$this->assertNotContains(
'this should not be executed',
$this->getOutput()
);
}

public function testDoNotExecuteOnWrongOsFamily()
{
$this->expectBuildException(__FUNCTION__, "Don't know how to detect os family 'unknownos'");
}

public function testExecuteOnCorrectOs()
{
$this->executeTarget(__FUNCTION__);
$this->assertInLogs('this should be executed');
}

public function testExecuteOnCorrectOsFamily()
{
$this->executeTarget(__FUNCTION__);
$this->assertInLogs('this should be executed');
}

public function testFailOnNonExistingDir()
{
try {
Expand Down
29 changes: 29 additions & 0 deletions test/etc/tasks/system/ExecTest.xml
Expand Up @@ -76,11 +76,40 @@
<exec command="echo 'this should not be executed'" os="unknownos"/>
</target>

<target name="testDoNotExecuteOnWrongOsFamily">
<exec command="echo 'this should not be executed'" osfamily="unknownos"/>
</target>

<target name="testExecuteOnCorrectOs">
<exec command="echo 'this should be executed'"
os="WINNT WIN32 Linux Darwin BSD" />
</target>

<target name="testExecuteOnCorrectOsFamily">

<if>
<os family="Unix"/>
<then>
<property name="current" value="unix"/>
</then>
<elseif>
<os family="windows"/>
<then>
<property name="current" value="windows"/>
</then>
</elseif>
<elseif>
<os family="mac"/>
<then>
<property name="current" value="mac"/>
</then>
</elseif>
</if>

<exec command="echo 'this should be executed'"
osfamily="unix" />
</target>

<target name="testFailOnNonExistingDir">
<exec command="echo 'foo'" dir="/this/dir/does/not/exist"/>
</target>
Expand Down

0 comments on commit 57b5e3b

Please sign in to comment.