phraseapp_updater 2.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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.