Skip to content

Commit

Permalink
feat: handle install command errors
Browse files Browse the repository at this point in the history
  • Loading branch information
kucaahbe committed Jan 29, 2024
1 parent 5464dc1 commit f2c6bee
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- better error messages for `myrc install`

## [0.1.0] - 2024-01-24

### Added
Expand All @@ -15,3 +17,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- experimental CLI output
- symlinking functionality
- selected [SDL](https://sdlang.org/) format for install file (`install.sdl`)

[unreleased]: https://github.com/kucaahbe/myrc.d/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/kucaahbe/myrc.d/releases/tag/v0.1.0
18 changes: 13 additions & 5 deletions source/cli.d
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,19 @@ void cli_install(ref Config app_config)
output ~= " -> ";
output ~= symlink.source.absolute;
} else {
string backup = symlink.link();
output ~= " -> ";
output ~= symlink.source.absolute;
if (backup)
output ~= " (backup: " ~ backup ~ ")";
import std.file: FileException;
try
{
string backup = symlink.link();
output ~= " -> ";
output ~= symlink.source.absolute;
if (backup)
output ~= " (backup: " ~ backup ~ ")";
}
catch (FileException e)
{
output ~= " # error: " ~ e.msg;
}
}
output ~= "\n";
}
Expand Down
20 changes: 19 additions & 1 deletion source/path.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import std.array;
import std.path: expandTilde, absolutePath, asNormalizedPath;
import std.path: expandTilde, absolutePath, asNormalizedPath, dirName;
import std.file: exists, isDir, isSymlink;

/** represent path in a file system */
Expand Down Expand Up @@ -69,6 +69,24 @@ struct Path
assert(path.exists);
}

/** Returns: [Path] representing _parent folder
*/
Path parent() inout
{
return Path(absolute.dirName);
}

/// returns parent folder as [Path]
unittest
{
import std.file;

immutable auto cwd = getcwd();

immutable auto path = Path(".test/app/source");
assert(path.parent.absolute == cwd ~ '/' ~ ".test/app");
}

/** Returns: true if [Path] is a directory in a file system */
bool isDir() inout
{
Expand Down
103 changes: 101 additions & 2 deletions source/symlink.d
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ struct Symlink {
*/
string link()
{
if (!source.exists)
throw new FileException(source.absolute, "file or directory does not exist");

auto parentDir = destination.parent;

if (!parentDir.exists)
throw new FileException(parentDir.absolute, "directory does not exist");

if (!parentDir.isDir)
throw new FileException(parentDir.absolute, "not a directory");

string backupPath;

if (destination.exists)
Expand All @@ -94,15 +105,16 @@ struct Symlink {
{
import std.file;
import std.path;
import test_file;

if (".test".exists) ".test".rmdirRecurse;
scope(exit) if (".test".exists) ".test".rmdirRecurse;

auto srcPath = ".test/app/source";
auto destPath = ".test/home/destination";

srcPath.dirName.mkdirRecurse;
destPath.dirName.mkdirRecurse;
TestFile(srcPath, "content").create;
TestFile(destPath).create;

auto link = Symlink(srcPath, destPath);
link.link();
Expand Down Expand Up @@ -140,6 +152,93 @@ struct Symlink {
assert(backup == destPathBackup, backup ~ "!=" ~ destPathBackup);
}

/** **fail case**: destination does not exist
* (raises [FileException] with corresponding message)
*/
unittest
{
import std.file;
import std.path;
import test_file;
import std.exception: collectExceptionMsg;

if (".test".exists) ".test".rmdirRecurse;
scope(exit) if (".test".exists) ".test".rmdirRecurse;

immutable auto cwd = getcwd();
auto srcPath = ".test/app/source";
auto destPath = ".test/home/destination";

TestFile(srcPath, "content").create;
// only create .test/
TestFile(destPath.dirName).create;
assert(destPath.dirName.dirName.isDir);

auto link = Symlink(srcPath, destPath);

immutable auto exceptionMsg = collectExceptionMsg!FileException(link.link);
immutable auto expectedExceptionMsg = cwd ~ "/.test/home" ~ ": directory does not exist";

assert(exceptionMsg == expectedExceptionMsg, exceptionMsg ~ " != " ~ expectedExceptionMsg);
}

/** **fail case**: destination is not a directory
* (raises [FileException] with corresponding message)
*/
unittest
{
import std.file;
import std.path;
import test_file;
import std.exception: collectExceptionMsg;

if (".test".exists) ".test".rmdirRecurse;
scope(exit) if (".test".exists) ".test".rmdirRecurse;

auto srcPath = ".test/app/source";
auto destPath = ".test/home/destination";
immutable auto cwd = getcwd();

TestFile(srcPath, "src content").create;
// destination directory is a file
TestFile(destPath.dirName, "dest content").create;

auto link = Symlink(srcPath, destPath);

immutable auto exceptionMsg = collectExceptionMsg!FileException(link.link);
immutable auto expectedExceptionMsg = cwd ~ '/' ~ destPath.dirName ~ ": not a directory";

assert(exceptionMsg == expectedExceptionMsg, exceptionMsg ~ " != " ~ expectedExceptionMsg);
}

/** **fail case**: source does not exist
* (raises [FileException] with corresponding message)
*/
unittest
{
import std.file;
import std.path;
import test_file;
import std.exception: collectExceptionMsg;

if (".test".exists) ".test".rmdirRecurse;
scope(exit) if (".test".exists) ".test".rmdirRecurse;

auto srcPath = ".test/app/source";
auto destPath = ".test/home/destination";
immutable auto cwd = getcwd();

TestFile(destPath).create;
assert(destPath.dirName.isDir);

auto link = Symlink(srcPath, destPath);

immutable auto exceptionMsg = collectExceptionMsg!FileException(link.link);
immutable auto expectedExceptionMsg = cwd ~ "/.test/app/source" ~ ": file or directory does not exist";

assert(exceptionMsg == expectedExceptionMsg, exceptionMsg ~ " != " ~ expectedExceptionMsg);
}

/** Returns: _actual [Path] of the destination */
Path actual() const
{
Expand Down

0 comments on commit f2c6bee

Please sign in to comment.