coopy 0.6.4.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +7 -0
- data/LICENSE.md +22 -0
- data/README.md +59 -0
- data/Rakefile +4 -6
- data/coopy.gemspec +26 -0
- data/lib/coopy.rb +32 -175
- data/lib/coopy/alignment.rb +260 -0
- data/lib/coopy/bag.rb +17 -0
- data/lib/coopy/cell_info.rb +24 -0
- data/lib/coopy/change_type.rb +10 -0
- data/lib/coopy/compare_flags.rb +62 -0
- data/lib/coopy/compare_table.rb +327 -0
- data/lib/coopy/coopy.rb +22 -0
- data/lib/coopy/cross_match.rb +10 -0
- data/lib/coopy/csv_table.rb +51 -0
- data/lib/coopy/diff_render.rb +307 -0
- data/lib/coopy/index.rb +73 -0
- data/lib/coopy/index_item.rb +17 -0
- data/lib/coopy/index_pair.rb +72 -0
- data/lib/coopy/mover.rb +123 -0
- data/lib/coopy/ordering.rb +27 -0
- data/lib/coopy/row.rb +9 -0
- data/lib/coopy/simple_cell.rb +15 -0
- data/lib/coopy/simple_table.rb +144 -0
- data/lib/coopy/simple_view.rb +36 -0
- data/lib/coopy/table.rb +44 -0
- data/lib/coopy/table_comparison_state.rb +33 -0
- data/lib/coopy/table_diff.rb +634 -0
- data/lib/coopy/table_text.rb +14 -0
- data/lib/coopy/table_view.rb +31 -0
- data/lib/coopy/unit.rb +53 -0
- data/lib/coopy/version.rb +3 -0
- data/lib/coopy/view.rb +34 -0
- data/spec/fixtures/bridges.html +10 -0
- data/spec/fixtures/bridges_diff.csv +8 -0
- data/spec/fixtures/bridges_new.csv +9 -0
- data/spec/fixtures/bridges_old.csv +9 -0
- data/spec/fixtures/planetary_bodies.html +22 -0
- data/spec/fixtures/planetary_bodies_diff.csv +19 -0
- data/spec/fixtures/planetary_bodies_new.csv +20 -0
- data/spec/fixtures/planetary_bodies_old.csv +19 -0
- data/spec/fixtures/quote_me.csv +10 -0
- data/spec/fixtures/quote_me2.csv +11 -0
- data/spec/integration/table_diff_spec.rb +57 -0
- data/spec/libs/compare_flags_spec.rb +40 -0
- data/spec/libs/coopy_spec.rb +14 -0
- data/spec/libs/ordering_spec.rb +28 -0
- data/spec/libs/unit_spec.rb +31 -0
- data/spec/spec_helper.rb +29 -0
- metadata +153 -46
- data/bin/sqlite_diff +0 -4
- data/bin/sqlite_patch +0 -4
- data/bin/sqlite_rediff +0 -4
- data/lib/coopy/dbi_sql_wrapper.rb +0 -89
- data/lib/coopy/diff_apply_sql.rb +0 -35
- data/lib/coopy/diff_columns.rb +0 -33
- data/lib/coopy/diff_output.rb +0 -21
- data/lib/coopy/diff_output_action.rb +0 -34
- data/lib/coopy/diff_output_group.rb +0 -40
- data/lib/coopy/diff_output_raw.rb +0 -17
- data/lib/coopy/diff_output_stats.rb +0 -45
- data/lib/coopy/diff_output_table.rb +0 -49
- data/lib/coopy/diff_output_tdiff.rb +0 -48
- data/lib/coopy/diff_parser.rb +0 -92
- data/lib/coopy/diff_render_csv.rb +0 -29
- data/lib/coopy/diff_render_html.rb +0 -74
- data/lib/coopy/diff_render_log.rb +0 -52
- data/lib/coopy/row_change.rb +0 -25
- data/lib/coopy/scraperwiki_sql_wrapper.rb +0 -8
- data/lib/coopy/scraperwiki_utils.rb +0 -23
- data/lib/coopy/sequel_sql_wrapper.rb +0 -73
- data/lib/coopy/sql_compare.rb +0 -222
- data/lib/coopy/sql_wrapper.rb +0 -34
- data/lib/coopy/sqlite_sql_wrapper.rb +0 -143
- data/test/test_coopy.rb +0 -126
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7493ee11a18d6521e605f88a26b937ce6b096f15
|
4
|
+
data.tar.gz: a0410f887465a882377849fe96e55c1c70588708
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 37677ed77595308b7a205686c3048ba02051603ca8b6ce3c6ff1000f97e5c8522a243472cf01e5f8782273a9161fa81540d70f9fbe0f13b30179a6f35e7f16a1
|
7
|
+
data.tar.gz: 6806bd9e2ded7bedd32315c6764beac55338b7ae50b5c119609840504e87ebe52fbf45c4d956ba065749603148676204dba430d62f429f2eeb74ae76541c3c67
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 The Open Data Institute
|
2
|
+
|
3
|
+
# MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Coopy for Ruby
|
2
|
+
|
3
|
+
[![Build Status](http://jenkins.theodi.org/job/coopy-ruby-master/badge/icon)](http://jenkins.theodi.org/job/coopy-ruby-master/)
|
4
|
+
[![Dependency Status](https://gemnasium.com/theodi/coopy-ruby.png)](https://gemnasium.com/theodi/coopy-ruby)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/theodi/coopy-ruby.png)](https://codeclimate.com/github/theodi/coopy-ruby)
|
6
|
+
|
7
|
+
A pure Ruby port of Paul Fitzpatrick's [coopyhx](http://paulfitz.github.io/coopyhx) library for tabular diffs.
|
8
|
+
|
9
|
+
Not all the coopyhx code is ported or tested. There will be bugs. However, basic two-file CSV diff appears to be working. See 'Usage' section below for details.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'coopy'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install coopy
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
You can diff Ruby's built-in CSV objects, like so:
|
28
|
+
|
29
|
+
```
|
30
|
+
old_table = Coopy::CsvTable.new(old_csv_object)
|
31
|
+
new_table = Coopy::CsvTable.new(new_csv_object)
|
32
|
+
|
33
|
+
alignment = Coopy.compare_tables(old_table,new_table).align
|
34
|
+
flags = Coopy::CompareFlags.new
|
35
|
+
highlighter = Coopy::TableDiff.new(alignment,flags)
|
36
|
+
|
37
|
+
diff_table = Coopy::SimpleTable.new(0,0)
|
38
|
+
highlighter.hilite diff_table
|
39
|
+
```
|
40
|
+
|
41
|
+
You can inspect `diff_table` to see the changes.
|
42
|
+
|
43
|
+
You can also generate an HTML view of this diff like this:
|
44
|
+
|
45
|
+
```
|
46
|
+
diff2html = Coopy::DiffRender.new
|
47
|
+
diff2html.render diff_table
|
48
|
+
html = diff2html.html
|
49
|
+
```
|
50
|
+
|
51
|
+
There is plenty more in the original coopyhx, but this is all that's known working at the moment.
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
1. Fork it
|
56
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
57
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
58
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
59
|
+
5. Create new Pull Request
|
data/Rakefile
CHANGED
data/coopy.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'coopy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "coopy"
|
8
|
+
spec.version = Coopy::VERSION
|
9
|
+
spec.authors = ["James Smith"]
|
10
|
+
spec.email = ["james@floppy.org.uk"]
|
11
|
+
spec.description = %q{Ruby port of coopyhx, for calculating tabular diffs}
|
12
|
+
spec.summary = %q{Ruby port of coopyhx, for calculating tabular diffs}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "simplecov-rcov"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
end
|
data/lib/coopy.rb
CHANGED
@@ -1,178 +1,35 @@
|
|
1
|
-
require
|
1
|
+
require "coopy/version"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
class Flavor
|
6
|
-
attr_accessor :key
|
7
|
-
attr_accessor :banner
|
8
|
-
attr_accessor :min_length
|
9
|
-
|
10
|
-
def sql_subject?
|
11
|
-
[:diff,:patch].include? key
|
12
|
-
end
|
13
|
-
|
14
|
-
def sql_object?
|
15
|
-
key == :diff
|
16
|
-
end
|
17
|
-
|
18
|
-
def can_choose_format?
|
19
|
-
key != :patch
|
20
|
-
end
|
21
|
-
|
22
|
-
def can_set_output?
|
23
|
-
key != :patch
|
24
|
-
end
|
25
|
-
|
26
|
-
def default_format
|
27
|
-
(key==:patch) ? :apply : :csv
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class OpenStruct
|
32
|
-
attr_accessor :format
|
33
|
-
attr_accessor :output
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.parse(flavor,args)
|
37
|
-
options = OpenStruct.new
|
38
|
-
options.format = flavor.default_format
|
39
|
-
options.output = nil
|
40
|
-
OptionParser.new do |opts|
|
41
|
-
begin
|
42
|
-
opts.banner = flavor.banner
|
43
|
-
opts.separator ""
|
44
|
-
opts.separator "Specific options"
|
45
|
-
if flavor.can_choose_format?
|
46
|
-
opts.on("-f","--format [FORMAT]", [:csv, :html, :tdiff, :apply, :stats],
|
47
|
-
"select format (csv,html,tdiff,apply,stats)") do |fmt|
|
48
|
-
options.format = fmt
|
49
|
-
end
|
50
|
-
end
|
51
|
-
if flavor.can_set_output?
|
52
|
-
opts.on("-o", "--output [FILENAME]",
|
53
|
-
"direct output to a file") do |fname|
|
54
|
-
options.output = fname
|
55
|
-
end
|
56
|
-
end
|
57
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
58
|
-
puts opts
|
59
|
-
exit
|
60
|
-
end
|
61
|
-
opts.parse!(args)
|
62
|
-
return options
|
63
|
-
rescue
|
64
|
-
puts "#{$!} (--help for help)"
|
65
|
-
exit 1
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.core(flavor,argv)
|
71
|
-
options = self.parse(flavor,argv)
|
72
|
-
|
73
|
-
if argv.length < flavor.min_length
|
74
|
-
self.parse(flavor,["--help"])
|
75
|
-
exit(1)
|
76
|
-
end
|
77
|
-
|
78
|
-
if flavor.sql_subject?
|
79
|
-
db = SQLite3::Database.new(argv[0])
|
80
|
-
sql = SqliteSqlWrapper.new(db)
|
81
|
-
end
|
82
|
-
|
83
|
-
if flavor.sql_object?
|
84
|
-
name1 = nil
|
85
|
-
name2 = nil
|
86
|
-
case argv.length
|
87
|
-
when 2
|
88
|
-
name0 = sql.get_table_names[0]
|
89
|
-
db.execute("ATTACH ? AS `__peer_ - _`",argv[1])
|
90
|
-
name1 = "main.#{name0}"
|
91
|
-
name2 = "__peer_ - _.#{name0}"
|
92
|
-
when 3
|
93
|
-
name1 = argv[1]
|
94
|
-
name2 = argv[2]
|
95
|
-
when 4
|
96
|
-
name1 = "main.#{argv[1]}"
|
97
|
-
db.execute("ATTACH ? AS __peer__",argv[2])
|
98
|
-
name2 = "__peer__.#{argv[3]}"
|
99
|
-
end
|
100
|
-
cmp = SqlCompare.new(sql,name1,name2)
|
101
|
-
else
|
102
|
-
cmp = DiffParser.new(argv[flavor.min_length-1])
|
103
|
-
end
|
104
|
-
|
105
|
-
patches = DiffOutputGroup.new
|
106
|
-
# patches << DiffOutputRaw.new
|
107
|
-
case options.format
|
108
|
-
when :html
|
109
|
-
patches << DiffRenderHtml.new
|
110
|
-
when :tdiff
|
111
|
-
patches << DiffOutputTdiff.new
|
112
|
-
when :csv
|
113
|
-
patches << DiffRenderCsv.new
|
114
|
-
when :apply
|
115
|
-
patches << DiffApplySql.new(sql,name1)
|
116
|
-
when :raw
|
117
|
-
patches << DiffOutputRaw.new
|
118
|
-
when :stats
|
119
|
-
patches << DiffOutputStats.new
|
120
|
-
else
|
121
|
-
patches << DiffRenderCsv.new
|
122
|
-
end
|
123
|
-
|
124
|
-
cmp.set_output(patches)
|
125
|
-
|
126
|
-
cmp.apply
|
127
|
-
result = patches.to_string
|
128
|
-
if result != ""
|
129
|
-
if options.output.nil?
|
130
|
-
print result
|
131
|
-
else
|
132
|
-
File.open(options.output,"w") do |f|
|
133
|
-
f << result
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
0
|
138
|
-
end
|
139
|
-
|
140
|
-
def self.diff(argv)
|
141
|
-
flavor = Flavor.new
|
142
|
-
flavor.key = :diff
|
143
|
-
flavor.banner = "Usage: sqlite_diff [options] ver1.sqlite ver2.sqlite"
|
144
|
-
flavor.min_length = 2
|
145
|
-
self.core(flavor,argv)
|
146
|
-
end
|
147
|
-
|
148
|
-
def self.patch(argv)
|
149
|
-
flavor = Flavor.new
|
150
|
-
flavor.key = :patch
|
151
|
-
flavor.banner = "Usage: sqlite_patch [options] db.sqlite patch.csv"
|
152
|
-
flavor.min_length = 2
|
153
|
-
self.core(flavor,argv)
|
154
|
-
end
|
155
|
-
|
156
|
-
def self.rediff(argv)
|
157
|
-
flavor = Flavor.new
|
158
|
-
flavor.key = :rediff
|
159
|
-
flavor.banner = "Usage: sqlite_rediff [options] patch.csv"
|
160
|
-
flavor.min_length = 1
|
161
|
-
self.core(flavor,argv)
|
162
|
-
end
|
3
|
+
module Coopy
|
4
|
+
# Your code goes here...
|
163
5
|
end
|
164
6
|
|
165
|
-
|
166
|
-
require 'coopy/
|
167
|
-
require 'coopy/
|
168
|
-
require 'coopy/
|
169
|
-
require 'coopy/
|
170
|
-
|
171
|
-
|
172
|
-
require 'coopy/
|
173
|
-
require 'coopy/
|
174
|
-
|
175
|
-
require 'coopy/
|
176
|
-
require 'coopy/
|
177
|
-
require '
|
178
|
-
|
7
|
+
# interfaces
|
8
|
+
require 'coopy/bag'
|
9
|
+
require 'coopy/row'
|
10
|
+
require 'coopy/table'
|
11
|
+
require 'coopy/view'
|
12
|
+
|
13
|
+
# proper classes
|
14
|
+
require 'coopy/compare_flags'
|
15
|
+
require 'coopy/change_type'
|
16
|
+
require 'coopy/cell_info'
|
17
|
+
require 'coopy/unit'
|
18
|
+
require 'coopy/ordering'
|
19
|
+
require 'coopy/simple_cell'
|
20
|
+
require 'coopy/index_item'
|
21
|
+
require 'coopy/index'
|
22
|
+
require 'coopy/cross_match'
|
23
|
+
require 'coopy/index_pair'
|
24
|
+
require 'coopy/alignment'
|
25
|
+
require 'coopy/table_view'
|
26
|
+
require 'coopy/table_comparison_state'
|
27
|
+
require 'coopy/compare_table'
|
28
|
+
require 'coopy/mover'
|
29
|
+
require 'coopy/table_diff'
|
30
|
+
require 'coopy/coopy'
|
31
|
+
require 'coopy/simple_view'
|
32
|
+
require 'coopy/csv_table'
|
33
|
+
require 'coopy/simple_table'
|
34
|
+
require 'coopy/table_text'
|
35
|
+
require 'coopy/diff_render'
|
@@ -0,0 +1,260 @@
|
|
1
|
+
module Coopy
|
2
|
+
class Alignment
|
3
|
+
|
4
|
+
attr_accessor :reference # Alignment
|
5
|
+
attr_accessor :meta # Alignment
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@map_a2b = {} # Map<Int,Int>
|
9
|
+
@map_b2a = {} # Map<Int,Int>
|
10
|
+
@ha = @hb = 0
|
11
|
+
@map_count = 0
|
12
|
+
@reference = nil
|
13
|
+
@meta = nil
|
14
|
+
@order_cache_has_reference = false
|
15
|
+
@ia = 0
|
16
|
+
@ib = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def range(ha, hb)
|
20
|
+
@ha = ha
|
21
|
+
@hb = hb
|
22
|
+
end
|
23
|
+
|
24
|
+
def tables(ta, tb)
|
25
|
+
@ta = ta
|
26
|
+
@tb = tb
|
27
|
+
end
|
28
|
+
|
29
|
+
def headers(ia, ib)
|
30
|
+
@ia = ia
|
31
|
+
@ib = ib
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_rowlike(flag)
|
35
|
+
end
|
36
|
+
|
37
|
+
def hb
|
38
|
+
@hb
|
39
|
+
end
|
40
|
+
|
41
|
+
def link(a, b)
|
42
|
+
@map_a2b[a] = b
|
43
|
+
@map_b2a[b] = a
|
44
|
+
@map_count+=1
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_index_columns(unit)
|
48
|
+
if @index_columns.nil?
|
49
|
+
@index_columns = []
|
50
|
+
end
|
51
|
+
@index_columns << unit
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_index_columns
|
55
|
+
@index_columns
|
56
|
+
end
|
57
|
+
|
58
|
+
def a2b(a)
|
59
|
+
@map_a2b[a]
|
60
|
+
end
|
61
|
+
|
62
|
+
def b2a(b)
|
63
|
+
@map_b2a[b]
|
64
|
+
end
|
65
|
+
|
66
|
+
def count
|
67
|
+
@map_count
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
map_a2b.to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_order
|
75
|
+
if @order_cache
|
76
|
+
if @reference
|
77
|
+
if !@order_cache_has_reference
|
78
|
+
@order_cache = nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
@order_cache = to_order_3 if @order_cache.nil?
|
83
|
+
@order_cache_has_reference = true if reference
|
84
|
+
@order_cache
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_source
|
88
|
+
@ta
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_target
|
92
|
+
@tb
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_source_header
|
96
|
+
@ia
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_target_header
|
100
|
+
@ib
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_order_3
|
104
|
+
ref = @reference
|
105
|
+
if ref.nil?
|
106
|
+
ref = Coopy::Alignment.new
|
107
|
+
ref.range(@ha,@ha)
|
108
|
+
ref.tables(@ta,@ta)
|
109
|
+
(0...@ha).each do |i|
|
110
|
+
ref.link(i,i)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
order = Coopy::Ordering.new
|
114
|
+
if @reference.nil?
|
115
|
+
order.ignore_parent
|
116
|
+
end
|
117
|
+
xp = 0
|
118
|
+
xl = 0
|
119
|
+
xr = 0
|
120
|
+
hp = @ha
|
121
|
+
hl = ref.hb
|
122
|
+
hr = @hb
|
123
|
+
vp = {}
|
124
|
+
vl = {}
|
125
|
+
vr = {}
|
126
|
+
(0...hp).each { |i| vp[i] = i }
|
127
|
+
(0...hl).each { |i| vl[i] = i }
|
128
|
+
(0...hr).each { |i| vr[i] = i }
|
129
|
+
ct_vp = hp
|
130
|
+
ct_vl = hl
|
131
|
+
ct_vr = hr
|
132
|
+
prev = -1
|
133
|
+
ct = 0
|
134
|
+
max_ct = (hp+hl+hr)*10
|
135
|
+
while (ct_vp>0 ||
|
136
|
+
ct_vl>0 ||
|
137
|
+
ct_vr>0) do
|
138
|
+
ct+=1
|
139
|
+
if ct>max_ct
|
140
|
+
puts("Ordering took too long, something went wrong")
|
141
|
+
break
|
142
|
+
end
|
143
|
+
xp = 0 if (xp>=hp)
|
144
|
+
xl = 0 if (xl>=hl)
|
145
|
+
xr = 0 if (xr>=hr)
|
146
|
+
if xp<hp && ct_vp>0
|
147
|
+
if a2b(xp).nil? && ref.a2b(xp).nil?
|
148
|
+
if vp.has_key?(xp)
|
149
|
+
order.add(-1,-1,xp)
|
150
|
+
prev = xp
|
151
|
+
vp.remove(xp)
|
152
|
+
ct_vp-=1
|
153
|
+
end
|
154
|
+
xp+=1
|
155
|
+
next
|
156
|
+
end
|
157
|
+
end
|
158
|
+
zl = nil
|
159
|
+
zr = nil
|
160
|
+
if xl<hl && ct_vl>0
|
161
|
+
zl = ref.b2a(xl)
|
162
|
+
if zl.nil?
|
163
|
+
if vl.has_key?(xl)
|
164
|
+
order.add(xl,-1,-1)
|
165
|
+
vl.remove(xl)
|
166
|
+
ct_vl-=1
|
167
|
+
end
|
168
|
+
xl+=1
|
169
|
+
next
|
170
|
+
end
|
171
|
+
end
|
172
|
+
if xr<hr && ct_vr>0
|
173
|
+
zr = b2a(xr)
|
174
|
+
if zr.nil?
|
175
|
+
if vr.has_key?(xr)
|
176
|
+
order.add(-1,xr,-1)
|
177
|
+
vr.delete(xr)
|
178
|
+
ct_vr-=1
|
179
|
+
end
|
180
|
+
xr+=1
|
181
|
+
next
|
182
|
+
end
|
183
|
+
end
|
184
|
+
if zl
|
185
|
+
if a2b(zl).nil?
|
186
|
+
# row deleted in remote
|
187
|
+
if vl.has_key?(xl)
|
188
|
+
order.add(xl,-1,zl)
|
189
|
+
prev = zl
|
190
|
+
vp.delete(zl)
|
191
|
+
ct_vp-=1
|
192
|
+
vl.delete(xl)
|
193
|
+
ct_vl-=1
|
194
|
+
xp = zl+1
|
195
|
+
end
|
196
|
+
xl+=1
|
197
|
+
next
|
198
|
+
end
|
199
|
+
end
|
200
|
+
if zr
|
201
|
+
if ref.a2b(zr).nil?
|
202
|
+
# row deleted in local
|
203
|
+
if vr.has_key?(xr)
|
204
|
+
order.add(-1,xr,zr)
|
205
|
+
prev = zr
|
206
|
+
vp.remove(zr)
|
207
|
+
ct_vp-=1
|
208
|
+
vr.remove(xr)
|
209
|
+
ct_vr-=1
|
210
|
+
xp = zr+1
|
211
|
+
end
|
212
|
+
xr+=1
|
213
|
+
next
|
214
|
+
end
|
215
|
+
end
|
216
|
+
if zl && zr && a2b(zl) && ref.a2b(zr)
|
217
|
+
# we have a choice of order
|
218
|
+
# local thinks zl should come next
|
219
|
+
# remote thinks zr should come next
|
220
|
+
if zl==prev+1 || zr!=prev+1
|
221
|
+
if vr.has_key?(xr)
|
222
|
+
order.add(ref.a2b(zr),xr,zr)
|
223
|
+
prev = zr
|
224
|
+
vp.delete(zr)
|
225
|
+
ct_vp-=1
|
226
|
+
vl.delete(ref.a2b(zr))
|
227
|
+
ct_vl-=1
|
228
|
+
vr.delete(xr)
|
229
|
+
ct_vr-=1
|
230
|
+
xp = zr+1
|
231
|
+
xl = ref.a2b(zr)+1
|
232
|
+
end
|
233
|
+
xr+=1
|
234
|
+
next
|
235
|
+
else
|
236
|
+
if vl.has_key?(xl)
|
237
|
+
order.add(xl,a2b(zl),zl)
|
238
|
+
prev = zl
|
239
|
+
vp.remove(zl)
|
240
|
+
ct_vp-=1
|
241
|
+
vl.remove(xl)
|
242
|
+
ct_vl-=1
|
243
|
+
vr.remove(a2b(zl))
|
244
|
+
ct_vr-=1
|
245
|
+
xp = zl+1
|
246
|
+
xr = a2b(zl)+1
|
247
|
+
end
|
248
|
+
xl+=1
|
249
|
+
next
|
250
|
+
end
|
251
|
+
end
|
252
|
+
xp+=1
|
253
|
+
xl+=1
|
254
|
+
xr+=1
|
255
|
+
end
|
256
|
+
return order
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
end
|