From 3d1a5e96a0ed84235283c8acd40d3780ff62cbd1 Mon Sep 17 00:00:00 2001 From: siad007 Date: Sun, 30 Oct 2016 18:21:13 +0100 Subject: [PATCH] Added Truncate Task --- classes/phing/tasks/defaults.properties | 1 + classes/phing/tasks/system/TruncateTask.php | 173 ++++++++++++++++++ .../en/source/appendixes/coretasks.xml | 68 +++++++ etc/phing-grammar.rng | 25 +++ .../phing/tasks/system/TruncateTaskTest.php | 105 +++++++++++ test/etc/tasks/system/TruncateTaskTest.xml | 59 ++++++ 6 files changed, 431 insertions(+) create mode 100644 classes/phing/tasks/system/TruncateTask.php create mode 100644 test/classes/phing/tasks/system/TruncateTaskTest.php create mode 100644 test/etc/tasks/system/TruncateTaskTest.xml diff --git a/classes/phing/tasks/defaults.properties b/classes/phing/tasks/defaults.properties index 76e8ec194c..904e2108e5 100644 --- a/classes/phing/tasks/defaults.properties +++ b/classes/phing/tasks/defaults.properties @@ -44,6 +44,7 @@ sleep=phing.tasks.system.SleepTask taskdef=phing.tasks.system.TaskdefTask tempfile=phing.tasks.system.TempFile touch=phing.tasks.system.TouchTask +truncate=phing.tasks.system.TruncateTask tstamp=phing.tasks.system.TstampTask typedef=phing.tasks.system.TypedefTask uptodate=phing.tasks.system.UpToDateTask diff --git a/classes/phing/tasks/system/TruncateTask.php b/classes/phing/tasks/system/TruncateTask.php new file mode 100644 index 0000000000..f44a5471aa --- /dev/null +++ b/classes/phing/tasks/system/TruncateTask.php @@ -0,0 +1,173 @@ +. + */ +include_once 'phing/Task.php'; +include_once 'phing/system/io/PhingFile.php'; +include_once 'phing/BuildException.php'; + +/** + * @author Siad Ardroumli + * @package phing.tasks.system + */ +class TruncateTask extends Task +{ + private $create = true; + private $mkdirs = false; + + private $length; + private $adjust; + private $file; + + /** + * Set a single target File. + * @param PhingFile|string $f the single File + * @throws \IOException + * @throws \NullPointerException + */ + public function setFile($f) + { + if (is_string($f)) { + $f = new PhingFile($f); + } + $this->file = $f; + } + + /** + * Set the amount by which files' lengths should be adjusted. + * It is permissible to append K / M / G / T / P. + * @param $adjust (positive or negative) adjustment amount. + */ + public function setAdjust($adjust) + { + $this->adjust = $adjust; + } + + /** + * Set the length to which files should be set. + * It is permissible to append K / M / G / T / P. + * @param $length (positive) adjustment amount. + * + * @throws \BuildException + */ + public function setLength($length) + { + $this->length = $length; + if ($this->length !== null && $this->length < 0) { + throw new BuildException('Cannot truncate to length ' . $this->length); + } + } + + /** + * Set whether to create nonexistent files. + * @param boolean $create default true. + */ + public function setCreate($create) + { + $this->create = $create; + } + + /** + * Set whether, when creating nonexistent files, nonexistent directories + * should also be created. + * @param boolean $mkdirs default false. + */ + public function setMkdirs($mkdirs) + { + $this->mkdirs = $mkdirs; + } + + /** + * {@inheritDoc}. + * @throws \BuildException + */ + public function main() + { + if ($this->length !== null && $this->adjust !== null) { + throw new BuildException( + 'length and adjust are mutually exclusive options' + ); + } + if ($this->length === null && $this->adjust === null) { + $this->length = 0; + } + if ($this->file === null) { + throw new BuildException('No files specified.'); + } + + if ($this->shouldProcess($this->file)) { + $this->process($this->file); + } + } + + /** + * @param PhingFile $f + * @return bool + * @throws \BuildException + */ + private function shouldProcess(PhingFile $f) + { + if ($f->isFile()) { + return true; + } + if (!$this->create) { + return false; + } + $exception = null; + try { + /** @var PhingFile $parent */ + $parent = $f->getParentFile(); + if ($this->mkdirs && !$parent->exists()) { + $parent->mkdirs(); + } + + if ($f->createNewFile()) { + return true; + } + } catch (IOException $e) { + $exception = $e; + } + $msg = "Unable to create " . $f; + if ($exception === null) { + $this->log($msg, Project::MSG_WARN); + return false; + } + throw new BuildException($msg, $exception); + } + + private function process(PhingFile $f) + { + $len = $f->length(); + $newLength = $this->length === null + ? $len + $this->adjust + : $this->length; + + if ($len === $newLength) { + //nothing to do! + return; + } + + $splFile = new SplFileObject($f->getPath(), 'a+'); + + if (!$splFile->ftruncate((int) $newLength)) { + throw new BuildException("Exception working with " . (string)$splFile); + } + + $splFile->rewind(); + clearstatcache(); + } +} diff --git a/docs/docbook5/en/source/appendixes/coretasks.xml b/docs/docbook5/en/source/appendixes/coretasks.xml index 305959fb37..a628b74a9a 100644 --- a/docs/docbook5/en/source/appendixes/coretasks.xml +++ b/docs/docbook5/en/source/appendixes/coretasks.xml @@ -4045,6 +4045,74 @@ file defines a task in the format: name=path.to.Task --> + + TruncateTask + Set the length of one file, as the intermittently available + truncate Unix utility/function. + + + Attributes + + + + + + + + + Name + Type + Description + Default + Required + + + + + file + String + The name of the file. + n/a + Yes + + + length + Integer + Specifies the new file length (in bytes) to set. + n/a + No + + + adjust + Integer + Specifies the number of bytes (and positive/negative + direction) by which to adjust file lengths. + n/a + No + + + create + Boolean + Whether to create nonexistent files. + true + No + + + mkdirs + Boolean + Whether to create nonexistent parent directories + when creating new files. + false + No + + + +
+ + Examples + <truncate file="foo" /> + +
TryCatchTask This task is a wrapper task that lets you run tasks(s) when another set of tasks fails, diff --git a/etc/phing-grammar.rng b/etc/phing-grammar.rng index 89686a5155..60100ab28f 100644 --- a/etc/phing-grammar.rng +++ b/etc/phing-grammar.rng @@ -255,6 +255,7 @@ + @@ -1698,6 +1699,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/classes/phing/tasks/system/TruncateTaskTest.php b/test/classes/phing/tasks/system/TruncateTaskTest.php new file mode 100644 index 0000000000..aa1ae459b7 --- /dev/null +++ b/test/classes/phing/tasks/system/TruncateTaskTest.php @@ -0,0 +1,105 @@ +. + */ +require_once 'phing/BuildFileTest.php'; + +/** + * Tests the Truncate Task + * + * @author Siad Ardroumli + * @package phing.tasks.system + */ +class TruncateTaskTest extends BuildFileTest +{ + public function setUp() + { + $this->configureProject( + PHING_TEST_BASE + . "/etc/tasks/system/TruncateTaskTest.xml" + ); + $this->executeTarget("setup"); + } + + public function tearDown() + { + $this->executeTarget("clean"); + } + + public function testBasic() + { + $this->executeTarget(__FUNCTION__); + $this->assertSame($this->getProject()->getProperty('test.basic.length'), 0); + } + + public function testExplicit() + { + $this->executeTarget(__FUNCTION__); + $this->assertSame($this->getProject()->getProperty('test.explicit.length'), 1034); + } + + public function testExtend() + { + $this->executeTarget(__FUNCTION__); + $this->assertSame($this->getProject()->getProperty('test.extend.length'), 5); + $this->assertSame($this->getProject()->getProperty('test.extend.adjust.length'), 10); + } + + public function testTruncate() + { + $this->executeTarget(__FUNCTION__); + $this->assertSame($this->getProject()->getProperty('test.truncate.length'), 5); + $this->assertSame($this->getProject()->getProperty('test.truncate.adjust.length'), 0); + } + + public function testNoCreate() + { + $this->executeTarget(__FUNCTION__); + $this->assertFileNotExists($this->getProject()->getProperty('tmp.dir') . '/foo'); + } + + public function testMkdirs() + { + $this->assertFileNotExists($this->getProject()->getProperty('tmp.dir') . '/baz'); + $this->executeTarget(__FUNCTION__); + $this->assertSame($this->getProject()->getProperty('test.mkdirs.length'), 0); + } + + /** + * @expectedException BuildException + */ + public function testInvalidAttrs() + { + $this->executeTarget(__FUNCTION__); + } + + /** + * @expectedException BuildException + */ + public function testBadLength() + { + $this->executeTarget(__FUNCTION__); + } + + /** + * @expectedException BuildException + */ + public function testNoFiles() + { + $this->executeTarget(__FUNCTION__); + } +} diff --git a/test/etc/tasks/system/TruncateTaskTest.xml b/test/etc/tasks/system/TruncateTaskTest.xml new file mode 100644 index 0000000000..54d048d5b2 --- /dev/null +++ b/test/etc/tasks/system/TruncateTaskTest.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file