branch_io_cli 0.10.0 → 0.11.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +78 -30
  3. data/lib/assets/completions/completion.bash +1 -1
  4. data/lib/assets/completions/completion.zsh +1 -1
  5. data/lib/assets/templates/command.erb +31 -0
  6. data/lib/assets/templates/program_description.erb +2 -0
  7. data/lib/assets/templates/report_description.erb +4 -0
  8. data/lib/assets/templates/setup_description.erb +52 -0
  9. data/lib/assets/templates/validate_description.erb +18 -0
  10. data/lib/branch_io_cli.rb +1 -0
  11. data/lib/branch_io_cli/cli.rb +50 -147
  12. data/lib/branch_io_cli/command/command.rb +28 -6
  13. data/lib/branch_io_cli/command/report_command.rb +1 -1
  14. data/lib/branch_io_cli/command/setup_command.rb +4 -7
  15. data/lib/branch_io_cli/command/validate_command.rb +0 -2
  16. data/lib/branch_io_cli/configuration.rb +2 -0
  17. data/lib/branch_io_cli/configuration/configuration.rb +27 -1
  18. data/lib/branch_io_cli/configuration/option.rb +28 -0
  19. data/lib/branch_io_cli/configuration/option_wrapper.rb +33 -0
  20. data/lib/branch_io_cli/configuration/report_configuration.rb +83 -7
  21. data/lib/branch_io_cli/configuration/setup_configuration.rb +142 -9
  22. data/lib/branch_io_cli/configuration/validate_configuration.rb +30 -1
  23. data/lib/branch_io_cli/core_ext/io.rb +5 -2
  24. data/lib/branch_io_cli/format.rb +15 -0
  25. data/lib/branch_io_cli/format/commander_format.rb +21 -0
  26. data/lib/branch_io_cli/format/markdown_format.rb +60 -0
  27. data/lib/branch_io_cli/helper/ios_helper.rb +14 -14
  28. data/lib/branch_io_cli/helper/methods.rb +2 -2
  29. data/lib/branch_io_cli/rake_task.rb +26 -54
  30. data/lib/branch_io_cli/version.rb +1 -1
  31. metadata +12 -2
@@ -1,17 +1,39 @@
1
1
  module BranchIOCLI
2
2
  module Command
3
3
  class Command
4
+ class << self
5
+ def command_name
6
+ matches = /BranchIOCLI::Command::(\w+)Command/.match name
7
+ matches[1].downcase
8
+ end
9
+
10
+ def configuration_class
11
+ root = command_name.capitalize
12
+
13
+ Object.const_get("BranchIOCLI")
14
+ .const_get("Configuration")
15
+ .const_get("#{root}Configuration")
16
+ end
17
+
18
+ def available_options
19
+ configuration_class.available_options
20
+ end
21
+
22
+ def examples
23
+ configuration_class.examples if configuration_class.respond_to?(:examples)
24
+ end
25
+
26
+ def return_value
27
+ configuration_class.return_value if configuration_class.respond_to?(:return_value)
28
+ end
29
+ end
30
+
4
31
  attr_reader :options # command-specific options from CLI
5
32
  attr_reader :config # command-specific configuration object
6
33
 
7
34
  def initialize(options)
8
35
  @options = options
9
- matches = /BranchIOCLI::Command::(\w+)Command/.match self.class.name
10
- root = matches[1]
11
-
12
- @config = Object.const_get("BranchIOCLI")
13
- .const_get("Configuration")
14
- .const_get("#{root}Configuration").new options
36
+ @config = self.class.configuration_class.new options
15
37
  end
16
38
 
17
39
  def run!
@@ -44,7 +44,7 @@ module BranchIOCLI
44
44
  if config.workspace_path
45
45
  config.workspace.file_references.map(&:path).each do |project_path|
46
46
  path = File.join File.dirname(config.workspace_path), project_path
47
- report.log_command "xcodebuild -list -project #{Shellwords.escape path}"
47
+ report.log_command ["xcodebuild", "-list", "-project", path]
48
48
  end
49
49
  end
50
50
 
@@ -1,11 +1,8 @@
1
1
  require "branch_io_cli/helper/methods"
2
- require "shellwords"
3
2
 
4
3
  module BranchIOCLI
5
4
  module Command
6
5
  class SetupCommand < Command
7
- attr_reader :config
8
-
9
6
  def initialize(options)
10
7
  super
11
8
  @keys = config.keys
@@ -47,7 +44,7 @@ module BranchIOCLI
47
44
  helper.ensure_uri_scheme_in_info_plist if is_app_target # does nothing if already present
48
45
 
49
46
  new_path = helper.add_universal_links_to_project @domains, false if is_app_target
50
- sh "git add #{Shellwords.escape(new_path)}" if options.commit && new_path
47
+ sh ["git", "add", new_path] if options.commit && new_path
51
48
 
52
49
  config_helper.target.add_system_frameworks options.frameworks unless options.frameworks.nil? || options.frameworks.empty?
53
50
 
@@ -79,7 +76,7 @@ module BranchIOCLI
79
76
  commit_message = options.commit if options.commit.kind_of?(String)
80
77
  commit_message ||= "[branch_io_cli] Branch SDK integration #{config.relative_path(config.xcodeproj_path)} (#{config.target.name})"
81
78
 
82
- sh "git commit -qm #{Shellwords.escape commit_message} #{changes.join(' ')}"
79
+ sh ["git", "commit", "-qm", commit_message, *changes]
83
80
  end
84
81
  # rubocop: enable Metrics/PerceivedComplexity
85
82
 
@@ -87,7 +84,7 @@ module BranchIOCLI
87
84
  # If the git command is not installed, there's not much we can do.
88
85
  # Don't want to use verify_git here, which will insist on installing
89
86
  # the command. The logic of that method could change.
90
- return if `which git`.empty?
87
+ return if `which git`.empty? || !config.check_repo_changes
91
88
 
92
89
  unless Dir.exist? ".git"
93
90
  `git rev-parse --git-dir > /dev/null 2>&1`
@@ -115,7 +112,7 @@ module BranchIOCLI
115
112
  sh "git stash -q"
116
113
  when /^Commit/
117
114
  message = ask "Please enter a commit message: "
118
- sh "git commit -aqm #{Shellwords.escape(message)}"
115
+ sh ["git", "commit", "-aqm", message]
119
116
  when /^Quit/
120
117
  say "Please stash or commit your changes before continuing."
121
118
  exit(-1)
@@ -1,8 +1,6 @@
1
1
  module BranchIOCLI
2
2
  module Command
3
3
  class ValidateCommand < Command
4
- attr_reader :config
5
-
6
4
  def run!
7
5
  valid = true
8
6
 
@@ -1,4 +1,6 @@
1
1
  require "branch_io_cli/configuration/configuration"
2
+ require "branch_io_cli/configuration/option"
3
+ require "branch_io_cli/configuration/option_wrapper"
2
4
  require "branch_io_cli/configuration/report_configuration"
3
5
  require "branch_io_cli/configuration/setup_configuration"
4
6
  require "branch_io_cli/configuration/validate_configuration"
@@ -7,6 +7,17 @@ module BranchIOCLI
7
7
  class Configuration
8
8
  class << self
9
9
  attr_accessor :current
10
+
11
+ def wrapper(hash, add_defaults = true)
12
+ OptionWrapper.new hash, available_options, add_defaults
13
+ end
14
+
15
+ def defaults
16
+ available_options.inject({}) do |defs, o|
17
+ next defs if o.default_value.nil?
18
+ defs.merge(o.name => o.default_value)
19
+ end
20
+ end
10
21
  end
11
22
 
12
23
  attr_reader :options
@@ -23,7 +34,7 @@ module BranchIOCLI
23
34
 
24
35
  def initialize(options)
25
36
  @options = options
26
- @pod_repo_update = options.pod_repo_update
37
+ @pod_repo_update = options.pod_repo_update if options.respond_to?(:pod_repo_update)
27
38
  Configuration.current = self
28
39
 
29
40
  print_identification self.class.name.sub(/^.*::(.*?)Configuration$/, '\1').downcase
@@ -108,6 +119,8 @@ EOF
108
119
  end
109
120
 
110
121
  def validate_target(allow_extensions = true)
122
+ return if @target
123
+
111
124
  non_test_targets = xcodeproj.targets.reject(&:test_target_type?)
112
125
  raise "No non-test target found in project" if non_test_targets.empty?
113
126
 
@@ -310,6 +323,19 @@ EOF
310
323
  end
311
324
  imports
312
325
  end
326
+
327
+ def method_missing(method_sym, *arguments, &block)
328
+ all_options = self.class.available_options.map(&:name)
329
+ return super unless all_options.include?(method_sym)
330
+
331
+ self.class.send :define_method, method_sym do
332
+ ivar = "@#{method_sym}"
333
+ value = instance_variable_get ivar
334
+ value
335
+ end
336
+
337
+ send method_sym
338
+ end
313
339
  end
314
340
  end
315
341
  end
@@ -0,0 +1,28 @@
1
+ module BranchIOCLI
2
+ module Configuration
3
+ class Option
4
+ attr_accessor :name
5
+ attr_accessor :type
6
+ attr_accessor :description
7
+ attr_accessor :default_value
8
+ attr_accessor :example
9
+ attr_accessor :argument_optional
10
+ attr_accessor :aliases
11
+ attr_accessor :negatable
12
+
13
+ def initialize(options)
14
+ @name = options[:name]
15
+ @type = options[:type]
16
+ @description = options[:description]
17
+ @default_value = options[:default_value]
18
+ @example = options[:example]
19
+ @argument_optional = options[:argument_optional] || false
20
+ @aliases = options[:aliases] || []
21
+ @aliases = [@aliases] unless @aliases.kind_of?(Array)
22
+ @negatable = options[:type].nil? if options[:negatable].nil?
23
+
24
+ @argument_optional ||= @negatable
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ module BranchIOCLI
2
+ module Configuration
3
+ # Proxy class for use with Command.new.
4
+ class OptionWrapper
5
+ attr_reader :hash
6
+ attr_reader :options
7
+ attr_reader :add_defaults
8
+
9
+ def initialize(hash, options, add_defaults = true)
10
+ raise ArgumentError if hash.nil?
11
+
12
+ @hash = hash
13
+ @options = options
14
+ @add_defaults = add_defaults
15
+
16
+ build_option_hash
17
+ end
18
+
19
+ def method_missing(method_sym, *arguments, &block)
20
+ option = @option_hash[method_sym]
21
+ return super unless option
22
+
23
+ value = hash[method_sym]
24
+ return value unless add_defaults && value.nil?
25
+ option.default_value
26
+ end
27
+
28
+ def build_option_hash
29
+ @option_hash = options.inject({}) { |hash, o| hash.merge o.name => o }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -43,13 +43,89 @@ end
43
43
 
44
44
  module BranchIOCLI
45
45
  module Configuration
46
+ # rubocop: disable Metrics/ClassLength
46
47
  class ReportConfiguration < Configuration
47
- attr_reader :clean
48
- attr_reader :header_only
49
- attr_reader :scheme
50
- attr_reader :configuration
48
+ class << self
49
+ def available_options
50
+ [
51
+ Option.new(
52
+ name: :workspace,
53
+ description: "Path to an Xcode workspace",
54
+ type: String,
55
+ example: "MyProject.xcworkspace"
56
+ ),
57
+ Option.new(
58
+ name: :xcodeproj,
59
+ description: "Path to an Xcode project",
60
+ type: String,
61
+ example: "MyProject.xcodeproj"
62
+ ),
63
+ Option.new(
64
+ name: :scheme,
65
+ description: "A scheme from the project or workspace to build",
66
+ type: String,
67
+ example: "MyProjectScheme"
68
+ ),
69
+ Option.new(
70
+ name: :target,
71
+ description: "A target to build",
72
+ type: String,
73
+ example: "MyProjectTarget"
74
+ ),
75
+ Option.new(
76
+ name: :configuration,
77
+ description: "The build configuration to use (default: Scheme-dependent)",
78
+ type: String,
79
+ example: "Debug/Release/CustomConfigName"
80
+ ),
81
+ Option.new(
82
+ name: :sdk,
83
+ description: "Passed as -sdk to xcodebuild",
84
+ type: String,
85
+ example: "iphoneos",
86
+ default_value: "iphonesimulator"
87
+ ),
88
+ Option.new(
89
+ name: :podfile,
90
+ description: "Path to the Podfile for the project",
91
+ type: String,
92
+ example: "/path/to/Podfile"
93
+ ),
94
+ Option.new(
95
+ name: :cartfile,
96
+ description: "Path to the Cartfile for the project",
97
+ type: String,
98
+ example: "/path/to/Cartfile"
99
+ ),
100
+ Option.new(
101
+ name: :clean,
102
+ description: "Clean before attempting to build",
103
+ default_value: true
104
+ ),
105
+ Option.new(
106
+ name: :header_only,
107
+ description: "Write a report header to standard output and exit",
108
+ default_value: false,
109
+ aliases: "-H"
110
+ ),
111
+ Option.new(
112
+ name: :pod_repo_update,
113
+ description: "Update the local podspec repo before installing",
114
+ default_value: true
115
+ ),
116
+ Option.new(
117
+ name: :out,
118
+ description: "Report output path",
119
+ default_value: "./report.txt",
120
+ aliases: "-o",
121
+ example: "./report.txt",
122
+ type: String
123
+ )
124
+ ]
125
+ end
126
+ end
127
+
51
128
  attr_reader :report_path
52
- attr_reader :sdk
53
129
 
54
130
  def validate_options
55
131
  @clean = options.clean
@@ -216,9 +292,8 @@ EOF
216
292
  return if options.target || xcscheme.nil?
217
293
 
218
294
  # Find the target used when running the scheme if the user didn't specify one.
219
- # This will be picked up in #validate_target
220
295
  entry = xcscheme.build_action.entries.select(&:build_for_running?).first
221
- options.target = entry.buildable_references.first.target_name
296
+ @target = xcodeproj.targets.find { |t| t.name == entry.buildable_references.first.target_name }
222
297
  end
223
298
 
224
299
  def all_schemes
@@ -391,5 +466,6 @@ EOF
391
466
  @branch_key_setting_from_info_plist
392
467
  end
393
468
  end
469
+ # rubocop: enable Metrics/ClassLength
394
470
  end
395
471
  end
@@ -1,6 +1,147 @@
1
1
  module BranchIOCLI
2
2
  module Configuration
3
+ # rubocop: disable Metrics/ClassLength
3
4
  class SetupConfiguration < Configuration
5
+ class << self
6
+ def examples
7
+ {
8
+ "Test without validation (can use dummy keys and domains)" => "branch_io setup -L key_live_xxxx -D myapp.app.link --no-validate",
9
+ "Use both live and test keys" => "branch_io setup -L key_live_xxxx -T key_test_yyyy -D myapp.app.link",
10
+ "Use custom or non-Branch domains" => "branch_io setup -D myapp.app.link,example.com,www.example.com",
11
+ "Avoid pod repo update" => "branch_io setup --no-pod-repo-update",
12
+ "Install using carthage bootstrap" => "branch_io --carthage-command \"bootstrap --no-use-binaries\""
13
+ }
14
+ end
15
+
16
+ def available_options
17
+ [
18
+ Option.new(
19
+ name: :live_key,
20
+ description: "Branch live key",
21
+ example: "key_live_xxxx",
22
+ type: String,
23
+ aliases: "-L"
24
+ ),
25
+ Option.new(
26
+ name: :test_key,
27
+ description: "Branch test key",
28
+ example: "key_test_yyyy",
29
+ type: String,
30
+ aliases: "-T"
31
+ ),
32
+ Option.new(
33
+ name: :domains,
34
+ description: "Comma-separated list of custom domain(s) or non-Branch domain(s)",
35
+ example: "example.com,www.example.com",
36
+ type: Array,
37
+ aliases: "-D"
38
+ ),
39
+ Option.new(
40
+ name: :app_link_subdomain,
41
+ description: "Branch app.link subdomain, e.g. myapp for myapp.app.link",
42
+ example: "myapp",
43
+ type: String
44
+ ),
45
+ Option.new(
46
+ name: :uri_scheme,
47
+ description: "Custom URI scheme used in the Branch Dashboard for this app",
48
+ example: "myurischeme[://]",
49
+ type: String,
50
+ aliases: "-U"
51
+ ),
52
+ Option.new(
53
+ name: :setting,
54
+ description: "Use a custom build setting for the Branch key (default: Use Info.plist)",
55
+ example: "BRANCH_KEY_SETTING",
56
+ type: String,
57
+ argument_optional: true,
58
+ aliases: "-s"
59
+ ),
60
+ Option.new(
61
+ name: :test_configurations,
62
+ description: "List of configurations that use the test key with a custom build setting (default: Debug configurations)",
63
+ example: "config1,config2",
64
+ type: Array,
65
+ negatable: true
66
+ ),
67
+ Option.new(
68
+ name: :xcodeproj,
69
+ description: "Path to an Xcode project to update",
70
+ example: "MyProject.xcodeproj",
71
+ type: String
72
+ ),
73
+ Option.new(
74
+ name: :target,
75
+ description: "Name of a target to modify in the Xcode project",
76
+ example: "MyAppTarget",
77
+ type: String
78
+ ),
79
+ Option.new(
80
+ name: :podfile,
81
+ description: "Path to the Podfile for the project",
82
+ example: "/path/to/Podfile",
83
+ type: String
84
+ ),
85
+ Option.new(
86
+ name: :cartfile,
87
+ description: "Path to the Cartfile for the project",
88
+ example: "/path/to/Cartfile",
89
+ type: String
90
+ ),
91
+ Option.new(
92
+ name: :carthage_command,
93
+ description: "Command to run when installing from Carthage",
94
+ example: "<command>",
95
+ type: String,
96
+ default_value: "update --platform ios"
97
+ ),
98
+ Option.new(
99
+ name: :frameworks,
100
+ description: "Comma-separated list of system frameworks to add to the project",
101
+ example: "AdSupport,CoreSpotlight,SafariServices",
102
+ type: Array
103
+ ),
104
+ Option.new(
105
+ name: :pod_repo_update,
106
+ description: "Update the local podspec repo before installing",
107
+ default_value: true
108
+ ),
109
+ Option.new(
110
+ name: :validate,
111
+ description: "Validate Universal Link configuration",
112
+ default_value: true
113
+ ),
114
+ Option.new(
115
+ name: :force,
116
+ description: "Update project even if Universal Link validation fails",
117
+ default_value: false
118
+ ),
119
+ Option.new(
120
+ name: :add_sdk,
121
+ description: "Add the Branch framework to the project",
122
+ default_value: true
123
+ ),
124
+ Option.new(
125
+ name: :patch_source,
126
+ description: "Add Branch SDK calls to the AppDelegate",
127
+ default_value: true
128
+ ),
129
+ Option.new(
130
+ name: :commit,
131
+ description: "Commit the results to Git",
132
+ type: String,
133
+ example: "message",
134
+ argument_optional: true
135
+ ),
136
+ Option.new(
137
+ name: :check_repo_changes,
138
+ description: "Check for uncommitted changes to a git repo",
139
+ default_value: true
140
+ )
141
+ ]
142
+ end
143
+ end
144
+
4
145
  APP_LINK_REGEXP = /\.app\.link$|\.test-app\.link$/
5
146
  SDK_OPTIONS =
6
147
  {
@@ -13,15 +154,6 @@ module BranchIOCLI
13
154
 
14
155
  attr_reader :keys
15
156
  attr_reader :all_domains
16
- attr_reader :carthage_command
17
- attr_reader :uri_scheme
18
- attr_reader :validate
19
- attr_reader :add_sdk
20
- attr_reader :force
21
- attr_reader :patch_source
22
- attr_reader :commit
23
- attr_reader :setting
24
- attr_reader :test_configurations
25
157
 
26
158
  def validate_options
27
159
  @validate = options.validate
@@ -294,5 +426,6 @@ module BranchIOCLI
294
426
  end
295
427
  end
296
428
  end
429
+ # rubocop: enable Metrics/ClassLength
297
430
  end
298
431
  end