Skip to content

Commit

Permalink
fix(publish): Exit early when publishing w/o commits (#1453)
Browse files Browse the repository at this point in the history
Lerna will throw an error, when publishing the current project and
there are no commits at all. This change will check if there are
any commits before proceeding with the publish command.

- Refactor the fixtures as preparation for tests with/without commit
- Add check if any commits are present
- Add tests for this behaviour

Closes #773.
  • Loading branch information
arndissler authored and evocateur committed Jul 16, 2018
1 parent 6961388 commit 6cbae35
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 7 deletions.
10 changes: 10 additions & 0 deletions commands/publish/__tests__/get-current-branch.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ test("getCurrentBranch", async () => {

expect(getCurrentBranch({ cwd })).toBe("master");
});

test("getCurrentBranch without commit", async () => {
const cwd = await initFixture("root-manifest-only", false);
expect.assertions(1);
try {
await getCurrentBranch({ cwd });
} catch (err) {
expect(err.message).toMatch(/Command failed: git rev-parse --abbrev-ref HEAD.*/);
}
});
21 changes: 21 additions & 0 deletions commands/publish/__tests__/is-anything-commited.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use strict";

const execa = require("execa");
const initFixture = require("@lerna-test/init-fixture")(__dirname);
const isAnythingCommited = require("../lib/is-anything-commited");

test("isAnythingCommited", async () => {
const cwd = await initFixture("root-manifest-only");

expect(isAnythingCommited({ cwd })).toBe(true);
});

test("isAnythingCommited without and with a commit", async () => {
const cwd = await initFixture("root-manifest-only", false);

expect(isAnythingCommited({ cwd })).toBe(false);

await execa("git", ["commit", "--allow-empty", "-m", "change"], { cwd });

expect(isAnythingCommited({ cwd })).toBe(true);
});
13 changes: 13 additions & 0 deletions commands/publish/__tests__/publish-command.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,19 @@ describe("PublishCommand", () => {
});
});

it("exists with an error when no commits are present", async () => {
expect.assertions(2);
const testDir = await initFixture("normal", false);
try {
await lernaPublish(testDir)();
} catch (err) {
expect(err.prefix).toBe("ENOCOMMIT");
expect(err.message).toBe(
"No commits in this repository. Please commit something before using publish."
);
}
});

it("exits with an error when git HEAD is detached", async () => {
const cwd = await initFixture("normal-no-inter-dependencies");

Expand Down
8 changes: 8 additions & 0 deletions commands/publish/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const gitPush = require("./lib/git-push");
const gitTag = require("./lib/git-tag");
const isBehindUpstream = require("./lib/is-behind-upstream");
const isBreakingChange = require("./lib/is-breaking-change");
const isAnythingCommited = require("./lib/is-anything-commited");

module.exports = factory;

Expand Down Expand Up @@ -81,6 +82,13 @@ class PublishCommand extends Command {

// git validation, if enabled, should happen before updates are calculated and versions picked
if (this.gitEnabled) {
if (!isAnythingCommited(this.execOpts)) {
throw new ValidationError(
"ENOCOMMIT",
"No commits in this repository. Please commit something before using publish."
);
}

this.currentBranch = getCurrentBranch(this.execOpts);

if (this.currentBranch === "HEAD") {
Expand Down
16 changes: 16 additions & 0 deletions commands/publish/lib/is-anything-commited.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"use strict";

const log = require("npmlog");
const childProcess = require("@lerna/child-process");

module.exports = isAnythingCommited;

function isAnythingCommited(opts) {
log.silly("isAnythingCommited");

const anyCommits = childProcess.execSync("git", ["rev-list", "--count", "--all", "--max-count=1"], opts);

log.verbose("isAnythingCommited", anyCommits);

return Boolean(parseInt(anyCommits, 10));
}
18 changes: 11 additions & 7 deletions helpers/init-fixture/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ module.exports = initFixture;
function initFixture(startDir) {
return (fixtureName, commitMessage = "Init commit") => {
const cwd = tempy.directory();
let chain = Promise.resolve();

return Promise.resolve()
.then(() => process.chdir(cwd))
.then(() => copyFixture(cwd, fixtureName, startDir))
.then(() => gitInit(cwd, "."))
.then(() => gitAdd(cwd, "-A"))
.then(() => gitCommit(cwd, commitMessage))
.then(() => cwd);
chain = chain.then(() => process.chdir(cwd));
chain = chain.then(() => copyFixture(cwd, fixtureName, startDir));
chain = chain.then(() => gitInit(cwd, "."));

if (commitMessage) {
chain = chain.then(() => gitAdd(cwd, "-A"));
chain = chain.then(() => gitCommit(cwd, commitMessage));
}

return chain.then(() => cwd);
};
}

0 comments on commit 6cbae35

Please sign in to comment.