本当はコードを書きたいんだけど、うまくアイディアが出てこないとか考えるのに使えるまとまった時間が足りないとか、なんか寝坊しちゃうとか昼寝しちゃうとか。
なんかそんな感じでダラダラしてる。まー休みなんだし、ダラダラすればいいのよ。勉強会に出たり git push しないといけないような強迫観念など不用なのよ。
疲れが取れてない気もするし、ちょっとよろしくない感じ。もっとダラダラ。ずっとダラダラ。
そう言えばものすごく久しぶりにSUBWAY食べた。店舗には石川県初進出って書いてあって、それはちょっと嘘書いちゃいかんよと思った。金沢は初めてだが松任にはあったぞ。
久しぶりすぎて思い出せないんだけど、バジルソースってなかったっけ。バジルマヨネーズだった。マヨネーズは好きじゃないのよね。
パンが柔らかくておいしかった。最近ああいうパンを出す店はあまりないのでとても好印象。金沢の人の新しもの好きが落ち着いたら贔屓にしようと思う。落ち着いたらなくなるかもしれんけど。
もう2, 3店舗くらい出してくれないかな。ちょっと不便。
て、RFC に
RFC 4627 - The application/json Media Type for JavaScript Object Notation (JSON)
なってるし、YAML と違って結構いろんな言語でちゃんとサポートされてるので、シリアライズ形式として優れているなと思っています。1
ただなんかちょっと腑に落ちないところがあって、上の RFC に以下のように書かれてるんですよね。
Any character may be escaped. If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. The hexadecimal letters A though F can be upper or lowercase. So, for example, a string containing only a single reverse solidus character may be represented as "\u005C".
2.5. Strings より。
で、
may ってどないやねん
と2。
ただまぁ現実的には生で書くわけじゃないので、ライブラリの挙動が合ってればそれでよく、実際、
- PHP
- Ruby
- JavaScript
で
- PHP -> JavaScript
- Ruby -> PHP
- PHP -> Ruby
の3つではすべて日本語は \u 形式で表現され、それで問題なく解釈できるという動きになってます。
まぁ、そういうことなんでしょうねぇ。
svnadmin dump した結果をスクリプトと手作業で編集して svnadmin load するのに成功した。まぁ成功して当たり前なんだけど、一応メモ。使ったのは svn 1.4.2 と Ruby 1.8.5 とエディタ。
svndumpfilter はそんなに使えない
svnadmin dump の結果に対して path で単純なフィルタリングを行う svndumpfilter というものがあるが、これを適用しても特に以下のようなリポジトリレイアウトの場合、あまり役に立たない。
branches/
各モジュール/
...
tags/
...
trunk/
...
このツールは以下のようなレイアウトになっていて、
モジュール/
branches/
tags/
trunk/
モジュール/
branches/
...
...
ここで言うモジュール単位に分割する際には使える。つまり、リポジトリそのものの操作がのちのち楽なのは後者のレイアウト。
新規にリポジトリを作成する場合はともかく、cvs2svn で既存のリポジトリを変換する場合は何も考えないと前者のレイアウトになってしまうので注意が必要。
※ その他にも cvs2svn は svn:eol-style を native にしてしまうのでクライアントのプラットフォームが混ざっている場合に思わぬ不具合を引き起こす可能性がある。
dump したテキストファイルは mbox のような感じ
なので、mbox っぽいデータを自分でパースしたことのある人ならなんとかなります。XML ではないのでデータの終わりは明示されず、始まりしか明示されないので、始まりの区切りをそこまでのデータの終わりとして機能させれば ok.
ただし改行コードは混ざっているので注意。パースする際に改行コードを無造作に chop しちゃダメ。
タグを打った操作の追跡時に注意が必要
svn copy は特定のパスだけを copy する作業がなかなかやりにくい。これが cvs2svn を使ってリポジトリを変換した際、タグを打つ操作に対応する revision を見るとなるほどと思う。丸ごといちばん上の階層から copy して、不要なパスを delete している。このとき、この delete するパスが存在していないと load の際に失敗する。
つまり、
branches/
..
trunk/
path1/
path2/
tags/
..
というリポジトリがあり、
branches/
path1/
trunk/
path1/
のように path1 だけを取り出したいという場合、最初の方の revision で path2 を add する作業をカットしてあると、copy -> delete のコンボ revision の中で path2 を delete するアクションがあってはいけない。
でもまぁ手作業対応もそれなりに可能
今回はまだリポジトリの full dump が 124MB、取り出したい部分の dump ファイルが 26MB で収まっていたので、なんとかエディタで開いてスクリプトで対処しきれなかった余計な部分のカット、逆にスクリプトで取り除きすぎてしまった部分を full dump から戻す作業を行えた。(重かったけど。)ブランチの数もせいぜい数十。
ただこのレベルを越えるとなるともっと精度の高いフィルタが必要だなとは思った。
使ったスクリプト
本当はできるだけ手作業を減らそうと、revision ごとに dump ファイルを分割する機能をつけて、保全した revision の差分を取ってゴニョゴニョ(まだあまり考えていない)する機能をつけようと思っていたのですが、面倒くさくなったので放置です。
実に中途半端な状態ですが、とりあえずバックアップ目的で貼っておきます。なんか使えそうならご自由に。
#! /usr/bin/env ruby
require 'pathname'
require 'logger'
=begin
Subversion の dump ファイルから特定の条件を満たす node および revision
だけの dump ファイルを生成する。
Usage: ruby SCRIPT srcdump > destdump
Revision について
=================
Prop-content-length: は当然ヘッダ部以降 PROPS-END までのサイズ。
Content-length: は Prop-content-length と同じ。この数字は Node の
content-length に影響されない。つまり、Revision の途中で Node がバッサ
リ落ちても影響ない
ただし Node をただ単独で落とすと cvs2svn が作る、丸ごと copy してから要
らないものを削除するという revision に対応できないことがある。
Node-copy* という文字列を見つけたら Revision 丸ごと保存したい。
Node について
=============
Prop-content-length: はヘッダ部以降 PROPS-END までのデータのサイズ
Text-content-length: は PROPS-END 以降次のヘッダまでのデータのサイズ
Content-length: は上の content-length の合計
=end
#
# svnadmin dump した結果を処理するツール
#
module Svndump
#
# パースした node および revision に対する共通メソッド
#
class Common
def initialize( loglevel = nil )
_init_logger( loglevel )
@curr_rev = nil
@curr_node = nil
@buf = []
@revs = []
end
#
# Logger の初期化
#
def _init_logger( level = nil )
if ( level.nil? )
return false
end
@logger = Logger.new( STDERR )
case level
when 'debug'
@logger.level = Logger::DEBUG
when 'info'
@logger.level = Logger::INFO
when 'warn'
@logger.level = Logger::WARN
when 'error'
@logger.level = Logger::ERROR
else # include 'fatal'
@logger.level = Logger::FATAL
end
return true
end
private :_init_logger
#
# 指定ファイルまたは標準入力から dump ファイルを読み込みあれこれ
#
# 行ごとに分割して特徴的なヘッダ行をもとに pre_hook, post_hook を定義
# chomp() しない。改行コードが混ざっている可能性があるので。
#
def read
while ( line = gets )
case line
when /\ARevision-number: ([0-9]+)/
revision_pre_hook()
@curr_rev = $1.to_i
@curr_node = nil
revision_post_hook()
when /\ANode-path: (.*)/
node_pre_hook()
@curr_node = $1
node_post_hook()
when /\ANode-copy/
nodecopy_pre_hook()
end
@buf.push( line )
end
end # of read()
def revision_pre_hook
end
def revision_post_hook
end
def node_pre_hook
end
def node_post_hook
end
def nodecopy_pre_hook
end
def clear_rev_buf
@rev_buf = []
@keep_rev = false
end
private :clear_rev_buf
def clear_buf
@buf = []
@storable = true
end
private :clear_buf
end # of class Common
#
# dump ファイルを各 revision ごとに分割する
#
class Splitter < Common
end
#
# 小さくする
#
class Compact < Common
#
# コンストラクタ
#
def initialize( loglevel = nil )
super( loglevel )
@dump_header = true
@keep_rev = false
@rev_buf = []
@storable = true
end
#
# 主処理
#
def run
read()
after_all()
end
#
# Revision-number の切り替わりのタイミングで呼ばれるメソッド
#
def revision_pre_hook
if ( !@logger.nil? )
@logger.debug( "in revision_pre_hook() rev #{@curr_rev} node #{@curr_node}" )
end
store2rev()
output_rev()
if ( @curr_rev == 0 )
@dump_header = nil
end
end
#
# Revision-number の行を読んだ瞬間に働く hook
#
def revision_post_hook
end
#
# Node-path の切り替わりのタイミングで呼ばれるメソッド
#
def node_pre_hook
if ( !@logger.nil? )
@logger.debug( "in node_pre_hook() rev #{@curr_rev} node #{@curr_node}" )
end
store2rev()
end
#
# Node-path の行を読んだ瞬間に働く hook
#
def node_post_hook
end
#
# Node-copy* 行が現れるタイミングで呼ばれるメソッド
#
def nodecopy_pre_hook
@keep_rev = true
end
#
# 全部読み終わった時点で呼ばれるメソッド
#
def after_all
if ( !@logger.nil? )
@logger.debug( "in after_all() rev #{@curr_rev} node #{@curr_node}" )
end
store2rev()
output_rev()
end
#
# 現在の @buf の内容を保存するかどうか
#
def store?
return ( @keep_rev or @storable )
end
private :store?
#
# dump header および revision 0 かどうか
#
def dump_header?
return @dump_header
end
private :dump_header?
#
# @buf_rev の内容を出力する
#
# 出力後、クリアもする
#
def output_rev
if ( !@logger.nil? )
p @curr_rev
pp @rev_buf
p "dump_header #{dump_header?}"
p @rev_buf.size
end
if ( dump_header? or @rev_buf.size > 1 )
@rev_buf.each { |buf|
puts buf.join()
}
@revs.push( @curr_rev )
end
clear_rev_buf()
end
#
# @buf の内容を @buf_rev に store
#
def store2rev
if ( !@logger.nil? )
@logger.debug( "in store2rev() store? #{store?}" )
end
if ( store? and @buf.size > 0 )
@rev_buf.push( @buf )
end
clear_buf()
end
end # of class Compact
end # of Svndump
#
# テストじゃなかったら実行する
#
if ( Pathname( __FILE__ ).realpath == Pathname( $0 ).realpath )
tool = Svndump::Compact.new( )
def tool.node_post_hook
if (
# ここの書き方で調整
)
@storable = true
else
@storable = false
end
end
tool.run
end
cf.
そういえばこの Fink の 4.2.5 は日本語ディレクトリに cd しようとすると落ちるんだった。忘れてた。それで使ってなかったんだ。しくしくしく…。
ぱらぱらーっと眺めた限りでは perldoc で提供されていたり、あちこちですでに見聞きしたものが多いかな。まとまっているので Perl newbie を卒業したくらいのレベルの人に読ませるにはいいかもしれない。少なくともこれ読んだうえですすんで他人には解読不能なコードを書くことはあるまい。
最近 Perl 書かないようにしてたこともあり、これで復習しよう。
一週間ほどサボります。
伊Olivetti社がパソコン部門を売却 (PC Watch)
97年の記事ですが。メモしておかないとまた忘れそうで。
from ホムクル
へぇ。
でもこの番組ってこういうランキング番組だったか? なんかクイズみたいなのやってなかった? なんかよく分からんなぁ。
- いちばん喋らないのは青森県
- 社長が多いのは福井県(お、新潟も多いのか)
- 社長が多いのは辛抱強いってことよりも仕事が少ないんじゃないか?と思うのが地元の素直な感想ですが。。。
あ、ホムクル最終回だ。それでこんな変わった構成だったのか?
http://blog.cnetnetworks.jp/umeda/archives/000683.html
個人的には少し懐かしいこの単語。内容には大きく共感します。
考えたらテレビの世界ではけっこう前から起きてますよね、この現象。「モデル → 女優、歌手」みたいな流れや「スポーツ選手 → バラエティ、レポーター」みたいな流れはすでにポピュラーなわけで。もちろん本当にプロより優れている人が埋もれていたというケースはそれほど多くないとは思いますし、前提としては他の世界である程度以上有名ということが多いとは思いますが、人材の流動化という意味ではいわゆるカタギな世界に比べるとずいぶん進んでますよね。
いろんな成功パターン、成功プロセスがあるはずだ、と思いながら行きますかね。