fastlane/lib/fastlane/fast_file.rb in fastlane-2.163.0 vs fastlane/lib/fastlane/fast_file.rb in fastlane-2.164.0
- old
+ new
@@ -257,57 +257,100 @@
action_completed('import', status: FastlaneCore::ActionCompletionStatus::SUCCESS)
return return_value
end
+ def find_tag(folder: nil, version: nil, remote: false)
+ req = Gem::Requirement.new(version)
+ all_tags = get_tags(folder: folder, remote: remote)
+
+ return all_tags.select { |t| req =~ FastlaneCore::TagVersion.new(t) }.last
+ end
+
# @param url [String] The git URL to clone the repository from
# @param branch [String] The branch to checkout in the repository
# @param path [String] The path to the Fastfile
# @param version [String, Array] Version requirement for repo tags
- def import_from_git(url: nil, branch: 'HEAD', path: 'fastlane/Fastfile', version: nil, dependencies: [])
+ # @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
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
require 'tmpdir'
action_launched('import_from_git')
+ is_eligible_for_caching = !version.nil? && !cache_path.nil?
+
+ UI.message("Eligible for caching") if is_eligible_for_caching
+
# Checkout the repo
repo_name = url.split("/").last
checkout_param = branch
- Dir.mktmpdir("fl_clone") do |tmp_path|
- clone_folder = File.join(tmp_path, repo_name)
+ 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(" ")
- checkout_path = "#{path.shellescape} #{checkout_dependencies}"
+ # If the current call is eligible for caching, we check out all the
+ # files and directories. If not, we only check out the specified
+ # `path` and `dependencies`.
+ checkout_path = is_eligible_for_caching ? "" : "#{path.shellescape} #{checkout_dependencies}"
- UI.message("Cloning remote git repo...")
- Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
- Actions.sh("git clone #{url.shellescape} #{clone_folder.shellescape} --depth 1 -n #{branch_option}")
+ if Dir[clone_folder].empty?
+ UI.message("Cloning remote git repo...")
+ Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
+ # 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}")
+ end
end
unless version.nil?
- req = Gem::Requirement.new(version)
- all_tags = fetch_remote_tags(folder: clone_folder)
- checkout_param = all_tags.select { |t| req =~ FastlaneCore::TagVersion.new(t) }.last
+ if is_eligible_for_caching
+ checkout_param = find_tag(folder: clone_folder, version: version, remote: false)
+
+ if checkout_param.nil?
+ # Update the repo and try again before failing
+ UI.message("Updating git repo...")
+ Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
+ Actions.sh("cd #{clone_folder.shellescape} && git checkout #{branch} && git reset --hard && git pull --all")
+ end
+
+ checkout_param = find_tag(folder: clone_folder, version: version, remote: false)
+ else
+ UI.message("Found tag #{checkout_param}. No git repo update needed.")
+ end
+ else
+ checkout_param = find_tag(folder: clone_folder, version: version, remote: true)
+ end
+
UI.user_error!("No tag found matching #{version.inspect}") if checkout_param.nil?
end
Actions.sh("cd #{clone_folder.shellescape} && git checkout #{checkout_param.shellescape} #{checkout_path}")
- # We also want to check out all the local actions of this fastlane setup
- containing = path.split(File::SEPARATOR)[0..-2]
- containing = "." if containing.count == 0
- actions_folder = File.join(containing, "actions")
- begin
- Actions.sh("cd #{clone_folder.shellescape} && git checkout #{checkout_param.shellescape} #{actions_folder.shellescape}")
- rescue
- # We don't care about a failure here, as local actions are optional
+ # Knowing that we check out all the files and directories when the
+ # current call is eligible for caching, we don't need to also
+ # explicitly check out the "actions" directory.
+ unless is_eligible_for_caching
+ # We also want to check out all the local actions of this fastlane setup
+ containing = path.split(File::SEPARATOR)[0..-2]
+ containing = "." if containing.count == 0
+ actions_folder = File.join(containing, "actions")
+ begin
+ Actions.sh("cd #{clone_folder.shellescape} && git checkout #{checkout_param.shellescape} #{actions_folder.shellescape}")
+ rescue
+ # We don't care about a failure here, as local actions are optional
+ end
end
return_value = nil
if dependencies.any?
return_value = [import(File.join(clone_folder, path))]
@@ -318,20 +361,28 @@
action_completed('import_from_git', status: FastlaneCore::ActionCompletionStatus::SUCCESS)
return return_value
end
+
+ if is_eligible_for_caching
+ import_block.call(File.expand_path(cache_path))
+ else
+ Dir.mktmpdir("fl_clone", &import_block)
+ end
end
end
#####################################################
# @!group Versioning helpers
#####################################################
- def fetch_remote_tags(folder: nil)
- UI.message("Fetching remote git tags...")
- Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
- Actions.sh("cd #{folder.shellescape} && git fetch --all --tags -q")
+ def get_tags(folder: nil, remote: false)
+ if remote
+ UI.message("Fetching remote git tags...")
+ Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
+ Actions.sh("cd #{folder.shellescape} && git fetch --all --tags -q")
+ end
end
# Fetch all possible tags
git_tags_string = Actions.sh("cd #{folder.shellescape} && git tag -l")
git_tags = git_tags_string.split("\n")