# frozen_string_literal: truemoduleBundlerclassLockfileParserclassPositionattr_reader:line,:columndefinitialize(line,column)@line=line@column=columnenddefadvance!(string)lines=string.count("\n")iflines>0@line+=lines@column=string.length-string.rindex("\n")else@column+=string.lengthendenddefto_s"#{line}:#{column}"endendattr_reader(:sources,:dependencies,:specs,:platforms,:bundler_version,:ruby_version,:checksums,)BUNDLED="BUNDLED WITH"DEPENDENCIES="DEPENDENCIES"CHECKSUMS="CHECKSUMS"PLATFORMS="PLATFORMS"RUBY="RUBY VERSION"GIT="GIT"GEM="GEM"PATH="PATH"PLUGIN="PLUGIN SOURCE"SPECS=" specs:"OPTIONS=/^ ([a-z]+): (.*)$/iSOURCE=[GIT,GEM,PATH,PLUGIN].freezeSECTIONS_BY_VERSION_INTRODUCED={Gem::Version.create("1.0")=>[DEPENDENCIES,PLATFORMS,GIT,GEM,PATH].freeze,Gem::Version.create("1.10")=>[BUNDLED].freeze,Gem::Version.create("1.12")=>[RUBY].freeze,Gem::Version.create("1.13")=>[PLUGIN].freeze,Gem::Version.create("2.5.0")=>[CHECKSUMS].freeze,}.freezeKNOWN_SECTIONS=SECTIONS_BY_VERSION_INTRODUCED.values.flatten!.freezeENVIRONMENT_VERSION_SECTIONS=[BUNDLED,RUBY].freezedeprecate_constant(:ENVIRONMENT_VERSION_SECTIONS)defself.sections_in_lockfile(lockfile_contents)sections=lockfile_contents.scan(/^\w[\w ]*$/)sections.uniq!sectionsenddefself.unknown_sections_in_lockfile(lockfile_contents)sections_in_lockfile(lockfile_contents)-KNOWN_SECTIONSenddefself.sections_to_ignore(base_version=nil)base_version&&=base_version.releasebase_version||=Gem::Version.create("1.0")attributes=[]SECTIONS_BY_VERSION_INTRODUCED.eachdo|version,introduced|nextifversion<=base_versionattributes+=introducedendattributesenddefself.bundled_withlockfile=Bundler.default_lockfilereturnunlesslockfile.file?lockfile_contents=Bundler.read_file(lockfile)returnunlesslockfile_contents.include?(BUNDLED)lockfile_contents.split(BUNDLED).last.stripenddefinitialize(lockfile)@platforms=[]@sources=[]@dependencies={}@parse_method=nil@specs={}@lockfile_path=beginSharedHelpers.relative_lockfile_pathrescueGemfileNotFound"Gemfile.lock"end@pos=Position.new(1,1)iflockfile.match?(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)raiseLockfileError,"Your #{@lockfile_path} contains merge conflicts.\n"\"Run `git checkout HEAD -- #{@lockfile_path}` first to get a clean lock."endlockfile.split(/((?:\r?\n)+)/)do|line|# split alternates between the line and the following whitespacenext@pos.advance!(line)ifline.match?(/^\s*$/)ifSOURCE.include?(line)@parse_method=:parse_sourceparse_source(line)elsifline==DEPENDENCIES@parse_method=:parse_dependencyelsifline==CHECKSUMS# This is a temporary solution to make this feature disabled by default# for all gemfiles that don't already explicitly include the feature.@checksums=true@parse_method=:parse_checksumelsifline==PLATFORMS@parse_method=:parse_platformelsifline==RUBY@parse_method=:parse_rubyelsifline==BUNDLED@parse_method=:parse_bundled_withelsif/^[^\s]/.match?(line)@parse_method=nilelsif@parse_methodsend(@parse_method,line)end@pos.advance!(line)end@specs=@specs.values.sort_by!(&:full_name)rescueArgumentError=>eBundler.ui.debug(e)raiseLockfileError,"Your lockfile is unreadable. Run `rm #{@lockfile_path}` "\"and then `bundle install` to generate a new lockfile. The error occurred while "\"evaluating #{@lockfile_path}:#{@pos}"enddefmay_include_redundant_platform_specific_gems?bundler_version.nil?||bundler_version<Gem::Version.new("1.16.2")endprivateTYPES={GIT=>Bundler::Source::Git,GEM=>Bundler::Source::Rubygems,PATH=>Bundler::Source::Path,PLUGIN=>Bundler::Plugin,}.freezedefparse_source(line)caselinewhenSPECSreturnunlessTYPES.key?(@type)@current_source=TYPES[@type].from_lock(@opts)@sources<<@current_sourcewhenOPTIONSvalue=$2value=trueifvalue=="true"value=falseifvalue=="false"key=$1if@opts[key]@opts[key]=Array(@opts[key])@opts[key]<<valueelse@opts[key]=valueendwhen*SOURCE@current_source=nil@opts={}@type=lineelseparse_spec(line)endendspace=/ /NAME_VERSION=/
^(#{space}{2}|#{space}{4}|#{space}{6})(?!#{space}) # Exactly 2, 4, or 6 spaces at the start of the line
(.*?) # Name
(?:#{space}\(([^-]*) # Space, followed by version
(?:-(.*))?\))? # Optional platform
(!)? # Optional pinned marker
(?:#{space}([^ ]+))? # Optional checksum
$ # Line end
/xodefparse_dependency(line)returnunlessline=~NAME_VERSIONspaces=$1returnunlessspaces.size==2name=-$2version=$3pinned=$5version=version.split(",").each(&:strip!)ifversiondep=Bundler::Dependency.new(name,version)ifpinned&&dep.name!="bundler"spec=@specs.find{|_,v|v.name==dep.name}dep.source=spec.last.sourceifspec# Path sources need to know what the default name / version# to use in the case that there are no gemspecs present. A fake# gemspec is created based on the version set on the dependency# TODO: Use the version from the spec instead of from the dependencyifversion&&version.size==1&&version.first=~/^\s*= (.+)\s*$/&&dep.source.is_a?(Bundler::Source::Path)dep.source.name=namedep.source.version=$1endend@dependencies[dep.name]=dependdefparse_checksum(line)returnunlessline=~NAME_VERSIONspaces=$1returnunlessspaces.size==2checksums=$6returnunlesschecksumsname=$2version=$3platform=$4version=Gem::Version.new(version)platform=platform?Gem::Platform.new(platform):Gem::Platform::RUBYfull_name=Gem::NameTuple.new(name,version,platform).full_namereturnunlessspec=@specs[full_name]checksums.split(",")do|lock_checksum|column=line.index(lock_checksum)+1checksum=Checksum.from_lock(lock_checksum,"#{@lockfile_path}:#{@pos.line}:#{column}")spec.source.checksum_store.register(spec,checksum)endenddefparse_spec(line)returnunlessline=~NAME_VERSIONspaces=$1name=-$2version=$3ifspaces.size==4# only load platform for non-dependency (spec) lineplatform=$4version=Gem::Version.new(version)platform=platform?Gem::Platform.new(platform):Gem::Platform::RUBY@current_spec=LazySpecification.new(name,version,platform,@current_source)@current_source.add_dependency_names(name)@specs[@current_spec.full_name]=@current_specelsifspaces.size==6version=version.split(",").each(&:strip!)ifversiondep=Gem::Dependency.new(name,version)@current_spec.dependencies<<dependenddefparse_platform(line)@platforms<<Gem::Platform.new($1.strip)ifline=~/^ (.*)$/enddefparse_bundled_with(line)line.strip!returnunlessGem::Version.correct?(line)@bundler_version=Gem::Version.create(line)enddefparse_ruby(line)line.strip!@ruby_version=lineendendend