From e2a4514be56b7d8a18c692323734d47a92260c07 Mon Sep 17 00:00:00 2001 From: rick Date: Thu, 13 Jan 2011 15:50:35 -0800 Subject: [PATCH] add the ability to revert whole commits that touch multiple files --- HISTORY.md | 5 ++-- lib/gollum/page.rb | 59 ++++++++++++++++++++++++---------------- lib/gollum/wiki.rb | 49 +++++++++++++++++++++++++++++---- test/test_page_revert.rb | 17 ++++++++++-- 4 files changed, 96 insertions(+), 34 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index e4f977dc..ba09e875 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,12 +2,13 @@ * Major Enhancements * Add Page sidebars, similar to Page footers. + * Add the ability to revert commits to the wiki. * Minor Enhancements - * Add `:sanitization` and `:history_sanitization` options for customizing + * Add `:sanitization` and `:history_sanitization` options for customizing how `Sanitize.clean` modifies formatted wiki content. * Add `--config` option for the command line, to specify a ruby file that is run during startup. - * Provide access to a parsed Nokogiri::DocumentFragment during markup + * Provide access to a parsed Nokogiri::DocumentFragment during markup rendering for added customization. * Bug Fixes * Use `@wiki.page_class` in Gollum::Markup where appropriate (#63). diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index faa5f1a1..61d04484 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -41,6 +41,40 @@ module Gollum filename =~ /^_/ ? false : match end + # Public: The format of a given filename. + # + # filename - The String filename. + # + # Returns the Symbol format of the page. One of: + # [ :markdown | :textile | :rdoc | :org | :rest | :asciidoc | :pod | + # :roff ] + def self.format_for(filename) + case filename.to_s + when /\.(md|mkdn?|mdown|markdown)$/i + :markdown + when /\.(textile)$/i + :textile + when /\.(rdoc)$/i + :rdoc + when /\.(org)$/i + :org + when /\.(creole)$/i + :creole + when /\.(re?st(\.txt)?)$/i + :rest + when /\.(asciidoc)$/i + :asciidoc + when /\.(pod)$/i + :pod + when /\.(\d)$/i + :roff + when /\.(media)?wiki$/i + :mediawiki + else + nil + end + end + # Reusable filter to turn a filename (without path) into a canonical name. # Strips extension, converts spaces to dashes. # @@ -143,30 +177,7 @@ module Gollum # [ :markdown | :textile | :rdoc | :org | :rest | :asciidoc | :pod | # :roff ] def format - case @blob.name - when /\.(md|mkdn?|mdown|markdown)$/i - :markdown - when /\.(textile)$/i - :textile - when /\.(rdoc)$/i - :rdoc - when /\.(org)$/i - :org - when /\.(creole)$/i - :creole - when /\.(re?st(\.txt)?)$/i - :rest - when /\.(asciidoc)$/i - :asciidoc - when /\.(pod)$/i - :pod - when /\.(\d)$/i - :roff - when /\.(media)?wiki$/i - :mediawiki - else - nil - end + self.class.format_for(@blob.name) end # Public: The current version of the page. diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index 7840c1c1..c94973eb 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -257,7 +257,7 @@ module Gollum sha1 end - # Public: Reverts a reverse diff for a given page. If only 1 SHA is given, + # Public: Applies a reverse diff for a given page. If only 1 SHA is given, # the reverse diff will be taken from its parent (^SHA...SHA). If two SHAs # are given, the reverse diff is taken from SHA1...SHA2. # @@ -286,14 +286,53 @@ module Gollum index = nil sha1 = commit_index(commit) { |i| index = i } - dir = ::File.dirname(page.path) - dir = '' if dir == '.' - @access.refresh - update_working_dir(index, dir, page.name, page.format) + + files = [] + if page + files << [page.path, page.name, page.format] + else + # Grit::Diff can't parse reverse diffs.... yet + lines = patch.split("\n") + while line = lines.shift + if line =~ %r{^diff --git b/.+? a/(.+)$} + path = $1 + ext = ::File.extname(path) + name = ::File.basename(path, ext) + if format = ::Gollum::Page.format_for(ext) + files << [path, name, format] + end + end + end + end + + files.each do |(path, name, format)| + dir = ::File.dirname(path) + dir = '' if dir == '.' + update_working_dir(index, dir, name, format) + end + sha1 end + # Public: Applies a reverse diff to the repo. If only 1 SHA is given, + # the reverse diff will be taken from its parent (^SHA...SHA). If two SHAs + # are given, the reverse diff is taken from SHA1...SHA2. + # + # sha1 - String SHA1 of the earlier parent if two SHAs are given, + # or the child. + # sha2 - Optional String SHA1 of the child. + # commit - The commit Hash details: + # :message - The String commit message. + # :name - The String author full name. + # :email - The String email address. + # + # Returns a String SHA1 of the new commit, or nil if the reverse diff does + # not apply. + def revert_commit(sha1, sha2 = nil, commit = {}) + revert_page(nil, sha1, sha2, commit) + end + # Public: Lists all pages for this wiki. # # treeish - The String commit ID or ref to find (default: master) diff --git a/test/test_page_revert.rb b/test/test_page_revert.rb index 9f96852f..6dcb4bde 100644 --- a/test/test_page_revert.rb +++ b/test/test_page_revert.rb @@ -12,19 +12,30 @@ context "Page Reverting" do end test "reverts single commit" do + page1 = @wiki.page("B") + sha = @wiki.revert_commit('7c45b5f16ff3bae2a0063191ef832701214d4df5') + page2 = @wiki.page("B") + assert_equal sha, page2.version.sha + assert_equal "INITIAL", body=page2.raw_data.strip + assert_equal body, File.read(File.join(@path, "B.md")).strip + end + + test "reverts single commit for a page" do page1 = @wiki.page('B') sha = @wiki.revert_page(page1, '7c45b5f16ff3bae2a0063191ef832701214d4df5') page2 = @wiki.page('B') assert_equal sha, page2.version.sha - assert_equal "INITIAL", page2.raw_data.strip + assert_equal "INITIAL", body=page2.raw_data.strip + assert_equal body, File.read(File.join(@path, "B.md")).strip end - test "reverts multiple commits" do + test "reverts multiple commits for a page" do page1 = @wiki.page('A') sha = @wiki.revert_page(page1, '302a5491a9a5ba12c7652ac831a44961afa312d2^', 'b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f') page2 = @wiki.page('A') assert_equal sha, page2.version.sha - assert_equal "INITIAL", page2.raw_data.strip + assert_equal "INITIAL", body=page2.raw_data.strip + assert_equal body, File.read(File.join(@path, "A.md")).strip end test "cannot revert conflicting commit" do