class BranchIOCLI::Helper::ToolHelper

Public Class Methods

add_carthage(options) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 67
        def add_carthage(options)
          # TODO: Collapse this and Command::update_cartfile
          verify_carthage

          # 1. Generate Cartfile
          cartfile_path = options.cartfile_path
          File.open(cartfile_path, "w") do |file|
            file.write <<-EOF
github "BranchMetrics/ios-branch-deep-linking"
            EOF
          end

          # 2. carthage update
          sh "carthage", *options.carthage_command.shellsplit, chdir: File.dirname(config.cartfile_path)

          # 3. Add Cartfile and Cartfile.resolved to commit (in case :commit param specified)
          helper.add_change cartfile_path
          helper.add_change "#{cartfile_path}.resolved"
          helper.add_change options.xcodeproj_path

          # 4. Add to target dependencies
          frameworks_group = options.xcodeproj.frameworks_group
          branch_framework = frameworks_group.new_file "Carthage/Build/iOS/Branch.framework"
          target = options.target
          target.frameworks_build_phase.add_file_reference branch_framework

          # 5. Create a copy-frameworks build phase
          carthage_build_phase = target.new_shell_script_build_phase "carthage copy-frameworks"
          carthage_build_phase.shell_script = "/usr/local/bin/carthage copy-frameworks"

          carthage_build_phase.input_paths << "$(SRCROOT)/Carthage/Build/iOS/Branch.framework"
          carthage_build_phase.output_paths << "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Branch.framework"

          update_framework_search_paths "$(SRCROOT)/Carthage/Build/iOS"

          options.xcodeproj.save

          return unless options.commit

          # For now, add Carthage folder to SCM

          # 6. Add the Carthage folder to the commit (in case :commit param specified)
          carthage_folder_path = Pathname.new(File.expand_path("../Carthage", cartfile_path)).relative_path_from(Pathname.pwd)
          cartfile_pathname = Pathname.new(cartfile_path).relative_path_from Pathname.pwd
          helper.add_change carthage_folder_path
          sh "git", "add", cartfile_pathname.to_s, "#{cartfile_pathname}.resolved", carthage_folder_path.to_s
        end
add_cocoapods(options) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 26
def add_cocoapods(options)
  verify_cocoapods

  podfile_path = options.podfile_path

  install_command = %w(pod install)
  install_command << "--repo-update" if options.pod_repo_update
  Dir.chdir(File.dirname(podfile_path)) do
    sh "pod", "init"
    PatternPatch::Patch.new(
      regexp: /^(\s*)# Pods for #{options.target.name}$/,
      mode: :append,
      text: "\n\\1pod \"Branch\""
    ).apply podfile_path
    # Store a Pod::Podfile representation of this file.
    options.open_podfile
    sh(*install_command)
  end

  return unless options.commit

  helper.add_change podfile_path
  helper.add_change "#{podfile_path}.lock"

  # For now, add Pods folder to SCM.
  pods_folder_path = Pathname.new(File.expand_path("../Pods", podfile_path)).relative_path_from Pathname.pwd
  workspace_path = Pathname.new(File.expand_path(options.xcodeproj_path.sub(/.xcodeproj$/, ".xcworkspace"))).relative_path_from Pathname.pwd
  podfile_pathname = Pathname.new(podfile_path).relative_path_from Pathname.pwd
  helper.add_change pods_folder_path
  helper.add_change workspace_path

  sh(
    "git",
    "add",
    podfile_pathname.to_s,
    "#{podfile_pathname}.lock",
    pods_folder_path.to_s,
    workspace_path.to_s
  )
end
add_direct(options) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 115
def add_direct(options)
  # Put the framework in the path for any existing Frameworks group in the project.
  frameworks_group = options.xcodeproj.frameworks_group
  framework_path = File.join frameworks_group.real_path, "Branch.framework"
  raise "#{framework_path} exists." if File.exist? framework_path

  say "Finding current framework release"

  # Find the latest release from GitHub.
  releases = JSON.parse helper.fetch "https://api.github.com/repos/BranchMetrics/ios-branch-deep-linking/releases"
  current_release = releases.first
  # Get the download URL for the framework.
  framework_asset = current_release["assets"][0]
  framework_url = framework_asset["browser_download_url"]

  say "Downloading Branch.framework v. #{current_release['tag_name']} (#{framework_asset['size']} bytes zipped)"

  Dir.mktmpdir do |download_folder|
    zip_path = File.join download_folder, "Branch.framework.zip"

    File.unlink zip_path if File.exist? zip_path

    # Download the framework zip
    helper.download framework_url, zip_path, size: framework_asset["size"]

    say "Unzipping Branch.framework"

    # Unzip
    Zip::File.open zip_path do |zip_file|
      # Start with just the framework and add dSYM, etc., later
      zip_file.glob "Carthage/Build/iOS/Branch.framework/**/*" do |entry|
        filename = entry.name.sub %r{^Carthage/Build/iOS}, frameworks_group.real_path.to_s
        FileUtils.mkdir_p File.dirname filename
        entry.extract filename
      end
    end
  end

  # Now the current framework is in framework_path

  say "Adding to #{options.xcodeproj_path}"

  # Add as a dependency in the Frameworks group
  framework = frameworks_group.new_file "Branch.framework" # relative to frameworks_group.real_path
  options.target.frameworks_build_phase.add_file_reference framework, true

  update_framework_search_paths "$(SRCROOT)"

  options.xcodeproj.save

  helper.add_change options.xcodeproj_path
  helper.add_change framework_path
  sh "git", "add", framework_path if options.commit
end
carthage_bootstrap_if_required(report = STDOUT) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 394
def carthage_bootstrap_if_required(report = STDOUT)
  return true unless config.cartfile_path
  return true if Dir.exist?(File.join(File.dirname(config.cartfile_path), "Carthage", "Build", "iOS"))

  say "carthage checkout required in order to build."
  if config.confirm
    install = confirm 'Run "carthage checkout && carthage build --platform ios" now?', true

    unless install
      say 'Please build your Carthage dependencies first in order to continue.'
      return false
    end
  end

  verify_carthage

  checkout_command = %w(carthage checkout)

  task = Task.new use_spinner: report != STDOUT
  # included by sh, but this is to the screen when generating a report.
  task.begin "Running #{IO.command_from_args(*checkout_command)}."
  if report.sh(*checkout_command).success?
    task.success "Done."
  else
    task.error "Failed."
    say "#{IO.command_from_args(*checkout_command)} failed. See report for details."
    return false
  end

  build_command = "carthage", "build", "--platform", "ios"

  task = Task.new use_spinner: report != STDOUT
  # included by sh, but this is to the screen when generating a report.
  task.begin "Running #{IO.command_from_args(*build_command)}."
  if report.sh(*build_command).success?
    task.success "Done."
  else
    task.error "Failed."
    say "#{IO.command_from_args(*build_command)} failed. See report for details."
    return false
  end

  true
end
config() click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 14
def config
  Configuration::Configuration.current
end
env() click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 18
def env
  Configuration::Environment
end
helper() click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 22
def helper
  BranchHelper
end
pod_install_if_required(report = STDOUT) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 352
        def pod_install_if_required(report = STDOUT)
          return true unless config.pod_install_required?
          # Only if a Podfile is detected/supplied at the command line.

          say "pod install required in order to build."
          if config.confirm
            install = confirm 'Run "pod install" now?', true

            unless install
              say 'Please run "pod install" or "pod update" first in order to continue.'
              return false
            end
          end

          verify_cocoapods

          install_command = %w(pod install)

          if config.pod_repo_update
            install_command << " --repo-update"
          else
            say <<-EOF
You have disabled "pod repo update". This can cause "pod install" to fail in
some cases. If that happens, please rerun without --no-pod-repo-update or run
"pod install --repo-update" manually.
                EOF
          end

          task = Task.new use_spinner: report != STDOUT
          # included by sh, but this is to the screen when generating a report.
          task.begin "Running #{IO.command_from_args(*install_command)}."
          if report.sh(*install_command).success?
            task.success "Done."
          else
            task.error "Failed."
            say "#{IO.command_from_args(*install_command)} failed. See report for details."
            return false
          end

          true
        end
update_cartfile(options, project) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 217
def update_cartfile(options, project)
  verify_carthage

  cartfile_path = options.cartfile_path
  return false if cartfile_path.nil?

  # 1. Patch Cartfile. Return if no change (Branch already present).
  return false unless PatchHelper.patch_cartfile cartfile_path

  # 2. carthage bootstrap (or other command)
  cmd = ["carthage", *options.carthage_command.shellsplit]
  cmd << "ios-branch-deep-linking" if options.carthage_command =~ /^(update|build)/
  sh(*cmd, chdir: File.dirname(config.cartfile_path))

  # 3. Add Cartfile and Cartfile.resolved to commit (in case :commit param specified)
  helper.add_change cartfile_path
  helper.add_change "#{cartfile_path}.resolved"
  helper.add_change options.xcodeproj_path

  # 4. Add to target dependencies
  frameworks_group = project.frameworks_group
  branch_framework = frameworks_group.new_file "Carthage/Build/iOS/Branch.framework"
  target = options.target
  target.frameworks_build_phase.add_file_reference branch_framework

  # 5. Add to copy-frameworks build phase
  carthage_build_phase = target.build_phases.find do |phase|
    phase.respond_to?(:shell_script) && phase.shell_script =~ /carthage\s+copy-frameworks/
  end

  if carthage_build_phase
    carthage_build_phase.input_paths << "$(SRCROOT)/Carthage/Build/iOS/Branch.framework"
    carthage_build_phase.output_paths << "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Branch.framework"
  end

  # 6. Check if Carthage folder is under SCM
  carthage_folder_path = Pathname.new(File.expand_path("../Carthage", cartfile_path)).relative_path_from Pathname.pwd
  `git ls-files #{carthage_folder_path.to_s.shellescape} --error-unmatch > /dev/null 2>&1`
  return true unless $?.exitstatus == 0

  # 7. If so, add the Carthage folder to the commit (in case :commit param specified)
  helper.add_change carthage_folder_path
  sh "git", "add", carthage_folder_path.to_s if options.commit

  true
end
update_framework_search_paths(path) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 170
def update_framework_search_paths(path)
  # Make sure this is in the FRAMEWORK_SEARCH_PATHS if we just added it.
  if config.xcodeproj.frameworks_group.files.count == 1
    target = config.target
    target.build_configurations.each do |c|
      # this accounts for project-level settings as well
      setting = target.resolved_build_setting("FRAMEWORK_SEARCH_PATHS")[c.name] || []
      next if setting.include?(path) || setting.include?("#{path}/**")
      setting << path

      c.build_settings["FRAMEWORK_SEARCH_PATHS"] = setting
    end
  end
  # If it already existed, it's almost certainly already in FRAMEWORK_SEARCH_PATHS.
end
update_podfile(options) click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 186
def update_podfile(options)
  verify_cocoapods

  podfile_path = options.podfile_path
  return false if podfile_path.nil?

  # 1. Patch Podfile. Return if no change (Branch pod already present).
  return false unless PatchHelper.patch_podfile podfile_path

  # 2. pod install
  command = %w(pod install)
  command << '--repo-update' if options.pod_repo_update

  sh(*command, chdir: File.dirname(config.podfile_path))

  # 3. Add Podfile and Podfile.lock to commit (in case :commit param specified)
  helper.add_change podfile_path
  helper.add_change "#{podfile_path}.lock"

  # 4. Check if Pods folder is under SCM
  pods_folder_path = Pathname.new(File.expand_path("../Pods", podfile_path)).relative_path_from Pathname.pwd
  `git ls-files #{pods_folder_path.to_s.shellescape} --error-unmatch > /dev/null 2>&1`
  return true unless $?.exitstatus == 0

  # 5. If so, add the Pods folder to the commit (in case :commit param specified)
  helper.add_change pods_folder_path
  sh "git", "add", pods_folder_path.to_s if options.commit

  true
end
verify_carthage() click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 312
def verify_carthage
  carthage_cmd = `which carthage`
  return unless carthage_cmd.empty?

  brew_cmd = `which brew`
  if brew_cmd.empty?
    say "'carthage' command not available in PATH and 'brew' command not available in PATH to install 'carthage'."
    exit(-1)
  end

  install = confirm "'carthage' command not available in PATH. Use Homebrew to install carthage?", true
  unless install
    say "Please install carthage or use --no-add-sdk to continue."
    exit(-1)
  end

  sh "brew", "install", "carthage"
end
verify_cocoapods() click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 264
def verify_cocoapods
  if defined?(Bundler)
    begin
      require "cocoapods"
    rescue LoadError
      # The only alternative here would be something like patch Gemfile, run bundle install
      # and then exec %w(bundle exec br) + ARGV, except merge anything inferred or obtained
      # by asking questions.
      say %(CocoaPods is required to continue. Please add 'gem "cocoapods"' to your Gemfile, run bundle install and then rerun this command.)
      exit(-1)
    end
  end

  pod_cmd = `which pod`
  return unless pod_cmd.empty?

  cmd = `which #{install_cmd}`
  if cmd.empty?
    say "'pod' command not available in PATH and '#{install_command}' command not available in PATH to install cocoapods."
    exit(-1)
  end

  sudo = env.from_homebrew? || File.writable?(Gem.dir) ? "" : "sudo "
  sudo_warning = sudo.blank? ? "" : " (requires a sudo password)"

  install = confirm "'pod' command not available in PATH. Install cocoapods#{sudo_warning}?", true
  unless install
    # TODO: There are times that --no-add-sdk is not available or doesn't avoid the need.
    say "Please install cocoapods or use --no-add-sdk to continue."
    exit(-1)
  end

  install_cmd = env.from_homebrew? ? "brew" : "gem"

  if sudo.blank?
    command = [install_cmd.to_s, "install", "cocoapods"]
  else
    command = [sudo, install_cmd.to_s, "install", "cocoapods"]
  end

  sh(*command)

  # Ensure master podspec repo is set up (will update if it exists).
  say "Synching master podspec repo. This may take some time."
  sh "pod", "setup"
  say "Done ✅"
end
verify_git() click to toggle source
# File lib/branch_io_cli/helper/tool_helper.rb, line 331
def verify_git
  return unless config.commit

  git_cmd = `which git`
  return unless git_cmd.empty?

  xcode_select_path = `which xcode-select`
  if xcode_select_path.empty?
    say "'git' command not available in PATH and 'xcode-select' command not available in PATH to install 'git'."
    exit(-1)
  end

  install = confirm "'git' command not available in PATH. Install Xcode command-line tools (requires password)?", true
  unless install
    say "Please install Xcode command tools or leave out the --commit option to continue."
    exit(-1)
  end

  sh "xcode-select", "--install"
end