# frozen_string_literal: truerequire"shellwords"require"tempfile"moduleBundlerclassSourceclassGit<PathclassGitNotInstalledError<GitErrordefinitializemsg=String.newmsg<<"You need to install git to be able to use gems from git repositories. "msg<<"For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git"supermsgendendclassGitNotAllowedError<GitErrordefinitialize(command)msg=String.newmsg<<"Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, "msg<<"this error message could probably be more useful. Please submit a ticket at http://github.com/bundler/bundler/issues "msg<<"with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"supermsgendendclassGitCommandError<GitErrordefinitialize(command,path=nil,extra_info=nil)msg=String.newmsg<<"Git error: command `git #{command}` in directory #{SharedHelpers.pwd} has failed."msg<<"\n#{extra_info}"ifextra_infomsg<<"\nIf this error persists you could try removing the cache directory '#{path}'"ifpath&&path.exist?supermsgendendclassMissingGitRevisionError<GitErrordefinitialize(ref,repo)msg="Revision #{ref} does not exist in the repository #{repo}. Maybe you misspelled it?"supermsgendend# The GitProxy is responsible to interact with git repositories.# All actions required by the Git source is encapsulated in this# object.classGitProxyattr_accessor:path,:uri,:refattr_writer:revisiondefinitialize(path,uri,ref,revision=nil,git=nil)@path=path@uri=uri@ref=ref@revision=revision@git=gitraiseGitNotInstalledError.newifallow?&&!Bundler.git_present?enddefrevisionreturn@revisionif@revisionbegin@revision||=find_local_revisionrescueGitCommandErrorraiseMissingGitRevisionError.new(ref,uri)end@revisionenddefbranch@branch||=allowed_in_pathdogit("rev-parse --abbrev-ref HEAD").stripendenddefcontains?(commit)allowed_in_pathdoresult=git_null("branch --contains #{commit}")$?==0&&result=~/^\* (.*)$/endenddefversiongit("--version").match(/(git version\s*)?((\.?\d+)+).*/)[2]enddeffull_versiongit("--version").sub("git version","").stripenddefcheckoutifpath.exist?returnifhas_revision_cached?Bundler.ui.info"Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"in_pathdogit_retry%(fetch --force --quiet --tags #{uri_escaped_with_configured_credentials} "refs/heads/*:refs/heads/*")endelseBundler.ui.info"Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"SharedHelpers.filesystem_access(path.dirname)do|p|FileUtils.mkdir_p(p)endgit_retry%(clone #{uri_escaped_with_configured_credentials} "#{path}" --bare --no-hardlinks --quiet)endenddefcopy_to(destination,submodules=false)# method 1unlessFile.exist?(destination.join(".git"))beginSharedHelpers.filesystem_access(destination.dirname)do|p|FileUtils.mkdir_p(p)endSharedHelpers.filesystem_access(destination)do|p|FileUtils.rm_rf(p)endgit_retry%(clone --no-checkout --quiet "#{path}" "#{destination}")File.chmod(((File.stat(destination).mode|0o777)&~File.umask),destination)rescueErrno::EEXIST=>efile_path=e.message[%r{.*?(/.*)},1]raiseGitError,"Bundler could not install a gem because it needs to "\"create a directory, but a file exists - #{file_path}. Please delete "\"this file and try again."endend# method 2SharedHelpers.chdir(destination)dogit_retry%(fetch --force --quiet --tags "#{path}")git"reset --hard #{@revision}"ifsubmodulesgit_retry"submodule update --init --recursive"elsifGem::Version.create(version)>=Gem::Version.create("2.9.0")git_retry"submodule deinit --all"endendendprivate# TODO: Do not rely on /dev/null.# Given that open3 is not cross platform until Ruby 1.9.3,# the best solution is to pipe to /dev/null if it exists.# If it doesn't, everything will work fine, but the user# will get the $stderr messages as well.defgit_null(command)git("#{command} 2>#{Bundler::NULL}",false)enddefgit_retry(command)Bundler::Retry.new("`git #{command}`",GitNotAllowedError).attemptsdogit(command)endenddefgit(command,check_errors=true,error_msg=nil)command_with_no_credentials=URICredentialsFilter.credential_filtered_string(command,uri)raiseGitNotAllowedError.new(command_with_no_credentials)unlessallow?out=SharedHelpers.with_clean_git_envdocapture_and_filter_stderr(uri){`git #{command}`}endstdout_with_no_credentials=URICredentialsFilter.credential_filtered_string(out,uri)raiseGitCommandError.new(command_with_no_credentials,path,error_msg)ifcheck_errors&&!$?.success?stdout_with_no_credentialsenddefhas_revision_cached?returnunless@revisionin_path{git("cat-file -e #{@revision}")}truerescueGitErrorfalseenddefremove_cacheFileUtils.rm_rf(path)enddeffind_local_revisionallowed_in_pathdogit("rev-parse --verify #{Shellwords.shellescape(ref)}",true).stripendend# Escape the URI for git commandsdefuri_escaped_with_configured_credentialsremote=configured_uri_for(uri)ifBundler::WINDOWS# Windows quoting requires double quotes only, with double quotes# inside the string escaped by being doubled.'"'+remote.gsub('"'){'""'}+'"'else# Bash requires single quoted strings, with the single quotes escaped# by ending the string, escaping the quote, and restarting the string."'"+remote.gsub("'"){"'\\''"}+"'"endend# Adds credentials to the URI as Fetcher#configured_uri_for doesdefconfigured_uri_for(uri)if/https?:/=~uriremote=URI(uri)config_auth=Bundler.settings[remote.to_s]||Bundler.settings[remote.host]remote.userinfo||=config_authremote.to_selseuriendenddefallow?@git?@git.allow_git_ops?:trueenddefin_path(&blk)checkoutunlesspath.exist?SharedHelpers.chdir(path,&blk)enddefallowed_in_pathreturnin_path{yield}ifallow?raiseGitError,"The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application"end# TODO: Replace this with Open3 when upgrading to bundler 2# Similar to #git_null, as Open3 is not cross-platform,# a temporary way is to use Tempfile to capture the stderr.# When replacing this using Open3, make sure git_null is# also replaced by Open3, so stdout and stderr all got handled properly.defcapture_and_filter_stderr(uri)return_value,captured_err=""backup_stderr=STDERR.dupbeginTempfile.open("captured_stderr")do|f|STDERR.reopen(f)return_value=yieldf.rewindcaptured_err=f.readendensureSTDERR.reopenbackup_stderrend$stderr.putsURICredentialsFilter.credential_filtered_string(captured_err,uri)ifuri&&!captured_err.empty?return_valueendendendendend