Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit aae4848

Browse files
authored
Merge pull request #2308 from wadethestealth/project-management
Project Management
2 parents 79afbab + 1069fc9 commit aae4848

29 files changed

+790
-396
lines changed

lib/atom/marker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const DecorableContext = React.createContext();
2525
class BareMarker extends React.Component {
2626
static propTypes = {
2727
...markerProps,
28-
id: PropTypes.string,
28+
id: PropTypes.number,
2929
bufferRange: RangePropType,
3030
markableHolder: RefHolderPropType,
3131
children: PropTypes.node,

lib/containers/current-pull-request-container.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ export default class CurrentPullRequestContainer extends React.Component {
3737
aheadCount: PropTypes.number,
3838
pushInProgress: PropTypes.bool.isRequired,
3939

40-
workspace: PropTypes.object.isRequired,
41-
4240
// Actions
4341
onOpenIssueish: PropTypes.func.isRequired,
4442
onOpenReviews: PropTypes.func.isRequired,
@@ -164,7 +162,6 @@ export default class CurrentPullRequestContainer extends React.Component {
164162
total={associatedPullRequests.totalCount}
165163
results={associatedPullRequests.nodes}
166164
isLoading={false}
167-
workspace={this.props.workspace}
168165
endpoint={this.props.endpoint}
169166
resultFilter={issueish => issueish.getHeadRepositoryID() === this.props.repository.id}
170167
{...this.controllerProps()}

lib/containers/github-tab-container.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,18 @@ export default class GitHubTabContainer extends React.Component {
7070
}
7171

7272
if (!this.props.repository.isPresent()) {
73-
// TODO include a better message here.
74-
return null;
73+
return (
74+
<GitHubTabController
75+
{...this.props}
76+
remoteOperationObserver={this.state.remoteOperationObserver}
77+
78+
allRemotes={new RemoteSet()}
79+
branches={new BranchSet()}
80+
aheadCount={0}
81+
pushInProgress={false}
82+
isLoading={false}
83+
/>
84+
);
7585
}
7686

7787
return (

lib/controllers/git-tab-controller.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export default class GitTabController extends React.Component {
3333
workingDirectoryPath: PropTypes.string,
3434
mergeMessage: PropTypes.string,
3535
fetchInProgress: PropTypes.bool.isRequired,
36+
currentWorkDir: PropTypes.string,
3637

3738
workspace: PropTypes.object.isRequired,
3839
commands: PropTypes.object.isRequired,
@@ -51,6 +52,9 @@ export default class GitTabController extends React.Component {
5152
openFiles: PropTypes.func.isRequired,
5253
openInitializeDialog: PropTypes.func.isRequired,
5354
controllerRef: RefHolderPropType,
55+
changeWorkingDirectory: PropTypes.func.isRequired,
56+
onDidChangeWorkDirs: PropTypes.func.isRequired,
57+
getCurrentWorkDirs: PropTypes.func.isRequired,
5458
};
5559

5660
constructor(props, context) {
@@ -99,7 +103,7 @@ export default class GitTabController extends React.Component {
99103
unstagedChanges={this.props.unstagedChanges}
100104
stagedChanges={this.props.stagedChanges}
101105
mergeConflicts={this.props.mergeConflicts}
102-
workingDirectoryPath={this.props.workingDirectoryPath}
106+
workingDirectoryPath={this.props.workingDirectoryPath || this.props.currentWorkDir}
103107
mergeMessage={this.props.mergeMessage}
104108
userStore={this.userStore}
105109
selectedCoAuthors={this.state.selectedCoAuthors}
@@ -119,6 +123,9 @@ export default class GitTabController extends React.Component {
119123
openFiles={this.props.openFiles}
120124
discardWorkDirChangesForPaths={this.props.discardWorkDirChangesForPaths}
121125
undoLastDiscard={this.props.undoLastDiscard}
126+
changeWorkingDirectory={this.props.changeWorkingDirectory}
127+
getCurrentWorkDirs={this.props.getCurrentWorkDirs}
128+
onDidChangeWorkDirs={this.props.onDidChangeWorkDirs}
122129

123130
attemptFileStageOperation={this.attemptFileStageOperation}
124131
attemptStageAllOperation={this.attemptStageAllOperation}

lib/controllers/github-tab-controller.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ export default class GitHubTabController extends React.Component {
2121
aheadCount: PropTypes.number,
2222
pushInProgress: PropTypes.bool.isRequired,
2323
isLoading: PropTypes.bool.isRequired,
24+
currentWorkDir: PropTypes.string,
25+
26+
changeWorkingDirectory: PropTypes.func.isRequired,
27+
onDidChangeWorkDirs: PropTypes.func.isRequired,
28+
getCurrentWorkDirs: PropTypes.func.isRequired,
2429
}
2530

2631
render() {
@@ -42,7 +47,7 @@ export default class GitHubTabController extends React.Component {
4247
loginModel={this.props.loginModel}
4348
rootHolder={this.props.rootHolder}
4449

45-
workingDirectory={this.props.workingDirectory}
50+
workingDirectory={this.props.workingDirectory || this.props.currentWorkDir}
4651
branches={this.props.branches}
4752
currentBranch={currentBranch}
4853
remotes={gitHubRemotes}
@@ -54,6 +59,9 @@ export default class GitHubTabController extends React.Component {
5459

5560
handlePushBranch={this.handlePushBranch}
5661
handleRemoteSelect={this.handleRemoteSelect}
62+
changeWorkingDirectory={this.props.changeWorkingDirectory}
63+
getCurrentWorkDirs={this.props.getCurrentWorkDirs}
64+
onDidChangeWorkDirs={this.props.onDidChangeWorkDirs}
5765
/>
5866
);
5967
}

lib/controllers/issueish-list-controller.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ export class BareIssueishListController extends React.Component {
5656
onOpenMore: PropTypes.func,
5757

5858
emptyComponent: PropTypes.func,
59-
workspace: PropTypes.object,
6059
endpoint: EndpointPropType,
6160
needReviewsButton: PropTypes.bool,
6261
};

lib/controllers/root-controller.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@ export default class RootController extends React.Component {
6060
switchboard: PropTypes.instanceOf(Switchboard),
6161
pipelineManager: PropTypes.object,
6262

63+
currentWorkDir: PropTypes.string,
64+
6365
// Git actions
6466
initialize: PropTypes.func.isRequired,
6567
clone: PropTypes.func.isRequired,
6668

6769
// Control
70+
changeWorkingDirectory: PropTypes.func.isRequired,
6871
startOpen: PropTypes.bool,
6972
startRevealed: PropTypes.bool,
7073
}
@@ -258,6 +261,10 @@ export default class RootController extends React.Component {
258261
}
259262

260263
renderPaneItems() {
264+
const {workdirContextPool} = this.props;
265+
const getCurrentWorkDirs = workdirContextPool.getCurrentWorkDirs.bind(workdirContextPool);
266+
const onDidChangeWorkDirs = workdirContextPool.onDidChangePoolContexts.bind(workdirContextPool);
267+
261268
return (
262269
<Fragment>
263270
<PaneItem
@@ -284,6 +291,10 @@ export default class RootController extends React.Component {
284291
discardWorkDirChangesForPaths={this.discardWorkDirChangesForPaths}
285292
undoLastDiscard={this.undoLastDiscard}
286293
refreshResolutionProgress={this.refreshResolutionProgress}
294+
currentWorkDir={this.props.currentWorkDir}
295+
getCurrentWorkDirs={getCurrentWorkDirs}
296+
onDidChangeWorkDirs={onDidChangeWorkDirs}
297+
changeWorkingDirectory={this.props.changeWorkingDirectory}
287298
/>
288299
)}
289300
</PaneItem>
@@ -297,6 +308,10 @@ export default class RootController extends React.Component {
297308
repository={this.props.repository}
298309
loginModel={this.props.loginModel}
299310
workspace={this.props.workspace}
311+
currentWorkDir={this.props.currentWorkDir}
312+
getCurrentWorkDirs={getCurrentWorkDirs}
313+
onDidChangeWorkDirs={onDidChangeWorkDirs}
314+
changeWorkingDirectory={this.props.changeWorkingDirectory}
300315
/>
301316
)}
302317
</PaneItem>

lib/error-boundary.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
export default class ErrorBoundary extends React.Component {
5+
static propTypes = {
6+
children: PropTypes.node.isRequired,
7+
fallback: PropTypes.any,
8+
};
9+
10+
constructor(props) {
11+
super(props);
12+
this.state = {hasError: false, error: null, errorInfo: null};
13+
}
14+
15+
static getDerivedStateFromError(error) {
16+
// Update state so the next render will show the fallback UI.
17+
return {hasError: true};
18+
}
19+
20+
componentDidCatch(error, errorInfo) {
21+
this.setState({
22+
error,
23+
errorInfo,
24+
});
25+
}
26+
27+
render() {
28+
if (this.state.hasError) {
29+
// You can render any custom fallback UI
30+
return this.props.fallback ? this.props.fallback : null;
31+
}
32+
33+
return this.props.children;
34+
}
35+
}

lib/github-package.js

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,14 @@ export default class GithubPackage {
175175
return !!event.target.closest('.github-FilePatchListView').querySelector('.is-selected');
176176
};
177177

178+
const handleProjectPathsChange = () => {
179+
const activeRepository = this.getActiveRepository();
180+
const activeRepositoryPath = activeRepository ? activeRepository.getWorkingDirectoryPath() : null;
181+
this.scheduleActiveContextUpdate({activeRepositoryPath});
182+
};
183+
178184
this.subscriptions.add(
179-
this.project.onDidChangePaths(this.scheduleActiveContextUpdate),
180-
this.workspace.getCenter().onDidChangeActivePaneItem(this.scheduleActiveContextUpdate),
185+
this.project.onDidChangePaths(handleProjectPathsChange),
181186
this.styleCalculator.startWatching(
182187
'github-package-styles',
183188
['editor.fontSize', 'editor.fontFamily', 'editor.lineHeight', 'editor.tabLength'],
@@ -269,6 +274,10 @@ export default class GithubPackage {
269274
}));
270275
}
271276

277+
const changeWorkingDirectory = workingDirectory => {
278+
this.scheduleActiveContextUpdate({activeRepositoryPath: workingDirectory});
279+
};
280+
272281
this.renderFn(
273282
<RootController
274283
ref={c => { this.controller = c; }}
@@ -294,6 +303,8 @@ export default class GithubPackage {
294303
startOpen={this.startOpen}
295304
startRevealed={this.startRevealed}
296305
removeFilePatchItem={this.removeFilePatchItem}
306+
currentWorkDir={this.getActiveWorkdir()}
307+
changeWorkingDirectory={changeWorkingDirectory}
297308
/>, this.element, callback,
298309
);
299310
}
@@ -495,14 +506,13 @@ export default class GithubPackage {
495506
* Derive the git working directory context that should be used for the package's git operations based on the current
496507
* state of the Atom workspace. In priority, this prefers:
497508
*
498-
* - A git working directory that contains the active pane item in the workspace's center.
499-
* - A git working directory corresponding to a single Project.
500-
* - When initially activating the package, the working directory that was active when the package was last
501-
* serialized.
509+
* - The preferred git working directory set by the user (This is also the working directory that was active when the
510+
* package was last serialized).
511+
* - A git working directory corresponding to "first" Project, whether or not there is a single project or multiple.
502512
* - The current context, unchanged, which may be a `NullWorkdirContext`.
503513
*
504514
* First updates the pool of resident contexts to match all git working directories that correspond to open
505-
* projects and pane items.
515+
* projects.
506516
*/
507517
async getNextContext(savedState) {
508518
const workdirs = new Set(
@@ -514,50 +524,34 @@ export default class GithubPackage {
514524
),
515525
);
516526

517-
const fromPaneItem = async maybeItem => {
518-
const itemPath = pathForPaneItem(maybeItem);
519-
520-
if (!itemPath) {
521-
return {};
522-
}
523-
524-
const itemWorkdir = await this.workdirCache.find(itemPath);
525-
526-
if (itemWorkdir && !this.project.contains(itemPath)) {
527-
workdirs.add(itemWorkdir);
528-
}
529-
530-
return {itemPath, itemWorkdir};
531-
};
532-
533-
const active = await fromPaneItem(this.workspace.getCenter().getActivePaneItem());
534-
527+
// Update pool with the open projects
535528
this.contextPool.set(workdirs, savedState);
536529

537-
if (active.itemPath) {
538-
// Prefer an active item
539-
return this.contextPool.getContext(active.itemWorkdir || active.itemPath);
530+
if (savedState.activeRepositoryPath) {
531+
// Preferred git directory (the preferred directory or the last serialized directory).
532+
const stateContext = this.contextPool.getContext(savedState.activeRepositoryPath);
533+
// If the context exists chose it, else continue.
534+
if (stateContext.isPresent()) {
535+
return stateContext;
536+
}
540537
}
541538

542-
if (this.project.getPaths().length === 1) {
543-
// Single project
544-
const projectPath = this.project.getPaths()[0];
539+
const projectPaths = this.project.getPaths();
540+
541+
if (projectPaths.length >= 1) {
542+
// Single or multiple projects (just choose the first, the user can select after)
543+
const projectPath = projectPaths[0];
545544
const activeWorkingDir = await this.workdirCache.find(projectPath);
546545
return this.contextPool.getContext(activeWorkingDir || projectPath);
547546
}
548547

549-
if (this.project.getPaths().length === 0 && !this.activeContext.getRepository().isUndetermined()) {
548+
if (projectPaths.length === 0 && !this.activeContext.getRepository().isUndetermined()) {
550549
// No projects. Revert to the absent context unless we've guessed that more projects are on the way.
551550
return WorkdirContext.absent({pipelineManager: this.pipelineManager});
552551
}
553552

554-
// Restore models from saved state. Will return a NullWorkdirContext if this path is not presently
555-
// resident in the pool.
556-
const savedWorkingDir = savedState.activeRepositoryPath;
557-
if (savedWorkingDir) {
558-
return this.contextPool.getContext(savedWorkingDir);
559-
}
560-
553+
// It is only possible to reach here if there there was no preferred directory, there are no project paths and the
554+
// the active context's repository is not undetermined.
561555
return this.activeContext;
562556
}
563557

@@ -600,22 +594,3 @@ export default class GithubPackage {
600594
}
601595
}
602596
}
603-
604-
function pathForPaneItem(paneItem) {
605-
if (!paneItem) {
606-
return null;
607-
}
608-
609-
// Likely GitHub package provided pane item
610-
if (typeof paneItem.getWorkingDirectory === 'function') {
611-
return paneItem.getWorkingDirectory();
612-
}
613-
614-
// TextEditor-like
615-
if (typeof paneItem.getPath === 'function') {
616-
return paneItem.getPath();
617-
}
618-
619-
// Oh well
620-
return null;
621-
}

0 commit comments

Comments
 (0)