Class: Gem::Source

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/rubygems/source.rb

Direct Known Subclasses

Local, SpecificFile

Defined Under Namespace

Classes: Local, SpecificFile

Constant Summary collapse

FILES =
{
  :released   => 'specs',
  :latest     => 'latest_specs',
  :prerelease => 'prerelease_specs',
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri) ⇒ Source

Returns a new instance of Source.



11
12
13
14
15
16
17
18
# File 'lib/rubygems/source.rb', line 11

def initialize(uri)
  unless uri.kind_of? URI
    uri = URI.parse(uri.to_s)
  end

  @uri = uri
  @api_uri = nil
end

Instance Attribute Details

#uriObject (readonly)

Returns the value of attribute uri



20
21
22
# File 'lib/rubygems/source.rb', line 20

def uri
  @uri
end

Instance Method Details

#<=>(other) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/rubygems/source.rb', line 27

def <=>(other)
  if !@uri
    return 0 unless other.uri
    return -1
  end

  return 1 if !other.uri

  @uri.to_s <=> other.uri.to_s
end

#==(other) ⇒ Object Also known as: eql?



40
41
42
43
44
45
46
47
# File 'lib/rubygems/source.rb', line 40

def ==(other)
  case other
  when self.class
    @uri == other.uri
  else
    false
  end
end

#api_uriObject



22
23
24
25
# File 'lib/rubygems/source.rb', line 22

def api_uri
  require 'rubygems/remote_fetcher'
  @api_uri ||= Gem::RemoteFetcher.fetcher.api_endpoint uri
end

#cache_dir(uri) ⇒ Object

Returns the local directory to write uri to.



58
59
60
61
62
63
# File 'lib/rubygems/source.rb', line 58

def cache_dir(uri)
  # Correct for windows paths
  escaped_path = uri.path.sub(/^\/([a-z]):\//i, '/\\1-/')
  root = File.join Gem.user_home, '.gem', 'specs'
  File.join root, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
end

#download(spec, dir = Dir.pwd) ⇒ Object



140
141
142
143
# File 'lib/rubygems/source.rb', line 140

def download(spec, dir=Dir.pwd)
  fetcher = Gem::RemoteFetcher.fetcher
  fetcher.download spec, @uri.to_s, dir
end

#fetch_spec(name) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rubygems/source.rb', line 69

def fetch_spec(name)
  fetcher = Gem::RemoteFetcher.fetcher

  spec_file_name = name.spec_name

  uri = @uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}"

  cache_dir = cache_dir uri

  local_spec = File.join cache_dir, spec_file_name

  if File.exist? local_spec then
    spec = Gem.read_binary local_spec
    spec = Marshal.load(spec) rescue nil
    return spec if spec
  end

  uri.path << '.rz'

  spec = fetcher.fetch_path uri
  spec = Gem.inflate spec

  if update_cache? then
    FileUtils.mkdir_p cache_dir

    open local_spec, 'wb' do |io|
      io.write spec
    end
  end

  # TODO: Investigate setting Gem::Specification#loaded_from to a URI
  Marshal.load spec
end

#hashObject



51
52
53
# File 'lib/rubygems/source.rb', line 51

def hash
  @uri.hash
end

#load_specs(type) ⇒ Object

Loads type kind of specs fetching from @uri if the on-disk cache is out of date.

type is one of the following:

:released => Return the list of all released specs :latest => Return the list of only the highest version of each gem :prerelease => Return the list of all prerelease only specs



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/rubygems/source.rb', line 114

def load_specs(type)
  file       = FILES[type]
  fetcher    = Gem::RemoteFetcher.fetcher
  file_name  = "#{file}.#{Gem.marshal_version}"
  spec_path  = @uri + "#{file_name}.gz"
  cache_dir  = cache_dir spec_path
  local_file = File.join(cache_dir, file_name)
  retried    = false

  FileUtils.mkdir_p cache_dir if update_cache?

  spec_dump = fetcher.cache_update_path spec_path, local_file, update_cache?

  begin
    Gem::NameTuple.from_list Marshal.load(spec_dump)
  rescue ArgumentError
    if update_cache? && !retried
      FileUtils.rm local_file
      retried = true
      retry
    else
      raise Gem::Exception.new("Invalid spec cache file in #{local_file}")
    end
  end
end

#update_cache?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/rubygems/source.rb', line 65

def update_cache?
  @update_cache ||= File.stat(Gem.user_home).uid == Process.uid
end