-
Notifications
You must be signed in to change notification settings - Fork 280
Update Pre-Push Context Modified Files #536
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
Conversation
ea44027 to
664a981
Compare
sds
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @taufek, thanks for the pull request. This would be a great feature to add.
My concern here is that you are not determining the modified refs from the list passed to the pre-push hook, but are inferring them from the current state of the local repository.
I imagine this works correctly in most cases, but I'm concerned that there are issues with this implementation which are not obvious because we're obtaining the refs ourselves rather than using the refs Git passes to the pre-push hook. For example, you can run git push origin HEAD:refs/heads/name-of-your-branch from a detached head (perhaps odd, but definitely possible).
I can appreciate this implementation makes it easier to test, but I think we need to be rigorous in our solution here and utilize the refs Git passes to the hook.
lib/overcommit/git_repo.rb
Outdated
| end | ||
|
|
||
| def parent_branch | ||
| `git show-branch -a \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a local repo of mine with a lot of remote branches, this can display warnings like:
warning: ignoring origin/some-remote-branch; cannot handle more than 25 refs
Would need to filter out stderr to avoid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch. Will update accordingly.
|
Thank you @sds for the feedback. It does make sense. I will dig further and incorporate your suggestion here. |
0d53662 to
5047375
Compare
|
@sds , I've updated based on your feedback. What do you think? |
f3a63ba to
8c6eca9
Compare
sds
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making those changes, @taufek. We're getting close here.
| `git push -u origin project-branch 2>&1 > #{File::NULL}` | ||
|
|
||
| touch 'added-1' | ||
| `echo add >> added-1` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to why we use the touch helper above, you should use the echo helper here. It saves us having to spawn a child process—which is slower than appending to the file directly in Ruby. A small optimization in this localized example, but when applied across the entire repository it has significant benefits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL. Will update accordingly.
spec/support/git_spec_helpers.rb
Outdated
| # @param ref [String] git ref | ||
| # @return [String] ref's sha1 | ||
| def get_sha1(ref) | ||
| `git show-ref --head`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems unnecessarily expensive (listing all the refs and then filtering for the one of interest). Any reason why
git rev-parse my-ref...wouldn't suffice here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely will try this out.
spec/support/git_spec_helpers.rb
Outdated
| def get_sha1(ref) | ||
| `git show-ref --head`. | ||
| split("\n"). | ||
| find { |x| x =~ /#{Regexp.quote(ref)}/i }. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another danger here is you aren't anchoring your regex with ^ / $, so a ref of foo will match foo, foobar, somefoobar, etc. Fortunately we should be able to avoid entirely with git rev-parse ....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
spec/support/git_spec_helpers.rb
Outdated
| touch 'delete-me' | ||
| `echo delete >> delete-me` | ||
| `git add . 2>&1 > #{File::NULL}` | ||
| `git commit -m "Initial commit" 2>&1 > #{File::NULL}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we intend to have with_remote_repo be a generic spec helper, it should create the most generic possible setup, and thus should not create any files/commits/objects.
spec/support/git_spec_helpers.rb
Outdated
| `git commit -m "Initial commit" 2>&1 > #{File::NULL}` | ||
|
|
||
| Dir.chdir '..' do | ||
| remote_url = "file://#{File.expand_path('some-repo')}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not hard code some-repo here (that assumes we know how the repo helper is implemented), but obtain it from the name of the repo directory that was created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thought was to create a repo with a remote with some default files. Your comment does make sense. It could easily misinterpreted and it is not generic enough for re-use.
spec/support/git_spec_helpers.rb
Outdated
| end | ||
|
|
||
| Dir.chdir '../local-repo' do | ||
| yield if block_given? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not to be overly pedantic, but when I read with_remote_repo I would expect that the block I pass would execute within the context of the remote repository, but I'll admit it's a bit hard to describe what we're trying to do concisely.
spec/support/git_spec_helpers.rb
Outdated
| yield if block_given? | ||
| end | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the issues with this implementation of with_remote_repo, I'm not entirely convinced this helper is going to get you much. We should probably stick with first principles in the specs:
remote_repo = repo do
# Create remote repository to our liking
...
end
local_repo = repo do
`git remote add origin file://#{remote_repo}`
`git fetch origin && git reset --hard origin/master`
# Create local repository to our liking
...
# Validate expectations
endThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will work. Thanks for the tip
| touch 'added-1' | ||
| `echo add >> added-1` | ||
| `echo append >> update-me` | ||
| `rm delete-me` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FileUtils.rm (again to avoid a child process).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
| end | ||
|
|
||
| describe '#modified_files' do | ||
| let(:remote_url) { "file://#{File.expand_path('some-repo')}" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of some-repo here is cheating a bit as it assumes we know the name of the directory of the repository, which we don't (it is returned by the repo helper).
We can work around this by creating the remote repo in the let so we have the reference.
let(:remote_repo) do
repo do
...
end
end
let(:remote_url) { "file://#{remote_repo}" }You can then enter the repo in the specs to perform additional custom setup work:
it ... do
Dir.chdir remote_repo do
...
end
endThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Will try this out.
718fd06 to
f64d664
Compare
Previously, `Overcommit::HookContext::PrePush::modified_files` is set as `[]` which does not give us any value in `applicable_files` as in `PreCommit` context. This change updates the method to return list of added and updated files: 1. compared between current branch and tracking branch if tracking branch is available. 2. compared between current branch with parent branch if tracking branch is not available. This gives us above values in `applicable_files` in `PrePush` context. One usage example is we can create a hook to scan prohibited keywords such as `eval`, `console.log`, etc. before pushing to remote. Previously we can only do it in `PreCommit` hook but now we could also do it in `PrePush`.
f64d664 to
0ad7976
Compare
|
@sds, This is ready for re-review. |
sds
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're amazing, @taufek. Thanks for writing such thorough tests!
|
Thanks @sds. Can't do it without you. I've learned so much. |
Continuation from sds#536 where it added `modified_files` for `PrePush` context. This is to add `modified_lines_in_file` for `PrePush` context.
Continuation from sds#536 where it added `modified_files` for `PrePush` context. This is to add `modified_lines_in_file` for `PrePush` context.
Continuation from sds#536 where it added `modified_files` for `PrePush` context. This is to add `modified_lines_in_file` for `PrePush` context.
Continuation from #536 where it added `modified_files` for `PrePush` context. This is to add `modified_lines_in_file` for `PrePush` context.
Previously,
Overcommit::HookContext::PrePush::modified_filesis set as[]whichdoes not give us any value in
applicable_filesas inPreCommitcontext.This change updates the method to return list of added and updated files in current branch:
compared between current branch and tracking branch if tracking branch is available.
compared between current branch with parent branch if tracking branch is not available.
This gives us above values in
applicable_filesinPrePushcontext.One usage example is we can create a hook to scan prohibited keywords such as
eval,console.log, etc. before pushing to remote. Previously we can only do it inPreCommithook but now we could also do it inPrePush.I think this will also allow us to reuse existing hooks for
PreCommitinPrePushcontext that relies onapplicable_filesmethod.