Skip to content

Commit cd2f97f

Browse files
authored
Backport PR #699 on branch 0.11.x (#702)
* Merge pull request #699
1 parent 1175534 commit cd2f97f

File tree

5 files changed

+155
-91
lines changed

5 files changed

+155
-91
lines changed

src/components/Toolbar.tsx

Lines changed: 9 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
22
import { classes } from 'typestyle';
3-
import { Dialog, showDialog } from '@jupyterlab/apputils';
43
import { PathExt } from '@jupyterlab/coreutils';
54

65
import {
@@ -23,52 +22,9 @@ import {
2322
toolbarMenuWrapperClass,
2423
toolbarNavClass
2524
} from '../style/Toolbar';
26-
import { GitCredentialsForm } from '../widgets/CredentialsBox';
27-
import { GitPullPushDialog, Operation } from '../widgets/gitPushPull';
2825
import { IGitExtension } from '../tokens';
2926
import { BranchMenu } from './BranchMenu';
30-
31-
/**
32-
* Displays an error dialog when a Git operation fails.
33-
*
34-
* @private
35-
* @param model - Git extension model
36-
* @param operation - Git operation name
37-
* @returns Promise for displaying a dialog
38-
*/
39-
async function showGitOperationDialog(
40-
model: IGitExtension,
41-
operation: Operation
42-
): Promise<void> {
43-
const title = `Git ${operation}`;
44-
let result = await showDialog({
45-
title: title,
46-
body: new GitPullPushDialog(model, operation),
47-
buttons: [Dialog.okButton({ label: 'DISMISS' })]
48-
});
49-
let retry = false;
50-
while (!result.button.accept) {
51-
const credentials = await showDialog({
52-
title: 'Git credentials required',
53-
body: new GitCredentialsForm(
54-
'Enter credentials for remote repository',
55-
retry ? 'Incorrect username or password.' : ''
56-
),
57-
buttons: [Dialog.cancelButton(), Dialog.okButton({ label: 'OK' })]
58-
});
59-
60-
if (!credentials.button.accept) {
61-
break;
62-
}
63-
64-
result = await showDialog({
65-
title: title,
66-
body: new GitPullPushDialog(model, operation, credentials.value),
67-
buttons: [Dialog.okButton({ label: 'DISMISS' })]
68-
});
69-
retry = true;
70-
}
71-
}
27+
import { CommandIDs } from '../gitMenuCommands';
7228

7329
/**
7430
* Interface describing component properties.
@@ -326,11 +282,10 @@ export class Toolbar extends React.Component<IToolbarProps, IToolbarState> {
326282
* @param event - event object
327283
*/
328284
private _onPullClick = (): void => {
329-
showGitOperationDialog(this.props.model, Operation.Pull).catch(reason => {
330-
console.error(
331-
`Encountered an error when pulling changes. Error: ${reason}`
332-
);
333-
});
285+
const commands = this.props.model.commands;
286+
if (commands) {
287+
commands.execute(CommandIDs.gitPull);
288+
}
334289
};
335290

336291
/**
@@ -339,11 +294,10 @@ export class Toolbar extends React.Component<IToolbarProps, IToolbarState> {
339294
* @param event - event object
340295
*/
341296
private _onPushClick = (): void => {
342-
showGitOperationDialog(this.props.model, Operation.Push).catch(reason => {
343-
console.error(
344-
`Encountered an error when pushing changes. Error: ${reason}`
345-
);
346-
});
297+
const commands = this.props.model.commands;
298+
if (commands) {
299+
commands.execute(CommandIDs.gitPush);
300+
}
347301
};
348302

349303
/**

src/gitMenuCommands.ts

Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { FileBrowser } from '@jupyterlab/filebrowser';
1111
import { ITerminal } from '@jupyterlab/terminal';
1212
import { IGitExtension } from './tokens';
1313
import { doGitClone } from './widgets/gitClone';
14+
import { GitPullPushDialog, Operation } from './widgets/gitPushPull';
15+
import { GitCredentialsForm } from './widgets/CredentialsBox';
1416

1517
/**
1618
* The command IDs used by the git plugin.
@@ -24,6 +26,8 @@ export namespace CommandIDs {
2426
export const gitToggleDoubleClickDiff = 'git:toggle-double-click-diff';
2527
export const gitAddRemote = 'git:add-remote';
2628
export const gitClone = 'git:clone';
29+
export const gitPush = 'git:push';
30+
export const gitPull = 'git:pull';
2731
}
2832

2933
/**
@@ -63,7 +67,8 @@ export function addCommands(
6367
console.error(e);
6468
main.dispose();
6569
}
66-
}
70+
},
71+
isEnabled: () => model.pathRepository !== null
6772
});
6873

6974
/** Add open/go to git interface command */
@@ -81,8 +86,8 @@ export function addCommands(
8186

8287
/** Add git init command */
8388
commands.addCommand(CommandIDs.gitInit, {
84-
label: 'Init',
85-
caption: ' Create an empty Git repository or reinitialize an existing one',
89+
label: 'Initialize a Repository',
90+
caption: 'Create an empty Git repository or reinitialize an existing one',
8691
execute: async () => {
8792
const currentPath = fileBrowser.model.path;
8893
const result = await showDialog({
@@ -95,7 +100,8 @@ export function addCommands(
95100
await model.init(currentPath);
96101
model.pathRepository = currentPath;
97102
}
98-
}
103+
},
104+
isEnabled: () => model.pathRepository === null
99105
});
100106

101107
/** Open URL externally */
@@ -127,7 +133,7 @@ export function addCommands(
127133

128134
/** Command to add a remote Git repository */
129135
commands.addCommand(CommandIDs.gitAddRemote, {
130-
label: 'Add remote repository',
136+
label: 'Add Remote Repository',
131137
caption: 'Add a Git remote repository',
132138
isEnabled: () => model.pathRepository !== null,
133139
execute: async args => {
@@ -162,12 +168,90 @@ export function addCommands(
162168

163169
/** Add git clone command */
164170
commands.addCommand(CommandIDs.gitClone, {
165-
label: 'Clone',
171+
label: 'Clone a Repository',
166172
caption: 'Clone a repository from a URL',
167173
isEnabled: () => model.pathRepository === null,
168174
execute: async () => {
169175
await doGitClone(model, fileBrowser.model.path);
170176
fileBrowser.model.refresh();
171177
}
172178
});
179+
180+
/** Add git push command */
181+
commands.addCommand(CommandIDs.gitPush, {
182+
label: 'Push to Remote',
183+
caption: 'Push code to remote repository',
184+
isEnabled: () => model.pathRepository !== null,
185+
execute: async () => {
186+
await Private.showGitOperationDialog(model, Operation.Push).catch(
187+
reason => {
188+
console.error(
189+
`Encountered an error when pushing changes. Error: ${reason}`
190+
);
191+
}
192+
);
193+
}
194+
});
195+
196+
/** Add git pull command */
197+
commands.addCommand(CommandIDs.gitPull, {
198+
label: 'Pull from Remote',
199+
caption: 'Pull latest code from remote repository',
200+
isEnabled: () => model.pathRepository !== null,
201+
execute: async () => {
202+
await Private.showGitOperationDialog(model, Operation.Pull).catch(
203+
reason => {
204+
console.error(
205+
`Encountered an error when pulling changes. Error: ${reason}`
206+
);
207+
}
208+
);
209+
}
210+
});
211+
}
212+
213+
/* eslint-disable no-inner-declarations */
214+
namespace Private {
215+
/**
216+
* Displays an error dialog when a Git operation fails.
217+
*
218+
* @private
219+
* @param model - Git extension model
220+
* @param operation - Git operation name
221+
* @returns Promise for displaying a dialog
222+
*/
223+
export async function showGitOperationDialog(
224+
model: IGitExtension,
225+
operation: Operation
226+
): Promise<void> {
227+
const title = `Git ${operation}`;
228+
let result = await showDialog({
229+
title: title,
230+
body: new GitPullPushDialog(model, operation),
231+
buttons: [Dialog.okButton({ label: 'DISMISS' })]
232+
});
233+
let retry = false;
234+
while (!result.button.accept) {
235+
const credentials = await showDialog({
236+
title: 'Git credentials required',
237+
body: new GitCredentialsForm(
238+
'Enter credentials for remote repository',
239+
retry ? 'Incorrect username or password.' : ''
240+
),
241+
buttons: [Dialog.cancelButton(), Dialog.okButton({ label: 'OK' })]
242+
});
243+
244+
if (!credentials.button.accept) {
245+
break;
246+
}
247+
248+
result = await showDialog({
249+
title: title,
250+
body: new GitPullPushDialog(model, operation, credentials.value),
251+
buttons: [Dialog.okButton({ label: 'DISMISS' })]
252+
});
253+
retry = true;
254+
}
255+
}
173256
}
257+
/* eslint-enable no-inner-declarations */

src/index.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,30 +146,34 @@ function createGitMenu(
146146
const menu = new Menu({ commands });
147147
menu.title.label = 'Git';
148148
[
149-
CommandIDs.gitUI,
150-
CommandIDs.gitTerminalCommand,
151149
CommandIDs.gitInit,
152150
CommandIDs.gitClone,
153-
CommandIDs.gitAddRemote
151+
CommandIDs.gitPush,
152+
CommandIDs.gitPull,
153+
CommandIDs.gitAddRemote,
154+
CommandIDs.gitTerminalCommand
154155
].forEach(command => {
155156
menu.addItem({ command });
156157
});
157158

159+
menu.addItem({ type: 'separator' });
160+
161+
menu.addItem({ command: CommandIDs.gitToggleSimpleStaging });
162+
163+
menu.addItem({ command: CommandIDs.gitToggleDoubleClickDiff });
164+
165+
menu.addItem({ type: 'separator' });
166+
158167
const tutorial = new Menu({ commands });
159-
tutorial.title.label = ' Tutorial ';
168+
tutorial.title.label = ' Help ';
160169
RESOURCES.map(args => {
161170
tutorial.addItem({
162171
args,
163172
command: CommandIDs.gitOpenUrl
164173
});
165174
});
166-
menu.addItem({ type: 'submenu', submenu: tutorial });
167-
168-
menu.addItem({ type: 'separator' });
169175

170-
menu.addItem({ command: CommandIDs.gitToggleSimpleStaging });
171-
172-
menu.addItem({ command: CommandIDs.gitToggleDoubleClickDiff });
176+
menu.addItem({ type: 'submenu', submenu: tutorial });
173177

174178
return menu;
175179
}

src/tokens.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { IChangedArgs } from '@jupyterlab/coreutils';
22
import { Token, JSONObject } from '@phosphor/coreutils';
33
import { IDisposable } from '@phosphor/disposable';
44
import { ISignal } from '@phosphor/signaling';
5+
import { CommandRegistry } from '@phosphor/commands';
56

67
export const EXTENSION_ID = 'jupyter.extensions.git_plugin';
78

@@ -56,6 +57,8 @@ export interface IGitExtension extends IDisposable {
5657
*/
5758
readonly statusChanged: ISignal<IGitExtension, Git.IStatusFileResult[]>;
5859

60+
readonly commands: CommandRegistry | null;
61+
5962
/**
6063
* Make request to add one or all files into
6164
* the staging area in repository

0 commit comments

Comments
 (0)