Skip to content

Commit

Permalink
Merge pull request #6 from boite/develop
Browse files Browse the repository at this point in the history
Add fs:setline command
  • Loading branch information
joostfaassen committed Sep 7, 2016
2 parents 1fe348a + 87c4d0e commit 09b4303
Show file tree
Hide file tree
Showing 28 changed files with 2,637 additions and 1,164 deletions.
12 changes: 6 additions & 6 deletions src/Command/FsMountCommand.php
Expand Up @@ -10,23 +10,23 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

use Droid\Plugin\Fs\Model\File\FileFactory;
use Droid\Plugin\Fs\Model\FsMount;
use Droid\Plugin\Fs\Model\Fstab\FstabBuilder;
use Droid\Plugin\Fs\Model\Fstab\FstabException;

class FsMountCommand extends Command
{
use CheckableTrait;

protected $fstabBuilder;
protected $fileFactory;
protected $fsMount;

public function __construct(
FstabBuilder $fstabBuilder,
FileFactory $fileFactory,
FsMount $fsMount,
$name = null
) {
$this->fstabBuilder = $fstabBuilder;
$this->fileFactory = $fileFactory;
$this->fsMount = $fsMount;
return parent::__construct($name);
}
Expand Down Expand Up @@ -91,8 +91,8 @@ public function execute(InputInterface $input, OutputInterface $output)
$this->activateCheckMode($input);

$fstab = $this
->fstabBuilder
->buildFstab($input->getOption('fstab'))
->fileFactory
->makeFile($input->getOption('fstab'))
;
try {
$fstab->addEntry(
Expand Down
144 changes: 144 additions & 0 deletions src/Command/FsSetlineCommand.php
@@ -0,0 +1,144 @@
<?php
namespace Droid\Plugin\Fs\Command;

use RuntimeException;

use Droid\Lib\Plugin\Command\CheckableTrait;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

use Droid\Plugin\Fs\Model\File\FileFactory;
use Droid\Plugin\Fs\Model\File\NameValueLine;
use Droid\Plugin\Fs\Model\File\UnusableFileException;

class FsSetlineCommand extends Command
{
use CheckableTrait;

protected $fileFactory;

public function __construct(
FileFactory $fileFactory,
$name = null
) {
$this->fileFactory = $fileFactory;
return parent::__construct($name);
}

public function configure()
{
$this->setName('fs:setline')
->setDescription('Add a (name, value) pair to a line based file, or update an existing (name, value) pair.')
->addArgument(
'file',
InputArgument::REQUIRED,
'The path to a line based file'
)
->addArgument(
'option-name',
InputArgument::REQUIRED,
'The name in a (name, value) pair'
)
->addArgument(
'option-value',
InputArgument::REQUIRED,
'The value in a (name, value) pair'
)
->addOption(
'--separator',
's',
InputOption::VALUE_REQUIRED,
'Characters which separate the name from the value in a (name, value) pair.'
)
;
$this->configureCheckMode();
}

public function execute(InputInterface $input, OutputInterface $output)
{
$this->activateCheckMode($input);

if (! file_exists($input->getArgument('file'))) {
throw new RuntimeException(
sprintf('The file "%s" does not exist.', $input->getArgument('file'))
);
}

if ($input->getOption('separator')) {
$this
->fileFactory
->getLineFactory()
->setFieldSeparator($input->getOption('separator'))
;
}

$file = $this->fileFactory->makeFile($input->getArgument('file'));
$line = $this->fileFactory->getLineFactory()->makeLine();

$line
->setFieldValue(
NameValueLine::FIELD_NAME,
$input->getArgument('option-name')
)
->setFieldValue(
NameValueLine::FIELD_VALUE,
$input->getArgument('option-value')
)
;

try {
$file->setLine($line);
} catch (UnusableFileException $e) {
throw new RuntimeException(
'I cannot set a line in the file',
null,
$e
);
}

if (! $file->changed()) {
$output->WriteLn(
sprintf(
'I am not making any changes to the file "%s"; it already has the line "%s%s%s".',
$input->getArgument('file'),
$input->getArgument('option-name'),
$this->fileFactory->getLineFactory()->getFieldSeparator(),
$input->getArgument('option-value')
)
);
$this->reportChange($output);
return 0;
} elseif ($this->checkMode()) {
$this->markChange();
$output->WriteLn(
sprintf(
'I would make a change to the file "%s".',
$input->getArgument('file')
)
);
$this->reportChange($output);
return 0;
}

$this->markChange();
$output->WriteLn(
sprintf(
'I am making your changes to the file "%s".',
$input->getArgument('file')
)
);
$file
->backup($this->backupName($input->getArgument('file')))
->finish()
;
$this->reportChange($output);
}

private function backupName($originalName)
{
return sprintf('%s.%s.backup', $originalName, date('Y-m-d_H-i-s'));
}
}
20 changes: 16 additions & 4 deletions src/DroidPlugin.php
Expand Up @@ -5,9 +5,15 @@
use Symfony\Component\Process\ProcessBuilder;

use Droid\Plugin\Fs\Command\FsChownCommand;
use Droid\Plugin\Fs\Command\FsMountCommand;
use Droid\Plugin\Fs\Command\FsSetlineCommand;
use Droid\Plugin\Fs\Model\File\FileFactory;
use Droid\Plugin\Fs\Model\File\LineBasedFile;
use Droid\Plugin\Fs\Model\File\LineFactory;
use Droid\Plugin\Fs\Model\File\NameValueLine;
use Droid\Plugin\Fs\Model\FsMount;
use Droid\Plugin\Fs\Model\Fstab\FstabBuilder;
use Droid\Plugin\Fs\Model\Fstab\FstabLineFactory;
use Droid\Plugin\Fs\Model\Fstab\Fstab;
use Droid\Plugin\Fs\Model\Fstab\FstabLine;
use Droid\Plugin\Fs\Service\PosixAclObjectLookup;

class DroidPlugin
Expand All @@ -28,11 +34,17 @@ public function getCommands()
);
$commands[] = new \Droid\Plugin\Fs\Command\FsCopyCommand();
$commands[] = new \Droid\Plugin\Fs\Command\FsMkdirCommand();
$commands[] = new \Droid\Plugin\Fs\Command\FsMountCommand(
new FstabBuilder(new FstabLineFactory),
$commands[] = new FsMountCommand(
new FileFactory(Fstab::class, new LineFactory(FstabLine::class)),
new FsMount(new ProcessBuilder)
);
$commands[] = new \Droid\Plugin\Fs\Command\FsRenameCommand();
$commands[] = new FsSetlineCommand(
new FileFactory(
LineBasedFile::class,
new LineFactory(NameValueLine::class)
)
);
$commands[] = new \Droid\Plugin\Fs\Command\FsTemplateCommand();
$commands[] = new \Droid\Plugin\Fs\Command\FsTouchCommand();
return $commands;
Expand Down
113 changes: 113 additions & 0 deletions src/Model/File/AbstractLine.php
@@ -0,0 +1,113 @@
<?php

namespace Droid\Plugin\Fs\Model\File;

abstract class AbstractLine implements LineInterface
{
protected $fieldSeparator = ' ';
protected $givenValues = array();
protected $originalLine;
protected $originalValues = array();

public function set($content)
{
$this->originalLine = $content;

if (trim($this->originalLine, " \t") == ''
|| substr($this->originalLine, 0, 1) == '#'
) {
return $this;
}

$this->originalValues = $this->parse($this->originalLine);

return $this;
}

public function setFieldValue($fieldName, $value)
{
if (isset($this->originalValues[$fieldName])
&& $this->originalValues[$fieldName] === $value
) {
# the given value is the same as the original value; ignore any given value
unset($this->givenValues[$fieldName]);
} else {
$this->givenValues[$fieldName] = $value;
}
return $this;
}

public function getFieldValue($fieldName)
{
if (array_key_exists($fieldName, $this->givenValues)) {
return $this->givenValues[$fieldName];
}
if (array_key_exists($fieldName, $this->originalValues)) {
return $this->originalValues[$fieldName];
}
return null;
}

public function isData()
{
return (bool) sizeof($this->originalValues);
}

public function changed()
{
if (empty($this->originalValues)) {
return false;
}
return (bool) sizeof($this->givenValues);
}

public function update(LineInterface $line)
{
foreach ($this->givenValues as $fieldName => $value) {
$line->setFieldValue($fieldName, $value);
}
return $this;
}

public function format($values)
{
return implode($this->fieldSeparator, $values);
}

public function setFieldSeparator($separator)
{
$this->fieldSeparator = $separator;

return $this;
}

abstract public function getMappingValues();

public function __toString()
{
if ($this->originalValues && $this->givenValues) {
# an updated line
return $this->format(
array_values(
array_replace($this->originalValues, $this->givenValues)
)
);
} elseif ($this->originalValues || $this->originalLine) {
# an unchanged line
return $this->originalLine;
} elseif ($this->givenValues) {
# a new line
return $this->format(array_values($this->givenValues));
}
return '';
}

/**
* Return a mapping of named fields to parsed values.
*
* @param string $data
*
* @return array
*/
abstract protected function parse($data);
}
30 changes: 30 additions & 0 deletions src/Model/File/FileFactory.php
@@ -0,0 +1,30 @@
<?php

namespace Droid\Plugin\Fs\Model\File;

class FileFactory
{
private $fileClassName;
private $lineFactory;

public function __construct(
$fileClassName,
LineFactory $lineFactory
) {
$this->fileClassName = $fileClassName;
$this->lineFactory = $lineFactory;
}

/**
* @return \Droid\Plugin\Fs\Model\File\LineFactory
*/
public function getLineFactory()
{
return $this->lineFactory;
}

public function makeFile($filename)
{
return new $this->fileClassName($this->lineFactory, $filename);
}
}

0 comments on commit 09b4303

Please sign in to comment.