ambient-xcode 0.6.0 → 0.7.0

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.
@@ -0,0 +1,71 @@
1
+ module Ambient
2
+ class CapabilitiesHelper
3
+ CAPABILITIES = {
4
+ application_group_ios: "ApplicationGroups.iOS",
5
+ background_modes: "BackgroundModes",
6
+ data_protection: "DataProtection",
7
+ game_center: "GameCenter",
8
+ healthkit: "HealthKit",
9
+ health_kit: "HealthKit",
10
+ homekit: "HomeKit",
11
+ home_kit: "HomeKit",
12
+ in_app_purchase: "InAppPurchase",
13
+ inter_app_audio: "InterAppAudio",
14
+ keychain: "Keychain",
15
+ maps: "Maps.iOS",
16
+ apple_pay: "OMC",
17
+ passbook: "Passbook",
18
+ wallet: "Passbook",
19
+ safari_keychain: "SafariKeychain",
20
+ personal_vpn: "VPNLite",
21
+ wireless_accessory_configuration: "WAC",
22
+ icloud: "iCloud"
23
+ }
24
+
25
+ def initialize(project, target)
26
+ @project = project
27
+ @target = target
28
+ end
29
+
30
+ def clear_capabilities
31
+ capabilities.delete_if { |_, _| true } if capabilities
32
+ end
33
+
34
+ def enable_capability(capability)
35
+ capabilities[capability_key(capability)] = {"enabled"=>"1"}
36
+ end
37
+
38
+ def disable_capability(capability)
39
+ capabilities.delete(capability_key(capability))
40
+ end
41
+
42
+ def set_development_team(team)
43
+ target_attributes["DevelopmentTeam"] = team
44
+ end
45
+
46
+ private
47
+
48
+ def capabilities
49
+ target_attributes["SystemCapabilities"]
50
+ end
51
+
52
+ def target_attributes
53
+ unless @project.root_object.attributes["TargetAttributes"]
54
+ @project.root_object.attributes["TargetAttributes"] = {}
55
+ end
56
+
57
+ unless @project.root_object.attributes["TargetAttributes"][@target.uuid]
58
+ @project.root_object.attributes["TargetAttributes"][@target.uuid] = {}
59
+ end
60
+
61
+ @project.root_object.attributes["TargetAttributes"][@target.uuid]
62
+ end
63
+
64
+ def capability_key(capability)
65
+ capability = CAPABILITIES[capability] || capability.to_s
66
+ prefix = "com.apple."
67
+ capability = "#{prefix}#{capability}" unless capability.start_with? prefix
68
+ capability
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'dsl/main_scope'
2
+ require_relative 'dsl/plist_scope'
3
+ require_relative 'dsl/scheme_scope'
4
+ require_relative 'dsl/target_scope'
@@ -0,0 +1,160 @@
1
+ module Ambient
2
+ module DSL
3
+ class MainScope
4
+ attr_reader :application
5
+
6
+ def initialize(application)
7
+ @application = application
8
+ end
9
+
10
+ def use_settings_from(filename)
11
+ application.configure { run_ambientfile(filename) }
12
+ end
13
+
14
+ def option(name, value)
15
+ application.configure { set_option(name, value) }
16
+ end
17
+
18
+ def base_ios_settings!(project_name, prefix: "", tests: false, ui_tests: false, swift: true, target: nil, test_target: nil, ui_test_target: nil)
19
+ use_defaults_for_everything_not_specified_in_this_file!
20
+ enable_default_warnings!
21
+
22
+ target ||= "project_name"
23
+ test_target ||= "#{project_name}Tests"
24
+ ui_test_target ||= "#{project_name}UITests"
25
+ tests = true if test_target
26
+ ui_tests = true if ui_test_target
27
+
28
+ option "ALWAYS_SEARCH_USER_PATHS", false
29
+ option "CLANG_CXX_LANGUAGE_STANDARD", "gnu++0x"
30
+ option "CLANG_CXX_LIBRARY", "libc++"
31
+ option "CLANG_ENABLE_MODULES", true
32
+ option "CLANG_ENABLE_OBJC_ARC", true
33
+
34
+ option "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Developer"
35
+ option "COPY_PHASE_STRIP", false
36
+
37
+ option "ENABLE_STRICT_OBJC_MSGSEND", true
38
+ option "GCC_C_LANGUAGE_STANDARD", "gnu99"
39
+ option "GCC_NO_COMMON_BLOCKS", true
40
+ option "SDKROOT", "iphoneos"
41
+ option "IPHONEOS_DEPLOYMENT_TARGET", "9.0"
42
+
43
+ scheme "Debug" do
44
+ option "DEBUG_INFORMATION_FORMAT", "dwarf"
45
+ option "ENABLE_TESTABILITY", true
46
+ option "MTL_ENABLE_DEBUG_INFO", true
47
+ option "ONLY_ACTIVE_ARCH", true
48
+ option "GCC_DYNAMIC_NO_PIC", false
49
+ option "GCC_OPTIMIZATION_LEVEL", "0"
50
+ option "GCC_PREPROCESSOR_DEFINITIONS", ["DEBUG=1", "$(inherited)"]
51
+ option "SWIFT_OPTIMIZATION_LEVEL", "-Onone" if swift
52
+ end
53
+
54
+ scheme "Release" do
55
+ option "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"
56
+ option "ENABLE_NS_ASSERTIONS", false
57
+ option "MTL_ENABLE_DEBUG_INFO", false
58
+ option "VALIDATE_PRODUCT", true
59
+ end
60
+
61
+ target project_name do
62
+ option "INFOPLIST_FILE", "#{project_name}/Info.plist"
63
+ option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}"
64
+ option "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon"
65
+ option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks"
66
+ option "PRODUCT_NAME", "$(TARGET_NAME)"
67
+ end
68
+
69
+ if tests
70
+ target test_target do
71
+ option "INFOPLIST_FILE", "#{project_name}Tests/Info.plist"
72
+ option "BUNDLE_LOADER", "$(TEST_HOST)"
73
+ option "TEST_HOST", "$(BUILT_PRODUCTS_DIR)/#{project_name}.app/#{project_name}"
74
+ option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}Tests"
75
+ option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
76
+ option "PRODUCT_NAME", "$(TARGET_NAME)"
77
+ end
78
+ end
79
+
80
+ if ui_tests
81
+ target ui_test_target do
82
+ option "INFOPLIST_FILE", "#{project_name}UITests/Info.plist"
83
+ option "TEST_TARGET_NAME", "#{project_name}"
84
+ option "PRODUCT_BUNDLE_IDENTIFIER", "#{prefix}#{project_name}UITests"
85
+ option "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
86
+ option "USES_XCTRUNNER", "YES"
87
+ option "PRODUCT_NAME", "$(TARGET_NAME)"
88
+ end
89
+ end
90
+ end
91
+
92
+ def enable_extra_warnings_and_static_analyser!
93
+ warnings = %w(GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED
94
+ GCC_WARN_MISSING_PARENTHESES
95
+ GCC_WARN_ABOUT_RETURN_TYPE
96
+ GCC_WARN_SIGN_COMPARE
97
+ GCC_WARN_CHECK_SWITCH_STATEMENTS
98
+ GCC_WARN_UNUSED_FUNCTION
99
+ GCC_WARN_UNUSED_LABEL
100
+ GCC_WARN_UNUSED_VALUE
101
+ GCC_WARN_UNUSED_VARIABLE
102
+ GCC_WARN_SHADOW
103
+ GCC_WARN_64_TO_32_BIT_CONVERSION
104
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS
105
+ GCC_WARN_UNDECLARED_SELECTOR
106
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
107
+ GCC_WARN_UNINITIALIZED_AUTOS
108
+ CLANG_WARN_INT_CONVERSION
109
+ CLANG_WARN_ENUM_CONVERSION
110
+ CLANG_WARN_CONSTANT_CONVERSION
111
+ CLANG_WARN_BOOL_CONVERSION
112
+ CLANG_WARN_EMPTY_BODY
113
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION
114
+ CLANG_WARN__DUPLICATE_METHOD_MATCH
115
+ GCC_WARN_64_TO_32_BIT_CONVERSION
116
+ RUN_CLANG_STATIC_ANALYZER
117
+ GCC_TREAT_WARNINGS_AS_ERRORS)
118
+ warnings.each { |w| option(w, true) }
119
+ end
120
+
121
+ def enable_default_warnings!
122
+ truthy = %w(CLANG_WARN_BOOL_CONVERSION
123
+ CLANG_WARN_CONSTANT_CONVERSION
124
+ CLANG_WARN_EMPTY_BODY
125
+ CLANG_WARN_ENUM_CONVERSION
126
+ CLANG_WARN_INT_CONVERSION
127
+ CLANG_WARN_UNREACHABLE_CODE
128
+ CLANG_WARN__DUPLICATE_METHOD_MATCH
129
+ GCC_WARN_64_TO_32_BIT_CONVERSION
130
+ GCC_WARN_UNDECLARED_SELECTOR
131
+ GCC_WARN_UNUSED_FUNCTION
132
+ GCC_WARN_UNUSED_VARIABLE)
133
+ error = %w(CLANG_WARN_DIRECT_OBJC_ISA_USAGE
134
+ CLANG_WARN_OBJC_ROOT_CLASS
135
+ GCC_WARN_ABOUT_RETURN_TYPE)
136
+ aggressive = %w(GCC_WARN_UNINITIALIZED_AUTOS)
137
+
138
+ truthy.each { |w| option(w, true) }
139
+ error.each { |w| option(w, "YES_ERROR") }
140
+ aggressive.each { |w| option(w, "YES_AGGRESSIVE") }
141
+ end
142
+
143
+ def target(name, &block)
144
+ TargetScope.new(application, name).configure(&block)
145
+ end
146
+
147
+ def use_defaults_for_everything_not_specified_in_this_file!
148
+ application.configure { @use_defaults = true }
149
+ end
150
+
151
+ def scheme(name, parent: nil, &block)
152
+ SchemeScope.new(application, nil, name, parent).configure(&block)
153
+ end
154
+
155
+ def plist(path, &block)
156
+ PlistScope.new(application, path).configure(&block)
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,21 @@
1
+ module Ambient
2
+ module DSL
3
+ class PlistScope
4
+ attr_reader :application,
5
+ :helper
6
+
7
+ def initialize(application, path)
8
+ @application = application
9
+ @helper = PlistHelper.new(path)
10
+ end
11
+
12
+ def configure(&block)
13
+ instance_eval(&block)
14
+ end
15
+
16
+ def entry(key, value)
17
+ helper.add_entry(key, value)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ module Ambient
2
+ module DSL
3
+ class SchemeScope
4
+ attr_reader :application
5
+
6
+ def initialize(application, target, name, parent)
7
+ @application = application
8
+ @target = target
9
+ @name = name
10
+ @parent = parent
11
+
12
+ application.configure do
13
+ set_parent_scheme(
14
+ target: target && target.name,
15
+ child: name,
16
+ parent: parent
17
+ )
18
+ end
19
+ end
20
+
21
+ def configure(&block)
22
+ if block
23
+ instance_eval(&block)
24
+ end
25
+ end
26
+
27
+ def option(option_name, value)
28
+ target = @target
29
+ name = @name
30
+ parent = @parent
31
+
32
+ if target
33
+ application.configure { set_option(option_name, value, target: target.name, scheme: name, parent: parent) }
34
+ else
35
+ application.configure { set_option(option_name, value, scheme: name, parent: parent) }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ module Ambient
2
+ module DSL
3
+ class TargetScope
4
+ attr_reader :application,
5
+ :name
6
+
7
+ def initialize(application, name)
8
+ @application = application
9
+ @name = name
10
+ end
11
+
12
+ def configure(&block)
13
+ instance_eval(&block)
14
+ end
15
+
16
+ def option(option_name, value)
17
+ target_name = @name
18
+ application.configure { set_option(option_name, value, target: target_name) }
19
+ end
20
+
21
+ def scheme(name, parent: nil, &block)
22
+ SchemeScope.new(application, self, name, parent).configure(&block)
23
+ end
24
+
25
+ def capability(capability_name)
26
+ target_name = @name
27
+ application.configure { set_capability(target_name, capability_name) }
28
+ end
29
+
30
+ def development_team(team_name)
31
+ target_name = @name
32
+ application.configure { set_development_team(target_name, team_name) }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ module Ambient
2
+ class Init
3
+ attr_reader :path,
4
+ :project_name,
5
+ :project_prefix
6
+
7
+ def initialize(path = nil, project_name = nil, project_prefix = nil)
8
+ @path = path || Dir.pwd
9
+ @project_name = project_name || "MyProject"
10
+ @project_prefix = project_prefix || "com.#{@project_name.downcase}."
11
+ end
12
+
13
+ def create_ambientfile
14
+ puts "# Creating Ambientfile..."
15
+ write_file
16
+ puts "File created at #{filepath}"
17
+ end
18
+
19
+ private
20
+
21
+ def write_file
22
+ File.open(filepath, 'w') { |file| file.write(contents) }
23
+ end
24
+
25
+ def filepath
26
+ "#{path}/Ambientfile"
27
+ end
28
+
29
+ def contents
30
+ "base_ios_settings! \"#{project_name}\", prefix: \"#{project_prefix}\"\n"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module Ambient
2
+ class PlistHelper
3
+ attr_reader :path
4
+
5
+ def initialize(path)
6
+ @path = path
7
+ end
8
+
9
+ def add_entry(key, value)
10
+ plist_as_dictionary[key] = value
11
+ puts "applying to plist: #{path} #{key}"
12
+ save
13
+ end
14
+
15
+ private
16
+
17
+ def plist_as_dictionary
18
+ @plist_as_dictionary ||= Plist::parse_xml(path)
19
+ end
20
+
21
+ def to_plist
22
+ plist_as_dictionary.to_plist
23
+ end
24
+
25
+ def save
26
+ File.open(path, 'w') { |file| file.write(to_plist) }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,83 @@
1
+ module Ambient
2
+ class ProjectCreation
3
+ attr_reader :path,
4
+ :name
5
+
6
+ def initialize(path, name)
7
+ @path = path
8
+ @name = name.gsub(/\W/, "")
9
+ check_name!
10
+ end
11
+
12
+ def create_ios_project
13
+ check_already_exists!
14
+ puts "# Setting up project..."
15
+ copy_from_template
16
+ rename_project_to_name
17
+ find_and_replace_instances_of_template_to_name
18
+ create_ambientfile
19
+ run_ambientfile
20
+ end
21
+
22
+ private
23
+
24
+ def check_already_exists!
25
+ return unless File.exists?(project_path)
26
+
27
+ puts "😱 #{name} already exists in the current directory"
28
+ exit 1
29
+ end
30
+
31
+ def check_name!
32
+ return if name
33
+
34
+ puts "😱 You must specify a project name when creating a new project"
35
+ puts "e.g. `ambient new MyProject`"
36
+ exit(1)
37
+ end
38
+
39
+ def run_ambientfile
40
+ Application.new(project_path).run_ambientfile
41
+ end
42
+
43
+ def create_ambientfile
44
+ Init.new(project_path, name).create_ambientfile
45
+ end
46
+
47
+ def copy_from_template
48
+ FileUtils.copy_entry ios_template_path, project_path
49
+ end
50
+
51
+ def rename_project_to_name
52
+ FileUtils.mv "#{project_path}/PRODUCTNAME",
53
+ "#{project_path}/#{name}"
54
+ FileUtils.mv "#{project_path}/PRODUCTNAME.xcodeproj",
55
+ "#{project_path}/#{name}.xcodeproj"
56
+ end
57
+
58
+ def find_and_replace_instances_of_template_to_name
59
+ files_in_project.each do |file|
60
+ find_and_replace(file, "PRODUCTNAME", name)
61
+ end
62
+ end
63
+
64
+ def project_path
65
+ path + "/#{name}"
66
+ end
67
+
68
+ def ios_template_path
69
+ File.expand_path("../../../templates/ios", __FILE__)
70
+ end
71
+
72
+ def files_in_project
73
+ Dir.glob(project_path + '/**/*').select { |path| File.file?(path) }
74
+ end
75
+
76
+ def find_and_replace(path, old, new)
77
+ text = File.read(path)
78
+ replace = text.gsub(old, new)
79
+ return if text == replace
80
+ File.open(path, "w") { |file| file.puts replace }
81
+ end
82
+ end
83
+ end