# encoding: utf-8 module ProxyTester class GitRepository private attr_reader :repository, :root_commit, :null_file, :file_creator public attr_reader :storage_path def initialize(storage_path, file_creator = ProxyTester::GitFile, null_file = ProxyTester::GitNullFile.new) @storage_path = ::File.expand_path(storage_path) @repository = Rugged::Repository.new(storage_path) @file_creator = file_creator @null_file = null_file rescue Rugged::RepositoryError raise Exceptions::RepositoryDoesNotExist, JSON.dump(repository: storage_path) end def self.create(storage_path) storage_path = ::File.expand_path(storage_path) Rugged::Repository.init_at(storage_path, :bare) new(storage_path) end def self.clone(source, destination, options = {}) bare = options.fetch(:bare, false) destination = ::File.expand_path(destination) if bare Rugged::Repository.clone_at(source, destination, bare: true) else Rugged::Repository.clone_at(source, destination) end new(destination) rescue Rugged::NetworkError raise Exceptions::RepositoryDoesNotExist, JSON.dump(repository: source) rescue Rugged::OSError raise Exceptions::RepositoryDoesNotExist, JSON.dump(repository: source) rescue Rugged::RepositoryError raise Exceptions::RepositoryInvalid, JSON.dump(repository: source) end def add_content(path, content = '', mode = 0100644, commit_info = default_commit_info) index = Rugged::Index.new unless repository.empty? root_commit = repository.lookup(repository.head.target) root_commit.tree.walk_blobs(:postorder) do |r, e| e.merge!( { path: "#{r}#{e[:name]}" } ) e.delete(:name) index.add(e) end end oid = repository.write(content, :blob) index.add(:path => path, :oid => oid, :mode => mode) options = {} options[:tree] = index.write_tree(repository) options[:parents] = repository.empty? ? [] : [ repository.head.target ].compact options[:update_ref] = 'HEAD' options.merge! commit_info Rugged::Commit.create(repository, options) end def find_file(name) files.fetch(name, null_file) end def all_files files.collect { |_,f| f } end def each_file(&block) all_files.each(&block) end private def files files_in_repository.reduce({}) do |memo, file| memo[file.name.to_sym] = file memo end end def files_in_repository return [] if repository.empty? head_commit = repository.head.target files = [] head_commit.tree.walk_blobs(:postorder) do |root, entry| files << file_creator.new("#{root}#{entry[:name]}", repository.lookup(entry[:oid]).content ) end files end def default_commit_info options = {} options[:author] = { :email => 'local_pac@local_pac', :name => 'Local Pac', :time => Time.now } options[:committer] = { :email => 'local_pac@local_pac', :name => 'Local Pac', :time => Time.now } options[:message] = 'Commit made by local pac itself' options end end end