2007-05-01 (Tue) [長年日記]

リポジトリ壊れた

WebDAVで外部に公開していたsvnリポジトリが、いつのまにか壊れていた。リポジトリタイプはfsfs。普通にチェックアウトできていたので気がつかなかったが、ふと思い立ってダンプしてみると最後まで終わらずにエラーで止まる。db/revs以下を見てみると途中のリビジョン情報のいくつかが消えて失われているようだ。

恐らくfsfsが不安定だったバージョンの時期に発生しているのだろうけれど、チェックアウトもアップデートもできていたので気づくのが遅れてしまった。また、バックアップも--delete付きでrsyncを走らせていたため、消滅したファイルはバックアップ先でも消滅してしまっていた。

直近のリビジョンは取得できることと、以前のダンプファイルがあるので大事には至らなかったが、 やっぱし定期的にダンプしたものもバックアップしておいたほうがよさそう。

ということで複数のリポジトリをぐるぐるとダンプして回るRakeを作って対処してみた。

# -*- mode: ruby -*-
#
require 'rake'
require 'date'

SVNADMIN_CMD = '/usr/local/bin/svnadmin'
BACKUP_DIR = '/home/svn/backups'
SVNROOT_BASE = '/home/svn'
SVNROOTS = ['foo1', 'foo2']

desc "svn repository backups"
task :svnbackup do
  SVNROOTS.each do |root|
    svndump root
  end
end

def svndump(root)
  Dir["#{SVNROOT_BASE}/#{root}/**"].each do |dir|
    mkdir "#{BACKUP_DIR}/#{root}" unless File.directory?("#{BACKUP_DIR}/#{root}")
    sh "#{SVNADMIN_CMD} dump #{dir} > #{BACKUP_DIR}/#{root}/#{File.basename(dir)}-#{Date.today.strftime('%Y-%m-%d')}.dump"
  end

  Dir["#{BACKUP_DIR}/#{root}/**/*.dump"].each do |file|
    sh "/usr/bin/gzip -9 -f #{file}"
  end
end

Tags: Subversion

ソースコードの色づけ

実はリポジトリ壊れたのに気がついたのは、結構前のことなので単になにかのソース貼り付けたかっただけだったりして。

前々からソースコードを貼り付けたときにシンタックスのハイライトが欲しいと思っていて、綺麗に整形して行番号や印刷やクリップボードやらと機能的なdp.SyntaxHighlighterが気になりまくりであったが、elisp未対応なので、よくelispコードを貼ってる白井さんのために断念。

Gonzuiから分かれたLangScanを使うことにしてみた。対応言語がやけに多くてとても良い。

使い方

こんな感じに書くと

 {{code(<<-'EOS', 'elisp')
  (lambda (x) (+ x 1))
  EOS
  }}

こうなります。

(lambda (x) (+ x 1))

Rubyだと

 {{code(<<-'EOS', 'ruby')
  class Duck
    def hello
      p "hello."
    end
  end
  EOS
  }}

こんな感じ。

class Duck
  def hello
    p "hello."
  end
end

codelist.rbプラグイン

codeプラグインは、こちらのcodelist.rbにちょこっと手を入れて使ってる。

2番目の引数で言語を指定するが、言語をあらわす文字列でもLangScanのシンボルを直接渡してもどちらでも動くようにした。

対応言語と文字列一覧は以下。

"autoconf" == LangScan::Autoconf
"automake" == LangScan::Automake
"bf" == LangScan::Brainfuck
"c" == LangScan::C
"csharp" == LangScan::Csharp
"css" == LangScan::CSS
"d" == LangScan::D
"eiffel" == LangScan::Eiffel
"elisp" == LangScan::EmacsLisp
"io" == LangScan::Io
"java" == LangScan::Java
"js" == LangScan::JavaScript
"lua" == LangScan::Lua
"ocaml" == LangScan::OCaml
"perl" == LangScan::Perl
"php" == LangScan::PHP
"python" == LangScan::Python
"rpmspec" == LangScan::RPMSpec
"ruby" == LangScan::Ruby
"scheme" == LangScan::Scheme
"sh" == LangScan::Shell
"text" == LangScan::Text

変更したcodelist.rbプラグイン

require 'langscan'

module LangScan
  def self.choose_by_abbrev(hint)
    ::LangScan::LangScanRegistry.each_value {|scanner|
      return scanner if hint.downcase == scanner.abbrev
    }
    ::LangScan::Text
  end
end

Highlight_type = [
  :fundef, :funcall, :classdef, :moduledef, :comment, :string,
  :keyword, :const, :character, :type
]

add_header_proc do
  %Q[\n]
end

def codelist(file)
  scanner = LangScan.choose(file)
  scanner = LangScan::Text unless scanner
  code(File.open(file).readlines.join, scanner)
end

def code(content, scanner = LangScan::Text)
  scanner = LangScan.choose_by_abbrev(scanner) if scanner.kind_of? String
  contents = []
  scanner.scan(content) {|f|
    text = if Highlight_type.include?(f.type)
             "#{CGI.escapeHTML(f.text)}"
           else
             CGI.escapeHTML(f.text)
           end
    f.text = text
    contents.push(f)
  }
  contents.sort! {|a, b| a.byteno <=> b.byteno }
  ret = "
\n"
  contents.each {|f|
    ret << f.text
  }
  ret << "
\n" return ret end

行番号対応はそのうち...

参考

Tags: tDiary