fatgem 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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/bin/fatgem +171 -0
  3. metadata +45 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 74b326838076701fc449b32973365e409769a3ef
4
+ data.tar.gz: c40e5edbeb89a115f526ec7281cd484b7349f7f7
5
+ SHA512:
6
+ metadata.gz: 1066b8d1b6dd3fdbaf098b803d404b80702babb1c3f1dbe0153b40985886d57e5fe3b1b2e736f66b80b39b9df6f35dff8bdc8c83eee979ccd8d5268b9b1401b9
7
+ data.tar.gz: ac70111cf30a46a2cecd179b7bc0bf42d2303f5974aa4342176bf5f98911abc4082eceff5a8558f2417d26915735796ab26a7b5760a2346f865cf69fa58a5b1e
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems/package'
4
+ require 'yaml'
5
+ require 'digest/sha1'
6
+ require 'tmpdir'
7
+ require 'open-uri'
8
+
9
+ class FatGem
10
+ class Error < StandardError; end
11
+
12
+ def self.tmp
13
+ Dir.mktmpdir do |dir|
14
+ yield new(dir)
15
+ end
16
+ end
17
+
18
+ attr_reader :directory
19
+
20
+ def initialize(directory)
21
+ @directory = directory
22
+ @files = Hash.new { |h, k| h[k] = {} }
23
+ @versions = {}
24
+ @specs = []
25
+ end
26
+
27
+ def open_tar(io, &blk)
28
+ Gem::Package::TarReader.new(io) do |reader|
29
+ reader.each(&blk)
30
+ end
31
+ end
32
+
33
+ def open_tar_gz(io, &blk)
34
+ Zlib::GzipReader.wrap io do |gzio|
35
+ open_tar(gzio, &blk)
36
+ end
37
+ end
38
+
39
+ def add_gem(path, ruby_version)
40
+
41
+ if @versions.has_key?(ruby_version)
42
+ version_str = ruby_version ? "Ruby v#{ruby_version}" : "all Ruby versions"
43
+ fail Error, ["Found two gems with same Ruby version:",
44
+ "- #{path} matches #{version_str}",
45
+ "- #{@versions[ruby_version]} also matches #{version_str}"].join("\n")
46
+ end
47
+
48
+ @versions[ruby_version] = path
49
+
50
+ yaml_metadata = nil
51
+
52
+ open_tar(open(path)) do |entry|
53
+ case entry.full_name
54
+ when "metadata.gz"
55
+ yaml_metadata = Gem.gunzip(entry.read)
56
+ when "metadata"
57
+ yaml_metadata = entry.read
58
+ when "data.tar.gz"
59
+ open_tar_gz(entry) do |data|
60
+ write_version(ruby_version, data.full_name, data.read)
61
+ end
62
+ end
63
+ end
64
+
65
+ fail Error, "#{path} does not contain a gemspec" if yaml_metadata.nil?
66
+
67
+ write_version(ruby_version, "metadata.yml", yaml_metadata)
68
+
69
+ spec = YAML.load(yaml_metadata)
70
+ @versions[spec] = path
71
+ @specs << spec
72
+ end
73
+
74
+ def write_version(version, path, content)
75
+ hash = Digest::SHA1.hexdigest(content)
76
+ blobpath = "data/#{hash}"
77
+ write(blobpath, content)
78
+ @files[version][path] = blobpath
79
+ end
80
+
81
+ def write(name, data)
82
+ path = File.join(@directory, name)
83
+ FileUtils.mkdir_p(File.dirname(path))
84
+ File.write(path, data)
85
+ end
86
+
87
+ RAKEFILE = <<-'EOF'
88
+ require 'yaml'
89
+ require 'rubygems/ext'
90
+
91
+ task :default do
92
+ versions = YAML.load_file("data/index")
93
+ ruby_main = RUBY_VERSION.split(".")[0,2].join(".")
94
+ files = versions[ruby_main] || versions[nil]
95
+
96
+ if files.nil?
97
+ $stderr.puts "ERROR: This gem can not be installed on #{RUBY_VERSION}"
98
+ exit 1
99
+ end
100
+
101
+ files.each do |name, hash|
102
+ dir = File.dirname(name)
103
+ FileUtils.mkdir_p(dir)
104
+ FileUtils.cp(hash, name)
105
+ end
106
+
107
+ FileUtils.rm_rf("data")
108
+
109
+ version_spec = YAML.load(File.read("metadata.yml"))
110
+ builder = Gem::Ext::Builder.new(version_spec)
111
+ builder.build_extensions
112
+ end
113
+ EOF
114
+
115
+ def assert_unique(type, specs = @specs)
116
+ values = specs.uniq(&type)
117
+ if values.size != 1
118
+ errors = values.map { |s| "- #{@versions[s]} has #{type} = #{s.send(type)}" }
119
+ if errors.empty?
120
+ errors << "- There's no gem with a specific platform"
121
+ end
122
+ fail Error, ["Can only fatten gems with same '#{type}'.", *errors].join("\n")
123
+ end
124
+ end
125
+
126
+ def finalize
127
+ platform_specs = @specs.select { |s| s.platform != "ruby" }
128
+
129
+ assert_unique :name
130
+ assert_unique :version
131
+ assert_unique :platform, platform_specs
132
+
133
+ main_spec = platform_specs[0]
134
+
135
+ write("data/index", @files.to_yaml)
136
+ write("Rakefile", RAKEFILE)
137
+
138
+ result = nil
139
+
140
+ Dir.chdir(@directory) do
141
+ main_spec.files = Dir["**/*"]
142
+ main_spec.extensions = ["Rakefile"]
143
+
144
+ file_name = Gem::Package.build(main_spec)
145
+ result = File.expand_path(file_name)
146
+ end
147
+
148
+ result
149
+ end
150
+ end
151
+
152
+ if ARGV.empty?
153
+ puts "usage: fatgem GEM1 GEM2 ..."
154
+ exit
155
+ end
156
+
157
+ begin
158
+ FatGem.tmp do |fat|
159
+ ARGV.each do |path|
160
+ version = path[/ruby(\d.\d)/, 1]
161
+ fat.add_gem(path, version)
162
+ end
163
+
164
+ path = fat.finalize
165
+ FileUtils.cp(path, File.basename(path))
166
+ end
167
+ rescue FatGem::Error => e
168
+ puts "ERROR: #{e.message}"
169
+ exit 1
170
+ end
171
+
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fatgem
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Magnus Holm
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email: judofyr@gmail.com
15
+ executables:
16
+ - fatgem
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/fatgem
21
+ homepage: https://github.com/judofyr/fatgem
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.9.3
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 2.4.5.1
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: Combine gems for multiple Ruby versions
45
+ test_files: []