-
Notifications
You must be signed in to change notification settings - Fork 314
/
index.ts
252 lines (227 loc) · 8.01 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
import {
ILayoutRestorer,
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';
import {
Dialog,
showErrorMessage,
Toolbar,
ICommandPalette
} from '@jupyterlab/apputils';
import { IChangedArgs } from '@jupyterlab/coreutils';
import { IDocumentManager } from '@jupyterlab/docmanager';
import { FileBrowserModel, IFileBrowserFactory } from '@jupyterlab/filebrowser';
import { IMainMenu } from '@jupyterlab/mainmenu';
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { IStatusBar } from '@jupyterlab/statusbar';
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
import {
addCommands,
addFileBrowserContextMenu,
createGitMenu
} from './commandsAndMenu';
import { createNotebookDiff } from './components/diff/NotebookDiff';
import { addStatusBarWidget } from './components/StatusWidget';
import { GitExtension } from './model';
import { getServerSettings } from './server';
import { gitIcon } from './style/icons';
import { CommandIDs, Git, IGitExtension } from './tokens';
import { addCloneButton } from './widgets/gitClone';
import { GitWidget } from './widgets/GitWidget';
import { gitCloneCommandPlugin } from './cloneCommand';
export { DiffModel } from './components/diff/model';
export { NotebookDiff } from './components/diff/NotebookDiff';
export { PlainTextDiff } from './components/diff/PlainTextDiff';
export { Git, IGitExtension } from './tokens';
export { logger, LoggerContext } from './logger';
/**
* The default running sessions extension.
*/
const plugin: JupyterFrontEndPlugin<IGitExtension> = {
id: '@jupyterlab/git:plugin',
requires: [
IMainMenu,
ILayoutRestorer,
IFileBrowserFactory,
IRenderMimeRegistry,
ISettingRegistry,
IDocumentManager,
IStatusBar,
ICommandPalette,
ITranslator
],
provides: IGitExtension,
activate,
autoStart: true
};
/**
* Export the plugin as default.
*/
export default [plugin, gitCloneCommandPlugin];
/**
* Activate the running plugin.
*/
async function activate(
app: JupyterFrontEnd,
mainMenu: IMainMenu,
restorer: ILayoutRestorer,
factory: IFileBrowserFactory,
renderMime: IRenderMimeRegistry,
settingRegistry: ISettingRegistry,
docmanager: IDocumentManager,
statusBar: IStatusBar,
palette: ICommandPalette,
translator?: ITranslator
): Promise<IGitExtension> {
let gitExtension: GitExtension | null = null;
let settings: ISettingRegistry.ISettings;
let serverSettings: Git.IServerSettings;
// Get a reference to the default file browser extension
// We don't use the current tracked browser because extension like jupyterlab-github
// or jupyterlab-gitlab are defining new filebrowsers that we don't support.
// And it is unlikely that another browser than the default will be used.
// Ref: https://github.com/jupyterlab/jupyterlab-git/issues/1014
const fileBrowser = factory.defaultBrowser;
translator = translator || nullTranslator;
const trans = translator.load('jupyterlab_git');
// Attempt to load application settings
try {
settings = await settingRegistry.load(plugin.id);
} catch (error) {
console.error(
trans.__('Failed to load settings for the Git Extension.\n%1', error)
);
}
try {
serverSettings = await getServerSettings(trans);
const { frontendVersion, gitVersion, serverVersion } = serverSettings;
// Version validation
if (!gitVersion) {
throw new Error(
trans.__(
'git command not found - please ensure you have Git > 2 installed'
)
);
} else {
const gitVersion_ = gitVersion.split('.');
if (Number.parseInt(gitVersion_[0]) < 2) {
throw new Error(
trans.__('git command version must be > 2; got %1.', gitVersion)
);
}
}
if (frontendVersion && frontendVersion !== serverVersion) {
throw new Error(
trans.__(
'The versions of the JupyterLab Git server frontend and backend do not match. ' +
'The @jupyterlab/git frontend extension has version: %1 ' +
'while the python package has version %2. ' +
'Please install identical version of jupyterlab-git Python package and the @jupyterlab/git extension. Try running: pip install --upgrade jupyterlab-git',
frontendVersion,
serverVersion
)
);
}
} catch (error) {
// If we fall here, nothing will be loaded in the frontend.
console.error(
trans.__('Failed to load the jupyterlab-git server extension settings'),
error
);
showErrorMessage(
trans.__('Failed to load the jupyterlab-git server extension'),
error.message,
[Dialog.warnButton({ label: trans.__('Dismiss') })]
);
return null;
}
// Create the Git model
gitExtension = new GitExtension(docmanager, app.docRegistry, settings);
// Whenever we restore the application, sync the Git extension path
Promise.all([app.restored, fileBrowser.model.restored]).then(() => {
gitExtension.pathRepository = fileBrowser.model.path;
});
const onPathChanged = (
model: FileBrowserModel,
change: IChangedArgs<string>
) => {
gitExtension.pathRepository = change.newValue;
gitExtension.refreshBranch();
};
// Whenever the file browser path changes, sync the Git extension path
fileBrowser.model.pathChanged.connect(onPathChanged);
const refreshBrowser = () => {
fileBrowser.model.refresh();
};
// Whenever the `HEAD` of the Git repository changes, refresh the file browser
gitExtension.headChanged.connect(refreshBrowser);
// Whenever a user adds/renames/saves/deletes/modifies a file within the lab environment, refresh the Git status
app.serviceManager.contents.fileChanged.connect(() =>
gitExtension.refreshStatus()
);
// Provided we were able to load application settings, create the extension widgets
if (settings) {
// Add JupyterLab commands
addCommands(app, gitExtension, fileBrowser.model, settings, translator);
// Create the Git widget sidebar
const gitPlugin = new GitWidget(
gitExtension,
settings,
app.commands,
fileBrowser.model,
trans
);
gitPlugin.id = 'jp-git-sessions';
gitPlugin.title.icon = gitIcon;
gitPlugin.title.caption = 'Git';
// Add the commands to the command palette
const category = 'Git Operations';
[
CommandIDs.gitToggleSimpleStaging,
CommandIDs.gitToggleDoubleClickDiff,
CommandIDs.gitOpenGitignore,
CommandIDs.gitShowDiff,
CommandIDs.gitInit,
CommandIDs.gitClone,
CommandIDs.gitMerge,
CommandIDs.gitPush,
CommandIDs.gitPull,
CommandIDs.gitResetToRemote,
CommandIDs.gitManageRemote,
CommandIDs.gitTerminalCommand
].forEach(command => palette.addItem({ command, category }));
// Let the application restorer track the running panel for restoration of
// application state (e.g. setting the running panel as the current side bar
// widget).
restorer.add(gitPlugin, 'git-sessions');
// Rank has been chosen somewhat arbitrarily to give priority to the running
// sessions widget in the sidebar.
app.shell.add(gitPlugin, 'left', { rank: 200 });
// Add a menu for the plugin
if (app.version.split('.').slice(0, 2).join('.') < '3.1') {
// Support JLab 3.0
mainMenu.addMenu(createGitMenu(app.commands, trans), { rank: 60 });
}
// Add a clone button to the file browser extension toolbar
addCloneButton(gitExtension, fileBrowser, app.commands, trans);
// Add the status bar widget
addStatusBarWidget(statusBar, gitExtension, settings, trans);
// Add the context menu items for the default file browser
addFileBrowserContextMenu(
gitExtension,
fileBrowser,
app.contextMenu,
trans
);
}
// Register diff providers
gitExtension.registerDiffProvider(
'Nbdime',
['.ipynb'],
(model: Git.Diff.IModel, toolbar?: Toolbar, translator?: ITranslator) =>
createNotebookDiff(model, renderMime, toolbar, translator)
);
return gitExtension;
}