phraseapp_updater 2.1.1 → 3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7c95df3029f6b77ecd8ea760f7d0cac9003879acfc04b9ac5674e47ea41d2cb
4
- data.tar.gz: 86f123de84997ba31604aa207ac51aa55e1ba9fc05758e2d89b4720d2be9d4e6
3
+ metadata.gz: f33deb3a77a37a47abdf44c354526cbe3ad3d10256bb2a046bf48922178187fd
4
+ data.tar.gz: f22f2ceed18653b09c24be4724707cdc40c39539535c226fd028bc03338437cd
5
5
  SHA512:
6
- metadata.gz: 2c3e5ccb85014ec287d027b41146c142bc7e291c07c7a00184375381983c00ba62988539314f37e194aeddf2e3ab7588f985c18ed019023c2324483121f35812
7
- data.tar.gz: 80bdb49e97c0e41d931b04689e6b95dac234975cff532937cc25c0237c55700703810f9146bed7a7cc26583f24a1de38a910f8339fc4a2f12bf4e8ee3bcf57fb
6
+ metadata.gz: 822cc67247e2e2752397127f6b4e5e0d893cdfc3c64a29f14067d2bc5b6e131f3924d5cad982960df65da4b47971c12ad43fc9caf9c9ff15e756a596a64c163e
7
+ data.tar.gz: a2e1152e1a376690722722d73c2654d4ab4e417530b66b86f7562cd0b17e54f06976a295bae601ec0d4ed1e8570a518eef9a37ff317f24001643e711c0365e6c
@@ -1,16 +1,22 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
3
  # Set up a working directory
4
- working_directory=$(mktemp -d -t phraseapp.XXXXXX)
4
+ working_directory=$(mktemp -d phraseapp.XXXXXX)
5
5
 
6
6
  function cleanup_working_directory(){
7
- rm -rf "${working_directory}"
7
+ local now archive
8
+ now="$(date "+%Y%m%d%H%M%S")"
9
+ archive="/tmp/phraseapp-updater-$now.tar.gz"
10
+ tar -C "$(dirname "$working_directory")" -czf "$archive" "$(basename "${working_directory}")"
11
+ rm -rf "${working_directory}"
12
+ echo "Working files saved to $archive"
8
13
  }
9
14
 
10
15
  trap "cleanup_working_directory" EXIT SIGINT
11
16
 
12
17
  function make_temporary_directory() {
13
- mktemp -d "${working_directory}/XXXXXXXX"
18
+ name="${1:-tmp}"
19
+ mktemp -d "${working_directory}/$name.XXXXXXXX"
14
20
  }
15
21
 
16
22
  function make_tree_from_directory() {
@@ -35,15 +41,15 @@ function make_tree_from_directory() {
35
41
  }
36
42
 
37
43
 
38
- function extract_commit() {
39
- extract_files "$1:${PREFIX}"
44
+ function extract_prefix_from_commit() {
45
+ extract_files "$1" "$2:${PREFIX}"
40
46
  }
41
47
 
42
48
  function extract_files() {
43
49
  local path
44
- path=$(make_temporary_directory)
50
+ path=$(make_temporary_directory "git.${1}.${2%%:*}")
45
51
 
46
- git archive --format=tar "$1" | tar -x -C "${path}"
52
+ git archive --format=tar "$2" | tar -x -C "${path}"
47
53
 
48
54
  echo "${path}"
49
55
  }
@@ -34,7 +34,7 @@ if [ "$local_branch" ] && [ "$current_branch" != "$local_branch" ]; then
34
34
  fi
35
35
 
36
36
  # First, fetch the current contents of PhraseApp's staged ("verified") state.
37
- current_phraseapp_path=$(make_temporary_directory)
37
+ current_phraseapp_path=$(make_temporary_directory phraseapp_download)
38
38
  common_ancestor=$(phraseapp_updater download "${current_phraseapp_path}" \
39
39
  --phraseapp_api_key="${PHRASEAPP_API_KEY}" \
40
40
  --phraseapp_project_id="${PHRASEAPP_PROJECT_ID}" \
@@ -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=$(extract_commit "${current_branch}")
65
- common_ancestor_path=$(extract_commit "${common_ancestor}")
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
 
@@ -87,7 +87,7 @@ if [ "${phraseapp_changed}" = 't' ] && [ "${branch_changed}" = 't' ]; then
87
87
  echo "$BRANCH branch and PhraseApp both changed: 3-way merging" >&2
88
88
 
89
89
  # 3-way merge
90
- merge_resolution_path=$(make_temporary_directory)
90
+ merge_resolution_path=$(make_temporary_directory merge_resolution)
91
91
  phraseapp_updater merge "${common_ancestor_path}" "${current_branch_path}" "${current_phraseapp_path}" \
92
92
  --to "${merge_resolution_path}" \
93
93
  --verbose="${VERBOSE}" \
@@ -2,7 +2,8 @@
2
2
 
3
3
  require 'phraseapp_updater/locale_file'
4
4
  require 'phraseapp_updater/index_by'
5
- require 'phraseapp-ruby'
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
- @client = PhraseApp::Client.new(PhraseApp::Auth::Credentials.new(token: api_key))
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 = PhraseApp::RequestParams::ProjectParams.new(
29
+ params = Phrase::ProjectCreateParameters.new(
23
30
  name: name,
24
31
  main_format: @locale_file_class.phraseapp_type)
25
- project = phraseapp_request { @client.project_create(params) }
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, = paginate_request(:projects_list, limit: 1) { |p| p.name == name }
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, = paginate_request(:tags_list, @project_id, limit: 1) do |t|
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 do
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
- # This is a paginated API, however the maximum page size of 100 is well
62
- # above our expected locale size, so we take the first page only for now
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
- phraseapp_request do
70
- params = PhraseApp::RequestParams::LocaleParams.new(
71
- name: name,
72
- code: name,
73
- default: default,
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
- download_file(locale, skip_unverified)
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
- known_locales = fetch_locales.index_by(&:name)
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
- default: (locale_file.locale_name == default_locale))
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
- STDERR.puts "Uploading #{locale_file}"
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 download_file(locale, skip_unverified)
112
- download_params = PhraseApp::RequestParams::LocaleDownloadParams.new
113
-
114
- download_params.file_format = @locale_file_class.phraseapp_type
115
- download_params.skip_unverified_translations = skip_unverified
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
- phraseapp_request { @client.locale_download(@project_id, locale.id, download_params) }
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
- upload_params.file = f.path
130
- phraseapp_request { @client.upload_create(@project_id, upload_params) }.id
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
- delete_params = PhraseApp::RequestParams::KeysDeleteParams.new
136
- delete_params.q = "unmentioned_in_upload:#{upload_id}"
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 = PhraseApp::RequestParams::TagParams.new(
154
- name: GIT_TAG_PREFIX + commit_hash)
155
- phraseapp_request { @client.tag_create(@project_id, params) }
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 paginate_request(method, *params, limit: nil, &filter)
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 = phraseapp_request do
164
- @client.public_send(method, *params, page, PAGE_SIZE)
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.filter(&filter)
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
- break if results.size == limit
176
- end
240
+ break if results.size == limit
241
+ break unless response.next_page?
177
242
 
178
- page += 1
243
+ page = response.next_page
179
244
  end
180
245
 
181
246
  results
182
247
  end
183
248
 
184
- def phraseapp_request(&block)
185
- res, err = block.call
249
+ def phraseapp_request(api_class, method, *params, **opts)
250
+ api_instance = api_class.new(@client)
186
251
 
187
- unless err.nil?
188
- error =
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
- res
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class PhraseAppUpdater
4
- VERSION = '2.1.1'
4
+ VERSION = '3.0.0'
5
5
  end
@@ -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
- default_locale_index = locale_files.find_index { |f| f.locale_name == @default_locale }
106
- raise RuntimeError.new("Missing default locale") unless default_locale_index
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[default_locale_index]
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: 2.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Kevin Griffin
7
+ - iKnow Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-23 00:00:00.000000000 Z
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: phraseapp-ruby
28
+ name: phrase
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.3'
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: '1.3'
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: '0.3'
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: '0.3'
54
+ version: 1.0.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: multi_json
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '1.12'
117
+ version: '2.2'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '1.12'
124
+ version: '2.2'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rake
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -167,22 +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
- - kev@bibo.com.ph
170
+ - systems@iknow.jp
171
171
  executables:
172
172
  - phraseapp_updater
173
173
  extensions: []
174
174
  extra_rdoc_files: []
175
175
  files:
176
- - ".circleci/config.yml"
177
- - ".envrc"
178
- - ".gitignore"
179
- - ".rspec"
180
- - ".travis.yml"
181
- - CODE_OF_CONDUCT.markdown
182
- - Gemfile
183
176
  - LICENSE.txt
184
- - README.markdown
185
- - Rakefile
186
177
  - bin/console
187
178
  - bin/phraseapp_common.sh
188
179
  - bin/phraseapp_updater
@@ -197,13 +188,7 @@ files:
197
188
  - lib/phraseapp_updater/phraseapp_api.rb
198
189
  - lib/phraseapp_updater/version.rb
199
190
  - lib/phraseapp_updater/yml_config_loader.rb
200
- - nix/gem/Gemfile
201
- - nix/gem/Gemfile.lock
202
- - nix/gem/gemset.nix
203
- - nix/generate.rb
204
- - phraseapp_updater.gemspec
205
- - shell.nix
206
- homepage: https://app.engoo.com
191
+ homepage: https://github.com/iknow/phraseapp_updater
207
192
  licenses:
208
193
  - MIT
209
194
  metadata: {}
@@ -222,7 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
207
  - !ruby/object:Gem::Version
223
208
  version: '0'
224
209
  requirements: []
225
- rubygems_version: 3.0.3
210
+ rubygems_version: 3.1.6
226
211
  signing_key:
227
212
  specification_version: 4
228
213
  summary: A three-way differ for PhraseApp projects.