unified 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 +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +33 -0
- data/Rakefile +1 -0
- data/lib/unified.rb +8 -0
- data/lib/unified/chunk.rb +88 -0
- data/lib/unified/diff.rb +74 -0
- data/lib/unified/line.rb +21 -0
- data/lib/unified/parser.rb +53 -0
- data/lib/unified/transformer.rb +25 -0
- data/lib/unified/version.rb +3 -0
- data/spec/chunk_spec.rb +134 -0
- data/spec/diff_spec.rb +203 -0
- data/spec/examples/invalid/no_chunk_header.diff +10 -0
- data/spec/examples/invalid/no_content.diff +0 -0
- data/spec/examples/invalid/no_modifications.diff +11 -0
- data/spec/examples/invalid/no_modified_file_header.diff +6 -0
- data/spec/examples/invalid/no_original_file_header.diff +6 -0
- data/spec/examples/valid/.DS_Store +0 -0
- data/spec/examples/valid/commit_revision.diff +5 -0
- data/spec/examples/valid/modified_filename.diff +7 -0
- data/spec/examples/valid/more_additions.diff +7 -0
- data/spec/examples/valid/more_deletions.diff +10 -0
- data/spec/examples/valid/multi_chunk.diff +19 -0
- data/spec/examples/valid/new_file.diff +8 -0
- data/spec/examples/valid/no_newline.diff +29 -0
- data/spec/examples/valid/null_git.diff +8 -0
- data/spec/examples/valid/removed_file.diff +8 -0
- data/spec/examples/valid/simple.diff +11 -0
- data/spec/examples/valid/simple_git.diff +29 -0
- data/spec/line_spec.rb +45 -0
- data/spec/parser_spec.rb +344 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/matchers/parse_matchers.rb +53 -0
- data/spec/transformer_spec.rb +82 -0
- data/unified.gemspec +26 -0
- metadata +173 -0
data/spec/diff_spec.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
require "unified/diff"
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe "Unified::Diff" do
|
5
|
+
|
6
|
+
def lines
|
7
|
+
[" Line 1", "+Line 2", "-Line 3"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def chunk(orig = 1, mod = 1, lines = lines)
|
11
|
+
Unified::Chunk.new(original: orig, modified: mod, lines: lines, section_header: "A header")
|
12
|
+
end
|
13
|
+
|
14
|
+
def diff(lines = lines)
|
15
|
+
Unified::Diff.new original_filename: "Original", modified_filename: "Modified",
|
16
|
+
original_revision: "OrigRev", modified_revision: "ModRev",
|
17
|
+
chunks: [chunk(1, 1, lines), chunk(25, 25, lines), chunk(50, 50, lines)]
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".parse!" do
|
21
|
+
it "parses all valid diff files" do
|
22
|
+
valid_diffs.each do |content|
|
23
|
+
expect { Unified::Diff.parse!(content) }.not_to raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns a Unified::Diff object" do
|
28
|
+
valid_diffs.each do |content|
|
29
|
+
expect(Unified::Diff.parse!(content)).to be_a_kind_of Unified::Diff
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "raises a Unified::ParseError for invalid diffs" do
|
34
|
+
invalid_diffs.each do |content|
|
35
|
+
expect { Unified::Diff.parse!(content) }.to raise_error(Unified::ParseError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "provides a line number and character for invalid diffs" do
|
40
|
+
invalid_diffs.each do |content|
|
41
|
+
begin
|
42
|
+
Unified::Diff.parse!(content)
|
43
|
+
rescue Unified::ParseError => e
|
44
|
+
e.message.should match /line \d+/
|
45
|
+
e.message.should match /char \d+/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#original_filename" do
|
52
|
+
it "returns the correct value" do
|
53
|
+
diff.original_filename.should == "Original"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#modified_filename" do
|
58
|
+
it "returns the correct value" do
|
59
|
+
diff.modified_filename.should == "Modified"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#original_revision" do
|
64
|
+
it "returns the correct value" do
|
65
|
+
diff.original_revision.should == "OrigRev"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#modified_revision" do
|
70
|
+
it "returns the correct value" do
|
71
|
+
diff.modified_revision.should == "ModRev"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#chunks" do
|
76
|
+
it "returns the correct number of chunks" do
|
77
|
+
diff.chunks.size.should == 3
|
78
|
+
end
|
79
|
+
it "returns chunk objects" do
|
80
|
+
diff.chunks.each do |chunk|
|
81
|
+
chunk.should be_a_kind_of Unified::Chunk
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#number_of_added_lines" do
|
87
|
+
it "returns the correct value" do
|
88
|
+
diff.number_of_added_lines.should == 3
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#number_of_deleted_lines" do
|
93
|
+
it "returns the correct value" do
|
94
|
+
diff.number_of_deleted_lines.should == 3
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#number_of_unchanged_lines" do
|
99
|
+
it "returns the correct value" do
|
100
|
+
diff.number_of_unchanged_lines.should == 3
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#number_of_modified_lines" do
|
105
|
+
it "returns the number of additions plus the number of deletions" do
|
106
|
+
diff.number_of_modified_lines.should == 6
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#total_number_of_lines" do
|
111
|
+
it "returns the total number of lines" do
|
112
|
+
diff.total_number_of_lines.should == 9
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#proportion_of_deleted_lines" do
|
117
|
+
it "returns 0 when there are no deleted lines" do
|
118
|
+
lines = [" Line 1", "+Line 2"]
|
119
|
+
diff(lines).proportion_of_deleted_lines.should == 0
|
120
|
+
end
|
121
|
+
|
122
|
+
it "returns 100 when there are only deleted lines" do
|
123
|
+
lines = ["-Line 1", "-Line 2"]
|
124
|
+
diff(lines).proportion_of_deleted_lines.should == 100
|
125
|
+
end
|
126
|
+
|
127
|
+
it "returns 50 when there are equal added and deleted lines" do
|
128
|
+
lines = ["-Line 1", "+Line 2", " Line 3"]
|
129
|
+
diff(lines).proportion_of_deleted_lines.should == 50
|
130
|
+
end
|
131
|
+
|
132
|
+
it "rounds to the nearest integer when the lines are not evenly divisible" do
|
133
|
+
lines = ["-Line 1", "-Line 2", "+Line 3"]
|
134
|
+
diff(lines).proportion_of_deleted_lines.should == 67
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#proportion_of_added_lines" do
|
139
|
+
it "returns 0 when there are no added lines" do
|
140
|
+
lines = [" Line 1", "-Line 2"]
|
141
|
+
diff(lines).proportion_of_added_lines.should == 0
|
142
|
+
end
|
143
|
+
|
144
|
+
it "returns 100 when there are only added lines" do
|
145
|
+
lines = ["+Line 1", "+Line 2"]
|
146
|
+
diff(lines).proportion_of_added_lines.should == 100
|
147
|
+
end
|
148
|
+
|
149
|
+
it "returns 50 when there are equal added and added lines" do
|
150
|
+
lines = ["-Line 1", "+Line 2", " Line 3"]
|
151
|
+
diff(lines).proportion_of_added_lines.should == 50
|
152
|
+
end
|
153
|
+
|
154
|
+
it "rounds to the nearest integer when the lines are not evenly divisible" do
|
155
|
+
lines = ["-Line 1", "-Line 2", "+Line 3"]
|
156
|
+
diff(lines).proportion_of_added_lines.should == 33
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "#each_chunk" do
|
161
|
+
it "iterates once for every chunk" do
|
162
|
+
index = 0
|
163
|
+
diff.each_chunk do
|
164
|
+
index += 1
|
165
|
+
end
|
166
|
+
|
167
|
+
index.should == 3
|
168
|
+
end
|
169
|
+
|
170
|
+
it "passes a chunk to the block" do
|
171
|
+
diff.each_chunk do |chunk|
|
172
|
+
expect(chunk).to be_a_kind_of Unified::Chunk
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#header" do
|
178
|
+
it "returns a valid diff header" do
|
179
|
+
diff.header.should == "--- Original\tOrigRev\n+++ Modified\tModRev"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "#to_s" do
|
184
|
+
it "returns the full diff output" do
|
185
|
+
diff.to_s.should == <<-EOF.strip
|
186
|
+
--- Original\tOrigRev
|
187
|
+
+++ Modified\tModRev
|
188
|
+
@@ -1,2 +1,2 @@ A header
|
189
|
+
Line 1
|
190
|
+
+Line 2
|
191
|
+
-Line 3
|
192
|
+
@@ -25,2 +25,2 @@ A header
|
193
|
+
Line 1
|
194
|
+
+Line 2
|
195
|
+
-Line 3
|
196
|
+
@@ -50,2 +50,2 @@ A header
|
197
|
+
Line 1
|
198
|
+
+Line 2
|
199
|
+
-Line 3
|
200
|
+
EOF
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
File without changes
|
Binary file
|
@@ -0,0 +1,19 @@
|
|
1
|
+
--- multi_chunk 2013-03-24 14:38:43.000000000 +0000
|
2
|
+
+++ multi_chunk 2013-03-24 14:38:52.000000000 +0000
|
3
|
+
@@ -1,7 +1,7 @@
|
4
|
+
Line 1
|
5
|
+
Line 2
|
6
|
+
Line 3
|
7
|
+
-Line4
|
8
|
+
+Line 4
|
9
|
+
Line 5
|
10
|
+
Line 6
|
11
|
+
Line 7
|
12
|
+
@@ -15,6 +15,6 @@
|
13
|
+
Line 15
|
14
|
+
Line 16
|
15
|
+
Line 17
|
16
|
+
-Line18
|
17
|
+
+Line 18
|
18
|
+
Line 19
|
19
|
+
Line 20
|
@@ -0,0 +1,29 @@
|
|
1
|
+
--- a/app/controllers/api/v1/code_reviews_controller.rb
|
2
|
+
+++ b/app/controllers/api/v1/code_reviews_controller.rb
|
3
|
+
@@ -1,24 +1,24 @@
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
class CodeReviewsController < ApplicationController
|
7
|
+
respond_to :json
|
8
|
+
|
9
|
+
def create
|
10
|
+
@review = CodeReview.create raw: params[:content]
|
11
|
+
render :json => {
|
12
|
+
url: code_review_path(@review),
|
13
|
+
expires_at: @review.expires_at
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def show
|
18
|
+
- @review = CodeReview.not_expired.find_by_secure_hash! params[:id]
|
19
|
+
+ @review = CodeReview.not_expired.find_by_token! params[:id]
|
20
|
+
sleep 0.5 and raise ActiveRecord::RecordNotFound if @review.nil?
|
21
|
+
render :json => {
|
22
|
+
content: @review.raw,
|
23
|
+
expires_at: @review.expires_at
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
--- a/app/controllers/api/v1/code_reviews_controller.rb
|
2
|
+
+++ b/app/controllers/api/v1/code_reviews_controller.rb
|
3
|
+
@@ -1,24 +1,24 @@
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
class CodeReviewsController < ApplicationController
|
7
|
+
respond_to :json
|
8
|
+
|
9
|
+
def create
|
10
|
+
@review = CodeReview.create raw: params[:content]
|
11
|
+
render :json => {
|
12
|
+
url: code_review_path(@review),
|
13
|
+
expires_at: @review.expires_at
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def show
|
18
|
+
- @review = CodeReview.not_expired.find_by_secure_hash! params[:id]
|
19
|
+
+ @review = CodeReview.not_expired.find_by_token! params[:id]
|
20
|
+
sleep 0.5 and raise ActiveRecord::RecordNotFound if @review.nil?
|
21
|
+
render :json => {
|
22
|
+
content: @review.raw,
|
23
|
+
expires_at: @review.expires_at
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
data/spec/line_spec.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'unified/line'
|
2
|
+
|
3
|
+
describe "Unified::Line" do
|
4
|
+
it "extends from String" do
|
5
|
+
line = Unified::Line.new "A line"
|
6
|
+
line.should respond_to(:gsub)
|
7
|
+
line.should respond_to(:size)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "additional methods" do
|
11
|
+
let(:addition) { Unified::Line.new "+An addition" }
|
12
|
+
let(:deletion) { Unified::Line.new "-A deletion" }
|
13
|
+
let(:unchanged) { Unified::Line.new " Unchanged" }
|
14
|
+
|
15
|
+
describe "#addition?" do
|
16
|
+
it "is true when a line begins with '+'" do
|
17
|
+
addition.addition?.should be_true
|
18
|
+
end
|
19
|
+
it "is false when a line doesn't begin with '-'" do
|
20
|
+
deletion.addition?.should be_false
|
21
|
+
unchanged.addition?.should be_false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#deletion?" do
|
26
|
+
it "is true when a line begins with '-'" do
|
27
|
+
deletion.deletion?.should be_true
|
28
|
+
end
|
29
|
+
it "is false when a line doesn't begin with '-'" do
|
30
|
+
addition.deletion?.should be_false
|
31
|
+
unchanged.deletion?.should be_false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#unchanged?" do
|
36
|
+
it "is true when a line begins with ' '" do
|
37
|
+
unchanged.unchanged?.should be_true
|
38
|
+
end
|
39
|
+
it "is false when a line doesn't begin with ' '" do
|
40
|
+
addition.unchanged?.should be_false
|
41
|
+
deletion.unchanged?.should be_false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|