From 8c231e46a137f0d1eb898fe7686f4db046a22de2 Mon Sep 17 00:00:00 2001 From: Evan Johnson Date: Sat, 9 Sep 2023 23:06:09 -0600 Subject: [PATCH 1/4] add HEAD semantic token types --- package.json | 16 ++++++++++++++++ src/common/constants.ts | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 484a1bb..50191d5 100644 --- a/package.json +++ b/package.json @@ -453,6 +453,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", @@ -468,6 +478,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" ] diff --git a/src/common/constants.ts b/src/common/constants.ts index c3648ed..4f234d0 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -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', -} \ No newline at end of file +} From 086066aa7d44325753b7876e904b3807913247ef Mon Sep 17 00:00:00 2001 From: Evan Johnson Date: Sat, 9 Sep 2023 23:22:27 -0600 Subject: [PATCH 2/4] add HEAD checking to generateRefTokensLine --- src/utils/viewUtils.ts | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/utils/viewUtils.ts b/src/utils/viewUtils.ts index e1d8bab..614ca61 100644 --- a/src/utils/viewUtils.ts +++ b/src/utils/viewUtils.ts @@ -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) @@ -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; } @@ -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; } @@ -126,4 +143,4 @@ export default class ViewUtils { return refsContent; } -} \ No newline at end of file +} From 6ea7fb5b745708959d910bd3ea891ca9d1296690 Mon Sep 17 00:00:00 2001 From: Evan Johnson Date: Sat, 9 Sep 2023 23:52:07 -0600 Subject: [PATCH 3/4] use generateRefTokensLine in log view --- src/views/logView.ts | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/views/logView.ts b/src/views/logView.ts index 1a2753d..61054ce 100644 --- a/src/views/logView.ts +++ b/src/views/logView.ts @@ -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)), ]; } @@ -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)} `; @@ -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); From 06d81d5cf9aadfb8efacc207e89b157fe8000ce4 Mon Sep 17 00:00:00 2001 From: Evan Johnson Date: Sat, 9 Sep 2023 23:54:44 -0600 Subject: [PATCH 4/4] get default branches on remotes when creating log view --- src/commands/loggingCommands.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/commands/loggingCommands.ts b/src/commands/loggingCommands.ts index b75c628..4ae7ae5 100644 --- a/src/commands/loggingCommands.ts +++ b/src/commands/loggingCommands.ts @@ -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) {