diff --git a/.gitignore b/.gitignore index d5e0cb1..2290eb7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .idea -*.gem \ No newline at end of file +*.gem +.bundle +Gemfile.lock +pkg/* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..b977f30 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "http://rubygems.org" + +# Specify your gem's dependencies in noexec.gemspec +gemspec + +gem 'rake' \ No newline at end of file diff --git a/LICENSE b/LICENSE index 61a2d83..67be45b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2012 Michal Papis +Copyright (c) 2011-2012 Josh Hull and Michal Papis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 62eb912..19579dc 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,63 @@ -# About +# rubygems-bundler && Noexec -Rubygems and Bundler integration, makes executable wrappers -generated by rubygems aware of bundler. +Let's stop using bundle exec, kthx. -# Installation +## Installation gem install rubygems-bundler -And follow the on screen instructions +Then, in your .profile (or somewhere you can set env variables) + + RUBYOPT="-r`noexec`" + +And you're done! + +Alternatively you can use rubygems-bundler to generate wrappers aware of noexec, install: + + gem install rubygems-bundler + +change a line in ~/.gemrc to: + + custom_shebang: $env ruby_noexec_wrapper + +and run (once): + + gem regenerate_binstubs + + +## Configuration + +Though you can let noexec do it's own thing and rely on looking up your binary via your Gemfile, +you can also specify which binaries you want included or excluded. +Create a .noexec.yaml file along side any Gemfiles you want to use. +Then, to enable (or disable) the usage of your particular binary into your bundle, +add an include or exclude section. For example: + +### .noexec.yaml -# Description + exclude: [rake] + +Or, + + include: [irb, ruby] + +## Problems? + +Things not going the way you'd like? Try your command again with +NOEXEC_DEBUG=1 set and create a ticket. I'll fix it right away! + +## How does this work? + +It adds a script to every execution of ruby via the RUBYOPT environment variable. +Then, when you run ruby, it takes a look at your working directory, +and every directory above it until it can find a `Gemfile`. +If the executable you're running is present in your Gemfile, +it switches to using that `Gemfile` instead (via `Bundle.setup`). + +Rubygems and Bundler integration, makes executable wrappers +generated by rubygems aware of bundler. + +# Old description This gem is intended to fill in the integration gap between Bundler and Rubygems, it also backports shebang customization @@ -32,7 +80,17 @@ and does not contain `Gemfile` Last note is that bundler handling can be used only when bundler is installed, but you will be warned when it is -# Controlling the wrapper +# Uninstallation + +Before uninstalling change a line in `~/.gemrc` to: + + custom_shebang: $env ruby + +and run `gem regenerate_binstubs` + +this will set all gems to `/usr/bin/env ruby` which is one of the safest choices (especially when using rvm). + +# Controlling the wrapper - the old way Wrappers generated by this gem will replace original rubygems wrapper, but it will not change wrapper behavior unless explicitly asked for. @@ -52,71 +110,15 @@ to blacklist them use the following line: To make your choices persistent put them into `~/.bashrc` or `~/.rvmrc`. -# Alternate use with noexec - -[Joshua Hull - @joshbuddy](https://github.com/joshbuddy) created -[noexec gem](https://github.com/joshbuddy/noexec), -It allows detecting Gemfile and loading Bundler only when it is required. - -To automatically use noexec change a line in ~/.gemrc to: - - custom_shebang: $env ruby_noexec_wrapper - -And run (once): - - gem regenerate_binstubs - - -# How it works - -Installation of gem will make any new installed gem use new bundler -aware wrapper: - - gem install rubygems-bundler - -Follow onscreen instructions. - -Now for running haml can be controlled if it will using bundler code or not: - - mpapis@niczsoft:~/test> USE_BUNDLER=no haml -v - Haml 3.1.1 (Separated Sally) - - mpapis@niczsoft:~/test> USE_BUNDLER=try haml -v - Haml/Sass 3.0.0 (Classy Cassidy) - - mpapis@niczsoft:~/test> gem uninstall bundler - Remove executables: - bundle - in addition to the gem? [Yn] y - Removing bundle - Successfully uninstalled bundler-1.0.14 - - mpapis@niczsoft:~/test> USE_BUNDLER=force haml -v - /home/mpapis/.rvm/gems/ruby-1.9.2-p180@test-bundler/bin/haml:25:in `rescue in
': (RuntimeError) - - Please install bundler first. - - from /home/mpapis/.rvm/gems/ruby-1.9.2-p180@test-bundler/bin/haml:18:in `
' - - mpapis@niczsoft:~/test> USE_BUNDLER=try haml -v - Haml 3.1.1 (Separated Sally) - -# Uninstallation - -Before uninstalling change a line in `~/.gemrc` to: - - custom_shebang: $env ruby - -and run `gem regenerate_binstubs` - -this will set all gems to `/usr/bin/env ruby` which is one of the safest choices (especially when using rvm). -# Author +# Authors + - Joshua Hull - Michal Papis # Thanks + - Carl Lerche : help with the noexec code - Yehuda Katz : the initial patch code - Wayne E. Seguin : support in writing good code - Evan Phoenix : support on rubygems internalls diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..2995527 --- /dev/null +++ b/Rakefile @@ -0,0 +1 @@ +require "bundler/gem_tasks" diff --git a/bin/noexec b/bin/noexec new file mode 100755 index 0000000..ca6e5eb --- /dev/null +++ b/bin/noexec @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby + +print File.expand_path(File.expand_path("../../lib/noexec/auto.rb", __FILE__)) \ No newline at end of file diff --git a/lib/noexec/auto.rb b/lib/noexec/auto.rb new file mode 100644 index 0000000..37b85f9 --- /dev/null +++ b/lib/noexec/auto.rb @@ -0,0 +1,76 @@ +DEBUG = ENV.key?('NOEXEC_DEBUG') + +begin + require "rubygems" + require "bundler" + + module Bundler + class << self + def reset! + @load = nil + end + end + end + + module Noexec + CURRENT = Dir.pwd + + extend self + + def log(msg) + puts msg if DEBUG + end + + def candidate?(gemfile, bin) + config_file = File.expand_path('../.noexec.yaml', gemfile) + log "Considering #{config_file.inspect}" + if File.exist?(config_file) + log "Using config file at #{config_file}" + config = YAML::load_file(config_file) + raise "You cannot have both an include and exclude section in your #{config_file.inspect}" unless config['include'].nil? ^ config['exclude'].nil? + if config['include'] && config['include'].include?(bin) + log "Binary included by config" + return true + elsif config['exclude'] && config['exclude'].include?(bin) + log "Binary excluded by config" + return false + end + log "Config based matching didn't find it, resorting to Gemfile lookup" + end + ENV['BUNDLE_GEMFILE'] = gemfile + Bundler.load.specs.each do |spec| + next if spec.name == 'bundler' + return true if %w(ruby irb).include?(bin) || spec.executables.include?(bin) + end + false + ensure + Bundler.reset! + end + + def setup + log "Noexec" + return if File.basename($0) == 'bundle' + return if ENV['BUNDLE_GEMFILE'] + gemfile = File.join(CURRENT, "Gemfile") + while true + if File.exist?(gemfile) + log "Examining #{gemfile}" + if Noexec.candidate?(gemfile, File.basename($0)) + log "Using #{gemfile}" + ENV['BUNDLE_GEMFILE'] = gemfile + Bundler.setup + return + end + end + new_gemfile = File.expand_path("../../Gemfile", gemfile) + break if new_gemfile == gemfile + gemfile = new_gemfile + end + log "No valid Gemfile found, moving on" + end + end + + Noexec.setup +rescue LoadError + warn "bundler not being used, unable to load" if DEBUG +end diff --git a/lib/noexec/version.rb b/lib/noexec/version.rb new file mode 100644 index 0000000..825aa84 --- /dev/null +++ b/lib/noexec/version.rb @@ -0,0 +1,3 @@ +module Noexec + VERSION = "0.1.0" +end diff --git a/noexec.gemspec b/noexec.gemspec new file mode 100644 index 0000000..0fdc1dd --- /dev/null +++ b/noexec.gemspec @@ -0,0 +1,20 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "noexec/version" + +Gem::Specification.new do |s| + s.name = "noexec" + s.version = Noexec::VERSION + s.authors = ["Josh Hull"] + s.email = ["joshbuddy@gmail.com"] + s.homepage = "https://github.com/joshbuddy/noexec" + s.summary = %q{Stop using bundle exec} + s.description = %q{Stop using bundle exec.} + + s.rubyforge_project = "noexec" + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = ["lib"] +end