txgh 6.0.3 → 6.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/txgh.rb +0 -1
- data/lib/txgh/errors.rb +20 -3
- data/lib/txgh/events.rb +8 -3
- data/lib/txgh/github_api.rb +14 -8
- data/lib/txgh/resource_committer.rb +1 -1
- data/lib/txgh/resource_updater.rb +8 -3
- data/lib/txgh/transifex_api.rb +4 -2
- data/lib/txgh/utils.rb +17 -0
- data/lib/txgh/version.rb +1 -1
- data/spec/events_spec.rb +40 -2
- data/spec/github_api_spec.rb +3 -3
- data/spec/resource_committer_spec.rb +1 -1
- data/spec/resource_updater_spec.rb +6 -1
- data/spec/transifex_api_spec.rb +6 -2
- data/spec/utils_spec.rb +44 -0
- metadata +2 -3
- data/lib/txgh/response_helpers.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abf79e14e41fd8e48b6e4243491b6f7d167ea173
|
4
|
+
data.tar.gz: a53bb4779937d8b42fc4d24c4476d2b40e152d0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 544945c0b37aa982633d86d2925cbe458d4788a54db2b7a0d614a020befb8dfabda7e1b4dbb367c73a63d214e5ec1de2a1c21a80364384e0b5042ee16f2608c9
|
7
|
+
data.tar.gz: 795f05ae83fd6fd2fcf52a0a11f8613a29e05c42c50ee2a8b29ca8124c5355fe6f216588cc4cafc176b53c68b3cd2574c883d79fefd760b30cf9afb553b2f139
|
data/lib/txgh.rb
CHANGED
@@ -19,7 +19,6 @@ module Txgh
|
|
19
19
|
autoload :ResourceDeleter, 'txgh/resource_deleter'
|
20
20
|
autoload :ResourceDownloader, 'txgh/resource_downloader'
|
21
21
|
autoload :ResourceUpdater, 'txgh/resource_updater'
|
22
|
-
autoload :ResponseHelpers, 'txgh/response_helpers'
|
23
22
|
autoload :TransifexApi, 'txgh/transifex_api'
|
24
23
|
autoload :TransifexProject, 'txgh/transifex_project'
|
25
24
|
autoload :TxBranchResource, 'txgh/tx_branch_resource'
|
data/lib/txgh/errors.rb
CHANGED
@@ -2,9 +2,26 @@ module Txgh
|
|
2
2
|
class TxghError < StandardError; end
|
3
3
|
class TxghInternalError < TxghError; end
|
4
4
|
|
5
|
-
class TransifexApiError < StandardError
|
6
|
-
|
7
|
-
|
5
|
+
class TransifexApiError < StandardError
|
6
|
+
attr_reader :status_code
|
7
|
+
|
8
|
+
def initialize(message, status_code)
|
9
|
+
super(message)
|
10
|
+
@status_code = status_code
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class TransifexNotFoundError < TransifexApiError
|
15
|
+
def initialize(message = 'Not found')
|
16
|
+
super(message, 404)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class TransifexUnauthorizedError < TransifexApiError
|
21
|
+
def initialize(message = 'Unauthorized')
|
22
|
+
super(message, 401)
|
23
|
+
end
|
24
|
+
end
|
8
25
|
|
9
26
|
class InvalidProviderError < StandardError; end
|
10
27
|
|
data/lib/txgh/events.rb
CHANGED
@@ -17,17 +17,22 @@ module Txgh
|
|
17
17
|
callback.call(options)
|
18
18
|
end
|
19
19
|
rescue => e
|
20
|
-
publish_error(e)
|
20
|
+
publish_error!(e)
|
21
21
|
end
|
22
22
|
|
23
23
|
def channels
|
24
24
|
channel_hash.keys
|
25
25
|
end
|
26
26
|
|
27
|
-
def publish_error(e)
|
27
|
+
def publish_error(e, params = {})
|
28
|
+
callbacks = channel_hash.fetch(ERROR_CHANNEL) { [] }
|
29
|
+
callbacks.map { |callback| callback.call(e, params) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def publish_error!(e, params = {})
|
28
33
|
# if nobody has subscribed to error events, raise original error
|
29
34
|
callbacks = channel_hash.fetch(ERROR_CHANNEL) { raise e }
|
30
|
-
callbacks.
|
35
|
+
callbacks.map { |callback| callback.call(e, params) }
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
data/lib/txgh/github_api.rb
CHANGED
@@ -34,17 +34,24 @@ module Txgh
|
|
34
34
|
client.create_ref(repo_name, branch, sha) rescue false
|
35
35
|
end
|
36
36
|
|
37
|
-
def update_contents(branch,
|
38
|
-
|
37
|
+
def update_contents(branch, content_list, message)
|
38
|
+
content_list.each do |file_params|
|
39
|
+
path = file_params.fetch(:path)
|
40
|
+
new_contents = file_params.fetch(:contents)
|
39
41
|
branch = Utils.relative_branch(branch)
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
file_sha = file_params.fetch(:sha) do
|
44
|
+
begin
|
45
|
+
client.contents(repo_name, { path: path, ref: branch })[:sha]
|
46
|
+
rescue Octokit::NotFound
|
47
|
+
nil
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
|
-
|
51
|
+
# If the file doesnt exist, then it isn't tracked by git and file_sha
|
52
|
+
# will be nil. In git land, a SHA of all zeroes means create a new file
|
53
|
+
# instead of updating an existing one.
|
54
|
+
current_sha = file_sha || '0' * 40
|
48
55
|
new_sha = Utils.git_hash_blob(new_contents)
|
49
56
|
options = { branch: branch }
|
50
57
|
|
@@ -81,6 +88,5 @@ module Txgh
|
|
81
88
|
def create_status(sha, state, options = {})
|
82
89
|
client.create_status(repo_name, sha, state, options)
|
83
90
|
end
|
84
|
-
|
85
91
|
end
|
86
92
|
end
|
@@ -24,15 +24,20 @@ module Txgh
|
|
24
24
|
upload_whole(tx_resource, file, categories)
|
25
25
|
end
|
26
26
|
|
27
|
-
fire_event_for(tx_resource,
|
27
|
+
fire_event_for(tx_resource, branch)
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
-
def fire_event_for(tx_resource,
|
32
|
+
def fire_event_for(tx_resource, branch)
|
33
|
+
ref = repo.api.get_ref(branch)
|
34
|
+
|
33
35
|
Txgh.events.publish(
|
34
36
|
'transifex.resource.updated', {
|
35
|
-
project: project,
|
37
|
+
project: project,
|
38
|
+
repo: repo,
|
39
|
+
resource: tx_resource,
|
40
|
+
sha: ref[:object][:sha]
|
36
41
|
}
|
37
42
|
)
|
38
43
|
end
|
data/lib/txgh/transifex_api.rb
CHANGED
@@ -180,8 +180,10 @@ module Txgh
|
|
180
180
|
raise TransifexNotFoundError, "404 Not Found: #{response.env.url}"
|
181
181
|
else
|
182
182
|
if (response.status / 100) != 2
|
183
|
-
raise TransifexApiError
|
184
|
-
"HTTP #{response.status}: #{response.env.url}, body: #{response.body}"
|
183
|
+
raise TransifexApiError.new(
|
184
|
+
"HTTP #{response.status}: #{response.env.url}, body: #{response.body}",
|
185
|
+
response.status
|
186
|
+
)
|
185
187
|
end
|
186
188
|
end
|
187
189
|
end
|
data/lib/txgh/utils.rb
CHANGED
@@ -64,6 +64,23 @@ module Txgh
|
|
64
64
|
obj
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
def deep_symbolize_keys(obj)
|
69
|
+
case obj
|
70
|
+
when Hash
|
71
|
+
obj.each_with_object({}) do |(k, v), ret|
|
72
|
+
ret[k.to_sym] = deep_symbolize_keys(v)
|
73
|
+
end
|
74
|
+
|
75
|
+
when Array
|
76
|
+
obj.map do |elem|
|
77
|
+
deep_symbolize_keys(elem)
|
78
|
+
end
|
79
|
+
|
80
|
+
else
|
81
|
+
obj
|
82
|
+
end
|
83
|
+
end
|
67
84
|
end
|
68
85
|
|
69
86
|
Utils.extend(Utils)
|
data/lib/txgh/version.rb
CHANGED
data/spec/events_spec.rb
CHANGED
@@ -43,13 +43,51 @@ describe Events do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
shared_examples 'an error publisher' do |options = {}|
|
47
|
+
let(:error) do
|
48
|
+
begin; raise 'foo'; rescue => e; e; end
|
49
|
+
end
|
50
|
+
|
47
51
|
it 'publishes the given error over the error channel' do
|
48
52
|
errors = []
|
49
53
|
events.subscribe('errors') { |e| errors << e }
|
50
|
-
events.
|
54
|
+
events.send(options.fetch(:method_sym), error)
|
51
55
|
expect(errors.size).to eq(1)
|
52
56
|
expect(errors.first.message).to eq('foo')
|
53
57
|
end
|
58
|
+
|
59
|
+
it 'includes additional params' do
|
60
|
+
errors = []
|
61
|
+
events.subscribe('errors') { |e, params| errors << { error: e, params: params } }
|
62
|
+
events.send(options.fetch(:method_sym), error, { foo: 'bar' })
|
63
|
+
expect(errors.size).to eq(1)
|
64
|
+
|
65
|
+
error = errors.first
|
66
|
+
expect(error[:error].message).to eq('foo')
|
67
|
+
expect(error[:params]).to eq(foo: 'bar')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns an array of the callback return values' do
|
71
|
+
events.subscribe('errors') { |e| 'abc' }
|
72
|
+
events.subscribe('errors') { |e| 'def' }
|
73
|
+
callback_return_values = events.send(options.fetch(:method_sym), error)
|
74
|
+
expect(callback_return_values).to eq(%w(abc def))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#publish_error' do
|
79
|
+
it_behaves_like 'an error publisher', method_sym: :publish_error
|
80
|
+
|
81
|
+
it 'does not raise errors if no error subscribers are configured' do
|
82
|
+
expect { events.publish_error(StandardError.new) }.to_not raise_error
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#publish_error!' do
|
87
|
+
it_behaves_like 'an error publisher', method_sym: :publish_error!
|
88
|
+
|
89
|
+
it 'raises errors if no error subscribers are configured' do
|
90
|
+
expect { events.publish_error!(StandardError.new) }.to raise_error(StandardError)
|
91
|
+
end
|
54
92
|
end
|
55
93
|
end
|
data/spec/github_api_spec.rb
CHANGED
@@ -55,7 +55,7 @@ describe GithubApi do
|
|
55
55
|
.with(repo, path, 'message', old_sha, new_contents, { branch: branch })
|
56
56
|
)
|
57
57
|
|
58
|
-
api.update_contents(branch, { path
|
58
|
+
api.update_contents(branch, [{ path: path, contents: new_contents }], 'message')
|
59
59
|
end
|
60
60
|
|
61
61
|
it "doesn't update the file contents if the file hasn't changed" do
|
@@ -67,7 +67,7 @@ describe GithubApi do
|
|
67
67
|
|
68
68
|
expect(client).to_not receive(:update_contents)
|
69
69
|
|
70
|
-
api.update_contents(branch, { path
|
70
|
+
api.update_contents(branch, [{ path: path, contents: old_contents }], 'message')
|
71
71
|
end
|
72
72
|
|
73
73
|
it "creates the file if it doesn't already exist" do
|
@@ -81,7 +81,7 @@ describe GithubApi do
|
|
81
81
|
.with(repo, path, 'message', '0' * 40, new_contents, { branch: branch })
|
82
82
|
)
|
83
83
|
|
84
|
-
api.update_contents(branch, { path
|
84
|
+
api.update_contents(branch, [{ path: path, contents: new_contents }], 'message')
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -14,6 +14,7 @@ describe ResourceUpdater do
|
|
14
14
|
let(:ref) { 'heads/master' }
|
15
15
|
let(:resource) { tx_config.resource(resource_slug, ref) }
|
16
16
|
let(:commit_sha) { '8765309' }
|
17
|
+
let(:file_sha) { 'abc123' }
|
17
18
|
|
18
19
|
let(:translations) do
|
19
20
|
YAML.load("|
|
@@ -25,7 +26,7 @@ describe ResourceUpdater do
|
|
25
26
|
end
|
26
27
|
|
27
28
|
let(:modified_files) do
|
28
|
-
[{ path: resource.source_file, content: translations, sha:
|
29
|
+
[{ path: resource.source_file, content: translations, sha: file_sha }]
|
29
30
|
end
|
30
31
|
|
31
32
|
before(:each) do
|
@@ -34,6 +35,10 @@ describe ResourceUpdater do
|
|
34
35
|
receive(:download).with(file[:path], ref).and_return(file)
|
35
36
|
)
|
36
37
|
end
|
38
|
+
|
39
|
+
allow(github_api).to receive(:get_ref).with(ref).and_return(
|
40
|
+
{ object: { sha: commit_sha } }
|
41
|
+
)
|
37
42
|
end
|
38
43
|
|
39
44
|
it 'correctly uploads modified files to transifex' do
|
data/spec/transifex_api_spec.rb
CHANGED
@@ -132,7 +132,9 @@ describe TransifexApi do
|
|
132
132
|
end
|
133
133
|
|
134
134
|
expect { api.create(resource, 'new_content') }.to(
|
135
|
-
raise_error(
|
135
|
+
raise_error(TransifexNotFoundError) do |e|
|
136
|
+
expect(e.status_code).to eq(404)
|
137
|
+
end
|
136
138
|
)
|
137
139
|
end
|
138
140
|
|
@@ -286,7 +288,9 @@ describe TransifexApi do
|
|
286
288
|
end
|
287
289
|
|
288
290
|
expect { api.download(resource, language) }.to(
|
289
|
-
raise_error(
|
291
|
+
raise_error(TransifexUnauthorizedError) do |e|
|
292
|
+
expect(e.status_code).to eq(401)
|
293
|
+
end
|
290
294
|
)
|
291
295
|
end
|
292
296
|
|
data/spec/utils_spec.rb
CHANGED
@@ -98,4 +98,48 @@ describe Utils do
|
|
98
98
|
expect(Utils.booleanize(false)).to eq(false)
|
99
99
|
end
|
100
100
|
end
|
101
|
+
|
102
|
+
describe '.deep_symbolize_keys' do
|
103
|
+
it 'symbolizes keys in a hash with depth 1' do
|
104
|
+
hash = { 'abc' => 'def', ghi: 'jkl' }
|
105
|
+
expect(Utils.deep_symbolize_keys(hash)).to eq(
|
106
|
+
{ abc: 'def', ghi: 'jkl' }
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'symbolizes keys in a hash with depth 2' do
|
111
|
+
hash = { 'abc' => { 'def' => 'ghi' } }
|
112
|
+
expect(Utils.deep_symbolize_keys(hash)).to eq(
|
113
|
+
{ abc: { def: 'ghi' } }
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'symbolizes keys in a hash with depth 3' do
|
118
|
+
hash = { 'abc' => { 'def' => { 'ghi' => 'jkl' }, 'mno' => 'pqr' } }
|
119
|
+
expect(Utils.deep_symbolize_keys(hash)).to eq(
|
120
|
+
{ abc: { def: { ghi: 'jkl' }, mno: 'pqr' } }
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'symbolizes hash keys in an array' do
|
125
|
+
array = [{ 'def' => 'ghi' }]
|
126
|
+
expect(Utils.deep_symbolize_keys(array)).to eq(
|
127
|
+
[{ def: 'ghi' }]
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'symbolizes keys nested inside arrays' do
|
132
|
+
hash = { 'abc' => [{ 'def' => 'ghi' }] }
|
133
|
+
expect(Utils.deep_symbolize_keys(hash)).to eq(
|
134
|
+
{ abc: [{ def: 'ghi' }] }
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "doesn't modify objects that aren't hashes" do
|
139
|
+
hash = { 'abc' => Set.new(%w(a b c)) }
|
140
|
+
expect(Utils.deep_symbolize_keys(hash)).to eq(
|
141
|
+
{ abc: hash['abc'] }
|
142
|
+
)
|
143
|
+
end
|
144
|
+
end
|
101
145
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: txgh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Jackowski
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-09-
|
12
|
+
date: 2016-09-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: abroad
|
@@ -133,7 +133,6 @@ files:
|
|
133
133
|
- lib/txgh/resource_deleter.rb
|
134
134
|
- lib/txgh/resource_downloader.rb
|
135
135
|
- lib/txgh/resource_updater.rb
|
136
|
-
- lib/txgh/response_helpers.rb
|
137
136
|
- lib/txgh/transifex_api.rb
|
138
137
|
- lib/txgh/transifex_project.rb
|
139
138
|
- lib/txgh/tx_branch_resource.rb
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Txgh
|
2
|
-
module ResponseHelpers
|
3
|
-
private
|
4
|
-
|
5
|
-
def respond_with(status, body, e = nil)
|
6
|
-
Txgh::Handlers::Response.new(status, body, e)
|
7
|
-
end
|
8
|
-
|
9
|
-
def respond_with_error(status, message, e = nil)
|
10
|
-
respond_with(status, error(message), e)
|
11
|
-
end
|
12
|
-
|
13
|
-
def error(message)
|
14
|
-
[{ error: message }]
|
15
|
-
end
|
16
|
-
|
17
|
-
def data(body)
|
18
|
-
{ data: body }
|
19
|
-
end
|
20
|
-
|
21
|
-
# includes these methods in the singleton class as well
|
22
|
-
def self.included(base)
|
23
|
-
base.extend(self)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|