feat: Wiki の管理方法変更(#188) #195
@@ -31,17 +31,20 @@ class WikiPagesController < ApplicationController
|
|||||||
|
|
||||||
def diff
|
def diff
|
||||||
id = params[:id]
|
id = params[:id]
|
||||||
from = params[:from]
|
return head :bad_request if id.blank?
|
||||||
|
|
||||||
|
from = params[:from].presence
|
||||||
to = params[:to].presence
|
to = params[:to].presence
|
||||||
return head :bad_request if id.blank? || from.blank?
|
|
||||||
|
|
||||||
page = WikiPage.find(id)
|
page = WikiPage.find(id)
|
||||||
|
|
||||||
from_rev = page.wiki_revisions.find(from)
|
from_rev = from && page.wiki_revisions.find(from)
|
||||||
to_rev = to ? page.wiki_revisions.find(to) : page.current_revision
|
to_rev = to ? page.wiki_revisions.find(to) : page.current_revision
|
||||||
return head :unprocessable_entity if !(from_rev&.content?) || !(to_rev&.content?)
|
if ((from_rev && !(from_rev.content?)) || !(to_rev&.content?))
|
||||||
|
return head :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
diffs = Diff::LCS.sdiff(from_rev.body.lines, to_rev.body.lines)
|
diffs = Diff::LCS.sdiff(from_rev&.body&.lines || [], to_rev.body.lines)
|
||||||
diff_json = diffs.map { |change|
|
diff_json = diffs.map { |change|
|
||||||
case change.action
|
case change.action
|
||||||
when ?=
|
when ?=
|
||||||
@@ -58,7 +61,7 @@ class WikiPagesController < ApplicationController
|
|||||||
|
|
||||||
render json: { wiki_page_id: page.id,
|
render json: { wiki_page_id: page.id,
|
||||||
title: page.title,
|
title: page.title,
|
||||||
older_revision_id: from_rev.id,
|
older_revision_id: from_rev&.id,
|
||||||
newer_revision_id: to_rev.id,
|
newer_revision_id: to_rev.id,
|
||||||
diff: diff_json }
|
diff: diff_json }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class WikiLine < ApplicationRecord
|
|||||||
sha = Digest::SHA256.hexdigest(body)
|
sha = Digest::SHA256.hexdigest(body)
|
||||||
now = Time.current
|
now = Time.current
|
||||||
|
|
||||||
upsert({ sha256: sha, body:, created_at: now, updated_at: now }, unique_by: :sha256)
|
upsert({ sha256: sha, body:, created_at: now, updated_at: now })
|
||||||
|
|
||||||
find_by!(sha256: sha)
|
find_by!(sha256: sha)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
namespace :wiki do
|
||||||
|
desc 'Wiki 移行'
|
||||||
|
task migrate: :environment do
|
||||||
|
require 'digest'
|
||||||
|
require 'gollum-lib'
|
||||||
|
|
||||||
|
wiki = Gollum::Wiki.new(Rails.root.join('wiki').to_s)
|
||||||
|
|
||||||
|
WikiPage.where.missing(:wiki_revisions).find_each do |wiki_page|
|
||||||
|
page = wiki.page("#{ wiki_page.id }.md")
|
||||||
|
next unless page
|
||||||
|
|
||||||
|
versions = page.versions
|
||||||
|
next if versions.blank?
|
||||||
|
|
||||||
|
base_revision_id = nil
|
||||||
|
versions.reverse_each do |version|
|
||||||
|
pg = wiki.page("#{ wiki_page.id }.md", version.id)
|
||||||
|
raw = pg&.raw_data
|
||||||
|
next unless raw
|
||||||
|
|
||||||
|
lines = raw.force_encoding('UTF-8').split("\n")
|
||||||
|
|
||||||
|
line_shas = lines.map { |l| Digest::SHA256.hexdigest(l) }
|
||||||
|
tree_sha = Digest::SHA256.hexdigest(line_shas.join(','))
|
||||||
|
|
||||||
|
at = version.authored_date
|
||||||
|
|
||||||
|
line_id_by_sha = WikiLine.where(sha256: line_shas).pluck(:sha256, :id).to_h
|
||||||
|
|
||||||
|
missing_rows = []
|
||||||
|
line_shas.each_with_index do |sha, i|
|
||||||
|
next if line_id_by_sha.key?(sha)
|
||||||
|
|
||||||
|
missing_rows << { sha256: sha,
|
||||||
|
body: lines[i],
|
||||||
|
created_at: at,
|
||||||
|
updated_at: at }
|
||||||
|
end
|
||||||
|
|
||||||
|
if missing_rows.any?
|
||||||
|
WikiLine.upsert_all(missing_rows)
|
||||||
|
line_id_by_sha = WikiLine.where(sha256: line_shas).pluck(:sha256, :id).to_h
|
||||||
|
end
|
||||||
|
line_ids = line_shas.map { |sha| line_id_by_sha.fetch(sha) }
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
wiki_page.lock!
|
||||||
|
|
||||||
|
rev = WikiRevision.create!(
|
||||||
|
wiki_page:,
|
||||||
|
base_revision_id:,
|
||||||
|
created_user_id: Integer(version.author.name) rescue 2,
|
||||||
|
kind: :content,
|
||||||
|
redirect_page_id: nil,
|
||||||
|
message: nil,
|
||||||
|
lines_count: lines.length,
|
||||||
|
tree_sha256: tree_sha,
|
||||||
|
created_at: at,
|
||||||
|
updated_at: at)
|
||||||
|
|
||||||
|
rows = line_ids.each_with_index.map do |line_id, pos|
|
||||||
|
{ wiki_revision_id: rev.id,
|
||||||
|
wiki_line_id: line_id,
|
||||||
|
position: pos }
|
||||||
|
end
|
||||||
|
WikiRevisionLine.insert_all!(rows)
|
||||||
|
end
|
||||||
|
base_revision_id = rev.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -84,7 +84,7 @@ export type WikiPageDiff = {
|
|||||||
wikiPageId: number
|
wikiPageId: number
|
||||||
title: string
|
title: string
|
||||||
olderRevisionId: number | null
|
olderRevisionId: number | null
|
||||||
newerRevisionId: number | null
|
newerRevisionId: number
|
||||||
diff: WikiPageDiffDiff[] }
|
diff: WikiPageDiffDiff[] }
|
||||||
|
|
||||||
export type WikiPageDiffDiff = {
|
export type WikiPageDiffDiff = {
|
||||||
|
|||||||
Reference in New Issue
Block a user