From 8c625419b88b1297d89ccc3522dab7548c830848 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 23 Aug 2010 16:13:38 -0700 Subject: [PATCH 01/39] add irb option for the cli script --- bin/gollum | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/bin/gollum b/bin/gollum index 9290e6c7..1aea84f9 100755 --- a/bin/gollum +++ b/bin/gollum @@ -14,9 +14,7 @@ Options: HELP require 'optparse' - require 'rubygems' -require 'gollum/frontend/app' exec = {} options = {} @@ -31,6 +29,10 @@ opts = OptionParser.new do |opts| puts "Gollum " + Gollum::VERSION exit 0 end + + opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do + options['irb'] = true + end end # Read command line options into `options` hash @@ -38,4 +40,36 @@ opts.parse! $path = ARGV[0] || Dir.pwd -Precious::App.run!(options) +if options['irb'] + require 'irb' + # http://jameskilton.com/2009/04/02/embedding-irb-into-your-ruby-application/ + module IRB # :nodoc: + def self.start_session(binding) + unless @__initialized + args = ARGV + ARGV.replace(ARGV.dup) + IRB.setup(nil) + ARGV.replace(args) + @__initialized = true + end + + workspace = WorkSpace.new(binding) + + irb = Irb.new(workspace) + + @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] + @CONF[:MAIN_CONTEXT] = irb.context + + catch(:IRB_EXIT) do + irb.eval_input + end + end + end + + require 'gollum' + wiki = Gollum::Wiki.new $path + IRB.start_session binding +else + require 'gollum/frontend/app' + Precious::App.run!(options) +end From 99995f7364323e18f9c451881d665b5da4191c55 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 23 Aug 2010 16:16:39 -0700 Subject: [PATCH 02/39] convert $path global to a gollum_path sinatra setting --- bin/gollum | 5 +++-- lib/gollum/frontend/app.rb | 17 +++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/bin/gollum b/bin/gollum index 1aea84f9..9a7fd9af 100755 --- a/bin/gollum +++ b/bin/gollum @@ -38,7 +38,7 @@ end # Read command line options into `options` hash opts.parse! -$path = ARGV[0] || Dir.pwd +gollum_path = ARGV[0] || Dir.pwd if options['irb'] require 'irb' @@ -67,9 +67,10 @@ if options['irb'] end require 'gollum' - wiki = Gollum::Wiki.new $path + wiki = Gollum::Wiki.new gollum_path IRB.start_session binding else require 'gollum/frontend/app' + Precious::App.set :gollum_path, gollum_path Precious::App.run!(options) end diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb index e4cb0991..f7c1f4c9 100644 --- a/lib/gollum/frontend/app.rb +++ b/lib/gollum/frontend/app.rb @@ -12,6 +12,7 @@ module Precious dir = File.dirname(File.expand_path(__FILE__)) # We want to serve public assets for now + set :public, "#{dir}/public" set :static, true @@ -40,7 +41,7 @@ module Precious get '/edit/:name' do @name = params[:name] - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) if page = wiki.page(@name) @page = page @content = page.raw_data @@ -52,7 +53,7 @@ module Precious post '/edit/:name' do name = params[:name] - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) page = wiki.page(name) format = params[:format].intern name = params[:rename] if params[:rename] @@ -64,7 +65,7 @@ module Precious post '/create/:name' do name = params[:page] - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) format = params[:format].intern @@ -80,13 +81,13 @@ module Precious post '/preview' do format = params['wiki_format'] data = params['text'] - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) wiki.preview_page("Preview", data, format).formatted_data end get '/history/:name' do @name = params[:name] - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) @page = wiki.page(@name) @page_num = [params[:page].to_i, 1].max @versions = @page.versions :page => @page_num @@ -108,7 +109,7 @@ module Precious get '/compare/:name/:version_list' do @name = params[:name] @versions = params[:version_list].split(/\.{2,3}/) - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) @page = wiki.page(@name) diffs = wiki.repo.diff(@versions.first, @versions.last, @page.path) @diff = diffs.first @@ -117,7 +118,7 @@ module Precious get %r{/(.+?)/([0-9a-f]{40})} do name = params[:captures][0] - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) if page = wiki.page(name, params[:captures][1]) @page = page @name = name @@ -133,7 +134,7 @@ module Precious end def show_page_or_file(name) - wiki = Gollum::Wiki.new($path) + wiki = Gollum::Wiki.new(settings.gollum_path) if page = wiki.page(name) @page = page @name = name From 05283347b0be7f3893ebd68604a869c2cf4be87a Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 23 Aug 2010 16:35:17 -0700 Subject: [PATCH 03/39] more descriptive irb output also, code poetry arguments --- bin/gollum | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/bin/gollum b/bin/gollum index 9a7fd9af..0ef6de8f 100755 --- a/bin/gollum +++ b/bin/gollum @@ -53,9 +53,8 @@ if options['irb'] @__initialized = true end - workspace = WorkSpace.new(binding) - - irb = Irb.new(workspace) + ws = WorkSpace.new(binding) + irb = Irb.new(ws) @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] @CONF[:MAIN_CONTEXT] = irb.context @@ -67,10 +66,28 @@ if options['irb'] end require 'gollum' - wiki = Gollum::Wiki.new gollum_path - IRB.start_session binding + begin + wiki = Gollum::Wiki.new(gollum_path) + if !wiki.exist? then raise Grit::InvalidGitRepositoryError end + puts "Loaded Gollum wiki at #{File.expand_path(gollum_path).inspect}." + puts + puts %( page = wiki.page('page-name')) + puts %( # => ) + puts + puts %( page.raw_data) + puts %( # => "# My wiki page") + puts + puts %( page.formatted_data) + puts %( # => "

My wiki page

") + puts + puts "Check out the Gollum README for more." + IRB.start_session(binding) + rescue Grit::InvalidGitRepositoryError, Grit::NoSuchPathError + puts "Invalid Gollum wiki at #{File.expand_path(gollum_path).inspect}" + exit 0 + end else require 'gollum/frontend/app' - Precious::App.set :gollum_path, gollum_path + Precious::App.set(:gollum_path, gollum_path) Precious::App.run!(options) end From 74ca65b0450cfe6c83372bc1eafc0e6431a78e78 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 23 Aug 2010 16:39:10 -0700 Subject: [PATCH 04/39] history updates --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 7261a905..7d20d2f1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -3,6 +3,9 @@ * Major Enhancements * Optimize page write/update/delete to use Grit::Index::read_tree instead of manually recreating entire index contents. + * Added --irb option for the gollum command. +* Minor Enhancements + * Support a `:gollum_path` Sinatra setting for `Precious::App` * Bug Fixes * Increase minimum Sanitize version requirement to 1.1.0. 1.0.x versions of Sanitize require Hpricot instead of Nokogiri From cc3d9529cc26c33b14902d30ab3b27dd594a736b Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 24 Aug 2010 11:15:29 -0700 Subject: [PATCH 05/39] add a cached Wiki#tree_map_for method --- lib/gollum/wiki.rb | 79 ++++++++++++++++++++++++++++++++++++++++++++++ test/test_wiki.rb | 15 +++++++++ 2 files changed, 94 insertions(+) diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index a5f9a094..030f5bd7 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -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 diff --git a/test/test_wiki.rb b/test/test_wiki.rb index f0edfd32..f6f774d1 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -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 From d606511fdf4695a07b59bcf8a5f952f07e732e70 Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 24 Aug 2010 11:25:05 -0700 Subject: [PATCH 06/39] use cached tree map when finding files --- lib/gollum/file.rb | 15 ++++++++------- test/test_file.rb | 7 +++++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/gollum/file.rb b/lib/gollum/file.rb index 20ceeec8..38f53e75 100644 --- a/lib/gollum/file.rb +++ b/lib/gollum/file.rb @@ -46,13 +46,14 @@ module Gollum # # Returns a Gollum::File or nil if the file could not be found. def find(name, version) - if commit = @wiki.repo.commit(version) - if (blob = commit.tree / name) && blob.is_a?(Grit::Blob) - @blob = blob - @path = name - @version = commit - self - end + checked = name.downcase + map = @wiki.tree_map_for(version) + sha = @wiki.ref_map[version] || version + if pair = map.detect { |(path, _)| path == checked } + @path = name + @blob = Grit::Blob.create(@wiki.repo, :id => pair.last, :name => ::File.basename(@path)) + @version = Grit::Commit.create(@wiki.repo, :id => sha) + self end end end diff --git a/test/test_file.rb b/test/test_file.rb index bcb507c4..56ded7f9 100644 --- a/test/test_file.rb +++ b/test/test_file.rb @@ -11,9 +11,12 @@ context "File" do end test "existing file" do - file = @wiki.file("Mordor/todo.txt") + commit = @wiki.repo.commits.first + file = @wiki.file("Mordor/todo.txt") assert_equal "[ ] Write section on Ents\n", file.raw_data - assert_equal @wiki.repo.commits.first.id, file.version.id + assert_equal 'todo.txt', file.name + assert_equal commit.id, file.version.id + assert_equal commit.author.name, file.version.author.name end test "accessing tree" do From 068a902a00e888d38ea9f1f8f6e46a5c87f787f3 Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 24 Aug 2010 11:47:02 -0700 Subject: [PATCH 07/39] don't modify path names in cached wiki treemaps --- lib/gollum/file.rb | 2 +- lib/gollum/wiki.rb | 1 - test/test_wiki.rb | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/gollum/file.rb b/lib/gollum/file.rb index 38f53e75..8dff7e47 100644 --- a/lib/gollum/file.rb +++ b/lib/gollum/file.rb @@ -49,7 +49,7 @@ module Gollum checked = name.downcase map = @wiki.tree_map_for(version) sha = @wiki.ref_map[version] || version - if pair = map.detect { |(path, _)| path == checked } + if pair = map.detect { |(path, _)| path.downcase == checked } @path = name @blob = Grit::Blob.create(@wiki.repo, :id => pair.last, :name => ::File.basename(@path)) @version = Grit::Commit.create(@wiki.repo, :id => sha) diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index 030f5bd7..433ba251 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -418,7 +418,6 @@ module Gollum 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 diff --git a/test/test_wiki.rb b/test/test_wiki.rb index f6f774d1..7b45ea53 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -59,14 +59,14 @@ context "Wiki" do 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] + 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] + assert_equal 'Bilbo-Baggins.md', @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'][0][0] end end From 292f6ec8dc582c83bb895bace8a4fb2f5f8e0b5e Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 24 Aug 2010 11:47:20 -0700 Subject: [PATCH 08/39] update Wiki#find_page_in_this_tree to use the new cached tree map. --- lib/gollum/page.rb | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index d93620bc..653f01d2 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -174,20 +174,15 @@ module Gollum dirs = self.path.split('/') dirs.pop + map = @wiki.tree_map_for(self.version.id) while !dirs.empty? - tree = self.version.tree / dirs.join('/') - if page = find_page_in_this_tree(tree, dirs.join('/'), '_Footer') + if page = find_page_in_this_tree(map, dirs.join('/'), '_Footer') return page end dirs.pop end - tree = self.version.tree - if page = find_page_in_this_tree(tree, '', '_Footer') - return page - end - - return nil + find_page_in_this_tree(map, '', '_Footer') end ######################################################################### @@ -289,22 +284,28 @@ module Gollum # Find a page in a given tree without recursing into subtrees. # - # tree - The Grit::Tree in which to look. + # tree - The Array tree map from Wiki#tree_map. # dir - The String path of the given Grit::Tree. # name - The canonical String page name. # # Returns a Gollum::Page or nil if the page could not be found. - def find_page_in_this_tree(tree, dir, name) - treemap = {} - tree.contents.each do |item| - case item - when Grit::Blob - if page_match(name, item.name) - path = dir == '' ? '' : ::File.join('/', dir) - page = self.class.new(@wiki).populate(item, path) - page.version = self.version - return page - end + def find_page_in_this_tree(map, dir, name) + checked = dir.downcase + map.each do |(full_name, blob_sha)| + dir_name = ::File.dirname(full_name) + if dir_name == '.' + dir_name = '' + else + dir_name.downcase! + end + blob_name = ::File.basename(full_name) + + if checked == dir_name && page_match(name, blob_name) + path = dir == '' ? '' : ::File.join('/', dir) + blob = Grit::Blob.create(@wiki.repo, :id => blob_sha, :name => blob_name) + page = self.class.new(@wiki).populate(blob, path) + page.version = self.version + return page end end From 3eeed9ba1e55d22d87a833f66f531620d6177ec0 Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 24 Aug 2010 12:15:11 -0700 Subject: [PATCH 09/39] update Wiki#find_page_in_tree to use cached tree map --- lib/gollum/page.rb | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index 653f01d2..ba996cb8 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -247,7 +247,8 @@ module Gollum # Returns a Gollum::Page or nil if the page could not be found. def find(name, version) if commit = @wiki.repo.commit(version) - if page = find_page_in_tree(commit.tree, name) + map = @wiki.tree_map_for(commit.id) + if page = find_page_in_tree(map, name) page.version = commit page end @@ -256,26 +257,19 @@ module Gollum # Find a page in a given tree. # - # tree - The Grit::Tree in which to look. + # map - The Array tree map from Wiki#tree_map. # name - The canonical String page name. # # Returns a Gollum::Page or nil if the page could not be found. - def find_page_in_tree(tree, name) - treemap = {} - trees = [tree] - - while !trees.empty? - ptree = trees.shift - ptree.contents.each do |item| - case item - when Grit::Blob - if page_match(name, item.name) - return self.class.new(@wiki).populate(item, tree_path(treemap, ptree)) - end - when Grit::Tree - treemap[item] = ptree - trees << item - end + def find_page_in_tree(map, name) + map.each do |(tree_name, blob_sha)| + blob_name = ::File.basename(tree_name) + if page_match(name, blob_name) + dir = ::File.dirname(tree_name) + blob = Grit::Blob.create(@wiki.repo, :id => blob_sha, :name => blob_name) + dir.sub! /(^\/)|(^\.$)/, '' + dir = "/#{dir}" if !dir.empty? + return self.class.new(@wiki).populate(blob, dir) end end @@ -284,7 +278,7 @@ module Gollum # Find a page in a given tree without recursing into subtrees. # - # tree - The Array tree map from Wiki#tree_map. + # map - The Array tree map from Wiki#tree_map. # dir - The String path of the given Grit::Tree. # name - The canonical String page name. # From 0500c7e10c31132211c1e6d1f7c2e318282bb4c0 Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 24 Aug 2010 12:39:26 -0700 Subject: [PATCH 10/39] cache the ref => sha lookup --- lib/gollum/page.rb | 13 ++++++------- lib/gollum/wiki.rb | 12 +++++++++--- test/test_markup.rb | 1 + 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index ba996cb8..fb54e47b 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -246,15 +246,14 @@ module Gollum # # Returns a Gollum::Page or nil if the page could not be found. def find(name, version) - if commit = @wiki.repo.commit(version) - map = @wiki.tree_map_for(commit.id) - if page = find_page_in_tree(map, name) - page.version = commit - page - end + map = @wiki.tree_map_for(version) + if page = find_page_in_tree(map, name) + sha = @wiki.ref_map[version] || version + page.version = Grit::Commit.create(@wiki.repo, :id => sha) + page end + rescue Grit::GitRuby::Repository::NoSuchShaFound end - # Find a page in a given tree. # # map - The Array tree map from Wiki#tree_map. diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index 433ba251..b00d8954 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -135,7 +135,9 @@ module Gollum parents = pcommit ? [pcommit] : [] actor = Grit::Actor.new(commit[:name], commit[:email]) - index.commit(commit[:message], parents, actor) + sha = index.commit(commit[:message], parents, actor) + @ref_map.clear + sha end # Public: Update an existing page with new content. The location of the @@ -172,7 +174,9 @@ module Gollum end actor = Grit::Actor.new(commit[:name], commit[:email]) - index.commit(commit[:message], [pcommit], actor) + sha = index.commit(commit[:message], [pcommit], actor) + @ref_map.clear + sha end # Public: Delete a page. @@ -192,7 +196,9 @@ module Gollum index.delete(page.path) actor = Grit::Actor.new(commit[:name], commit[:email]) - index.commit(commit[:message], [pcommit], actor) + sha = index.commit(commit[:message], [pcommit], actor) + @ref_map.clear + sha end # Public: Lists all pages for this wiki. diff --git a/test/test_markup.rb b/test/test_markup.rb index 8b3b4579..99e37319 100644 --- a/test/test_markup.rb +++ b/test/test_markup.rb @@ -349,6 +349,7 @@ context "Markup" do index.add("greek/Bilbo-Baggins.md", content) index.commit("Add alpha.jpg") + @wiki.clear_cache page = @wiki.page("Bilbo Baggins") rendered = Gollum::Markup.new(page).render assert_equal output, rendered From 8301428974c5729b2adebefc34e6eb43fb4c68e9 Mon Sep 17 00:00:00 2001 From: Henrik Hansen Date: Sun, 29 Aug 2010 10:08:08 +0200 Subject: [PATCH 11/39] Add sections to clean up markup test code --- test/test_markup.rb | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/test/test_markup.rb b/test/test_markup.rb index 8b3b4579..9744d3d5 100644 --- a/test/test_markup.rb +++ b/test/test_markup.rb @@ -21,6 +21,12 @@ context "Markup" do assert @wiki.pages[0].formatted_data end + ######################################################################### + # + # Links + # + ######################################################################### + test "double page links no space" do @wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", @commit) @@ -100,6 +106,12 @@ context "Markup" do assert_equal "

a http://example.com b

", page.formatted_data end + ######################################################################### + # + # Images + # + ######################################################################### + test "image with http url" do ['http', 'https'].each do |scheme| name = "Bilbo Baggins #{scheme}" @@ -217,6 +229,12 @@ context "Markup" do relative_image(content, output) end + ######################################################################### + # + # File links + # + ######################################################################### + test "file link with absolute path" do index = @wiki.repo.index index.add("alpha.jpg", "hi") @@ -248,6 +266,12 @@ context "Markup" do assert_equal %{

a Alpha b

}, page.formatted_data end + ######################################################################### + # + # Code + # + ######################################################################### + test "code blocks" do content = "a\n\n```ruby\nx = 1\n```\n\nb" output = "

a

\n\n
" +
@@ -296,6 +320,12 @@ context "Markup" do
     compare(content, output)
   end
 
+  #########################################################################
+  #
+  # Various
+  #
+  #########################################################################
+
   test "escaped wiki link" do
     content = "a '[[Foo]], b"
     output = "

a [[Foo]], b

" @@ -317,6 +347,12 @@ context "Markup" do compare(content, output, 'org') end + ######################################################################### + # + # TeX + # + ######################################################################### + test "tex block syntax" do content = 'a \[ a^2 \] b' output = "

a b

" @@ -329,6 +365,12 @@ context "Markup" do compare(content, output, 'md') end + ######################################################################### + # + # Helpers + # + ######################################################################### + def compare(content, output, ext = "md", regexes = []) index = @wiki.repo.index index.add("Bilbo-Baggins.#{ext}", content) @@ -353,4 +395,4 @@ context "Markup" do rendered = Gollum::Markup.new(page).render assert_equal output, rendered end -end \ No newline at end of file +end From 959f02b50ed1d97a2c5a4aec4d50872d636a8ac3 Mon Sep 17 00:00:00 2001 From: Henrik Hansen Date: Sun, 29 Aug 2010 14:26:14 +0200 Subject: [PATCH 12/39] Use correct capitalization of TeX --- test/test_markup.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_markup.rb b/test/test_markup.rb index 9744d3d5..b93e8b6e 100644 --- a/test/test_markup.rb +++ b/test/test_markup.rb @@ -353,13 +353,13 @@ context "Markup" do # ######################################################################### - test "tex block syntax" do + test "TeX block syntax" do content = 'a \[ a^2 \] b' output = "

a b

" compare(content, output, 'md') end - test "tex inline syntax" do + test "TeX inline syntax" do content = 'a \( a^2 \) b' output = "

a b

" compare(content, output, 'md') From 94f05b07964e58da7eda395a1d3ccf125bb8d40c Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Tue, 24 Aug 2010 13:58:05 -0700 Subject: [PATCH 13/39] Update working dir (if present) when edited via the API. Closes #6. --- HISTORY.md | 1 + gollum.gemspec | 2 +- lib/gollum/wiki.rb | 102 +++++++++++++++++++++++++++++++++++++++------ test/helper.rb | 6 +++ test/test_wiki.rb | 57 ++++++++++++++++++++++++- 5 files changed, 153 insertions(+), 15 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7d20d2f1..9a585d1d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,7 @@ * Optimize page write/update/delete to use Grit::Index::read_tree instead of manually recreating entire index contents. * Added --irb option for the gollum command. + * Update working dir (if present) when edited via the API (#6) * Minor Enhancements * Support a `:gollum_path` Sinatra setting for `Precious::App` * Bug Fixes diff --git a/gollum.gemspec b/gollum.gemspec index e13e105b..7aa05337 100644 --- a/gollum.gemspec +++ b/gollum.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |s| s.rdoc_options = ["--charset=UTF-8"] s.extra_rdoc_files = %w[README.md LICENSE] - s.add_dependency('grit', "~> 2.2") + s.add_dependency('grit', "~> 2.3") s.add_dependency('github-markup', [">= 0.4.0", "< 1.0.0"]) s.add_dependency('albino', "~> 1.0") s.add_dependency('sinatra', "~> 1.0") diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index b00d8954..ea4ab46d 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -135,9 +135,12 @@ module Gollum parents = pcommit ? [pcommit] : [] actor = Grit::Actor.new(commit[:name], commit[:email]) - sha = index.commit(commit[:message], parents, actor) + sha1 = index.commit(commit[:message], parents, actor) + @ref_map.clear - sha + update_working_dir(index, '', name, format) + + sha1 end # Public: Update an existing page with new content. The location of the @@ -162,21 +165,26 @@ module Gollum format ||= page.format index = self.repo.index + dir = ::File.dirname(page.path) + dir = '' if dir == '.' + index.read_tree(pcommit.tree.id) if page.name == name && page.format == format index.add(page.path, normalize(data)) else index.delete(page.path) - dir = ::File.dirname(page.path) - dir = '' if dir == '.' add_to_index(index, dir, name, format, data, :allow_same_ext) end actor = Grit::Actor.new(commit[:name], commit[:email]) - sha = index.commit(commit[:message], [pcommit], actor) + sha1 = index.commit(commit[:message], [pcommit], actor) + @ref_map.clear - sha + update_working_dir(index, dir, page.name, page.format) + update_working_dir(index, dir, name, format) + + sha1 end # Public: Delete a page. @@ -195,10 +203,16 @@ module Gollum index.read_tree(pcommit.tree.id) index.delete(page.path) + dir = ::File.dirname(page.path) + dir = '' if dir == '.' + actor = Grit::Actor.new(commit[:name], commit[:email]) - sha = index.commit(commit[:message], [pcommit], actor) + sha1 = index.commit(commit[:message], [pcommit], actor) + @ref_map.clear - sha + update_working_dir(index, dir, page.name, page.format) + + sha1 end # Public: Lists all pages for this wiki. @@ -265,6 +279,45 @@ module Gollum data.gsub(/\r/, '') end + # Assemble a Page's filename from its name and format. + # + # name - The String name of the page (may be in human format). + # format - The Symbol format of the page. + # + # Returns the String filename. + def page_file_name(name, format) + ext = @page_class.format_to_ext(format) + @page_class.cname(name) + '.' + ext + end + + # Update the given file in the repository's working directory if there + # is a working directory present. + # + # index - The Grit::Index with which to sync. + # dir - The String directory in which the file lives. + # name - The String name of the page (may be in human format). + # format - The Symbol format of the page. + # + # Returns nothing. + def update_working_dir(index, dir, name, format) + unless @repo.bare + path = + if dir == '' + page_file_name(name, format) + else + ::File.join(dir, page_file_name(name, format)) + end + + Dir.chdir(::File.join(@repo.path, '..')) do + if file_path_scheduled_for_deletion?(index.tree, path) + @repo.git.rm({'f' => true}, '--', path) + else + @repo.git.checkout({}, 'HEAD', '--', path) + end + end + end + end + # Fill an array with a list of pages. # # commit - The Grit::Commit @@ -290,8 +343,32 @@ module Gollum list end - # Determine if a given page path is scheduled to be deleted in the next - # commit for the given Index. + # Determine if a given file is scheduled to be deleted in the next commit + # for the given Index. + # + # map - The Hash map: + # key - The String directory or filename. + # val - The Hash submap or the String contents of the file. + # path - The String path of the file including extension. + # + # Returns the Boolean response. + def file_path_scheduled_for_deletion?(map, path) + parts = path.split('/') + if parts.size == 1 + deletions = map.keys.select { |k| !map[k] } + deletions.any? { |d| d == parts.first } + else + part = parts.shift + if rest = map[part] + file_path_scheduled_for_deletion?(rest, parts.join('/')) + else + false + end + end + end + + # Determine if a given page (regardless of format) is scheduled to be + # deleted in the next commit for the given Index. # # map - The Hash map: # key - The String directory or filename. @@ -311,7 +388,7 @@ module Gollum if rest = map[part] page_path_scheduled_for_deletion?(rest, parts.join('/')) else - nil + false end end end @@ -332,8 +409,7 @@ module Gollum # # Returns nothing (modifies the Index in place). def add_to_index(index, dir, name, format, data, allow_same_ext = false) - ext = @page_class.format_to_ext(format) - path = @page_class.cname(name) + '.' + ext + path = page_file_name(name, format) dir = '/' if dir.strip.empty? diff --git a/test/helper.rb b/test/helper.rb index 0b11383e..1db68446 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -18,6 +18,12 @@ def testpath(path) File.join(TEST_DIR, path) end +def commit_details + { :message => "Did something at #{Time.now}", + :name => "Tom Preston-Werner", + :email => "tom@github.com" } +end + # test/spec/mini 3 # http://gist.github.com/25455 # chris@ozmm.org diff --git a/test/test_wiki.rb b/test/test_wiki.rb index 7b45ea53..5b066bc7 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -238,4 +238,59 @@ context "Wiki page writing" do teardown do FileUtils.rm_r(File.join(File.dirname(__FILE__), *%w[examples test.git])) end -end \ No newline at end of file +end + +context "Wiki sync with working directory" do + setup do + @path = testpath('examples/wdtest') + Grit::Repo.init(@path) + @wiki = Gollum::Wiki.new(@path) + end + + test "write a page" do + @wiki.write_page("New Page", :markdown, "Hi", commit_details) + assert_equal "Hi", File.read(File.join(@path, "New-Page.md")) + end + + test "update a page with same name and format" do + @wiki.write_page("New Page", :markdown, "Hi", commit_details) + page = @wiki.page("New Page") + @wiki.update_page(page, page.name, page.format, "Bye", commit_details) + assert_equal "Bye", File.read(File.join(@path, "New-Page.md")) + end + + test "update a page with different name and same format" do + @wiki.write_page("New Page", :markdown, "Hi", commit_details) + page = @wiki.page("New Page") + @wiki.update_page(page, "New Page 2", page.format, "Bye", commit_details) + assert_equal "Bye", File.read(File.join(@path, "New-Page-2.md")) + assert !File.exist?(File.join(@path, "New-Page.md")) + end + + test "update a page with same name and different format" do + @wiki.write_page("New Page", :markdown, "Hi", commit_details) + page = @wiki.page("New Page") + @wiki.update_page(page, page.name, :textile, "Bye", commit_details) + assert_equal "Bye", File.read(File.join(@path, "New-Page.textile")) + assert !File.exist?(File.join(@path, "New-Page.md")) + end + + test "update a page with different name and different format" do + @wiki.write_page("New Page", :markdown, "Hi", commit_details) + page = @wiki.page("New Page") + @wiki.update_page(page, "New Page 2", :textile, "Bye", commit_details) + assert_equal "Bye", File.read(File.join(@path, "New-Page-2.textile")) + assert !File.exist?(File.join(@path, "New-Page.md")) + end + + test "delete a page" do + @wiki.write_page("New Page", :markdown, "Hi", commit_details) + page = @wiki.page("New Page") + @wiki.delete_page(page, commit_details) + assert !File.exist?(File.join(@path, "New-Page.md")) + end + + teardown do + FileUtils.rm_r(@path) + end +end From dddb73672ab9991da74e3e864e514566f74fad1e Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 29 Aug 2010 18:50:19 -0700 Subject: [PATCH 14/39] Minor readme typo and various whitespace fixups. --- README.md | 2 +- test/helper.rb | 2 +- test/test_wiki.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ecee5c06..5100bb18 100644 --- a/README.md +++ b/README.md @@ -326,7 +326,7 @@ Initialize the Gollum::Repo object: wiki = Gollum::Wiki.new("my-gollum-repo.git") # => -By default, internal wiki links are all absolute from the root. To specify a different base path, you can send specify the `:base_path` option: +By default, internal wiki links are all absolute from the root. To specify a different base path, you can specify the `:base_path` option: wiki = Gollum::Wiki.new("my-gollum-repo.git", :base_path => "/wiki") diff --git a/test/helper.rb b/test/helper.rb index 1db68446..f6e01ded 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -32,7 +32,7 @@ def context(*args, &block) return super unless (name = args.first) && block require 'test/unit' klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do - def self.test(name, &block) + def self.test(name, &block) define_method("test_#{name.gsub(/\W/,'_')}", &block) if block end def self.xtest(*args) end diff --git a/test/test_wiki.rb b/test/test_wiki.rb index 5b066bc7..458e9621 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -35,7 +35,7 @@ context "Wiki" do test "list pages" do pages = @wiki.pages assert_equal \ - %w(Bilbo-Baggins.md Eye-Of-Sauron.md Home.textile My-Precious.md), + %w(Bilbo-Baggins.md Eye-Of-Sauron.md Home.textile My-Precious.md), pages.map { |p| p.filename }.sort end From db1ccc452559e8dc82ee53f108c48a5a97a06ba4 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Mon, 30 Aug 2010 16:10:14 -0700 Subject: [PATCH 15/39] DRY up test commit details. --- test/test_markup.rb | 24 ++++++--------- test/test_wiki.rb | 75 +++++++++++++++------------------------------ 2 files changed, 34 insertions(+), 65 deletions(-) diff --git a/test/test_markup.rb b/test/test_markup.rb index 99e37319..0a3e6649 100644 --- a/test/test_markup.rb +++ b/test/test_markup.rb @@ -6,10 +6,6 @@ context "Markup" do FileUtils.rm_rf(@path) Grit::Repo.init_bare(@path) @wiki = Gollum::Wiki.new(@path) - - @commit = { :message => "Add stuff", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } end teardown do @@ -17,12 +13,12 @@ context "Markup" do end test "formats page from Wiki#pages" do - @wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", @commit) + @wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", commit_details) assert @wiki.pages[0].formatted_data end test "double page links no space" do - @wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", @commit) + @wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", commit_details) # "

a FooBar b

" page = @wiki.page("Bilbo Baggins") @@ -41,7 +37,7 @@ context "Markup" do end test "double page links with space" do - @wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]] [[Bar]] b", @commit) + @wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]] [[Bar]] b", commit_details) # "

a Foo Bar b

" page = @wiki.page("Bilbo Baggins") @@ -60,7 +56,7 @@ context "Markup" do end test "page link" do - @wiki.write_page("Bilbo Baggins", :markdown, "a [[Bilbo Baggins]] b", @commit) + @wiki.write_page("Bilbo Baggins", :markdown, "a [[Bilbo Baggins]] b", commit_details) page = @wiki.page("Bilbo Baggins") output = page.formatted_data @@ -70,7 +66,7 @@ context "Markup" do end test "absent page link" do - @wiki.write_page("Tolkien", :markdown, "a [[J. R. R. Tolkien]]'s b", @commit) + @wiki.write_page("Tolkien", :markdown, "a [[J. R. R. Tolkien]]'s b", commit_details) page = @wiki.page("Tolkien") output = page.formatted_data @@ -83,7 +79,7 @@ context "Markup" do ["/wiki", "/wiki/"].each_with_index do |path, i| name = "Bilbo Baggins #{i}" @wiki = Gollum::Wiki.new(@path, :base_path => path) - @wiki.write_page(name, :markdown, "a [[#{name}]] b", @commit) + @wiki.write_page(name, :markdown, "a [[#{name}]] b", commit_details) page = @wiki.page(name) output = page.formatted_data @@ -94,7 +90,7 @@ context "Markup" do end test "external page link" do - @wiki.write_page("Bilbo Baggins", :markdown, "a [[http://example.com]] b", @commit) + @wiki.write_page("Bilbo Baggins", :markdown, "a [[http://example.com]] b", commit_details) page = @wiki.page("Bilbo Baggins") assert_equal "

a http://example.com b

", page.formatted_data @@ -103,7 +99,7 @@ context "Markup" do test "image with http url" do ['http', 'https'].each do |scheme| name = "Bilbo Baggins #{scheme}" - @wiki.write_page(name, :markdown, "a [[#{scheme}://example.com/bilbo.jpg]] b", @commit) + @wiki.write_page(name, :markdown, "a [[#{scheme}://example.com/bilbo.jpg]] b", commit_details) page = @wiki.page(name) output = page.formatted_data @@ -116,7 +112,7 @@ context "Markup" do index = @wiki.repo.index index.add("alpha.jpg", "hi") index.commit("Add alpha.jpg") - @wiki.write_page("Bilbo Baggins", :markdown, "a [[/alpha.jpg]] [[a | /alpha.jpg]] b", @commit) + @wiki.write_page("Bilbo Baggins", :markdown, "a [[/alpha.jpg]] [[a | /alpha.jpg]] b", commit_details) page = @wiki.page("Bilbo Baggins") assert_equal %{

a a b

}, page.formatted_data @@ -221,7 +217,7 @@ context "Markup" do index = @wiki.repo.index index.add("alpha.jpg", "hi") index.commit("Add alpha.jpg") - @wiki.write_page("Bilbo Baggins", :markdown, "a [[Alpha|/alpha.jpg]] b", @commit) + @wiki.write_page("Bilbo Baggins", :markdown, "a [[Alpha|/alpha.jpg]] b", commit_details) page = @wiki.page("Bilbo Baggins") output = Gollum::Markup.new(page).render diff --git a/test/test_wiki.rb b/test/test_wiki.rb index 458e9621..2e5e4ede 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -94,58 +94,48 @@ context "Wiki page writing" do end test "write_page" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - @wiki.write_page("Gollum", :markdown, "# Gollum", commit) + cd = commit_details + @wiki.write_page("Gollum", :markdown, "# Gollum", cd) assert_equal 1, @wiki.repo.commits.size - assert_equal "Gollum page", @wiki.repo.commits.first.message - assert_equal "Tom Preston-Werner", @wiki.repo.commits.first.author.name - assert_equal "tom@github.com", @wiki.repo.commits.first.author.email + assert_equal cd[:message], @wiki.repo.commits.first.message + assert_equal cd[:name], @wiki.repo.commits.first.author.name + assert_equal cd[:email], @wiki.repo.commits.first.author.email assert @wiki.page("Gollum") - @wiki.write_page("Bilbo", :markdown, "# Bilbo", commit) + @wiki.write_page("Bilbo", :markdown, "# Bilbo", commit_details) assert_equal 2, @wiki.repo.commits.size assert @wiki.page("Bilbo") assert @wiki.page("Gollum") end test "is not allowed to overwrite file" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - @wiki.write_page("Abc-Def", :markdown, "# Gollum", commit) + @wiki.write_page("Abc-Def", :markdown, "# Gollum", commit_details) assert_raises Gollum::DuplicatePageError do - @wiki.write_page("ABC DEF", :textile, "# Gollum", commit) + @wiki.write_page("ABC DEF", :textile, "# Gollum", commit_details) end end test "update_page" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - @wiki.write_page("Gollum", :markdown, "# Gollum", commit) + @wiki.write_page("Gollum", :markdown, "# Gollum", commit_details) page = @wiki.page("Gollum") - @wiki.update_page(page, page.name, :markdown, "# Gollum2", commit) + cd = commit_details + @wiki.update_page(page, page.name, :markdown, "# Gollum2", cd) assert_equal 2, @wiki.repo.commits.size assert_equal "# Gollum2", @wiki.page("Gollum").raw_data - assert_equal "Gollum page", @wiki.repo.commits.first.message - assert_equal "Tom Preston-Werner", @wiki.repo.commits.first.author.name - assert_equal "tom@github.com", @wiki.repo.commits.first.author.email + assert_equal cd[:message], @wiki.repo.commits.first.message + assert_equal cd[:name], @wiki.repo.commits.first.author.name + assert_equal cd[:email], @wiki.repo.commits.first.author.email end test "update page with format change" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - @wiki.write_page("Gollum", :markdown, "# Gollum", commit) + @wiki.write_page("Gollum", :markdown, "# Gollum", commit_details) assert_equal :markdown, @wiki.page("Gollum").format page = @wiki.page("Gollum") - @wiki.update_page(page, page.name, :textile, "h1. Gollum", commit) + @wiki.update_page(page, page.name, :textile, "h1. Gollum", commit_details) assert_equal 2, @wiki.repo.commits.size assert_equal :textile, @wiki.page("Gollum").format @@ -153,30 +143,24 @@ context "Wiki page writing" do end test "update page with name change" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - @wiki.write_page("Gollum", :markdown, "# Gollum", commit) + @wiki.write_page("Gollum", :markdown, "# Gollum", commit_details) assert_equal :markdown, @wiki.page("Gollum").format page = @wiki.page("Gollum") - @wiki.update_page(page, 'Smeagol', :markdown, "h1. Gollum", commit) + @wiki.update_page(page, 'Smeagol', :markdown, "h1. Gollum", commit_details) assert_equal 2, @wiki.repo.commits.size assert_equal "h1. Gollum", @wiki.page("Smeagol").raw_data end test "update page with name and format change" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - @wiki.write_page("Gollum", :markdown, "# Gollum", commit) + @wiki.write_page("Gollum", :markdown, "# Gollum", commit_details) assert_equal :markdown, @wiki.page("Gollum").format page = @wiki.page("Gollum") - @wiki.update_page(page, 'Smeagol', :textile, "h1. Gollum", commit) + @wiki.update_page(page, 'Smeagol', :textile, "h1. Gollum", commit_details) assert_equal 2, @wiki.repo.commits.size assert_equal :textile, @wiki.page("Smeagol").format @@ -184,17 +168,13 @@ context "Wiki page writing" do end test "update nested page with format change" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - index = @wiki.repo.index index.add("lotr/Gollum.md", "# Gollum") index.commit("Add nested page") page = @wiki.page("Gollum") assert_equal :markdown, @wiki.page("Gollum").format - @wiki.update_page(page, page.name, :textile, "h1. Gollum", commit) + @wiki.update_page(page, page.name, :textile, "h1. Gollum", commit_details) page = @wiki.page("Gollum") assert_equal "lotr/Gollum.textile", page.path @@ -203,23 +183,16 @@ context "Wiki page writing" do end test "delete root page" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - @wiki.write_page("Gollum", :markdown, "# Gollum", commit) + @wiki.write_page("Gollum", :markdown, "# Gollum", commit_details) page = @wiki.page("Gollum") - @wiki.delete_page(page, commit) + @wiki.delete_page(page, commit_details) assert_equal 2, @wiki.repo.commits.size assert_nil @wiki.page("Gollum") end test "delete nested page" do - commit = { :message => "Gollum page", - :name => "Tom Preston-Werner", - :email => "tom@github.com" } - index = @wiki.repo.index index.add("greek/Bilbo-Baggins.md", "hi") index.add("Gollum.md", "hi") @@ -227,7 +200,7 @@ context "Wiki page writing" do page = @wiki.page("Bilbo-Baggins") assert page - @wiki.delete_page(page, commit) + @wiki.delete_page(page, commit_details) assert_equal 2, @wiki.repo.commits.size assert_nil @wiki.page("Bilbo-Baggins") From f4c4b2e49cd7a268c56dd43bf248ad5c93873ce2 Mon Sep 17 00:00:00 2001 From: Dean Strelau Date: Fri, 20 Aug 2010 21:29:20 -0400 Subject: [PATCH 16/39] Update development dependencies. Closes github#18 Tests require a few markdown libraries to pass. --- gollum.gemspec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gollum.gemspec b/gollum.gemspec index 7aa05337..cf0833e8 100644 --- a/gollum.gemspec +++ b/gollum.gemspec @@ -31,9 +31,11 @@ Gem::Specification.new do |s| s.add_dependency('sanitize', "~> 1.1") s.add_dependency('nokogiri', "~> 1.4") - s.add_development_dependency('shoulda') + s.add_development_dependency('RedCloth') s.add_development_dependency('mocha') s.add_development_dependency('org-ruby') + s.add_development_dependency('rdiscount') + s.add_development_dependency('shoulda') # = MANIFEST = s.files = %w[ @@ -503,4 +505,4 @@ Gem::Specification.new do |s| # = MANIFEST = s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ } -end \ No newline at end of file +end From 6f077702e1606550030f97ecf1609c01cbe5128f Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 16:57:55 -0700 Subject: [PATCH 17/39] Page#find_page_in_this_tree is redundant --- lib/gollum/page.rb | 53 +++++++++++++--------------------------------- lib/gollum/wiki.rb | 19 +++++++++++++++++ 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index fb54e47b..f0948987 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -176,13 +176,13 @@ module Gollum dirs.pop map = @wiki.tree_map_for(self.version.id) while !dirs.empty? - if page = find_page_in_this_tree(map, dirs.join('/'), '_Footer') + if page = find_page_in_tree(map, '_Footer', dirs.join('/')) return page end dirs.pop end - find_page_in_this_tree(map, '', '_Footer') + find_page_in_tree(map, '_Footer', '') end ######################################################################### @@ -254,51 +254,28 @@ module Gollum end rescue Grit::GitRuby::Repository::NoSuchShaFound end + # Find a page in a given tree. # - # map - The Array tree map from Wiki#tree_map. - # name - The canonical String page name. + # map - The Array tree map from Wiki#tree_map. + # name - The canonical String page name. + # checked_dir - Optional String of the directory a matching page needs + # to be in. The string should # # Returns a Gollum::Page or nil if the page could not be found. - def find_page_in_tree(map, name) - map.each do |(tree_name, blob_sha)| - blob_name = ::File.basename(tree_name) - if page_match(name, blob_name) - dir = ::File.dirname(tree_name) - blob = Grit::Blob.create(@wiki.repo, :id => blob_sha, :name => blob_name) - dir.sub! /(^\/)|(^\.$)/, '' - dir = "/#{dir}" if !dir.empty? - return self.class.new(@wiki).populate(blob, dir) - end + def find_page_in_tree(map, name, checked_dir = nil) + if checked_dir = Wiki.normalize_directory(checked_dir) + checked_dir.downcase! end - return nil # nothing was found - end - - # Find a page in a given tree without recursing into subtrees. - # - # map - The Array tree map from Wiki#tree_map. - # dir - The String path of the given Grit::Tree. - # name - The canonical String page name. - # - # Returns a Gollum::Page or nil if the page could not be found. - def find_page_in_this_tree(map, dir, name) - checked = dir.downcase map.each do |(full_name, blob_sha)| - dir_name = ::File.dirname(full_name) - if dir_name == '.' - dir_name = '' - else - dir_name.downcase! - end blob_name = ::File.basename(full_name) - - if checked == dir_name && page_match(name, blob_name) - path = dir == '' ? '' : ::File.join('/', dir) + dir = Wiki.normalize_directory(::File.dirname(full_name)) + blob_in_dir = checked_dir.nil? || dir.downcase == checked_dir + + if blob_in_dir && page_match(name, blob_name) blob = Grit::Blob.create(@wiki.repo, :id => blob_sha, :name => blob_name) - page = self.class.new(@wiki).populate(blob, path) - page.version = self.version - return page + return self.class.new(@wiki).populate(blob, dir) end end diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index b00d8954..eb8f1bef 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -431,6 +431,25 @@ module Gollum def clear_cache @ref_map = {} @tree_map = {} + end # Normalizes a given directory name for searching through tree paths. + # Ensures that a directory begins with a slash, or + # + # normalize_directory("") # => "" + # normalize_directory(".") # => "" + # normalize_directory("foo") # => "/foo" + # normalize_directory("/foo/") # => "/foo" + # normalize_directory("/") # => "" + # + # dir - String directory name. + # + # Returns a normalized String directory name, or nil if no directory + # is given. + def self.normalize_directory(dir) + if dir + dir = ::File.expand_path(dir, '/') + dir = '' if dir == '/' + end + dir end end end From 7e2b1fdbc62c74ef47b33fcff67a8789273127b0 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 17:30:45 -0700 Subject: [PATCH 18/39] Wiki#tree_map_for returns an array of BlobEntry instances --- lib/gollum.rb | 1 + lib/gollum/blob_entry.rb | 51 ++++++++++++++++++++++++++++++++++++++++ lib/gollum/file.rb | 4 ++-- lib/gollum/page.rb | 15 ++++-------- lib/gollum/wiki.rb | 27 ++++----------------- test/test_wiki.rb | 8 +++++-- 6 files changed, 69 insertions(+), 37 deletions(-) create mode 100644 lib/gollum/blob_entry.rb diff --git a/lib/gollum.rb b/lib/gollum.rb index 21a0c8ea..68e96fff 100644 --- a/lib/gollum.rb +++ b/lib/gollum.rb @@ -12,6 +12,7 @@ require 'gollum/ruby1.8' # internal require 'gollum/pagination' +require 'gollum/blob_entry' require 'gollum/wiki' require 'gollum/page' require 'gollum/file' diff --git a/lib/gollum/blob_entry.rb b/lib/gollum/blob_entry.rb new file mode 100644 index 00000000..23c92084 --- /dev/null +++ b/lib/gollum/blob_entry.rb @@ -0,0 +1,51 @@ +module Gollum + class BlobEntry + # Gets the String SHA for this blob. + attr_reader :sha + + # Gets the String full path for this blob. + attr_reader :path + + def initialize(sha, path) + @sha = sha + @path = path + @dir = @name = @blob = nil + end + + # Gets the normalized directory path for this blob. + def dir + @dir ||= self.class.normalize_dir(::File.dirname(@path)) + end + + # Gets the String file base name for this blob. + def name + @name ||= ::File.basename(@path) + end + + # Gets the Grit::Blob instance for this blob. + def blob(repo) + @blob ||= Grit::Blob.create(repo, :id => @sha, :name => @name) + end + + # Normalizes a given directory name for searching through tree paths. + # Ensures that a directory begins with a slash, or + # + # normalize_dir("") # => "" + # normalize_dir(".") # => "" + # normalize_dir("foo") # => "/foo" + # normalize_dir("/foo/") # => "/foo" + # normalize_dir("/") # => "" + # + # dir - String directory name. + # + # Returns a normalized String directory name, or nil if no directory + # is given. + def self.normalize_dir(dir) + if dir + dir = ::File.expand_path(dir, '/') + dir = '' if dir == '/' + end + dir + end + end +end \ No newline at end of file diff --git a/lib/gollum/file.rb b/lib/gollum/file.rb index 8dff7e47..0f1f58fd 100644 --- a/lib/gollum/file.rb +++ b/lib/gollum/file.rb @@ -49,9 +49,9 @@ module Gollum checked = name.downcase map = @wiki.tree_map_for(version) sha = @wiki.ref_map[version] || version - if pair = map.detect { |(path, _)| path.downcase == checked } + if entry = map.detect { |entry| entry.path.downcase == checked } @path = name - @blob = Grit::Blob.create(@wiki.repo, :id => pair.last, :name => ::File.basename(@path)) + @blob = Grit::Blob.create(@wiki.repo, :id => entry.sha, :name => entry.name) @version = Grit::Commit.create(@wiki.repo, :id => sha) self end diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index f0948987..7ac45bdb 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -264,19 +264,14 @@ module Gollum # # Returns a Gollum::Page or nil if the page could not be found. def find_page_in_tree(map, name, checked_dir = nil) - if checked_dir = Wiki.normalize_directory(checked_dir) + if checked_dir = BlobEntry.normalize_dir(checked_dir) checked_dir.downcase! end - map.each do |(full_name, blob_sha)| - blob_name = ::File.basename(full_name) - dir = Wiki.normalize_directory(::File.dirname(full_name)) - blob_in_dir = checked_dir.nil? || dir.downcase == checked_dir - - if blob_in_dir && page_match(name, blob_name) - blob = Grit::Blob.create(@wiki.repo, :id => blob_sha, :name => blob_name) - return self.class.new(@wiki).populate(blob, dir) - end + map.each do |entry| + next unless checked_dir.nil? || entry.dir.downcase == checked_dir + next unless page_match(name, entry.name) + return self.class.new(@wiki).populate(entry.blob(@wiki.repo), entry.dir) end return nil # nothing was found diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index eb8f1bef..af92cbba 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -375,7 +375,7 @@ module Gollum # # ref - A String ref that is either a commit SHA or references one. # - # Returns an Array of [filename, sha] Arrays. + # Returns an Array of BlobEntry instances. def tree_map_for(ref) sha = @ref_map[ref] || ref @tree_map[sha] || begin @@ -390,7 +390,7 @@ module Gollum # # sha - String commit SHA. # - # Returns an Array of [filename, sha] Arrays. + # Returns an Array of BlobEntry instances. def parse_tree_for(sha) tree = @repo.git.native(:ls_tree, {:r => true, :z => true}, sha) items = [] @@ -405,12 +405,12 @@ module Gollum # line - A String line of output: # "100644 blob 839c2291b30495b9a882c17d08254d3c90d8fb53 Home.md" # - # Returns an Array of [filename, sha]. + # Returns an Array of BlobEntry instances. def parse_tree_line(line) data, name = line.split("\t") mode, type, sha = data.split(' ') name = decode_git_path(name) - [name, sha] + BlobEntry.new sha, name end # Decode octal sequences (\NNN) in tree path names. @@ -431,25 +431,6 @@ module Gollum def clear_cache @ref_map = {} @tree_map = {} - end # Normalizes a given directory name for searching through tree paths. - # Ensures that a directory begins with a slash, or - # - # normalize_directory("") # => "" - # normalize_directory(".") # => "" - # normalize_directory("foo") # => "/foo" - # normalize_directory("/foo/") # => "/foo" - # normalize_directory("/") # => "" - # - # dir - String directory name. - # - # Returns a normalized String directory name, or nil if no directory - # is given. - def self.normalize_directory(dir) - if dir - dir = ::File.expand_path(dir, '/') - dir = '' if dir == '/' - end - dir end end end diff --git a/test/test_wiki.rb b/test/test_wiki.rb index 7b45ea53..a7d065f1 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -59,14 +59,18 @@ context "Wiki" do 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] + + entry = @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'][0] + assert_equal 'Bilbo-Baggins.md', entry.path 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] + + entry = @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'][0] + assert_equal 'Bilbo-Baggins.md', entry.path end end From 6dab4f7fe62ea166fead2220b736b4cd3e16f0ba Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 17:41:35 -0700 Subject: [PATCH 19/39] Wiki#pages uses the treemap --- lib/gollum/blob_entry.rb | 18 +++++++++++++++++- lib/gollum/page.rb | 2 +- lib/gollum/wiki.rb | 37 +++++++++++++------------------------ 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/lib/gollum/blob_entry.rb b/lib/gollum/blob_entry.rb index 23c92084..14ef59b9 100644 --- a/lib/gollum/blob_entry.rb +++ b/lib/gollum/blob_entry.rb @@ -22,11 +22,27 @@ module Gollum @name ||= ::File.basename(@path) end - # Gets the Grit::Blob instance for this blob. + # Gets a Grit::Blob instance for this blob. + # + # repo - Grit::Repo instance for the Grit::Blob. + # + # Returns an unbaked Grit::Blob instance. def blob(repo) @blob ||= Grit::Blob.create(repo, :id => @sha, :name => @name) end + # Gets a Page instance for this blob. + # + # wiki - Gollum::Wiki instance for the Gollum::Page + # + # Returns a Gollum::Page instance. + def page(wiki, commit) + blob = self.blob(wiki.repo) + page = wiki.page_class.new(wiki).populate(blob, self.dir) + page.version = commit + page + end + # Normalizes a given directory name for searching through tree paths. # Ensures that a directory begins with a slash, or # diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index 7ac45bdb..f2b7f1c2 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -271,7 +271,7 @@ module Gollum map.each do |entry| next unless checked_dir.nil? || entry.dir.downcase == checked_dir next unless page_match(name, entry.name) - return self.class.new(@wiki).populate(entry.blob(@wiki.repo), entry.dir) + return entry.page(@wiki, @version) end return nil # nothing was found diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index af92cbba..440e967d 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -207,12 +207,7 @@ module Gollum # # Returns an Array of Gollum::Page instances. def pages(treeish = nil) - treeish ||= 'master' - if commit = @repo.commit(treeish) - tree_list(commit) - else - [] - end + tree_list(treeish || 'master') end # Public: All of the versions that have touched the Page. @@ -256,6 +251,12 @@ module Gollum # Returns the Hash cache. attr_reader :tree_map + # Gets the page class used by all instances of this Wiki. + attr_reader :page_class + + # Gets the file class used by all instances of this Wiki. + attr_reader :file_class + # Normalize the data. # # data - The String data to be normalized. @@ -267,27 +268,15 @@ module Gollum # Fill an array with a list of pages. # - # commit - The Grit::Commit - # tree - The Grit::Tree to start with. - # sub_tree - Optional String specifying the parent path of the Page. + # ref - A String ref that is either a commit SHA or references one. # # Returns a flat Array of Gollum::Page instances. - def tree_list(commit, tree = commit.tree, sub_tree = nil) - list = [] - path = tree.name ? "#{sub_tree}/#{tree.name}" : '' - tree.contents.each do |item| - case item - when Grit::Blob - if @page_class.valid_page_name?(item.name) - page = @page_class.new(self).populate(item, path) - page.version = commit - list << page - end - when Grit::Tree - list.push *tree_list(commit, item, path) - end + def tree_list(ref) + tree_map_for(ref).inject([]) do |list, entry| + next list unless @page_class.valid_page_name?(entry.name) + sha = ref_map[ref] + list << entry.page(self, @repo.commit(sha)) end - list end # Determine if a given page path is scheduled to be deleted in the next From 646c8e21b263de2c3b894872ed1af1d3bb59fff7 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 17:52:20 -0700 Subject: [PATCH 20/39] Add Wiki#size to efficiently count pages without loading them. --- HISTORY.md | 1 + lib/gollum/wiki.rb | 11 +++++++++++ test/test_wiki.rb | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 7d20d2f1..25a3c15f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,7 @@ * Added --irb option for the gollum command. * Minor Enhancements * Support a `:gollum_path` Sinatra setting for `Precious::App` + * Add Wiki#size to efficiently count pages without loading them. * Bug Fixes * Increase minimum Sanitize version requirement to 1.1.0. 1.0.x versions of Sanitize require Hpricot instead of Nokogiri diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index 440e967d..25d984f0 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -210,6 +210,17 @@ module Gollum tree_list(treeish || 'master') end + # Fill an array with a list of pages. + # + # ref - A String ref that is either a commit SHA or references one. + # + # Returns a flat Array of Gollum::Page instances. + def size(ref = nil) + tree_map_for(ref || 'master').inject(0) do |num, entry| + num + (@page_class.valid_page_name?(entry.name) ? 1 : 0) + end + end + # Public: All of the versions that have touched the Page. # # options - The options Hash: diff --git a/test/test_wiki.rb b/test/test_wiki.rb index a7d065f1..3749e443 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -39,6 +39,10 @@ context "Wiki" do pages.map { |p| p.filename }.sort end + test "counts pages" do + assert_equal 4, @wiki.size + end + test "normalizes commit hash" do commit = {:message => 'abc'} assert_equal({:message => 'abc', :name => 'Anonymous', :email => 'anon@anon.com'}, From ba18cbebe84521157749061157b1d3e9a5f86749 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 17:56:03 -0700 Subject: [PATCH 21/39] more tree_map tests --- lib/gollum/blob_entry.rb | 4 ++++ test/test_wiki.rb | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/gollum/blob_entry.rb b/lib/gollum/blob_entry.rb index 14ef59b9..b224fc4a 100644 --- a/lib/gollum/blob_entry.rb +++ b/lib/gollum/blob_entry.rb @@ -43,6 +43,10 @@ module Gollum page end + def inspect + %(#) + end + # Normalizes a given directory name for searching through tree paths. # Ensures that a directory begins with a slash, or # diff --git a/test/test_wiki.rb b/test/test_wiki.rb index 3749e443..b5f52030 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -64,8 +64,13 @@ context "Wiki" do @wiki.tree_map_for 'master' assert_equal({"master"=>"60f12f4254f58801b9ee7db7bca5fa8aeefaa56b"}, @wiki.ref_map) - entry = @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'][0] - assert_equal 'Bilbo-Baggins.md', entry.path + map = @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'] + assert_equal 'Bilbo-Baggins.md', map[0].path + assert_equal '', map[0].dir + assert_equal map[0].path, map[0].name + assert_equal 'Mordor/Eye-Of-Sauron.md', map[3].path + assert_equal '/Mordor', map[3].dir + assert_equal 'Eye-Of-Sauron.md', map[3].name end test "#tree_map_for only caches tree for commit" do From 515f8610c44e10d1bdd864e186746c624cd8e44c Mon Sep 17 00:00:00 2001 From: Jon Frisby Date: Mon, 30 Aug 2010 12:18:57 +0800 Subject: [PATCH 22/39] Make --version not cough up a furball. Commit 8c625419b88b1297d89ccc3522dab7548c830848 moved the require down, which broke --version. --- bin/gollum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/gollum b/bin/gollum index 0ef6de8f..603c8dd5 100755 --- a/bin/gollum +++ b/bin/gollum @@ -15,6 +15,7 @@ HELP require 'optparse' require 'rubygems' +require 'gollum' exec = {} options = {} @@ -65,7 +66,6 @@ if options['irb'] end end - require 'gollum' begin wiki = Gollum::Wiki.new(gollum_path) if !wiki.exist? then raise Grit::InvalidGitRepositoryError end From 1f8a67598a6cbf97fee8af2bf20b907c24b4d442 Mon Sep 17 00:00:00 2001 From: Jon Frisby Date: Fri, 20 Aug 2010 18:54:26 +0800 Subject: [PATCH 23/39] Use Grit to determine committer instead of executing a sub-shell and calling the git CLI. --- lib/gollum/frontend/app.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb index f7c1f4c9..0d6be29b 100644 --- a/lib/gollum/frontend/app.rb +++ b/lib/gollum/frontend/app.rb @@ -58,7 +58,7 @@ module Precious format = params[:format].intern name = params[:rename] if params[:rename] - wiki.update_page(page, name, format, params[:content], commit_message) + wiki.update_page(page, name, format, params[:content], commit_message(wiki)) redirect "/#{Gollum::Page.cname name}" end @@ -70,7 +70,7 @@ module Precious format = params[:format].intern begin - wiki.write_page(name, format, params[:content], commit_message) + wiki.write_page(name, format, params[:content], commit_message(wiki)) redirect "/#{name}" rescue Gollum::DuplicatePageError => e @message = "Duplicate page: #{e.message}" @@ -148,10 +148,10 @@ module Precious end end - def commit_message + def commit_message(wiki) { :message => params[:message], - :name => `git config --get user.name `.strip, - :email => `git config --get user.email`.strip } + :name => wiki.repo.config['user.name'], + :email => wiki.repo.config['user.email'] } end end end From 6de9ddfd3f79a9cb320aab3c43b8e0a912107b2e Mon Sep 17 00:00:00 2001 From: Jon Frisby Date: Fri, 20 Aug 2010 18:55:05 +0800 Subject: [PATCH 24/39] Make an attempt at setting a proper mime-type when showing a file. Prevents things like having the browser show raw binary data when you have a PDF in your repo. --- lib/gollum/frontend/app.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb index 0d6be29b..bdc9f1e4 100644 --- a/lib/gollum/frontend/app.rb +++ b/lib/gollum/frontend/app.rb @@ -141,6 +141,7 @@ module Precious @content = page.formatted_data mustache :page elsif file = wiki.file(name) + content_type MIME::Types.type_for(name).to_s file.raw_data else @name = name From bf37f44970e89f92c7a9dab3fa19be4e13fa7078 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 18:09:14 -0700 Subject: [PATCH 25/39] pull default name/email for commits from wiki repo's git config --- lib/gollum/frontend/app.rb | 10 ++++------ lib/gollum/wiki.rb | 16 ++++++++++++++-- test/test_wiki.rb | 6 ++++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb index bdc9f1e4..0c88a8f0 100644 --- a/lib/gollum/frontend/app.rb +++ b/lib/gollum/frontend/app.rb @@ -58,7 +58,7 @@ module Precious format = params[:format].intern name = params[:rename] if params[:rename] - wiki.update_page(page, name, format, params[:content], commit_message(wiki)) + wiki.update_page(page, name, format, params[:content], commit_message) redirect "/#{Gollum::Page.cname name}" end @@ -70,7 +70,7 @@ module Precious format = params[:format].intern begin - wiki.write_page(name, format, params[:content], commit_message(wiki)) + wiki.write_page(name, format, params[:content], commit_message) redirect "/#{name}" rescue Gollum::DuplicatePageError => e @message = "Duplicate page: #{e.message}" @@ -149,10 +149,8 @@ module Precious end end - def commit_message(wiki) - { :message => params[:message], - :name => wiki.repo.config['user.name'], - :email => wiki.repo.config['user.email'] } + def commit_message + { :message => params[:message] } end end end diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index c84650cb..4770bec3 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -441,11 +441,23 @@ module Gollum # # Returns the commit Hash def normalize_commit(commit = {}) - commit[:name] = self.class.default_committer_name if commit[:name].to_s.empty? - commit[:email] = self.class.default_committer_email if commit[:email].to_s.empty? + commit[:name] = default_committer_name if commit[:name].to_s.empty? + commit[:email] = default_committer_email if commit[:email].to_s.empty? commit end + # Gets the default name for commits. + def default_committer_name + @default_committer_name ||= \ + @repo.config['user.name'] || self.class.default_committer_name + end + + # Gets the default email for commits. + def default_committer_email + @default_committer_email ||= \ + @repo.config['user.email'] || self.class.default_committer_email + 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. # diff --git a/test/test_wiki.rb b/test/test_wiki.rb index 004e48b8..51cd287b 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -45,12 +45,14 @@ context "Wiki" do test "normalizes commit hash" do commit = {:message => 'abc'} - assert_equal({:message => 'abc', :name => 'Anonymous', :email => 'anon@anon.com'}, + name = @wiki.repo.config['user.name'] + email = @wiki.repo.config['user.email'] + assert_equal({:message => 'abc', :name => name, :email => email}, @wiki.normalize_commit(commit.dup)) commit[:name] = 'bob' commit[:email] = '' - assert_equal({:message => 'abc', :name => 'bob', :email => 'anon@anon.com'}, + assert_equal({:message => 'abc', :name => 'bob', :email => email}, @wiki.normalize_commit(commit.dup)) commit[:email] = 'foo@bar.com' From e0d234c255afcb438801d18a0fade654af1f48a2 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 18:25:48 -0700 Subject: [PATCH 26/39] use grit to get the file's mime type, as suggested. http://github.com/github/gollum/commit/6de9ddfd3f79a9cb320aab3c43b8e0a912107b2e#commitcomment-137656 --- HISTORY.md | 1 + lib/gollum/file.rb | 5 +++++ lib/gollum/frontend/app.rb | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 37752ff0..29a7344d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,7 @@ * Minor Enhancements * Support a `:gollum_path` Sinatra setting for `Precious::App` * Add Wiki#size to efficiently count pages without loading them. + * Add the correct content type when serving files from the frontend. * Bug Fixes * Increase minimum Sanitize version requirement to 1.1.0. 1.0.x versions of Sanitize require Hpricot instead of Nokogiri diff --git a/lib/gollum/file.rb b/lib/gollum/file.rb index 0f1f58fd..8e7c33d3 100644 --- a/lib/gollum/file.rb +++ b/lib/gollum/file.rb @@ -33,6 +33,11 @@ module Gollum # Public: The String path of the file. attr_reader :path + # Public: The String mime type of the file. + def mime_type + @blob.mime_type + end + ######################################################################### # # Internal Methods diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb index 0c88a8f0..31bbaf5c 100644 --- a/lib/gollum/frontend/app.rb +++ b/lib/gollum/frontend/app.rb @@ -141,7 +141,7 @@ module Precious @content = page.formatted_data mustache :page elsif file = wiki.file(name) - content_type MIME::Types.type_for(name).to_s + content_type file.mime_type file.raw_data else @name = name From 7c70174725195f23aa8e57023673ddbca8b615a1 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 30 Aug 2010 18:50:02 -0700 Subject: [PATCH 27/39] handle invalid options --- bin/gollum | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bin/gollum b/bin/gollum index 603c8dd5..4e257208 100755 --- a/bin/gollum +++ b/bin/gollum @@ -37,7 +37,13 @@ opts = OptionParser.new do |opts| end # Read command line options into `options` hash -opts.parse! +begin + opts.parse! +rescue OptionParser::InvalidOption + puts "gollum: #{$!.message}" + puts "gollum: try 'gollum --help' for more information" + exit +end gollum_path = ARGV[0] || Dir.pwd From 5fcb5d971a53258ab4768dc0ac487ed83db58bf0 Mon Sep 17 00:00:00 2001 From: Paul Baumgart Date: Wed, 1 Sep 2010 22:02:19 -0700 Subject: [PATCH 28/39] Add support for RFC 1738 special characters in page names. Escape all links and redirects to support this. Some changes to app.rb necessary for correct routing by Sinatra. --- lib/gollum/frontend/app.rb | 19 ++++++++++--------- .../frontend/templates/compare.mustache | 2 +- lib/gollum/frontend/templates/create.mustache | 2 +- lib/gollum/frontend/templates/edit.mustache | 4 ++-- .../frontend/templates/history.mustache | 6 +++--- lib/gollum/frontend/templates/page.mustache | 6 +++--- lib/gollum/frontend/views/layout.rb | 6 ++++++ lib/gollum/markup.rb | 5 +++-- 8 files changed, 29 insertions(+), 21 deletions(-) diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb index 31bbaf5c..81a7fe5b 100644 --- a/lib/gollum/frontend/app.rb +++ b/lib/gollum/frontend/app.rb @@ -1,3 +1,4 @@ +require 'cgi' require 'sinatra' require 'gollum' require 'mustache/sinatra' @@ -39,8 +40,8 @@ module Precious show_page_or_file('Home') end - get '/edit/:name' do - @name = params[:name] + get '/edit/*' do + @name = params[:splat].first wiki = Gollum::Wiki.new(settings.gollum_path) if page = wiki.page(@name) @page = page @@ -51,8 +52,8 @@ module Precious end end - post '/edit/:name' do - name = params[:name] + post '/edit/*' do + name = params[:splat].first wiki = Gollum::Wiki.new(settings.gollum_path) page = wiki.page(name) format = params[:format].intern @@ -60,10 +61,10 @@ module Precious wiki.update_page(page, name, format, params[:content], commit_message) - redirect "/#{Gollum::Page.cname name}" + redirect "/#{CGI.escape(Gollum::Page.cname(name))}" end - post '/create/:name' do + post '/create/*' do name = params[:page] wiki = Gollum::Wiki.new(settings.gollum_path) @@ -71,7 +72,7 @@ module Precious begin wiki.write_page(name, format, params[:content], commit_message) - redirect "/#{name}" + redirect "/#{CGI.escape(name)}" rescue Gollum::DuplicatePageError => e @message = "Duplicate page: #{e.message}" mustache :error @@ -97,10 +98,10 @@ module Precious post '/compare/:name' do @versions = params[:versions] || [] if @versions.size < 2 - redirect "/history/#{params[:name]}" + redirect "/history/#{CGI.escape(params[:name])}" else redirect "/compare/%s/%s...%s" % [ - params[:name], + CGI.escape(params[:name]), @versions.last, @versions.first] end diff --git a/lib/gollum/frontend/templates/compare.mustache b/lib/gollum/frontend/templates/compare.mustache index 3a99fbd2..5f7f99ae 100644 --- a/lib/gollum/frontend/templates/compare.mustache +++ b/lib/gollum/frontend/templates/compare.mustache @@ -1,7 +1,7 @@

{{title}}: {{before}} → {{after}}

diff --git a/lib/gollum/frontend/templates/create.mustache b/lib/gollum/frontend/templates/create.mustache index 969f2512..146d43c7 100644 --- a/lib/gollum/frontend/templates/create.mustache +++ b/lib/gollum/frontend/templates/create.mustache @@ -2,7 +2,7 @@ « Home

{{title}}

-
+