Skip to content

Commit

Permalink
Commands: pass execOpts to all utility executions to avoid implicit p…
Browse files Browse the repository at this point in the history
…rocess.cwd() (#733)
  • Loading branch information
evocateur authored Apr 6, 2017
1 parent 114a07a commit 0cd40ec
Show file tree
Hide file tree
Showing 14 changed files with 212 additions and 160 deletions.
10 changes: 10 additions & 0 deletions src/Command.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ export default class Command {
return this.constructor.name;
}

get execOpts() {
if (!this._execOpts) {
this._execOpts = {
cwd: this.repository.rootPath,
};
}

return this._execOpts;
}

// Override this to inherit config from another command.
// For example `updated` inherits config from `publish`.
get otherCommandConfigs() {
Expand Down
10 changes: 6 additions & 4 deletions src/ConventionalCommitUtilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@ const CHANGELOG_HEADER = dedent(`# Change Log

export default class ConventionalCommitUtilities {
@logger.logifySync()
static recommendVersion(pkg) {
static recommendVersion(pkg, opts) {
const name = pkg.name;
const version = pkg.version;
const pkgLocation = pkg.location;

const recommendedBump = ChildProcessUtilities.execSync(
`${require.resolve("conventional-recommended-bump/cli.js")} -l ${name} --commit-path=${pkgLocation} -p angular`
`${require.resolve("conventional-recommended-bump/cli.js")} -l ${name} --commit-path=${pkgLocation} -p angular`,
opts
);

return semver.inc(version, recommendedBump);
}

@logger.logifySync()
static updateChangelog(pkg) {
static updateChangelog(pkg, opts) {
const name = pkg.name;
const pkgLocation = pkg.location;
const changelogLocation = ConventionalCommitUtilities.changelogLocation(pkg);
Expand All @@ -39,7 +40,8 @@ export default class ConventionalCommitUtilities {
// run conventional-changelog-cli to generate the markdown
// for the upcoming release.
const newEntry = ChildProcessUtilities.execSync(
`${require.resolve("conventional-changelog-cli/cli.js")} -l ${name} --commit-path=${pkgLocation} --pkg=${path.join(pkgLocation, "package.json")} -p angular`
`${require.resolve("conventional-changelog-cli/cli.js")} -l ${name} --commit-path=${pkgLocation} --pkg=${path.join(pkgLocation, "package.json")} -p angular`,
opts
);

// CHANGELOG entries start with <a name=, we remove
Expand Down
83 changes: 43 additions & 40 deletions src/GitUtilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,109 +4,112 @@ import escapeArgs from "command-join";

export default class GitUtilities {
@logger.logifySync()
static isDetachedHead() {
const branchName = GitUtilities.getCurrentBranch();
static isDetachedHead(opts) {
const branchName = GitUtilities.getCurrentBranch(opts);
return branchName === "HEAD";
}

@logger.logifySync()
static isInitialized(cwd) {
static isInitialized(opts) {
try {
// we only want the return code, so ignore stdout/stderr
ChildProcessUtilities.execSync("git rev-parse", { cwd, stdio: "ignore" });
ChildProcessUtilities.execSync("git rev-parse", Object.assign({}, opts, {
stdio: "ignore"
}));
return true;
} catch (err) {
return false;
}
}

@logger.logifySync()
static addFile(file) {
ChildProcessUtilities.execSync("git add " + escapeArgs(file));
static addFile(file, opts) {
ChildProcessUtilities.execSync("git add " + escapeArgs(file), opts);
}

@logger.logifySync()
static commit(message) {
static commit(message, opts) {
// Use echo to allow multi\nline strings.
ChildProcessUtilities.execSync("git commit -m \"$(echo \"" + message + "\")\"");
ChildProcessUtilities.execSync("git commit -m \"$(echo \"" + message + "\")\"", opts);
}

@logger.logifySync()
static addTag(tag) {
ChildProcessUtilities.execSync("git tag -a " + tag + " -m \"" + tag + "\"");
static addTag(tag, opts) {
ChildProcessUtilities.execSync("git tag -a " + tag + " -m \"" + tag + "\"", opts);
}

@logger.logifySync()
static removeTag(tag) {
ChildProcessUtilities.execSync("git tag -d " + tag);
static removeTag(tag, opts) {
ChildProcessUtilities.execSync("git tag -d " + tag, opts);
}

@logger.logifySync()
static hasTags() {
return !!ChildProcessUtilities.execSync("git tag");
static hasTags(opts) {
return !!ChildProcessUtilities.execSync("git tag", opts);
}

@logger.logifySync()
static getLastTaggedCommit() {
return ChildProcessUtilities.execSync("git rev-list --tags --max-count=1");
static getLastTaggedCommit(opts) {
return ChildProcessUtilities.execSync("git rev-list --tags --max-count=1", opts);
}

@logger.logifySync()
static getLastTaggedCommitInBranch() {
const tagName = GitUtilities.getLastTag();
return ChildProcessUtilities.execSync("git rev-list -n 1 " + tagName);
static getLastTaggedCommitInBranch(opts) {
const tagName = GitUtilities.getLastTag(opts);
return ChildProcessUtilities.execSync("git rev-list -n 1 " + tagName, opts);
}

@logger.logifySync()
static getFirstCommit() {
return ChildProcessUtilities.execSync("git rev-list --max-parents=0 HEAD");
static getFirstCommit(opts) {
return ChildProcessUtilities.execSync("git rev-list --max-parents=0 HEAD", opts);
}

@logger.logifySync()
static pushWithTags(remote, tags) {
ChildProcessUtilities.execSync(`git push ${remote} ${GitUtilities.getCurrentBranch()}`);
ChildProcessUtilities.execSync(`git push ${remote} ${tags.join(" ")}`);
static pushWithTags(remote, tags, opts) {
const branch = GitUtilities.getCurrentBranch(opts);
ChildProcessUtilities.execSync(`git push ${remote} ${branch}`, opts);
ChildProcessUtilities.execSync(`git push ${remote} ${tags.join(" ")}`, opts);
}

@logger.logifySync()
static getLastTag() {
return ChildProcessUtilities.execSync("git describe --tags --abbrev=0");
static getLastTag(opts) {
return ChildProcessUtilities.execSync("git describe --tags --abbrev=0", opts);
}

@logger.logifySync()
static describeTag(commit) {
return ChildProcessUtilities.execSync("git describe --tags " + commit);
static describeTag(commit, opts) {
return ChildProcessUtilities.execSync("git describe --tags " + commit, opts);
}

@logger.logifySync()
static diffSinceIn(since, location) {
return ChildProcessUtilities.execSync("git diff --name-only " + since + " -- " + escapeArgs(location));
static diffSinceIn(since, location, opts) {
return ChildProcessUtilities.execSync("git diff --name-only " + since + " -- " + escapeArgs(location), opts);
}

@logger.logifySync()
static getCurrentBranch() {
return ChildProcessUtilities.execSync("git rev-parse --abbrev-ref HEAD");
static getCurrentBranch(opts) {
return ChildProcessUtilities.execSync("git rev-parse --abbrev-ref HEAD", opts);
}

@logger.logifySync()
static getCurrentSHA() {
return ChildProcessUtilities.execSync("git rev-parse HEAD");
static getCurrentSHA(opts) {
return ChildProcessUtilities.execSync("git rev-parse HEAD", opts);
}

@logger.logifySync()
static checkoutChanges(changes) {
ChildProcessUtilities.execSync("git checkout -- " + changes);
static checkoutChanges(changes, opts) {
ChildProcessUtilities.execSync("git checkout -- " + changes, opts);
}

@logger.logifySync()
static init(cwd) {
return ChildProcessUtilities.execSync("git init", { cwd });
static init(opts) {
return ChildProcessUtilities.execSync("git init", opts);
}

@logger.logifySync()
static hasCommit() {
static hasCommit(opts) {
try {
ChildProcessUtilities.execSync("git log");
ChildProcessUtilities.execSync("git log", opts);
return true;
} catch (e) {
return false;
Expand Down
11 changes: 6 additions & 5 deletions src/UpdatedPackagesCollector.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Update {

export default class UpdatedPackagesCollector {
constructor(command) {
this.execOpts = command.execOpts;
this.logger = command.logger;
this.repository = command.repository;
this.packages = command.filteredPackages;
Expand All @@ -28,10 +29,10 @@ export default class UpdatedPackagesCollector {
collectUpdatedPackages() {
this.logger.info("Checking for updated packages...");

const hasTags = GitUtilities.hasTags();
const hasTags = GitUtilities.hasTags(this.execOpts);

if (hasTags) {
const tag = GitUtilities.getLastTag();
const tag = GitUtilities.getLastTag(this.execOpts);
this.logger.info("Comparing with: " + tag);
} else {
this.logger.info("No tags found! Comparing with initial commit.");
Expand All @@ -47,12 +48,12 @@ export default class UpdatedPackagesCollector {
if (this.flags.canary !== true) {
currentSHA = this.flags.canary;
} else {
currentSHA = GitUtilities.getCurrentSHA();
currentSHA = GitUtilities.getCurrentSHA(this.execOpts);
}

commits = this.getAssociatedCommits(currentSHA);
} else if (hasTags) {
commits = GitUtilities.describeTag(GitUtilities.getLastTaggedCommitInBranch());
commits = GitUtilities.describeTag(GitUtilities.getLastTaggedCommitInBranch(this.execOpts), this.execOpts);
}

const updatedPackages = {};
Expand Down Expand Up @@ -145,7 +146,7 @@ export default class UpdatedPackagesCollector {

hasDiffSinceThatIsntIgnored(pkg, commits) {
const folder = path.relative(this.repository.rootPath, pkg.location);
const diff = GitUtilities.diffSinceIn(commits, pkg.location);
const diff = GitUtilities.diffSinceIn(commits, pkg.location, this.execOpts);

if (diff === "") {
return false;
Expand Down
17 changes: 7 additions & 10 deletions src/commands/DiffCommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import Command from "../Command";
import ChildProcessUtilities from "../ChildProcessUtilities";
import find from "lodash/find";

function getLastCommit() {
if (GitUtilities.hasTags()) {
return GitUtilities.getLastTaggedCommit();
function getLastCommit(execOpts) {
if (GitUtilities.hasTags(execOpts)) {
return GitUtilities.getLastTaggedCommit(execOpts);
}

return GitUtilities.getFirstCommit();
return GitUtilities.getFirstCommit(execOpts);
}

export default class DiffCommand extends Command {
Expand All @@ -28,15 +28,12 @@ export default class DiffCommand extends Command {
}
}

if (!GitUtilities.hasCommit()) {
if (!GitUtilities.hasCommit(this.execOpts)) {
callback(new Error("Can't diff. There are no commits in this repository, yet."));
return;
}

this.args = ["diff", getLastCommit(), "--color=auto"];
this.opts = {
cwd: this.repository.rootPath,
};
this.args = ["diff", getLastCommit(this.execOpts), "--color=auto"];

if (targetPackage) {
this.args.push("--", targetPackage.location);
Expand All @@ -46,7 +43,7 @@ export default class DiffCommand extends Command {
}

execute(callback) {
ChildProcessUtilities.spawn("git", this.args, this.opts, (code) => {
ChildProcessUtilities.spawn("git", this.args, this.execOpts, (code) => {
if (code) {
callback(new Error("Errored while spawning `git diff`."));
} else {
Expand Down
19 changes: 9 additions & 10 deletions src/commands/ImportCommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Command from "../Command";
import PromptUtilities from "../PromptUtilities";
import ChildProcessUtilities from "../ChildProcessUtilities";
import FileSystemUtilities from "../FileSystemUtilities";
import GitUtilities from "../GitUtilities";

export default class ImportCommand extends Command {
initialize(callback) {
Expand Down Expand Up @@ -36,11 +37,9 @@ export default class ImportCommand extends Command {
const targetBase = getTargetBase(this.repository.packageConfigs);
this.targetDir = path.join(targetBase, externalRepoBase);

try {
if (FileSystemUtilities.existsSync(this.targetDir)) {
return callback(new Error(`Target directory already exists "${this.targetDir}"`));
}
} catch (e) { /* Pass */ }
if (FileSystemUtilities.existsSync(path.resolve(this.repository.rootPath, this.targetDir))) {
return callback(new Error(`Target directory already exists "${this.targetDir}"`));
}

this.externalExecOpts = {
encoding: "utf8",
Expand All @@ -54,9 +53,9 @@ export default class ImportCommand extends Command {
}

// Stash the repo's pre-import head away in case something goes wrong.
this.preImportHead = ChildProcessUtilities.execSync("git log --format=\"%h\" -1").split("\n")[0];
this.preImportHead = GitUtilities.getCurrentSHA(this.execOpts);

if (ChildProcessUtilities.execSync("git diff " + this.preImportHead)) {
if (ChildProcessUtilities.execSync("git diff-index HEAD", this.execOpts)) {
return callback(new Error("Local repository has un-committed changes"));
}

Expand Down Expand Up @@ -102,16 +101,16 @@ export default class ImportCommand extends Command {
//
// Fall back to three-way merge, which can help with duplicate commits
// due to merge history.
ChildProcessUtilities.exec("git am -3", {}, (err) => {
ChildProcessUtilities.exec("git am -3", this.execOpts, (err) => {
if (err) {

// Give some context for the error message.
err = `Failed to apply commit ${sha}.\n${err}\n` +
`Rolling back to previous HEAD (commit ${this.preImportHead}).`;

// Abort the failed `git am` and roll back to previous HEAD.
ChildProcessUtilities.execSync("git am --abort");
ChildProcessUtilities.execSync("git reset --hard " + this.preImportHead);
ChildProcessUtilities.execSync("git am --abort", this.execOpts);
ChildProcessUtilities.execSync(`git reset --hard ${this.preImportHead}`, this.execOpts);
}
done(err);
}).stdin.end(patch);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/InitCommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export default class InitCommand extends Command {
runPreparations() {}

initialize(callback) {
if (!GitUtilities.isInitialized(this.repository.rootPath)) {
if (!GitUtilities.isInitialized(this.execOpts)) {
this.logger.info("Initializing Git repository.");
GitUtilities.init(this.repository.rootPath);
GitUtilities.init(this.execOpts);
}

this.exact = this.getOptions().exact;
Expand Down
Loading

0 comments on commit 0cd40ec

Please sign in to comment.