Class: Fastlane::Helper::SettingsBundleHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/fastlane/plugin/settings_bundle/helper/settings_bundle_helper.rb

Defined Under Namespace

Classes: Settings

Class Method Summary collapse

Class Method Details

.expanded_build_setting(target, setting_name, configuration) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/fastlane/plugin/settings_bundle/helper/settings_bundle_helper.rb', line 159

def expanded_build_setting(target, setting_name, configuration)
  setting_value = target.resolved_build_setting(setting_name)[configuration]
  return if setting_value.nil?

  search_position = 0
  while (matches = /\$\(([^(){}]*)\)|\$\{([^(){}]*)\}/.match(setting_value, search_position))
    macro_name = matches[1] || matches[2]
    search_position = setting_value.index(macro_name) - 2

    expanded_macro = macro_name == "SRCROOT" ? "." : expanded_build_setting(target, macro_name, configuration)
    search_position += macro_name.length + 3 and next if expanded_macro.nil?

    setting_value.gsub!(/\$\(#{macro_name}\)|\$\{#{macro_name}\}/, expanded_macro)
    search_position += expanded_macro.length
  end
  setting_value
end

.formatted_value(value, settings) ⇒ Object

Takes a value, a version number and a build number and returns a formatted string. :version is replaced by the version number. :build is replaced by the build number. Neither the version nor the build number is required. Omitting both from the format will result in the format being returned as the value.

:value: A string value containing :version, :build, neither or both :settings: A Settings struct containing settings from a project



39
40
41
# File 'lib/fastlane/plugin/settings_bundle/helper/settings_bundle_helper.rb', line 39

def formatted_value(value, settings)
  value.gsub(/:version/, settings.version.to_s).gsub(/:build/, settings.build.to_s)
end

.settings_from_project(project, configuration, target_name) ⇒ Object

Takes an open Xcodeproj::Project and extracts the current settings, returning a Settings struct with settings data. Raises on error.

:project: An open Xcodeproj::Project via Xcodeproj::Project.open, e.g. :configuration: A valid build configuration in the project :target_name: A valid target name in the project or nil to use the first application target



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fastlane/plugin/settings_bundle/helper/settings_bundle_helper.rb', line 50

def settings_from_project(project, configuration, target_name)
  if target_name
    target = project.targets.find { |t| t.name == target_name }
    raise "Target named \"#{target_name}\" not found" if target.nil?
  else
    # find the first non-test, non-extension target
    # TODO: Make this a :target parameter
    target = project.targets.find { |t| !t.test_target_type? && !t.extension_target_type? }
    raise "No application target found" if target.nil?
  end

  # this can differ from one configuration to another.
  # take from Release, since only one Settings.bundle per project
  # (not per configuration)
  release_info_plist_path = expanded_build_setting target, "INFOPLIST_FILE", configuration

  raise "Info.plist not found for configuration #{configuration}" if release_info_plist_path.nil?

  project_parent = File.dirname project.path

  release_info_plist_path = File.join project_parent, release_info_plist_path

  # try to open and parse the Info.plist. raises on failure.
  info_plist = File.open(release_info_plist_path) { |f| Plist.parse_xml f }
  raise "Failed to parse plist file #{release_info_plist_path}" if info_plist.nil?

  # increments already happened. read the current state.
  current_marketing_version = info_plist["CFBundleShortVersionString"]
  current_build_number = info_plist["CFBundleVersion"]

  raise "CFBundleShortVersionString not found in Info.plist" if current_marketing_version.nil?
  raise "CFBundleVersion not found in Info.plist" if current_build_number.nil?

  Settings.new current_marketing_version, current_build_number
end

.update_settings_plist_title_setting(project, bundle_name, file, key, value) ⇒ Object

Takes an open Xcodeproj::Project, extracts the settings bundle and updates the specified setting key in the specified file to the specified value. Only valid for title items. Raises on error.

:project: An open Xcodeproj::Project, obtained from Xcodeproj::Project.open, e.g. :bundle_name: (String) Regex to identify the bundle to look for, usually Settings.bundle. :file: A settings plist file in the Settings.bundle, usually “Root.plist” :key: A valid NSUserDefaults key in the Settings.bundle :value: A new value for the key



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/fastlane/plugin/settings_bundle/helper/settings_bundle_helper.rb', line 96

def update_settings_plist_title_setting(project, bundle_name, file, key, value)
  settings_bundle = project.files.find { |f| f.path =~ /#{bundle_name}/ }

  raise "#{bundle_name} not found in project" if settings_bundle.nil?

  # The #real_path method returns the full resolved path to the Settings.bundle
  settings_bundle_path = settings_bundle.real_path

  plist_path = File.join settings_bundle_path, file

  # raises IOError
  settings_plist = File.open(plist_path) { |f| Plist.parse_xml f }

  raise "Could not parse #{plist_path}" if settings_plist.nil?

  preference_specifiers = settings_plist["PreferenceSpecifiers"]

  raise "#{file} is not a settings plist file" if preference_specifiers.nil?

  # Find the specifier for the supplied key
  title_specifier = preference_specifiers.find do |specifier|
    specifier["Key"] == key
  end

  raise "preference specifier for key #{key} not found in #{file}" if title_specifier.nil?
  raise "preference for key #{key} must be of type title" unless title_specifier["Type"] == "PSTitleValueSpecifier"

  # Update to the new value. Old value need not be present.
  title_specifier["DefaultValue"] = value.to_s

  # Save (raises)
  Plist::Emit.save_plist settings_plist, plist_path

  Actions.add_modified_files [plist_path] if Actions.respond_to? :add_modified_files
end

.xcodeproj_path_from_params(params) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/fastlane/plugin/settings_bundle/helper/settings_bundle_helper.rb', line 132

def xcodeproj_path_from_params(params)
  return params[:xcodeproj] if params[:xcodeproj]

  # Adapted from commit_version_bump
  # https://github.com/fastlane/fastlane/blob/master/fastlane/lib/fastlane/actions/commit_version_bump.rb#L21

  # This may not be a git project. Search relative to the Gemfile.
  repo_path = Bundler.root

  # find an xcodeproj (ignoring dependencies)
  xcodeproj_paths = Fastlane::Helper::XcodeprojHelper.find(repo_path)

  # no projects found: error
  UI.user_error!('Could not find a .xcodeproj in the current repository\'s working directory.') and return nil if xcodeproj_paths.count == 0

  # too many projects found: error
  if xcodeproj_paths.count > 1
    repo_pathname = Pathname.new repo_path
    relative_projects = xcodeproj_paths.map { |e| Pathname.new(e).relative_path_from(repo_pathname).to_s }.join("\n")
    UI.user_error!("Found multiple .xcodeproj projects in the current repository's working directory. Please specify your app's main project: \n#{relative_projects}")
    return nil
  end

  # one project found: great
  xcodeproj_paths.first
end