gollum 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of gollum might be problematic. Click here for more details.

data/HISTORY.md CHANGED
@@ -1,6 +1,36 @@
1
+ # 1.1.0 / 2010-10-28
2
+
3
+ * Major Enhancements
4
+ * Optimize page write/update/delete to use Grit::Index::read_tree instead
5
+ of manually recreating entire index contents.
6
+ * Added --irb option for the gollum command.
7
+ * Update working dir (if present) when edited via the API (#6)
8
+ * Add basic `git grep` based search for repos.
9
+ * Minor Enhancements
10
+ * Support a `:gollum_path` Sinatra setting for `Precious::App`
11
+ * Add Wiki#size to efficiently count pages without loading them.
12
+ * Add the correct content type when serving files from the frontend.
13
+ * Add --host option and default it to 127.0.0.1.
14
+ * Allow anchors in page links, such as `[[Abc#header]]`.
15
+ * All pages retrieved with a SHA add `rel="nofollow"` to all
16
+ page links.
17
+ * Bug Fixes
18
+ * Increase minimum Sanitize version requirement to 1.1.0.
19
+ 1.0.x versions of Sanitize require Hpricot instead of Nokogiri
20
+ and have bugs that may allow non-whitelisted HTML to sneak
21
+ through.
22
+ * Introduce Ruby 1.9 compatibility fixes.
23
+ * Commit hashes are normalized so that missing author data is replaced with
24
+ anonymous info.
25
+ * Prevent `Gollum::Wiki#write_page` from clobbering existing pages.
26
+ * Handle duplicate page errors in frontend.
27
+ * Fix bugs trying to retrieve pages with invalid names.
28
+ * CGI escape page names in links and redirects.
29
+
1
30
  # 1.0.1 / 2010-08-12
2
31
 
3
- * Force Grit dep to 2.1 or higher.
32
+ * Bug Fixes
33
+ * Force Grit dep to 2.1 or higher.
4
34
 
5
35
  # 1.0.0 / 2010-08-12
6
36
 
data/README.md CHANGED
@@ -63,7 +63,7 @@ choose. Special footers can be created in `footer files`. Other content
63
63
  ## PAGE FILES
64
64
 
65
65
  Page files may be written in any format supported by
66
- [GitHub-Markup](http://github.com/defunkt/github-markup) (except roff). The
66
+ [GitHub-Markup](http://github.com/github/markup) (except roff). The
67
67
  current list of formats and allowed extensions is:
68
68
 
69
69
  * ASCIIDoc: .asciidoc
@@ -326,7 +326,7 @@ Initialize the Gollum::Repo object:
326
326
  wiki = Gollum::Wiki.new("my-gollum-repo.git")
327
327
  # => <Gollum::Wiki>
328
328
 
329
- By default, internal wiki links are all absolute from the root. To specify a different base path, you can send specify the `:base_path` option:
329
+ By default, internal wiki links are all absolute from the root. To specify a different base path, you can specify the `:base_path` option:
330
330
 
331
331
  wiki = Gollum::Wiki.new("my-gollum-repo.git", :base_path => "/wiki")
332
332
 
data/Rakefile CHANGED
@@ -47,7 +47,7 @@ task :default => :test
47
47
 
48
48
  require 'rake/testtask'
49
49
  Rake::TestTask.new(:test) do |test|
50
- test.libs << 'lib' << 'test'
50
+ test.libs << 'lib' << 'test' << '.'
51
51
  test.pattern = 'test/**/test_*.rb'
52
52
  test.verbose = true
53
53
  end
@@ -143,4 +143,4 @@ task :validate do
143
143
  puts "A `VERSION` file at root level violates Gem best practices."
144
144
  exit!
145
145
  end
146
- end
146
+ end
data/bin/gollum CHANGED
@@ -8,18 +8,17 @@ Gollum is a multi-format Wiki Engine/API/Frontend.
8
8
  Basic Command Line Usage:
9
9
  gollum [OPTIONS] [PATH]
10
10
 
11
- PATH The path to the Gollum repository.
11
+ PATH The path to the Gollum repository (default .).
12
12
 
13
13
  Options:
14
14
  HELP
15
15
 
16
16
  require 'optparse'
17
-
18
17
  require 'rubygems'
19
- require 'gollum/frontend/app'
18
+ require 'gollum'
20
19
 
21
20
  exec = {}
22
- options = {}
21
+ options = { 'port' => 4567, 'bind' => '127.0.0.1' }
23
22
  opts = OptionParser.new do |opts|
24
23
  opts.banner = help
25
24
 
@@ -27,15 +26,78 @@ opts = OptionParser.new do |opts|
27
26
  options['port'] = port.to_i
28
27
  end
29
28
 
29
+ opts.on("--host [HOST]", "Hostname or IP address to listen on (default 0.0.0.0).") do |host|
30
+ options['bind'] = host
31
+ end
32
+
30
33
  opts.on("--version", "Display current version.") do
31
34
  puts "Gollum " + Gollum::VERSION
32
35
  exit 0
33
36
  end
37
+
38
+ opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do
39
+ options['irb'] = true
40
+ end
34
41
  end
35
42
 
36
43
  # Read command line options into `options` hash
37
- opts.parse!
44
+ begin
45
+ opts.parse!
46
+ rescue OptionParser::InvalidOption
47
+ puts "gollum: #{$!.message}"
48
+ puts "gollum: try 'gollum --help' for more information"
49
+ exit
50
+ end
38
51
 
39
- $path = ARGV[0] || Dir.pwd
52
+ gollum_path = ARGV[0] || Dir.pwd
40
53
 
41
- Precious::App.run!(options)
54
+ if options['irb']
55
+ require 'irb'
56
+ # http://jameskilton.com/2009/04/02/embedding-irb-into-your-ruby-application/
57
+ module IRB # :nodoc:
58
+ def self.start_session(binding)
59
+ unless @__initialized
60
+ args = ARGV
61
+ ARGV.replace(ARGV.dup)
62
+ IRB.setup(nil)
63
+ ARGV.replace(args)
64
+ @__initialized = true
65
+ end
66
+
67
+ ws = WorkSpace.new(binding)
68
+ irb = Irb.new(ws)
69
+
70
+ @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
71
+ @CONF[:MAIN_CONTEXT] = irb.context
72
+
73
+ catch(:IRB_EXIT) do
74
+ irb.eval_input
75
+ end
76
+ end
77
+ end
78
+
79
+ begin
80
+ wiki = Gollum::Wiki.new(gollum_path)
81
+ if !wiki.exist? then raise Grit::InvalidGitRepositoryError end
82
+ puts "Loaded Gollum wiki at #{File.expand_path(gollum_path).inspect}."
83
+ puts
84
+ puts %( page = wiki.page('page-name'))
85
+ puts %( # => <Gollum::Page>)
86
+ puts
87
+ puts %( page.raw_data)
88
+ puts %( # => "# My wiki page")
89
+ puts
90
+ puts %( page.formatted_data)
91
+ puts %( # => "<h1>My wiki page</h1>")
92
+ puts
93
+ puts "Check out the Gollum README for more."
94
+ IRB.start_session(binding)
95
+ rescue Grit::InvalidGitRepositoryError, Grit::NoSuchPathError
96
+ puts "Invalid Gollum wiki at #{File.expand_path(gollum_path).inspect}"
97
+ exit 0
98
+ end
99
+ else
100
+ require 'gollum/frontend/app'
101
+ Precious::App.set(:gollum_path, gollum_path)
102
+ Precious::App.run!(options)
103
+ end
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
4
4
  s.rubygems_version = '1.3.5'
5
5
 
6
6
  s.name = 'gollum'
7
- s.version = '1.0.1'
8
- s.date = '2010-08-12'
7
+ s.version = '1.1.0'
8
+ s.date = '2010-10-28'
9
9
  s.rubyforge_project = 'gollum'
10
10
 
11
11
  s.summary = "A simple, Git-powered wiki."
@@ -23,17 +23,19 @@ Gem::Specification.new do |s|
23
23
  s.rdoc_options = ["--charset=UTF-8"]
24
24
  s.extra_rdoc_files = %w[README.md LICENSE]
25
25
 
26
- s.add_dependency('grit', "~> 2.1")
26
+ s.add_dependency('grit', "~> 2.3")
27
27
  s.add_dependency('github-markup', [">= 0.4.0", "< 1.0.0"])
28
28
  s.add_dependency('albino', "~> 1.0")
29
29
  s.add_dependency('sinatra', "~> 1.0")
30
30
  s.add_dependency('mustache', [">= 0.11.2", "< 1.0.0"])
31
- s.add_dependency('sanitize', "~> 1.0")
31
+ s.add_dependency('sanitize', "~> 1.1")
32
32
  s.add_dependency('nokogiri', "~> 1.4")
33
33
 
34
- s.add_development_dependency('shoulda')
34
+ s.add_development_dependency('RedCloth')
35
35
  s.add_development_dependency('mocha')
36
36
  s.add_development_dependency('org-ruby')
37
+ s.add_development_dependency('rdiscount')
38
+ s.add_development_dependency('shoulda')
37
39
 
38
40
  # = MANIFEST =
39
41
  s.files = %w[
@@ -46,6 +48,7 @@ Gem::Specification.new do |s|
46
48
  gollum.gemspec
47
49
  lib/gollum.rb
48
50
  lib/gollum/albino.rb
51
+ lib/gollum/blob_entry.rb
49
52
  lib/gollum/file.rb
50
53
  lib/gollum/frontend/app.rb
51
54
  lib/gollum/frontend/public/css/editbar.css
@@ -443,19 +446,24 @@ Gem::Specification.new do |s|
443
446
  lib/gollum/frontend/templates/create.mustache
444
447
  lib/gollum/frontend/templates/edit.mustache
445
448
  lib/gollum/frontend/templates/editbar.mustache
449
+ lib/gollum/frontend/templates/error.mustache
446
450
  lib/gollum/frontend/templates/history.mustache
447
451
  lib/gollum/frontend/templates/layout.mustache
448
452
  lib/gollum/frontend/templates/page.mustache
453
+ lib/gollum/frontend/templates/search.mustache
449
454
  lib/gollum/frontend/views/compare.rb
450
455
  lib/gollum/frontend/views/create.rb
451
456
  lib/gollum/frontend/views/edit.rb
452
457
  lib/gollum/frontend/views/editable.rb
458
+ lib/gollum/frontend/views/error.rb
453
459
  lib/gollum/frontend/views/history.rb
454
460
  lib/gollum/frontend/views/layout.rb
455
461
  lib/gollum/frontend/views/page.rb
462
+ lib/gollum/frontend/views/search.rb
456
463
  lib/gollum/markup.rb
457
464
  lib/gollum/page.rb
458
465
  lib/gollum/pagination.rb
466
+ lib/gollum/ruby1.8.rb
459
467
  lib/gollum/wiki.rb
460
468
  templates/formatting.html
461
469
  test/examples/lotr.git/HEAD
@@ -503,4 +511,4 @@ Gem::Specification.new do |s|
503
511
  # = MANIFEST =
504
512
 
505
513
  s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
506
- end
514
+ end
@@ -1,13 +1,18 @@
1
1
  # stdlib
2
2
  require 'digest/md5'
3
+ require 'ostruct'
3
4
 
4
5
  # external
5
6
  require 'grit'
6
7
  require 'github/markup'
7
8
  require 'sanitize'
8
9
 
10
+ # ruby 1.8 compatibility
11
+ require 'gollum/ruby1.8'
12
+
9
13
  # internal
10
14
  require 'gollum/pagination'
15
+ require 'gollum/blob_entry'
11
16
  require 'gollum/wiki'
12
17
  require 'gollum/page'
13
18
  require 'gollum/file'
@@ -15,7 +20,7 @@ require 'gollum/markup'
15
20
  require 'gollum/albino'
16
21
 
17
22
  module Gollum
18
- VERSION = '1.0.1'
23
+ VERSION = '1.1.0'
19
24
 
20
25
  SANITIZATION_OPTIONS = {
21
26
  :elements => [
@@ -54,5 +59,24 @@ module Gollum
54
59
  'img' => {'href' => ['http', 'https', :relative]}
55
60
  }
56
61
  }
62
+ HISTORY_SANITIZATION_OPTIONS = SANITIZATION_OPTIONS.merge(
63
+ :add_attributes => {
64
+ 'a' => {'rel' => 'nofollow'}
65
+ }
66
+ )
67
+
68
+ class Error < StandardError; end
69
+ class DuplicatePageError < Error
70
+ attr_accessor :dir
71
+ attr_accessor :existing_path
72
+ attr_accessor :attempted_path
73
+
74
+ def initialize(dir, existing, attempted, message = nil)
75
+ @dir = dir
76
+ @existing_path = existing
77
+ @attempted_path = attempted
78
+ super(message || "Cannot write #{@dir}/#{@attempted_path}, found #{@dir}/#{@existing_path}.")
79
+ end
80
+ end
57
81
  end
58
82
 
@@ -0,0 +1,71 @@
1
+ module Gollum
2
+ class BlobEntry
3
+ # Gets the String SHA for this blob.
4
+ attr_reader :sha
5
+
6
+ # Gets the String full path for this blob.
7
+ attr_reader :path
8
+
9
+ def initialize(sha, path)
10
+ @sha = sha
11
+ @path = path
12
+ @dir = @name = @blob = nil
13
+ end
14
+
15
+ # Gets the normalized directory path for this blob.
16
+ def dir
17
+ @dir ||= self.class.normalize_dir(::File.dirname(@path))
18
+ end
19
+
20
+ # Gets the String file base name for this blob.
21
+ def name
22
+ @name ||= ::File.basename(@path)
23
+ end
24
+
25
+ # Gets a Grit::Blob instance for this blob.
26
+ #
27
+ # repo - Grit::Repo instance for the Grit::Blob.
28
+ #
29
+ # Returns an unbaked Grit::Blob instance.
30
+ def blob(repo)
31
+ @blob ||= Grit::Blob.create(repo, :id => @sha, :name => @name)
32
+ end
33
+
34
+ # Gets a Page instance for this blob.
35
+ #
36
+ # wiki - Gollum::Wiki instance for the Gollum::Page
37
+ #
38
+ # Returns a Gollum::Page instance.
39
+ def page(wiki, commit)
40
+ blob = self.blob(wiki.repo)
41
+ page = wiki.page_class.new(wiki).populate(blob, self.dir)
42
+ page.version = commit
43
+ page
44
+ end
45
+
46
+ def inspect
47
+ %(#<Gollum::BlobEntry #{@sha} #{@path}>)
48
+ end
49
+
50
+ # Normalizes a given directory name for searching through tree paths.
51
+ # Ensures that a directory begins with a slash, or
52
+ #
53
+ # normalize_dir("") # => ""
54
+ # normalize_dir(".") # => ""
55
+ # normalize_dir("foo") # => "/foo"
56
+ # normalize_dir("/foo/") # => "/foo"
57
+ # normalize_dir("/") # => ""
58
+ #
59
+ # dir - String directory name.
60
+ #
61
+ # Returns a normalized String directory name, or nil if no directory
62
+ # is given.
63
+ def self.normalize_dir(dir)
64
+ if dir
65
+ dir = ::File.expand_path(dir, '/')
66
+ dir = '' if dir == '/'
67
+ end
68
+ dir
69
+ end
70
+ end
71
+ end
@@ -33,6 +33,11 @@ module Gollum
33
33
  # Public: The String path of the file.
34
34
  attr_reader :path
35
35
 
36
+ # Public: The String mime type of the file.
37
+ def mime_type
38
+ @blob.mime_type
39
+ end
40
+
36
41
  #########################################################################
37
42
  #
38
43
  # Internal Methods
@@ -46,14 +51,14 @@ module Gollum
46
51
  #
47
52
  # Returns a Gollum::File or nil if the file could not be found.
48
53
  def find(name, version)
49
- commit = @wiki.repo.commit(version)
50
- if blob = commit.tree / name
51
- @blob = blob
54
+ checked = name.downcase
55
+ map = @wiki.tree_map_for(version)
56
+ sha = @wiki.ref_map[version] || version
57
+ if entry = map.detect { |entry| entry.path.downcase == checked }
52
58
  @path = name
53
- @version = commit
59
+ @blob = Grit::Blob.create(@wiki.repo, :id => entry.sha, :name => entry.name)
60
+ @version = Grit::Commit.create(@wiki.repo, :id => sha)
54
61
  self
55
- else
56
- nil
57
62
  end
58
63
  end
59
64
  end
@@ -1,3 +1,4 @@
1
+ require 'cgi'
1
2
  require 'sinatra'
2
3
  require 'gollum'
3
4
  require 'mustache/sinatra'
@@ -12,6 +13,7 @@ module Precious
12
13
  dir = File.dirname(File.expand_path(__FILE__))
13
14
 
14
15
  # We want to serve public assets for now
16
+
15
17
  set :public, "#{dir}/public"
16
18
  set :static, true
17
19
 
@@ -38,9 +40,9 @@ module Precious
38
40
  show_page_or_file('Home')
39
41
  end
40
42
 
41
- get '/edit/:name' do
42
- @name = params[:name]
43
- wiki = Gollum::Wiki.new($path)
43
+ get '/edit/*' do
44
+ @name = params[:splat].first
45
+ wiki = Gollum::Wiki.new(settings.gollum_path)
44
46
  if page = wiki.page(@name)
45
47
  @page = page
46
48
  @content = page.raw_data
@@ -50,38 +52,43 @@ module Precious
50
52
  end
51
53
  end
52
54
 
53
- post '/edit/:name' do
54
- name = params[:name]
55
- wiki = Gollum::Wiki.new($path)
55
+ post '/edit/*' do
56
+ name = params[:splat].first
57
+ wiki = Gollum::Wiki.new(settings.gollum_path)
56
58
  page = wiki.page(name)
57
59
  format = params[:format].intern
58
60
  name = params[:rename] if params[:rename]
59
61
 
60
62
  wiki.update_page(page, name, format, params[:content], commit_message)
61
63
 
62
- redirect "/#{Gollum::Page.cname name}"
64
+ redirect "/#{CGI.escape(Gollum::Page.cname(name))}"
63
65
  end
64
66
 
65
- post '/create/:name' do
67
+ post '/create/*' do
66
68
  name = params[:page]
67
- wiki = Gollum::Wiki.new($path)
69
+ wiki = Gollum::Wiki.new(settings.gollum_path)
68
70
 
69
71
  format = params[:format].intern
70
72
 
71
- wiki.write_page(name, format, params[:content], commit_message)
72
- redirect "/#{name}"
73
+ begin
74
+ wiki.write_page(name, format, params[:content], commit_message)
75
+ redirect "/#{CGI.escape(name)}"
76
+ rescue Gollum::DuplicatePageError => e
77
+ @message = "Duplicate page: #{e.message}"
78
+ mustache :error
79
+ end
73
80
  end
74
81
 
75
82
  post '/preview' do
76
83
  format = params['wiki_format']
77
84
  data = params['text']
78
- wiki = Gollum::Wiki.new($path)
85
+ wiki = Gollum::Wiki.new(settings.gollum_path)
79
86
  wiki.preview_page("Preview", data, format).formatted_data
80
87
  end
81
88
 
82
89
  get '/history/:name' do
83
90
  @name = params[:name]
84
- wiki = Gollum::Wiki.new($path)
91
+ wiki = Gollum::Wiki.new(settings.gollum_path)
85
92
  @page = wiki.page(@name)
86
93
  @page_num = [params[:page].to_i, 1].max
87
94
  @versions = @page.versions :page => @page_num
@@ -91,10 +98,10 @@ module Precious
91
98
  post '/compare/:name' do
92
99
  @versions = params[:versions] || []
93
100
  if @versions.size < 2
94
- redirect "/history/#{params[:name]}"
101
+ redirect "/history/#{CGI.escape(params[:name])}"
95
102
  else
96
103
  redirect "/compare/%s/%s...%s" % [
97
- params[:name],
104
+ CGI.escape(params[:name]),
98
105
  @versions.last,
99
106
  @versions.first]
100
107
  end
@@ -103,7 +110,7 @@ module Precious
103
110
  get '/compare/:name/:version_list' do
104
111
  @name = params[:name]
105
112
  @versions = params[:version_list].split(/\.{2,3}/)
106
- wiki = Gollum::Wiki.new($path)
113
+ wiki = Gollum::Wiki.new(settings.gollum_path)
107
114
  @page = wiki.page(@name)
108
115
  diffs = wiki.repo.diff(@versions.first, @versions.last, @page.path)
109
116
  @diff = diffs.first
@@ -112,7 +119,7 @@ module Precious
112
119
 
113
120
  get %r{/(.+?)/([0-9a-f]{40})} do
114
121
  name = params[:captures][0]
115
- wiki = Gollum::Wiki.new($path)
122
+ wiki = Gollum::Wiki.new(settings.gollum_path)
116
123
  if page = wiki.page(name, params[:captures][1])
117
124
  @page = page
118
125
  @name = name
@@ -123,18 +130,26 @@ module Precious
123
130
  end
124
131
  end
125
132
 
133
+ get '/search' do
134
+ @query = params[:q]
135
+ wiki = Gollum::Wiki.new(settings.gollum_path)
136
+ @results = wiki.search @query
137
+ mustache :search
138
+ end
139
+
126
140
  get '/*' do
127
141
  show_page_or_file(params[:splat].first)
128
142
  end
129
143
 
130
144
  def show_page_or_file(name)
131
- wiki = Gollum::Wiki.new($path)
145
+ wiki = Gollum::Wiki.new(settings.gollum_path)
132
146
  if page = wiki.page(name)
133
147
  @page = page
134
148
  @name = name
135
149
  @content = page.formatted_data
136
150
  mustache :page
137
151
  elsif file = wiki.file(name)
152
+ content_type file.mime_type
138
153
  file.raw_data
139
154
  else
140
155
  @name = name
@@ -143,12 +158,7 @@ module Precious
143
158
  end
144
159
 
145
160
  def commit_message
146
- message = params[:message]
147
- author_name = `git config --get user.name`.strip || 'Anonymous'
148
- author_email = `git config --get user.email`.strip || 'anon@anon.com'
149
- { :message => message,
150
- :name => author_name,
151
- :email => author_email }
161
+ { :message => params[:message] }
152
162
  end
153
163
  end
154
164
  end