Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
MartkCz committed Mar 27, 2022
0 parents commit 576b558
Show file tree
Hide file tree
Showing 8 changed files with 401 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## IDE
.idea

## composer
composer.lock
vendor
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
phpstan:
vendor/bin/phpstan analyse
14 changes: 14 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "utilitte/console",
"require": {
"php": ">= 8.1",
"phpstan/phpstan": "^1.5",
"nette/utils": "^3.2",
"utilitte/asserts": "^1.2"
},
"autoload": {
"psr-4": {
"Utilitte\\Console\\": "src"
}
}
}
5 changes: 5 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
parameters:
level: 9
paths:
- src
editorUrl: 'file://%%file%%'
63 changes: 63 additions & 0 deletions src/CommandLine.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php declare(strict_types = 1);

namespace Utilitte\Console;

use LogicException;

final class CommandLine
{

private static string $currentDir;

public static function passthru(string $command, ?string $workingDir = null): int
{
if ($workingDir) {
$command = sprintf('cd "%s" && %s', $workingDir, $command);
}

passthru($command, $result);

return $result;
}

/**
* @param string $command
* @param bool $silent
* @return string[]
*/
public static function command(string $command, bool $silent = false): array
{
if ($silent) {
$state = exec($command, $output, $return);
} else {
$state = system($command, $return);
$output[0] = $state;
}

if ($state === false) {
throw new LogicException("Command $command errored");
}

if ($return !== 0) {
throw new LogicException("Command $command exited with code $return", 1);
}

return $output;
}

public static function getCwd(): string
{
if (!isset(self::$currentDir)) {
$working = getcwd();

if ($working === false) {
throw new LogicException('Cannot get current working dir.');
}

self::$currentDir = $working;
}

return self::$currentDir;
}

}
107 changes: 107 additions & 0 deletions src/ComposerFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php declare(strict_types = 1);

namespace Utilitte\Console;

use InvalidArgumentException;
use LogicException;
use Nette\Utils\FileSystem;
use Nette\Utils\Json;
use Nette\Utils\JsonException;
use Utilitte\Asserts\TypeAssert;

final class ComposerFile
{

private string $file;

/** @var mixed[] */
private array $contents;

public function __construct(private string $directory)
{
$file = $directory . '/composer.json';

if (!file_exists($file)) {
throw new InvalidArgumentException(sprintf('Composer file %s does not exist.', $file));
}

$this->file = $file;

try {
$this->contents = (array) Json::decode(FileSystem::read($file), Json::FORCE_ARRAY);
} catch (JsonException $e) {
throw new InvalidArgumentException(sprintf('Composer file %s is not a valid json.', $file), previous: $e);
}
}

public function getName(): string
{
return TypeAssert::string($this->getSection('name'));
}

/**
* @return array<string, string>
*/
public function getRequire(): array
{
/** @var array<string, string> $require */
$require = $this->getSectionWithDefault('require', []);

return $require;
}

/**
* @return array<string, string>
*/
public function getDevRequire(): array
{
/** @var array<string, string> $require */
$require = $this->getSectionWithDefault('dev-require', []);

return $require;
}

/**
* @return array<string, string>
*/
public function getLibraries(): array
{
$libs = [];
foreach (array_merge($this->getRequire(), $this->getDevRequire()) as $name => $version) {
if (!str_contains($name, '/')) {
continue;
}

$libs[$name] = $version;
}

return $libs;
}

public function getLibraryPath(string $name): string
{
return $this->directory . '/vendor/' . $name;
}

private function getSection(string $section): mixed
{
return $this->contents[$section]
??
throw new LogicException(sprintf('Composer file %s does not have section %s.', $this->file, $section));
}

private function getSectionWithDefault(string $section, mixed $default): mixed
{
return $this->contents[$section] ?? $default;
}

public static function getParsedFileNullable(string $directory): ?self
{
try {
return new self($directory);
} catch (InvalidArgumentException) {
return null;
}
}

}
60 changes: 60 additions & 0 deletions src/Git.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php declare(strict_types = 1);

namespace Utilitte\Console;

use LogicException;

final class Git
{

public function __construct(
private string $directory,
)
{
}

public function isGitDirectory(): bool
{
return is_dir($this->directory . '/.git');
}

public function hasUncommittedFiles(): bool
{
$this->validate();

return (bool) $this->command('git status -s');
}

/**
* @return string[]
*/
public function getUncommitedFiles(): array
{
return $this->command('git status -s');
}

public function hasUnpushedCommits(): bool
{
$this->validate();

$return = $this->command('git status -s -b');

return str_contains($return[0], '[ahead');
}

/**
* @return string[]
*/
private function command(string $command): array
{
return CommandLine::command(sprintf('cd "%s" && %s', $this->directory, $command), true);
}

private function validate(): void
{
if (!$this->isGitDirectory()) {
throw new LogicException(sprintf('Directory %s, is not a git directory.', $this->directory));
}
}

}
Loading

0 comments on commit 576b558

Please sign in to comment.