Skip to content

Commit

Permalink
[Environment Variables] Add support for scheme environment variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Martin committed Oct 26, 2015
1 parent eedcb65 commit d39abc2
Show file tree
Hide file tree
Showing 12 changed files with 557 additions and 20 deletions.
20 changes: 4 additions & 16 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,23 @@
# This configuration was generated by `rubocop --auto-gen-config`
# on 2015-03-06 13:49:50 +0100 using RuboCop version 0.28.0.
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2015-10-25 15:59:02 -0700 using RuboCop version 0.34.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 499
# Offense count: 804
# Configuration parameters: AllowURI, URISchemes.
Metrics/LineLength:
Max: 186

# Offense count: 66
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 46

# Offense count: 2
# Configuration parameters: CountKeywordArgs.
Metrics/ParameterLists:
Max: 7

# Offense count: 9
Metrics/PerceivedComplexity:
Max: 16

# Offense count: 94
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/DotPosition:
Enabled: false

# Offense count: 1
Style/DoubleNegation:
Enabled: false
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

##### Enhancements

* Add accessors for working with Environment Variables in xcscheme files
[Justin Martin](https://github.com/justinseanmartin)
[Xcodeproj#326](https://github.com/CocoaPods/Xcodeproj/pull/326)

* Add method to create new variant groups (groups for localized versions of the same file)
[Tim Bodeit](https://github.com/timbodeit)
[Xcodeproj#315](https://github.com/CocoaPods/Xcodeproj/pull/315)
Expand Down
2 changes: 1 addition & 1 deletion lib/xcodeproj/constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Constants

# @return [String] The last known OS X SDK (stable).
#
LAST_KNOWN_OSX_SDK = '10.11'
LAST_KNOWN_OSX_SDK = '10.11'

# @return [String] The last known tvOS SDK (stable).
LAST_KNOWN_TVOS_SDK = '9.0'
Expand Down
117 changes: 117 additions & 0 deletions lib/xcodeproj/scheme/environment_variables.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
require 'xcodeproj/scheme/xml_element_wrapper'

module Xcodeproj
class XCScheme
VARIABLES_NODE = 'EnvironmentVariables'
VARIABLE_NODE = 'EnvironmentVariable'

# This class wraps the EnvironmentVariables node of a .xcscheme XML file. This
# is just a container of EnvironmentVariable objects. It can either appear on a
# LaunchAction or TestAction scheme group.
#
class EnvironmentVariables < XMLElementWrapper
# @param [REXML::Element,Array{EnvironmentVariable},Array{Hash{String => String}}] node_or_target
# The 'EnvironmentVariables' XML node that this object represents.
# If nil, it will create a default XML node to use.
#
def initialize(node_or_target = nil)
create_xml_element_with_fallback(node_or_target, VARIABLES_NODE) do
@all_variables = []
node_or_target.each { |var| add_variable(var) } unless node_or_target.nil?
end
end

# @return [Array{EnvironmentVariable}]
# The key value pairs currently set in @xml_element
#
def all_variables
@all_variables ||= @xml_element.get_elements(VARIABLE_NODE).map { |variable| EnvironmentVariable.new(variable) }
end

# @param [EnvironmentVariable,Hash{String => String}] variable
# The key value pairs currently set in @xml_element
#
# @return [Array{EnvironmentVariable}]
# The new set of environment variables after addition
#
def add_variable(variable)
env_var = variable.is_a?(EnvironmentVariable) ? variable : EnvironmentVariable.new(variable)
all_variables.each { |existing_var| remove_variable(existing_var) if existing_var.key == env_var.key }
@xml_element.add_element(env_var.xml_element)
@all_variables << env_var
end

# @param [EnvironmentVariable,Hash{String => String}] variable
# The key value pairs currently set in @xml_element
#
# @return [Array{EnvironmentVariable}]
# The new set of environment variables after removal
#
def remove_variable(variable)
env_var = variable.is_a?(EnvironmentVariable) ? variable : all_variables.select { |var| var.key == variable[:key] }[0]
raise "Unexpected parameter type: #{env_var.class}" unless env_var.is_a?(EnvironmentVariable)
@xml_element.delete_element(env_var.xml_element)
@all_variables -= [env_var]
end

# @param [EnvironmentVariable,Hash{String => String}] variable
# The key value pairs currently set in @xml_element
#
def to_a
all_variables.map(&:to_h)
end
end

# This class wraps the EnvironmentVariable node of a .xcscheme XML file.
# Environment variables are accessible via the NSDictionary returned from
# [[NSProcessInfo processInfo] environment] in your app code.
#
class EnvironmentVariable < XMLElementWrapper
# @param [REXML::Element,EnvironmentVariable,Hash{String => String}] value
# The 'EnvironmentVariable' XML node that this object represents.
# If nil, it will create a default XML node to use. If a hash, it
# must contain keys 'key' and 'value', and optionally have 'enabled'.
# If not supplied, it will default to being enabled.
#
def initialize(value)
create_xml_element_with_fallback(value, VARIABLE_NODE) do
raise "Must pass a Hash with 'key' and 'value'!" unless value.is_a?(Hash) && value.key?(:key) && value.key?(:value)

@xml_element.attributes['key'] = value[:key]
@xml_element.attributes['value'] = value[:value]
@xml_element.attributes['isEnabled'] = value.key?(:enabled) ? bool_to_string(value[:enabled]) : bool_to_string(true)
end
end

def key
@xml_element.attributes['key']
end

def key=(key)
@xml_element.attributes['key'] = key
end

def value
@xml_element.attributes['value']
end

def value=(value)
@xml_element.attributes['value'] = value
end

def enabled
string_to_bool(@xml_element.attributes['isEnabled'])
end

def enabled=(enabled)
@xml_element.attributes['isEnabled'] = bool_to_string(enabled)
end

# @return [Hash{:key => String, :value => String, :enabled => Boolean}]
# The environment variable XML node with attributes converted to Hash keys
def to_h
{ :key => key, :value => value, :enabled => enabled }
end
end
end
end
22 changes: 22 additions & 0 deletions lib/xcodeproj/scheme/launch_action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,28 @@ def buildable_product_runnable=(runnable)
@xml_element.add_element(runnable.xml_element) if runnable
end

# @return [EnvironmentVariables]
# Returns the set of environment variables that are currently set at test runtime
# NOTE: If this creates a new node, it will not automatically be added to the xml document
#
def environment_variables
env_vars_nodes = @xml_element.get_elements(XCScheme::VARIABLES_NODE)
raise 'Unexpected number of EnvironmentVariables nodes found!' if env_vars_nodes.count > 1

env_vars_nodes.count == 0 ? nil : EnvironmentVariables.new(env_vars_nodes[0])
end

# @param [EnvironmentVariables] env_vars
# Overwrites the set of environment variables that should be set at test runtime
#
def environment_variables=(env_vars)
@xml_element.get_elements(XCScheme::VARIABLES_NODE).each { |node| node.parent.delete_element(node) }

raise "Unexpected parameter type: #{env_vars.class}" unless env_vars.nil? || env_vars.is_a?(EnvironmentVariables)
@xml_element.add_element(env_vars.xml_element) unless env_vars.nil?
environment_variables
end

# @todo handle 'AdditionalOptions' tag
end
end
Expand Down
23 changes: 23 additions & 0 deletions lib/xcodeproj/scheme/test_action.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'xcodeproj/scheme/abstract_scheme_action'
require 'xcodeproj/scheme/environment_variables'

module Xcodeproj
class XCScheme
Expand Down Expand Up @@ -84,6 +85,28 @@ def add_macro_expansion(macro_expansion)
@xml_element.add_element(macro_expansion.xml_element)
end

# @return [EnvironmentVariables]
# Returns the set of environment variables that are currently set at test runtime
# NOTE: If this creates a new node, it will not automatically be added to the xml document
#
def environment_variables
env_vars_nodes = @xml_element.get_elements(XCScheme::VARIABLES_NODE)
raise 'Unexpected number of EnvironmentVariables nodes found!' if env_vars_nodes.count > 1

env_vars_nodes.count == 0 ? nil : EnvironmentVariables.new(env_vars_nodes[0])
end

# @param [EnvironmentVariables] env_vars
# Overwrites the set of environment variables that should be set at test runtime
#
def environment_variables=(env_vars)
@xml_element.get_elements(XCScheme::VARIABLES_NODE).each { |node| node.parent.delete_element(node) }

raise "Unexpected parameter type: #{env_vars.class}" unless env_vars.nil? || env_vars.is_a?(EnvironmentVariables)
@xml_element.add_element(env_vars.xml_element) unless env_vars.nil?
environment_variables
end

#-------------------------------------------------------------------------#

class TestableReference < XMLElementWrapper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@
ReferencedContainer = "container:SharedSchemes.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "testkey"
value = "testval"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "testkeydisabled"
value = "testvaldisabled"
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
Expand All @@ -48,7 +60,8 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "632143E8175736EE0038D40D"
Expand All @@ -57,6 +70,18 @@
ReferencedContainer = "container:SharedSchemes.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "launchkey"
value = "launchval"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "launchkeydisabled"
value = "launchvaldisabled"
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
Expand All @@ -66,7 +91,8 @@
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "632143E8175736EE0038D40D"
Expand Down
2 changes: 1 addition & 1 deletion spec/plist_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def o.to_hash

it 'allows hashes, strings, booleans, numbers, and arrays of hashes and strings as values' do
hash = {
'hash' => { 'a hash' => 'in a hash' },
'hash' => { 'a hash' => 'in a hash' },
'string' => 'string',
'true_bool' => '1',
'false_bool' => '0',
Expand Down
Loading

0 comments on commit d39abc2

Please sign in to comment.