mirror of
https://github.com/Microsoft/vscode
synced 2024-09-13 21:55:38 +00:00
26120e5bf4
For /fixTestFailures, I want to get more 'real world' tests and test fixes. This makes a change in the selfhost test provider such that when a test fails and is then fixed, we record the code changes into a JSON file in the `.build` directory. In a few days I'll follow up with team members to collect their test failures and use them as evaluation tests for copilot. The FailureTracker will be removed when I've gotten enough data.
109 lines
3.1 KiB
TypeScript
109 lines
3.1 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as path from 'path';
|
|
import * as cp from 'child_process';
|
|
import * as fs from 'fs';
|
|
import * as File from 'vinyl';
|
|
import * as es from 'event-stream';
|
|
import * as filter from 'gulp-filter';
|
|
import { Stream } from 'stream';
|
|
|
|
const watcherPath = path.join(__dirname, 'watcher.exe');
|
|
|
|
function toChangeType(type: '0' | '1' | '2'): 'change' | 'add' | 'unlink' {
|
|
switch (type) {
|
|
case '0': return 'change';
|
|
case '1': return 'add';
|
|
default: return 'unlink';
|
|
}
|
|
}
|
|
|
|
function watch(root: string): Stream {
|
|
const result = es.through();
|
|
let child: cp.ChildProcess | null = cp.spawn(watcherPath, [root]);
|
|
|
|
child.stdout!.on('data', function (data) {
|
|
const lines: string[] = data.toString('utf8').split('\n');
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i].trim();
|
|
if (line.length === 0) {
|
|
continue;
|
|
}
|
|
|
|
const changeType = <'0' | '1' | '2'>line[0];
|
|
const changePath = line.substr(2);
|
|
|
|
// filter as early as possible
|
|
if (/^\.git/.test(changePath) || /(^|\\)out($|\\)/.test(changePath)) {
|
|
continue;
|
|
}
|
|
|
|
const changePathFull = path.join(root, changePath);
|
|
|
|
const file = new File({
|
|
path: changePathFull,
|
|
base: root
|
|
});
|
|
(<any>file).event = toChangeType(changeType);
|
|
result.emit('data', file);
|
|
}
|
|
});
|
|
|
|
child.stderr!.on('data', function (data) {
|
|
result.emit('error', data);
|
|
});
|
|
|
|
child.on('exit', function (code) {
|
|
result.emit('error', 'Watcher died with code ' + code);
|
|
child = null;
|
|
});
|
|
|
|
process.once('SIGTERM', function () { process.exit(0); });
|
|
process.once('SIGTERM', function () { process.exit(0); });
|
|
process.once('exit', function () { if (child) { child.kill(); } });
|
|
|
|
return result;
|
|
}
|
|
|
|
const cache: { [cwd: string]: Stream } = Object.create(null);
|
|
|
|
module.exports = function (pattern: string | string[] | filter.FileFunction, options?: { cwd?: string; base?: string; dot?: boolean }) {
|
|
options = options || {};
|
|
|
|
const cwd = path.normalize(options.cwd || process.cwd());
|
|
let watcher = cache[cwd];
|
|
|
|
if (!watcher) {
|
|
watcher = cache[cwd] = watch(cwd);
|
|
}
|
|
|
|
const rebase = !options.base ? es.through() : es.mapSync(function (f: File) {
|
|
f.base = options!.base!;
|
|
return f;
|
|
});
|
|
|
|
return watcher
|
|
.pipe(filter(['**', '!.git{,/**}'], { dot: options.dot })) // ignore all things git
|
|
.pipe(filter(pattern, { dot: options.dot }))
|
|
.pipe(es.map(function (file: File, cb) {
|
|
fs.stat(file.path, function (err, stat) {
|
|
if (err && err.code === 'ENOENT') { return cb(undefined, file); }
|
|
if (err) { return cb(); }
|
|
if (!stat.isFile()) { return cb(); }
|
|
|
|
fs.readFile(file.path, function (err, contents) {
|
|
if (err && err.code === 'ENOENT') { return cb(undefined, file); }
|
|
if (err) { return cb(); }
|
|
|
|
file.contents = contents;
|
|
file.stat = stat;
|
|
cb(undefined, file);
|
|
});
|
|
});
|
|
}))
|
|
.pipe(rebase);
|
|
};
|