Browse Source

initial prototype for configs

Michaël Lemaire 4 months ago
commit
67b11fd976
8 changed files with 141 additions and 0 deletions
  1. 9 0
      .editorconfig
  2. 3 0
      .gitignore
  3. 3 0
      README.md
  4. 104 0
      cli.ts
  5. 7 0
      testapp/.thunderk-backedup.json
  6. 1 0
      testapp/data/.gitignore
  7. 4 0
      testapp/run.sh
  8. 10 0
      tsconfig.json

+ 9 - 0
.editorconfig

@@ -0,0 +1,9 @@
+root = true
+
+[*.{ts,json}]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+deno.d.ts
+.vscode
+.local

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# typescript/backedup
+
+[![Build Status](https://thunderk.visualstudio.com/typescript/_apis/build/status/backedup?branchName=master)](https://dev.azure.com/thunderk/typescript/_build?pipelineNameFilter=backedup)

+ 104 - 0
cli.ts

@@ -0,0 +1,104 @@
+#!/usr/bin/env -S deno run --allow-env --allow-run --allow-read --allow-write
+
+import * as path from "https://deno.land/std/path/mod.ts";
+
+/**
+ * Run the backedup command line tool
+ *
+ * This allows to execute another program, with data files
+ * synchronization performed to a remote SSH server.
+ *
+ * Before launching the program, data files are retrieved,
+ * and after the program ended, data files are uploaded.
+ */
+export async function run(): Promise<void> {
+  const directory = Deno.args[0] || Deno.cwd();
+  const remote = await readRemoteConfig();
+  const program = await readProgramConfig(directory);
+  const config = { remote, program };
+  await runConfig(config);
+}
+
+const SELF_NAME = "thunderk-backedup";
+const HOME_DIRECTORY = Deno.env.get("HOME") ||
+  `/home/${Deno.env.get("USER") || "backedup"}`;
+
+type RemoteConfig = {
+  host: string;
+  directory: string;
+};
+
+type ProgramConfig = {
+  id: string;
+  command: string[];
+  directory: string;
+  env: { [name: string]: string };
+  saves: { [name: string]: string };
+};
+
+type RunConfig = {
+  remote: RemoteConfig;
+  program: ProgramConfig;
+};
+
+/**
+ * Read the remote configuration, from the user directory
+ */
+async function readRemoteConfig(): Promise<RemoteConfig> {
+  const config_path = path.join(
+    HOME_DIRECTORY,
+    ".config",
+    `/${SELF_NAME}.json`,
+  );
+  console.debug(`Reading remote config: ${config_path}`);
+  const content = await Deno.readTextFile(config_path);
+  const data = JSON.parse(content);
+  if (data.host && data.directory) {
+    return {
+      host: data.host,
+      directory: data.directory,
+    };
+  } else {
+    throw new Error("Bad remote configuration");
+  }
+}
+
+/**
+ * Read the program configuration from a directory
+ */
+async function readProgramConfig(directory: string): Promise<ProgramConfig> {
+  const config_path = path.join(directory, `.${SELF_NAME}.json`);
+  const content = await Deno.readTextFile(config_path);
+  console.debug(`Reading program config: ${config_path}`);
+  const data = JSON.parse(content);
+  if (data.id && data.command) {
+    return {
+      id: data.id,
+      command: typeof data.command == "string"
+        ? data.command.split(" ")
+        : data.command,
+      directory: data.pwd || directory,
+      env: data.env || {},
+      saves: data.saves || {},
+    };
+  } else {
+    throw new Error("Bad program configuration");
+  }
+}
+
+/**
+ * Run a configuration
+ */
+async function runConfig(config: RunConfig): Promise<void> {
+  console.debug(`Running ${JSON.stringify(config)}`);
+  const process = Deno.run({
+    cmd: config.program.command,
+    cwd: config.program.directory,
+    env: { ...Deno.env.toObject(), ...config.program.env },
+  });
+  await process.status();
+}
+
+if (import.meta.main) {
+  await run();
+}

+ 7 - 0
testapp/.thunderk-backedup.json

@@ -0,0 +1,7 @@
+{
+  "id": "test",
+  "command": "bash -c ./run.sh",
+  "saves": {
+    "main": "data"
+  }
+}

+ 1 - 0
testapp/data/.gitignore

@@ -0,0 +1 @@
+testdata.txt

+ 4 - 0
testapp/run.sh

@@ -0,0 +1,4 @@
+#!/bin/sh
+set -e
+date > data/testdata.txt
+echo "All good!"

+ 10 - 0
tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "module": "esnext",
+    "target": "ESNext",
+    "strict": true,
+    "noImplicitReturns": true,
+    "noFallthroughCasesInSwitch": true,
+    "preserveConstEnums": true
+  }
+}