repomate 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/repomate +65 -0
- data/etc/config.yml +18 -0
- data/lib/repomate/architecture.rb +105 -0
- data/lib/repomate/base.rb +335 -0
- data/lib/repomate/category.rb +60 -0
- data/lib/repomate/cli.rb +123 -0
- data/lib/repomate/component.rb +102 -0
- data/lib/repomate/configuration.rb +75 -0
- data/lib/repomate/database.rb +30 -0
- data/lib/repomate/metafile.rb +137 -0
- data/lib/repomate/package.rb +116 -0
- data/lib/repomate/repository.rb +49 -0
- data/lib/repomate/suite.rb +96 -0
- data/lib/repomate/templates/archrelease.erb +6 -0
- data/lib/repomate/templates/packages.erb +6 -0
- data/lib/repomate/templates/suiterelease.erb +41 -0
- data/lib/repomate.rb +14 -0
- metadata +152 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
# RepoMate module
|
2
|
+
module RepoMate
|
3
|
+
|
4
|
+
# Class for the component layer of the directory structure
|
5
|
+
class Component
|
6
|
+
|
7
|
+
# Init
|
8
|
+
def initialize(component, suitename, category)
|
9
|
+
@component = component
|
10
|
+
@suitename = suitename
|
11
|
+
@category = category
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the given architecture name (eg. main, contrib, non-free)
|
15
|
+
def name
|
16
|
+
@component
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the directory strcuture of the component including all lower layers
|
20
|
+
def directory
|
21
|
+
File.join(Cfg.rootdir, @category, @suitename, @component)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Checks if the component directory exists
|
25
|
+
def exist?
|
26
|
+
Dir.exist?(directory)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Checks if the component is allowed (See: configurationfile)
|
30
|
+
def is_allowed?
|
31
|
+
self.allowed.include?(@component)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Checks if directory is unused
|
35
|
+
def is_unused?(dir)
|
36
|
+
status = true
|
37
|
+
|
38
|
+
path = Dir.glob(File.join(dir, "*"))
|
39
|
+
path.each do |dirorfile|
|
40
|
+
status = false if File.directory?(dirorfile)
|
41
|
+
status = false if File.basename(dirorfile) =~ /\.deb$/
|
42
|
+
end
|
43
|
+
|
44
|
+
status
|
45
|
+
end
|
46
|
+
|
47
|
+
# Creates the directory strcuture of the component including all lower layers
|
48
|
+
def create
|
49
|
+
FileUtils.mkdir_p(directory) unless exist?
|
50
|
+
end
|
51
|
+
|
52
|
+
# Deletes the components directory including all lower layers
|
53
|
+
def destroy
|
54
|
+
FileUtils.rm_r(directory) if exist?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns a list of all debian files in the component directory
|
58
|
+
def files
|
59
|
+
Dir.glob(File.join(directory, "*.deb"))
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns a dataset including the name of the component, the fullpath recursive through all lower layers
|
63
|
+
def self.dataset(category=nil)
|
64
|
+
data = []
|
65
|
+
self.all.each do |entry|
|
66
|
+
parts = entry.split(/\//)
|
67
|
+
unless parts.length < 3
|
68
|
+
next unless parts[0].eql?(category) || category.eql?("all")
|
69
|
+
data << {
|
70
|
+
:category => parts[0],
|
71
|
+
:suitename => parts[1],
|
72
|
+
:component => parts[2],
|
73
|
+
:fullpath => File.join(Cfg.rootdir, entry)
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
data
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns all directories without @rootdir
|
81
|
+
def self.all
|
82
|
+
config = Configuration.new
|
83
|
+
suites = Suite.all
|
84
|
+
dirs = []
|
85
|
+
rootdir = Cfg.rootdir
|
86
|
+
suites.each do |suite|
|
87
|
+
components = Dir.glob(File.join(rootdir, suite, "*"))
|
88
|
+
components.each do |component|
|
89
|
+
dirs.push component.gsub(/#{rootdir}\//, '') if File.directory? component
|
90
|
+
end
|
91
|
+
end
|
92
|
+
return dirs
|
93
|
+
end
|
94
|
+
|
95
|
+
# Gets all configured architectures
|
96
|
+
def self.allowed
|
97
|
+
Cfg.components.uniq
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
# RepoMate module
|
4
|
+
module RepoMate
|
5
|
+
|
6
|
+
# Configuration class
|
7
|
+
class Configuration
|
8
|
+
|
9
|
+
# Init
|
10
|
+
def initialize
|
11
|
+
@configfile = File.join(ENV['HOME'], '.repomate')
|
12
|
+
|
13
|
+
configure(@configfile)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Loads configfile
|
17
|
+
def configure(configfile)
|
18
|
+
filecontent = []
|
19
|
+
|
20
|
+
filecontent = YAML::load_file(configfile) if File.exists?(configfile)
|
21
|
+
|
22
|
+
merge(filecontent)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Merges configfile content with defaults
|
26
|
+
def merge(filecontent=nil)
|
27
|
+
config = {}
|
28
|
+
|
29
|
+
defaults = {
|
30
|
+
:rootdir => '/var/lib/repomate/repository',
|
31
|
+
:logdir => '/var/log/repomate',
|
32
|
+
:dpkg => '/usr/bin/dpkg',
|
33
|
+
:suites => [ "lenny", "squeeze" ],
|
34
|
+
:components => [ "main", "contrib" ],
|
35
|
+
:architectures => [ "all", "amd64" ],
|
36
|
+
:origin => 'Repository',
|
37
|
+
:label => 'Repository',
|
38
|
+
:gpg_enable => 'yes',
|
39
|
+
:gpg_email => 'someone@example.net',
|
40
|
+
:gpg_password => 'secret',
|
41
|
+
}
|
42
|
+
|
43
|
+
if filecontent
|
44
|
+
defaults.each do |key, value|
|
45
|
+
keysymbol = key.to_sym
|
46
|
+
setter = "#{key}="
|
47
|
+
|
48
|
+
if filecontent[keysymbol]
|
49
|
+
config[keysymbol] = filecontent[keysymbol]
|
50
|
+
else
|
51
|
+
config[keysymbol] = value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
else
|
55
|
+
config = defaults
|
56
|
+
end
|
57
|
+
|
58
|
+
config.each do |key, value|
|
59
|
+
setter = "#{key}="
|
60
|
+
|
61
|
+
self.class.send(:attr_accessor, key) unless respond_to?(setter)
|
62
|
+
|
63
|
+
send setter, value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns
|
69
|
+
Cfg = Configuration.new
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
|
3
|
+
# RepoMate module
|
4
|
+
module RepoMate
|
5
|
+
|
6
|
+
# Class for the database
|
7
|
+
class Database
|
8
|
+
|
9
|
+
# Init
|
10
|
+
def initialize(dbfile)
|
11
|
+
@db = SQLite3::Database.new(dbfile)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Checks if the database file already exists
|
15
|
+
def exists?
|
16
|
+
File.exists?(@dbfile)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Executes a query
|
20
|
+
def query(sql)
|
21
|
+
@db.execute(sql)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Deletes a categories directory
|
25
|
+
def destroy
|
26
|
+
FileUtils.rm_r(@dbfile) if exists?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'date'
|
3
|
+
require 'time'
|
4
|
+
require 'gpgme'
|
5
|
+
require 'digest/md5'
|
6
|
+
require 'digest/sha1'
|
7
|
+
require 'digest/sha2'
|
8
|
+
|
9
|
+
# RepoMate module
|
10
|
+
module RepoMate
|
11
|
+
|
12
|
+
# Class that can create and delete all metafiles like Packages, Packages.gz, Release and Release.gpg
|
13
|
+
class Metafile
|
14
|
+
|
15
|
+
# Init
|
16
|
+
def initialize
|
17
|
+
@repository = Repository.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a lit of all existing metafiles as array
|
21
|
+
def all
|
22
|
+
rootdir = Cfg.rootdir
|
23
|
+
dirlist = ["#{rootdir}/*/*", "#{rootdir}/*/*/*/*"]
|
24
|
+
filelist = ["Packages", "Packages.gz", "Release", "Release.gpg" ]
|
25
|
+
files = []
|
26
|
+
|
27
|
+
dirlist.each do |dirs|
|
28
|
+
Dir.glob(dirs).each do |dir|
|
29
|
+
filelist.each do |file|
|
30
|
+
fullname = File.join(dir, file)
|
31
|
+
files << fullname if File.exists? fullname
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
return files
|
36
|
+
end
|
37
|
+
|
38
|
+
# Deletes all existing metafiles
|
39
|
+
def destroy
|
40
|
+
all.each { |file| FileUtils.rm_f(file) }
|
41
|
+
end
|
42
|
+
|
43
|
+
# Creates all metafiles
|
44
|
+
def create
|
45
|
+
destroy
|
46
|
+
create_packages
|
47
|
+
|
48
|
+
if Cfg.gpg_enable
|
49
|
+
if Cfg.gpg_password.nil? || Cfg.gpg_email.nil?
|
50
|
+
puts "Configure password and email for GPG!"
|
51
|
+
exit 1
|
52
|
+
else
|
53
|
+
create_release
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Create Packages* files
|
59
|
+
def create_packages
|
60
|
+
source_category = "dists"
|
61
|
+
|
62
|
+
packages_template = ERB.new File.new(File.join(File.dirname(__FILE__), "templates/packages.erb")).read, nil, "%"
|
63
|
+
|
64
|
+
Architecture.dataset(source_category).each do |entry|
|
65
|
+
source = Architecture.new(entry[:architecture], entry[:component], entry[:suitename], source_category)
|
66
|
+
source.files.each do |fullname|
|
67
|
+
package = Package.new(fullname, entry[:suitename], entry[:component])
|
68
|
+
|
69
|
+
checksums = package.get_checksums
|
70
|
+
|
71
|
+
packagesfile = File.join(entry[:fullpath], "Packages")
|
72
|
+
size = File.size(fullname)
|
73
|
+
path = File.join("dists", entry[:suitename], entry[:component], entry[:architecture_dir], package.newbasename)
|
74
|
+
|
75
|
+
File.open(packagesfile, 'a') do |file|
|
76
|
+
package.controlfile.each { |key, value| file.puts "#{key}: #{value}" if key }
|
77
|
+
file.puts packages_template.result(binding)
|
78
|
+
end
|
79
|
+
raise "Could not gzip" unless system "gzip -9 -c #{packagesfile} > #{packagesfile}.gz"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create Release* files
|
85
|
+
def create_release
|
86
|
+
source_category = "dists"
|
87
|
+
suites = []
|
88
|
+
|
89
|
+
archrelease_template = ERB.new File.new(File.join(File.dirname(__FILE__), "templates/archrelease.erb")).read, nil, "%"
|
90
|
+
suiterelease_template = ERB.new File.new(File.join(File.dirname(__FILE__), "templates/suiterelease.erb")).read, nil, "%"
|
91
|
+
|
92
|
+
now = Time.new.strftime("%a, %d %b %Y %H:%M:%S %Z")
|
93
|
+
|
94
|
+
Architecture.dataset(source_category).each do |entry|
|
95
|
+
releasefile = File.join(entry[:fullpath], "Release")
|
96
|
+
|
97
|
+
suites << entry[:suitename] unless suites.include?(entry[:suitename])
|
98
|
+
|
99
|
+
File.open(releasefile, 'w') { |file| file.puts archrelease_template.result(binding) }
|
100
|
+
end
|
101
|
+
|
102
|
+
suites.each do |suite|
|
103
|
+
architecture = []
|
104
|
+
component = []
|
105
|
+
|
106
|
+
Architecture.dataset(source_category).each do |entry|
|
107
|
+
if entry[:suitename].eql?(suite)
|
108
|
+
architecture << entry[:architecture] unless architecture.include?(entry[:architecture])
|
109
|
+
component << entry[:component] unless component.include?(entry[:component])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
releasefile = File.join(Cfg.rootdir, source_category, suite, "Release")
|
114
|
+
|
115
|
+
File.open(releasefile, 'w') { |file| file.puts suiterelease_template.result(binding).gsub(/^\s+\n|^\n|^\s{3}/, '') }
|
116
|
+
begin
|
117
|
+
sign(releasefile)
|
118
|
+
rescue
|
119
|
+
destroy
|
120
|
+
create_packages
|
121
|
+
puts "GPG email/password incorrect"
|
122
|
+
return
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Sign a file
|
128
|
+
def sign(file)
|
129
|
+
crypto = GPGME::Crypto.new :password => Cfg.gpg_password
|
130
|
+
outfile = "#{file}.gpg"
|
131
|
+
output = File.open(outfile, 'w')
|
132
|
+
crypto.sign File.open(file, 'r'), :symmetric => false, :output => output, :signer => Cfg.gpg_email, :mode => GPGME::SIG_MODE_DETACH
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'digest/sha1'
|
3
|
+
require 'digest/sha2'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'date'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
# RepoMate module
|
9
|
+
module RepoMate
|
10
|
+
|
11
|
+
# Class for reading debian packages
|
12
|
+
class Package
|
13
|
+
|
14
|
+
attr_reader :name, :basename, :newbasename, :controlfile, :architecture, :version, :suitename, :component, :fullname
|
15
|
+
|
16
|
+
# Init
|
17
|
+
def initialize(fullname, suitename, component)
|
18
|
+
@fullname = fullname
|
19
|
+
@suitename = suitename
|
20
|
+
@component = component
|
21
|
+
@basename = File.basename(fullname)
|
22
|
+
@mtime = File.mtime(fullname)
|
23
|
+
@pkgdbfile = File.join(Cfg.rootdir, "packages.db")
|
24
|
+
@pkgdb = Database.new(@pkgdbfile)
|
25
|
+
|
26
|
+
check_package
|
27
|
+
create_table
|
28
|
+
|
29
|
+
@controlfile = read_controlfile
|
30
|
+
@name = @controlfile['Package']
|
31
|
+
@version = @controlfile['Version']
|
32
|
+
@architecture = @controlfile['Architecture']
|
33
|
+
@newbasename = "#{@name}-#{@version}_#{@architecture}.deb"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Create the package table
|
37
|
+
def create_table
|
38
|
+
sql = "create table if not exists checksums (
|
39
|
+
date varchar(25),
|
40
|
+
basename varchar(70),
|
41
|
+
mtime varchar(25),
|
42
|
+
md5 varchar(32),
|
43
|
+
sha1 varchar(40),
|
44
|
+
sha256 varchar(64)
|
45
|
+
)"
|
46
|
+
@pkgdb.query(sql)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Gets checksums for the given package
|
50
|
+
def get_checksums
|
51
|
+
result = []
|
52
|
+
|
53
|
+
@pkgdb.query("select md5, sha1, sha256 from checksums where basename = '#{@basename}' and mtime = '#{@mtime.iso8601}'").each do |row|
|
54
|
+
result = row
|
55
|
+
# puts "Hit: #{@basename} #{result}"
|
56
|
+
end
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
# Creates the checksums for a package
|
61
|
+
def create_checksums
|
62
|
+
# puts "Ins: #{@basename}"
|
63
|
+
now = DateTime.now
|
64
|
+
md5 = Digest::MD5.file(@fullname).to_s
|
65
|
+
sha1 = Digest::SHA1.file(@fullname).to_s
|
66
|
+
sha256 = Digest::SHA256.new(256).file(@fullname).to_s
|
67
|
+
@pkgdb.query("insert into checksums values ( '#{now}', '#{@basename}', '#{@mtime.iso8601}', '#{md5}', '#{sha1}', '#{sha256}' )")
|
68
|
+
end
|
69
|
+
|
70
|
+
# Gets checksums for the given package
|
71
|
+
def delete_checksums
|
72
|
+
# puts "Del: #{@basename}"
|
73
|
+
@pkgdb.query("delete from checksums where basename = '#{@basename}'")
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
# Checks if the given package is a debian package
|
79
|
+
def check_package
|
80
|
+
unless `file --dereference #{@fullname}` =~ /Debian binary package/i
|
81
|
+
puts "File does not exist or is not a Debian package!"
|
82
|
+
false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Extracts the controlfile and returns is
|
87
|
+
def read_controlfile
|
88
|
+
gzbasename = "control.tar.gz"
|
89
|
+
basename = "control"
|
90
|
+
tmpdir = File.expand_path "#{Dir.tmpdir}/#{Time.now.to_i}#{rand(1000)}/"
|
91
|
+
gzfullname = File.join(tmpdir, gzbasename)
|
92
|
+
fullname = File.join(tmpdir, basename)
|
93
|
+
|
94
|
+
controlfile = {}
|
95
|
+
|
96
|
+
FileUtils.mkdir_p(tmpdir)
|
97
|
+
|
98
|
+
begin
|
99
|
+
raise "Could not untar" unless system "ar -p #{@fullname} #{gzbasename} > #{gzfullname}"
|
100
|
+
raise Errno::ENOENT, "Package file does not exist" unless File.exists?(gzfullname)
|
101
|
+
raise "Could not untar" unless system "tar xfz #{gzfullname} -C #{tmpdir}"
|
102
|
+
|
103
|
+
File.open(fullname) do |file|
|
104
|
+
while(line = file.gets)
|
105
|
+
line =~ %r{([a-zA-Z]+):\s(.*)}
|
106
|
+
controlfile[$1] = $2
|
107
|
+
end
|
108
|
+
end
|
109
|
+
ensure
|
110
|
+
FileUtils.rm_rf(tmpdir)
|
111
|
+
end
|
112
|
+
controlfile
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# RepoMate module
|
2
|
+
module RepoMate
|
3
|
+
|
4
|
+
# Class for creating the repository structure
|
5
|
+
class Repository
|
6
|
+
|
7
|
+
attr_reader :categories
|
8
|
+
|
9
|
+
# Init
|
10
|
+
def initialize
|
11
|
+
@categories = ["stage", "pool", "dists"]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Creates the base structure
|
15
|
+
def create(suitename=nil, component=nil, architecture=nil)
|
16
|
+
unless Suite.allowed.include?(suitename)
|
17
|
+
STDERR.puts "Suitename (#{suitename}) is not configured"
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
unless Component.allowed.include?(component)
|
22
|
+
STDERR.puts "Component (#{component}) is not configured"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
unless architecture.nil?
|
27
|
+
unless Architecture.allowed.include?(architecture)
|
28
|
+
STDERR.puts "Architecture (#{architecture}) is not configured"
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@categories.each do |category|
|
34
|
+
if category.eql?("stage")
|
35
|
+
Component.new(component, suitename, category).create
|
36
|
+
else
|
37
|
+
if architecture && component && suitename
|
38
|
+
Architecture.new(architecture, component, suitename, category).create
|
39
|
+
elsif component && suitename
|
40
|
+
Component.new(component, suitename, category).create
|
41
|
+
elsif suitename.nil?
|
42
|
+
Suite.new(suitename, category).create
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# RepoMate module
|
2
|
+
module RepoMate
|
3
|
+
|
4
|
+
# Class for the suite layer of the directory structure
|
5
|
+
class Suite
|
6
|
+
|
7
|
+
# Init
|
8
|
+
def initialize(suitename, category)
|
9
|
+
@suitename = suitename
|
10
|
+
@category = category
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the given suite name (eg. lenny, squeeze)
|
14
|
+
def name
|
15
|
+
@suitename
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the directory strcuture of the suite including all lower layers
|
19
|
+
def directory
|
20
|
+
File.join(Cfg.rootdir, @category, @suitename)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Checks if the suite directory exists
|
24
|
+
def exist?
|
25
|
+
Dir.exist?(directory)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Checks if the suite is allowed (See: configurationfile)
|
29
|
+
def is_allowed?
|
30
|
+
self.allowed.include?(@suitename)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Checks if directory is unused
|
34
|
+
def is_unused?(dir)
|
35
|
+
status = true
|
36
|
+
|
37
|
+
path = Dir.glob(File.join(dir, "*"))
|
38
|
+
path.each do |dirorfile|
|
39
|
+
status = false if File.directory?(dirorfile)
|
40
|
+
status = false if File.basename(dirorfile) =~ /\.deb$/
|
41
|
+
end
|
42
|
+
|
43
|
+
status
|
44
|
+
end
|
45
|
+
|
46
|
+
# Creates the directory strcuture of the suite including all lower layers
|
47
|
+
def create
|
48
|
+
FileUtils.mkdir_p(directory) unless exist?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Deletes the suites directory including all lower layers
|
52
|
+
def destroy
|
53
|
+
FileUtils.rm_r(directory) if exist?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns a dataset including the name of the suite, the fullpath recursive through all lower layers
|
57
|
+
def self.dataset(category=nil)
|
58
|
+
data = []
|
59
|
+
self.all.each do |entry|
|
60
|
+
# p entry
|
61
|
+
parts = entry.split(/\//)
|
62
|
+
unless parts.length < 2
|
63
|
+
next unless parts[0].eql?(category) || category.eql?("all")
|
64
|
+
|
65
|
+
data << {
|
66
|
+
:category => parts[0],
|
67
|
+
:suitename => parts[1],
|
68
|
+
:fullpath => File.join(Cfg.rootdir, entry),
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
data
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns all directories without @rootdir
|
76
|
+
def self.all
|
77
|
+
categories = Category.all
|
78
|
+
dirs = []
|
79
|
+
rootdir = Cfg.rootdir
|
80
|
+
categories.each do |category|
|
81
|
+
suites = Dir.glob(File.join(rootdir, category, "*"))
|
82
|
+
suites.each do |suite|
|
83
|
+
dirs.push suite.gsub(/#{rootdir}\//, '') if File.directory? suite
|
84
|
+
end
|
85
|
+
end
|
86
|
+
return dirs
|
87
|
+
end
|
88
|
+
|
89
|
+
# Gets all configured architectures
|
90
|
+
def self.allowed
|
91
|
+
Cfg.suites.uniq
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
Origin: <%= Cfg.origin %>
|
2
|
+
Label: <%= Cfg.label %>
|
3
|
+
Suite: stable
|
4
|
+
Codename: <%= suite %>
|
5
|
+
Date: <%= now %>
|
6
|
+
Architectures: <%= architecture.join(', ') %>
|
7
|
+
Components: <%= component.join(', ') %>
|
8
|
+
Description: Repository for debian
|
9
|
+
MD5Sum:
|
10
|
+
<% Architecture.dataset(source_category).each do |entry| %>
|
11
|
+
<% source = Architecture.new(entry[:architecture], entry[:component], entry[:suitename], source_category) %>
|
12
|
+
<% Dir.glob(File.join(entry[:fullpath], "Packages*")).each do |file| %>
|
13
|
+
<% path = File.join(entry[:component], entry[:architecture_dir], File.basename(file)) %>
|
14
|
+
<%= Digest::MD5.file(file) %> <%= File.size(file) %> <%= path %>
|
15
|
+
<% end %>
|
16
|
+
<% file = File.join(entry[:fullpath], "Release") %>
|
17
|
+
<% path = File.join(entry[:component], entry[:architecture_dir], File.basename(file)) %>
|
18
|
+
<%= Digest::MD5.file(file) %> <%= File.size(file) %> <%= path %>
|
19
|
+
<% end %>
|
20
|
+
SHA1:
|
21
|
+
<% Architecture.dataset(source_category).each do |entry| %>
|
22
|
+
<% source = Architecture.new(entry[:architecture], entry[:component], entry[:suitename], source_category) %>
|
23
|
+
<% Dir.glob(File.join(entry[:fullpath], "Packages*")).each do |file| %>
|
24
|
+
<% path = File.join(entry[:component], entry[:architecture_dir], File.basename(file)) %>
|
25
|
+
<%= Digest::SHA1.file(file) %> <%= File.size(file) %> <%= path %>
|
26
|
+
<% end %>
|
27
|
+
<% file = File.join(entry[:fullpath], "Release") %>
|
28
|
+
<% path = File.join(entry[:component], entry[:architecture_dir], File.basename(file)) %>
|
29
|
+
<%= Digest::SHA1.file(file) %> <%= File.size(file) %> <%= path %>
|
30
|
+
<% end %>
|
31
|
+
SHA256:
|
32
|
+
<% Architecture.dataset(source_category).each do |entry| %>
|
33
|
+
<% source = Architecture.new(entry[:architecture], entry[:component], entry[:suitename], source_category) %>
|
34
|
+
<% Dir.glob(File.join(entry[:fullpath], "Packages*")).each do |file| %>
|
35
|
+
<% path = File.join(entry[:component], entry[:architecture_dir], File.basename(file)) %>
|
36
|
+
<%= Digest::SHA256.new(256).file(file) %> <%= File.size(file) %> <%= path %>
|
37
|
+
<% end %>
|
38
|
+
<% file = File.join(entry[:fullpath], "Release") %>
|
39
|
+
<% path = File.join(entry[:component], entry[:architecture_dir], File.basename(file)) %>
|
40
|
+
<%= Digest::SHA256.new(256).file(file) %> <%= File.size(file) %> <%= path %>
|
41
|
+
<% end %>
|
data/lib/repomate.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'repomate/architecture'
|
4
|
+
require 'repomate/base'
|
5
|
+
require 'repomate/category'
|
6
|
+
require 'repomate/cli'
|
7
|
+
require 'repomate/component'
|
8
|
+
require 'repomate/configuration'
|
9
|
+
require 'repomate/database'
|
10
|
+
require 'repomate/metafile'
|
11
|
+
require 'repomate/package'
|
12
|
+
require 'repomate/repository'
|
13
|
+
require 'repomate/suite'
|
14
|
+
|