Skip to content

Commit a45aaf1

Browse files
committed
Run xcstringstool via Open3 so the catalog scan output stays clean
fastlane's sh treats each call as an action: even with log: false it prints a '--- Step: shell command ---' banner per call and lists it in the run summary. extract is chunked into ~7 calls and sync runs twice, so that wrapped the real progress in a wall of banners. Run xcstringstool through Open3.capture2e instead (argv — safe for paths with spaces; captured output surfaced only on failure), via a run_xcstringstool helper. The scan now prints just its own progress lines.
1 parent 45a5965 commit a45aaf1

1 file changed

Lines changed: 13 additions & 5 deletions

File tree

fastlane/lanes/localization_catalog.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'json'
44
require 'tmpdir'
55
require 'fileutils'
6+
require 'open3'
67
require_relative 'catalog_helper'
78
require_relative 'catalog_strings_helper'
89

@@ -156,6 +157,15 @@ def catalog_excluded?(path)
156157
File.basename(path) == 'AppLocalizedString.swift'
157158
end
158159

160+
# Run `xcstringstool <args>` quietly via argv (no shell, so source paths with spaces are safe), capturing
161+
# output and surfacing it only on failure. Used instead of fastlane's `sh` for these bulk calls: each passes
162+
# hundreds of file paths (or a `--stringsdata` pair per file), so `sh` would echo a massive command line AND
163+
# print a "Step: shell command" banner per call. Open3 keeps the run silent and banner-free.
164+
def run_xcstringstool(*args)
165+
output, status = Open3.capture2e('xcrun', 'xcstringstool', *args)
166+
UI.user_error!("xcstringstool #{args.first} failed:\n#{output}") unless status.success?
167+
end
168+
159169
# xcstringstool extract -> one .stringsdata per source file (basename-disambiguated). Chunked to stay under
160170
# the OS argument limit; each chunk gets its own output subdir (see below), which sync then consumes together.
161171
# `--SwiftUI-Text` (extract `Text("literal")`) is OFF by default and gated behind `swiftui:`. The app has
@@ -179,8 +189,7 @@ def extract_stringsdata(files:, output_dir:, swiftui: false)
179189
chunk_dir = File.join(output_dir, "chunk-#{index}")
180190
FileUtils.mkdir_p(chunk_dir)
181191
UI.message("Extracting strings… (batch #{index + 1}/#{batches.size})")
182-
# log: false — each command lists up to 400 file paths; echoing them buries the output.
183-
sh('xcrun', 'xcstringstool', 'extract', *chunk, *flags, '--output-directory', chunk_dir, log: false)
192+
run_xcstringstool('extract', *chunk, *flags, '--output-directory', chunk_dir)
184193
end
185194
end
186195

@@ -198,8 +207,7 @@ def sync_localizable_catalog(stringsdata_dir:)
198207
UI.user_error!('xcstringstool produced no .stringsdata') if stringsdata.empty?
199208

200209
UI.message("Syncing #{stringsdata.count} extracted file(s) into #{File.basename(LOCALIZABLE_CATALOG)}…")
201-
# log: false — the command passes a `--stringsdata <path>` pair per file (thousands of args).
202-
sh('xcrun', 'xcstringstool', 'sync', LOCALIZABLE_CATALOG, *stringsdata.flat_map { |f| ['--stringsdata', f] }, log: false)
210+
run_xcstringstool('sync', LOCALIZABLE_CATALOG, *stringsdata.flat_map { |f| ['--stringsdata', f] })
203211
JSON.parse(File.read(LOCALIZABLE_CATALOG))['strings'].count
204212
end
205213

@@ -234,7 +242,7 @@ def current_english_values(stringsdata_dir)
234242
fresh = File.join(tmp, 'Localizable.xcstrings')
235243
File.write(fresh, "#{JSON.pretty_generate('sourceLanguage' => 'en', 'strings' => {}, 'version' => '1.0')}\n")
236244
stringsdata = stringsdata_files(stringsdata_dir)
237-
sh('xcrun', 'xcstringstool', 'sync', fresh, *stringsdata.flat_map { |f| ['--stringsdata', f] }, log: false)
245+
run_xcstringstool('sync', fresh, *stringsdata.flat_map { |f| ['--stringsdata', f] })
238246
english_values(JSON.parse(File.read(fresh)))
239247
end
240248
end

0 commit comments

Comments
 (0)