Skip to content

Commit 92e22fb

Browse files
committed
feat: add interactive tooltip and catch
1 parent e0ac10f commit 92e22fb

3 files changed

Lines changed: 65 additions & 19 deletions

File tree

app/src/lib/git/config.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -340,24 +340,30 @@ export function getOriginFilePath(
340340
}
341341

342342
/**
343-
* Format a human-readable scope description for a config value origin.
344-
* Detects whether a global-scoped value comes from a standard location
345-
* (~/.gitconfig or ~/.config/git/config) vs. a conditionally included file
346-
* (via includeIf directive).
343+
* Check whether a global-scoped config value comes from a conditionally
344+
* included file (via includeIf directive) rather than a standard location.
347345
*/
348-
export function formatConfigScope(origin: IConfigValueOrigin): string {
346+
export function isConditionalInclude(origin: IConfigValueOrigin): boolean {
347+
if (origin.scope !== 'global') {
348+
return false
349+
}
349350
const filePath = getOriginFilePath(origin)
351+
return (
352+
!/[/\\]\.gitconfig$/i.test(filePath) &&
353+
!/[/\\]\.config[/\\]git[/\\]config$/i.test(filePath)
354+
)
355+
}
356+
357+
/** Format a human-readable scope description for a config value origin. */
358+
export function formatConfigScope(origin: IConfigValueOrigin): string {
350359
if (origin.scope === 'local') {
351360
return 'local'
352361
} else if (origin.scope === 'system') {
353362
return 'system'
354363
} else if (origin.scope === 'worktree') {
355364
return 'worktree'
356365
} else if (origin.scope === 'global') {
357-
const isStandardGlobalPath =
358-
/[/\\]\.gitconfig$/i.test(filePath) ||
359-
/[/\\]\.config[/\\]git[/\\]config$/i.test(filePath)
360-
return isStandardGlobalPath ? 'global' : 'global, via [includeIf]'
366+
return isConditionalInclude(origin) ? 'global, via [includeIf]' : 'global'
361367
}
362368
return origin.scope
363369
}

app/src/ui/changes/commit-message.tsx

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import {
4040
import {
4141
setGlobalConfigValue,
4242
IConfigValueOrigin,
43+
getOriginFilePath,
44+
isConditionalInclude,
4345
formatConfigScope,
4446
formatConfigPath,
4547
} from '../../lib/git/config'
@@ -73,25 +75,26 @@ import {
7375
} from '../../lib/feature-flag'
7476
import { AriaLiveContainer } from '../accessibility/aria-live-container'
7577
import { TooltippedContent } from '../lib/tooltipped-content'
78+
import { showItemInFolder } from '../main-process-proxy'
7679
import { HookProgress } from '../../lib/git'
7780
import { assertNever } from '../../lib/fatal-error'
7881

7982
function renderScopeValue(origin: IConfigValueOrigin): JSX.Element {
80-
const scope = formatConfigScope(origin)
81-
if (scope.includes('includeIf')) {
83+
if (isConditionalInclude(origin)) {
8284
return (
8385
<span>
8486
global, via <em>[includeIf]</em>
8587
</span>
8688
)
8789
}
88-
return <span>{scope}</span>
90+
return <span>{formatConfigScope(origin)}</span>
8991
}
9092

9193
function formatConfigOriginTooltip(
9294
fieldName: string,
9395
origin: IConfigValueOrigin,
94-
repositoryPath: string
96+
repositoryPath: string,
97+
onRevealFile: () => void
9598
): JSX.Element {
9699
return (
97100
<div className="config-origin-tooltip">
@@ -100,7 +103,9 @@ function formatConfigOriginTooltip(
100103
<span className="config-origin-tooltip-label">Scope:</span>
101104
{renderScopeValue(origin)}
102105
<span className="config-origin-tooltip-label">File:</span>
103-
<span>{formatConfigPath(origin, repositoryPath)}</span>
106+
<LinkButton onClick={onRevealFile}>
107+
{formatConfigPath(origin, repositoryPath)}
108+
</LinkButton>
104109
</div>
105110
)
106111
}
@@ -838,10 +843,20 @@ export class CommitMessage extends React.Component<
838843
const { commitAuthorNameOrigin, commitAuthorEmailOrigin } = this.props
839844
const repoPath = this.props.repository.path
840845
const nameTooltip = commitAuthorNameOrigin
841-
? formatConfigOriginTooltip('Name', commitAuthorNameOrigin, repoPath)
846+
? formatConfigOriginTooltip(
847+
'Name',
848+
commitAuthorNameOrigin,
849+
repoPath,
850+
this.onRevealNameConfigFile
851+
)
842852
: undefined
843853
const emailTooltip = commitAuthorEmailOrigin
844-
? formatConfigOriginTooltip('Email', commitAuthorEmailOrigin, repoPath)
854+
? formatConfigOriginTooltip(
855+
'Email',
856+
commitAuthorEmailOrigin,
857+
repoPath,
858+
this.onRevealEmailConfigFile
859+
)
845860
: undefined
846861

847862
return (
@@ -852,13 +867,15 @@ export class CommitMessage extends React.Component<
852867
className="commit-author-name"
853868
tooltip={nameTooltip}
854869
tooltipClassName="config-origin"
870+
interactive={true}
855871
>
856872
{commitAuthor.name}
857873
</TooltippedContent>
858874
<TooltippedContent
859875
className="commit-author-email"
860876
tooltip={emailTooltip}
861877
tooltipClassName="config-origin"
878+
interactive={true}
862879
>
863880
{commitAuthor.email}
864881
</TooltippedContent>
@@ -867,6 +884,24 @@ export class CommitMessage extends React.Component<
867884
)
868885
}
869886

887+
private onRevealNameConfigFile = () => {
888+
const { commitAuthorNameOrigin } = this.props
889+
if (commitAuthorNameOrigin) {
890+
showItemInFolder(
891+
getOriginFilePath(commitAuthorNameOrigin, this.props.repository.path)
892+
)
893+
}
894+
}
895+
896+
private onRevealEmailConfigFile = () => {
897+
const { commitAuthorEmailOrigin } = this.props
898+
if (commitAuthorEmailOrigin) {
899+
showItemInFolder(
900+
getOriginFilePath(commitAuthorEmailOrigin, this.props.repository.path)
901+
)
902+
}
903+
}
904+
870905
private onUpdateUserEmail = async (email: string) => {
871906
await setGlobalConfigValue('user.email', email)
872907
this.props.onRefreshAuthor()

app/src/ui/preferences/preferences.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -933,9 +933,14 @@ export class Preferences extends React.Component<
933933
this.state.initialCommitterName ||
934934
this.state.initialCommitterEmail
935935
) {
936-
// User unchecked the box — remove identity from global config
937-
await removeGlobalConfigValue('user.name')
938-
await removeGlobalConfigValue('user.email')
936+
// User unchecked the box — remove identity from global config.
937+
// Ignore errors if values are already absent.
938+
try {
939+
await removeGlobalConfigValue('user.name')
940+
} catch {}
941+
try {
942+
await removeGlobalConfigValue('user.email')
943+
} catch {}
939944
shouldRefreshAuthor = true
940945
}
941946

0 commit comments

Comments
 (0)