has_versions 0.3.0 → 0.4.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/.gitignore +1 -37
- data/Gemfile.lock +17 -45
- data/Rakefile +16 -16
- data/has_versions.gemspec +6 -6
- data/lib/has_versions/apply/simple.rb +1 -1
- data/lib/has_versions/attributes.rb +2 -26
- data/lib/has_versions/configuration.rb +3 -16
- data/lib/has_versions/diff/simple.rb +1 -1
- data/lib/has_versions/merge/always_conflicted.rb +9 -0
- data/lib/has_versions/merge/base.rb +22 -0
- data/lib/has_versions/merge/choose_first.rb +9 -0
- data/lib/has_versions/merge/diff3.rb +66 -0
- data/lib/has_versions/merge/fast_forward.rb +34 -0
- data/lib/has_versions/merge/merge_base.rb +75 -0
- data/lib/has_versions/merge/octopus.rb +42 -0
- data/lib/has_versions/merge/three_way.rb +53 -0
- data/lib/has_versions/merge.rb +16 -45
- data/lib/has_versions/orm/cassandra_object.rb +15 -0
- data/lib/has_versions/reset/simple.rb +2 -2
- data/lib/has_versions/version.rb +1 -1
- data/lib/has_versions/versioned.rb +1 -5
- data/lib/has_versions/versioning_key.rb +0 -1
- data/lib/has_versions.rb +10 -0
- data/spec/has_versions/apply_spec.rb +5 -5
- data/spec/has_versions/configuration_spec.rb +7 -7
- data/spec/has_versions/diff_spec.rb +4 -4
- data/spec/has_versions/merge/diff3_spec.rb +29 -0
- data/spec/has_versions/merge/merge_base_spec.rb +61 -0
- data/spec/has_versions/merge/octopus_spec.rb +74 -0
- data/spec/has_versions/merge/three_way_spec.rb +57 -0
- data/spec/has_versions/reset_spec.rb +1 -2
- data/spec/has_versions/stage_spec.rb +14 -15
- data/spec/has_versions/versioned_spec.rb +4 -4
- data/spec/has_versions/versioning_key_spec.rb +1 -1
- data/spec/spec_helper.rb +7 -8
- data/spec/support/matchers/be_a_uuid.rb +0 -1
- data/spec/support/version.rb +10 -0
- metadata +34 -69
- data/lib/has_versions/merge/stupid.rb +0 -44
- data/lib/has_versions/stage.rb +0 -121
- data/spec/has_versions/merge_spec.rb +0 -67
- data/spec/support/matchers/have_key.rb +0 -25
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has_versions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-10-10 00:00:00.000000000Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: i18n
|
17
|
-
requirement: &
|
16
|
+
requirement: &70120472609720 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -22,21 +21,21 @@ dependencies:
|
|
22
21
|
version: '0'
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *70120472609720
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
26
|
name: activesupport
|
28
|
-
requirement: &
|
27
|
+
requirement: &70120472608780 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
30
|
- - ~>
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
version: '3'
|
32
|
+
version: '3.0'
|
34
33
|
type: :runtime
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *70120472608780
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
37
|
name: simple_uuid
|
39
|
-
requirement: &
|
38
|
+
requirement: &70120472607900 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
40
|
requirements:
|
42
41
|
- - ! '>='
|
@@ -44,21 +43,21 @@ dependencies:
|
|
44
43
|
version: '0'
|
45
44
|
type: :runtime
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
46
|
+
version_requirements: *70120472607900
|
48
47
|
- !ruby/object:Gem::Dependency
|
49
48
|
name: rspec
|
50
|
-
requirement: &
|
49
|
+
requirement: &70120472607200 !ruby/object:Gem::Requirement
|
51
50
|
none: false
|
52
51
|
requirements:
|
53
52
|
- - ~>
|
54
53
|
- !ruby/object:Gem::Version
|
55
|
-
version: '2'
|
54
|
+
version: '2.0'
|
56
55
|
type: :development
|
57
56
|
prerelease: false
|
58
|
-
version_requirements: *
|
57
|
+
version_requirements: *70120472607200
|
59
58
|
- !ruby/object:Gem::Dependency
|
60
59
|
name: yard
|
61
|
-
requirement: &
|
60
|
+
requirement: &70120472606420 !ruby/object:Gem::Requirement
|
62
61
|
none: false
|
63
62
|
requirements:
|
64
63
|
- - ~>
|
@@ -66,21 +65,10 @@ dependencies:
|
|
66
65
|
version: 0.6.0
|
67
66
|
type: :development
|
68
67
|
prerelease: false
|
69
|
-
version_requirements: *
|
70
|
-
- !ruby/object:Gem::Dependency
|
71
|
-
name: cucumber
|
72
|
-
requirement: &17218360 !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ! '>='
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0'
|
78
|
-
type: :development
|
79
|
-
prerelease: false
|
80
|
-
version_requirements: *17218360
|
68
|
+
version_requirements: *70120472606420
|
81
69
|
- !ruby/object:Gem::Dependency
|
82
70
|
name: bundler
|
83
|
-
requirement: &
|
71
|
+
requirement: &70120472605360 !ruby/object:Gem::Requirement
|
84
72
|
none: false
|
85
73
|
requirements:
|
86
74
|
- - ~>
|
@@ -88,40 +76,7 @@ dependencies:
|
|
88
76
|
version: 1.0.0
|
89
77
|
type: :development
|
90
78
|
prerelease: false
|
91
|
-
version_requirements: *
|
92
|
-
- !ruby/object:Gem::Dependency
|
93
|
-
name: simplecov
|
94
|
-
requirement: &17217060 !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
|
-
requirements:
|
97
|
-
- - ! '>='
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version: 0.3.8
|
100
|
-
type: :development
|
101
|
-
prerelease: false
|
102
|
-
version_requirements: *17217060
|
103
|
-
- !ruby/object:Gem::Dependency
|
104
|
-
name: reek
|
105
|
-
requirement: &17216340 !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
|
-
requirements:
|
108
|
-
- - ~>
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: 1.2.8
|
111
|
-
type: :development
|
112
|
-
prerelease: false
|
113
|
-
version_requirements: *17216340
|
114
|
-
- !ruby/object:Gem::Dependency
|
115
|
-
name: roodi
|
116
|
-
requirement: &17215620 !ruby/object:Gem::Requirement
|
117
|
-
none: false
|
118
|
-
requirements:
|
119
|
-
- - ~>
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
version: 2.1.0
|
122
|
-
type: :development
|
123
|
-
prerelease: false
|
124
|
-
version_requirements: *17215620
|
79
|
+
version_requirements: *70120472605360
|
125
80
|
description: ActiveModel versioning
|
126
81
|
email:
|
127
82
|
- grantr@gmail.com
|
@@ -152,10 +107,17 @@ files:
|
|
152
107
|
- lib/has_versions/diff.rb
|
153
108
|
- lib/has_versions/diff/simple.rb
|
154
109
|
- lib/has_versions/merge.rb
|
155
|
-
- lib/has_versions/merge/
|
110
|
+
- lib/has_versions/merge/always_conflicted.rb
|
111
|
+
- lib/has_versions/merge/base.rb
|
112
|
+
- lib/has_versions/merge/choose_first.rb
|
113
|
+
- lib/has_versions/merge/diff3.rb
|
114
|
+
- lib/has_versions/merge/fast_forward.rb
|
115
|
+
- lib/has_versions/merge/merge_base.rb
|
116
|
+
- lib/has_versions/merge/octopus.rb
|
117
|
+
- lib/has_versions/merge/three_way.rb
|
118
|
+
- lib/has_versions/orm/cassandra_object.rb
|
156
119
|
- lib/has_versions/reset.rb
|
157
120
|
- lib/has_versions/reset/simple.rb
|
158
|
-
- lib/has_versions/stage.rb
|
159
121
|
- lib/has_versions/version.rb
|
160
122
|
- lib/has_versions/versioned.rb
|
161
123
|
- lib/has_versions/versioning_key.rb
|
@@ -163,16 +125,17 @@ files:
|
|
163
125
|
- spec/has_versions/apply_spec.rb
|
164
126
|
- spec/has_versions/configuration_spec.rb
|
165
127
|
- spec/has_versions/diff_spec.rb
|
166
|
-
- spec/has_versions/
|
128
|
+
- spec/has_versions/merge/diff3_spec.rb
|
129
|
+
- spec/has_versions/merge/merge_base_spec.rb
|
130
|
+
- spec/has_versions/merge/octopus_spec.rb
|
131
|
+
- spec/has_versions/merge/three_way_spec.rb
|
167
132
|
- spec/has_versions/reset_spec.rb
|
168
133
|
- spec/has_versions/stage_spec.rb
|
169
134
|
- spec/has_versions/versioned_spec.rb
|
170
135
|
- spec/has_versions/versioning_key_spec.rb
|
171
136
|
- spec/spec_helper.rb
|
172
137
|
- spec/support/matchers/be_a_uuid.rb
|
173
|
-
- spec/support/matchers/have_key.rb
|
174
138
|
- spec/support/version.rb
|
175
|
-
has_rdoc: true
|
176
139
|
homepage: ''
|
177
140
|
licenses:
|
178
141
|
- MIT
|
@@ -194,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
157
|
version: '0'
|
195
158
|
requirements: []
|
196
159
|
rubyforge_project: has_versions
|
197
|
-
rubygems_version: 1.
|
160
|
+
rubygems_version: 1.8.10
|
198
161
|
signing_key:
|
199
162
|
specification_version: 3
|
200
163
|
summary: ActiveModel versioning
|
@@ -205,12 +168,14 @@ test_files:
|
|
205
168
|
- spec/has_versions/apply_spec.rb
|
206
169
|
- spec/has_versions/configuration_spec.rb
|
207
170
|
- spec/has_versions/diff_spec.rb
|
208
|
-
- spec/has_versions/
|
171
|
+
- spec/has_versions/merge/diff3_spec.rb
|
172
|
+
- spec/has_versions/merge/merge_base_spec.rb
|
173
|
+
- spec/has_versions/merge/octopus_spec.rb
|
174
|
+
- spec/has_versions/merge/three_way_spec.rb
|
209
175
|
- spec/has_versions/reset_spec.rb
|
210
176
|
- spec/has_versions/stage_spec.rb
|
211
177
|
- spec/has_versions/versioned_spec.rb
|
212
178
|
- spec/has_versions/versioning_key_spec.rb
|
213
179
|
- spec/spec_helper.rb
|
214
180
|
- spec/support/matchers/be_a_uuid.rb
|
215
|
-
- spec/support/matchers/have_key.rb
|
216
181
|
- spec/support/version.rb
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module HasVersions
|
2
|
-
module Merge
|
3
|
-
|
4
|
-
# takes a list of versions and attempts to merge them with the current version.
|
5
|
-
# returns the merged version if successful
|
6
|
-
# raises MergeConflict if failed
|
7
|
-
#
|
8
|
-
# Doesn't attempt to determine common ancestry. The merge base is always the current version (self).
|
9
|
-
# Since there is no ancestry, conflict resolution is conservative. Any conflicting values generate a conflict.
|
10
|
-
#
|
11
|
-
# In general merging more than 1 version will generate a conflict.
|
12
|
-
module Stupid
|
13
|
-
include Diff3
|
14
|
-
|
15
|
-
def merge(*versions)
|
16
|
-
merged_version = self.class.new
|
17
|
-
merged_version.snapshot = snapshot.dup
|
18
|
-
|
19
|
-
# get the full list of attributes in each version and the merge base (self)
|
20
|
-
attributes = (versions.collect { |v| v.snapshot.keys }.flatten + snapshot.keys).uniq
|
21
|
-
conflicts = HashWithIndifferentAccess.new
|
22
|
-
|
23
|
-
# do 3-way merge on each attribute
|
24
|
-
attributes.each do |key|
|
25
|
-
theirs = versions.collect { |v| v.snapshot[key] }
|
26
|
-
clean, result = diff3(snapshot[key], snapshot[key], *theirs)
|
27
|
-
|
28
|
-
if clean
|
29
|
-
puts "clean: #{result.inspect}"
|
30
|
-
merged_version.snapshot[key] = result
|
31
|
-
else
|
32
|
-
conflicts[key] = result
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# raise if conflicts is not empty
|
37
|
-
raise MergeConflict.new(conflicts, merged_version), conflicts.inspect unless conflicts.empty?
|
38
|
-
merged_version
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
data/lib/has_versions/stage.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
#TODO this should move to a contrib gem
|
2
|
-
module HasVersions
|
3
|
-
module Stage
|
4
|
-
# stage versions onto an object, returning true or false if there are conflicts.
|
5
|
-
# extends the object and each versioned attribute with methods to retrieve status, conflicts, and original value.
|
6
|
-
# extends the object with a resolution and conflicted/modified attribute lists
|
7
|
-
#
|
8
|
-
#TODO should this be part of the plugin?
|
9
|
-
|
10
|
-
def stage(*versions)
|
11
|
-
original = to_version
|
12
|
-
|
13
|
-
# try merging
|
14
|
-
begin
|
15
|
-
merge_result = original.merge(*versions)
|
16
|
-
conflicts = HashWithIndifferentAccess.new
|
17
|
-
# if merge fails, get the conflicts and result
|
18
|
-
rescue MergeConflict => e
|
19
|
-
conflicts = e.conflicts
|
20
|
-
merge_result = e.result
|
21
|
-
end
|
22
|
-
|
23
|
-
reset!(merge_result)
|
24
|
-
|
25
|
-
stage_extend_self(versions, conflicts, original, merge_result)
|
26
|
-
stage_extend_attributes(conflicts, original)
|
27
|
-
|
28
|
-
conflicts.empty?
|
29
|
-
end
|
30
|
-
# devang also wants an api that is similar to the old one, with pending objects, and old values in the attributes.
|
31
|
-
# we can implement something that attaches a non-updated object in pending, with all the old apis
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def stage_extend_self(staged, conflicts, original, merge_result)
|
36
|
-
# extend self with StagedAttribute and set conflicts and original
|
37
|
-
self.extend(StagedAttribute)
|
38
|
-
self.conflicts = conflicts
|
39
|
-
self.original = self.class.new.reset!(original) #TODO should this be a clone or new? should it inherit the key or id or other attributes?
|
40
|
-
|
41
|
-
# extend self with Staged and set the proper values
|
42
|
-
self.extend(Staged)
|
43
|
-
self.staged = staged
|
44
|
-
self.resolution = merge_result
|
45
|
-
# modified attributes is the conflicted keys plus the modified keys
|
46
|
-
self.modified_attributes = (conflicts.keys + original.diff(merge_result).keys).uniq
|
47
|
-
end
|
48
|
-
|
49
|
-
def stage_extend_attributes(conflicts, original)
|
50
|
-
# for each attribute, extend with StagedAttribute and set proper values
|
51
|
-
versioned_attributes.each do |key, value|
|
52
|
-
v.extend(StagedAttribute)
|
53
|
-
v.conflicts = conflicts[key] || []
|
54
|
-
v.original = original.snapshot[key]
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
# included in attributes of staged objects
|
61
|
-
module StagedAttribute
|
62
|
-
|
63
|
-
def conflicted?
|
64
|
-
!@conflicts.empty?
|
65
|
-
end
|
66
|
-
|
67
|
-
def modified?
|
68
|
-
@original != self
|
69
|
-
end
|
70
|
-
|
71
|
-
def conflicts
|
72
|
-
@conflicts
|
73
|
-
end
|
74
|
-
|
75
|
-
def conflicts=(conflicts)
|
76
|
-
@conflicts = conflicts
|
77
|
-
end
|
78
|
-
|
79
|
-
def original
|
80
|
-
@original
|
81
|
-
end
|
82
|
-
|
83
|
-
def original=(original)
|
84
|
-
@original = original
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# included in staged objects
|
89
|
-
# TODO maybe this should be included in the class up front
|
90
|
-
module Staged
|
91
|
-
|
92
|
-
def staged
|
93
|
-
@staged
|
94
|
-
end
|
95
|
-
|
96
|
-
def staged=(staged)
|
97
|
-
@staged = staged
|
98
|
-
end
|
99
|
-
|
100
|
-
def resolution
|
101
|
-
@resolution
|
102
|
-
end
|
103
|
-
|
104
|
-
def resolution=(resolution)
|
105
|
-
@resolution = resolution
|
106
|
-
end
|
107
|
-
|
108
|
-
def modified_attributes
|
109
|
-
@modified_attributes
|
110
|
-
end
|
111
|
-
|
112
|
-
def modified_attributes=(modified_attributes)
|
113
|
-
@modified_attributes = modified_attributes
|
114
|
-
end
|
115
|
-
|
116
|
-
def conflicted_attributes
|
117
|
-
@conflicts.keys
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
|
3
|
-
class MergingVersion < Version; end
|
4
|
-
|
5
|
-
describe "Merge" do
|
6
|
-
describe "Diff3" do
|
7
|
-
|
8
|
-
it 'should behave like a 3-way merge' do
|
9
|
-
extend HasVersions::Merge::Diff3
|
10
|
-
|
11
|
-
diff3('A','A','A').should == [true, 'A']
|
12
|
-
diff3('A','B','A').should == [true, 'B']
|
13
|
-
diff3('A','A','B').should == [true, 'B']
|
14
|
-
diff3('B','A','A').should == [true, 'A']
|
15
|
-
diff3('B','A','C').should == [false, ['A', 'C']]
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'should take multiple theirs' do
|
19
|
-
extend HasVersions::Merge::Diff3
|
20
|
-
|
21
|
-
diff3('A','A',*['A','A']).should == [true, 'A']
|
22
|
-
diff3('A','A',*['B','B']).should == [true, 'B']
|
23
|
-
diff3('A','A',*['B','B']).should == [true, 'B']
|
24
|
-
diff3('A','A',*['A','B']).should == [false, ['A','B']]
|
25
|
-
diff3('A','A',*['B','C']).should == [false, ['B','C']]
|
26
|
-
diff3('A','B',*['C','D']).should == [false, ['C','D','B']]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "Stupid" do
|
31
|
-
class MergingVersion
|
32
|
-
include HasVersions::Merge::Stupid
|
33
|
-
end
|
34
|
-
|
35
|
-
let (:foo1) { MergingVersion.new(name: 'foo1') }
|
36
|
-
let (:foo2) { MergingVersion.new(name: 'foo2') }
|
37
|
-
let (:foo3) { MergingVersion.new(name: 'foo3') }
|
38
|
-
let (:socks) { MergingVersion.new(stripey: 'socks') }
|
39
|
-
|
40
|
-
it 'should merge a version into another' do
|
41
|
-
foo1.merge(foo2).snapshot.should have_key(:name).with_value('foo2')
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'should merge non-conflicting versions' # but it doesn't, because it can't merge more than one version (when ours == base)
|
45
|
-
|
46
|
-
it 'should raise when versions conflict' do
|
47
|
-
expect { foo1.merge(foo2, foo3) }.to raise_error(HasVersions::MergeConflict)
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'should put the conflicts in the MergeConflict exception' do
|
51
|
-
begin
|
52
|
-
foo1.merge(foo2, foo3)
|
53
|
-
rescue HasVersions::MergeConflict => e
|
54
|
-
e.conflicts.should have_key(:name).with_value(['foo2', 'foo3'])
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'should put the merge result in the MergeConflict exception' do
|
59
|
-
begin
|
60
|
-
foo1.merge(foo2, foo3)
|
61
|
-
rescue HasVersions::MergeConflict => e
|
62
|
-
e.result.snapshot.should have_key(:name).with_value('foo1')
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'rspec/expectations'
|
2
|
-
|
3
|
-
RSpec::Matchers.define :have_key do |first|
|
4
|
-
match do |actual|
|
5
|
-
if @second
|
6
|
-
actual.has_key?(first) && actual[first] == @second
|
7
|
-
else
|
8
|
-
actual.has_key?(first)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
chain :with_value do |second|
|
13
|
-
@second = second
|
14
|
-
end
|
15
|
-
|
16
|
-
failure_message_for_should do |actual|
|
17
|
-
if @second
|
18
|
-
%(expected #{actual.inspect} to have key "#{first.inspect}" with value #{@second.inspect})
|
19
|
-
else
|
20
|
-
%(expected #{actual.inspect} to have key "#{first.inspect}")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
|