Init

[?]
Nov 22, 2020, 10:29 AM
L3EBZ3DGUAQUMYJLZMPRTJHKSRJFYWO2P2S773JHAACAXNNASR6QC

Dependencies

Change contents

  • file addition: tslint.json (-xw-x--x--)
    [1.0]
    {
    "rules": {
    "no-string-throw": true,
    "no-unused-expression": true,
    "no-duplicate-variable": true,
    "curly": true,
    "class-name": true,
    "semicolon": [true, "always"],
    "triple-equals": true
    },
    "defaultSeverity": "warning"
    }
  • file addition: tsconfig.json (-xw-x--x--)
    [1.0]
    {
    "compilerOptions": {
    "module": "commonjs",
    "target": "es2019",
    "lib": ["ES2019"],
    "outDir": "out",
    "sourceMap": true,
    "strict": true,
    "rootDir": "src"
    },
    "exclude": ["node_modules", ".vscode-test"]
    }
  • file addition: src (dxwrx-rx-r)
    [1.0]
  • file addition: extension.ts (-xw-x--x--)
    [0.497]
    import * as vscode from 'vscode';
    import { Uri } from "vscode";
    import * as path from 'path';
    import * as cp from 'child_process';
    import * as os from 'os';
    export interface IPijul {
    path: string;
    version: string;
    }
    export interface Diff {
    operation: string;
    line: number | undefined;
    }
    enum Section {
    Init,
    Changes,
    }
    class Repository implements vscode.TextDocumentContentProvider {
    panel: vscode.WebviewPanel | undefined;
    provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
    return new Promise<string>((c, e) => {
    if (vscode.workspace.rootPath == undefined) {
    return e(new Error("No workspace open"));
    }
    const buffers: Buffer[] = [];
    const child = cp.spawn("pijul", [
    'reset',
    '--repository', vscode.workspace.rootPath,
    '--dry-run',
    uri.path.slice(1)
    ]);
    child.stdout.on('data', (b: Buffer) => buffers.push(b));
    child.on('exit', code => code ? e(new Error(`Could not output ${uri}`)) : c(Buffer.concat(buffers).toString('utf8')));
    })
    }
    initPanel(): vscode.WebviewPanel {
    if (this.panel == undefined) {
    this.panel = vscode.window.createWebviewPanel(
    'pijul.record',
    'Record a change',
    vscode.ViewColumn.One,
    { enableScripts: true }
    );
    this.panel.onDidDispose(
    () => {
    this.panel = undefined;
    },
    undefined,
    );
    } else {
    this.panel.reveal(vscode.ViewColumn.One);
    }
    return this.panel
    }
    async recordPanel() {
    console.log('recordPanel');
    const change = await diff();
    const lines = change.split(os.EOL);
    let cont = "";
    let section = Section.Init;
    let currentChange = "";
    let currentChangeName = "";
    change.split(os.EOL).forEach((line) => {
    if (line == "# Changes") {
    section = Section.Changes;
    cont = cont + "<h2>Changes</h2>"
    } else if (section == Section.Changes) {
    if (line.startsWith(' ')) {
    currentChange = currentChange + '\n' + line
    } else if (line.startsWith('+')) {
    currentChange = currentChange + `\n<div style="background:#afa">${line}</div>`
    } else if (line.startsWith('-')) {
    currentChange = currentChange + `\n<div style="background:#faa">${line}</div>`
    } else {
    if (currentChange != "") {
    cont = cont + `<h3><input type = "checkbox" checked/>${currentChangeName}</h3><div style="margin-left:2em"><pre>${currentChange}</pre></div>`;
    }
    currentChangeName = line;
    currentChange = "";
    }
    }
    });
    console.log(cont);
    let panel = this.initPanel();
    panel.webview.html = `<!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Record a change</title>
    </head>
    <body>
    ${cont}
    <button>Ok</button>
    </body>
    </html>`;
    }
    }
    function diff(): Promise<string> {
    return new Promise<string>((c, e) => {
    const buffers: Buffer[] = [];
    if (vscode.workspace.rootPath == undefined) {
    return c();
    }
    const child = cp.spawn("pijul", [
    'diff',
    '--repository', vscode.workspace.rootPath,
    ]);
    child.stdout.on('data', (b: Buffer) => buffers.push(b));
    child.on('exit', code => {
    if (code) {
    return e(new Error(`Could not record`))
    }
    return c(Buffer.concat(buffers).toString('utf8'))
    })
    })
    }
    function findPijul(path: string): Promise<IPijul> {
    return new Promise<IPijul>((c, e) => {
    const buffers: Buffer[] = [];
    const child = cp.spawn(path, ['--version']);
    child.stdout.on('data', (b: Buffer) => buffers.push(b));
    child.on('exit', code => code ? e(new Error('No Pijul found on path')) : c({
    path,
    version: Buffer.concat(buffers).toString('utf8').trim()
    }));
    });
    }
    async function pijulReset(path: string | undefined): Promise<void> {
    return new Promise<void>((c, e) => {
    if (vscode.workspace.rootPath == undefined) {
    return c();
    }
    let args: string[] = ['reset', '--repository', vscode.workspace.rootPath];
    if (path != undefined) {
    args.push(path)
    }
    const child = cp.spawn("pijul", args);
    child.on('exit', (code: number) => {
    if (code) {
    e(new Error(`Cannot reset repository ${vscode.workspace.rootPath}`));
    } else {
    c();
    }
    });
    });
    }
    async function pijulRecord(message: string | undefined): Promise<void> {
    return new Promise<void>((c, e) => {
    if (vscode.workspace.rootPath == undefined) {
    return c();
    }
    if (message == undefined) {
    return e(new Error(`No change message`));
    }
    let args: string[] = ['record', '--repository', vscode.workspace.rootPath, '-a', '-m', message];
    const child = cp.spawn("pijul", args);
    child.on('exit', (code: number) => {
    if (code) {
    e(new Error(`Cannot record in repository ${vscode.workspace.rootPath}`));
    } else {
    c();
    }
    });
    });
    }
    function pijulStatus(): Promise<Map<string, [Diff]>> {
    return new Promise<Map<string, [Diff]>>((c, e) => {
    const buffers: Buffer[] = [];
    const errbuf: Buffer[] = [];
    if (vscode.workspace.rootPath == undefined) {
    return e(new Error('no root'));
    }
    const child = cp.spawn("pijul", ['diff', '--json', '--repository', vscode.workspace.rootPath]);
    child.stdout.on('data', (b: Buffer) => buffers.push(b));
    child.stderr.on('data', (b: Buffer) => errbuf.push(b));
    child.on('exit', code => {
    const out = Buffer.concat(buffers).toString('utf8').trim();
    const err = Buffer.concat(errbuf).toString('utf8');
    if (out == '') {
    return c(new Map());
    }
    const json = JSON.parse(out);
    let changes: Map<string, [Diff]> = new Map();
    for (let k of Object.keys(json)) {
    changes.set(k, json[k]);
    }
    if (code) {
    return e(new Error('Not found'))
    } else {
    return c(changes);
    }
    })
    });
    }
    function createResourceUri(relativePath: string): vscode.Uri {
    const root = "/";
    if (vscode.workspace.rootPath != undefined) {
    vscode.workspace.rootPath
    };
    const absolutePath = path.join(root, relativePath);
    return vscode.Uri.file(absolutePath);
    }
    async function updateStatus(event: Uri | undefined, diff: vscode.SourceControlResourceGroup) {
    if (event != undefined && event.path.includes(".pijul")) {
    return;
    }
    try {
    const changes = await pijulStatus();
    var states: vscode.SourceControlResourceState[] = [];
    changes.forEach((value: [Diff], key: string) => {
    states.push({
    resourceUri: createResourceUri(key),
    command: {
    command: "pijul.diff",
    title: "Check",
    arguments: [key, value],
    }
    });
    });
    diff.resourceStates = states;
    } catch (error) {
    return
    };
    }
    async function hide_dotpijul() {
    const config = vscode.workspace.getConfiguration('files');
    let excl: any | undefined = config.inspect('exclude');
    if (excl != undefined) {
    if (excl.globalValue != undefined) {
    excl.globalValue["**/.pijul"] = true;
    await config.update('exclude', excl.globalValue, true);
    } else {
    await config.update('exclude', { "**/.pijul": true }, true);
    }
    }
    }
    export async function activate(context: vscode.ExtensionContext) {
    // const ipijul = await findPijul("pijul");
    await hide_dotpijul();
    const pijulSCM = vscode.scm.createSourceControl('pijul', 'Pijul');
    pijulSCM.acceptInputCommand = {
    command: "pijul.record",
    title: "Record change"
    };
    const diff = pijulSCM.createResourceGroup('diff', 'Diff');
    await updateStatus(undefined, diff);
    const watcher = vscode.workspace.createFileSystemWatcher(`**/*`);
    watcher.onDidChange(async event => { await updateStatus(event, diff); });
    watcher.onDidCreate(async event => { await updateStatus(event, diff); });
    watcher.onDidDelete(async event => { await updateStatus(event, diff); });
    context.subscriptions.push(vscode.commands.registerCommand("pijul.diff",
    async (uri: string, diff: [Diff]) => {
    if (vscode.workspace.rootPath == undefined) {
    return;
    };
    const absolutePath = path.join(vscode.workspace.rootPath, uri);
    const new_version = vscode.Uri.file(absolutePath);
    const old_version = vscode.Uri.file(uri).with({ scheme: "pijul" });
    console.log(diff);
    const op = diff[0].operation;
    if (op == 'edit' || op == 'replacement' || op == 'solve order conflict' ||
    op == 'unsolve order conflict' || op == 'resurrect zombies') {
    await vscode.commands.executeCommand('vscode.diff', old_version, new_version);
    }
    }
    ));
    context.subscriptions.push(vscode.commands.registerCommand("pijul.reset",
    async () => {
    await pijulReset(undefined);
    await updateStatus(undefined, diff);
    }));
    let repo = new Repository();
    context.subscriptions.push(vscode.commands.registerCommand("pijul.record",
    async () => {
    await repo.recordPanel();
    // await pijulRecord(pijulSCM.inputBox.value);
    pijulSCM.inputBox.value = "";
    await updateStatus(undefined, diff);
    }));
    vscode.workspace.registerTextDocumentContentProvider('pijul', repo);
    }
    export function deactivate() { }
  • file addition: package.json (-xw-x--x--)
    [1.0]
    {
    "name": "helloworld-sample",
    "displayName": "helloworld-sample",
    "description": "HelloWorld example for VS Code",
    "version": "0.0.1",
    "publisher": "pijul",
    "repository": "https://nest.pijul.com/pijul_org/vscode",
    "engines": {
    "vscode": "^1.34.0"
    },
    "categories": [
    "SCM Providers"
    ],
    "activationEvents": [
    "*"
    ],
    "main": "./out/extension.js",
    "contributes": {
    "commands": [
    {
    "command": "pijul.reset",
    "title": "Reset the repository",
    "icon": "$(discard)"
    },
    {
    "command": "pijul.record",
    "title": "Record the changes",
    "icon": "$(check)"
    },
    {
    "command": "pijul.diff",
    "title": "Show diff"
    }
    ],
    "menus": {
    "scm/title": [
    {
    "command": "pijul.reset",
    "when": "scmProvider == pijul",
    "group": "navigation"
    },
    {
    "command": "pijul.record",
    "when": "scmProvider == pijul",
    "group": "navigation"
    }
    ]
    }
    },
    "scripts": {
    "vscode:prepublish": "npm run compile",
    "compile": "tsc -p ./",
    "lint": "tslint -p ./",
    "watch": "tsc -watch -p ./"
    },
    "devDependencies": {
    "@types/node": "^12.12.0",
    "@types/vscode": "^1.34.0",
    "tslint": "^5.19.0",
    "typescript": "^3.8.3"
    }
    }
  • file addition: default.nix (-xw-x--x--)
    [1.0]
    with import <nixpkgs> {};
    stdenv.mkDerivation {
    name = "vscode-extension";
    buildInputs = [ nodejs nodePackages.yo ];
    }