pandler 0.0.1

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 (37) hide show
  1. data/.gitignore +23 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +47 -0
  5. data/Rakefile +10 -0
  6. data/Vagrantfile +33 -0
  7. data/bin/pandle +8 -0
  8. data/etc/yum/pandler.py +52 -0
  9. data/lib/pandler.rb +8 -0
  10. data/lib/pandler/chroot.rb +229 -0
  11. data/lib/pandler/cli.rb +40 -0
  12. data/lib/pandler/version.rb +3 -0
  13. data/lib/pandler/yumfile.rb +26 -0
  14. data/lib/pandler/yumrepo.rb +240 -0
  15. data/pandler.gemspec +24 -0
  16. data/spec/pandler/chroot_spec.rb +93 -0
  17. data/spec/pandler/cli_spec.rb +20 -0
  18. data/spec/pandler/yumfile_spec.rb +20 -0
  19. data/spec/pandler/yumrepo_spec.rb +152 -0
  20. data/spec/pandler_spec.rb +8 -0
  21. data/spec/resources/yumrepo/pandler-test-0.0.1-1.x86_64.rpm +0 -0
  22. data/spec/resources/yumrepo/pandler-test-a-0.0.1-1.x86_64.rpm +0 -0
  23. data/spec/resources/yumrepo/pandler-test-a-0.0.2-1.x86_64.rpm +0 -0
  24. data/spec/resources/yumrepo/pandler-test-dep-a-0.0.1-1.x86_64.rpm +0 -0
  25. data/spec/resources/yumrepo/pandler-test-dep-b-0.0.1-1.x86_64.rpm +0 -0
  26. data/spec/resources/yumrepo/pandler-test-dep-required-0.0.1-1.x86_64.rpm +0 -0
  27. data/spec/resources/yumrepo/pandler-test-dep-required-required-0.0.1-1.x86_64.rpm +0 -0
  28. data/spec/resources/yumrepo/repodata/09267893997a9b34726567132f642093ebd2a4b5e65096a6562efc3a29106723-other.xml.gz +0 -0
  29. data/spec/resources/yumrepo/repodata/596e9069dad80db19e7ba4c36b3df1e52583231b95bfa61186408c77520a213a-primary.xml.gz +0 -0
  30. data/spec/resources/yumrepo/repodata/7dd30f881bb1b1cbd723a5fa9d996b96805e25015b56140c99a444bf248c4260-other.sqlite.bz2 +0 -0
  31. data/spec/resources/yumrepo/repodata/8e6f832a8605163914b5aaf46e42daeaad10f9785d202c6c99c9d903354b3194-filelists.xml.gz +0 -0
  32. data/spec/resources/yumrepo/repodata/a810cd5676bb578a196231dae1f37179241630f6745a3d33691279ff61bfe175-primary.sqlite.bz2 +0 -0
  33. data/spec/resources/yumrepo/repodata/ad696c5b02dadaef085b16712ce0464ae0d4c102b3ccf1ce0f14e371a119463a-filelists.sqlite.bz2 +0 -0
  34. data/spec/resources/yumrepo/repodata/repomd.xml +55 -0
  35. data/spec/spec_helper.rb +82 -0
  36. data/vagrant_file.sh +30 -0
  37. metadata +156 -0
@@ -0,0 +1,40 @@
1
+ require "pandler"
2
+ require "thor"
3
+
4
+ class Pandler::CLI < Thor
5
+ class_option :yumfile, :type => :string, :aliases => "-f", :desc => "Default: Yumfile"
6
+
7
+ def initialize(args=[], options={}, config={})
8
+ super
9
+ @chroot = Pandler::Chroot.new
10
+ @yumrepo = Pandler::Yumrepo.new
11
+ end
12
+
13
+ desc "version", "Display pandler version"
14
+ map ["-v", "--version"] => :version
15
+ def version
16
+ puts Pandler::VERSION
17
+ end
18
+
19
+ desc "install", "Install"
20
+ def install
21
+ @chroot.init
22
+ @yumrepo.createrepo
23
+ @chroot.install(*@yumrepo.install_pkgs)
24
+ end
25
+
26
+ desc "list", "List"
27
+ def list
28
+ puts @chroot.list
29
+ end
30
+
31
+ desc "clean", "Clean"
32
+ def clean
33
+ @chroot.clean
34
+ end
35
+
36
+ desc "exec", "Execute"
37
+ def exec(*cmd)
38
+ @chroot.execute(*cmd)
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Pandler
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ class Pandler::Yumfile
2
+ attr_reader :repos, :rpms
3
+
4
+ def initialize(filename)
5
+ @repos = {}
6
+ @rpms = []
7
+ load_file(filename) if File.exists? filename
8
+ end
9
+
10
+ private
11
+
12
+ def load_file(filename)
13
+ contents = File.read(filename)
14
+ instance_eval(contents, filename, 1)
15
+ @rpms.sort!
16
+ self
17
+ end
18
+
19
+ def repo(name, url)
20
+ @repos[name] = url
21
+ end
22
+
23
+ def rpm(name)
24
+ @rpms.push(name)
25
+ end
26
+ end
@@ -0,0 +1,240 @@
1
+ require "erb"
2
+ require "open3"
3
+ require "yaml"
4
+
5
+ class Hash
6
+ def to_yaml( opts = {} )
7
+ YAML::quick_emit( object_id, opts ) do |out|
8
+ out.map( taguri, to_yaml_style ) do |map|
9
+ sort.each do |k, v|
10
+ map.add( k, v )
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ class Pandler::Yumrepo
18
+ attr_reader :base_dir, :repo_dir, :yumfile_path, :lockfile_path
19
+ def initialize(args = {})
20
+ @base_dir = args[:base_dir] || File.expand_path("pandler")
21
+ @repo_dir = args[:repo_dir] || File.join(base_dir, "yumrepo")
22
+ @yumfile_path = args[:yumfile_path] || File.expand_path("Yumfile")
23
+ @lockfile_path = args[:lockfile_path] || yumfile_path + ".lock"
24
+
25
+ @cache_dir = File.join(base_dir, "yumcache")
26
+ @yum_log = File.join(@cache_dir, "/var/lib/yum/pandler.log")
27
+ FileUtils.mkdir_p base_dir
28
+ FileUtils.mkdir_p repo_dir
29
+ FileUtils.mkdir_p @cache_dir
30
+
31
+ @yumfile = Pandler::Yumfile.new(yumfile_path)
32
+ @lockfile = read_lockfile
33
+ end
34
+
35
+ def createrepo
36
+ setup_dirs
37
+ setup_files
38
+ yum_download
39
+ write_lockfile
40
+ symlink_pkgs
41
+ run_cmd("createrepo", "-v", repo_dir)
42
+ end
43
+
44
+ def install_pkgs
45
+ specs.sort_by { |package, spec| spec["name"] }.map { |package, spec| package }
46
+ end
47
+
48
+ def specs
49
+ @specs
50
+ end
51
+
52
+ private
53
+
54
+ def run_cmd(*cmd)
55
+ ret = Kernel.system(*cmd)
56
+ raise "command failed(ret: #{ret}) '#{cmd.join(" ")}'" unless ret
57
+ end
58
+
59
+ def repos
60
+ @yumfile.repos
61
+ end
62
+
63
+ def rpms
64
+ @yumfile.rpms
65
+ end
66
+
67
+ def read_lockfile
68
+ File.exists?(lockfile_path) ? YAML.load_file(lockfile_path) : nil
69
+ end
70
+
71
+ def write_lockfile
72
+ open(@lockfile_path, "w") do |f|
73
+ YAML.dump({
74
+ "repos" => repos,
75
+ "rpms" => rpms,
76
+ "specs" => specs,
77
+ }, f)
78
+ end
79
+ end
80
+
81
+ def yum_download
82
+ run_cmd(*yum("install", *download_pkgs))
83
+ update_specs
84
+ end
85
+
86
+ def download_pkgs
87
+ pkgs = []
88
+ if @lockfile.nil?
89
+ pkgs = rpms
90
+ else
91
+ pkgs = @lockfile["specs"].keys
92
+ new_pkgs = rpms - @lockfile["rpms"]
93
+ removed_pkgs = @lockfile["rpms"] - rpms
94
+
95
+ if new_pkgs.size > 0
96
+ pkgs += new_pkgs
97
+ end
98
+
99
+ if removed_pkgs.size > 0
100
+ removed_pkgs.each do |rm|
101
+ rm_package = ""
102
+ @lockfile["specs"].each { |package, spec| rm_package = package if spec["name"] == rm }
103
+ rpms_package = []
104
+ rpms.each { |name| @lockfile["specs"].each { |package, spec| rpms_package.push package if spec["name"] == name } }
105
+ @lockfile["specs"].each do |package, spec|
106
+ if spec["comesfrom"].include? rm_package
107
+ if spec["comesfrom"].select { |pkg| rpms_package.include?(pkg) or pkg == rm_package } == [rm_package]
108
+ pkgs.delete(package)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ pkgs
116
+ end
117
+
118
+ def update_specs
119
+ @specs = read_yum_log
120
+ solve_comesfrom
121
+ end
122
+
123
+ def read_yum_log
124
+ results = {}
125
+ File.open(@yum_log).each_line do |log|
126
+ data = Hash[log.chomp.split("\t").map{|f| f.split(":", 2)}]
127
+ if results.has_key? data["package"]
128
+ results[data["package"]]["relatedto"].push data["relatedto"]
129
+ else
130
+ package = data.delete("package")
131
+ data["relatedto"] = [data["relatedto"]] if data.has_key?("relatedto")
132
+ results[package] = data
133
+ end
134
+ end
135
+ results
136
+ end
137
+
138
+ def solve_comesfrom
139
+ @specs.each do |package, spec|
140
+ checked_pkg = {}
141
+ @specs[package]["comesfrom"] = comesfrom(package, checked_pkg)
142
+ end
143
+ end
144
+
145
+ def comesfrom(pkgs, checked_pkg)
146
+ rpm_list = []
147
+ pkgs.each do |pkg|
148
+ next if checked_pkg[pkg]
149
+
150
+ checked_pkg[pkg] = true
151
+ spec = @specs[pkg]
152
+
153
+ rpm_list.push pkg if rpms.include?(@specs[pkg]["name"])
154
+ if spec.has_key? "relatedto"
155
+ spec["relatedto"].each do |related|
156
+ rpm_list.push related if rpms.include?(@specs[related]["name"])
157
+ end
158
+ rpm_list += comesfrom(spec["relatedto"], checked_pkg)
159
+ end
160
+ end
161
+ rpm_list.uniq
162
+ end
163
+
164
+ def yum(*args)
165
+ cmd = ["yum", "--disableplugin=*", "--enableplugin=pandler"]
166
+ cmd += ["--installroot", @cache_dir, *args]
167
+ cmd
168
+ end
169
+
170
+ def symlink_pkgs
171
+ Dir.chdir(repo_dir) do
172
+ pkgs = Dir.glob("../yumcache/var/cache/yum/**/packages/*.rpm")
173
+ FileUtils.mkdir_p repo_dir
174
+ FileUtils.ln_s(pkgs, ".", { :force => true })
175
+ end
176
+ end
177
+
178
+ def setup_dirs
179
+ dirs = [
180
+ '/var/lib/rpm',
181
+ '/var/lib/yum',
182
+ '/var/log',
183
+ '/var/lock/rpm',
184
+ '/var/cache/yum',
185
+ '/tmp',
186
+ '/var/tmp',
187
+ '/etc/yum.repos.d',
188
+ '/etc/yum',
189
+ '/etc/yum/plugin',
190
+ '/etc/yum/pluginconf.d',
191
+ ]
192
+ dirs.each do |dir|
193
+ FileUtils.mkdir_p(File.join(@cache_dir, dir))
194
+ end
195
+ end
196
+
197
+ def setup_files
198
+ open(File.join(@cache_dir, "/etc/yum/yum.conf"), "w") { |f| f.write yum_conf }
199
+ open(File.join(@cache_dir, "/etc/yum/pluginconf.d/pandler.conf"), "w") { |f| f.write plugin_conf }
200
+ FileUtils.cp(yum_plugin_path, File.join(@cache_dir, "/etc/yum/plugin"))
201
+ end
202
+
203
+ def yum_plugin_path
204
+ File.expand_path("../../../etc/yum/pandler.py", __FILE__)
205
+ end
206
+
207
+ def yum_conf
208
+ content = ERB.new <<-EOF
209
+ [main]
210
+ cachedir=/var/cache/yum
211
+ debuglevel=1
212
+ reposdir=/dev/null
213
+ logfile=/var/log/yum.log
214
+ retries=20
215
+ obsoletes=1
216
+ gpgcheck=0
217
+ assumeyes=1
218
+ syslog_ident=pandler
219
+ syslog_device=
220
+ plugins=1
221
+ pluginpath=<%= @cache_dir %>/etc/yum/plugin
222
+ pluginconfpath=<%= @cache_dir %>/etc/yum/pluginconf.d
223
+ <% repos.each { |repo, url| %>
224
+ [<%= repo %>]
225
+ name=<%= repo %>
226
+ enabled=1
227
+ baseurl=<%= url %>
228
+ <% } %>
229
+ EOF
230
+ content.result(binding)
231
+ end
232
+
233
+ def plugin_conf
234
+ content = <<-EOF
235
+ [main]
236
+ enabled=1
237
+ EOF
238
+ content
239
+ end
240
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pandler/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "pandler"
8
+ gem.version = Pandler::VERSION
9
+ gem.authors = ["Ryosuke IWANAGA"]
10
+ gem.email = ["riywo.jp@gmail.com"]
11
+ gem.description = %q{Manage your packages with chroot}
12
+ gem.summary = %q{Yumfile}
13
+ gem.homepage = "https://github.com/riywo/pandler"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'thor', '>= 0.13.6'
21
+
22
+ gem.add_development_dependency 'rake', '>= 0.9.2.2'
23
+ gem.add_development_dependency 'rspec'
24
+ end
@@ -0,0 +1,93 @@
1
+ require "pathname"
2
+
3
+ describe Pandler::Chroot do
4
+ include TempDirHelper
5
+ before :all do
6
+ # @base_dir = File.expand_path("../../../.spec_cache", __FILE__)
7
+ yumrepo = "file://" + File.expand_path("../../resources/yumrepo", __FILE__)
8
+ @chroot = Pandler::Chroot.new(:yumrepo => yumrepo)
9
+ end
10
+
11
+ subject { @chroot }
12
+ its(:root_dir) { should eq "#{@chroot.base_dir}/root" }
13
+
14
+ describe "chroot file path" do
15
+ subject { @chroot.real_path("/") }
16
+ it { should eq @chroot.root_dir + "/" }
17
+ end
18
+
19
+ describe "init" do
20
+ before(:all) { @chroot.init }
21
+ it "should create directories" do
22
+ [
23
+ '/var/lib/rpm',
24
+ '/var/lib/yum',
25
+ '/var/lib/dbus',
26
+ '/var/log',
27
+ '/var/lock/rpm',
28
+ '/var/cache/yum',
29
+ '/etc/rpm',
30
+ '/tmp',
31
+ '/tmp/ccache',
32
+ '/var/tmp',
33
+ '/etc/yum.repos.d',
34
+ '/etc/yum',
35
+ '/proc',
36
+ '/sys',
37
+ ].each do |path|
38
+ Pathname(@chroot.real_path(path)).should exist
39
+ end
40
+ end
41
+ it "should create files" do
42
+ [
43
+ '/etc/mtab',
44
+ '/etc/fstab',
45
+ '/var/log/yum.log',
46
+ '/etc/yum/yum.conf',
47
+ '/etc/yum.conf',
48
+ '/etc/resolv.conf',
49
+ '/etc/hosts',
50
+ ].each do |path|
51
+ Pathname(@chroot.real_path(path)).should exist
52
+ end
53
+ end
54
+ it "should create devs" do
55
+ [
56
+ '/dev/null',
57
+ '/dev/full',
58
+ '/dev/zero',
59
+ '/dev/random',
60
+ '/dev/urandom',
61
+ '/dev/tty',
62
+ '/dev/console',
63
+ '/dev/stdin',
64
+ '/dev/stdout',
65
+ '/dev/stderr',
66
+ '/dev/fd',
67
+ # '/dev/ptmx',
68
+ ].each do |path|
69
+ Pathname(@chroot.real_path(path)).should exist
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "install first time" do
75
+ before(:all) { @chroot.install("pandler-test-0.0.1-1.x86_64", "pandler-test-a-0.0.1-1.x86_64") }
76
+ it "should execute /pandler-test" do
77
+ Kernel.system("chroot", @chroot.root_dir, "/pandler-test").should be_true
78
+ end
79
+ end
80
+
81
+ describe "exec /pandler-test" do
82
+ subject { capture_stdout { @chroot.execute("/pandler-test") } }
83
+ it { should eq "pandler test\n" }
84
+ end
85
+
86
+ describe "install second time" do
87
+ before(:all) { @chroot.install("pandler-test-0.0.1-1.x86_64") }
88
+ subject { @chroot.installed_pkgs }
89
+ it { should eq ["pandler-test-0.0.1-1.x86_64"] }
90
+ end
91
+
92
+ after(:all) { @chroot.clean }
93
+ end
@@ -0,0 +1,20 @@
1
+ describe Pandler::CLI do
2
+ include TempDirHelper
3
+ include PandleHelper
4
+ describe "version" do
5
+ it "displays gem version" do
6
+ pandle("version").chomp.should == Pandler::VERSION
7
+ end
8
+
9
+ it "displays gem version on shortcut command" do
10
+ pandle("-v").chomp.should == Pandler::VERSION
11
+ end
12
+ end
13
+
14
+ =begin
15
+ describe "exec echo 'test'" do
16
+ subject { pandle("exec echo 'test'") }
17
+ it { should eq "test\n" }
18
+ end
19
+ =end
20
+ end