Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

All notable changes to the "gops" extension will be documented in this file.

Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)

## [Unreleased]
## [0.0.5]

- Initial release
- Added ability to perform diff checks on changed files
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@
"command": "gops.tag",
"title": "Create Tag",
"icon": "$(tag)"
},
{
"command": "gops.showDiff",
"title": "Show Diff",
"icon": "$(diff)"
}
],
"viewsContainers": {
Expand Down Expand Up @@ -167,7 +172,7 @@
},
"devDependencies": {
"@types/mocha": "^10.0.10",
"@types/node": "22.x",
"@types/node": "^22.19.19",
"@types/vscode": "^1.110.0",
"@vscode/test-cli": "^0.0.11",
"@vscode/test-electron": "^2.5.2",
Expand Down
Binary file modified resources/gops-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 25 additions & 1 deletion src/commands/CommandRegistrar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import { GitService } from "../services/GitService";
import { COMMANDS } from "./Commands";
import { GitTreeNode } from "../gopstree/types";
import { Logger } from "../logging/Logger";
import { DiffService } from "../services/DiffService";
import { ChangedFileNode } from "../gopstree/nodes/ChangedFileNode";

export class CommandRegistrar {
constructor(
private context: vscode.ExtensionContext,
private treeDataProvider: TreeDataProvider,
private gitService: GitService,
private diffService: DiffService,
) {}

registerAll() {
Expand Down Expand Up @@ -92,7 +95,28 @@ export class CommandRegistrar {
this.treeDataProvider.refresh(node.parent);
}
},
);
);

this.register(COMMANDS.SHOW_DIFF, async (node: GitTreeNode) => {
console.debug(`executed command: ${COMMANDS.SHOW_DIFF}`);
if (!node || !(node instanceof ChangedFileNode) || !node.fileName) {
return;
}
const repoPath = this.gitService.getRepoPath();

await this.diffService.openDiff({
left: {
repositoryPath: repoPath,
fileName: node.fileName,
ref: "HEAD",
},
right: {
repositoryPath: repoPath,
fileName: node.fileName,
},
title: `Diff: ${node.fileName}`,
});
});
}

private register(
Expand Down
1 change: 1 addition & 0 deletions src/commands/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export const COMMANDS = {
CREATE_BRANCH_FROM_CURRENT: "gops.branch.current",
CREATE_BRANCH: "gops.branch",
CREATE_TAG: "gops.tag",
SHOW_DIFF: "gops.showDiff",
} as const;
12 changes: 9 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@ import * as vscode from "vscode";
import { TreeDataProvider } from "./gopstree/TreeDataProvider";
import { GitService } from "./services/GitService";
import { CommandRegistrar } from "./commands/CommandRegistrar";
import { DiffService } from "./services/DiffService";
import { FileService } from "./services/FileService";

export function activate(context: vscode.ExtensionContext) {
const gitService = new GitService();
const fileService = new FileService(context.globalStorageUri.fsPath);
const diffService = new DiffService(fileService, gitService);
const treeDataProvider = new TreeDataProvider(gitService);
vscode.window.createTreeView("gitOpsTreeview", {treeDataProvider});

const treeView = vscode.window.createTreeView("gitOpsTreeview", { treeDataProvider });
// Register commands
const registrar = new CommandRegistrar(
context,
treeDataProvider,
gitService,
diffService,
);
registrar.registerAll();


context.subscriptions.push(treeView);
console.log("Gops extension activated.");
}

Expand Down
11 changes: 8 additions & 3 deletions src/gopstree/TreeDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { RemoteBranchNode } from "./nodes/RemoteBranchNode";
import { Constants } from "../constants/Constants";
import { GitTreeNode } from "./types";
import { Notifications } from "../notifications/Notifications";
import { ChangedFileNode } from "./nodes/ChangedFileNode";

export class TreeDataProvider implements vscode.TreeDataProvider<GitTreeNode> {
private _onDidChangeTreeData = new vscode.EventEmitter<
Expand Down Expand Up @@ -81,9 +82,13 @@ export class TreeDataProvider implements vscode.TreeDataProvider<GitTreeNode> {
...status.renamed.map((f) => f.to),
];

return changedFiles.map(
(f) => new TreeItemModel({ label: f }, NodeType.File, vscode.TreeItemCollapsibleState.None)
);
const allChangedFiles = changedFiles.map((f) => {
const node = new ChangedFileNode(f);
console.debug(node.toString());
return node;
});

return allChangedFiles;
}

private async getTags(): Promise<TreeItemModel[]> {
Expand Down
37 changes: 37 additions & 0 deletions src/gopstree/nodes/ChangedFileNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ContextValue } from "../ContextValue";
import { NodeType } from "./NodeType";
import { TreeItemModel } from "../TreeItemModel";
import * as vscode from 'vscode';
import { createChangedFileTooltip, formatChangedFileLabel } from "./utils/nodeUtils";
import { COMMANDS } from "../../commands/Commands";

export class ChangedFileNode extends TreeItemModel<NodeType.Changes> {
public override command?: vscode.Command;
constructor(
public readonly fileName: string,
) {
const fomatted = formatChangedFileLabel(fileName);
super(
{
label: fomatted.label,
highlights: fomatted.highlights,
},
NodeType.Changes,
vscode.TreeItemCollapsibleState.None,
);
this.contextValue = ContextValue.Changes;
this.command = {
title: "Show Diff",
command: COMMANDS.SHOW_DIFF,
arguments: [this],
};

this.tooltip = createChangedFileTooltip(
fileName,
);
}

public toString(): string {
return `ChangedFileNode(${this.fileName}, contextValue=${this.contextValue})`;
}
}
15 changes: 15 additions & 0 deletions src/gopstree/nodes/utils/nodeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,18 @@ export const createRemoteBranchTooltip = (
isTracking ? "Tracking enabled" : "Not tracking",
].join("\n");
};

export const formatChangedFileLabel = (
fileName: string,
): LabelWithHighlights => {
return {
label: fileName,
highlights: [],
};
};

export const createChangedFileTooltip = (
fileName: string,
): string => {
return `File: ${fileName}`;
};
File renamed without changes.
7 changes: 7 additions & 0 deletions src/models/DiffRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { FileRevision } from "./FileRevision";

export interface DiffRequest {
left: FileRevision;
right: FileRevision;
title?: string;
}
5 changes: 5 additions & 0 deletions src/models/FileRevision.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface FileRevision {
repositoryPath: string;
fileName: string;
ref?: string;
}
File renamed without changes.
File renamed without changes.
35 changes: 35 additions & 0 deletions src/services/DiffService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as vscode from "vscode";
import * as path from "path";
import { DiffRequest } from "../models/DiffRequest";
import { GitService } from "./GitService";
import { FileService } from "./FileService";

export class DiffService {
constructor(
private readonly fileService: FileService,
private readonly gitService: GitService,
) {}

public async openDiff(request: DiffRequest): Promise<void> {
const headContent = await this.gitService.getFileContent(
request.left.ref ?? "HEAD",
request.left.fileName,
);

const tempFile = await this.fileService.createTempFile(
request.left.fileName,
headContent,
);

const rightUri = vscode.Uri.file(
path.join(request.right.repositoryPath, request.right.fileName),
);

await vscode.commands.executeCommand(
"vscode.diff",
vscode.Uri.file(tempFile),
rightUri,
request.title,
);
}
}
27 changes: 27 additions & 0 deletions src/services/FileService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as fs from "fs";
import * as path from "path";

export class FileService {
constructor(private readonly storagePath: string) {}

public async createTempFile(
filePath: string,
content: string,
): Promise<string> {
const tempDir = this.getTempDir();

await fs.promises.mkdir(tempDir, { recursive: true });

const safeName = filePath.replace(/[\/\\]/g, "_");

const tempFilePath = path.join(tempDir, `${Date.now()}_${safeName}`);

await fs.promises.writeFile(tempFilePath, content, "utf8");

return tempFilePath;
}

private getTempDir(): string {
return path.join(this.storagePath, "temp");
}
}
10 changes: 7 additions & 3 deletions src/services/GitService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import * as vscode from "vscode";
import * as path from "path";
import { Logger } from "../logging/Logger";
import { Notifications } from "../notifications/Notifications";
import { LocalBranchModel } from "./LocalBranchModel";
import { RemoteBranchModel } from "./RemoteBranchModel";
import { AheadBehindModel } from "./AheadBehindModel";
import { LocalBranchModel } from "../models/LocalBranchModel";
import { RemoteBranchModel } from "../models/RemoteBranchModel";
import { AheadBehindModel } from "../models/AheadBehindModel";

export class GitService {
private git: SimpleGit;
Expand Down Expand Up @@ -74,6 +74,10 @@ export class GitService {
return log.all;
}

public async getFileContent(ref: string, filePath: string): Promise<string> {
return await this.git.show([`${ref}:${filePath}`]);
}

// #region [Branch Operations]

async checkout(branch: string) {
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"sourceMap": true,
"rootDir": "src",
"strict": true /* enable all strict type-checking options */,
"outDir": "dist"
"outDir": "dist",
"types": ["node"]
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
Expand Down
Loading