Skip to content

Commit c077c67

Browse files
committed
Adds AI-powered explanation for unpushed branch changes on Graph View
Also adds more item context for new AI-assisted commands to explain unpushed changes (#4443, #4522)
1 parent b221e58 commit c077c67

File tree

6 files changed

+70
-9
lines changed

6 files changed

+70
-9
lines changed

contributions.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,19 @@
113113
]
114114
}
115115
},
116+
"gitlens.ai.explainUnpushed:graph": {
117+
"label": "Explain Unpushed Changes (Preview)",
118+
"icon": "$(sparkle)",
119+
"menus": {
120+
"webview/context": [
121+
{
122+
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+ahead\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
123+
"group": "1_gitlens_ai",
124+
"order": 20
125+
}
126+
]
127+
}
128+
},
116129
"gitlens.ai.explainWip": {
117130
"label": "Explain Working Changes (Preview)...",
118131
"commandPalette": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6234,6 +6234,11 @@
62346234
"title": "Explain Changes (Preview)",
62356235
"icon": "$(sparkle)"
62366236
},
6237+
{
6238+
"command": "gitlens.ai.explainUnpushed:graph",
6239+
"title": "Explain Unpushed Changes (Preview)",
6240+
"icon": "$(sparkle)"
6241+
},
62376242
{
62386243
"command": "gitlens.ai.explainWip",
62396244
"title": "Explain Working Changes (Preview)...",
@@ -11040,6 +11045,10 @@
1104011045
"command": "gitlens.ai.explainStash:views",
1104111046
"when": "false"
1104211047
},
11048+
{
11049+
"command": "gitlens.ai.explainUnpushed:graph",
11050+
"when": "false"
11051+
},
1104311052
{
1104411053
"command": "gitlens.ai.explainWip",
1104511054
"when": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
@@ -23339,6 +23348,11 @@
2333923348
"when": "webviewItem =~ /gitlens:branch\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
2334023349
"group": "1_gitlens_ai@10"
2334123350
},
23351+
{
23352+
"command": "gitlens.ai.explainUnpushed:graph",
23353+
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+ahead\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
23354+
"group": "1_gitlens_ai@20"
23355+
},
2334223356
{
2334323357
"command": "gitlens.graph.openBranchOnRemote",
2334423358
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+(tracking|remote)\\b)/ && gitlens:repos:withRemotes",

src/commands/explainBranch.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { ExplainCommandBase } from './explainBase';
1616

1717
export interface ExplainBranchCommandArgs extends ExplainBaseArgs {
1818
ref?: string;
19+
baseBranch?: string;
1920
}
2021

2122
@command()
@@ -67,15 +68,25 @@ export class ExplainBranchCommand extends ExplainCommandBase {
6768
}
6869

6970
// Clarifying the base branch
70-
const baseBranchNameResult = await getBranchMergeTargetName(this.container, branch);
7171
let baseBranch;
72-
if (!baseBranchNameResult.paused) {
73-
baseBranch = await svc.branches.getBranch(baseBranchNameResult.value);
74-
}
75-
76-
if (!baseBranch) {
77-
void showGenericErrorMessage(`Unable to find the base branch for branch ${branch.name}.`);
78-
return;
72+
if (args.baseBranch) {
73+
// Use the provided base branch
74+
baseBranch = await svc.branches.getBranch(args.baseBranch);
75+
if (!baseBranch) {
76+
void showGenericErrorMessage(`Unable to find the specified base branch: ${args.baseBranch}`);
77+
return;
78+
}
79+
} else {
80+
// Fall back to automatic merge target detection
81+
const baseBranchNameResult = await getBranchMergeTargetName(this.container, branch);
82+
if (!baseBranchNameResult.paused) {
83+
baseBranch = await svc.branches.getBranch(baseBranchNameResult.value);
84+
}
85+
86+
if (!baseBranch) {
87+
void showGenericErrorMessage(`Unable to find the base branch for branch ${branch.name}.`);
88+
return;
89+
}
7990
}
8091

8192
// Get the diff between the branch and its upstream or base

src/constants.commands.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type ContributedCommands =
1010
| 'gitlens.ai.explainCommit:views'
1111
| 'gitlens.ai.explainStash:graph'
1212
| 'gitlens.ai.explainStash:views'
13+
| 'gitlens.ai.explainUnpushed:graph'
1314
| 'gitlens.ai.explainWip:graph'
1415
| 'gitlens.ai.explainWip:views'
1516
| 'gitlens.ai.feedback.helpful'

src/env/node/git/sub-providers/graph.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,9 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
356356
: branchIdOfMainWorktree === branchId
357357
? '+checkedout'
358358
: ''
359-
}${branch?.starred ? '+starred' : ''}`,
359+
}${branch?.starred ? '+starred' : ''}${branch?.upstream?.state.ahead ? '+ahead' : ''}${
360+
branch?.upstream?.state.behind ? '+behind' : ''
361+
}`,
360362
webviewItemValue: {
361363
type: 'branch',
362364
ref: createReference(tip, repoPath, {

src/webviews/plus/graph/graphWebview.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
706706
this.copyWorkingChangesToWorktree,
707707
),
708708
this.host.registerWebviewCommand('gitlens.ai.generateCommitMessage:graph', this.generateCommitMessage),
709+
this.host.registerWebviewCommand('gitlens.ai.explainUnpushed:graph', this.aiExplainUnpushed),
709710
this.host.registerWebviewCommand('gitlens.ai.explainBranch:graph', this.explainBranch),
710711
this.host.registerWebviewCommand('gitlens.ai.explainCommit:graph', this.explainCommit),
711712
this.host.registerWebviewCommand('gitlens.ai.explainStash:graph', this.explainStash),
@@ -3897,6 +3898,25 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
38973898
});
38983899
}
38993900

3901+
@log()
3902+
private aiExplainUnpushed(item?: GraphItemContext) {
3903+
if (isGraphItemRefContext(item, 'branch')) {
3904+
const { ref } = item.webviewItemValue;
3905+
3906+
if (!ref.upstream) {
3907+
return Promise.resolve();
3908+
}
3909+
3910+
return executeCommand<ExplainBranchCommandArgs>('gitlens.ai.explainBranch', {
3911+
repoPath: ref.repoPath,
3912+
ref: ref.ref,
3913+
baseBranch: ref.upstream.name,
3914+
source: { source: 'graph', context: { type: 'branch' } },
3915+
});
3916+
}
3917+
3918+
return Promise.resolve();
3919+
}
39003920
@log()
39013921
private explainBranch(item?: GraphItemContext) {
39023922
const ref = this.getGraphItemRef(item, 'branch');

0 commit comments

Comments
 (0)