txgh 6.0.0.beta1 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/txgh/config/config_pair.rb +1 -1
- data/lib/txgh/config/providers/git_provider.rb +1 -1
- data/lib/txgh/github_api.rb +32 -54
- data/lib/txgh/github_status.rb +1 -1
- data/lib/txgh/pusher.rb +1 -1
- data/lib/txgh/resource_committer.rb +2 -2
- data/lib/txgh/resource_contents.rb +11 -2
- data/lib/txgh/resource_downloader.rb +1 -1
- data/lib/txgh/resource_updater.rb +15 -37
- data/lib/txgh/tx_branch_resource.rb +6 -3
- data/lib/txgh/tx_resource.rb +4 -4
- data/lib/txgh/version.rb +1 -1
- data/spec/config/tx_manager_spec.rb +2 -2
- data/spec/diff_calculator_spec.rb +56 -0
- data/spec/github_api_spec.rb +45 -97
- data/spec/github_status_spec.rb +2 -3
- data/spec/merge_calculator_spec.rb +46 -0
- data/spec/resource_committer_spec.rb +1 -1
- data/spec/resource_contents_spec.rb +30 -11
- data/spec/resource_downloader_spec.rb +2 -2
- data/spec/resource_updater_spec.rb +14 -30
- data/spec/tx_resource_spec.rb +0 -6
- data/txgh.gemspec +1 -1
- metadata +7 -9
- data/README.md +0 -334
- data/lib/ext/zipline/output_stream.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cee1db178f1ad7cdc40a20d13eb5e7f22aa8da3e
|
4
|
+
data.tar.gz: ad1b43ad46d06e5c2bfadb35e19e64153ce17ced
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76946e935626508ed67deddaa9aae76947c43eac2a776b077f848ed2e5945e52832832c8d6305f1219b171392ac71bdd1b89027a6267274fb022e3819ab41d8f
|
7
|
+
data.tar.gz: 4a6b2dc8948e3c03a051631f47524ee00c77c070f538cee59cd5d56516cf3b5ff19ee0803b21e538f0d0b593dc0d3884d87de69d906b12dde071c14f4baff5ed
|
@@ -34,7 +34,7 @@ module Txgh
|
|
34
34
|
private
|
35
35
|
|
36
36
|
def download
|
37
|
-
github_repo.api.download(
|
37
|
+
github_repo.api.download(payload, ref)[:content]
|
38
38
|
rescue Octokit::NotFound
|
39
39
|
raise Txgh::GitConfigNotFoundError, "Config file #{payload} not found in #{ref}"
|
40
40
|
end
|
data/lib/txgh/github_api.rb
CHANGED
@@ -4,41 +4,42 @@ require 'octokit'
|
|
4
4
|
module Txgh
|
5
5
|
class GithubApi
|
6
6
|
class << self
|
7
|
-
def create_from_credentials(login, access_token)
|
7
|
+
def create_from_credentials(login, access_token, repo_name)
|
8
8
|
create_from_client(
|
9
|
-
Octokit::Client.new(login: login, access_token: access_token)
|
9
|
+
Octokit::Client.new(login: login, access_token: access_token), repo_name
|
10
10
|
)
|
11
11
|
end
|
12
12
|
|
13
|
-
def create_from_client(client)
|
14
|
-
new(client)
|
13
|
+
def create_from_client(client, repo_name)
|
14
|
+
new(client, repo_name)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
attr_reader :client
|
18
|
+
attr_reader :client, :repo_name
|
19
19
|
|
20
|
-
def initialize(client)
|
20
|
+
def initialize(client, repo_name)
|
21
21
|
@client = client
|
22
|
+
@repo_name = repo_name
|
22
23
|
end
|
23
24
|
|
24
|
-
def tree(
|
25
|
-
client.tree(
|
25
|
+
def tree(sha)
|
26
|
+
client.tree(repo_name, sha, recursive: 1)
|
26
27
|
end
|
27
28
|
|
28
|
-
def blob(
|
29
|
-
client.blob(
|
29
|
+
def blob(sha)
|
30
|
+
client.blob(repo_name, sha)
|
30
31
|
end
|
31
32
|
|
32
|
-
def create_ref(
|
33
|
-
client.create_ref(
|
33
|
+
def create_ref(branch, sha)
|
34
|
+
client.create_ref(repo_name, branch, sha) rescue false
|
34
35
|
end
|
35
36
|
|
36
|
-
def update_contents(
|
37
|
+
def update_contents(branch, content_map, message)
|
37
38
|
content_map.each do |path, new_contents|
|
38
39
|
branch = Utils.relative_branch(branch)
|
39
40
|
|
40
41
|
file = begin
|
41
|
-
client.contents(
|
42
|
+
client.contents(repo_name, { path: path, ref: branch })
|
42
43
|
rescue Octokit::NotFound
|
43
44
|
nil
|
44
45
|
end
|
@@ -49,59 +50,36 @@ module Txgh
|
|
49
50
|
|
50
51
|
if current_sha != new_sha
|
51
52
|
client.update_contents(
|
52
|
-
|
53
|
+
repo_name, path, message, current_sha, new_contents, options
|
53
54
|
)
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
|
60
|
-
base_commit = get_commit(repo, parent[:object][:sha])
|
61
|
-
|
62
|
-
tree_data = content_map.map do |path, content|
|
63
|
-
blob = client.create_blob(repo, content)
|
64
|
-
{ path: path, mode: '100644', type: 'blob', sha: blob }
|
65
|
-
end
|
66
|
-
|
67
|
-
tree_options = { base_tree: base_commit[:commit][:tree][:sha] }
|
68
|
-
|
69
|
-
tree = client.create_tree(repo, tree_data, tree_options)
|
70
|
-
commit = client.create_commit(
|
71
|
-
repo, message, tree[:sha], parent[:object][:sha]
|
72
|
-
)
|
73
|
-
|
74
|
-
# don't update the ref if the commit introduced no new changes
|
75
|
-
unless allow_empty
|
76
|
-
diff = client.compare(repo, parent[:object][:sha], commit[:sha])
|
77
|
-
return if diff[:files].empty?
|
78
|
-
end
|
79
|
-
|
80
|
-
# false means don't force push
|
81
|
-
client.update_ref(repo, branch, commit[:sha], false)
|
59
|
+
def get_commit(sha)
|
60
|
+
client.commit(repo_name, sha)
|
82
61
|
end
|
83
62
|
|
84
|
-
def
|
85
|
-
client.
|
63
|
+
def get_ref(ref)
|
64
|
+
client.ref(repo_name, ref)
|
86
65
|
end
|
87
66
|
|
88
|
-
def
|
89
|
-
client.
|
90
|
-
end
|
67
|
+
def download(path, branch)
|
68
|
+
file = client.contents(repo_name, { path: path, ref: branch }).to_h
|
91
69
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
if found = tree[:tree].find { |t| t[:path] == path }
|
98
|
-
b = blob(repo, found[:sha])
|
99
|
-
b['encoding'] == 'utf-8' ? b['content'] : Base64.decode64(b['content'])
|
70
|
+
file[:content] = case file[:encoding]
|
71
|
+
when 'base64'
|
72
|
+
Base64.decode64(file[:content])
|
73
|
+
else
|
74
|
+
file[:content].force_encoding(file[:encoding])
|
100
75
|
end
|
76
|
+
|
77
|
+
file.delete(:encoding)
|
78
|
+
file
|
101
79
|
end
|
102
80
|
|
103
|
-
def create_status(
|
104
|
-
client.create_status(
|
81
|
+
def create_status(sha, state, options = {})
|
82
|
+
client.create_status(repo_name, sha, state, options)
|
105
83
|
end
|
106
84
|
|
107
85
|
end
|
data/lib/txgh/github_status.rb
CHANGED
data/lib/txgh/pusher.rb
CHANGED
@@ -19,7 +19,7 @@ module Txgh
|
|
19
19
|
|
20
20
|
if translations
|
21
21
|
repo.api.update_contents(
|
22
|
-
|
22
|
+
branch, { file_name => translations }, message
|
23
23
|
)
|
24
24
|
|
25
25
|
fire_event_for(tx_resource, branch, language)
|
@@ -30,7 +30,7 @@ module Txgh
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def fire_event_for(tx_resource, branch, language)
|
33
|
-
head = repo.api.get_ref(
|
33
|
+
head = repo.api.get_ref(branch)
|
34
34
|
sha = head[:object][:sha]
|
35
35
|
|
36
36
|
Txgh.events.publish(
|
@@ -37,7 +37,7 @@ module Txgh
|
|
37
37
|
|
38
38
|
def phrases
|
39
39
|
@phrases ||= extractor.from_string(raw) do |extractor|
|
40
|
-
extractor.extract_each.map do |key, value|
|
40
|
+
extractor.extract_each(preserve_arrays: true).map do |key, value|
|
41
41
|
{ 'key' => key, 'string' => value }
|
42
42
|
end
|
43
43
|
end
|
@@ -56,7 +56,7 @@ module Txgh
|
|
56
56
|
serializer.from_stream(stream, language) do |serializer|
|
57
57
|
phrases.each do |phrase|
|
58
58
|
serializer.write_key_value(
|
59
|
-
phrase['key'], (phrase['string'] || '')
|
59
|
+
phrase['key'], str(phrase['string'] || '')
|
60
60
|
)
|
61
61
|
end
|
62
62
|
end
|
@@ -95,6 +95,15 @@ module Txgh
|
|
95
95
|
|
96
96
|
attr_reader :raw
|
97
97
|
|
98
|
+
def str(obj)
|
99
|
+
case obj
|
100
|
+
when Array
|
101
|
+
obj
|
102
|
+
else
|
103
|
+
obj.to_s
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
98
107
|
def extractor
|
99
108
|
id = EXTRACTOR_MAP.fetch(tx_resource.type) do
|
100
109
|
raise TxghInternalError,
|
@@ -12,48 +12,36 @@ module Txgh
|
|
12
12
|
@logger = logger || Logger.new(STDOUT)
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
# in Transifex.
|
17
|
-
def update_resource(tx_resource, commit_sha, categories = {})
|
15
|
+
def update_resource(tx_resource, categories = {})
|
18
16
|
# don't process the resource unless the project slugs are the same
|
19
17
|
return unless tx_resource.project_slug == project.name
|
18
|
+
branch = tx_resource.branch || repo.diff_point
|
19
|
+
file = repo.api.download(tx_resource.source_file)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
tree['tree'].each do |file|
|
26
|
-
logger.info("process each tree entry: #{file['path']}")
|
27
|
-
|
28
|
-
if tx_resource.source_file == file['path']
|
29
|
-
if repo.upload_diffs?
|
30
|
-
upload_diff(tx_resource, file, categories)
|
31
|
-
else
|
32
|
-
upload_whole(tx_resource, file, categories)
|
33
|
-
end
|
34
|
-
|
35
|
-
fire_event_for(tx_resource, commit_sha)
|
36
|
-
end
|
21
|
+
if repo.upload_diffs? && tx_resource.has_branch?
|
22
|
+
upload_diff(tx_resource, file, categories)
|
23
|
+
else
|
24
|
+
upload_whole(tx_resource, file, categories)
|
37
25
|
end
|
26
|
+
|
27
|
+
fire_event_for(tx_resource, file)
|
38
28
|
end
|
39
29
|
|
40
30
|
private
|
41
31
|
|
42
|
-
def fire_event_for(tx_resource,
|
32
|
+
def fire_event_for(tx_resource, file)
|
43
33
|
Txgh.events.publish(
|
44
34
|
'transifex.resource.updated', {
|
45
|
-
project: project, repo: repo, resource: tx_resource, sha:
|
35
|
+
project: project, repo: repo, resource: tx_resource, sha: file[:sha]
|
46
36
|
}
|
47
37
|
)
|
48
38
|
end
|
49
39
|
|
50
40
|
def upload_whole(tx_resource, file, categories)
|
51
|
-
content = contents_of(file['sha'])
|
52
|
-
|
53
41
|
if repo.process_all_branches?
|
54
|
-
upload_by_branch(tx_resource, content, categories)
|
42
|
+
upload_by_branch(tx_resource, file[:content], categories)
|
55
43
|
else
|
56
|
-
upload(tx_resource, content)
|
44
|
+
upload(tx_resource, file[:content])
|
57
45
|
end
|
58
46
|
end
|
59
47
|
|
@@ -77,11 +65,11 @@ module Txgh
|
|
77
65
|
end
|
78
66
|
|
79
67
|
def head_content(tx_resource, file)
|
80
|
-
ResourceContents.from_string(tx_resource,
|
68
|
+
ResourceContents.from_string(tx_resource, file[:content])
|
81
69
|
end
|
82
70
|
|
83
71
|
def diff_point_content(tx_resource, file)
|
84
|
-
raw_content = repo.api.download(
|
72
|
+
raw_content = repo.api.download(file[:path], repo.diff_point)
|
85
73
|
ResourceContents.from_string(tx_resource, raw_content)
|
86
74
|
end
|
87
75
|
|
@@ -108,15 +96,5 @@ module Txgh
|
|
108
96
|
resource = project.api.get_resource(*tx_resource.slugs)
|
109
97
|
deserialize_categories(Array(resource['categories']))
|
110
98
|
end
|
111
|
-
|
112
|
-
def contents_of(sha)
|
113
|
-
blob = repo.api.blob(repo.name, sha)
|
114
|
-
|
115
|
-
if blob['encoding'] == 'utf-8'
|
116
|
-
blob['content']
|
117
|
-
else
|
118
|
-
Base64.decode64(blob['content'])
|
119
|
-
end
|
120
|
-
end
|
121
99
|
end
|
122
100
|
end
|
@@ -5,9 +5,8 @@ module Txgh
|
|
5
5
|
extend Forwardable
|
6
6
|
|
7
7
|
def_delegators :@resource, *[
|
8
|
-
:project_slug, :type, :source_lang, :source_file, :
|
9
|
-
:
|
10
|
-
:to_h, :to_api_h
|
8
|
+
:project_slug, :type, :source_lang, :source_file, :translation_file,
|
9
|
+
:lang_map, :translation_path, :original_resource_slug, :to_h, :to_api_h
|
11
10
|
]
|
12
11
|
|
13
12
|
attr_reader :resource, :branch
|
@@ -50,6 +49,10 @@ module Txgh
|
|
50
49
|
)
|
51
50
|
end
|
52
51
|
|
52
|
+
def has_branch?
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
53
56
|
private
|
54
57
|
|
55
58
|
def slugified_branch
|
data/lib/txgh/tx_resource.rb
CHANGED
@@ -27,10 +27,6 @@ module Txgh
|
|
27
27
|
@translation_file = translation_file
|
28
28
|
end
|
29
29
|
|
30
|
-
def L10N_resource_slug
|
31
|
-
"L10N#{resource_slug}"
|
32
|
-
end
|
33
|
-
|
34
30
|
def lang_map(tx_lang)
|
35
31
|
@lang_map.fetch(tx_lang, tx_lang)
|
36
32
|
end
|
@@ -66,5 +62,9 @@ module Txgh
|
|
66
62
|
def branch
|
67
63
|
nil
|
68
64
|
end
|
65
|
+
|
66
|
+
def has_branch?
|
67
|
+
false
|
68
|
+
end
|
69
69
|
end
|
70
70
|
end
|
data/lib/txgh/version.rb
CHANGED
@@ -39,8 +39,8 @@ describe TxManager do
|
|
39
39
|
it 'loads tx config from a git repository' do
|
40
40
|
expect(repo.api).to(
|
41
41
|
receive(:download)
|
42
|
-
.with(
|
43
|
-
.and_return("[main]\nlang_map = ko:ko_KR")
|
42
|
+
.with('./tx.config', 'my_branch')
|
43
|
+
.and_return(content: "[main]\nlang_map = ko:ko_KR")
|
44
44
|
)
|
45
45
|
|
46
46
|
config = TxManager.tx_config(project, repo, 'my_branch')
|
@@ -35,6 +35,29 @@ describe DiffCalculator do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
context 'with an array added to HEAD' do
|
39
|
+
let(:head_phrases) do
|
40
|
+
diff_point_phrases + [
|
41
|
+
phrase('villains', %w(Khan Chang Valeris Shinzon))
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:diff_point_phrases) do
|
46
|
+
[
|
47
|
+
phrase('Bajor', 'Bajoran'),
|
48
|
+
phrase('Cardassia', 'Cardassian')
|
49
|
+
]
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'includes the new array' do
|
53
|
+
expect(diff[:added].size).to eq(1)
|
54
|
+
expect(diff[:modified].size).to eq(0)
|
55
|
+
phrase = diff[:added].first
|
56
|
+
expect(phrase['key']).to eq('villains')
|
57
|
+
expect(phrase['string']).to eq(%w(Khan Chang Valeris Shinzon))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
38
61
|
context 'with phrases removed from HEAD' do
|
39
62
|
let(:head_phrases) do
|
40
63
|
[]
|
@@ -50,6 +73,21 @@ describe DiffCalculator do
|
|
50
73
|
end
|
51
74
|
end
|
52
75
|
|
76
|
+
context 'with an array removed from HEAD' do
|
77
|
+
let(:head_phrases) do
|
78
|
+
[]
|
79
|
+
end
|
80
|
+
|
81
|
+
let(:diff_point_phrases) do
|
82
|
+
phrase('villains', %w(Khan Chang Valeris Shinzon))
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'does not include the array' do
|
86
|
+
expect(diff[:added].size).to eq(0)
|
87
|
+
expect(diff[:modified].size).to eq(0)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
53
91
|
context 'with phrases modified in HEAD' do
|
54
92
|
let(:head_phrases) do
|
55
93
|
[phrase('TheNextGeneration', 'Jean Luc Picard (rocks)')]
|
@@ -68,6 +106,24 @@ describe DiffCalculator do
|
|
68
106
|
end
|
69
107
|
end
|
70
108
|
|
109
|
+
context 'with an array modified in HEAD' do
|
110
|
+
let(:head_phrases) do
|
111
|
+
[phrase('villains', %w(Khan Chang Valeris Shinzon))]
|
112
|
+
end
|
113
|
+
|
114
|
+
let(:diff_point_phrases) do
|
115
|
+
[phrase('villains', %w(Khan Chang Valeris))]
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'includes the entire array' do
|
119
|
+
expect(diff[:added].size).to eq(0)
|
120
|
+
expect(diff[:modified].size).to eq(1)
|
121
|
+
phrase = diff[:modified].first
|
122
|
+
expect(phrase['key']).to eq('villains')
|
123
|
+
expect(phrase['string']).to eq(%w(Khan Chang Valeris Shinzon))
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
71
127
|
context 'with no phrases modified, added, or removed' do
|
72
128
|
let(:head_phrases) do
|
73
129
|
[
|