redis-diff_match_patch 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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/LICENSE +19 -0
- data/README.md +75 -0
- data/Rakefile +11 -0
- data/lib/bin_dec_hex.lua +542 -0
- data/lib/diff_match_patch-diff.lua +2283 -0
- data/lib/diff_match_patch-merge.lua +2364 -0
- data/lib/diff_match_patch-patch.lua +2363 -0
- data/lib/diff_match_patch.lua +2195 -0
- data/lib/redis-diff_match_patch.rb +50 -0
- data/redis-diff_match_patch.gemspec +23 -0
- data/test/redis-diff_match_patch_test.rb +142 -0
- metadata +88 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
require "redis"
|
2
|
+
require "digest/sha1"
|
3
|
+
|
4
|
+
class Redis
|
5
|
+
|
6
|
+
class DiffMatchPatch
|
7
|
+
|
8
|
+
attr_reader :redis
|
9
|
+
|
10
|
+
VERSION = "1.0.0"
|
11
|
+
|
12
|
+
RESOURCE_DIR = File.dirname(__FILE__)
|
13
|
+
DIFF_SCRIPT = File.read File.join(RESOURCE_DIR, "diff_match_patch-diff.lua")
|
14
|
+
DIFF_SHA1 = Digest::SHA1.hexdigest DIFF_SCRIPT
|
15
|
+
PATCH_SCRIPT = File.read File.join(RESOURCE_DIR, "diff_match_patch-patch.lua")
|
16
|
+
PATCH_SHA1 = Digest::SHA1.hexdigest PATCH_SCRIPT
|
17
|
+
MERGE_SCRIPT = File.read File.join(RESOURCE_DIR, "diff_match_patch-merge.lua")
|
18
|
+
MERGE_SHA1 = Digest::SHA1.hexdigest MERGE_SCRIPT
|
19
|
+
|
20
|
+
def initialize redis = Redis.new
|
21
|
+
@redis = redis
|
22
|
+
end
|
23
|
+
|
24
|
+
def diff src_key, dst_key, patch_key = nil
|
25
|
+
exec DIFF_SCRIPT, DIFF_SHA1, [ src_key, dst_key, patch_key ]
|
26
|
+
end
|
27
|
+
|
28
|
+
def patch src_key, patch_key, dst_key = nil
|
29
|
+
exec PATCH_SCRIPT, PATCH_SHA1, [ src_key, patch_key, dst_key ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def merge ancestor_key, key1, key2, result_key = nil
|
33
|
+
exec MERGE_SCRIPT, MERGE_SHA1, [ ancestor_key, key1, key2, result_key ]
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def exec script, sha1, args
|
39
|
+
@redis.evalsha sha1, args.count, *args
|
40
|
+
rescue Exception => e
|
41
|
+
if e.message =~ /NOSCRIPT/
|
42
|
+
@redis.eval script, args.count, *args
|
43
|
+
else
|
44
|
+
raise e
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "redis-diff_match_patch"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "redis-diff_match_patch"
|
7
|
+
s.version = Redis::DiffMatchPatch::VERSION
|
8
|
+
s.authors = ["Alex McHale"]
|
9
|
+
s.email = ["alex@anticlever.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A Ruby library for computing diff-match-patch on Redis servers.}
|
12
|
+
s.description = %q{This library will allow you to perform atomic diffs, patches and merges on Redis strings.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "redis-diff_match_patch"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "redis"
|
22
|
+
s.add_development_dependency "turn"
|
23
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require "turn"
|
2
|
+
require "minitest/autorun"
|
3
|
+
require "turn/autorun"
|
4
|
+
|
5
|
+
Turn.config do |c|
|
6
|
+
c.format = :pretty
|
7
|
+
c.trace = nil
|
8
|
+
c.natural = true
|
9
|
+
c.ansi = true
|
10
|
+
end
|
11
|
+
|
12
|
+
class Redis
|
13
|
+
|
14
|
+
class TestDiffMatchPatch < MiniTest::Unit::TestCase
|
15
|
+
|
16
|
+
def setup
|
17
|
+
@redis = Redis.new
|
18
|
+
@dmp = DiffMatchPatch.new @redis
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
@autodel.each { |k| @redis.del k } if @autodel
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_simple_diff_patch_cycle
|
26
|
+
set :doc1, "hello world"
|
27
|
+
set :doc2, "Howdy, world!"
|
28
|
+
|
29
|
+
expected_patch = <<-EXPECTED_PATCH.gsub(/^ {8}/, "")
|
30
|
+
@@ -1,11 +1,13 @@
|
31
|
+
-hello
|
32
|
+
+Howdy,
|
33
|
+
world
|
34
|
+
+!
|
35
|
+
EXPECTED_PATCH
|
36
|
+
|
37
|
+
@dmp.diff k(:doc1), k(:doc2), k(:diff)
|
38
|
+
assert_equal expected_patch, get(:diff)
|
39
|
+
|
40
|
+
@dmp.patch k(:doc1), k(:diff), k(:result)
|
41
|
+
assert_equal "Howdy, world!", get(:result)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_complex_diff_patch_cycle
|
45
|
+
set :doc, "hello world"
|
46
|
+
set :doc1, "Howdy, world"
|
47
|
+
set :doc2, "hello my friends!"
|
48
|
+
|
49
|
+
@dmp.diff k(:doc), k(:doc1), k(:diff1)
|
50
|
+
@dmp.diff k(:doc), k(:doc2), k(:diff2)
|
51
|
+
|
52
|
+
@dmp.patch k(:doc), k(:diff1), k(:result)
|
53
|
+
@dmp.patch k(:result), k(:diff2), k(:result)
|
54
|
+
|
55
|
+
assert_equal "Howdy, my friends!", get(:result)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_merge_cycle
|
59
|
+
set :doc, "hello world"
|
60
|
+
set :doc1, "Howdy, world"
|
61
|
+
set :doc2, "hello my friends!"
|
62
|
+
|
63
|
+
@dmp.merge k(:doc), k(:doc1), k(:doc2), k(:result)
|
64
|
+
|
65
|
+
assert_equal "Howdy, my friends!", get(:result)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_diff_without_destination_key
|
69
|
+
@redis.set k(:doc1), "My name is Alex."
|
70
|
+
@redis.set k(:doc2), "Your name is Bob!"
|
71
|
+
|
72
|
+
expected = <<-EXPECTED_PATCH.gsub(/^ {8}/, "")
|
73
|
+
@@ -1,6 +1,8 @@
|
74
|
+
-My
|
75
|
+
+Your
|
76
|
+
nam
|
77
|
+
@@ -10,9 +10,8 @@
|
78
|
+
is
|
79
|
+
-Alex.
|
80
|
+
+Bob!
|
81
|
+
EXPECTED_PATCH
|
82
|
+
|
83
|
+
actual = @dmp.diff k(:doc1), k(:doc2)
|
84
|
+
|
85
|
+
assert_equal expected, actual
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_patch_without_destination_key
|
89
|
+
set :doc, "My name is Alex."
|
90
|
+
|
91
|
+
set :diff, <<-PATCH.gsub(/^ {8}/, "")
|
92
|
+
@@ -1,6 +1,8 @@
|
93
|
+
-My
|
94
|
+
+Your
|
95
|
+
nam
|
96
|
+
@@ -10,9 +10,8 @@
|
97
|
+
is
|
98
|
+
-Alex.
|
99
|
+
+Bob!
|
100
|
+
PATCH
|
101
|
+
|
102
|
+
result = @dmp.patch k(:doc), k(:diff)
|
103
|
+
|
104
|
+
assert_equal "Your name is Bob!", result
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_merge_without_destination_key
|
108
|
+
set :doc, "Page One\nI'd like to tell you a story.\nThen end."
|
109
|
+
set :doc1, "Page Two\nI'd like to tell you a wonderful story.\nThen end."
|
110
|
+
set :doc2, "Page One\nI'm about to tell you a story.\nThe end, goodbye!"
|
111
|
+
|
112
|
+
expected = "Page Two\nI'm about to tell you a wonderful story.\nThe end, goodbye!"
|
113
|
+
actual = @dmp.merge k(:doc), k(:doc1), k(:doc2)
|
114
|
+
|
115
|
+
assert_equal expected, actual
|
116
|
+
end
|
117
|
+
|
118
|
+
protected
|
119
|
+
|
120
|
+
def k key
|
121
|
+
key = "test-diff-match-patch:#{key}"
|
122
|
+
|
123
|
+
@autodel ||= []
|
124
|
+
@autodel.push key
|
125
|
+
@autodel.uniq!
|
126
|
+
|
127
|
+
key
|
128
|
+
end
|
129
|
+
|
130
|
+
def set key, value
|
131
|
+
@redis.set k(key), value
|
132
|
+
|
133
|
+
value
|
134
|
+
end
|
135
|
+
|
136
|
+
def get key
|
137
|
+
@redis.get k(key)
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redis-diff_match_patch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alex McHale
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: redis
|
16
|
+
requirement: &70198342574300 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70198342574300
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: turn
|
27
|
+
requirement: &70198342573880 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70198342573880
|
36
|
+
description: This library will allow you to perform atomic diffs, patches and merges
|
37
|
+
on Redis strings.
|
38
|
+
email:
|
39
|
+
- alex@anticlever.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- LICENSE
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- lib/bin_dec_hex.lua
|
50
|
+
- lib/diff_match_patch-diff.lua
|
51
|
+
- lib/diff_match_patch-merge.lua
|
52
|
+
- lib/diff_match_patch-patch.lua
|
53
|
+
- lib/diff_match_patch.lua
|
54
|
+
- lib/redis-diff_match_patch.rb
|
55
|
+
- redis-diff_match_patch.gemspec
|
56
|
+
- test/redis-diff_match_patch_test.rb
|
57
|
+
homepage: ''
|
58
|
+
licenses: []
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
hash: 1939673064840796369
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
hash: 1939673064840796369
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project: redis-diff_match_patch
|
83
|
+
rubygems_version: 1.8.11
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: A Ruby library for computing diff-match-patch on Redis servers.
|
87
|
+
test_files:
|
88
|
+
- test/redis-diff_match_patch_test.rb
|