diff --git a/backend/app/controllers/wiki_pages_controller.rb b/backend/app/controllers/wiki_pages_controller.rb index 4943fbf..fb465a3 100644 --- a/backend/app/controllers/wiki_pages_controller.rb +++ b/backend/app/controllers/wiki_pages_controller.rb @@ -31,17 +31,20 @@ class WikiPagesController < ApplicationController def diff id = params[:id] - from = params[:from] + return head :bad_request if id.blank? + + from = params[:from].presence to = params[:to].presence - return head :bad_request if id.blank? || from.blank? 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 - 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| case change.action when ?= @@ -58,7 +61,7 @@ class WikiPagesController < ApplicationController render json: { wiki_page_id: page.id, title: page.title, - older_revision_id: from_rev.id, + older_revision_id: from_rev&.id, newer_revision_id: to_rev.id, diff: diff_json } end diff --git a/backend/app/models/wiki_line.rb b/backend/app/models/wiki_line.rb index 7a1b4e2..c169917 100644 --- a/backend/app/models/wiki_line.rb +++ b/backend/app/models/wiki_line.rb @@ -8,7 +8,7 @@ class WikiLine < ApplicationRecord sha = Digest::SHA256.hexdigest(body) 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) end diff --git a/backend/lib/tasks/migrate_wiki.rake b/backend/lib/tasks/migrate_wiki.rake new file mode 100644 index 0000000..1fd7ad1 --- /dev/null +++ b/backend/lib/tasks/migrate_wiki.rake @@ -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 diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 46cacce..0dccb59 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -84,7 +84,7 @@ export type WikiPageDiff = { wikiPageId: number title: string olderRevisionId: number | null - newerRevisionId: number | null + newerRevisionId: number diff: WikiPageDiffDiff[] } export type WikiPageDiffDiff = {