From d375836989fd730acbb4a04218d143b9fef63e0d Mon Sep 17 00:00:00 2001 From: Kai Jellinghaus Date: Mon, 7 Nov 2022 16:02:49 +0100 Subject: [PATCH] feat(cli): Tarball pull (#867) * Add tarball pull * Move command & prompt on conflict * Remove old file Co-authored-by: Ruben Fiszel --- cli/context.ts | 2 ++ cli/main.ts | 2 ++ cli/pull.ts | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 cli/pull.ts diff --git a/cli/context.ts b/cli/context.ts index ed094d1445..ae8eacdaac 100644 --- a/cli/context.ts +++ b/cli/context.ts @@ -13,6 +13,7 @@ export type Context = { workspace: string; baseUrl: string; urlStore: string; + token: string; }; export async function getContext({ @@ -45,5 +46,6 @@ export async function getContext({ workspace: workspaceId, baseUrl: baseUrl, urlStore: urlStore, + token: token, }; } diff --git a/cli/main.ts b/cli/main.ts index bb14ce4153..f1acac0adc 100644 --- a/cli/main.ts +++ b/cli/main.ts @@ -13,6 +13,7 @@ import user from "./user.ts"; import setup from "./setup.ts"; import variable from "./variable.ts"; import push from "./push.ts"; +import pull from "./pull.ts"; const VERSION = "v1.45.0"; @@ -71,6 +72,7 @@ await new Command() .command("setup", setup) .command("variable", variable) .command("push", push) + .command("pull", pull) .command( "upgrade", new UpgradeCommand({ diff --git a/cli/pull.ts b/cli/pull.ts new file mode 100644 index 0000000000..cc42ae8019 --- /dev/null +++ b/cli/pull.ts @@ -0,0 +1,85 @@ +import { Untar } from "https://deno.land/std@0.162.0/archive/tar.ts"; +import { Command } from "https://deno.land/x/cliffy@v0.25.4/command/command.ts"; +import { + copy, + readerFromStreamReader, +} from "https://deno.land/std@0.162.0/streams/mod.ts"; +import { getContext } from "./context.ts"; +import { GlobalOptions } from "./types.ts"; +import * as path from "https://deno.land/std@0.162.0/path/mod.ts"; +import { colors } from "https://deno.land/x/cliffy@v0.25.4/ansi/colors.ts"; +import { ensureDir } from "https://deno.land/std@0.162.0/fs/ensure_dir.ts"; +import { Confirm } from "https://deno.land/x/cliffy@v0.25.4/prompt/confirm.ts"; + +async function pull(opts: GlobalOptions & { override: boolean }, dir: string) { + const { workspace, baseUrl, token } = await getContext(opts); + + const requestHeaders: HeadersInit = new Headers(); + requestHeaders.set("Authorization", "Bearer " + token); + requestHeaders.set("Content-Type", "application/octet-stream"); + + const tarResponse = await fetch( + baseUrl + "/api/w/" + workspace + "/workspaces/tarball", + { + headers: requestHeaders, + method: "GET", + } + ); + + if (!tarResponse.ok) { + console.log(colors.red("Failed to request tarball from API")); + console.log(colors.red(await tarResponse.text())); + return; + } + + const streamReader = tarResponse.body?.getReader(); + if (!streamReader) { + console.log(colors.red("Failed to read tar request body")); + return; + } + console.log(colors.yellow("Streaming tarball to disk...")); + const denoReader = readerFromStreamReader(streamReader); + const untar = new Untar(denoReader); + for await (const entry of untar) { + console.log(entry.fileName); + const filePath = path.resolve(dir, entry.fileName); + if (entry.type === "directory") { + await ensureDir(filePath); + continue; + } + await ensureDir(path.dirname(filePath)); + if (!opts.override) { + let exists = false; + try { + const _stat = await Deno.stat(filePath); + exists = true; + } catch { + exists = false; + } + if (exists) { + if ( + !(await Confirm.prompt( + "Conflict at " + + filePath + + " do you want to override the local version?" + )) + ) { + continue; + } + } + } + const file = await Deno.open(filePath, { write: true, create: true }); + await copy(entry, file); + file.close(); + } + console.log(colors.green("Done. Wrote all files to disk.")); +} + +const command = new Command() + .description( + "Pull all definitions in the current workspace from the API and write them to disk." + ) + .arguments("") + .action(pull as any); + +export default command;