add a cached Wiki#tree_map_for method

This commit is contained in:
rick
2010-08-24 11:15:29 -07:00
parent 74ca65b045
commit cc3d9529cc
2 changed files with 94 additions and 0 deletions
+79
View File
@@ -63,6 +63,7 @@ module Gollum
@base_path = options[:base_path] || "/"
@page_class = options[:page_class] || self.class.page_class
@file_class = options[:file_class] || self.class.file_class
clear_cache
end
# Public: check whether the wiki's git repo exists on the filesystem.
@@ -235,6 +236,20 @@ module Gollum
# Returns the String path.
attr_reader :path
# Gets a Hash cache of refs to commit SHAs.
#
# {"master" => "abc123", ...}
#
# Returns the Hash cache.
attr_reader :ref_map
# Gets a Hash cache of commit SHAs to a recursive tree of blobs.
#
# {"abc123" => [["lib/foo.rb", "blob-sha"], [file, sha], ...], ...}
#
# Returns the Hash cache.
attr_reader :tree_map
# Normalize the data.
#
# data - The String data to be normalized.
@@ -348,5 +363,69 @@ module Gollum
commit[:email] = self.class.default_committer_email if commit[:email].to_s.empty?
commit
end
# Finds a full listing of files and their blob SHA for a given ref. Each
# listing is cached based on its actual commit SHA.
#
# ref - A String ref that is either a commit SHA or references one.
#
# Returns an Array of [filename, sha] Arrays.
def tree_map_for(ref)
sha = @ref_map[ref] || ref
@tree_map[sha] || begin
real_sha = @repo.git.rev_list({:max_count=>1}, ref)
@ref_map[ref] = real_sha if real_sha != ref
@tree_map[real_sha] ||= parse_tree_for(real_sha)
end
end
# Finds the full listing of files and their blob SHA for a given commit
# SHA. No caching or ref lookups are performed.
#
# sha - String commit SHA.
#
# Returns an Array of [filename, sha] Arrays.
def parse_tree_for(sha)
tree = @repo.git.native(:ls_tree, {:r => true, :z => true}, sha)
items = []
tree.split("\0").each do |line|
items << parse_tree_line(line)
end
items
end
# Parses a line of output from the `ls-tree` command.
#
# line - A String line of output:
# "100644 blob 839c2291b30495b9a882c17d08254d3c90d8fb53 Home.md"
#
# Returns an Array of [filename, sha].
def parse_tree_line(line)
data, name = line.split("\t")
mode, type, sha = data.split(' ')
name = decode_git_path(name)
[name, sha]
end
# Decode octal sequences (\NNN) in tree path names.
#
# path - String path name.
#
# Returns a decoded String.
def decode_git_path(path)
if path[0] == ?" && path[-1] == ?"
path = path[1...-1]
path.gsub!(/\\\d{3}/) { |m| m[1..-1].to_i(8).chr }
end
path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m.to_s}")) }
path.downcase!
path
end
# Resets the ref and tree caches for this wiki.
def clear_cache
@ref_map = {}
@tree_map = {}
end
end
end
+15
View File
@@ -53,6 +53,21 @@ context "Wiki" do
assert_equal({:message => 'abc', :name => 'bob', :email => 'foo@bar.com'},
@wiki.normalize_commit(commit.dup))
end
test "#tree_map_for caches ref and tree" do
assert @wiki.ref_map.empty?
assert @wiki.tree_map.empty?
@wiki.tree_map_for 'master'
assert_equal({"master"=>"60f12f4254f58801b9ee7db7bca5fa8aeefaa56b"}, @wiki.ref_map)
assert_equal 'bilbo-baggins.md', @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'][0][0]
end
test "#tree_map_for only caches tree for commit" do
assert @wiki.tree_map.empty?
@wiki.tree_map_for '60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'
assert @wiki.ref_map.empty?
assert_equal 'bilbo-baggins.md', @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'][0][0]
end
end
context "Wiki page previewing" do