/Ruby/lib/ruby/gems/2.0.0/gems/bundler-1.7.4/lib/bundler/lockfile_parser.rb

https://gitlab.com/orvi2014/rcs-db-ext · Ruby · 157 lines · 119 code · 22 blank · 16 comment · 28 complexity · e68ee83c4099eaf700da234bc204d2b3 MD5 · raw file

  1. require "strscan"
  2. # Some versions of the Bundler 1.1 RC series introduced corrupted
  3. # lockfiles. There were two major problems:
  4. #
  5. # * multiple copies of the same GIT section appeared in the lockfile
  6. # * when this happened, those sections got multiple copies of gems
  7. # in those sections.
  8. #
  9. # As a result, Bundler 1.1 contains code that fixes the earlier
  10. # corruption. We will remove this fix-up code in Bundler 1.2.
  11. module Bundler
  12. class LockfileParser
  13. attr_reader :sources, :dependencies, :specs, :platforms
  14. DEPENDENCIES = "DEPENDENCIES"
  15. PLATFORMS = "PLATFORMS"
  16. GIT = "GIT"
  17. GEM = "GEM"
  18. PATH = "PATH"
  19. SPECS = " specs:"
  20. OPTIONS = /^ ([a-z]+): (.*)$/i
  21. def initialize(lockfile)
  22. @platforms = []
  23. @sources = []
  24. @dependencies = []
  25. @state = :source
  26. @specs = {}
  27. @rubygems_aggregate = Source::Rubygems.new
  28. if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
  29. raise LockfileError, "Your Gemfile.lock contains merge conflicts.\n" \
  30. "Run `git checkout HEAD -- Gemfile.lock` first to get a clean lock."
  31. end
  32. lockfile.split(/(?:\r?\n)+/).each do |line|
  33. if line == DEPENDENCIES
  34. @state = :dependency
  35. elsif line == PLATFORMS
  36. @state = :platform
  37. else
  38. send("parse_#{@state}", line)
  39. end
  40. end
  41. @sources << @rubygems_aggregate
  42. @specs = @specs.values
  43. end
  44. private
  45. TYPES = {
  46. "GIT" => Bundler::Source::Git,
  47. "GEM" => Bundler::Source::Rubygems,
  48. "PATH" => Bundler::Source::Path
  49. }
  50. def parse_source(line)
  51. case line
  52. when GIT, GEM, PATH
  53. @current_source = nil
  54. @opts, @type = {}, line
  55. when SPECS
  56. case @type
  57. when "PATH"
  58. @current_source = TYPES[@type].from_lock(@opts)
  59. @sources << @current_source
  60. when "GIT"
  61. @current_source = TYPES[@type].from_lock(@opts)
  62. # Strip out duplicate GIT sections
  63. if @type == "GIT" && @sources.include?(@current_source)
  64. @current_source = @sources.find { |s| s == @current_source }
  65. else
  66. @sources << @current_source
  67. end
  68. when "GEM"
  69. Array(@opts["remote"]).each do |url|
  70. @rubygems_aggregate.add_remote(url)
  71. end
  72. @current_source = @rubygems_aggregate
  73. end
  74. when OPTIONS
  75. value = $2
  76. value = true if value == "true"
  77. value = false if value == "false"
  78. key = $1
  79. if @opts[key]
  80. @opts[key] = Array(@opts[key])
  81. @opts[key] << value
  82. else
  83. @opts[key] = value
  84. end
  85. else
  86. parse_spec(line)
  87. end
  88. end
  89. NAME_VERSION = '(?! )(.*?)(?: \(([^-]*)(?:-(.*))?\))?'
  90. NAME_VERSION_2 = %r{^ {2}#{NAME_VERSION}(!)?$}
  91. NAME_VERSION_4 = %r{^ {4}#{NAME_VERSION}$}
  92. NAME_VERSION_6 = %r{^ {6}#{NAME_VERSION}$}
  93. def parse_dependency(line)
  94. if line =~ NAME_VERSION_2
  95. name, version, pinned = $1, $2, $4
  96. version = version.split(",").map { |d| d.strip } if version
  97. dep = Bundler::Dependency.new(name, version)
  98. if pinned && dep.name != 'bundler'
  99. spec = @specs.find {|k, v| v.name == dep.name }
  100. dep.source = spec.last.source if spec
  101. # Path sources need to know what the default name / version
  102. # to use in the case that there are no gemspecs present. A fake
  103. # gemspec is created based on the version set on the dependency
  104. # TODO: Use the version from the spec instead of from the dependency
  105. if version && version.size == 1 && version.first =~ /^\s*= (.+)\s*$/ && dep.source.is_a?(Bundler::Source::Path)
  106. dep.source.name = name
  107. dep.source.version = $1
  108. end
  109. end
  110. @dependencies << dep
  111. end
  112. end
  113. def parse_spec(line)
  114. if line =~ NAME_VERSION_4
  115. name, version = $1, Gem::Version.new($2)
  116. platform = $3 ? Gem::Platform.new($3) : Gem::Platform::RUBY
  117. @current_spec = LazySpecification.new(name, version, platform)
  118. @current_spec.source = @current_source
  119. # Avoid introducing multiple copies of the same spec (caused by
  120. # duplicate GIT sections)
  121. @specs[@current_spec.identifier] ||= @current_spec
  122. elsif line =~ NAME_VERSION_6
  123. name, version = $1, $2
  124. version = version.split(',').map { |d| d.strip } if version
  125. dep = Gem::Dependency.new(name, version)
  126. @current_spec.dependencies << dep
  127. end
  128. end
  129. def parse_platform(line)
  130. if line =~ /^ (.*)$/
  131. @platforms << Gem::Platform.new($1)
  132. end
  133. end
  134. end
  135. end