coopy 0.6.4.1 → 1.0.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.
- 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
|
+
[](http://jenkins.theodi.org/job/coopy-ruby-master/)
|
4
|
+
[](https://gemnasium.com/theodi/coopy-ruby)
|
5
|
+
[](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
|