spinjector 0.0.2 → 0.0.6
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 +4 -4
- data/.gitignore +1 -0
- data/Examples/Configuration/helloworld.yaml +8 -0
- data/Examples/Configuration/helloworld_explicit_script.yaml +9 -0
- data/Examples/Configuration/helloworld_short.yaml +3 -0
- data/Examples/Configuration/spinjector_configuration.yaml +18 -0
- data/Examples/Images/build_phases.png +0 -0
- data/Examples/Images/hello_world_explicit.png +0 -0
- data/Examples/Scripts/helloworld.sh +1 -0
- data/Makefile +11 -0
- data/README.md +88 -0
- data/lib/spinjector/entity/configuration.rb +9 -0
- data/lib/spinjector/entity/script.rb +45 -0
- data/lib/spinjector/entity/target.rb +10 -0
- data/lib/spinjector/project_service.rb +120 -0
- data/lib/spinjector/script_mapper.rb +36 -0
- data/lib/spinjector/yaml_parser.rb +65 -0
- data/lib/spinjector.rb +18 -125
- data/spinjector.gemspec +6 -2
- metadata +61 -6
- data/README +0 -0
- data/spinjector-0.0.1.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c73f5e26de7982019f85fa697d310590caf4750b75981e7bbcef7023a27e6c8c
|
4
|
+
data.tar.gz: 81933229a9142400ad0ae4ca2c9494064a384a73d9d88d091fda299749ddda5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e766f518c4d1420ffaa5a28b4eedc69a9d4e94836bf0f5574cbc257efcb332f5797b77597681f04ee9824016498069a66eaebd3548f584a24befc4f5576fbc9
|
7
|
+
data.tar.gz: 61a8228e352c8c3f06770fcde3c5aeef9ffa3068b16986beb4cef7c91fa5e16e5c57bdd8ff2d566638fb914fe254c400da0f99f2f03ea4075aea74408bb022bc
|
data/.gitignore
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
@@ -0,0 +1,18 @@
|
|
1
|
+
scripts:
|
2
|
+
foo:
|
3
|
+
name: "Foo"
|
4
|
+
script_path: "Scripts/helloworld.sh"
|
5
|
+
bar:
|
6
|
+
name: "Bar"
|
7
|
+
script: |
|
8
|
+
echo Bar
|
9
|
+
execution_position: :after_compile
|
10
|
+
|
11
|
+
targets:
|
12
|
+
TargetNameA:
|
13
|
+
- foo
|
14
|
+
- "helloworld.yaml"
|
15
|
+
- bar
|
16
|
+
- "helloworld_explicit_script.yaml"
|
17
|
+
TargetNameB:
|
18
|
+
- "helloworld_short.yaml"
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
echo "Hello World"
|
data/Makefile
ADDED
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# spinjector
|
2
|
+
Inject Script phase in your Xcode project easily.
|
3
|
+
|
4
|
+
# How to install
|
5
|
+
|
6
|
+
```
|
7
|
+
gem install spinjector
|
8
|
+
```
|
9
|
+
|
10
|
+
# How to use
|
11
|
+
## Global configuration file
|
12
|
+
First, create a YAML configuration file under `./Configuration/spinjector_configuration.yaml` (default path where spinjector looks for a configuration file).
|
13
|
+
|
14
|
+
```
|
15
|
+
scripts:
|
16
|
+
foo:
|
17
|
+
name: "Foo"
|
18
|
+
script: |
|
19
|
+
echo Foo
|
20
|
+
execution_position: :after_compile
|
21
|
+
|
22
|
+
targets:
|
23
|
+
TargetNameA:
|
24
|
+
- foo
|
25
|
+
- "helloworld.yaml"
|
26
|
+
- "helloworld_explicit_script.yaml"
|
27
|
+
TargetNameB:
|
28
|
+
- "helloworld_short.yaml"
|
29
|
+
- foo
|
30
|
+
|
31
|
+
```
|
32
|
+
|
33
|
+
## Script configuration file
|
34
|
+
Then, for each script you want to inject in your Xcode project:
|
35
|
+
- You can use `scripts` section in the global configuration file to define your script directly (eg. `foo`)...
|
36
|
+
|
37
|
+
- ...Or create a script configuration file (eg. `helloworld.yaml`)
|
38
|
+
|
39
|
+
```
|
40
|
+
name: "Hello World" # required. Script phase name.
|
41
|
+
|
42
|
+
# One and only one :script_path or :script may appear.
|
43
|
+
# For now, it makes no sense to have 2 differents script sources.
|
44
|
+
script_path: "Script/helloworld.sh" # required. Script file path.
|
45
|
+
script: | # required. Script.
|
46
|
+
<some code lines>
|
47
|
+
<other code lines>
|
48
|
+
|
49
|
+
input_paths: # optional.
|
50
|
+
- ""
|
51
|
+
|
52
|
+
output_paths: # optional.
|
53
|
+
- ""
|
54
|
+
|
55
|
+
input_file_list_paths: # optional.
|
56
|
+
- ""
|
57
|
+
|
58
|
+
output_file_list_paths: # optional.
|
59
|
+
- ""
|
60
|
+
|
61
|
+
dependency_file: # optional.
|
62
|
+
|
63
|
+
execution_position: # optional. [:before-compile | :after-compile | :before-headers | :after-headers].
|
64
|
+
```
|
65
|
+
|
66
|
+
- If you use the `script_path option`, create the script file
|
67
|
+
```
|
68
|
+
echo Hello World
|
69
|
+
```
|
70
|
+
|
71
|
+
## Execution
|
72
|
+
Finally, inject script phases
|
73
|
+
```
|
74
|
+
spinjector [-c] <path-to-your-global-configuration-file>
|
75
|
+
```
|
76
|
+
|
77
|
+
Enjoy your build phases
|
78
|
+

|
79
|
+

|
80
|
+
|
81
|
+
## How to contribute
|
82
|
+
|
83
|
+
1. After all your changes are reviewed and merged
|
84
|
+
2. Create a `release` branch
|
85
|
+
3. Update the version in field `s.version` from file `spinjector.gemspec`
|
86
|
+
4. Execute `make publish`
|
87
|
+
|
88
|
+
You may need to configure your account at step `4.` if you've never pushed any gem. You can find all the informations you need on [the official documentation](https://guides.rubygems.org/make-your-own-gem/#your-first-gem).
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
class Script
|
3
|
+
|
4
|
+
attr_reader :name, :source_code, :shell_path, :input_paths, :output_paths, :input_file_list_paths, :output_file_list_paths, :dependency_file, :execution_position, :show_env_vars_in_log
|
5
|
+
|
6
|
+
def initialize(
|
7
|
+
name,
|
8
|
+
source_code,
|
9
|
+
shell_path,
|
10
|
+
input_paths,
|
11
|
+
output_paths,
|
12
|
+
input_file_list_paths,
|
13
|
+
output_file_list_paths,
|
14
|
+
dependency_file,
|
15
|
+
execution_position,
|
16
|
+
show_env_vars_in_log
|
17
|
+
)
|
18
|
+
@name = name
|
19
|
+
@source_code = source_code
|
20
|
+
@shell_path = shell_path
|
21
|
+
@input_paths = input_paths
|
22
|
+
@output_paths = output_paths
|
23
|
+
@input_file_list_paths = input_file_list_paths
|
24
|
+
@output_file_list_paths = output_file_list_paths
|
25
|
+
@dependency_file = dependency_file
|
26
|
+
@execution_position = execution_position
|
27
|
+
@show_env_vars_in_log = show_env_vars_in_log
|
28
|
+
verify()
|
29
|
+
end
|
30
|
+
|
31
|
+
def verify
|
32
|
+
verify_execution_position()
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify_execution_position
|
36
|
+
case execution_position
|
37
|
+
when :before_compile, :before_headers
|
38
|
+
true
|
39
|
+
when :after_compile, :after_headers
|
40
|
+
false
|
41
|
+
else
|
42
|
+
raise ArgumentError, "Unknown execution position `#{execution_position}`"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
require_relative 'entity/configuration'
|
3
|
+
require_relative 'entity/script'
|
4
|
+
require_relative 'entity/target'
|
5
|
+
|
6
|
+
# @return [String] prefix used for all the build phase injected by this script
|
7
|
+
# [SPI] stands for Script Phase Injector
|
8
|
+
#
|
9
|
+
BUILD_PHASE_PREFIX = '[SPI] '.freeze
|
10
|
+
|
11
|
+
class ProjectService
|
12
|
+
|
13
|
+
# @param [Xcodeproj::Project] project
|
14
|
+
#
|
15
|
+
def initialize(project)
|
16
|
+
@project = project
|
17
|
+
end
|
18
|
+
|
19
|
+
# Remove all script phases prefixed by BUILD_PHASE_PREFIX from project
|
20
|
+
#
|
21
|
+
def remove_all_scripts
|
22
|
+
@project.targets.each do |target|
|
23
|
+
# Delete script phases no longer present in the target.
|
24
|
+
native_target_script_phases = target.shell_script_build_phases.select do |bp|
|
25
|
+
!bp.name.nil? && bp.name.start_with?(BUILD_PHASE_PREFIX)
|
26
|
+
end
|
27
|
+
native_target_script_phases.each do |script_phase|
|
28
|
+
target.build_phases.delete(script_phase)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [Configuration] configuration containing all scripts to add in each target
|
34
|
+
#
|
35
|
+
def add_scripts_in_targets(configuration)
|
36
|
+
configuration.targets.each do |target|
|
37
|
+
xcode_target = app_target(target.name)
|
38
|
+
add_scripts_in_target(target.scripts, xcode_target)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# @param [String] target_name
|
45
|
+
# @return [Xcodeproj::Project::Object::PBXNativeTarget] the target named by target_name
|
46
|
+
#
|
47
|
+
def app_target(target_name)
|
48
|
+
target = @project.targets.find { |t| t.name == target_name }
|
49
|
+
raise "[Error] Invalid #{target_name} target." unless !target.nil?
|
50
|
+
return target
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [Array<Script>] scripts the script phases defined in configuration files
|
54
|
+
# @param [Xcodeproj::Project::Object::PBXNativeTarget] target to add the script phases
|
55
|
+
#
|
56
|
+
def add_scripts_in_target(scripts, target)
|
57
|
+
scripts.each do |script|
|
58
|
+
name_with_prefix = BUILD_PHASE_PREFIX + script.name
|
59
|
+
phase = target.new_shell_script_build_phase(name_with_prefix)
|
60
|
+
phase.shell_script = script.source_code
|
61
|
+
phase.shell_path = script.shell_path
|
62
|
+
phase.input_paths = script.input_paths
|
63
|
+
phase.output_paths = script.output_paths
|
64
|
+
phase.input_file_list_paths = script.input_file_list_paths
|
65
|
+
phase.output_file_list_paths = script.output_file_list_paths
|
66
|
+
phase.dependency_file = script.dependency_file
|
67
|
+
# At least with Xcode 10 `showEnvVarsInLog` is *NOT* set to any value even if it's checked and it only
|
68
|
+
# gets set to '0' if the user has explicitly disabled this.
|
69
|
+
if script.show_env_vars_in_log == '0'
|
70
|
+
phase.show_env_vars_in_log = script.show_env_vars_in_log
|
71
|
+
end
|
72
|
+
execution_position = script.execution_position
|
73
|
+
reorder_script_phase(target, phase, execution_position)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param [Xcodeproj::Project::Object::PBXNativeTarget] target where build phases should be reordered
|
78
|
+
# @param [Hash] script_phase to reorder
|
79
|
+
# @param [Symbol] execution_position could be :before_compile, :after_compile, :before_headers, :after_headers
|
80
|
+
#
|
81
|
+
def reorder_script_phase(target, script_phase, execution_position)
|
82
|
+
return if execution_position == :any || execution_position.to_s.empty?
|
83
|
+
|
84
|
+
# Find the point P where to add the script phase
|
85
|
+
target_phase_type = case execution_position
|
86
|
+
when :before_compile, :after_compile
|
87
|
+
Xcodeproj::Project::Object::PBXSourcesBuildPhase
|
88
|
+
when :before_headers, :after_headers
|
89
|
+
Xcodeproj::Project::Object::PBXHeadersBuildPhase
|
90
|
+
else
|
91
|
+
raise ArgumentError, "Unknown execution position `#{execution_position}`"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Decide whether to add script_phase before or after point P
|
95
|
+
order_before = case execution_position
|
96
|
+
when :before_compile, :before_headers
|
97
|
+
true
|
98
|
+
when :after_compile, :after_headers
|
99
|
+
false
|
100
|
+
else
|
101
|
+
raise ArgumentError, "Unknown execution position `#{execution_position}`"
|
102
|
+
end
|
103
|
+
|
104
|
+
# Get the first build phase index of P
|
105
|
+
target_phase_index = target.build_phases.index do |bp|
|
106
|
+
bp.is_a?(target_phase_type)
|
107
|
+
end
|
108
|
+
return if target_phase_index.nil?
|
109
|
+
|
110
|
+
# Get the script phase we want to reorder index
|
111
|
+
script_phase_index = target.build_phases.index do |bp|
|
112
|
+
bp.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && !bp.name.nil? && bp.name == script_phase.name
|
113
|
+
end
|
114
|
+
|
115
|
+
# Move script phase to P if needed
|
116
|
+
if (order_before && script_phase_index > target_phase_index) || (!order_before && script_phase_index < target_phase_index)
|
117
|
+
target.build_phases.move_from(script_phase_index, target_phase_index)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'entity/script'
|
2
|
+
|
3
|
+
class ScriptMapper
|
4
|
+
|
5
|
+
def initialize(script_hash)
|
6
|
+
@script_hash = script_hash
|
7
|
+
verify_syntax
|
8
|
+
end
|
9
|
+
|
10
|
+
def map
|
11
|
+
script_code = @script_hash["script"] || load_script(@script_hash["script_path"])
|
12
|
+
Script.new(
|
13
|
+
@script_hash["name"],
|
14
|
+
script_code,
|
15
|
+
@script_hash["shell_path"] || '/bin/sh',
|
16
|
+
@script_hash["input_paths"] || [],
|
17
|
+
@script_hash["output_paths"] || [],
|
18
|
+
@script_hash["input_file_list_paths"] || [],
|
19
|
+
@script_hash["output_file_list_paths"] || [],
|
20
|
+
@script_hash["dependency_file"],
|
21
|
+
@script_hash["execution_position"] || :before_compile,
|
22
|
+
@script_hash["show_env_vars_in_log"]
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify_syntax
|
27
|
+
raise "[Error] Invalid script description #{@script_hash}" unless @script_hash.is_a?(Hash)
|
28
|
+
raise "[Error] Script must have a name and an associated script" unless @script_hash.has_key?("name") && @script_hash.has_key?("script") || @script_hash.has_key?("script_path")
|
29
|
+
raise "[Error] Invalid name in script #{@script_hash}" unless !@script_hash["name"].nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_script(path)
|
33
|
+
raise "[Error] File #{path} does not exist" unless !path.nil? && File.exist?(path)
|
34
|
+
File.read(path)
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require_relative 'entity/configuration'
|
3
|
+
require_relative 'entity/script'
|
4
|
+
require_relative 'entity/target'
|
5
|
+
require_relative 'script_mapper'
|
6
|
+
|
7
|
+
class YAMLParser
|
8
|
+
|
9
|
+
# The configuration to use in order to add scripts in your project
|
10
|
+
#
|
11
|
+
attr_reader :configuration
|
12
|
+
|
13
|
+
def initialize(yaml_file_path)
|
14
|
+
@configuration_description = load_yml_content(yaml_file_path)
|
15
|
+
@configuration = Configuration.new(targets)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def targets
|
21
|
+
if @configuration_description["targets"].nil?
|
22
|
+
puts "[Warning] There is no target in your configuration file."
|
23
|
+
return
|
24
|
+
end
|
25
|
+
@configuration_description["targets"].map do |target_name, script_entries|
|
26
|
+
if script_entries.nil?
|
27
|
+
puts "[Warning] There is no scripts in your configuration file under target #{target_name}"
|
28
|
+
return
|
29
|
+
end
|
30
|
+
scripts = script_entries.map do |entry|
|
31
|
+
get_script(entry)
|
32
|
+
end
|
33
|
+
Target.new(target_name, scripts)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_script(entry)
|
38
|
+
script =
|
39
|
+
if !@configuration_description["scripts"].nil? && !@configuration_description["scripts"][entry].nil?
|
40
|
+
get_script_by_name(entry)
|
41
|
+
elsif File.exist?(entry)
|
42
|
+
get_script_by_path(entry)
|
43
|
+
else
|
44
|
+
raise "[Error] Script #{entry} does not exist" unless !script.nil?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_script_by_name(name)
|
49
|
+
script_description = @configuration_description["scripts"][name]
|
50
|
+
ScriptMapper.new(script_description).map()
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_script_by_path(path)
|
54
|
+
script_description = load_yml_content(path)
|
55
|
+
ScriptMapper.new(script_description).map()
|
56
|
+
end
|
57
|
+
|
58
|
+
# @param [String] configuration_path
|
59
|
+
# @return [Hash] the hash in the configuration file
|
60
|
+
#
|
61
|
+
def load_yml_content(configuration_path)
|
62
|
+
raise "[Error] YAML file #{configuration_path} not found." unless File.exist?(configuration_path)
|
63
|
+
YAML.load(File.read(configuration_path)) || {}
|
64
|
+
end
|
65
|
+
end
|
data/lib/spinjector.rb
CHANGED
@@ -3,139 +3,32 @@
|
|
3
3
|
# @author Guillaume Berthier
|
4
4
|
#
|
5
5
|
|
6
|
+
require 'optparse'
|
6
7
|
require 'xcodeproj'
|
7
|
-
|
8
|
-
|
9
|
-
# @return [String] prefix used for all the build phase injected by this script
|
10
|
-
# [SPI] stands for Script Phase Injector
|
11
|
-
#
|
12
|
-
BUILD_PHASE_PREFIX = '[SPI] '.freeze
|
8
|
+
require_relative 'spinjector/project_service'
|
9
|
+
require_relative 'spinjector/yaml_parser'
|
13
10
|
|
14
11
|
CONFIGURATION_FILE_PATH = 'Configuration/spinjector_configuration.yaml'.freeze
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
project.targets.each do |target|
|
20
|
-
# Delete script phases no longer present in the target.
|
21
|
-
native_target_script_phases = target.shell_script_build_phases.select do |bp|
|
22
|
-
!bp.name.nil? && bp.name.start_with?(BUILD_PHASE_PREFIX)
|
23
|
-
end
|
24
|
-
native_target_script_phases.each do |script_phase|
|
25
|
-
target.build_phases.delete(script_phase)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# @param [Xcodeproj::Project] project
|
31
|
-
#
|
32
|
-
def inject_script_phases(project)
|
33
|
-
configuration_file = load_yml_content(CONFIGURATION_FILE_PATH)
|
34
|
-
configuration_file.each do |target_name, script_paths|
|
35
|
-
return unless !target_name.nil?
|
36
|
-
script_phases = (script_paths || []).flat_map do |script_path|
|
37
|
-
load_yml_content(script_path)
|
38
|
-
end
|
39
|
-
target = app_target(project, target_name)
|
40
|
-
create_script_phases(script_phases, target)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# @param [String] configuration_path
|
45
|
-
# @return [Hash] the hash in the configuration file
|
46
|
-
#
|
47
|
-
def load_yml_content(configuration_path)
|
48
|
-
if !File.exist?(configuration_path)
|
49
|
-
puts "Script phase #{configuration_path} unknown"
|
50
|
-
return {}
|
51
|
-
end
|
52
|
-
YAML.load(File.read(configuration_path)) || {}
|
53
|
-
end
|
54
|
-
|
55
|
-
# @param [Xcodeproj::Project] project
|
56
|
-
# @param [String] target_name
|
57
|
-
# @return [Xcodeproj::Project::Object::PBXNativeTarget] the target named by target_name
|
58
|
-
#
|
59
|
-
def app_target(project, target_name)
|
60
|
-
target = project.targets.find { |t| t.name == target_name }
|
61
|
-
puts "Invalid #{target_name} target." unless !target.nil?
|
62
|
-
return target
|
63
|
-
end
|
64
|
-
|
65
|
-
# @param [Array<Hash>] script_phases the script phases defined in configuration files
|
66
|
-
# @param [Xcodeproj::Project::Object::PBXNativeTarget] target to add the script phases
|
67
|
-
#
|
68
|
-
def create_script_phases(script_phases, target)
|
69
|
-
script_phases.each do |script_phase|
|
70
|
-
name_with_prefix = BUILD_PHASE_PREFIX + script_phase["name"]
|
71
|
-
phase = target.new_shell_script_build_phase(name_with_prefix)
|
72
|
-
script = File.read(script_phase["script_path"])
|
73
|
-
phase.shell_script = script
|
74
|
-
phase.shell_path = script_phase["shell_path"] || '/bin/sh'
|
75
|
-
phase.input_paths = script_phase["input_paths"]
|
76
|
-
phase.output_paths = script_phase["output_paths"]
|
77
|
-
phase.input_file_list_paths = script_phase["input_file_list_paths"]
|
78
|
-
phase.output_file_list_paths = script_phase["output_file_list_paths"]
|
79
|
-
phase.dependency_file = script_phase["dependency_file"]
|
80
|
-
# At least with Xcode 10 `showEnvVarsInLog` is *NOT* set to any value even if it's checked and it only
|
81
|
-
# gets set to '0' if the user has explicitly disabled this.
|
82
|
-
if (show_env_vars_in_log = script_phase.fetch("show_env_vars_in_log", '1')) == '0'
|
83
|
-
phase.show_env_vars_in_log = show_env_vars_in_log
|
84
|
-
end
|
13
|
+
options = {}
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.banner = "Usage: spinjector [options]"
|
85
16
|
|
86
|
-
|
87
|
-
|
17
|
+
opts.on("-cName", "--configuration-path=Name", "Inject scripts using configuration file at Name location. Default is ./#{CONFIGURATION_FILE_PATH}") do |config_path|
|
18
|
+
options[:configuration_path] = config_path
|
88
19
|
end
|
89
|
-
end
|
90
|
-
|
91
|
-
# @param [Xcodeproj::Project::Object::PBXNativeTarget] target where build phases should be reordered
|
92
|
-
# @param [Hash] script_phase to reorder
|
93
|
-
# @param [Symbol] execution_position could be :before_compile, :after_compile, :before_headers, :after_headers
|
94
|
-
#
|
95
|
-
def reorder_script_phase(target, script_phase, execution_position)
|
96
|
-
return if execution_position == :any || execution_position.to_s.empty?
|
20
|
+
end.parse!
|
97
21
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
Xcodeproj::Project::Object::PBXSourcesBuildPhase
|
102
|
-
when :before_headers, :after_headers
|
103
|
-
Xcodeproj::Project::Object::PBXHeadersBuildPhase
|
104
|
-
else
|
105
|
-
raise ArgumentError, "Unknown execution position `#{execution_position}`"
|
106
|
-
end
|
107
|
-
|
108
|
-
# Decide whether to add script_phase before or after point P
|
109
|
-
order_before = case execution_position
|
110
|
-
when :before_compile, :before_headers
|
111
|
-
true
|
112
|
-
when :after_compile, :after_headers
|
113
|
-
false
|
114
|
-
else
|
115
|
-
raise ArgumentError, "Unknown execution position `#{execution_position}`"
|
116
|
-
end
|
117
|
-
|
118
|
-
# Get the first build phase index of P
|
119
|
-
target_phase_index = target.build_phases.index do |bp|
|
120
|
-
bp.is_a?(target_phase_type)
|
121
|
-
end
|
122
|
-
return if target_phase_index.nil?
|
22
|
+
project_path = Dir.glob("*.xcodeproj").first
|
23
|
+
project = Xcodeproj::Project.open(project_path)
|
24
|
+
raise "[Error] No xcodeproj found" unless !project.nil?
|
123
25
|
|
124
|
-
|
125
|
-
|
126
|
-
bp.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && !bp.name.nil? && bp.name == script_phase.name
|
127
|
-
end
|
26
|
+
configuration_file_path = options[:configuration_path] || CONFIGURATION_FILE_PATH
|
27
|
+
configuration = YAMLParser.new(configuration_file_path).configuration
|
128
28
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
target.build_phases.move_from(script_phase_index, target_phase_index)
|
133
|
-
end
|
134
|
-
end
|
29
|
+
project_service = ProjectService.new(project)
|
30
|
+
project_service.remove_all_scripts()
|
31
|
+
project_service.add_scripts_in_targets(configuration)
|
135
32
|
|
136
|
-
project_path = Dir.glob("*.xcodeproj").first
|
137
|
-
project = Xcodeproj::Project.open(project_path)
|
138
|
-
remove_all_spi_script_phases(project)
|
139
|
-
inject_script_phases(project)
|
140
33
|
project.save()
|
141
|
-
puts "Success"
|
34
|
+
puts "Success."
|
data/spinjector.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'spinjector'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.6'
|
4
4
|
s.executables << 'spinjector'
|
5
5
|
s.summary = "Inject script phases into your Xcode project"
|
6
6
|
s.description = ""
|
@@ -8,6 +8,10 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.email = 'guillaume.berthier@fabernovel.com'
|
9
9
|
# use `git ls-files -coz -x *.gem` for development
|
10
10
|
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
11
|
-
s.homepage = 'https://
|
11
|
+
s.homepage = 'https://github.com/faberNovel/spinjector'
|
12
12
|
s.license = 'MIT'
|
13
|
+
|
14
|
+
s.add_dependency 'optparse', '~> 0.1'
|
15
|
+
s.add_dependency 'xcodeproj', '~> 1.21'
|
16
|
+
s.add_dependency 'yaml', '~> 0.2'
|
13
17
|
end
|
metadata
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spinjector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillaume Berthier, Fabernovel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2022-01-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: optparse
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: xcodeproj
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.21'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.21'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yaml
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.2'
|
13
55
|
description: ''
|
14
56
|
email: guillaume.berthier@fabernovel.com
|
15
57
|
executables:
|
@@ -18,12 +60,25 @@ extensions: []
|
|
18
60
|
extra_rdoc_files: []
|
19
61
|
files:
|
20
62
|
- ".gitignore"
|
21
|
-
-
|
63
|
+
- Examples/Configuration/helloworld.yaml
|
64
|
+
- Examples/Configuration/helloworld_explicit_script.yaml
|
65
|
+
- Examples/Configuration/helloworld_short.yaml
|
66
|
+
- Examples/Configuration/spinjector_configuration.yaml
|
67
|
+
- Examples/Images/build_phases.png
|
68
|
+
- Examples/Images/hello_world_explicit.png
|
69
|
+
- Examples/Scripts/helloworld.sh
|
70
|
+
- Makefile
|
71
|
+
- README.md
|
22
72
|
- bin/spinjector
|
23
73
|
- lib/spinjector.rb
|
24
|
-
- spinjector
|
74
|
+
- lib/spinjector/entity/configuration.rb
|
75
|
+
- lib/spinjector/entity/script.rb
|
76
|
+
- lib/spinjector/entity/target.rb
|
77
|
+
- lib/spinjector/project_service.rb
|
78
|
+
- lib/spinjector/script_mapper.rb
|
79
|
+
- lib/spinjector/yaml_parser.rb
|
25
80
|
- spinjector.gemspec
|
26
|
-
homepage: https://
|
81
|
+
homepage: https://github.com/faberNovel/spinjector
|
27
82
|
licenses:
|
28
83
|
- MIT
|
29
84
|
metadata: {}
|
data/README
DELETED
File without changes
|
data/spinjector-0.0.1.gem
DELETED
Binary file
|