bundix 2.0.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 (5) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bundix +44 -0
  3. data/lib/bundix/source.rb +114 -0
  4. data/lib/bundix.rb +109 -0
  5. metadata +47 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 463a40e4d1cb3c3f2d3734509fb2c5f71bdbaa1b
4
+ data.tar.gz: 1d38eaad6a27ac93279500dd86ce21477bb73259
5
+ SHA512:
6
+ metadata.gz: a2ff4f560cc61af3f388b10677bc660a678b4f12174916e47ed9de050dd2115758e4dcb70bc6f05fd0c33c7a7616de2b14c8eff32677369b7920b108f88a8830
7
+ data.tar.gz: 3eb1c4652f577833e51cc1682a283fb2484d19b6066eb1f9a2a78e84d6514c3f7a85632529982bde640e39d2ae616fbd4b3d23f90e7386270fcd6afbcc8a9797
data/bin/bundix ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+
5
+ require_relative '../lib/bundix'
6
+
7
+ options = {}
8
+
9
+ op = OptionParser.new do |o|
10
+ o.on '--gemset=gemset.nix', 'path to the gemset.nix' do |value|
11
+ options[:gemset] = File.expand_path(value)
12
+ end
13
+
14
+ o.on '--lockfile=Gemfile.lock', 'path to the Gemfile.lock' do |value|
15
+ options[:lockfile] = File.expand_path(value)
16
+ end
17
+
18
+ o.on '-d', '--dependencies', 'include gem dependencies' do
19
+ options[:deps] = true
20
+ end
21
+
22
+ o.on '-q', '--quiet', 'only output errors' do
23
+ options[:quiet] = true
24
+ end
25
+
26
+ o.on '-v', '--version', 'show the version of bundix' do
27
+ puts Bundix::VERSION
28
+ exit
29
+ end
30
+ end
31
+
32
+ op.parse!
33
+ $VERBOSE = !options[:quiet]
34
+ gemset = Bundix.new(options).convert
35
+
36
+ tempfile = Tempfile.new('gemset.nix', encoding: 'UTF-8')
37
+ begin
38
+ Bundix.object2nix(gemset, 2, tempfile)
39
+ tempfile.close
40
+ FileUtils.cp(tempfile.path, options[:gemset])
41
+ ensure
42
+ tempfile.close!
43
+ tempfile.unlink
44
+ end
@@ -0,0 +1,114 @@
1
+ class Bundix
2
+ class Source < Struct.new(:spec)
3
+ def convert
4
+ case spec.source
5
+ when Bundler::Source::Rubygems
6
+ convert_rubygems
7
+ when Bundler::Source::Git
8
+ convert_git
9
+ else
10
+ pp spec
11
+ fail 'unkown bundler source'
12
+ end
13
+ end
14
+
15
+ def sh(*args)
16
+ Bundix.sh(*args)
17
+ end
18
+
19
+ def nix_prefetch_url(*args)
20
+ sh(NIX_PREFETCH_URL, '--type', 'sha256', *args)
21
+ end
22
+
23
+ def nix_prefetch_git(uri, revision)
24
+ home = ENV['HOME']
25
+ ENV['HOME'] = '/homeless-shelter'
26
+ sh(NIX_PREFETCH_GIT, '--url', uri, '--rev', revision, '--hash', 'sha256', '--leave-dotGit')
27
+ ensure
28
+ ENV['HOME'] = home
29
+ end
30
+
31
+ def fetch_local_hash(spec)
32
+ spec.source.caches.each do |cache|
33
+ path = File.join(cache, "#{spec.name}-#{spec.version}.gem")
34
+ next unless File.file?(path)
35
+ begin
36
+ return nix_prefetch_url("file://#{path}")[SHA256_32]
37
+ rescue
38
+ end
39
+ end
40
+
41
+ nil
42
+ end
43
+
44
+ def fetch_remotes_hash(spec, remotes)
45
+ remotes.each do |remote|
46
+ begin
47
+ return fetch_remote_hash(spec, remote)
48
+ rescue
49
+ end
50
+ end
51
+
52
+ nil
53
+ end
54
+
55
+ def fetch_remote_hash(spec, remote)
56
+ hash = nil
57
+
58
+ if URI(remote).host == 'rubygems.org'
59
+ uri = "#{remote}/api/v1/versions/#{spec.name}.json"
60
+ puts "Getting SHA256 from: #{uri}" if $VERBOSE
61
+ open uri do |io|
62
+ versions = JSON.parse(io.read)
63
+ if found_version = versions.find{|obj| obj['number'] == spec.version.to_s }
64
+ hash = found_version['sha']
65
+ break
66
+ end
67
+ end
68
+ end
69
+
70
+ uri = "#{remote}/gems/#{spec.name}-#{spec.version}.gem"
71
+
72
+ if hash
73
+ begin
74
+ nix_prefetch_url(uri, hash)[SHA256_16]
75
+ rescue
76
+ nix_prefetch_url(uri)[SHA256_32]
77
+ end
78
+ else
79
+ nix_prefetch_url(uri)[SHA256_32]
80
+ end
81
+ end
82
+
83
+ def convert_rubygems
84
+ remotes = spec.source.remotes.map{|remote| remote.to_s.sub(/\/+$/, '') }
85
+ hash = fetch_local_hash(spec) || fetch_remotes_hash(spec, remotes)
86
+ hash = sh(NIX_HASH, '--type', 'sha256', '--to-base32', hash)[SHA256_32]
87
+ fail "couldn't fetch hash for #{spec.name}-#{spec.version}" unless hash
88
+ puts "#{hash} => #{spec.name}-#{spec.version}.gem" if $VERBOSE
89
+
90
+ {
91
+ type: 'gem',
92
+ remotes: remotes,
93
+ sha256: hash
94
+ }
95
+ end
96
+
97
+ def convert_git
98
+ revision = spec.source.options.fetch('revision')
99
+ uri = spec.source.options.fetch('uri')
100
+ hash = nix_prefetch_git(uri, revision)[/^\h{64}$/m]
101
+ hash = sh(NIX_HASH, '--type', 'sha256', '--to-base32', hash)[SHA256_32]
102
+ fail "couldn't fetch hash for #{spec.name}-#{spec.version}" unless hash
103
+ puts "#{hash} => #{uri}" if $VERBOSE
104
+
105
+ {
106
+ type: 'git',
107
+ url: uri.to_s,
108
+ rev: revision,
109
+ sha256: hash,
110
+ fetchSubmodules: false
111
+ }
112
+ end
113
+ end
114
+ end
data/lib/bundix.rb ADDED
@@ -0,0 +1,109 @@
1
+ require 'bundler'
2
+ require 'json'
3
+ require 'open-uri'
4
+ require 'open3'
5
+ require 'pp'
6
+
7
+ require_relative 'bundix/source'
8
+
9
+ class Bundix
10
+ VERSION = '2.0.0'
11
+
12
+ NIX_INSTANTIATE = 'nix-instantiate'
13
+ NIX_PREFETCH_URL = 'nix-prefetch-url'
14
+ NIX_PREFETCH_GIT = 'nix-prefetch-git'
15
+ NIX_HASH = 'nix-hash'
16
+
17
+ SHA256_32 = %r(^[a-z0-9]{52}$)
18
+ SHA256_16 = %r(^[a-f0-9]{64}$)
19
+
20
+ attr_reader :options
21
+
22
+ def initialize(options)
23
+ @options = {
24
+ gemset: './gemset.nix',
25
+ lockfile: './Gemfile.lock',
26
+ quiet: false,
27
+ tempfile: nil,
28
+ deps: false
29
+ }.merge(options)
30
+ end
31
+
32
+ def convert
33
+ cache = parse_gemset
34
+ lock = parse_lockfile
35
+
36
+ # reverse so git comes last
37
+ lock.specs.reverse_each.with_object({}) do |spec, gems|
38
+ name, cached = cache.find{|k, v|
39
+ k == spec.name &&
40
+ v['version'] == spec.version.to_s &&
41
+ v.dig('source', 'sha256').to_s.size == 52
42
+ }
43
+
44
+ if cached
45
+ gems[name] = cached
46
+ next
47
+ end
48
+
49
+ gems[spec.name] = {
50
+ version: spec.version.to_s,
51
+ source: Source.new(spec).convert
52
+ }
53
+
54
+ if options[:deps] && spec.dependencies.any?
55
+ gems[spec.name][:dependencies] = spec.dependencies.map(&:name) - ['bundler']
56
+ end
57
+ end
58
+ end
59
+
60
+ def parse_gemset
61
+ return {} unless File.file?(options[:gemset])
62
+ json = Bundix.sh(
63
+ NIX_INSTANTIATE, '--eval', '-E', "builtins.toJSON(import #{options[:gemset]})")
64
+ JSON.parse(json.strip.gsub(/\\"/, '"')[1..-2])
65
+ end
66
+
67
+ def parse_lockfile
68
+ Bundler::LockfileParser.new(File.read(options[:lockfile]))
69
+ end
70
+
71
+ def self.object2nix(obj, level = 2, out = '')
72
+ case obj
73
+ when Hash
74
+ out << "{\n"
75
+ obj.each do |k, v|
76
+ out << ' ' * level
77
+ if k.to_s =~ /^[a-zA-Z_-]+[a-zA-Z0-9_-]*$/
78
+ out << k.to_s
79
+ else
80
+ object2nix(k, level + 2, out)
81
+ end
82
+ out << ' = '
83
+ object2nix(v, level + 2, out)
84
+ out << (v.is_a?(Hash) ? "\n" : ";\n")
85
+ end
86
+ out << (' ' * (level - 2)) << (level == 2 ? '}' : '};')
87
+ when Array
88
+ out << '[' << obj.map{|o| o.to_str.dump }.join(' ') << ']'
89
+ when String
90
+ out << obj.dump
91
+ when Symbol
92
+ out << obj.to_s.dump
93
+ when true, false
94
+ out << obj.to_s
95
+ else
96
+ fail obj.inspect
97
+ end
98
+ end
99
+
100
+ def self.sh(*args)
101
+ out, status = Open3.capture2e(*args)
102
+ unless status.success?
103
+ puts "$ #{args.join(' ')}" if $VERBOSE
104
+ puts out if $VERBOSE
105
+ fail "command execution failed: #{status}"
106
+ end
107
+ out
108
+ end
109
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bundix
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael 'manveru' Fellinger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-27 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Creates Nix packages from Gemfiles.
14
+ email:
15
+ executables:
16
+ - bundix
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/bundix
21
+ - lib/bundix.rb
22
+ - lib/bundix/source.rb
23
+ homepage: https://github.com/manveru/bundix
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.5.1
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: Creates Nix packages from Gemfiles.
47
+ test_files: []