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 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.2
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( '-p', '--project NAME', 'Specify a project name. Default is $DIR.' ) do |project|
15
- options[:project] = project
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
- Gaffer::Base.new(options).compile
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
 
@@ -1,4 +1,9 @@
1
1
  require 'tmpdir'
2
+ require 'erb'
2
3
  require 'git'
4
+ require 'rush'
5
+ require 'fileutils'
6
+ require 'right_aws'
3
7
  require File.dirname(__FILE__) + '/gaffer/base'
4
8
  require File.dirname(__FILE__) + '/gaffer/deb'
9
+ require File.dirname(__FILE__) + '/gaffer/repro'
@@ -1,35 +1,85 @@
1
1
  module Gaffer
2
2
  class Base
3
- attr_accessor :dir, :git, :project, :readme, :depends, :version, :prefix, :maintainer, :build
3
+ attr_accessor :dir, :git, :project, :readme, :depends, :version, :prefix, :maintainer, :build_name
4
4
 
5
5
  def initialize(options)
6
- @dir = options[:dir] || Dir.pwd
7
- @git = Git.open(@dir)
8
- @version = options[:version]
9
- @project = options[:project] || File.basename(File.dirname(@git.repo.path))
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 = options[:prefix] || "opt/#{@project}"
14
+ @prefix = "opt/#{@project}"
12
15
 
13
- @git.chdir do
14
- @readme = File.read("README") rescue "no README file"
15
- @depends = File.read("DEPENDS").chomp rescue "libc6 (>= 2.10)"
16
- @version ||= File.read("VERSION").chomp
17
- end
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
- @build = "#{@version}-#{build_id}"
23
+ @build_name = "#{@version}-#{build_id}"
22
24
 
23
- raise "Bad version #{@version}" unless @version =~ /^\d+[.]\d+[.]\d+$/
24
- end
25
+ puts "======> #{@version.inspect}"
25
26
 
26
- def compile
27
- @git.add_tag(@build)
27
+ @git.add_tag(@build_name)
28
28
  ## check version - tag repo
29
- [ "i386", "amd64" ].each do |arch|
30
- Gaffer::Deb.new(self, arch, project, depends).compile
31
- Gaffer::Deb.new(self, arch, "#{project}-dev", "#{project} (>= #{@version})").compile
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
@@ -1,66 +1,83 @@
1
1
  module Gaffer
2
2
  class Deb
3
- def initialize(base, arch, package, depends)
3
+ attr_accessor :package, :readme, :depends, :arch
4
+
5
+ def initialize(base, _package, _depends)
4
6
  @base = base
5
- @arch = arch
6
- @package = package
7
- @depends = depends
7
+ @arch = "all"
8
+ @package = _package
9
+ @depends = _depends
8
10
  @dev = !!(@package =~ /-dev$/)
9
11
  end
10
12
 
11
- def compile
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
- system "mkdir #{dir}/DEBIAN"
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
- system "find #{install_dir} | grep -v [.]git | grep -v #{install_dir}$ | xargs rm -rf"
23
+ Rush.bash "find #{install_dir} | grep -v [.]git | grep -v #{install_dir}$ | xargs rm -rf"
23
24
  else
24
- system "rm -rf #{install_dir}/.git"
25
- [ "preinst", "postinst", "prerm", "postrm" ].each do |script|
26
- system "cp #{@base.dir}/#{script} #{dir}/DEBIAN/" if File.exists?("#{@base.dir}/#{script}")
27
- end
28
- if File.exists?("#{@base.dir}/init.conf")
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
- system "mkdir -p #{dir}/etc/init"
31
- system "cp #{@base.dir}/init.conf #{dir}/etc/init/#{@base.project}.conf"
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
- system "dpkg-deb -b #{dir} ./#{filebase}.deb"
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 #{@package} #{@base.build}"
60
+ "Gaffer package #{package} #{build_name}"
44
61
  end
45
62
 
46
63
  def filebase
47
- "#{@package}_#{@base.build}_#{@arch}"
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
- <<CONTROL
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
@@ -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
- - 2
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-01 00:00:00 -07:00
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
- - --charset=UTF-8
98
+ rdoc_options: []
99
+
57
100
  require_paths:
58
101
  - lib
59
102
  required_ruby_version: !ruby/object:Gem::Requirement