class Bundler::Source::Git

def base_name

def base_name
  File.basename(uri, ".git")
end

def cache

def cache
  if cache_path.exist?
    Bundler.ui.info "Updating #{uri}"
    in_cache { git "fetch --quiet #{uri} master:master" }
  else
    Bundler.ui.info "Fetching #{uri}"
    FileUtils.mkdir_p(cache_path.dirname)
    git "clone #{uri} #{cache_path} --bare --no-hardlinks"
  end
end

def cache_path

def cache_path
  @cache_path ||= Bundler.cache.join("git", "#{base_name}-#{uri_hash}")
end

def git(command)

def git(command)
  out = %x{git #{command}}
  if $? != 0
    raise GitError, "An error has occurred in git. Cannot complete bundling."
  end
  out
end

def in_cache(&blk)

def in_cache(&blk)
  Dir.chdir(cache_path, &blk)
end

def initialize(options)

def initialize(options)
  @options = options
  @glob = options["glob"] || "{,*/}*.gemspec"
  @uri  = options["uri"]
  @ref  = options["ref"] || options["branch"] || 'master'
end

def install(spec)

def install(spec)
  Bundler.ui.debug "  * Using git #{uri}"
  if @installed
    Bundler.ui.debug "  * Already checked out revision: #{ref}"
  else
    Bundler.ui.debug "  * Checking out revision: #{ref}"
    FileUtils.mkdir_p(path)
    Dir.chdir(path) do
      unless File.exist?(".git")
        %x(git clone --no-checkout #{cache_path} #{path})
      end
      git "fetch --quiet"
      git "reset --hard #{revision}"
    end
    @installed = true
  end
end

def options

def options
  @options.merge("ref" => revision)
end

def path

def path
  Bundler.install_path.join("#{base_name}-#{uri_hash}-#{ref}")
end

def revision

def revision
  @revision ||= in_cache { git("rev-parse #{ref}").strip }
end

def specs

def specs
  @specs ||= begin
    index = Index.new
    # Start by making sure the git cache is up to date
    cache
    # Find all gemspecs in the repo
    in_cache do
      out   = %x(git ls-tree -r #{revision}).strip
      lines = out.split("\n").select { |l| l =~ /\.gemspec$/ }
      # Loop over the lines and extract the relative path and the
      # git hash
      lines.each do |line|
        next unless line =~ %r{^(\d+) (blob|tree) ([a-zf0-9]+)\t(.*)$}
        hash, file = $3, $4
        # Read the gemspec
        if spec = eval(%x(git cat-file blob #{$3}))
          spec = Specification.from_gemspec(spec)
          spec.relative_loaded_from = file
          spec.source = self
          index << spec
        end
      end
    end
    index << default_spec if default_spec && index.empty?
    index.freeze
  end
end

def to_s

def to_s
  ref = @options["ref"] ? @options["ref"][0..6] : @ref
  "#{@uri} (at #{ref})"
end

def uri_hash

def uri_hash
  Digest::SHA1.hexdigest(URI.parse(uri).normalize.to_s.sub(%r{/$}, ''))
end