Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Adds [Cursor](https://cursor.so) support — closes [#3222](https://github.com/gitkraken/vscode-gitlens/issues/3222)
- Adds monospace formatting in commit messages — closes [#2350](https://github.com/gitkraken/vscode-gitlens/issues/2350)
- Adds a new `${authorFirst}` and `${authorLast}` commit formatting tokens that can be used in inline blame, commit hovers, etc — closes [#2980](https://github.com/gitkraken/vscode-gitlens/issues/2980)
- Adds a way to force push from the Graph

### Changed

Expand Down
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8825,6 +8825,13 @@
"icon": "$(gitlens-repo-pull)",
"enablement": "!operationInProgress"
},
{
"command": "gitlens.graph.pushWithForce",
"title": "Push (force)",
"category": "GitLens",
"icon": "$(gitlens-repo-force-push)",
"enablement": "!operationInProgress"
},
{
"command": "gitlens.graph.fetch",
"title": "Fetch",
Expand Down Expand Up @@ -11995,6 +12002,10 @@
"command": "gitlens.graph.pull",
"when": "false"
},
{
"command": "gitlens.graph.pushWithForce",
"when": "false"
},
{
"command": "gitlens.graph.fetch",
"when": "false"
Expand Down
2 changes: 1 addition & 1 deletion src/commands/git/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ export class PullGitCommand extends QuickCommand<State> {
state.flags = result;
}

await this.execute(state as PullStepState);
endSteps(state);
void this.execute(state as PullStepState);
}

return state.counter < 0 ? StepResultBreak : undefined;
Expand Down
10 changes: 8 additions & 2 deletions src/plus/webviews/graph/graphWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
this.host.registerWebviewCommand('gitlens.graph.push', this.push),
this.host.registerWebviewCommand('gitlens.graph.pull', this.pull),
this.host.registerWebviewCommand('gitlens.graph.fetch', this.fetch),
this.host.registerWebviewCommand('gitlens.graph.pushWithForce', this.forcePush),
this.host.registerWebviewCommand('gitlens.graph.publishBranch', this.publishBranch),
this.host.registerWebviewCommand('gitlens.graph.switchToAnotherBranch', this.switchToAnother),

Expand Down Expand Up @@ -2855,16 +2856,21 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
void RepoActions.fetch(this.repository, ref);
}

@log()
private forcePush(item?: GraphItemContext) {
this.push(item, true);
}

@log()
private pull(item?: GraphItemContext) {
const ref = item != null ? this.getGraphItemRef(item, 'branch') : undefined;
void RepoActions.pull(this.repository, ref);
}

@log()
private push(item?: GraphItemContext) {
private push(item?: GraphItemContext, force?: boolean) {
const ref = item != null ? this.getGraphItemRef(item) : undefined;
void RepoActions.push(this.repository, undefined, ref);
void RepoActions.push(this.repository, force, ref);
}

@log()
Expand Down
149 changes: 7 additions & 142 deletions src/webviews/apps/plus/graph/GraphWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ import {
} from '../../../../plus/webviews/graph/protocol';
import { createCommandLink } from '../../../../system/commands';
import { filterMap, first, groupByFilterMap, join } from '../../../../system/iterable';
import { pluralize } from '../../../../system/string';
import { createWebviewCommandLink } from '../../../../system/webview';
import type { IpcNotification } from '../../../protocol';
import { DidChangeHostWindowFocusNotification } from '../../../protocol';
Expand All @@ -86,6 +85,7 @@ import { GlSearchBox } from '../../shared/components/search/react';
import type { SearchNavigationEventDetail } from '../../shared/components/search/search-box';
import type { DateTimeFormat } from '../../shared/date';
import { formatDate, fromNow } from '../../shared/date';
import { GitActionsButtons } from './actions/gitActionsButtons';
import { GlGraphHover } from './hover/graphHover.react';
import type { GraphMinimapDaySelectedEventDetail } from './minimap/minimap';
import { GlGraphMinimapContainer } from './minimap/minimap-container.react';
Expand Down Expand Up @@ -991,146 +991,6 @@ export function GraphWrapper({
onChangeSelection?.(rows);
};

const renderFetchAction = () => {
let action: 'fetch' | 'pull' | 'push' = 'fetch';
let icon = 'repo-fetch';
let label = 'Fetch';
let isBehind = false;
let isAhead = false;

const remote = branchState?.upstream ? (
<>
<span className="md-code">{branchState?.upstream}</span>
</>
) : (
'remote'
);

let tooltip;
if (branchState) {
isAhead = branchState.ahead > 0;
isBehind = branchState.behind > 0;

const branchPrefix = (
<>
<span className="md-code">{branchName}</span> is
</>
);

if (isBehind) {
action = 'pull';
icon = 'repo-pull';
label = 'Pull';
tooltip = (
<>
Pull {pluralize('commit', branchState.behind)} from {remote}
{branchState.provider?.name ? ` on ${branchState.provider?.name}` : ''}
</>
);
if (isAhead) {
tooltip = (
<>
{tooltip}
<hr />
{branchPrefix} {pluralize('commit', branchState.behind)} behind and{' '}
{pluralize('commit', branchState.ahead)} ahead of {remote}
{branchState.provider?.name ? ` on ${branchState.provider?.name}` : ''}
</>
);
} else {
tooltip = (
<>
{tooltip}
<hr />
{branchPrefix} {pluralize('commit', branchState.behind)} behind {remote}
{branchState.provider?.name ? ` on ${branchState.provider?.name}` : ''}
</>
);
}
} else if (isAhead) {
action = 'push';
icon = 'repo-push';
label = 'Push';
tooltip = (
<>
Push {pluralize('commit', branchState.ahead)} to {remote}
{branchState.provider?.name ? ` on ${branchState.provider?.name}` : ''}
<hr />
{branchPrefix} {pluralize('commit', branchState.ahead)} ahead of {remote}
</>
);
}
}

const lastFetchedDate = lastFetched && new Date(lastFetched);
const fetchedText = lastFetchedDate && lastFetchedDate.getTime() !== 0 ? fromNow(lastFetchedDate) : undefined;

return (
<>
{(isBehind || isAhead) && (
<GlTooltip placement="bottom">
<a
href={createWebviewCommandLink(
`gitlens.graph.${action}`,
state.webviewId,
state.webviewInstanceId,
)}
className={`action-button${isBehind ? ' is-behind' : ''}${isAhead ? ' is-ahead' : ''}`}
>
<span className={`glicon glicon-${icon} action-button__icon`}></span>
{label}
{(isAhead || isBehind) && (
<span>
<span className="pill action-button__pill">
{isBehind && (
<span>
{branchState!.behind}
<span className="codicon codicon-arrow-down"></span>
</span>
)}
{isAhead && (
<span>
{isBehind && <>&nbsp;&nbsp;</>}
{branchState!.ahead}
<span className="codicon codicon-arrow-up"></span>
</span>
)}
</span>
</span>
)}
</a>
<div slot="content" style={{ whiteSpace: 'break-spaces' }}>
{tooltip}
{fetchedText && (
<>
<hr /> Last fetched {fetchedText}
</>
)}
</div>
</GlTooltip>
)}
<GlTooltip placement="bottom">
<a
href={createWebviewCommandLink('gitlens.graph.fetch', state.webviewId, state.webviewInstanceId)}
className="action-button"
>
<span className="glicon glicon-repo-fetch action-button__icon"></span>
Fetch {fetchedText && <span className="action-button__small">({fetchedText})</span>}
</a>
<span slot="content" style={{ whiteSpace: 'break-spaces' }}>
Fetch from {remote}
{branchState?.provider?.name ? ` on ${branchState.provider?.name}` : ''}
{fetchedText && (
<>
<hr /> Last fetched {fetchedText}
</>
)}
</span>
</GlTooltip>
</>
);
};

return (
<>
<header className="titlebar graph-app__header">
Expand Down Expand Up @@ -1274,7 +1134,12 @@ export function GraphWrapper({
<span>
<span className="codicon codicon-chevron-right"></span>
</span>
{renderFetchAction()}
<GitActionsButtons
branchName={branchName}
branchState={branchState}
lastFetched={lastFetched}
state={state}
/>
</>
)}
</div>
Expand Down
38 changes: 38 additions & 0 deletions src/webviews/apps/plus/graph/actions/fetchButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { ReactNode } from 'react';
import React from 'react';
import type { BranchState, State } from '../../../../../plus/webviews/graph/protocol';
import { createWebviewCommandLink } from '../../../../../system/webview';
import { GlTooltip } from '../../../shared/components/overlays/tooltip.react';

export const FetchButton = ({
state,
fetchedText,
branchState,
remote,
}: {
branchState: BranchState | undefined;
state: State;
fetchedText: string | undefined;
remote: ReactNode;
}) => {
return (
<GlTooltip placement="bottom">
<a
href={createWebviewCommandLink('gitlens.graph.fetch', state.webviewId, state.webviewInstanceId)}
className="action-button"
>
<span className="glicon glicon-repo-fetch action-button__icon"></span>
Fetch {fetchedText && <span className="action-button__small">({fetchedText})</span>}
</a>
<span slot="content" style={{ whiteSpace: 'break-spaces' }}>
Fetch from {remote}
{branchState?.provider?.name ? ` on ${branchState.provider?.name}` : ''}
{fetchedText && (
<>
<hr /> Last fetched {fetchedText}
</>
)}
</span>
</GlTooltip>
);
};
35 changes: 35 additions & 0 deletions src/webviews/apps/plus/graph/actions/gitActionsButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import type { BranchState, State } from '../../../../../plus/webviews/graph/protocol';
import { fromNow } from '../../../../../system/date';
import { FetchButton } from './fetchButton';
import { PushPullButton } from './pushPullButton';

export const GitActionsButtons = ({
branchState,
branchName,
lastFetched,
state,
}: {
branchState: BranchState | undefined;
branchName: string | undefined;
lastFetched: Date | undefined;
state: State;
}) => {
const remote = branchState?.upstream ? <span className="md-code">{branchState?.upstream}</span> : 'remote';

const lastFetchedDate = lastFetched && new Date(lastFetched);
const fetchedText = lastFetchedDate && lastFetchedDate.getTime() !== 0 ? fromNow(lastFetchedDate) : undefined;

return (
<>
<PushPullButton
branchState={branchState}
state={state}
fetchedText={fetchedText}
branchName={branchName}
remote={remote}
/>
<FetchButton branchState={branchState} fetchedText={fetchedText} remote={remote} state={state} />
</>
);
};
Loading
Loading