mirror of https://github.com/actions/setup-node
Add correct tool-cache
This commit is contained in:
parent
9bb7038a07
commit
9580326150
|
@ -1,15 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
"$basedir/node" "$basedir/../shelljs/bin/shjs" "$@"
|
|
||||||
ret=$?
|
|
||||||
else
|
|
||||||
node "$basedir/../shelljs/bin/shjs" "$@"
|
|
||||||
ret=$?
|
|
||||||
fi
|
|
||||||
exit $ret
|
|
|
@ -1,7 +0,0 @@
|
||||||
@IF EXIST "%~dp0\node.exe" (
|
|
||||||
"%~dp0\node.exe" "%~dp0\..\shelljs\bin\shjs" %*
|
|
||||||
) ELSE (
|
|
||||||
@SETLOCAL
|
|
||||||
@SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
node "%~dp0\..\shelljs\bin\shjs" %*
|
|
||||||
)
|
|
|
@ -1,7 +1,7 @@
|
||||||
# `@actions/exec`
|
# `@actions/exec`
|
||||||
|
|
||||||
> Functions necessary for running tools on the command line
|
> Functions necessary for running tools on the command line
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
See [src/exec.ts](src/exec.ts).
|
See [src/exec.ts](src/exec.ts).
|
|
@ -1,12 +1,12 @@
|
||||||
import * as im from './interfaces';
|
import * as im from './interfaces';
|
||||||
/**
|
/**
|
||||||
* Exec a command.
|
* Exec a command.
|
||||||
* Output will be streamed to the live console.
|
* Output will be streamed to the live console.
|
||||||
* Returns promise with return code
|
* Returns promise with return code
|
||||||
*
|
*
|
||||||
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
|
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
|
||||||
* @param args optional arguments for tool. Escaping is handled by the lib.
|
* @param args optional arguments for tool. Escaping is handled by the lib.
|
||||||
* @param options optional exec options. See ExecOptions
|
* @param options optional exec options. See ExecOptions
|
||||||
* @returns Promise<number> exit code
|
* @returns Promise<number> exit code
|
||||||
*/
|
*/
|
||||||
export declare function exec(commandLine: string, args?: string[], options?: im.ExecOptions): Promise<number>;
|
export declare function exec(commandLine: string, args?: string[], options?: im.ExecOptions): Promise<number>;
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const tr = require("./toolrunner");
|
const tr = require("./toolrunner");
|
||||||
/**
|
/**
|
||||||
* Exec a command.
|
* Exec a command.
|
||||||
* Output will be streamed to the live console.
|
* Output will be streamed to the live console.
|
||||||
* Returns promise with return code
|
* Returns promise with return code
|
||||||
*
|
*
|
||||||
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
|
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
|
||||||
* @param args optional arguments for tool. Escaping is handled by the lib.
|
* @param args optional arguments for tool. Escaping is handled by the lib.
|
||||||
* @param options optional exec options. See ExecOptions
|
* @param options optional exec options. See ExecOptions
|
||||||
* @returns Promise<number> exit code
|
* @returns Promise<number> exit code
|
||||||
*/
|
*/
|
||||||
function exec(commandLine, args, options) {
|
function exec(commandLine, args, options) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const commandArgs = tr.argStringToArray(commandLine);
|
const commandArgs = tr.argStringToArray(commandLine);
|
||||||
if (commandArgs.length === 0) {
|
if (commandArgs.length === 0) {
|
||||||
throw new Error(`Parameter 'commandLine' cannot be null or empty.`);
|
throw new Error(`Parameter 'commandLine' cannot be null or empty.`);
|
||||||
}
|
}
|
||||||
// Path to tool to execute should be first arg
|
// Path to tool to execute should be first arg
|
||||||
const toolPath = commandArgs[0];
|
const toolPath = commandArgs[0];
|
||||||
args = commandArgs.slice(1).concat(args || []);
|
args = commandArgs.slice(1).concat(args || []);
|
||||||
const runner = new tr.ToolRunner(toolPath, args, options);
|
const runner = new tr.ToolRunner(toolPath, args, options);
|
||||||
return runner.exec();
|
return runner.exec();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.exec = exec;
|
exports.exec = exec;
|
||||||
//# sourceMappingURL=exec.js.map
|
//# sourceMappingURL=exec.js.map
|
|
@ -1,35 +1,35 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
import * as stream from 'stream';
|
import * as stream from 'stream';
|
||||||
/**
|
/**
|
||||||
* Interface for exec options
|
* Interface for exec options
|
||||||
*/
|
*/
|
||||||
export interface ExecOptions {
|
export interface ExecOptions {
|
||||||
/** optional working directory. defaults to current */
|
/** optional working directory. defaults to current */
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
/** optional envvar dictionary. defaults to current process's env */
|
/** optional envvar dictionary. defaults to current process's env */
|
||||||
env?: {
|
env?: {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
};
|
};
|
||||||
/** optional. defaults to false */
|
/** optional. defaults to false */
|
||||||
silent?: boolean;
|
silent?: boolean;
|
||||||
/** optional out stream to use. Defaults to process.stdout */
|
/** optional out stream to use. Defaults to process.stdout */
|
||||||
outStream?: stream.Writable;
|
outStream?: stream.Writable;
|
||||||
/** optional err stream to use. Defaults to process.stderr */
|
/** optional err stream to use. Defaults to process.stderr */
|
||||||
errStream?: stream.Writable;
|
errStream?: stream.Writable;
|
||||||
/** optional. whether to skip quoting/escaping arguments if needed. defaults to false. */
|
/** optional. whether to skip quoting/escaping arguments if needed. defaults to false. */
|
||||||
windowsVerbatimArguments?: boolean;
|
windowsVerbatimArguments?: boolean;
|
||||||
/** optional. whether to fail if output to stderr. defaults to false */
|
/** optional. whether to fail if output to stderr. defaults to false */
|
||||||
failOnStdErr?: boolean;
|
failOnStdErr?: boolean;
|
||||||
/** optional. defaults to failing on non zero. ignore will not fail leaving it up to the caller */
|
/** optional. defaults to failing on non zero. ignore will not fail leaving it up to the caller */
|
||||||
ignoreReturnCode?: boolean;
|
ignoreReturnCode?: boolean;
|
||||||
/** optional. How long in ms to wait for STDIO streams to close after the exit event of the process before terminating. defaults to 10000 */
|
/** optional. How long in ms to wait for STDIO streams to close after the exit event of the process before terminating. defaults to 10000 */
|
||||||
delay?: number;
|
delay?: number;
|
||||||
/** optional. Listeners for output. Callback functions that will be called on these events */
|
/** optional. Listeners for output. Callback functions that will be called on these events */
|
||||||
listeners?: {
|
listeners?: {
|
||||||
stdout?: (data: Buffer) => void;
|
stdout?: (data: Buffer) => void;
|
||||||
stderr?: (data: Buffer) => void;
|
stderr?: (data: Buffer) => void;
|
||||||
stdline?: (data: string) => void;
|
stdline?: (data: string) => void;
|
||||||
errline?: (data: string) => void;
|
errline?: (data: string) => void;
|
||||||
debug?: (data: string) => void;
|
debug?: (data: string) => void;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
//# sourceMappingURL=interfaces.js.map
|
//# sourceMappingURL=interfaces.js.map
|
|
@ -1,37 +1,37 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
import * as events from 'events';
|
import * as events from 'events';
|
||||||
import * as im from './interfaces';
|
import * as im from './interfaces';
|
||||||
export declare class ToolRunner extends events.EventEmitter {
|
export declare class ToolRunner extends events.EventEmitter {
|
||||||
constructor(toolPath: string, args?: string[], options?: im.ExecOptions);
|
constructor(toolPath: string, args?: string[], options?: im.ExecOptions);
|
||||||
private toolPath;
|
private toolPath;
|
||||||
private args;
|
private args;
|
||||||
private options;
|
private options;
|
||||||
private _debug;
|
private _debug;
|
||||||
private _getCommandString;
|
private _getCommandString;
|
||||||
private _processLineBuffer;
|
private _processLineBuffer;
|
||||||
private _getSpawnFileName;
|
private _getSpawnFileName;
|
||||||
private _getSpawnArgs;
|
private _getSpawnArgs;
|
||||||
private _endsWith;
|
private _endsWith;
|
||||||
private _isCmdFile;
|
private _isCmdFile;
|
||||||
private _windowsQuoteCmdArg;
|
private _windowsQuoteCmdArg;
|
||||||
private _uvQuoteCmdArg;
|
private _uvQuoteCmdArg;
|
||||||
private _cloneExecOptions;
|
private _cloneExecOptions;
|
||||||
private _getSpawnOptions;
|
private _getSpawnOptions;
|
||||||
/**
|
/**
|
||||||
* Exec a tool.
|
* Exec a tool.
|
||||||
* Output will be streamed to the live console.
|
* Output will be streamed to the live console.
|
||||||
* Returns promise with return code
|
* Returns promise with return code
|
||||||
*
|
*
|
||||||
* @param tool path to tool to exec
|
* @param tool path to tool to exec
|
||||||
* @param options optional exec options. See ExecOptions
|
* @param options optional exec options. See ExecOptions
|
||||||
* @returns number
|
* @returns number
|
||||||
*/
|
*/
|
||||||
exec(): Promise<number>;
|
exec(): Promise<number>;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Convert an arg string to an array of args. Handles escaping
|
* Convert an arg string to an array of args. Handles escaping
|
||||||
*
|
*
|
||||||
* @param argString string of arguments
|
* @param argString string of arguments
|
||||||
* @returns string[] array of arguments
|
* @returns string[] array of arguments
|
||||||
*/
|
*/
|
||||||
export declare function argStringToArray(argString: string): string[];
|
export declare function argStringToArray(argString: string): string[];
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
||||||
Copyright 2019 GitHub
|
Copyright 2019 GitHub
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,7 +1,7 @@
|
||||||
# `@actions/exit`
|
# `@actions/exit`
|
||||||
|
|
||||||
> TODO: description
|
> TODO: description
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
See [src/exit.ts](src/exit.ts).
|
See [src/exit.ts](src/exit.ts).
|
|
@ -1,29 +1,29 @@
|
||||||
/**
|
/**
|
||||||
* The code to exit an action
|
* The code to exit an action
|
||||||
*/
|
*/
|
||||||
export declare enum ExitCode {
|
export declare enum ExitCode {
|
||||||
/**
|
/**
|
||||||
* A code indicating that the action was successful
|
* A code indicating that the action was successful
|
||||||
*/
|
*/
|
||||||
Success = 0,
|
Success = 0,
|
||||||
/**
|
/**
|
||||||
* A code indicating that the action was a failure
|
* A code indicating that the action was a failure
|
||||||
*/
|
*/
|
||||||
Failure = 1,
|
Failure = 1,
|
||||||
/**
|
/**
|
||||||
* A code indicating that the action is complete, but neither succeeded nor failed
|
* A code indicating that the action is complete, but neither succeeded nor failed
|
||||||
*/
|
*/
|
||||||
Neutral = 78
|
Neutral = 78
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Exit the action as a success.
|
* Exit the action as a success.
|
||||||
*/
|
*/
|
||||||
export declare function success(): void;
|
export declare function success(): void;
|
||||||
/**
|
/**
|
||||||
* Exit the action as a failure.
|
* Exit the action as a failure.
|
||||||
*/
|
*/
|
||||||
export declare function failure(): void;
|
export declare function failure(): void;
|
||||||
/**
|
/**
|
||||||
* Exit the action neither a success or a failure
|
* Exit the action neither a success or a failure
|
||||||
*/
|
*/
|
||||||
export declare function neutral(): void;
|
export declare function neutral(): void;
|
||||||
|
|
|
@ -1,44 +1,44 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
/**
|
/**
|
||||||
* The code to exit an action
|
* The code to exit an action
|
||||||
*/
|
*/
|
||||||
var ExitCode;
|
var ExitCode;
|
||||||
(function (ExitCode) {
|
(function (ExitCode) {
|
||||||
/**
|
/**
|
||||||
* A code indicating that the action was successful
|
* A code indicating that the action was successful
|
||||||
*/
|
*/
|
||||||
ExitCode[ExitCode["Success"] = 0] = "Success";
|
ExitCode[ExitCode["Success"] = 0] = "Success";
|
||||||
/**
|
/**
|
||||||
* A code indicating that the action was a failure
|
* A code indicating that the action was a failure
|
||||||
*/
|
*/
|
||||||
ExitCode[ExitCode["Failure"] = 1] = "Failure";
|
ExitCode[ExitCode["Failure"] = 1] = "Failure";
|
||||||
/**
|
/**
|
||||||
* A code indicating that the action is complete, but neither succeeded nor failed
|
* A code indicating that the action is complete, but neither succeeded nor failed
|
||||||
*/
|
*/
|
||||||
ExitCode[ExitCode["Neutral"] = 78] = "Neutral";
|
ExitCode[ExitCode["Neutral"] = 78] = "Neutral";
|
||||||
})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
|
})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
|
||||||
// TODO: These exit codes may not behave as expected on the new runtime, due to
|
// TODO: These exit codes may not behave as expected on the new runtime, due to
|
||||||
// complexities of async logging and sync exiting.
|
// complexities of async logging and sync exiting.
|
||||||
/**
|
/**
|
||||||
* Exit the action as a success.
|
* Exit the action as a success.
|
||||||
*/
|
*/
|
||||||
function success() {
|
function success() {
|
||||||
process.exit(ExitCode.Success);
|
process.exit(ExitCode.Success);
|
||||||
}
|
}
|
||||||
exports.success = success;
|
exports.success = success;
|
||||||
/**
|
/**
|
||||||
* Exit the action as a failure.
|
* Exit the action as a failure.
|
||||||
*/
|
*/
|
||||||
function failure() {
|
function failure() {
|
||||||
process.exit(ExitCode.Failure);
|
process.exit(ExitCode.Failure);
|
||||||
}
|
}
|
||||||
exports.failure = failure;
|
exports.failure = failure;
|
||||||
/**
|
/**
|
||||||
* Exit the action neither a success or a failure
|
* Exit the action neither a success or a failure
|
||||||
*/
|
*/
|
||||||
function neutral() {
|
function neutral() {
|
||||||
process.exit(ExitCode.Neutral);
|
process.exit(ExitCode.Neutral);
|
||||||
}
|
}
|
||||||
exports.neutral = neutral;
|
exports.neutral = neutral;
|
||||||
//# sourceMappingURL=exit.js.map
|
//# sourceMappingURL=exit.js.map
|
|
@ -1,49 +1,49 @@
|
||||||
# `@actions/io`
|
# `@actions/io`
|
||||||
|
|
||||||
> Core functions for cli filesystem scenarios
|
> Core functions for cli filesystem scenarios
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/**
|
/**
|
||||||
* Copies a file or folder.
|
* Copies a file or folder.
|
||||||
*
|
*
|
||||||
* @param source source path
|
* @param source source path
|
||||||
* @param dest destination path
|
* @param dest destination path
|
||||||
* @param options optional. See CopyOptions.
|
* @param options optional. See CopyOptions.
|
||||||
*/
|
*/
|
||||||
export function cp(source: string, dest: string, options?: CopyOptions): Promise<void>
|
export function cp(source: string, dest: string, options?: CopyOptions): Promise<void>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a path recursively with force
|
* Remove a path recursively with force
|
||||||
*
|
*
|
||||||
* @param path path to remove
|
* @param path path to remove
|
||||||
*/
|
*/
|
||||||
export function rmRF(path: string): Promise<void>
|
export function rmRF(path: string): Promise<void>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a directory. Creates the full path with folders in between
|
* Make a directory. Creates the full path with folders in between
|
||||||
*
|
*
|
||||||
* @param p path to create
|
* @param p path to create
|
||||||
* @returns Promise<void>
|
* @returns Promise<void>
|
||||||
*/
|
*/
|
||||||
export function mkdirP(p: string): Promise<void>
|
export function mkdirP(p: string): Promise<void>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves a path.
|
* Moves a path.
|
||||||
*
|
*
|
||||||
* @param source source path
|
* @param source source path
|
||||||
* @param dest destination path
|
* @param dest destination path
|
||||||
* @param options optional. See CopyOptions.
|
* @param options optional. See CopyOptions.
|
||||||
*/
|
*/
|
||||||
export function mv(source: string, dest: string, options?: CopyOptions): Promise<void>
|
export function mv(source: string, dest: string, options?: CopyOptions): Promise<void>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
||||||
*
|
*
|
||||||
* @param tool name of the tool
|
* @param tool name of the tool
|
||||||
* @param options optional. See WhichOptions.
|
* @param options optional. See WhichOptions.
|
||||||
* @returns Promise<string> path to tool
|
* @returns Promise<string> path to tool
|
||||||
*/
|
*/
|
||||||
export function which(tool: string, options?: WhichOptions): Promise<string>
|
export function which(tool: string, options?: WhichOptions): Promise<string>
|
||||||
```
|
```
|
|
@ -1,29 +1,29 @@
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
export declare const copyFile: typeof fs.promises.copyFile, lstat: typeof fs.promises.lstat, mkdir: typeof fs.promises.mkdir, readdir: typeof fs.promises.readdir, rmdir: typeof fs.promises.rmdir, stat: typeof fs.promises.stat, unlink: typeof fs.promises.unlink;
|
export declare const copyFile: typeof fs.promises.copyFile, lstat: typeof fs.promises.lstat, mkdir: typeof fs.promises.mkdir, readdir: typeof fs.promises.readdir, rmdir: typeof fs.promises.rmdir, stat: typeof fs.promises.stat, unlink: typeof fs.promises.unlink;
|
||||||
export declare const IS_WINDOWS: boolean;
|
export declare const IS_WINDOWS: boolean;
|
||||||
export declare function exists(fsPath: string): Promise<boolean>;
|
export declare function exists(fsPath: string): Promise<boolean>;
|
||||||
export declare function isDirectory(fsPath: string, useStat?: boolean): Promise<boolean>;
|
export declare function isDirectory(fsPath: string, useStat?: boolean): Promise<boolean>;
|
||||||
/**
|
/**
|
||||||
* On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
|
* On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
|
||||||
* \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
|
* \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
|
||||||
*/
|
*/
|
||||||
export declare function isRooted(p: string): boolean;
|
export declare function isRooted(p: string): boolean;
|
||||||
/**
|
/**
|
||||||
* Recursively create a directory at `fsPath`.
|
* Recursively create a directory at `fsPath`.
|
||||||
*
|
*
|
||||||
* This implementation is optimistic, meaning it attempts to create the full
|
* This implementation is optimistic, meaning it attempts to create the full
|
||||||
* path first, and backs up the path stack from there.
|
* path first, and backs up the path stack from there.
|
||||||
*
|
*
|
||||||
* @param fsPath The path to create
|
* @param fsPath The path to create
|
||||||
* @param maxDepth The maximum recursion depth
|
* @param maxDepth The maximum recursion depth
|
||||||
* @param depth The current recursion depth
|
* @param depth The current recursion depth
|
||||||
*/
|
*/
|
||||||
export declare function mkdirP(fsPath: string, maxDepth?: number, depth?: number): Promise<void>;
|
export declare function mkdirP(fsPath: string, maxDepth?: number, depth?: number): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* Best effort attempt to determine whether a file exists and is executable.
|
* Best effort attempt to determine whether a file exists and is executable.
|
||||||
* @param filePath file path to check
|
* @param filePath file path to check
|
||||||
* @param extensions additional file extensions to try
|
* @param extensions additional file extensions to try
|
||||||
* @return if file exists and is executable, returns the file path. otherwise empty string.
|
* @return if file exists and is executable, returns the file path. otherwise empty string.
|
||||||
*/
|
*/
|
||||||
export declare function tryGetExecutablePath(filePath: string, extensions: string[]): Promise<string>;
|
export declare function tryGetExecutablePath(filePath: string, extensions: string[]): Promise<string>;
|
||||||
|
|
|
@ -1,194 +1,194 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var _a;
|
var _a;
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const assert_1 = require("assert");
|
const assert_1 = require("assert");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
_a = fs.promises, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.unlink = _a.unlink;
|
_a = fs.promises, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.unlink = _a.unlink;
|
||||||
exports.IS_WINDOWS = process.platform === 'win32';
|
exports.IS_WINDOWS = process.platform === 'win32';
|
||||||
function exists(fsPath) {
|
function exists(fsPath) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
yield exports.stat(fsPath);
|
yield exports.stat(fsPath);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (err.code === 'ENOENT') {
|
if (err.code === 'ENOENT') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.exists = exists;
|
exports.exists = exists;
|
||||||
function isDirectory(fsPath, useStat = false) {
|
function isDirectory(fsPath, useStat = false) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath);
|
const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath);
|
||||||
return stats.isDirectory();
|
return stats.isDirectory();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.isDirectory = isDirectory;
|
exports.isDirectory = isDirectory;
|
||||||
/**
|
/**
|
||||||
* On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
|
* On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
|
||||||
* \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
|
* \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
|
||||||
*/
|
*/
|
||||||
function isRooted(p) {
|
function isRooted(p) {
|
||||||
p = normalizeSeparators(p);
|
p = normalizeSeparators(p);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
throw new Error('isRooted() parameter "p" cannot be empty');
|
throw new Error('isRooted() parameter "p" cannot be empty');
|
||||||
}
|
}
|
||||||
if (exports.IS_WINDOWS) {
|
if (exports.IS_WINDOWS) {
|
||||||
return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello
|
return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello
|
||||||
); // e.g. C: or C:\hello
|
); // e.g. C: or C:\hello
|
||||||
}
|
}
|
||||||
return p.startsWith('/');
|
return p.startsWith('/');
|
||||||
}
|
}
|
||||||
exports.isRooted = isRooted;
|
exports.isRooted = isRooted;
|
||||||
/**
|
/**
|
||||||
* Recursively create a directory at `fsPath`.
|
* Recursively create a directory at `fsPath`.
|
||||||
*
|
*
|
||||||
* This implementation is optimistic, meaning it attempts to create the full
|
* This implementation is optimistic, meaning it attempts to create the full
|
||||||
* path first, and backs up the path stack from there.
|
* path first, and backs up the path stack from there.
|
||||||
*
|
*
|
||||||
* @param fsPath The path to create
|
* @param fsPath The path to create
|
||||||
* @param maxDepth The maximum recursion depth
|
* @param maxDepth The maximum recursion depth
|
||||||
* @param depth The current recursion depth
|
* @param depth The current recursion depth
|
||||||
*/
|
*/
|
||||||
function mkdirP(fsPath, maxDepth = 1000, depth = 1) {
|
function mkdirP(fsPath, maxDepth = 1000, depth = 1) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
assert_1.ok(fsPath, 'a path argument must be provided');
|
assert_1.ok(fsPath, 'a path argument must be provided');
|
||||||
fsPath = path.resolve(fsPath);
|
fsPath = path.resolve(fsPath);
|
||||||
if (depth >= maxDepth)
|
if (depth >= maxDepth)
|
||||||
return exports.mkdir(fsPath);
|
return exports.mkdir(fsPath);
|
||||||
try {
|
try {
|
||||||
yield exports.mkdir(fsPath);
|
yield exports.mkdir(fsPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
switch (err.code) {
|
switch (err.code) {
|
||||||
case 'ENOENT': {
|
case 'ENOENT': {
|
||||||
yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1);
|
yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1);
|
||||||
yield exports.mkdir(fsPath);
|
yield exports.mkdir(fsPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
let stats;
|
let stats;
|
||||||
try {
|
try {
|
||||||
stats = yield exports.stat(fsPath);
|
stats = yield exports.stat(fsPath);
|
||||||
}
|
}
|
||||||
catch (err2) {
|
catch (err2) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
if (!stats.isDirectory())
|
if (!stats.isDirectory())
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.mkdirP = mkdirP;
|
exports.mkdirP = mkdirP;
|
||||||
/**
|
/**
|
||||||
* Best effort attempt to determine whether a file exists and is executable.
|
* Best effort attempt to determine whether a file exists and is executable.
|
||||||
* @param filePath file path to check
|
* @param filePath file path to check
|
||||||
* @param extensions additional file extensions to try
|
* @param extensions additional file extensions to try
|
||||||
* @return if file exists and is executable, returns the file path. otherwise empty string.
|
* @return if file exists and is executable, returns the file path. otherwise empty string.
|
||||||
*/
|
*/
|
||||||
function tryGetExecutablePath(filePath, extensions) {
|
function tryGetExecutablePath(filePath, extensions) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let stats = undefined;
|
let stats = undefined;
|
||||||
try {
|
try {
|
||||||
// test file exists
|
// test file exists
|
||||||
stats = yield exports.stat(filePath);
|
stats = yield exports.stat(filePath);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (err.code !== 'ENOENT') {
|
if (err.code !== 'ENOENT') {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
|
console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stats && stats.isFile()) {
|
if (stats && stats.isFile()) {
|
||||||
if (exports.IS_WINDOWS) {
|
if (exports.IS_WINDOWS) {
|
||||||
// on Windows, test for valid extension
|
// on Windows, test for valid extension
|
||||||
const upperExt = path.extname(filePath).toUpperCase();
|
const upperExt = path.extname(filePath).toUpperCase();
|
||||||
if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) {
|
if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) {
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isUnixExecutable(stats)) {
|
if (isUnixExecutable(stats)) {
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// try each extension
|
// try each extension
|
||||||
const originalFilePath = filePath;
|
const originalFilePath = filePath;
|
||||||
for (const extension of extensions) {
|
for (const extension of extensions) {
|
||||||
filePath = originalFilePath + extension;
|
filePath = originalFilePath + extension;
|
||||||
stats = undefined;
|
stats = undefined;
|
||||||
try {
|
try {
|
||||||
stats = yield exports.stat(filePath);
|
stats = yield exports.stat(filePath);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (err.code !== 'ENOENT') {
|
if (err.code !== 'ENOENT') {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
|
console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stats && stats.isFile()) {
|
if (stats && stats.isFile()) {
|
||||||
if (exports.IS_WINDOWS) {
|
if (exports.IS_WINDOWS) {
|
||||||
// preserve the case of the actual file (since an extension was appended)
|
// preserve the case of the actual file (since an extension was appended)
|
||||||
try {
|
try {
|
||||||
const directory = path.dirname(filePath);
|
const directory = path.dirname(filePath);
|
||||||
const upperName = path.basename(filePath).toUpperCase();
|
const upperName = path.basename(filePath).toUpperCase();
|
||||||
for (const actualName of yield exports.readdir(directory)) {
|
for (const actualName of yield exports.readdir(directory)) {
|
||||||
if (upperName === actualName.toUpperCase()) {
|
if (upperName === actualName.toUpperCase()) {
|
||||||
filePath = path.join(directory, actualName);
|
filePath = path.join(directory, actualName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`);
|
console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`);
|
||||||
}
|
}
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isUnixExecutable(stats)) {
|
if (isUnixExecutable(stats)) {
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.tryGetExecutablePath = tryGetExecutablePath;
|
exports.tryGetExecutablePath = tryGetExecutablePath;
|
||||||
function normalizeSeparators(p) {
|
function normalizeSeparators(p) {
|
||||||
p = p || '';
|
p = p || '';
|
||||||
if (exports.IS_WINDOWS) {
|
if (exports.IS_WINDOWS) {
|
||||||
// convert slashes on Windows
|
// convert slashes on Windows
|
||||||
p = p.replace(/\//g, '\\');
|
p = p.replace(/\//g, '\\');
|
||||||
// remove redundant slashes
|
// remove redundant slashes
|
||||||
return p.replace(/\\\\+/g, '\\');
|
return p.replace(/\\\\+/g, '\\');
|
||||||
}
|
}
|
||||||
// remove redundant slashes
|
// remove redundant slashes
|
||||||
return p.replace(/\/\/+/g, '/');
|
return p.replace(/\/\/+/g, '/');
|
||||||
}
|
}
|
||||||
// on Mac/Linux, test the execute bit
|
// on Mac/Linux, test the execute bit
|
||||||
// R W X R W X R W X
|
// R W X R W X R W X
|
||||||
// 256 128 64 32 16 8 4 2 1
|
// 256 128 64 32 16 8 4 2 1
|
||||||
function isUnixExecutable(stats) {
|
function isUnixExecutable(stats) {
|
||||||
return ((stats.mode & 1) > 0 ||
|
return ((stats.mode & 1) > 0 ||
|
||||||
((stats.mode & 8) > 0 && stats.gid === process.getgid()) ||
|
((stats.mode & 8) > 0 && stats.gid === process.getgid()) ||
|
||||||
((stats.mode & 64) > 0 && stats.uid === process.getuid()));
|
((stats.mode & 64) > 0 && stats.uid === process.getuid()));
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=io-util.js.map
|
//# sourceMappingURL=io-util.js.map
|
|
@ -1,48 +1,48 @@
|
||||||
/**
|
/**
|
||||||
* Interface for cp/mv options
|
* Interface for cp/mv options
|
||||||
*/
|
*/
|
||||||
export interface CopyOptions {
|
export interface CopyOptions {
|
||||||
/** Optional. Whether to recursively copy all subdirectories. Defaults to false */
|
/** Optional. Whether to recursively copy all subdirectories. Defaults to false */
|
||||||
recursive?: boolean;
|
recursive?: boolean;
|
||||||
/** Optional. Whether to overwrite existing files in the destination. Defaults to true */
|
/** Optional. Whether to overwrite existing files in the destination. Defaults to true */
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Copies a file or folder.
|
* Copies a file or folder.
|
||||||
*
|
*
|
||||||
* @param source source path
|
* @param source source path
|
||||||
* @param dest destination path
|
* @param dest destination path
|
||||||
* @param options optional. See CopyOptions.
|
* @param options optional. See CopyOptions.
|
||||||
*/
|
*/
|
||||||
export declare function cp(source: string, dest: string, options?: CopyOptions): Promise<void>;
|
export declare function cp(source: string, dest: string, options?: CopyOptions): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* Moves a path.
|
* Moves a path.
|
||||||
*
|
*
|
||||||
* @param source source path
|
* @param source source path
|
||||||
* @param dest destination path
|
* @param dest destination path
|
||||||
* @param options optional. See CopyOptions.
|
* @param options optional. See CopyOptions.
|
||||||
*/
|
*/
|
||||||
export declare function mv(source: string, dest: string, options?: CopyOptions): Promise<void>;
|
export declare function mv(source: string, dest: string, options?: CopyOptions): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* Remove a path recursively with force
|
* Remove a path recursively with force
|
||||||
*
|
*
|
||||||
* @param inputPath path to remove
|
* @param inputPath path to remove
|
||||||
*/
|
*/
|
||||||
export declare function rmRF(inputPath: string): Promise<void>;
|
export declare function rmRF(inputPath: string): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* Make a directory. Creates the full path with folders in between
|
* Make a directory. Creates the full path with folders in between
|
||||||
* Will throw if it fails
|
* Will throw if it fails
|
||||||
*
|
*
|
||||||
* @param fsPath path to create
|
* @param fsPath path to create
|
||||||
* @returns Promise<void>
|
* @returns Promise<void>
|
||||||
*/
|
*/
|
||||||
export declare function mkdirP(fsPath: string): Promise<void>;
|
export declare function mkdirP(fsPath: string): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
||||||
* If you check and the tool does not exist, it will throw.
|
* If you check and the tool does not exist, it will throw.
|
||||||
*
|
*
|
||||||
* @param tool name of the tool
|
* @param tool name of the tool
|
||||||
* @param check whether to check if tool exists
|
* @param check whether to check if tool exists
|
||||||
* @returns Promise<string> path to tool
|
* @returns Promise<string> path to tool
|
||||||
*/
|
*/
|
||||||
export declare function which(tool: string, check?: boolean): Promise<string>;
|
export declare function which(tool: string, check?: boolean): Promise<string>;
|
||||||
|
|
|
@ -1,262 +1,262 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const childProcess = require("child_process");
|
const childProcess = require("child_process");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const util_1 = require("util");
|
const util_1 = require("util");
|
||||||
const ioUtil = require("./io-util");
|
const ioUtil = require("./io-util");
|
||||||
const exec = util_1.promisify(childProcess.exec);
|
const exec = util_1.promisify(childProcess.exec);
|
||||||
/**
|
/**
|
||||||
* Copies a file or folder.
|
* Copies a file or folder.
|
||||||
*
|
*
|
||||||
* @param source source path
|
* @param source source path
|
||||||
* @param dest destination path
|
* @param dest destination path
|
||||||
* @param options optional. See CopyOptions.
|
* @param options optional. See CopyOptions.
|
||||||
*/
|
*/
|
||||||
function cp(source, dest, options = {}) {
|
function cp(source, dest, options = {}) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
yield move(source, dest, options, { deleteOriginal: false });
|
yield move(source, dest, options, { deleteOriginal: false });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.cp = cp;
|
exports.cp = cp;
|
||||||
/**
|
/**
|
||||||
* Moves a path.
|
* Moves a path.
|
||||||
*
|
*
|
||||||
* @param source source path
|
* @param source source path
|
||||||
* @param dest destination path
|
* @param dest destination path
|
||||||
* @param options optional. See CopyOptions.
|
* @param options optional. See CopyOptions.
|
||||||
*/
|
*/
|
||||||
function mv(source, dest, options = {}) {
|
function mv(source, dest, options = {}) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
yield move(source, dest, options, { deleteOriginal: true });
|
yield move(source, dest, options, { deleteOriginal: true });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.mv = mv;
|
exports.mv = mv;
|
||||||
/**
|
/**
|
||||||
* Remove a path recursively with force
|
* Remove a path recursively with force
|
||||||
*
|
*
|
||||||
* @param inputPath path to remove
|
* @param inputPath path to remove
|
||||||
*/
|
*/
|
||||||
function rmRF(inputPath) {
|
function rmRF(inputPath) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (ioUtil.IS_WINDOWS) {
|
if (ioUtil.IS_WINDOWS) {
|
||||||
// Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
|
// Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
|
||||||
// program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
|
// program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
|
||||||
try {
|
try {
|
||||||
if (yield ioUtil.isDirectory(inputPath, true)) {
|
if (yield ioUtil.isDirectory(inputPath, true)) {
|
||||||
yield exec(`rd /s /q "${inputPath}"`);
|
yield exec(`rd /s /q "${inputPath}"`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
yield exec(`del /f /a "${inputPath}"`);
|
yield exec(`del /f /a "${inputPath}"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// if you try to delete a file that doesn't exist, desired result is achieved
|
// if you try to delete a file that doesn't exist, desired result is achieved
|
||||||
// other errors are valid
|
// other errors are valid
|
||||||
if (err.code !== 'ENOENT')
|
if (err.code !== 'ENOENT')
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
// Shelling out fails to remove a symlink folder with missing source, this unlink catches that
|
// Shelling out fails to remove a symlink folder with missing source, this unlink catches that
|
||||||
try {
|
try {
|
||||||
yield ioUtil.unlink(inputPath);
|
yield ioUtil.unlink(inputPath);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// if you try to delete a file that doesn't exist, desired result is achieved
|
// if you try to delete a file that doesn't exist, desired result is achieved
|
||||||
// other errors are valid
|
// other errors are valid
|
||||||
if (err.code !== 'ENOENT')
|
if (err.code !== 'ENOENT')
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let isDir = false;
|
let isDir = false;
|
||||||
try {
|
try {
|
||||||
isDir = yield ioUtil.isDirectory(inputPath);
|
isDir = yield ioUtil.isDirectory(inputPath);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// if you try to delete a file that doesn't exist, desired result is achieved
|
// if you try to delete a file that doesn't exist, desired result is achieved
|
||||||
// other errors are valid
|
// other errors are valid
|
||||||
if (err.code !== 'ENOENT')
|
if (err.code !== 'ENOENT')
|
||||||
throw err;
|
throw err;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isDir) {
|
if (isDir) {
|
||||||
yield exec(`rm -rf "${inputPath}"`);
|
yield exec(`rm -rf "${inputPath}"`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
yield ioUtil.unlink(inputPath);
|
yield ioUtil.unlink(inputPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.rmRF = rmRF;
|
exports.rmRF = rmRF;
|
||||||
/**
|
/**
|
||||||
* Make a directory. Creates the full path with folders in between
|
* Make a directory. Creates the full path with folders in between
|
||||||
* Will throw if it fails
|
* Will throw if it fails
|
||||||
*
|
*
|
||||||
* @param fsPath path to create
|
* @param fsPath path to create
|
||||||
* @returns Promise<void>
|
* @returns Promise<void>
|
||||||
*/
|
*/
|
||||||
function mkdirP(fsPath) {
|
function mkdirP(fsPath) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
yield ioUtil.mkdirP(fsPath);
|
yield ioUtil.mkdirP(fsPath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.mkdirP = mkdirP;
|
exports.mkdirP = mkdirP;
|
||||||
/**
|
/**
|
||||||
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
||||||
* If you check and the tool does not exist, it will throw.
|
* If you check and the tool does not exist, it will throw.
|
||||||
*
|
*
|
||||||
* @param tool name of the tool
|
* @param tool name of the tool
|
||||||
* @param check whether to check if tool exists
|
* @param check whether to check if tool exists
|
||||||
* @returns Promise<string> path to tool
|
* @returns Promise<string> path to tool
|
||||||
*/
|
*/
|
||||||
function which(tool, check) {
|
function which(tool, check) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (!tool) {
|
if (!tool) {
|
||||||
throw new Error("parameter 'tool' is required");
|
throw new Error("parameter 'tool' is required");
|
||||||
}
|
}
|
||||||
// recursive when check=true
|
// recursive when check=true
|
||||||
if (check) {
|
if (check) {
|
||||||
const result = yield which(tool, false);
|
const result = yield which(tool, false);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
if (ioUtil.IS_WINDOWS) {
|
if (ioUtil.IS_WINDOWS) {
|
||||||
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);
|
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`);
|
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// build the list of extensions to try
|
// build the list of extensions to try
|
||||||
const extensions = [];
|
const extensions = [];
|
||||||
if (ioUtil.IS_WINDOWS && process.env.PATHEXT) {
|
if (ioUtil.IS_WINDOWS && process.env.PATHEXT) {
|
||||||
for (const extension of process.env.PATHEXT.split(path.delimiter)) {
|
for (const extension of process.env.PATHEXT.split(path.delimiter)) {
|
||||||
if (extension) {
|
if (extension) {
|
||||||
extensions.push(extension);
|
extensions.push(extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if it's rooted, return it if exists. otherwise return empty.
|
// if it's rooted, return it if exists. otherwise return empty.
|
||||||
if (ioUtil.isRooted(tool)) {
|
if (ioUtil.isRooted(tool)) {
|
||||||
const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions);
|
const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions);
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
// if any path separators, return empty
|
// if any path separators, return empty
|
||||||
if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) {
|
if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
// build the list of directories
|
// build the list of directories
|
||||||
//
|
//
|
||||||
// Note, technically "where" checks the current directory on Windows. From a task lib perspective,
|
// Note, technically "where" checks the current directory on Windows. From a task lib perspective,
|
||||||
// it feels like we should not do this. Checking the current directory seems like more of a use
|
// it feels like we should not do this. Checking the current directory seems like more of a use
|
||||||
// case of a shell, and the which() function exposed by the task lib should strive for consistency
|
// case of a shell, and the which() function exposed by the task lib should strive for consistency
|
||||||
// across platforms.
|
// across platforms.
|
||||||
const directories = [];
|
const directories = [];
|
||||||
if (process.env.PATH) {
|
if (process.env.PATH) {
|
||||||
for (const p of process.env.PATH.split(path.delimiter)) {
|
for (const p of process.env.PATH.split(path.delimiter)) {
|
||||||
if (p) {
|
if (p) {
|
||||||
directories.push(p);
|
directories.push(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return the first match
|
// return the first match
|
||||||
for (const directory of directories) {
|
for (const directory of directories) {
|
||||||
const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions);
|
const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions);
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
throw new Error(`which failed with message ${err.message}`);
|
throw new Error(`which failed with message ${err.message}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.which = which;
|
exports.which = which;
|
||||||
// Copies contents of source into dest, making any necessary folders along the way.
|
// Copies contents of source into dest, making any necessary folders along the way.
|
||||||
// Deletes the original copy if deleteOriginal is true
|
// Deletes the original copy if deleteOriginal is true
|
||||||
function copyDirectoryContents(source, dest, force, deleteOriginal = false) {
|
function copyDirectoryContents(source, dest, force, deleteOriginal = false) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (yield ioUtil.isDirectory(source)) {
|
if (yield ioUtil.isDirectory(source)) {
|
||||||
if (yield ioUtil.exists(dest)) {
|
if (yield ioUtil.exists(dest)) {
|
||||||
if (!(yield ioUtil.isDirectory(dest))) {
|
if (!(yield ioUtil.isDirectory(dest))) {
|
||||||
throw new Error(`${dest} is not a directory`);
|
throw new Error(`${dest} is not a directory`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
yield mkdirP(dest);
|
yield mkdirP(dest);
|
||||||
}
|
}
|
||||||
// Copy all child files, and directories recursively
|
// Copy all child files, and directories recursively
|
||||||
const sourceChildren = yield ioUtil.readdir(source);
|
const sourceChildren = yield ioUtil.readdir(source);
|
||||||
for (const newSource of sourceChildren) {
|
for (const newSource of sourceChildren) {
|
||||||
const newDest = path.join(dest, path.basename(newSource));
|
const newDest = path.join(dest, path.basename(newSource));
|
||||||
yield copyDirectoryContents(path.resolve(source, newSource), newDest, force, deleteOriginal);
|
yield copyDirectoryContents(path.resolve(source, newSource), newDest, force, deleteOriginal);
|
||||||
}
|
}
|
||||||
if (deleteOriginal) {
|
if (deleteOriginal) {
|
||||||
yield ioUtil.rmdir(source);
|
yield ioUtil.rmdir(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (force) {
|
if (force) {
|
||||||
yield ioUtil.copyFile(source, dest);
|
yield ioUtil.copyFile(source, dest);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
yield ioUtil.copyFile(source, dest, fs.constants.COPYFILE_EXCL);
|
yield ioUtil.copyFile(source, dest, fs.constants.COPYFILE_EXCL);
|
||||||
}
|
}
|
||||||
if (deleteOriginal) {
|
if (deleteOriginal) {
|
||||||
yield ioUtil.unlink(source);
|
yield ioUtil.unlink(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function move(source, dest, options = {}, moveOptions) {
|
function move(source, dest, options = {}, moveOptions) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const { force, recursive } = readCopyOptions(options);
|
const { force, recursive } = readCopyOptions(options);
|
||||||
if (yield ioUtil.isDirectory(source)) {
|
if (yield ioUtil.isDirectory(source)) {
|
||||||
if (!recursive) {
|
if (!recursive) {
|
||||||
throw new Error(`non-recursive cp failed, ${source} is a directory`);
|
throw new Error(`non-recursive cp failed, ${source} is a directory`);
|
||||||
}
|
}
|
||||||
// If directory exists, move source inside it. Otherwise, create it and move contents of source inside.
|
// If directory exists, move source inside it. Otherwise, create it and move contents of source inside.
|
||||||
if (yield ioUtil.exists(dest)) {
|
if (yield ioUtil.exists(dest)) {
|
||||||
if (!(yield ioUtil.isDirectory(dest))) {
|
if (!(yield ioUtil.isDirectory(dest))) {
|
||||||
throw new Error(`${dest} is not a directory`);
|
throw new Error(`${dest} is not a directory`);
|
||||||
}
|
}
|
||||||
dest = path.join(dest, path.basename(source));
|
dest = path.join(dest, path.basename(source));
|
||||||
}
|
}
|
||||||
yield copyDirectoryContents(source, dest, force, moveOptions.deleteOriginal);
|
yield copyDirectoryContents(source, dest, force, moveOptions.deleteOriginal);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((yield ioUtil.exists(dest)) && (yield ioUtil.isDirectory(dest))) {
|
if ((yield ioUtil.exists(dest)) && (yield ioUtil.isDirectory(dest))) {
|
||||||
dest = path.join(dest, path.basename(source));
|
dest = path.join(dest, path.basename(source));
|
||||||
}
|
}
|
||||||
if (force) {
|
if (force) {
|
||||||
yield ioUtil.copyFile(source, dest);
|
yield ioUtil.copyFile(source, dest);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
yield ioUtil.copyFile(source, dest, fs.constants.COPYFILE_EXCL);
|
yield ioUtil.copyFile(source, dest, fs.constants.COPYFILE_EXCL);
|
||||||
}
|
}
|
||||||
if (moveOptions.deleteOriginal) {
|
if (moveOptions.deleteOriginal) {
|
||||||
yield ioUtil.unlink(source);
|
yield ioUtil.unlink(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function readCopyOptions(options) {
|
function readCopyOptions(options) {
|
||||||
const force = options.force == null ? true : options.force;
|
const force = options.force == null ? true : options.force;
|
||||||
const recursive = Boolean(options.recursive);
|
const recursive = Boolean(options.recursive);
|
||||||
return { force, recursive };
|
return { force, recursive };
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=io.js.map
|
//# sourceMappingURL=io.js.map
|
|
@ -1,7 +1,82 @@
|
||||||
# `@actions/tool-cache`
|
# `@actions/tool-cache`
|
||||||
|
|
||||||
> Functions necessary for downloading and caching tools.
|
> Functions necessary for downloading and caching tools.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
See [src/tool-cache.ts](src/tool-cache.ts).
|
#### Download
|
||||||
|
|
||||||
|
You can use this to download tools (or other files) from a download URL:
|
||||||
|
|
||||||
|
```
|
||||||
|
const tc = require('@actions/tool-cache');
|
||||||
|
|
||||||
|
const node12Path = await tc.downloadTool('http://nodejs.org/dist/v12.7.0/node-v12.7.0-linux-x64.tar.gz');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Extract
|
||||||
|
|
||||||
|
These can then be extracted in platform specific ways:
|
||||||
|
|
||||||
|
```
|
||||||
|
const tc = require('@actions/tool-cache');
|
||||||
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
tc.downloadTool('http://nodejs.org/dist/v12.7.0/node-v12.7.0-win-x64.zip');
|
||||||
|
const node12ExtractedFolder = await tc.extractZip(node12Path, 'path/to/extract/to');
|
||||||
|
|
||||||
|
// Or alternately
|
||||||
|
tc.downloadTool('http://nodejs.org/dist/v12.7.0/node-v12.7.0-win-x64.7z');
|
||||||
|
const node12ExtractedFolder = await tc.extract7z(node12Path, 'path/to/extract/to');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const node12Path = await tc.downloadTool('http://nodejs.org/dist/v12.7.0/node-v12.7.0-linux-x64.tar.gz');
|
||||||
|
const node12ExtractedFolder = await tc.extractTar(node12Path, 'path/to/extract/to');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Cache
|
||||||
|
|
||||||
|
Finally, you can cache these directories in our tool-cache. This is useful if you want to switch back and forth between versions of a tool, or save a tool between runs for private runners (private runners are still in development but are on the roadmap).
|
||||||
|
|
||||||
|
You'll often want to add it to the path as part of this step:
|
||||||
|
|
||||||
|
```
|
||||||
|
const tc = require('@actions/tool-cache');
|
||||||
|
const core = require('@actions/core');
|
||||||
|
|
||||||
|
const node12Path = await tc.downloadTool('http://nodejs.org/dist/v12.7.0/node-v12.7.0-linux-x64.tar.gz');
|
||||||
|
const node12ExtractedFolder = await tc.extractTar(node12Path, 'path/to/extract/to');
|
||||||
|
|
||||||
|
const cachedPath = await tc.cacheDir(node12ExtractedFolder, 'node', '12.7.0');
|
||||||
|
core.addPath(cachedPath);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also cache files for reuse.
|
||||||
|
|
||||||
|
```
|
||||||
|
const tc = require('@actions/tool-cache');
|
||||||
|
|
||||||
|
tc.cacheFile('path/to/exe', 'destFileName.exe', 'myExeName', '1.1.0');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Find
|
||||||
|
|
||||||
|
Finally, you can find directories and files you've previously cached:
|
||||||
|
|
||||||
|
```
|
||||||
|
const tc = require('@actions/tool-cache');
|
||||||
|
const core = require('@actions/core');
|
||||||
|
|
||||||
|
const nodeDirectory = tc.find('node', '12.x', 'x64');
|
||||||
|
core.addPath(nodeDirectory);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can even find all cached versions of a tool:
|
||||||
|
|
||||||
|
```
|
||||||
|
const tc = require('@actions/tool-cache');
|
||||||
|
|
||||||
|
const allNodeVersions = tc.findAllVersions('node');
|
||||||
|
console.log(`Versions of node available: ${allNodeVersions}`);
|
||||||
|
```
|
||||||
|
|
|
@ -1,78 +1,78 @@
|
||||||
export declare class HTTPError extends Error {
|
export declare class HTTPError extends Error {
|
||||||
readonly httpStatusCode: number | undefined;
|
readonly httpStatusCode: number | undefined;
|
||||||
constructor(httpStatusCode: number | undefined);
|
constructor(httpStatusCode: number | undefined);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Download a tool from an url and stream it into a file
|
* Download a tool from an url and stream it into a file
|
||||||
*
|
*
|
||||||
* @param url url of tool to download
|
* @param url url of tool to download
|
||||||
* @returns path to downloaded tool
|
* @returns path to downloaded tool
|
||||||
*/
|
*/
|
||||||
export declare function downloadTool(url: string): Promise<string>;
|
export declare function downloadTool(url: string): Promise<string>;
|
||||||
/**
|
/**
|
||||||
* Extract a .7z file
|
* Extract a .7z file
|
||||||
*
|
*
|
||||||
* @param file path to the .7z file
|
* @param file path to the .7z file
|
||||||
* @param dest destination directory. Optional.
|
* @param dest destination directory. Optional.
|
||||||
* @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this
|
* @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this
|
||||||
* problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will
|
* problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will
|
||||||
* gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is
|
* gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is
|
||||||
* bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line
|
* bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line
|
||||||
* interface, it is smaller than the full command line interface, and it does support long paths. At the
|
* interface, it is smaller than the full command line interface, and it does support long paths. At the
|
||||||
* time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website.
|
* time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website.
|
||||||
* Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path
|
* Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path
|
||||||
* to 7zr.exe can be pass to this function.
|
* to 7zr.exe can be pass to this function.
|
||||||
* @returns path to the destination directory
|
* @returns path to the destination directory
|
||||||
*/
|
*/
|
||||||
export declare function extract7z(file: string, dest?: string, _7zPath?: string): Promise<string>;
|
export declare function extract7z(file: string, dest?: string, _7zPath?: string): Promise<string>;
|
||||||
/**
|
/**
|
||||||
* Extract a tar
|
* Extract a tar
|
||||||
*
|
*
|
||||||
* @param file path to the tar
|
* @param file path to the tar
|
||||||
* @param dest destination directory. Optional.
|
* @param dest destination directory. Optional.
|
||||||
* @returns path to the destination directory
|
* @returns path to the destination directory
|
||||||
*/
|
*/
|
||||||
export declare function extractTar(file: string, dest?: string): Promise<string>;
|
export declare function extractTar(file: string, dest?: string): Promise<string>;
|
||||||
/**
|
/**
|
||||||
* Extract a zip
|
* Extract a zip
|
||||||
*
|
*
|
||||||
* @param file path to the zip
|
* @param file path to the zip
|
||||||
* @param dest destination directory. Optional.
|
* @param dest destination directory. Optional.
|
||||||
* @returns path to the destination directory
|
* @returns path to the destination directory
|
||||||
*/
|
*/
|
||||||
export declare function extractZip(file: string, dest?: string): Promise<string>;
|
export declare function extractZip(file: string, dest?: string): Promise<string>;
|
||||||
/**
|
/**
|
||||||
* Caches a directory and installs it into the tool cacheDir
|
* Caches a directory and installs it into the tool cacheDir
|
||||||
*
|
*
|
||||||
* @param sourceDir the directory to cache into tools
|
* @param sourceDir the directory to cache into tools
|
||||||
* @param tool tool name
|
* @param tool tool name
|
||||||
* @param version version of the tool. semver format
|
* @param version version of the tool. semver format
|
||||||
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
||||||
*/
|
*/
|
||||||
export declare function cacheDir(sourceDir: string, tool: string, version: string, arch?: string): Promise<string>;
|
export declare function cacheDir(sourceDir: string, tool: string, version: string, arch?: string): Promise<string>;
|
||||||
/**
|
/**
|
||||||
* Caches a downloaded file (GUID) and installs it
|
* Caches a downloaded file (GUID) and installs it
|
||||||
* into the tool cache with a given targetName
|
* into the tool cache with a given targetName
|
||||||
*
|
*
|
||||||
* @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid.
|
* @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid.
|
||||||
* @param targetFile the name of the file name in the tools directory
|
* @param targetFile the name of the file name in the tools directory
|
||||||
* @param tool tool name
|
* @param tool tool name
|
||||||
* @param version version of the tool. semver format
|
* @param version version of the tool. semver format
|
||||||
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
||||||
*/
|
*/
|
||||||
export declare function cacheFile(sourceFile: string, targetFile: string, tool: string, version: string, arch?: string): Promise<string>;
|
export declare function cacheFile(sourceFile: string, targetFile: string, tool: string, version: string, arch?: string): Promise<string>;
|
||||||
/**
|
/**
|
||||||
* Finds the path to a tool version in the local installed tool cache
|
* Finds the path to a tool version in the local installed tool cache
|
||||||
*
|
*
|
||||||
* @param toolName name of the tool
|
* @param toolName name of the tool
|
||||||
* @param versionSpec version of the tool
|
* @param versionSpec version of the tool
|
||||||
* @param arch optional arch. defaults to arch of computer
|
* @param arch optional arch. defaults to arch of computer
|
||||||
*/
|
*/
|
||||||
export declare function find(toolName: string, versionSpec: string, arch?: string): string;
|
export declare function find(toolName: string, versionSpec: string, arch?: string): string;
|
||||||
/**
|
/**
|
||||||
* Finds the paths to all versions of a tool that are installed in the local tool cache
|
* Finds the paths to all versions of a tool that are installed in the local tool cache
|
||||||
*
|
*
|
||||||
* @param toolName name of the tool
|
* @param toolName name of the tool
|
||||||
* @param arch optional arch. defaults to arch of computer
|
* @param arch optional arch. defaults to arch of computer
|
||||||
*/
|
*/
|
||||||
export declare function findAllVersions(toolName: string, arch?: string): string[];
|
export declare function findAllVersions(toolName: string, arch?: string): string[];
|
||||||
|
|
|
@ -1,437 +1,436 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = require("@actions/core");
|
const core = require("@actions/core");
|
||||||
const io = require("@actions/io");
|
const io = require("@actions/io");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const os = require("os");
|
const os = require("os");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const httpm = require("typed-rest-client/HttpClient");
|
const httpm = require("typed-rest-client/HttpClient");
|
||||||
const semver = require("semver");
|
const semver = require("semver");
|
||||||
const shell = require("shelljs");
|
const uuidV4 = require("uuid/v4");
|
||||||
const uuidV4 = require("uuid/v4");
|
const exec_1 = require("@actions/exec/lib/exec");
|
||||||
const exec_1 = require("@actions/exec/lib/exec");
|
const assert_1 = require("assert");
|
||||||
const assert_1 = require("assert");
|
class HTTPError extends Error {
|
||||||
class HTTPError extends Error {
|
constructor(httpStatusCode) {
|
||||||
constructor(httpStatusCode) {
|
super(`Unexpected HTTP response: ${httpStatusCode}`);
|
||||||
super(`Unexpected HTTP response: ${httpStatusCode}`);
|
this.httpStatusCode = httpStatusCode;
|
||||||
this.httpStatusCode = httpStatusCode;
|
Object.setPrototypeOf(this, new.target.prototype);
|
||||||
Object.setPrototypeOf(this, new.target.prototype);
|
}
|
||||||
}
|
}
|
||||||
}
|
exports.HTTPError = HTTPError;
|
||||||
exports.HTTPError = HTTPError;
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
const IS_WINDOWS = process.platform === 'win32';
|
const userAgent = 'actions/tool-cache';
|
||||||
const userAgent = 'actions/tool-cache';
|
// On load grab temp directory and cache directory and remove them from env (currently don't want to expose this)
|
||||||
// On load grab temp directory and cache directory and remove them from env (currently don't want to expose this)
|
let tempDirectory = process.env['RUNNER_TEMP'] || '';
|
||||||
let tempDirectory = process.env['RUNNER_TEMP'] || '';
|
let cacheRoot = process.env['RUNNER_TOOL_CACHE'] || '';
|
||||||
let cacheRoot = process.env['RUNNER_TOOL_CACHE'] || '';
|
// If directories not found, place them in common temp locations
|
||||||
// If directories not found, place them in common temp locations
|
if (!tempDirectory || !cacheRoot) {
|
||||||
if (!tempDirectory || !cacheRoot) {
|
let baseLocation;
|
||||||
let baseLocation;
|
if (IS_WINDOWS) {
|
||||||
if (IS_WINDOWS) {
|
// On windows use the USERPROFILE env variable
|
||||||
// On windows use the USERPROFILE env variable
|
baseLocation = process.env['USERPROFILE'] || 'C:\\';
|
||||||
baseLocation = process.env['USERPROFILE'] || 'C:\\';
|
}
|
||||||
}
|
else {
|
||||||
else {
|
if (process.platform === 'darwin') {
|
||||||
if (process.platform === 'darwin') {
|
baseLocation = '/Users';
|
||||||
baseLocation = '/Users';
|
}
|
||||||
}
|
else {
|
||||||
else {
|
baseLocation = '/home';
|
||||||
baseLocation = '/home';
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!tempDirectory) {
|
||||||
if (!tempDirectory) {
|
tempDirectory = path.join(baseLocation, 'actions', 'temp');
|
||||||
tempDirectory = path.join(baseLocation, 'actions', 'temp');
|
}
|
||||||
}
|
if (!cacheRoot) {
|
||||||
if (!cacheRoot) {
|
cacheRoot = path.join(baseLocation, 'actions', 'cache');
|
||||||
cacheRoot = path.join(baseLocation, 'actions', 'cache');
|
}
|
||||||
}
|
}
|
||||||
}
|
/**
|
||||||
/**
|
* Download a tool from an url and stream it into a file
|
||||||
* Download a tool from an url and stream it into a file
|
*
|
||||||
*
|
* @param url url of tool to download
|
||||||
* @param url url of tool to download
|
* @returns path to downloaded tool
|
||||||
* @returns path to downloaded tool
|
*/
|
||||||
*/
|
function downloadTool(url) {
|
||||||
function downloadTool(url) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
// Wrap in a promise so that we can resolve from within stream callbacks
|
||||||
// Wrap in a promise so that we can resolve from within stream callbacks
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
||||||
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
try {
|
||||||
try {
|
const http = new httpm.HttpClient(userAgent, [], {
|
||||||
const http = new httpm.HttpClient(userAgent, [], {
|
allowRetries: true,
|
||||||
allowRetries: true,
|
maxRetries: 3
|
||||||
maxRetries: 3
|
});
|
||||||
});
|
const destPath = path.join(tempDirectory, uuidV4());
|
||||||
const destPath = path.join(tempDirectory, uuidV4());
|
yield io.mkdirP(tempDirectory);
|
||||||
yield io.mkdirP(tempDirectory);
|
core.debug(`Downloading ${url}`);
|
||||||
core.debug(`Downloading ${url}`);
|
core.debug(`Downloading ${destPath}`);
|
||||||
core.debug(`Downloading ${destPath}`);
|
if (fs.existsSync(destPath)) {
|
||||||
if (fs.existsSync(destPath)) {
|
throw new Error(`Destination file path ${destPath} already exists`);
|
||||||
throw new Error(`Destination file path ${destPath} already exists`);
|
}
|
||||||
}
|
const response = yield http.get(url);
|
||||||
const response = yield http.get(url);
|
if (response.message.statusCode !== 200) {
|
||||||
if (response.message.statusCode !== 200) {
|
const err = new HTTPError(response.message.statusCode);
|
||||||
const err = new HTTPError(response.message.statusCode);
|
core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`);
|
||||||
core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`);
|
throw err;
|
||||||
throw err;
|
}
|
||||||
}
|
const file = fs.createWriteStream(destPath);
|
||||||
const file = fs.createWriteStream(destPath);
|
file.on('open', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
file.on('open', () => __awaiter(this, void 0, void 0, function* () {
|
try {
|
||||||
try {
|
const stream = response.message.pipe(file);
|
||||||
const stream = response.message.pipe(file);
|
stream.on('close', () => {
|
||||||
stream.on('close', () => {
|
core.debug('download complete');
|
||||||
core.debug('download complete');
|
resolve(destPath);
|
||||||
resolve(destPath);
|
});
|
||||||
});
|
}
|
||||||
}
|
catch (err) {
|
||||||
catch (err) {
|
core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`);
|
||||||
core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`);
|
reject(err);
|
||||||
reject(err);
|
}
|
||||||
}
|
}));
|
||||||
}));
|
file.on('error', err => {
|
||||||
file.on('error', err => {
|
file.end();
|
||||||
file.end();
|
reject(err);
|
||||||
reject(err);
|
});
|
||||||
});
|
}
|
||||||
}
|
catch (err) {
|
||||||
catch (err) {
|
reject(err);
|
||||||
reject(err);
|
}
|
||||||
}
|
}));
|
||||||
}));
|
});
|
||||||
});
|
}
|
||||||
}
|
exports.downloadTool = downloadTool;
|
||||||
exports.downloadTool = downloadTool;
|
/**
|
||||||
/**
|
* Extract a .7z file
|
||||||
* Extract a .7z file
|
*
|
||||||
*
|
* @param file path to the .7z file
|
||||||
* @param file path to the .7z file
|
* @param dest destination directory. Optional.
|
||||||
* @param dest destination directory. Optional.
|
* @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this
|
||||||
* @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this
|
* problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will
|
||||||
* problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will
|
* gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is
|
||||||
* gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is
|
* bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line
|
||||||
* bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line
|
* interface, it is smaller than the full command line interface, and it does support long paths. At the
|
||||||
* interface, it is smaller than the full command line interface, and it does support long paths. At the
|
* time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website.
|
||||||
* time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website.
|
* Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path
|
||||||
* Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path
|
* to 7zr.exe can be pass to this function.
|
||||||
* to 7zr.exe can be pass to this function.
|
* @returns path to the destination directory
|
||||||
* @returns path to the destination directory
|
*/
|
||||||
*/
|
function extract7z(file, dest, _7zPath) {
|
||||||
function extract7z(file, dest, _7zPath) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
assert_1.ok(IS_WINDOWS, 'extract7z() not supported on current OS');
|
||||||
assert_1.ok(IS_WINDOWS, 'extract7z() not supported on current OS');
|
assert_1.ok(file, 'parameter "file" is required');
|
||||||
assert_1.ok(file, 'parameter "file" is required');
|
dest = dest || (yield _createExtractFolder(dest));
|
||||||
dest = dest || (yield _createExtractFolder(dest));
|
const originalCwd = process.cwd();
|
||||||
const originalCwd = process.cwd();
|
process.chdir(dest);
|
||||||
process.chdir(dest);
|
if (_7zPath) {
|
||||||
if (_7zPath) {
|
try {
|
||||||
try {
|
const args = [
|
||||||
const args = [
|
'x',
|
||||||
'x',
|
'-bb1',
|
||||||
'-bb1',
|
'-bd',
|
||||||
'-bd',
|
'-sccUTF-8',
|
||||||
'-sccUTF-8',
|
file
|
||||||
file
|
];
|
||||||
];
|
const options = {
|
||||||
const options = {
|
silent: true
|
||||||
silent: true
|
};
|
||||||
};
|
yield exec_1.exec(`"${_7zPath}"`, args, options);
|
||||||
yield exec_1.exec(`"${_7zPath}"`, args, options);
|
}
|
||||||
}
|
finally {
|
||||||
finally {
|
process.chdir(originalCwd);
|
||||||
process.chdir(originalCwd);
|
}
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else {
|
const escapedScript = path
|
||||||
const escapedScript = path
|
.join(__dirname, '..', 'scripts', 'Invoke-7zdec.ps1')
|
||||||
.join(__dirname, '..', 'scripts', 'Invoke-7zdec.ps1')
|
.replace(/'/g, "''")
|
||||||
.replace(/'/g, "''")
|
.replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines
|
||||||
.replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines
|
const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
||||||
const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
const escapedTarget = dest.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
||||||
const escapedTarget = dest.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
const command = `& '${escapedScript}' -Source '${escapedFile}' -Target '${escapedTarget}'`;
|
||||||
const command = `& '${escapedScript}' -Source '${escapedFile}' -Target '${escapedTarget}'`;
|
const args = [
|
||||||
const args = [
|
'-NoLogo',
|
||||||
'-NoLogo',
|
'-Sta',
|
||||||
'-Sta',
|
'-NoProfile',
|
||||||
'-NoProfile',
|
'-NonInteractive',
|
||||||
'-NonInteractive',
|
'-ExecutionPolicy',
|
||||||
'-ExecutionPolicy',
|
'Unrestricted',
|
||||||
'Unrestricted',
|
'-Command',
|
||||||
'-Command',
|
command
|
||||||
command
|
];
|
||||||
];
|
const options = {
|
||||||
const options = {
|
silent: true
|
||||||
silent: true
|
};
|
||||||
};
|
try {
|
||||||
try {
|
const powershellPath = yield io.which('powershell', true);
|
||||||
const powershellPath = yield io.which('powershell', true);
|
yield exec_1.exec(`"${powershellPath}"`, args, options);
|
||||||
yield exec_1.exec(`"${powershellPath}"`, args, options);
|
}
|
||||||
}
|
finally {
|
||||||
finally {
|
process.chdir(originalCwd);
|
||||||
process.chdir(originalCwd);
|
}
|
||||||
}
|
}
|
||||||
}
|
return dest;
|
||||||
return dest;
|
});
|
||||||
});
|
}
|
||||||
}
|
exports.extract7z = extract7z;
|
||||||
exports.extract7z = extract7z;
|
/**
|
||||||
/**
|
* Extract a tar
|
||||||
* Extract a tar
|
*
|
||||||
*
|
* @param file path to the tar
|
||||||
* @param file path to the tar
|
* @param dest destination directory. Optional.
|
||||||
* @param dest destination directory. Optional.
|
* @returns path to the destination directory
|
||||||
* @returns path to the destination directory
|
*/
|
||||||
*/
|
function extractTar(file, dest) {
|
||||||
function extractTar(file, dest) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
if (!file) {
|
||||||
if (!file) {
|
throw new Error("parameter 'file' is required");
|
||||||
throw new Error("parameter 'file' is required");
|
}
|
||||||
}
|
dest = dest || (yield _createExtractFolder(dest));
|
||||||
dest = dest || (yield _createExtractFolder(dest));
|
const tarPath = yield io.which('tar', true);
|
||||||
const tarPath = yield io.which('tar', true);
|
yield exec_1.exec(`"${tarPath}"`, ['xzC', dest, '-f', file]);
|
||||||
yield exec_1.exec(`"${tarPath}"`, ['xzC', dest, '-f', file]);
|
return dest;
|
||||||
return dest;
|
});
|
||||||
});
|
}
|
||||||
}
|
exports.extractTar = extractTar;
|
||||||
exports.extractTar = extractTar;
|
/**
|
||||||
/**
|
* Extract a zip
|
||||||
* Extract a zip
|
*
|
||||||
*
|
* @param file path to the zip
|
||||||
* @param file path to the zip
|
* @param dest destination directory. Optional.
|
||||||
* @param dest destination directory. Optional.
|
* @returns path to the destination directory
|
||||||
* @returns path to the destination directory
|
*/
|
||||||
*/
|
function extractZip(file, dest) {
|
||||||
function extractZip(file, dest) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
if (!file) {
|
||||||
if (!file) {
|
throw new Error("parameter 'file' is required");
|
||||||
throw new Error("parameter 'file' is required");
|
}
|
||||||
}
|
dest = dest || (yield _createExtractFolder(dest));
|
||||||
dest = dest || (yield _createExtractFolder(dest));
|
if (IS_WINDOWS) {
|
||||||
if (IS_WINDOWS) {
|
yield extractZipWin(file, dest);
|
||||||
yield extractZipWin(file, dest);
|
}
|
||||||
}
|
else {
|
||||||
else {
|
yield extractZipNix(file, dest);
|
||||||
yield extractZipNix(file, dest);
|
}
|
||||||
}
|
return dest;
|
||||||
return dest;
|
});
|
||||||
});
|
}
|
||||||
}
|
exports.extractZip = extractZip;
|
||||||
exports.extractZip = extractZip;
|
function extractZipWin(file, dest) {
|
||||||
function extractZipWin(file, dest) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
// build the powershell command
|
||||||
// build the powershell command
|
const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines
|
||||||
const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines
|
const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
||||||
const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
const command = `$ErrorActionPreference = 'Stop' ; try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}')`;
|
||||||
const command = `$ErrorActionPreference = 'Stop' ; try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}')`;
|
// run powershell
|
||||||
// run powershell
|
const powershellPath = yield io.which('powershell');
|
||||||
const powershellPath = yield io.which('powershell');
|
const args = [
|
||||||
const args = [
|
'-NoLogo',
|
||||||
'-NoLogo',
|
'-Sta',
|
||||||
'-Sta',
|
'-NoProfile',
|
||||||
'-NoProfile',
|
'-NonInteractive',
|
||||||
'-NonInteractive',
|
'-ExecutionPolicy',
|
||||||
'-ExecutionPolicy',
|
'Unrestricted',
|
||||||
'Unrestricted',
|
'-Command',
|
||||||
'-Command',
|
command
|
||||||
command
|
];
|
||||||
];
|
yield exec_1.exec(`"${powershellPath}"`, args);
|
||||||
yield exec_1.exec(`"${powershellPath}"`, args);
|
});
|
||||||
});
|
}
|
||||||
}
|
function extractZipNix(file, dest) {
|
||||||
function extractZipNix(file, dest) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
const unzipPath = path.join(__dirname, '..', 'scripts', 'externals', 'unzip');
|
||||||
const unzipPath = path.join(__dirname, '..', 'scripts', 'externals', 'unzip');
|
yield exec_1.exec(`"${unzipPath}"`, [file], { cwd: dest });
|
||||||
yield exec_1.exec(`"${unzipPath}"`, [file], { cwd: dest });
|
});
|
||||||
});
|
}
|
||||||
}
|
/**
|
||||||
/**
|
* Caches a directory and installs it into the tool cacheDir
|
||||||
* Caches a directory and installs it into the tool cacheDir
|
*
|
||||||
*
|
* @param sourceDir the directory to cache into tools
|
||||||
* @param sourceDir the directory to cache into tools
|
* @param tool tool name
|
||||||
* @param tool tool name
|
* @param version version of the tool. semver format
|
||||||
* @param version version of the tool. semver format
|
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
||||||
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
*/
|
||||||
*/
|
function cacheDir(sourceDir, tool, version, arch) {
|
||||||
function cacheDir(sourceDir, tool, version, arch) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
version = semver.clean(version) || version;
|
||||||
version = semver.clean(version) || version;
|
arch = arch || os.arch();
|
||||||
arch = arch || os.arch();
|
core.debug(`Caching tool ${tool} ${version} ${arch}`);
|
||||||
core.debug(`Caching tool ${tool} ${version} ${arch}`);
|
core.debug(`source dir: ${sourceDir}`);
|
||||||
core.debug(`source dir: ${sourceDir}`);
|
if (!fs.statSync(sourceDir).isDirectory()) {
|
||||||
if (!fs.statSync(sourceDir).isDirectory()) {
|
throw new Error('sourceDir is not a directory');
|
||||||
throw new Error('sourceDir is not a directory');
|
}
|
||||||
}
|
// Create the tool dir
|
||||||
// Create the tool dir
|
const destPath = yield _createToolPath(tool, version, arch);
|
||||||
const destPath = yield _createToolPath(tool, version, arch);
|
// copy each child item. do not move. move can fail on Windows
|
||||||
// copy each child item. do not move. move can fail on Windows
|
// due to anti-virus software having an open handle on a file.
|
||||||
// due to anti-virus software having an open handle on a file.
|
for (const itemName of fs.readdirSync(sourceDir)) {
|
||||||
for (const itemName of fs.readdirSync(sourceDir)) {
|
const s = path.join(sourceDir, itemName);
|
||||||
const s = path.join(sourceDir, itemName);
|
yield io.cp(s, destPath, { recursive: true });
|
||||||
shell.cp('-R', s, destPath);
|
}
|
||||||
}
|
// write .complete
|
||||||
// write .complete
|
_completeToolPath(tool, version, arch);
|
||||||
_completeToolPath(tool, version, arch);
|
return destPath;
|
||||||
return destPath;
|
});
|
||||||
});
|
}
|
||||||
}
|
exports.cacheDir = cacheDir;
|
||||||
exports.cacheDir = cacheDir;
|
/**
|
||||||
/**
|
* Caches a downloaded file (GUID) and installs it
|
||||||
* Caches a downloaded file (GUID) and installs it
|
* into the tool cache with a given targetName
|
||||||
* into the tool cache with a given targetName
|
*
|
||||||
*
|
* @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid.
|
||||||
* @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid.
|
* @param targetFile the name of the file name in the tools directory
|
||||||
* @param targetFile the name of the file name in the tools directory
|
* @param tool tool name
|
||||||
* @param tool tool name
|
* @param version version of the tool. semver format
|
||||||
* @param version version of the tool. semver format
|
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
||||||
* @param arch architecture of the tool. Optional. Defaults to machine architecture
|
*/
|
||||||
*/
|
function cacheFile(sourceFile, targetFile, tool, version, arch) {
|
||||||
function cacheFile(sourceFile, targetFile, tool, version, arch) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
version = semver.clean(version) || version;
|
||||||
version = semver.clean(version) || version;
|
arch = arch || os.arch();
|
||||||
arch = arch || os.arch();
|
core.debug(`Caching tool ${tool} ${version} ${arch}`);
|
||||||
core.debug(`Caching tool ${tool} ${version} ${arch}`);
|
core.debug(`source file: ${sourceFile}`);
|
||||||
core.debug(`source file: ${sourceFile}`);
|
if (!fs.statSync(sourceFile).isFile()) {
|
||||||
if (!fs.statSync(sourceFile).isFile()) {
|
throw new Error('sourceFile is not a file');
|
||||||
throw new Error('sourceFile is not a file');
|
}
|
||||||
}
|
// create the tool dir
|
||||||
// create the tool dir
|
const destFolder = yield _createToolPath(tool, version, arch);
|
||||||
const destFolder = yield _createToolPath(tool, version, arch);
|
// copy instead of move. move can fail on Windows due to
|
||||||
// copy instead of move. move can fail on Windows due to
|
// anti-virus software having an open handle on a file.
|
||||||
// anti-virus software having an open handle on a file.
|
const destPath = path.join(destFolder, targetFile);
|
||||||
const destPath = path.join(destFolder, targetFile);
|
core.debug(`destination file ${destPath}`);
|
||||||
core.debug(`destination file ${destPath}`);
|
yield io.cp(sourceFile, destPath);
|
||||||
yield io.cp(sourceFile, destPath);
|
// write .complete
|
||||||
// write .complete
|
_completeToolPath(tool, version, arch);
|
||||||
_completeToolPath(tool, version, arch);
|
return destFolder;
|
||||||
return destFolder;
|
});
|
||||||
});
|
}
|
||||||
}
|
exports.cacheFile = cacheFile;
|
||||||
exports.cacheFile = cacheFile;
|
/**
|
||||||
/**
|
* Finds the path to a tool version in the local installed tool cache
|
||||||
* Finds the path to a tool version in the local installed tool cache
|
*
|
||||||
*
|
* @param toolName name of the tool
|
||||||
* @param toolName name of the tool
|
* @param versionSpec version of the tool
|
||||||
* @param versionSpec version of the tool
|
* @param arch optional arch. defaults to arch of computer
|
||||||
* @param arch optional arch. defaults to arch of computer
|
*/
|
||||||
*/
|
function find(toolName, versionSpec, arch) {
|
||||||
function find(toolName, versionSpec, arch) {
|
if (!toolName) {
|
||||||
if (!toolName) {
|
throw new Error('toolName parameter is required');
|
||||||
throw new Error('toolName parameter is required');
|
}
|
||||||
}
|
if (!versionSpec) {
|
||||||
if (!versionSpec) {
|
throw new Error('versionSpec parameter is required');
|
||||||
throw new Error('versionSpec parameter is required');
|
}
|
||||||
}
|
arch = arch || os.arch();
|
||||||
arch = arch || os.arch();
|
// attempt to resolve an explicit version
|
||||||
// attempt to resolve an explicit version
|
if (!_isExplicitVersion(versionSpec)) {
|
||||||
if (!_isExplicitVersion(versionSpec)) {
|
const localVersions = findAllVersions(toolName, arch);
|
||||||
const localVersions = findAllVersions(toolName, arch);
|
const match = _evaluateVersions(localVersions, versionSpec);
|
||||||
const match = _evaluateVersions(localVersions, versionSpec);
|
versionSpec = match;
|
||||||
versionSpec = match;
|
}
|
||||||
}
|
// check for the explicit version in the cache
|
||||||
// check for the explicit version in the cache
|
let toolPath = '';
|
||||||
let toolPath = '';
|
if (versionSpec) {
|
||||||
if (versionSpec) {
|
versionSpec = semver.clean(versionSpec) || '';
|
||||||
versionSpec = semver.clean(versionSpec) || '';
|
const cachePath = path.join(cacheRoot, toolName, versionSpec, arch);
|
||||||
const cachePath = path.join(cacheRoot, toolName, versionSpec, arch);
|
core.debug(`checking cache: ${cachePath}`);
|
||||||
core.debug(`checking cache: ${cachePath}`);
|
if (fs.existsSync(cachePath) && fs.existsSync(`${cachePath}.complete`)) {
|
||||||
if (fs.existsSync(cachePath) && fs.existsSync(`${cachePath}.complete`)) {
|
core.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch}`);
|
||||||
core.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch}`);
|
toolPath = cachePath;
|
||||||
toolPath = cachePath;
|
}
|
||||||
}
|
else {
|
||||||
else {
|
core.debug('not found');
|
||||||
core.debug('not found');
|
}
|
||||||
}
|
}
|
||||||
}
|
return toolPath;
|
||||||
return toolPath;
|
}
|
||||||
}
|
exports.find = find;
|
||||||
exports.find = find;
|
/**
|
||||||
/**
|
* Finds the paths to all versions of a tool that are installed in the local tool cache
|
||||||
* Finds the paths to all versions of a tool that are installed in the local tool cache
|
*
|
||||||
*
|
* @param toolName name of the tool
|
||||||
* @param toolName name of the tool
|
* @param arch optional arch. defaults to arch of computer
|
||||||
* @param arch optional arch. defaults to arch of computer
|
*/
|
||||||
*/
|
function findAllVersions(toolName, arch) {
|
||||||
function findAllVersions(toolName, arch) {
|
const versions = [];
|
||||||
const versions = [];
|
arch = arch || os.arch();
|
||||||
arch = arch || os.arch();
|
const toolPath = path.join(cacheRoot, toolName);
|
||||||
const toolPath = path.join(cacheRoot, toolName);
|
if (fs.existsSync(toolPath)) {
|
||||||
if (fs.existsSync(toolPath)) {
|
const children = fs.readdirSync(toolPath);
|
||||||
const children = fs.readdirSync(toolPath);
|
for (const child of children) {
|
||||||
for (const child of children) {
|
if (_isExplicitVersion(child)) {
|
||||||
if (_isExplicitVersion(child)) {
|
const fullPath = path.join(toolPath, child, arch || '');
|
||||||
const fullPath = path.join(toolPath, child, arch || '');
|
if (fs.existsSync(fullPath) && fs.existsSync(`${fullPath}.complete`)) {
|
||||||
if (fs.existsSync(fullPath) && fs.existsSync(`${fullPath}.complete`)) {
|
versions.push(child);
|
||||||
versions.push(child);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return versions;
|
||||||
return versions;
|
}
|
||||||
}
|
exports.findAllVersions = findAllVersions;
|
||||||
exports.findAllVersions = findAllVersions;
|
function _createExtractFolder(dest) {
|
||||||
function _createExtractFolder(dest) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
if (!dest) {
|
||||||
if (!dest) {
|
// create a temp dir
|
||||||
// create a temp dir
|
dest = path.join(tempDirectory, uuidV4());
|
||||||
dest = path.join(tempDirectory, uuidV4());
|
}
|
||||||
}
|
yield io.mkdirP(dest);
|
||||||
yield io.mkdirP(dest);
|
return dest;
|
||||||
return dest;
|
});
|
||||||
});
|
}
|
||||||
}
|
function _createToolPath(tool, version, arch) {
|
||||||
function _createToolPath(tool, version, arch) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
const folderPath = path.join(cacheRoot, tool, semver.clean(version) || version, arch || '');
|
||||||
const folderPath = path.join(cacheRoot, tool, semver.clean(version) || version, arch || '');
|
core.debug(`destination ${folderPath}`);
|
||||||
core.debug(`destination ${folderPath}`);
|
const markerPath = `${folderPath}.complete`;
|
||||||
const markerPath = `${folderPath}.complete`;
|
yield io.rmRF(folderPath);
|
||||||
yield io.rmRF(folderPath);
|
yield io.rmRF(markerPath);
|
||||||
yield io.rmRF(markerPath);
|
yield io.mkdirP(folderPath);
|
||||||
yield io.mkdirP(folderPath);
|
return folderPath;
|
||||||
return folderPath;
|
});
|
||||||
});
|
}
|
||||||
}
|
function _completeToolPath(tool, version, arch) {
|
||||||
function _completeToolPath(tool, version, arch) {
|
const folderPath = path.join(cacheRoot, tool, semver.clean(version) || version, arch || '');
|
||||||
const folderPath = path.join(cacheRoot, tool, semver.clean(version) || version, arch || '');
|
const markerPath = `${folderPath}.complete`;
|
||||||
const markerPath = `${folderPath}.complete`;
|
fs.writeFileSync(markerPath, '');
|
||||||
fs.writeFileSync(markerPath, '');
|
core.debug('finished caching tool');
|
||||||
core.debug('finished caching tool');
|
}
|
||||||
}
|
function _isExplicitVersion(versionSpec) {
|
||||||
function _isExplicitVersion(versionSpec) {
|
const c = semver.clean(versionSpec) || '';
|
||||||
const c = semver.clean(versionSpec) || '';
|
core.debug(`isExplicit: ${c}`);
|
||||||
core.debug(`isExplicit: ${c}`);
|
const valid = semver.valid(c) != null;
|
||||||
const valid = semver.valid(c) != null;
|
core.debug(`explicit? ${valid}`);
|
||||||
core.debug(`explicit? ${valid}`);
|
return valid;
|
||||||
return valid;
|
}
|
||||||
}
|
function _evaluateVersions(versions, versionSpec) {
|
||||||
function _evaluateVersions(versions, versionSpec) {
|
let version = '';
|
||||||
let version = '';
|
core.debug(`evaluating ${versions.length} versions`);
|
||||||
core.debug(`evaluating ${versions.length} versions`);
|
versions = versions.sort((a, b) => {
|
||||||
versions = versions.sort((a, b) => {
|
if (semver.gt(a, b)) {
|
||||||
if (semver.gt(a, b)) {
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
return -1;
|
||||||
return -1;
|
});
|
||||||
});
|
for (let i = versions.length - 1; i >= 0; i--) {
|
||||||
for (let i = versions.length - 1; i >= 0; i--) {
|
const potential = versions[i];
|
||||||
const potential = versions[i];
|
const satisfied = semver.satisfies(potential, versionSpec);
|
||||||
const satisfied = semver.satisfies(potential, versionSpec);
|
if (satisfied) {
|
||||||
if (satisfied) {
|
version = potential;
|
||||||
version = potential;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
if (version) {
|
||||||
if (version) {
|
core.debug(`matched: ${version}`);
|
||||||
core.debug(`matched: ${version}`);
|
}
|
||||||
}
|
else {
|
||||||
else {
|
core.debug('match not found');
|
||||||
core.debug('match not found');
|
}
|
||||||
}
|
return version;
|
||||||
return version;
|
}
|
||||||
}
|
//# sourceMappingURL=tool-cache.js.map
|
||||||
//# sourceMappingURL=tool-cache.js.map
|
|
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@
|
||||||
"_from": "file:toolkit\\actions-tool-cache-0.0.0.tgz",
|
"_from": "file:toolkit\\actions-tool-cache-0.0.0.tgz",
|
||||||
"_id": "@actions/tool-cache@0.0.0",
|
"_id": "@actions/tool-cache@0.0.0",
|
||||||
"_inBundle": false,
|
"_inBundle": false,
|
||||||
"_integrity": "sha512-R08MGFekNLkf1ofh5wi8QVgmFyPgkKC+Cp8FRE1n6zOpHbUWv3QGa6eR6z+2ESuGCstOPtbq/tRgZsSusItm9Q==",
|
"_integrity": "sha512-33oYAVRdp6MWNT7Yca0//SmOsvpE7FpFfNA/LzwjIZdLucHaO6V67dqZ5p81CTBncrZal+O5kE9B8qSk0rhipg==",
|
||||||
"_location": "/@actions/tool-cache",
|
"_location": "/@actions/tool-cache",
|
||||||
"_phantomChildren": {},
|
"_phantomChildren": {},
|
||||||
"_requested": {
|
"_requested": {
|
||||||
|
@ -17,10 +17,11 @@
|
||||||
"fetchSpec": "C:\\Users\\Administrator\\Documents\\setup-node\\toolkit\\actions-tool-cache-0.0.0.tgz"
|
"fetchSpec": "C:\\Users\\Administrator\\Documents\\setup-node\\toolkit\\actions-tool-cache-0.0.0.tgz"
|
||||||
},
|
},
|
||||||
"_requiredBy": [
|
"_requiredBy": [
|
||||||
|
"#USER",
|
||||||
"/"
|
"/"
|
||||||
],
|
],
|
||||||
"_resolved": "C:\\Users\\Administrator\\Documents\\setup-node\\toolkit\\actions-tool-cache-0.0.0.tgz",
|
"_resolved": "C:\\Users\\Administrator\\Documents\\setup-node\\toolkit\\actions-tool-cache-0.0.0.tgz",
|
||||||
"_shasum": "e4ffe745db46f47e512db20e80f8ad25910e41d1",
|
"_shasum": "ce9e7d81ebb138911d20b9f74c8aa6120caac9b1",
|
||||||
"_spec": "@actions/tool-cache@file:toolkit/actions-tool-cache-0.0.0.tgz",
|
"_spec": "@actions/tool-cache@file:toolkit/actions-tool-cache-0.0.0.tgz",
|
||||||
"_where": "C:\\Users\\Administrator\\Documents\\setup-node",
|
"_where": "C:\\Users\\Administrator\\Documents\\setup-node",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -32,7 +33,6 @@
|
||||||
"@actions/exec": "^0.0.0",
|
"@actions/exec": "^0.0.0",
|
||||||
"@actions/io": "^0.0.0",
|
"@actions/io": "^0.0.0",
|
||||||
"semver": "^6.1.0",
|
"semver": "^6.1.0",
|
||||||
"shelljs": "^0.3.0",
|
|
||||||
"typed-rest-client": "^1.4.0",
|
"typed-rest-client": "^1.4.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,60 +1,60 @@
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$Source,
|
[string]$Source,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$Target)
|
[string]$Target)
|
||||||
|
|
||||||
# This script translates the output from 7zdec into UTF8. Node has limited
|
# This script translates the output from 7zdec into UTF8. Node has limited
|
||||||
# built-in support for encodings.
|
# built-in support for encodings.
|
||||||
#
|
#
|
||||||
# 7zdec uses the system default code page. The system default code page varies
|
# 7zdec uses the system default code page. The system default code page varies
|
||||||
# depending on the locale configuration. On an en-US box, the system default code
|
# depending on the locale configuration. On an en-US box, the system default code
|
||||||
# page is Windows-1252.
|
# page is Windows-1252.
|
||||||
#
|
#
|
||||||
# Note, on a typical en-US box, testing with the 'ç' character is a good way to
|
# Note, on a typical en-US box, testing with the 'ç' character is a good way to
|
||||||
# determine whether data is passed correctly between processes. This is because
|
# determine whether data is passed correctly between processes. This is because
|
||||||
# the 'ç' character has a different code point across each of the common encodings
|
# the 'ç' character has a different code point across each of the common encodings
|
||||||
# on a typical en-US box, i.e.
|
# on a typical en-US box, i.e.
|
||||||
# 1) the default console-output code page (IBM437)
|
# 1) the default console-output code page (IBM437)
|
||||||
# 2) the system default code page (i.e. CP_ACP) (Windows-1252)
|
# 2) the system default code page (i.e. CP_ACP) (Windows-1252)
|
||||||
# 3) UTF8
|
# 3) UTF8
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
# Redefine the wrapper over STDOUT to use UTF8. Node expects UTF8 by default.
|
# Redefine the wrapper over STDOUT to use UTF8. Node expects UTF8 by default.
|
||||||
$stdout = [System.Console]::OpenStandardOutput()
|
$stdout = [System.Console]::OpenStandardOutput()
|
||||||
$utf8 = New-Object System.Text.UTF8Encoding($false) # do not emit BOM
|
$utf8 = New-Object System.Text.UTF8Encoding($false) # do not emit BOM
|
||||||
$writer = New-Object System.IO.StreamWriter($stdout, $utf8)
|
$writer = New-Object System.IO.StreamWriter($stdout, $utf8)
|
||||||
[System.Console]::SetOut($writer)
|
[System.Console]::SetOut($writer)
|
||||||
|
|
||||||
# All subsequent output must be written using [System.Console]::WriteLine(). In
|
# All subsequent output must be written using [System.Console]::WriteLine(). In
|
||||||
# PowerShell 4, Write-Host and Out-Default do not consider the updated stream writer.
|
# PowerShell 4, Write-Host and Out-Default do not consider the updated stream writer.
|
||||||
|
|
||||||
Set-Location -LiteralPath $Target
|
Set-Location -LiteralPath $Target
|
||||||
|
|
||||||
# Print the ##command.
|
# Print the ##command.
|
||||||
$_7zdec = Join-Path -Path "$PSScriptRoot" -ChildPath "externals/7zdec.exe"
|
$_7zdec = Join-Path -Path "$PSScriptRoot" -ChildPath "externals/7zdec.exe"
|
||||||
[System.Console]::WriteLine("##[command]$_7zdec x `"$Source`"")
|
[System.Console]::WriteLine("##[command]$_7zdec x `"$Source`"")
|
||||||
|
|
||||||
# The $OutputEncoding variable instructs PowerShell how to interpret the output
|
# The $OutputEncoding variable instructs PowerShell how to interpret the output
|
||||||
# from the external command.
|
# from the external command.
|
||||||
$OutputEncoding = [System.Text.Encoding]::Default
|
$OutputEncoding = [System.Text.Encoding]::Default
|
||||||
|
|
||||||
# Note, the output from 7zdec.exe needs to be iterated over. Otherwise PowerShell.exe
|
# Note, the output from 7zdec.exe needs to be iterated over. Otherwise PowerShell.exe
|
||||||
# will launch the external command in such a way that it inherits the streams.
|
# will launch the external command in such a way that it inherits the streams.
|
||||||
& $_7zdec x $Source 2>&1 |
|
& $_7zdec x $Source 2>&1 |
|
||||||
ForEach-Object {
|
ForEach-Object {
|
||||||
if ($_ -is [System.Management.Automation.ErrorRecord]) {
|
if ($_ -is [System.Management.Automation.ErrorRecord]) {
|
||||||
[System.Console]::WriteLine($_.Exception.Message)
|
[System.Console]::WriteLine($_.Exception.Message)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[System.Console]::WriteLine($_)
|
[System.Console]::WriteLine($_)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[System.Console]::WriteLine("##[debug]7zdec.exe exit code '$LASTEXITCODE'")
|
[System.Console]::WriteLine("##[debug]7zdec.exe exit code '$LASTEXITCODE'")
|
||||||
[System.Console]::Out.Flush()
|
[System.Console]::Out.Flush()
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
exit $LASTEXITCODE
|
exit $LASTEXITCODE
|
||||||
}
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"name": "ShellJS",
|
|
||||||
"twitter": [
|
|
||||||
"r2r"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"loopfunc": true,
|
|
||||||
"sub": true,
|
|
||||||
"undef": true,
|
|
||||||
"unused": true,
|
|
||||||
"node": true
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
test/
|
|
||||||
tmp/
|
|
|
@ -1,5 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "0.8"
|
|
||||||
- "0.10"
|
|
||||||
- "0.11"
|
|
|
@ -1,26 +0,0 @@
|
||||||
Copyright (c) 2012, Artur Adib <aadib@mozilla.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
You may use this project under the terms of the New BSD license as follows:
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of Artur Adib nor the
|
|
||||||
names of the contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
@ -1,569 +0,0 @@
|
||||||
# ShellJS - Unix shell commands for Node.js [![Build Status](https://secure.travis-ci.org/arturadib/shelljs.png)](http://travis-ci.org/arturadib/shelljs)
|
|
||||||
|
|
||||||
ShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts!
|
|
||||||
|
|
||||||
The project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and battled-tested in projects like:
|
|
||||||
|
|
||||||
+ [PDF.js](http://github.com/mozilla/pdf.js) - Firefox's next-gen PDF reader
|
|
||||||
+ [Firebug](http://getfirebug.com/) - Firefox's infamous debugger
|
|
||||||
+ [JSHint](http://jshint.com) - Most popular JavaScript linter
|
|
||||||
+ [Zepto](http://zeptojs.com) - jQuery-compatible JavaScript library for modern browsers
|
|
||||||
+ [Yeoman](http://yeoman.io/) - Web application stack and development tool
|
|
||||||
+ [Deployd.com](http://deployd.com) - Open source PaaS for quick API backend generation
|
|
||||||
|
|
||||||
and [many more](https://npmjs.org/browse/depended/shelljs).
|
|
||||||
|
|
||||||
## Installing
|
|
||||||
|
|
||||||
Via npm:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install [-g] shelljs
|
|
||||||
```
|
|
||||||
|
|
||||||
If the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to
|
|
||||||
run ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ shjs my_script
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also just copy `shell.js` into your project's directory, and `require()` accordingly.
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### JavaScript
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
require('shelljs/global');
|
|
||||||
|
|
||||||
if (!which('git')) {
|
|
||||||
echo('Sorry, this script requires git');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy files to release dir
|
|
||||||
mkdir('-p', 'out/Release');
|
|
||||||
cp('-R', 'stuff/*', 'out/Release');
|
|
||||||
|
|
||||||
// Replace macros in each .js file
|
|
||||||
cd('lib');
|
|
||||||
ls('*.js').forEach(function(file) {
|
|
||||||
sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
|
|
||||||
sed('-i', /.*REMOVE_THIS_LINE.*\n/, '', file);
|
|
||||||
sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file);
|
|
||||||
});
|
|
||||||
cd('..');
|
|
||||||
|
|
||||||
// Run external tool synchronously
|
|
||||||
if (exec('git commit -am "Auto-commit"').code !== 0) {
|
|
||||||
echo('Error: Git commit failed');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### CoffeeScript
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
require 'shelljs/global'
|
|
||||||
|
|
||||||
if not which 'git'
|
|
||||||
echo 'Sorry, this script requires git'
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
# Copy files to release dir
|
|
||||||
mkdir '-p', 'out/Release'
|
|
||||||
cp '-R', 'stuff/*', 'out/Release'
|
|
||||||
|
|
||||||
# Replace macros in each .js file
|
|
||||||
cd 'lib'
|
|
||||||
for file in ls '*.js'
|
|
||||||
sed '-i', 'BUILD_VERSION', 'v0.1.2', file
|
|
||||||
sed '-i', /.*REMOVE_THIS_LINE.*\n/, '', file
|
|
||||||
sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat 'macro.js', file
|
|
||||||
cd '..'
|
|
||||||
|
|
||||||
# Run external tool synchronously
|
|
||||||
if (exec 'git commit -am "Auto-commit"').code != 0
|
|
||||||
echo 'Error: Git commit failed'
|
|
||||||
exit 1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Global vs. Local
|
|
||||||
|
|
||||||
The example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var shell = require('shelljs');
|
|
||||||
shell.echo('hello world');
|
|
||||||
```
|
|
||||||
|
|
||||||
## Make tool
|
|
||||||
|
|
||||||
A convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script.
|
|
||||||
|
|
||||||
Example (CoffeeScript):
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
require 'shelljs/make'
|
|
||||||
|
|
||||||
target.all = ->
|
|
||||||
target.bundle()
|
|
||||||
target.docs()
|
|
||||||
|
|
||||||
target.bundle = ->
|
|
||||||
cd __dirname
|
|
||||||
mkdir 'build'
|
|
||||||
cd 'lib'
|
|
||||||
(cat '*.js').to '../build/output.js'
|
|
||||||
|
|
||||||
target.docs = ->
|
|
||||||
cd __dirname
|
|
||||||
mkdir 'docs'
|
|
||||||
cd 'lib'
|
|
||||||
for file in ls '*.js'
|
|
||||||
text = grep '//@', file # extract special comments
|
|
||||||
text.replace '//@', '' # remove comment tags
|
|
||||||
text.to 'docs/my_docs.md'
|
|
||||||
```
|
|
||||||
|
|
||||||
To run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
DO NOT MODIFY BEYOND THIS POINT - IT'S AUTOMATICALLY GENERATED
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
## Command reference
|
|
||||||
|
|
||||||
|
|
||||||
All commands run synchronously, unless otherwise stated.
|
|
||||||
|
|
||||||
|
|
||||||
### cd('dir')
|
|
||||||
Changes to directory `dir` for the duration of the script
|
|
||||||
|
|
||||||
|
|
||||||
### pwd()
|
|
||||||
Returns the current directory.
|
|
||||||
|
|
||||||
|
|
||||||
### ls([options ,] path [,path ...])
|
|
||||||
### ls([options ,] path_array)
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-R`: recursive
|
|
||||||
+ `-A`: all files (include files beginning with `.`, except for `.` and `..`)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
ls('projs/*.js');
|
|
||||||
ls('-R', '/users/me', '/tmp');
|
|
||||||
ls('-R', ['/users/me', '/tmp']); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
Returns array of files in the given path, or in current directory if no path provided.
|
|
||||||
|
|
||||||
|
|
||||||
### find(path [,path ...])
|
|
||||||
### find(path_array)
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
find('src', 'lib');
|
|
||||||
find(['src', 'lib']); // same as above
|
|
||||||
find('.').filter(function(file) { return file.match(/\.js$/); });
|
|
||||||
```
|
|
||||||
|
|
||||||
Returns array of all files (however deep) in the given paths.
|
|
||||||
|
|
||||||
The main difference from `ls('-R', path)` is that the resulting file names
|
|
||||||
include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
|
|
||||||
|
|
||||||
|
|
||||||
### cp([options ,] source [,source ...], dest)
|
|
||||||
### cp([options ,] source_array, dest)
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-f`: force
|
|
||||||
+ `-r, -R`: recursive
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cp('file1', 'dir1');
|
|
||||||
cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
|
|
||||||
cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
Copies files. The wildcard `*` is accepted.
|
|
||||||
|
|
||||||
|
|
||||||
### rm([options ,] file [, file ...])
|
|
||||||
### rm([options ,] file_array)
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-f`: force
|
|
||||||
+ `-r, -R`: recursive
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
rm('-rf', '/tmp/*');
|
|
||||||
rm('some_file.txt', 'another_file.txt');
|
|
||||||
rm(['some_file.txt', 'another_file.txt']); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
Removes files. The wildcard `*` is accepted.
|
|
||||||
|
|
||||||
|
|
||||||
### mv(source [, source ...], dest')
|
|
||||||
### mv(source_array, dest')
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `f`: force
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mv('-f', 'file', 'dir/');
|
|
||||||
mv('file1', 'file2', 'dir/');
|
|
||||||
mv(['file1', 'file2'], 'dir/'); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
Moves files. The wildcard `*` is accepted.
|
|
||||||
|
|
||||||
|
|
||||||
### mkdir([options ,] dir [, dir ...])
|
|
||||||
### mkdir([options ,] dir_array)
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `p`: full path (will create intermediate dirs if necessary)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');
|
|
||||||
mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
Creates directories.
|
|
||||||
|
|
||||||
|
|
||||||
### test(expression)
|
|
||||||
Available expression primaries:
|
|
||||||
|
|
||||||
+ `'-b', 'path'`: true if path is a block device
|
|
||||||
+ `'-c', 'path'`: true if path is a character device
|
|
||||||
+ `'-d', 'path'`: true if path is a directory
|
|
||||||
+ `'-e', 'path'`: true if path exists
|
|
||||||
+ `'-f', 'path'`: true if path is a regular file
|
|
||||||
+ `'-L', 'path'`: true if path is a symboilc link
|
|
||||||
+ `'-p', 'path'`: true if path is a pipe (FIFO)
|
|
||||||
+ `'-S', 'path'`: true if path is a socket
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
if (test('-d', path)) { /* do something with dir */ };
|
|
||||||
if (!test('-f', path)) continue; // skip if it's a regular file
|
|
||||||
```
|
|
||||||
|
|
||||||
Evaluates expression using the available primaries and returns corresponding value.
|
|
||||||
|
|
||||||
|
|
||||||
### cat(file [, file ...])
|
|
||||||
### cat(file_array)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var str = cat('file*.txt');
|
|
||||||
var str = cat('file1', 'file2');
|
|
||||||
var str = cat(['file1', 'file2']); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
Returns a string containing the given file, or a concatenated string
|
|
||||||
containing the files if more than one file is given (a new line character is
|
|
||||||
introduced between each file). Wildcard `*` accepted.
|
|
||||||
|
|
||||||
|
|
||||||
### 'string'.to(file)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cat('input.txt').to('output.txt');
|
|
||||||
```
|
|
||||||
|
|
||||||
Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as
|
|
||||||
those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_
|
|
||||||
|
|
||||||
|
|
||||||
### 'string'.toEnd(file)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cat('input.txt').toEnd('output.txt');
|
|
||||||
```
|
|
||||||
|
|
||||||
Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as
|
|
||||||
those returned by `cat`, `grep`, etc).
|
|
||||||
|
|
||||||
|
|
||||||
### sed([options ,] search_regex, replacement, file)
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');
|
|
||||||
sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
|
|
||||||
```
|
|
||||||
|
|
||||||
Reads an input string from `file` and performs a JavaScript `replace()` on the input
|
|
||||||
using the given search regex and replacement string or function. Returns the new string after replacement.
|
|
||||||
|
|
||||||
|
|
||||||
### grep([options ,] regex_filter, file [, file ...])
|
|
||||||
### grep([options ,] regex_filter, file_array)
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-v`: Inverse the sense of the regex and print the lines not matching the criteria.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
grep('-v', 'GLOBAL_VARIABLE', '*.js');
|
|
||||||
grep('GLOBAL_VARIABLE', '*.js');
|
|
||||||
```
|
|
||||||
|
|
||||||
Reads input string from given files and returns a string containing all lines of the
|
|
||||||
file that match the given `regex_filter`. Wildcard `*` accepted.
|
|
||||||
|
|
||||||
|
|
||||||
### which(command)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var nodeExec = which('node');
|
|
||||||
```
|
|
||||||
|
|
||||||
Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.
|
|
||||||
Returns string containing the absolute path to the command.
|
|
||||||
|
|
||||||
|
|
||||||
### echo(string [,string ...])
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
echo('hello world');
|
|
||||||
var str = echo('hello world');
|
|
||||||
```
|
|
||||||
|
|
||||||
Prints string to stdout, and returns string with additional utility methods
|
|
||||||
like `.to()`.
|
|
||||||
|
|
||||||
|
|
||||||
### pushd([options,] [dir | '-N' | '+N'])
|
|
||||||
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
+ `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`.
|
|
||||||
+ `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
|
||||||
+ `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// process.cwd() === '/usr'
|
|
||||||
pushd('/etc'); // Returns /etc /usr
|
|
||||||
pushd('+1'); // Returns /usr /etc
|
|
||||||
```
|
|
||||||
|
|
||||||
Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack.
|
|
||||||
|
|
||||||
### popd([options,] ['-N' | '+N'])
|
|
||||||
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
+ `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
|
|
||||||
+ `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
echo(process.cwd()); // '/usr'
|
|
||||||
pushd('/etc'); // '/etc /usr'
|
|
||||||
echo(process.cwd()); // '/etc'
|
|
||||||
popd(); // '/usr'
|
|
||||||
echo(process.cwd()); // '/usr'
|
|
||||||
```
|
|
||||||
|
|
||||||
When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack.
|
|
||||||
|
|
||||||
### dirs([options | '+N' | '-N'])
|
|
||||||
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-c`: Clears the directory stack by deleting all of the elements.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
+ `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
|
|
||||||
+ `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
|
|
||||||
|
|
||||||
Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified.
|
|
||||||
|
|
||||||
See also: pushd, popd
|
|
||||||
|
|
||||||
|
|
||||||
### ln(options, source, dest)
|
|
||||||
### ln(source, dest)
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `s`: symlink
|
|
||||||
+ `f`: force
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
ln('file', 'newlink');
|
|
||||||
ln('-sf', 'file', 'existing');
|
|
||||||
```
|
|
||||||
|
|
||||||
Links source to dest. Use -f to force the link, should dest already exist.
|
|
||||||
|
|
||||||
|
|
||||||
### exit(code)
|
|
||||||
Exits the current process with the given exit code.
|
|
||||||
|
|
||||||
### env['VAR_NAME']
|
|
||||||
Object containing environment variables (both getter and setter). Shortcut to process.env.
|
|
||||||
|
|
||||||
### exec(command [, options] [, callback])
|
|
||||||
Available options (all `false` by default):
|
|
||||||
|
|
||||||
+ `async`: Asynchronous execution. Defaults to true if a callback is provided.
|
|
||||||
+ `silent`: Do not echo program output to console.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var version = exec('node --version', {silent:true}).output;
|
|
||||||
|
|
||||||
var child = exec('some_long_running_process', {async:true});
|
|
||||||
child.stdout.on('data', function(data) {
|
|
||||||
/* ... do something with data ... */
|
|
||||||
});
|
|
||||||
|
|
||||||
exec('some_long_running_process', function(code, output) {
|
|
||||||
console.log('Exit code:', code);
|
|
||||||
console.log('Program output:', output);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Executes the given `command` _synchronously_, unless otherwise specified.
|
|
||||||
When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's
|
|
||||||
`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and
|
|
||||||
the `callback` gets the arguments `(code, output)`.
|
|
||||||
|
|
||||||
**Note:** For long-lived processes, it's best to run `exec()` asynchronously as
|
|
||||||
the current synchronous implementation uses a lot of CPU. This should be getting
|
|
||||||
fixed soon.
|
|
||||||
|
|
||||||
|
|
||||||
### chmod(octal_mode || octal_string, file)
|
|
||||||
### chmod(symbolic_mode, file)
|
|
||||||
|
|
||||||
Available options:
|
|
||||||
|
|
||||||
+ `-v`: output a diagnostic for every file processed
|
|
||||||
+ `-c`: like verbose but report only when a change is made
|
|
||||||
+ `-R`: change files and directories recursively
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
chmod(755, '/Users/brandon');
|
|
||||||
chmod('755', '/Users/brandon'); // same as above
|
|
||||||
chmod('u+x', '/Users/brandon');
|
|
||||||
```
|
|
||||||
|
|
||||||
Alters the permissions of a file or directory by either specifying the
|
|
||||||
absolute permissions in octal form or expressing the changes in symbols.
|
|
||||||
This command tries to mimic the POSIX behavior as much as possible.
|
|
||||||
Notable exceptions:
|
|
||||||
|
|
||||||
+ In symbolic modes, 'a-r' and '-r' are identical. No consideration is
|
|
||||||
given to the umask.
|
|
||||||
+ There is no "quiet" option since default behavior is to run silent.
|
|
||||||
|
|
||||||
|
|
||||||
## Non-Unix commands
|
|
||||||
|
|
||||||
|
|
||||||
### tempdir()
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var tmp = tempdir(); // "/tmp" for most *nix platforms
|
|
||||||
```
|
|
||||||
|
|
||||||
Searches and returns string containing a writeable, platform-dependent temporary directory.
|
|
||||||
Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).
|
|
||||||
|
|
||||||
|
|
||||||
### error()
|
|
||||||
Tests if error occurred in the last command. Returns `null` if no error occurred,
|
|
||||||
otherwise returns string explaining the error
|
|
||||||
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
|
|
||||||
### config.silent
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var silentState = config.silent; // save old silent state
|
|
||||||
config.silent = true;
|
|
||||||
/* ... */
|
|
||||||
config.silent = silentState; // restore old silent state
|
|
||||||
```
|
|
||||||
|
|
||||||
Suppresses all command output if `true`, except for `echo()` calls.
|
|
||||||
Default is `false`.
|
|
||||||
|
|
||||||
### config.fatal
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
config.fatal = true;
|
|
||||||
cp('this_file_does_not_exist', '/dev/null'); // dies here
|
|
||||||
/* more commands... */
|
|
||||||
```
|
|
||||||
|
|
||||||
If `true` the script will die on errors. Default is `false`.
|
|
|
@ -1,51 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
require('../global');
|
|
||||||
|
|
||||||
if (process.argv.length < 3) {
|
|
||||||
console.log('ShellJS: missing argument (script name)');
|
|
||||||
console.log();
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var args,
|
|
||||||
scriptName = process.argv[2];
|
|
||||||
env['NODE_PATH'] = __dirname + '/../..';
|
|
||||||
|
|
||||||
if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) {
|
|
||||||
if (test('-f', scriptName + '.js'))
|
|
||||||
scriptName += '.js';
|
|
||||||
if (test('-f', scriptName + '.coffee'))
|
|
||||||
scriptName += '.coffee';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!test('-f', scriptName)) {
|
|
||||||
console.log('ShellJS: script not found ('+scriptName+')');
|
|
||||||
console.log();
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
args = process.argv.slice(3);
|
|
||||||
|
|
||||||
for (var i = 0, l = args.length; i < l; i++) {
|
|
||||||
if (args[i][0] !== "-"){
|
|
||||||
args[i] = '"' + args[i] + '"'; // fixes arguments with multiple words
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scriptName.match(/\.coffee$/)) {
|
|
||||||
//
|
|
||||||
// CoffeeScript
|
|
||||||
//
|
|
||||||
if (which('coffee')) {
|
|
||||||
exec('coffee ' + scriptName + ' ' + args.join(' '), { async: true });
|
|
||||||
} else {
|
|
||||||
console.log('ShellJS: CoffeeScript interpreter not found');
|
|
||||||
console.log();
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
// JavaScript
|
|
||||||
//
|
|
||||||
exec('node ' + scriptName + ' ' + args.join(' '), { async: true });
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
var shell = require('./shell.js');
|
|
||||||
for (var cmd in shell)
|
|
||||||
global[cmd] = shell[cmd];
|
|
|
@ -1,47 +0,0 @@
|
||||||
require('./global');
|
|
||||||
|
|
||||||
global.config.fatal = true;
|
|
||||||
global.target = {};
|
|
||||||
|
|
||||||
// This ensures we only execute the script targets after the entire script has
|
|
||||||
// been evaluated
|
|
||||||
var args = process.argv.slice(2);
|
|
||||||
setTimeout(function() {
|
|
||||||
var t;
|
|
||||||
|
|
||||||
if (args.length === 1 && args[0] === '--help') {
|
|
||||||
console.log('Available targets:');
|
|
||||||
for (t in global.target)
|
|
||||||
console.log(' ' + t);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap targets to prevent duplicate execution
|
|
||||||
for (t in global.target) {
|
|
||||||
(function(t, oldTarget){
|
|
||||||
|
|
||||||
// Wrap it
|
|
||||||
global.target[t] = function(force) {
|
|
||||||
if (oldTarget.done && !force)
|
|
||||||
return;
|
|
||||||
oldTarget.done = true;
|
|
||||||
return oldTarget.apply(oldTarget, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
})(t, global.target[t]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute desired targets
|
|
||||||
if (args.length > 0) {
|
|
||||||
args.forEach(function(arg) {
|
|
||||||
if (arg in global.target)
|
|
||||||
global.target[arg]();
|
|
||||||
else {
|
|
||||||
console.log('no such target: ' + arg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if ('all' in global.target) {
|
|
||||||
global.target.all();
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 0);
|
|
|
@ -1,66 +0,0 @@
|
||||||
{
|
|
||||||
"_from": "shelljs@^0.3.0",
|
|
||||||
"_id": "shelljs@0.3.0",
|
|
||||||
"_inBundle": false,
|
|
||||||
"_integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=",
|
|
||||||
"_location": "/shelljs",
|
|
||||||
"_phantomChildren": {},
|
|
||||||
"_requested": {
|
|
||||||
"type": "range",
|
|
||||||
"registry": true,
|
|
||||||
"raw": "shelljs@^0.3.0",
|
|
||||||
"name": "shelljs",
|
|
||||||
"escapedName": "shelljs",
|
|
||||||
"rawSpec": "^0.3.0",
|
|
||||||
"saveSpec": null,
|
|
||||||
"fetchSpec": "^0.3.0"
|
|
||||||
},
|
|
||||||
"_requiredBy": [
|
|
||||||
"/@actions/tool-cache"
|
|
||||||
],
|
|
||||||
"_resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
|
|
||||||
"_shasum": "3596e6307a781544f591f37da618360f31db57b1",
|
|
||||||
"_spec": "shelljs@^0.3.0",
|
|
||||||
"_where": "C:\\Users\\Administrator\\Documents\\setup-node\\toolkit\\actions-tool-cache-0.0.0.tgz",
|
|
||||||
"author": {
|
|
||||||
"name": "Artur Adib",
|
|
||||||
"email": "aadib@mozilla.com"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"shjs": "./bin/shjs"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/arturadib/shelljs/issues"
|
|
||||||
},
|
|
||||||
"bundleDependencies": false,
|
|
||||||
"dependencies": {},
|
|
||||||
"deprecated": false,
|
|
||||||
"description": "Portable Unix shell commands for Node.js",
|
|
||||||
"devDependencies": {
|
|
||||||
"jshint": "~2.1.11"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8.0"
|
|
||||||
},
|
|
||||||
"homepage": "http://github.com/arturadib/shelljs",
|
|
||||||
"keywords": [
|
|
||||||
"unix",
|
|
||||||
"shell",
|
|
||||||
"makefile",
|
|
||||||
"make",
|
|
||||||
"jake",
|
|
||||||
"synchronous"
|
|
||||||
],
|
|
||||||
"license": "BSD*",
|
|
||||||
"main": "./shell.js",
|
|
||||||
"name": "shelljs",
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/arturadib/shelljs.git"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "node scripts/run-tests"
|
|
||||||
},
|
|
||||||
"version": "0.3.0"
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
require('../global');
|
|
||||||
|
|
||||||
echo('Appending docs to README.md');
|
|
||||||
|
|
||||||
cd(__dirname + '/..');
|
|
||||||
|
|
||||||
// Extract docs from shell.js
|
|
||||||
var docs = grep('//@', 'shell.js');
|
|
||||||
|
|
||||||
docs = docs.replace(/\/\/\@include (.+)/g, function(match, path) {
|
|
||||||
var file = path.match('.js$') ? path : path+'.js';
|
|
||||||
return grep('//@', file);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove '//@'
|
|
||||||
docs = docs.replace(/\/\/\@ ?/g, '');
|
|
||||||
// Append docs to README
|
|
||||||
sed('-i', /## Command reference(.|\n)*/, '## Command reference\n\n' + docs, 'README.md');
|
|
||||||
|
|
||||||
echo('All done.');
|
|
|
@ -1,50 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
require('../global');
|
|
||||||
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
var failed = false;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Lint
|
|
||||||
//
|
|
||||||
JSHINT_BIN = './node_modules/jshint/bin/jshint';
|
|
||||||
cd(__dirname + '/..');
|
|
||||||
|
|
||||||
if (!test('-f', JSHINT_BIN)) {
|
|
||||||
echo('JSHint not found. Run `npm install` in the root dir first.');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exec(JSHINT_BIN + ' *.js test/*.js').code !== 0) {
|
|
||||||
failed = true;
|
|
||||||
echo('*** JSHINT FAILED! (return code != 0)');
|
|
||||||
echo();
|
|
||||||
} else {
|
|
||||||
echo('All JSHint tests passed');
|
|
||||||
echo();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Unit tests
|
|
||||||
//
|
|
||||||
cd(__dirname + '/../test');
|
|
||||||
ls('*.js').forEach(function(file) {
|
|
||||||
echo('Running test:', file);
|
|
||||||
if (exec('node ' + file).code !== 123) { // 123 avoids false positives (e.g. premature exit)
|
|
||||||
failed = true;
|
|
||||||
echo('*** TEST FAILED! (missing exit code "123")');
|
|
||||||
echo();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (failed) {
|
|
||||||
echo();
|
|
||||||
echo('*******************************************************');
|
|
||||||
echo('WARNING: Some tests did not pass!');
|
|
||||||
echo('*******************************************************');
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
echo();
|
|
||||||
echo('All tests passed.');
|
|
||||||
}
|
|
|
@ -1,157 +0,0 @@
|
||||||
//
|
|
||||||
// ShellJS
|
|
||||||
// Unix shell commands on top of Node's API
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 Artur Adib
|
|
||||||
// http://github.com/arturadib/shelljs
|
|
||||||
//
|
|
||||||
|
|
||||||
var common = require('./src/common');
|
|
||||||
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ All commands run synchronously, unless otherwise stated.
|
|
||||||
//@
|
|
||||||
|
|
||||||
//@include ./src/cd
|
|
||||||
var _cd = require('./src/cd');
|
|
||||||
exports.cd = common.wrap('cd', _cd);
|
|
||||||
|
|
||||||
//@include ./src/pwd
|
|
||||||
var _pwd = require('./src/pwd');
|
|
||||||
exports.pwd = common.wrap('pwd', _pwd);
|
|
||||||
|
|
||||||
//@include ./src/ls
|
|
||||||
var _ls = require('./src/ls');
|
|
||||||
exports.ls = common.wrap('ls', _ls);
|
|
||||||
|
|
||||||
//@include ./src/find
|
|
||||||
var _find = require('./src/find');
|
|
||||||
exports.find = common.wrap('find', _find);
|
|
||||||
|
|
||||||
//@include ./src/cp
|
|
||||||
var _cp = require('./src/cp');
|
|
||||||
exports.cp = common.wrap('cp', _cp);
|
|
||||||
|
|
||||||
//@include ./src/rm
|
|
||||||
var _rm = require('./src/rm');
|
|
||||||
exports.rm = common.wrap('rm', _rm);
|
|
||||||
|
|
||||||
//@include ./src/mv
|
|
||||||
var _mv = require('./src/mv');
|
|
||||||
exports.mv = common.wrap('mv', _mv);
|
|
||||||
|
|
||||||
//@include ./src/mkdir
|
|
||||||
var _mkdir = require('./src/mkdir');
|
|
||||||
exports.mkdir = common.wrap('mkdir', _mkdir);
|
|
||||||
|
|
||||||
//@include ./src/test
|
|
||||||
var _test = require('./src/test');
|
|
||||||
exports.test = common.wrap('test', _test);
|
|
||||||
|
|
||||||
//@include ./src/cat
|
|
||||||
var _cat = require('./src/cat');
|
|
||||||
exports.cat = common.wrap('cat', _cat);
|
|
||||||
|
|
||||||
//@include ./src/to
|
|
||||||
var _to = require('./src/to');
|
|
||||||
String.prototype.to = common.wrap('to', _to);
|
|
||||||
|
|
||||||
//@include ./src/toEnd
|
|
||||||
var _toEnd = require('./src/toEnd');
|
|
||||||
String.prototype.toEnd = common.wrap('toEnd', _toEnd);
|
|
||||||
|
|
||||||
//@include ./src/sed
|
|
||||||
var _sed = require('./src/sed');
|
|
||||||
exports.sed = common.wrap('sed', _sed);
|
|
||||||
|
|
||||||
//@include ./src/grep
|
|
||||||
var _grep = require('./src/grep');
|
|
||||||
exports.grep = common.wrap('grep', _grep);
|
|
||||||
|
|
||||||
//@include ./src/which
|
|
||||||
var _which = require('./src/which');
|
|
||||||
exports.which = common.wrap('which', _which);
|
|
||||||
|
|
||||||
//@include ./src/echo
|
|
||||||
var _echo = require('./src/echo');
|
|
||||||
exports.echo = _echo; // don't common.wrap() as it could parse '-options'
|
|
||||||
|
|
||||||
//@include ./src/dirs
|
|
||||||
var _dirs = require('./src/dirs').dirs;
|
|
||||||
exports.dirs = common.wrap("dirs", _dirs);
|
|
||||||
var _pushd = require('./src/dirs').pushd;
|
|
||||||
exports.pushd = common.wrap('pushd', _pushd);
|
|
||||||
var _popd = require('./src/dirs').popd;
|
|
||||||
exports.popd = common.wrap("popd", _popd);
|
|
||||||
|
|
||||||
//@include ./src/ln
|
|
||||||
var _ln = require('./src/ln');
|
|
||||||
exports.ln = common.wrap('ln', _ln);
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### exit(code)
|
|
||||||
//@ Exits the current process with the given exit code.
|
|
||||||
exports.exit = process.exit;
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### env['VAR_NAME']
|
|
||||||
//@ Object containing environment variables (both getter and setter). Shortcut to process.env.
|
|
||||||
exports.env = process.env;
|
|
||||||
|
|
||||||
//@include ./src/exec
|
|
||||||
var _exec = require('./src/exec');
|
|
||||||
exports.exec = common.wrap('exec', _exec, {notUnix:true});
|
|
||||||
|
|
||||||
//@include ./src/chmod
|
|
||||||
var _chmod = require('./src/chmod');
|
|
||||||
exports.chmod = common.wrap('chmod', _chmod);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ## Non-Unix commands
|
|
||||||
//@
|
|
||||||
|
|
||||||
//@include ./src/tempdir
|
|
||||||
var _tempDir = require('./src/tempdir');
|
|
||||||
exports.tempdir = common.wrap('tempdir', _tempDir);
|
|
||||||
|
|
||||||
|
|
||||||
//@include ./src/error
|
|
||||||
var _error = require('./src/error');
|
|
||||||
exports.error = _error;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ## Configuration
|
|
||||||
//@
|
|
||||||
|
|
||||||
exports.config = common.config;
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### config.silent
|
|
||||||
//@ Example:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ var silentState = config.silent; // save old silent state
|
|
||||||
//@ config.silent = true;
|
|
||||||
//@ /* ... */
|
|
||||||
//@ config.silent = silentState; // restore old silent state
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Suppresses all command output if `true`, except for `echo()` calls.
|
|
||||||
//@ Default is `false`.
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### config.fatal
|
|
||||||
//@ Example:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ config.fatal = true;
|
|
||||||
//@ cp('this_file_does_not_exist', '/dev/null'); // dies here
|
|
||||||
//@ /* more commands... */
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ If `true` the script will die on errors. Default is `false`.
|
|
|
@ -1,43 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### cat(file [, file ...])
|
|
||||||
//@ ### cat(file_array)
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ var str = cat('file*.txt');
|
|
||||||
//@ var str = cat('file1', 'file2');
|
|
||||||
//@ var str = cat(['file1', 'file2']); // same as above
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Returns a string containing the given file, or a concatenated string
|
|
||||||
//@ containing the files if more than one file is given (a new line character is
|
|
||||||
//@ introduced between each file). Wildcard `*` accepted.
|
|
||||||
function _cat(options, files) {
|
|
||||||
var cat = '';
|
|
||||||
|
|
||||||
if (!files)
|
|
||||||
common.error('no paths given');
|
|
||||||
|
|
||||||
if (typeof files === 'string')
|
|
||||||
files = [].slice.call(arguments, 1);
|
|
||||||
// if it's array leave it as it is
|
|
||||||
|
|
||||||
files = common.expand(files);
|
|
||||||
|
|
||||||
files.forEach(function(file) {
|
|
||||||
if (!fs.existsSync(file))
|
|
||||||
common.error('no such file or directory: ' + file);
|
|
||||||
|
|
||||||
cat += fs.readFileSync(file, 'utf8') + '\n';
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cat[cat.length-1] === '\n')
|
|
||||||
cat = cat.substring(0, cat.length-1);
|
|
||||||
|
|
||||||
return common.ShellString(cat);
|
|
||||||
}
|
|
||||||
module.exports = _cat;
|
|
|
@ -1,19 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
var common = require('./common');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### cd('dir')
|
|
||||||
//@ Changes to directory `dir` for the duration of the script
|
|
||||||
function _cd(options, dir) {
|
|
||||||
if (!dir)
|
|
||||||
common.error('directory not specified');
|
|
||||||
|
|
||||||
if (!fs.existsSync(dir))
|
|
||||||
common.error('no such file or directory: ' + dir);
|
|
||||||
|
|
||||||
if (!fs.statSync(dir).isDirectory())
|
|
||||||
common.error('not a directory: ' + dir);
|
|
||||||
|
|
||||||
process.chdir(dir);
|
|
||||||
}
|
|
||||||
module.exports = _cd;
|
|
|
@ -1,208 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
var PERMS = (function (base) {
|
|
||||||
return {
|
|
||||||
OTHER_EXEC : base.EXEC,
|
|
||||||
OTHER_WRITE : base.WRITE,
|
|
||||||
OTHER_READ : base.READ,
|
|
||||||
|
|
||||||
GROUP_EXEC : base.EXEC << 3,
|
|
||||||
GROUP_WRITE : base.WRITE << 3,
|
|
||||||
GROUP_READ : base.READ << 3,
|
|
||||||
|
|
||||||
OWNER_EXEC : base.EXEC << 6,
|
|
||||||
OWNER_WRITE : base.WRITE << 6,
|
|
||||||
OWNER_READ : base.READ << 6,
|
|
||||||
|
|
||||||
// Literal octal numbers are apparently not allowed in "strict" javascript. Using parseInt is
|
|
||||||
// the preferred way, else a jshint warning is thrown.
|
|
||||||
STICKY : parseInt('01000', 8),
|
|
||||||
SETGID : parseInt('02000', 8),
|
|
||||||
SETUID : parseInt('04000', 8),
|
|
||||||
|
|
||||||
TYPE_MASK : parseInt('0770000', 8)
|
|
||||||
};
|
|
||||||
})({
|
|
||||||
EXEC : 1,
|
|
||||||
WRITE : 2,
|
|
||||||
READ : 4
|
|
||||||
});
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### chmod(octal_mode || octal_string, file)
|
|
||||||
//@ ### chmod(symbolic_mode, file)
|
|
||||||
//@
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-v`: output a diagnostic for every file processed//@
|
|
||||||
//@ + `-c`: like verbose but report only when a change is made//@
|
|
||||||
//@ + `-R`: change files and directories recursively//@
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ chmod(755, '/Users/brandon');
|
|
||||||
//@ chmod('755', '/Users/brandon'); // same as above
|
|
||||||
//@ chmod('u+x', '/Users/brandon');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Alters the permissions of a file or directory by either specifying the
|
|
||||||
//@ absolute permissions in octal form or expressing the changes in symbols.
|
|
||||||
//@ This command tries to mimic the POSIX behavior as much as possible.
|
|
||||||
//@ Notable exceptions:
|
|
||||||
//@
|
|
||||||
//@ + In symbolic modes, 'a-r' and '-r' are identical. No consideration is
|
|
||||||
//@ given to the umask.
|
|
||||||
//@ + There is no "quiet" option since default behavior is to run silent.
|
|
||||||
function _chmod(options, mode, filePattern) {
|
|
||||||
if (!filePattern) {
|
|
||||||
if (options.length > 0 && options.charAt(0) === '-') {
|
|
||||||
// Special case where the specified file permissions started with - to subtract perms, which
|
|
||||||
// get picked up by the option parser as command flags.
|
|
||||||
// If we are down by one argument and options starts with -, shift everything over.
|
|
||||||
filePattern = mode;
|
|
||||||
mode = options;
|
|
||||||
options = '';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
common.error('You must specify a file.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'R': 'recursive',
|
|
||||||
'c': 'changes',
|
|
||||||
'v': 'verbose'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (typeof filePattern === 'string') {
|
|
||||||
filePattern = [ filePattern ];
|
|
||||||
}
|
|
||||||
|
|
||||||
var files;
|
|
||||||
|
|
||||||
if (options.recursive) {
|
|
||||||
files = [];
|
|
||||||
common.expand(filePattern).forEach(function addFile(expandedFile) {
|
|
||||||
var stat = fs.lstatSync(expandedFile);
|
|
||||||
|
|
||||||
if (!stat.isSymbolicLink()) {
|
|
||||||
files.push(expandedFile);
|
|
||||||
|
|
||||||
if (stat.isDirectory()) { // intentionally does not follow symlinks.
|
|
||||||
fs.readdirSync(expandedFile).forEach(function (child) {
|
|
||||||
addFile(expandedFile + '/' + child);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
files = common.expand(filePattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
files.forEach(function innerChmod(file) {
|
|
||||||
file = path.resolve(file);
|
|
||||||
if (!fs.existsSync(file)) {
|
|
||||||
common.error('File not found: ' + file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When recursing, don't follow symlinks.
|
|
||||||
if (options.recursive && fs.lstatSync(file).isSymbolicLink()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var perms = fs.statSync(file).mode;
|
|
||||||
var type = perms & PERMS.TYPE_MASK;
|
|
||||||
|
|
||||||
var newPerms = perms;
|
|
||||||
|
|
||||||
if (isNaN(parseInt(mode, 8))) {
|
|
||||||
// parse options
|
|
||||||
mode.split(',').forEach(function (symbolicMode) {
|
|
||||||
/*jshint regexdash:true */
|
|
||||||
var pattern = /([ugoa]*)([=\+-])([rwxXst]*)/i;
|
|
||||||
var matches = pattern.exec(symbolicMode);
|
|
||||||
|
|
||||||
if (matches) {
|
|
||||||
var applyTo = matches[1];
|
|
||||||
var operator = matches[2];
|
|
||||||
var change = matches[3];
|
|
||||||
|
|
||||||
var changeOwner = applyTo.indexOf('u') != -1 || applyTo === 'a' || applyTo === '';
|
|
||||||
var changeGroup = applyTo.indexOf('g') != -1 || applyTo === 'a' || applyTo === '';
|
|
||||||
var changeOther = applyTo.indexOf('o') != -1 || applyTo === 'a' || applyTo === '';
|
|
||||||
|
|
||||||
var changeRead = change.indexOf('r') != -1;
|
|
||||||
var changeWrite = change.indexOf('w') != -1;
|
|
||||||
var changeExec = change.indexOf('x') != -1;
|
|
||||||
var changeSticky = change.indexOf('t') != -1;
|
|
||||||
var changeSetuid = change.indexOf('s') != -1;
|
|
||||||
|
|
||||||
var mask = 0;
|
|
||||||
if (changeOwner) {
|
|
||||||
mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0);
|
|
||||||
}
|
|
||||||
if (changeGroup) {
|
|
||||||
mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0);
|
|
||||||
}
|
|
||||||
if (changeOther) {
|
|
||||||
mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sticky bit is special - it's not tied to user, group or other.
|
|
||||||
if (changeSticky) {
|
|
||||||
mask |= PERMS.STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (operator) {
|
|
||||||
case '+':
|
|
||||||
newPerms |= mask;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '-':
|
|
||||||
newPerms &= ~mask;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '=':
|
|
||||||
newPerms = type + mask;
|
|
||||||
|
|
||||||
// According to POSIX, when using = to explicitly set the permissions, setuid and setgid can never be cleared.
|
|
||||||
if (fs.statSync(file).isDirectory()) {
|
|
||||||
newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.verbose) {
|
|
||||||
log(file + ' -> ' + newPerms.toString(8));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (perms != newPerms) {
|
|
||||||
if (!options.verbose && options.changes) {
|
|
||||||
log(file + ' -> ' + newPerms.toString(8));
|
|
||||||
}
|
|
||||||
fs.chmodSync(file, newPerms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
common.error('Invalid symbolic mode change: ' + symbolicMode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// they gave us a full number
|
|
||||||
newPerms = type + parseInt(mode, 8);
|
|
||||||
|
|
||||||
// POSIX rules are that setuid and setgid can only be added using numeric form, but not cleared.
|
|
||||||
if (fs.statSync(file).isDirectory()) {
|
|
||||||
newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.chmodSync(file, newPerms);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
module.exports = _chmod;
|
|
|
@ -1,203 +0,0 @@
|
||||||
var os = require('os');
|
|
||||||
var fs = require('fs');
|
|
||||||
var _ls = require('./ls');
|
|
||||||
|
|
||||||
// Module globals
|
|
||||||
var config = {
|
|
||||||
silent: false,
|
|
||||||
fatal: false
|
|
||||||
};
|
|
||||||
exports.config = config;
|
|
||||||
|
|
||||||
var state = {
|
|
||||||
error: null,
|
|
||||||
currentCmd: 'shell.js',
|
|
||||||
tempDir: null
|
|
||||||
};
|
|
||||||
exports.state = state;
|
|
||||||
|
|
||||||
var platform = os.type().match(/^Win/) ? 'win' : 'unix';
|
|
||||||
exports.platform = platform;
|
|
||||||
|
|
||||||
function log() {
|
|
||||||
if (!config.silent)
|
|
||||||
console.log.apply(this, arguments);
|
|
||||||
}
|
|
||||||
exports.log = log;
|
|
||||||
|
|
||||||
// Shows error message. Throws unless _continue or config.fatal are true
|
|
||||||
function error(msg, _continue) {
|
|
||||||
if (state.error === null)
|
|
||||||
state.error = '';
|
|
||||||
state.error += state.currentCmd + ': ' + msg + '\n';
|
|
||||||
|
|
||||||
if (msg.length > 0)
|
|
||||||
log(state.error);
|
|
||||||
|
|
||||||
if (config.fatal)
|
|
||||||
process.exit(1);
|
|
||||||
|
|
||||||
if (!_continue)
|
|
||||||
throw '';
|
|
||||||
}
|
|
||||||
exports.error = error;
|
|
||||||
|
|
||||||
// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings.
|
|
||||||
// For now, this is a dummy function to bookmark places we need such strings
|
|
||||||
function ShellString(str) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
exports.ShellString = ShellString;
|
|
||||||
|
|
||||||
// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.:
|
|
||||||
// parseOptions('-a', {'a':'alice', 'b':'bob'});
|
|
||||||
function parseOptions(str, map) {
|
|
||||||
if (!map)
|
|
||||||
error('parseOptions() internal error: no map given');
|
|
||||||
|
|
||||||
// All options are false by default
|
|
||||||
var options = {};
|
|
||||||
for (var letter in map)
|
|
||||||
options[map[letter]] = false;
|
|
||||||
|
|
||||||
if (!str)
|
|
||||||
return options; // defaults
|
|
||||||
|
|
||||||
if (typeof str !== 'string')
|
|
||||||
error('parseOptions() internal error: wrong str');
|
|
||||||
|
|
||||||
// e.g. match[1] = 'Rf' for str = '-Rf'
|
|
||||||
var match = str.match(/^\-(.+)/);
|
|
||||||
if (!match)
|
|
||||||
return options;
|
|
||||||
|
|
||||||
// e.g. chars = ['R', 'f']
|
|
||||||
var chars = match[1].split('');
|
|
||||||
|
|
||||||
chars.forEach(function(c) {
|
|
||||||
if (c in map)
|
|
||||||
options[map[c]] = true;
|
|
||||||
else
|
|
||||||
error('option not recognized: '+c);
|
|
||||||
});
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
exports.parseOptions = parseOptions;
|
|
||||||
|
|
||||||
// Expands wildcards with matching (ie. existing) file names.
|
|
||||||
// For example:
|
|
||||||
// expand(['file*.js']) = ['file1.js', 'file2.js', ...]
|
|
||||||
// (if the files 'file1.js', 'file2.js', etc, exist in the current dir)
|
|
||||||
function expand(list) {
|
|
||||||
var expanded = [];
|
|
||||||
list.forEach(function(listEl) {
|
|
||||||
// Wildcard present on directory names ?
|
|
||||||
if(listEl.search(/\*[^\/]*\//) > -1 || listEl.search(/\*\*[^\/]*\//) > -1) {
|
|
||||||
var match = listEl.match(/^([^*]+\/|)(.*)/);
|
|
||||||
var root = match[1];
|
|
||||||
var rest = match[2];
|
|
||||||
var restRegex = rest.replace(/\*\*/g, ".*").replace(/\*/g, "[^\\/]*");
|
|
||||||
restRegex = new RegExp(restRegex);
|
|
||||||
|
|
||||||
_ls('-R', root).filter(function (e) {
|
|
||||||
return restRegex.test(e);
|
|
||||||
}).forEach(function(file) {
|
|
||||||
expanded.push(file);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Wildcard present on file names ?
|
|
||||||
else if (listEl.search(/\*/) > -1) {
|
|
||||||
_ls('', listEl).forEach(function(file) {
|
|
||||||
expanded.push(file);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
expanded.push(listEl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return expanded;
|
|
||||||
}
|
|
||||||
exports.expand = expand;
|
|
||||||
|
|
||||||
// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e.
|
|
||||||
// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006
|
|
||||||
function unlinkSync(file) {
|
|
||||||
try {
|
|
||||||
fs.unlinkSync(file);
|
|
||||||
} catch(e) {
|
|
||||||
// Try to override file permission
|
|
||||||
if (e.code === 'EPERM') {
|
|
||||||
fs.chmodSync(file, '0666');
|
|
||||||
fs.unlinkSync(file);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.unlinkSync = unlinkSync;
|
|
||||||
|
|
||||||
// e.g. 'shelljs_a5f185d0443ca...'
|
|
||||||
function randomFileName() {
|
|
||||||
function randomHash(count) {
|
|
||||||
if (count === 1)
|
|
||||||
return parseInt(16*Math.random(), 10).toString(16);
|
|
||||||
else {
|
|
||||||
var hash = '';
|
|
||||||
for (var i=0; i<count; i++)
|
|
||||||
hash += randomHash(1);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'shelljs_'+randomHash(20);
|
|
||||||
}
|
|
||||||
exports.randomFileName = randomFileName;
|
|
||||||
|
|
||||||
// extend(target_obj, source_obj1 [, source_obj2 ...])
|
|
||||||
// Shallow extend, e.g.:
|
|
||||||
// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3}
|
|
||||||
function extend(target) {
|
|
||||||
var sources = [].slice.call(arguments, 1);
|
|
||||||
sources.forEach(function(source) {
|
|
||||||
for (var key in source)
|
|
||||||
target[key] = source[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
exports.extend = extend;
|
|
||||||
|
|
||||||
// Common wrapper for all Unix-like commands
|
|
||||||
function wrap(cmd, fn, options) {
|
|
||||||
return function() {
|
|
||||||
var retValue = null;
|
|
||||||
|
|
||||||
state.currentCmd = cmd;
|
|
||||||
state.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
var args = [].slice.call(arguments, 0);
|
|
||||||
|
|
||||||
if (options && options.notUnix) {
|
|
||||||
retValue = fn.apply(this, args);
|
|
||||||
} else {
|
|
||||||
if (args.length === 0 || typeof args[0] !== 'string' || args[0][0] !== '-')
|
|
||||||
args.unshift(''); // only add dummy option if '-option' not already present
|
|
||||||
retValue = fn.apply(this, args);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (!state.error) {
|
|
||||||
// If state.error hasn't been set it's an error thrown by Node, not us - probably a bug...
|
|
||||||
console.log('shell.js: internal error');
|
|
||||||
console.log(e.stack || e);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
if (config.fatal)
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.currentCmd = 'shell.js';
|
|
||||||
return retValue;
|
|
||||||
};
|
|
||||||
} // wrap
|
|
||||||
exports.wrap = wrap;
|
|
|
@ -1,201 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
var common = require('./common');
|
|
||||||
var os = require('os');
|
|
||||||
|
|
||||||
// Buffered file copy, synchronous
|
|
||||||
// (Using readFileSync() + writeFileSync() could easily cause a memory overflow
|
|
||||||
// with large files)
|
|
||||||
function copyFileSync(srcFile, destFile) {
|
|
||||||
if (!fs.existsSync(srcFile))
|
|
||||||
common.error('copyFileSync: no such file or directory: ' + srcFile);
|
|
||||||
|
|
||||||
var BUF_LENGTH = 64*1024,
|
|
||||||
buf = new Buffer(BUF_LENGTH),
|
|
||||||
bytesRead = BUF_LENGTH,
|
|
||||||
pos = 0,
|
|
||||||
fdr = null,
|
|
||||||
fdw = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
fdr = fs.openSync(srcFile, 'r');
|
|
||||||
} catch(e) {
|
|
||||||
common.error('copyFileSync: could not read src file ('+srcFile+')');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
fdw = fs.openSync(destFile, 'w');
|
|
||||||
} catch(e) {
|
|
||||||
common.error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (bytesRead === BUF_LENGTH) {
|
|
||||||
bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
|
|
||||||
fs.writeSync(fdw, buf, 0, bytesRead);
|
|
||||||
pos += bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.closeSync(fdr);
|
|
||||||
fs.closeSync(fdw);
|
|
||||||
|
|
||||||
fs.chmodSync(destFile, fs.statSync(srcFile).mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursively copies 'sourceDir' into 'destDir'
|
|
||||||
// Adapted from https://github.com/ryanmcgrath/wrench-js
|
|
||||||
//
|
|
||||||
// Copyright (c) 2010 Ryan McGrath
|
|
||||||
// Copyright (c) 2012 Artur Adib
|
|
||||||
//
|
|
||||||
// Licensed under the MIT License
|
|
||||||
// http://www.opensource.org/licenses/mit-license.php
|
|
||||||
function cpdirSyncRecursive(sourceDir, destDir, opts) {
|
|
||||||
if (!opts) opts = {};
|
|
||||||
|
|
||||||
/* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
|
|
||||||
var checkDir = fs.statSync(sourceDir);
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(destDir, checkDir.mode);
|
|
||||||
} catch (e) {
|
|
||||||
//if the directory already exists, that's okay
|
|
||||||
if (e.code !== 'EEXIST') throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
var files = fs.readdirSync(sourceDir);
|
|
||||||
|
|
||||||
for (var i = 0; i < files.length; i++) {
|
|
||||||
var srcFile = sourceDir + "/" + files[i];
|
|
||||||
var destFile = destDir + "/" + files[i];
|
|
||||||
var srcFileStat = fs.lstatSync(srcFile);
|
|
||||||
|
|
||||||
if (srcFileStat.isDirectory()) {
|
|
||||||
/* recursion this thing right on back. */
|
|
||||||
cpdirSyncRecursive(srcFile, destFile, opts);
|
|
||||||
} else if (srcFileStat.isSymbolicLink()) {
|
|
||||||
var symlinkFull = fs.readlinkSync(srcFile);
|
|
||||||
fs.symlinkSync(symlinkFull, destFile, os.platform() === "win32" ? "junction" : null);
|
|
||||||
} else {
|
|
||||||
/* At this point, we've hit a file actually worth copying... so copy it on over. */
|
|
||||||
if (fs.existsSync(destFile) && !opts.force) {
|
|
||||||
common.log('skipping existing file: ' + files[i]);
|
|
||||||
} else {
|
|
||||||
copyFileSync(srcFile, destFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // for files
|
|
||||||
} // cpdirSyncRecursive
|
|
||||||
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### cp([options ,] source [,source ...], dest)
|
|
||||||
//@ ### cp([options ,] source_array, dest)
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-f`: force
|
|
||||||
//@ + `-r, -R`: recursive
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ cp('file1', 'dir1');
|
|
||||||
//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
|
|
||||||
//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Copies files. The wildcard `*` is accepted.
|
|
||||||
function _cp(options, sources, dest) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'f': 'force',
|
|
||||||
'R': 'recursive',
|
|
||||||
'r': 'recursive'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get sources, dest
|
|
||||||
if (arguments.length < 3) {
|
|
||||||
common.error('missing <source> and/or <dest>');
|
|
||||||
} else if (arguments.length > 3) {
|
|
||||||
sources = [].slice.call(arguments, 1, arguments.length - 1);
|
|
||||||
dest = arguments[arguments.length - 1];
|
|
||||||
} else if (typeof sources === 'string') {
|
|
||||||
sources = [sources];
|
|
||||||
} else if ('length' in sources) {
|
|
||||||
sources = sources; // no-op for array
|
|
||||||
} else {
|
|
||||||
common.error('invalid arguments');
|
|
||||||
}
|
|
||||||
|
|
||||||
var exists = fs.existsSync(dest),
|
|
||||||
stats = exists && fs.statSync(dest);
|
|
||||||
|
|
||||||
// Dest is not existing dir, but multiple sources given
|
|
||||||
if ((!exists || !stats.isDirectory()) && sources.length > 1)
|
|
||||||
common.error('dest is not a directory (too many sources)');
|
|
||||||
|
|
||||||
// Dest is an existing file, but no -f given
|
|
||||||
if (exists && stats.isFile() && !options.force)
|
|
||||||
common.error('dest file already exists: ' + dest);
|
|
||||||
|
|
||||||
if (options.recursive) {
|
|
||||||
// Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*"
|
|
||||||
// (see Github issue #15)
|
|
||||||
sources.forEach(function(src, i) {
|
|
||||||
if (src[src.length - 1] === '/')
|
|
||||||
sources[i] += '*';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create dest
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(dest, parseInt('0777', 8));
|
|
||||||
} catch (e) {
|
|
||||||
// like Unix's cp, keep going even if we can't create dest dir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sources = common.expand(sources);
|
|
||||||
|
|
||||||
sources.forEach(function(src) {
|
|
||||||
if (!fs.existsSync(src)) {
|
|
||||||
common.error('no such file or directory: '+src, true);
|
|
||||||
return; // skip file
|
|
||||||
}
|
|
||||||
|
|
||||||
// If here, src exists
|
|
||||||
if (fs.statSync(src).isDirectory()) {
|
|
||||||
if (!options.recursive) {
|
|
||||||
// Non-Recursive
|
|
||||||
common.log(src + ' is a directory (not copied)');
|
|
||||||
} else {
|
|
||||||
// Recursive
|
|
||||||
// 'cp /a/source dest' should create 'source' in 'dest'
|
|
||||||
var newDest = path.join(dest, path.basename(src)),
|
|
||||||
checkDir = fs.statSync(src);
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(newDest, checkDir.mode);
|
|
||||||
} catch (e) {
|
|
||||||
//if the directory already exists, that's okay
|
|
||||||
if (e.code !== 'EEXIST') throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpdirSyncRecursive(src, newDest, {force: options.force});
|
|
||||||
}
|
|
||||||
return; // done with dir
|
|
||||||
}
|
|
||||||
|
|
||||||
// If here, src is a file
|
|
||||||
|
|
||||||
// When copying to '/path/dir':
|
|
||||||
// thisDest = '/path/dir/file1'
|
|
||||||
var thisDest = dest;
|
|
||||||
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
|
|
||||||
thisDest = path.normalize(dest + '/' + path.basename(src));
|
|
||||||
|
|
||||||
if (fs.existsSync(thisDest) && !options.force) {
|
|
||||||
common.error('dest file already exists: ' + thisDest, true);
|
|
||||||
return; // skip file
|
|
||||||
}
|
|
||||||
|
|
||||||
copyFileSync(src, thisDest);
|
|
||||||
}); // forEach(src)
|
|
||||||
}
|
|
||||||
module.exports = _cp;
|
|
|
@ -1,191 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var _cd = require('./cd');
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
// Pushd/popd/dirs internals
|
|
||||||
var _dirStack = [];
|
|
||||||
|
|
||||||
function _isStackIndex(index) {
|
|
||||||
return (/^[\-+]\d+$/).test(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _parseStackIndex(index) {
|
|
||||||
if (_isStackIndex(index)) {
|
|
||||||
if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd
|
|
||||||
return (/^-/).test(index) ? Number(index) - 1 : Number(index);
|
|
||||||
} else {
|
|
||||||
common.error(index + ': directory stack index out of range');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
common.error(index + ': invalid number');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _actualDirStack() {
|
|
||||||
return [process.cwd()].concat(_dirStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### pushd([options,] [dir | '-N' | '+N'])
|
|
||||||
//@
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
|
|
||||||
//@
|
|
||||||
//@ Arguments:
|
|
||||||
//@
|
|
||||||
//@ + `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`.
|
|
||||||
//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
|
||||||
//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ // process.cwd() === '/usr'
|
|
||||||
//@ pushd('/etc'); // Returns /etc /usr
|
|
||||||
//@ pushd('+1'); // Returns /usr /etc
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack.
|
|
||||||
function _pushd(options, dir) {
|
|
||||||
if (_isStackIndex(options)) {
|
|
||||||
dir = options;
|
|
||||||
options = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'n' : 'no-cd'
|
|
||||||
});
|
|
||||||
|
|
||||||
var dirs = _actualDirStack();
|
|
||||||
|
|
||||||
if (dir === '+0') {
|
|
||||||
return dirs; // +0 is a noop
|
|
||||||
} else if (!dir) {
|
|
||||||
if (dirs.length > 1) {
|
|
||||||
dirs = dirs.splice(1, 1).concat(dirs);
|
|
||||||
} else {
|
|
||||||
return common.error('no other directory');
|
|
||||||
}
|
|
||||||
} else if (_isStackIndex(dir)) {
|
|
||||||
var n = _parseStackIndex(dir);
|
|
||||||
dirs = dirs.slice(n).concat(dirs.slice(0, n));
|
|
||||||
} else {
|
|
||||||
if (options['no-cd']) {
|
|
||||||
dirs.splice(1, 0, dir);
|
|
||||||
} else {
|
|
||||||
dirs.unshift(dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options['no-cd']) {
|
|
||||||
dirs = dirs.slice(1);
|
|
||||||
} else {
|
|
||||||
dir = path.resolve(dirs.shift());
|
|
||||||
_cd('', dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
_dirStack = dirs;
|
|
||||||
return _dirs('');
|
|
||||||
}
|
|
||||||
exports.pushd = _pushd;
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### popd([options,] ['-N' | '+N'])
|
|
||||||
//@
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
|
|
||||||
//@
|
|
||||||
//@ Arguments:
|
|
||||||
//@
|
|
||||||
//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
|
|
||||||
//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ echo(process.cwd()); // '/usr'
|
|
||||||
//@ pushd('/etc'); // '/etc /usr'
|
|
||||||
//@ echo(process.cwd()); // '/etc'
|
|
||||||
//@ popd(); // '/usr'
|
|
||||||
//@ echo(process.cwd()); // '/usr'
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack.
|
|
||||||
function _popd(options, index) {
|
|
||||||
if (_isStackIndex(options)) {
|
|
||||||
index = options;
|
|
||||||
options = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'n' : 'no-cd'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!_dirStack.length) {
|
|
||||||
return common.error('directory stack empty');
|
|
||||||
}
|
|
||||||
|
|
||||||
index = _parseStackIndex(index || '+0');
|
|
||||||
|
|
||||||
if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) {
|
|
||||||
index = index > 0 ? index - 1 : index;
|
|
||||||
_dirStack.splice(index, 1);
|
|
||||||
} else {
|
|
||||||
var dir = path.resolve(_dirStack.shift());
|
|
||||||
_cd('', dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _dirs('');
|
|
||||||
}
|
|
||||||
exports.popd = _popd;
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### dirs([options | '+N' | '-N'])
|
|
||||||
//@
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-c`: Clears the directory stack by deleting all of the elements.
|
|
||||||
//@
|
|
||||||
//@ Arguments:
|
|
||||||
//@
|
|
||||||
//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
|
|
||||||
//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
|
|
||||||
//@
|
|
||||||
//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified.
|
|
||||||
//@
|
|
||||||
//@ See also: pushd, popd
|
|
||||||
function _dirs(options, index) {
|
|
||||||
if (_isStackIndex(options)) {
|
|
||||||
index = options;
|
|
||||||
options = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'c' : 'clear'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options['clear']) {
|
|
||||||
_dirStack = [];
|
|
||||||
return _dirStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stack = _actualDirStack();
|
|
||||||
|
|
||||||
if (index) {
|
|
||||||
index = _parseStackIndex(index);
|
|
||||||
|
|
||||||
if (index < 0) {
|
|
||||||
index = stack.length + index;
|
|
||||||
}
|
|
||||||
|
|
||||||
common.log(stack[index]);
|
|
||||||
return stack[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
common.log(stack.join(' '));
|
|
||||||
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
exports.dirs = _dirs;
|
|
|
@ -1,20 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### echo(string [,string ...])
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ echo('hello world');
|
|
||||||
//@ var str = echo('hello world');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Prints string to stdout, and returns string with additional utility methods
|
|
||||||
//@ like `.to()`.
|
|
||||||
function _echo() {
|
|
||||||
var messages = [].slice.call(arguments, 0);
|
|
||||||
console.log.apply(this, messages);
|
|
||||||
return common.ShellString(messages.join(' '));
|
|
||||||
}
|
|
||||||
module.exports = _echo;
|
|
|
@ -1,10 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### error()
|
|
||||||
//@ Tests if error occurred in the last command. Returns `null` if no error occurred,
|
|
||||||
//@ otherwise returns string explaining the error
|
|
||||||
function error() {
|
|
||||||
return common.state.error;
|
|
||||||
};
|
|
||||||
module.exports = error;
|
|
|
@ -1,181 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var _tempDir = require('./tempdir');
|
|
||||||
var _pwd = require('./pwd');
|
|
||||||
var path = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
var child = require('child_process');
|
|
||||||
|
|
||||||
// Hack to run child_process.exec() synchronously (sync avoids callback hell)
|
|
||||||
// Uses a custom wait loop that checks for a flag file, created when the child process is done.
|
|
||||||
// (Can't do a wait loop that checks for internal Node variables/messages as
|
|
||||||
// Node is single-threaded; callbacks and other internal state changes are done in the
|
|
||||||
// event loop).
|
|
||||||
function execSync(cmd, opts) {
|
|
||||||
var tempDir = _tempDir();
|
|
||||||
var stdoutFile = path.resolve(tempDir+'/'+common.randomFileName()),
|
|
||||||
codeFile = path.resolve(tempDir+'/'+common.randomFileName()),
|
|
||||||
scriptFile = path.resolve(tempDir+'/'+common.randomFileName()),
|
|
||||||
sleepFile = path.resolve(tempDir+'/'+common.randomFileName());
|
|
||||||
|
|
||||||
var options = common.extend({
|
|
||||||
silent: common.config.silent
|
|
||||||
}, opts);
|
|
||||||
|
|
||||||
var previousStdoutContent = '';
|
|
||||||
// Echoes stdout changes from running process, if not silent
|
|
||||||
function updateStdout() {
|
|
||||||
if (options.silent || !fs.existsSync(stdoutFile))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var stdoutContent = fs.readFileSync(stdoutFile, 'utf8');
|
|
||||||
// No changes since last time?
|
|
||||||
if (stdoutContent.length <= previousStdoutContent.length)
|
|
||||||
return;
|
|
||||||
|
|
||||||
process.stdout.write(stdoutContent.substr(previousStdoutContent.length));
|
|
||||||
previousStdoutContent = stdoutContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function escape(str) {
|
|
||||||
return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd += ' > '+stdoutFile+' 2>&1'; // works on both win/unix
|
|
||||||
|
|
||||||
var script =
|
|
||||||
"var child = require('child_process')," +
|
|
||||||
" fs = require('fs');" +
|
|
||||||
"child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {" +
|
|
||||||
" fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');" +
|
|
||||||
"});";
|
|
||||||
|
|
||||||
if (fs.existsSync(scriptFile)) common.unlinkSync(scriptFile);
|
|
||||||
if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile);
|
|
||||||
if (fs.existsSync(codeFile)) common.unlinkSync(codeFile);
|
|
||||||
|
|
||||||
fs.writeFileSync(scriptFile, script);
|
|
||||||
child.exec('"'+process.execPath+'" '+scriptFile, {
|
|
||||||
env: process.env,
|
|
||||||
cwd: _pwd(),
|
|
||||||
maxBuffer: 20*1024*1024
|
|
||||||
});
|
|
||||||
|
|
||||||
// The wait loop
|
|
||||||
// sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage
|
|
||||||
// (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing
|
|
||||||
// CPU usage, though apparently not so much on Windows)
|
|
||||||
while (!fs.existsSync(codeFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }
|
|
||||||
while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }
|
|
||||||
|
|
||||||
// At this point codeFile exists, but it's not necessarily flushed yet.
|
|
||||||
// Keep reading it until it is.
|
|
||||||
var code = parseInt('', 10);
|
|
||||||
while (isNaN(code)) {
|
|
||||||
code = parseInt(fs.readFileSync(codeFile, 'utf8'), 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
var stdout = fs.readFileSync(stdoutFile, 'utf8');
|
|
||||||
|
|
||||||
// No biggie if we can't erase the files now -- they're in a temp dir anyway
|
|
||||||
try { common.unlinkSync(scriptFile); } catch(e) {}
|
|
||||||
try { common.unlinkSync(stdoutFile); } catch(e) {}
|
|
||||||
try { common.unlinkSync(codeFile); } catch(e) {}
|
|
||||||
try { common.unlinkSync(sleepFile); } catch(e) {}
|
|
||||||
|
|
||||||
// some shell return codes are defined as errors, per http://tldp.org/LDP/abs/html/exitcodes.html
|
|
||||||
if (code === 1 || code === 2 || code >= 126) {
|
|
||||||
common.error('', true); // unix/shell doesn't really give an error message after non-zero exit codes
|
|
||||||
}
|
|
||||||
// True if successful, false if not
|
|
||||||
var obj = {
|
|
||||||
code: code,
|
|
||||||
output: stdout
|
|
||||||
};
|
|
||||||
return obj;
|
|
||||||
} // execSync()
|
|
||||||
|
|
||||||
// Wrapper around exec() to enable echoing output to console in real time
|
|
||||||
function execAsync(cmd, opts, callback) {
|
|
||||||
var output = '';
|
|
||||||
|
|
||||||
var options = common.extend({
|
|
||||||
silent: common.config.silent
|
|
||||||
}, opts);
|
|
||||||
|
|
||||||
var c = child.exec(cmd, {env: process.env, maxBuffer: 20*1024*1024}, function(err) {
|
|
||||||
if (callback)
|
|
||||||
callback(err ? err.code : 0, output);
|
|
||||||
});
|
|
||||||
|
|
||||||
c.stdout.on('data', function(data) {
|
|
||||||
output += data;
|
|
||||||
if (!options.silent)
|
|
||||||
process.stdout.write(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
c.stderr.on('data', function(data) {
|
|
||||||
output += data;
|
|
||||||
if (!options.silent)
|
|
||||||
process.stdout.write(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### exec(command [, options] [, callback])
|
|
||||||
//@ Available options (all `false` by default):
|
|
||||||
//@
|
|
||||||
//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided.
|
|
||||||
//@ + `silent`: Do not echo program output to console.
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ var version = exec('node --version', {silent:true}).output;
|
|
||||||
//@
|
|
||||||
//@ var child = exec('some_long_running_process', {async:true});
|
|
||||||
//@ child.stdout.on('data', function(data) {
|
|
||||||
//@ /* ... do something with data ... */
|
|
||||||
//@ });
|
|
||||||
//@
|
|
||||||
//@ exec('some_long_running_process', function(code, output) {
|
|
||||||
//@ console.log('Exit code:', code);
|
|
||||||
//@ console.log('Program output:', output);
|
|
||||||
//@ });
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Executes the given `command` _synchronously_, unless otherwise specified.
|
|
||||||
//@ When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's
|
|
||||||
//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and
|
|
||||||
//@ the `callback` gets the arguments `(code, output)`.
|
|
||||||
//@
|
|
||||||
//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as
|
|
||||||
//@ the current synchronous implementation uses a lot of CPU. This should be getting
|
|
||||||
//@ fixed soon.
|
|
||||||
function _exec(command, options, callback) {
|
|
||||||
if (!command)
|
|
||||||
common.error('must specify command');
|
|
||||||
|
|
||||||
// Callback is defined instead of options.
|
|
||||||
if (typeof options === 'function') {
|
|
||||||
callback = options;
|
|
||||||
options = { async: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback is defined with options.
|
|
||||||
if (typeof options === 'object' && typeof callback === 'function') {
|
|
||||||
options.async = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
options = common.extend({
|
|
||||||
silent: common.config.silent,
|
|
||||||
async: false
|
|
||||||
}, options);
|
|
||||||
|
|
||||||
if (options.async)
|
|
||||||
return execAsync(command, options, callback);
|
|
||||||
else
|
|
||||||
return execSync(command, options);
|
|
||||||
}
|
|
||||||
module.exports = _exec;
|
|
|
@ -1,51 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
var common = require('./common');
|
|
||||||
var _ls = require('./ls');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### find(path [,path ...])
|
|
||||||
//@ ### find(path_array)
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ find('src', 'lib');
|
|
||||||
//@ find(['src', 'lib']); // same as above
|
|
||||||
//@ find('.').filter(function(file) { return file.match(/\.js$/); });
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Returns array of all files (however deep) in the given paths.
|
|
||||||
//@
|
|
||||||
//@ The main difference from `ls('-R', path)` is that the resulting file names
|
|
||||||
//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
|
|
||||||
function _find(options, paths) {
|
|
||||||
if (!paths)
|
|
||||||
common.error('no path specified');
|
|
||||||
else if (typeof paths === 'object')
|
|
||||||
paths = paths; // assume array
|
|
||||||
else if (typeof paths === 'string')
|
|
||||||
paths = [].slice.call(arguments, 1);
|
|
||||||
|
|
||||||
var list = [];
|
|
||||||
|
|
||||||
function pushFile(file) {
|
|
||||||
if (common.platform === 'win')
|
|
||||||
file = file.replace(/\\/g, '/');
|
|
||||||
list.push(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// why not simply do ls('-R', paths)? because the output wouldn't give the base dirs
|
|
||||||
// to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory
|
|
||||||
|
|
||||||
paths.forEach(function(file) {
|
|
||||||
pushFile(file);
|
|
||||||
|
|
||||||
if (fs.statSync(file).isDirectory()) {
|
|
||||||
_ls('-RA', file+'/*').forEach(function(subfile) {
|
|
||||||
pushFile(subfile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
module.exports = _find;
|
|
|
@ -1,52 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### grep([options ,] regex_filter, file [, file ...])
|
|
||||||
//@ ### grep([options ,] regex_filter, file_array)
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria.
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ grep('-v', 'GLOBAL_VARIABLE', '*.js');
|
|
||||||
//@ grep('GLOBAL_VARIABLE', '*.js');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Reads input string from given files and returns a string containing all lines of the
|
|
||||||
//@ file that match the given `regex_filter`. Wildcard `*` accepted.
|
|
||||||
function _grep(options, regex, files) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'v': 'inverse'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!files)
|
|
||||||
common.error('no paths given');
|
|
||||||
|
|
||||||
if (typeof files === 'string')
|
|
||||||
files = [].slice.call(arguments, 2);
|
|
||||||
// if it's array leave it as it is
|
|
||||||
|
|
||||||
files = common.expand(files);
|
|
||||||
|
|
||||||
var grep = '';
|
|
||||||
files.forEach(function(file) {
|
|
||||||
if (!fs.existsSync(file)) {
|
|
||||||
common.error('no such file or directory: ' + file, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var contents = fs.readFileSync(file, 'utf8'),
|
|
||||||
lines = contents.split(/\r*\n/);
|
|
||||||
lines.forEach(function(line) {
|
|
||||||
var matched = line.match(regex);
|
|
||||||
if ((options.inverse && !matched) || (!options.inverse && matched))
|
|
||||||
grep += line + '\n';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return common.ShellString(grep);
|
|
||||||
}
|
|
||||||
module.exports = _grep;
|
|
|
@ -1,53 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
var common = require('./common');
|
|
||||||
var os = require('os');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### ln(options, source, dest)
|
|
||||||
//@ ### ln(source, dest)
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `s`: symlink
|
|
||||||
//@ + `f`: force
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ ln('file', 'newlink');
|
|
||||||
//@ ln('-sf', 'file', 'existing');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Links source to dest. Use -f to force the link, should dest already exist.
|
|
||||||
function _ln(options, source, dest) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
's': 'symlink',
|
|
||||||
'f': 'force'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!source || !dest) {
|
|
||||||
common.error('Missing <source> and/or <dest>');
|
|
||||||
}
|
|
||||||
|
|
||||||
source = path.resolve(process.cwd(), String(source));
|
|
||||||
dest = path.resolve(process.cwd(), String(dest));
|
|
||||||
|
|
||||||
if (!fs.existsSync(source)) {
|
|
||||||
common.error('Source file does not exist', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fs.existsSync(dest)) {
|
|
||||||
if (!options.force) {
|
|
||||||
common.error('Destination file exists', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.unlinkSync(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.symlink) {
|
|
||||||
fs.symlinkSync(source, dest, os.platform() === "win32" ? "junction" : null);
|
|
||||||
} else {
|
|
||||||
fs.linkSync(source, dest, os.platform() === "win32" ? "junction" : null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = _ln;
|
|
|
@ -1,126 +0,0 @@
|
||||||
var path = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
var common = require('./common');
|
|
||||||
var _cd = require('./cd');
|
|
||||||
var _pwd = require('./pwd');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### ls([options ,] path [,path ...])
|
|
||||||
//@ ### ls([options ,] path_array)
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-R`: recursive
|
|
||||||
//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`)
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ ls('projs/*.js');
|
|
||||||
//@ ls('-R', '/users/me', '/tmp');
|
|
||||||
//@ ls('-R', ['/users/me', '/tmp']); // same as above
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Returns array of files in the given path, or in current directory if no path provided.
|
|
||||||
function _ls(options, paths) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'R': 'recursive',
|
|
||||||
'A': 'all',
|
|
||||||
'a': 'all_deprecated'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.all_deprecated) {
|
|
||||||
// We won't support the -a option as it's hard to image why it's useful
|
|
||||||
// (it includes '.' and '..' in addition to '.*' files)
|
|
||||||
// For backwards compatibility we'll dump a deprecated message and proceed as before
|
|
||||||
common.log('ls: Option -a is deprecated. Use -A instead');
|
|
||||||
options.all = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!paths)
|
|
||||||
paths = ['.'];
|
|
||||||
else if (typeof paths === 'object')
|
|
||||||
paths = paths; // assume array
|
|
||||||
else if (typeof paths === 'string')
|
|
||||||
paths = [].slice.call(arguments, 1);
|
|
||||||
|
|
||||||
var list = [];
|
|
||||||
|
|
||||||
// Conditionally pushes file to list - returns true if pushed, false otherwise
|
|
||||||
// (e.g. prevents hidden files to be included unless explicitly told so)
|
|
||||||
function pushFile(file, query) {
|
|
||||||
// hidden file?
|
|
||||||
if (path.basename(file)[0] === '.') {
|
|
||||||
// not explicitly asking for hidden files?
|
|
||||||
if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common.platform === 'win')
|
|
||||||
file = file.replace(/\\/g, '/');
|
|
||||||
|
|
||||||
list.push(file);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
paths.forEach(function(p) {
|
|
||||||
if (fs.existsSync(p)) {
|
|
||||||
var stats = fs.statSync(p);
|
|
||||||
// Simple file?
|
|
||||||
if (stats.isFile()) {
|
|
||||||
pushFile(p, p);
|
|
||||||
return; // continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple dir?
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
// Iterate over p contents
|
|
||||||
fs.readdirSync(p).forEach(function(file) {
|
|
||||||
if (!pushFile(file, p))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Recursive?
|
|
||||||
if (options.recursive) {
|
|
||||||
var oldDir = _pwd();
|
|
||||||
_cd('', p);
|
|
||||||
if (fs.statSync(file).isDirectory())
|
|
||||||
list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*'));
|
|
||||||
_cd('', oldDir);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return; // continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// p does not exist - possible wildcard present
|
|
||||||
|
|
||||||
var basename = path.basename(p);
|
|
||||||
var dirname = path.dirname(p);
|
|
||||||
// Wildcard present on an existing dir? (e.g. '/tmp/*.js')
|
|
||||||
if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) {
|
|
||||||
// Escape special regular expression chars
|
|
||||||
var regexp = basename.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1');
|
|
||||||
// Translates wildcard into regex
|
|
||||||
regexp = '^' + regexp.replace(/\*/g, '.*') + '$';
|
|
||||||
// Iterate over directory contents
|
|
||||||
fs.readdirSync(dirname).forEach(function(file) {
|
|
||||||
if (file.match(new RegExp(regexp))) {
|
|
||||||
if (!pushFile(path.normalize(dirname+'/'+file), basename))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Recursive?
|
|
||||||
if (options.recursive) {
|
|
||||||
var pp = dirname + '/' + file;
|
|
||||||
if (fs.lstatSync(pp).isDirectory())
|
|
||||||
list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*'));
|
|
||||||
} // recursive
|
|
||||||
} // if file matches
|
|
||||||
}); // forEach
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
common.error('no such file or directory: ' + p, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
module.exports = _ls;
|
|
|
@ -1,68 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
// Recursively creates 'dir'
|
|
||||||
function mkdirSyncRecursive(dir) {
|
|
||||||
var baseDir = path.dirname(dir);
|
|
||||||
|
|
||||||
// Base dir exists, no recursion necessary
|
|
||||||
if (fs.existsSync(baseDir)) {
|
|
||||||
fs.mkdirSync(dir, parseInt('0777', 8));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base dir does not exist, go recursive
|
|
||||||
mkdirSyncRecursive(baseDir);
|
|
||||||
|
|
||||||
// Base dir created, can create dir
|
|
||||||
fs.mkdirSync(dir, parseInt('0777', 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### mkdir([options ,] dir [, dir ...])
|
|
||||||
//@ ### mkdir([options ,] dir_array)
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `p`: full path (will create intermediate dirs if necessary)
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');
|
|
||||||
//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Creates directories.
|
|
||||||
function _mkdir(options, dirs) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'p': 'fullpath'
|
|
||||||
});
|
|
||||||
if (!dirs)
|
|
||||||
common.error('no paths given');
|
|
||||||
|
|
||||||
if (typeof dirs === 'string')
|
|
||||||
dirs = [].slice.call(arguments, 1);
|
|
||||||
// if it's array leave it as it is
|
|
||||||
|
|
||||||
dirs.forEach(function(dir) {
|
|
||||||
if (fs.existsSync(dir)) {
|
|
||||||
if (!options.fullpath)
|
|
||||||
common.error('path already exists: ' + dir, true);
|
|
||||||
return; // skip dir
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base dir does not exist, and no -p option given
|
|
||||||
var baseDir = path.dirname(dir);
|
|
||||||
if (!fs.existsSync(baseDir) && !options.fullpath) {
|
|
||||||
common.error('no such file or directory: ' + baseDir, true);
|
|
||||||
return; // skip dir
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.fullpath)
|
|
||||||
mkdirSyncRecursive(dir);
|
|
||||||
else
|
|
||||||
fs.mkdirSync(dir, parseInt('0777', 8));
|
|
||||||
});
|
|
||||||
} // mkdir
|
|
||||||
module.exports = _mkdir;
|
|
|
@ -1,80 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
var common = require('./common');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### mv(source [, source ...], dest')
|
|
||||||
//@ ### mv(source_array, dest')
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `f`: force
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ mv('-f', 'file', 'dir/');
|
|
||||||
//@ mv('file1', 'file2', 'dir/');
|
|
||||||
//@ mv(['file1', 'file2'], 'dir/'); // same as above
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Moves files. The wildcard `*` is accepted.
|
|
||||||
function _mv(options, sources, dest) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'f': 'force'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get sources, dest
|
|
||||||
if (arguments.length < 3) {
|
|
||||||
common.error('missing <source> and/or <dest>');
|
|
||||||
} else if (arguments.length > 3) {
|
|
||||||
sources = [].slice.call(arguments, 1, arguments.length - 1);
|
|
||||||
dest = arguments[arguments.length - 1];
|
|
||||||
} else if (typeof sources === 'string') {
|
|
||||||
sources = [sources];
|
|
||||||
} else if ('length' in sources) {
|
|
||||||
sources = sources; // no-op for array
|
|
||||||
} else {
|
|
||||||
common.error('invalid arguments');
|
|
||||||
}
|
|
||||||
|
|
||||||
sources = common.expand(sources);
|
|
||||||
|
|
||||||
var exists = fs.existsSync(dest),
|
|
||||||
stats = exists && fs.statSync(dest);
|
|
||||||
|
|
||||||
// Dest is not existing dir, but multiple sources given
|
|
||||||
if ((!exists || !stats.isDirectory()) && sources.length > 1)
|
|
||||||
common.error('dest is not a directory (too many sources)');
|
|
||||||
|
|
||||||
// Dest is an existing file, but no -f given
|
|
||||||
if (exists && stats.isFile() && !options.force)
|
|
||||||
common.error('dest file already exists: ' + dest);
|
|
||||||
|
|
||||||
sources.forEach(function(src) {
|
|
||||||
if (!fs.existsSync(src)) {
|
|
||||||
common.error('no such file or directory: '+src, true);
|
|
||||||
return; // skip file
|
|
||||||
}
|
|
||||||
|
|
||||||
// If here, src exists
|
|
||||||
|
|
||||||
// When copying to '/path/dir':
|
|
||||||
// thisDest = '/path/dir/file1'
|
|
||||||
var thisDest = dest;
|
|
||||||
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
|
|
||||||
thisDest = path.normalize(dest + '/' + path.basename(src));
|
|
||||||
|
|
||||||
if (fs.existsSync(thisDest) && !options.force) {
|
|
||||||
common.error('dest file already exists: ' + thisDest, true);
|
|
||||||
return; // skip file
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path.resolve(src) === path.dirname(path.resolve(thisDest))) {
|
|
||||||
common.error('cannot move to self: '+src, true);
|
|
||||||
return; // skip file
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.renameSync(src, thisDest);
|
|
||||||
}); // forEach(src)
|
|
||||||
} // mv
|
|
||||||
module.exports = _mv;
|
|
|
@ -1 +0,0 @@
|
||||||
// see dirs.js
|
|
|
@ -1 +0,0 @@
|
||||||
// see dirs.js
|
|
|
@ -1,11 +0,0 @@
|
||||||
var path = require('path');
|
|
||||||
var common = require('./common');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### pwd()
|
|
||||||
//@ Returns the current directory.
|
|
||||||
function _pwd(options) {
|
|
||||||
var pwd = path.resolve(process.cwd());
|
|
||||||
return common.ShellString(pwd);
|
|
||||||
}
|
|
||||||
module.exports = _pwd;
|
|
|
@ -1,145 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
// Recursively removes 'dir'
|
|
||||||
// Adapted from https://github.com/ryanmcgrath/wrench-js
|
|
||||||
//
|
|
||||||
// Copyright (c) 2010 Ryan McGrath
|
|
||||||
// Copyright (c) 2012 Artur Adib
|
|
||||||
//
|
|
||||||
// Licensed under the MIT License
|
|
||||||
// http://www.opensource.org/licenses/mit-license.php
|
|
||||||
function rmdirSyncRecursive(dir, force) {
|
|
||||||
var files;
|
|
||||||
|
|
||||||
files = fs.readdirSync(dir);
|
|
||||||
|
|
||||||
// Loop through and delete everything in the sub-tree after checking it
|
|
||||||
for(var i = 0; i < files.length; i++) {
|
|
||||||
var file = dir + "/" + files[i],
|
|
||||||
currFile = fs.lstatSync(file);
|
|
||||||
|
|
||||||
if(currFile.isDirectory()) { // Recursive function back to the beginning
|
|
||||||
rmdirSyncRecursive(file, force);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(currFile.isSymbolicLink()) { // Unlink symlinks
|
|
||||||
if (force || isWriteable(file)) {
|
|
||||||
try {
|
|
||||||
common.unlinkSync(file);
|
|
||||||
} catch (e) {
|
|
||||||
common.error('could not remove file (code '+e.code+'): ' + file, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else // Assume it's a file - perhaps a try/catch belongs here?
|
|
||||||
if (force || isWriteable(file)) {
|
|
||||||
try {
|
|
||||||
common.unlinkSync(file);
|
|
||||||
} catch (e) {
|
|
||||||
common.error('could not remove file (code '+e.code+'): ' + file, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we know everything in the sub-tree has been deleted, we can delete the main directory.
|
|
||||||
// Huzzah for the shopkeep.
|
|
||||||
|
|
||||||
var result;
|
|
||||||
try {
|
|
||||||
result = fs.rmdirSync(dir);
|
|
||||||
} catch(e) {
|
|
||||||
common.error('could not remove directory (code '+e.code+'): ' + dir, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} // rmdirSyncRecursive
|
|
||||||
|
|
||||||
// Hack to determine if file has write permissions for current user
|
|
||||||
// Avoids having to check user, group, etc, but it's probably slow
|
|
||||||
function isWriteable(file) {
|
|
||||||
var writePermission = true;
|
|
||||||
try {
|
|
||||||
var __fd = fs.openSync(file, 'a');
|
|
||||||
fs.closeSync(__fd);
|
|
||||||
} catch(e) {
|
|
||||||
writePermission = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return writePermission;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### rm([options ,] file [, file ...])
|
|
||||||
//@ ### rm([options ,] file_array)
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-f`: force
|
|
||||||
//@ + `-r, -R`: recursive
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ rm('-rf', '/tmp/*');
|
|
||||||
//@ rm('some_file.txt', 'another_file.txt');
|
|
||||||
//@ rm(['some_file.txt', 'another_file.txt']); // same as above
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Removes files. The wildcard `*` is accepted.
|
|
||||||
function _rm(options, files) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'f': 'force',
|
|
||||||
'r': 'recursive',
|
|
||||||
'R': 'recursive'
|
|
||||||
});
|
|
||||||
if (!files)
|
|
||||||
common.error('no paths given');
|
|
||||||
|
|
||||||
if (typeof files === 'string')
|
|
||||||
files = [].slice.call(arguments, 1);
|
|
||||||
// if it's array leave it as it is
|
|
||||||
|
|
||||||
files = common.expand(files);
|
|
||||||
|
|
||||||
files.forEach(function(file) {
|
|
||||||
if (!fs.existsSync(file)) {
|
|
||||||
// Path does not exist, no force flag given
|
|
||||||
if (!options.force)
|
|
||||||
common.error('no such file or directory: '+file, true);
|
|
||||||
|
|
||||||
return; // skip file
|
|
||||||
}
|
|
||||||
|
|
||||||
// If here, path exists
|
|
||||||
|
|
||||||
var stats = fs.lstatSync(file);
|
|
||||||
if (stats.isFile() || stats.isSymbolicLink()) {
|
|
||||||
|
|
||||||
// Do not check for file writing permissions
|
|
||||||
if (options.force) {
|
|
||||||
common.unlinkSync(file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isWriteable(file))
|
|
||||||
common.unlinkSync(file);
|
|
||||||
else
|
|
||||||
common.error('permission denied: '+file, true);
|
|
||||||
|
|
||||||
return;
|
|
||||||
} // simple file
|
|
||||||
|
|
||||||
// Path is an existing directory, but no -r flag given
|
|
||||||
if (stats.isDirectory() && !options.recursive) {
|
|
||||||
common.error('path is a directory', true);
|
|
||||||
return; // skip path
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursively remove existing directory
|
|
||||||
if (stats.isDirectory() && options.recursive) {
|
|
||||||
rmdirSyncRecursive(file, options.force);
|
|
||||||
}
|
|
||||||
}); // forEach(file)
|
|
||||||
} // rm
|
|
||||||
module.exports = _rm;
|
|
|
@ -1,43 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### sed([options ,] search_regex, replacement, file)
|
|
||||||
//@ Available options:
|
|
||||||
//@
|
|
||||||
//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');
|
|
||||||
//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input
|
|
||||||
//@ using the given search regex and replacement string or function. Returns the new string after replacement.
|
|
||||||
function _sed(options, regex, replacement, file) {
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'i': 'inplace'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (typeof replacement === 'string' || typeof replacement === 'function')
|
|
||||||
replacement = replacement; // no-op
|
|
||||||
else if (typeof replacement === 'number')
|
|
||||||
replacement = replacement.toString(); // fallback
|
|
||||||
else
|
|
||||||
common.error('invalid replacement string');
|
|
||||||
|
|
||||||
if (!file)
|
|
||||||
common.error('no file given');
|
|
||||||
|
|
||||||
if (!fs.existsSync(file))
|
|
||||||
common.error('no such file or directory: ' + file);
|
|
||||||
|
|
||||||
var result = fs.readFileSync(file, 'utf8').replace(regex, replacement);
|
|
||||||
if (options.inplace)
|
|
||||||
fs.writeFileSync(file, result, 'utf8');
|
|
||||||
|
|
||||||
return common.ShellString(result);
|
|
||||||
}
|
|
||||||
module.exports = _sed;
|
|
|
@ -1,56 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var os = require('os');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
// Returns false if 'dir' is not a writeable directory, 'dir' otherwise
|
|
||||||
function writeableDir(dir) {
|
|
||||||
if (!dir || !fs.existsSync(dir))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!fs.statSync(dir).isDirectory())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var testFile = dir+'/'+common.randomFileName();
|
|
||||||
try {
|
|
||||||
fs.writeFileSync(testFile, ' ');
|
|
||||||
common.unlinkSync(testFile);
|
|
||||||
return dir;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### tempdir()
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ var tmp = tempdir(); // "/tmp" for most *nix platforms
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Searches and returns string containing a writeable, platform-dependent temporary directory.
|
|
||||||
//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).
|
|
||||||
function _tempDir() {
|
|
||||||
var state = common.state;
|
|
||||||
if (state.tempDir)
|
|
||||||
return state.tempDir; // from cache
|
|
||||||
|
|
||||||
state.tempDir = writeableDir(os.tempDir && os.tempDir()) || // node 0.8+
|
|
||||||
writeableDir(process.env['TMPDIR']) ||
|
|
||||||
writeableDir(process.env['TEMP']) ||
|
|
||||||
writeableDir(process.env['TMP']) ||
|
|
||||||
writeableDir(process.env['Wimp$ScrapDir']) || // RiscOS
|
|
||||||
writeableDir('C:\\TEMP') || // Windows
|
|
||||||
writeableDir('C:\\TMP') || // Windows
|
|
||||||
writeableDir('\\TEMP') || // Windows
|
|
||||||
writeableDir('\\TMP') || // Windows
|
|
||||||
writeableDir('/tmp') ||
|
|
||||||
writeableDir('/var/tmp') ||
|
|
||||||
writeableDir('/usr/tmp') ||
|
|
||||||
writeableDir('.'); // last resort
|
|
||||||
|
|
||||||
return state.tempDir;
|
|
||||||
}
|
|
||||||
module.exports = _tempDir;
|
|
|
@ -1,85 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### test(expression)
|
|
||||||
//@ Available expression primaries:
|
|
||||||
//@
|
|
||||||
//@ + `'-b', 'path'`: true if path is a block device
|
|
||||||
//@ + `'-c', 'path'`: true if path is a character device
|
|
||||||
//@ + `'-d', 'path'`: true if path is a directory
|
|
||||||
//@ + `'-e', 'path'`: true if path exists
|
|
||||||
//@ + `'-f', 'path'`: true if path is a regular file
|
|
||||||
//@ + `'-L', 'path'`: true if path is a symboilc link
|
|
||||||
//@ + `'-p', 'path'`: true if path is a pipe (FIFO)
|
|
||||||
//@ + `'-S', 'path'`: true if path is a socket
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ if (test('-d', path)) { /* do something with dir */ };
|
|
||||||
//@ if (!test('-f', path)) continue; // skip if it's a regular file
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Evaluates expression using the available primaries and returns corresponding value.
|
|
||||||
function _test(options, path) {
|
|
||||||
if (!path)
|
|
||||||
common.error('no path given');
|
|
||||||
|
|
||||||
// hack - only works with unary primaries
|
|
||||||
options = common.parseOptions(options, {
|
|
||||||
'b': 'block',
|
|
||||||
'c': 'character',
|
|
||||||
'd': 'directory',
|
|
||||||
'e': 'exists',
|
|
||||||
'f': 'file',
|
|
||||||
'L': 'link',
|
|
||||||
'p': 'pipe',
|
|
||||||
'S': 'socket'
|
|
||||||
});
|
|
||||||
|
|
||||||
var canInterpret = false;
|
|
||||||
for (var key in options)
|
|
||||||
if (options[key] === true) {
|
|
||||||
canInterpret = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canInterpret)
|
|
||||||
common.error('could not interpret expression');
|
|
||||||
|
|
||||||
if (options.link) {
|
|
||||||
try {
|
|
||||||
return fs.lstatSync(path).isSymbolicLink();
|
|
||||||
} catch(e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(path))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (options.exists)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var stats = fs.statSync(path);
|
|
||||||
|
|
||||||
if (options.block)
|
|
||||||
return stats.isBlockDevice();
|
|
||||||
|
|
||||||
if (options.character)
|
|
||||||
return stats.isCharacterDevice();
|
|
||||||
|
|
||||||
if (options.directory)
|
|
||||||
return stats.isDirectory();
|
|
||||||
|
|
||||||
if (options.file)
|
|
||||||
return stats.isFile();
|
|
||||||
|
|
||||||
if (options.pipe)
|
|
||||||
return stats.isFIFO();
|
|
||||||
|
|
||||||
if (options.socket)
|
|
||||||
return stats.isSocket();
|
|
||||||
} // test
|
|
||||||
module.exports = _test;
|
|
|
@ -1,29 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### 'string'.to(file)
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ cat('input.txt').to('output.txt');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as
|
|
||||||
//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_
|
|
||||||
function _to(options, file) {
|
|
||||||
if (!file)
|
|
||||||
common.error('wrong arguments');
|
|
||||||
|
|
||||||
if (!fs.existsSync( path.dirname(file) ))
|
|
||||||
common.error('no such file or directory: ' + path.dirname(file));
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.writeFileSync(file, this.toString(), 'utf8');
|
|
||||||
} catch(e) {
|
|
||||||
common.error('could not write to file (code '+e.code+'): '+file, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = _to;
|
|
|
@ -1,29 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### 'string'.toEnd(file)
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ cat('input.txt').toEnd('output.txt');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as
|
|
||||||
//@ those returned by `cat`, `grep`, etc).
|
|
||||||
function _toEnd(options, file) {
|
|
||||||
if (!file)
|
|
||||||
common.error('wrong arguments');
|
|
||||||
|
|
||||||
if (!fs.existsSync( path.dirname(file) ))
|
|
||||||
common.error('no such file or directory: ' + path.dirname(file));
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.appendFileSync(file, this.toString(), 'utf8');
|
|
||||||
} catch(e) {
|
|
||||||
common.error('could not append to file (code '+e.code+'): '+file, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = _toEnd;
|
|
|
@ -1,83 +0,0 @@
|
||||||
var common = require('./common');
|
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
// Cross-platform method for splitting environment PATH variables
|
|
||||||
function splitPath(p) {
|
|
||||||
for (i=1;i<2;i++) {}
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
return [];
|
|
||||||
|
|
||||||
if (common.platform === 'win')
|
|
||||||
return p.split(';');
|
|
||||||
else
|
|
||||||
return p.split(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkPath(path) {
|
|
||||||
return fs.existsSync(path) && fs.statSync(path).isDirectory() == false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@
|
|
||||||
//@ ### which(command)
|
|
||||||
//@
|
|
||||||
//@ Examples:
|
|
||||||
//@
|
|
||||||
//@ ```javascript
|
|
||||||
//@ var nodeExec = which('node');
|
|
||||||
//@ ```
|
|
||||||
//@
|
|
||||||
//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.
|
|
||||||
//@ Returns string containing the absolute path to the command.
|
|
||||||
function _which(options, cmd) {
|
|
||||||
if (!cmd)
|
|
||||||
common.error('must specify command');
|
|
||||||
|
|
||||||
var pathEnv = process.env.path || process.env.Path || process.env.PATH,
|
|
||||||
pathArray = splitPath(pathEnv),
|
|
||||||
where = null;
|
|
||||||
|
|
||||||
// No relative/absolute paths provided?
|
|
||||||
if (cmd.search(/\//) === -1) {
|
|
||||||
// Search for command in PATH
|
|
||||||
pathArray.forEach(function(dir) {
|
|
||||||
if (where)
|
|
||||||
return; // already found it
|
|
||||||
|
|
||||||
var attempt = path.resolve(dir + '/' + cmd);
|
|
||||||
if (checkPath(attempt)) {
|
|
||||||
where = attempt;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common.platform === 'win') {
|
|
||||||
var baseAttempt = attempt;
|
|
||||||
attempt = baseAttempt + '.exe';
|
|
||||||
if (checkPath(attempt)) {
|
|
||||||
where = attempt;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
attempt = baseAttempt + '.cmd';
|
|
||||||
if (checkPath(attempt)) {
|
|
||||||
where = attempt;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
attempt = baseAttempt + '.bat';
|
|
||||||
if (checkPath(attempt)) {
|
|
||||||
where = attempt;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} // if 'win'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command not found anywhere?
|
|
||||||
if (!checkPath(cmd) && !where)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
where = where || path.resolve(cmd);
|
|
||||||
|
|
||||||
return common.ShellString(where);
|
|
||||||
}
|
|
||||||
module.exports = _which;
|
|
|
@ -25,13 +25,12 @@
|
||||||
},
|
},
|
||||||
"@actions/tool-cache": {
|
"@actions/tool-cache": {
|
||||||
"version": "file:toolkit/actions-tool-cache-0.0.0.tgz",
|
"version": "file:toolkit/actions-tool-cache-0.0.0.tgz",
|
||||||
"integrity": "sha512-R08MGFekNLkf1ofh5wi8QVgmFyPgkKC+Cp8FRE1n6zOpHbUWv3QGa6eR6z+2ESuGCstOPtbq/tRgZsSusItm9Q==",
|
"integrity": "sha512-33oYAVRdp6MWNT7Yca0//SmOsvpE7FpFfNA/LzwjIZdLucHaO6V67dqZ5p81CTBncrZal+O5kE9B8qSk0rhipg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/core": "^0.0.0",
|
"@actions/core": "^0.0.0",
|
||||||
"@actions/exec": "^0.0.0",
|
"@actions/exec": "^0.0.0",
|
||||||
"@actions/io": "^0.0.0",
|
"@actions/io": "^0.0.0",
|
||||||
"semver": "^6.1.0",
|
"semver": "^6.1.0",
|
||||||
"shelljs": "^0.3.0",
|
|
||||||
"typed-rest-client": "^1.4.0",
|
"typed-rest-client": "^1.4.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
}
|
}
|
||||||
|
@ -4523,11 +4522,6 @@
|
||||||
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
|
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"shelljs": {
|
|
||||||
"version": "0.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
|
|
||||||
"integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E="
|
|
||||||
},
|
|
||||||
"shellwords": {
|
"shellwords": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
"author": "GitHub",
|
"author": "GitHub",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/exit": "file:toolkit/actions-exit-0.0.0.tgz",
|
|
||||||
"@actions/core": "file:toolkit/actions-core-0.0.0.tgz",
|
"@actions/core": "file:toolkit/actions-core-0.0.0.tgz",
|
||||||
"@actions/io": "file:toolkit/actions-io-0.0.0.tgz",
|
|
||||||
"@actions/exec": "file:toolkit/actions-exec-0.0.0.tgz",
|
"@actions/exec": "file:toolkit/actions-exec-0.0.0.tgz",
|
||||||
|
"@actions/exit": "file:toolkit/actions-exit-0.0.0.tgz",
|
||||||
|
"@actions/io": "file:toolkit/actions-io-0.0.0.tgz",
|
||||||
"@actions/tool-cache": "file:toolkit/actions-tool-cache-0.0.0.tgz",
|
"@actions/tool-cache": "file:toolkit/actions-tool-cache-0.0.0.tgz",
|
||||||
"semver": "^6.1.1"
|
"semver": "^6.1.1"
|
||||||
},
|
},
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue