@repokit/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +11 -0
- package/Cargo.lock +517 -0
- package/Cargo.toml +26 -0
- package/README.md +204 -0
- package/dist/cjs/CommandParser.js +68 -0
- package/dist/cjs/ConfigurationParser.js +46 -0
- package/dist/cjs/RepoKitCommand.js +16 -0
- package/dist/cjs/RepoKitConfig.js +10 -0
- package/dist/cjs/TaskPooler.js +42 -0
- package/dist/cjs/commands/parse_commands.js +15 -0
- package/dist/cjs/commands/parse_configuration.js +15 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/types.js +2 -0
- package/dist/mjs/CommandParser.js +51 -0
- package/dist/mjs/ConfigurationParser.js +31 -0
- package/dist/mjs/RepoKitCommand.js +16 -0
- package/dist/mjs/RepoKitConfig.js +8 -0
- package/dist/mjs/TaskPooler.js +28 -0
- package/dist/mjs/commands/parse_commands.js +4 -0
- package/dist/mjs/commands/parse_configuration.js +4 -0
- package/dist/mjs/index.js +3 -0
- package/dist/mjs/package.json +4 -0
- package/dist/mjs/types.js +1 -0
- package/dist/types/CommandParser.d.ts +5 -0
- package/dist/types/ConfigurationParser.d.ts +4 -0
- package/dist/types/RepoKitCommand.d.ts +14 -0
- package/dist/types/RepoKitConfig.d.ts +6 -0
- package/dist/types/TaskPooler.d.ts +10 -0
- package/dist/types/commands/parse_commands.d.ts +1 -0
- package/dist/types/commands/parse_configuration.d.ts +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/types.d.ts +18 -0
- package/install.sh +43 -0
- package/package.json +40 -0
- package/repokit.ts +36 -0
- package/src/CommandParser.ts +59 -0
- package/src/ConfigurationParser.ts +34 -0
- package/src/RepoKitCommand.ts +24 -0
- package/src/RepoKitConfig.ts +10 -0
- package/src/TaskPooler.ts +31 -0
- package/src/commands/parse_commands.ts +5 -0
- package/src/commands/parse_configuration.ts +5 -0
- package/src/index.ts +3 -0
- package/src/types.ts +22 -0
- package/tsconfig.json +24 -0
- package/workspaces/concurrency/mod.rs +1 -0
- package/workspaces/concurrency/thread_pool.rs +32 -0
- package/workspaces/configuration/configuration.rs +47 -0
- package/workspaces/configuration/configuration_template.ts +23 -0
- package/workspaces/configuration/mod.rs +1 -0
- package/workspaces/executables/external_executable.rs +4 -0
- package/workspaces/executables/intenal_executable.rs +9 -0
- package/workspaces/executables/internal_executable_definition.rs +8 -0
- package/workspaces/executables/mod.rs +3 -0
- package/workspaces/executor/executor.rs +62 -0
- package/workspaces/executor/mod.rs +1 -0
- package/workspaces/external_commands/external_commands.rs +125 -0
- package/workspaces/external_commands/mod.rs +1 -0
- package/workspaces/internal_commands/command_template.ts +24 -0
- package/workspaces/internal_commands/help.rs +146 -0
- package/workspaces/internal_commands/internal_registry.rs +59 -0
- package/workspaces/internal_commands/list_commands.rs +106 -0
- package/workspaces/internal_commands/list_owners.rs +74 -0
- package/workspaces/internal_commands/locate_command.rs +78 -0
- package/workspaces/internal_commands/mod.rs +10 -0
- package/workspaces/internal_commands/onboarder.rs +66 -0
- package/workspaces/internal_commands/register_command.rs +117 -0
- package/workspaces/internal_commands/search_commands.rs +189 -0
- package/workspaces/internal_commands/typescript_command.rs +63 -0
- package/workspaces/internal_commands/upgrade_repokit.rs +76 -0
- package/workspaces/logger/logger.rs +98 -0
- package/workspaces/logger/mod.rs +1 -0
- package/workspaces/main.rs +21 -0
- package/workspaces/repokit/interfaces.rs +41 -0
- package/workspaces/repokit/mod.rs +2 -0
- package/workspaces/repokit/repokit.rs +141 -0
- package/workspaces/validations/command_validations.rs +140 -0
- package/workspaces/validations/mod.rs +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface IRepoKitConfig {
|
|
2
|
+
project: string;
|
|
3
|
+
commands?: Record<string, ICommand>;
|
|
4
|
+
}
|
|
5
|
+
export interface IRepoKitCommand {
|
|
6
|
+
name: string;
|
|
7
|
+
owner?: string;
|
|
8
|
+
description: string;
|
|
9
|
+
commands: Record<string, ICommand>;
|
|
10
|
+
}
|
|
11
|
+
export interface ICommand {
|
|
12
|
+
command: string;
|
|
13
|
+
description: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ILocatedCommand extends IRepoKitCommand {
|
|
16
|
+
location: string;
|
|
17
|
+
}
|
|
18
|
+
export type AsyncTask<T> = () => Promise<T>;
|
package/install.sh
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
set -e
|
|
2
|
+
|
|
3
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
4
|
+
|
|
5
|
+
cd $REPO_ROOT
|
|
6
|
+
|
|
7
|
+
command_exists() {
|
|
8
|
+
command -v "$1" >/dev/null 2>&1
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if command_exists rustc && command_exists cargo; then
|
|
12
|
+
echo "Rust is installed."
|
|
13
|
+
else
|
|
14
|
+
echo "Installing rust"
|
|
15
|
+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
if npm list --depth=0 tsx >/dev/null 2>&1; then
|
|
19
|
+
echo "Found tsx installation"
|
|
20
|
+
else
|
|
21
|
+
# Node Dependencies installation
|
|
22
|
+
if [ -f "${REPO_ROOT}/yarn.lock" ]; then
|
|
23
|
+
yarn add -D tsx
|
|
24
|
+
elif [ -f "${REPO_ROOT}/pnpm-lock.yaml" ]; then
|
|
25
|
+
pnpm add -D tsx
|
|
26
|
+
elif [ -f "${REPO_ROOT}/package-lock.json" ]; then
|
|
27
|
+
npm i -D tsx
|
|
28
|
+
else
|
|
29
|
+
echo "No node.js package manager detected"
|
|
30
|
+
echo "Run npm init to create your node.js project"
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
echo "Installing Repokit CLI"
|
|
36
|
+
|
|
37
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
38
|
+
cd "$SCRIPT_DIR"
|
|
39
|
+
|
|
40
|
+
. "$HOME/.cargo/env"
|
|
41
|
+
RUSTFLAGS="-Awarnings" cargo build --release > /dev/null
|
|
42
|
+
cargo install --path . > /dev/null
|
|
43
|
+
repokit
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@repokit/core",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A knowledgebase for your repository - wrapped in a CLI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Alex Figliolia",
|
|
7
|
+
"main": "dist/cjs/index.js",
|
|
8
|
+
"module": "dist/mjs/index.js",
|
|
9
|
+
"types": "dist/types/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/types/index.d.ts",
|
|
13
|
+
"import": "./dist/mjs/index.js",
|
|
14
|
+
"require": "./dist/cjs/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build:all": "yarn build:ts && yarn lint:all && yarn install:repokit",
|
|
22
|
+
"build:rust": "cargo build --release",
|
|
23
|
+
"build:ts": "yarn ts-packager -e src",
|
|
24
|
+
"install:repokit": "yarn build:rust && cargo install --path .",
|
|
25
|
+
"lint:all": "repokit format:rust && repokit lint:ts",
|
|
26
|
+
"postinstall": "chmod +x ./install.sh && ./install.sh",
|
|
27
|
+
"repokit": "yarn build:ts && yarn install:repokit && repokit",
|
|
28
|
+
"run:dev": "cargo run --package repokit --bin repokit"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@figliolia/event-emitter": "^1.1.6",
|
|
32
|
+
"@figliolia/ts-packager": "^1.2.1",
|
|
33
|
+
"@types/node": "^25.0.10",
|
|
34
|
+
"oxfmt": "^0.27.0",
|
|
35
|
+
"oxlint": "^1.42.0",
|
|
36
|
+
"oxlint-tsgolint": "^0.11.3",
|
|
37
|
+
"tsx": "^4.21.0",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/repokit.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { RepoKitConfig } from "@repokit/core";
|
|
2
|
+
|
|
3
|
+
export const RepoKit = new RepoKitConfig({
|
|
4
|
+
project: "Repokit",
|
|
5
|
+
commands: {
|
|
6
|
+
"lint:rust": {
|
|
7
|
+
command: "cargo clippy",
|
|
8
|
+
description: "Lints rust files",
|
|
9
|
+
},
|
|
10
|
+
"format:rust": {
|
|
11
|
+
command: "cargo clippy --fix --allow-dirty",
|
|
12
|
+
description: "Formats rust files",
|
|
13
|
+
},
|
|
14
|
+
"build:rust": {
|
|
15
|
+
command: "cargo build --release",
|
|
16
|
+
description: "Build CLI in production mode",
|
|
17
|
+
},
|
|
18
|
+
"run:rust": {
|
|
19
|
+
command: "cargo run --package repokit --bin repokit",
|
|
20
|
+
description: "Run CLI in development mode",
|
|
21
|
+
},
|
|
22
|
+
"install:rust": {
|
|
23
|
+
command: "repokit build:rust && cargo install --path .",
|
|
24
|
+
description: "Installs the production CLI and adds it to your path",
|
|
25
|
+
},
|
|
26
|
+
"lint:ts": {
|
|
27
|
+
command:
|
|
28
|
+
"yarn oxlint --type-aware --type-check --report-unused-disable-directives --fix && yarn oxfmt",
|
|
29
|
+
description: "Lints typescript files",
|
|
30
|
+
},
|
|
31
|
+
"build:ts": {
|
|
32
|
+
command: "yarn ts-packager -e src",
|
|
33
|
+
description: "Builds the typescript package",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { stat } from "node:fs/promises";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
|
|
6
|
+
import type { ILocatedCommand } from "./types";
|
|
7
|
+
import { TaskPooler } from "./TaskPooler";
|
|
8
|
+
import { RepoKitCommand } from "./RepoKitCommand";
|
|
9
|
+
|
|
10
|
+
export class CommandParser {
|
|
11
|
+
public static async parse() {
|
|
12
|
+
const { paths, root } = this.parsePaths();
|
|
13
|
+
if (!root || !existsSync(root) || !(await stat(root)).isDirectory()) {
|
|
14
|
+
return console.log(JSON.stringify([]));
|
|
15
|
+
}
|
|
16
|
+
const pathList = paths.split(",").filter(Boolean);
|
|
17
|
+
const pool = new TaskPooler<ILocatedCommand[]>();
|
|
18
|
+
const results = await Promise.all(
|
|
19
|
+
pathList.map(path =>
|
|
20
|
+
pool.enqueue(() => this.parseCommand(join(root, path))),
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
console.log(JSON.stringify(results.flat()));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private static async parseCommand(path: string) {
|
|
27
|
+
const commands: ILocatedCommand[] = [];
|
|
28
|
+
const declaredExports = await import(path);
|
|
29
|
+
for (const key in declaredExports) {
|
|
30
|
+
if (declaredExports[key] instanceof RepoKitCommand) {
|
|
31
|
+
commands.push({ ...declaredExports[key].toJSON(), location: path });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return commands;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private static parsePaths() {
|
|
38
|
+
try {
|
|
39
|
+
return parseArgs({
|
|
40
|
+
options: {
|
|
41
|
+
paths: {
|
|
42
|
+
default: "",
|
|
43
|
+
multiple: false,
|
|
44
|
+
short: "p",
|
|
45
|
+
type: "string",
|
|
46
|
+
},
|
|
47
|
+
root: {
|
|
48
|
+
default: "",
|
|
49
|
+
multiple: false,
|
|
50
|
+
short: "r",
|
|
51
|
+
type: "string",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
}).values;
|
|
55
|
+
} catch {
|
|
56
|
+
return { paths: "", root: "" };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
|
|
5
|
+
import { RepoKitConfig } from "./RepoKitConfig";
|
|
6
|
+
|
|
7
|
+
export class ConfigurationParser {
|
|
8
|
+
public static async parse() {
|
|
9
|
+
const root = this.parseRoot();
|
|
10
|
+
const path = join(root, "repokit.ts");
|
|
11
|
+
if (!existsSync(path)) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const config = await import(path);
|
|
15
|
+
for (const key in config) {
|
|
16
|
+
if (config[key] instanceof RepoKitConfig) {
|
|
17
|
+
return console.log(JSON.stringify(config[key]));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private static parseRoot() {
|
|
23
|
+
return parseArgs({
|
|
24
|
+
options: {
|
|
25
|
+
root: {
|
|
26
|
+
default: "",
|
|
27
|
+
multiple: false,
|
|
28
|
+
short: "r",
|
|
29
|
+
type: "string",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}).values.root;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ICommand, IRepoKitCommand } from "./types";
|
|
2
|
+
|
|
3
|
+
export class RepoKitCommand {
|
|
4
|
+
name: string;
|
|
5
|
+
owner: string;
|
|
6
|
+
description: string;
|
|
7
|
+
commands: Record<string, ICommand>;
|
|
8
|
+
constructor({
|
|
9
|
+
name,
|
|
10
|
+
description,
|
|
11
|
+
owner = "",
|
|
12
|
+
commands = {},
|
|
13
|
+
}: IRepoKitCommand) {
|
|
14
|
+
this.name = name;
|
|
15
|
+
this.owner = owner;
|
|
16
|
+
this.commands = commands;
|
|
17
|
+
this.description = description;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public toJSON() {
|
|
21
|
+
const { name, owner, commands, description } = this;
|
|
22
|
+
return { name, owner, commands, description };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ICommand, IRepoKitConfig } from "./types";
|
|
2
|
+
|
|
3
|
+
export class RepoKitConfig implements Required<IRepoKitConfig> {
|
|
4
|
+
project: string;
|
|
5
|
+
commands: Record<string, ICommand>;
|
|
6
|
+
constructor({ project, commands = {} }: IRepoKitConfig) {
|
|
7
|
+
this.project = project;
|
|
8
|
+
this.commands = commands;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AutoIncrementingID } from "@figliolia/event-emitter";
|
|
2
|
+
|
|
3
|
+
import type { AsyncTask } from "./types";
|
|
4
|
+
|
|
5
|
+
export class TaskPooler<T> {
|
|
6
|
+
private readonly IDs = new AutoIncrementingID();
|
|
7
|
+
private readonly runningTasks = new Map<string, Promise<T>>();
|
|
8
|
+
constructor(public maxSize = 10) {}
|
|
9
|
+
|
|
10
|
+
public enqueue(task: AsyncTask<T>) {
|
|
11
|
+
return new Promise<T>(resolve => {
|
|
12
|
+
if (this.runningTasks.size < 10) {
|
|
13
|
+
return resolve(this.indexRunningTask(task));
|
|
14
|
+
}
|
|
15
|
+
resolve(this.indexBehindNextOpening(task));
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private indexRunningTask(task: AsyncTask<T>) {
|
|
20
|
+
const ID = this.IDs.get();
|
|
21
|
+
const promise = task();
|
|
22
|
+
this.runningTasks.set(ID, promise);
|
|
23
|
+
void promise.finally(() => this.runningTasks.delete(ID));
|
|
24
|
+
return promise;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private async indexBehindNextOpening(task: AsyncTask<T>) {
|
|
28
|
+
await Promise.race(this.runningTasks.values());
|
|
29
|
+
return this.indexRunningTask(task);
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface IRepoKitConfig {
|
|
2
|
+
project: string;
|
|
3
|
+
commands?: Record<string, ICommand>;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface IRepoKitCommand {
|
|
7
|
+
name: string;
|
|
8
|
+
owner?: string;
|
|
9
|
+
description: string;
|
|
10
|
+
commands: Record<string, ICommand>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ICommand {
|
|
14
|
+
command: string;
|
|
15
|
+
description: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ILocatedCommand extends IRepoKitCommand {
|
|
19
|
+
location: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type AsyncTask<T> = () => Promise<T>;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "nodenext",
|
|
4
|
+
"target": "esnext",
|
|
5
|
+
"lib": ["ESNext"],
|
|
6
|
+
"moduleResolution": "nodenext",
|
|
7
|
+
"noUncheckedIndexedAccess": true,
|
|
8
|
+
"exactOptionalPropertyTypes": true,
|
|
9
|
+
"noImplicitReturns": true,
|
|
10
|
+
"noImplicitOverride": true,
|
|
11
|
+
"noUnusedLocals": true,
|
|
12
|
+
"noUnusedParameters": true,
|
|
13
|
+
"noFallthroughCasesInSwitch": true,
|
|
14
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
15
|
+
"strict": true,
|
|
16
|
+
"isolatedModules": true,
|
|
17
|
+
"noUncheckedSideEffectImports": true,
|
|
18
|
+
"moduleDetection": "force",
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"paths": {
|
|
21
|
+
"@repokit/core": ["./src/index.ts"]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pub mod thread_pool;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
use tokio::{
|
|
2
|
+
runtime::{self, Runtime},
|
|
3
|
+
task::JoinHandle,
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
pub struct ThreadPool {
|
|
7
|
+
pub pool: Runtime,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
impl ThreadPool {
|
|
11
|
+
pub fn new(threads_override: Option<usize>, pool_override: Option<Runtime>) -> ThreadPool {
|
|
12
|
+
let pool = pool_override.unwrap_or(ThreadPool::create_pool(threads_override));
|
|
13
|
+
ThreadPool { pool }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
pub fn spawn<T: Send + 'static, F: (Fn() -> T) + 'static + Send>(
|
|
17
|
+
&mut self,
|
|
18
|
+
task: F,
|
|
19
|
+
) -> JoinHandle<T> {
|
|
20
|
+
self.pool.spawn(async move { task() })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fn create_pool(threads: Option<usize>) -> Runtime {
|
|
24
|
+
let mut pool = runtime::Builder::new_multi_thread();
|
|
25
|
+
pool.enable_all();
|
|
26
|
+
match threads {
|
|
27
|
+
Some(size) => pool.worker_threads(size),
|
|
28
|
+
None => &pool,
|
|
29
|
+
};
|
|
30
|
+
pool.build().unwrap()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
fs::File,
|
|
3
|
+
io,
|
|
4
|
+
path::{Path, PathBuf},
|
|
5
|
+
process::exit,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
use crate::logger::logger::Logger;
|
|
9
|
+
|
|
10
|
+
pub struct Configuration;
|
|
11
|
+
|
|
12
|
+
impl Configuration {
|
|
13
|
+
pub fn create(root: &str) {
|
|
14
|
+
let file_path = format!("{root}/repokit.ts");
|
|
15
|
+
let path_buf = Path::new(&file_path);
|
|
16
|
+
if path_buf.exists() {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
Configuration::welcome();
|
|
20
|
+
let mut source = File::open(Configuration::template_path()).expect("Template");
|
|
21
|
+
let mut target = File::create(path_buf).expect("creating");
|
|
22
|
+
io::copy(&mut source, &mut target).expect("writing");
|
|
23
|
+
target.sync_all().expect("Flushing");
|
|
24
|
+
Logger::info(
|
|
25
|
+
format!(
|
|
26
|
+
"Please fill out this file with your desired settings. Then run {}",
|
|
27
|
+
Logger::blue_bright("repokit onboard")
|
|
28
|
+
)
|
|
29
|
+
.as_str(),
|
|
30
|
+
);
|
|
31
|
+
Logger::log_file_path(file_path.as_str());
|
|
32
|
+
exit(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fn welcome() {
|
|
36
|
+
Logger::info("Welcome to Repokit! Let's get you setup");
|
|
37
|
+
Logger::info("Creating your configuration file:");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn template_path() -> PathBuf {
|
|
41
|
+
let file_path = file!();
|
|
42
|
+
let dir = Path::new(file_path)
|
|
43
|
+
.parent()
|
|
44
|
+
.expect("Failed to get parent directory");
|
|
45
|
+
dir.join("configuration_template.ts")
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RepoKitConfig } from "@repokit/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Please fill out this config file with your desired
|
|
5
|
+
* repokit settings
|
|
6
|
+
*/
|
|
7
|
+
export const RepoKit = new RepoKitConfig({
|
|
8
|
+
project: "Your Project Name",
|
|
9
|
+
commands: {
|
|
10
|
+
"<your-first-command>": {
|
|
11
|
+
command: "<insert shell command here>",
|
|
12
|
+
description: "A description for using your command",
|
|
13
|
+
},
|
|
14
|
+
"<your-second-command>": {
|
|
15
|
+
command: "<insert shell command here>",
|
|
16
|
+
description: "A description for using your command",
|
|
17
|
+
},
|
|
18
|
+
"<your-third-command>": {
|
|
19
|
+
command: "<insert shell command here>",
|
|
20
|
+
description: "A description for using your command",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pub mod configuration;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
use crate::executables::internal_executable_definition::InternalExecutableDefinition;
|
|
4
|
+
|
|
5
|
+
pub trait InternalExecutable {
|
|
6
|
+
fn run(&self, args: Vec<String>, internals: &HashMap<String, Box<dyn InternalExecutable>>);
|
|
7
|
+
fn help(&self);
|
|
8
|
+
fn get_definition(&self) -> &InternalExecutableDefinition;
|
|
9
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
use std::ffi::OsStr;
|
|
2
|
+
use std::process::Command;
|
|
3
|
+
use std::str;
|
|
4
|
+
|
|
5
|
+
pub struct Executor {}
|
|
6
|
+
|
|
7
|
+
impl Executor {
|
|
8
|
+
pub fn exec<T: AsRef<OsStr>>(
|
|
9
|
+
command: T,
|
|
10
|
+
composer: impl Fn(&mut Command) -> &mut Command,
|
|
11
|
+
) -> String {
|
|
12
|
+
let output = composer(&mut Executor::spawn(command))
|
|
13
|
+
.output()
|
|
14
|
+
.expect("command failed to execute");
|
|
15
|
+
if output.status.success() {
|
|
16
|
+
return Executor::unwrap(&output.stdout);
|
|
17
|
+
}
|
|
18
|
+
Executor::unwrap(&output.stderr)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
pub fn with_stdio<T: AsRef<OsStr>>(
|
|
22
|
+
command: T,
|
|
23
|
+
composer: impl Fn(&mut Command) -> &mut Command,
|
|
24
|
+
) {
|
|
25
|
+
let mut child = composer(&mut Executor::spawn(command))
|
|
26
|
+
.spawn()
|
|
27
|
+
.expect("Failed to execute");
|
|
28
|
+
child.wait().expect("failed to wait on child process");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub fn spawn<T: AsRef<OsStr>>(program: T) -> Command {
|
|
32
|
+
let mut command = Executor::platform_command();
|
|
33
|
+
command.arg(program);
|
|
34
|
+
command
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fn platform_command() -> Command {
|
|
38
|
+
if cfg!(target_os = "windows") {
|
|
39
|
+
return Executor::windows_command();
|
|
40
|
+
}
|
|
41
|
+
Executor::unix_command()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fn windows_command() -> Command {
|
|
45
|
+
let mut child_process = Command::new("cmd");
|
|
46
|
+
child_process.arg("/C");
|
|
47
|
+
child_process
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fn unix_command() -> Command {
|
|
51
|
+
let mut child_process = Command::new("sh");
|
|
52
|
+
child_process.arg("-c");
|
|
53
|
+
child_process
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fn unwrap(io: &[u8]) -> String {
|
|
57
|
+
str::from_utf8(io)
|
|
58
|
+
.expect("Invalid output")
|
|
59
|
+
.trim()
|
|
60
|
+
.to_string()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pub mod executor;
|