1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# frozen_string_literal: true
module Gitlab
module Git
class Wiki
include Gitlab::Git::WrapsGitalyErrors
DuplicatePageError = Class.new(StandardError)
DEFAULT_PAGINATION = Kaminari.config.default_per_page
CommitDetails = Struct.new(:user_id, :username, :name, :email, :message) do
def to_h
{ user_id: user_id, username: username, name: name, email: email, message: message }
end
end
# GollumSlug inlines just enough knowledge from Gollum::Page to generate a
# slug, which is used when previewing pages that haven't been persisted
class GollumSlug
class << self
def cname(name, char_white_sub = '-', char_other_sub = '-')
if name.respond_to?(:gsub)
name.gsub(/\s/, char_white_sub).gsub(/[<>+]/, char_other_sub)
else
''
end
end
def format_to_ext(format)
format == :markdown ? "md" : format.to_s
end
def canonicalize_filename(filename)
::File.basename(filename, ::File.extname(filename)).tr('-', ' ')
end
def generate(title, format)
ext = format_to_ext(format.to_sym)
name = cname(title) + '.' + ext
canonical_name = canonicalize_filename(name)
path =
if name.include?('/')
name.sub(%r{/[^/]+$}, '/')
else
''
end
path + cname(canonical_name, '-', '-')
end
end
end
attr_reader :repository
# TODO remove argument when issue
# https://gitlab.com/gitlab-org/gitlab/-/issues/329190
# is closed.
def self.default_ref(container = nil)
Gitlab::DefaultBranch.value(object: container)
end
# Initialize with a Gitlab::Git::Repository instance
def initialize(repository)
@repository = repository
end
def repository_exists?
@repository.exists?
end
def list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
wrapped_gitaly_errors do
gitaly_list_pages(
limit: limit,
sort: sort,
direction_desc: direction_desc,
load_content: load_content
)
end
end
def page(title:, version: nil, dir: nil, load_content: true)
wrapped_gitaly_errors do
gitaly_find_page(title: title, version: version, dir: dir, load_content: load_content)
end
end
def count_page_versions(page_path)
@repository.count_commits(ref: 'HEAD', path: page_path)
end
def preview_slug(title, format)
GollumSlug.generate(title, format)
end
private
def gitaly_wiki_client
@gitaly_wiki_client ||= Gitlab::GitalyClient::WikiService.new(@repository)
end
def gitaly_find_page(title:, version: nil, dir: nil, load_content: true)
return unless title.present?
wiki_page, version = gitaly_wiki_client.find_page(title: title, version: version, dir: dir, load_content: load_content)
return unless wiki_page
Gitlab::Git::WikiPage.from_gitaly_wiki_page(wiki_page, version)
rescue GRPC::InvalidArgument
nil
end
def gitaly_list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
params = { limit: limit, sort: sort, direction_desc: direction_desc }
gitaly_pages =
if load_content
gitaly_wiki_client.load_all_pages(**params)
else
gitaly_wiki_client.list_all_pages(**params)
end
gitaly_pages.map do |wiki_page, version|
Gitlab::Git::WikiPage.from_gitaly_wiki_page(wiki_page, version)
end
end
end
end
end
|