class RBS::Collection::Sources::Git - rbs: Ruby Standard Library Documentation

# class RBS::Collection::Sources::Git

### Constants

METADATA_FILENAME

### Attributes

name[R]
remote[R]
repo_dir[R]
revision[R]

### Public Class Methods

new(name:, revision:, remote:, repo_dir:) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 18
    def initialize(name:, revision:, remote:, repo_dir:)
      @name = name
      @remote = remote
      @repo_dir = repo_dir || 'gems'
      @revision = revision
      @need_setup = true
    end

### Public Instance Methods

has?(name, version) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 26
    def has?(name, version)
      setup! do
        if version
          (gems_versions[name] || Set[]).include?(version)
        else
          gems_versions.key?(name)
        end
      end
    end

install(dest:, name:, version:, stdout:) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 43
    def install(dest:, name:, version:, stdout:)
      setup!()

      gem_dir = dest.join(name, version)

      colored_io = CLI::ColoredIO.new(stdout: stdout)

      case
      when gem_dir.symlink?
        colored_io.puts_green("Updating to #{format_config_entry(name, version)} from a local source")
        gem_dir.unlink
        _install(dest: dest, name: name, version: version)
      when gem_dir.directory?
        prev = load_metadata(dir: gem_dir)

        if prev == metadata_content(name: name, version: version)
          colored_io.puts "Using #{format_config_entry(name, version)}"
        else
          colored_io.puts_green("Updating to #{format_config_entry(name, version)} from #{format_config_entry(prev["name"], prev["version"])}")
          FileUtils.remove_entry_secure(gem_dir.to_s)
          _install(dest: dest, name: name, version: version)
        end
      when !gem_dir.exist?
        colored_io.puts_green("Installing #{format_config_entry(name, version)}")
        _install(dest: dest, name: name, version: version)
      else
        raise
      end
    end

load_metadata(dir:) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 223
    def load_metadata(dir:)
      # @type var content: Hash[String, untyped]
      content = YAML.load_file(dir.join(METADATA_FILENAME).to_s)
      _ = content.slice("name", "version", "source")
    end

manifest_of(name, version) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 73
    def manifest_of(name, version)
      setup! do
        path = File.join(repo_dir, name, version, 'manifest.yaml')
        content = git('cat-file', '-p', "#{resolved_revision}:#{path}")
        YAML.safe_load(content)
      rescue CommandError
        if has?(name, version)
          nil
        else
          raise
        end
      end
    end

metadata_content(name:, version:) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 207
    def metadata_content(name:, version:)
      {
        "name" => name,
        "version" => version,
        "source" => to_lockfile
      }
    end

resolved_revision() click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 172
    def resolved_revision
      @resolved_revision ||=
        begin
          if commit_hash?
            revision
          else
            setup! { git('rev-parse', "refs/remotes/origin/#{revision}").chomp }
          end
        end
    end

to_lockfile() click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 113
    def to_lockfile
      {
        'type' => 'git',
        'name' => name,
        'revision' => resolved_revision,
        'remote' => remote,
        'repo_dir' => repo_dir,
      }
    end

versions(name) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 36
    def versions(name)
      setup! do
        versions = gems_versions[name] or raise "Git source `#{name}` doesn't have `#{name}`"
        versions.sort
      end
    end

write_metadata(dir:, name:, version:) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 215
    def write_metadata(dir:, name:, version:)
      dir.join(METADATA_FILENAME).write(
        YAML.dump(
          metadata_content(name: name, version: version)
        )
      )
    end

### Private Instance Methods

_install(dest:, name:, version:) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 87
            def _install(dest:, name:, version:)
      # Should checkout that revision to support symlinks
      git("reset", "--hard", resolved_revision)

      dir = dest.join(name, version)
      dir.mkpath
      src = gem_repo_dir.join(name, version)

      cp_r(src, dir)
      write_metadata(dir: dir, name: name, version: version)
    end

commit_hash?() click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 183
            def commit_hash?
      revision.match?(/\A[a-f0-9]{40}\z/)
    end

cp_r(src, dest) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 99
            def cp_r(src, dest)
      Find.find(src) do |file_src|
        file_src = Pathname(file_src)

        # Skip file if it starts with _, such as _test/
        Find.prune if file_src.basename.to_s.start_with?('_')

        file_src_relative = file_src.relative_path_from(src)
        file_dest = dest.join(file_src_relative)
        file_dest.dirname.mkpath
        FileUtils.copy_entry(file_src, file_dest, false, true) unless file_src.directory?
      end
    end

format_config_entry(name, version) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 123
            def format_config_entry(name, version)
      rev = resolved_revision[0..10]
      desc = "#{name}@#{rev}"

      "#{name}:#{version} (#{desc})"
    end

gem_repo_dir() click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 168
            def gem_repo_dir
      git_dir.join @repo_dir
    end

gems_versions() click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 229
            def gems_versions
      @gems_versions ||= begin
        repo_path = Pathname(repo_dir)

        paths = git('ls-tree', '--full-tree', '-dr', '--name-only', '-z', resolved_revision, File.join(repo_dir, "")).split("\0").map {|line| Pathname(line) }

        # @type var versions: Hash[String, Set[String]]
        versions = {}

        paths.each do |full_path|
          path = full_path.relative_path_from(repo_path)

          gem_name, version = path.descend.take(2)

          if gem_name
            versions[gem_name.to_s] ||= Set[]

            if version && !version.basename.to_s.start_with?('_')
              versions[gem_name.to_s] << version.basename.to_s
            end
          end
        end

        versions
      end
    end

git(*cmd, **opt) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 187
            def git(*cmd, **opt)
      sh! 'git', *cmd, **opt
    end

git?(*cmd, **opt) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 191
            def git?(*cmd, **opt)
      git(*cmd, **opt)
    rescue CommandError
      nil
    end

git_dir() click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 158
            def git_dir
      @git_dir ||= (
        base = Pathname(ENV['XDG_CACHE_HOME'] || File.expand_path("~/.cache"))
        cache_key = remote.start_with?('.') ? "#{remote}\0#{Dir.pwd}" : remote
        dir = base.join('rbs', Digest::SHA256.hexdigest(cache_key))
        dir.mkpath
        dir
      )
    end

need_to_fetch?(revision) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 152
            def need_to_fetch?(revision)
      return true unless commit_hash?

      !git?('cat-file', '-e', revision)
    end

setup!() { || ... } click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 130
            def setup!
      if @need_setup
        git_dir.mkpath
        if git_dir.join('.git').directory?
          if need_to_fetch?(revision)
            git 'fetch', 'origin'
          end
        else
          begin
            # git v2.27.0 or greater
            git 'clone', '--filter=blob:none', remote, git_dir.to_s, chdir: nil
          rescue CommandError
            git 'clone', remote, git_dir.to_s, chdir: nil
          end
        end

        @need_setup = false
      end

      yield if block_given?
    end

sh!(*cmd, **opt) click to toggle source

    # File rbs-3.8.0/lib/rbs/collection/sources/git.rb, line 197
            def sh!(*cmd, **opt)
      RBS.logger.debug "$ #{cmd.join(' ')}"
      opt = { chdir: git_dir }.merge(opt).compact
      (__skip__ = Open3.capture3(*cmd, **opt)).then do |out, err, status|
        raise CommandError, "Unexpected status #{status.exitstatus}\n\n#{err}" unless status.success?

        out
      end
    end