repomate 0.1.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.
- 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
|
+
|