diff --git a/README.md b/README.md index d8e55e8f..bcdc39c8 100644 --- a/README.md +++ b/README.md @@ -297,10 +297,11 @@ exist) and commit the change. The file will be written at the repo root. wiki.write_page('Page Name', :markdown, 'Page contents', commit) -Update an existing page (keeps the same name, format, and directory location). +Update an existing page. If the format is different than the page's current +format, the file name will be changed to reflect the new format. page = wiki.page('Page Name') - wiki.update_page(page, 'Page contents', commit) + wiki.update_page(page, page.format, 'Page contents', commit) To delete a page and commit the change: diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb index 33eb015e..4b3b0d70 100644 --- a/lib/gollum/frontend/app.rb +++ b/lib/gollum/frontend/app.rb @@ -54,8 +54,10 @@ module Precious name = params[:name] wiki = Gollum::Wiki.new($path) page = wiki.page(name) + format = params[:format].intern + + wiki.update_page(page, format, params[:content], commit_message) - wiki.update_page(page, params[:content], commit_message) redirect "/#{name}" end diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index 86a414fd..1017bc9a 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -25,7 +25,7 @@ module Gollum @blob = nil end - # Public: The on-disk filename of the page. + # Public: The on-disk filename of the page including extension. # # Returns the String name. def name diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index 07ec00f4..15d42313 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -6,10 +6,10 @@ module Gollum # Sets the page class used by all instances of this Wiki. attr_writer :page_class - # Sets the file class used by all instances of this Wiki. + # Sets the file class used by all instances of this Wiki. attr_writer :file_class - # Gets the page class used by all instances of this Wiki. + # Gets the page class used by all instances of this Wiki. # Default: Gollum::Page. def page_class @page_class || @@ -20,7 +20,7 @@ module Gollum end end - # Gets the file class used by all instances of this Wiki. + # Gets the file class used by all instances of this Wiki. # Default: Gollum::File. def file_class @file_class || @@ -31,7 +31,7 @@ module Gollum end end end - + # The String base path to prefix to internal links. For example, when set # to "/wiki", the page "Hobbit" will be linked as "/wiki/Hobbit". Defaults @@ -40,7 +40,7 @@ module Gollum # Public: Initialize a new Gollum Repo. # - # repo - The String path to the Git repository that holds the Gollum + # repo - The String path to the Git repository that holds the Gollum # site. # options - Optional Hash: # :page_class - The page Class. Default: Gollum::Page @@ -85,6 +85,7 @@ module Gollum # Public: Write a new version of a page to the Gollum repo root. # # name - The String name of the page. + # format - The Symbol format of the page. # data - The new String contents of the page. # commit - The commit Hash details: # :message - The String commit message. @@ -93,14 +94,12 @@ module Gollum # # Returns the String SHA1 of the newly written version. def write_page(name, format, data, commit = {}) - ext = @page_class.format_to_ext(format) - path = @page_class.cname(name) + '.' + ext - map = {} if pcommit = @repo.commit('master') map = tree_map(pcommit.tree) end - map[path] = normalize(data) + + map = add_to_tree_map(map, '', name, format, data) index = tree_map_to_index(map) parents = pcommit ? [pcommit] : [] @@ -109,9 +108,12 @@ module Gollum end # Public: Update an existing page with new content. The location of the - # page inside the repository and the page's format will not change. + # page inside the repository will not change. If the given format is + # different than the current format of the page, the filename will be + # changed to reflect the new format. # # page - The Gollum::Page to update. + # format - The Symbol format of the page. # data - The new String contents of the page. # commit - The commit Hash details: # :message - The String commit message. @@ -119,11 +121,22 @@ module Gollum # :email - The String email address. # # Returns the String SHA1 of the newly written version. - def update_page(page, data, commit = {}) + def update_page(page, format, data, commit = {}) pcommit = @repo.commit('master') map = tree_map(pcommit.tree) - index = tree_map_to_index(map) - index.add(page.path, normalize(data)) + + index = nil + + if page.format == format + index = tree_map_to_index(map) + index.add(page.path, normalize(data)) + else + map = delete_from_tree_map(map, page.path) + dir = ::File.dirname(page.path) + name = page.name.split('.')[0..-2].join('.') + map = add_to_tree_map(map, dir, name, format, data) + index = tree_map_to_index(map) + end actor = Grit::Actor.new(commit[:name], commit[:email]) index.commit(commit[:message], [pcommit], actor) @@ -142,14 +155,7 @@ module Gollum pcommit = @repo.commit('master') map = tree_map(pcommit.tree) - parts = page.path.split('/') - name = parts.pop - container = nil - parts.each do |part| - container = map[part] - end - (container || map).delete(name) - + map = delete_from_tree_map(map, page.path) index = tree_map_to_index(map) actor = Grit::Actor.new(commit[:name], commit[:email]) @@ -263,5 +269,36 @@ module Gollum end index end + + def add_to_tree_map(map, dir, name, format, data) + ext = @page_class.format_to_ext(format) + path = @page_class.cname(name) + '.' + ext + + parts = dir.split('/') + container = nil + parts.each do |part| + container = map[part] + end + + (container || map)[path] = normalize(data) + map + end + + # Delete an entry from a tree map. + # + # map - The Hash tree map of the repository. + # path - The String path of the file to delete. + # + # Returns the modified Hash tree map. + def delete_from_tree_map(map, path) + parts = path.split('/') + name = parts.pop + container = nil + parts.each do |part| + container = map[part] + end + (container || map).delete(name) + map + end end end \ No newline at end of file diff --git a/test/test_wiki.rb b/test/test_wiki.rb index 2bb913de..2eda249f 100644 --- a/test/test_wiki.rb +++ b/test/test_wiki.rb @@ -74,7 +74,7 @@ context "Wiki page writing" do @wiki.write_page("Gollum", :markdown, "# Gollum", commit) page = @wiki.page("Gollum") - @wiki.update_page(page, "# Gollum2", commit) + @wiki.update_page(page, :markdown, "# Gollum2", commit) assert_equal 2, @wiki.repo.commits.size assert_equal "# Gollum2", @wiki.page("Gollum").raw_data @@ -83,6 +83,41 @@ context "Wiki page writing" do assert_equal "tom@github.com", @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) + + assert_equal :markdown, @wiki.page("Gollum").format + + page = @wiki.page("Gollum") + @wiki.update_page(page, :textile, "h1. Gollum", commit) + + assert_equal 2, @wiki.repo.commits.size + assert_equal :textile, @wiki.page("Gollum").format + assert_equal "h1. Gollum", @wiki.page("Gollum").raw_data + 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, :textile, "h1. Gollum", commit) + + page = @wiki.page("Gollum") + assert_equal "lotr/Gollum.textile", page.path + assert_equal :textile, page.format + assert_equal "h1. Gollum", page.raw_data + end + test "delete root page" do commit = { :message => "Gollum page", :name => "Tom Preston-Werner",