project_wiki.rb 4.2 KB
Newer Older
D
Dmitriy Zaporozhets 已提交
1 2 3 4
class ProjectWiki
  include Gitlab::ShellAdapter

  MARKUPS = {
5
    'Markdown' => :markdown,
6 7
    'RDoc'     => :rdoc,
    'AsciiDoc' => :asciidoc
8
  } unless defined?(MARKUPS)
D
Dmitriy Zaporozhets 已提交
9 10 11 12 13 14

  class CouldNotCreateWikiError < StandardError; end

  # Returns a string describing what went wrong after
  # an operation fails.
  attr_reader :error_message
V
Valery Sizov 已提交
15
  attr_reader :project
D
Dmitriy Zaporozhets 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29

  def initialize(project, user = nil)
    @project = project
    @user = user
  end

  def path
    @project.path + '.wiki'
  end

  def path_with_namespace
    @project.path_with_namespace + ".wiki"
  end

30 31 32 33
  def web_url
    Gitlab::Routing.url_helpers.namespace_project_wiki_url(@project.namespace, @project, :home)
  end

D
Dmitriy Zaporozhets 已提交
34 35 36 37 38 39 40 41 42 43 44 45
  def url_to_repo
    gitlab_shell.url_to_repo(path_with_namespace)
  end

  def ssh_url_to_repo
    url_to_repo
  end

  def http_url_to_repo
    [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
  end

46
  def wiki_base_path
47
    [Gitlab.config.gitlab.relative_url_root, "/", @project.path_with_namespace, "/wikis"].join('')
48 49
  end

D
Dmitriy Zaporozhets 已提交
50 51 52 53
  # Returns the Gollum::Wiki object.
  def wiki
    @wiki ||= begin
      Gollum::Wiki.new(path_to_repo)
54
    rescue Rugged::OSError
D
Dmitriy Zaporozhets 已提交
55 56 57 58
      create_repo!
    end
  end

59 60 61 62
  def repository_exists?
    !!repository.exists?
  end

D
Dmitriy Zaporozhets 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  def empty?
    pages.empty?
  end

  # Returns an Array of Gitlab WikiPage instances or an
  # empty Array if this Wiki has no pages.
  def pages
    wiki.pages.map { |page| WikiPage.new(self, page, true) }
  end

  # Finds a page within the repository based on a tile
  # or slug.
  #
  # title - The human readable or parameterized title of
  #         the page.
  #
  # Returns an initialized WikiPage instance or nil
  def find_page(title, version = nil)
M
Marin Jankovski 已提交
81 82
    page_title, page_dir = page_title_and_dir(title)
    if page = wiki.page(page_title, version, page_dir)
D
Dmitriy Zaporozhets 已提交
83 84 85 86 87 88
      WikiPage.new(self, page, true)
    else
      nil
    end
  end

89 90 91 92 93 94 95 96 97
  def find_file(name, version = nil, try_on_disk = true)
    version = wiki.ref if version.nil? # Gollum::Wiki#file ?
    if wiki_file = wiki.file(name, version, try_on_disk)
      wiki_file
    else
      nil
    end
  end

D
Dmitriy Zaporozhets 已提交
98 99 100
  def create_page(title, content, format = :markdown, message = nil)
    commit = commit_details(:created, message, title)

101
    wiki.write_page(title, format.to_sym, content, commit)
102 103

    update_project_activity
D
Dmitriy Zaporozhets 已提交
104 105 106 107 108 109 110 111
  rescue Gollum::DuplicatePageError => e
    @error_message = "Duplicate page: #{e.message}"
    return false
  end

  def update_page(page, content, format = :markdown, message = nil)
    commit = commit_details(:updated, message, page.title)

112
    wiki.update_page(page, page.name, format.to_sym, content, commit)
113 114

    update_project_activity
D
Dmitriy Zaporozhets 已提交
115 116 117 118
  end

  def delete_page(page, message = nil)
    wiki.delete_page(page, commit_details(:deleted, message, page.title))
119 120

    update_project_activity
D
Dmitriy Zaporozhets 已提交
121 122
  end

M
Marin Jankovski 已提交
123
  def page_title_and_dir(title)
124
    title_array = title.split("/")
M
Marin Jankovski 已提交
125
    title = title_array.pop
S
Stan Hu 已提交
126
    [title, title_array.join("/")]
M
Marin Jankovski 已提交
127 128
  end

D
Dmitriy Zaporozhets 已提交
129
  def search_files(query)
V
Valery Sizov 已提交
130
    repository.search_files_by_content(query, default_branch)
D
Dmitriy Zaporozhets 已提交
131 132 133
  end

  def repository
134
    @repository ||= Repository.new(path_with_namespace, @project)
D
Dmitriy Zaporozhets 已提交
135 136 137 138 139 140
  end

  def default_branch
    wiki.class.default_ref
  end

D
Dmitriy Zaporozhets 已提交
141 142
  def create_repo!
    if init_repo(path_with_namespace)
143
      wiki = Gollum::Wiki.new(path_to_repo)
D
Dmitriy Zaporozhets 已提交
144 145 146
    else
      raise CouldNotCreateWikiError
    end
147 148 149 150

    repository.after_create

    wiki
D
Dmitriy Zaporozhets 已提交
151
  end
G
Gabriel Mazetto 已提交
152

153 154 155 156 157 158
  def hook_attrs
    {
      web_url: web_url,
      git_ssh_url: ssh_url_to_repo,
      git_http_url: http_url_to_repo,
      path_with_namespace: path_with_namespace,
G
Gabriel Mazetto 已提交
159
      default_branch: default_branch
160 161
    }
  end
D
Dmitriy Zaporozhets 已提交
162

163 164 165 166
  def repository_storage_path
    project.repository_storage_path
  end

167 168
  private

D
Dmitriy Zaporozhets 已提交
169
  def init_repo(path_with_namespace)
170
    gitlab_shell.add_repository(project.repository_storage_path, path_with_namespace)
D
Dmitriy Zaporozhets 已提交
171 172 173 174 175
  end

  def commit_details(action, message = nil, title = nil)
    commit_message = message || default_message(action, title)

176
    { email: @user.email, name: @user.name, message: commit_message }
D
Dmitriy Zaporozhets 已提交
177 178 179 180 181 182 183
  end

  def default_message(action, title)
    "#{@user.username} #{action} page: #{title}"
  end

  def path_to_repo
184
    @path_to_repo ||= File.join(project.repository_storage_path, "#{path_with_namespace}.git")
D
Dmitriy Zaporozhets 已提交
185
  end
186 187 188 189

  def update_project_activity
    @project.touch(:last_activity_at)
  end
D
Dmitriy Zaporozhets 已提交
190
end