Last active
August 8, 2019 08:51
-
-
Save tijn/fa4ba9361a0eab9ef832e8f82e6dd231 to your computer and use it in GitHub Desktop.
install-ruby-shim
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'erb' | |
require 'optparse' | |
require 'pathname' | |
PROJECT_ROOT_FILES = %w(.ruby-version Gemfile .env) | |
$verbose = false | |
$force = false | |
$dry_run = false | |
optionparser = OptionParser.new do |parser| | |
parser.banner = "Usage: #{$0} [options] PATH" | |
parser.separator '' | |
parser.separator 'Install a shim in ~/bin for your Ruby project. Use this instead of a symlink if your script depends on bundler or rbenv.' | |
parser.separator '' | |
parser.on("-d", "--[no-]dry-run", "print shim to stdout; do not write to file") do |d| | |
$dry_run = d | |
end | |
parser.on("-f", "--[no-]force", "Overwrite shim if it already exists") do |f| | |
$force = f | |
end | |
parser.on("-v", "--[no-]verbose", "Run verbosely") do |v| | |
$verbose = v | |
end | |
parser.on_tail("-h", "--help", "Show this message") do | |
puts parser | |
exit | |
end | |
end | |
optionparser.parse!(ARGV) | |
if ARGV.empty? | |
$stderr.puts "PATH is missing." | |
$stderr.puts | |
abort optionparser.to_s | |
end | |
def info(*string) | |
$stderr.puts(*string) if $verbose | |
end | |
def detect_project_root(dir) | |
Pathname.new(dir).ascend do |path| | |
return path.to_s if PROJECT_ROOT_FILES.any? { |filename| File.exist?("#{path}/#{filename}") } | |
end | |
abort "Cannot find #{PROJECT_ROOT_FILES.join(' or ')} for executable." | |
end | |
class String | |
def lchomp(match) | |
if index(match) == 0 | |
self[match.size..-1] | |
else | |
self.dup | |
end | |
end | |
end | |
# Set project_root, subdir, and basename | |
target = ARGV.first | |
full_path = File.absolute_path target | |
project_root = detect_project_root(full_path) | |
subdir = File.dirname(full_path).lchomp(project_root) | |
basename = File.basename(target) | |
info "project root = #{project_root}" | |
info "subdir = #{subdir}" | |
info "basename = #{basename}" | |
if project_root.start_with?(ENV['HOME']) | |
project_root = project_root.sub(ENV['HOME'], '$HOME') | |
info "normalized project root = #{project_root}" | |
end | |
# Generate the script | |
script = ERB.new(DATA.read).result(binding) # the call to #binding gives the template access to all vars | |
if $dry_run | |
puts script | |
exit 0 | |
end | |
# Write the shim | |
shim = "#{ENV['HOME']}/bin/#{basename}" | |
abort "File #{shim} already exists. Use --force to overwrite it." if File.exist?(shim) && !$force | |
File.write(shim, script) | |
`chmod +x #{shim}` | |
__END__ | |
#!/bin/sh | |
# A very very stupid shim that seems to work fine for my projects | |
# The good thing about it is that it: | |
# | |
# 1. is stupidly simple | |
# 2. does not change the working directory! | |
# 3. does not change anything besides two ENV variables | |
dir=<%= project_root %> | |
export RBENV_DIR=$dir | |
export BUNDLE_GEMFILE=$dir/Gemfile | |
$dir<%= subdir %>/$(basename "$0") "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment