Skip to content

Commit

Permalink
feat: exec directive
Browse files Browse the repository at this point in the history
  • Loading branch information
kucaahbe committed Feb 13, 2024
1 parent 85c00d4 commit b0d890c
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 22 deletions.
49 changes: 29 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,6 @@

Symlinking CLI tool for dotfiles (or any other configuration files organized in a directory).

## Install

| Operating system | Link |
|---|---|
| Ubuntu 22.04 (Jammy Jellyfish) | [:arrow_upper_right:](https://github.com/kucaahbe/myrc.d/releases/latest) |
| Ubuntu 20.04 (Focal Fossa) | [:arrow_upper_right:](https://github.com/kucaahbe/myrc.d/releases/latest) |
| macOS | [:arrow_upper_right:](https://github.com/kucaahbe/myrc.d/releases/latest) |

### Build

Install [D compiler](https://dlang.org/download.html), `cd` into directory and run `dub`:

```console
dub build --build=release
```

#### Build issues

[documented here](build_issues.md)

## Usage

In the directory from where the app is started, the `install.sdl` manifest file is required: there should be specified
Expand All @@ -30,6 +10,15 @@ folder installation details:
```
# the "install" section is mandatory
install {
# executes specified commands, unless requirements below met
exec "git submodule -q update --init" {
# requirements:
// file should be created in $PWD
creates:file `LS_COLORS/.git`
creates:file `zsh-completions/.git`
creates:file `zsh-syntax-highlighting/.git`
}
ln "bashrc", "~/.bashrc"
ln "bash_profile", "~/.bash_profile"
}
Expand All @@ -50,3 +39,23 @@ me@host:~/doftiles$ myrc
/home/me/dotfiles/bashrc -> /home/me/.bashrc
/home/me/dotfiles/bash_profile -> /home/me/.bash_profile
```

## Install

| Operating system | Link |
|---|---|
| Ubuntu 22.04 (Jammy Jellyfish) | [:arrow_upper_right:](https://github.com/kucaahbe/myrc.d/releases/latest) |
| Ubuntu 20.04 (Focal Fossa) | [:arrow_upper_right:](https://github.com/kucaahbe/myrc.d/releases/latest) |
| macOS | [:arrow_upper_right:](https://github.com/kucaahbe/myrc.d/releases/latest) |

### Build

Install [D compiler](https://dlang.org/download.html), `cd` into directory and run `dub`:

```console
dub build --build=release
```

#### Build issues

[documented here](build_issues.md)
26 changes: 25 additions & 1 deletion source/cli.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import std.file: getcwd;
import std.format: format;
import std.array: split, join;
import std.algorithm.iteration: map, filter;
import std.algorithm.searching: maxElement;
import std.algorithm.searching: all, maxElement;
import std.stdio;
import core.stdc.stdlib;
import std.conv: to;
Expand Down Expand Up @@ -38,6 +39,16 @@ void cli_install(ref Config app_config)
{
string output = getcwd ~ " install:\n";

foreach (command ; app_config.commands) {
if (command.outcomes.length > 0 && command.outcomes.all!(o => o.ok)) {
output ~= "+ `"~command.inspect~"`\n";
} else {
output ~= "exec `"~command.inspect~"...`\n";
command.invoke();
output ~= "# `"~command.output.split('\n').join("\n# ")~"`\n";
}
}

foreach (symlink ; app_config.symlinks) {
if (!symlink.source.exists) {
output ~= "# " ~ symlink.source.absolute ~ ": no such file or directory\n";
Expand Down Expand Up @@ -119,6 +130,19 @@ private void printStatus1(ref Config app_config)

string output = getcwd ~ ":\n";

foreach (command ; app_config.commands) {
if (command.outcomes.all!(o => o.ok)) {
output ~= "+ `"~command.inspect~"`\n";
} else {
output ~= "- `"~command.inspect~"`\n";
foreach (outcome ; command.outcomes) {
if (!outcome.ok) {
output ~= " # " ~ outcome.path.absolute ~ " does not exist\n";
}
}
}
}

foreach (symlink ; app_config.symlinks) {
output ~= symlink.ok ? "+ " : "- ";
output ~= symlink.destination.absolute;
Expand Down
62 changes: 62 additions & 0 deletions source/command.d
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import std.array: join;
import std.process;
import path;

Expand All @@ -22,6 +23,18 @@ class Command {
this.args = args;
}

/** returns string representation of the command
(command name and arguments) */
string inspect() {
return name ~ ' ' ~ args.join(' ');
}

/// string representation of [Command]
unittest {
auto cmd = new Command("echo", ["12", "3"]);
assert(cmd.inspect == "echo 12 3");
}

/** invokes the command */
void invoke() {
scope(exit) run = true;
Expand Down Expand Up @@ -119,4 +132,53 @@ class CommandOutcome
this.type = type;
this.path = path;
}

/** test if outcome criteria is satisfied
* Returns: true if the outcome exists */
bool ok() {
switch (type) {
case File:
return path.isFile;
case Directory:
return path.isDir;
case Symlink:
return path.isSymlink;
default:
return false;
}
}

/// returns true if the outcome exists
unittest {
import std.file;
import std.process;
import std.conv;
import test_file;
import test_dir;

auto testDir = setupTestDir(__FILE__, __LINE__);
scope(exit) removeTestDir(testDir);

auto file = testDir ~ "/file";
auto dir = testDir ~ "/dir";
auto symlink = testDir ~ "/symlink";

auto path = Path(file);
auto outcome = new CommandOutcome(CommandOutcome.File, path);
assert(!outcome.ok);
TestFile(file, "content").create();
assert(outcome.ok);

path = Path(dir);
outcome = new CommandOutcome(CommandOutcome.Directory, path);
assert(!outcome.ok);
dir.mkdir;
assert(outcome.ok);

path = Path(symlink);
outcome = new CommandOutcome(CommandOutcome.Symlink, path);
assert(!outcome.ok);
file.symlink(symlink);
assert(outcome.ok);
}
}
48 changes: 47 additions & 1 deletion source/path.d
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import std.array;
import std.path: expandTilde, absolutePath, asNormalizedPath, dirName;
import std.file: exists, isDir, isSymlink;
import std.file: exists, isFile, isDir, isSymlink;

/** represent path in a file system */
struct Path
Expand Down Expand Up @@ -88,6 +88,52 @@ struct Path
assert(path.parent.absolute == cwd ~ '/' ~ ".test/app");
}

/** Returns: true if [Path] is a regular file in a file system */
bool isFile() inout
{
return exists && absolute.isFile;
}

/// returns true if [absolute] exists and is a file
unittest
{
import std.file;
import std.process;
import test_file;
import test_dir;

auto testDir = setupTestDir(__FILE__, __LINE__);
scope(exit) removeTestDir(testDir);

immutable auto file_path = testDir ~ "/file";

const auto path = Path(file_path);
assert(!path.isFile);
TestFile(file_path, "content").create;
assert(path.isFile);
}

/// returns true if [absolute] exists and is a file
unittest
{
import std.file;
import std.process;
import test_file;
import test_dir;

auto testDir = setupTestDir(__FILE__, __LINE__);
scope(exit) removeTestDir(testDir);

immutable auto file_path = testDir ~ "/file";

const auto path = Path(file_path);
assert(!path.isFile);

TestFile(file_path, "content").create;

assert(path.isFile);
}

/** Returns: true if [Path] is a directory in a file system */
bool isDir() inout
{
Expand Down

0 comments on commit b0d890c

Please sign in to comment.