mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-05 01:25:38 -05:00
Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 (#14050)
* Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 * Fix breaks * Extension management fixes * Fix breaks in windows bundling * Fix/skip failing tests * Update distro * Add clear to nuget.config * Add hygiene task * Bump distro * Fix hygiene issue * Add build to hygiene exclusion * Update distro * Update hygiene * Hygiene exclusions * Update tsconfig * Bump distro for server breaks * Update build config * Update darwin path * Add done calls to notebook tests * Skip failing tests * Disable smoke tests
This commit is contained in:
@@ -13,7 +13,6 @@ import * as iconv from 'iconv-lite-umd';
|
||||
import * as filetype from 'file-type';
|
||||
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util';
|
||||
import { CancellationToken, Progress, Uri } from 'vscode';
|
||||
import { URI } from 'vscode-uri';
|
||||
import { detectEncoding } from './encoding';
|
||||
import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status, CommitOptions, BranchQuery } from './api/git';
|
||||
import * as byline from 'byline';
|
||||
@@ -261,6 +260,7 @@ export interface IGitErrorData {
|
||||
exitCode?: number;
|
||||
gitErrorCode?: string;
|
||||
gitCommand?: string;
|
||||
gitArgs?: string[];
|
||||
}
|
||||
|
||||
export class GitError {
|
||||
@@ -272,6 +272,7 @@ export class GitError {
|
||||
exitCode?: number;
|
||||
gitErrorCode?: string;
|
||||
gitCommand?: string;
|
||||
gitArgs?: string[];
|
||||
|
||||
constructor(data: IGitErrorData) {
|
||||
if (data.error) {
|
||||
@@ -288,6 +289,7 @@ export class GitError {
|
||||
this.exitCode = data.exitCode;
|
||||
this.gitErrorCode = data.gitErrorCode;
|
||||
this.gitCommand = data.gitCommand;
|
||||
this.gitArgs = data.gitArgs;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
@@ -351,6 +353,12 @@ function sanitizePath(path: string): string {
|
||||
|
||||
const COMMIT_FORMAT = '%H%n%aN%n%aE%n%at%n%ct%n%P%n%B';
|
||||
|
||||
export interface ICloneOptions {
|
||||
readonly parentPath: string;
|
||||
readonly progress: Progress<{ increment: number }>;
|
||||
readonly recursive?: boolean;
|
||||
}
|
||||
|
||||
export class Git {
|
||||
|
||||
readonly path: string;
|
||||
@@ -373,18 +381,18 @@ export class Git {
|
||||
return;
|
||||
}
|
||||
|
||||
async clone(url: string, parentPath: string, progress: Progress<{ increment: number }>, cancellationToken?: CancellationToken): Promise<string> {
|
||||
async clone(url: string, options: ICloneOptions, cancellationToken?: CancellationToken): Promise<string> {
|
||||
let baseFolderName = decodeURI(url).replace(/[\/]+$/, '').replace(/^.*[\/\\]/, '').replace(/\.git$/, '') || 'repository';
|
||||
let folderName = baseFolderName;
|
||||
let folderPath = path.join(parentPath, folderName);
|
||||
let folderPath = path.join(options.parentPath, folderName);
|
||||
let count = 1;
|
||||
|
||||
while (count < 20 && await new Promise(c => exists(folderPath, c))) {
|
||||
folderName = `${baseFolderName}-${count++}`;
|
||||
folderPath = path.join(parentPath, folderName);
|
||||
folderPath = path.join(options.parentPath, folderName);
|
||||
}
|
||||
|
||||
await mkdirp(parentPath);
|
||||
await mkdirp(options.parentPath);
|
||||
|
||||
const onSpawn = (child: cp.ChildProcess) => {
|
||||
const decoder = new StringDecoder('utf8');
|
||||
@@ -408,14 +416,18 @@ export class Git {
|
||||
}
|
||||
|
||||
if (totalProgress !== previousProgress) {
|
||||
progress.report({ increment: totalProgress - previousProgress });
|
||||
options.progress.report({ increment: totalProgress - previousProgress });
|
||||
previousProgress = totalProgress;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
await this.exec(parentPath, ['clone', url.includes(' ') ? encodeURI(url) : url, folderPath, '--progress'], { cancellationToken, onSpawn });
|
||||
let command = ['clone', url.includes(' ') ? encodeURI(url) : url, folderPath, '--progress'];
|
||||
if (options.recursive) {
|
||||
command.push('--recursive');
|
||||
}
|
||||
await this.exec(options.parentPath, command, { cancellationToken, onSpawn });
|
||||
} catch (err) {
|
||||
if (err.stderr) {
|
||||
err.stderr = err.stderr.replace(/^Cloning.+$/m, '').trim();
|
||||
@@ -445,7 +457,7 @@ export class Git {
|
||||
const [, letter] = match;
|
||||
|
||||
try {
|
||||
const networkPath = await new Promise<string>(resolve =>
|
||||
const networkPath = await new Promise<string | undefined>(resolve =>
|
||||
realpath.native(`${letter}:`, { encoding: 'utf8' }, (err, resolvedPath) =>
|
||||
resolve(err !== null ? undefined : resolvedPath),
|
||||
),
|
||||
@@ -526,7 +538,8 @@ export class Git {
|
||||
stderr: result.stderr,
|
||||
exitCode: result.exitCode,
|
||||
gitErrorCode: getGitErrorCode(result.stderr),
|
||||
gitCommand: args[0]
|
||||
gitCommand: args[0],
|
||||
gitArgs: args
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -679,7 +692,7 @@ export function parseGitmodules(raw: string): Submodule[] {
|
||||
return;
|
||||
}
|
||||
|
||||
const propertyMatch = /^\s*(\w+)\s+=\s+(.*)$/.exec(line);
|
||||
const propertyMatch = /^\s*(\w+)\s*=\s*(.*)$/.exec(line);
|
||||
|
||||
if (!propertyMatch) {
|
||||
return;
|
||||
@@ -1155,7 +1168,7 @@ export class Repository {
|
||||
break;
|
||||
}
|
||||
|
||||
const originalUri = URI.file(path.isAbsolute(resourcePath) ? resourcePath : path.join(this.repositoryRoot, resourcePath));
|
||||
const originalUri = Uri.file(path.isAbsolute(resourcePath) ? resourcePath : path.join(this.repositoryRoot, resourcePath));
|
||||
let status: Status = Status.UNTRACKED;
|
||||
|
||||
// Copy or Rename status comes with a number, e.g. 'R100'. We don't need the number, so we use only first character of the status.
|
||||
@@ -1183,7 +1196,7 @@ export class Repository {
|
||||
break;
|
||||
}
|
||||
|
||||
const uri = URI.file(path.isAbsolute(newPath) ? newPath : path.join(this.repositoryRoot, newPath));
|
||||
const uri = Uri.file(path.isAbsolute(newPath) ? newPath : path.join(this.repositoryRoot, newPath));
|
||||
result.push({
|
||||
uri,
|
||||
renameUri: uri,
|
||||
@@ -1233,7 +1246,7 @@ export class Repository {
|
||||
}
|
||||
|
||||
if (paths && paths.length) {
|
||||
for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) {
|
||||
for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) {
|
||||
await this.run([...args, '--', ...chunk]);
|
||||
}
|
||||
} else {
|
||||
@@ -1286,13 +1299,17 @@ export class Repository {
|
||||
await this.run(['update-index', add, '--cacheinfo', mode, hash, path]);
|
||||
}
|
||||
|
||||
async checkout(treeish: string, paths: string[], opts: { track?: boolean } = Object.create(null)): Promise<void> {
|
||||
async checkout(treeish: string, paths: string[], opts: { track?: boolean, detached?: boolean } = Object.create(null)): Promise<void> {
|
||||
const args = ['checkout', '-q'];
|
||||
|
||||
if (opts.track) {
|
||||
args.push('--track');
|
||||
}
|
||||
|
||||
if (opts.detached) {
|
||||
args.push('--detach');
|
||||
}
|
||||
|
||||
if (treeish) {
|
||||
args.push(treeish);
|
||||
}
|
||||
@@ -1308,23 +1325,30 @@ export class Repository {
|
||||
} catch (err) {
|
||||
if (/Please,? commit your changes or stash them/.test(err.stderr || '')) {
|
||||
err.gitErrorCode = GitErrorCodes.DirtyWorkTree;
|
||||
err.gitTreeish = treeish;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async commit(message: string, opts: CommitOptions = Object.create(null)): Promise<void> {
|
||||
const args = ['commit', '--quiet', '--allow-empty-message', '--file', '-'];
|
||||
async commit(message: string | undefined, opts: CommitOptions = Object.create(null)): Promise<void> {
|
||||
const args = ['commit', '--quiet', '--allow-empty-message'];
|
||||
|
||||
if (opts.all) {
|
||||
args.push('--all');
|
||||
}
|
||||
|
||||
if (opts.amend) {
|
||||
if (opts.amend && message) {
|
||||
args.push('--amend');
|
||||
}
|
||||
|
||||
if (opts.amend && !message) {
|
||||
args.push('--amend', '--no-edit');
|
||||
} else {
|
||||
args.push('--file', '-');
|
||||
}
|
||||
|
||||
if (opts.signoff) {
|
||||
args.push('--signoff');
|
||||
}
|
||||
@@ -1341,8 +1365,11 @@ export class Repository {
|
||||
args.push('--no-verify');
|
||||
}
|
||||
|
||||
// Stops git from guessing at user/email
|
||||
args.splice(0, 0, '-c', 'user.useConfigOnly=true');
|
||||
|
||||
try {
|
||||
await this.run(args, { input: message || '' });
|
||||
await this.run(args, !opts.amend || message ? { input: message || '' } : {});
|
||||
} catch (commitErr) {
|
||||
await this.handleCommitError(commitErr);
|
||||
}
|
||||
@@ -1405,6 +1432,11 @@ export class Repository {
|
||||
await this.run(args);
|
||||
}
|
||||
|
||||
async move(from: string, to: string): Promise<void> {
|
||||
const args = ['mv', from, to];
|
||||
await this.run(args);
|
||||
}
|
||||
|
||||
async setBranchUpstream(name: string, upstream: string): Promise<void> {
|
||||
const args = ['branch', '--set-upstream-to', upstream, name];
|
||||
await this.run(args);
|
||||
@@ -1455,7 +1487,7 @@ export class Repository {
|
||||
const args = ['clean', '-f', '-q'];
|
||||
|
||||
for (const paths of groups) {
|
||||
for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) {
|
||||
for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) {
|
||||
promises.push(limiter.queue(() => this.run([...args, '--', ...chunk])));
|
||||
}
|
||||
}
|
||||
@@ -1495,7 +1527,7 @@ export class Repository {
|
||||
|
||||
try {
|
||||
if (paths && paths.length > 0) {
|
||||
for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) {
|
||||
for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) {
|
||||
await this.run([...args, '--', ...chunk]);
|
||||
}
|
||||
} else {
|
||||
@@ -1527,9 +1559,11 @@ export class Repository {
|
||||
await this.run(args);
|
||||
}
|
||||
|
||||
async fetch(options: { remote?: string, ref?: string, all?: boolean, prune?: boolean, depth?: number, silent?: boolean } = {}): Promise<void> {
|
||||
async fetch(options: { remote?: string, ref?: string, all?: boolean, prune?: boolean, depth?: number, silent?: boolean, readonly cancellationToken?: CancellationToken } = {}): Promise<void> {
|
||||
const args = ['fetch'];
|
||||
const spawnOptions: SpawnOptions = {};
|
||||
const spawnOptions: SpawnOptions = {
|
||||
cancellationToken: options.cancellationToken,
|
||||
};
|
||||
|
||||
if (options.remote) {
|
||||
args.push(options.remote);
|
||||
@@ -1608,7 +1642,25 @@ export class Repository {
|
||||
}
|
||||
}
|
||||
|
||||
async push(remote?: string, name?: string, setUpstream: boolean = false, tags = false, forcePushMode?: ForcePushMode): Promise<void> {
|
||||
async rebase(branch: string, options: PullOptions = {}): Promise<void> {
|
||||
const args = ['rebase'];
|
||||
|
||||
args.push(branch);
|
||||
|
||||
try {
|
||||
await this.run(args, options);
|
||||
} catch (err) {
|
||||
if (/^CONFLICT \([^)]+\): \b/m.test(err.stdout || '')) {
|
||||
err.gitErrorCode = GitErrorCodes.Conflict;
|
||||
} else if (/cannot rebase onto multiple branches/i.test(err.stderr || '')) {
|
||||
err.gitErrorCode = GitErrorCodes.CantRebaseMultipleBranches;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async push(remote?: string, name?: string, setUpstream: boolean = false, followTags = false, forcePushMode?: ForcePushMode, tags = false): Promise<void> {
|
||||
const args = ['push'];
|
||||
|
||||
if (forcePushMode === ForcePushMode.ForceWithLease) {
|
||||
@@ -1621,10 +1673,14 @@ export class Repository {
|
||||
args.push('-u');
|
||||
}
|
||||
|
||||
if (tags) {
|
||||
if (followTags) {
|
||||
args.push('--follow-tags');
|
||||
}
|
||||
|
||||
if (tags) {
|
||||
args.push('--tags');
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
args.push(remote);
|
||||
}
|
||||
@@ -1650,6 +1706,11 @@ export class Repository {
|
||||
}
|
||||
}
|
||||
|
||||
async cherryPick(commitHash: string): Promise<void> {
|
||||
const args = ['cherry-pick', commitHash];
|
||||
await this.run(args);
|
||||
}
|
||||
|
||||
async blame(path: string): Promise<string> {
|
||||
try {
|
||||
const args = ['blame', sanitizePath(path)];
|
||||
@@ -1734,11 +1795,17 @@ export class Repository {
|
||||
}
|
||||
}
|
||||
|
||||
getStatus(limit = 5000): Promise<{ status: IFileStatus[]; didHitLimit: boolean; }> {
|
||||
getStatus(opts?: { limit?: number, ignoreSubmodules?: boolean }): Promise<{ status: IFileStatus[]; didHitLimit: boolean; }> {
|
||||
return new Promise<{ status: IFileStatus[]; didHitLimit: boolean; }>((c, e) => {
|
||||
const parser = new GitStatusParser();
|
||||
const env = { GIT_OPTIONAL_LOCKS: '0' };
|
||||
const child = this.stream(['status', '-z', '-u'], { env });
|
||||
const args = ['status', '-z', '-u'];
|
||||
|
||||
if (opts?.ignoreSubmodules) {
|
||||
args.push('--ignore-submodules');
|
||||
}
|
||||
|
||||
const child = this.stream(args, { env });
|
||||
|
||||
const onExit = (exitCode: number) => {
|
||||
if (exitCode !== 0) {
|
||||
@@ -1748,13 +1815,15 @@ export class Repository {
|
||||
stderr,
|
||||
exitCode,
|
||||
gitErrorCode: getGitErrorCode(stderr),
|
||||
gitCommand: 'status'
|
||||
gitCommand: 'status',
|
||||
gitArgs: args
|
||||
}));
|
||||
}
|
||||
|
||||
c({ status: parser.status, didHitLimit: false });
|
||||
};
|
||||
|
||||
const limit = opts?.limit ?? 5000;
|
||||
const onStdoutData = (raw: string) => {
|
||||
parser.update(raw);
|
||||
|
||||
@@ -1818,7 +1887,7 @@ export class Repository {
|
||||
args.push('--sort', `-${opts.sort}`);
|
||||
}
|
||||
|
||||
args.push('--format', '%(refname) %(objectname)');
|
||||
args.push('--format', '%(refname) %(objectname) %(*objectname)');
|
||||
|
||||
if (opts?.pattern) {
|
||||
args.push(opts.pattern);
|
||||
@@ -1833,12 +1902,12 @@ export class Repository {
|
||||
const fn = (line: string): Ref | null => {
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
if (match = /^refs\/heads\/([^ ]+) ([0-9a-f]{40})$/.exec(line)) {
|
||||
if (match = /^refs\/heads\/([^ ]+) ([0-9a-f]{40}) ([0-9a-f]{40})?$/.exec(line)) {
|
||||
return { name: match[1], commit: match[2], type: RefType.Head };
|
||||
} else if (match = /^refs\/remotes\/([^/]+)\/([^ ]+) ([0-9a-f]{40})$/.exec(line)) {
|
||||
} else if (match = /^refs\/remotes\/([^/]+)\/([^ ]+) ([0-9a-f]{40}) ([0-9a-f]{40})?$/.exec(line)) {
|
||||
return { name: `${match[1]}/${match[2]}`, commit: match[3], type: RefType.RemoteHead, remote: match[1] };
|
||||
} else if (match = /^refs\/tags\/([^ ]+) ([0-9a-f]{40})$/.exec(line)) {
|
||||
return { name: match[1], commit: match[2], type: RefType.Tag };
|
||||
} else if (match = /^refs\/tags\/([^ ]+) ([0-9a-f]{40}) ([0-9a-f]{40})?$/.exec(line)) {
|
||||
return { name: match[1], commit: match[3] ?? match[2], type: RefType.Tag };
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user