read-only-gollum 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/HISTORY.md +102 -0
- data/Home.md +3 -0
- data/LICENSE +21 -0
- data/README.md +477 -0
- data/Rakefile +142 -0
- data/bin/read-only-gollum +126 -0
- data/docs/sanitization.md +32 -0
- data/lib/gollum.rb +41 -0
- data/lib/gollum/blob_entry.rb +78 -0
- data/lib/gollum/committer.rb +218 -0
- data/lib/gollum/file.rb +64 -0
- data/lib/gollum/frontend/app.rb +225 -0
- data/lib/gollum/frontend/public/css/dialog.css +141 -0
- data/lib/gollum/frontend/public/css/editor.css +537 -0
- data/lib/gollum/frontend/public/css/gollum.css +660 -0
- data/lib/gollum/frontend/public/css/ie7.css +69 -0
- data/lib/gollum/frontend/public/css/template.css +381 -0
- data/lib/gollum/frontend/public/images/icon-sprite.png +0 -0
- data/lib/gollum/frontend/public/javascript/editor/gollum.editor.js +1096 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/asciidoc.js +167 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/creole.js +104 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/markdown.js +211 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/org.js +173 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/pod.js +111 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/rdoc.js +74 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/textile.js +175 -0
- data/lib/gollum/frontend/public/javascript/gollum.dialog.js +263 -0
- data/lib/gollum/frontend/public/javascript/gollum.js +161 -0
- data/lib/gollum/frontend/public/javascript/gollum.placeholder.js +54 -0
- data/lib/gollum/frontend/public/javascript/jquery.color.js +123 -0
- data/lib/gollum/frontend/public/javascript/jquery.js +7179 -0
- data/lib/gollum/frontend/templates/compare.mustache +38 -0
- data/lib/gollum/frontend/templates/create.mustache +17 -0
- data/lib/gollum/frontend/templates/edit.mustache +17 -0
- data/lib/gollum/frontend/templates/editor.mustache +116 -0
- data/lib/gollum/frontend/templates/error.mustache +8 -0
- data/lib/gollum/frontend/templates/history.mustache +58 -0
- data/lib/gollum/frontend/templates/layout.mustache +28 -0
- data/lib/gollum/frontend/templates/page.mustache +37 -0
- data/lib/gollum/frontend/templates/pages.mustache +35 -0
- data/lib/gollum/frontend/templates/search.mustache +36 -0
- data/lib/gollum/frontend/templates/searchbar.mustache +10 -0
- data/lib/gollum/frontend/views/compare.rb +94 -0
- data/lib/gollum/frontend/views/create.rb +48 -0
- data/lib/gollum/frontend/views/edit.rb +52 -0
- data/lib/gollum/frontend/views/editable.rb +13 -0
- data/lib/gollum/frontend/views/error.rb +7 -0
- data/lib/gollum/frontend/views/history.rb +44 -0
- data/lib/gollum/frontend/views/layout.rb +20 -0
- data/lib/gollum/frontend/views/page.rb +57 -0
- data/lib/gollum/frontend/views/pages.rb +19 -0
- data/lib/gollum/frontend/views/search.rb +20 -0
- data/lib/gollum/git_access.rb +248 -0
- data/lib/gollum/markup.rb +489 -0
- data/lib/gollum/page.rb +430 -0
- data/lib/gollum/pagination.rb +61 -0
- data/lib/gollum/sanitization.rb +174 -0
- data/lib/gollum/tex.rb +89 -0
- data/lib/gollum/web_sequence_diagram.rb +43 -0
- data/lib/gollum/wiki.rb +636 -0
- data/read-only-gollum.gemspec +224 -0
- data/templates/formatting.html +92 -0
- data/test/examples/empty.git/HEAD +1 -0
- data/test/examples/empty.git/config +5 -0
- data/test/examples/empty.git/description +1 -0
- data/test/examples/empty.git/hooks/applypatch-msg.sample +15 -0
- data/test/examples/empty.git/hooks/commit-msg.sample +24 -0
- data/test/examples/empty.git/hooks/post-commit.sample +8 -0
- data/test/examples/empty.git/hooks/post-receive.sample +15 -0
- data/test/examples/empty.git/hooks/post-update.sample +8 -0
- data/test/examples/empty.git/hooks/pre-applypatch.sample +14 -0
- data/test/examples/empty.git/hooks/pre-commit.sample +46 -0
- data/test/examples/empty.git/hooks/pre-rebase.sample +169 -0
- data/test/examples/empty.git/hooks/prepare-commit-msg.sample +36 -0
- data/test/examples/empty.git/hooks/update.sample +128 -0
- data/test/examples/empty.git/info/exclude +6 -0
- data/test/examples/empty.git/objects/info/.gitkeep +0 -0
- data/test/examples/empty.git/objects/pack/.gitkeep +0 -0
- data/test/examples/empty.git/refs/heads/.gitkeep +0 -0
- data/test/examples/lotr.git/COMMIT_EDITMSG +1 -0
- data/test/examples/lotr.git/HEAD +1 -0
- data/test/examples/lotr.git/ORIG_HEAD +1 -0
- data/test/examples/lotr.git/config +12 -0
- data/test/examples/lotr.git/description +1 -0
- data/test/examples/lotr.git/index +0 -0
- data/test/examples/lotr.git/info/exclude +6 -0
- data/test/examples/lotr.git/logs/HEAD +3 -0
- data/test/examples/lotr.git/logs/refs/heads/master +3 -0
- data/test/examples/lotr.git/objects/06/131480411710c92a82fe2d1e76932c70feb2e5 +0 -0
- data/test/examples/lotr.git/objects/0a/de1e2916346d4c1f2fb63b863fd3c16808fe44 +0 -0
- data/test/examples/lotr.git/objects/0e/d8cbe0a25235bd867e65193c7d837c66b328ef +3 -0
- data/test/examples/lotr.git/objects/12/629d666c5e3178f82f533f543d61b53dc78c0b +0 -0
- data/test/examples/lotr.git/objects/1d/b89ebba7e2c14d93b94ff98cfa3708a4f0d4e3 +2 -0
- data/test/examples/lotr.git/objects/24/49c2681badfd3c189e8ed658dacffe8ba48fe5 +0 -0
- data/test/examples/lotr.git/objects/25/4bdc1ba27d8b8a794538a8522d9a2b56ec2dd9 +0 -0
- data/test/examples/lotr.git/objects/2c/b9156ad383914561a8502fc70f5a1d887e48ad +4 -0
- data/test/examples/lotr.git/objects/5d/cac289a8603188d2c5caf481dcba2985126aaa +0 -0
- data/test/examples/lotr.git/objects/60/f12f4254f58801b9ee7db7bca5fa8aeefaa56b +0 -0
- data/test/examples/lotr.git/objects/71/4323c104239440a5c66ab12a67ed07a83c404f +0 -0
- data/test/examples/lotr.git/objects/84/0ec5b1ba1320e8ec443f28f99566f615d5af10 +0 -0
- data/test/examples/lotr.git/objects/93/6b83ee0dd8837adb82511e40d5e4ebe59bb675 +0 -0
- data/test/examples/lotr.git/objects/94/523d7ae48aeba575099dd12926420d8fd0425d +2 -0
- data/test/examples/lotr.git/objects/96/97dc65e095658bbd1b8e8678e08881e86d32f1 +0 -0
- data/test/examples/lotr.git/objects/a3/1ca2a7c352c92531a8b99815d15843b259e814 +0 -0
- data/test/examples/lotr.git/objects/a6/59b3763b822dd97544621fd0beef162ea37b14 +4 -0
- data/test/examples/lotr.git/objects/a8/ad3c09dd842a3517085bfadd37718856dee813 +0 -0
- data/test/examples/lotr.git/objects/aa/b61fe89d56f8614c0a8151da34f939dcedfa68 +0 -0
- data/test/examples/lotr.git/objects/bc/4b5fc0ce2c2ba3acef6647e4f67256ee45ab60 +0 -0
- data/test/examples/lotr.git/objects/c3/b43e9f08966b088e7a0192e436b7a884542e05 +0 -0
- data/test/examples/lotr.git/objects/dc/596d6b2dd89ab05c66f4abd7d5eb706bc17f19 +0 -0
- data/test/examples/lotr.git/objects/ec/da3205bee14520aab5a7bb307392064b938e83 +0 -0
- data/test/examples/lotr.git/objects/f4/84ebb1f40f8eb20d1bcd8d1d71934d2b8ae961 +0 -0
- data/test/examples/lotr.git/objects/fa/e7ef5344202bba4129abdc13060d9297d99465 +3 -0
- data/test/examples/lotr.git/objects/info/packs +2 -0
- data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.idx +0 -0
- data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.pack +0 -0
- data/test/examples/lotr.git/packed-refs +2 -0
- data/test/examples/lotr.git/refs/heads/master +1 -0
- data/test/examples/lotr.git/refs/remotes/origin/HEAD +1 -0
- data/test/examples/page_file_dir.git/COMMIT_EDITMSG +1 -0
- data/test/examples/page_file_dir.git/HEAD +1 -0
- data/test/examples/page_file_dir.git/config +6 -0
- data/test/examples/page_file_dir.git/description +1 -0
- data/test/examples/page_file_dir.git/index +0 -0
- data/test/examples/page_file_dir.git/info/exclude +6 -0
- data/test/examples/page_file_dir.git/logs/HEAD +1 -0
- data/test/examples/page_file_dir.git/logs/refs/heads/master +1 -0
- data/test/examples/page_file_dir.git/objects/0c/7d27db1f575263efdcab3dc650f4502a2dbcbf +0 -0
- data/test/examples/page_file_dir.git/objects/22/b404803c966dd92865614d86ff22ca12e50c1e +0 -0
- data/test/examples/page_file_dir.git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 +0 -0
- data/test/examples/page_file_dir.git/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6 +0 -0
- data/test/examples/page_file_dir.git/objects/5b/43e14e0a15fb6f08feab1773d1c0991e9f71e2 +0 -0
- data/test/examples/page_file_dir.git/refs/heads/master +1 -0
- data/test/examples/revert.git/COMMIT_EDITMSG +1 -0
- data/test/examples/revert.git/HEAD +1 -0
- data/test/examples/revert.git/config +12 -0
- data/test/examples/revert.git/description +1 -0
- data/test/examples/revert.git/index +0 -0
- data/test/examples/revert.git/info/exclude +6 -0
- data/test/examples/revert.git/logs/HEAD +2 -0
- data/test/examples/revert.git/logs/refs/heads/master +2 -0
- data/test/examples/revert.git/objects/20/2ced67cea93c7b6bd2928aa1daef8d1d55a20d +0 -0
- data/test/examples/revert.git/objects/41/76394bfa11222363c66ce7e84b5f154095b6d9 +0 -0
- data/test/examples/revert.git/objects/6a/69f92020f5df77af6e8813ff1232493383b708 +0 -0
- data/test/examples/revert.git/objects/b4/785957bc986dc39c629de9fac9df46972c00fc +0 -0
- data/test/examples/revert.git/objects/f4/03b791119f8232b7cb0ba455c624ac6435f433 +0 -0
- data/test/examples/revert.git/objects/info/packs +2 -0
- data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.idx +0 -0
- data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.pack +0 -0
- data/test/examples/revert.git/packed-refs +2 -0
- data/test/examples/revert.git/refs/heads/master +1 -0
- data/test/examples/revert.git/refs/remotes/origin/HEAD +1 -0
- data/test/examples/yubiwa.git/HEAD +1 -0
- data/test/examples/yubiwa.git/config +5 -0
- data/test/examples/yubiwa.git/description +1 -0
- data/test/examples/yubiwa.git/info/exclude +6 -0
- data/test/examples/yubiwa.git/objects/10/fa2ddc4e3b4009d8a453aace10bd6148c1ad00 +0 -0
- data/test/examples/yubiwa.git/objects/52/4b82874327ea7cbf730389964ba7cb3de966de +0 -0
- data/test/examples/yubiwa.git/objects/58/3fc201cb457fb3f1480f3e1e5999b119633835 +0 -0
- data/test/examples/yubiwa.git/objects/87/bc1dd46ab3d3874d4e898d45dd512cc20a7cc8 +1 -0
- data/test/examples/yubiwa.git/objects/89/64ed1b4e21aa90e831763bbce9034bfda81b70 +0 -0
- data/test/examples/yubiwa.git/objects/9f/f6dd0660da5fba2d3374adb2b84fa653bb538b +0 -0
- data/test/examples/yubiwa.git/objects/ac/e97abf2b177815a1972d7db22f229f58c83309 +0 -0
- data/test/examples/yubiwa.git/objects/b1/f443863a4816628807fbf86141ebef055dda34 +0 -0
- data/test/examples/yubiwa.git/refs/heads/master +1 -0
- data/test/helper.rb +66 -0
- data/test/test_app.rb +169 -0
- data/test/test_committer.rb +64 -0
- data/test/test_file.rb +27 -0
- data/test/test_git_access.rb +52 -0
- data/test/test_markup.rb +628 -0
- data/test/test_page.rb +166 -0
- data/test/test_page_revert.rb +45 -0
- data/test/test_wiki.rb +462 -0
- metadata +470 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
module Precious
|
2
|
+
module Views
|
3
|
+
class Create < Layout
|
4
|
+
include Editable
|
5
|
+
|
6
|
+
attr_reader :page, :name
|
7
|
+
|
8
|
+
def title
|
9
|
+
"Create a new page"
|
10
|
+
end
|
11
|
+
|
12
|
+
def is_create_page
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_edit_page
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def format
|
21
|
+
@format = (@page.format || false) if @format.nil? && @page
|
22
|
+
@format.to_s.downcase
|
23
|
+
end
|
24
|
+
|
25
|
+
def has_footer
|
26
|
+
@footer = (@page.footer || false) if @footer.nil? && @page
|
27
|
+
!!@footer
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_sidebar
|
31
|
+
@sidebar = (@page.sidebar || false) if @sidebar.nil? && @page
|
32
|
+
!!@sidebar
|
33
|
+
end
|
34
|
+
|
35
|
+
def page_name
|
36
|
+
@name.gsub('-', ' ')
|
37
|
+
end
|
38
|
+
|
39
|
+
def formats
|
40
|
+
super(:markdown)
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_markup
|
44
|
+
Precious::App.settings.default_markup
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Precious
|
2
|
+
module Views
|
3
|
+
class Edit < Layout
|
4
|
+
include Editable
|
5
|
+
|
6
|
+
attr_reader :page, :content
|
7
|
+
|
8
|
+
def title
|
9
|
+
"#{@page.title}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def page_name
|
13
|
+
@name.gsub('-', ' ')
|
14
|
+
end
|
15
|
+
|
16
|
+
def footer
|
17
|
+
if @footer.nil?
|
18
|
+
if page = @page.footer
|
19
|
+
@footer = page.raw_data
|
20
|
+
else
|
21
|
+
@footer = false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
@footer
|
25
|
+
end
|
26
|
+
|
27
|
+
def sidebar
|
28
|
+
if @sidebar.nil?
|
29
|
+
if page = @page.sidebar
|
30
|
+
@sidebar = page.raw_data
|
31
|
+
else
|
32
|
+
@sidebar = false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@sidebar
|
36
|
+
end
|
37
|
+
|
38
|
+
def is_create_page
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_edit_page
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def format
|
47
|
+
@format = (@page.format || false) if @format.nil?
|
48
|
+
@format.to_s.downcase
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Precious
|
2
|
+
module Editable
|
3
|
+
def formats(selected = @page.format)
|
4
|
+
Gollum::Page::FORMAT_NAMES.map do |key, val|
|
5
|
+
{ :name => val,
|
6
|
+
:id => key.to_s,
|
7
|
+
:selected => selected == key}
|
8
|
+
end.sort do |a, b|
|
9
|
+
a[:name].downcase <=> b[:name].downcase
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Precious
|
2
|
+
module Views
|
3
|
+
class History < Layout
|
4
|
+
attr_reader :page, :page_num
|
5
|
+
|
6
|
+
def title
|
7
|
+
@page.title
|
8
|
+
end
|
9
|
+
|
10
|
+
def versions
|
11
|
+
i = @versions.size + 1
|
12
|
+
@versions.map do |v|
|
13
|
+
i -= 1
|
14
|
+
{ :id => v.id,
|
15
|
+
:id7 => v.id[0..6],
|
16
|
+
:num => i,
|
17
|
+
:selected => @page.version.id == v.id,
|
18
|
+
:author => v.author.name,
|
19
|
+
:message => v.message,
|
20
|
+
:date => v.committed_date.strftime("%B %d, %Y"),
|
21
|
+
:gravatar => Digest::MD5.hexdigest(v.author.email) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def previous_link
|
26
|
+
label = "« Previous"
|
27
|
+
if @page_num == 1
|
28
|
+
%(<span class="disabled">#{label}</span>)
|
29
|
+
else
|
30
|
+
%(<a href="/history/#{@page.name}?page=#{@page_num-1}" hotkey="h">#{label}</a>)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def next_link
|
35
|
+
label = "Next »"
|
36
|
+
if @versions.size == Gollum::Page.per_page
|
37
|
+
%(<a href="/history/#{@page.name}?page=#{@page_num+1}" hotkey="l">#{label}</a>)
|
38
|
+
else
|
39
|
+
%(<span class="disabled">#{label}</span>)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Precious
|
4
|
+
module Views
|
5
|
+
class Layout < Mustache
|
6
|
+
include Rack::Utils
|
7
|
+
alias_method :h, :escape_html
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
def escaped_name
|
12
|
+
CGI.escape(@name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def title
|
16
|
+
"Home"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Precious
|
2
|
+
module Views
|
3
|
+
class Page < Layout
|
4
|
+
attr_reader :content, :page, :footer
|
5
|
+
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
|
6
|
+
DEFAULT_AUTHOR = 'you'
|
7
|
+
|
8
|
+
def title
|
9
|
+
@page.title
|
10
|
+
end
|
11
|
+
|
12
|
+
def format
|
13
|
+
@page.format.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def author
|
17
|
+
return DEFAULT_AUTHOR unless @page.version
|
18
|
+
@page.version.author.name
|
19
|
+
end
|
20
|
+
|
21
|
+
def date
|
22
|
+
return Time.now.strftime(DATE_FORMAT) unless @page.version
|
23
|
+
@page.version.authored_date.strftime(DATE_FORMAT)
|
24
|
+
end
|
25
|
+
|
26
|
+
def editable
|
27
|
+
@editable
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_footer
|
31
|
+
@footer = (@page.footer || false) if @footer.nil?
|
32
|
+
!!@footer
|
33
|
+
end
|
34
|
+
|
35
|
+
def footer_content
|
36
|
+
has_footer && @footer.formatted_data
|
37
|
+
end
|
38
|
+
|
39
|
+
def footer_format
|
40
|
+
has_footer && @footer.format.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_sidebar
|
44
|
+
@sidebar = (@page.sidebar || false) if @sidebar.nil?
|
45
|
+
!!@sidebar
|
46
|
+
end
|
47
|
+
|
48
|
+
def sidebar_content
|
49
|
+
has_sidebar && @sidebar.formatted_data
|
50
|
+
end
|
51
|
+
|
52
|
+
def sidebar_format
|
53
|
+
has_sidebar && @sidebar.format.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Precious
|
2
|
+
module Views
|
3
|
+
class Pages < Layout
|
4
|
+
attr_reader :results, :ref
|
5
|
+
|
6
|
+
def title
|
7
|
+
"All pages in #{@ref}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def has_results
|
11
|
+
!@results.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def no_results
|
15
|
+
@results.empty?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Precious
|
2
|
+
module Views
|
3
|
+
class Search < Layout
|
4
|
+
attr_reader :content, :page, :footer, :results, :query
|
5
|
+
|
6
|
+
def title
|
7
|
+
"Search results for " + @query
|
8
|
+
end
|
9
|
+
|
10
|
+
def has_results
|
11
|
+
!@results.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def no_results
|
15
|
+
@results.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
module Gollum
|
2
|
+
# Controls all access to the Git objects from Gollum. Extend this class to
|
3
|
+
# add custom caching for special cases.
|
4
|
+
class GitAccess
|
5
|
+
# Initializes the GitAccess instance.
|
6
|
+
#
|
7
|
+
# path - The String path to the Git repository that holds the
|
8
|
+
# Gollum site.
|
9
|
+
# page_file_dir - String the directory in which all page files reside
|
10
|
+
#
|
11
|
+
# Returns this instance.
|
12
|
+
def initialize(path, page_file_dir = nil)
|
13
|
+
@page_file_dir = page_file_dir
|
14
|
+
@path = path
|
15
|
+
@repo = Grit::Repo.new(path)
|
16
|
+
clear
|
17
|
+
end
|
18
|
+
|
19
|
+
# Public: Determines whether the Git repository exists on disk.
|
20
|
+
#
|
21
|
+
# Returns true if it exists, or false.
|
22
|
+
def exist?
|
23
|
+
@repo.git.exist?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Public: Converts a given Git reference to a SHA, using the cache if
|
27
|
+
# available.
|
28
|
+
#
|
29
|
+
# ref - a String Git reference (ex: "master")
|
30
|
+
#
|
31
|
+
# Returns a String, or nil if the ref isn't found.
|
32
|
+
def ref_to_sha(ref)
|
33
|
+
ref = ref.to_s
|
34
|
+
return if ref.empty?
|
35
|
+
sha =
|
36
|
+
if sha?(ref)
|
37
|
+
ref
|
38
|
+
else
|
39
|
+
get_cache(:ref, ref) { ref_to_sha!(ref) }
|
40
|
+
end.to_s
|
41
|
+
sha.empty? ? nil : sha
|
42
|
+
end
|
43
|
+
|
44
|
+
# Public: Gets a recursive list of Git blobs for the whole tree at the
|
45
|
+
# given commit.
|
46
|
+
#
|
47
|
+
# ref - A String Git reference or Git SHA to a commit.
|
48
|
+
#
|
49
|
+
# Returns an Array of BlobEntry instances.
|
50
|
+
def tree(ref)
|
51
|
+
if sha = ref_to_sha(ref)
|
52
|
+
get_cache(:tree, sha) { tree!(sha) }
|
53
|
+
else
|
54
|
+
[]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Fetches the contents of the Git blob at the given SHA.
|
59
|
+
#
|
60
|
+
# sha - A String Git SHA.
|
61
|
+
#
|
62
|
+
# Returns the String content of the blob.
|
63
|
+
def blob(sha)
|
64
|
+
cat_file!(sha)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Public: Looks up the Git commit using the given Git SHA or ref.
|
68
|
+
#
|
69
|
+
# ref - A String Git SHA or ref.
|
70
|
+
#
|
71
|
+
# Returns a Grit::Commit.
|
72
|
+
def commit(ref)
|
73
|
+
if sha?(ref)
|
74
|
+
get_cache(:commit, ref) { commit!(ref) }
|
75
|
+
else
|
76
|
+
if sha = get_cache(:ref, ref)
|
77
|
+
commit(sha)
|
78
|
+
else
|
79
|
+
if cm = commit!(ref)
|
80
|
+
set_cache(:ref, ref, cm.id)
|
81
|
+
set_cache(:commit, cm.id, cm)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Public: Clears all of the cached data that this GitAccess is tracking.
|
88
|
+
#
|
89
|
+
# Returns nothing.
|
90
|
+
def clear
|
91
|
+
@ref_map = {}
|
92
|
+
@tree_map = {}
|
93
|
+
@commit_map = {}
|
94
|
+
end
|
95
|
+
|
96
|
+
# Public: Refreshes just the cached Git reference data. This should
|
97
|
+
# be called after every Gollum update.
|
98
|
+
#
|
99
|
+
# Returns nothing.
|
100
|
+
def refresh
|
101
|
+
@ref_map.clear
|
102
|
+
end
|
103
|
+
|
104
|
+
#########################################################################
|
105
|
+
#
|
106
|
+
# Internal Methods
|
107
|
+
#
|
108
|
+
#########################################################################
|
109
|
+
|
110
|
+
# Gets the String path to the Git repository.
|
111
|
+
attr_reader :path
|
112
|
+
|
113
|
+
# Gets the Grit::Repo instance for the Git repository.
|
114
|
+
attr_reader :repo
|
115
|
+
|
116
|
+
# Gets a Hash cache of refs to commit SHAs.
|
117
|
+
#
|
118
|
+
# {"master" => "abc123", ...}
|
119
|
+
#
|
120
|
+
attr_reader :ref_map
|
121
|
+
|
122
|
+
# Gets a Hash cache of commit SHAs to a recursive tree of blobs.
|
123
|
+
#
|
124
|
+
# {"abc123" => [<BlobEntry>, <BlobEntry>]}
|
125
|
+
#
|
126
|
+
attr_reader :tree_map
|
127
|
+
|
128
|
+
# Gets a Hash cache of commit SHAs to the Grit::Commit instance.
|
129
|
+
#
|
130
|
+
# {"abcd123" => <Grit::Commit>}
|
131
|
+
#
|
132
|
+
attr_reader :commit_map
|
133
|
+
|
134
|
+
# Checks to see if the given String is a 40 character hex SHA.
|
135
|
+
#
|
136
|
+
# str - Possible String SHA.
|
137
|
+
#
|
138
|
+
# Returns true if the String is a SHA, or false.
|
139
|
+
def sha?(str)
|
140
|
+
!!(str =~ /^[0-9a-f]{40}$/)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Looks up the Git SHA for the given Git ref.
|
144
|
+
#
|
145
|
+
# ref - String Git ref.
|
146
|
+
#
|
147
|
+
# Returns a String SHA.
|
148
|
+
def ref_to_sha!(ref)
|
149
|
+
@repo.git.rev_list({:max_count=>1}, ref)
|
150
|
+
rescue Grit::GitRuby::Repository::NoSuchShaFound
|
151
|
+
end
|
152
|
+
|
153
|
+
# Looks up the Git blobs for a given commit.
|
154
|
+
#
|
155
|
+
# sha - String commit SHA.
|
156
|
+
#
|
157
|
+
# Returns an Array of BlobEntry instances.
|
158
|
+
def tree!(sha)
|
159
|
+
tree = @repo.git.native(:ls_tree,
|
160
|
+
{:r => true, :l => true, :z => true}, sha)
|
161
|
+
if tree.respond_to?(:force_encoding)
|
162
|
+
tree.force_encoding("UTF-8")
|
163
|
+
end
|
164
|
+
items = tree.split("\0").inject([]) do |memo, line|
|
165
|
+
memo << parse_tree_line(line)
|
166
|
+
end
|
167
|
+
|
168
|
+
if dir = @page_file_dir
|
169
|
+
regex = /^#{dir}\//
|
170
|
+
items.select { |i| i.path =~ regex }
|
171
|
+
else
|
172
|
+
items
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Reads the content from the Git db at the given SHA.
|
177
|
+
#
|
178
|
+
# sha - The String SHA.
|
179
|
+
#
|
180
|
+
# Returns the String content of the Git object.
|
181
|
+
def cat_file!(sha)
|
182
|
+
@repo.git.cat_file({:p => true}, sha)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Reads a Git commit.
|
186
|
+
#
|
187
|
+
# sha - The string SHA of the Git commit.
|
188
|
+
#
|
189
|
+
# Returns a Grit::Commit.
|
190
|
+
def commit!(sha)
|
191
|
+
@repo.commit(sha)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Attempts to get the given data from a cache. If it doesn't exist, it'll
|
195
|
+
# pass the results of the yielded block to the cache for future accesses.
|
196
|
+
#
|
197
|
+
# name - The cache prefix used in building the full cache key.
|
198
|
+
# key - The unique cache key suffix, usually a String Git SHA.
|
199
|
+
#
|
200
|
+
# Yields a block to pass to the cache.
|
201
|
+
# Returns the cached result.
|
202
|
+
def get_cache(name, key)
|
203
|
+
cache = instance_variable_get("@#{name}_map")
|
204
|
+
value = cache[key]
|
205
|
+
if value.nil? && block_given?
|
206
|
+
set_cache(name, key, value = yield)
|
207
|
+
end
|
208
|
+
value == :_nil ? nil : value
|
209
|
+
end
|
210
|
+
|
211
|
+
# Writes some data to the internal cache.
|
212
|
+
#
|
213
|
+
# name - The cache prefix used in building the full cache key.
|
214
|
+
# key - The unique cache key suffix, usually a String Git SHA.
|
215
|
+
# value - The value to write to the cache.
|
216
|
+
#
|
217
|
+
# Returns nothing.
|
218
|
+
def set_cache(name, key, value)
|
219
|
+
cache = instance_variable_get("@#{name}_map")
|
220
|
+
cache[key] = value || :_nil
|
221
|
+
end
|
222
|
+
|
223
|
+
# Parses a line of output from the `ls-tree` command.
|
224
|
+
#
|
225
|
+
# line - A String line of output:
|
226
|
+
# "100644 blob 839c2291b30495b9a882c17d08254d3c90d8fb53 Home.md"
|
227
|
+
#
|
228
|
+
# Returns an Array of BlobEntry instances.
|
229
|
+
def parse_tree_line(line)
|
230
|
+
mode, type, sha, size, *name = line.split(/\s+/)
|
231
|
+
BlobEntry.new(sha, name.join(' '), size.to_i)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Decode octal sequences (\NNN) in tree path names.
|
235
|
+
#
|
236
|
+
# path - String path name.
|
237
|
+
#
|
238
|
+
# Returns a decoded String.
|
239
|
+
def decode_git_path(path)
|
240
|
+
if path[0] == ?" && path[-1] == ?"
|
241
|
+
path = path[1...-1]
|
242
|
+
path.gsub!(/\\\d{3}/) { |m| m[1..-1].to_i(8).chr }
|
243
|
+
end
|
244
|
+
path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m.to_s}")) }
|
245
|
+
path
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|