Class: BranchIOCLI::Configuration::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/branch_io_cli/configuration/configuration.rb

Overview

rubocop: disable Metrics/ClassLength

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Configuration

Returns a new instance of Configuration.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/branch_io_cli/configuration/configuration.rb', line 86

def initialize(options)
  @options = options
  @pod_repo_update = options.pod_repo_update if self.class.available_options.map(&:name).include?(:pod_repo_update)
  @sdk = "iphonesimulator" # to load Xcode build settings for commands without a --sdk option
  @confirm = options.confirm

  Configuration.current = self

  unless quiet
    say "\n"
    print_identification
    say ASCII_ART
    say "\n"
  end

  validate_options
  log
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_sym, *arguments, &block) ⇒ Object



464
465
466
467
468
469
470
471
472
473
474
# File 'lib/branch_io_cli/configuration/configuration.rb', line 464

def method_missing(method_sym, *arguments, &block)
  all_options = self.class.available_options.map(&:name)
  return super unless all_options.include?(method_sym)

  # Define an attr_reader for this method
  self.class.send :define_method, method_sym do
    instance_variable_get "@#{method_sym}"
  end

  send method_sym
end

Class Attribute Details

.currentObject

Returns the value of attribute current.



10
11
12
# File 'lib/branch_io_cli/configuration/configuration.rb', line 10

def current
  @current
end

Instance Attribute Details

#appsObject (readonly)

Returns the value of attribute apps.



83
84
85
# File 'lib/branch_io_cli/configuration/configuration.rb', line 83

def apps
  @apps
end

#cartfile_pathObject (readonly)

Returns the value of attribute cartfile_path.



76
77
78
# File 'lib/branch_io_cli/configuration/configuration.rb', line 76

def cartfile_path
  @cartfile_path
end

#keysObject (readonly)

Returns the value of attribute keys.



82
83
84
# File 'lib/branch_io_cli/configuration/configuration.rb', line 82

def keys
  @keys
end

#optionsObject (readonly)

Returns the value of attribute options.



70
71
72
# File 'lib/branch_io_cli/configuration/configuration.rb', line 70

def options
  @options
end

#pod_repo_updateObject (readonly)

Returns the value of attribute pod_repo_update.



80
81
82
# File 'lib/branch_io_cli/configuration/configuration.rb', line 80

def pod_repo_update
  @pod_repo_update
end

#podfileObject (readonly)

Returns the value of attribute podfile.



74
75
76
# File 'lib/branch_io_cli/configuration/configuration.rb', line 74

def podfile
  @podfile
end

#podfile_pathObject (readonly)

Returns the value of attribute podfile_path.



75
76
77
# File 'lib/branch_io_cli/configuration/configuration.rb', line 75

def podfile_path
  @podfile_path
end

#quietObject (readonly)

Returns the value of attribute quiet.



84
85
86
# File 'lib/branch_io_cli/configuration/configuration.rb', line 84

def quiet
  @quiet
end

#sdkObject (readonly)

Returns the value of attribute sdk.



81
82
83
# File 'lib/branch_io_cli/configuration/configuration.rb', line 81

def sdk
  @sdk
end

#sdk_integration_modeObject (readonly)

Returns the value of attribute sdk_integration_mode.



77
78
79
# File 'lib/branch_io_cli/configuration/configuration.rb', line 77

def sdk_integration_mode
  @sdk_integration_mode
end

#targetObject (readonly)

Returns the value of attribute target.



73
74
75
# File 'lib/branch_io_cli/configuration/configuration.rb', line 73

def target
  @target
end

#workspaceObject (readonly)

Returns the value of attribute workspace.



78
79
80
# File 'lib/branch_io_cli/configuration/configuration.rb', line 78

def workspace
  @workspace
end

#workspace_pathObject (readonly)

Returns the value of attribute workspace_path.



79
80
81
# File 'lib/branch_io_cli/configuration/configuration.rb', line 79

def workspace_path
  @workspace_path
end

#xcodeprojObject (readonly)

Returns the value of attribute xcodeproj.



71
72
73
# File 'lib/branch_io_cli/configuration/configuration.rb', line 71

def xcodeproj
  @xcodeproj
end

#xcodeproj_pathObject (readonly)

Returns the value of attribute xcodeproj_path.



72
73
74
# File 'lib/branch_io_cli/configuration/configuration.rb', line 72

def xcodeproj_path
  @xcodeproj_path
end

Class Method Details

.absolute_path(path) ⇒ Object



32
33
34
35
# File 'lib/branch_io_cli/configuration/configuration.rb', line 32

def absolute_path(path)
  return path unless current
  current.absolute_path path
end

.available_optionsObject



27
28
29
30
# File 'lib/branch_io_cli/configuration/configuration.rb', line 27

def available_options
  root = name.gsub(/^.*::(\w+)Configuration$/, '\1')
  BranchIOCLI::Configuration.const_get("#{root.capitalize}Options").available_options
end

.defaultsObject



16
17
18
19
20
21
22
23
24
25
# File 'lib/branch_io_cli/configuration/configuration.rb', line 16

def defaults
  available_options.inject({}) do |defs, o|
    default_value = o.env_value
    default_value = o.default_value if default_value.nil?

    next defs if default_value.nil?

    defs.merge(o.name => default_value)
  end
end

.open_podfile(path) ⇒ Object



42
43
44
45
# File 'lib/branch_io_cli/configuration/configuration.rb', line 42

def open_podfile(path)
  return false unless current
  current.open_podfile absolute_path path
end

.open_xcodeproj(path) ⇒ Object



47
48
49
50
# File 'lib/branch_io_cli/configuration/configuration.rb', line 47

def open_xcodeproj(path)
  return false unless current
  current.open_xcodeproj absolute_path path
end

.relative_path(path) ⇒ Object



37
38
39
40
# File 'lib/branch_io_cli/configuration/configuration.rb', line 37

def relative_path(path)
  return path unless current
  current.relative_path path
end

.rootObject



52
53
54
55
# File 'lib/branch_io_cli/configuration/configuration.rb', line 52

def root
  return nil unless current
  current.root
end

.uri_scheme_without_suffix(scheme) ⇒ Object

Removes any trailing :/* from the argument and returns a copy. Matches:

myscheme
myscheme:
myscheme://
myscheme:///
etc.


64
65
66
67
# File 'lib/branch_io_cli/configuration/configuration.rb', line 64

def uri_scheme_without_suffix(scheme)
  return nil if scheme.blank?
  scheme.sub %r{:/*$}, ""
end

.wrapper(hash, add_defaults = true) ⇒ Object



12
13
14
# File 'lib/branch_io_cli/configuration/configuration.rb', line 12

def wrapper(hash, add_defaults = true)
  OptionWrapper.new hash, available_options, add_defaults
end

Instance Method Details

#absolute_path(path) ⇒ Object



143
144
145
146
147
148
149
150
# File 'lib/branch_io_cli/configuration/configuration.rb', line 143

def absolute_path(path)
  return nil if path.nil?

  path = Pathname.new(path) unless path.kind_of? Pathname
  return path.to_s if path.absolute?

  (root + path).to_s
end

#all_xcodeproj_pathsObject



178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/branch_io_cli/configuration/configuration.rb', line 178

def all_xcodeproj_paths
  return @all_xcodeproj_paths if @all_xcodeproj_paths
  xcodeproj_paths = Dir[File.expand_path(File.join(".", "**/*.xcodeproj"))]
  @all_xcodeproj_paths = xcodeproj_paths.select do |p|
    valid = true
    Pathname.new(p).each_filename do |f|
      valid = false && break if f == "Carthage" || f == "Pods"
    end
    valid
  end
  @all_xcodeproj_paths
end

#app_delegate_objc_pathObject



377
378
379
380
381
382
# File 'lib/branch_io_cli/configuration/configuration.rb', line 377

def app_delegate_objc_path
  app_delegate = target.source_build_phase.files.find { |f| f.file_ref.path =~ /AppDelegate\.m$/ }
  return nil if app_delegate.nil?

  app_delegate.file_ref.real_path.to_s
end

#app_delegate_swift_pathObject



368
369
370
371
372
373
374
375
# File 'lib/branch_io_cli/configuration/configuration.rb', line 368

def app_delegate_swift_path
  return nil unless swift_version && swift_version.to_f >= 3.0

  app_delegate = target.source_build_phase.files.find { |f| f.file_ref.path =~ /AppDelegate\.swift$/ }
  return nil if app_delegate.nil?

  app_delegate.file_ref.real_path.to_s
end

#branch_importsObject



436
437
438
439
440
441
442
443
444
445
446
447
# File 'lib/branch_io_cli/configuration/configuration.rb', line 436

def branch_imports
  return @branch_imports if @branch_imports

  source_files = target.source_build_phase.files.map { |f| f.file_ref.real_path.to_s }
  source_files << bridging_header_path if bridging_header_path && File.exist?(bridging_header_path)
  @branch_imports = source_files.compact.map do |f|
    imports = branch_imports_from_file f
    next {} if imports.empty?
    { f => imports }
  end.inject({}, :merge)
  @branch_imports
end

#branch_imports_from_file(path) ⇒ Object

Detect anything that appears to be an attempt to import the Branch SDK, even if it might be wrong.



451
452
453
454
455
456
457
458
459
460
461
462
# File 'lib/branch_io_cli/configuration/configuration.rb', line 451

def branch_imports_from_file(path)
  imports = []
  File.readlines(path).each_with_index do |line, line_no|
    next unless line =~ /(include|import).*branch/i
    imports << "#{line_no}: #{line.chomp}"
  end
  imports
rescue StandardError
  # Quietly ignore anything that can't be opened for now.
  # TODO: Get these errors into report output.
  []
end

#bridging_header_path(configuration = "Release") ⇒ Object



417
418
419
420
421
422
423
424
425
426
# File 'lib/branch_io_cli/configuration/configuration.rb', line 417

def bridging_header_path(configuration = "Release")
  return @bridging_header_path if @bridging_header_path

  return nil unless target
  path = target.expanded_build_setting "SWIFT_OBJC_BRIDGING_HEADER", configuration
  return nil unless path

  @bridging_header_path = File.expand_path path, File.dirname(xcodeproj_path)
  @bridging_header_path
end

#bridging_header_required?Boolean

Returns:

  • (Boolean)


361
362
363
364
365
366
# File 'lib/branch_io_cli/configuration/configuration.rb', line 361

def bridging_header_required?
  return false unless swift_version
  # If there is a Podfile and use_frameworks! is not present for this
  # target, we need a bridging header.
  podfile && !uses_frameworks?
end

#confirm_with_userObject

Prompt the user to confirm the configuration or edit.



477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
# File 'lib/branch_io_cli/configuration/configuration.rb', line 477

def confirm_with_user
  confirmed = Helper::Util.confirm "Is this OK? ", true
  return if confirmed

  loop do
    Helper::Util.clear

    print_identification

    say "<%= color('The following options may be adjusted before continuing.', BOLD) %>"
    choice = choose do |menu|
      self.class.available_options.reject(&:skip_confirmation).each do |option|
        value = send option.confirm_symbol
        menu.choice "#{option.label}: #{option.display_value(value)}"
      end

      menu.choice "Accept and continue"
      menu.choice "Quit"
      menu.readline = true
      menu.prompt = "What would you like to do?"
    end

    Helper::Util.clear

    print_identification

    if (option = self.class.available_options.find { |o| choice =~ /^#{Regexp.quote(o.label)}/ })
      loop do
        break if prompt_for_option(option)
        say "Invalid value for option.\n\n"
      end
    elsif choice =~ /^Accept/
      log
      return
    else
      exit(0)
    end
  end
end

#find_projectObject



191
192
193
# File 'lib/branch_io_cli/configuration/configuration.rb', line 191

def find_project
  all_xcodeproj_paths.count == 1 ? all_xcodeproj_paths.first : nil
end

#helperObject



125
126
127
# File 'lib/branch_io_cli/configuration/configuration.rb', line 125

def helper
  Helper::BranchHelper
end

#ios_urischemes_from_api(apps = @apps) ⇒ Object



404
405
406
# File 'lib/branch_io_cli/configuration/configuration.rb', line 404

def ios_urischemes_from_api(apps = @apps)
  Set.new apps.map(&:ios_uri_scheme).compact
end

#key_valid?(key, type) ⇒ Boolean

Returns:

  • (Boolean)


300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/branch_io_cli/configuration/configuration.rb', line 300

def key_valid?(key, type)
  return false if key.nil?
  return true if key.empty?
  unless key =~ /^key_#{type}_.+/
    say "#{key.inspect} is not a valid #{type} Branch key. It must begin with key_#{type}_."
    return false
  end

  # For now: When using --no-validate with the setup command, don't call the Branch API.
  return true unless self.class.available_options.map(&:name).include?(:validate) && validate

  begin
    # Retrieve info from the API
    app = BranchApp[key]
    @apps[key] = app
    true
  rescue StandardError => e
    say "Error fetching app for key #{key} from Branch API: #{e.message}"
    false
  end
end

#logObject



109
110
111
112
113
114
115
116
117
# File 'lib/branch_io_cli/configuration/configuration.rb', line 109

def log
  return if quiet

  say <<EOF
<%= color('Configuration:', [CYAN, BOLD, UNDERLINE]) %>

EOF
  # subclass implementation follows
end

#messages_view_controller_pathObject



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/branch_io_cli/configuration/configuration.rb', line 384

def messages_view_controller_path
  return nil unless target.symbol_type == :messages_extension

  all_paths = target.source_build_phase.files.map { |f| f.file_ref.real_path.to_s }
  swift_paths = all_paths.grep(/\.swift$/)

  # We're looking for the @interface declaration for a class that inherits from
  # MSMessagesAppViewController. The target probably doesn't have a headers
  # build phase. Include all .ms from the source build phase and any .h
  # with the same root.
  objc_paths = all_paths.grep(/\.m$/)
  objc_paths += objc_paths.map { |p| p.sub(/\.m$/, '.h') }.select { |f| File.exist? f }

  path = swift_paths.find { |f| /class.*:\s+MSMessagesAppViewController\s*{\n/m.match_file? f } ||
         objc_paths.find { |f| /@interface.*:\s+MSMessagesAppViewController/.match_file? f }

  # If we found a .h, patch the corresponding .m.
  path && path.sub(/\.h$/, '.m')
end

#modules_enabled?Boolean

TODO: How many of these can vary by configuration?

Returns:

  • (Boolean)


410
411
412
413
414
415
# File 'lib/branch_io_cli/configuration/configuration.rb', line 410

def modules_enabled?
  return nil unless target
  setting = target.resolved_build_setting("CLANG_ENABLE_MODULES")["Release"]
  return nil unless setting
  setting == "YES"
end

#open_podfile(path = podfile_path) ⇒ Object



242
243
244
245
246
247
248
249
250
# File 'lib/branch_io_cli/configuration/configuration.rb', line 242

def open_podfile(path = podfile_path)
  @podfile = Pod::Podfile.from_file path
  @podfile_path = File.expand_path path
  @sdk_integration_mode = :cocoapods
  true
rescue Pod::PlainInformative => e
  say e.message
  false
end

#open_xcodeproj(path = xcodeproj_path) ⇒ Object



252
253
254
255
256
257
258
259
# File 'lib/branch_io_cli/configuration/configuration.rb', line 252

def open_xcodeproj(path = xcodeproj_path)
  @xcodeproj = Xcodeproj::Project.open path
  @xcodeproj_path = File.expand_path path
  true
rescue Xcodeproj::PlainInformative => e
  say e.message
  false
end

#pod_install_required?Boolean

Returns:

  • (Boolean)


329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/branch_io_cli/configuration/configuration.rb', line 329

def pod_install_required?
  # If this is set, its existence has been verified.
  return false unless podfile_path

  lockfile_path = "#{podfile_path}.lock"
  manifest_path = File.expand_path "../Pods/Manifest.lock", podfile_path

  return true unless File.exist?(lockfile_path) && File.exist?(manifest_path)

  lockfile = Pod::Lockfile.from_file Pathname.new lockfile_path
  manifest = Pod::Lockfile.from_file Pathname.new manifest_path

  # diff the contents of Podfile.lock and Pods/Manifest.lock
  # This is just what is done in the "[CP] Check Pods Manifest.lock" script build phase
  # in a project using CocoaPods.
  return true unless lockfile == manifest

  # compare checksum of Podfile with checksum in Podfile.lock
  # This is a good sanity check, but perhaps unnecessary. It means pod install
  # has not been run since the Podfile was modified, which is probably an oversight.
  return true unless lockfile.to_hash["PODFILE CHECKSUM"] == podfile.checksum

  false
end


119
120
121
122
123
# File 'lib/branch_io_cli/configuration/configuration.rb', line 119

def print_identification
  say <<EOF
<%= color("branch_io #{self.class.name.sub(/^.*::(.*?)Configuration$/, '\1').downcase} v. #{VERSION}", BOLD) %>
EOF
end

#prompt_for_option(option) ⇒ Object



517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
# File 'lib/branch_io_cli/configuration/configuration.rb', line 517

def prompt_for_option(option)
  say "<%= color('#{option.label}', BOLD) %>\n\n"
  say "#{option.description}\n\n"
  value = send option.confirm_symbol
  say "<%= color('Type', BOLD) %>: #{option.ui_type}\n"
  say "<%= color('Current value', BOLD) %>: #{option.display_value(value)}"
  say "<%= color('Example', BOLD) %>: #{option.example}" if option.example
  say "\n"

  valid_values = option.valid_values

  if valid_values && !option.type.nil? && option.type != Array
    new_value = choose(*valid_values) do |menu|
      menu.readline = true
      menu.prompt = "Please choose from this list. "
    end

    # Valid because chosen from list
  elsif valid_values && option.type == Array
    # There seems to be a problem with using menu.gather, so we do this.
    valid_values.each do |v|
      say "#{v}\n"
    end

    new_value = ask "Please enter one or more of the above, separated by commas: " do |q|
      q.readline = true
      q.completion = valid_values
    end

    new_value = new_value.split(",") # comma-split with ask("...", Array) not working
  elsif option.type.nil?
    new_value = Helper::Util.confirm "#{option.label}? ", value
  else
    new_value = ask "Please enter a new value for #{option.label}: ", option.type
  end

  new_value = option.convert new_value

  return false unless option.valid?(new_value)
  instance_variable_set "@#{option.confirm_symbol}", new_value
  true
end

#relative_path(path) ⇒ Object



152
153
154
155
156
157
158
159
# File 'lib/branch_io_cli/configuration/configuration.rb', line 152

def relative_path(path)
  return nil if path.nil?

  path = Pathname.new(path) unless path.kind_of? Pathname
  return path.to_s unless path.absolute?

  path.relative_path_from(root).to_s
end

#rootObject



133
134
135
136
137
138
139
140
141
# File 'lib/branch_io_cli/configuration/configuration.rb', line 133

def root
  return @root if @root
  if workspace
    @root = Pathname.new(workspace_path).dirname
  else
    @root = Pathname.new(xcodeproj_path).dirname
  end
  @root
end

#swift_versionObject



428
429
430
431
432
433
434
# File 'lib/branch_io_cli/configuration/configuration.rb', line 428

def swift_version
  return @swift_version if @swift_version

  return nil unless target
  @swift_version = target.resolved_build_setting("SWIFT_VERSION")["Release"]
  @swift_version
end

#target_nameObject



129
130
131
# File 'lib/branch_io_cli/configuration/configuration.rb', line 129

def target_name
  target.name.nil? ? nil : target.name
end

#uses_frameworks?Boolean

Returns:

  • (Boolean)


354
355
356
357
358
359
# File 'lib/branch_io_cli/configuration/configuration.rb', line 354

def uses_frameworks?
  return nil unless podfile
  target_definition = podfile.target_definition_list.find { |t| t.name == target.name }
  return nil unless target_definition
  target_definition.uses_frameworks?
end

#validate_buildfile_at_path(buildfile_path, filename) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/branch_io_cli/configuration/configuration.rb', line 261

def validate_buildfile_at_path(buildfile_path, filename)
  valid = buildfile_path =~ %r{/?#{filename}$}
  say "#{filename} path must end in /#{filename}." unless valid

  if valid
    valid = File.exist? buildfile_path
    say "#{buildfile_path} not found." and return false unless valid
  end

  if filename == "Podfile" && open_podfile(buildfile_path)
    true
  elsif filename == "Cartfile"
    @cartfile_path = buildfile_path
    @sdk_integration_mode = :carthage
    true
  else
    false
  end
end

#validate_buildfile_path(buildfile_path, filename) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/branch_io_cli/configuration/configuration.rb', line 225

def validate_buildfile_path(buildfile_path, filename)
  # Disable Podfile/Cartfile update if --no-add-sdk is present
  return unless sdk_integration_mode.nil?

  # No --podfile or --cartfile option
  if buildfile_path.nil?
    # Check for Podfile/Cartfile next to workspace or project
    buildfile_path = File.expand_path "../#{filename}", (workspace_path || xcodeproj_path)
    return unless File.exist? buildfile_path
  end

  # Validate. Prompt if not valid.
  buildfile_path = ask "Please enter the path to your #{filename}: " while !buildfile_path || !validate_buildfile_at_path(buildfile_path, filename)

  @sdk_integration_mode = filename == "Podfile" ? :cocoapods : :carthage
end

#validate_key(key, type, options = {}) ⇒ Object



322
323
324
325
326
327
# File 'lib/branch_io_cli/configuration/configuration.rb', line 322

def validate_key(key, type, options = {})
  return if options[:accept_nil] && key.nil?
  key = ask "Please enter your #{type} Branch key or use --#{type}-key [enter for none]: " until key_valid? key, type
  @keys[type] = key unless key.empty?
  instance_variable_set "@#{type}_key", key
end

#validate_keys(optional: false) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/branch_io_cli/configuration/configuration.rb', line 281

def validate_keys(optional: false)
  @keys = {}
  @apps = {}

  # 1. Check the options passed in. If nothing (nil) passed, continue.
  validate_key options.live_key, :live, accept_nil: true
  validate_key options.test_key, :test, accept_nil: true

  # 2. Did we find a valid key above?
  while !optional && @keys.empty?
    # 3. If not, prompt.
    say "A live key, a test key or both is required."
    validate_key nil, :live
    validate_key nil, :test
  end

  # 4. We have at least one valid key now, unless optional is truthy.
end

#validate_optionsObject



105
106
107
# File 'lib/branch_io_cli/configuration/configuration.rb', line 105

def validate_options
  # implemented in subclasses
end

#validate_target(allow_extensions = true) ⇒ Object



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/branch_io_cli/configuration/configuration.rb', line 195

def validate_target(allow_extensions = true)
  return if @target

  non_test_targets = xcodeproj.targets.reject(&:test_target_type?)
  raise "No non-test target found in project" if non_test_targets.empty?

  valid_targets = non_test_targets.reject { |t| !allow_extensions && t.extension_target_type? }

  begin
    target = helper.target_from_project xcodeproj, options.target

    # If a test target was explicitly specified.
    raise "Cannot use test targets" if target.test_target_type?

    # If an extension target was explicitly specified for validation.
    raise "Extension targets not allowed for this command" if !allow_extensions && target.extension_target_type?

    @target = target
  rescue StandardError => e
    say e.message

    choice = choose do |menu|
      valid_targets.each { |t| menu.choice t.name }
      menu.prompt = "Which target do you wish to use? "
    end

    @target = xcodeproj.targets.find { |t| t.name = choice }
  end
end

#validate_xcodeproj_pathObject

  1. Look for options.xcodeproj.

  2. If not specified, look for projects under . (excluding anything in Pods or Carthage folder).

  3. If none or more than one found, prompt the user.



164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/branch_io_cli/configuration/configuration.rb', line 164

def validate_xcodeproj_path
  if options.xcodeproj
    path = options.xcodeproj
  else
    path = find_project
  end

  loop do
    path = ask "Please enter the path to your Xcode project or use --xcodeproj: " if path.nil?
    # TODO: Allow the user to choose if xcodeproj_paths.count > 0
    return if open_xcodeproj path
  end
end