Skip to content

Commit

Permalink
Merge pull request #72 from svenfuchs/sf-bin
Browse files Browse the repository at this point in the history
Support executables
  • Loading branch information
svenfuchs authored Mar 24, 2018
2 parents 6b8753e + f2f742c commit 195f6d1
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 12 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ gem_name - name of the gem (optional, will default to the current directory name
```
--[no-]scaffold Scaffold gem files (default: true)
--dir DIR Directory to place the gem in (defaults to the given name, or the current working dir)
--bin Create an executable ./bin/[name], add executables directive to .gemspec
-t, --template NAME Template groups to use for scaffolding
--rspec Use the rspec group (by default adds .rspec and spec/spec_helper.rb)
--travis Use the rspec group (by default adds .travis.yml)
--travis Use the travis group (by default adds .travis.yml)
-l, --[no-]license NAME License(s) to add (default: mit)
-s, --strategy NAME Strategy for collecting files [glob|git] in .gemspec (default: glob)
--[no-]git Initialize a git repo (default: true)
Expand Down Expand Up @@ -269,6 +270,7 @@ gem_name - name of the gem (optional, will default to the current directory name
### Options
```
--[no]-bin Add bin files directive to the gemspec (defaults to true if a ./bin directory exists)
--dir DIR Directory to place the gem in (defaults to the given name, or the current working dir)
-l, --[no-]license NAMES License(s) to list in the gemspec
-s, --strategy Strategy for collecting files [glob|git] in gemspec (default: glob)
Expand Down
10 changes: 8 additions & 2 deletions lib/gem/release.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ module Release
Abort = Class.new(StandardError)

STRATEGIES = {
git: '`git ls-files app lib`.split("\n")',
glob: "Dir.glob('{bin/*,lib/**/*,[A-Z]*}')"
git: {
files: '`git ls-files app lib`.split("\n")',
bin_files: '`git ls-files bin`.split("\n").map { |f| File.basename(f) }',
},
glob: {
files: "Dir.glob('{bin/*,lib/**/*,[A-Z]*}')",
bin_files: "Dir.glob('bin/*').map { |f| File.basename(f) }",
}
}
end
end
Expand Down
13 changes: 12 additions & 1 deletion lib/gem/release/cmds/bootstrap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Bootstrap < Base
DEFAULTS = {
strategy: :glob,
scaffold: true,
bin: false,
git: true,
github: false,
push: false,
Expand All @@ -70,10 +71,11 @@ class Bootstrap < Base
DESCR = {
scaffold: 'Scaffold gem files',
dir: 'Directory to place the gem in (defaults to the given name, or the current working dir)',
bin: 'Create an executable ./bin/[name], add executables directive to .gemspec',
license: 'License(s) to add',
template: 'Template groups to use for scaffolding',
rspec: 'Use the rspec group (by default adds .rspec and spec/spec_helper.rb)',
travis: 'Use the rspec group (by default adds .travis.yml)',
travis: 'Use the travis group (by default adds .travis.yml)',
strategy: 'Strategy for collecting files [glob|git] in .gemspec',
git: 'Initialize a git repo',
github: 'Initialize a git repo, create on github',
Expand All @@ -89,6 +91,10 @@ class Bootstrap < Base
opts[:dir] = value
end

opt '--bin', descr(:bin) do
opts[:bin] = true
end

opt '-t', '--template NAME', descr(:template) do |value|
(opts[:templates] ||= []) << value
end
Expand Down Expand Up @@ -170,10 +176,15 @@ def scaffold

def files
files = Files::Templates.new(FILES, opts[:templates], data).all
files << executable if opts[:bin]
files << license if opts[:license]
files.compact
end

def executable
Files::Templates.executable("bin/#{gem.name}")
end

def license
file = Files::Templates.license(opts[:license], data)
warn :unknown_license, opts[:license] unless file
Expand Down
5 changes: 5 additions & 0 deletions lib/gem/release/cmds/gemspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ class Gemspec < Base
}

DESCR = {
bin: 'Add bin files directive to the gemspec (defaults to true if a ./bin directory exists)',
dir: 'Directory to place the gem in (defaults to the given name, or the current working dir)',
license: 'License(s) to list in the gemspec',
strategy: 'Strategy for collecting files [glob|git] in gemspec'
}

opt '--[no]-bin', descr(:bin) do |value|
opts[:bin] = value
end

opt '--dir DIR', descr(:dir) do |value|
opts[:dir] = value
end
Expand Down
11 changes: 10 additions & 1 deletion lib/gem/release/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ def data
licenses: licenses,
summary: '[summary]',
description: '[description]',
files: files
files: files,
bin_files: bin_files
}
end

Expand Down Expand Up @@ -61,6 +62,14 @@ def license
end

def files
strategy[:files]
end

def bin_files
strategy[:bin_files] if opts.key?(:bin) ? opts[:bin] : File.directory?('./bin')
end

def strategy
STRATEGIES[(opts[:strategy] || :glob).to_sym] || STRATEGIES[:glob]
end
end
Expand Down
6 changes: 4 additions & 2 deletions lib/gem/release/files/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ class Template
'version.rb' => 'lib/%{gem_path}/version.rb'
}

attr_accessor :source, :target, :data
attr_accessor :source, :target, :data, :opts

def initialize(source, target, data)
def initialize(source, target, data, opts)
@source = source
@target = (FILES[target] || target) % data
@data = data
@opts = opts
end

PATH = File.expand_path('../..', __FILE__)
Expand All @@ -31,6 +32,7 @@ def write
return false if exists?
FileUtils.mkdir_p(File.dirname(target))
File.write(target, render)
FileUtils.chmod('+x', target) if opts[:executable]
true
end

Expand Down
20 changes: 18 additions & 2 deletions lib/gem/release/files/templates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@ class Templates < Struct.new(:files, :groups, :data)
['../../templates/%s', __FILE__],
]

EXECUTABLE = [
['./.gem-release/executable'],
['~/.gem-release/executable'],
['../../templates/executable', __FILE__],
]

LICENSE = [
['./.gem-release/licenses'],
['~/.gem-release/licenses'],
['../../templates/licenses', __FILE__],
]

def self.executable(target)
file = Templates.new([".*"], [], {}).executable
file.target = target if file
file
end

def self.license(name, data)
file = Templates.new(["#{name}{,.*}"], [], data).license
file.target = "LICENSE#{File.extname(file.target)}" if file
Expand All @@ -43,13 +55,17 @@ def custom
templates_for(CUSTOM, '**/*')
end

def executable
templates_for(EXECUTABLE).first
end

def license
templates_for(LICENSE, files).first
end

def templates_for(sources, files)
def templates_for(sources, files = nil, opts = {})
all = Group.new(groups, data, sources, files).all
all.map { |source, target| Template.new(source, target, data) }
all.map { |source, target| Template.new(source, target, data, opts) }
end
end
end
Expand Down
4 changes: 3 additions & 1 deletion lib/gem/release/files/templates/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ def all
private

def pattern
"{#{paths.join(',')}}/{#{files.join(',')}}"
pattern = "{#{paths.join(',')}}"
pattern << "/{#{files.join(',')}}" if files.any?
pattern
end

def relative(file)
Expand Down
1 change: 1 addition & 0 deletions lib/gem/release/templates/executable
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/usr/bin/env ruby
4 changes: 3 additions & 1 deletion lib/gem/release/templates/gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ Gem::Specification.new do |s|
s.summary = '<%= summary %>'
s.description = '<%= description %>'

s.files = <%= files %>
s.files = <%= files %><% if bin_files %>
s.executables = <%= bin_files %>
<% end %>
s.platform = Gem::Platform::RUBY
s.require_paths = ['lib']
end
28 changes: 28 additions & 0 deletions spec/gem/release/cmds/bootstrap_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,34 @@
end
end

describe 'given --bin' do
cwd 'foo-bar'
let(:opts) { { bin: true } }
let(:spec) { File.read('foo-bar.gemspec') }

describe 'by default' do
run_cmd

it { should have_file 'bin/foo-bar', '#!/usr/bin/env ruby' }
end

describe 'with custom template ./.gem-release/executable' do
file './.gem-release/executable', 'foo'
run_cmd

it { should have_file 'bin/foo-bar', 'foo' }
it { expect(spec).to specify :executables, "Dir.glob('bin/*')" }
end

describe 'with custom template ~/.gem-release/executable' do
file '~/.gem-release/executable', 'foo'
run_cmd

it { should have_file 'bin/foo-bar', 'foo' }
it { expect(spec).to specify :executables, "Dir.glob('bin/*')" }
end
end

describe 'given --rspec' do
let(:opts) { { rspec: true } }

Expand Down
46 changes: 46 additions & 0 deletions spec/gem/release/cmds/gemspec_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,52 @@
end
end

describe 'bin files' do
describe 'given --bin' do
run_cmd

describe 'default (glob)' do
let(:opts) { { bin: true } }
it { expect(spec).to specify :executables, "Dir.glob('bin/*')" }
end

describe 'given --strategy git' do
let(:opts) { { bin: true, strategy: :git } }
it { expect(spec).to specify :executables, '`git ls-files bin`' }
end
end

describe 'given a directory ./bin' do
file './bin/foo'
run_cmd

describe 'default (glob)' do
it { expect(spec).to specify :executables, "Dir.glob('bin/*')" }
end

describe 'given --strategy git' do
let(:opts) { { strategy: :git } }
it { expect(spec).to specify :executables, '`git ls-files bin`' }
end
end

describe 'given --no-bin and a directory ./bin' do
file './bin/foo'
run_cmd

describe 'default (glob)' do
let(:opts) { { bin: false } }
it { expect(spec).to_not specify :executables }
end

describe 'given --strategy git' do
let(:opts) { { bin: false, strategy: :git } }
it { expect(spec).to_not specify :executables }
end
end

end

describe 'license' do
run_cmd

Expand Down
2 changes: 1 addition & 1 deletion spec/support/matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def version(path)
RSpec::Matchers.define :specify do |name, value|
match do |gemspec|
line = gemspec.split("\n").detect { |line| line =~ /#{name}\s+=/ }
line.include?(value)
line && line.include?(value)
end

failure_message do |gemspec|
Expand Down

0 comments on commit 195f6d1

Please sign in to comment.