diff --git a/fastlane/lib/fastlane/actions/import_from_git.rb b/fastlane/lib/fastlane/actions/import_from_git.rb index ea9ee5e54fd..cddcdae1f4b 100644 --- a/fastlane/lib/fastlane/actions/import_from_git.rb +++ b/fastlane/lib/fastlane/actions/import_from_git.rb @@ -30,9 +30,10 @@ def self.available_options default_value: 'HEAD', optional: true), FastlaneCore::ConfigItem.new(key: :dependencies, - description: "The array of additional Fastfiles in the repository", - default_value: [], - optional: true), + description: "The array of additional Fastfiles in the repository", + default_value: [], + type: Array, + optional: true), FastlaneCore::ConfigItem.new(key: :path, description: "The path of the Fastfile in the repository", default_value: 'fastlane/Fastfile', @@ -43,6 +44,11 @@ def self.available_options optional: true), FastlaneCore::ConfigItem.new(key: :cache_path, description: "The path to a directory where the repository should be cloned into. Defaults to `nil`, which causes the repository to be cloned on every call, to a temporary directory", + optional: true), + FastlaneCore::ConfigItem.new(key: :git_extra_headers, + description: "An optional list of custom HTTP headers to access the git repo (`Authorization: Basic `, `Cache-Control: no-cache`, etc.)", + default_value: [], + type: Array, optional: true) ] end @@ -68,7 +74,8 @@ def self.example_code branch: "HEAD", # The branch to checkout on the repository. path: "fastlane/Fastfile", # The path of the Fastfile in the repository. version: [">= 1.1.0", "< 2.0.0"], # The version to checkout on the repository. Multiple conditions can be used to select the latest version within constraints. - cache_path: "~/.cache/fastlane/imported" # A directory in which the repository will be added, which means that it will not be cloned again on subsequent calls. + cache_path: "~/.cache/fastlane/imported", # A directory in which the repository will be added, which means that it will not be cloned again on subsequent calls. + git_extra_headers: ["Authorization: Basic ", "Cache-Control: no-cache"] )' ] end diff --git a/fastlane/lib/fastlane/fast_file.rb b/fastlane/lib/fastlane/fast_file.rb index e804b4d837d..08379630d93 100644 --- a/fastlane/lib/fastlane/fast_file.rb +++ b/fastlane/lib/fastlane/fast_file.rb @@ -278,7 +278,8 @@ def find_tag(folder: nil, version: nil, remote: false) # @param version [String, Array] Version requirement for repo tags # @param dependencies [Array] An optional array of additional Fastfiles in the repository # @param cache_path [String] An optional path to a directory where the repository should be cloned into - def import_from_git(url: nil, branch: 'HEAD', path: 'fastlane/Fastfile', version: nil, dependencies: [], cache_path: nil) # rubocop:disable Metrics/PerceivedComplexity + # @param git_extra_headers [Array] An optional array of custom HTTP headers to access the git repo (`Authorization: Basic `, `Cache-Control: no-cache`, etc.) + def import_from_git(url: nil, branch: 'HEAD', path: 'fastlane/Fastfile', version: nil, dependencies: [], cache_path: nil, git_extra_headers: []) # rubocop:disable Metrics/PerceivedComplexity UI.user_error!("Please pass a path to the `import_from_git` action") if url.to_s.length == 0 Actions.execute_action('import_from_git') do @@ -297,8 +298,6 @@ def import_from_git(url: nil, branch: 'HEAD', path: 'fastlane/Fastfile', version import_block = proc do |target_path| clone_folder = File.join(target_path, repo_name) - branch_option = "--branch #{branch}" if branch != 'HEAD' - checkout_dependencies = dependencies.map(&:shellescape).join(" ") # If the current call is eligible for caching, we check out all the @@ -309,12 +308,16 @@ def import_from_git(url: nil, branch: 'HEAD', path: 'fastlane/Fastfile', version if Dir[clone_folder].empty? UI.message("Cloning remote git repo...") Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do + command = ['git', 'clone', url, clone_folder, '--no-checkout'] # When using cached clones, we need the entire repository history # so we can switch between tags or branches instantly, or else, # it would defeat the caching's purpose. - depth = is_eligible_for_caching ? "" : "--depth 1" - - Actions.sh("git clone #{url.shellescape} #{clone_folder.shellescape} #{depth} --no-checkout #{branch_option}") + command += ['--depth', '1'] unless is_eligible_for_caching + command += ['--branch', branch] unless branch == 'HEAD' + git_extra_headers.each do |header| + command += ['--config', "http.extraHeader=#{header}"] + end + Actions.sh(*command) end end diff --git a/fastlane/spec/actions_specs/import_from_git_spec.rb b/fastlane/spec/actions_specs/import_from_git_spec.rb index 42008154aae..4837e6b81e7 100644 --- a/fastlane/spec/actions_specs/import_from_git_spec.rb +++ b/fastlane/spec/actions_specs/import_from_git_spec.rb @@ -305,6 +305,29 @@ def self.is_supported?(platform) end end + it "works with one HTTP header" do + header = 'Authorization: Basic my_base_64_key' + + allow(Fastlane::Actions).to receive(:sh).and_call_original + expect(Fastlane::Actions).to receive(:sh).with(any_args, '--config', "http.extraHeader=#{header}") + + Fastlane::FastFile.new.parse("lane :test do + import_from_git(url: '#{source_directory_path}', git_extra_headers: ['#{header}']) + end").runner.execute(:test) + end + + it "works with two HTTP headers" do + first_header = 'Authorization: Basic my_base_64_key' + second_header = 'Cache-Control: no-cache' + + allow(Fastlane::Actions).to receive(:sh).and_call_original + expect(Fastlane::Actions).to receive(:sh).with(any_args, '--config', "http.extraHeader=#{first_header}", '--config', "http.extraHeader=#{second_header}") + + Fastlane::FastFile.new.parse("lane :test do + import_from_git(url: '#{source_directory_path}', git_extra_headers: ['#{first_header}', '#{second_header}']) + end").runner.execute(:test) + end + after :all do ENV.delete("FORCE_SH_DURING_TESTS")