Skip to content

Commit 8f54ac7

Browse files
author
Kevin Paulisse
committed
Initial commit of the Diff object
1 parent 3ac4575 commit 8f54ac7

3 files changed

Lines changed: 256 additions & 0 deletions

File tree

lib/octocatalog-diff/api/v1.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# frozen_string_literal: true
22

3+
require_relative 'v1/catalog'
34
require_relative 'v1/catalog-compile'
45
require_relative 'v1/catalog-diff'
56
require_relative 'v1/config'
7+
require_relative 'v1/diff'
68

79
module OctocatalogDiff
810
module API
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# frozen_string_literal: true
2+
3+
require_relative 'common'
4+
5+
module OctocatalogDiff
6+
module API
7+
module V1
8+
# This class represents a `diff` produced by a catalog-diff operation. This has traditionally
9+
# been stored as an array with:
10+
# [0] Type of change - '+', '-', '!', '~'
11+
# [1] Type, title, and maybe structure, delimited by "\f"
12+
# [2] Content of the "old" catalog
13+
# [3] Content of the "new" catalog
14+
# [4] File and line of the "old" catalog
15+
# [5] File and line of the "new" catalog
16+
# This object seeks to preserve this traditional structure, while providing methods to make it
17+
# easier to deal with.
18+
class Diff
19+
attr_reader :raw
20+
21+
# Constructor: Accepts a diff in the traditional array format and stores it.
22+
# @param raw [Array] Diff in the traditional format
23+
def initialize(raw)
24+
unless raw.is_a?(Array)
25+
raise ArgumentError, 'OctocatalogDiff::API::V1::Diff#initialize expects Array argument'
26+
end
27+
@raw = raw
28+
end
29+
30+
# Public: Retrieve an indexed value from the array
31+
# @return [?] Indexed value
32+
def [](i)
33+
@raw[i]
34+
end
35+
36+
# Public: Get the change type
37+
# @return [String] Change type symbol (~, !, +, -)
38+
def change_type
39+
@raw[0]
40+
end
41+
42+
# Public: Get the change type (English word)
43+
# @return [String] Change type word
44+
def change_type_word
45+
return 'change' if @raw[0] == '!' || @raw[0] == '~'
46+
return 'addition' if @raw[0] == '+'
47+
return 'removal' if @raw[0] == '-'
48+
raise ArgumentError, "No change type corresponds to #{@raw[0].inspect}"
49+
end
50+
51+
# Public: Get the type_title string
52+
# @return [?] Type_title_structure
53+
def type_title
54+
@raw[1]
55+
end
56+
57+
# Public: Get the resource type
58+
# @return [String] Resource type
59+
def type
60+
@raw[1].split(/\f/)[0]
61+
end
62+
63+
# Public: Get the resource title
64+
# @return [String] Resource title
65+
def title
66+
@raw[1].split(/\f/)[1]
67+
end
68+
69+
# Public: Get the structure of the resource as an array
70+
# @return [Array] Structure of resource
71+
def structure
72+
@raw[1].split(/\f/)[2..-1]
73+
end
74+
75+
# Public: Get the "old" value, i.e. "from" catalog
76+
# @return [?] "old" value
77+
def old_value
78+
return nil if @raw[0] == '+'
79+
@raw[2]
80+
end
81+
82+
# Public: Get the "new" value, i.e. "to" catalog
83+
# @return [?] "old" value
84+
def new_value
85+
return nil if @raw[0] == '-'
86+
return @raw[2] if @raw[0] == '+'
87+
@raw[3]
88+
end
89+
90+
# Public: Get the "old" location, i.e. location in the "from" catalog
91+
# @return [Hash] <file:, line:> of resource
92+
def old_location
93+
return nil if @raw[0] == '+'
94+
return @raw[3] if @raw[0] == '-'
95+
@raw[4]
96+
end
97+
98+
# Public: Get the "new" location, i.e. location in the "to" catalog
99+
# @return [Hash] <file:, line:> of resource
100+
def new_location
101+
return @raw[3] if @raw[0] == '+'
102+
return nil if @raw[0] == '-'
103+
@raw[5]
104+
end
105+
106+
# Public: Get the filename from the "old" location
107+
# @return [String] Filename
108+
def old_file
109+
x = old_location
110+
x.nil? ? nil : x['file']
111+
end
112+
113+
# Public: Get the line number from the "old" location
114+
# @return [String] Line number
115+
def old_line
116+
x = old_location
117+
x.nil? ? nil : x['line']
118+
end
119+
120+
# Public: Get the filename from the "new" location
121+
# @return [String] Filename
122+
def new_file
123+
x = new_location
124+
x.nil? ? nil : x['file']
125+
end
126+
127+
# Public: Get the line number from the "new" location
128+
# @return [String] Line number
129+
def new_line
130+
x = new_location
131+
x.nil? ? nil : x['line']
132+
end
133+
end
134+
end
135+
end
136+
end
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# frozen_string_literal: true
2+
3+
require_relative '../../spec_helper'
4+
5+
require OctocatalogDiff::Spec.require_path('/api/v1/diff')
6+
7+
describe OctocatalogDiff::API::V1::Diff do
8+
let(:type_title) { "File\f/etc/foo" }
9+
let(:parameters) { { 'parameters' => { 'owner' => 'root' } } }
10+
let(:tts) { "File\f/etc/foo\fparameters\fcontent" }
11+
12+
let(:loc_1) { { 'file' => '/var/tmp/foo.pp', 'line' => 35 } }
13+
let(:loc_2) { { 'file' => '/var/tmp/foo.pp', 'line' => 12 } }
14+
15+
let(:add_1) { ['+', type_title, parameters] }
16+
let(:add_2) { ['+', type_title, parameters, loc_1] }
17+
18+
let(:del_1) { ['-', type_title, parameters] }
19+
let(:del_2) { ['-', type_title, parameters, loc_1] }
20+
21+
let(:chg_1) { ['~', tts, 'old', 'new'] }
22+
let(:chg_2) { ['~', tts, 'old', 'new', loc_1, loc_2] }
23+
24+
describe '#[]' do
25+
it 'should return expected numeric values from an add/remove array' do
26+
testobj = described_class.new(add_1)
27+
expect(testobj[0]).to eq('+')
28+
expect(testobj[1]).to eq(type_title)
29+
expect(testobj[2]).to eq(parameters)
30+
expect(testobj[3]).to be_nil
31+
end
32+
33+
it 'should return expected numeric values from a change array' do
34+
testobj = described_class.new(chg_2)
35+
expect(testobj[0]).to eq('~')
36+
expect(testobj[1]).to eq(tts)
37+
expect(testobj[2]).to eq('old')
38+
expect(testobj[3]).to eq('new')
39+
expect(testobj[4]).to eq(loc_1)
40+
expect(testobj[5]).to eq(loc_2)
41+
expect(testobj[6]).to be_nil
42+
end
43+
end
44+
45+
describe '#change_type' do
46+
it 'should identify the symbol' do
47+
testobj = described_class.new(chg_2)
48+
expect(testobj.change_type).to eq('~')
49+
end
50+
end
51+
52+
describe '#change_type_word' do
53+
it 'should identify addition' do
54+
testobj = described_class.new(add_1)
55+
expect(testobj.change_type_word).to eq('addition')
56+
end
57+
58+
it 'should identify removal' do
59+
testobj = described_class.new(del_1)
60+
expect(testobj.change_type_word).to eq('removal')
61+
end
62+
63+
it 'should identify change with ~' do
64+
testobj = described_class.new(chg_1)
65+
expect(testobj.change_type_word).to eq('change')
66+
end
67+
68+
it 'should identify change with !' do
69+
x = chg_1.dup
70+
x[0] = '!'
71+
testobj = described_class.new(x)
72+
expect(testobj.change_type_word).to eq('change')
73+
end
74+
75+
it 'should raise ArgumentError for unknown symbol' do
76+
x = chg_1.dup
77+
x[0] = '#'
78+
testobj = described_class.new(x)
79+
expect { testobj.change_type_word }.to raise_error(ArgumentError)
80+
end
81+
end
82+
83+
describe '#type_title' do
84+
end
85+
86+
describe '#type' do
87+
end
88+
89+
describe '#title' do
90+
end
91+
92+
describe '#structure' do
93+
end
94+
95+
describe '#old_value' do
96+
end
97+
98+
describe '#new_value' do
99+
end
100+
101+
describe '#old_location' do
102+
end
103+
104+
describe '#new_location' do
105+
end
106+
107+
describe '#old_file' do
108+
end
109+
110+
describe '#old_line' do
111+
end
112+
113+
describe '#new_file' do
114+
end
115+
116+
describe '#new_line' do
117+
end
118+
end

0 commit comments

Comments
 (0)