right_publish 0.3.0 → 0.4.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/Gemfile +2 -0
- data/Gemfile.lock +2 -0
- data/README.rdoc +25 -25
- data/VERSION +1 -1
- data/bin/right_publish +1 -5
- data/lib/right_publish/annotation.rb +101 -0
- data/lib/right_publish/cli.rb +91 -0
- data/lib/right_publish/profile.rb +30 -20
- data/lib/right_publish/repo.rb +74 -25
- data/lib/right_publish/repos/apt.rb +8 -10
- data/lib/right_publish/repos/gem.rb +15 -11
- data/lib/right_publish/repos/msi.rb +45 -0
- data/lib/right_publish/repos/yum.rb +8 -11
- data/lib/right_publish/storage.rb +42 -3
- data/lib/right_publish/stores/local.rb +3 -3
- data/lib/right_publish.rb +24 -86
- data/right_publish.gemspec +13 -3
- data/spec/annotation_spec.rb +22 -0
- data/spec/repo_manager_spec.rb +1 -3
- data/spec/repo_spec.rb +5 -7
- data/spec/repos/apt_spec.rb +3 -3
- data/spec/repos/gem_spec.rb +3 -3
- data/spec/repos/yum_spec.rb +3 -3
- data/spec/spec_helper.rb +7 -0
- data/spec/storage_manager_spec.rb +0 -1
- data/spec/storage_spec.rb +26 -2
- data/spec/stores/local_spec.rb +0 -1
- data/spec/stores/s3_spec.rb +0 -1
- metadata +87 -52
@@ -1,10 +1,8 @@
|
|
1
1
|
module RightPublish
|
2
|
-
class AptRepo
|
3
|
-
include RightPublish::Repo
|
4
|
-
|
2
|
+
class AptRepo < Repo
|
5
3
|
DEFAULT_APT_AUTO = true
|
6
4
|
DEFAULT_APT_DIR = 'apt/'
|
7
|
-
DEFAULT_DESCRIPTION = "
|
5
|
+
DEFAULT_DESCRIPTION = "Apt Repository"
|
8
6
|
REPO_KEY = :apt_repo
|
9
7
|
|
10
8
|
REPO_OPTIONS = {
|
@@ -22,7 +20,7 @@ module RightPublish
|
|
22
20
|
@@supported_archs = [ 'i386', 'amd64' ]
|
23
21
|
@@all_archs = [ 'i386', 'amd64', BIN_ALL_ARCH ]
|
24
22
|
|
25
|
-
def
|
23
|
+
def add(file_or_dir, target)
|
26
24
|
repo_updates = {}
|
27
25
|
|
28
26
|
# If we specified a target, let's make sure it's in our profile
|
@@ -39,9 +37,6 @@ module RightPublish
|
|
39
37
|
pkgs << path
|
40
38
|
end
|
41
39
|
|
42
|
-
# Synchronize the upstream source to our local cache
|
43
|
-
fetch
|
44
|
-
|
45
40
|
repo_path = File.join(Profile.config[:local_storage][:cache_dir], repo_config[:subdir])
|
46
41
|
write_conf_file repo_path if repo_config[:auto]
|
47
42
|
|
@@ -56,9 +51,12 @@ module RightPublish
|
|
56
51
|
end
|
57
52
|
end
|
58
53
|
rebuild_index(repo_config[:subdir]) if not repo_config[:auto]
|
54
|
+
end
|
59
55
|
|
60
|
-
|
61
|
-
|
56
|
+
def annotate(options={})
|
57
|
+
options[:subdir] ||= File.join(repo_config[:subdir], 'pool', 'main')
|
58
|
+
options[:filter] = ['*.deb']
|
59
|
+
super(options)
|
62
60
|
end
|
63
61
|
|
64
62
|
def self.pkg_parts(pkg_name)
|
@@ -1,24 +1,23 @@
|
|
1
1
|
module RightPublish
|
2
|
-
class GemRepo
|
3
|
-
include RightPublish::Repo
|
4
|
-
|
2
|
+
class GemRepo < Repo
|
5
3
|
DEFAULT_GEM_DIR = 'gems/'
|
6
4
|
REPO_KEY = :gem_repo
|
7
|
-
REPO_OPTIONS = {:subdir=>DEFAULT_GEM_DIR}
|
5
|
+
REPO_OPTIONS = {:subdir=>DEFAULT_GEM_DIR, :prune=>false}
|
8
6
|
|
9
7
|
GEMS_SUBDIRECTORY = 'gems'
|
10
8
|
GEM_EXT = 'gem'
|
11
9
|
|
12
|
-
def
|
10
|
+
def add(file_or_dir, target)
|
13
11
|
gems_list = get_pkg_list(file_or_dir, GEM_EXT)
|
14
12
|
|
15
|
-
# Synchronize the upstream source to our local cache
|
16
|
-
fetch
|
17
|
-
|
18
13
|
# Copy gem files to the repository
|
19
14
|
destination = File.join(repo_config[:subdir], GEMS_SUBDIRECTORY)
|
20
15
|
gems_list.each do |path|
|
21
|
-
|
16
|
+
# RubyGems repos do not normally prune; it must be explicitly enabled.
|
17
|
+
if repo_config[:prune]
|
18
|
+
do_in_subdir(destination) { prune_all("#{pkg_parts(path)[:name]}-*.gem") }
|
19
|
+
end
|
20
|
+
|
22
21
|
install_file(path, destination)
|
23
22
|
end
|
24
23
|
|
@@ -28,11 +27,16 @@ module RightPublish
|
|
28
27
|
indexed = system('gem generate_index 2>&1 >/dev/null') # requires 'builder' gem to be installed
|
29
28
|
raise Exception, "gem generate_index failed; cannot continue publishing" unless indexed
|
30
29
|
end
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
def annotate(options={})
|
33
|
+
options[:subdir] ||= File.join(repo_config[:subdir], 'gems')
|
34
|
+
options[:filter] = ['*.gem']
|
35
|
+
super(options)
|
34
36
|
end
|
35
37
|
|
38
|
+
protected
|
39
|
+
|
36
40
|
def pkg_parts(name)
|
37
41
|
result = {:name=>nil, :version=>nil}
|
38
42
|
result[:name], result[:version] = /([A-Za-z0-9\-_]+)-([0-9\.]+)\.#{GEM_EXT}\Z/.match(name).captures
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module RightPublish
|
2
|
+
class MsiRepo < Repo
|
3
|
+
DEFAULT_MSI_DIR = 'msi/'
|
4
|
+
REPO_KEY = :msi_repo
|
5
|
+
REPO_OPTIONS = {:subdir=>DEFAULT_MSI_DIR, :prune=>true}
|
6
|
+
|
7
|
+
GEMS_SUBDIRECTORY = 'gems'
|
8
|
+
MSI_EXT = 'msi'
|
9
|
+
|
10
|
+
def add(file_or_dir, target)
|
11
|
+
msi_list = get_pkg_list(file_or_dir, MSI_EXT)
|
12
|
+
|
13
|
+
# Copy MSI files to the repository
|
14
|
+
destination = repo_config[:subdir]
|
15
|
+
msi_list.each do |path|
|
16
|
+
# RubyGems repos do not normally prune; it must be explicitly enabled.
|
17
|
+
if repo_config[:prune]
|
18
|
+
do_in_subdir(destination) { prune_all("#{pkg_parts(path)[:name]}-*.msi") }
|
19
|
+
end
|
20
|
+
|
21
|
+
install_file(path, destination)
|
22
|
+
end
|
23
|
+
|
24
|
+
# No index generation is necessary; MSI is not a distribution mechanism. The annotated
|
25
|
+
# HTML will suffice to direct people to the proper download.
|
26
|
+
end
|
27
|
+
|
28
|
+
def annotate(options={})
|
29
|
+
options[:subdir] ||= repo_config[:subdir]
|
30
|
+
options[:filter] = ['*.msi']
|
31
|
+
options[:use_remote_storage] = true
|
32
|
+
super(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def pkg_parts(name)
|
38
|
+
result = {:name=>nil, :version=>nil}
|
39
|
+
result[:name], result[:version] = /([A-Za-z0-9\-_]+)-([0-9\.]+)\.#{MSI_EXT}\Z/.match(name).captures
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
RightPublish::RepoManager.register_repo(MsiRepo)
|
45
|
+
end
|
@@ -1,13 +1,10 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
module RightPublish
|
4
|
-
|
5
|
-
class YumRepo
|
6
|
-
include RightPublish::Repo
|
7
|
-
|
4
|
+
class YumRepo < Repo
|
8
5
|
DEFAULT_YUM_EPEL = 1
|
9
6
|
DEFAULT_YUM_DIR = 'yum/'
|
10
|
-
DEFAULT_DESCRIPTION = "
|
7
|
+
DEFAULT_DESCRIPTION = "Yum Repository"
|
11
8
|
REPO_KEY = :yum_repo
|
12
9
|
DEFAULT_EPEL_LAYOUT = "rightlink"
|
13
10
|
REPO_OPTIONS = {
|
@@ -27,7 +24,7 @@ module RightPublish
|
|
27
24
|
ARCHITECTURES = [ 'i386', 'x86_64' ]
|
28
25
|
PKG_TYPES = [ ARCHITECTURES, BIN_ALL_ARCH, SRC_ALL_ARCH ]
|
29
26
|
|
30
|
-
def
|
27
|
+
def add(file_or_dir, target)
|
31
28
|
repo_updates = {}
|
32
29
|
|
33
30
|
get_pkg_list(file_or_dir, YUM_EXT) do |path|
|
@@ -40,9 +37,6 @@ module RightPublish
|
|
40
37
|
end
|
41
38
|
return if repo_updates.size == 0
|
42
39
|
|
43
|
-
# Synchronize the upstream source to our local cache
|
44
|
-
fetch
|
45
|
-
|
46
40
|
full_pkg_paths = []
|
47
41
|
repo_updates.each_pair do |repo_path, pkgs|
|
48
42
|
pkgs.each do |pkg|
|
@@ -57,9 +51,12 @@ module RightPublish
|
|
57
51
|
regen_metadata( repo_path )
|
58
52
|
sign_metadata( repo_path )
|
59
53
|
end
|
54
|
+
end
|
60
55
|
|
61
|
-
|
62
|
-
|
56
|
+
def annotate(options={})
|
57
|
+
options[:subdir] ||= File.join(repo_config[:subdir], '1')
|
58
|
+
options[:filter] = ['*.rpm']
|
59
|
+
super(options)
|
63
60
|
end
|
64
61
|
|
65
62
|
def import_pkg( pkg, repo_path )
|
@@ -29,11 +29,23 @@ module RightPublish
|
|
29
29
|
end
|
30
30
|
|
31
31
|
module Storage
|
32
|
+
def self.ls(bucket, options={})
|
33
|
+
storage = bucket.get_directories()
|
34
|
+
storage.files.each do |file|
|
35
|
+
# skip directories
|
36
|
+
next if file.key[-1,1] == '/'
|
37
|
+
# skip files not located in specified subdir
|
38
|
+
next if file.key[0,options[:subdir].size] != options[:subdir] if options.has_key? :subdir
|
39
|
+
|
40
|
+
yield(file)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
32
44
|
def self.sync_dirs(src, dest, options={})
|
33
45
|
src_dir = src.get_directories()
|
34
46
|
dest_dir = dest.get_directories()
|
35
47
|
|
36
|
-
src_map = get_etag_map(src_dir, options)
|
48
|
+
src_map = get_etag_map(src_dir, options)
|
37
49
|
dest_map = get_etag_map(dest_dir, options)
|
38
50
|
|
39
51
|
dest_map.each_pair do |hash, files|
|
@@ -53,7 +65,9 @@ module RightPublish
|
|
53
65
|
else
|
54
66
|
remote_file = files.shift
|
55
67
|
Profile.log("Synchronizing: #{remote_file.first}", :debug)
|
56
|
-
local_copy = dest_dir.files.create(:key=>remote_file.first, :body=>remote_file.last.body,
|
68
|
+
local_copy = dest_dir.files.create(:key=>remote_file.first, :body=>remote_file.last.body,
|
69
|
+
:acl=>'public-read',
|
70
|
+
:content_type => guess_mime_type(remote_file.first))
|
57
71
|
end
|
58
72
|
|
59
73
|
files.each_key do |file|
|
@@ -65,12 +79,37 @@ module RightPublish
|
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
68
|
-
|
82
|
+
# Given a filename, make an educated guess as to its MIME type. We rely on the mime-types
|
83
|
+
# gem and its built-in database of extensions and types, but many extensions are in use
|
84
|
+
# by multiple MIME types.
|
85
|
+
#
|
86
|
+
# If the extension maps to more than one MIME type, we will pick the first type that is
|
87
|
+
# a member of RightPublish::MIME_TYPES. This gives us 100% reliable behavior for MIME
|
88
|
+
# types that RightPublish "knows," and passable behavior for other types.
|
89
|
+
#
|
90
|
+
# @param [String] filename relative or absolute filename
|
91
|
+
# @return [String] the inferred MIME type for filename, based on its extension
|
92
|
+
def self.guess_mime_type(filename)
|
93
|
+
filename = File.basename(filename)
|
94
|
+
candidates = MIME::Types.type_for(filename)
|
95
|
+
|
96
|
+
if candidates.size == 1
|
97
|
+
winner = candidates.first
|
98
|
+
elsif preferred = candidates.detect { |c| RightPublish::MIME_TYPES.keys.include? c.to_s }
|
99
|
+
winner = preferred
|
100
|
+
else
|
101
|
+
winner = 'application/octet-stream'
|
102
|
+
end
|
103
|
+
|
104
|
+
winner.to_s
|
105
|
+
end
|
69
106
|
|
70
107
|
def self.get_etag_map(dir, options={})
|
71
108
|
hash_map = {}
|
72
109
|
dir.files.each do |file|
|
110
|
+
# skip directories
|
73
111
|
next if file.key[-1,1] == '/'
|
112
|
+
# skip files not located in specified subdir
|
74
113
|
next if file.key[0,options[:subdir].size] != options[:subdir] if options.has_key? :subdir
|
75
114
|
|
76
115
|
md5 = dir.compute_md5(file)
|
@@ -3,10 +3,10 @@ require 'digest/md5'
|
|
3
3
|
|
4
4
|
module RightPublish
|
5
5
|
module LocalStorage
|
6
|
-
|
7
|
-
DEFAULT_LOCAL_CACHEDIR = '~/.rp_cache'
|
6
|
+
DEFAULT_LOCAL_CACHEDIR = File.expand_path('~/.right_publish/cache')
|
8
7
|
STORAGE_KEY = :local_storage
|
9
|
-
STORAGE_OPTIONS = { :cache_dir=>DEFAULT_LOCAL_CACHEDIR}
|
8
|
+
STORAGE_OPTIONS = { :cache_dir=>DEFAULT_LOCAL_CACHEDIR }
|
9
|
+
|
10
10
|
def compute_md5(file)
|
11
11
|
Digest::MD5.file(File.join(service.path_to(self.key), file.key)).hexdigest
|
12
12
|
end
|
data/lib/right_publish.rb
CHANGED
@@ -3,95 +3,33 @@
|
|
3
3
|
# RightScale RightPublish (right_publish) - (c) 2013 RightScale Inc
|
4
4
|
#
|
5
5
|
|
6
|
-
require '
|
7
|
-
|
8
|
-
require 'right_publish/profile'
|
9
|
-
require 'right_publish/repo'
|
6
|
+
require 'mime/types'
|
10
7
|
|
11
8
|
module RightPublish
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
puts e
|
24
|
-
exit -1
|
25
|
-
end
|
26
|
-
|
27
|
-
# These options override profile attributes.
|
28
|
-
profile.settings[:local_storage][:cache_dir] = options[:local_cache] if options[:local_cache]
|
29
|
-
profile.settings[:verbose] = true if options[:verbose]
|
30
|
-
|
31
|
-
# We already know this is a valid type, parse_args checked
|
32
|
-
repo = RepoManager.get_repository(REPOSITORY_TYPES[options[:repo_type]])
|
33
|
-
begin
|
34
|
-
case options[:cmd]
|
35
|
-
when "publish"
|
36
|
-
repo.publish(options[:files], options[:dist])
|
37
|
-
when "store"
|
38
|
-
repo.store
|
39
|
-
when "fetch"
|
40
|
-
repo.fetch
|
41
|
-
else
|
42
|
-
end
|
43
|
-
rescue RuntimeError => e
|
44
|
-
RightPublish::Profile.log("Fatal Error:\n\t#{e}", :error)
|
45
|
-
exit -1
|
46
|
-
end
|
47
|
-
RightPublish::Profile.log("Success!")
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.parse_args()
|
51
|
-
options = Trollop.options do
|
52
|
-
version "RightPublish alpha (c) 2013 RightScale Inc"
|
53
|
-
banner <<-EOS
|
54
|
-
RightPublish can manage a YUM/APT/RubyGem repository in remote storage, e.g. S3.
|
55
|
-
|
56
|
-
Usage:
|
57
|
-
right_publish [global_options] <command> [file1, file2, ...]
|
58
|
-
|
59
|
-
commands:
|
60
|
-
fetch
|
61
|
-
publish
|
62
|
-
store
|
63
|
-
|
64
|
-
global options:
|
65
|
-
EOS
|
66
|
-
|
67
|
-
opt :local_cache, "Local cache location", :type => String
|
68
|
-
opt :profile, "Publish profile", :type => String
|
69
|
-
opt :repo_type, "Repository type: #{REPOSITORY_TYPES.keys.inspect}", :type => String
|
70
|
-
opt :dist, "Target distribution. Required for binary packages. If unspecified for noarch and source packages, will copy to all distributions specified in profile.", :type => String
|
71
|
-
opt :verbose, "Verbose output"
|
72
|
-
|
73
|
-
stop_on SUB_COMMANDS
|
74
|
-
end
|
75
|
-
|
76
|
-
options[:cmd]= ARGV.shift
|
77
|
-
options[:files] = expand_argv_globs
|
78
|
-
|
79
|
-
Trollop.die "argument --profile is required" unless options[:profile]
|
80
|
-
Trollop.die "argument --repo-type is required" unless options[:repo_type]
|
81
|
-
Trollop.die "profile does not exist: #{options[:profile]}" unless File.exist?(options[:profile])
|
82
|
-
Trollop.die "invalid repository type: #{options[:repo_type]}" unless REPOSITORY_TYPES[options[:repo_type]]
|
83
|
-
|
84
|
-
options
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.expand_argv_globs
|
88
|
-
files = []
|
89
|
-
|
90
|
-
ARGV.each do |glob|
|
91
|
-
files += Dir.glob(glob)
|
92
|
-
end
|
9
|
+
# Combined list of MIME types that should be registered with mime-types, AND preferred
|
10
|
+
# MIME types for this application to use, in cases where a given filename extension is
|
11
|
+
# used by multiple MIME types.
|
12
|
+
MIME_TYPES = {
|
13
|
+
'application/x-deb' => 'deb',
|
14
|
+
'application/x-ruby-gem' => 'gem',
|
15
|
+
'application/x-rpm' => 'rpm',
|
16
|
+
'application/x-msi' => 'msi',
|
17
|
+
'text/xml' => 'xml',
|
18
|
+
}
|
19
|
+
end
|
93
20
|
|
94
|
-
|
21
|
+
# Register some extra MIME types that the gem may not know about.
|
22
|
+
RightPublish::MIME_TYPES.each_pair do |name, extension|
|
23
|
+
if MIME::Types[name].empty?
|
24
|
+
type = MIME::Type.new(name) do |t|
|
25
|
+
t.extensions = [extension]
|
26
|
+
t.encoding = '8bit'
|
95
27
|
end
|
28
|
+
MIME::Types.add(type)
|
96
29
|
end
|
97
30
|
end
|
31
|
+
|
32
|
+
require 'right_publish/profile'
|
33
|
+
require 'right_publish/annotation'
|
34
|
+
require 'right_publish/repo'
|
35
|
+
require 'right_publish/cli'
|
data/right_publish.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "right_publish"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brian Szmyd", "Tony Spataro"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-11-01"
|
13
13
|
s.description = "A tool for maintaining S3-based DEB, GEM and RPM packages."
|
14
14
|
s.email = "support@rightscale.com"
|
15
15
|
s.executables = ["autosign.expect", "right_publish"]
|
@@ -27,16 +27,20 @@ Gem::Specification.new do |s|
|
|
27
27
|
"bin/autosign.expect",
|
28
28
|
"bin/right_publish",
|
29
29
|
"lib/right_publish.rb",
|
30
|
+
"lib/right_publish/annotation.rb",
|
31
|
+
"lib/right_publish/cli.rb",
|
30
32
|
"lib/right_publish/profile.rb",
|
31
33
|
"lib/right_publish/repo.rb",
|
32
34
|
"lib/right_publish/repos/apt.rb",
|
33
35
|
"lib/right_publish/repos/gem.rb",
|
36
|
+
"lib/right_publish/repos/msi.rb",
|
34
37
|
"lib/right_publish/repos/yum.rb",
|
35
38
|
"lib/right_publish/repos/zypp.rb",
|
36
39
|
"lib/right_publish/storage.rb",
|
37
40
|
"lib/right_publish/stores/local.rb",
|
38
41
|
"lib/right_publish/stores/s3.rb",
|
39
42
|
"right_publish.gemspec",
|
43
|
+
"spec/annotation_spec.rb",
|
40
44
|
"spec/repo_manager_spec.rb",
|
41
45
|
"spec/repo_spec.rb",
|
42
46
|
"spec/repos/apt_spec.rb",
|
@@ -51,7 +55,7 @@ Gem::Specification.new do |s|
|
|
51
55
|
s.homepage = "https://github.com/rightscale/right_publish"
|
52
56
|
s.licenses = ["Proprietary"]
|
53
57
|
s.require_paths = ["lib"]
|
54
|
-
s.rubygems_version = "1.8.
|
58
|
+
s.rubygems_version = "1.8.23"
|
55
59
|
s.summary = "Package publishing and indexing tool"
|
56
60
|
|
57
61
|
if s.respond_to? :specification_version then
|
@@ -60,6 +64,8 @@ Gem::Specification.new do |s|
|
|
60
64
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
61
65
|
s.add_runtime_dependency(%q<builder>, [">= 0"])
|
62
66
|
s.add_runtime_dependency(%q<fog>, ["~> 1.9"])
|
67
|
+
s.add_runtime_dependency(%q<excon>, ["<= 0.25.3"])
|
68
|
+
s.add_runtime_dependency(%q<mime-types>, ["~> 1.0"])
|
63
69
|
s.add_runtime_dependency(%q<trollop>, ["~> 2.0"])
|
64
70
|
s.add_development_dependency(%q<rake>, ["~> 0.9"])
|
65
71
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
@@ -73,6 +79,8 @@ Gem::Specification.new do |s|
|
|
73
79
|
else
|
74
80
|
s.add_dependency(%q<builder>, [">= 0"])
|
75
81
|
s.add_dependency(%q<fog>, ["~> 1.9"])
|
82
|
+
s.add_dependency(%q<excon>, ["<= 0.25.3"])
|
83
|
+
s.add_dependency(%q<mime-types>, ["~> 1.0"])
|
76
84
|
s.add_dependency(%q<trollop>, ["~> 2.0"])
|
77
85
|
s.add_dependency(%q<rake>, ["~> 0.9"])
|
78
86
|
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
@@ -87,6 +95,8 @@ Gem::Specification.new do |s|
|
|
87
95
|
else
|
88
96
|
s.add_dependency(%q<builder>, [">= 0"])
|
89
97
|
s.add_dependency(%q<fog>, ["~> 1.9"])
|
98
|
+
s.add_dependency(%q<excon>, ["<= 0.25.3"])
|
99
|
+
s.add_dependency(%q<mime-types>, ["~> 1.0"])
|
90
100
|
s.add_dependency(%q<trollop>, ["~> 2.0"])
|
91
101
|
s.add_dependency(%q<rake>, ["~> 0.9"])
|
92
102
|
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|