summaryrefslogtreecommitdiff
path: root/std/installer/mod.ts
diff options
context:
space:
mode:
authorBartek Iwańczuk <biwanczuk@gmail.com>2020-01-31 17:34:50 +0100
committerGitHub <noreply@github.com>2020-01-31 17:34:50 +0100
commite1697421e2c00508cd78976b6ec586e056530c30 (patch)
treef7d2a8501bfb91cbf2453784895a46d5e3737381 /std/installer/mod.ts
parentc7a2a33ea1a3245bfc1b9af1db2282ef8e3f7ab3 (diff)
chore: remove std/installer, port installer tests to Rust (#3843)
Diffstat (limited to 'std/installer/mod.ts')
-rw-r--r--std/installer/mod.ts303
1 files changed, 0 insertions, 303 deletions
diff --git a/std/installer/mod.ts b/std/installer/mod.ts
deleted file mode 100644
index ce6c40f37..000000000
--- a/std/installer/mod.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-#!/usr/bin/env -S deno --allow-all
-// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-const { env, stdin, args, exit, writeFile, chmod, run } = Deno;
-import { parse } from "../flags/mod.ts";
-import { exists } from "../fs/exists.ts";
-import { ensureDir } from "../fs/ensure_dir.ts";
-import * as path from "../path/mod.ts";
-
-const encoder = new TextEncoder();
-const decoder = new TextDecoder("utf-8");
-// Regular expression to test disk driver letter. eg "C:\\User\username\path\to"
-const driverLetterReg = /^[c-z]:/i;
-const isWindows = Deno.build.os === "win";
-
-function showHelp(): void {
- console.log(`deno installer
- Install remote or local script as executables.
-
-USAGE:
- deno -A https://deno.land/std/installer/mod.ts [OPTIONS] EXE_NAME SCRIPT_URL [FLAGS...]
-
-ARGS:
- EXE_NAME Name for executable
- SCRIPT_URL Local or remote URL of script to install
- [FLAGS...] List of flags for script, both Deno permission and script specific
- flag can be used.
-
-OPTIONS:
- -d, --dir <PATH> Installation directory path (defaults to ~/.deno/bin)
-`);
-}
-
-enum Permission {
- Read,
- Write,
- Net,
- Env,
- Run,
- All
-}
-
-function getPermissionFromFlag(flag: string): Permission | undefined {
- switch (flag) {
- case "--allow-read":
- return Permission.Read;
- case "--allow-write":
- return Permission.Write;
- case "--allow-net":
- return Permission.Net;
- case "--allow-env":
- return Permission.Env;
- case "--allow-run":
- return Permission.Run;
- case "--allow-all":
- return Permission.All;
- case "-A":
- return Permission.All;
- }
-}
-
-function getFlagFromPermission(perm: Permission): string {
- switch (perm) {
- case Permission.Read:
- return "--allow-read";
- case Permission.Write:
- return "--allow-write";
- case Permission.Net:
- return "--allow-net";
- case Permission.Env:
- return "--allow-env";
- case Permission.Run:
- return "--allow-run";
- case Permission.All:
- return "--allow-all";
- }
- return "";
-}
-
-function getInstallerDir(): string {
- // In Windows's Powershell $HOME environmental variable maybe null
- // if so use $USERPROFILE instead.
- const { HOME, USERPROFILE } = env();
-
- const HOME_PATH = HOME || USERPROFILE;
-
- if (!HOME_PATH) {
- throw new Error("$HOME is not defined.");
- }
-
- return path.resolve(HOME_PATH, ".deno", "bin");
-}
-
-async function readCharacter(): Promise<string> {
- const byteArray = new Uint8Array(1024);
- await stdin.read(byteArray);
- const line = decoder.decode(byteArray);
- return line[0];
-}
-
-async function yesNoPrompt(message: string): Promise<boolean> {
- console.log(`${message} [yN]`);
- const input = await readCharacter();
- console.log();
- return input === "y" || input === "Y";
-}
-
-function checkIfExistsInPath(filePath: string): boolean {
- // In Windows's Powershell $PATH not exist, so use $Path instead.
- // $HOMEDRIVE is only used on Windows.
- const { PATH, Path, HOMEDRIVE } = env();
-
- const envPath = (PATH as string) || (Path as string) || "";
-
- const paths = envPath.split(isWindows ? ";" : ":");
-
- let fileAbsolutePath = filePath;
-
- for (const p of paths) {
- const pathInEnv = path.normalize(p);
- // On Windows paths from env contain drive letter.
- // (eg. C:\Users\username\.deno\bin)
- // But in the path of Deno, there is no drive letter.
- // (eg \Users\username\.deno\bin)
- if (isWindows) {
- if (driverLetterReg.test(pathInEnv)) {
- fileAbsolutePath = HOMEDRIVE + "\\" + fileAbsolutePath;
- }
- }
- if (pathInEnv === fileAbsolutePath) {
- return true;
- }
- fileAbsolutePath = filePath;
- }
-
- return false;
-}
-
-export function isRemoteUrl(url: string): boolean {
- return /^https?:\/\//.test(url);
-}
-
-function validateModuleName(moduleName: string): boolean {
- if (/^[a-z][\w-]*$/i.test(moduleName)) {
- return true;
- } else {
- throw new Error("Invalid module name: " + moduleName);
- }
-}
-
-async function generateExecutable(
- filePath: string,
- commands: string[]
-): Promise<void> {
- commands = commands.map((v): string => JSON.stringify(v));
- // On Windows if user is using Powershell .cmd extension is need to run the
- // installed module.
- // Generate batch script to satisfy that.
- const templateHeader =
- "This executable is generated by Deno. Please don't modify it unless you " +
- "know what it means.";
- if (isWindows) {
- const template = `% ${templateHeader} %
-@IF EXIST "%~dp0\deno.exe" (
- "%~dp0\deno.exe" ${commands.slice(1).join(" ")} %*
-) ELSE (
- @SETLOCAL
- @SET PATHEXT=%PATHEXT:;.TS;=;%
- ${commands.join(" ")} %*
-)
-`;
- const cmdFile = filePath + ".cmd";
- await writeFile(cmdFile, encoder.encode(template));
- await chmod(cmdFile, 0o755);
- }
-
- // generate Shell script
- const template = `#!/bin/sh
-# ${templateHeader}
-basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
-
-case \`uname\` in
- *CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
-esac
-
-if [ -x "$basedir/deno" ]; then
- "$basedir/deno" ${commands.slice(1).join(" ")} "$@"
- ret=$?
-else
- ${commands.join(" ")} "$@"
- ret=$?
-fi
-exit $ret
-`;
- await writeFile(filePath, encoder.encode(template));
- await chmod(filePath, 0o755);
-}
-
-export async function install(
- moduleName: string,
- moduleUrl: string,
- flags: string[],
- installationDir?: string
-): Promise<void> {
- if (!installationDir) {
- installationDir = getInstallerDir();
- }
- await ensureDir(installationDir);
-
- // if install local module
- if (!isRemoteUrl(moduleUrl)) {
- moduleUrl = path.resolve(moduleUrl);
- }
-
- validateModuleName(moduleName);
- const filePath = path.join(installationDir, moduleName);
-
- if (await exists(filePath)) {
- const msg =
- "⚠️ " +
- moduleName +
- " is already installed" +
- ", do you want to overwrite it?";
- if (!(await yesNoPrompt(msg))) {
- return;
- }
- }
-
- // ensure script that is being installed exists
- const ps = run({
- args: [Deno.execPath(), "fetch", "--reload", moduleUrl],
- stdout: "inherit",
- stderr: "inherit"
- });
-
- const { code } = await ps.status();
-
- if (code !== 0) {
- throw new Error("Failed to fetch module.");
- }
-
- const grantedPermissions: Permission[] = [];
- const scriptArgs: string[] = [];
-
- for (const flag of flags) {
- const permission = getPermissionFromFlag(flag);
- if (permission === undefined) {
- scriptArgs.push(flag);
- } else {
- grantedPermissions.push(permission);
- }
- }
-
- const commands = [
- "deno",
- "run",
- ...grantedPermissions.map(getFlagFromPermission),
- moduleUrl,
- ...scriptArgs
- ];
-
- await generateExecutable(filePath, commands);
-
- console.log(`✅ Successfully installed ${moduleName}`);
- console.log(filePath);
-
- if (!checkIfExistsInPath(installationDir)) {
- console.log(`\nℹ️ Add ${installationDir} to PATH`);
- console.log(
- " echo 'export PATH=\"" +
- installationDir +
- ":$PATH\"' >> ~/.bashrc # change" +
- " this to your shell"
- );
- }
-}
-
-async function main(): Promise<void> {
- const parsedArgs = parse(args, { stopEarly: true });
-
- if (parsedArgs.h || parsedArgs.help) {
- return showHelp();
- }
-
- if (parsedArgs._.length < 2) {
- return showHelp();
- }
-
- const moduleName = parsedArgs._[0];
- const moduleUrl = parsedArgs._[1];
- const flags = parsedArgs._.slice(2);
- const installationDir = parsedArgs.d || parsedArgs.dir;
-
- try {
- await install(moduleName, moduleUrl, flags, installationDir);
- } catch (e) {
- console.log(e);
- exit(1);
- }
-}
-
-if (import.meta.main) {
- main();
-}