jump-starter 1.1.17 → 1.1.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +17 -1
- data/README.md +33 -1
- data/jumpstarter.gemspec +3 -0
- data/lib/jumpstarter_core/bash.rb +37 -0
- data/lib/jumpstarter_core/commandRunner.rb +7 -7
- data/lib/jumpstarter_core/commands.rb +0 -3
- data/lib/jumpstarter_core/git.rb +91 -0
- data/lib/jumpstarter_core/instructions.rb +53 -396
- data/lib/jumpstarter_core/parser.rb +163 -0
- data/lib/jumpstarter_core/pip.rb +57 -0
- data/lib/jumpstarter_core/setup.rb +65 -16
- data/lib/jumpstarter_core/version.rb +1 -1
- data/lib/jumpstarter_core/xcode.rb +105 -0
- data/lib/jumpstarter_core/xcode_helper.rb +40 -0
- metadata +36 -3
- data/LICENSE.txt +0 -21
@@ -0,0 +1,163 @@
|
|
1
|
+
require_relative './git'
|
2
|
+
require_relative './pip'
|
3
|
+
require_relative './bash'
|
4
|
+
require_relative './xcode'
|
5
|
+
|
6
|
+
module Jumpstarter
|
7
|
+
class InstructionParser
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Gets the arguments of a line
|
11
|
+
# --foo = variable/boolean/number
|
12
|
+
# --"foo" = String
|
13
|
+
# --"foo bar baz" = String
|
14
|
+
def get_args(line)
|
15
|
+
return Hash[line.scan(/--?([^=\s]+)(?:=(\"[^\"]+\"|\S+))?/)]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Parse each line individually
|
19
|
+
# If the command is recognized, create the corrisponding
|
20
|
+
# instruction class and call `compose!` on it
|
21
|
+
#
|
22
|
+
# `compose!` returns a string that is valid
|
23
|
+
# ruby code and can such be run
|
24
|
+
def parse(line)
|
25
|
+
|
26
|
+
inst_elm = line.split
|
27
|
+
|
28
|
+
## Read the command
|
29
|
+
cmd = inst_elm[0]
|
30
|
+
|
31
|
+
## Parse the arguments
|
32
|
+
args = InstructionParser.get_args(line)
|
33
|
+
|
34
|
+
## Arguments that apply to all commands
|
35
|
+
msg_success = args["msg_success"]
|
36
|
+
msg_error = args["msg_error"]
|
37
|
+
should_crash = args["should_crash"]
|
38
|
+
|
39
|
+
# Switch over the command finding the appropiate
|
40
|
+
# instruction. Once found, process the remaining
|
41
|
+
# inst_elm or args and feed them into the class
|
42
|
+
case cmd
|
43
|
+
when "pip"
|
44
|
+
package = inst_elm[1]
|
45
|
+
return Jumpstarter::Pip::Install.new(
|
46
|
+
package: package,
|
47
|
+
msg_success: msg_success,
|
48
|
+
msg_error: msg_error,
|
49
|
+
should_crash: should_crash
|
50
|
+
).compose!
|
51
|
+
when "git"
|
52
|
+
subcmd = inst_elm[1]
|
53
|
+
remote = inst_elm[2]
|
54
|
+
branch = inst_elm[3] if inst_elm[3]
|
55
|
+
case subcmd
|
56
|
+
when "fork"
|
57
|
+
return Jumpstarter::Git::Fork.new(
|
58
|
+
remote: remote,
|
59
|
+
username: args["username"],
|
60
|
+
password: args["password"],
|
61
|
+
msg_success: msg_success,
|
62
|
+
msg_error: msg_error,
|
63
|
+
should_crash: should_crash
|
64
|
+
).compose!
|
65
|
+
when "pull"
|
66
|
+
return Jumpstarter::Git::Pull.new(
|
67
|
+
remote: remote,
|
68
|
+
branch: branch,
|
69
|
+
msg_success: msg_success,
|
70
|
+
msg_error: msg_error,
|
71
|
+
should_crash: should_crash
|
72
|
+
).compose!
|
73
|
+
when "clone"
|
74
|
+
return Jumpstarter::Git::Clone.new(
|
75
|
+
remote: remote,
|
76
|
+
username: args["username"],
|
77
|
+
msg_success: msg_success,
|
78
|
+
msg_error: msg_error,
|
79
|
+
should_crash: should_crash
|
80
|
+
).compose!
|
81
|
+
else
|
82
|
+
end
|
83
|
+
when "bash"
|
84
|
+
return Jumpstarter::Bash::Run.new(
|
85
|
+
cmd: args["cmd"],
|
86
|
+
msg_success: msg_success,
|
87
|
+
msg_error: msg_error,
|
88
|
+
should_crash: should_crash
|
89
|
+
).compose!
|
90
|
+
when "cd"
|
91
|
+
path = inst_elm[1]
|
92
|
+
return Jumpstarter::Bash::CD.new(
|
93
|
+
path: path,
|
94
|
+
msg_success: msg_success,
|
95
|
+
msg_error: msg_error,
|
96
|
+
should_crash: should_crash
|
97
|
+
).compose!
|
98
|
+
when "xcode"
|
99
|
+
subcmd = inst_elm[1]
|
100
|
+
case subcmd
|
101
|
+
when "scheme"
|
102
|
+
action = args["action"]
|
103
|
+
case action
|
104
|
+
when "edit"
|
105
|
+
return Jumpstarter::Xcode::EditSchemeEnvVars.new(
|
106
|
+
proj_path: args["path"],
|
107
|
+
scheme_name: args["scheme_name"],
|
108
|
+
shared: args["shared"],
|
109
|
+
key: args["env_var_key"],
|
110
|
+
value: args["env_var_val"],
|
111
|
+
msg_success: msg_success,
|
112
|
+
msg_error: msg_error,
|
113
|
+
should_crash: should_crash
|
114
|
+
).compose!
|
115
|
+
when "duplicate"
|
116
|
+
return Jumpstarter::Xcode::DuplicateScheme.new(
|
117
|
+
proj_path: args["path"],
|
118
|
+
original_scheme_name: args["original_scheme_name"],
|
119
|
+
new_scheme_name: args["new_scheme_name"],
|
120
|
+
original_shared: args["original_shared"],
|
121
|
+
new_shared: args["new_shared"],
|
122
|
+
msg_success: msg_success,
|
123
|
+
msg_error: msg_error,
|
124
|
+
should_crash: should_crash
|
125
|
+
).compose!
|
126
|
+
when "create"
|
127
|
+
return Jumpstarter::Xcode::CreateScheme.new(
|
128
|
+
proj_path: args["path"],
|
129
|
+
scheme_name: args["scheme_name"],
|
130
|
+
shared: args["shared"],
|
131
|
+
msg_success: msg_success,
|
132
|
+
msg_error: msg_error,
|
133
|
+
should_crash: should_crash
|
134
|
+
).compose!
|
135
|
+
else
|
136
|
+
end
|
137
|
+
when "target"
|
138
|
+
action = args["action"]
|
139
|
+
case action
|
140
|
+
when "edit"
|
141
|
+
return Jumpstarter::Xcode::EditTargetBundleID.new(
|
142
|
+
proj_path: args["path"],
|
143
|
+
bundle_id: args["bundle_id"],
|
144
|
+
team_id: args["team_id"],
|
145
|
+
code_siging_identity: args["code_siging_identity"],
|
146
|
+
msg_success: msg_success,
|
147
|
+
msg_error: msg_error,
|
148
|
+
should_crash: should_crash
|
149
|
+
).compose!
|
150
|
+
else
|
151
|
+
end
|
152
|
+
else
|
153
|
+
end
|
154
|
+
else
|
155
|
+
# In a case where the command is not understood
|
156
|
+
# assume the line is a ruby line and simply return
|
157
|
+
# that line to the starter.rb file to run normally
|
158
|
+
return "#{line}"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Jumpstarter
|
2
|
+
class Pip
|
3
|
+
#******************#
|
4
|
+
# Instructions #
|
5
|
+
#******************#
|
6
|
+
class Install < I_Instructions
|
7
|
+
def run!()
|
8
|
+
# Check if pip is installed
|
9
|
+
if not Jumpstarter::Pip.installed!
|
10
|
+
# Install PIP
|
11
|
+
CommandRunner.execute(
|
12
|
+
command: Commands::Pip::Install,
|
13
|
+
error: nil
|
14
|
+
)
|
15
|
+
end
|
16
|
+
# pip is installed
|
17
|
+
CommandRunner.execute(
|
18
|
+
command: "pip3 install #{@package}",
|
19
|
+
error: nil
|
20
|
+
)
|
21
|
+
return true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class InstallPIP < I_Instructions
|
26
|
+
def run!()
|
27
|
+
# install pip
|
28
|
+
CommandRunner.execute(
|
29
|
+
command: Commands::Pip::Install,
|
30
|
+
error: nil
|
31
|
+
)
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
|
35
|
+
def crash_on_error!()
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
class << self
|
40
|
+
#*****************#
|
41
|
+
# Class Methods #
|
42
|
+
#*****************#
|
43
|
+
def installed!()
|
44
|
+
# Run version
|
45
|
+
version = CommandRunner.execute(
|
46
|
+
command: Commands::Pip::Version,
|
47
|
+
error: nil
|
48
|
+
)
|
49
|
+
return (/pip (\d+)(.\d+)?(.\d+)?/ =~ version)
|
50
|
+
end
|
51
|
+
|
52
|
+
def required_imports
|
53
|
+
['instructions', 'writer.rb', 'commandRunner.rb']
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,18 +1,42 @@
|
|
1
1
|
require_relative './instructions'
|
2
|
+
require_relative './parser'
|
3
|
+
require 'terminal-table'
|
2
4
|
|
3
5
|
module Jumpstarter
|
6
|
+
FILE = 'Starter'
|
4
7
|
class Setup
|
5
8
|
class << self
|
6
9
|
|
7
|
-
|
10
|
+
## HELPER METHOD
|
11
|
+
def options(ops)
|
12
|
+
rows = []
|
13
|
+
c = 0
|
14
|
+
ops.each do |v|
|
15
|
+
rows << [v, c]
|
16
|
+
c = c + 1
|
17
|
+
end
|
18
|
+
return Terminal::Table.new :rows => rows
|
19
|
+
end
|
8
20
|
|
9
|
-
def
|
10
|
-
## Find path to
|
11
|
-
|
21
|
+
def find!()
|
22
|
+
## Find path to Starter file
|
23
|
+
file_path = ""
|
24
|
+
path = Dir.glob("./**/#{Jumpstarter::FILE}")
|
12
25
|
if path.length == 1
|
13
26
|
puts "Found Setup file at #{path[0]}"
|
14
|
-
|
27
|
+
file_path = path[0]
|
28
|
+
else
|
29
|
+
puts "We found multiple Starter files in this directory tree"
|
30
|
+
puts "Please select the one you want to use by typing the number that corrisponds to that file below"
|
31
|
+
puts options(path)
|
32
|
+
puts "Choose file #"
|
33
|
+
num = (STDIN.gets.chomp).to_i
|
34
|
+
file_path = path[num]
|
15
35
|
end
|
36
|
+
return file_path
|
37
|
+
end
|
38
|
+
def setup!()
|
39
|
+
proccess_file(Setup.find!)
|
16
40
|
end
|
17
41
|
|
18
42
|
def parse_into_inst(line)
|
@@ -24,23 +48,48 @@ module Jumpstarter
|
|
24
48
|
result = inst.run!
|
25
49
|
return result
|
26
50
|
end
|
51
|
+
|
52
|
+
def fill_with_inst!()
|
53
|
+
text = ""
|
54
|
+
rel_files = [
|
55
|
+
"instructions.rb",
|
56
|
+
"commands.rb",
|
57
|
+
"commandRunner.rb",
|
58
|
+
"OS.rb",
|
59
|
+
"xcode_helper.rb",
|
60
|
+
"Writer.rb",
|
61
|
+
"git.rb",
|
62
|
+
"bash.rb",
|
63
|
+
"xcode.rb",
|
64
|
+
"pip.rb"
|
65
|
+
]
|
66
|
+
rel_files.each do |f|
|
67
|
+
File.open(__dir__ + "/#{f}", "r") do |f|
|
68
|
+
f.each_line do |line|
|
69
|
+
text = "#{text}#{line}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
text = "#{text}\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
return text
|
76
|
+
end
|
27
77
|
def proccess_file(path)
|
78
|
+
puts "Processing file #{path}"
|
79
|
+
cmd_file = fill_with_inst!
|
28
80
|
File.open(path, "r") do |f|
|
29
81
|
f.each_line do |line|
|
30
82
|
inst = parse_into_inst(line)
|
31
|
-
|
32
|
-
if result
|
33
|
-
# Success
|
34
|
-
puts "#{inst.success_message!}"
|
35
|
-
else
|
36
|
-
# Error
|
37
|
-
puts "#{inst.error_message!}"
|
38
|
-
if inst.crash_on_error!
|
39
|
-
# CRASH
|
40
|
-
end
|
41
|
-
end
|
83
|
+
cmd_file = "#{cmd_file}\n#{inst}"
|
42
84
|
end
|
43
85
|
end
|
86
|
+
# Setup.eval_file(cmd_file)
|
87
|
+
File.open("Starter.rb", 'w') { |file| file.write(cmd_file) }
|
88
|
+
system("ruby Starter.rb")
|
89
|
+
# File.delete("Starter.rb")
|
90
|
+
end
|
91
|
+
def eval_file(file_text)
|
92
|
+
eval(cmd_file)
|
44
93
|
end
|
45
94
|
end
|
46
95
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
require 'xcodeproj'
|
3
|
+
require 'plist'
|
4
|
+
module Jumpstarter
|
5
|
+
class Xcode
|
6
|
+
#******************#
|
7
|
+
# Instructions #
|
8
|
+
#******************#
|
9
|
+
class CreateScheme < I_Instructions
|
10
|
+
def run!()
|
11
|
+
new_scheme = Xcodeproj::XCScheme.new()
|
12
|
+
new_scheme.save_as(@proj_path, @scheme_name, @shared)
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class DuplicateScheme < I_Instructions
|
18
|
+
def run!()
|
19
|
+
existing_scheme_path = @original_shared ? Xcodeproj::XCScheme.shared_data_dir(@proj_path) : Xcodeproj::XCScheme.user_data_dir(@proj_path)
|
20
|
+
existing_scheme = "#{existing_scheme_path}/#{@original_scheme_name}.xcscheme"
|
21
|
+
new_scheme = Xcodeproj::XCScheme.new(existing_scheme)
|
22
|
+
new_scheme.save_as(@proj_path, @new_scheme_name, @new_shared)
|
23
|
+
return true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class EditSchemeEnvVars < I_Instructions
|
28
|
+
|
29
|
+
def run!()
|
30
|
+
existing_scheme_path = @shared ? Xcodeproj::XCScheme.shared_data_dir(@proj_path) : Xcodeproj::XCScheme.user_data_dir(@proj_path)
|
31
|
+
existing_scheme = "#{existing_scheme_path}/#{@scheme_name}.xcscheme"
|
32
|
+
scheme = Xcodeproj::XCScheme.new(existing_scheme)
|
33
|
+
environment_variables = scheme.launch_action.environment_variables
|
34
|
+
environment_variables.assign_variable(:key => @key, :value => @value)
|
35
|
+
scheme.launch_action.environment_variables = environment_variables
|
36
|
+
scheme.save!
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class EditTargetBundleID < I_Instructions
|
42
|
+
def run!()
|
43
|
+
project = Xcodeproj::Project.open(@proj_path)
|
44
|
+
|
45
|
+
unless project.root_object.attributes["TargetAttributes"]
|
46
|
+
puts "Your file format is old, please update and try again"
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
target_dictionary = project.targets.map { |f| { name: f.name, uuid: f.uuid, build_configuration_list: f.build_configuration_list } }
|
51
|
+
changed_targets = []
|
52
|
+
project.root_object.attributes["TargetAttributes"].each do |target, sett|
|
53
|
+
found_target = target_dictionary.detect { |h| h[:uuid] == target }
|
54
|
+
style_value = @code_sign_style == "manual" ? 'Manual' : 'Automatic'
|
55
|
+
build_configuration_list = found_target[:build_configuration_list]
|
56
|
+
build_configuration_list.set_setting("CODE_SIGN_STYLE", style_value)
|
57
|
+
sett["ProvisioningStyle"] = style_value
|
58
|
+
|
59
|
+
if not @team_id.empty?
|
60
|
+
sett["DevelopmentTeam"] = @team_id
|
61
|
+
build_configuration_list.set_setting("DEVELOPMENT_TEAM", @team_id)
|
62
|
+
else
|
63
|
+
teams = Jumpstarter::XCHelper.teams!
|
64
|
+
puts "Provisioning Profile"
|
65
|
+
puts options(teams)
|
66
|
+
print "Please select the team for #{found_target[:name]}: "
|
67
|
+
num = (STDIN.gets.chomp).to_i
|
68
|
+
team = teams[num]
|
69
|
+
build_configuration_list.set_setting("DEVELOPMENT_TEAM", team)
|
70
|
+
end
|
71
|
+
if @code_siging_identity
|
72
|
+
build_configuration_list.set_setting("CODE_SIGN_IDENTITY", @code_siging_identity)
|
73
|
+
end
|
74
|
+
if @bundle_id
|
75
|
+
build_configuration_list.set_setting("PRODUCT_BUNDLE_IDENTIFIER", @bundle_id)
|
76
|
+
end
|
77
|
+
changed_targets << found_target[:name]
|
78
|
+
end
|
79
|
+
project.save
|
80
|
+
|
81
|
+
changed_targets.each do |target|
|
82
|
+
puts "Updated Target: #{target}"
|
83
|
+
end
|
84
|
+
return true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
class << self
|
88
|
+
#*****************#
|
89
|
+
# Class Methods #
|
90
|
+
#*****************#
|
91
|
+
def self.installed!()
|
92
|
+
# Run version
|
93
|
+
version = CommandRunner.execute(
|
94
|
+
command: Commands::Pip::Version,
|
95
|
+
error: nil
|
96
|
+
)
|
97
|
+
return (/pip (\d+)(.\d+)?(.\d+)?/ =~ version)
|
98
|
+
end
|
99
|
+
|
100
|
+
def required_imports
|
101
|
+
['instructions', 'writer.rb', 'commandRunner.rb']
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
require 'plist'
|
3
|
+
require 'shellwords'
|
4
|
+
|
5
|
+
module Jumpstarter
|
6
|
+
class XCHelper
|
7
|
+
class << self
|
8
|
+
def teams!()
|
9
|
+
teams = []
|
10
|
+
path = File.expand_path("~") + "/Library/MobileDevice/Provisioning Profiles/"
|
11
|
+
output_plist_file = "profile.plist"
|
12
|
+
Dir.foreach(path) do |f|
|
13
|
+
file_path = File.expand_path("~") + "/Library/MobileDevice/Provisioning\\ Profiles/#{f}"
|
14
|
+
if File.extname(file_path) == '.mobileprovision'
|
15
|
+
system("security cms -D -i #{file_path} > #{output_plist_file}")
|
16
|
+
profile_plist = Plist.parse_xml("profile.plist")
|
17
|
+
team = profile_plist['TeamIdentifier'].first
|
18
|
+
teams << team
|
19
|
+
File.delete("#{output_plist_file}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
return teams
|
23
|
+
end
|
24
|
+
def update_targets_plist_ids(project, bundleName)
|
25
|
+
target = project.targets.first
|
26
|
+
files = target.source_build_phase.files.to_a.map do |pbx_build_file|
|
27
|
+
pbx_build_file.file_ref.real_path.to_s
|
28
|
+
end.select do |path|
|
29
|
+
path.end_with?(".plist")
|
30
|
+
end.select do |path|
|
31
|
+
File.exists?(path)
|
32
|
+
end
|
33
|
+
files.each do |f|
|
34
|
+
profile_plist = Plist.parse_xml(f)
|
35
|
+
current = profile_plist['NSExtension']['NSExtensionAttributes']['WKAppBundleIdentifier']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|