rubyrep 1.1.2 → 1.2.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/.gemtest +0 -0
- data/History.txt +9 -0
- data/bin/rubyrep +0 -0
- data/config/hoe.rb +15 -17
- data/lib/rubyrep.rb +1 -1
- data/lib/rubyrep/connection_extenders/connection_extenders.rb +14 -1
- data/lib/rubyrep/connection_extenders/jdbc_extender.rb +4 -19
- data/lib/rubyrep/proxy_connection.rb +5 -0
- data/lib/rubyrep/replication_difference.rb +4 -0
- data/lib/rubyrep/replication_extenders/postgresql_replication.rb +14 -1
- data/lib/rubyrep/replication_run.rb +37 -11
- data/lib/rubyrep/replication_runner.rb +7 -1
- data/lib/rubyrep/table_scan_helper.rb +9 -1
- data/lib/rubyrep/version.rb +2 -2
- data/sims/performance/performance.rake +3 -2
- data/spec/connection_extenders_registration_spec.rb +5 -1
- data/spec/proxy_connection_spec.rb +14 -2
- data/spec/replication_run_spec.rb +62 -0
- data/spec/table_scan_helper_spec.rb +7 -0
- data/tasks/database.rake +1 -1
- data/tasks/rspec.rake +3 -7
- metadata +29 -16
data/.gemtest
ADDED
File without changes
|
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 1.2.0 2011-03-07
|
2
|
+
|
3
|
+
* Feature: compatibility with Rails 3
|
4
|
+
* Feature: do not replicate record updates that didn't change any fields (props to daudo)
|
5
|
+
* Bug fix: reducing deadlock problems (props to gtanzillo)
|
6
|
+
* Bug fix: adding missing schema prefix in PostgreSQL triggers
|
7
|
+
* Bug fix: scans / syncs fail due to incorrect handling of case sensitivity of string primary key columns
|
8
|
+
* Bug fix: reducing risk of foreign key conflicts during replication (props for root cause analysis to TonyB)
|
9
|
+
|
1
10
|
== 1.1.2 2009-05-10
|
2
11
|
|
3
12
|
* Bug fix: escape primary keys in replication triggers
|
data/bin/rubyrep
CHANGED
File without changes
|
data/config/hoe.rb
CHANGED
@@ -45,25 +45,23 @@ end
|
|
45
45
|
|
46
46
|
# Generate all the Rake tasks
|
47
47
|
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
48
|
-
hoe = Hoe.
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
48
|
+
hoe = Hoe.spec(GEM_NAME) do
|
49
|
+
self.version = VERS
|
50
|
+
developer AUTHOR, EMAIL
|
51
|
+
description = DESCRIPTION
|
52
|
+
summary = DESCRIPTION
|
53
|
+
url = HOMEPATH
|
54
|
+
rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
55
|
+
test_globs = ["test/**/test_*.rb"]
|
56
|
+
clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
|
57
|
+
|
58
58
|
# == Optional
|
59
|
-
|
60
|
-
#
|
61
|
-
|
62
|
-
|
63
|
-
['activerecord' , '>= 2.3.5']
|
64
|
-
]
|
59
|
+
changes = paragraphs_of("History.txt", 0..1).join("\\n\\n")
|
60
|
+
#extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
61
|
+
extra_deps << ['activesupport', '>= 3.0.5']
|
62
|
+
extra_deps << ['activerecord' , '>= 3.0.5']
|
65
63
|
|
66
|
-
#
|
64
|
+
#spec_extras = {} # A hash of extra values to set in the gemspec.
|
67
65
|
|
68
66
|
end
|
69
67
|
|
data/lib/rubyrep.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
class ActiveRecord::ConnectionAdapters::AbstractAdapter
|
2
|
+
# The current log subscriber
|
3
|
+
attr_accessor :log_subscriber
|
4
|
+
end
|
5
|
+
|
1
6
|
class ActiveRecord::ConnectionAdapters::Column
|
2
7
|
# Bug in ActiveRecord parsing of PostgreSQL timestamps with microseconds:
|
3
8
|
# Certain values are incorrectly rounded, thus ending up with timestamps
|
@@ -107,9 +112,17 @@ module RR
|
|
107
112
|
if config[:logger].respond_to?(:debug)
|
108
113
|
logger = config[:logger]
|
109
114
|
else
|
110
|
-
logger =
|
115
|
+
logger = ActiveSupport::BufferedLogger.new(config[:logger])
|
111
116
|
end
|
112
117
|
db_connection.instance_variable_set :@logger, logger
|
118
|
+
if ActiveSupport.const_defined?(:Notifications)
|
119
|
+
connection_object_id = db_connection.object_id
|
120
|
+
db_connection.log_subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |name, start, finish, id, payload|
|
121
|
+
if payload[:connection_id] == connection_object_id and logger.debug?
|
122
|
+
logger.debug payload[:sql].squeeze(" ")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
113
126
|
end
|
114
127
|
end
|
115
128
|
|
@@ -58,23 +58,8 @@ module RR
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
# And here comes the monkey patch to revert it again...
|
66
|
-
require 'active_record/connection_adapters/jdbc_adapter_spec'
|
67
|
-
require 'jdbc_adapter/jdbc_sqlite3'
|
68
|
-
module ::ActiveRecord
|
69
|
-
module ConnectionAdapters
|
70
|
-
class JdbcColumn < Column
|
71
|
-
def self.string_to_binary(value)
|
72
|
-
value
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.binary_to_string(value)
|
76
|
-
value
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
61
|
+
require 'activerecord-jdbc-adapter'
|
62
|
+
if ArJdbc.const_defined?(:PostgreSQL)
|
63
|
+
ArJdbc::PostgreSQL::RecordNotUnique = ActiveRecord::RecordNotUnique unless ArJdbc::PostgreSQL.const_defined?(:RecordNotUnique)
|
64
|
+
ArJdbc::PostgreSQL::InvalidForeignKey = ActiveRecord::InvalidForeignKey unless ArJdbc::PostgreSQL.const_defined?(:InvalidForeignKey)
|
80
65
|
end
|
@@ -19,6 +19,10 @@ module RR
|
|
19
19
|
# * :+no_diff+: changes in both databases constitute no difference
|
20
20
|
attr_accessor :type
|
21
21
|
|
22
|
+
# Is set to +true+ if first replication attempt failed but it should be tried again later
|
23
|
+
attr_accessor :second_chance
|
24
|
+
alias_method :second_chance?, :second_chance
|
25
|
+
|
22
26
|
# A hash with keys :+left+ and / or :+right+.
|
23
27
|
# Hash values are LoggedChange instances.
|
24
28
|
def changes
|
@@ -45,13 +45,25 @@ module RR
|
|
45
45
|
activity_check = ""
|
46
46
|
if params[:exclude_rr_activity] then
|
47
47
|
activity_check = <<-end_sql
|
48
|
-
PERFORM ACTIVE FROM #{params[:activity_table]};
|
48
|
+
PERFORM ACTIVE FROM #{schema_prefix}#{params[:activity_table]};
|
49
49
|
IF FOUND THEN
|
50
50
|
RETURN NULL;
|
51
51
|
END IF;
|
52
52
|
end_sql
|
53
53
|
end
|
54
54
|
|
55
|
+
version_string = select_value("select version();")
|
56
|
+
version = version_string.gsub(/^\s*postgresql\s*([0-9.]+).*$/i, '\1')
|
57
|
+
if version >= '8.4'
|
58
|
+
modification_check = <<-end_sql
|
59
|
+
IF NEW IS NOT DISTINCT FROM OLD THEN
|
60
|
+
RETURN NULL;
|
61
|
+
END IF;
|
62
|
+
end_sql
|
63
|
+
else
|
64
|
+
modification_check = ""
|
65
|
+
end
|
66
|
+
|
55
67
|
# now create the trigger
|
56
68
|
execute(<<-end_sql)
|
57
69
|
CREATE OR REPLACE FUNCTION "#{params[:trigger_name]}"() RETURNS TRIGGER AS $change_trigger$
|
@@ -61,6 +73,7 @@ module RR
|
|
61
73
|
INSERT INTO #{schema_prefix}#{params[:log_table]}(change_table, change_key, change_type, change_time)
|
62
74
|
SELECT '#{params[:table]}', #{key_clause('OLD', params)}, 'D', now();
|
63
75
|
ELSIF (TG_OP = 'UPDATE') THEN
|
76
|
+
#{modification_check}
|
64
77
|
INSERT INTO #{schema_prefix}#{params[:log_table]}(change_table, change_key, change_new_key, change_type, change_time)
|
65
78
|
SELECT '#{params[:table]}', #{key_clause('OLD', params)}, #{key_clause('NEW', params)}, 'U', now();
|
66
79
|
ELSIF (TG_OP = 'INSERT') THEN
|
@@ -11,6 +11,11 @@ module RR
|
|
11
11
|
# The current TaskSweeper
|
12
12
|
attr_accessor :sweeper
|
13
13
|
|
14
|
+
# An array of ReplicationDifference which originally failed replication but should be tried one more time
|
15
|
+
def second_chancers
|
16
|
+
@second_chancers ||= []
|
17
|
+
end
|
18
|
+
|
14
19
|
# Returns the current ReplicationHelper; creates it if necessary
|
15
20
|
def helper
|
16
21
|
@helper ||= ReplicationHelper.new(self)
|
@@ -39,6 +44,20 @@ module RR
|
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
47
|
+
# Returns the next available ReplicationDifference.
|
48
|
+
# (Either new unprocessed differences or if not available, the first available 'second chancer'.)
|
49
|
+
#
|
50
|
+
def load_difference
|
51
|
+
@loaders ||= LoggedChangeLoaders.new(session)
|
52
|
+
@loaders.update # ensure the cache of change log records is up-to-date
|
53
|
+
diff = ReplicationDifference.new @loaders
|
54
|
+
diff.load
|
55
|
+
unless diff.loaded? or second_chancers.empty?
|
56
|
+
diff = second_chancers.shift
|
57
|
+
end
|
58
|
+
diff
|
59
|
+
end
|
60
|
+
|
42
61
|
# Executes the replication run.
|
43
62
|
def run
|
44
63
|
return unless [:left, :right].any? do |database|
|
@@ -57,29 +76,36 @@ module RR
|
|
57
76
|
# Check for this and if timed out, return (silently).
|
58
77
|
return if sweeper.terminated?
|
59
78
|
|
60
|
-
loaders = LoggedChangeLoaders.new(session)
|
61
|
-
|
62
79
|
success = false
|
63
80
|
begin
|
64
81
|
replicator # ensure that replicator is created and has chance to validate settings
|
65
82
|
|
66
83
|
loop do
|
67
84
|
begin
|
68
|
-
|
69
|
-
diff = ReplicationDifference.new loaders
|
70
|
-
diff.load
|
85
|
+
diff = load_difference
|
71
86
|
break unless diff.loaded?
|
72
87
|
break if sweeper.terminated?
|
73
88
|
if diff.type != :no_diff and not event_filtered?(diff)
|
74
89
|
replicator.replicate_difference diff
|
75
90
|
end
|
76
91
|
rescue Exception => e
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
#
|
82
|
-
|
92
|
+
if e.message =~ /violates foreign key constraint|foreign key constraint fails/i and !diff.second_chance?
|
93
|
+
# Note:
|
94
|
+
# Identifying the foreign key constraint violation via regular expression is
|
95
|
+
# database dependent and *dirty*.
|
96
|
+
# It would be better to use the ActiveRecord #translate_exception mechanism.
|
97
|
+
# However as per version 3.0.5 this doesn't work yet properly.
|
98
|
+
|
99
|
+
diff.second_chance = true
|
100
|
+
second_chancers << diff
|
101
|
+
else
|
102
|
+
begin
|
103
|
+
helper.log_replication_outcome diff, e.message,
|
104
|
+
e.class.to_s + "\n" + e.backtrace.join("\n")
|
105
|
+
rescue Exception => _
|
106
|
+
# if logging to database itself fails, re-raise the original exception
|
107
|
+
raise e
|
108
|
+
end
|
83
109
|
end
|
84
110
|
end
|
85
111
|
end
|
@@ -2,6 +2,12 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
|
2
2
|
|
3
3
|
require 'optparse'
|
4
4
|
require 'thread'
|
5
|
+
require 'monitor'
|
6
|
+
|
7
|
+
class Monitor
|
8
|
+
alias lock mon_enter
|
9
|
+
alias unlock mon_exit
|
10
|
+
end
|
5
11
|
|
6
12
|
module RR
|
7
13
|
# This class implements the functionality of the 'replicate' command.
|
@@ -94,7 +100,7 @@ EOS
|
|
94
100
|
# Initializes the waiter thread used for replication pauses and processing
|
95
101
|
# the process TERM signal.
|
96
102
|
def init_waiter
|
97
|
-
@termination_mutex =
|
103
|
+
@termination_mutex = Monitor.new
|
98
104
|
@termination_mutex.lock
|
99
105
|
@waiter_thread ||= Thread.new {@termination_mutex.lock; self.termination_requested = true}
|
100
106
|
%w(TERM INT).each do |signal|
|
@@ -19,7 +19,15 @@ module RR
|
|
19
19
|
return 1 unless left_row
|
20
20
|
rank = 0
|
21
21
|
primary_key_names.any? do |key|
|
22
|
-
|
22
|
+
if left_row[key].kind_of?(String)
|
23
|
+
# When databases order strings, then 'a' < 'A' while for Ruby 'A' < 'a'
|
24
|
+
# ==> Use a combination of case sensitive and case insensitive comparing to
|
25
|
+
# reproduce the database behaviour.
|
26
|
+
rank = left_row[key].casecmp(right_row[key]) # deal with 'a' to 'B' comparisons
|
27
|
+
rank = -(left_row[key] <=> right_row[key]) if rank == 0 # deal with 'a' to 'A' comparisons
|
28
|
+
else
|
29
|
+
rank = left_row[key] <=> right_row[key]
|
30
|
+
end
|
23
31
|
rank != 0
|
24
32
|
end
|
25
33
|
rank
|
data/lib/rubyrep/version.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
require 'rake'
|
2
3
|
require 'benchmark'
|
3
4
|
|
@@ -136,7 +137,7 @@ def populate_rep_data
|
|
136
137
|
# Updating progress bar
|
137
138
|
progress_bar.step
|
138
139
|
|
139
|
-
database = [:left, :right]
|
140
|
+
database = [:left, :right][rand(2)]
|
140
141
|
|
141
142
|
case rand(100)
|
142
143
|
when 0...BIG_REP_INSERT
|
@@ -147,7 +148,7 @@ def populate_rep_data
|
|
147
148
|
next_id += 1
|
148
149
|
session.send(database).insert_record 'big_rep', attributes
|
149
150
|
when BIG_REP_INSERT...BIG_REP_UPDATE
|
150
|
-
id = all_ids[database].
|
151
|
+
id = all_ids[database][rand(all_ids[database].size)]
|
151
152
|
attributes = session.send(database).select_one("select * from big_rep where id = '#{id}'")
|
152
153
|
column = number_columns[rand(number_columns.size)]
|
153
154
|
attributes[column] = rand(1000)
|
@@ -10,9 +10,13 @@ describe ConnectionExtenders do
|
|
10
10
|
it "db_connect should install the already created logger" do
|
11
11
|
configuration = deep_copy(Initializer.configuration)
|
12
12
|
io = StringIO.new
|
13
|
-
logger =
|
13
|
+
logger = ActiveSupport::BufferedLogger.new(io)
|
14
14
|
configuration.left[:logger] = logger
|
15
15
|
session = Session.new configuration
|
16
|
+
|
17
|
+
session.left.connection.instance_eval {@logger}.should == logger
|
18
|
+
session.right.connection.instance_eval {@logger}.should_not == logger
|
19
|
+
|
16
20
|
session.left.select_one "select 'left_query'"
|
17
21
|
session.right.select_one "select 'right_query'"
|
18
22
|
|
@@ -9,7 +9,7 @@ describe ProxyConnection do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "initialize should connect to the database" do
|
12
|
-
|
12
|
+
(!!@connection.connection.active?).should == true
|
13
13
|
end
|
14
14
|
|
15
15
|
it "initialize should store the configuratin" do
|
@@ -17,9 +17,21 @@ describe ProxyConnection do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it "destroy should disconnect from the database" do
|
20
|
+
if ActiveSupport.const_defined?(:Notifications)
|
21
|
+
ConnectionExtenders::install_logger @connection.connection, :logger => StringIO.new
|
22
|
+
log_subscriber = @connection.connection.log_subscriber
|
23
|
+
|
24
|
+
ActiveSupport::Notifications.notifier.listeners_for("sql.active_record").should include(log_subscriber)
|
25
|
+
end
|
26
|
+
|
20
27
|
@connection.destroy
|
21
28
|
|
22
|
-
|
29
|
+
if ActiveSupport.const_defined?(:Notifications)
|
30
|
+
ActiveSupport::Notifications.notifier.listeners_for("sql.active_record").should_not include(log_subscriber)
|
31
|
+
@connection.connection.log_subscriber.should be_nil
|
32
|
+
end
|
33
|
+
|
34
|
+
(!!@connection.connection.active?).should == false
|
23
35
|
end
|
24
36
|
|
25
37
|
it "cursors should return the current cursor hash or an empty hash if nil" do
|
@@ -135,6 +135,68 @@ describe ReplicationRun do
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
+
it "run should replication records with foreign key constraints" do
|
139
|
+
begin
|
140
|
+
config = deep_copy(standard_config)
|
141
|
+
config.options[:committer] = :never_commit
|
142
|
+
|
143
|
+
session = Session.new(config)
|
144
|
+
|
145
|
+
session.left.insert_record 'referencing_table', {
|
146
|
+
'id' => '5',
|
147
|
+
}
|
148
|
+
session.left.insert_record 'rr_pending_changes', {
|
149
|
+
'change_table' => 'referencing_table',
|
150
|
+
'change_key' => 'id|5',
|
151
|
+
'change_type' => 'I',
|
152
|
+
'change_time' => Time.now
|
153
|
+
}
|
154
|
+
|
155
|
+
session.left.insert_record 'referenced_table2', {
|
156
|
+
'id' => '6',
|
157
|
+
}
|
158
|
+
session.left.insert_record 'rr_pending_changes', {
|
159
|
+
'change_table' => 'referenced_table2',
|
160
|
+
'change_key' => 'id|6',
|
161
|
+
'change_type' => 'I',
|
162
|
+
'change_time' => Time.now
|
163
|
+
}
|
164
|
+
|
165
|
+
session.left.update_record 'referencing_table', {
|
166
|
+
'id' => 5,
|
167
|
+
'third_fk' => '6'
|
168
|
+
}
|
169
|
+
session.left.insert_record 'rr_pending_changes', {
|
170
|
+
'change_table' => 'referencing_table',
|
171
|
+
'change_key' => 'id|5',
|
172
|
+
'change_new_key' => 'id|5',
|
173
|
+
'change_type' => 'U',
|
174
|
+
'change_time' => Time.now
|
175
|
+
}
|
176
|
+
|
177
|
+
run = ReplicationRun.new session, TaskSweeper.new(1)
|
178
|
+
run.run
|
179
|
+
|
180
|
+
session.right.select_record(:table => "referencing_table", :from => {'id' => 5}).should == {
|
181
|
+
'id' => 5,
|
182
|
+
'first_fk' => nil,
|
183
|
+
'second_fk' => nil,
|
184
|
+
'third_fk' => 6
|
185
|
+
}
|
186
|
+
ensure
|
187
|
+
Committers::NeverCommitter.rollback_current_session
|
188
|
+
if session
|
189
|
+
session.left.execute "delete from referencing_table where id = 5"
|
190
|
+
session.left.execute "delete from referenced_table2 where id = 6"
|
191
|
+
|
192
|
+
session.right.execute "delete from referencing_table where id = 5"
|
193
|
+
session.right.execute "delete from referenced_table2 where id = 6"
|
194
|
+
|
195
|
+
session.left.execute "delete from rr_pending_changes"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
138
200
|
it "run should not replicate filtered changes" do
|
139
201
|
begin
|
140
202
|
config = deep_copy(standard_config)
|
@@ -13,6 +13,13 @@ describe TableScanHelper do
|
|
13
13
|
@scan.rank_rows({'first_id' => 1, 'second_id' => 1}, {'first_id' => 1, 'second_id' => 1}).should == 0
|
14
14
|
@scan.rank_rows({'first_id' => 1, 'second_id' => 1}, {'first_id' => 1, 'second_id' => 2}).should == -1
|
15
15
|
@scan.rank_rows({'first_id' => 2, 'second_id' => 1}, {'first_id' => 1, 'second_id' => 1}).should == 1
|
16
|
+
|
17
|
+
# should rank strings according to database logic ('a' < 'A')
|
18
|
+
# instead of the Ruby logic (which is the other way round)
|
19
|
+
@scan.rank_rows({'first_id' => 'a', 'second_id' => 1}, {'first_id' => 'B', 'second_id' => 1}).should == -1
|
20
|
+
@scan.rank_rows({'first_id' => 'a', 'second_id' => 1}, {'first_id' => 'A', 'second_id' => 1}).should == -1
|
21
|
+
@scan.rank_rows({'first_id' => 'a', 'second_id' => 1}, {'first_id' => 'a', 'second_id' => 1}).should == 0
|
22
|
+
|
16
23
|
lambda {@scan.rank_rows(nil,nil)}.should raise_error(RuntimeError, 'At least one of left_row and right_row must not be nil!')
|
17
24
|
@scan.rank_rows(nil, {'first_id' => 1, 'second_id' => 1}).should == 1
|
18
25
|
@scan.rank_rows({'first_id' => 1, 'second_id' => 1}, nil).should == -1
|
data/tasks/database.rake
CHANGED
@@ -18,7 +18,7 @@ def create_database(config)
|
|
18
18
|
@charset = ENV['CHARSET'] || 'utf8'
|
19
19
|
@collation = ENV['COLLATION'] || 'utf8_general_ci'
|
20
20
|
begin
|
21
|
-
connection = RR::ConnectionExtenders.db_connect(config.merge({
|
21
|
+
connection = RR::ConnectionExtenders.db_connect(config.merge({:database => nil}))
|
22
22
|
connection.create_database(config[:database], {:charset => @charset, :collation => @collation})
|
23
23
|
RR::ConnectionExtenders.db_connect(config)
|
24
24
|
rescue
|
data/tasks/rspec.rake
CHANGED
@@ -41,18 +41,14 @@ namespace :spec do
|
|
41
41
|
desc "Run the specs for all supported databases"
|
42
42
|
task :all_dbs do
|
43
43
|
[:postgres, :mysql].each do |test_db|
|
44
|
-
puts "Running specs for #{test_db
|
45
|
-
|
46
|
-
system "spec spec"
|
44
|
+
puts "Running specs for #{test_db}"
|
45
|
+
system "bash -c 'RR_TEST_DB=#{test_db} spec spec'"
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
49
|
desc "Run the specs for all supported databases and ruby platforms"
|
51
50
|
task :all_rubies do
|
52
|
-
|
53
|
-
system "rake spec:all_dbs"
|
54
|
-
puts "Running spec:all_dbs in jruby"
|
55
|
-
system "export PATH=#{JRUBY_HOME}/bin:$PATH; rake spec:all_dbs"
|
51
|
+
system %(rvm exec bash -c 'for db in postgres mysql; do echo "`rvm current` - $db:"; RR_TEST_DB=$db spec spec; done')
|
56
52
|
end
|
57
53
|
|
58
54
|
begin
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyrep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 31
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 1
|
7
|
-
- 1
|
8
8
|
- 2
|
9
|
-
|
9
|
+
- 0
|
10
|
+
version: 1.2.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Arndt Lehmann
|
@@ -14,53 +15,60 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2011-03-07 00:00:00 +09:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: activesupport
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
27
30
|
segments:
|
28
|
-
- 2
|
29
31
|
- 3
|
32
|
+
- 0
|
30
33
|
- 5
|
31
|
-
version:
|
34
|
+
version: 3.0.5
|
32
35
|
type: :runtime
|
33
36
|
version_requirements: *id001
|
34
37
|
- !ruby/object:Gem::Dependency
|
35
38
|
name: activerecord
|
36
39
|
prerelease: false
|
37
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
38
42
|
requirements:
|
39
43
|
- - ">="
|
40
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 13
|
41
46
|
segments:
|
42
|
-
- 2
|
43
47
|
- 3
|
48
|
+
- 0
|
44
49
|
- 5
|
45
|
-
version:
|
50
|
+
version: 3.0.5
|
46
51
|
type: :runtime
|
47
52
|
version_requirements: *id002
|
48
53
|
- !ruby/object:Gem::Dependency
|
49
54
|
name: hoe
|
50
55
|
prerelease: false
|
51
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
52
58
|
requirements:
|
53
59
|
- - ">="
|
54
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 41
|
55
62
|
segments:
|
56
63
|
- 2
|
57
|
-
-
|
58
|
-
-
|
59
|
-
version: 2.
|
64
|
+
- 9
|
65
|
+
- 1
|
66
|
+
version: 2.9.1
|
60
67
|
type: :development
|
61
68
|
version_requirements: *id003
|
62
|
-
description:
|
63
|
-
email:
|
69
|
+
description: ""
|
70
|
+
email:
|
71
|
+
- mail@arndtlehman.com
|
64
72
|
executables:
|
65
73
|
- rubyrep
|
66
74
|
extensions: []
|
@@ -222,8 +230,9 @@ files:
|
|
222
230
|
- tasks/stats.rake
|
223
231
|
- tasks/task_helper.rb
|
224
232
|
- tasks/website.rake
|
233
|
+
- .gemtest
|
225
234
|
has_rdoc: true
|
226
|
-
homepage:
|
235
|
+
homepage:
|
227
236
|
licenses: []
|
228
237
|
|
229
238
|
post_install_message:
|
@@ -233,25 +242,29 @@ rdoc_options:
|
|
233
242
|
require_paths:
|
234
243
|
- lib
|
235
244
|
required_ruby_version: !ruby/object:Gem::Requirement
|
245
|
+
none: false
|
236
246
|
requirements:
|
237
247
|
- - ">="
|
238
248
|
- !ruby/object:Gem::Version
|
249
|
+
hash: 3
|
239
250
|
segments:
|
240
251
|
- 0
|
241
252
|
version: "0"
|
242
253
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
254
|
+
none: false
|
243
255
|
requirements:
|
244
256
|
- - ">="
|
245
257
|
- !ruby/object:Gem::Version
|
258
|
+
hash: 3
|
246
259
|
segments:
|
247
260
|
- 0
|
248
261
|
version: "0"
|
249
262
|
requirements: []
|
250
263
|
|
251
264
|
rubyforge_project: rubyrep
|
252
|
-
rubygems_version: 1.
|
265
|
+
rubygems_version: 1.5.2
|
253
266
|
signing_key:
|
254
267
|
specification_version: 3
|
255
|
-
summary:
|
268
|
+
summary: ""
|
256
269
|
test_files: []
|
257
270
|
|