summaryrefslogtreecommitdiff
path: root/lib/bundler/repository.rb
blob: 5c554edc9c8fbaf93feab5574f4d3a9698228a86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
module Bundler
  class InvalidRepository < StandardError ; end

  class Repository

    attr_reader :path

    def initialize(path)
      @path = Pathname.new(path)
      unless valid?
        raise InvalidRepository, "'#{path}' is not a valid gem repository"
      end
    end

    # Returns the source index for all gems installed in the
    # repository
    def source_index
      Gem::SourceIndex.from_gems_in(@path.join("specifications"))
    end

    def valid?
      (Dir[@path.join("*")] - Dir[@path.join("{cache,doc,gems,environments,specifications}")]).empty?
    end

    # Checks whether a gem is installed
    def install_cached_gems(options = {})
      cached_gems.each do |name, version|
        unless installed?(name, version)
          install_cached_gem(name, version, options)
        end
      end
    end

    def install_cached_gem(name, version, options = {})
      cached_gem = cache_path.join("#{name}-#{version}.gem")
      # TODO: Add a warning if cached_gem is not a file
      if cached_gem.file?
        Bundler.logger.info "Installing #{name}-#{version}.gem"
        installer = Gem::Installer.new(cached_gem.to_s, options.merge(
          :install_dir         => @path,
          :ignore_dependencies => true,
          :env_shebang         => true,
          :wrappers            => true
        ))
        installer.install
      end
    end

  private

    def cache_path
      @path.join("cache")
    end

    def cache_files
      Dir[cache_path.join("*.gem")]
    end

    def cached_gems
      cache_files.map do |f|
        full_name = File.basename(f).gsub(/\.gem$/, '')
        full_name.split(/-(?=[^-]+$)/)
      end
    end

    def spec_path
      @path.join("specifications")
    end

    def spec_files
      Dir[spec_path.join("*.gemspec")]
    end

    def gem_path
      @path.join("gems")
    end

    def gems
      Dir[gem_path.join("*")]
    end

    def installed?(name, version)
      spec_files.any? { |g| File.basename(g) == "#{name}-#{version}.gemspec" } &&
        gems.any? { |g| File.basename(g) == "#{name}-#{version}" }
    end

  end
end