spitball 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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'