Skip to content

Commit 3369ab8

Browse files
authored
Add strings minification command (#45)
1 parent f39269f commit 3369ab8

File tree

3 files changed

+172
-0
lines changed

3 files changed

+172
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
require 'dry/cli'
2+
require 'xcodeproj'
3+
4+
module EmergeCLI
5+
module Commands
6+
module Autofixes
7+
class MinifyStrings < EmergeCLI::Commands::GlobalOptions
8+
desc 'Minify strings in the app'
9+
10+
option :path, type: :string, required: true, desc: 'Path to the xcarchive'
11+
12+
# Constants
13+
SCRIPT_NAME = 'EmergeTools Minify Strings'.freeze
14+
ENABLE_USER_SCRIPT_SANDBOXING = 'ENABLE_USER_SCRIPT_SANDBOXING'.freeze
15+
STRINGS_FILE_OUTPUT_ENCODING = 'STRINGS_FILE_OUTPUT_ENCODING'.freeze
16+
STRINGS_FILE_OUTPUT_ENCODING_VALUE = 'UTF-8'.freeze
17+
SCRIPT_CONTENT = %{import os
18+
import json
19+
from multiprocessing.pool import ThreadPool
20+
21+
def minify(file_path):
22+
os.system(f"plutil -convert json '{file_path}'")
23+
new_content = ''
24+
try:
25+
with open(file_path, 'r') as input_file:
26+
data = json.load(input_file)
27+
28+
for key, value in data.items():
29+
fixed_key = json.dumps(key, ensure_ascii=False).encode('utf8').decode()
30+
fixed_value = json.dumps(value, ensure_ascii=False).encode('utf8').decode()
31+
new_line = f'{fixed_key} = {fixed_value};\\n'
32+
new_content += new_line
33+
34+
with open(file_path, 'w') as output_file:
35+
output_file.write(new_content)
36+
except:
37+
return
38+
39+
file_extension = '.strings'
40+
stringFiles = []
41+
42+
for root, _, files in os.walk(os.environ['BUILT_PRODUCTS_DIR'], followlinks=True):
43+
for filename in files:
44+
if filename.endswith(file_extension):
45+
input_path = os.path.join(root, filename)
46+
stringFiles.append(input_path)
47+
48+
# create a thread pool
49+
with ThreadPool() as pool:
50+
pool.map(minify, stringFiles)
51+
}.freeze
52+
53+
def call(**options)
54+
@options = options
55+
before(options)
56+
57+
raise 'Path must be an xcodeproj' unless @options[:path].end_with?('.xcodeproj')
58+
raise 'Path does not exist' unless File.exist?(@options[:path])
59+
60+
Sync do
61+
project = Xcodeproj::Project.open(@options[:path])
62+
63+
project.targets.each do |target|
64+
target.build_configurations.each do |config|
65+
enable_user_script_sandboxing(config)
66+
set_output_encoding(config)
67+
end
68+
69+
add_run_script(target)
70+
end
71+
72+
project.save
73+
end
74+
end
75+
76+
private
77+
78+
def enable_user_script_sandboxing(config)
79+
Logger.info "Enabling user script sandboxing for #{config.name}"
80+
config.build_settings[ENABLE_USER_SCRIPT_SANDBOXING] = 'NO'
81+
end
82+
83+
def set_output_encoding(config)
84+
Logger.info "Setting output encoding for #{config.name}"
85+
config.build_settings[STRINGS_FILE_OUTPUT_ENCODING] = STRINGS_FILE_OUTPUT_ENCODING_VALUE
86+
end
87+
88+
def add_run_script(target)
89+
phase = target.shell_script_build_phases.find { |item| item.name == SCRIPT_NAME }
90+
return unless phase.nil?
91+
Logger.info "Creating script '#{SCRIPT_NAME}'"
92+
phase = target.new_shell_script_build_phase(SCRIPT_NAME)
93+
phase.shell_script = SCRIPT_CONTENT
94+
phase.shell_path = `which python3`.strip
95+
end
96+
end
97+
end
98+
end
99+
end

lib/emerge_cli.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
require_relative 'commands/order_files/validate_xcode_project'
1717
require_relative 'commands/upload/build'
1818
require_relative 'commands/build_distribution/validate_app'
19+
require_relative 'commands/autofixes/minify_strings'
1920

2021
require_relative 'reaper/ast_parser'
2122
require_relative 'reaper/code_deleter'
@@ -66,6 +67,10 @@ module EmergeCLI
6667
register 'build-distribution' do |prefix|
6768
prefix.register 'validate-app', Commands::BuildDistribution::ValidateApp
6869
end
70+
71+
register 'autofix' do |prefix|
72+
prefix.register 'minify-strings', Commands::Autofixes::MinifyStrings
73+
end
6974
end
7075

7176
# By default the log level is INFO, but can be overridden by the --debug flag
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
require 'test_helper'
2+
3+
module EmergeCLI
4+
module Commands
5+
module Autofixes
6+
class MinifyStringsTest < Minitest::Test
7+
SCRIPT_NAME = 'EmergeTools Minify Strings'.freeze
8+
ENABLE_USER_SCRIPT_SANDBOXING = 'ENABLE_USER_SCRIPT_SANDBOXING'.freeze
9+
STRINGS_FILE_OUTPUT_ENCODING = 'STRINGS_FILE_OUTPUT_ENCODING'.freeze
10+
STRINGS_FILE_OUTPUT_ENCODING_VALUE = 'UTF-8'.freeze
11+
12+
def setup
13+
@command = EmergeCLI::Commands::Autofixes::MinifyStrings.new
14+
15+
FileUtils.mkdir_p('tmp/test_autofix_strings')
16+
FileUtils.cp_r('test/test_files/ExampleApp.xcodeproj', 'tmp/test_autofix_strings/ExampleApp.xcodeproj')
17+
end
18+
19+
def teardown
20+
FileUtils.rm_rf('tmp/test_autofix_strings')
21+
end
22+
23+
def test_script_is_created
24+
options = {
25+
path: 'tmp/test_autofix_strings/ExampleApp.xcodeproj'
26+
}
27+
28+
@command.call(**options)
29+
30+
project = Xcodeproj::Project.open('tmp/test_autofix_strings/ExampleApp.xcodeproj')
31+
32+
phase = project.targets[0].shell_script_build_phases.find do |item|
33+
item.name == SCRIPT_NAME
34+
end
35+
assert_equal SCRIPT_NAME, phase.name
36+
end
37+
38+
def test_user_script_sandboxing_is_disabled
39+
options = {
40+
path: 'tmp/test_autofix_strings/ExampleApp.xcodeproj'
41+
}
42+
43+
@command.call(**options)
44+
45+
project = Xcodeproj::Project.open('tmp/test_autofix_strings/ExampleApp.xcodeproj')
46+
47+
project.targets[0].build_configurations.each do |config|
48+
assert_equal 'NO', config.build_settings[ENABLE_USER_SCRIPT_SANDBOXING]
49+
end
50+
end
51+
52+
def test_strings_encoding_is_utf8
53+
options = {
54+
path: 'tmp/test_autofix_strings/ExampleApp.xcodeproj'
55+
}
56+
57+
@command.call(**options)
58+
59+
project = Xcodeproj::Project.open('tmp/test_autofix_strings/ExampleApp.xcodeproj')
60+
61+
project.targets[0].build_configurations.each do |config|
62+
assert_equal STRINGS_FILE_OUTPUT_ENCODING_VALUE, config.build_settings[STRINGS_FILE_OUTPUT_ENCODING]
63+
end
64+
end
65+
end
66+
end
67+
end
68+
end

0 commit comments

Comments
 (0)