Skip to content

Commit

Permalink
Merge branch 'develop' into more-move-commands
Browse files Browse the repository at this point in the history
  • Loading branch information
kahole committed Oct 8, 2023
2 parents 8f45612 + 7308619 commit 9a12bc3
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 30 deletions.
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@
{
"command": "magit.toggle-fold",
"title": "Magit Toggle Fold"
},
{
"command": "magit.toggle-all-folds-in-change-section-at-point",
"title": "Magit Toggle All Folds in Change Section at Point"
},
{
"command": "magit.toggle-all-folds-for-change-views",
"title": "Magit Toggle All Folds for Change Views"
}
],
"menus": {
Expand Down Expand Up @@ -367,6 +375,14 @@
{
"command": "magit.toggle-fold",
"when": "editorLangId == magit"
},
{
"command": "magit.toggle-all-folds-in-change-section-at-point",
"when": "editorLangId == magit"
},
{
"command": "magit.toggle-all-folds-for-change-views",
"when": "editorLangId == magit"
}
]
},
Expand Down Expand Up @@ -453,6 +469,16 @@
"superType": "label",
"description": "Name of a git ref from a remote."
},
{
"id": "magit-head-name",
"superType": "label",
"description": "Name of the (local) HEAD git ref."
},
{
"id": "magit-remote-head-name",
"superType": "label",
"description": "Name of a HEAD git ref on a remote repo."
},
{
"id": "magit-tag-name",
"superType": "label",
Expand All @@ -468,6 +494,12 @@
"magit-remote-ref-name": [
"variable.other.constant"
],
"magit-head-name": [
"entity.name.tag"
],
"magit-remote-head-name": [
"variable.object.property"
],
"magit-tag-name": [
"string.highlight"
]
Expand Down
4 changes: 2 additions & 2 deletions src/commands/diffingCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async function showStash({ repository }: MenuState) {
}
}

function stashToMagitChanges(nameStatusText: string, diff: string): MagitChange[] {
export function stashToMagitChanges(nameStatusText: string, diff: string): MagitChange[] {
const DIFF_PREFIX = 'diff --git';
const filesWithStatus = nameStatusText.split(Constants.LineSplitterRegex).filter(t => t !== '').map(s => s.split('\t'));
const diffs = diff.split(DIFF_PREFIX).filter(r => r !== '');
Expand Down Expand Up @@ -134,7 +134,7 @@ function getStatusFromString(status: String): number {
case 'A':
return Status.INDEX_ADDED;
case 'C':
return Status.INDEX_COPIED ;
return Status.INDEX_COPIED;
case 'D':
return Status.DELETED;
case 'R' :
Expand Down
11 changes: 10 additions & 1 deletion src/commands/loggingCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,16 @@ async function log(repository: MagitRepository, args: string[], revs: string[],
const logEntries = parseLog(output.stdout);
const revName = revs.join(' ');
const uri = LogView.encodeLocation(repository);
return ViewUtils.showView(uri, new LogView(uri, { entries: logEntries, revName }));

let defaultBranches: { [remoteName: string]: string } = {};
for await (const remote of repository.remotes) {
try {
let defaultBranch = await gitRun(repository.gitRepository, ['symbolic-ref', `refs/remotes/${remote.name}/HEAD`], undefined, LogLevel.Error);
defaultBranches[remote.name] = defaultBranch.stdout.replace(`refs/remotes/${remote.name}/`, '').trimEnd();
} catch { } // gitRun will throw an error if remote/HEAD doesn't exist - we do not need to do anything in this case
}

return ViewUtils.showView(uri, new LogView(uri, { entries: logEntries, revName }, repository, defaultBranches));
}

async function getRevs(repository: MagitRepository) {
Expand Down
12 changes: 12 additions & 0 deletions src/commands/macros.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { commands, TextEditor, Range, window, Selection, TextEditorRevealType, Position } from 'vscode';
import { MagitRepository } from '../models/magitRepository';
import { ChangeSectionView } from '../views/changes/changesSectionView';
import { ChangeView } from '../views/changes/changeView';
import { DocumentView } from '../views/general/documentView';
import { View } from '../views/general/view';
import { ChangeView } from '../views/changes/changeView';
Expand Down Expand Up @@ -39,6 +40,17 @@ export async function toggleAllFoldsInChangeSection(repo: MagitRepository, view:
}
}

export async function toggleAllFoldsForChangeViews(repo: MagitRepository, view: DocumentView) {
let changeViews = Array.from(view.walkAllSubViews()).filter(x => x instanceof ChangeView);
if (changeViews.length === 0) {
return;
}
const newFoldState = !changeViews[0].folded;
for (let changeView of changeViews) {
changeView.folded = newFoldState;
}
}

const subViewDepthSearchFlatten = (view: View, depth: number = 0): View[] => {
if (view.folded || depth >= 3) {
return [];
Expand Down
7 changes: 5 additions & 2 deletions src/commands/visitAtPointCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { PullRequestView } from '../views/forge/pullRequestView';
import { sep } from 'path';
import { ErrorMessageView } from '../views/errorMessageView';
import { processView } from './processCommands';
import { stashToMagitChanges } from './diffingCommands';

export async function magitVisitAtPoint(repository: MagitRepository, currentView: DocumentView) {

Expand Down Expand Up @@ -141,9 +142,11 @@ async function visitHunk(selectedView: HunkView, activePosition?: Position) {
}

export async function visitCommit(repository: MagitRepository, commitHash: string) {
const result = await gitRun(repository.gitRepository, ['show', commitHash]);
const nameStatus = await gitRun(repository.gitRepository, ['show', '--name-status', '--pretty=format:', commitHash]);
const header = await gitRun(repository.gitRepository, ['show', '-s', '--shortstat', commitHash]);
const diffs = await gitRun(repository.gitRepository, ['show', '--pretty=format:', commitHash]);
const commit: MagitCommit = { hash: commitHash, message: '', parents: [] };

const uri = CommitDetailView.encodeLocation(repository, commit.hash);
return ViewUtils.showView(uri, new CommitDetailView(uri, commit, result.stdout));
return ViewUtils.showView(uri, new CommitDetailView(uri, commit, header.stdout, stashToMagitChanges(nameStatus.stdout, diffs.stdout)));
}
4 changes: 3 additions & 1 deletion src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ export const MagitDocumentSelector: DocumentSelector = { scheme: MagitUriScheme,
export enum SemanticTokenTypes {
RefName = 'magit-ref-name',
RemoteRefName = 'magit-remote-ref-name',
HeadName = 'magit-head-name',
RemoteHeadName = 'magit-remote-head-name',
TagName = 'magit-tag-name',
}
}
2 changes: 2 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
saveClose,
clearSaveClose,
quitMagitView,
toggleAllFoldsForChangeViews,
toggleAllFoldsInChangeSection,
moveToPreviousEntity,
moveToNextEntity,
Expand Down Expand Up @@ -203,6 +204,7 @@ export function activate(context: ExtensionContext) {
context.subscriptions.push(commands.registerTextEditorCommand('magit.move-to-staged-changes', CommandPrimer.primeRepoAndView(moveToStagedChanges, false)));

context.subscriptions.push(commands.registerTextEditorCommand('magit.toggle-all-folds-in-change-section-at-point', CommandPrimer.primeRepoAndView(toggleAllFoldsInChangeSection, true)));
context.subscriptions.push(commands.registerTextEditorCommand('magit.toggle-all-folds-for-change-views', CommandPrimer.primeRepoAndView(toggleAllFoldsForChangeViews, true)));

context.subscriptions.push(commands.registerTextEditorCommand('magit.save-and-close-editor', saveClose));
context.subscriptions.push(commands.registerTextEditorCommand('magit.clear-and-abort-editor', clearSaveClose));
Expand Down
16 changes: 14 additions & 2 deletions src/utils/gitRawRunner.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { Repository } from '../typings/git';
import { run, SpawnOptions } from './commandRunner/command';
import { window } from 'vscode';
import GitProcessLogger from './gitProcessLogger';
import * as Constants from '../common/constants';

export enum LogLevel {
None,
Error,
Detailed
}

export async function gitRun(repository: Repository, args: string[], spawnOptions?: SpawnOptions, logLevel = LogLevel.Detailed) {
export async function gitRun(repository: Repository, args: string[], spawnOptions?: SpawnOptions, logLevel = LogLevel.Detailed, showStatus: boolean = true) {
if (showStatus) {
window.setStatusBarMessage(`Running git ${args.join(' ')}...`);
}

let logEntry;
if (logLevel > LogLevel.None) {
Expand All @@ -26,11 +31,18 @@ export async function gitRun(repository: Repository, args: string[], spawnOption
GitProcessLogger.logGitResult(result, logEntry);
}

if (showStatus) {
window.setStatusBarMessage(`Git finished successfully`, Constants.StatusMessageDisplayTimeout);
}
return result;
} catch (error) {
} catch (error: any) {
if (logLevel > LogLevel.None && logEntry) {
GitProcessLogger.logGitError(error, logEntry);
}

if (showStatus) {
window.setStatusBarMessage(error.message);
}
throw error;
}
}
25 changes: 21 additions & 4 deletions src/utils/viewUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default class ViewUtils {
return selectedViews;
}

public static generateRefTokensLine(commitHash: string, refs?: Ref[]): (string | Token)[] {
public static generateRefTokensLine(commitHash: string, refs?: Ref[], headName?: string, defaultBranches?: { [remoteName: string]: string }): (string | Token)[] {

const matchingRefs = (refs ?? [])
.filter(ref => ref.commit === commitHash)
Expand All @@ -103,7 +103,19 @@ export default class ViewUtils {
let m = matchingRefs.find(other => other.name === namePart && other.type === RefType.Head);
if (m && m.name) {
hasMatchingRemoteBranch[m.name!] = true;
refsContent.push(new Token(remotePart + '/', SemanticTokenTypes.RemoteRefName), new Token(m.name ?? '', SemanticTokenTypes.RefName));

// Determine if local or remote branches are HEADs
let remoteRefTokenType = SemanticTokenTypes.RemoteRefName;
if (defaultBranches && ref.remote && defaultBranches[ref.remote] === namePart) {
remoteRefTokenType = SemanticTokenTypes.RemoteHeadName;
}

let refTokenType = SemanticTokenTypes.RefName;
if (m.name === headName) {
refTokenType = SemanticTokenTypes.HeadName;
}

refsContent.push(new Token(remotePart + '/', remoteRefTokenType), new Token(m.name ?? '', refTokenType));
refsContent.push(' ');
return;
}
Expand All @@ -114,8 +126,13 @@ export default class ViewUtils {

let refTokenType = SemanticTokenTypes.RefName;

if (ref.remote) {
if (ref.name === headName) {
refTokenType = SemanticTokenTypes.HeadName;
} else if (ref.remote) {
refTokenType = SemanticTokenTypes.RemoteRefName;
if (defaultBranches && ref.remote && ref.remote + '/' + defaultBranches[ref.remote] === ref.name) {
refTokenType = SemanticTokenTypes.RemoteHeadName;
}
} else if (ref.type === RefType.Tag) {
refTokenType = SemanticTokenTypes.TagName;
}
Expand All @@ -126,4 +143,4 @@ export default class ViewUtils {

return refsContent;
}
}
}
12 changes: 9 additions & 3 deletions src/views/commitDetailView.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import { DocumentView } from './general/documentView';
import { Uri } from 'vscode';
import { Section } from './general/sectionHeader';
import * as Constants from '../common/constants';
import { TextView } from './general/textView';
import { MagitCommit } from '../models/magitCommit';
import { MagitRepository } from '../models/magitRepository';
import { MagitChange } from '../models/magitChange';
import { ChangeSectionView } from './changes/changesSectionView';

export class CommitDetailView extends DocumentView {

static UriPath: string = 'commit.magit';
isHighlightable = false;
needsUpdate = false;

constructor(uri: Uri, public commit: MagitCommit, diff: string) {
constructor(uri: Uri, public commit: MagitCommit, header: string, diffChanges: MagitChange[]) {
super(uri);

const commitTextView = new TextView(diff);
commitTextView.isHighlightable = false;
const commitTextView = new ChangeSectionView(Section.Changes, diffChanges);
const headerView = new TextView(header);
headerView.isHighlightable = false;

this.addSubview(headerView);
this.addSubview(commitTextView);
}

Expand Down
9 changes: 8 additions & 1 deletion src/views/general/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,11 @@ export abstract class View {
addSubview(...views: View[]) {
this.subViews.push(...views);
}
}

*walkAllSubViews(): Generator<View> {
for (let subView of this.subViews) {
yield subView;
yield* subView.walkAllSubViews();
}
}
}
24 changes: 10 additions & 14 deletions src/views/logView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@ import { DocumentView } from './general/documentView';
import { TextView } from './general/textView';
import { Token } from './general/semanticTextView';
import { SemanticTokenTypes } from '../common/constants';
import { Ref, RefType } from '../typings/git';
import ViewUtils from '../utils/viewUtils';
import { MagitRemote } from '../models/magitRemote';

export default class LogView extends DocumentView {

static UriPath: string = 'log.magit';

constructor(uri: Uri, log: MagitLog) {
constructor(uri: Uri, log: MagitLog, magitState: MagitRepository, defaultBranches?: { [remoteName: string]: string }) {
super(uri);
const refs = magitState.remotes.reduce((prev, remote) => remote.branches.concat(prev), magitState.branches.concat(magitState.tags));

this.subViews = [
new TextView(`Commits in ${log.revName}`),
...log.entries.map(entry => new CommitLongFormItemView(entry)),
...log.entries.map(entry => new CommitLongFormItemView(entry, refs, magitState.HEAD?.name, defaultBranches)),
];
}

Expand All @@ -34,8 +38,8 @@ export default class LogView extends DocumentView {

export class CommitLongFormItemView extends CommitItemView {

constructor(public logEntry: MagitLogEntry) {
super(logEntry.commit);
constructor(public logEntry: MagitLogEntry, refs?: Ref[], headName?: string, defaultBranches?: { [remoteName: string]: string }) {
super(logEntry.commit, undefined, refs);

const timeDistance = formatDistanceToNowStrict(logEntry.time);
const hash = `${GitTextUtils.shortHash(logEntry.commit.hash)} `;
Expand All @@ -46,16 +50,8 @@ export class CommitLongFormItemView extends CommitItemView {
const msg = GitTextUtils.shortCommitMessage(logEntry.commit.message);
this.content.push(`${hash}${graph}`);

const refTokens: Token[] = logEntry.refs.map(ref => new Token(ref, SemanticTokenTypes.RefName));
if (refTokens.length) {

this.content.push(' (');
refTokens.forEach(refToken => {
this.content.push(refToken, ' ');
});
this.content.pop();

this.content.push(') ');
if (logEntry.refs.length) {
this.content.push(...ViewUtils.generateRefTokensLine(logEntry.commit.hash, refs, headName, defaultBranches));
}

const availableMsgWidth = 70 - this.content.reduce((prev, v) => prev + v.length, 0);
Expand Down

0 comments on commit 9a12bc3

Please sign in to comment.