# encoding: utf-8 #-- # Copyright (C) 2012-2013 Gitorious AS # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. #++ # Need consistent Time formatting in JSON require "time" class Time; def to_json(*args); "\"#{iso8601}\""; end; end module Dolt class RepositoryLookup def initialize(repo_resolver, archiver = nil) @repo_resolver = repo_resolver @archiver = archiver end def blob(repo, ref, path) repository = resolve_repository(repo) tpl_data(repository, ref, path, { :blob => repository.rev_parse("#{ref}:#{path}"), :filemode => filemode(repository, ref, path) }) end def tree(repo, ref, path) repository = resolve_repository(repo) tpl_data(repository, ref, path, { :tree => repository.tree(ref, path) }).merge(:readme => readme(repo, ref, path)) end def tree_entry(repo, ref, path) repository = resolve_repository(repo) result = repository.tree_entry(ref, path) key = result.class.to_s.match(/Blob/) ? :blob : :tree hash = tpl_data(repository, ref, path, { key => result, :type => key }) hash[:readme] = readme(repo, ref, path) if key == :tree hash[:filemode] = filemode(repository, ref, path) if key == :blob hash end def blame(repo, ref, path) repository = resolve_repository(repo) tpl_data(repository, ref, path, { :blame => repository.blame(ref, path), :filemode => filemode(repository, ref, path) }) end def history(repo, ref, path, count) repository = resolve_repository(repo) tpl_data(repository, ref, path, { :commits => repository.log(ref, path, count) }) end def refs(repo) repository = resolve_repository(repo) names = repository.refs.map(&:name) { :tags => expand_refs(repository, names, :tags), :heads => expand_refs(repository, names, :heads) }.merge(repository.to_hash) end def tree_history(repo, ref, path, count) repository = resolve_repository(repo) tpl_data(repository, ref, path, { :tree => repository.tree_history(ref, path, count) }) end def archive(repo, ref, format) repository = resolve_repository(repo) @archiver.archive(repository, ref, format) end def repositories repo_resolver.all end def resolve_repository(repo) ResolvedRepository.new(repo, repo_resolver.resolve(repo)) end def rev_parse_oid(repo, ref) resolve_repository(repo).rev_parse_oid(ref) end private def repo_resolver; @repo_resolver; end def tpl_data(repo, ref, path, locals = {}) { :path => path, :ref => ref }.merge(repo.to_hash).merge(locals) end def expand_refs(repository, names, type) names.select { |n| n =~ /#{type}/ }.map do |n| [n.sub(/^refs\/#{type}\//, ""), repository.rev_parse_oid(n)] end end def readme(repo_name, ref, path) repository = resolve_repository(repo_name) readmes = repository.readmes(ref, path) readme = readmes.detect {|blob| Makeup::Markup.can_render?(blob[:name])} return unless readme blob_path = File.join(*[path, readme[:name]].reject { |p| p == "" }) blob = repository.blob(ref, blob_path) {:blob => blob, :path => blob_path} end def filemode(repo, ref, path) file = File.basename(path) refspec = "#{ref}:#{File.dirname(path).sub(/^\.$/, '')}" entry = repo.rev_parse(refspec).find { |e| e[:name] == file } entry.nil? ? nil : entry[:filemode].to_s(8) end end class ResolvedRepository def initialize(slug, repository) @repository = repository @data = { :repository_slug => slug } @data[:repository_meta] = repository.meta if repository.respond_to?(:meta) end def to_hash @data end def method_missing(method, *args, &block) @repository.send(method, *args, &block) end end end