gollum-lib 5.0.a.4 → 5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +12 -7
  4. data/Rakefile +5 -5
  5. data/adapter_dependencies.rb +7 -0
  6. data/gemspec.rb +18 -10
  7. data/gollum-lib.gemspec +2 -6
  8. data/gollum-lib_java.gemspec +2 -2
  9. data/lib/gollum-lib.rb +9 -9
  10. data/lib/gollum-lib/blob_entry.rb +2 -8
  11. data/lib/gollum-lib/committer.rb +22 -60
  12. data/lib/gollum-lib/file.rb +105 -82
  13. data/lib/gollum-lib/file_view.rb +8 -4
  14. data/lib/gollum-lib/filter.rb +12 -0
  15. data/lib/gollum-lib/filter/code.rb +9 -13
  16. data/lib/gollum-lib/filter/critic_markup.rb +97 -0
  17. data/lib/gollum-lib/filter/emoji.rb +10 -8
  18. data/lib/gollum-lib/filter/macro.rb +5 -2
  19. data/lib/gollum-lib/filter/plantuml.rb +1 -1
  20. data/lib/gollum-lib/filter/remote_code.rb +3 -2
  21. data/lib/gollum-lib/filter/render.rb +25 -2
  22. data/lib/gollum-lib/filter/sanitize.rb +1 -8
  23. data/lib/gollum-lib/filter/tags.rb +57 -47
  24. data/lib/gollum-lib/filter/toc.rb +17 -21
  25. data/lib/gollum-lib/filter/yaml.rb +1 -1
  26. data/lib/gollum-lib/git_access.rb +0 -25
  27. data/lib/gollum-lib/helpers.rb +13 -3
  28. data/lib/gollum-lib/macro/audio.rb +9 -0
  29. data/lib/gollum-lib/macro/global_toc.rb +2 -1
  30. data/lib/gollum-lib/macro/navigation.rb +8 -6
  31. data/lib/gollum-lib/macro/note.rb +19 -0
  32. data/lib/gollum-lib/macro/octicon.rb +12 -0
  33. data/lib/gollum-lib/macro/warn.rb +11 -0
  34. data/lib/gollum-lib/markup.rb +17 -32
  35. data/lib/gollum-lib/markups.rb +11 -7
  36. data/lib/gollum-lib/page.rb +79 -165
  37. data/lib/gollum-lib/pagination.rb +7 -6
  38. data/lib/gollum-lib/redirects.rb +38 -0
  39. data/lib/gollum-lib/sanitization.rb +32 -357
  40. data/lib/gollum-lib/version.rb +1 -1
  41. data/lib/gollum-lib/wiki.rb +216 -404
  42. metadata +73 -28
  43. data/ROADMAP +0 -6
@@ -1,5 +1,5 @@
1
1
  module Gollum
2
2
  module Lib
3
- VERSION = '5.0.a.4'
3
+ VERSION = '5.0'
4
4
  end
5
5
  end
@@ -1,18 +1,11 @@
1
1
  # ~*~ encoding: utf-8 ~*~
2
+ require 'pathname'
3
+
2
4
  module Gollum
3
5
  class Wiki
4
6
  include Pagination
5
7
 
6
8
  class << self
7
- # Sets the page class used by all instances of this Wiki.
8
- attr_writer :page_class
9
-
10
- # Sets the file class used by all instances of this Wiki.
11
- attr_writer :file_class
12
-
13
- # Sets the markup class used by all instances of this Wiki.
14
- attr_writer :markup_classes
15
-
16
9
  # Sets the default ref for the wiki.
17
10
  attr_writer :default_ref
18
11
 
@@ -22,87 +15,10 @@ module Gollum
22
15
  # Sets the default email for commits.
23
16
  attr_writer :default_committer_email
24
17
 
25
- # Sets sanitization options. Set to false to deactivate
26
- # sanitization altogether.
27
- attr_writer :sanitization
28
-
29
- # Sets sanitization options. Set to false to deactivate
30
- # sanitization altogether.
31
- attr_writer :history_sanitization
32
-
33
18
  # Hash for setting different default wiki options
34
19
  # These defaults can be overridden by options passed directly to initialize()
35
20
  attr_writer :default_options
36
21
 
37
- # Gets the page class used by all instances of this Wiki.
38
- # Default: Gollum::Page.
39
- def page_class
40
- @page_class ||
41
- if superclass.respond_to?(:page_class)
42
- superclass.page_class
43
- else
44
- ::Gollum::Page
45
- end
46
- end
47
-
48
- # Gets the file class used by all instances of this Wiki.
49
- # Default: Gollum::File.
50
- def file_class
51
- @file_class ||
52
- if superclass.respond_to?(:file_class)
53
- superclass.file_class
54
- else
55
- ::Gollum::File
56
- end
57
- end
58
-
59
- # Gets the markup class used by all instances of this Wiki.
60
- # Default: Gollum::Markup
61
- def markup_classes
62
- @markup_classes ||=
63
- if superclass.respond_to?(:markup_classes)
64
- superclass.markup_classes
65
- else
66
- Hash.new(::Gollum::Markup)
67
- end
68
- end
69
-
70
- # Gets the default markup class used by all instances of this Wiki.
71
- # Kept for backwards compatibility until Gollum v2.x
72
- def markup_class(language=:default)
73
- markup_classes[language]
74
- end
75
-
76
- # Sets the default markup class used by all instances of this Wiki.
77
- # Kept for backwards compatibility until Gollum v2.x
78
- def markup_class=(default)
79
- @markup_classes = Hash.new(default).update(markup_classes)
80
- default
81
- end
82
-
83
- alias_method :default_markup_class, :markup_class
84
- alias_method :default_markup_class=, :markup_class=
85
-
86
- # Gets the default sanitization options for current pages used by
87
- # instances of this Wiki.
88
- def sanitization
89
- if @sanitization.nil?
90
- @sanitization = Sanitization.new
91
- end
92
- @sanitization
93
- end
94
-
95
- # Gets the default sanitization options for older page revisions used by
96
- # instances of this Wiki.
97
- def history_sanitization
98
- if @history_sanitization.nil?
99
- @history_sanitization = sanitization ?
100
- sanitization.history_sanitization :
101
- false
102
- end
103
- @history_sanitization
104
- end
105
-
106
22
  def default_ref
107
23
  @default_ref || 'master'
108
24
  end
@@ -131,21 +47,12 @@ module Gollum
131
47
  # to "/".
132
48
  attr_reader :base_path
133
49
 
134
- # Gets the sanitization options for current pages used by this Wiki.
135
- attr_reader :sanitization
136
-
137
- # Gets the sanitization options for older page revisions used by this Wiki.
138
- attr_reader :history_sanitization
139
-
140
50
  # Gets the String ref in which all page files reside.
141
51
  attr_reader :ref
142
52
 
143
53
  # Gets the String directory in which all page files reside.
144
54
  attr_reader :page_file_dir
145
55
 
146
- # Gets the boolean live preview value.
147
- attr_reader :live_preview
148
-
149
56
  # Injects custom css from custom.css in root repo.
150
57
  # Defaults to false
151
58
  attr_reader :css
@@ -170,28 +77,25 @@ module Gollum
170
77
  # works, and what filter classes need to implement.
171
78
  attr_reader :filter_chain
172
79
 
80
+ # Global metadata to be merged into the metadata for each page
81
+ attr_reader :metadata
82
+
173
83
  # Public: Initialize a new Gollum Repo.
174
84
  #
175
85
  # path - The String path to the Git repository that holds the Gollum
176
86
  # site.
177
87
  # options - Optional Hash:
178
88
  # :universal_toc - Table of contents on all pages. Default: false
179
- # :live_preview - Livepreview editing for markdown files. Default: true
180
89
  # :base_path - String base path for all Wiki links.
181
90
  # Default: "/"
182
- # :page_class - The page Class. Default: Gollum::Page
183
- # :file_class - The file Class. Default: Gollum::File
184
- # :markup_classes - A hash containing the markup Classes for each
185
- # document type. Default: { Gollum::Markup }
186
- # :sanitization - An instance of Sanitization.
187
91
  # :page_file_dir - String the directory in which all page files reside
188
92
  # :ref - String the repository ref to retrieve pages from
189
93
  # :mathjax - Set to false to disable mathjax.
190
94
  # :user_icons - Enable user icons on the history page. [gravatar, identicon, none].
191
95
  # Default: none
192
- # :show_all - Show all files in file view, not just valid pages.
193
- # Default: false
194
- # :collapse_tree - Start with collapsed file view. Default: false
96
+ # :global_tag_lookup - Enable 4.x compatibility behavior for links
97
+ # :hyphened_tag_lookup - Spaces in tag paths are treated as dashes (-)
98
+ # :case_insensitive_tag_lookup - Paths in tags are compared case_insensitively
195
99
  # :css - Include the custom.css file from the repo.
196
100
  # :emoji - Parse and interpret emoji tags (e.g. :heart:).
197
101
  # :h1_title - Concatenate all h1's on a page to form the
@@ -216,31 +120,22 @@ module Gollum
216
120
  path = path.path
217
121
  end
218
122
 
219
- # Use .fetch instead of ||
220
- #
221
- # o = { :a => false }
222
- # o[:a] || true # => true
223
- # o.fetch :a, true # => false
224
-
225
123
  @path = path
226
124
  @repo_is_bare = options.fetch :repo_is_bare, nil
227
125
  @page_file_dir = options.fetch :page_file_dir, nil
126
+ @page_file_dir = Pathname.new("/#{@page_file_dir}").cleanpath.to_s[1..-1] if @page_file_dir
228
127
  @access = options.fetch :access, GitAccess.new(path, @page_file_dir, @repo_is_bare)
229
128
  @base_path = options.fetch :base_path, "/"
230
- @page_class = options.fetch :page_class, self.class.page_class
231
- @file_class = options.fetch :file_class, self.class.file_class
232
- @markup_classes = options.fetch :markup_classes, self.class.markup_classes
233
129
  @repo = @access.repo
234
130
  @ref = options.fetch :ref, self.class.default_ref
235
- @sanitization = options.fetch :sanitization, self.class.sanitization
236
- @history_sanitization = options.fetch :history_sanitization, self.class.history_sanitization
237
- @live_preview = options.fetch :live_preview, true
238
131
  @universal_toc = options.fetch :universal_toc, false
239
132
  @mathjax = options.fetch :mathjax, false
240
- @show_all = options.fetch :show_all, false
241
- @collapse_tree = options.fetch :collapse_tree, false
133
+ @global_tag_lookup = options.fetch :global_tag_lookup, false
134
+ @hyphened_tag_lookup = options.fetch :hyphened_tag_lookup, false
135
+ @case_insensitive_tag_lookup = options.fetch :case_insensitive_tag_lookup, false
242
136
  @css = options.fetch :css, false
243
137
  @emoji = options.fetch :emoji, false
138
+ @critic_markup = options.fetch :critic_markup, false
244
139
  @h1_title = options.fetch :h1_title, false
245
140
  @display_metadata = options.fetch :display_metadata, true
246
141
  @index_page = options.fetch :index_page, 'Home'
@@ -249,10 +144,12 @@ module Gollum
249
144
  options[:user_icons] : 'none'
250
145
  @allow_uploads = options.fetch :allow_uploads, false
251
146
  @per_page_uploads = options.fetch :per_page_uploads, false
147
+ @metadata = options.fetch :metadata, {}
252
148
  @filter_chain = options.fetch :filter_chain,
253
- [:YAML, :BibTeX, :PlainText, :TOC, :RemoteCode, :Code, :Macro, :Emoji, :Sanitize, :PlantUML, :Tags, :PandocBib, :Render]
149
+ [:YAML, :BibTeX, :PlainText, :CriticMarkup, :TOC, :RemoteCode, :Code, :Macro, :Emoji, :Sanitize, :PlantUML, :Tags, :PandocBib, :Render]
254
150
  @filter_chain.delete(:Emoji) unless options.fetch :emoji, false
255
151
  @filter_chain.delete(:PandocBib) unless ::Gollum::MarkupRegisterUtils.using_pandoc?
152
+ @filter_chain.delete(:CriticMarkup) unless options.fetch :critic_markup, false
256
153
  end
257
154
 
258
155
  # Public: check whether the wiki's git repo exists on the filesystem.
@@ -264,25 +161,13 @@ module Gollum
264
161
 
265
162
  # Public: Get the formatted page for a given page name, version, and dir.
266
163
  #
267
- # name - The human or canonical String page name of the wiki page.
164
+ # path - The String path to the the wiki page (may or may not include file extension).
268
165
  # version - The String version ID to find (default: @ref).
269
- # dir - The directory String relative to the repo.
166
+ # global_match - If true, find a File matching path's filename, but not it's directory (so anywhere in the repo)
270
167
  #
271
168
  # Returns a Gollum::Page or nil if no matching page was found.
272
- def page(name, version = @ref, dir = nil, exact = false)
273
- version = @ref if version.nil?
274
- @page_class.new(self).find(name, version, dir, exact)
275
- end
276
-
277
- # Public: Convenience method instead of calling page(name, nil, dir).
278
- #
279
- # name - The human or canonical String page name of the wiki page.
280
- # version - The String version ID to find (default: @ref).
281
- # dir - The directory String relative to the repo.
282
- #
283
- # Returns a Gollum::Page or nil if no matching page was found.
284
- def paged(name, dir = nil, exact = false, version = @ref)
285
- page(name, version, dir, exact)
169
+ def page(path, version = nil, global_match = false)
170
+ ::Gollum::Page.find(self, path, version.nil? ? @ref : version, false, global_match)
286
171
  end
287
172
 
288
173
  # Public: Get the static file for a given name.
@@ -295,8 +180,8 @@ module Gollum
295
180
  # Returns a Gollum::File or nil if no matching file was found. Note
296
181
  # that if you specify try_on_disk=true, you may or may not get a file
297
182
  # for which on_disk? is actually true.
298
- def file(name, version = @ref, try_on_disk = false)
299
- @file_class.new(self).find(name, version, try_on_disk)
183
+ def file(name, version = nil, try_on_disk = false)
184
+ ::Gollum::File.find(self, name, version.nil? ? @ref : version, try_on_disk)
300
185
  end
301
186
 
302
187
  # Public: Create an in-memory Page with the given data and format. This
@@ -309,18 +194,12 @@ module Gollum
309
194
  #
310
195
  # Returns the in-memory Gollum::Page.
311
196
  def preview_page(name, data, format)
312
- page = @page_class.new(self)
313
- ext = @page_class.format_to_ext(format.to_sym)
314
- filename = "#{name}.#{ext}"
315
- blob = OpenStruct.new(:name => filename, :data => data, :is_symlink => false)
316
- page.populate(blob)
317
- page.version = @access.commit(@ref)
318
- page
197
+ ::Gollum::PreviewPage.new(self, "#{name}.#{::Gollum::Page.format_to_ext(format.to_sym)}", data, @access.commit(@ref))
319
198
  end
320
199
 
321
200
  # Public: Write a new version of a page to the Gollum repo root.
322
201
  #
323
- # name - The String name of the page.
202
+ # path - The String path where the page will be written.
324
203
  # format - The Symbol format of the page.
325
204
  # data - The new String contents of the page.
326
205
  # commit - The commit Hash details:
@@ -333,23 +212,50 @@ module Gollum
333
212
  # :committer - Optional Gollum::Committer instance. If provided,
334
213
  # assume that this operation is part of batch of
335
214
  # updates and the commit happens later.
336
- # dir - The String subdirectory of the Gollum::Page without any
337
- # prefix or suffix slashes (e.g. "foo/bar").
338
215
  # Returns the String SHA1 of the newly written version, or the
339
216
  # Gollum::Committer instance if this is part of a batch update.
340
- def write_page(name, format, data, commit = {}, dir = '')
341
- sanitized_dir = ::File.join([@page_file_dir, dir].compact)
342
-
343
- multi_commit = !!commit[:committer]
344
- committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
345
- committer.add_to_index(sanitized_dir, name, format, data)
217
+ def write_page(path, format, data, commit = {})
218
+ write(merge_path_elements(nil, path, format), data, commit)
219
+ end
346
220
 
347
- committer.after_commit do |index, _sha|
348
- @access.refresh
349
- index.update_working_dir(sanitized_dir, name, format)
350
- end
221
+ # Public: Write a new version of a file to the Gollum repo.
222
+ #
223
+ # path - The String path where the file will be written.
224
+ # data - The new String contents of the page.
225
+ # commit - The commit Hash details:
226
+ # :message - The String commit message.
227
+ # :name - The String author full name.
228
+ # :email - The String email address.
229
+ # :parent - Optional Gollum::Git::Commit parent to this update.
230
+ # :tree - Optional String SHA of the tree to create the
231
+ # index from.
232
+ # :committer - Optional Gollum::Committer instance. If provided,
233
+ # assume that this operation is part of batch of
234
+ # updates and the commit happens later.
235
+ # Returns the String SHA1 of the newly written version, or the
236
+ # Gollum::Committer instance if this is part of a batch update
237
+ def write_file(name, data, commit = {})
238
+ write(merge_path_elements(nil, name, nil), data, commit)
239
+ end
351
240
 
352
- multi_commit ? committer : committer.commit
241
+ # Public: Write a file to the Gollum repo regardless of existing versions.
242
+ #
243
+ # path - The String path where the file will be written.
244
+ # data - The new String contents of the page.
245
+ # commit - The commit Hash details:
246
+ # :message - The String commit message.
247
+ # :name - The String author full name.
248
+ # :email - The String email address.
249
+ # :parent - Optional Gollum::Git::Commit parent to this update.
250
+ # :tree - Optional String SHA of the tree to create the
251
+ # index from.
252
+ # :committer - Optional Gollum::Committer instance. If provided,
253
+ # assume that this operation is part of batch of
254
+ # updates and the commit happens later.
255
+ # Returns the String SHA1 of the newly written version, or the
256
+ # Gollum::Committer instance if this is part of a batch update
257
+ def overwrite_file(name, data, commit = {})
258
+ write(merge_path_elements(nil, name, nil), data, commit, force_overwrite = true)
353
259
  end
354
260
 
355
261
  # Public: Rename an existing page without altering content.
@@ -392,12 +298,12 @@ module Gollum
392
298
  committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
393
299
 
394
300
  committer.delete(page.path)
395
- committer.add_to_index(target_dir, target_name, page.format, page.raw_data)
301
+ committer.add_to_index(merge_path_elements(target_dir, target_name, page.format), page.raw_data)
396
302
 
397
303
  committer.after_commit do |index, _sha|
398
304
  @access.refresh
399
- index.update_working_dir(source_dir, source_name, page.format)
400
- index.update_working_dir(target_dir, target_name, page.format)
305
+ index.update_working_dir(merge_path_elements(source_dir, source_name, page.format))
306
+ index.update_working_dir(merge_path_elements(target_dir, target_name, page.format))
401
307
  end
402
308
 
403
309
  multi_commit ? committer : committer.commit
@@ -429,24 +335,24 @@ module Gollum
429
335
  name ||= page.name
430
336
  format ||= page.format
431
337
  dir = ::File.dirname(page.path)
432
- dir = '' if dir == '.'
433
- filename = (rename = page.name != name) ?
434
- name : page.filename_stripped
338
+ dir = nil if dir == '.'
339
+ rename = (page.name != name || page.format != format)
340
+ new_path = ::File.join([dir, self.page_file_name(name, format)].compact) if rename
435
341
 
436
342
  multi_commit = !!commit[:committer]
437
343
  committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
438
344
 
439
- if !rename && page.format == format
345
+ if !rename
440
346
  committer.add(page.path, normalize(data))
441
347
  else
442
348
  committer.delete(page.path)
443
- committer.add_to_index(dir, filename, format, data)
349
+ committer.add_to_index(new_path, data)
444
350
  end
445
351
 
446
352
  committer.after_commit do |index, _sha|
447
353
  @access.refresh
448
- index.update_working_dir(dir, page.filename_stripped, page.format)
449
- index.update_working_dir(dir, filename, format)
354
+ index.update_working_dir(page.path)
355
+ index.update_working_dir(new_path) if rename
450
356
  end
451
357
 
452
358
  multi_commit ? committer : committer.commit
@@ -469,21 +375,7 @@ module Gollum
469
375
  # Returns the String SHA1 of the newly written version, or the
470
376
  # Gollum::Committer instance if this is part of a batch update.
471
377
  def delete_page(page, commit)
472
-
473
- multi_commit = !!commit[:committer]
474
- committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
475
-
476
- committer.delete(page.path)
477
-
478
- committer.after_commit do |index, _sha|
479
- dir = ::File.dirname(page.path)
480
- dir = '' if dir == '.'
481
-
482
- @access.refresh
483
- index.update_working_dir(dir, page.filename_stripped, page.format)
484
- end
485
-
486
- multi_commit ? committer : committer.commit
378
+ delete_file(page.url_path, commit)
487
379
  end
488
380
 
489
381
  # Public: Delete a file.
@@ -503,21 +395,16 @@ module Gollum
503
395
  # Returns the String SHA1 of the newly written version, or the
504
396
  # Gollum::Committer instance if this is part of a batch update.
505
397
  def delete_file(path, commit)
506
- dir = ::File.dirname(path)
507
- ext = ::File.extname(path)
508
- format = ext.split('.').last || 'txt'
509
- filename = ::File.basename(path, ext)
510
-
398
+ fullpath = ::File.join([page_file_dir, path].compact)
511
399
  multi_commit = !!commit[:committer]
512
400
  committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
513
401
 
514
- committer.delete(path)
402
+ committer.delete(fullpath)
515
403
 
516
404
  committer.after_commit do |index, _sha|
517
405
  dir = '' if dir == '.'
518
-
519
406
  @access.refresh
520
- index.update_working_dir(dir, filename, format)
407
+ index.update_working_dir(fullpath)
521
408
  end
522
409
 
523
410
  multi_commit ? committer : committer.commit
@@ -536,48 +423,12 @@ module Gollum
536
423
  # :name - The String author full name.
537
424
  # :email - The String email address.
538
425
  # :parent - Optional Gollum::Git::Commit parent to this update.
539
- #
540
426
  # Returns a String SHA1 of the new commit, or nil if the reverse diff does
541
427
  # not apply.
542
428
  def revert_page(page, sha1, sha2 = nil, commit = {})
543
- if sha2.is_a?(Hash)
544
- commit = sha2
545
- sha2 = nil
546
- end
547
-
548
- patch = full_reverse_diff_for(page, sha1, sha2)
549
- committer = Committer.new(self, commit)
550
- parent = committer.parents[0]
551
- committer.options[:tree] = @repo.git.apply_patch(parent.sha, patch)
552
- return false unless committer.options[:tree]
553
- committer.after_commit do |index, _sha|
554
- @access.refresh
555
-
556
- files = []
557
- if page
558
- files << [page.path, page.filename_stripped, page.format]
559
- else
560
- # Grit::Diff can't parse reverse diffs.... yet
561
- patch.each_line do |line|
562
- if line =~ %r(^diff --git b/.+? a/(.+)$)
563
- path = Regexp.last_match[1]
564
- ext = ::File.extname(path)
565
- name = ::File.basename(path, ext)
566
- if (format = ::Gollum::Page.format_for(ext))
567
- files << [path, name, format]
568
- end
569
- end
570
- end
571
- end
572
-
573
- files.each do |(path, name, format)|
574
- dir = ::File.dirname(path)
575
- dir = '' if dir == '.'
576
- index.update_working_dir(dir, name, format)
577
- end
578
- end
579
-
580
- committer.commit
429
+ return false unless page
430
+ left, right, options = parse_revert_options(sha1, sha2, commit)
431
+ commit_and_update_paths(@repo.git.revert_path(page.path, left, right), [page.path], options)
581
432
  end
582
433
 
583
434
  # Public: Applies a reverse diff to the repo. If only 1 SHA is given,
@@ -595,7 +446,9 @@ module Gollum
595
446
  # Returns a String SHA1 of the new commit, or nil if the reverse diff does
596
447
  # not apply.
597
448
  def revert_commit(sha1, sha2 = nil, commit = {})
598
- revert_page(nil, sha1, sha2, commit)
449
+ left, right, options = parse_revert_options(sha1, sha2, commit)
450
+ tree, files = repo.git.revert_commit(left, right)
451
+ commit_and_update_paths(tree, files, options)
599
452
  end
600
453
 
601
454
  # Public: Lists all pages for this wiki.
@@ -604,7 +457,7 @@ module Gollum
604
457
  #
605
458
  # Returns an Array of Gollum::Page instances.
606
459
  def pages(treeish = nil)
607
- tree_list(treeish || @ref)
460
+ tree_list(treeish || @ref, true, false)
608
461
  end
609
462
 
610
463
  # Public: Lists all non-page files for this wiki.
@@ -613,7 +466,7 @@ module Gollum
613
466
  #
614
467
  # Returns an Array of Gollum::File instances.
615
468
  def files(treeish = nil)
616
- file_list(treeish || @ref)
469
+ tree_list(treeish || @ref, false, true)
617
470
  end
618
471
 
619
472
  # Public: Returns the number of pages accessible from a commit
@@ -623,7 +476,7 @@ module Gollum
623
476
  # Returns a Fixnum
624
477
  def size(ref = nil)
625
478
  tree_map_for(ref || @ref).inject(0) do |num, entry|
626
- num + (@page_class.valid_page_name?(entry.name) ? 1 : 0)
479
+ num + (::Gollum::Page.valid_page_name?(entry.name) ? 1 : 0)
627
480
  end
628
481
  rescue Gollum::Git::NoSuchShaFound
629
482
  0
@@ -636,36 +489,34 @@ module Gollum
636
489
  # Returns an Array with Objects of page name and count of matches
637
490
  def search(query)
638
491
  options = {:path => page_file_dir, :ref => ref}
639
- results = {}
640
- @repo.git.grep(query, options).each do |hit|
641
- name = hit[:name]
642
- count = hit[:count]
643
- # Remove ext only from known extensions.
644
- # test.pdf => test.pdf, test.md => test
645
- file_name = Page::valid_page_name?(name) ? name.chomp(::File.extname(name)) : name
646
- results[file_name] = count.to_i
647
- end
648
-
649
- # Use ls_files '*query*' to search for file names. Grep only searches file content.
650
- # Spaces are converted to dashes when saving pages to disk.
651
- @repo.git.ls_files(query, options).each do |path|
652
- # Remove ext only from known extensions.
653
- file_name = Page::valid_page_name?(path) ? path.chomp(::File.extname(path)) : path
654
- # If there's not already a result for file_name then
655
- # the value is nil and nil.to_i is 0.
656
- results[file_name] = results[file_name].to_i + 1;
657
- end
658
-
659
- results.map do |key, val|
660
- { :count => val, :name => key }
492
+ search_terms = query.scan(/"([^"]+)"|(\S+)/).flatten.compact.map {|term| Regexp.escape(term)}
493
+ search_terms_regex = search_terms.join('|')
494
+ query = /^(.*(?:#{search_terms_regex}).*)$/i
495
+ results = @repo.git.grep(search_terms, options) do |name, data|
496
+ result = {:count => 0}
497
+ result[:name] = extract_page_file_dir(name)
498
+ result[:filename_count] = result[:name].scan(/#{search_terms_regex}/i).size
499
+ result[:context] = []
500
+ if data
501
+ begin
502
+ data.scan(query) do |match|
503
+ result[:context] << match.first
504
+ result[:count] += match.first.scan(/#{search_terms_regex}/i).size
505
+ end
506
+ rescue ArgumentError # https://github.com/gollum/gollum/issues/1491
507
+ next
508
+ end
509
+ end
510
+ ((result[:count] + result[:filename_count]) == 0) ? nil : result
661
511
  end
512
+ [results, search_terms]
662
513
  end
663
514
 
664
515
  # Public: All of the versions that have touched the Page.
665
516
  #
666
517
  # options - The options Hash:
667
- # :page - The Integer page number (default: 1).
668
- # :per_page - The Integer max count of items to return.
518
+ # :page_num - The Integer page number (default: 1).
519
+ # :per_page - The Integer max count of items to return.
669
520
  #
670
521
  # Returns an Array of Gollum::Git::Commit.
671
522
  def log(options = {})
@@ -680,7 +531,7 @@ module Gollum
680
531
  # Returns an Array of Gollum::Git::Commit.
681
532
  def latest_changes(options={})
682
533
  options[:max_count] = 10 unless options[:max_count]
683
- @repo.log(@ref, nil, options)
534
+ @repo.log(@ref, page_file_dir, options)
684
535
  end
685
536
 
686
537
  # Public: Refreshes just the cached Git reference data. This should
@@ -691,92 +542,23 @@ module Gollum
691
542
  @access.refresh
692
543
  end
693
544
 
694
- # Public: Creates a Sanitize instance using the Wiki's sanitization
695
- # options.
696
- #
697
- # Returns a Sanitize instance.
698
- def sanitizer
699
- if (options = sanitization)
700
- @sanitizer ||= options.to_sanitize
701
- end
702
- end
703
-
704
- # Public: Creates a Sanitize instance using the Wiki's history sanitization
705
- # options.
706
- #
707
- # Returns a Sanitize instance.
708
- def history_sanitizer
709
- if (options = history_sanitization)
710
- @history_sanitizer ||= options.to_sanitize
545
+ def redirects
546
+ if @redirects.nil? || @redirects.stale?
547
+ @redirects = {}.extend(::Gollum::Redirects)
548
+ @redirects.init(self)
549
+ @redirects.load
711
550
  end
551
+ @redirects
712
552
  end
713
553
 
714
- # Public: Add an additional link to the filter chain.
715
- #
716
- # name - A symbol which represents the name of a class under the
717
- # Gollum::Render namespace to insert into the chain.
718
- #
719
- # loc - A "location specifier" -- that is, where to put the new
720
- # filter in the chain. This can be one of `:first`, `:last`,
721
- # `:before => :SomeElement`, or `:after => :SomeElement`, where
722
- # `:SomeElement` (if specified) is a symbol already in the
723
- # filter chain. A `:before` or `:after` which references a
724
- # filter that doesn't exist will cause `ArgumentError` to be
725
- # raised.
726
- #
727
- # Returns nothing.
728
- def add_filter(name, loc)
729
- unless name.is_a? Symbol
730
- raise ArgumentError,
731
- "Invalid filter name #{name.inspect} (must be a symbol)"
732
- end
733
-
734
- case loc
735
- when :first
736
- @filter_chain.unshift(name)
737
- when :last
738
- @filter_chain.push(name)
739
- when Hash
740
- if loc.length != 1
741
- raise ArgumentError,
742
- "Invalid location specifier"
743
- end
744
- if ([:before, :after] && loc.keys).empty?
745
- raise ArgumentError,
746
- "Invalid location specifier"
747
- end
748
-
749
- next_to = loc.values.first
750
- relative = loc.keys.first
751
-
752
- i = @filter_chain.index(next_to)
753
- if i.nil?
754
- raise ArgumentError,
755
- "Unknown filter #{next_to.inspect}"
756
- end
757
-
758
- i += 1 if relative == :after
759
- @filter_chain.insert(i, name)
760
- else
761
- raise ArgumentError,
762
- "Invalid location specifier"
763
- end
554
+ def add_redirect(old_path, new_path)
555
+ redirects[old_path] = new_path
556
+ redirects.dump
764
557
  end
765
558
 
766
- # Remove the named filter from the filter chain.
767
- #
768
- # Returns nothing. Raises `ArgumentError` if the named filter doesn't
769
- # exist in the chain.
770
- def remove_filter(name)
771
- unless name.is_a? Symbol
772
- raise ArgumentError,
773
- "Invalid filter name #{name.inspect} (must be a symbol)"
774
- end
775
-
776
- unless @filter_chain.delete(name)
777
- raise ArgumentError,
778
- "#{name.inspect} not found in filter chain"
779
- end
559
+ def remove_redirect(path)
560
+ redirects.tap{|k| k.delete(path)}
561
+ redirects.dump
780
562
  end
781
563
 
782
564
  #########################################################################
@@ -795,15 +577,6 @@ module Gollum
795
577
  # Returns the String path.
796
578
  attr_reader :path
797
579
 
798
- # Gets the page class used by all instances of this Wiki.
799
- attr_reader :page_class
800
-
801
- # Gets the file class used by all instances of this Wiki.
802
- attr_reader :file_class
803
-
804
- # Gets the markup class used by all instances of this Wiki.
805
- attr_reader :markup_classes
806
-
807
580
  # Toggles display of universal table of contents
808
581
  attr_reader :universal_toc
809
582
 
@@ -817,8 +590,14 @@ module Gollum
817
590
  # When false, only valid pages in the git repo are displayed.
818
591
  attr_reader :show_all
819
592
 
820
- # Start with collapsed file view. Default: false
821
- attr_reader :collapse_tree
593
+ # Enable 4.x compatibility behavior for links
594
+ attr_reader :global_tag_lookup
595
+
596
+ # Enable 4.x compatibility for case-case_insensitive links
597
+ attr_reader :case_insensitive_tag_lookup
598
+
599
+ # Spaces in tag paths are treated as dashes (-)
600
+ attr_reader :hyphened_tag_lookup
822
601
 
823
602
  # Toggles file upload functionality.
824
603
  attr_reader :allow_uploads
@@ -843,72 +622,30 @@ module Gollum
843
622
  #
844
623
  # Returns the String filename.
845
624
  def page_file_name(name, format)
846
- "#{name}.#{@page_class.format_to_ext(format)}"
847
- end
848
-
849
- # Fill an array with a list of pages.
850
- #
851
- # ref - A String ref that is either a commit SHA or references one.
852
- #
853
- # Returns a flat Array of Gollum::Page instances.
854
- def tree_list(ref)
855
- if (sha = @access.ref_to_sha(ref))
856
- commit = @access.commit(sha)
857
- tree_map_for(sha).inject([]) do |list, entry|
858
- next list unless @page_class.valid_page_name?(entry.name)
859
- list << entry.page(self, commit)
860
- end
861
- else
862
- []
863
- end
625
+ format.nil? ? name : "#{name}.#{::Gollum::Page.format_to_ext(format)}"
864
626
  end
865
627
 
866
- # Fill an array with a list of files.
628
+ # Fill an array with a list of pages and files in the wiki.
867
629
  #
868
630
  # ref - A String ref that is either a commit SHA or references one.
869
631
  #
870
- # Returns a flat Array of Gollum::File instances.
871
- def file_list(ref)
632
+ # Returns a flat Array of Gollum::Page and Gollum::File instances.
633
+ def tree_list(ref = @ref, pages=true, files=true)
872
634
  if (sha = @access.ref_to_sha(ref))
873
635
  commit = @access.commit(sha)
874
636
  tree_map_for(sha).inject([]) do |list, entry|
875
- next list if entry.name.start_with?('_')
876
- next list if @page_class.valid_page_name?(entry.name)
877
- list << entry.file(self, commit)
637
+ if ::Gollum::Page.valid_page_name?(entry.name)
638
+ list << entry.page(self, commit) if pages
639
+ elsif files && !entry.name.start_with?('_') && !::Gollum::Page.protected_files.include?(entry.name)
640
+ list << entry.file(self, commit)
641
+ end
642
+ list
878
643
  end
879
644
  else
880
645
  []
881
646
  end
882
647
  end
883
648
 
884
- # Creates a reverse diff for the given SHAs on the given Gollum::Page.
885
- #
886
- # page - The Gollum::Page to scope the patch to, or a String Path.
887
- # sha1 - String SHA1 of the earlier parent if two SHAs are given,
888
- # or the child.
889
- # sha2 - Optional String SHA1 of the child.
890
- #
891
- # Returns a String of the reverse Diff to apply.
892
- def full_reverse_diff_for(page, sha1, sha2 = nil)
893
- sha1, sha2 = "#{sha1}^", sha1 if sha2.nil?
894
- if page
895
- path = (page.respond_to?(:path) ? page.path : page.to_s)
896
- return repo.diff(sha2, sha1, path).first.diff
897
- end
898
- repo.diff(sha2, sha1).map { |d| d.diff }.join("\n")
899
- end
900
-
901
- # Creates a reverse diff for the given SHAs.
902
- #
903
- # sha1 - String SHA1 of the earlier parent if two SHAs are given,
904
- # or the child.
905
- # sha2 - Optional String SHA1 of the child.
906
- #
907
- # Returns a String of the reverse Diff to apply.
908
- def full_reverse_diff(sha1, sha2 = nil)
909
- full_reverse_diff_for(nil, sha1, sha2)
910
- end
911
-
912
649
  # Gets the default name for commits.
913
650
  #
914
651
  # Returns the String name.
@@ -943,7 +680,7 @@ module Gollum
943
680
  # ignore_page_file_dir - Boolean, if true, searches all files within the git repo, regardless of dir/subdir
944
681
  #
945
682
  # Returns an Array of BlobEntry instances.
946
- def tree_map_for(ref, ignore_page_file_dir=false)
683
+ def tree_map_for(ref, ignore_page_file_dir = false)
947
684
  if ignore_page_file_dir && !@page_file_dir.nil?
948
685
  @root_access ||= GitAccess.new(path, nil, @repo_is_bare)
949
686
  @root_access.tree(ref)
@@ -957,5 +694,80 @@ module Gollum
957
694
  def inspect
958
695
  %(#<#{self.class.name}:#{object_id} #{@repo.path}>)
959
696
  end
697
+
698
+ # Public: Creates a Sanitize instance
699
+ #
700
+ # Returns a Sanitize instance.
701
+ def sanitizer
702
+ @sanitizer ||= Gollum::Sanitization.new(Gollum::Markup.to_xml_opts)
703
+ end
704
+
705
+ private
706
+
707
+ def parse_revert_options(sha1, sha2, commit = {})
708
+ if sha2.is_a?(Hash)
709
+ return "#{sha1}^", sha1, sha2
710
+ elsif sha2.nil?
711
+ return "#{sha1}^", sha1, commit
712
+ else
713
+ return sha1, sha2, commit
714
+ end
715
+ end
716
+
717
+ def commit_and_update_paths(tree, paths, options)
718
+ return false unless tree
719
+ committer = Committer.new(self, options)
720
+ parent = committer.parents[0]
721
+
722
+ committer.options[:tree] = tree
723
+
724
+ committer.after_commit do |index, _sha|
725
+ @access.refresh
726
+
727
+ paths.each do |path|
728
+ index.update_working_dir(path)
729
+ end
730
+ end
731
+
732
+ committer.commit
733
+ end
734
+
735
+ # Conjoins elements of a page or file path and prefixes the page_file_dir.
736
+ # Throws Gollum::IllegalDirectoryPath if page_file_dir is set, and the resulting
737
+ # path is not below it (e.g. if the dir or name contained '../')
738
+ #
739
+ # dir - The String directory path
740
+ # name - The String name of the Page or File
741
+ # format - The Symbol format of the page. Should be nil for Files.
742
+ #
743
+ # Returns a String path. .
744
+ def merge_path_elements(dir, name, format)
745
+ result = ::File.join([@page_file_dir, dir, self.page_file_name(name, format)].compact)
746
+ result = Pathname.new(result).cleanpath.to_s
747
+ if @page_file_dir
748
+ raise Gollum::IllegalDirectoryPath unless result.start_with?("#{@page_file_dir}/")
749
+ result
750
+ else
751
+ result[0] == '/' ? result[1..-1] : result
752
+ end
753
+ end
754
+
755
+ def extract_page_file_dir(path)
756
+ @page_file_dir ? path[@page_file_dir.length+1..-1] : path
757
+ end
758
+
759
+ def write(path, data, commit = {}, force_overwrite = false)
760
+ multi_commit = !!commit[:committer]
761
+ committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
762
+ committer.add_to_index(path, data, commit, force_overwrite)
763
+
764
+ committer.after_commit do |index, _sha|
765
+ @access.refresh
766
+ index.update_working_dir(path)
767
+ end
768
+
769
+ multi_commit ? committer : committer.commit
770
+ end
771
+
960
772
  end
961
773
  end