1
1
mirror of https://github.com/kahole/edamagit.git synced 2024-08-16 02:30:31 +03:00

adds staging and implements updates

This commit is contained in:
kahole 2019-12-12 22:09:00 +01:00
parent 50430b3d8e
commit 85c3a0fb4c
21 changed files with 213 additions and 151 deletions

View File

@ -7,5 +7,6 @@
"out": true // set this to false to include "out" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off"
"typescript.tsc.autoDetect": "off",
"typescript.tsdk": "node_modules/typescript/lib"
}

6
package-lock.json generated
View File

@ -868,9 +868,9 @@
}
},
"typescript": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz",
"integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==",
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz",
"integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==",
"dev": true
},
"vscode-test": {

View File

@ -95,8 +95,12 @@
"languages": [
{
"id": "magit-status",
"aliases": ["Magit"],
"extensions": [".magit"],
"aliases": [
"Magit"
],
"extensions": [
".magit"
],
"configuration": "./languages/magit.language-configuration.json"
}
],
@ -113,6 +117,11 @@
"key": "tab",
"when": "editorTextFocus && editorLangId == magit-status"
},
{
"command": "extension.magit",
"key": "g",
"when": "editorTextFocus && editorLangId == magit-status"
},
{
"command": "extension.magit-visit-at-point",
"key": "enter",
@ -174,8 +183,8 @@
"@types/vscode": "^1.40.0",
"glob": "^7.1.5",
"mocha": "^6.2.2",
"typescript": "^3.6.4",
"tslint": "^5.20.0",
"typescript": "^3.7.3",
"tslint": "^5.20.1",
"vscode-test": "^1.2.2"
}
}
}

View File

@ -1,11 +1,11 @@
import { gitApi } from "../extension";
import { exec, spawn, ExecException } from "child_process";
import { getCurrentMagitRepo } from "../utils/magitUtils";
import { window } from "vscode";
import MagitUtils from "../utils/magitUtils";
export async function magitCommit() {
let currentRepository = getCurrentMagitRepo();
let currentRepository = MagitUtils.getCurrentMagitRepo();
// TODO: show menu etc..

View File

@ -1,10 +1,10 @@
import { MagitPicker } from "../menus/magitPicker";
import { PushingMenu } from "../menus/pushing/pushingMenu";
import { getCurrentMagitRepo } from "../utils/magitUtils";
import MagitUtils from "../utils/magitUtils";
export function pushing() {
let currentRepository = getCurrentMagitRepo();
let currentRepository = MagitUtils.getCurrentMagitRepo();
if (currentRepository) {
console.log("Working tree changes, but from pushing command");

View File

@ -1,28 +1,101 @@
import { getCurrentMagitRepo } from "../utils/magitUtils";
// repository.apply( hunk.diff ) FOR Å STAGE HUNKS!
// NB! Trenger kanskje headeren til hele diffen for å utføre disse.
// Den kan hektes på i et eget felt i Hunk-modellen, null stress joggedress!
import { window, workspace, commands } from "vscode";
import { HunkView } from "../views/changes/HunkView";
import { ChangeView } from "../views/changes/changeView";
import MagitUtils from "../utils/magitUtils";
import FilePathUtils from "../utils/filePathUtils";
import { ChangeSectionView } from "../views/changes/changesSectionView";
import { Section } from "../views/sectionHeader";
import { internalMagitStatus } from "./statusCommands";
import MagitStatusView from "../views/magitStatusView";
export function magitStage() {
let currentRepository = getCurrentMagitRepo();
if (currentRepository) {
let repository = MagitUtils.getCurrentMagitRepo();
let currentView = repository?.views?.get(window.activeTextEditor?.document.uri.toString() ?? "");
if (currentView) {
let clickedView = currentView.click(window.activeTextEditor!.selection.active);
let currentRepository = repository!;
// currentRepository
// .apply("my cool diff")
// .catch(err => {});
// TODO: Is this a good way of solving this?
if (clickedView instanceof HunkView) {
let changeHunkDiff = (clickedView as HunkView).changeHunk.diff;
// Apply diff
// currentRepository
// .apply((clickedView as HunkView).changeHunk.diffHeader + changeHunkDiff)
// .catch(err => { console.log(err); });
} else if (clickedView instanceof ChangeView) {
let magitChange = (clickedView as ChangeView).change;
currentRepository
._repository
.add([magitChange.uri], { update: true }) // TODO: litt usikker om update eller ikke
.then(() => internalMagitStatus(currentRepository))
.then(() => (currentView as MagitStatusView).triggerUpdate())
.catch(err => { console.log(err); });
} else if (clickedView instanceof ChangeSectionView) {
let section = (clickedView as ChangeSectionView).section;
switch (section) {
case Section.Untracked:
magitStageAll(StageAllKind.AllUntracked);
break;
case Section.Unstaged:
magitStageAll(StageAllKind.AllTracked);
break;
default:
break;
}
} else {
// TODO:
// Switch to a quick pick where i can pass data, and have a title
// Maybe make a simple wrapper
// This should NOT be the same as a menu!
window.showQuickPick([
...currentRepository.magitState?.workingTreeChanges!,
...currentRepository.magitState?.indexChanges!,
...currentRepository.magitState?.untrackedFiles!,
// ...currentRepository.magitState?.mergeChanges
].map(c => FilePathUtils.pathRelativeTo(c.uri, currentRepository.rootUri)),
{ placeHolder: "Stage" }
)
.then(chosenFilePath => {
})
.then(() => internalMagitStatus(currentRepository))
.then(() => (currentView as MagitStatusView).triggerUpdate());
}
// NB! Trenger kanskje headeren til hele diffen for å utføre disse.
// Den kan hektes på i et eget felt i Hunk-modellen, null stress joggedress!
}
}
export function magitStageAll() {
let currentRepository = getCurrentMagitRepo();
export enum StageAllKind {
All = "stageAll",
AllTracked = "stageAllTracked",
AllUntracked = "stageAllUntracked"
}
if (currentRepository) {
export function magitStageAll(kind: StageAllKind = StageAllKind.AllTracked) {
currentRepository.apply("all my cool diffs");
const editor = window.activeTextEditor;
const currentRepository = MagitUtils.getCurrentMagitRepo();
if (!editor || !currentRepository) {
return;
}
let currentView = currentRepository.views?.get(editor.document.uri.toString());
if (currentView instanceof MagitStatusView) {
commands.executeCommand("git." + kind.valueOf())
.then(() => internalMagitStatus(currentRepository))
.then(() => (currentView as MagitStatusView).triggerUpdate());
}
}

View File

@ -1,21 +1,34 @@
import { MagitState } from "../models/magitStatus";
import { MagitChange } from "../models/magitChange";
import { encodeLocation } from "../contentProvider";
import { workspace, window, ViewColumn, Range } from "vscode";
import { gitApi, magitRepositories } from "../extension";
import { Repository, Status, Change } from "../typings/git";
import { FilePathUtils } from "../utils/filePathUtils";
import { GitTextUtils } from "../utils/gitTextUtils";
import FilePathUtils from "../utils/filePathUtils";
import GitTextUtils from "../utils/gitTextUtils";
import { MagitRepository } from "../models/magitRepository";
import MagitUtils from "../utils/magitUtils";
import MagitStatusView from "../views/magitStatusView";
import { Status } from "../typings/git";
export function magitStatus() {
// Magit status already open?
let repository = MagitUtils.getCurrentMagitRepo();
let currentView = repository?.views?.get(window.activeTextEditor?.document.uri.toString() ?? "");
if (currentView instanceof MagitStatusView) {
let currentRepository = repository!;
internalMagitStatus(currentRepository)
.then(() => (currentView as MagitStatusView).triggerUpdate())
return;
}
// New magit status document
if (workspace.workspaceFolders && workspace.workspaceFolders[0]) {
const rootPath = workspace.workspaceFolders[0].uri.fsPath;
let repository: MagitRepository | undefined;
// TODO: clean up this mess
let repos = Object.entries(magitRepositories).filter(
@ -34,9 +47,8 @@ export function magitStatus() {
let magitRepo: MagitRepository = repository;
magitRepositories[repository.rootUri.fsPath] = repository;
MagitStatus(repository)
.then(m => {
magitRepo.magitState = m;
internalMagitStatus(magitRepo)
.then(() => {
const uri = encodeLocation(magitRepo.rootUri.fsPath);
workspace.openTextDocument(uri).then(doc => window.showTextDocument(doc, ViewColumn.Beside));
});
@ -47,7 +59,7 @@ export function magitStatus() {
}
}
async function MagitStatus(repository: Repository): Promise<MagitState> {
export async function internalMagitStatus(repository: MagitRepository): Promise<void> {
await repository.status();
@ -105,7 +117,7 @@ async function MagitStatus(repository: Repository): Promise<MagitState> {
let commitCache = commits.reduce((prev, commit) => ({ ...prev, [commit.hash]: commit }), {});
return {
repository.magitState = {
_state: repository.state,
stashes,
log,

View File

@ -1,35 +1,18 @@
import { window, TextEditor, Range, workspace } from "vscode";
import * as Constants from '../common/constants';
import { magitRepositories } from "../extension";
import { HunkView } from "../views/changes/HunkView";
import MagitUtils from "../utils/magitUtils";
export function magitVisitAtPoint() {
if (window.activeTextEditor) {
let repository = MagitUtils.getCurrentMagitRepo();
let currentView = repository?.views?.get(window.activeTextEditor?.document.uri.toString() ?? "");
const editor = window.activeTextEditor;
const currentRepository = magitRepositories[window.activeTextEditor.document.uri.query];
if (!editor || !currentRepository) {
return;
}
let currentView = currentRepository.views!.get(editor.document.uri.toString());
if (currentView) {
let clickedView = currentView.click(editor.selection.active);
console.log(editor.selection.active.line);
console.log(clickedView);
// TODO: Is this a good way of solving this?
if (clickedView instanceof HunkView) {
// (clickedView as HunkView).changeHunk.diff
}
}
// let selectedLine = editor.document.getText().split(Constants.LineSplitterRegex)[editor.selection.active.line];
// console.log(selectedLine);
if (currentView) {
let clickedView = currentView.click(window.activeTextEditor!.selection.active);
let currentRepository = repository!;
console.log(window.activeTextEditor!.selection.active.line);
console.log(clickedView);
}
// let selectedLine = editor.document.getText().split(Constants.LineSplitterRegex)[editor.selection.active.line];
// console.log(selectedLine);
}

View File

@ -1,8 +1,11 @@
import { Repository } from "../typings/git";
import { Uri } from "vscode";
interface BaseRepository {
getStashes(): Promise<Stash[]>;
pushTo(remote?: string, name?: string, setUpstream?: boolean, forcePushMode?: ForcePushMode): Promise<void>;
add(resources: Uri[], opts?: { update?: boolean }): Promise<void>;
stage(resource: Uri, contents: string): Promise<void>;
}
// Repository.prototype.getStashes = function(this: any) {

View File

@ -14,18 +14,22 @@ export default class ContentProvider implements vscode.TextDocumentContentProvid
// TODO: can be used for BOLD, gutter displays, and other bonus styles:
// private _editorDecoration = vscode.window.createTextEditorDecorationType({ textDecoration: 'underline' });
private _subscriptions: vscode.Disposable;
// private _subscriptions: vscode.Disposable;
constructor() {
// Listen to the `closeTextDocument`-event which means we must
// clear the corresponding View
this._subscriptions = vscode.workspace.onDidCloseTextDocument(
doc => magitRepositories[doc.uri.query].views!.delete(doc.uri.toString()));
// TODO:
// Might not need to delete all views. Keep magit-status view?
// and then just update
// might wanna delete other types of views though
// this._subscriptions = vscode.workspace.onDidCloseTextDocument(
// doc => magitRepositories[doc.uri.query].views!.delete(doc.uri.toString()));
}
dispose() {
this._subscriptions.dispose();
// this._subscriptions.dispose();
// this._documents.clear();
// this._editorDecoration.dispose();
this._onDidChange.dispose();
@ -42,16 +46,14 @@ export default class ContentProvider implements vscode.TextDocumentContentProvid
let magitRepo = magitRepositories[uri.query];
let statusView = new MagitStatusView(uri, magitRepo.magitState!, this._onDidChange);
if (!magitRepo.views) {
magitRepo.views = new Map<string, View>();
}
magitRepo.views!.set(uri.toString(), statusView);
let statusView = new MagitStatusView(uri, this._onDidChange, magitRepo.magitState!);
magitRepo.views.set(uri.toString(), statusView);
// this._documents.set(uri.toString(), statusView);
return statusView.value;
return statusView.render(0).join('\n');
}
// provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentLink[] | undefined {

View File

@ -1,6 +1,6 @@
import * as vscode from 'vscode';
import { View } from './views/abstract/view';
import { getCurrentMagitRepo } from './utils/magitUtils';
import MagitUtils from './utils/magitUtils';
export default class FoldingRangeProvider implements vscode.FoldingRangeProvider {
@ -12,7 +12,7 @@ export default class FoldingRangeProvider implements vscode.FoldingRangeProvider
let foldingRanges: vscode.FoldingRange[] = [];
let currentRepository = getCurrentMagitRepo();
let currentRepository = MagitUtils.getCurrentMagitRepo();
if (currentRepository && currentRepository.views) {
let currentView = currentRepository.views.get(document.uri.toString());

View File

@ -1,6 +1,5 @@
import * as vscode from 'vscode';
import { View } from './views/abstract/view';
import { getCurrentMagitRepo } from './utils/magitUtils';
import MagitUtils from './utils/magitUtils';
export default class HighlightProvider implements vscode.DocumentHighlightProvider {
@ -12,7 +11,7 @@ export default class HighlightProvider implements vscode.DocumentHighlightProvid
let highlights: vscode.DocumentHighlight[] = [];
let currentRepository = getCurrentMagitRepo();
let currentRepository = MagitUtils.getCurrentMagitRepo();
if (currentRepository && currentRepository.views) {
let currentView = currentRepository.views.get(document.uri.toString());

View File

@ -2,4 +2,5 @@
export interface MagitChangeHunk {
diff: string;
diffHeader: string;
}

View File

@ -1,6 +1,7 @@
import { dirname, sep } from 'path';
import { Uri } from 'vscode';
export class FilePathUtils {
export default class FilePathUtils {
// https://github.com/microsoft/vscode/blob/f667462a2a8a12c92dbcdd8acf92df7354063691/extensions/git/src/util.ts#L309
private static isWindowsPath(path: string): boolean {
@ -25,4 +26,8 @@ export class FilePathUtils {
return descendant.startsWith(parent);
}
public static pathRelativeTo(uri: Uri, root: Uri) {
return uri.path.slice(root.path.length + 1);
}
}

View File

@ -1,13 +1,17 @@
import { MagitChangeHunk } from "../models/magitChangeHunk";
import { FinalLineBreakRegex } from "../common/constants";
export class GitTextUtils {
export default class GitTextUtils {
public static diffToHunks(diff: string): MagitChangeHunk[] {
let hunksStart = diff.indexOf("@@");
let diffHeader = diff.slice(0, hunksStart);
return diff
.replace(FinalLineBreakRegex, '') // remove extra line break at the end
.substring(diff.indexOf("@@"))
.replace(FinalLineBreakRegex, '') // removes extra line break at the end
.slice(hunksStart)
.split(/\n(?=^@@.*@@.*$)/gm)
.map(hunkText => ({ diff: hunkText }));
.map(hunkText => ({ diff: hunkText, diffHeader }));
}
}

View File

@ -2,8 +2,11 @@ import { MagitRepository } from "../models/magitRepository";
import { magitRepositories } from "../extension";
import { window } from "vscode";
export function getCurrentMagitRepo(): MagitRepository | undefined {
if (window.activeTextEditor) {
return magitRepositories[window.activeTextEditor.document.uri.query];
export default class MagitUtils {
public static getCurrentMagitRepo(): MagitRepository | undefined {
if (window.activeTextEditor) {
return magitRepositories[window.activeTextEditor.document.uri.query];
}
}
}

View File

@ -0,0 +1,11 @@
import { View } from "./view";
import { Uri, EventEmitter } from "vscode";
export abstract class DocumentView extends View {
public abstract triggerUpdate(): void;
constructor(protected uri: Uri, protected emitter: EventEmitter<Uri>) {
super();
}
}

View File

@ -19,7 +19,7 @@ function mapFileStatusToLabel(status: Status): string {
case Status.MODIFIED:
return "modified";
case Status.INDEX_ADDED:
return "added";
return "new file";
case Status.INDEX_DELETED:
case Status.DELETED:
return "deleted";

View File

@ -8,7 +8,7 @@ import { ChangeHeaderView } from "./changeHeaderView";
export class ChangeView extends View {
isFoldable = true;
constructor(private change: MagitChange) {
constructor(public change: MagitChange) {
super();
this.subViews = [new ChangeHeaderView(change)];
if (this.change.hunks) {

View File

@ -7,7 +7,7 @@ import { LineBreakView } from "../lineBreakView";
export class ChangeSectionView extends View {
isFoldable = true;
constructor(section: Section, private changes: MagitChange[]) {
constructor(public section: Section, private changes: MagitChange[]) {
super();
this.subViews = [
new SectionHeaderView(section, changes.length),

View File

@ -1,75 +1,31 @@
import * as vscode from 'vscode';
import { MagitState } from '../models/magitStatus';
import { MagitChange } from "../models/magitChange";
import { ChangeView } from './changes/changeView';
import { ChangeSectionView } from './changes/changesSectionView';
import { Section } from './sectionHeader';
import { View } from './abstract/view';
import { RestView } from './restView';
import { DocumentView } from './abstract/documentView';
export default class MagitStatusView extends View {
export default class MagitStatusView extends DocumentView {
private readonly _uri: vscode.Uri;
private readonly _emitter: vscode.EventEmitter<vscode.Uri>;
constructor(uri: vscode.Uri, emitter: vscode.EventEmitter<vscode.Uri>, magitState: MagitState) {
super(uri, emitter);
// private readonly _lines: string[];
private readonly SECTION_FOLD_REGION_END: string = '.';
constructor(uri: vscode.Uri, magitStatus: MagitState, emitter: vscode.EventEmitter<vscode.Uri>) {
super();
this._uri = uri;
// The ReferencesDocument has access to the event emitter from
// the containg provider. This allows it to signal changes
this._emitter = emitter;
// Start with printing a header and start resolving
// this._lines = [];
if (magitStatus.untrackedFiles && magitStatus.untrackedFiles.length > 0) {
// this._lines.push(`Untracked files (${magitStatus.untrackedFiles.length})`);
// let untrackedFiles = this.renderChanges(magitStatus.untrackedFiles);
// this._lines.push(...untrackedFiles);
// this._lines.push(this.SECTION_FOLD_REGION_END);
this.subViews.push(new ChangeSectionView(Section.Untracked, magitStatus.untrackedFiles));
if (magitState.untrackedFiles && magitState.untrackedFiles.length > 0) {
this.subViews.push(new ChangeSectionView(Section.Untracked, magitState.untrackedFiles));
}
if (magitStatus.workingTreeChanges && magitStatus.workingTreeChanges.length > 0) {
let unstagedView = new ChangeSectionView(Section.Unstaged, magitStatus.workingTreeChanges);
this.subViews.push(unstagedView);
// this._lines.push(...unstagedView.render(0));
// this._lines.push(this.SECTION_FOLD_REGION_END);
if (magitState.workingTreeChanges && magitState.workingTreeChanges.length > 0) {
this.subViews.push(new ChangeSectionView(Section.Unstaged, magitState.workingTreeChanges));
}
if (magitStatus.indexChanges && magitStatus.indexChanges.length > 0) {
this.subViews.push(new ChangeSectionView(Section.Staged, magitStatus.indexChanges));
// this._lines.push(`Staged changes (${magitStatus.indexChanges.length})`);
// let stagedChanges = this.renderChanges(magitStatus.indexChanges);
// this._lines.push(...stagedChanges);
// this._lines.push(this.SECTION_FOLD_REGION_END);
if (magitState.indexChanges && magitState.indexChanges.length > 0) {
this.subViews.push(new ChangeSectionView(Section.Staged, magitState.indexChanges));
}
this.subViews.push(new RestView(magitStatus));
this.subViews.push(new RestView(magitState));
}
// private renderChanges(changes: MagitChange[]) : string[] {
// return changes
// .map(change => {
// return new ChangeView(change).render(0).join('\n');
// // let hunkRender = change.hunks ? change.hunks.map( h => h.diff ).join('\n') : '\n';
// // return `${mapFileStatusToLabel(change.status)} ${change.uri.path}${hunkRender}`;
// });
// }
get value() {
return this.render(0).join('\n');
public triggerUpdate() {
this.emitter.fire(this.uri);
}
}