spitball 0.2.5 → 0.3.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.
data/Rakefile CHANGED
@@ -22,10 +22,10 @@ begin
22
22
  gem.description = "Use bundler to generate gem tarball packages."
23
23
  gem.email = "freels@twitter.com"
24
24
  gem.homepage = "http://github.com/freels/spitball"
25
- gem.authors = ["Matt Freels", "Brandon Mitchell"]
25
+ gem.authors = ["Matt Freels", "Brandon Mitchell", "Joshua Hull"]
26
26
 
27
- gem.add_dependency 'bundler', '>= 0.9.5'
28
- gem.add_dependency 'sinatra', '>= 1.0'
27
+ gem.add_dependency 'bundler', '~> 1.0.0'
28
+ gem.add_dependency 'sinatra', '~> 1.0'
29
29
 
30
30
  gem.add_development_dependency 'rspec'
31
31
  gem.add_development_dependency 'rr'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.5
1
+ 0.3.0
data/bin/spitball CHANGED
@@ -37,7 +37,6 @@ end
37
37
 
38
38
  opts.permute!(ARGV)
39
39
 
40
-
41
40
  args[:gemfile] = ARGV[0]
42
41
  args[:destination] = ARGV[1]
43
42
 
@@ -47,9 +46,10 @@ unless args[:gemfile] and args[:destination]
47
46
  end
48
47
 
49
48
  gemfile = File.read(args[:gemfile])
49
+ gemfile_lock = File.read("#{args[:gemfile]}.lock")
50
50
 
51
51
  ball = args[:host] ?
52
- Spitball::Remote.new(gemfile, args[:host], (args[:port] || 8080).to_i) :
53
- Spitball.new(gemfile, :without => args[:without])
52
+ Spitball::Remote.new(gemfile, gemfile_lock, :host => args[:host], :port => (args[:port] || 8080).to_i) :
53
+ Spitball.new(gemfile, gemfile_lock, :without => args[:without])
54
54
 
55
55
  ball.copy_to args[:destination]
data/bin/spitball-server CHANGED
@@ -20,6 +20,7 @@ OptionParser.new { |op|
20
20
  set :run, true
21
21
 
22
22
  mime_type :gemfile, 'text/plain'
23
+ mime_type :lock, 'text/plain'
23
24
  mime_type :tgz, 'application/x-compressed'
24
25
 
25
26
  # return json array of cached SHAs
@@ -33,7 +34,7 @@ get '/:digest.:format' do |digest, format|
33
34
  error 400 unless ['tgz', 'gemfile'].include? format
34
35
 
35
36
  # this returns 404 on Errno::ENOENT
36
- send_file Spitball::Repo.path(digest, format), :type => format
37
+ send_file Spitball::Repo.bundle_path(digest, format), :type => format
37
38
  end
38
39
 
39
40
  class Streamer
@@ -45,7 +46,7 @@ end
45
46
  # 202 Accepted if it does not. The body of the response is the URI for
46
47
  # the tarball.
47
48
  post '/create' do
48
- ball = Spitball.new(request.body.read)
49
+ ball = Spitball.new(params['gemfile'], params['gemfile_lock'])
49
50
  url = "#{request.url.split("/create").first}/#{ball.digest}.tgz"
50
51
  response['Location'] = url
51
52
 
@@ -55,18 +56,30 @@ post '/create' do
55
56
  else
56
57
  status 202
57
58
 
58
- pid = open("|-")
59
+ i,o = IO.pipe
59
60
 
60
- if pid == nil # child
61
- begin
62
- ball.cache!
63
- rescue Object => e
64
- puts "#{e.class}: #{e}", e.backtrace.map{|l| "\t#{l}" }
65
- exit! 1
61
+ # fork twice. once so we can have a pid to detach from in order to clean up,
62
+ # twice in order to properly redirect stdout for underlying shell commands.
63
+ pid = fork do
64
+ baller = open("|-")
65
+ if baller == nil # child
66
+ begin
67
+ ball.cache!
68
+ rescue Object => e
69
+ puts "#{e.class}: #{e}", e.backtrace.map{|l| "\t#{l}" }
70
+ end
71
+ else
72
+ while buf = baller.read(200)
73
+ $stdout.print buf
74
+ o.print buf
75
+ end
66
76
  end
67
77
  exit!
68
78
  end
69
79
 
70
- Streamer.new(pid)
80
+ o.close
81
+ Process.detach(pid)
82
+
83
+ Streamer.new(i)
71
84
  end
72
85
  end
@@ -0,0 +1,27 @@
1
+ module Bundler
2
+ class FakeDsl
3
+
4
+ def initialize(file)
5
+ @groups = Hash.new{|h, k| h[k] = []}
6
+ instance_eval(file)
7
+ end
8
+
9
+ def __groups
10
+ @groups
11
+ end
12
+
13
+ def group(name, &blk)
14
+ @current_group = name.to_sym
15
+ instance_eval(&blk)
16
+ @current_group = nil
17
+ end
18
+ alias_method :groups, :group
19
+
20
+ def gem(*args)
21
+ @groups[@current_group] << args.first
22
+ end
23
+
24
+ def method_missing(*args)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,108 @@
1
+ require "strscan"
2
+
3
+ module Bundler
4
+ class FakeLockfileParser
5
+ attr_reader :sources, :dependencies, :specs, :platforms
6
+
7
+ def initialize(lockfile)
8
+ @platforms = []
9
+ @sources = []
10
+ @dependencies = []
11
+ @specs = []
12
+ @state = :source
13
+
14
+ lockfile.split(/(\r?\n)+/).each do |line|
15
+ if line == "DEPENDENCIES"
16
+ @state = :dependency
17
+ elsif line == "PLATFORMS"
18
+ @state = :platform
19
+ else
20
+ send("parse_#{@state}", line)
21
+ end
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ TYPES = {
28
+ "GIT" => Bundler::Source::Git,
29
+ "GEM" => Bundler::Source::Rubygems,
30
+ "PATH" => Bundler::Source::Path
31
+ }
32
+
33
+ def parse_source(line)
34
+ case line
35
+ when "GIT", "GEM", "PATH"
36
+ @current_source = nil
37
+ @opts, @type = {}, line
38
+ when " specs:"
39
+ @current_source = TYPES[@type].from_lock(@opts)
40
+ @sources << @current_source
41
+ when /^ ([a-z]+): (.*)$/i
42
+ value = $2
43
+ value = true if value == "true"
44
+ value = false if value == "false"
45
+
46
+ key = $1
47
+
48
+ if @opts[key]
49
+ @opts[key] = Array(@opts[key])
50
+ @opts[key] << value
51
+ else
52
+ @opts[key] = value
53
+ end
54
+ else
55
+ parse_spec(line)
56
+ end
57
+ end
58
+
59
+ NAME_VERSION = '(?! )(.*?)(?: \(([^-]*)(?:-(.*))?\))?'
60
+
61
+ def parse_dependency(line)
62
+ if line =~ %r{^ {2}#{NAME_VERSION}(!)?$}
63
+ name, version, pinned = $1, $2, $4
64
+ version = version.split(",").map { |d| d.strip } if version
65
+
66
+ dep = Bundler::Dependency.new(name, version)
67
+
68
+ if pinned && dep.name != 'bundler'
69
+ spec = @specs.find { |s| s.name == dep.name }
70
+ dep.source = spec.source if spec
71
+
72
+ # Path sources need to know what the default name / version
73
+ # to use in the case that there are no gemspecs present. A fake
74
+ # gemspec is created based on the version set on the dependency
75
+ # TODO: Use the version from the spec instead of from the dependency
76
+ if version && version.size == 1 && version.first =~ /^\s*= (.+)\s*$/ && dep.source.is_a?(Bundler::Source::Path)
77
+ dep.source.name = name
78
+ dep.source.version = $1
79
+ end
80
+ end
81
+
82
+ @dependencies << dep
83
+ end
84
+ end
85
+
86
+ def parse_spec(line)
87
+ if line =~ %r{^ {4}#{NAME_VERSION}$}
88
+ name, version = $1, Gem::Version.new($2)
89
+ platform = $3 ? Gem::Platform.new($3) : Gem::Platform::RUBY
90
+ @current_spec = LazySpecification.new(name, version, platform)
91
+ @current_spec.source = @current_source
92
+ @specs << @current_spec
93
+ elsif line =~ %r{^ {6}#{NAME_VERSION}$}
94
+ name, version = $1, $2
95
+ version = version.split(',').map { |d| d.strip } if version
96
+ dep = Gem::Dependency.new(name, version)
97
+ @current_spec.dependencies << dep
98
+ end
99
+ end
100
+
101
+ def parse_platform(line)
102
+ if line =~ /^ (.*)$/
103
+ @platforms << Gem::Platform.new($1)
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -2,7 +2,7 @@ require 'digest/sha1'
2
2
 
3
3
  module Spitball::Digest
4
4
  def digest
5
- @digest ||= ::Digest::SHA1.hexdigest "#{options.to_a.sort}:#{gemfile}"
5
+ @digest ||= ::Digest::SHA1.hexdigest "#{options.to_a.sort}:#{gemfile_lock}"
6
6
  end
7
7
 
8
8
  def hash
@@ -3,10 +3,11 @@ require 'uri'
3
3
 
4
4
  class Spitball::Remote
5
5
 
6
- def initialize(gemfile, host, port)
6
+ def initialize(gemfile, gemfile_lock, opts = {})
7
7
  @gemfile = gemfile
8
- @host = host
9
- @port = port
8
+ @gemfile_lock = gemfile_lock
9
+ @host = opts[:host]
10
+ @port = opts[:port]
10
11
  end
11
12
 
12
13
  def copy_to(path)
@@ -18,10 +19,11 @@ class Spitball::Remote
18
19
 
19
20
  def generate_remote_tarball
20
21
  url = URI.parse("http://#{@host}:#{@port}/create")
21
- res = Net::HTTP.start(url.host, url.port) do |http|
22
- http.post(url.path, @gemfile) do |body|
23
- print body
24
- end
22
+ req = Net::HTTP::Post.new(url.path)
23
+ req.form_data = {'gemfile' => @gemfile, 'gemfile_lock' => @gemfile_lock}
24
+
25
+ res = Net::HTTP.new(url.host, url.port).start do |http|
26
+ http.request(req) {|r| puts r.read_body }
25
27
  end
26
28
 
27
29
  print "\nDownloading tarball..."; $stdout.flush
data/lib/spitball/repo.rb CHANGED
@@ -3,21 +3,25 @@ module Spitball::Repo
3
3
 
4
4
  WORKING_DIR = ENV['SPITBALL_CACHE'] || '/tmp/spitball'
5
5
 
6
- def path(digest, extension = nil)
6
+ def bundle_path(digest, extension = nil)
7
7
  extension = ".#{extension}" unless extension.nil? or extension.empty?
8
8
  File.join WORKING_DIR, "bundle_#{digest}#{extension}"
9
9
  end
10
10
 
11
+ def gemcache_path
12
+ File.join(WORKING_DIR, "gemcache")
13
+ end
14
+
15
+ def gemfile(digest)
16
+ bundle_path digest, 'gemfile'
17
+ end
18
+
11
19
  def exist?(digest)
12
20
  File.exist? tarball(digest)
13
21
  end
14
22
 
15
23
  def tarball(digest)
16
- path(digest, 'tgz')
17
- end
18
-
19
- def gemfile(digest)
20
- path(digest, 'gemfile')
24
+ bundle_path(digest, 'tgz')
21
25
  end
22
26
 
23
27
  def cached_digests
@@ -26,8 +30,8 @@ module Spitball::Repo
26
30
  end.compact.uniq.sort
27
31
  end
28
32
 
29
- def make_cache_dir
30
- FileUtils.mkdir_p WORKING_DIR
33
+ def make_cache_dirs
34
+ FileUtils.mkdir_p File.join(WORKING_DIR, "gemcache")
31
35
  end
32
36
 
33
37
  def clean_up_unused(access_window)
data/lib/spitball.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  require 'fileutils'
2
+ require 'digest/md5'
3
+ require 'bundler'
4
+ require 'ext/bundler_lockfile_parser'
5
+ require 'ext/bundler_fake_dsl'
2
6
 
3
7
  class Spitball
4
8
  require 'spitball/digest'
@@ -14,11 +18,13 @@ class Spitball
14
18
 
15
19
  include Spitball::Digest
16
20
 
17
- attr_reader :gemfile, :options
21
+ attr_reader :gemfile, :gemfile_lock, :without, :options
18
22
 
19
- def initialize(gemfile, options = {})
20
- @gemfile = gemfile
21
- @options = options
23
+ def initialize(gemfile, gemfile_lock, options = {})
24
+ @gemfile = gemfile
25
+ @gemfile_lock = gemfile_lock
26
+ @options = options
27
+ @without = (options[:without] || []).map{|w| w.to_sym}
22
28
  end
23
29
 
24
30
  def copy_to(dest)
@@ -31,14 +37,12 @@ class Spitball
31
37
  end
32
38
 
33
39
  def cache!(sync = true)
34
- Spitball::Repo.make_cache_dir
35
-
40
+ Spitball::Repo.make_cache_dirs
36
41
  unless cached?
37
42
  lock = Spitball::FileLock.new(bundle_path('lock'))
38
-
39
43
  if lock.acquire_lock
40
44
  begin
41
- create_bundle
45
+ create_bundle
42
46
  ensure
43
47
  lock.release_lock
44
48
  end
@@ -49,43 +53,66 @@ class Spitball
49
53
  end
50
54
 
51
55
  def create_bundle
56
+ ENV['BUNDLE_GEMFILE'] = gemfile_path # make bundler happy! :) *cry*
57
+ Spitball::Repo.make_cache_dirs
52
58
  FileUtils.mkdir_p bundle_path
53
59
 
60
+ # save gemfile and lock file for future reference.
54
61
  File.open(gemfile_path, 'w') {|f| f.write gemfile }
62
+ File.open(gemfile_lock_path, 'w') {|f| f.write gemfile_lock }
55
63
 
56
- if system "cd #{bundle_path} && bundle install #{bundle_path} --disable-shared-gems #{without_clause} 2>&1"
64
+ parsed_lockfile, dsl = Bundler::FakeLockfileParser.new(gemfile_lock), Bundler::FakeDsl.new(gemfile)
57
65
 
58
- # rewrite bang lines to #!/usr/bin/env ruby
59
- # in serious lameness, OS X sed (more posix compliant?) requires
60
- # a slightly different sed incantation for in place editing
61
- if Dir["#{bundle_path}/bin/*"].length > 0
62
- if RUBY_PLATFORM =~ /linux/
63
- system "cd #{bundle_path} && find bin/* -exec sed -i'' '1,1 s|^#!/.*/ruby[ ]*|#!/usr/bin/env ruby|' {} \\;"
64
- else
65
- system "cd #{bundle_path} && find bin/* -exec sed -i '' '1,1 s|^#!/.*/ruby[ ]*|#!/usr/bin/env ruby|' {} \\;"
66
- end
66
+ Dir.chdir(Repo.gemcache_path) do
67
+ parsed_lockfile.specs.each do |spec|
68
+ install_gem(spec, parsed_lockfile.sources) unless without.any?{|w| dsl.__groups[w].include?(spec.name)}
67
69
  end
70
+ end
68
71
 
69
- system "tar czf #{tarball_path}.#{Process.pid} -C #{bundle_path} ."
70
- system "mv #{tarball_path}.#{Process.pid} #{tarball_path}"
71
- else
72
- raise BundleCreationFailure, "Bundle build failure."
72
+ Dir.chdir(bundle_path) do
73
+ Dir["#{bundle_path}/bin/**"].each do |file|
74
+ contents = File.read(file)
75
+ contents.gsub!(/^#!.*?\n/, "#!/usr/bin/env ruby\n")
76
+ File.open(file, 'w') {|f| f << contents}
77
+ end
73
78
  end
74
79
 
80
+ system "rm -rf #{bundle_path}/cache"
81
+ system "tar czf #{tarball_path}.#{Process.pid} -C #{bundle_path} ."
82
+ system "mv #{tarball_path}.#{Process.pid} #{tarball_path}"
75
83
  FileUtils.rm_rf bundle_path
76
84
  end
77
85
 
78
- def without_clause
79
- without = Array(options[:without] || [])
80
- return '' if without.empty?
86
+ def install_gem(spec, sources)
87
+ cache_dir = File.join(Repo.gemcache_path, "#{spec.name}-#{::Digest::MD5.hexdigest([spec.name, spec.version, sources_opt(sources)].join('/'))}")
88
+ unless File.exist?(cache_dir)
89
+ FileUtils.mkdir_p(cache_dir)
90
+ out = `gem install #{spec.name} -v'#{spec.version}' --no-rdoc --no-ri --ignore-dependencies -i#{cache_dir} #{sources_opt(sources)} 2>&1`
91
+ $? == 0 ? (puts out) : (raise BundleCreationFailure, out)
92
+ else
93
+ puts "Using cached version of #{spec.name} (#{spec.version})"
94
+ end
95
+ `cp -R #{cache_dir}/* #{bundle_path}`
96
+ end
81
97
 
82
- "--without=#{without.join(',')}"
98
+ def sources_opt(sources)
99
+ sources.
100
+ map{|s| s.remotes}.flatten.
101
+ map{|s| s.to_s}.
102
+ sort.
103
+ map{|s| %w{gemcutter rubygems rubyforge}.include?(s) ? "http://rubygems.org" : s}.
104
+ map{|s| "--source #{s}"}.
105
+ join(' ')
83
106
  end
84
107
 
85
108
  # Paths
86
109
 
87
110
  def bundle_path(extension = nil)
88
- Repo.path(digest, extension)
111
+ Repo.bundle_path(digest, extension)
112
+ end
113
+
114
+ def gemfile_lock_path
115
+ File.expand_path('Gemfile.lock', bundle_path)
89
116
  end
90
117
 
91
118
  def gemfile_path
@@ -93,6 +120,6 @@ class Spitball
93
120
  end
94
121
 
95
122
  def tarball_path
96
- Repo.path(digest, 'tgz')
123
+ Repo.bundle_path(digest, 'tgz')
97
124
  end
98
125
  end
data/spec/spec_helper.rb CHANGED
@@ -30,6 +30,14 @@ end
30
30
 
31
31
  # helper methods
32
32
 
33
+ def capture_stdout
34
+ $stdout = StringIO.new
35
+ yield
36
+ $stdout.string
37
+ ensure
38
+ $stdout = STDOUT
39
+ end
40
+
33
41
  def purge_test_cache
34
42
  FileUtils.rm_rf SPITBALL_CACHE
35
43
  end
@@ -49,12 +57,6 @@ def use_success_bundler
49
57
  end
50
58
  end
51
59
 
52
- def use_fail_bundler
53
- make_bundler do |f|
54
- f.puts "exit 1"
55
- end
56
- end
57
-
58
60
  def purge_bin
59
61
  FileUtils.rm_rf File.expand_path('bin', SPEC_DIR)
60
62
  end
@@ -6,16 +6,30 @@ describe Spitball do
6
6
 
7
7
  @gemfile = <<-end_gemfile
8
8
  source :rubygems
9
- gem "activerecord"
9
+ gem "json_pure"
10
10
  end_gemfile
11
11
 
12
- @spitball = Spitball.new(@gemfile)
12
+ @lockfile = <<-end_lockfile.strip.gsub(/\n[ ]{6}/m, "\n")
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ specs:
16
+ json_pure (1.4.6)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ json_pure
23
+ end_lockfile
24
+
25
+ @spitball = Spitball.new(@gemfile, @lockfile)
13
26
  end
14
27
 
15
28
  describe "cached?" do
16
29
  it "returns true if the tarball has already been cached" do
17
30
  @spitball.should_not be_cached
18
- @spitball.cache!
31
+ mock(@spitball).install_gem(anything, anything).times(any_times)
32
+ capture_stdout { @spitball.cache! }
19
33
  @spitball.should be_cached
20
34
  end
21
35
  end
@@ -34,7 +48,6 @@ describe Spitball do
34
48
  mock.instance_of(Spitball::FileLock).acquire_lock { true }
35
49
  mock(@spitball).create_bundle
36
50
  mock.instance_of(Spitball::FileLock).release_lock
37
-
38
51
  @spitball.cache!
39
52
  end
40
53
 
@@ -69,30 +82,56 @@ describe Spitball do
69
82
 
70
83
  describe "create_bundle" do
71
84
  it "generates a bundle at the bundle_path" do
72
- @spitball.create_bundle
73
-
85
+ mock(@spitball).install_gem(anything, anything).times(any_times)
86
+ capture_stdout { @spitball.create_bundle }
74
87
  File.exist?(@spitball.tarball_path).should == true
75
88
  end
76
-
77
- it "raises an exception if bundle creation fails" do
78
- use_fail_bundler
79
-
80
- lambda { @spitball.create_bundle }.should raise_error(Spitball::BundleCreationFailure)
81
- File.exist?(@spitball.tarball_path).should_not == true
82
- end
83
89
  end
84
90
 
85
91
  describe "without_clause" do
86
- it "returns a --without bundler option if :without is set" do
87
- Spitball.new('gemfile', :without => "system").without_clause.should == '--without=system'
88
- end
89
-
90
- it "returns an empty string if without is not set" do
91
- Spitball.new('gemfile').without_clause.should == ''
92
+ before do
93
+ @gemfile = <<-end_gemfile
94
+ source :rubygems
95
+ group 'development' do
96
+ gem "activerecord"
97
+ end
98
+ end_gemfile
99
+
100
+ @lockfile = <<-end_lockfile.strip.gsub(/\n[ ]{6}/m, "\n")
101
+ GEM
102
+ remote: http://rubygems.org/
103
+ specs:
104
+ activemodel (3.0.1)
105
+ activesupport (= 3.0.1)
106
+ builder (~> 2.1.2)
107
+ i18n (~> 0.4.1)
108
+ activerecord (3.0.1)
109
+ activemodel (= 3.0.1)
110
+ activesupport (= 3.0.1)
111
+ arel (~> 1.0.0)
112
+ tzinfo (~> 0.3.23)
113
+ activesupport (3.0.1)
114
+ arel (1.0.1)
115
+ activesupport (~> 3.0.0)
116
+ builder (2.1.2)
117
+ i18n (0.4.2)
118
+ tzinfo (0.3.23)
119
+
120
+ PLATFORMS
121
+ ruby
122
+
123
+ DEPENDENCIES
124
+ activerecord
125
+ end_lockfile
92
126
  end
93
-
94
- it "allows multiple groups" do
95
- Spitball.new('gemfile', :without => ["system", "test"]).without_clause.should == '--without=system,test'
127
+
128
+ it "should use without" do
129
+ @spitball = Spitball.new(@gemfile, @lockfile)
130
+ mock(@spitball).install_gem(anything, anything).times(3)
131
+ @spitball.create_bundle
132
+ @spitball = Spitball.new(@gemfile, @lockfile, :without => 'development')
133
+ mock(@spitball).install_gem(anything, anything).times(1)
134
+ @spitball.create_bundle
96
135
  end
97
136
  end
98
137
  end
@@ -100,7 +139,7 @@ end
100
139
  describe Spitball::FileLock do
101
140
  describe "acquire_lock" do
102
141
  before do
103
- Spitball::Repo.make_cache_dir
142
+ Spitball::Repo.make_cache_dirs
104
143
  @lock_path = File.expand_path('test.lock', SPITBALL_CACHE)
105
144
  @lock = Spitball::FileLock.new(@lock_path)
106
145
  end
@@ -120,50 +159,56 @@ end
120
159
 
121
160
  describe Spitball::Repo do
122
161
  before do
123
- Spitball::Repo.make_cache_dir
162
+ Spitball::Repo.make_cache_dirs
124
163
  end
125
164
 
126
- describe "make_cache_dir" do
165
+ describe "make_cache_dirs" do
127
166
  it "creates the correct cache dir" do
128
167
  FileUtils.rm_rf(SPITBALL_CACHE)
129
168
 
130
169
  File.exist?(SPITBALL_CACHE).should_not == true
131
- Spitball::Repo.make_cache_dir
170
+ Spitball::Repo.make_cache_dirs
132
171
  File.exist?(SPITBALL_CACHE).should == true
133
172
  end
134
173
  end
135
174
 
136
- describe "path" do
175
+ describe "bundle_path" do
137
176
  it "generates paths with the correct cache" do
138
- Spitball::Repo.path('digest').should =~ %r[^#{SPITBALL_CACHE}]
177
+ Spitball::Repo.bundle_path('digest').should =~ %r[^#{SPITBALL_CACHE}]
139
178
  end
140
179
 
141
180
  it "generates paths with extensions" do
142
- Spitball::Repo.path('digest', 'tgz').should =~ %r[\.tgz$]
181
+ Spitball::Repo.bundle_path('digest', 'tgz').should =~ %r[\.tgz$]
143
182
  end
144
183
 
145
184
  it "generates paths prefixed with bundle_" do
146
- Spitball::Repo.path('digest', 'tgz').should =~ %r[bundle_digest\.tgz$]
185
+ Spitball::Repo.bundle_path('digest', 'tgz').should =~ %r[bundle_digest\.tgz$]
186
+ end
187
+ end
188
+
189
+ describe "gemcache_path" do
190
+ it "returns the correct path in the cache dir" do
191
+ Spitball::Repo.gemcache_path.should == File.join(SPITBALL_CACHE, "gemcache")
147
192
  end
148
193
  end
149
194
 
150
195
  describe "exist?" do
151
196
  it "returns true if tarball for a digest exists" do
152
197
  Spitball::Repo.exist?('digest').should_not == true
153
- File.open(Spitball::Repo.path('digest', 'tgz'), 'w') {|f| f.write 'tarball!' }
198
+ File.open(Spitball::Repo.bundle_path('digest', 'tgz'), 'w') {|f| f.write 'tarball!' }
154
199
  Spitball::Repo.exist?('digest').should == true
155
200
  end
156
201
  end
157
202
 
158
203
  describe "tarball" do
159
204
  it "returns the path of the cached tarball for a digest" do
160
- Spitball::Repo.tarball('digest').should == Spitball::Repo.path('digest', 'tgz')
205
+ Spitball::Repo.tarball('digest').should == Spitball::Repo.bundle_path('digest', 'tgz')
161
206
  end
162
207
  end
163
208
 
164
209
  describe "gemfile" do
165
210
  it "returns the path of the cached gemfile for a digest" do
166
- Spitball::Repo.gemfile('digest').should == Spitball::Repo.path('digest', 'gemfile')
211
+ Spitball::Repo.gemfile('digest').should == Spitball::Repo.bundle_path('digest', 'gemfile')
167
212
  end
168
213
  end
169
214
 
@@ -197,15 +242,16 @@ end
197
242
 
198
243
  describe Spitball::Digest do
199
244
  it "generates a digest based on the spitball's options and gemfile" do
200
- [Spitball.new('gemfile contents', :without => "system").digest,
201
- Spitball.new('gemfile contents 2', :without => "system").digest,
202
- Spitball.new('gemfile', :without => "other_group").digest,
203
- Spitball.new('gemfile').digest
245
+ [Spitball.new('gemfile contents', 'gemlock', :without => "system").digest,
246
+ Spitball.new('gemfile contents 2', 'gemlock', :without => "system").digest,
247
+ Spitball.new('gemfile', 'gemlock', :without => "other_group").digest,
248
+ Spitball.new('gemfile', 'gemlock').digest,
249
+ Spitball.new('gemfile', 'gemlock2').digest
204
250
  ].uniq.length.should == 4
205
251
  end
206
252
 
207
253
  it "provides a hash equal to the digest's hash"do
208
- spitball = Spitball.new('gemfile contents')
254
+ spitball = Spitball.new('gemfile contents', 'gemlock contents')
209
255
  spitball.hash.should == spitball.digest.hash
210
256
  end
211
257
  end
data/spitball.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{spitball}
8
- s.version = "0.2.5"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Matt Freels", "Brandon Mitchell"]
12
- s.date = %q{2010-09-08}
11
+ s.authors = ["Matt Freels", "Brandon Mitchell", "Joshua Hull"]
12
+ s.date = %q{2010-10-27}
13
13
  s.description = %q{Use bundler to generate gem tarball packages.}
14
14
  s.email = %q{freels@twitter.com}
15
15
  s.executables = ["spitball", "spitball-cache-cleanup", "spitball-server"]
@@ -18,13 +18,14 @@ Gem::Specification.new do |s|
18
18
  ]
19
19
  s.files = [
20
20
  ".gitignore",
21
- "Gemfile.sample",
22
21
  "README.md",
23
22
  "Rakefile",
24
23
  "VERSION",
25
24
  "bin/spitball",
26
25
  "bin/spitball-cache-cleanup",
27
26
  "bin/spitball-server",
27
+ "lib/ext/bundler_fake_dsl.rb",
28
+ "lib/ext/bundler_lockfile_parser.rb",
28
29
  "lib/spitball.rb",
29
30
  "lib/spitball/digest.rb",
30
31
  "lib/spitball/file_lock.rb",
@@ -50,19 +51,19 @@ Gem::Specification.new do |s|
50
51
  s.specification_version = 3
51
52
 
52
53
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
- s.add_runtime_dependency(%q<bundler>, [">= 0.9.5"])
54
- s.add_runtime_dependency(%q<sinatra>, [">= 1.0"])
54
+ s.add_runtime_dependency(%q<bundler>, ["~> 1.0.0"])
55
+ s.add_runtime_dependency(%q<sinatra>, ["~> 1.0"])
55
56
  s.add_development_dependency(%q<rspec>, [">= 0"])
56
57
  s.add_development_dependency(%q<rr>, [">= 0"])
57
58
  else
58
- s.add_dependency(%q<bundler>, [">= 0.9.5"])
59
- s.add_dependency(%q<sinatra>, [">= 1.0"])
59
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_dependency(%q<sinatra>, ["~> 1.0"])
60
61
  s.add_dependency(%q<rspec>, [">= 0"])
61
62
  s.add_dependency(%q<rr>, [">= 0"])
62
63
  end
63
64
  else
64
- s.add_dependency(%q<bundler>, [">= 0.9.5"])
65
- s.add_dependency(%q<sinatra>, [">= 1.0"])
65
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
66
+ s.add_dependency(%q<sinatra>, ["~> 1.0"])
66
67
  s.add_dependency(%q<rspec>, [">= 0"])
67
68
  s.add_dependency(%q<rr>, [">= 0"])
68
69
  end
metadata CHANGED
@@ -1,22 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spitball
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 5
10
- version: 0.2.5
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Freels
14
14
  - Brandon Mitchell
15
+ - Joshua Hull
15
16
  autorequire:
16
17
  bindir: bin
17
18
  cert_chain: []
18
19
 
19
- date: 2010-09-08 00:00:00 -07:00
20
+ date: 2010-10-27 00:00:00 -07:00
20
21
  default_executable:
21
22
  dependencies:
22
23
  - !ruby/object:Gem::Dependency
@@ -25,14 +26,14 @@ dependencies:
25
26
  requirement: &id001 !ruby/object:Gem::Requirement
26
27
  none: false
27
28
  requirements:
28
- - - ">="
29
+ - - ~>
29
30
  - !ruby/object:Gem::Version
30
- hash: 49
31
+ hash: 23
31
32
  segments:
33
+ - 1
32
34
  - 0
33
- - 9
34
- - 5
35
- version: 0.9.5
35
+ - 0
36
+ version: 1.0.0
36
37
  type: :runtime
37
38
  version_requirements: *id001
38
39
  - !ruby/object:Gem::Dependency
@@ -41,7 +42,7 @@ dependencies:
41
42
  requirement: &id002 !ruby/object:Gem::Requirement
42
43
  none: false
43
44
  requirements:
44
- - - ">="
45
+ - - ~>
45
46
  - !ruby/object:Gem::Version
46
47
  hash: 15
47
48
  segments:
@@ -90,13 +91,14 @@ extra_rdoc_files:
90
91
  - README.md
91
92
  files:
92
93
  - .gitignore
93
- - Gemfile.sample
94
94
  - README.md
95
95
  - Rakefile
96
96
  - VERSION
97
97
  - bin/spitball
98
98
  - bin/spitball-cache-cleanup
99
99
  - bin/spitball-server
100
+ - lib/ext/bundler_fake_dsl.rb
101
+ - lib/ext/bundler_lockfile_parser.rb
100
102
  - lib/spitball.rb
101
103
  - lib/spitball/digest.rb
102
104
  - lib/spitball/file_lock.rb
data/Gemfile.sample DELETED
@@ -1,8 +0,0 @@
1
- source :rubygems
2
-
3
- group "native" do
4
- gem 'mysql'
5
- gem 'json'
6
- end
7
-
8
- gem 'activesupport'