duct 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +72 -8
- data/Rakefile +7 -1
- data/bin/duct +8 -0
- data/duct.gemspec +5 -2
- data/examples/sinatra.rb +32 -0
- data/lib/duct.rb +3 -5
- data/lib/duct/cli.rb +58 -0
- data/lib/duct/runner.rb +59 -0
- data/lib/duct/version.rb +1 -1
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/cli_spec.rb +50 -0
- metadata +50 -20
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: f20e93081ed84a57df274ce99797d4aba409c43e
|
|
4
|
+
data.tar.gz: f075c2159472292ee1cb0f6cae1927b06cb2a8a8
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0b8619568bf00163da213ee8bd4ea5480d582101b9dcc7916fb9a4cca4032126682f27488b23694f2897d274b8dd8a0710adea06ee9ae4c7616ec0c8740c4fc8
|
|
7
|
+
data.tar.gz: 76cde8fe434e75b2101bf13d92cc3a96d095141aeb08a6cd78017c6f09d56d5f7c6627660ef8f8810638a62df88d8f5d079f79c6b6c3f198e1ca80a8130aaa67
|
data/README.md
CHANGED
|
@@ -1,24 +1,84 @@
|
|
|
1
1
|
# Duct
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Duct is a small wrapper around [bundler](http://bundler.io/). It allows you to embed a Gemfile in a script.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Usecase
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Sometimes you write small scripts to do different tasks. Sometimes you store them for future use. Sometimes those
|
|
10
|
+
scripts use some gems to do their task (database access, web requests, whatever). So, after some time, you reuse them
|
|
11
|
+
and you don't know which version of which gems did you use and you can run into trouble (like with full fledged apps in
|
|
12
|
+
the pre-bundler days). That's when you do the obvious workaround: create a directory to store the script together with a
|
|
13
|
+
`Gemfile` and a `Gemfile.lock`.
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
That's a good solution but feels a bit overkill. Duct allows you to embed the `Gemfile` (and the `Gemfile.lock`) in the same file, so it's a single file to store together with others, as a [gist](https://gist.github.com/), etc.
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
## Installation
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
Duct is a command line utility, so just install it via rubygems:
|
|
16
20
|
|
|
17
21
|
$ gem install duct
|
|
18
22
|
|
|
19
23
|
## Usage
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
First, write your `Gemfile` in the data section of your script, after the `__END__` label, and after a `@@ Gemfile`
|
|
26
|
+
label:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
require 'sinatra'
|
|
30
|
+
|
|
31
|
+
get '/' do
|
|
32
|
+
'Hello, world!'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
__END__
|
|
36
|
+
@@ Gemfile
|
|
37
|
+
source 'https://rubygems.org'
|
|
38
|
+
|
|
39
|
+
gem 'sinatra'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
(this is very much like the [Sinatra inline templates](http://www.sinatrarb.com/intro.html#Inline%20Templates), and can
|
|
43
|
+
in fact be combined with them).
|
|
44
|
+
|
|
45
|
+
Then, run the script using the `duct` command:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
$ duct my_script.rb
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The default action is running the script, checking previously whether dependencies are met, and installing them (via
|
|
52
|
+
`bundle install`) if needed. Notice that your script data section will be updated with a section for the `Gemfile.lock`
|
|
53
|
+
if needed (beware of conflicts with your editor while you develop the script).
|
|
54
|
+
|
|
55
|
+
### Passing parameters
|
|
56
|
+
|
|
57
|
+
If your script expects parameters, just pass them after the filename:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
$ duct my_script.rb param1 param2
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Updating the bundle
|
|
64
|
+
|
|
65
|
+
You can run any of the `bundle` subcommands (mainly `update`, with or without a gem name, but also `outdated`, `check`,
|
|
66
|
+
`list`, `show` and [all the rest](http://bundler.io/v1.5/man/bundle.1.html#PRIMARY-COMMANDS)) passing them *before* the
|
|
67
|
+
filename:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
$ duct update sinatra my_script.rb
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Remember that updating the bundle will update the `Gemfile.lock` section in your script, so remember to save those
|
|
74
|
+
changes.
|
|
75
|
+
|
|
76
|
+
### Using the script data
|
|
77
|
+
|
|
78
|
+
Duct will ignore the part of the data section **before** the first `@@ XYZ` label (and the sections with other labels
|
|
79
|
+
than `@@ Gemfile` and `@@ Gemfile.lock`, as it was mentioned for the Sinatra inline templates case), so you can still
|
|
80
|
+
use that ruby feature, but you will need to make sure your script handles and ignores the `Gemfile` and `Gemfile.lock`
|
|
81
|
+
sections, of course.
|
|
22
82
|
|
|
23
83
|
## Contributing
|
|
24
84
|
|
|
@@ -27,3 +87,7 @@ TODO: Write usage instructions here
|
|
|
27
87
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
28
88
|
4. Push to the branch (`git push origin my-new-feature`)
|
|
29
89
|
5. Create new Pull Request
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
Released under the MIT License, Copyright (c) 2014 Sergio Gil.
|
data/Rakefile
CHANGED
data/bin/duct
ADDED
data/duct.gemspec
CHANGED
|
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
|
8
8
|
spec.version = Duct::VERSION
|
|
9
9
|
spec.authors = ["Sergio Gil"]
|
|
10
10
|
spec.email = ["sgilperez@gmail.com"]
|
|
11
|
-
spec.description = %q{
|
|
12
|
-
spec.summary = %q{
|
|
11
|
+
spec.description = %q{Embeds a Gemfile in a script}
|
|
12
|
+
spec.summary = %q{Embeds a Gemfile in a script}
|
|
13
13
|
spec.homepage = "https://github.com/porras/duct"
|
|
14
14
|
spec.license = "MIT"
|
|
15
15
|
|
|
@@ -18,6 +18,9 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
+
spec.add_dependency "bundler"
|
|
22
|
+
|
|
21
23
|
spec.add_development_dependency "bundler", "~> 1.3"
|
|
22
24
|
spec.add_development_dependency "rake"
|
|
25
|
+
spec.add_development_dependency "rspec"
|
|
23
26
|
end
|
data/examples/sinatra.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
|
|
3
|
+
get '/' do
|
|
4
|
+
@name = params[:name] || 'world'
|
|
5
|
+
erb :index
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
__END__
|
|
9
|
+
@@ Gemfile
|
|
10
|
+
source 'https://rubygems.org'
|
|
11
|
+
|
|
12
|
+
gem 'sinatra'
|
|
13
|
+
@@ Gemfile.lock
|
|
14
|
+
GEM
|
|
15
|
+
remote: https://rubygems.org/
|
|
16
|
+
specs:
|
|
17
|
+
rack (1.5.2)
|
|
18
|
+
rack-protection (1.5.1)
|
|
19
|
+
rack
|
|
20
|
+
sinatra (1.4.4)
|
|
21
|
+
rack (~> 1.4)
|
|
22
|
+
rack-protection (~> 1.4)
|
|
23
|
+
tilt (~> 1.3, >= 1.3.4)
|
|
24
|
+
tilt (1.4.1)
|
|
25
|
+
|
|
26
|
+
PLATFORMS
|
|
27
|
+
ruby
|
|
28
|
+
|
|
29
|
+
DEPENDENCIES
|
|
30
|
+
sinatra
|
|
31
|
+
@@ index
|
|
32
|
+
Hello, <%= @name %>!
|
data/lib/duct.rb
CHANGED
data/lib/duct/cli.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'duct/runner'
|
|
2
|
+
|
|
3
|
+
module Duct
|
|
4
|
+
class Cli
|
|
5
|
+
BUNDLER_COMMANDS = %w{
|
|
6
|
+
update
|
|
7
|
+
check
|
|
8
|
+
list
|
|
9
|
+
show
|
|
10
|
+
outdated
|
|
11
|
+
console
|
|
12
|
+
open
|
|
13
|
+
viz
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
USAGE = %Q{Commands:
|
|
17
|
+
duct myscript.rb [param1 param2] # Installs bundle included in myscript.rb if needed and
|
|
18
|
+
# runs myscript with optional parameters.
|
|
19
|
+
duct update sinatra myscript.rb # Runs specified bundler command on the bundled included
|
|
20
|
+
# in myscript, passing the additional parameters. Available
|
|
21
|
+
# commands: #{BUNDLER_COMMANDS.join(', ')}.
|
|
22
|
+
# Run bundle help for more info.}
|
|
23
|
+
|
|
24
|
+
def initialize(args)
|
|
25
|
+
@args = args
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def filename
|
|
29
|
+
command ? @args.last : @args.first
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def command
|
|
33
|
+
@args[0..-2].join(' ') if BUNDLER_COMMANDS.include?(@args.first)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def params
|
|
37
|
+
command ? [] : @args[1..-1]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def error?
|
|
41
|
+
!(command || filename)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def run
|
|
45
|
+
if error?
|
|
46
|
+
puts(USAGE)
|
|
47
|
+
exit(-1)
|
|
48
|
+
end
|
|
49
|
+
runner.run
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def runner
|
|
55
|
+
@runner ||= Duct::Runner.new(self)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/duct/runner.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'tmpdir'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
|
|
4
|
+
module Duct
|
|
5
|
+
class Runner
|
|
6
|
+
def initialize(config)
|
|
7
|
+
@config = config
|
|
8
|
+
@script, @data = File.read(@config.filename).split(/^__END__$/, 2)
|
|
9
|
+
@preamble = @data.split(/^@@\s*(.*\S)\s*$/, 2).first
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
copy_embedded_files
|
|
14
|
+
system "BUNDLE_GEMFILE=#{tempdir}/Gemfile bundle #{@config.command}"
|
|
15
|
+
update_embedded_files
|
|
16
|
+
exec "BUNDLE_GEMFILE=#{tempdir}/Gemfile bundle exec ruby #{@config.filename} #{@config.params.join(' ')}; rm -rf #{tempdir}" unless @config.command
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def copy_embedded_files
|
|
22
|
+
embedded_files.each do |file, contents|
|
|
23
|
+
IO.write("#{tempdir}/#{file}", contents)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def update_embedded_files
|
|
28
|
+
contents = @script.dup
|
|
29
|
+
|
|
30
|
+
contents << "__END__"
|
|
31
|
+
contents << @preamble
|
|
32
|
+
|
|
33
|
+
Dir.glob("#{tempdir}/*") do |filename|
|
|
34
|
+
contents << "@@ #{File.basename(filename)}\n"
|
|
35
|
+
contents << File.read(filename)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
IO.write(@config.filename, contents)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def embedded_files
|
|
42
|
+
@embedded_files ||= {}.tap do |files|
|
|
43
|
+
file = nil
|
|
44
|
+
@data.each_line do |line|
|
|
45
|
+
if line =~ /^@@\s*(.*\S)\s*$/
|
|
46
|
+
file = ''
|
|
47
|
+
files[$1.to_sym] = file
|
|
48
|
+
elsif file
|
|
49
|
+
file << line
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def tempdir
|
|
56
|
+
@tempdir ||= Dir.mktmpdir
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
data/lib/duct/version.rb
CHANGED
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'duct/cli'
|
|
3
|
+
|
|
4
|
+
describe Duct::Cli do
|
|
5
|
+
subject { Duct::Cli.new(argv) }
|
|
6
|
+
|
|
7
|
+
context 'just filename' do
|
|
8
|
+
let(:argv) { ['myscript.rb'] }
|
|
9
|
+
|
|
10
|
+
its(:filename) { should == 'myscript.rb' }
|
|
11
|
+
its(:command) { should be_nil }
|
|
12
|
+
its(:params) { should be_empty }
|
|
13
|
+
its(:error?) { should be_false }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context 'filename and params' do
|
|
17
|
+
let(:argv) { ['myscript.rb', 'param1', 'param2'] }
|
|
18
|
+
|
|
19
|
+
its(:filename) { should == 'myscript.rb' }
|
|
20
|
+
its(:command) { should be_nil }
|
|
21
|
+
its(:params) { should == ['param1', 'param2'] }
|
|
22
|
+
its(:error?) { should be_false }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'command and filename' do
|
|
26
|
+
let(:argv) { ['update', 'myscript.rb'] }
|
|
27
|
+
|
|
28
|
+
its(:filename) { should == 'myscript.rb' }
|
|
29
|
+
its(:command) { should == 'update' }
|
|
30
|
+
its(:params) { should be_empty }
|
|
31
|
+
its(:error?) { should be_false }
|
|
32
|
+
|
|
33
|
+
context 'with params for the command' do
|
|
34
|
+
let(:argv) { ['update', 'sinatra', 'myscript.rb'] }
|
|
35
|
+
|
|
36
|
+
its(:filename) { should == 'myscript.rb' }
|
|
37
|
+
its(:command) { should == 'update sinatra' }
|
|
38
|
+
its(:params) { should be_empty }
|
|
39
|
+
its(:error?) { should be_false }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'errors' do
|
|
44
|
+
context 'nothing' do
|
|
45
|
+
let(:argv) { [] }
|
|
46
|
+
|
|
47
|
+
its(:error?) { should be_true }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
metadata
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: duct
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 0.1.0
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Sergio Gil
|
|
9
8
|
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date: 2014-01-
|
|
11
|
+
date: 2014-01-13 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: bundler
|
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
|
|
16
|
+
requirements:
|
|
17
|
+
- - '>='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - '>='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
18
30
|
requirements:
|
|
19
31
|
- - ~>
|
|
20
32
|
- !ruby/object:Gem::Version
|
|
@@ -22,7 +34,6 @@ dependencies:
|
|
|
22
34
|
type: :development
|
|
23
35
|
prerelease: false
|
|
24
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
-
none: false
|
|
26
37
|
requirements:
|
|
27
38
|
- - ~>
|
|
28
39
|
- !ruby/object:Gem::Version
|
|
@@ -30,23 +41,36 @@ dependencies:
|
|
|
30
41
|
- !ruby/object:Gem::Dependency
|
|
31
42
|
name: rake
|
|
32
43
|
requirement: !ruby/object:Gem::Requirement
|
|
33
|
-
none: false
|
|
34
44
|
requirements:
|
|
35
|
-
- -
|
|
45
|
+
- - '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - '>='
|
|
36
60
|
- !ruby/object:Gem::Version
|
|
37
61
|
version: '0'
|
|
38
62
|
type: :development
|
|
39
63
|
prerelease: false
|
|
40
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
-
none: false
|
|
42
65
|
requirements:
|
|
43
|
-
- -
|
|
66
|
+
- - '>='
|
|
44
67
|
- !ruby/object:Gem::Version
|
|
45
68
|
version: '0'
|
|
46
|
-
description:
|
|
69
|
+
description: Embeds a Gemfile in a script
|
|
47
70
|
email:
|
|
48
71
|
- sgilperez@gmail.com
|
|
49
|
-
executables:
|
|
72
|
+
executables:
|
|
73
|
+
- duct
|
|
50
74
|
extensions: []
|
|
51
75
|
extra_rdoc_files: []
|
|
52
76
|
files:
|
|
@@ -55,33 +79,39 @@ files:
|
|
|
55
79
|
- LICENSE.txt
|
|
56
80
|
- README.md
|
|
57
81
|
- Rakefile
|
|
82
|
+
- bin/duct
|
|
58
83
|
- duct.gemspec
|
|
84
|
+
- examples/sinatra.rb
|
|
59
85
|
- lib/duct.rb
|
|
86
|
+
- lib/duct/cli.rb
|
|
87
|
+
- lib/duct/runner.rb
|
|
60
88
|
- lib/duct/version.rb
|
|
89
|
+
- spec/spec_helper.rb
|
|
90
|
+
- spec/unit/cli_spec.rb
|
|
61
91
|
homepage: https://github.com/porras/duct
|
|
62
92
|
licenses:
|
|
63
93
|
- MIT
|
|
94
|
+
metadata: {}
|
|
64
95
|
post_install_message:
|
|
65
96
|
rdoc_options: []
|
|
66
97
|
require_paths:
|
|
67
98
|
- lib
|
|
68
99
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
|
-
none: false
|
|
70
100
|
requirements:
|
|
71
|
-
- -
|
|
101
|
+
- - '>='
|
|
72
102
|
- !ruby/object:Gem::Version
|
|
73
103
|
version: '0'
|
|
74
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
|
-
none: false
|
|
76
105
|
requirements:
|
|
77
|
-
- -
|
|
106
|
+
- - '>='
|
|
78
107
|
- !ruby/object:Gem::Version
|
|
79
108
|
version: '0'
|
|
80
109
|
requirements: []
|
|
81
110
|
rubyforge_project:
|
|
82
|
-
rubygems_version:
|
|
111
|
+
rubygems_version: 2.0.3
|
|
83
112
|
signing_key:
|
|
84
|
-
specification_version:
|
|
85
|
-
summary:
|
|
86
|
-
test_files:
|
|
87
|
-
|
|
113
|
+
specification_version: 4
|
|
114
|
+
summary: Embeds a Gemfile in a script
|
|
115
|
+
test_files:
|
|
116
|
+
- spec/spec_helper.rb
|
|
117
|
+
- spec/unit/cli_spec.rb
|