gaffer 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|