mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-14 01:25:37 -05:00
146 lines
4.0 KiB
TypeScript
146 lines
4.0 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
'use strict';
|
|
|
|
import * as path from 'path';
|
|
import * as arrays from 'vs/base/common/arrays';
|
|
import * as strings from 'vs/base/common/strings';
|
|
import * as paths from 'vs/base/common/paths';
|
|
import * as platform from 'vs/base/common/platform';
|
|
import * as types from 'vs/base/common/types';
|
|
import { ParsedArgs } from 'vs/platform/environment/common/environment';
|
|
import { realpathSync } from 'vs/base/node/extfs';
|
|
|
|
export function validatePaths(args: ParsedArgs): ParsedArgs {
|
|
// Track URLs if they're going to be used
|
|
if (args['open-url']) {
|
|
args._urls = args._;
|
|
args._ = [];
|
|
}
|
|
|
|
// Realpath/normalize paths and watch out for goto line mode
|
|
const paths = doValidatePaths(args._, args.goto);
|
|
|
|
// Update environment
|
|
args._ = paths;
|
|
args.diff = args.diff && paths.length === 2;
|
|
|
|
return args;
|
|
}
|
|
|
|
function doValidatePaths(args: string[], gotoLineMode?: boolean): string[] {
|
|
const cwd = process.env['VSCODE_CWD'] || process.cwd();
|
|
const result = args.map(arg => {
|
|
let pathCandidate = String(arg);
|
|
|
|
let parsedPath: IPathWithLineAndColumn;
|
|
if (gotoLineMode) {
|
|
parsedPath = parseLineAndColumnAware(pathCandidate);
|
|
pathCandidate = parsedPath.path;
|
|
}
|
|
|
|
if (pathCandidate) {
|
|
pathCandidate = preparePath(cwd, pathCandidate);
|
|
}
|
|
|
|
let realPath: string;
|
|
try {
|
|
realPath = realpathSync(pathCandidate);
|
|
} catch (error) {
|
|
// in case of an error, assume the user wants to create this file
|
|
// if the path is relative, we join it to the cwd
|
|
realPath = path.normalize(path.isAbsolute(pathCandidate) ? pathCandidate : path.join(cwd, pathCandidate));
|
|
}
|
|
|
|
const basename = path.basename(realPath);
|
|
if (basename /* can be empty if code is opened on root */ && !paths.isValidBasename(basename)) {
|
|
return null; // do not allow invalid file names
|
|
}
|
|
|
|
if (gotoLineMode) {
|
|
parsedPath.path = realPath;
|
|
return toPath(parsedPath);
|
|
}
|
|
|
|
return realPath;
|
|
});
|
|
|
|
const caseInsensitive = platform.isWindows || platform.isMacintosh;
|
|
const distinct = arrays.distinct(result, e => e && caseInsensitive ? e.toLowerCase() : e);
|
|
|
|
return arrays.coalesce(distinct);
|
|
}
|
|
|
|
function preparePath(cwd: string, p: string): string {
|
|
|
|
// Trim trailing quotes
|
|
if (platform.isWindows) {
|
|
p = strings.rtrim(p, '"'); // https://github.com/Microsoft/vscode/issues/1498
|
|
}
|
|
|
|
// Trim whitespaces
|
|
p = strings.trim(strings.trim(p, ' '), '\t');
|
|
|
|
if (platform.isWindows) {
|
|
|
|
// Resolve the path against cwd if it is relative
|
|
p = path.resolve(cwd, p);
|
|
|
|
// Trim trailing '.' chars on Windows to prevent invalid file names
|
|
p = strings.rtrim(p, '.');
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
export interface IPathWithLineAndColumn {
|
|
path: string;
|
|
line?: number;
|
|
column?: number;
|
|
}
|
|
|
|
export function parseLineAndColumnAware(rawPath: string): IPathWithLineAndColumn {
|
|
const segments = rawPath.split(':'); // C:\file.txt:<line>:<column>
|
|
|
|
let path: string;
|
|
let line: number = null;
|
|
let column: number = null;
|
|
|
|
segments.forEach(segment => {
|
|
const segmentAsNumber = Number(segment);
|
|
if (!types.isNumber(segmentAsNumber)) {
|
|
path = !!path ? [path, segment].join(':') : segment; // a colon can well be part of a path (e.g. C:\...)
|
|
} else if (line === null) {
|
|
line = segmentAsNumber;
|
|
} else if (column === null) {
|
|
column = segmentAsNumber;
|
|
}
|
|
});
|
|
|
|
if (!path) {
|
|
throw new Error('Format for `--goto` should be: `FILE:LINE(:COLUMN)`');
|
|
}
|
|
|
|
return {
|
|
path: path,
|
|
line: line !== null ? line : void 0,
|
|
column: column !== null ? column : line !== null ? 1 : void 0 // if we have a line, make sure column is also set
|
|
};
|
|
}
|
|
|
|
function toPath(p: IPathWithLineAndColumn): string {
|
|
const segments = [p.path];
|
|
|
|
if (types.isNumber(p.line)) {
|
|
segments.push(String(p.line));
|
|
}
|
|
|
|
if (types.isNumber(p.column)) {
|
|
segments.push(String(p.column));
|
|
}
|
|
|
|
return segments.join(':');
|
|
} |