has_versions 0.4.9 → 0.5.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.
Files changed (47) hide show
  1. data/Rakefile +7 -24
  2. data/has_versions.gemspec +5 -6
  3. data/lib/has_versions/attributes.rb +3 -3
  4. data/lib/has_versions/configuration.rb +0 -1
  5. data/lib/has_versions/reset.rb +10 -4
  6. data/lib/has_versions/version_methods/diff.rb +40 -0
  7. data/lib/has_versions/version_methods/log.rb +45 -0
  8. data/lib/has_versions/versioned.rb +9 -12
  9. data/lib/has_versions.rb +8 -9
  10. data/test/has_versions/attributes_test.rb +15 -10
  11. data/test/has_versions/configuration_test.rb +12 -0
  12. data/test/has_versions/reset_test.rb +29 -0
  13. data/test/has_versions/version_methods/diff_test.rb +68 -0
  14. data/test/has_versions/version_methods/log_test.rb +33 -0
  15. data/test/has_versions/versioned_test.rb +27 -0
  16. data/test/helper.rb +6 -0
  17. data/test/support/test_model.rb +21 -0
  18. data/test/support/test_version.rb +15 -0
  19. metadata +24 -96
  20. data/lib/has_versions/apply/simple.rb +0 -34
  21. data/lib/has_versions/apply.rb +0 -9
  22. data/lib/has_versions/diff/simple.rb +0 -27
  23. data/lib/has_versions/diff.rb +0 -7
  24. data/lib/has_versions/merge/always_conflicted.rb +0 -9
  25. data/lib/has_versions/merge/base.rb +0 -22
  26. data/lib/has_versions/merge/choose_first.rb +0 -9
  27. data/lib/has_versions/merge/diff3.rb +0 -66
  28. data/lib/has_versions/merge/fast_forward.rb +0 -34
  29. data/lib/has_versions/merge/merge_base.rb +0 -75
  30. data/lib/has_versions/merge/octopus.rb +0 -42
  31. data/lib/has_versions/merge/three_way.rb +0 -53
  32. data/lib/has_versions/merge.rb +0 -32
  33. data/lib/has_versions/reset/simple.rb +0 -19
  34. data/spec/has_versions/apply_spec.rb +0 -33
  35. data/spec/has_versions/configuration_spec.rb +0 -33
  36. data/spec/has_versions/diff_spec.rb +0 -40
  37. data/spec/has_versions/merge/diff3_spec.rb +0 -29
  38. data/spec/has_versions/merge/merge_base_spec.rb +0 -61
  39. data/spec/has_versions/merge/octopus_spec.rb +0 -74
  40. data/spec/has_versions/merge/three_way_spec.rb +0 -57
  41. data/spec/has_versions/reset_spec.rb +0 -40
  42. data/spec/has_versions/stage_spec.rb +0 -17
  43. data/spec/has_versions/versioned_spec.rb +0 -60
  44. data/spec/spec_helper.rb +0 -17
  45. data/spec/support/matchers/be_a_uuid.rb +0 -7
  46. data/spec/support/version.rb +0 -17
  47. data/test/test_helper.rb +0 -3
@@ -1,33 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Configuration' do
4
- subject do
5
- HasVersions::Configuration.new do
6
- type :baz, expected: Hash
7
- attribute :foo
8
- attribute :bar
9
- attribute :baz, type: :baz
10
- end
11
- end
12
-
13
- it 'should include specified attributes' do
14
- subject.attributes.should include(:foo)
15
- subject.attributes.should include(:bar)
16
- end
17
-
18
- it 'should set options on attributes' do
19
- subject.attributes[:baz].should include(type: :baz)
20
- end
21
-
22
- it 'should allow indifferent access to attributes' do
23
- subject.attributes.should include("foo")
24
- end
25
-
26
- it 'should include specified types' do
27
- subject.types.should include(:baz)
28
- end
29
-
30
- it 'should propagate type options to typed attributes' do
31
- subject.attributes[:baz].should include(expected: Hash)
32
- end
33
- end
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class DiffingVersion < Version; end
4
-
5
- describe DiffingVersion do
6
- class DiffingVersion
7
- include HasVersions::Diff::Simple
8
-
9
- def versioning_decode_value(key, value)
10
- if key == 'name'
11
- value.upcase
12
- else
13
- value
14
- end
15
- end
16
-
17
- def versioning_codable?(name)
18
- true
19
- end
20
- end
21
-
22
- let (:foo) { described_class.new(name: 'foo', argyle: 'socks') }
23
- let (:foo2) { described_class.new(name: 'foo2', stripey: 'socks') }
24
-
25
- it 'should return empty when diffed with itself' do
26
- foo.diff(foo).should be_empty
27
- end
28
-
29
- it 'should return a patch when diffed with another version' do
30
- foo.diff(foo2).should include(name: ['FOO', 'FOO2'])
31
- end
32
-
33
- it 'should include patches for attributes added' do
34
- foo.diff(foo2).should include(stripey: [nil, 'socks'])
35
- end
36
-
37
- it 'should include patches for attributes deleted' do
38
- foo.diff(foo2).should include(argyle: ['socks', nil])
39
- end
40
- end
@@ -1,29 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Merge" do
4
- describe "Diff3" do
5
-
6
- it 'should behave like a 3-way merge' do
7
- extend HasVersions::Merge::Diff3
8
-
9
- diff3('A','A','A').should == [true, 'A']
10
- diff3('A','B','A').should == [true, 'B']
11
- diff3('A','A','B').should == [true, 'B']
12
- diff3('B','A','A').should == [true, 'A']
13
- diff3('B','A','C').should == [false, ['A', 'C']]
14
- end
15
-
16
- it 'should take multiple theirs' do
17
- extend HasVersions::Merge::Diff3
18
-
19
- diff3('A','A',*['A','A']).should == [true, 'A']
20
- diff3('A','A',*['B','B']).should == [true, 'B']
21
- diff3('A','A',*['B','B']).should == [true, 'B']
22
- diff3('A','A',*['A','B']).should == [false, ['A','B']]
23
- diff3('A','A',*['B','C']).should == [false, ['B','C']]
24
- diff3('A','B',*['C','D']).should == [false, ['C','D','B']]
25
- end
26
-
27
- it 'should handle _missing values'
28
- end
29
- end
@@ -1,61 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Merge" do
4
- describe "MergeBase" do
5
- include HasVersions::Merge::MergeBase
6
-
7
- it 'should find no bases for one version' do
8
- v = MergingVersion.new
9
- merge_bases([v]).should == []
10
- end
11
-
12
- it 'should find merge base for a version and its parent' do
13
- p1 = MergingVersion.new
14
- v1 = MergingVersion.new
15
- v1.parents = p1
16
- merge_bases([v1, p1]).should == [p1]
17
- end
18
-
19
- it 'should find merge base for versions with multiple ancestors' do
20
- p1 = MergingVersion.new
21
- p2 = MergingVersion.new
22
- v1 = MergingVersion.new
23
- v1.parents = p1
24
- p1.parents = p2
25
- merge_bases([v1, p1]).should == [p1]
26
- end
27
-
28
- it 'should find merge base for two versions with the same parent' do
29
- p1 = MergingVersion.new
30
- v1 = MergingVersion.new
31
- v2 = MergingVersion.new
32
- v1.parents = v2.parents = [p1]
33
- merge_bases([v1, v2]).should == [p1]
34
- end
35
-
36
- it 'should find merge base for multiple versions with different parents' do
37
- p1, p2, v1, v2, v3 = *5.times.collect { MergingVersion.new }
38
- p2.parents = [p1]
39
- v1.parents = [p1]
40
- v2.parents = [p2]
41
- v3.parents = [v2]
42
- merge_bases([v1, v2, v3]).should == [p1]
43
- end
44
-
45
- it 'should find no base for versions with no common ancestry' do
46
- v1 = MergingVersion.new
47
- v2 = MergingVersion.new
48
- merge_bases([v1, v2]).should == []
49
- end
50
-
51
- #TODO this is broken
52
- it 'should find multiple bases for versions with criss-cross ancestry' do
53
- p1, p2, p3, v1, v2 = *5.times.collect { MergingVersion.new }
54
- p2.parents = [p1]
55
- p3.parents = [p1]
56
- v1.parents = [p3, p2]
57
- v2.parents = [p2, p3]
58
- merge_bases([v1, v2]).should == [p2, p3]
59
- end
60
- end
61
- end
@@ -1,74 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HasVersions::Merge::Octopus do
4
-
5
- it 'should only accept 3+ versions' do
6
- expect { merge([MergingVersion.new]) }.to raise_error(HasVersions::MergeFailed)
7
- expect { merge([MergingVersion.new]*2) }.to raise_error(HasVersions::MergeFailed)
8
- end
9
-
10
- it 'should merge identical versions' do
11
- v1 = MergingVersion.new(name: 'foo1')
12
- v2 = MergingVersion.new(name: 'foo1')
13
- v3 = MergingVersion.new(name: 'foo1')
14
- merge([v1, v2, v3]).resolution.snapshot.should include(name: 'foo1')
15
- end
16
-
17
- it 'should merge many versions' do
18
- v1 = MergingVersion.new(name: 'foo1')
19
- v2 = MergingVersion.new(name: 'foo1')
20
- v3 = MergingVersion.new(name: 'foo1')
21
- v4 = MergingVersion.new(name: 'foo1')
22
- v5 = MergingVersion.new(name: 'foo1')
23
- v6 = MergingVersion.new(name: 'foo1')
24
- merge([v1, v2, v3, v4, v5, v6]).resolution.snapshot.should include(name: 'foo1')
25
- end
26
-
27
- it 'should detect conflicts' do
28
- v1 = MergingVersion.new(name: 'foo1')
29
- v2 = MergingVersion.new(name: 'foo2')
30
- v3 = MergingVersion.new(name: 'foo3')
31
- merge([v1, v2, v3]).conflicts.should include(name: ['foo1', 'foo2', 'foo3'])
32
- end
33
-
34
- it 'should merge ancestors cleanly' do
35
- v1 = MergingVersion.new(name: 'foo1')
36
- v2 = MergingVersion.new(name: 'foo2')
37
- v3 = MergingVersion.new(name: 'foo3')
38
-
39
- v3.parents = v2
40
- v2.parents = v1
41
- merge([v1, v2, v3]).conflicts.should be_empty
42
- merge([v1, v2, v3]).resolution.snapshot.should include(name: 'foo3')
43
- end
44
-
45
- it 'should merge missing attributes' do
46
- v1 = MergingVersion.new(name: 'foo1')
47
- v2 = MergingVersion.new(name: 'foo1', socks: 'stripey')
48
- v3 = MergingVersion.new(hat: 'silly')
49
- merge([v1, v2, v3]).resolution.snapshot.should include(name: 'foo1', socks: 'stripey', hat: 'silly')
50
- end
51
-
52
- it 'should save the partial merge result' do
53
- v1 = MergingVersion.new(name: 'foo1', socks: 'stripey')
54
- v2 = MergingVersion.new(name: 'foo2', socks: 'argyle')
55
- v3 = MergingVersion.new(name: 'foo3', socks: 'argyle')
56
- p1 = MergingVersion.new(name: 'foo', socks: 'argyle')
57
- v1.parents = v2.parents = v3.parents = p1
58
- merge([v1, v2, v3]).conflicts.should include(name: ['foo1', 'foo2', 'foo3'])
59
- merge([v1, v2, v3]).resolution.snapshot.should include(socks: 'stripey')
60
- end
61
-
62
- it 'should set parents' do
63
- v1 = MergingVersion.new(name: 'foo1', socks: 'stripey')
64
- v2 = MergingVersion.new(name: 'foo2', socks: 'argyle')
65
- v3 = MergingVersion.new(name: 'foo3', socks: 'argyle')
66
- merge([v1, v2, v3]).resolution.parents.should == [v1, v2, v3]
67
- end
68
-
69
- def merge(versions, options={})
70
- s = HasVersions::Merge::Octopus.new(versions, options)
71
- s.merge
72
- s
73
- end
74
- end
@@ -1,57 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HasVersions::Merge::ThreeWay do
4
-
5
- it 'should only accept 2 versions' do
6
- expect { merge([MergingVersion.new]) }.to raise_error(HasVersions::MergeFailed)
7
- expect { merge([MergingVersion.new]*3) }.to raise_error(HasVersions::MergeFailed)
8
- end
9
-
10
- it 'should merge identical versions' do
11
- v1 = MergingVersion.new(name: 'foo1')
12
- v2 = MergingVersion.new(name: 'foo1')
13
- merge([v1, v2]).resolution.snapshot.should include(name: 'foo1')
14
- end
15
-
16
- it 'should detect conflicts' do
17
- v1 = MergingVersion.new(name: 'foo1')
18
- v2 = MergingVersion.new(name: 'foo2')
19
- merge([v1, v2]).conflicts.should include(name: ['foo1', 'foo2'])
20
- end
21
-
22
- it 'should merge ancestors cleanly' do
23
- v1 = MergingVersion.new(name: 'foo1')
24
- v2 = MergingVersion.new(name: 'foo2')
25
-
26
- v2.parents = [v1]
27
- merge([v1, v2]).conflicts.should be_empty
28
- merge([v1, v2]).resolution.snapshot.should include(name: 'foo2')
29
- end
30
-
31
- it 'should merge missing attributes' do
32
- v1 = MergingVersion.new(name: 'foo1')
33
- v2 = MergingVersion.new(name: 'foo1', socks: 'stripey')
34
- merge([v1, v2]).resolution.snapshot.should include(name: 'foo1', socks: 'stripey')
35
- end
36
-
37
- it 'should save the partial merge result' do
38
- v1 = MergingVersion.new(name: 'foo1', socks: 'stripey')
39
- v2 = MergingVersion.new(name: 'foo2', socks: 'argyle')
40
- p1 = MergingVersion.new(name: 'foo', socks: 'argyle')
41
- v1.parents = v2.parents = p1
42
- merge([v1, v2]).conflicts.should include(name: ['foo1', 'foo2'])
43
- merge([v1, v2]).resolution.snapshot.should include(socks: 'stripey')
44
- end
45
-
46
- it 'should set parents' do
47
- v1 = MergingVersion.new(name: 'foo1', socks: 'stripey')
48
- v2 = MergingVersion.new(name: 'foo2', socks: 'argyle')
49
- merge([v1, v2]).resolution.parents.should == [v1, v2]
50
- end
51
-
52
- def merge(versions, options={})
53
- s = HasVersions::Merge::ThreeWay.new(versions, options)
54
- s.merge
55
- s
56
- end
57
- end
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class ResetObjectVersion < Version; end
4
-
5
- class ResetObject
6
- include HasVersions::Versioned
7
-
8
- include HasVersions::Reset::Simple
9
-
10
- attr_accessor :name
11
- attr_accessor :set
12
-
13
- has_versions(ResetObjectVersion) do
14
- attribute :name
15
- end
16
- end
17
-
18
- describe "Reset" do
19
- describe "Simple" do
20
- subject do
21
- ResetObject.new.reset!(ResetObjectVersion.new(set: [1,2,3]))
22
- end
23
-
24
- its(:set) { should be_a(Set) }
25
- end
26
-
27
- describe "FromVersion" do
28
- class ResetObject
29
- extend HasVersions::Reset::FromVersion
30
- end
31
-
32
- subject do
33
- ResetObject.from_version(ResetObjectVersion.new(name: 'foo'))
34
- end
35
-
36
- it { should be_a(ResetObject) }
37
-
38
- its(:name) { should == 'foo' }
39
- end
40
- end
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class StagingObjectVersion < Version; end
4
-
5
- # class StagingObject
6
- # include HasVersions::Versioned
7
- # include HasVersions::Stage
8
- #
9
- # attr_accessor :name
10
- #
11
- # has_versions(StagingObjectVersion) do
12
- # attribute :name
13
- # end
14
- # end
15
- #
16
- # describe StagingObject do
17
- # end
@@ -1,60 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class VersionedObject
4
- include HasVersions::Versioned
5
-
6
- attr_accessor :name
7
- attr_accessor :time
8
- attr_accessor :color
9
- end
10
-
11
- class VersionedObjectVersion < Version; end
12
-
13
- describe VersionedObject do
14
- it { should respond_to(:versioning_configuration) }
15
- it { should respond_to(:version_class) }
16
-
17
- it 'should not be versioned' do
18
- described_class.is_versioned?.should be_false
19
- end
20
-
21
- context "configured" do
22
- subject do
23
- described_class.has_versions(VersionedObjectVersion) do
24
- attribute :name
25
- attribute :time
26
- end
27
- described_class.versioned_attribute(:color)
28
-
29
- described_class
30
- end
31
-
32
- it 'should be versioned' do
33
- subject.is_versioned?.should be_true
34
- end
35
-
36
- it 'should have attributes' do
37
- subject.versioning_configuration.attributes.should == ["name", "time", "color"]
38
- end
39
-
40
- its(:version_class) { should be(VersionedObjectVersion) }
41
- its(:versioning_configuration) { should be_a(HasVersions::Configuration) }
42
- end
43
-
44
- describe "configured instance" do
45
- subject do
46
- v = VersionedObject.new
47
- v.name = 'foo'
48
- v.time = Time.parse("1970-01-01 2:43")
49
- v
50
- end
51
-
52
- its(:versioned_attributes) { should include(name: 'foo') }
53
-
54
- its(:to_version) { should be_a(VersionedObjectVersion) }
55
-
56
- it 'should set attributes in to_version' do
57
- subject.to_version.snapshot.should include(name: 'foo')
58
- end
59
- end
60
- end
data/spec/spec_helper.rb DELETED
@@ -1,17 +0,0 @@
1
- # $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- # $LOAD_PATH.unshift(File.dirname(__FILE__))
3
-
4
- # p "#{$LOAD_PATH.inspect}"
5
-
6
- require 'rspec'
7
- require 'has_versions'
8
-
9
- # Requires supporting files with custom matchers and macros, etc,
10
- # in ./support/ and its subdirectories.
11
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each do |f|
12
- require f
13
- end
14
-
15
- RSpec.configure do |config|
16
- config.mock_with :rspec
17
- end
@@ -1,7 +0,0 @@
1
- require 'rspec/expectations'
2
-
3
- RSpec::Matchers.define :be_a_uuid do |expected|
4
- match do |actual|
5
- actual =~ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ # c14ba018-2f15-11e0-9a06-b6e5e5c60f13
6
- end
7
- end
@@ -1,17 +0,0 @@
1
- class Version
2
- attr_accessor :snapshot
3
-
4
- def initialize(snapshot=nil)
5
- @snapshot = (snapshot || {}).with_indifferent_access
6
- end
7
- end
8
-
9
- class MergingVersion < Version
10
- def parents
11
- @parents || []
12
- end
13
-
14
- def parents=(parents)
15
- @parents = Array(parents)
16
- end
17
- end
data/test/test_helper.rb DELETED
@@ -1,3 +0,0 @@
1
- require 'bundler/setup'
2
- require 'minitest/autorun'
3
- Bundler.require