gaffer 0.0.2 → 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/Rakefile +3 -0
- data/VERSION +1 -1
- data/bin/gaffer +26 -13
- data/lib/gaffer.rb +5 -0
- data/lib/gaffer/base.rb +70 -20
- data/lib/gaffer/deb.rb +49 -32
- data/lib/gaffer/repro.rb +175 -0
- metadata +48 -5
data/Rakefile
CHANGED
@@ -10,6 +10,9 @@ Jeweler::Tasks.new do |s|
|
|
10
10
|
s.files = FileList["[A-Z]*", "{bin,default,lib,spec}/**/*"]
|
11
11
|
s.executables = %w(gaffer)
|
12
12
|
s.add_dependency "git"
|
13
|
+
s.add_dependency "right_aws"
|
14
|
+
s.add_dependency "bundler"
|
15
|
+
s.add_dependency "rush"
|
13
16
|
end
|
14
17
|
|
15
18
|
#Jeweler::RubyforgeTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/bin/gaffer
CHANGED
@@ -4,23 +4,15 @@ require File.dirname(__FILE__) + '/../lib/gaffer'
|
|
4
4
|
|
5
5
|
require 'optparse'
|
6
6
|
|
7
|
-
options = {
|
7
|
+
options = {}
|
8
8
|
|
9
9
|
optparse = OptionParser.new do|opts|
|
10
10
|
opts.banner = <<banner
|
11
|
-
Usage: gaffer [options] ...
|
11
|
+
Usage: gaffer [options] ACTION [ DIR [ DIR [ ... ] ] ]
|
12
12
|
banner
|
13
13
|
|
14
|
-
opts.on( '-
|
15
|
-
options[:
|
16
|
-
end
|
17
|
-
|
18
|
-
opts.on( '-P', '--prefix PREFIX', 'Install prefix. Default is /opt/$PROJECT/' ) do |prefix|
|
19
|
-
options[:prefix] = prefix
|
20
|
-
end
|
21
|
-
|
22
|
-
opts.on( '-v', '--version VERSION', 'Specify a project name. Default is $DIR/VERSION' ) do |version|
|
23
|
-
options[:version] = version
|
14
|
+
opts.on( '-f', '--force', 'Force an action' ) do
|
15
|
+
options[:force] = true
|
24
16
|
end
|
25
17
|
|
26
18
|
opts.on( '-h', '--help', 'Display this screen' ) do
|
@@ -31,5 +23,26 @@ end
|
|
31
23
|
|
32
24
|
optparse.parse!
|
33
25
|
|
34
|
-
|
26
|
+
command = ARGV.shift
|
27
|
+
target = ARGV.shift || Dir::pwd
|
28
|
+
|
29
|
+
gaffer = Gaffer::Base.new(options)
|
30
|
+
|
31
|
+
case command
|
32
|
+
when "initrepo"
|
33
|
+
gaffer.repro.init
|
34
|
+
when "pull"
|
35
|
+
gaffer.repro.pull
|
36
|
+
when "build"
|
37
|
+
gaffer.build(target)
|
38
|
+
when "push"
|
39
|
+
gaffer.repro.push
|
40
|
+
when "add"
|
41
|
+
gaffer.add(target)
|
42
|
+
when "publish"
|
43
|
+
gaffer.push gaffer.compile(target)
|
44
|
+
else
|
45
|
+
puts "No action: --help for help [#{command}]"
|
46
|
+
exit 1
|
47
|
+
end
|
35
48
|
|
data/lib/gaffer.rb
CHANGED
data/lib/gaffer/base.rb
CHANGED
@@ -1,35 +1,85 @@
|
|
1
1
|
module Gaffer
|
2
2
|
class Base
|
3
|
-
attr_accessor :dir, :git, :project, :readme, :depends, :version, :prefix, :maintainer, :
|
3
|
+
attr_accessor :dir, :git, :project, :readme, :depends, :version, :prefix, :maintainer, :build_name
|
4
4
|
|
5
5
|
def initialize(options)
|
6
|
-
@
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
@force = options[:force]
|
7
|
+
end
|
8
|
+
|
9
|
+
def build(dir)
|
10
|
+
@git = Git::open(dir)
|
11
|
+
|
12
|
+
@project = File::basename(File::dirname(@git.repo.path))
|
10
13
|
@maintainer = "#{@git.config["user.name"]} <#{@git.config["user.email"]}>"
|
11
|
-
@prefix =
|
14
|
+
@prefix = "opt/#{@project}"
|
12
15
|
|
13
|
-
@
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
@readme = File::read("#{dir}/README") rescue "no README file"
|
17
|
+
@depends = File::read("#{dir}/DEPENDS").chomp rescue "libc6 (>= 2.10)"
|
18
|
+
@version = File::read("#{dir}/VERSION").chomp
|
19
|
+
|
20
|
+
raise "Bad version #{@version}" unless @version =~ /^\d+[.]\d+[.]\d+$/
|
18
21
|
|
19
|
-
puts "======> #{@version.inspect}"
|
20
22
|
build_id = @git.tags.map { |a| a.name =~ /^#{@version}-(.+)/; $1.to_i }.sort.last.to_i + 1
|
21
|
-
@
|
23
|
+
@build_name = "#{@version}-#{build_id}"
|
22
24
|
|
23
|
-
|
24
|
-
end
|
25
|
+
puts "======> #{@version.inspect}"
|
25
26
|
|
26
|
-
|
27
|
-
@git.add_tag(@build)
|
27
|
+
@git.add_tag(@build_name)
|
28
28
|
## check version - tag repo
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
|
30
|
+
Gaffer::Deb::new(self, project, depends).build
|
31
|
+
# Gaffer::Deb::new(self, "#{project}-dev", "#{project} (>= #{@version})").build
|
32
|
+
end
|
33
|
+
|
34
|
+
def add(file)
|
35
|
+
file = File.expand_path(file)
|
36
|
+
Dir.chdir(repro_dir) do
|
37
|
+
repro.include(file)
|
32
38
|
end
|
33
39
|
end
|
40
|
+
|
41
|
+
def push_changed(dir, &blk)
|
42
|
+
# I can optimze later
|
43
|
+
start = Time::now
|
44
|
+
Dir.chdir(dir) do
|
45
|
+
blk.call
|
46
|
+
Dir["**/*"].select { |file| File::stat(file).mtime >= start }.each do |file|
|
47
|
+
puts "PUSHING: #{f}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def repro
|
53
|
+
options = {}
|
54
|
+
|
55
|
+
options[:aws_key] ||= ENV['AWS_ACCESS_KEY_ID']
|
56
|
+
options[:aws_secret] ||= ENV['AWS_SECRET_ACCESS_KEY']
|
57
|
+
options[:bucket] ||= ENV['REP_BUCKET']
|
58
|
+
options[:email] ||= ENV['REP_EMAIL']
|
59
|
+
options[:maintainer] ||= ENV['REP_MAINTAINER']
|
60
|
+
options[:key] ||= options[:email]
|
61
|
+
|
62
|
+
options[:codename] ||= "maverick"
|
63
|
+
options[:components] ||= "main"
|
64
|
+
options[:force] ||= !!@force
|
65
|
+
|
66
|
+
dir = repro_dir
|
67
|
+
|
68
|
+
puts "Repo: #{dir}"
|
69
|
+
|
70
|
+
Gaffer::Repro.new(dir, options)
|
71
|
+
end
|
72
|
+
|
73
|
+
def repro_dir
|
74
|
+
if ENV['HOME']
|
75
|
+
"#{ENV['HOME']}/.gaffer/repo"
|
76
|
+
else
|
77
|
+
"/var/lib/gaffer/repo"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def repro_ready?
|
82
|
+
File.exists? "#{repro_dir}/ubuntu/conf/distributions"
|
83
|
+
end
|
34
84
|
end
|
35
85
|
end
|
data/lib/gaffer/deb.rb
CHANGED
@@ -1,66 +1,83 @@
|
|
1
1
|
module Gaffer
|
2
2
|
class Deb
|
3
|
-
|
3
|
+
attr_accessor :package, :readme, :depends, :arch
|
4
|
+
|
5
|
+
def initialize(base, _package, _depends)
|
4
6
|
@base = base
|
5
|
-
@arch =
|
6
|
-
@package =
|
7
|
-
@depends =
|
7
|
+
@arch = "all"
|
8
|
+
@package = _package
|
9
|
+
@depends = _depends
|
8
10
|
@dev = !!(@package =~ /-dev$/)
|
9
11
|
end
|
10
12
|
|
11
|
-
def
|
12
|
-
puts self.inspect
|
13
|
+
def build
|
13
14
|
Dir.mktmpdir do |dir|
|
14
15
|
install_dir = "#{dir}/#{@base.prefix}"
|
15
16
|
Git.clone(@base.dir, install_dir)
|
16
|
-
|
17
|
-
puts control
|
17
|
+
Rush.bash "mkdir #{dir}/DEBIAN"
|
18
18
|
File.open("#{dir}/DEBIAN/control", "w") do |f|
|
19
19
|
f.write(control)
|
20
20
|
end
|
21
|
+
puts control
|
21
22
|
if @dev
|
22
|
-
|
23
|
+
Rush.bash "find #{install_dir} | grep -v [.]git | grep -v #{install_dir}$ | xargs rm -rf"
|
23
24
|
else
|
24
|
-
|
25
|
-
[
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
Rush.bash "find #{install_dir} | grep [.]git | grep -v #{install_dir}$ | xargs rm -rf"
|
26
|
+
# [ :preinst, :postinst, :prerm, :postrm ].each do |script|
|
27
|
+
# file = File.open("#{dir}/DEBIAN/#{script}","w")
|
28
|
+
# file.chmod(0755)
|
29
|
+
# file.write(template(script))
|
30
|
+
# file.close
|
31
|
+
# end
|
32
|
+
if has_init?
|
29
33
|
puts "INSTALLING init.conf"
|
30
|
-
|
31
|
-
|
34
|
+
Rush.bash "mkdir -p #{dir}/etc/init"
|
35
|
+
Rush.bash "cp #{@base.dir}/init.conf #{dir}/etc/init/#{@base.project}.conf"
|
36
|
+
end
|
37
|
+
if File.exists?("#{@base.dir}/Gemfile")
|
38
|
+
Dir.chdir(@base.dir) do
|
39
|
+
# TODO this can break in strange ways - STDOUT/STDERR is a mess
|
40
|
+
if Rush.bash('bundle install --deployment').match(/native extensions/)
|
41
|
+
@arch = Rush.bash "dpkg --print-architecture"
|
42
|
+
end
|
43
|
+
end
|
32
44
|
end
|
33
45
|
end
|
34
|
-
|
46
|
+
Rush.bash "dpkg-deb -b #{dir} ./#{filebase}.deb"
|
47
|
+
File.expand_path("./#{filebase}.deb")
|
35
48
|
end
|
36
49
|
end
|
37
50
|
|
51
|
+
def has_init?
|
52
|
+
File.exists?("#{@base.dir}/init.conf")
|
53
|
+
end
|
54
|
+
|
38
55
|
def origin_url
|
39
56
|
@base.git.remotes.select { |r| r.name == "origin" }.map { |r| r.url }.first
|
40
57
|
end
|
41
58
|
|
42
59
|
def description
|
43
|
-
"Gaffer package #{
|
60
|
+
"Gaffer package #{package} #{build_name}"
|
44
61
|
end
|
45
62
|
|
46
63
|
def filebase
|
47
|
-
"#{
|
64
|
+
"#{package}_#{build_name}_#{@arch}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def template(type)
|
68
|
+
ERB.new(File.read("#{File.dirname(__FILE__)}/../../templates/#{type}.erb")).result(binding)
|
69
|
+
end
|
70
|
+
|
71
|
+
def maintainer
|
72
|
+
@base.maintainer
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_name
|
76
|
+
@base.build_name
|
48
77
|
end
|
49
78
|
|
50
79
|
def control
|
51
|
-
|
52
|
-
Source: #{@package}
|
53
|
-
Section: unknown
|
54
|
-
Priority: extra
|
55
|
-
Maintainer: #{@base.maintainer}
|
56
|
-
Version: #{@base.build}
|
57
|
-
Homepage: #{origin_url}
|
58
|
-
Package: #{@package}
|
59
|
-
Architecture: #{@arch}
|
60
|
-
Depends: #{@depends}
|
61
|
-
Description: #{description}
|
62
|
-
#{@readme}
|
63
|
-
CONTROL
|
80
|
+
template(:control)
|
64
81
|
end
|
65
82
|
end
|
66
83
|
end
|
data/lib/gaffer/repro.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
module Gaffer
|
2
|
+
class Repro
|
3
|
+
|
4
|
+
def initialize(root, options = {})
|
5
|
+
@root = root
|
6
|
+
@maintainer = options[:maintainer]
|
7
|
+
@email = options[:email]
|
8
|
+
@key = options[:key]
|
9
|
+
@force = options[:force]
|
10
|
+
@codename = options[:codename]
|
11
|
+
@components = options[:components]
|
12
|
+
@bucket = options[:bucket]
|
13
|
+
@aws_key = options[:aws_key]
|
14
|
+
@aws_secret = options[:aws_secret]
|
15
|
+
end
|
16
|
+
|
17
|
+
def init
|
18
|
+
if not Dir[@root].empty?
|
19
|
+
raise "Dir #{@root} not empty - cannot init" unless @force
|
20
|
+
FileUtils.rm_rf @root
|
21
|
+
end
|
22
|
+
create_dirs
|
23
|
+
write_file "ubuntu/conf/options", options
|
24
|
+
write_file "ubuntu/conf/distributions", distributes
|
25
|
+
write_version 1
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_dirs
|
29
|
+
repo_dirs.each do |dir|
|
30
|
+
if not File.exists?("#{@root}/ubuntu/#{dir}")
|
31
|
+
puts "* mkdir -p #{@root}/ubuntu/#{dir}"
|
32
|
+
FileUtils.mkdir_p "#{@root}/ubuntu/#{dir}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def include(file)
|
38
|
+
bump_version
|
39
|
+
file = File.expand_path(file)
|
40
|
+
Dir.chdir("#{@root}/ubuntu") do
|
41
|
+
run "reprepro includedeb #{@codename} #{file}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def ready!
|
46
|
+
raise "No repo. Use 'gaffer pull' to download a repo from S3 or 'gaffer initrepo' to make a new one" unless File.include? "#{@root}/ubuntu/conf/distributions"
|
47
|
+
end
|
48
|
+
|
49
|
+
def push
|
50
|
+
raise "Remote version #{remote_version} is higher than local #{local_version}. Use --force to override" if (remote_version > local_version && !@force)
|
51
|
+
puts "Version: #{local_version}"
|
52
|
+
delete_remote
|
53
|
+
write_remote
|
54
|
+
puts " [apt source]"
|
55
|
+
puts url
|
56
|
+
puts ""
|
57
|
+
end
|
58
|
+
|
59
|
+
def pull
|
60
|
+
raise "Local version #{local_version} is higher than local #{remote_version}. Use --force to override" if (remote_version < local_version && !@force)
|
61
|
+
create_dirs
|
62
|
+
puts "Version: #{remote_version}"
|
63
|
+
delete_local
|
64
|
+
write_local
|
65
|
+
end
|
66
|
+
|
67
|
+
def url
|
68
|
+
"deb http://#{@bucket}.s3.amazonaws.com/ubuntu/ #{@codename} #{@components}"
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def repo_dirs
|
74
|
+
%w(conf dists incoming indices logs pool project tmp)
|
75
|
+
end
|
76
|
+
|
77
|
+
def write_file(path, data)
|
78
|
+
FileUtils.mkdir_p File.dirname("#{@root}/#{path}")
|
79
|
+
File.open("#{@root}/#{path}","w") do |f|
|
80
|
+
f.write(data)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def options
|
85
|
+
d = []
|
86
|
+
d << "ask-passphrase"
|
87
|
+
d << "basedir ."
|
88
|
+
d.join("\n") + "\n"
|
89
|
+
end
|
90
|
+
|
91
|
+
def distributes
|
92
|
+
d = []
|
93
|
+
d << "Origin: #{@maintainer}"
|
94
|
+
d << "Label: #{@maintainer} Deploy Repo"
|
95
|
+
d << "Codename: #{@codename}"
|
96
|
+
d << "Architectures: i386 amd64 source"
|
97
|
+
d << "Components: #{@components}"
|
98
|
+
d << "Description: Deploy repo for #{@maintainer}"
|
99
|
+
d << "SignWith: #{@key}" if @key
|
100
|
+
d.join("\n") + "\n"
|
101
|
+
end
|
102
|
+
|
103
|
+
def run(cmd)
|
104
|
+
Dir.chdir("#{@root}/ubuntu") do
|
105
|
+
puts "DEBUG: #{cmd}"
|
106
|
+
system(cmd) || (raise "Commmand failed: #{cmd}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def s3
|
111
|
+
raise "Need aws key and secret to use s3" if @aws_key.nil? or @aws_secret.nil?
|
112
|
+
@s3 ||= RightAws::S3.new(@aws_key, @aws_secret, :logger => Logger.new(nil))
|
113
|
+
end
|
114
|
+
|
115
|
+
def remote
|
116
|
+
bucket.keys('prefix' => 'ubuntu').map { |k| k.to_s }
|
117
|
+
end
|
118
|
+
|
119
|
+
def local
|
120
|
+
Dir.chdir(@root) do
|
121
|
+
Dir["**/*"].reject { |f| File.directory?(f) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def delete_local
|
126
|
+
(local - remote).each do |file|
|
127
|
+
puts "* local delete #{file}"
|
128
|
+
File.delete("#{@root}/#{file}")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def delete_remote
|
133
|
+
(remote - local).each do |file|
|
134
|
+
puts "* remote delete #{file}"
|
135
|
+
bucket.delete(file)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def write_local
|
140
|
+
remote.each do |file|
|
141
|
+
puts "* local write #{file}"
|
142
|
+
write_file(file, bucket.get(file))
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def write_remote
|
147
|
+
local.each do |file|
|
148
|
+
next if File.directory?("#{@root}/#{file}")
|
149
|
+
puts "* remote write #{file}"
|
150
|
+
bucket.put("#{file}", File.open("#{@root}/#{file}"), {}, file =~ /^ubuntu\/(db|conf)\// ? 'private' : 'public-read')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def bucket
|
155
|
+
raise "bucket not set" unless @bucket
|
156
|
+
s3.bucket(@bucket, true)
|
157
|
+
end
|
158
|
+
|
159
|
+
def local_version
|
160
|
+
File.read("#{@root}/ubuntu/conf/version").to_i rescue 0
|
161
|
+
end
|
162
|
+
|
163
|
+
def remote_version
|
164
|
+
bucket.get("ubuntu/conf/version").to_i rescue 0
|
165
|
+
end
|
166
|
+
|
167
|
+
def bump_version
|
168
|
+
write_version(local_version + 1)
|
169
|
+
end
|
170
|
+
|
171
|
+
def write_version(version)
|
172
|
+
write_file "ubuntu/conf/version", version.to_s
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.2
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Orion Henry
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-23 00:00:00 -08:00
|
19
19
|
default_executable: gaffer
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -32,6 +32,48 @@ dependencies:
|
|
32
32
|
version: "0"
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: right_aws
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: bundler
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rush
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
35
77
|
description: Duct tape together some debian packages
|
36
78
|
email: orion@heroku.com
|
37
79
|
executables:
|
@@ -47,13 +89,14 @@ files:
|
|
47
89
|
- lib/gaffer.rb
|
48
90
|
- lib/gaffer/base.rb
|
49
91
|
- lib/gaffer/deb.rb
|
92
|
+
- lib/gaffer/repro.rb
|
50
93
|
has_rdoc: true
|
51
94
|
homepage: http://github.com/orionz/gaffer
|
52
95
|
licenses: []
|
53
96
|
|
54
97
|
post_install_message:
|
55
|
-
rdoc_options:
|
56
|
-
|
98
|
+
rdoc_options: []
|
99
|
+
|
57
100
|
require_paths:
|
58
101
|
- lib
|
59
102
|
required_ruby_version: !ruby/object:Gem::Requirement
|