Skip to content

Instantly share code, notes, and snippets.

@christhekeele
Last active May 3, 2016 00:19
Show Gist options
  • Save christhekeele/5594243 to your computer and use it in GitHub Desktop.
Save christhekeele/5594243 to your computer and use it in GitHub Desktop.
Ever committed with `gem 'foobar', path: '~/source'` in your Gemfile and broken a build?This git pre-commit hook ensures you never will again.If you try and commit while a gem in your Gemfile is loading with the `:path` option, you will be stopped with a helpful message. The only exception: gems embedded within your project are allowed.
#!/usr/bin/env ruby
# A pre-commit hook script to ensure that no local gem dependencies (gem 'asdf', path: '~/local')
# exist in your Gemfile before commiting.`
# Allows gems to be loaded from source within the current project directory, but not from outside.
puts 'Checking for local dependencies in your Gemfile.'
ROOT_PATH = File.expand_path('../../..', __FILE__)
NESTED_GEMSPECS = Dir["#{ROOT_PATH}/**/*.gemspec"]
GEMFILE = ENV['BUNDLE_GEMFILE'] || File.join(ROOT_PATH, 'Gemfile')
def local?(gemspec)
gemspec.source.instance_of?(Bundler::Source::Path)
end
def nested?(gemspec)
NESTED_GEMSPECS.any? { |filename| filename.include?(gemspec.name) }
end
if open(GEMFILE) { |gemfile| gemfile.grep(/path/) }
require 'rubygems'
require 'bundler/setup'
local_gems = Gem.loaded_specs.values.select do |gemspec|
local?(gemspec) and not nested?(gemspec)
end
unless local_gems.empty? then raise SyntaxError,
"You have local dependencies in your Gemfile:" \
" #{local_gems.map{|g| g.name + ' is loading from ' + g.source.path.to_s}.join(', ')}." \
" Remove the :path parameter from this/these gems in your Gemfile before committing." end
end
@petebrowne
Copy link

How do set this up? Can be it done globally?

@lee-dohm
Copy link

@petebrowne There are a couple different ways to add hooks globally, depending on whether or not you are using Git v1.7.1+ ...

http://stackoverflow.com/questions/2293498/git-commit-hooks-global-settings

@christhekeele
Copy link
Author

@petebrowne: @lee-dohm's nailed it. Even if you could have global hooks without using templates, you'd want to use templates for this hook because it uses relative file paths from your project directory.

@christhekeele
Copy link
Author

Note: As is this hook also prevents committing with a Gemfile in an invalid state. That sounds like a win to me, but if you want to disable this side affect simply remove the raise e line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment