smeagol 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/smeagol/app.rb +41 -12
- data/lib/smeagol/cache.rb +25 -18
- data/lib/smeagol/templates/versions.mustache +36 -0
- data/lib/smeagol/version.rb +1 -1
- data/lib/smeagol/views/base.rb +80 -0
- data/lib/smeagol/views/page.rb +2 -52
- data/lib/smeagol/views/versions.rb +25 -0
- data/test/test_cache.rb +3 -3
- metadata +7 -4
data/lib/smeagol/app.rb
CHANGED
@@ -3,7 +3,9 @@ require 'rack/file'
|
|
3
3
|
require 'sinatra'
|
4
4
|
require 'mustache'
|
5
5
|
require 'tmpdir'
|
6
|
+
require 'smeagol/views/base'
|
6
7
|
require 'smeagol/views/page'
|
8
|
+
require 'smeagol/views/versions'
|
7
9
|
|
8
10
|
module Smeagol
|
9
11
|
class App < Sinatra::Base
|
@@ -41,9 +43,32 @@ module Smeagol
|
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
46
|
+
# Lists the tagged versions of the repo.
|
47
|
+
get '/versions' do
|
48
|
+
wiki = Smeagol::Wiki.new(repository.path)
|
49
|
+
Mustache.render(get_template('versions'), Smeagol::Views::Versions.new(wiki))
|
50
|
+
end
|
51
|
+
|
52
|
+
|
44
53
|
# All other resources go through Gollum.
|
45
54
|
get '/*' do
|
46
|
-
|
55
|
+
splat = params[:splat].first
|
56
|
+
|
57
|
+
# If the path starts with a version identifier, use it.
|
58
|
+
version = 'master'
|
59
|
+
tag_name = nil
|
60
|
+
if splat.index(/^v\d/)
|
61
|
+
repo = Grit::Repo.new(repository.path)
|
62
|
+
tag_name = splat.split('/').first
|
63
|
+
repo.tags.each do |tag|
|
64
|
+
if tag.name == tag_name
|
65
|
+
version = tag.commit.id
|
66
|
+
splat = splat.split('/')[1..-1].join('/')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
name = splat
|
47
72
|
name = "Home" if name == ""
|
48
73
|
name = name.gsub(/\/+$/, '')
|
49
74
|
name = File.sanitize_path(name)
|
@@ -54,18 +79,20 @@ module Smeagol
|
|
54
79
|
cache = Smeagol::Cache.new(wiki)
|
55
80
|
|
56
81
|
# First check the cache
|
57
|
-
if settings.cache_enabled && cache.cache_hit?(name)
|
58
|
-
cache.get_page(name)
|
82
|
+
if settings.cache_enabled && cache.cache_hit?(name, version)
|
83
|
+
cache.get_page(name, version)
|
59
84
|
# Then try to create the wiki page
|
60
|
-
elsif page = wiki.page(name)
|
61
|
-
content = Mustache.render(
|
62
|
-
cache.set_page(name, content) if settings.cache_enabled
|
85
|
+
elsif page = wiki.page(name, version)
|
86
|
+
content = Mustache.render(get_template('page'), Smeagol::Views::Page.new(page))
|
87
|
+
cache.set_page(name, page.version.id, content) if settings.cache_enabled
|
63
88
|
content
|
64
89
|
# If it is a directory, redirect to the index page
|
65
90
|
elsif File.directory?(file_path)
|
66
|
-
|
91
|
+
url = "/#{name}/index.html"
|
92
|
+
url = "/#{tag_name}#{url}" unless tag_name.nil?
|
93
|
+
redirect url
|
67
94
|
# If it is not a wiki page then try to find the file
|
68
|
-
elsif file = wiki.file(name)
|
95
|
+
elsif file = wiki.file(name, version)
|
69
96
|
content_type get_mime_type(name)
|
70
97
|
file.raw_data
|
71
98
|
# Otherwise return a 404 error
|
@@ -84,14 +111,16 @@ module Smeagol
|
|
84
111
|
private
|
85
112
|
# The Mustache template to use for page rendering.
|
86
113
|
#
|
114
|
+
# name - The name of the template to use.
|
115
|
+
#
|
87
116
|
# Returns the content of the page.mustache file in the root of the Gollum
|
88
117
|
# repository if it exists. Otherwise, it uses the default page.mustache file
|
89
118
|
# packaged with the Smeagol library.
|
90
|
-
def
|
91
|
-
if File.exists?("#{repository.path}
|
92
|
-
IO.read("#{repository.path}
|
119
|
+
def get_template(name)
|
120
|
+
if File.exists?("#{repository.path}/#{name}.mustache")
|
121
|
+
IO.read("#{repository.path}/#{name}.mustache")
|
93
122
|
else
|
94
|
-
IO.read(File.join(File.dirname(__FILE__),
|
123
|
+
IO.read(File.join(File.dirname(__FILE__), "templates/#{name}.mustache"))
|
95
124
|
end
|
96
125
|
end
|
97
126
|
|
data/lib/smeagol/cache.rb
CHANGED
@@ -26,34 +26,39 @@ module Smeagol
|
|
26
26
|
|
27
27
|
# Checks if a cache hit is found for a given gollum page.
|
28
28
|
#
|
29
|
-
# name
|
29
|
+
# name - The name of the page to check.
|
30
|
+
# version - The version of the page to check.
|
30
31
|
#
|
31
32
|
# Returns true if the page has been cached, otherwise returns false.
|
32
|
-
def cache_hit?(name)
|
33
|
-
page = wiki.page(name)
|
34
|
-
File.exists?(page_path(name)) unless page.nil?
|
33
|
+
def cache_hit?(name, version='master')
|
34
|
+
page = wiki.page(name, version)
|
35
|
+
File.exists?(page_path(name, version)) unless page.nil?
|
35
36
|
end
|
36
37
|
|
37
38
|
# Retrieves the content of the cached page.
|
38
39
|
#
|
39
|
-
# name
|
40
|
+
# name - The name of the wiki page.
|
41
|
+
# version - The version of the wiki page.
|
40
42
|
#
|
41
43
|
# Returns the contents of the HTML page if cached. Otherwise returns nil.
|
42
|
-
def get_page(name)
|
43
|
-
IO.read(page_path(name)) if cache_hit?(name)
|
44
|
+
def get_page(name, version='master')
|
45
|
+
IO.read(page_path(name, version)) if cache_hit?(name, version)
|
44
46
|
end
|
45
47
|
|
46
48
|
# Sets the cached content for a page.
|
47
49
|
#
|
48
50
|
# name - The name of the wiki page.
|
51
|
+
# version - The version of the page.
|
49
52
|
# content - The content to cache.
|
50
53
|
#
|
51
54
|
# Returns nothing.
|
52
|
-
def set_page(name, content)
|
53
|
-
page
|
55
|
+
def set_page(name, version, content)
|
56
|
+
p "set page: #{name} : #{version.class}"
|
57
|
+
page = wiki.page(name, version)
|
54
58
|
if !page.nil?
|
55
|
-
|
56
|
-
File.
|
59
|
+
path = page_path(name, version)
|
60
|
+
FileUtils.mkdir_p(File.dirname(path))
|
61
|
+
File.open(path, 'w') do |f|
|
57
62
|
f.write(content)
|
58
63
|
end
|
59
64
|
end
|
@@ -62,22 +67,24 @@ module Smeagol
|
|
62
67
|
# Removes the cached content for a page.
|
63
68
|
#
|
64
69
|
# name - The name of the wiki page.
|
70
|
+
# version - The version of the page.
|
65
71
|
#
|
66
72
|
# Returns nothing.
|
67
|
-
def remove_page(name)
|
68
|
-
page = wiki.page(name)
|
69
|
-
File.delete(page_path(name)) if !page.nil? && File.exists?(page_path(name))
|
73
|
+
def remove_page(name, version='master')
|
74
|
+
page = wiki.page(name, version)
|
75
|
+
File.delete(page_path(name, version)) if !page.nil? && File.exists?(page_path(name, version))
|
70
76
|
end
|
71
77
|
|
72
78
|
# Retrieves the path to the cache for a given page.
|
73
79
|
#
|
74
|
-
# name
|
80
|
+
# name - The name of the wiki page.
|
81
|
+
# version - The version of the page.
|
75
82
|
#
|
76
83
|
# Returns a file path to the cached wiki page.
|
77
|
-
def page_path(name)
|
78
|
-
page = wiki.page(name)
|
84
|
+
def page_path(name, version='master')
|
85
|
+
page = wiki.page(name, version)
|
79
86
|
if !page.nil?
|
80
|
-
"#{path}/#{page.path}/#{page.version}"
|
87
|
+
"#{path}/#{page.path}/#{page.version.id}"
|
81
88
|
end
|
82
89
|
end
|
83
90
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
5
|
+
<title>{{wiki_title}} - Versions</title>
|
6
|
+
<link rel="stylesheet" href="/smeagol/main.css" type="text/css"/>
|
7
|
+
|
8
|
+
<!--[if lt IE 9]>
|
9
|
+
<script src="/smeagol/html5.js"></script>
|
10
|
+
<![endif]-->
|
11
|
+
</head>
|
12
|
+
|
13
|
+
<body>
|
14
|
+
{{{ribbon_html}}}
|
15
|
+
|
16
|
+
<div id="container">
|
17
|
+
<header>
|
18
|
+
<h1>{{wiki_title}}</h1>
|
19
|
+
</header>
|
20
|
+
|
21
|
+
<nav>
|
22
|
+
{{{menu_html}}}
|
23
|
+
</nav>
|
24
|
+
|
25
|
+
<article>
|
26
|
+
<h1>Versions</h1>
|
27
|
+
<div id="content">
|
28
|
+
{{{content}}}
|
29
|
+
</div>
|
30
|
+
</article>
|
31
|
+
|
32
|
+
<footer>
|
33
|
+
</footer>
|
34
|
+
</div>
|
35
|
+
</body>
|
36
|
+
</html>
|
data/lib/smeagol/version.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Smeagol
|
2
|
+
module Views
|
3
|
+
class Base < ::Mustache
|
4
|
+
# Initializes a new mustache view template data object.
|
5
|
+
#
|
6
|
+
# wiki - The wiki that this view represents.
|
7
|
+
#
|
8
|
+
# Returns a new view object.
|
9
|
+
def initialize(wiki)
|
10
|
+
@wiki = wiki
|
11
|
+
end
|
12
|
+
|
13
|
+
# Public: The title of the wiki. This is set in the settings file.
|
14
|
+
def wiki_title
|
15
|
+
wiki.settings.title
|
16
|
+
end
|
17
|
+
|
18
|
+
# Public: The tagline for the wiki. This is set in the settings file.
|
19
|
+
def tagline
|
20
|
+
wiki.settings.tagline
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: The URL of the project source code. This is set in the settings
|
24
|
+
# file.
|
25
|
+
def source_url
|
26
|
+
wiki.settings.source_url
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: The HTML menu generated from the settings.yml file.
|
30
|
+
def menu_html
|
31
|
+
menu = wiki.settings.menu
|
32
|
+
if !menu.nil?
|
33
|
+
html = "<ul>\n"
|
34
|
+
menu.each do |item|
|
35
|
+
html << "<li><a href=\"#{item.href}\">#{item.title}</a></li>\n"
|
36
|
+
end
|
37
|
+
html << "</ul>\n"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: The HTML for the GitHub ribbon, if enabled. This can be set in
|
42
|
+
# the settings file as `ribbon`.
|
43
|
+
def ribbon_html
|
44
|
+
if !source_url.nil? && !wiki.settings.ribbon.nil?
|
45
|
+
name, pos = *wiki.settings.ribbon.split(' ')
|
46
|
+
pos ||= 'right'
|
47
|
+
|
48
|
+
html = "<a href=\"#{source_url}\">"
|
49
|
+
html << "<img style=\"position:absolute; top:0; #{pos}:0; border:0;\" src=\"#{ribbon_url(name, pos)}\" alt=\"Fork me on GitHub\"/>"
|
50
|
+
html << "</a>"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
##########################################################################
|
56
|
+
#
|
57
|
+
# Internal Methods
|
58
|
+
#
|
59
|
+
##########################################################################
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
# The Gollum::Page that this view represents.
|
64
|
+
attr_reader :wiki
|
65
|
+
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Generates the correct ribbon url
|
70
|
+
def ribbon_url(name, pos)
|
71
|
+
hexcolors = {'red' => 'aa0000', 'green' => '007200', 'darkblue' => '121621', 'orange' => 'ff7600', 'gray' => '6d6d6d', 'white' => 'ffffff'}
|
72
|
+
if hexcolor = hexcolors[name]
|
73
|
+
"http://s3.amazonaws.com/github/ribbons/forkme_#{pos}_#{name}_#{hexcolor}.png"
|
74
|
+
else
|
75
|
+
name
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/smeagol/views/page.rb
CHANGED
@@ -1,25 +1,16 @@
|
|
1
1
|
module Smeagol
|
2
2
|
module Views
|
3
|
-
class Page <
|
3
|
+
class Page < Base
|
4
4
|
# Initializes a new page template data object.
|
5
5
|
#
|
6
6
|
# page - The individual wiki page that this view represents.
|
7
7
|
#
|
8
8
|
# Returns a new page object.
|
9
9
|
def initialize(page)
|
10
|
+
super(page.wiki)
|
10
11
|
@page = page
|
11
12
|
end
|
12
13
|
|
13
|
-
# Public: The title of the wiki. This is set in the settings file.
|
14
|
-
def wiki_title
|
15
|
-
page.wiki.settings.title
|
16
|
-
end
|
17
|
-
|
18
|
-
# Public: The tagline for the wiki. This is set in the settings file.
|
19
|
-
def tagline
|
20
|
-
page.wiki.settings.tagline
|
21
|
-
end
|
22
|
-
|
23
14
|
# Public: The title of the page.
|
24
15
|
def page_title
|
25
16
|
page.title
|
@@ -40,41 +31,10 @@ module Smeagol
|
|
40
31
|
page.version.authored_date.strftime("%B %d, %Y")
|
41
32
|
end
|
42
33
|
|
43
|
-
# Public: The URL of the project source code. This is set in the settings
|
44
|
-
# file.
|
45
|
-
def source_url
|
46
|
-
page.wiki.settings.source_url
|
47
|
-
end
|
48
|
-
|
49
34
|
# Public: A flag stating that this is not the home page.
|
50
35
|
def not_home?
|
51
36
|
page.title != "Home"
|
52
37
|
end
|
53
|
-
|
54
|
-
# Public: The HTML menu generated from the settings.yml file.
|
55
|
-
def menu_html
|
56
|
-
menu = @page.wiki.settings.menu
|
57
|
-
if !menu.nil?
|
58
|
-
html = "<ul>\n"
|
59
|
-
menu.each do |item|
|
60
|
-
html << "<li><a href=\"#{item.href}\">#{item.title}</a></li>\n"
|
61
|
-
end
|
62
|
-
html << "</ul>\n"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Public: The HTML for the GitHub ribbon, if enabled. This can be set in
|
67
|
-
# the settings file as `ribbon`.
|
68
|
-
def ribbon_html
|
69
|
-
if !source_url.nil? && !page.wiki.settings.ribbon.nil?
|
70
|
-
name, pos = *page.wiki.settings.ribbon.split(' ')
|
71
|
-
pos ||= 'right'
|
72
|
-
|
73
|
-
html = "<a href=\"#{source_url}\">"
|
74
|
-
html << "<img style=\"position:absolute; top:0; #{pos}:0; border:0;\" src=\"#{ribbon_url(name, pos)}\" alt=\"Fork me on GitHub\"/>"
|
75
|
-
html << "</a>"
|
76
|
-
end
|
77
|
-
end
|
78
38
|
|
79
39
|
|
80
40
|
##########################################################################
|
@@ -87,16 +47,6 @@ module Smeagol
|
|
87
47
|
|
88
48
|
# The Gollum::Page that this view represents.
|
89
49
|
attr_reader :page
|
90
|
-
|
91
|
-
# Generates the correct ribbon url
|
92
|
-
def ribbon_url(name, pos)
|
93
|
-
hexcolors = {'red' => 'aa0000', 'green' => '007200', 'darkblue' => '121621', 'orange' => 'ff7600', 'gray' => '6d6d6d', 'white' => 'ffffff'}
|
94
|
-
if hexcolor = hexcolors[name]
|
95
|
-
"http://s3.amazonaws.com/github/ribbons/forkme_#{pos}_#{name}_#{hexcolor}.png"
|
96
|
-
else
|
97
|
-
name
|
98
|
-
end
|
99
|
-
end
|
100
50
|
end
|
101
51
|
end
|
102
52
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Smeagol
|
2
|
+
module Views
|
3
|
+
class Versions < Base
|
4
|
+
# Public: The title of the wiki. This is set in the settings file.
|
5
|
+
def wiki_title
|
6
|
+
wiki.settings.title
|
7
|
+
end
|
8
|
+
|
9
|
+
# Public: The HTML formatted content of the page.
|
10
|
+
def content
|
11
|
+
html = "<a href=\"/\">Current</a><br/>"
|
12
|
+
wiki.repo.tags.each do |tag|
|
13
|
+
html << "<a href=\"/#{tag.name}\">#{tag.name}</a><br/>"
|
14
|
+
end
|
15
|
+
html
|
16
|
+
end
|
17
|
+
|
18
|
+
# Public: The URL of the project source code. This is set in the settings
|
19
|
+
# file.
|
20
|
+
def source_url
|
21
|
+
wiki.settings.source_url
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/test/test_cache.rb
CHANGED
@@ -9,7 +9,7 @@ class CacheTestCase < MiniTest::Unit::TestCase
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_should_show_cache_hit
|
12
|
-
@cache.set_page('Home', 'abc')
|
12
|
+
@cache.set_page('Home', 'master', 'abc')
|
13
13
|
assert @cache.cache_hit?('Home')
|
14
14
|
end
|
15
15
|
|
@@ -22,12 +22,12 @@ class CacheTestCase < MiniTest::Unit::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_should_cache_page
|
25
|
-
@cache.set_page('Home', 'abc')
|
25
|
+
@cache.set_page('Home', 'master', 'abc')
|
26
26
|
assert_equal 'abc', @cache.get_page('Home')
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_should_remove_cache
|
30
|
-
@cache.set_page('Home', 'abc')
|
30
|
+
@cache.set_page('Home', 'master', 'abc')
|
31
31
|
@cache.remove_page('Home')
|
32
32
|
assert !@cache.cache_hit?('Home')
|
33
33
|
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ben Johnson
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-12 00:00:00 -06:00
|
19
19
|
default_executable: smeagol
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -229,8 +229,11 @@ files:
|
|
229
229
|
- lib/smeagol/public/smeagol/main.css
|
230
230
|
- lib/smeagol/public/smeagol/pygment.css
|
231
231
|
- lib/smeagol/templates/page.mustache
|
232
|
+
- lib/smeagol/templates/versions.mustache
|
232
233
|
- lib/smeagol/version.rb
|
234
|
+
- lib/smeagol/views/base.rb
|
233
235
|
- lib/smeagol/views/page.rb
|
236
|
+
- lib/smeagol/views/versions.rb
|
234
237
|
- lib/smeagol/wiki.rb
|
235
238
|
- lib/smeagol.rb
|
236
239
|
- README.md
|