phraseapp_updater 2.1.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/phraseapp_common.sh +6 -6
- data/bin/synchronize_phraseapp.sh +2 -2
- data/lib/phraseapp_updater/phraseapp_api.rb +134 -98
- data/lib/phraseapp_updater/version.rb +1 -1
- data/lib/phraseapp_updater.rb +5 -4
- metadata +10 -26
- data/.envrc +0 -1
- data/.github/workflows/gem-push.yml +0 -31
- data/.github/workflows/test.yml +0 -41
- data/.gitignore +0 -9
- data/.rspec +0 -2
- data/.travis.yml +0 -5
- data/CODE_OF_CONDUCT.markdown +0 -50
- data/Gemfile +0 -8
- data/README.markdown +0 -177
- data/Rakefile +0 -7
- data/nix/gem/Gemfile +0 -24
- data/nix/gem/Gemfile.lock +0 -68
- data/nix/gem/gemset.nix +0 -230
- data/nix/generate.rb +0 -41
- data/phraseapp_updater.gemspec +0 -35
- data/shell.nix +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f33deb3a77a37a47abdf44c354526cbe3ad3d10256bb2a046bf48922178187fd
|
4
|
+
data.tar.gz: f22f2ceed18653b09c24be4724707cdc40c39539535c226fd028bc03338437cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 822cc67247e2e2752397127f6b4e5e0d893cdfc3c64a29f14067d2bc5b6e131f3924d5cad982960df65da4b47971c12ad43fc9caf9c9ff15e756a596a64c163e
|
7
|
+
data.tar.gz: a2e1152e1a376690722722d73c2654d4ab4e417530b66b86f7562cd0b17e54f06976a295bae601ec0d4ed1e8570a518eef9a37ff317f24001643e711c0365e6c
|
data/bin/phraseapp_common.sh
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
|
3
3
|
# Set up a working directory
|
4
|
-
working_directory=$(mktemp -d
|
4
|
+
working_directory=$(mktemp -d phraseapp.XXXXXX)
|
5
5
|
|
6
6
|
function cleanup_working_directory(){
|
7
7
|
local now archive
|
8
8
|
now="$(date "+%Y%m%d%H%M%S")"
|
9
9
|
archive="/tmp/phraseapp-updater-$now.tar.gz"
|
10
|
-
tar czf "$archive" "${working_directory}"
|
10
|
+
tar -C "$(dirname "$working_directory")" -czf "$archive" "$(basename "${working_directory}")"
|
11
11
|
rm -rf "${working_directory}"
|
12
12
|
echo "Working files saved to $archive"
|
13
13
|
}
|
@@ -41,15 +41,15 @@ function make_tree_from_directory() {
|
|
41
41
|
}
|
42
42
|
|
43
43
|
|
44
|
-
function
|
45
|
-
extract_files "$1:${PREFIX}"
|
44
|
+
function extract_prefix_from_commit() {
|
45
|
+
extract_files "$1" "$2:${PREFIX}"
|
46
46
|
}
|
47
47
|
|
48
48
|
function extract_files() {
|
49
49
|
local path
|
50
|
-
path=$(make_temporary_directory "git.${1%%:*}")
|
50
|
+
path=$(make_temporary_directory "git.${1}.${2%%:*}")
|
51
51
|
|
52
|
-
git archive --format=tar "$
|
52
|
+
git archive --format=tar "$2" | tar -x -C "${path}"
|
53
53
|
|
54
54
|
echo "${path}"
|
55
55
|
}
|
@@ -61,8 +61,8 @@ elif ! git merge-base --is-ancestor "${common_ancestor}" "${current_branch}"; th
|
|
61
61
|
skip_ancestor_merge=t
|
62
62
|
fi
|
63
63
|
|
64
|
-
current_branch_path=$(
|
65
|
-
common_ancestor_path=$(
|
64
|
+
current_branch_path=$(extract_prefix_from_commit current_branch "${current_branch}")
|
65
|
+
common_ancestor_path=$(extract_prefix_from_commit common_ancestor "${common_ancestor}")
|
66
66
|
|
67
67
|
current_phraseapp_tree=$(make_tree_from_directory "${current_phraseapp_path}")
|
68
68
|
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'phraseapp_updater/locale_file'
|
4
4
|
require 'phraseapp_updater/index_by'
|
5
|
-
require '
|
5
|
+
require 'uri'
|
6
|
+
require 'phrase'
|
6
7
|
require 'parallel'
|
7
8
|
require 'tempfile'
|
8
9
|
|
@@ -13,16 +14,24 @@ class PhraseAppUpdater
|
|
13
14
|
PAGE_SIZE = 100
|
14
15
|
|
15
16
|
def initialize(api_key, project_id, locale_file_class)
|
16
|
-
|
17
|
+
config = Phrase::Configuration.new do |c|
|
18
|
+
c.api_key['Authorization'] = api_key
|
19
|
+
c.api_key_prefix['Authorization'] = 'token'
|
20
|
+
c.debugging = false
|
21
|
+
end
|
22
|
+
|
23
|
+
@client = Phrase::ApiClient.new(config)
|
17
24
|
@project_id = project_id
|
18
25
|
@locale_file_class = locale_file_class
|
19
26
|
end
|
20
27
|
|
21
28
|
def create_project(name, parent_commit)
|
22
|
-
params =
|
29
|
+
params = Phrase::ProjectCreateParameters.new(
|
23
30
|
name: name,
|
24
31
|
main_format: @locale_file_class.phraseapp_type)
|
25
|
-
|
32
|
+
|
33
|
+
project = phraseapp_request(Phrase::ProjectsApi, :project_create, params)
|
34
|
+
|
26
35
|
STDERR.puts "Created project #{name} for #{parent_commit}"
|
27
36
|
|
28
37
|
@project_id = project.id
|
@@ -32,7 +41,8 @@ class PhraseAppUpdater
|
|
32
41
|
end
|
33
42
|
|
34
43
|
def lookup_project_id(name)
|
35
|
-
result, =
|
44
|
+
result, = paginated_request(Phrase::ProjectsApi, :projects_list, { per_page: PAGE_SIZE }, limit: 1) { |p| p.name == name }
|
45
|
+
|
36
46
|
raise ProjectNotFoundError.new(name) if result.nil?
|
37
47
|
|
38
48
|
result.id
|
@@ -41,9 +51,10 @@ class PhraseAppUpdater
|
|
41
51
|
# We mark projects with their parent git commit using a tag with a
|
42
52
|
# well-known prefix. We only allow one tag with this prefix at once.
|
43
53
|
def read_parent_commit
|
44
|
-
git_tag, =
|
54
|
+
git_tag, = paginated_request(Phrase::TagsApi, :tags_list, @project_id, limit: 1) do |t|
|
45
55
|
t.name.start_with?(GIT_TAG_PREFIX)
|
46
56
|
end
|
57
|
+
|
47
58
|
raise MissingGitParentError.new if git_tag.nil?
|
48
59
|
|
49
60
|
git_tag.name.delete_prefix(GIT_TAG_PREFIX)
|
@@ -51,35 +62,28 @@ class PhraseAppUpdater
|
|
51
62
|
|
52
63
|
def update_parent_commit(commit_hash)
|
53
64
|
previous_parent = read_parent_commit
|
54
|
-
phraseapp_request
|
55
|
-
@client.tag_delete(@project_id, GIT_TAG_PREFIX + previous_parent)
|
56
|
-
end
|
65
|
+
phraseapp_request(Phrase::TagsApi, :tag_delete, @project_id, GIT_TAG_PREFIX + previous_parent)
|
57
66
|
store_parent_commit(commit_hash)
|
58
67
|
end
|
59
68
|
|
60
69
|
def fetch_locales
|
61
|
-
|
62
|
-
|
63
|
-
phraseapp_request { @client.locales_list(@project_id, 1, 100) }.map do |pa_locale|
|
64
|
-
Locale.new(pa_locale)
|
65
|
-
end
|
70
|
+
locales = paginated_request(Phrase::LocalesApi, :locales_list, @project_id)
|
71
|
+
locales.map { |pa_locale| Locale.new(pa_locale) }
|
66
72
|
end
|
67
73
|
|
68
74
|
def create_locale(name, default: false)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
@client.locale_create(@project_id, params)
|
76
|
-
end
|
75
|
+
params = Phrase::LocaleCreateParameters.new(
|
76
|
+
name: name,
|
77
|
+
code: name,
|
78
|
+
default: default,
|
79
|
+
)
|
80
|
+
phraseapp_request(Phrase::LocalesApi, :locale_create, @project_id, params)
|
77
81
|
end
|
78
82
|
|
79
83
|
def download_files(locales, skip_unverified:)
|
80
84
|
results = threaded_request(locales) do |locale|
|
81
85
|
STDERR.puts "Downloading file for #{locale}"
|
82
|
-
|
86
|
+
download_locale(locale, skip_unverified)
|
83
87
|
end
|
84
88
|
|
85
89
|
locales.zip(results).map do |locale, file_contents|
|
@@ -87,18 +91,65 @@ class PhraseAppUpdater
|
|
87
91
|
end
|
88
92
|
end
|
89
93
|
|
94
|
+
# Empirically, PhraseApp fails to parse the uploaded files when uploaded in
|
95
|
+
# parallel. Give it a better chance by uploading them one at a time.
|
90
96
|
def upload_files(locale_files, default_locale:)
|
91
|
-
|
97
|
+
is_default = ->(l) { l.locale_name == default_locale }
|
92
98
|
|
99
|
+
# Ensure the locales all exist
|
100
|
+
STDERR.puts('Creating locales')
|
101
|
+
known_locales = fetch_locales.index_by(&:name)
|
93
102
|
threaded_request(locale_files) do |locale_file|
|
94
103
|
unless known_locales.has_key?(locale_file.locale_name)
|
95
|
-
create_locale(locale_file.locale_name,
|
96
|
-
|
104
|
+
create_locale(locale_file.locale_name, default: is_default.(locale_file))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Upload the files in a stable order, ensuring the default locale is first.
|
109
|
+
locale_files.sort! do |a, b|
|
110
|
+
next -1 if is_default.(a)
|
111
|
+
next 1 if is_default.(b)
|
112
|
+
|
113
|
+
a.locale_name <=> b.locale_name
|
114
|
+
end
|
115
|
+
|
116
|
+
uploads = {}
|
117
|
+
|
118
|
+
uploads = locale_files.to_h do |locale_file|
|
119
|
+
STDERR.puts("Uploading #{locale_file}")
|
120
|
+
upload_id = upload_file(locale_file)
|
121
|
+
[upload_id, locale_file]
|
122
|
+
end
|
123
|
+
|
124
|
+
# Validate the uploads, retrying failures as necessary
|
125
|
+
successful_upload_ids = {}
|
126
|
+
|
127
|
+
STDERR.puts('Verifying uploads...')
|
128
|
+
until uploads.empty?
|
129
|
+
threaded_request(uploads.to_a) do |upload_id, locale_file|
|
130
|
+
upload = phraseapp_request(Phrase::UploadsApi, :upload_show, @project_id, upload_id)
|
131
|
+
|
132
|
+
case upload.state
|
133
|
+
when "enqueued", "processing"
|
134
|
+
STDERR.puts("#{locale_file}: still processing")
|
135
|
+
when "success"
|
136
|
+
STDERR.puts("#{locale_file}: success")
|
137
|
+
successful_upload_ids[locale_file.locale_name] = upload_id
|
138
|
+
uploads.delete(upload_id)
|
139
|
+
when "error"
|
140
|
+
STDERR.puts("#{locale_file}: upload failure, retrying")
|
141
|
+
new_upload_id = upload_file(locale_file)
|
142
|
+
uploads.delete(upload_id)
|
143
|
+
uploads[new_upload_id] = locale_file
|
144
|
+
else
|
145
|
+
raise RuntimeError.new("Unknown upload state: #{upload.state}")
|
146
|
+
end
|
97
147
|
end
|
98
148
|
|
99
|
-
|
100
|
-
upload_file(locale_file)
|
149
|
+
sleep(2) unless uploads.empty?
|
101
150
|
end
|
151
|
+
|
152
|
+
successful_upload_ids
|
102
153
|
end
|
103
154
|
|
104
155
|
def remove_keys_not_in_uploads(upload_ids)
|
@@ -108,105 +159,101 @@ class PhraseAppUpdater
|
|
108
159
|
end
|
109
160
|
end
|
110
161
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
162
|
+
def download_locale(locale, skip_unverified)
|
163
|
+
opts = {
|
164
|
+
file_format: @locale_file_class.phraseapp_type,
|
165
|
+
skip_unverified_translations: skip_unverified,
|
166
|
+
}
|
116
167
|
|
117
|
-
|
168
|
+
# Avoid allocating a tempfile (and emitting unnecessary warnings) by using `return_type` of `String`
|
169
|
+
phraseapp_request(Phrase::LocalesApi, :locale_download, @project_id, locale.id, return_type: 'String', **opts)
|
118
170
|
end
|
119
171
|
|
120
172
|
def upload_file(locale_file)
|
121
|
-
upload_params = create_upload_params(locale_file.locale_name)
|
122
|
-
|
123
173
|
# The PhraseApp gem only accepts a filename to upload,
|
124
174
|
# so we need to write the file out and pass it the path
|
125
175
|
Tempfile.create([locale_file.locale_name, ".json"]) do |f|
|
126
176
|
f.write(locale_file.content)
|
127
177
|
f.close
|
128
178
|
|
129
|
-
|
130
|
-
|
179
|
+
opts = {
|
180
|
+
file: f,
|
181
|
+
file_encoding: 'UTF-8',
|
182
|
+
file_format: @locale_file_class.phraseapp_type,
|
183
|
+
locale_id: locale_file.locale_name,
|
184
|
+
skip_unverification: false,
|
185
|
+
update_translations: true,
|
186
|
+
tags: [generate_upload_tag],
|
187
|
+
}
|
188
|
+
|
189
|
+
result = phraseapp_request(Phrase::UploadsApi, :upload_create, @project_id, **opts)
|
190
|
+
|
191
|
+
result.id
|
131
192
|
end
|
132
193
|
end
|
133
194
|
|
134
195
|
def remove_keys_not_in_upload(upload_id)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
begin
|
139
|
-
phraseapp_request { @client.keys_delete(@project_id, delete_params) }
|
140
|
-
rescue RuntimeError => _e
|
141
|
-
# PhraseApp will accept but mark invalid uploads, however the gem
|
142
|
-
# returns the same response in both cases. If we call this API
|
143
|
-
# with the ID of an upload of a bad file, it will fail.
|
144
|
-
# This usually occurs when sending up an empty file, which is
|
145
|
-
# a case we can ignore. However, it'd be better to have a way
|
146
|
-
# to detect a bad upload and find the cause.
|
147
|
-
end
|
196
|
+
delete_pattern = "unmentioned_in_upload:#{upload_id}"
|
197
|
+
phraseapp_request(Phrase::KeysApi, :keys_delete_collection, @project_id, q: delete_pattern)
|
148
198
|
end
|
149
199
|
|
150
200
|
private
|
151
201
|
|
152
202
|
def store_parent_commit(commit_hash)
|
153
|
-
params =
|
154
|
-
|
155
|
-
|
203
|
+
params = Phrase::TagCreateParameters.new(name: GIT_TAG_PREFIX + commit_hash)
|
204
|
+
phraseapp_request(Phrase::TagsApi,:tag_create, @project_id, params)
|
205
|
+
end
|
206
|
+
|
207
|
+
def wrap_phrase_errors
|
208
|
+
yield
|
209
|
+
rescue Phrase::ApiError => e
|
210
|
+
if e.code == 401
|
211
|
+
raise BadAPIKeyError.new(e)
|
212
|
+
elsif e.message.match?(/not found/)
|
213
|
+
raise BadProjectIDError.new(e, @project_id)
|
214
|
+
elsif e.message.match?(/has already been taken/)
|
215
|
+
raise ProjectNameTakenError.new(e)
|
216
|
+
else
|
217
|
+
raise
|
218
|
+
end
|
156
219
|
end
|
157
220
|
|
158
|
-
def
|
221
|
+
def paginated_request(api_class, method, *params, limit: nil, **opts, &filter)
|
222
|
+
|
223
|
+
api_instance = api_class.new(@client)
|
159
224
|
page = 1
|
160
225
|
results = []
|
161
226
|
|
162
227
|
loop do
|
163
|
-
response =
|
164
|
-
|
228
|
+
response = wrap_phrase_errors do
|
229
|
+
api_instance.public_send(method, *params, opts.merge(page: page, page_size: PAGE_SIZE))
|
165
230
|
end
|
166
231
|
|
167
|
-
break if response.empty?
|
232
|
+
break if response.data.empty?
|
168
233
|
|
169
|
-
matches = response.
|
234
|
+
matches = response.data
|
235
|
+
matches = matches.filter(&filter) if filter
|
170
236
|
matches = matches[0, limit - results.size] if limit
|
171
237
|
|
172
|
-
unless matches.empty?
|
173
|
-
results.concat(matches)
|
238
|
+
results.concat(matches) unless matches.empty?
|
174
239
|
|
175
|
-
|
176
|
-
|
240
|
+
break if results.size == limit
|
241
|
+
break unless response.next_page?
|
177
242
|
|
178
|
-
page
|
243
|
+
page = response.next_page
|
179
244
|
end
|
180
245
|
|
181
246
|
results
|
182
247
|
end
|
183
248
|
|
184
|
-
def phraseapp_request(
|
185
|
-
|
249
|
+
def phraseapp_request(api_class, method, *params, **opts)
|
250
|
+
api_instance = api_class.new(@client)
|
186
251
|
|
187
|
-
|
188
|
-
|
189
|
-
if err.respond_to?(:error)
|
190
|
-
err.error
|
191
|
-
else
|
192
|
-
err.errors.join('|')
|
193
|
-
end
|
194
|
-
|
195
|
-
raise RuntimeError.new(error)
|
252
|
+
response = wrap_phrase_errors do
|
253
|
+
api_instance.public_send(method, *params, opts)
|
196
254
|
end
|
197
255
|
|
198
|
-
|
199
|
-
|
200
|
-
rescue RuntimeError => e
|
201
|
-
if e.message.match?(/\(401\)/)
|
202
|
-
raise BadAPIKeyError.new(e)
|
203
|
-
elsif e.message.match?(/not found/)
|
204
|
-
raise BadProjectIDError.new(e, @project_id)
|
205
|
-
elsif e.message.match?(/has already been taken/)
|
206
|
-
raise ProjectNameTakenError.new(e)
|
207
|
-
else
|
208
|
-
raise
|
209
|
-
end
|
256
|
+
response.data
|
210
257
|
end
|
211
258
|
|
212
259
|
# PhraseApp allows two concurrent connections at a time.
|
@@ -216,17 +263,6 @@ class PhraseAppUpdater
|
|
216
263
|
Parallel.map(worklist, in_threads: THREAD_COUNT, &block)
|
217
264
|
end
|
218
265
|
|
219
|
-
def create_upload_params(locale_name)
|
220
|
-
upload_params = PhraseApp::RequestParams::UploadParams.new
|
221
|
-
upload_params.file_encoding = 'UTF-8'
|
222
|
-
upload_params.file_format = @locale_file_class.phraseapp_type
|
223
|
-
upload_params.locale_id = locale_name
|
224
|
-
upload_params.skip_unverification = false
|
225
|
-
upload_params.update_translations = true
|
226
|
-
upload_params.tags = [generate_upload_tag]
|
227
|
-
upload_params
|
228
|
-
end
|
229
|
-
|
230
266
|
def generate_upload_tag
|
231
267
|
"phraseapp_updater_upload_#{Time.now.strftime('%Y%m%d%H%M%S')}"
|
232
268
|
end
|
data/lib/phraseapp_updater.rb
CHANGED
@@ -102,13 +102,14 @@ class PhraseAppUpdater
|
|
102
102
|
# We assert that the default locale contains all legitimate strings, and so
|
103
103
|
# we clean up orphaned content on PhraseApp post-upload by removing keys not
|
104
104
|
# in the default locale.
|
105
|
-
|
106
|
-
|
105
|
+
unless locale_files.find { |f| f.locale_name == @default_locale }
|
106
|
+
raise RuntimeError.new("Missing default locale")
|
107
|
+
end
|
107
108
|
|
108
109
|
upload_ids = @phraseapp_api.upload_files(locale_files, default_locale: @default_locale)
|
109
|
-
default_upload_id = upload_ids
|
110
|
+
default_upload_id = upload_ids.fetch(@default_locale)
|
110
111
|
|
111
|
-
STDERR.puts "Removing keys not in default locale upload #{default_upload_id}"
|
112
|
+
STDERR.puts "Removing keys not in default locale '#{@default_locale}' upload '#{default_upload_id}'"
|
112
113
|
@phraseapp_api.remove_keys_not_in_upload(default_upload_id)
|
113
114
|
end
|
114
115
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phraseapp_updater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- iKnow Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -25,33 +25,33 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.19'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: phrase
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 2.8.3
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 2.8.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: hashdiff
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 1.0.1
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 1.0.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: multi_json
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,23 +167,13 @@ dependencies:
|
|
167
167
|
description: A tool for merging data on PhraseApp with local changes (usually two
|
168
168
|
git revisions)
|
169
169
|
email:
|
170
|
-
-
|
170
|
+
- systems@iknow.jp
|
171
171
|
executables:
|
172
172
|
- phraseapp_updater
|
173
173
|
extensions: []
|
174
174
|
extra_rdoc_files: []
|
175
175
|
files:
|
176
|
-
- ".envrc"
|
177
|
-
- ".github/workflows/gem-push.yml"
|
178
|
-
- ".github/workflows/test.yml"
|
179
|
-
- ".gitignore"
|
180
|
-
- ".rspec"
|
181
|
-
- ".travis.yml"
|
182
|
-
- CODE_OF_CONDUCT.markdown
|
183
|
-
- Gemfile
|
184
176
|
- LICENSE.txt
|
185
|
-
- README.markdown
|
186
|
-
- Rakefile
|
187
177
|
- bin/console
|
188
178
|
- bin/phraseapp_common.sh
|
189
179
|
- bin/phraseapp_updater
|
@@ -198,13 +188,7 @@ files:
|
|
198
188
|
- lib/phraseapp_updater/phraseapp_api.rb
|
199
189
|
- lib/phraseapp_updater/version.rb
|
200
190
|
- lib/phraseapp_updater/yml_config_loader.rb
|
201
|
-
|
202
|
-
- nix/gem/Gemfile.lock
|
203
|
-
- nix/gem/gemset.nix
|
204
|
-
- nix/generate.rb
|
205
|
-
- phraseapp_updater.gemspec
|
206
|
-
- shell.nix
|
207
|
-
homepage: https://app.engoo.com
|
191
|
+
homepage: https://github.com/iknow/phraseapp_updater
|
208
192
|
licenses:
|
209
193
|
- MIT
|
210
194
|
metadata: {}
|
data/.envrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
eval "$(lorri direnv)"
|
@@ -1,31 +0,0 @@
|
|
1
|
-
name: Publish Ruby Gem
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches: [ "master" ]
|
6
|
-
|
7
|
-
jobs:
|
8
|
-
build:
|
9
|
-
name: Build + Publish
|
10
|
-
runs-on: ubuntu-latest
|
11
|
-
permissions:
|
12
|
-
contents: read
|
13
|
-
packages: write
|
14
|
-
|
15
|
-
steps:
|
16
|
-
- uses: actions/checkout@v3
|
17
|
-
- name: Set up Ruby 2.7
|
18
|
-
uses: ruby/setup-ruby@v1
|
19
|
-
with:
|
20
|
-
ruby-version: 2.7
|
21
|
-
|
22
|
-
- name: Publish to RubyGems
|
23
|
-
run: |
|
24
|
-
mkdir -p $HOME/.gem
|
25
|
-
touch $HOME/.gem/credentials
|
26
|
-
chmod 0600 $HOME/.gem/credentials
|
27
|
-
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
28
|
-
gem build *.gemspec
|
29
|
-
gem push *.gem
|
30
|
-
env:
|
31
|
-
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
data/.github/workflows/test.yml
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
name: Run Tests
|
2
|
-
|
3
|
-
on:
|
4
|
-
pull_request:
|
5
|
-
branches: "**"
|
6
|
-
|
7
|
-
permissions:
|
8
|
-
contents: read
|
9
|
-
checks: write
|
10
|
-
pull-requests: write
|
11
|
-
|
12
|
-
jobs:
|
13
|
-
test:
|
14
|
-
runs-on: ubuntu-latest
|
15
|
-
|
16
|
-
strategy:
|
17
|
-
matrix:
|
18
|
-
ruby-version: ['2.7', '3.0', '3.1']
|
19
|
-
|
20
|
-
steps:
|
21
|
-
- uses: actions/checkout@v3
|
22
|
-
- name: Set up Ruby
|
23
|
-
uses: ruby/setup-ruby@v1
|
24
|
-
with:
|
25
|
-
ruby-version: ${{ matrix.ruby-version }}
|
26
|
-
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
27
|
-
- name: Run tests
|
28
|
-
run: bundle exec rspec --profile 10 --format RspecJunitFormatter --out test_results/rspec.xml --format progress
|
29
|
-
- name: Upload result
|
30
|
-
uses: actions/upload-artifact@v3
|
31
|
-
if: always()
|
32
|
-
with:
|
33
|
-
name: rspec.xml
|
34
|
-
path: test_results/rspec.xml
|
35
|
-
- name: Test Report
|
36
|
-
uses: dorny/test-reporter@v1
|
37
|
-
if: always()
|
38
|
-
with:
|
39
|
-
name: Rspec Tests - ${{ matrix.ruby-version }}
|
40
|
-
path: test_results/rspec.xml
|
41
|
-
reporter: java-junit
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
data/CODE_OF_CONDUCT.markdown
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# Contributor Code of Conduct
|
2
|
-
|
3
|
-
As contributors and maintainers of this project, and in the interest of
|
4
|
-
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
-
contribute through reporting issues, posting feature requests, updating
|
6
|
-
documentation, submitting pull requests or patches, and other activities.
|
7
|
-
|
8
|
-
We are committed to making participation in this project a harassment-free
|
9
|
-
experience for everyone, regardless of level of experience, gender, gender
|
10
|
-
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
-
body size, race, ethnicity, age, religion, or nationality.
|
12
|
-
|
13
|
-
Examples of unacceptable behavior by participants include:
|
14
|
-
|
15
|
-
* The use of sexualized language or imagery
|
16
|
-
* Personal attacks
|
17
|
-
* Trolling or insulting/derogatory comments
|
18
|
-
* Public or private harassment
|
19
|
-
* Publishing other's private information, such as physical or electronic
|
20
|
-
addresses, without explicit permission
|
21
|
-
* Other unethical or unprofessional conduct
|
22
|
-
|
23
|
-
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
-
threatening, offensive, or harmful.
|
28
|
-
|
29
|
-
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
-
fairly and consistently applying these principles to every aspect of managing
|
31
|
-
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
-
Conduct may be permanently removed from the project team.
|
33
|
-
|
34
|
-
This code of conduct applies both within project spaces and in public spaces
|
35
|
-
when an individual is representing the project or its community.
|
36
|
-
|
37
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
-
reported by contacting a project maintainer at kev@bibo.com.ph. All
|
39
|
-
complaints will be reviewed and investigated and will result in a response that
|
40
|
-
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
-
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
-
incident.
|
43
|
-
|
44
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
-
version 1.3.0, available at
|
46
|
-
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
-
|
48
|
-
[homepage]: http://contributor-covenant.org
|
49
|
-
[version]: http://contributor-covenant.org/version/1/3/0/
|
50
|
-
|
data/Gemfile
DELETED
data/README.markdown
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
# PhraseAppUpdater
|
2
|
-
|
3
|
-
[![Build Status](https://travis-ci.org/iknow/phraseapp_updater.svg?branch=master)](https://travis-ci.org/iknow/phraseapp_updater)
|
4
|
-
|
5
|
-
**Version** 2.0.0
|
6
|
-
|
7
|
-
This is a tool for managing synchronization between locale data in
|
8
|
-
[PhraseApp](https://phraseapp.com) and committed in your project. It can perform
|
9
|
-
JSON-aware three-way merges with respect to a common ancestor, and maintains a
|
10
|
-
record of the common ancestor on PhraseApp using tags.
|
11
|
-
|
12
|
-
Our workflow considers localization data stored on PhraseApp to be a working
|
13
|
-
copy for a given branch. We expect developers working on the code and
|
14
|
-
translators working on PhraseApp to both be able to make changes and have them
|
15
|
-
integrated.
|
16
|
-
|
17
|
-
PhraseApp provides [APIs](https://phraseapp.com/docs/api/v2/) and a [Ruby
|
18
|
-
gem](https://github.com/phrase/phraseapp-ruby) for accessing them, but the API
|
19
|
-
only allows either a) completely overwriting PhraseApp's data with local data or
|
20
|
-
b) reapplying PhraseApp's data on top of the local data. Neither of these cases
|
21
|
-
is appropriate for integrating changes made on both sides.
|
22
|
-
|
23
|
-
What we want instead is a three way merge where the committed data wins on
|
24
|
-
conflict. Non-conflicting changes on PhraseApp are preserved, while changes to
|
25
|
-
the same key on both sides take the committed data. The result of the merge is
|
26
|
-
then applied to both sides, keeping them up to date with each other.
|
27
|
-
|
28
|
-
This is especially important when removing keys. Imagine we have the
|
29
|
-
following, no-longer useful key:
|
30
|
-
|
31
|
-
```json
|
32
|
-
unused:
|
33
|
-
one: An unused
|
34
|
-
```
|
35
|
-
|
36
|
-
On PhraseApp, we've added another plural form:
|
37
|
-
|
38
|
-
|
39
|
-
```json
|
40
|
-
unused:
|
41
|
-
one: An unused
|
42
|
-
zero: No unused's
|
43
|
-
```
|
44
|
-
|
45
|
-
And in our feature branch, we remove it. The result we want is that the key
|
46
|
-
completely disappears, instead of getting a result like either of the above.
|
47
|
-
|
48
|
-
## Installation
|
49
|
-
|
50
|
-
This gem provides a command line interface for performing the
|
51
|
-
merge and uploading the result to PhraseApp. To use it, install the gem:
|
52
|
-
|
53
|
-
`gem install phraseapp_updater`
|
54
|
-
|
55
|
-
You may also use this gem programatically from your own application.
|
56
|
-
|
57
|
-
Add this line to your application's Gemfile:
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
gem 'phraseapp_updater'
|
61
|
-
```
|
62
|
-
|
63
|
-
And then execute:
|
64
|
-
|
65
|
-
$ bundle
|
66
|
-
|
67
|
-
Or install it yourself as:
|
68
|
-
|
69
|
-
$ gem install phraseapp_updater
|
70
|
-
|
71
|
-
## Usage
|
72
|
-
|
73
|
-
CLI
|
74
|
-
---
|
75
|
-
|
76
|
-
**Setup**
|
77
|
-
|
78
|
-
`phraseapp_updater setup` creates and initializes a PhraseApp project
|
79
|
-
corresponding to your branch. It must be provided with the current git revision
|
80
|
-
of the branch and the path to the locale files.
|
81
|
-
|
82
|
-
```
|
83
|
-
phraseapp_updater setup --phraseapp_project_name=<yourbranch> --parent_commit=<yourhash> --phraseapp_api_key=<yourkey> --file-format=json <path_to_locales>
|
84
|
-
```
|
85
|
-
|
86
|
-
**Synchronize**
|
87
|
-
|
88
|
-
`phraseapp_updater synchronize` synchronizes a git remote branch with its
|
89
|
-
corresponding PhraseApp project, incorporating changes from each side into the
|
90
|
-
other. If both sides were changed, a three-way merge is performed. The result is
|
91
|
-
uploaded to PhraseApp and committed and pushed to the git remote as appropriate.
|
92
|
-
|
93
|
-
The option `--no_commit` may be provided to restrict changes to the PhraseApp
|
94
|
-
side. If specified, then in the case that the branch was modified, the merge
|
95
|
-
result will be uploaded to PhraseApp and the common ancestor updated to the
|
96
|
-
branch head.
|
97
|
-
|
98
|
-
```
|
99
|
-
phraseapp_updater synchronize <checkout_path> --prefix=config/locales --phraseapp_project_id=<yourid> --phraseapp_api_key=<yourkey> --file-format=json
|
100
|
-
```
|
101
|
-
|
102
|
-
**Download**
|
103
|
-
|
104
|
-
`phraseapp_updater download` downloads and normalizes locale files from
|
105
|
-
PhraseApp, saving them to the specified location. The revision of the recorded
|
106
|
-
common ancestor is printed to standard out.
|
107
|
-
|
108
|
-
```
|
109
|
-
phraseapp_updater download --phraseapp_project_id=<yourid> --phraseapp_api_key=<yourkey> --file-format=json <target_path>
|
110
|
-
```
|
111
|
-
|
112
|
-
**Upload**
|
113
|
-
|
114
|
-
`phraseapp_updater upload` uploads normalized locale files from your branch to
|
115
|
-
PhraseApp and resets the recorded common ancestor to the specified revision.
|
116
|
-
|
117
|
-
```
|
118
|
-
phraseapp_updater upload --phraseapp_project_id=<yourid> --phraseapp_api_key=<yourkey> --file-format=json <path_to_locales>
|
119
|
-
```
|
120
|
-
|
121
|
-
**Update Parent Commit**
|
122
|
-
`phraseapp_updater update_parent_commit` records a new common ancestor on
|
123
|
-
PhraseApp without changing the locales.
|
124
|
-
|
125
|
-
```
|
126
|
-
phraseapp_updater update_parent_commit --phraseapp_project_id=<yourid> --phraseapp_api_key=<yourkey> --parent_commit=<yournewhash>
|
127
|
-
```
|
128
|
-
|
129
|
-
**Merge**
|
130
|
-
|
131
|
-
`phraseapp_updater merge` performs a content-aware three-way merge between
|
132
|
-
locale files in three directories: `ancestor_path`, `our_path`, and
|
133
|
-
`their_path`. In the case of conflicts, the changes from `our_path` are
|
134
|
-
accepted. The results are normalized and written to the path specified with
|
135
|
-
`to`.
|
136
|
-
|
137
|
-
```
|
138
|
-
phraseapp_updater merge ancestor_path our_path their_path --to target_path --file-format=json
|
139
|
-
```
|
140
|
-
|
141
|
-
|
142
|
-
**Diff**
|
143
|
-
|
144
|
-
Performs a content-aware diff between locale files in two directories. Returns
|
145
|
-
with exit status 1 or 0 to signal differences or no differences respectively
|
146
|
-
|
147
|
-
```
|
148
|
-
phraseapp_updater diff path1 path2 --file-format=json
|
149
|
-
```
|
150
|
-
|
151
|
-
## Future Improvements
|
152
|
-
|
153
|
-
If you'd like to contribute, these would be very helpful!
|
154
|
-
|
155
|
-
* We'd like to use "unverified" translations on PhraseApp as the equivalent of
|
156
|
-
an unstaged working copy. For this to work, we need to be able to recover
|
157
|
-
previous translations at the same key. While PhraseApp doesn't itself keep
|
158
|
-
this history, we could do this by restoring the absent keys from the diff
|
159
|
-
between verified and unverified download from the common ancestor.
|
160
|
-
* Expose the changed files on the command line.
|
161
|
-
* Checking if PhraseApp files changed during execution before upload, to reduce the race condition window.
|
162
|
-
* More specs for the API and shell.
|
163
|
-
|
164
|
-
## Development
|
165
|
-
|
166
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
167
|
-
|
168
|
-
To install this gem onto your local machine, run `bundle exec rake install`. When everything is working, make a pull request.
|
169
|
-
|
170
|
-
## Contributing
|
171
|
-
|
172
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/iknow/phraseapp_updater. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
173
|
-
|
174
|
-
## License
|
175
|
-
|
176
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
177
|
-
|
data/Rakefile
DELETED
data/nix/gem/Gemfile
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
source "https://rubygems.org/"
|
2
|
-
|
3
|
-
gem "byebug", "11.0.1"
|
4
|
-
gem "coderay", "1.1.2"
|
5
|
-
gem "deep_merge", "1.2.1"
|
6
|
-
gem "diff-lcs", "1.3"
|
7
|
-
gem "hashdiff", "0.4.0"
|
8
|
-
gem "io-console", "0.5.4"
|
9
|
-
gem "irb", "1.2.1"
|
10
|
-
gem "method_source", "0.9.2"
|
11
|
-
gem "multi_json", "1.14.1"
|
12
|
-
gem "oj", "2.18.5"
|
13
|
-
gem "parallel", "1.19.1"
|
14
|
-
gem "phraseapp-ruby", "1.6.0"
|
15
|
-
gem "pry", "0.12.2"
|
16
|
-
gem "rake", "10.5.0"
|
17
|
-
gem "reline", "0.1.2"
|
18
|
-
gem "rspec", "3.8.0"
|
19
|
-
gem "rspec-core", "3.8.0"
|
20
|
-
gem "rspec-expectations", "3.8.3"
|
21
|
-
gem "rspec-mocks", "3.8.0"
|
22
|
-
gem "rspec-support", "3.8.0"
|
23
|
-
gem "rspec_junit_formatter", "0.4.1"
|
24
|
-
gem "thor", "0.20.3"
|
data/nix/gem/Gemfile.lock
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: https://rubygems.org/
|
3
|
-
specs:
|
4
|
-
byebug (11.0.1)
|
5
|
-
coderay (1.1.2)
|
6
|
-
deep_merge (1.2.1)
|
7
|
-
diff-lcs (1.3)
|
8
|
-
hashdiff (0.4.0)
|
9
|
-
io-console (0.5.4)
|
10
|
-
irb (1.2.1)
|
11
|
-
reline (>= 0.0.1)
|
12
|
-
method_source (0.9.2)
|
13
|
-
multi_json (1.14.1)
|
14
|
-
oj (2.18.5)
|
15
|
-
parallel (1.19.1)
|
16
|
-
phraseapp-ruby (1.6.0)
|
17
|
-
pry (0.12.2)
|
18
|
-
coderay (~> 1.1.0)
|
19
|
-
method_source (~> 0.9.0)
|
20
|
-
rake (10.5.0)
|
21
|
-
reline (0.1.2)
|
22
|
-
io-console (~> 0.5)
|
23
|
-
rspec (3.8.0)
|
24
|
-
rspec-core (~> 3.8.0)
|
25
|
-
rspec-expectations (~> 3.8.0)
|
26
|
-
rspec-mocks (~> 3.8.0)
|
27
|
-
rspec-core (3.8.0)
|
28
|
-
rspec-support (~> 3.8.0)
|
29
|
-
rspec-expectations (3.8.3)
|
30
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
-
rspec-support (~> 3.8.0)
|
32
|
-
rspec-mocks (3.8.0)
|
33
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
-
rspec-support (~> 3.8.0)
|
35
|
-
rspec-support (3.8.0)
|
36
|
-
rspec_junit_formatter (0.4.1)
|
37
|
-
rspec-core (>= 2, < 4, != 2.12.0)
|
38
|
-
thor (0.20.3)
|
39
|
-
|
40
|
-
PLATFORMS
|
41
|
-
ruby
|
42
|
-
|
43
|
-
DEPENDENCIES
|
44
|
-
byebug (= 11.0.1)
|
45
|
-
coderay (= 1.1.2)
|
46
|
-
deep_merge (= 1.2.1)
|
47
|
-
diff-lcs (= 1.3)
|
48
|
-
hashdiff (= 0.4.0)
|
49
|
-
io-console (= 0.5.4)
|
50
|
-
irb (= 1.2.1)
|
51
|
-
method_source (= 0.9.2)
|
52
|
-
multi_json (= 1.14.1)
|
53
|
-
oj (= 2.18.5)
|
54
|
-
parallel (= 1.19.1)
|
55
|
-
phraseapp-ruby (= 1.6.0)
|
56
|
-
pry (= 0.12.2)
|
57
|
-
rake (= 10.5.0)
|
58
|
-
reline (= 0.1.2)
|
59
|
-
rspec (= 3.8.0)
|
60
|
-
rspec-core (= 3.8.0)
|
61
|
-
rspec-expectations (= 3.8.3)
|
62
|
-
rspec-mocks (= 3.8.0)
|
63
|
-
rspec-support (= 3.8.0)
|
64
|
-
rspec_junit_formatter (= 0.4.1)
|
65
|
-
thor (= 0.20.3)
|
66
|
-
|
67
|
-
BUNDLED WITH
|
68
|
-
1.17.3
|
data/nix/gem/gemset.nix
DELETED
@@ -1,230 +0,0 @@
|
|
1
|
-
{
|
2
|
-
byebug = {
|
3
|
-
groups = ["default"];
|
4
|
-
platforms = [];
|
5
|
-
source = {
|
6
|
-
remotes = ["https://rubygems.org"];
|
7
|
-
sha256 = "1mmkls9n56l4gx2k0dnyianwz36z2zgpxli5bpsbr7jbw7hn2x6j";
|
8
|
-
type = "gem";
|
9
|
-
};
|
10
|
-
version = "11.0.1";
|
11
|
-
};
|
12
|
-
coderay = {
|
13
|
-
groups = ["default"];
|
14
|
-
platforms = [];
|
15
|
-
source = {
|
16
|
-
remotes = ["https://rubygems.org"];
|
17
|
-
sha256 = "15vav4bhcc2x3jmi3izb11l4d9f3xv8hp2fszb7iqmpsccv1pz4y";
|
18
|
-
type = "gem";
|
19
|
-
};
|
20
|
-
version = "1.1.2";
|
21
|
-
};
|
22
|
-
deep_merge = {
|
23
|
-
groups = ["default"];
|
24
|
-
platforms = [];
|
25
|
-
source = {
|
26
|
-
remotes = ["https://rubygems.org"];
|
27
|
-
sha256 = "1q3picw7zx1xdkybmrnhmk2hycxzaa0jv4gqrby1s90dy5n7fmsb";
|
28
|
-
type = "gem";
|
29
|
-
};
|
30
|
-
version = "1.2.1";
|
31
|
-
};
|
32
|
-
diff-lcs = {
|
33
|
-
groups = ["default"];
|
34
|
-
platforms = [];
|
35
|
-
source = {
|
36
|
-
remotes = ["https://rubygems.org"];
|
37
|
-
sha256 = "18w22bjz424gzafv6nzv98h0aqkwz3d9xhm7cbr1wfbyas8zayza";
|
38
|
-
type = "gem";
|
39
|
-
};
|
40
|
-
version = "1.3";
|
41
|
-
};
|
42
|
-
hashdiff = {
|
43
|
-
groups = ["default"];
|
44
|
-
platforms = [];
|
45
|
-
source = {
|
46
|
-
remotes = ["https://rubygems.org"];
|
47
|
-
sha256 = "1ncwxv7jbm3jj9phv6dd514463bkjwggxk10n2z100wf4cjcicrk";
|
48
|
-
type = "gem";
|
49
|
-
};
|
50
|
-
version = "0.4.0";
|
51
|
-
};
|
52
|
-
io-console = {
|
53
|
-
groups = ["default"];
|
54
|
-
platforms = [];
|
55
|
-
source = {
|
56
|
-
remotes = ["https://rubygems.org"];
|
57
|
-
sha256 = "109yzpv9kslwra2mxnjsg3r6mwxkbqmxihj266qdvccapghi05wg";
|
58
|
-
type = "gem";
|
59
|
-
};
|
60
|
-
version = "0.5.4";
|
61
|
-
};
|
62
|
-
irb = {
|
63
|
-
dependencies = ["reline"];
|
64
|
-
groups = ["default"];
|
65
|
-
platforms = [];
|
66
|
-
source = {
|
67
|
-
remotes = ["https://rubygems.org"];
|
68
|
-
sha256 = "1r1y8i46qd5izdszzzn5jxvwvq00m89rk0hm8cs8f21p7nlwmh5w";
|
69
|
-
type = "gem";
|
70
|
-
};
|
71
|
-
version = "1.2.1";
|
72
|
-
};
|
73
|
-
method_source = {
|
74
|
-
groups = ["default"];
|
75
|
-
platforms = [];
|
76
|
-
source = {
|
77
|
-
remotes = ["https://rubygems.org"];
|
78
|
-
sha256 = "1pviwzvdqd90gn6y7illcdd9adapw8fczml933p5vl739dkvl3lq";
|
79
|
-
type = "gem";
|
80
|
-
};
|
81
|
-
version = "0.9.2";
|
82
|
-
};
|
83
|
-
multi_json = {
|
84
|
-
groups = ["default"];
|
85
|
-
platforms = [];
|
86
|
-
source = {
|
87
|
-
remotes = ["https://rubygems.org"];
|
88
|
-
sha256 = "0xy54mjf7xg41l8qrg1bqri75agdqmxap9z466fjismc1rn2jwfr";
|
89
|
-
type = "gem";
|
90
|
-
};
|
91
|
-
version = "1.14.1";
|
92
|
-
};
|
93
|
-
oj = {
|
94
|
-
groups = ["default"];
|
95
|
-
platforms = [];
|
96
|
-
source = {
|
97
|
-
remotes = ["https://rubygems.org"];
|
98
|
-
sha256 = "1jli4mi1xpmm8564pc09bfvv7znzqghidwa3zfw21r365ihmbv2p";
|
99
|
-
type = "gem";
|
100
|
-
};
|
101
|
-
version = "2.18.5";
|
102
|
-
};
|
103
|
-
parallel = {
|
104
|
-
groups = ["default"];
|
105
|
-
platforms = [];
|
106
|
-
source = {
|
107
|
-
remotes = ["https://rubygems.org"];
|
108
|
-
sha256 = "12jijkap4akzdv11lm08dglsc8jmc87xcgq6947i1s3qb69f4zn2";
|
109
|
-
type = "gem";
|
110
|
-
};
|
111
|
-
version = "1.19.1";
|
112
|
-
};
|
113
|
-
phraseapp-ruby = {
|
114
|
-
groups = ["default"];
|
115
|
-
platforms = [];
|
116
|
-
source = {
|
117
|
-
remotes = ["https://rubygems.org"];
|
118
|
-
sha256 = "14n2hhwjn32xk0qk6rprs3awnrddhnd4zckyd0a4j8lv8k648pnn";
|
119
|
-
type = "gem";
|
120
|
-
};
|
121
|
-
version = "1.6.0";
|
122
|
-
};
|
123
|
-
pry = {
|
124
|
-
dependencies = ["coderay" "method_source"];
|
125
|
-
groups = ["default"];
|
126
|
-
platforms = [];
|
127
|
-
source = {
|
128
|
-
remotes = ["https://rubygems.org"];
|
129
|
-
sha256 = "00rm71x0r1jdycwbs83lf9l6p494m99asakbvqxh8rz7zwnlzg69";
|
130
|
-
type = "gem";
|
131
|
-
};
|
132
|
-
version = "0.12.2";
|
133
|
-
};
|
134
|
-
rake = {
|
135
|
-
groups = ["default"];
|
136
|
-
platforms = [];
|
137
|
-
source = {
|
138
|
-
remotes = ["https://rubygems.org"];
|
139
|
-
sha256 = "0jcabbgnjc788chx31sihc5pgbqnlc1c75wakmqlbjdm8jns2m9b";
|
140
|
-
type = "gem";
|
141
|
-
};
|
142
|
-
version = "10.5.0";
|
143
|
-
};
|
144
|
-
reline = {
|
145
|
-
dependencies = ["io-console"];
|
146
|
-
groups = ["default"];
|
147
|
-
platforms = [];
|
148
|
-
source = {
|
149
|
-
remotes = ["https://rubygems.org"];
|
150
|
-
sha256 = "0908ijrngc3wkn5iny7d0kxkp74w6ixk2nwzzngplplfla1vkp8x";
|
151
|
-
type = "gem";
|
152
|
-
};
|
153
|
-
version = "0.1.2";
|
154
|
-
};
|
155
|
-
rspec = {
|
156
|
-
dependencies = ["rspec-core" "rspec-expectations" "rspec-mocks"];
|
157
|
-
groups = ["default"];
|
158
|
-
platforms = [];
|
159
|
-
source = {
|
160
|
-
remotes = ["https://rubygems.org"];
|
161
|
-
sha256 = "15ppasvb9qrscwlyjz67ppw1lnxiqnkzx5vkx1bd8x5n3dhikxc3";
|
162
|
-
type = "gem";
|
163
|
-
};
|
164
|
-
version = "3.8.0";
|
165
|
-
};
|
166
|
-
rspec-core = {
|
167
|
-
dependencies = ["rspec-support"];
|
168
|
-
groups = ["default"];
|
169
|
-
platforms = [];
|
170
|
-
source = {
|
171
|
-
remotes = ["https://rubygems.org"];
|
172
|
-
sha256 = "1p1s5bnbqp3sxk67y0fh0x884jjym527r0vgmhbm81w7aq6b7l4p";
|
173
|
-
type = "gem";
|
174
|
-
};
|
175
|
-
version = "3.8.0";
|
176
|
-
};
|
177
|
-
rspec-expectations = {
|
178
|
-
dependencies = ["diff-lcs" "rspec-support"];
|
179
|
-
groups = ["default"];
|
180
|
-
platforms = [];
|
181
|
-
source = {
|
182
|
-
remotes = ["https://rubygems.org"];
|
183
|
-
sha256 = "1c4gs5ybf7km0qshdm92p38zvg32n1j2kr5fgs2icacz7xf2y6fy";
|
184
|
-
type = "gem";
|
185
|
-
};
|
186
|
-
version = "3.8.3";
|
187
|
-
};
|
188
|
-
rspec-mocks = {
|
189
|
-
dependencies = ["diff-lcs" "rspec-support"];
|
190
|
-
groups = ["default"];
|
191
|
-
platforms = [];
|
192
|
-
source = {
|
193
|
-
remotes = ["https://rubygems.org"];
|
194
|
-
sha256 = "06y508cjqycb4yfhxmb3nxn0v9xqf17qbd46l1dh4xhncinr4fyp";
|
195
|
-
type = "gem";
|
196
|
-
};
|
197
|
-
version = "3.8.0";
|
198
|
-
};
|
199
|
-
rspec-support = {
|
200
|
-
groups = ["default"];
|
201
|
-
platforms = [];
|
202
|
-
source = {
|
203
|
-
remotes = ["https://rubygems.org"];
|
204
|
-
sha256 = "0p3m7drixrlhvj2zpc38b11x145bvm311x6f33jjcxmvcm0wq609";
|
205
|
-
type = "gem";
|
206
|
-
};
|
207
|
-
version = "3.8.0";
|
208
|
-
};
|
209
|
-
rspec_junit_formatter = {
|
210
|
-
dependencies = ["rspec-core"];
|
211
|
-
groups = ["default"];
|
212
|
-
platforms = [];
|
213
|
-
source = {
|
214
|
-
remotes = ["https://rubygems.org"];
|
215
|
-
sha256 = "1aynmrgnv26pkprrajvp7advb8nbh0x4pkwk6jwq8qmwzarzk21p";
|
216
|
-
type = "gem";
|
217
|
-
};
|
218
|
-
version = "0.4.1";
|
219
|
-
};
|
220
|
-
thor = {
|
221
|
-
groups = ["default"];
|
222
|
-
platforms = [];
|
223
|
-
source = {
|
224
|
-
remotes = ["https://rubygems.org"];
|
225
|
-
sha256 = "1yhrnp9x8qcy5vc7g438amd5j9sw83ih7c30dr6g6slgw9zj3g29";
|
226
|
-
type = "gem";
|
227
|
-
};
|
228
|
-
version = "0.20.3";
|
229
|
-
};
|
230
|
-
}
|
data/nix/generate.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
#! /usr/bin/env nix-shell
|
2
|
-
#! nix-shell -i ruby -p ruby -p bundler -p bundix
|
3
|
-
# frozen_string_literal: true
|
4
|
-
|
5
|
-
# Bundix doesn't support `gemspec` directive in Gemfiles, as it doesn't copy the
|
6
|
-
# gemspec (and its dependencies) into the store.
|
7
|
-
# This workaround is from https://github.com/manveru/bundix/issues/10#issuecomment-405879379
|
8
|
-
|
9
|
-
require 'shellwords'
|
10
|
-
|
11
|
-
def sh(*args)
|
12
|
-
warn args.shelljoin
|
13
|
-
system(*args) || raise
|
14
|
-
end
|
15
|
-
|
16
|
-
sh 'bundle', 'lock'
|
17
|
-
|
18
|
-
require 'fileutils'
|
19
|
-
require 'bundler'
|
20
|
-
|
21
|
-
lockfile = Bundler::LockfileParser.new(File.read('Gemfile.lock'))
|
22
|
-
gems = lockfile.specs.select { |spec| spec.source.is_a?(Bundler::Source::Rubygems) }
|
23
|
-
sources = [URI('https://rubygems.org/')] | gems.map(&:source).flat_map(&:remotes)
|
24
|
-
|
25
|
-
FileUtils.mkdir_p 'nix/gem'
|
26
|
-
Dir.chdir 'nix/gem' do
|
27
|
-
['Gemfile', 'Gemfile.lock', 'gemset.nix'].each do |f|
|
28
|
-
File.delete(f) if File.exist?(f)
|
29
|
-
end
|
30
|
-
|
31
|
-
File.open('Gemfile', 'w') do |gemfile|
|
32
|
-
sources.each { |source| gemfile.puts "source #{source.to_s.inspect}" }
|
33
|
-
gemfile.puts
|
34
|
-
|
35
|
-
gems.each do |gem|
|
36
|
-
gemfile.puts "gem #{gem.name.inspect}, #{gem.version.to_s.inspect}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
sh 'bundix', '-l'
|
41
|
-
end
|
data/phraseapp_updater.gemspec
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'phraseapp_updater/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "phraseapp_updater"
|
8
|
-
spec.version = PhraseAppUpdater::VERSION
|
9
|
-
spec.authors = ["Kevin Griffin"]
|
10
|
-
spec.email = ["kev@bibo.com.ph"]
|
11
|
-
|
12
|
-
spec.summary = %q{A three-way differ for PhraseApp projects.}
|
13
|
-
spec.description = %q{A tool for merging data on PhraseApp with local changes (usually two git revisions)}
|
14
|
-
spec.homepage = "https://app.engoo.com"
|
15
|
-
spec.license = "MIT"
|
16
|
-
|
17
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
-
spec.bindir = "bin"
|
19
|
-
spec.executables = ["phraseapp_updater"]
|
20
|
-
spec.require_paths = ["lib"]
|
21
|
-
|
22
|
-
spec.add_dependency "thor", "~> 0.19"
|
23
|
-
spec.add_dependency "phraseapp-ruby", "~> 1.3"
|
24
|
-
spec.add_dependency "hashdiff", "~> 0.3"
|
25
|
-
spec.add_dependency "multi_json", "~> 1.12"
|
26
|
-
spec.add_dependency "oj", "~> 2.18"
|
27
|
-
spec.add_dependency "deep_merge", "~> 1.1"
|
28
|
-
spec.add_dependency "parallel", "~> 1.12"
|
29
|
-
|
30
|
-
spec.add_development_dependency "bundler", "~> 2.2"
|
31
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
33
|
-
spec.add_development_dependency "pry", "~> 0.10"
|
34
|
-
end
|
35
|
-
|