Skip to content

Instantly share code, notes, and snippets.

@cbandy
Last active August 29, 2015 14:02
Show Gist options
  • Save cbandy/9e3b5d69e16f1bc85eaf to your computer and use it in GitHub Desktop.
Save cbandy/9e3b5d69e16f1bc85eaf to your computer and use it in GitHub Desktop.
Play with libsolv
$ ls -lvh ~/.gem/specs/*/*specs*
-rw-rw-r-- 1 cbandy cbandy 1.9M Mar 6 05:45 ~/.gem/specs/api.rubygems.org%443/latest_specs.4.8
-rw-rw-r-- 1 cbandy cbandy 1.9M Mar 7 14:25 ~/.gem/specs/rubygems.org%80/latest_specs.4.8
-rw-rw-r-- 1 cbandy cbandy 5.6M Mar 6 05:38 ~/.gem/specs/rubygems.org%80/specs.4.8
-rw-rw-r-- 1 cbandy cbandy 2.0M Jun 4 05:00 ~/.gem/specs/rubygems.org%443/latest_specs.4.8
-rw-rw-r-- 1 cbandy cbandy 6.0M Jun 17 13:50 ~/.gem/specs/rubygems.org%443/specs.4.8
$ ls -lvh rubygems.solv
-rw-rw-r-- 1 cbandy cbandy 3.1M Jun 17 13:51 rubygems.solv
$ cat ~/.gem/specs/rubygems.org%443/specs.4.8 | gzip | wc -c
1802187
$ cat rubygems.solv | gzip | wc -c
1490050
sudo apt-get install cmake
sudo apt-get install libexpat1-dev
sudo apt-get install swig
mkdir build
cd build
cmake -D ENABLE_RUBY:BOOL=ON -D ENABLE_DEBIAN:BOOL=ON ..
make
~/libsolv/build/bindings/ruby$ irb -r './solv'
irb(main):001:0> Solv
=> Solv
irb(main):002:0> pool = Solv::Pool.new
=> #<Solv::Pool:0x0000000195b338 @__swigtype__="_p_Pool">
irb(main):003:0> repo = pool.add_repo('installed')
=> <Repo #1 installed>
irb(main):004:0> repo.add_debdb
=> true
irb(main):005:0> repo.nsolvables
=> 655
irb(main):011:0> htop = repo.solvables.find { |solvable| solvable.name == 'htop' }
=> <Solvable #259 htop-1.0.1-1.amd64>
irb(main):012:0> htop.arch
=> "amd64"
irb(main):013:0> htop.evr
=> "1.0.1-1"
irb(main):014:0> htop.vendor
=> "<NULL>"
irb(main):018:0> htop.to_s
=> "htop-1.0.1-1.amd64"
irb(main):023:0> htop.lookup_deparray(Solv::SOLVABLE_REQUIRES)
=> [<Id #-2147483570 libc6 >= 2.15>, <Id #-2147483399 libncursesw5 >= 5.6+20070908>, <Id #400 libtinfo5>]
irb(main):024:0> dep = pool.Dep('bundler')
=> <Id #3451 bundler>
irb(main):028:0> one = pool.str2id('1.0.0')
=> 317
irb(main):029:0> reldep = dep.Rel(Solv::REL_EQ | Solv::REL_GT, one)
=> <Id #-2147481736 bundler >= 1.0.0>
irb(main):030:0> reldep.to_s
=> "bundler >= 1.0.0"
irb(main):031:0> pool.rel2id(pool.str2id('bundler'), pool.str2id('1.0.0'), Solv::REL_EQ | Solv::REL_GT)
=> -2147481736
irb(main):032:0> dep2 = pool.Dep('bundler >= 1.0.0')
=> <Id #3452 bundler >= 1.0.0>
irb(main):033:0> htop.add_deparray(Solv::SOLVABLE_REQUIRES, dep2)
=> nil
irb(main):034:0> htop.lookup_deparray(Solv::SOLVABLE_REQUIRES)
=> [<Id #-2147483570 libc6 >= 2.15>, <Id #-2147483399 libncursesw5 >= 5.6+20070908>, <Id #400 libtinfo5>, <Id #3452 bundler >= 1.0.0>]
1 amd64-freebsd-8
1 dalvik10
1 i386-mswin32-mq5.3
1 i386-mswin32-mq6
1 i686-darwin10
1 i686-darwin8.8.2
1 i686-darwin8.9.1
1 ironruby
1 powerpc-darwin8.3.0
1 Ruby
1 sparc-solaris2.8-mq5.3
1 universal-darwin-11
1 universal-darwin-13
1 universal-dotnet-2.0
1 universal-jruby-1.2
1 universal-mingw
1 universal-mswin32
1 universal-.net-2.0
1 universal-rubinius-1.2.1
1 x86_64-darwin10.8.0
1 x86_64-darwin12.0.0
1 x86_64-mingw64
1 x86_64-solaris-2.11
1 x86-freebsd-9
2 android
2 i386-linux
2 i686-darwin8.4.1
2 powerpc-darwin8.10.0
2 sparc-solaris-2.10
2 universal-macruby
2 universal-.net
2 universal-ruby-1.9.3
2 windows
2 x86_64-darwin11.3.0
2 x86-darwin-11
2 x86-mingw32-1.9.2
2 x86-mswin32-1.9.2
2 x86-mswin32-80
2 x86-solaris-2.10
3 amd64-freebsd-9
3 armv6l-linux
3 do_not_install
3 universal-darwin9.0
3 x64-mswin64-100
4 universal-freebsd
4 universal-rubinius
4 universal-rubinius-2.0
4 universal-ruby-1.9.2
4 universal-solaris
4 x86-darwin-8
4 x86-freebsd-7
4 x86-mingw32-1.9.1
4 x86-mswin32-1.9.1
5 universal-ruby-1.8.7
5 x86_64-darwin
5 x86-cygwin
6 linux
6 universal-darwin-8
7 x86_64-darwin-13
8 arm-linux
8 universal-java-1.7
9 universal-darwin8.0
10 x86-mswin32-100
11 i486-linux
11 powerpc-darwin
11 x86_64-darwin-11
13 universal-linux
13 x86-darwin-9
14 universal-java-1.5
15 x86_64-darwin10.7.0
17 x86_64-darwin-10
19 x86_64-darwin-12
21 mingw32
23 universal-mingw32
25 i586-linux
29 universal-darwin-10
32 universal-rubinius-1.2
33 universal-darwin-9
35 x86-darwin-10
49 i686-linux
52 universal-java
56 x64-mingw32
62 universal-java-1.6
68 darwin
68 universal-dotnet
97 universal-darwin
100 x86_64-linux
144 jruby
170 x86-linux
239 i386-mswin32
252 i386-mingw32
255 x86-mswin32
376 mswin32
460 x86-mswin32-60
1362 x86-mingw32
3047 java
411952 ruby
#require 'solv'
module RubySolv
def self.extended(other)
ruby_platforms = { Gem::Platform::RUBY => Solv::ARCH_ANY }
Gem::Platform.new('java').to_s.tap { |java| ruby_platforms[java] = other.str2id(java) }
other.instance_variable_set(:@ruby_platforms, ruby_platforms)
end
def archid_from_platform(gem_platform)
key = gem_platform.to_s
@ruby_platforms[key] ||= str2id(Gem::Platform === gem_platform ? key : Gem::Platform.new(gem_platform).to_s)
end
def relids_from_dependency(gem_dependency)
relations = []
gem_dependency.requirement.requirements.each do |(operation, version)|
case operation
when '='
relations << [gem_dependency.name, version.to_s, Solv::REL_EQ]
when '!='
relations << [gem_dependency.name, version.to_s, Solv::REL_GT | Solv::REL_LT]
when '>'
relations << [gem_dependency.name, version.to_s, Solv::REL_GT]
when '<'
relations << [gem_dependency.name, version.to_s, Solv::REL_LT]
when '>='
relations << [gem_dependency.name, version.to_s, Solv::REL_EQ | Solv::REL_GT]
when '<='
relations << [gem_dependency.name, version.to_s, Solv::REL_EQ | Solv::REL_LT]
when '~>'
relations << [gem_dependency.name, version.to_s, Solv::REL_EQ | Solv::REL_GT]
relations << [gem_dependency.name, version.bump.to_s, Solv::REL_LT]
end
end
relations.map do |(name, version, flags)|
rel2id(str2id(name), str2id(version), flags)
end
end
end
pool = Solv::Pool.new
pool.extend RubySolv
pool.installed = pool.add_repo('installed')
Gem::Specification.find_all.each do |gem|
solvable = pool.installed.add_solvable
solvable.name = gem.name
solvable.evr = gem.version.to_s
solvable.archid = pool.archid_from_platform(gem.platform)
gem.dependencies.select { |dep| dep.type == :runtime }.each do |gem_dep|
pool.relids_from_dependency(gem_dep).each do |relation|
solvable.add_deparray(Solv::SOLVABLE_REQUIRES, relation)
end
end
end
#puts pool.installed.solvables.to_a
require 'rubygems/name_tuple'
require 'rubygems/remote_fetcher'
rubygems = pool.add_repo('https://rubygems.org')
source = Gem::Source.new('https://rubygems.org')
source.load_specs(:released).each do |tuple|
solvable = rubygems.add_solvable
solvable.name = tuple.name
solvable.evr = tuple.version.to_s
solvable.archid = pool.archid_from_platform(tuple.platform)
end
File.open('rubygems.solv', 'w') do |file|
rubygems.write(Solv::xfopen_fd('', file.fileno))
end
#count_platforms = {}
#source.load_specs(:released).each do |tuple|
# count_platforms[tuple.platform] ||= 0
# count_platforms[tuple.platform] += 1
#end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment