Skip to content

Commit

Permalink
fix: Using custom file system provider over content provider (#1053)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnstonCode committed Aug 25, 2020
1 parent 8d0da6b commit 4ceeafe
Show file tree
Hide file tree
Showing 16 changed files with 1,852 additions and 1,499 deletions.
2,558 changes: 1,284 additions & 1,274 deletions package.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ export enum Operation {
Status = "Status",
StatusRemote = "StatusRemote",
SwitchBranch = "SwitchBranch",
Update = "Update"
Update = "Update",
List = "List"
}

export interface ISvnResourceGroup extends SourceControlResourceGroup {
Expand Down
4 changes: 2 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import { RepoLogProvider } from "./historyView/repoLogProvider";
import * as messages from "./messages";
import { SourceControlManager } from "./source_control_manager";
import { Svn } from "./svn";
import { SvnContentProvider } from "./svnContentProvider";
import { SvnFinder } from "./svnFinder";
import SvnProvider from "./treeView/dataProviders/svnProvider";
import { toDisposable } from "./util";
import { BranchChangesProvider } from "./historyView/branchChangesProvider";
import { IsSvn19orGreater } from "./contexts/isSvn19orGreater";
import { IsSvn18orGreater } from "./contexts/isSvn18orGreater";
import { tempSvnFs } from "./temp_svn_fs";
import { SvnFileSystemProvider } from "./svnFileSystemProvider";

async function init(
_context: ExtensionContext,
Expand All @@ -46,7 +46,7 @@ async function init(
disposables.push(
sourceControlManager,
tempSvnFs,
new SvnContentProvider(sourceControlManager),
new SvnFileSystemProvider(sourceControlManager),
new SvnProvider(sourceControlManager),
new RepoLogProvider(sourceControlManager),
new ItemLogProvider(sourceControlManager),
Expand Down
38 changes: 37 additions & 1 deletion src/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import {
SvnDepth,
SvnUriAction,
ISvnPathChange,
IStoredAuth
IStoredAuth,
ISvnListItem
} from "./common/types";
import { debounce, globalSequentialize, memoize, throttle } from "./decorators";
import { exists } from "./fs";
Expand Down Expand Up @@ -754,6 +755,15 @@ export class Repository implements IRemoteRepository {
});
}

public async showBuffer(
filePath: string | Uri,
revision?: string
): Promise<Buffer> {
return this.run<Buffer>(Operation.Show, () => {
return this.repository.showBuffer(filePath, revision);
});
}

public async addFiles(files: string[]) {
return this.run(Operation.Add, () => this.repository.addFiles(files));
}
Expand Down Expand Up @@ -837,6 +847,10 @@ export class Repository implements IRemoteRepository {
return this.run(Operation.Patch, () => this.repository.patch(files));
}

public async patchBuffer(files: string[]) {
return this.run(Operation.Patch, () => this.repository.patchBuffer(files));
}

public async patchChangelist(changelistName: string) {
return this.run(Operation.Patch, () =>
this.repository.patchChangelist(changelistName)
Expand All @@ -853,18 +867,34 @@ export class Repository implements IRemoteRepository {
return this.run(Operation.Log, () => this.repository.plainLog());
}

public async plainLogBuffer() {
return this.run(Operation.Log, () => this.repository.plainLogBuffer());
}

public async plainLogByRevision(revision: number) {
return this.run(Operation.Log, () =>
this.repository.plainLogByRevision(revision)
);
}

public async plainLogByRevisionBuffer(revision: number) {
return this.run(Operation.Log, () =>
this.repository.plainLogByRevisionBuffer(revision)
);
}

public async plainLogByText(search: string) {
return this.run(Operation.Log, () =>
this.repository.plainLogByText(search)
);
}

public async plainLogByTextBuffer(search: string) {
return this.run(Operation.Log, () =>
this.repository.plainLogByTextBuffer(search)
);
}

public async log(
rfrom: string,
rto: string,
Expand Down Expand Up @@ -922,6 +952,12 @@ export class Repository implements IRemoteRepository {
);
}

public async list(filePath: string): Promise<ISvnListItem[]> {
return this.run<ISvnListItem[]>(Operation.List, () => {
return this.repository.ls(filePath);
});
}

public getPathNormalizer(): PathNormalizer {
return new PathNormalizer(this.repository.info);
}
Expand Down
30 changes: 29 additions & 1 deletion src/source_control_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ import {
IDisposable,
isDescendant,
isSvnFolder,
normalizePath
normalizePath,
eventToPromise
} from "./util";
import { matchAll } from "./util/globMatch";

type State = "uninitialized" | "initialized";

export class SourceControlManager implements IDisposable {
private _onDidOpenRepository = new EventEmitter<Repository>();
public readonly onDidOpenRepository: Event<Repository> = this
Expand All @@ -60,6 +63,29 @@ export class SourceControlManager implements IDisposable {

private configurationChangeDisposable: Disposable;

private _onDidChangeState = new EventEmitter<State>();
readonly onDidchangeState = this._onDidChangeState.event;

private _state: State = "uninitialized";
get state(): State {
return this._state;
}

setState(state: State): void {
this._state = state;
this._onDidChangeState.fire(state);
}

get isInitialized(): Promise<void> {
if (this._state === "initialized") {
return Promise.resolve();
}

return eventToPromise(
filterEvent(this.onDidchangeState, s => s === "initialized")
) as Promise<any>;
}

get repositories(): Repository[] {
return this.openRepositories.map(r => r.repository);
}
Expand Down Expand Up @@ -149,6 +175,8 @@ export class SourceControlManager implements IDisposable {
this.disposables
);

this.setState("initialized");

await this.scanWorkspaceFolders();
}

Expand Down
111 changes: 111 additions & 0 deletions src/svn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ export function cpErrorHandler(
};
}

export interface BufferResult {
exitCode: number;
stdout: Buffer;
stderr: string;
}

export class Svn {
public version: string;

Expand Down Expand Up @@ -223,6 +229,111 @@ export class Svn {
return { exitCode, stdout: decodedStdout, stderr };
}

public async execBuffer(
cwd: string,
args: any[],
options: ICpOptions = {}
): Promise<BufferResult> {
if (cwd) {
this.lastCwd = cwd;
options.cwd = cwd;
}

if (options.log !== false) {
const argsOut = args.map(arg => (/ |^$/.test(arg) ? `'${arg}'` : arg));
this.logOutput(
`[${this.lastCwd.split(/[\\\/]+/).pop()}]$ svn ${argsOut.join(" ")}\n`
);
}

if (options.username) {
args.push("--username", options.username);
}
if (options.password) {
args.push("--password", options.password);
}

if (options.username || options.password) {
// Configuration format: FILE:SECTION:OPTION=[VALUE]
// Disable password store
args.push("--config-option", "config:auth:password-stores=");
// Disable store auth credentials
args.push("--config-option", "servers:global:store-auth-creds=no");
}

// Force non interactive environment
args.push("--non-interactive");

const defaults: cp.SpawnOptions = {
env: proc.env
};
if (cwd) {
defaults.cwd = cwd;
}

defaults.env = Object.assign({}, proc.env, options.env || {}, {
LC_ALL: "en_US.UTF-8",
LANG: "en_US.UTF-8"
});

const process = cp.spawn(this.svnPath, args, defaults);

const disposables: IDisposable[] = [];

const once = (
ee: NodeJS.EventEmitter,
name: string,
fn: (...args: any[]) => void
) => {
ee.once(name, fn);
disposables.push(toDisposable(() => ee.removeListener(name, fn)));
};

const on = (
ee: NodeJS.EventEmitter,
name: string,
fn: (...args: any[]) => void
) => {
ee.on(name, fn);
disposables.push(toDisposable(() => ee.removeListener(name, fn)));
};

const [exitCode, stdout, stderr] = await Promise.all<any>([
new Promise<number>((resolve, reject) => {
once(process, "error", reject);
once(process, "exit", resolve);
}),
new Promise<Buffer>(resolve => {
const buffers: Buffer[] = [];
on(process.stdout as Readable, "data", (b: Buffer) => buffers.push(b));
once(process.stdout as Readable, "close", () =>
resolve(Buffer.concat(buffers))
);
}),
new Promise<string>(resolve => {
const buffers: Buffer[] = [];
on(process.stderr as Readable, "data", (b: Buffer) => buffers.push(b));
once(process.stderr as Readable, "close", () =>
resolve(Buffer.concat(buffers).toString())
);
})
]);

dispose(disposables);

if (options.log !== false && stderr.length > 0) {
const name = this.lastCwd.split(/[\\\/]+/).pop();
const err = stderr
.split("\n")
.filter((line: string) => line)
.map((line: string) => `[${name}]$ ${line}`)
.join("\n");
this.logOutput(err);
}

return { exitCode, stdout, stderr };
}

public async getRepositoryRoot(path: string) {
try {
const result = await this.exec(path, ["info", "--xml"]);
Expand Down
Loading

0 comments on commit 4ceeafe

Please sign in to comment.