Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to stash changes before running hooks #63

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

kevinoid
Copy link
Contributor

@kevinoid kevinoid commented Feb 6, 2016

In order to ensure any pre-commit tests are run against the files as they will appear in the commit, this PR adds an option to run git stash to save any changes to the working tree before running the scripts, then restore any changes after the scripts finish.

The save/restore procedure is based on Chris Torek's StackOverflow answer to a question asking how to do exactly this. This implementation does not do a hard reset before restoring the stash by default, since it assumes that if scripts modify tracked files the changes should be kept. But it does provide this behavior, and git clean, as configurable options.

It follows the convention requested in #4 by making the new stash option default to off. Although there are no known implementation issues (with the exception of the git bug noted in Torek's SO answer), current scripts may expect modified/untracked files to exist or modify untracked files in a way which prevents applying the stash, making default-on behavior backwards-incompatible.

The tests are split into a separate file. Since each stash option is tested against a project repository and a clean/reset is done between each test, the tests are somewhat slow. By splitting the tests into a separate file, we can avoid running them by default. They can instead be run as test-stash, as part of test-all, and as part of test-travis.

This commit is based off of the work of Christopher Hiller in #47, although the implementation differs significantly due to the use of Promises in place of async, which I found to be significantly clearer, more flexible, and they make the tests significantly more concise.

Thanks for considering,
Kevin

Fixes: #4

Previously log would always call .exit(), which is intended to be fatal.
In order to support non-fatal logging, split out a logOnly method which
outputs the formatted lines but does not exit.  This preserves the
current API completely.

Also add a call to .slice() if the lines argument is not a string so
that the argument Array is not modified.  This codepath is not currently
used, but it is no longer a waiting surprise for future callers.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
In order to ensure any pre-commit tests are run against the files as
they will appear in the commit, this commit adds an option to run `git
stash` to save any changes to the working tree before running the
scripts, then restore any changes after the scripts finish.

The save/restore procedure is based on Chris Torek's StackOverflow
answer to a question asking how to do exactly this.[1]  This
implementation does not do a hard reset before restoring the stash by
default, since it assumes that if scripts modify tracked files the
changes should be kept.  But it does provide this behavior, and `git
clean`, as configurable options.

It follows the convention requested in observing#4 by making the new stash option
default to off.  Although there are no known implementation issues (with
the exception of the git bug noted in Torek's SO answer), current
scripts may expect modified/untracked files to exist or modify untracked
files in a way which prevents applying the stash, making default-on
behavior backwards-incompatible.

The tests are split into a separate file.  Since each stash option is
tested against a project repository and a clean/reset is done between
each test, the tests are somewhat slow.  By splitting the tests into a
separate file, we can avoid running them by default.  They can instead
be run as test-stash, as part of test-all, and as part of test-travis.

This commit is based off of the work of Christopher Hiller in observing#47,
although the implementation differs significantly due to the use of
Promises in place of async, which I found to be significantly clearer,
more flexible, and they make the tests significantly more concise.

Fixes: observing#4

1.  https://stackoverflow.com/a/20480591

Signed-off-by: Christopher Hiller <boneskull@boneskull.com>
[kevin@kevinlocke.name: Reimplement using Promises and Torek's method]
Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
@3rd-Eden
Copy link
Member

3rd-Eden commented Feb 8, 2016

Thanks for your pull request, @Swaagie Any opinions?

var spawn = require('cross-spawn')
, which = require('which')
, path = require('path')
, util = require('util')
, tty = require('tty');
, tty = require('tty')
, bufferedSpawn = require('buffered-spawn')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buffered-spawn isn't really needed. As this a CLI file, there really is no need for async execution. That's why we're using an sync exec throughout the code base. Using https://github.com/observing/pre-commit/blob/master/index.js#L67-L71 would make the code a lot easier to read manage as there would be no need for promises and async flow control.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to think of synchronous execution as an anti-pattern since it prevents the addition of concurrency. But if you feel strongly about it, I can rework the commit to use only synchronous methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants