# 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 . #++ require "rugged" require "libdolt/git" require "libdolt/git/blame" require "libdolt/git/commit" require "libdolt/git/submodule" require "libdolt/git/tree" module Dolt module Git class Repository def initialize(root) @repo = Rugged::Repository.new(root) end def bare?; @repo.bare?; end def path; @repo.path; end def rev_parse(*args); @repo.rev_parse(*args); end def rev_parse_oid(*args); @repo.rev_parse_oid(*args); end def refs(*args); @repo.refs(*args); end def lookup(*args); @repo.lookup(*args); end def submodules(ref) config = rev_parse("#{ref}:.gitmodules") Dolt::Git::Submodule.parse_config(config.content) rescue Rugged::TreeError => err # Raised if .gitmodules cannot be found, which means no submodules [] end def blob(ref, path) rev_parse("#{ref}:#{path}") end def tree(ref, path) object = rev_parse("#{ref}:#{path}") raise StandardError.new("Not a tree") if !object.is_a?(Rugged::Tree) annotate_tree(ref, path, object) end def tree_entry(ref, path) annotate_tree(ref, path, rev_parse("#{ref}:#{path}")) end def blame(ref, blob_path) process = Dolt::Git.git(path, "blame -l -t -p #{ref} -- #{blob_path}") Dolt::Git::Blame.parse_porcelain(process.stdout.read) end def log(ref, path, limit) entry_history(ref, path, limit) end def tree_history(ref, path, limit = 1) tree = rev_parse("#{ref}:#{path}") if tree.class != Rugged::Tree message = "#{ref}:#{path} is not a tree (#{tree.class.to_s})" raise Exception.new(message) end annotate_history(path || "./", ref, tree, limit) end def readmes(ref, path="") tree(ref, path).entries.select do |e| e[:type] == :blob && e[:name].match(/readme/i) end rescue Exception => err [] end private def entry_history(ref, entry, limit) process = Dolt::Git.git(path, "log -n #{limit} #{ref} -- #{entry}") Dolt::Git::Commit.parse_log(process.stdout.read) end def annotate_history(path, ref, entries, limit) resolve = lambda { |p| path == "" ? p : File.join(path, p) } entries.map do |e| e.merge(:history => entry_history(ref, resolve.call(e[:name]), limit)) end end def annotate_tree(ref, path, object) if object.class.to_s.match(/Blob/) || !object.find { |e| e[:type].nil? } return object end annotate_submodules(ref, path, object) end def annotate_submodules(ref, path, tree) modules = submodules(ref) entries = tree.entries.map do |entry| if entry[:type].nil? mod = path == "" ? entry[:name] : File.join(path, entry[:name]) meta = modules.find { |s| s[:path] == mod } if meta entry[:type] = :submodule entry[:url] = meta[:url] end end entry end Dolt::Git::Tree.new(tree.oid, entries) end end end end