Skip to content

Commit

Permalink
Merge pull request gollum#166 from arr2036/mediawiki_compat
Browse files Browse the repository at this point in the history
Gollum doesn't play nice with un-canonicalized filenames, and breaks offsite links when replacing mediawiki
  • Loading branch information
atmos committed Apr 10, 2012
2 parents db477a0 + 96bb1e7 commit aa36443
Show file tree
Hide file tree
Showing 19 changed files with 202 additions and 34 deletions.
5 changes: 3 additions & 2 deletions lib/gollum/committer.rb
Expand Up @@ -73,7 +73,7 @@ def parents
#
# dir - The String subdirectory of the Gollum::Page without any
# prefix or suffix slashes (e.g. "foo/bar").
# name - The String Gollum::Page name.
# name - The String Gollum::Page filename_stripped.
# format - The Symbol Gollum::Page format.
# data - The String wiki data to store in the tree map.
# allow_same_ext - A Boolean determining if the tree map allows the same
Expand Down Expand Up @@ -111,7 +111,8 @@ def add_to_index(dir, name, format, data, allow_same_ext = false)
# is a working directory present.
#
# dir - The String directory in which the file lives.
# name - The String name of the page (may be in human format).
# name - The String name of the page or the stripped filename
# (should be pre-canonicalized if required).
# format - The Symbol format of the page.
#
# Returns nothing.
Expand Down
40 changes: 31 additions & 9 deletions lib/gollum/page.rb
Expand Up @@ -76,11 +76,20 @@ def self.format_for(filename)
end

# Reusable filter to turn a filename (without path) into a canonical name.
# Strips extension, converts spaces to dashes.
# Strips extension, converts dashes to spaces.
#
# Returns the filtered String.
def self.canonicalize_filename(filename)
filename.split('.')[0..-2].join('.').gsub('-', ' ')
strip_filename(filename).gsub('-', ' ')
end

# Reusable filter to strip extension and path from filename
#
# filename - The string path or filename to strip
#
# Returns the stripped String.
def self.strip_filename(filename)
::File.basename(filename, ::File.extname(filename))
end

# Public: Initialize a page.
Expand All @@ -100,6 +109,13 @@ def filename
@blob && @blob.name
end

# Public: The on-disk filename of the page with extension stripped.
#
# Returns the String name.
def filename_stripped
self.class.strip_filename(filename)
end

# Public: The canonical page name without extension, and dashes converted
# to spaces.
#
Expand Down Expand Up @@ -246,17 +262,22 @@ def historical?

# Convert a human page name into a canonical page name.
#
# name - The String human page name.
# name - The String human page name.
# char_white_sub - Substitution for whitespace
# char_other_sub - Substitution for other special chars
#
# Examples
#
# Page.cname("Bilbo Baggins")
# # => 'Bilbo-Baggins'
#
# Page.cname("Bilbo Baggins",'_')
# # => 'Bilbo_Baggins'
#
# Returns the String canonical name.
def self.cname(name)
name.respond_to?(:gsub) ?
name.gsub(%r{[ /<>]}, '-') :
def self.cname(name, char_white_sub = '-', char_other_sub = '-')
name.respond_to?(:gsub) ?
name.gsub(%r{\s},char_white_sub).gsub(%r{[/<>+]}, char_other_sub) :
''
end

Expand Down Expand Up @@ -370,10 +391,11 @@ def tree_path(treemap, tree)
# Returns a Boolean.
def page_match(name, filename)
if match = self.class.valid_filename?(filename)
Page.cname(name).downcase == Page.cname(match).downcase
else
false
@wiki.ws_subs.each do |sub|
return true if Page.cname(name).downcase == Page.cname(match, sub).downcase
end
end
false
end

# Loads a sub page. Sub page nanes (footers) are prefixed with
Expand Down
47 changes: 31 additions & 16 deletions lib/gollum/wiki.rb
Expand Up @@ -20,7 +20,10 @@ class << self

# Sets the default email for commits.
attr_accessor :default_committer_email


# Array of chars to substitute whitespace for when trying to locate file in git repo.
attr_accessor :default_ws_subs

# Sets sanitization options. Set to false to deactivate
# sanitization altogether.
attr_writer :sanitization
Expand Down Expand Up @@ -102,6 +105,8 @@ def history_sanitization
self.default_ref = 'master'
self.default_committer_name = 'Anonymous'
self.default_committer_email = 'anon@anon.com'

self.default_ws_subs = ['_','-']

# 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
Expand All @@ -119,6 +124,9 @@ def history_sanitization

# Gets the String directory in which all page files reside.
attr_reader :page_file_dir

# Gets the Array of chars to sub for ws in filenames.
attr_reader :ws_subs

# Public: Initialize a new Gollum Repo.
#
Expand All @@ -134,6 +142,7 @@ def history_sanitization
# :sanitization - An instance of Sanitization.
# :page_file_dir - String the directory in which all page files reside
# :ref - String the repository ref to retrieve pages from
# :ws_subs - Array of chars to sub for ws in filenames.
#
# Returns a fresh Gollum::Repo.
def initialize(path, options = {})
Expand All @@ -151,6 +160,8 @@ def initialize(path, options = {})
@repo = @access.repo
@ref = options[:ref] || self.class.default_ref
@sanitization = options[:sanitization] || self.class.sanitization
@ws_subs = options[:ws_subs] ||
self.class.default_ws_subs
@history_sanitization = options[:history_sanitization] ||
self.class.history_sanitization
end
Expand Down Expand Up @@ -228,12 +239,14 @@ def write_page(name, format, data, commit = {})
else
Committer.new(self, commit)
end

committer.add_to_index('', name, format, data)

filename = Gollum::Page.cname(name)

committer.add_to_index('', filename, format, data)

committer.after_commit do |index, sha|
@access.refresh
index.update_working_dir('', name, format)
index.update_working_dir('', filename, format)
end

multi_commit ? committer : committer.commit
Expand Down Expand Up @@ -265,7 +278,10 @@ def update_page(page, name, format, data, commit = {})
name ||= page.name
format ||= page.format
dir = ::File.dirname(page.path)
dir = '' if dir == '.'
dir = '' if dir == '.'
filename = (rename = page.name != name) ?
Gollum::Page.cname(name) : page.filename_stripped

multi_commit = false

committer = if obj = commit[:committer]
Expand All @@ -274,18 +290,18 @@ def update_page(page, name, format, data, commit = {})
else
Committer.new(self, commit)
end

if page.name == name && page.format == format
if !rename && page.format == format
committer.add(page.path, normalize(data))
else
committer.delete(page.path)
committer.add_to_index(dir, name, format, data, :allow_same_ext)
committer.add_to_index(dir, filename, format, data, :allow_same_ext)
end

committer.after_commit do |index, sha|
@access.refresh
index.update_working_dir(dir, page.name, page.format)
index.update_working_dir(dir, name, format)
index.update_working_dir(dir, page.filename_stripped, page.format)
index.update_working_dir(dir, filename, format)
end

multi_commit ? committer : committer.commit
Expand Down Expand Up @@ -324,7 +340,7 @@ def delete_page(page, commit)
dir = '' if dir == '.'

@access.refresh
index.update_working_dir(dir, page.name, page.format)
index.update_working_dir(dir, page.filename_stripped, page.format)
end

multi_commit ? committer : committer.commit
Expand Down Expand Up @@ -362,7 +378,7 @@ def revert_page(page, sha1, sha2 = nil, commit = {})

files = []
if page
files << [page.path, page.name, page.format]
files << [page.path, page.filename_stripped, page.format]
else
# Grit::Diff can't parse reverse diffs.... yet
patch.each_line do |line|
Expand Down Expand Up @@ -522,13 +538,12 @@ def normalize(data)

# Assemble a Page's filename from its name and format.
#
# name - The String name of the page (may be in human format).
# name - The String name of the page (should be pre-canonicalized).
# 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
name + '.' + @page_class.format_to_ext(format)
end

# Fill an array with a list of pages.
Expand Down
2 changes: 1 addition & 1 deletion test/examples/lotr.git/COMMIT_EDITMSG
@@ -1 +1 @@
add sidebars
Test out whitespace with Sam
1 change: 1 addition & 0 deletions test/examples/lotr.git/ORIG_HEAD
@@ -0,0 +1 @@
a8ad3c09dd842a3517085bfadd37718856dee813
Binary file modified test/examples/lotr.git/index
Binary file not shown.
1 change: 1 addition & 0 deletions test/examples/lotr.git/logs/HEAD
@@ -1,2 +1,3 @@
0000000000000000000000000000000000000000 60f12f4254f58801b9ee7db7bca5fa8aeefaa56b rick <technoweenie@gmail.com> 1291341857 -0800 clone: from /Users/rick/p/gollum/test/examples/lotr.git
60f12f4254f58801b9ee7db7bca5fa8aeefaa56b a8ad3c09dd842a3517085bfadd37718856dee813 rick <technoweenie@gmail.com> 1291341922 -0800 commit: add sidebars
a8ad3c09dd842a3517085bfadd37718856dee813 1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3 Arran Cudbard-Bell <a.cudbardb@freeradius.org> 1309107565 +0200 commit: Test out whitespace with Sam
1 change: 1 addition & 0 deletions test/examples/lotr.git/logs/refs/heads/master
@@ -1,2 +1,3 @@
0000000000000000000000000000000000000000 60f12f4254f58801b9ee7db7bca5fa8aeefaa56b rick <technoweenie@gmail.com> 1291341857 -0800 clone: from /Users/rick/p/gollum/test/examples/lotr.git
60f12f4254f58801b9ee7db7bca5fa8aeefaa56b a8ad3c09dd842a3517085bfadd37718856dee813 rick <technoweenie@gmail.com> 1291341922 -0800 commit: add sidebars
a8ad3c09dd842a3517085bfadd37718856dee813 1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3 Arran Cudbard-Bell <a.cudbardb@freeradius.org> 1309107565 +0200 commit: Test out whitespace with Sam
Binary file not shown.
@@ -0,0 +1,2 @@
x��KN�0 �a�9���Q�G�H#��p'vh��t�����,�ͯ�n� pS~]Z���` ��gK���q�X���]��X|�Y��c1Y����O ��$����1��k�|��C
wyz���|�]^ڏ��,�~���3��m�S�G�5��;��'����p�������}3|�j�K�Wo
Binary file not shown.
@@ -0,0 +1,4 @@
x�RMK1���b�
e���TPO��%�4;�6�Y�h-��;[mK�!���L�G�t�����)�c��H��]M�,�ǧ�p�(@�e�#�4��SP�>�
<v4ոG���'_�7<A[4o*�$����QG ���
�t�x�9��p��\�M,�ZUe ���B\����J��?��k��:[6&?D� �i/�6�n$q�8^�勜�Q�s��2ӉuömY�s�`Љ�6�6=m�;���EG��!���\Q˶��_Ve�IX�瘌�h�s�J��}T3Y�He�RW��5��SŘK���T�>���O����ʳSh�A
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion test/examples/lotr.git/refs/heads/master
@@ -1 +1 @@
a8ad3c09dd842a3517085bfadd37718856dee813
1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3
2 changes: 1 addition & 1 deletion test/test_committer.rb
Expand Up @@ -50,7 +50,7 @@
end

test "parents with default master ref" do
ref = 'a8ad3c09dd842a3517085bfadd37718856dee813'
ref = '1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3'
committer = Gollum::Committer.new(@wiki)
assert_equal ref, committer.parents.first.sha
end
Expand Down
4 changes: 2 additions & 2 deletions test/test_git_access.rb
Expand Up @@ -18,9 +18,9 @@
assert @access.ref_map.empty?
assert @access.tree_map.empty?
@access.tree 'master'
assert_equal({"master"=>"a8ad3c09dd842a3517085bfadd37718856dee813"}, @access.ref_map)
assert_equal({"master"=>"1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3"}, @access.ref_map)

map = @access.tree_map['a8ad3c09dd842a3517085bfadd37718856dee813']
map = @access.tree_map['1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3']
assert_equal 'Bilbo-Baggins.md', map[0].path
assert_equal '', map[0].dir
assert_equal map[0].path, map[0].name
Expand Down
20 changes: 20 additions & 0 deletions test/test_page.rb
Expand Up @@ -25,7 +25,27 @@
test "get existing page case insensitive" do
assert_equal @wiki.page('Bilbo Baggins').path, @wiki.page('bilbo baggins').path
end

test "get existing page with hyphen" do
assert_equal @wiki.page('Bilbo Baggins').path, @wiki.page('Bilbo-Baggins').path
end

test "get existing page with underscore" do
assert_nil @wiki.page('Bilbo_Baggins')
end

test "get existing page where filename contains whitespace, with hypen" do
assert_equal @wiki.page('Samwise Gamgee').path, @wiki.page('Samwise-Gamgee').path
end

test "get existing page where filename contains whitespace, with underscore" do
assert_equal @wiki.page('Samwise Gamgee').path, @wiki.page('Samwise_Gamgee').path
end

test "get existing page where filename contains whitespace, with whitespace" do
assert_equal @wiki.page('Samwise Gamgee').path, @wiki.page('Samwise Gamgee').path
end

test "get nested page" do
page = @wiki.page('Eye Of Sauron')
assert_equal 'Mordor/Eye-Of-Sauron.md', page.path
Expand Down

0 comments on commit aa36443

Please sign in to comment.