Skip to content

Commit

Permalink
Add 'Discard All and Pull' button (#1020)
Browse files Browse the repository at this point in the history
* Add discard and pull menu item

* Apply suggestions from code review

Co-authored-by: Frédéric Collonval <[email protected]>

* Add missing entry menu in settings description

* Add discard fallback to pull operation

* Remove unused command ids

* Apply suggestions from code review

Co-authored-by: Frédéric Collonval <[email protected]>

* Apply suggestions from code review

* Rename `discard` to `force` to align with `push`

* Hide toast if action cancelled by user

Co-authored-by: Frédéric Collonval <[email protected]>
Co-authored-by: Frédéric Collonval <[email protected]>
  • Loading branch information
3 people authored Nov 11, 2021
1 parent b268a40 commit 7707fc2
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 35 deletions.
8 changes: 8 additions & 0 deletions schema/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,17 @@
{
"command": "git:push"
},
{
"command": "git:push",
"args": { "force": true }
},
{
"command": "git:pull"
},
{
"command": "git:pull",
"args": { "force": true }
},
{
"command": "git:add-remote"
},
Expand Down
67 changes: 54 additions & 13 deletions src/commandsAndMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
Level
} from './tokens';
import { GitCredentialsForm } from './widgets/CredentialsBox';
import { discardAllChanges } from './widgets/discardAllChanges';
import { GitCloneForm } from './widgets/GitCloneForm';

interface IGitCloneArgs {
Expand Down Expand Up @@ -389,15 +390,26 @@ export function addCommands(

/** Add git pull command */
commands.addCommand(CommandIDs.gitPull, {
label: trans.__('Pull from Remote'),
caption: trans.__('Pull latest code from remote repository'),
label: args =>
args.force
? trans.__('Pull from Remote (Force)')
: trans.__('Pull from Remote'),
caption: args =>
args.force
? trans.__(
'Discard all current changes and pull from remote repository'
)
: trans.__('Pull latest code from remote repository'),
isEnabled: () => gitModel.pathRepository !== null,
execute: async () => {
logger.log({
level: Level.RUNNING,
message: trans.__('Pulling…')
});
execute: async args => {
try {
if (args.force) {
await discardAllChanges(gitModel, trans, args.fallback as boolean);
}
logger.log({
level: Level.RUNNING,
message: trans.__('Pulling…')
});
const details = await Private.showGitOperationDialog(
gitModel,
Operation.Pull,
Expand All @@ -413,11 +425,37 @@ export function addCommands(
'Encountered an error when pulling changes. Error: ',
error
);
logger.log({
message: trans.__('Failed to pull'),
level: Level.ERROR,
error: error as Error
});

const errorMsg =
typeof error === 'string' ? error : (error as Error).message;

// Discard changes then retry pull
if (
errorMsg
.toLowerCase()
.includes(
'your local changes to the following files would be overwritten by merge'
)
) {
await commands.execute(CommandIDs.gitPull, {
force: true,
fallback: true
});
} else {
if ((error as any).cancelled) {
// Empty message to hide alert
logger.log({
message: '',
level: Level.INFO
});
} else {
logger.log({
message: trans.__('Failed to pull'),
level: Level.ERROR,
error
});
}
}
}
}
});
Expand Down Expand Up @@ -1155,10 +1193,13 @@ export function createGitMenu(
CommandIDs.gitAddRemote,
CommandIDs.gitTerminalCommand
].forEach(command => {
menu.addItem({ command });
if (command === CommandIDs.gitPush) {
menu.addItem({ command, args: { force: true } });
}
menu.addItem({ command });
if (command === CommandIDs.gitPull) {
menu.addItem({ command, args: { force: true } });
}
});

menu.addItem({ type: 'separator' });
Expand Down
24 changes: 3 additions & 21 deletions src/components/FileList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ContextCommandIDs, CommandIDs, Git } from '../tokens';
import { ActionButton } from './ActionButton';
import { FileItem } from './FileItem';
import { GitStage } from './GitStage';
import { discardAllChanges } from '../widgets/discardAllChanges';

export interface IFileListState {
selectedFile: Git.IStatusFile | null;
Expand Down Expand Up @@ -189,7 +190,7 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
const result = await showDialog({
title: this.props.trans.__('Discard all changes'),
body: this.props.trans.__(
'Are you sure you want to permanently discard changes to all files? This action cannot be undone.'
'Are you sure you want to permanently discard changes to all unstaged files? This action cannot be undone.'
),
buttons: [
Dialog.cancelButton({ label: this.props.trans.__('Cancel') }),
Expand All @@ -211,26 +212,7 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
/** Discard changes in all unstaged and staged files */
discardAllChanges = async (event: React.MouseEvent): Promise<void> => {
event.stopPropagation();
const result = await showDialog({
title: this.props.trans.__('Discard all changes'),
body: this.props.trans.__(
'Are you sure you want to permanently discard changes to all files? This action cannot be undone.'
),
buttons: [
Dialog.cancelButton({ label: this.props.trans.__('Cancel') }),
Dialog.warnButton({ label: this.props.trans.__('Discard') })
]
});
if (result.button.accept) {
try {
await this.props.model.resetToCommit();
} catch (reason) {
showErrorMessage(
this.props.trans.__('Discard all changes failed.'),
reason
);
}
}
await discardAllChanges(this.props.model, this.props.trans);
};

/** Add a specific unstaged file */
Expand Down
1 change: 0 additions & 1 deletion src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,6 @@ export enum CommandIDs {
gitMerge = 'git:merge',
gitOpenGitignore = 'git:open-gitignore',
gitPush = 'git:push',
gitForcePush = 'git:force-push',
gitPull = 'git:pull',
gitSubmitCommand = 'git:submit-commit',
gitShowDiff = 'git:show-diff'
Expand Down
43 changes: 43 additions & 0 deletions src/widgets/discardAllChanges.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { showDialog, Dialog, showErrorMessage } from '@jupyterlab/apputils';
import { TranslationBundle } from '@jupyterlab/translation';
import { IGitExtension } from '../tokens';

/**
* Discard changes in all unstaged and staged files
*
* @param isFallback If dialog is called when the classical pull operation fails
*/
export async function discardAllChanges(
model: IGitExtension,
trans: TranslationBundle,
isFallback?: boolean
): Promise<void> {
const result = await showDialog({
title: trans.__('Discard all changes'),
body: isFallback
? trans.__(
'Your current changes forbid pulling the latest changes. Do you want to permanently discard those changes? This action cannot be undone.'
)
: trans.__(
'Are you sure you want to permanently discard changes to all files? This action cannot be undone.'
),
buttons: [
Dialog.cancelButton({ label: trans.__('Cancel') }),
Dialog.warnButton({ label: trans.__('Discard') })
]
});

if (result.button.accept) {
try {
return model.resetToCommit('HEAD');
} catch (reason) {
showErrorMessage(trans.__('Discard all changes failed.'), reason);
return Promise.reject(reason);
}
}

return Promise.reject({
cancelled: true,
message: 'The user refused to discard all changes'
});
}

0 comments on commit 7707fc2

Please sign in to comment.