reflection 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -5,9 +5,9 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "reflection"
8
- gem.summary = %Q{Helps you keeping your development machine in sync with production.}
8
+ gem.summary = %Q{Keep your development machine in sync with production.}
9
9
  gem.description = %Q{
10
- Reflection is designed to keep your production assets (database comming soon) in sync with your development system.
10
+ Reflection is designed to keep your development system in sync with your production system's files and database (by dumping).
11
11
  It uses a shared git repository to store these files, which allows you to mirror your production environment without the need of
12
12
  direct access to your production servers.
13
13
  }
data/Reflection.gemspec CHANGED
@@ -5,14 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{reflection}
8
- s.version = "0.3.1"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andreas Wolff"]
12
- s.date = %q{2009-11-17}
12
+ s.date = %q{2009-11-18}
13
13
  s.default_executable = %q{reflection}
14
14
  s.description = %q{
15
- Reflection is designed to keep your production assets (database comming soon) in sync with your development system.
15
+ Reflection is designed to keep your development system in sync with your production system's files and database (by dumping).
16
16
  It uses a shared git repository to store these files, which allows you to mirror your production environment without the need of
17
17
  direct access to your production servers.
18
18
  }
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  "lib/reflection/directory.rb",
43
43
  "lib/reflection/directory/base.rb",
44
44
  "lib/reflection/directory/stash.rb",
45
+ "lib/reflection/rails.rb",
45
46
  "lib/reflection/repository.rb",
46
47
  "lib/reflection/support.rb",
47
48
  "lib/reflection/support/home.rb",
@@ -52,6 +53,7 @@ Gem::Specification.new do |s|
52
53
  "spec/reflection/config_spec.rb",
53
54
  "spec/reflection/directory/base_spec.rb",
54
55
  "spec/reflection/directory/stash_spec.rb",
56
+ "spec/reflection/rails_spec.rb",
55
57
  "spec/reflection/repository_spec.rb",
56
58
  "spec/reflection/support/home_spec.rb",
57
59
  "spec/reflection/support_spec.rb",
@@ -63,13 +65,14 @@ Gem::Specification.new do |s|
63
65
  s.rdoc_options = ["--charset=UTF-8"]
64
66
  s.require_paths = ["lib"]
65
67
  s.rubygems_version = %q{1.3.5}
66
- s.summary = %q{Helps you keeping your development machine in sync with production.}
68
+ s.summary = %q{Keep your development machine in sync with production.}
67
69
  s.test_files = [
68
70
  "spec/reflection/cli_spec.rb",
69
71
  "spec/reflection/command/stash_spec.rb",
70
72
  "spec/reflection/config_spec.rb",
71
73
  "spec/reflection/directory/base_spec.rb",
72
74
  "spec/reflection/directory/stash_spec.rb",
75
+ "spec/reflection/rails_spec.rb",
73
76
  "spec/reflection/repository_spec.rb",
74
77
  "spec/reflection/support/home_spec.rb",
75
78
  "spec/reflection/support_spec.rb",
data/TODO CHANGED
@@ -1,8 +1,6 @@
1
- + Add config files ('$ reflection path/to/config')
2
- + Add DB Dumper (include in cli-opt-parser)
3
1
  + Remove stash directory if its empty (on reinit)
4
2
  + Add Logger (Reflection::Support.log)
5
- + After command callbacks: Twitter, Campfire on Serverside
3
+ + After command callbacks: Apphunk
6
4
  + List existing reflections in client side
7
5
  + Allow to apply any (git) version, not just the latest
8
6
  + Add cli option use tmp-apply (removes ~/.reflection/apply-dir after command)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.0
@@ -5,17 +5,23 @@ module Reflection
5
5
  class Apply < Reflection::Command::Base
6
6
 
7
7
  def validate!
8
- validate.existence_of options.directory
8
+ validate.existence_of config.directory
9
+ if config.rails_root
10
+ validate.existence_of config.rails_root
11
+ Reflection::Rails.validate_environment(config)
12
+ end
9
13
  end
10
14
 
11
15
  def run!
12
- stash_directory = Directory::Stash.new(Reflection::Repository.new(options.repository), 'apply')
13
- target_directory = Directory::Base.new(options.directory)
16
+ stash_directory = Directory::Stash.new(Reflection::Repository.new(config.repository), 'apply')
17
+ target_directory = Directory::Base.new(config.directory)
14
18
 
15
19
  get_user_approval_for_cleaning_target(target_directory)
20
+ get_user_approval_for_apply_database_dump if config.rails_root
21
+
16
22
  verify_that_target_is_not_a_repository(target_directory)
17
23
 
18
- Reflection.log.info "Applying '#{options.repository}' >> '#{options.directory}'.."
24
+ Reflection.log.info "Applying '#{config.repository}' >> '#{config.directory}'.."
19
25
 
20
26
  target_directory.clean!
21
27
 
@@ -32,6 +38,7 @@ module Reflection
32
38
  stash_directory.get_git_index_from(target_directory.path)
33
39
  end
34
40
 
41
+ Reflection::Rails.apply(config, target_directory)
35
42
  Reflection.log.info "Apply Command done."
36
43
  end
37
44
 
@@ -40,7 +47,18 @@ module Reflection
40
47
 
41
48
  def get_user_approval_for_cleaning_target(target_directory)
42
49
  puts "\nIn order to get a fresh copy of your files, Reflection will have to remove all files under '#{target_directory.path}'."
43
- puts "If you're sure, hit <enter> to proceed.."
50
+ puts "If you are sure, hit <enter> to proceed.."
51
+
52
+ unless STDIN.getc == 10
53
+ puts "Aborting.."
54
+ exit
55
+ end
56
+ end
57
+
58
+ def get_user_approval_for_apply_database_dump
59
+ puts "\nCaution: You've enabled Rails database dumping/applying."
60
+ puts "In order to apply a fresh dump, Reflection will override your database."
61
+ puts "If you are sure, hit <enter> to proceed.."
44
62
 
45
63
  unless STDIN.getc == 10
46
64
  puts "Aborting.."
@@ -1,16 +1,16 @@
1
1
  module Reflection
2
2
  module Command
3
3
  class Base
4
- attr_accessor :options
4
+ attr_accessor :config
5
5
 
6
- def self.run!(options)
7
- command = self.new(options)
6
+ def self.run!(config)
7
+ command = self.new(config)
8
8
  command.validate! if command.respond_to?(:validate!)
9
9
  command.run!
10
10
  end
11
11
 
12
- def initialize(new_options)
13
- self.options = new_options
12
+ def initialize(new_config)
13
+ self.config = new_config
14
14
  end
15
15
 
16
16
  def validate
@@ -5,14 +5,18 @@ module Reflection
5
5
  class Stash < Reflection::Command::Base
6
6
 
7
7
  def validate!
8
- validate.existence_of options.directory
8
+ validate.existence_of config.directory
9
+ if config.rails_root
10
+ validate.existence_of config.rails_root
11
+ Reflection::Rails.validate_environment(config)
12
+ end
9
13
  end
10
14
 
11
15
  def run!
12
- Reflection.log.info "Stashing '#{options.directory}'.."
16
+ Reflection.log.info "Stashing '#{config.directory}'.."
13
17
 
14
- stash_directory = Directory::Stash.new(Reflection::Repository.new(options.repository), 'stash')
15
- target_directory = Directory::Base.new(options.directory)
18
+ stash_directory = Directory::Stash.new(Reflection::Repository.new(config.repository), 'stash')
19
+ target_directory = Directory::Base.new(config.directory)
16
20
 
17
21
  verify_that_target_is_not_a_repository(target_directory)
18
22
 
@@ -34,8 +38,10 @@ module Reflection
34
38
 
35
39
  def stash_directory_into_repository(stash_directory, target_directory)
36
40
  copy_stash_repository_git_index_to_target(stash_directory.git_index, target_directory.path)
41
+ Reflection::Rails.stash(config, target_directory) if config.rails_root
37
42
  commit_and_push_files(target_directory.path, target_directory.name)
38
43
  move_stash_repository_git_index_back(target_directory.git_index, stash_directory.path)
44
+ Reflection::Rails.clean_target(target_directory) if config.rails_root
39
45
  end
40
46
 
41
47
 
@@ -11,6 +11,8 @@ module Reflection
11
11
  attr_accessor :command
12
12
  attr_accessor :directory
13
13
  attr_accessor :repository
14
+ attr_accessor :rails_root
15
+ attr_accessor :rails_environment
14
16
  attr_accessor :store_configuration_path
15
17
 
16
18
  def self.parse(args = [])
@@ -28,13 +30,21 @@ module Reflection
28
30
  end
29
31
 
30
32
  def to_hash
31
- { :command => self.command, :repository => self.repository, :directory => self.directory }
33
+ {
34
+ :command => self.command,
35
+ :repository => self.repository,
36
+ :directory => self.directory,
37
+ :rails_root => self.rails_root,
38
+ :rails_environment => self.rails_environment
39
+ }
32
40
  end
33
41
 
34
42
  def from_hash(hash)
35
43
  self.command = hash[:command]
36
44
  self.directory = hash[:directory]
37
45
  self.repository = hash[:repository]
46
+ self.rails_root = hash[:rails_root]
47
+ self.rails_environment = hash[:rails_environment]
38
48
  end
39
49
 
40
50
  def write(path)
@@ -61,8 +71,10 @@ module Reflection
61
71
 
62
72
  def parse_command_line_options(args)
63
73
  opt_parser = OptionParser.new do |opts|
64
- opts.banner = "Usage: reflection --COMMAND --repository=GIT_REPO --directory=PATH"
65
-
74
+ opts.banner = "Usage: reflection --COMMAND --repository=GIT_REPO --directory=PATH\n"
75
+ opts.banner << " -or-\n"
76
+ opts.banner << "Usage: reflection /path/to/reflection-config-file.yml"
77
+
66
78
  opts.separator " "
67
79
  opts.separator "On the server side:"
68
80
 
@@ -86,7 +98,16 @@ module Reflection
86
98
  end
87
99
 
88
100
  opts.separator " "
89
- opts.separator "Additional options for both:"
101
+ opts.separator "Additional options for both:"
102
+
103
+ opts.on("--rails [RAILS_ROOT]", "Enable dumping/applying of a Rails managed MySQL database") do |path|
104
+ self.rails_root = path || nil
105
+ end
106
+
107
+ opts.on("--rails-env [ENV]", "Rails environment to instrument") do |environment|
108
+ self.rails_environment = environment || nil
109
+ end
110
+
90
111
  opts.on("--write [FILE]", "Create a configuration FILE from the current commandline options") do |config_file_path|
91
112
  self.store_configuration_path = config_file_path if config_file_path
92
113
  end
@@ -0,0 +1,62 @@
1
+ module Reflection
2
+ module Rails
3
+ class << self
4
+
5
+ def validate_environment(config)
6
+ env_file_path = File.join(config.rails_root, 'config/environments', "#{config.rails_environment}.rb")
7
+ unless File.exist?(env_file_path)
8
+ Reflection::Support.exit_with_error("Rails environment '#{config.rails_environment}' doesn't exist in #{env_file_path}.")
9
+ end
10
+ end
11
+
12
+ def clean_target(target_directory)
13
+ target_file_path = File.join(target_directory.path, '_rails_database_dump.sql')
14
+ if File.exist?(target_file_path)
15
+ %x(rm #{target_file_path})
16
+ end
17
+ end
18
+
19
+ def database_command_line_options(database_config)
20
+ options = []
21
+ options << "-h #{database_config['host']}"
22
+ options << "-u #{database_config['username']}"
23
+ options << "-p #{database_config['password']}" if database_config['password'] && !database_config['password'].empty?
24
+ options << "#{database_config['database']}"
25
+ options.join(' ')
26
+ end
27
+
28
+ def read_database_configuration(config)
29
+ begin
30
+ database_path = File.join(config.rails_root, "config/database.yml")
31
+ if db_config = YAML.load_file(database_path)[config.rails_environment]
32
+ return db_config
33
+ else
34
+ Reflection.log.error("Rails database configuration for '#{config.rails_environment}' isn't available in #{database_path}")
35
+ return false
36
+ end
37
+ rescue => e
38
+ Reflection.log.error("Error while parsing Rails database configuration: #{e}")
39
+ return false
40
+ end
41
+ end
42
+
43
+ def stash(config, target_directory)
44
+ Reflection.log.debug "Stashing database dump.."
45
+ return unless database_config = read_database_configuration(config)
46
+ options = database_command_line_options(database_config)
47
+ target_file_path = File.join(target_directory.path, '_rails_database_dump.sql')
48
+ %x(mysqldump #{options} --add-drop-table > #{target_file_path})
49
+ end
50
+
51
+ def apply(config, target_directory)
52
+ Reflection.log.debug "Applying database dump.."
53
+ return unless database_config = read_database_configuration(config)
54
+ options = database_command_line_options(database_config)
55
+ target_file_path = File.join(target_directory.path, '_rails_database_dump.sql')
56
+ %x(mysql #{options} < #{target_file_path})
57
+ clean_target(target_directory)
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -10,6 +10,9 @@ module Reflection
10
10
  puts "** #{message}" if message && !message.empty?
11
11
  end
12
12
 
13
+ def error(message)
14
+ puts "!! #{message}" if message && !message.empty?
15
+ end
13
16
  end
14
17
  end
15
18
  end
data/lib/reflection.rb CHANGED
@@ -5,6 +5,7 @@ module Reflection
5
5
  autoload :Config, 'reflection/config'
6
6
  autoload :Command, 'reflection/command'
7
7
  autoload :Directory, 'reflection/directory'
8
+ autoload :Rails, 'reflection/rails'
8
9
  autoload :Repository, 'reflection/repository'
9
10
  autoload :Support, 'reflection/support'
10
11
  autoload :Validations, 'reflection/validations'
@@ -2,8 +2,8 @@ require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
3
  describe Reflection::Command::Stash do
4
4
  before(:each) do
5
- @options = OpenStruct.new({ :directory => '/home/tmp/fu_asset_directory', :command => :stash })
6
- @subject = Reflection::Command::Stash.new(@options)
5
+ @config = OpenStruct.new({ :directory => '/home/tmp/fu_asset_directory', :command => :stash })
6
+ @subject = Reflection::Command::Stash.new(@config)
7
7
  end
8
8
 
9
9
  describe 'validations' do
@@ -83,6 +83,13 @@ describe Reflection::Command::Stash do
83
83
  @subject.stash_directory_into_repository(@mock_stash_directory, @mock_target_directory)
84
84
  end
85
85
 
86
+ it 'should call the stash command on the database dumper if enabled' do
87
+ @config.rails_root = "/rails/root"
88
+ Reflection::Rails.should_receive(:stash).with(@config, @mock_target_directory)
89
+ @subject.stash_directory_into_repository(@mock_stash_directory, @mock_target_directory)
90
+ end
91
+
92
+
86
93
  it "should add and push the contents of directory to the repository" do
87
94
  @subject.should_receive(:commit_and_push_files).with("/home/tmp/assets", "assets")
88
95
  @subject.stash_directory_into_repository(@mock_stash_directory, @mock_target_directory)
@@ -2,7 +2,9 @@ require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
3
  describe Reflection::Config do
4
4
  before(:each) do
5
- @valid_options = { :command => :stash, :repository => 'repo', :directory => 'dir' }
5
+ @valid_options = {
6
+ :command => :stash, :repository => 'repo', :directory => 'dir', :rails_root => "rails_root", :rails_environment => 'development'
7
+ }
6
8
  end
7
9
 
8
10
  describe 'parse' do
@@ -41,6 +43,8 @@ describe Reflection::Config do
41
43
  @config.command = :stash
42
44
  @config.repository = 'repo'
43
45
  @config.directory = 'dir'
46
+ @config.rails_root = 'rails_root'
47
+ @config.rails_environment = 'development'
44
48
  @config.to_hash.should == @valid_options
45
49
  end
46
50
  end
@@ -52,6 +56,8 @@ describe Reflection::Config do
52
56
  @config.command.should eql(:stash)
53
57
  @config.repository.should eql('repo')
54
58
  @config.directory.should eql('dir')
59
+ @config.rails_root.should eql('rails_root')
60
+ @config.rails_environment.should eql('development')
55
61
  end
56
62
  end
57
63
 
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Reflection::Rails do
4
+ before(:each) do
5
+ @config = OpenStruct.new({ :rails_root => '/rails_root/', :rails_environment => 'development' })
6
+ @rails = Reflection::Rails
7
+ end
8
+
9
+ describe 'validate_environment' do
10
+ it "should fail if the specified environment does't exist" do
11
+ Reflection::Support.should_receive(:exit_with_error)
12
+ File.stub!(:exist?).and_return(false)
13
+ @rails.validate_environment(@config)
14
+ end
15
+ end
16
+
17
+ describe 'read_database_configuration' do
18
+ it 'should read the configuration for the specified environment' do
19
+ db_config = { "host" => "localhost", "username" => "root" }
20
+ YAML.should_receive(:load_file).with('/rails_root/config/database.yml').and_return({ "production" => {}, "development" => db_config })
21
+ db_config = @rails.read_database_configuration(@config)
22
+ db_config.should == db_config
23
+ end
24
+
25
+ it "should log an error and return false if the environment isn't configured" do
26
+ Reflection.log.should_receive(:error).with(/available/)
27
+ YAML.stub!(:load_file).and_return({ "production" => {} })
28
+ @rails.read_database_configuration(@config).should be_false
29
+ end
30
+
31
+ it "should log an error and return false if the database.yml cannot be found" do
32
+ Reflection.log.should_receive(:error).with(/Error/)
33
+ YAML.stub!(:load_file).and_raise(StandardError)
34
+ @rails.read_database_configuration(@config).should be_false
35
+ end
36
+ end
37
+
38
+ describe 'database_command_line_options' do
39
+ before(:each) do
40
+ @db_config = { "host" => "localhost", "database" => "test", "username" => "root", "password" => "secret" }
41
+ end
42
+
43
+ it 'should create options for the mysql command' do
44
+ @rails.database_command_line_options(@db_config).should == "-h localhost -u root -p secret test"
45
+ end
46
+
47
+ it 'should ignore the password option if its not available' do
48
+ @db_config['password'] = ""
49
+ @rails.database_command_line_options(@db_config).should == "-h localhost -u root test"
50
+
51
+ @db_config['password'] = nil
52
+ @rails.database_command_line_options(@db_config).should == "-h localhost -u root test"
53
+ end
54
+ end
55
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reflection
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Wolff
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-17 00:00:00 +01:00
12
+ date: 2009-11-18 00:00:00 +01:00
13
13
  default_executable: reflection
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,7 +32,7 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.2.5
34
34
  version:
35
- description: "\n Reflection is designed to keep your production assets (database comming soon) in sync with your development system.\n It uses a shared git repository to store these files, which allows you to mirror your production environment without the need of \n direct access to your production servers.\n "
35
+ description: "\n Reflection is designed to keep your development system in sync with your production system's files and database (by dumping).\n It uses a shared git repository to store these files, which allows you to mirror your production environment without the need of \n direct access to your production servers.\n "
36
36
  email: rubyphunk@gmail.com
37
37
  executables:
38
38
  - reflection
@@ -61,6 +61,7 @@ files:
61
61
  - lib/reflection/directory.rb
62
62
  - lib/reflection/directory/base.rb
63
63
  - lib/reflection/directory/stash.rb
64
+ - lib/reflection/rails.rb
64
65
  - lib/reflection/repository.rb
65
66
  - lib/reflection/support.rb
66
67
  - lib/reflection/support/home.rb
@@ -71,6 +72,7 @@ files:
71
72
  - spec/reflection/config_spec.rb
72
73
  - spec/reflection/directory/base_spec.rb
73
74
  - spec/reflection/directory/stash_spec.rb
75
+ - spec/reflection/rails_spec.rb
74
76
  - spec/reflection/repository_spec.rb
75
77
  - spec/reflection/support/home_spec.rb
76
78
  - spec/reflection/support_spec.rb
@@ -104,13 +106,14 @@ rubyforge_project:
104
106
  rubygems_version: 1.3.5
105
107
  signing_key:
106
108
  specification_version: 3
107
- summary: Helps you keeping your development machine in sync with production.
109
+ summary: Keep your development machine in sync with production.
108
110
  test_files:
109
111
  - spec/reflection/cli_spec.rb
110
112
  - spec/reflection/command/stash_spec.rb
111
113
  - spec/reflection/config_spec.rb
112
114
  - spec/reflection/directory/base_spec.rb
113
115
  - spec/reflection/directory/stash_spec.rb
116
+ - spec/reflection/rails_spec.rb
114
117
  - spec/reflection/repository_spec.rb
115
118
  - spec/reflection/support/home_spec.rb
116
119
  - spec/reflection/support_spec.rb