diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index ed16668ac6..bbc2bc05c3 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,14 +1,3 @@
-trigger:
- branches:
- include:
- - master
- - releases/*
-
-pr:
- branches:
- include:
- - "*"
-
jobs:
- job: Linux
pool:
diff --git a/lib/atom/atom-text-editor.js b/lib/atom/atom-text-editor.js
index abf5164906..8d180480ac 100644
--- a/lib/atom/atom-text-editor.js
+++ b/lib/atom/atom-text-editor.js
@@ -5,7 +5,7 @@ import {CompositeDisposable} from 'event-kit';
import RefHolder from '../models/ref-holder';
import {RefHolderPropType} from '../prop-types';
-import {autobind, extractProps} from '../helpers';
+import {extractProps} from '../helpers';
const editorUpdateProps = {
mini: PropTypes.bool,
@@ -28,7 +28,7 @@ export default class AtomTextEditor extends React.Component {
static propTypes = {
...editorCreationProps,
- workspace: PropTypes.object.isRequired, // FIXME make more specific
+ workspace: PropTypes.object.isRequired,
didChangeCursorPosition: PropTypes.func,
didAddSelection: PropTypes.func,
@@ -50,7 +50,6 @@ export default class AtomTextEditor extends React.Component {
constructor(props) {
super(props);
- autobind(this, 'observeSelections');
this.subs = new CompositeDisposable();
@@ -98,7 +97,7 @@ export default class AtomTextEditor extends React.Component {
this.subs.dispose();
}
- observeSelections(selection) {
+ observeSelections = selection => {
const selectionSubs = new CompositeDisposable(
selection.onDidChangeRange(this.props.didChangeSelectionRange),
selection.onDidDestroy(() => {
diff --git a/lib/atom/decoration.js b/lib/atom/decoration.js
index 9e3049f1a2..cd3cbead27 100644
--- a/lib/atom/decoration.js
+++ b/lib/atom/decoration.js
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import {Disposable} from 'event-kit';
import cx from 'classnames';
-import {createItem, autobind, extractProps} from '../helpers';
+import {createItem, extractProps} from '../helpers';
import {RefHolderPropType} from '../prop-types';
import {TextEditorContext} from './atom-text-editor';
import {DecorableContext} from './marker';
@@ -40,8 +40,6 @@ class BareDecoration extends React.Component {
constructor(props, context) {
super(props, context);
- autobind(this, 'observeParents');
-
this.decorationHolder = new RefHolder();
this.editorSub = new Disposable();
this.decorableSub = new Disposable();
@@ -93,7 +91,7 @@ class BareDecoration extends React.Component {
}
}
- observeParents() {
+ observeParents = () => {
this.decorationHolder.map(decoration => decoration.destroy());
const editorValid = this.props.editorHolder.map(editor => !editor.isDestroyed()).getOr(false);
diff --git a/lib/models/repository-states/present.js b/lib/models/repository-states/present.js
index c591d25c7e..830c18280e 100644
--- a/lib/models/repository-states/present.js
+++ b/lib/models/repository-states/present.js
@@ -43,6 +43,7 @@ export default class Present extends State {
this.commitMessageTemplate = null;
this.fetchInitialMessage();
+ /* istanbul ignore else */
if (history) {
this.discardHistory.updateHistory(history);
}
@@ -165,6 +166,7 @@ export default class Present extends State {
keys.add(Keys.statusBundle);
}
+ /* istanbul ignore else */
if (keys.size > 0) {
this.cache.invalidate(Array.from(keys));
this.didUpdate();
@@ -557,6 +559,7 @@ export default class Present extends State {
destructiveAction,
partialDiscardFilePath,
);
+ /* istanbul ignore else */
if (snapshots) {
await this.saveDiscardHistory();
}
diff --git a/package-lock.json b/package-lock.json
index eef33d95bb..31ec405425 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -244,6 +244,15 @@
"acorn": "^5.0.3"
}
},
+ "agent-base": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+ "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+ "dev": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ },
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
@@ -2016,15 +2025,14 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"codecov": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.1.0.tgz",
- "integrity": "sha512-aWQc/rtHbcWEQLka6WmBAOpV58J2TwyXqlpAQGhQaSiEUoigTTUk6lLd2vB3kXkhnDyzyH74RXfmV4dq2txmdA==",
+ "version": "github:codecov/codecov-node#e427d900309adb50746a39a50aa7d80071a5ddd0",
+ "from": "github:codecov/codecov-node#e427d90",
"dev": true,
"requires": {
"argv": "^0.0.2",
"ignore-walk": "^3.0.1",
"js-yaml": "^3.12.0",
- "request": "^2.87.0",
+ "teeny-request": "^3.7.0",
"urlgrey": "^0.4.4"
},
"dependencies": {
@@ -2854,6 +2862,21 @@
"is-symbol": "^1.0.1"
}
},
+ "es6-promise": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
+ "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==",
+ "dev": true
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "dev": true,
+ "requires": {
+ "es6-promise": "^4.0.3"
+ }
+ },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -4024,6 +4047,33 @@
"sshpk": "^1.7.0"
}
},
+ "https-proxy-agent": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
+ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+ "dev": true,
+ "requires": {
+ "agent-base": "^4.1.0",
+ "debug": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
+ }
+ },
"iconv-lite": {
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
@@ -5082,7 +5132,7 @@
},
"load-json-file": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
"requires": {
@@ -7693,6 +7743,25 @@
"xtend": "^4.0.0"
}
},
+ "teeny-request": {
+ "version": "3.11.3",
+ "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-3.11.3.tgz",
+ "integrity": "sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw==",
+ "dev": true,
+ "requires": {
+ "https-proxy-agent": "^2.2.1",
+ "node-fetch": "^2.2.0",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+ "dev": true
+ }
+ }
+ },
"temp": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
diff --git a/package.json b/package.json
index 33e7651c5e..5b0603a104 100644
--- a/package.json
+++ b/package.json
@@ -78,7 +78,7 @@
"babel-plugin-istanbul": "4.1.6",
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
- "codecov": "3.1.0",
+ "codecov": "codecov/codecov-node#e427d90",
"cross-env": "5.2.0",
"cross-unzip": "0.2.1",
"dedent-js": "1.0.1",
diff --git a/test/atom/atom-text-editor.test.js b/test/atom/atom-text-editor.test.js
index 23f764074a..a2d8cb7e78 100644
--- a/test/atom/atom-text-editor.test.js
+++ b/test/atom/atom-text-editor.test.js
@@ -1,5 +1,5 @@
import React from 'react';
-import {mount} from 'enzyme';
+import {mount, shallow} from 'enzyme';
import {TextBuffer} from 'atom';
import RefHolder from '../../lib/models/ref-holder';
@@ -35,6 +35,12 @@ describe('AtomTextEditor', function() {
assert.isTrue(workspace.isTextEditor(app.instance().refModel.get()));
});
+ it('returns undefined if the current model is unavailable', function() {
+ const emptyHolder = new RefHolder();
+ const app = shallow();
+ assert.isUndefined(app.instance().getModel());
+ });
+
it('configures the created text editor with props', function() {
mount(
{
+ sub = repository.onDidUpdate(() => {
+ sub.dispose();
+ resolve();
+ });
+ });
+
+ await assert.async.strictEqual(repository.getCommitMessage(), 'hai');
+ });
+ });
+
+ describe('update broadcast', function() {
+ it('broadcasts an update when set', async function() {
+ const repository = new Repository(await cloneRepository());
+ await repository.getLoadPromise();
+ const didUpdate = sinon.spy();
+ sub = repository.onDidUpdate(didUpdate);
+
+ repository.setCommitMessage('new message');
+ assert.isTrue(didUpdate.called);
+ });
+
+ it('may suppress the update when set', async function() {
+ const repository = new Repository(await cloneRepository());
+ await repository.getLoadPromise();
+ const didUpdate = sinon.spy();
+ sub = repository.onDidUpdate(didUpdate);
+
+ repository.setCommitMessage('quietly now', {suppressUpdate: true});
+ assert.isFalse(didUpdate.called);
+ });
+ });
+
describe('updateCommitMessageAfterFileSystemChange', function() {
it('handles events with no `path` property', async function() {
const {repository} = await wireUpObserver();
@@ -2213,6 +2320,31 @@ describe('Repository', function() {
);
await assert.async.strictEqual(repository.getCommitMessage(), fs.readFileSync(templatePath, 'utf8'));
});
+
+ it('leaves the commit message alone if the template content did not change', async function() {
+ const {repository, observer, subscriptions} = await wireUpObserver();
+ sub = subscriptions;
+ await observer.start();
+
+ const templateOnePath = path.join(repository.getWorkingDirectoryPath(), 'the-template-0.txt');
+ const templateTwoPath = path.join(repository.getWorkingDirectoryPath(), 'the-template-1.txt');
+ const templateContent = 'the same';
+
+ await Promise.all(
+ [templateOnePath, templateTwoPath].map(p => fs.writeFile(p, templateContent, {encoding: 'utf8'})),
+ );
+
+ await repository.git.setConfig('commit.template', templateOnePath);
+ await expectEvents(repository, path.join('.git', 'config'));
+ await assert.async.strictEqual(repository.getCommitMessage(), 'the same');
+
+ repository.setCommitMessage('different');
+
+ await repository.git.setConfig('commit.template', templateTwoPath);
+ await expectEvents(repository, path.join('.git', 'config'));
+ assert.strictEqual(repository.getCommitMessage(), 'different');
+ });
+
it('updates commit message to empty string if commit.template is unset', async function() {
const {repository, observer, subscriptions} = await wireUpObserver();
sub = subscriptions;