ょゎさんとこで発覚した現象だが、 Ruby CVS HEAD で tDiary を動かすとデータファイルが消える。
結論から言うと原因はこれ。 このコードは tdiary/default.rb 1.23 で入っているので、 tDiary 1.5.3 以降の全バージョンで発現すると思われる。
--- tdiary/defaultio.rb 2 Aug 2004 12:54:12 -0000 1.1.1.2 +++ tdiary/defaultio.rb 24 Mar 2005 02:11:52 -0000 1.2 @@ -189,8 +189,8 @@ while l = fh.gets( "\n.\n" ) begin headers, body = TDiary::parse_tdiary( l ) - style = headers['Format'] || 'tDiary' - diary = eval( "#{style( style )}::new( headers['Date'], headers['Title'], body, Time::at( headers['Last-Modified'].to_i ) )" ) + _style = headers['Format'] || 'tDiary' + diary = eval( "#{style( _style )}::new( headers['Date'], headers['Title'], body, Time::at( headers['Last-Modified'].to_i ) )" ) diary.show( headers['Visible'] == 'true' ? true : false ) diaries[headers['Date']] = diary rescue NameError
該当コードを発見する方法…… ruby に -d をつける
しかし、例外が起こるとファイルが消えるというのもそれはそれで変だな。 何が起こっているのだろう。
あー、わかった。
def restore( fh, diaries ) : (前半略) : # read and parse diary while l = fh.gets( "\n.\n" ) begin headers, body = TDiary::parse_tdiary( l ) style = headers['Format'] || 'tDiary' diary = eval( "#{style( style )}::new( headers['Date'], headers['Title'], body, Time::at( headers['Last-Modified'].to_i ) )" ) diary.show( headers['Visible'] == 'true' ? true : false ) diaries[headers['Date']] = diary rescue NameError rescue raise end end ensure fh.flock( File::LOCK_UN ) end end
style(style) の行で NoMethodError が起こるが それは NameError の下位クラスなので rescue されてなかったことになり、 ファイルには記録がないことになる。 で、消してるのはここか。
module tDiary class DefaultIO def transaction( date ) : : if diaries.empty? File::delete( @dfile ) # also delete parser cache @tdiary.store_parser_cache( date, nil, nil) end
ちなみに、ここはロックされてないように見える。 restore から store の間に別のプロセスが 記事を追加していたら、それを消してしまう可能性があるのではないか。 ……とは言え、相当なレアケースだからどうでもいいような気もするな。
(16:45)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.