|
1 | 1 | import React from 'react';
|
2 | 2 | import PropTypes from 'prop-types';
|
3 | 3 |
|
| 4 | +import {GitError} from '../git-shell-out-strategy'; |
4 | 5 | import ObserveModelDecorator from '../decorators/observe-model';
|
5 | 6 | import {BranchPropType, RemotePropType} from '../prop-types';
|
6 | 7 | import BranchView from '../views/branch-view';
|
@@ -149,7 +150,6 @@ export default class StatusBarTileController extends React.Component {
|
149 | 150 | <PushPullMenuView
|
150 | 151 | onMarkSpecialClick={this.handleOpenGitTimingsView}
|
151 | 152 | workspace={this.props.workspace}
|
152 |
| - notificationManager={this.props.notificationManager} |
153 | 153 | inProgress={this.state.inProgress}
|
154 | 154 | push={this.push}
|
155 | 155 | pull={this.pull}
|
@@ -186,25 +186,89 @@ export default class StatusBarTileController extends React.Component {
|
186 | 186 | });
|
187 | 187 | }
|
188 | 188 |
|
| 189 | + async attemptGitOperation(operation, errorTransform = message => ({message})) { |
| 190 | + const operationPromise = operation(); |
| 191 | + try { |
| 192 | + return await operationPromise; |
| 193 | + } catch (error) { |
| 194 | + if (!(error instanceof GitError)) { throw error; } |
| 195 | + const {message, description} = errorTransform(error.stdErr); |
| 196 | + this.props.notificationManager.addError( |
| 197 | + message || 'Cannot complete remote interaction', |
| 198 | + {description, dismissable: true}, |
| 199 | + ); |
| 200 | + return null; |
| 201 | + } |
| 202 | + } |
| 203 | + |
189 | 204 | @autobind
|
190 | 205 | checkout(branchName, options) {
|
191 | 206 | return this.setInProgressWhile(() => this.props.repository.checkout(branchName, options));
|
192 | 207 | }
|
193 | 208 |
|
194 | 209 | @autobind
|
195 |
| - async push(options) { |
| 210 | + async push({force, setUpstream}) { |
| 211 | + await this.attemptGitOperation( |
| 212 | + () => this.doPush({force, setUpstream}), |
| 213 | + description => { |
| 214 | + if (/rejected[\s\S]*failed to push/.test(description)) { |
| 215 | + return { |
| 216 | + message: 'Push rejected', |
| 217 | + description: 'The tip of your current branch is behind its remote counterpart.' + |
| 218 | + ' Try pulling before pushing again. Or, to force push, hold `cmd` or `ctrl` while clicking.', |
| 219 | + }; |
| 220 | + } |
| 221 | + |
| 222 | + return {message: 'Unable to push', description: `<pre>${description}</pre>`}; |
| 223 | + }, |
| 224 | + ); |
| 225 | + } |
| 226 | + |
| 227 | + async doPush(options) { |
196 | 228 | await this.setInProgressWhile(() => {
|
197 | 229 | return this.props.repository.push(this.props.currentBranch.getName(), options);
|
198 | 230 | }, {push: true});
|
199 | 231 | }
|
200 | 232 |
|
201 | 233 | @autobind
|
202 | 234 | async pull() {
|
| 235 | + await this.attemptGitOperation( |
| 236 | + () => this.doPull(), |
| 237 | + description => { |
| 238 | + if (/error: Your local changes to the following files would be overwritten by merge/.test(description)) { |
| 239 | + const lines = description.split('\n'); |
| 240 | + const files = lines.slice(3, lines.length - 3).map(l => `\`${l.trim()}\``).join('<br>'); |
| 241 | + return { |
| 242 | + message: 'Pull aborted', |
| 243 | + description: 'Local changes to the following would be overwritten by merge:<br>' + files + |
| 244 | + '<br>Please commit your changes or stash them before you merge.', |
| 245 | + }; |
| 246 | + } |
| 247 | + |
| 248 | + return {message: 'Unable to pull', description: `<pre>${description}</pre>`}; |
| 249 | + }, |
| 250 | + ); |
| 251 | + |
| 252 | + } |
| 253 | + |
| 254 | + async doPull() { |
203 | 255 | await this.setInProgressWhile(() => this.props.repository.pull(this.props.currentBranch.getName()), {pull: true});
|
204 | 256 | }
|
205 | 257 |
|
206 | 258 | @autobind
|
207 | 259 | async fetch() {
|
| 260 | + await this.attemptGitOperation( |
| 261 | + () => this.doFetch(), |
| 262 | + description => { |
| 263 | + return { |
| 264 | + message: 'Unable to fetch', |
| 265 | + description: `<pre>${description}</pre>`, |
| 266 | + }; |
| 267 | + }, |
| 268 | + ); |
| 269 | + } |
| 270 | + |
| 271 | + async doFetch() { |
208 | 272 | await this.setInProgressWhile(() => this.props.repository.fetch(this.props.currentBranch.getName()), {fetch: true});
|
209 | 273 | }
|
210 | 274 | }
|
0 commit comments