Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
The initial commit includes the following commands:

- new
- register
- global
- versions

It is very much in a proof-of-concept stage.
  • Loading branch information
Nitemaeric committed Oct 12, 2024
0 parents commit 73cfb6c
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DS_Store

builds
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# drenv - DragonRuby Environment Manager

**drenv** is a cross-platform CLI tool that helps you declutter your DragonRuby
installations.

**drenv** is built with [Deno](https://deno.com) and is inspired by
[rbenv](https://rbenv.org).

## Installation

For now, you can install **drenv** by downloading the binary from this repo's
releases page.

Alternatively, you can clone this repo and build the binary yourself.

```sh
deno compile --allow-read --allow-write --allow-env --output=builds/drenv --target=aarch64-apple-darwin main.ts
```

## Usage

### `drenv help [command]`

This command will display the help message for **drenv**.

Calling `drenv` without any arguments will also display this message.

```
Usage: drenv [options] [command]
CLI to manage DragonRuby environments
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
new <name> Create a new DragonRuby project
register <path> Register a DragonRuby installation
global [version] Get or set the global version of DragonRuby
versions List out all locally installed versions of DragonRuby
help [command] display help for command
```

### `drenv register <path>`

This command will copy a local DragonRuby installation at the specified path
into **drenv**'s home directory.

> [!IMPORTANT]
> You will need to register at least one DragonRuby installation before you can
> use **drenv**.
### `drenv global <version>`

This command sets the version of DragonRuby that **drenv** will use when
creating new projects.

### `drenv new <name>`

This command will create a new DragonRuby project with the specified name.

Under the hood, all **drenv** does is copy the contents of the global DragonRuby
installation into the new project directory.

### `drenv versions`

This command will list out all registered versions of DragonRuby.

```
5.32
* 6.3
```

Tested on MacOS Macbook Pro M1 with DragonRuby 5.32 and 6.3.
48 changes: 48 additions & 0 deletions commands/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { exists } from "jsr:@std/fs";

export class NotInstalled extends Error {
version: string;

constructor(version: string) {
super(`drenv: version '${version}' not installed`);

this.name = "NotInstalled";
this.version = version;
}
}

export class NoGlobalVersion extends Error {
constructor() {
super("drenv: no global version configured");
this.name = "NoGlobalVersion";
}
}

export default async function global(version: string | undefined = undefined) {
if (version) {
return setGlobalVersion(version);
} else {
return getGlobalVersion();
}
}

const setGlobalVersion = async (version: string) => {
if (!await exists(`${Deno.env.get("HOME")}/.drenv/versions/${version}`)) {
throw new NotInstalled(version);
}

return Deno.writeTextFile(
`${Deno.env.get("HOME")}/.drenv/.dragonruby-version`,
version,
);
};

const getGlobalVersion = async () => {
if (!await exists(`${Deno.env.get("HOME")}/.drenv/.dragonruby-version`)) {
throw new NoGlobalVersion();
}

return Deno.readTextFile(
`${Deno.env.get("HOME")}/.drenv/.dragonruby-version`,
);
};
10 changes: 10 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"tasks": {
"dev": "deno run --watch main.ts"
},
"imports": {
"@std/assert": "jsr:@std/assert@1",
"@std/fs": "jsr:@std/fs@^1.0.4",
"commander": "npm:commander@^12.1.0"
}
}
44 changes: 44 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 77 additions & 0 deletions main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Command } from "npm:commander";
import { copy } from "jsr:@std/fs";

import global from "./commands/global.ts";

import { readFirstLine } from "./utils/read-first-line.ts";

const program = new Command();

const actionRunner = (fn: (...args: any[]) => Promise<any>) => {
return (...args: any[]): any =>
fn(...args)
.then(
(value) =>
typeof value === "string" ||
typeof value === "number" && console.log(value),
)
.catch(
(error) => console.error(error.message),
);
};

program
.name("drenv")
.description("CLI to manage DragonRuby environments")
.version("0.1.0");

program.command("new")
.argument("<name>", "Name of the new project")
.description("Create a new DragonRuby project")
.action(async (name) => {
await copy(
`${Deno.env.get("HOME")}/.drenv/versions/${await global()}`,
name,
);
});

program.command("register")
.argument("<path>", "Path to a fresh DragonRuby directory")
.description("Register a DragonRuby installation")
.action(async (path) => {
const content = await readFirstLine(path + "/CHANGELOG-CURR.txt");
const version = content.match(/[0-9\.]+/)?.[0];

await copy(path, `${Deno.env.get("HOME")}/.drenv/versions/${version}`);
});

program.command("global")
.argument("[version]", "Version of DragonRuby to use")
.description("Get or set the global version of DragonRuby")
.action(actionRunner(global));

program.command("versions")
.description("List out all locally installed versions of DragonRuby")
.action(async (options) => {
const directories = await Deno.readDir(
`${Deno.env.get("HOME")}/.drenv/versions/`,
);

let currentVersion;

try {
const content = await readFirstLine("./CHANGELOG-CURR.txt");

currentVersion = content.match(/[0-9\.]+/)?.[0];
} catch (error) {}

for await (const directory of directories) {
if (directory.name == currentVersion) {
console.log("* " + directory.name);
} else {
console.log(" " + directory.name);
}
}
});

program.parse();
15 changes: 15 additions & 0 deletions utils/read-first-line.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const readFirstLine = async (path: string) => {
const file = await Deno.open(path);

const buffer = new Uint8Array(1);
const decoder = new TextDecoder();
let content = "";

while (decoder.decode(buffer) != "\n") {
await file.read(buffer);

content += decoder.decode(buffer);
}

return content;
};

0 comments on commit 73cfb6c

Please sign in to comment.