ropes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Mjg3YzUwYjBmNTFiMmQ4MGI1NGJiMjdkZWJkMTFlNjQ3NGNlOGU5Yg==
5
+ data.tar.gz: !binary |-
6
+ NDJmMzAzMWVlZGI1YmJiMjMwMjUwZWFmYjZmNmZiNzQ1ZDYxMzM1Mw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NDBmY2Q0Y2Y5ZDIxNGIyNTBhOGM2ODg4ZmFjN2RhZGMwYmNhZGM0OTAyYmRm
10
+ YTkxZDcwN2QyNTU3ZjY0YTIwOGI4M2Q2YmM1OTgzZjQ5OGYwMjA1YTQ0Mzky
11
+ OTQxMTVhMjE2MWQ2MTk4MWY5NjJjMjIyMjAyMTI5YjEzZmYwYTE=
12
+ data.tar.gz: !binary |-
13
+ YWNjZGUzZDk0MmIwYWE3Yzk2ODUwOWVhNGQzNDUzNTYxZWQyODI4ODA5YTdh
14
+ ZTVmMWM2ZTFjZWU0ZjlmNjYyNTMyYmE0YzUwMDkzYjk0ZmM5OWE2NGMyOGEw
15
+ M2MwZTY3NDRhNjYzNWJhYmFjMGVmZmVkZGQ3Mjc3MmY3NTZlYWQ=
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .ruby-version
19
+ .ruby-gemset
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ropes.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Andy Sykes
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Ropes
2
+
3
+ This is a simple gem you can use either programmatically or via a simple utility to build
4
+ apt and yum repositories from either a directory of package files, or from information
5
+ you supply.
6
+
7
+ It will generate the following files:
8
+ * `Releases`
9
+ * `Releases.gpg` (if you specify a GPG key to use)
10
+ * `Contents-{arch}.gz`
11
+ * `Packages`
12
+ * `Packages.gz`
13
+ * `Packages.bz2`
14
+
15
+ ## Current status
16
+
17
+ As of 0.0.1, it generates only `Releases`, `Releases.gpg`, `Packages` and `Packages.gz`.
18
+ This is enough to get a basic Ubuntu repository working. There is no yum support.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'ropes'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install ropes
33
+
34
+ ## Usage
35
+
36
+ Here's an example of creating a repository object, adding a few packages to it,
37
+ then retrieving the various repository files. It's your reponsibility at the moment
38
+ to put files in the correct places - once there's a command line tool, it'll do this
39
+ for you.
40
+
41
+ repo = Ropes::Repository.new({
42
+ :origin => "andytinycat",
43
+ :type => :apt,
44
+ :distribution => "precise",
45
+ :version => "12.04",
46
+ :architecture => "amd64",
47
+ :components => "main",
48
+ :description => "testing",
49
+ :package_base => "packages"
50
+ })
51
+
52
+ repo.add_file_by_path("some_custom_package.deb")
53
+
54
+ File.open("Packages", "w") do |file|
55
+ file.write repo.packages_file
56
+ end
57
+
58
+ File.open("Release", "w") do |file|
59
+ file.write repo.release_file
60
+ end
61
+
62
+ File.open("Release.gpg", "w") do |file|
63
+ file.write repo.release_file_gpg("/path/to/your/gpg.key")
64
+ end
65
+
66
+ File.open("Packages.gz", "w") do |file|
67
+ file.write repo.packages_file_gz
68
+ end
69
+
70
+ ## Contributing
71
+
72
+ 1. Fork it
73
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
74
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
75
+ 4. Push to the branch (`git push origin my-new-feature`)
76
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,173 @@
1
+ require 'debeasy'
2
+ require 'stringio'
3
+ require 'zlib'
4
+ require 'tempfile'
5
+ require 'digest'
6
+ require 'gpgme'
7
+ require 'uuid'
8
+
9
+ module Ropes
10
+
11
+ class Error < RuntimeError; end
12
+ class InvalidRepositoryType < Error; end
13
+
14
+ class Repository
15
+
16
+ def initialize(options)
17
+ missing_options = %w{
18
+ origin
19
+ type
20
+ distribution
21
+ version
22
+ architecture
23
+ components
24
+ description
25
+ package_base}.reject do |required_option|
26
+ options.has_key?(required_option.to_sym)
27
+ end
28
+
29
+ raise "Missing options: #{missing_options.join(", ")}" unless missing_options.empty?
30
+
31
+ raise InvalidRepositoryType, "Repository type #{options[:type]} is neither :apt or :yum" unless options[:type] == :yum or options[:type] == :apt
32
+
33
+ @release_file = nil
34
+ @packages_file = nil
35
+ @packages_field_gz = nil
36
+
37
+ @options = options
38
+ @packages = []
39
+ @field_order = %w{
40
+ package
41
+ priority
42
+ section
43
+ installed_size
44
+ maintainer
45
+ architecture
46
+ source
47
+ version
48
+ depends
49
+ filename
50
+ size
51
+ MD5sum
52
+ SHA1
53
+ SHA256
54
+ description
55
+ description-md5
56
+ bugs
57
+ origin
58
+ supported
59
+ }
60
+ @mandatory_fields = %w{
61
+ package
62
+ version
63
+ architecture
64
+ maintainer
65
+ description
66
+ }
67
+ end
68
+
69
+ def add_file_by_path(path)
70
+ metadata = Debeasy.read(path).to_hash
71
+ if validate_metadata(metadata).empty?
72
+ @packages << metadata
73
+ else
74
+ raise "Missing mandatory fields on package: #{validate_metadata(metadata).join(", ")}"
75
+ end
76
+ end
77
+
78
+ def add_file_by_info(package)
79
+ if validate_metadata(path).empty?
80
+ if package.is_a? Hash
81
+ @packages << package
82
+ else
83
+ raise "Package metadata must be in hash format"
84
+ end
85
+ else
86
+ raise "Missing mandatory fields on package: #{validate_metadata(metadata).join(", ")}"
87
+ end
88
+ end
89
+
90
+ # Get the Packages file as a string
91
+
92
+ def packages_file
93
+ return @packages_file unless @packages_file.nil?
94
+ entries = @packages.map do |package|
95
+ lines = []
96
+ @field_order.each do |field|
97
+ if package[field] != nil
98
+ case field
99
+ when "filename"
100
+ lines << packages_line(field.capitalize, "#{@options[:package_base]}/#{package[field]}")
101
+ when "installed_size"
102
+ lines << packages_line("Installed-Size", package[field])
103
+ when "SHA1", "SHA256", "MD5sum"
104
+ lines << packages_line(field, package[field])
105
+ else
106
+ lines << packages_line(field.capitalize, package[field])
107
+ end
108
+ end
109
+ end
110
+ lines.join("\n")
111
+ end
112
+ @packages_file = entries.join("\n\n") + "\n"
113
+ end
114
+
115
+ # Get the Packages file as a gzip'ed string
116
+
117
+ def packages_file_gz
118
+ io = StringIO.new("w")
119
+ gz = Zlib::GzipWriter.new(io)
120
+ gz.write(packages_file())
121
+ gz.close
122
+ io.string
123
+ end
124
+
125
+ # Get the Release file as a string
126
+
127
+ def release_file
128
+
129
+ # Have to create the files in real life to get the real size
130
+ temp_packages_file = Tempfile.new("Packages")
131
+ temp_packages_file.write packages_file
132
+ temp_packages_file_gz= Tempfile.new("Packages.gz")
133
+ temp_packages_file_gz.write packages_file_gz
134
+
135
+ lines = []
136
+ lines << "Origin: #{@options[:origin]}"
137
+ lines << "Label: #{@options[:origin]}"
138
+ lines << "Suite: #{@options[:distribution]}"
139
+ lines << "Version: #{@options[:version]}"
140
+ lines << "Codename: #{@options[:distribution]}"
141
+ lines << "Date: #{Time.new.utc.strftime '%a, %d %b %Y %H:%M:%S UTC'}"
142
+ lines << "Architectures: #{@options[:architecture]}"
143
+ lines << "Components: #{@options[:components]}"
144
+ lines << "Description: #{@options[:description]}"
145
+ lines << "MD5Sum:"
146
+ lines << " #{Digest::MD5.hexdigest(packages_file)} #{temp_packages_file.size} #{@options[:components]}/binary-#{@options[:architecture]}/Packages"
147
+ lines << " #{Digest::MD5.hexdigest(packages_file_gz)} #{temp_packages_file_gz.size} #{@options[:components]}/binary-#{@options[:architecture]}/Packages.gz"
148
+ lines.join("\n") + "\n"
149
+ end
150
+
151
+ # Get detached GPG signature of Release file
152
+
153
+ def release_file_gpg(path_to_gpgkey)
154
+ GPGME::Key.import(File.open(path_to_gpgkey))
155
+ GPGME::Crypto.new.sign(release_file, {
156
+ :mode => GPGME::SIG_MODE_DETACH,
157
+ :armor => true
158
+ })
159
+ end
160
+
161
+ private
162
+
163
+
164
+ def packages_line(field, value)
165
+ "#{field}: #{value}"
166
+ end
167
+
168
+ def validate_metadata(metadata_hash)
169
+ @mandatory_fields.reject {|field| metadata_hash.has_key?(field)}
170
+ end
171
+
172
+ end
173
+ end
@@ -0,0 +1,3 @@
1
+ module Ropes
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ropes.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "ropes/version"
2
+ require "ropes/repository"
3
+
4
+ module Ropes
5
+
6
+ end
data/ropes.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ropes/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ropes"
8
+ spec.version = Ropes::VERSION
9
+ spec.authors = ["Andy Sykes"]
10
+ spec.email = ["github@tinycat.co.uk"]
11
+ spec.description = %q{Build apt and yum repositories from
12
+ a directory, or from supplied information}
13
+ spec.summary = %q{Build apt and yum repositories with Ruby}
14
+ spec.homepage = "https://github.com/andytinycat/ropes"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_dependency "debeasy"
25
+ spec.add_dependency "gpgme"
26
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ropes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andy Sykes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: debeasy
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: gpgme
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: ! "Build apt and yum repositories from\n a directory,
70
+ or from supplied information"
71
+ email:
72
+ - github@tinycat.co.uk
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lib/ropes.rb
83
+ - lib/ropes/repository.rb
84
+ - lib/ropes/version.rb
85
+ - ropes.gemspec
86
+ homepage: https://github.com/andytinycat/ropes
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.0.7
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Build apt and yum repositories with Ruby
110
+ test_files: []