hg webを開くコマンドのlinux対応

ubutu引っ越しシリーズ。 個人的に使っていたツール周りをlinuxに移植している。

anatofuz.hatenablog.com

このエントリで紹介していた個人ツールのhg-browselinuxに対応させた。 といっても、macOSopenコマンドをxdg-openに書き換えればいいだけなので割と簡単。

実際に書き換えた結果はこんな感じ。

#!/usr/bin/env perl
use strict;
use warnings;

# hg config経由でhgrcにかかれているpush先を確認する
my $push_path = `hg config paths.default`;

if ($?){
    print "[eror] failed exec hg config paths.default";
    exit 1;
}

my $open_cmd = $^O eq 'darwin' ? "open" : "xdg-open"; #linux open cmd is xdg-open

# 無かったら特に何もしない
exit 1 unless ($push_path);


# yomitanはパスで開けないので別枠
my $url;

if ($push_path =~ /(yomitan)|(chatan)/){
    $url = yomitan($push_path);
} elsif ($push_path =~ /firefly/){
    $url = firefly($push_path);
} else {
  if ( $push_path =~ m[(https?|ssh)://(\w+@)?(.*)]){
      $url = "http://$3";
  }
  die 'invalid url';
}

`$open_cmd $url`;


sub yomitan {
    my $input  = shift;
    my $http_domain = 'https://ie.u-ryukyu.ac.jp/hg/';
    my $url;

    if ($input =~ m[.*//home/hg/y(\d+)(.+)]){
        $url = $http_domain . "y$1$2";
    }
    return $url;
}

sub firefly {
    my $input  = shift;
    my $http_domain = 'http://www.cr.ie.u-ryukyu.ac.jp/';
    my $url;
    if (($input =~ m[.*?firefly.cr.ie.u-ryukyu.ac.jp/(.*)] )||($input =~  m[.*firefly/(.*)])){
        $url = $http_domain.$1;
    }
    return $url;
}

まぁほとんど変化はないのだけど、今までIPC::Run3を使っていた箇所をPerlのバッククォート演算子(`)を使うように変更した。 これに伴ってコアモジュールだけで済むようになったので便利。

linuxの対応は、Perlの場合特殊変数$^OでOSの名前が取れるので、darwin(macOS)かそうでないかで処理を分けている。 まぁこれにwindows対応まで入れるとif-elsifを書かないといけなさそうだけど、まぁしばらくwindows上で生で動かす予定はないので良さそう

Ubuntuデスクトップ環境を構築した

ということで昨日のハング事件はやはりSSD側の問題らしくて、kernelパラメーターをいじれば回避出来るとの神情報をもらったので、linuxデスクトップを復活させた。

最初はmanjaroを使ってぶいぶい構築していたのだけれど、解像度を下げたら画面に何も映らなくなるという事件が発生した。泣きながら再構築したら、次はハングが発生したり、pacmanでのinstallに失敗するケースが出てきたりとなかなかつらい状態になった。

なんとなくarchは早かった気がするので、安定のubuntu20.10を構築して今に至ります。 やーハングしないと快適ですわね...。31日から10回くらいOSインストールしている気がする。

今はUbuntuから打っているけれどわりとツラミポイントがあるきがする

  • Ctrl + L でカタカナにするとかのmacの変換が使えない
    • ficitix? の設定でどうにかなりそうな気がする
  • command keyのショートカットの代わりにCtrlキーになったので、いろいろとショートカットが衝突する
    • windows key (special key)を使うという手もあるが... 
    • 特に今までcommandでやってたキーバインド(全選択とか)がubuntuだとどうなるかあんまわからん
  • 定期的に挙動がおかしいところがある
    • ハングはしないもののmacOSとかと比べるとグギギみたいなところが多々
    • manjaroで解像度切り替えて何も出なくなったのは厳しかった

linux desktopロマンがあって面白くて、度重なるエラーはググり力とLinux対応力が求められる感じがして力が付きそう。 しばらubuntu使ってみて機会があればarch系リベンジしたい。

macOSのMacUTF8からUTF8にリネームするPerlスクリプト

linuxに引っ越しシリーズで書いてみたやつ。

もともとmacOSのBooksディレクトリに電子書籍を日本語ファイル名で置いていた。Linuxに作業環境を移すためにファイルの転送をする場合、実はmacOSのutf8は微妙にutf8と異なるmacUTF8なので変換をする必要がある。

rsyncとiconvを組み合わせる方法もあるけど、今回はすでに転送してしまったのでPerlで解決した。

#!/usr/bin/env perl
use strict;
use warnings;
use Encode;
use Encode::UTF8Mac;
use Path::Tiny;

my $root = path("Books");
my @queue = ($root->children);
my @rename_list;

while (@queue) {
  my $child = shift @queue;
  if ($child->is_dir) {
    push(@queue, $child->children);
  }
  if ($child =~ /(?:pdf|epub)/) {
    next if $child =~ /^\p{ascii}+$/;
    push(@rename_list, $child);
  }
}

for my $file (@rename_list) {
  my $fpath = path($file);
  my $mac_file_name  = Encode::decode('utf-8-mac', $file);
  my $utf8_file_name = Encode::encode('utf8', $mac_file_name);
  $fpath->move($utf8_file_name);
}

クロネコヤマトをCUIで追跡するコマンドを書いた

2021/01/03 追記

queueが自分で打っててめんどうだったのでlsに変えました


というわけでクロネコヤマトから情報を取ってくるツールを書きました。kuronekocatという名前です。

ほしかったthinkpadが届くまでひたすらクロネコヤマトの追跡ページをリロードしてたのでツールにしました。完全に自分が使う様です。

github.com

いますぐ

brewからとりましょう!!

$brew install anatofuz/kuronekocat/kuronekocat

使い方

基本的にはkuronekocat get <追跡番号>で情報が見れます。

+ikoma+anatofuz$ kuronekocat get 301905465514
+--------------+---+------------+-------+-------+------------------------+--------------+
|   伝票番号   | # |  荷物状況  | 日 付 | 時 刻 |        担当店名        | 担当店コード |
+--------------+---+------------+-------+-------+------------------------+--------------+
| 301905465514 | ↓ | 荷物受付   | 12/28 | 18:50 | 新東京法人営業支店     |       036600 |
+              +---+------------+-------+-------+------------------------+--------------+
|              | ↓ | 発送       | 12/28 | 18:50 | 新東京法人営業支店     |       036600 |
+              +---+------------+-------+-------+------------------------+--------------+
|              | ↓ | 作業店通過 | 12/28 | 20:53 | 羽田クロノゲートベース |       032990 |
+              +---+------------+-------+-------+------------------------+--------------+
|              | ↓ | 作業店通過 | 12/29 | 04:05 | 羽田空港ベース店       |       419990 |
+              +---+------------+-------+-------+------------------------+--------------+
|              | □ | 配達完了   | 12/30 | 11:17 | 中城センター           |       098161 |
+--------------+---+------------+-------+-------+------------------------+--------------+

伝票番号いちいち覚えてられないので、addでキューに追加できます。 追加時はオプションとして説明文をexplainに続いて入力できます。

$kuronekocat add --number 301905465514 --explain thinkpad

キューの一覧はqueueで確認できます。

$ kuronekocat queue
+--------------+--------------+
|     品物     |   追跡番号   |
+--------------+--------------+
| 624158714325 | 624158714325 |
| thinkpad     | 301905465514 |
+--------------+--------------+

キューに入ってるものはgetコマンドから打ちで表示されます。

+ikoma+anatofuz$ kuronekocat get
+--------------+--------------+---+----------------------------+-------+-------+----------------------------------+--------------+
|     品物     |   伝票番号   | # |          荷物状況          | 日 付 | 時 刻 |             担当店名             | 担当店コード |
+--------------+--------------+---+----------------------------+-------+-------+----------------------------------+--------------+
| 624158714325 | 624158714325 | ↓ | 発送                       | 12/28 | 16:21 | 長田センター                     |       098123 |
+              +              +---+----------------------------+-------+-------+----------------------------------+--------------+
|              |              | ↓ | 陸・海上切替え             | 12/28 | 16:37 | 長田センター                     |       098123 |
+              +              +---+----------------------------+-------+-------+----------------------------------+--------------+
|              |              | ↓ | 依頼受付(日・時間帯変更) | 12/28 | 19:13 | 新宮城主管支店 サービスセンター |       113005 |
+              +              +---+----------------------------+-------+-------+----------------------------------+--------------+
|              |              | □ | 陸・海上切替え             | 12/29 | 22:37 | 沖縄ベース                       |       098990 |
+--------------+--------------+---+----------------------------+-------+-------+----------------------------------+--------------+
| thinkpad     | 301905465514 | ↓ | 荷物受付                   | 12/28 | 18:50 | 新東京法人営業支店               |       036600 |
+              +              +---+----------------------------+-------+-------+----------------------------------+--------------+
|              |              | ↓ | 発送                       | 12/28 | 18:50 | 新東京法人営業支店               |       036600 |
+              +              +---+----------------------------+-------+-------+----------------------------------+--------------+
|              |              | ↓ | 作業店通過                 | 12/28 | 20:53 | 羽田クロノゲートベース           |       032990 |
+              +              +---+----------------------------+-------+-------+----------------------------------+--------------+
|              |              | ↓ | 作業店通過                 | 12/29 | 04:05 | 羽田空港ベース店                 |       419990 |
+              +              +---+----------------------------+-------+-------+----------------------------------+--------------+
|              |              | □ | 配達完了                   | 12/30 | 11:17 | 中城センター                     |       098161 |
+--------------+--------------+---+----------------------------+-------+-------+----------------------------------+--------------+

受け取った場合はreceiveでキューから消します。伝票番号でも商品名でもokです。

+ikoma+anatofuz$ kuronekocat queue
+--------------+--------------+
|     品物     |   追跡番号   |
+--------------+--------------+
| 624158714325 | 624158714325 |
| thinkpad     | 301905465514 |
+--------------+--------------+

$ kuronekocat receive thinkpad
$ kuronekocat queue
+--------------+--------------+
|     品物     |   追跡番号   |
+--------------+--------------+
| 624158714325 | 624158714325 |
+--------------+--------------+

くりかえし

brewにも登録しています。どうぞお使いください。

$brew install anatofuz/kuronekocat/kuronekocat

実装について

自分が作る前にあるものを使うと楽なので、GitHubを探しました。 見たところ1件それっぽいのがヒットしました。

github.com

しかしこれはpython実装となっていて、いくつかのライブラリをinstallする必要があります。 作業環境をmacOSから変更しようとしてたこともあり、シングルバイナリでの再実装を検討しました。

となってくるとRustかgolangですが、どうせHTTPを叩く必要があるのでそこまで速度も必要なさそうなので、golangを今回選択しました。 あとはCLIツールを使うならおなじみcobraを使ってエイヤで書きました。

内部は単純にクロネコヤマトの追跡ページにpostして、それをパースする感じです。 追跡ページはGoogle検索の結果出てくるページと、ヤマトのCGIのページの2種類あるのですが、前者の方はgetでいけるもののクエリパラメータによくわからんキーが入っていたので断念しました。その為素朴にpostしています。この際Shift-JisでHTMLが返ってくるので、気合でutf8に変換するなどをしています。

かなりやっつけで書いたので色々と雑な実装すが、まぁ使う分には問題ないので...

今回はGitHub releaseを使ったりhomebrewで配布をしたかったのですが、Twitterで教えてもらったgoreleaserを利用しています。かなりぱぱっと出来て便利でした。

github.com

というわけでどうぞお使いください。READMEは後ほど書きます

最近awesome-perlに追加されたモジュールを眺める

これはPerlアドベントカレンダー23日目の記事です。 昨日はnanto_viさんで「Perl の wantarray 関数で返り値の扱いを確認する」でした。

さて15日目の記事でmoznionさんの方で話があったawesome-perlですが、ここ数週間でかなりプルリクが飛んできていました。 その中で様々なモジュールがawsome-perlに加わっています。 ということで最近awesome-perlに追加されたモジュールの中からいくつか使って雰囲気を見てみます。

.......あ、ちょうどよかったので広告です! BigSureを使っている人はplenv関連のアップデートをお願いします!!!

anatofuz.hatenablog.com

HTML5::DOM

このプルリクエストで追加されました。 プルリクエストを送ってきたAzq2さんが作成したCPANモジュールの様です。

今回はcpanfileに書いてcpmでinstallしようと思います。

cpanfileはこんな感じです。

requires 'HTML5::DOM';

早速インストールします。

$ cpm install
FAIL install HTML5-DOM-1.18
FAIL install HTML5-DOM-1.18
0 distribution installed.

インストールしようとしたところFAILしました。悲しいですね。

2020-12-23T15:00:56,99566,HTML5-DOM-1.18| cc -c  -I/Users/anatofuz/.perl-cpm/work/1608703254.99547/HTML5-DOM-1.18/third_party/modest/include -std=c99 -fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -DPERL_USE_SAFE_PUTENV -O3   -DVERSION=\"1.18\" -DXS_VERSION=\"1.18\"  "-I/Users/anatofuz/.plenv/versions/5.32.0/lib/perl5/5.32.0/darwin-2level/CORE"   DOM.c
2020-12-23T15:00:57,99566,HTML5-DOM-1.18| DOM.xs:515:13: warning: 5 enumeration values not handled in switch: 'MyCSS_SELECTORS_TYPE_UNDEF', 'MyCSS_SELECTORS_TYPE_ATTRIBUTE', 'MyCSS_SELECTORS_TYPE_PSEUDO_CLASS_FUNCTION'... [-Wswitch]
2020-12-23T15:00:57,99566,HTML5-DOM-1.18|                                 switch (entry->type) {
2020-12-23T15:00:57,99566,HTML5-DOM-1.18|                                         ^
2020-12-23T15:00:57,99566,HTML5-DOM-1.18| DOM.xs:515:13: note: add missing switch cases
2020-12-23T15:00:57,99566,HTML5-DOM-1.18|                                 switch (entry->type) {
2020-12-23T15:00:57,99566,HTML5-DOM-1.18|                                         ^
2020-12-23T15:00:59,99566,HTML5-DOM-1.18| 1 warning generated.
2020-12-23T15:00:59,99566,HTML5-DOM-1.18| cc -c  -I/Users/anatofuz/.perl-cpm/work/1608703254.99547/HTML5-DOM-1.18/third_party/modest/include -std=c99 -fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -DPERL_USE_SAFE_PUTENV -O3   -DVERSION=\"1.18\" -DXS_VERSION=\"1.18\"  "-I/Users/anatofuz/.plenv/versions/5.32.0/lib/perl5/5.32.0/darwin-2level/CORE"   utils.c
2020-12-23T15:00:59,99566,HTML5-DOM-1.18| utils.c:126:1: warning: non-void function does not return a value [-Wreturn-type]
2020-12-23T15:00:59,99566,HTML5-DOM-1.18| }
2020-12-23T15:00:59,99566,HTML5-DOM-1.18| ^
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| 1 warning generated.
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| cc -c  -I/Users/anatofuz/.perl-cpm/work/1608703254.99547/HTML5-DOM-1.18/third_party/modest/include -std=c99 -fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -DPERL_USE_SAFE_PUTENV -O3   -DVERSION=\"1.18\" -DXS_VERSION=\"1.18\"  "-I/Users/anatofuz/.plenv/versions/5.32.0/lib/perl5/5.32.0/darwin-2level/CORE"   modest_modest.c
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| In file included from modest_modest.c:5:
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| ./third_party/modest/source/modest/finder/pseudo_class.c:112:13: error: implicitly declaring library function 'snprintf' with type 'int (char *, unsigned long, const char *, ...)' [-Werror,-Wimplicit-function-declaration]
2020-12-23T15:01:00,99566,HTML5-DOM-1.18|             snprintf(new_data, length, "%s", str);
2020-12-23T15:01:00,99566,HTML5-DOM-1.18|             ^
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| ./third_party/modest/source/modest/finder/pseudo_class.c:112:13: note: include the header <stdio.h> or explicitly provide a declaration for 'snprintf'
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| 1 error generated.
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| make: *** [modest_modest.o] Error 1
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| ! Retrying (you can turn off this behavior by --no-retry)
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| Executing /usr/bin/make
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| "/Users/anatofuz/.plenv/versions/5.32.0/bin/perl5.32.0" -MExtUtils::Command::MM -e 'cp_nonempty' -- DOM.bs blib/arch/auto/HTML5/DOM/DOM.bs 644
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| cc -c  -I/Users/anatofuz/.perl-cpm/work/1608703254.99547/HTML5-DOM-1.18/third_party/modest/include -std=c99 -fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -DPERL_USE_SAFE_PUTENV -O3   -DVERSION=\"1.18\" -DXS_VERSION=\"1.18\"  "-I/Users/anatofuz/.plenv/versions/5.32.0/lib/perl5/5.32.0/darwin-2level/CORE"   modest_modest.c
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| In file included from modest_modest.c:5:
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| ./third_party/modest/source/modest/finder/pseudo_class.c:112:13: error: implicitly declaring library function 'snprintf' with type 'int (char *, unsigned long, const char *, ...)' [-Werror,-Wimplicit-function-declaration]
2020-12-23T15:01:00,99566,HTML5-DOM-1.18|             snprintf(new_data, length, "%s", str);
2020-12-23T15:01:00,99566,HTML5-DOM-1.18|             ^
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| ./third_party/modest/source/modest/finder/pseudo_class.c:112:13: note: include the header <stdio.h> or explicitly provide a declaration for 'snprintf'
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| 1 error generated.
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| make: *** [modest_modest.o] Error 1
2020-12-23T15:01:00,99566,HTML5-DOM-1.18| Failed to install distribution

見るとCCのエラーで死んでいます。CCが動いているのでXSかなと思ったのですが、これはsubmoduleのModestというプロジェクトのビルドに失敗している様です。

調べてみたところModestとはC言語で実装されたHTMLのrendererで、HTMLパーサーなどが実装されています。HTML5::Domはこのプロジェクトを呼び出してHTMLのパースを行うモジュールなので、高速ということの様です。

せっかくなのでubuntucpm installしてみました。

$ cpm install HTML5::DOM
DONE install HTML5-DOM-1.18
1 distribution installed.

無事通ったようです。

#!/usr/bin/env perl
use warnings;
use strict;
use HTML5::DOM;

my $parser = HTML5::DOM->new;

my $html = '<div>Hello world!</div>';

# parsing with custom options (extends options defined in HTML5::DOM->new)
my $tree = $parser->parse($html, {
    scripts     => 0,
});

print "$tree->body->text\n"; #Hello World!

$parser->parseを実行するとHTML5::DOM::Treeオブジェクトが返ってきます。

HTML5::DOM::Treeは様々なものを返しますが、今回の例題で<div>Hello World!</div>の中からHelloWorldを取り出すには、まずbodyメソッドを実行してHTML5::DOM::Nodeを返す必要があります。

Nodeも様々なAPIがありますが、中でtextを使うとtextの代入、及び取得が可能な様です。

Asm::X86

Asm::X86X86のインストラクションかどうかを判定することが出来るモジュールです。 また、AT&TアセンブラIntel形式に変換することも可能です。

このプルリクエストで追加されました。

#!/usr/bin/env perl
use strict;
use warnings;
use Asm::X86 qw(@instr is_instr);

print "mov YES\n" if is_instr ("MOV");
print "bic YES\n" if is_instr ("BIC");

例えば上のコードでは、movx86の命令ですのでis_instrはtrueを返しますが、bicはARMの命令なのでfalseを返します。

ELF::Writer

ELF::Writerは、 ELF形式のバイナリを生成することが出来るライブラリの様です。

リポジトリのテストには終了コード42で終わるELFのバイナリが置かれています

実際のテストコードはこのあたりを読んでみましょう。(なんとなく読んだけどAPIをちゃんと把握しないとだめそう)

Video::Generator

Video::GeneratorとはPerlでビデオ生成する!?モジュールです。 このプルリクエストで追加されました。

EXAMPLE2を参考にコードを書いてみます。今回はtempdirを使わずにvideoに書き込みに行きます。 なお予めvideoディレクトリを作っておく必要があります。

use strict;
use warnings;

use File::Path qw(rmtree);
use File::Spec::Functions qw(catfile);
use Video::Generator;

# Object.
my $obj = Video::Generator->new(
        'verbose' => 1,
);

# Create video.
my $video_file = catfile("video", 'foo.mpg');
$obj->create($video_file);

実行するとこんな感じのログが出ます。

$ carton exec -- perl hoge.pl
Video pattern generator created images for video in temporary directory.
Created video file.
Removed temporary directory.

確認するとvideoディレクトリにfoo.mpgが生成されています。

$ ls video
foo.mpg

驚くべきことにPerlで動画が作成されました。 動画はYoutubeにあげてみようと思いましたが、利用規約の関係で削除されてしまいました。

モジュール内部でFFmpeg::Commandが使われているので、話は単純でPerlからffmpeg/avconvを叩いて動画を作成している様です。

おわり

こうしてみるとBaseband-processorさんがめっちゃくちゃプルリクだしてますね...。今は収まったみたいすが一時期の勢いは過ごそうでした。

Growiのバックアップツールをgolangで書き直した

anatofuz.hatenablog.com

↑で書いていたtoolをgolangに書き直しました。ついでに最新のGrowiのスキーマにも対応しました。

mercurialからGitにリポジトリを変換したので、試したい方はこちらをご利用ください。

github.com

使い方

$./growibackup ${revison.json} ${backup_dir}

エントリの内容はrevison.jsonに書かれているので、それを指定します。 docker-composeで動かしている場合は、こんな感じのシェルスクリプト化すると楽です。

DAY=`date "+%Y-%m-%d"`
REVJSON=revision_back_${DAY}.json
docker exec growi_mongo_1 mongoexport -d growi -c revisions --pretty --jsonArray --out ${REVJSON}
docker cp growi_mongo_1:${REVJSON} .
docker exec growi_mongo_1 rm ${REVJSON}
./growibackup ${REVJSON} Growi

生成されたmarkdownPerlの時と同様にシンプルなファイルになっています。 研究室ではmercurialを使っているので、hgリポジトリ化してみました。

www.cr.ie.u-ryukyu.ac.jp

DB関係

revisionsのスキーマが変わったのか、mongodbのバージョンアップをしたためかわかりませんが、以前実装した時とrevisionsの要素の型が異なっていました。

以前はこんな感じでしたが

 type Revision struct {
       ID            string    `json:"_id"`
       Format        string    `json:"format"`
       CreatedAt     time.Time `json:"createdAt"`
       Path          string    `json:"path"`
       Body          string    `json:"body"`
       Author        string    `json:"author"`
       HasDiffToPrev bool      `json:"hasDiffToPrev"`
       V             int       `json:"__v"`
 }

今はこんな感じです

type Revision struct {
  ID struct {
    Oid string `json:"$oid"`
  } `json:"_id"`
  Format    string `json:"format"`
  CreatedAt struct {
    Date time.Time `json:"$date"`
  } `json:"createdAt"`
  Path   string `json:"path"`
  Body   string `json:"body"`
  Author struct {
    Oid string `json:"$oid"`
  } `json:"author"`
  HasDiffToPrev bool `json:"hasDiffToPrev"`
  V             int  `json:"__v"`
}

jsonからgolangの構造体を作るにはJSON-to-Goを使うと便利です。

また以前はdocker exec growi_mongo_1 mongoexport -d growi -c revisions --out ${REVJSON} みたいな感じでjson化していましたが、今日やってみたところrevisonの配列ではなくて、revisionが1件1件乗っている、invalidなjsonが返ってきました。

{
  "_id": {
    "$oid": "5df9ce81f7f7970046c44609"
  },
  "format": "markdown",
  "createdAt": {
    "$date": "2019-12-18T07:00:17.357Z"
  },
  "path": "/user/anatofuz/note/2019/12/18",
  "body": "# 日報\n\n- nkmr先生の講義で発表\n- 実験2のTAをした\n- GearsOSの書き換え作業\n\n## GearsOSの書き換え\n\n- なんか`sys_read_impl.h`時代の名残があったので幾つかファイル
を削除した\n    - interface_impl headerimplの2種類\n- そろそろsyscall interfaceを書くべき?\n    - interfaceの仕様が結構混乱を招きそうな気配を感じている\n    - チュートリアル>的な資料の充実...?",
  "author": {
    "$oid": "5df5ef37d744a60045dd1524"
  },
  "__v": 0
}
{
  "_id": {
    "$oid": "5df9e9baf7f7970046c4460b"
  },
  "format": "markdown",
  "createdAt": {
    "$date": "2019-12-18T08:56:26.446Z"
  },
  "path": "/user/anatofuz/note/2019/12/18",
  "body": "# 日報\n\n- nkmr先生の講義で発表\n- 実験2のTAをした\n- GearsOSの書き換え作業\n\n## GearsOSの書き換え\n\n- なんか`sys_read_impl.h`時代の名残があったので幾つかファイル
を削除した\n    - interface_impl headerimplの2種類\n- そろそろsyscall interfaceを書くべき?\n    - interfaceの仕様が結構混乱を招きそうな気配を感じている\n    - チュートリアル>的な資料の充実...?\n    \n## 次の継続に行く書き方\n\n`__code next(int ret_val,...)`\n- この `ret_val`は実装している方のitnerfaceに記述されている必要がある",
  "author": {
    "$oid": "5df5ef37d744a60045dd1524"
  },
  "hasDiffToPrev": true,
  "__v": 0
}

色々試したところ、--jsonArrayをつければvalidなjsonとして返ってくるらしく、つけたところちゃんとrevisionの配列のjsonとして返ってきました。

Perlからの移植

自分で使う分にはPerlでいいんですが、後輩の引き継ぎとビルドの手軽さを考えるとgolangでの書き直しをしてみました。バイナリのポン置きしたいし。

もともとメインルーチンはPerlで書いていたので素朴に移植するみたいな感じでした。 ポインタ周りをあまり使って無くて、じゃぶじゃぶインスタンスを作りまくる感じにしたのでメモリには優しくなさそう....。

戸惑ったのはtime.Time型の比較をするBeforeAfterというメソッドがあるのですが、当初「prevよりrevが新しかったら更新をする」という意図でこう書いていました。 これはrevisions.jsonにはエントリのすべての更新記録があるのですが、CVSで管理するので最新の1件だけあればいいので、それを特定する必要がある為です。

    if prevRev, ok := path2Revision[rev.Path]; ok {
      if prevRev.CreatedAt.Date.After(rev.CreatedAt.Date) {
        path2Revision[rev.Path] = rev
      }
      continue

実はこの場合、prev自体がBeforeかAfterで考えないといけないという設計らしく、実際はAfterじゃなくてBeforeでした。

    if prevRev, ok := path2Revision[rev.Path]; ok {
      if prevRev.CreatedAt.Date.Before(rev.CreatedAt.Date) {
        path2Revision[rev.Path] = rev
      }
      continue

mac OS BigSurでplenvを使いたい俺たちは

TL;DR

$cd ~/.plenv/plugins/perl-build; git pull

PerlのBigSur問題

plenvはPerlソースコードをローカルに持ってきて、ビルドを行う仕組みになっています。 BigSur以前のmacOSでは正常にビルドができましたが、BigSurでは次のようなエラーが出てしまいビルド出来ないケースがあります。

Which of these apply, if any? [darwin]

*** Unexpected product version 11.0.
***
*** Try running sw_vers and see what its ProductVersion says.

Installation failure: sh Configure -Dprefix=/Users/anatofuz/.plenv/versions/debug-32 -de -Dversiononly -DDEBUGGING=-g -Doptimize=-O0 -A'eval:scriptdir=/Users/anatofuz/.plenv/versions/debug-32/bin' at /Users/anatofuz/.plenv/plugins/perl-build/bin/perl-build line 12763.
ABORT

この問題は、PerlのビルドスクリプトConfiguermacOSのバージョンが決め打ちされている為です。

ほどなくしてパッチが作成され、Perl5本体には取り込まれていますが、5.32などの過去のバージョンには当然取り込まれていません。

github.com

Devel::PatchPerl

過去のリリースにもパッチを当てたい場合、手動でやるのはめんどうなのでよしなにパッチを当ててくれるDevel::PatchPerlというライブラリがあります。

metacpan.org

Devel::PatchPerlはpatch_sourceというAPIが提供されていて、これを叩くとバージョンごとによしなにパッチを当ててくれます。

パッチを当てるPerlのバージョンと内容は、この様にハッシュリファレンスで、Perlのバージョンを正規表現で、あてるパッチをサブルーチンで指定します。

  {
    perl => [
              qr/^5\.004_05$/,
              qr/^5\.005(?:_0[1-4])?$/,
              qr/^5\.6\.[01]$/,
            ],
    subs => [
              [ \&_patch_configure ],
              [ \&_patch_makedepend_lc ],
            ],
  },

今回のBigsurの問題はhints/darwin.shファイルの問題なのですが、実は数日前のcommitで、すべてのバージョンに対してhintsのパッチを当てるようになっていました。

github.com

さらによく見てみると、hintsに関してはパッチ形式ではなく、hintsファイルをbase64Perlモジュールに直接埋め込んでおり、それに差し替えるという方法でした。(macOSのパッチ)

埋め込まれているこのhintsをbase64で戻したところ、上記のPerl5に取り込まれたパッチがあたっている状態でした。

この変更があるDevel::PatchPerlのバージョンは2.04です。

Perl-Build

plenvがデフォルトで呼び出す(であろう)PerlのビルドツールはPerl-Buildです。 Perl-Buildが内部的にConfigureとかを呼び出すようになっています。

実はデフォルトでPerl-BuildはDevel::PatchPerlを当てるようになっています

さらにPerl-Buildがデフォルトで使うDevel::PatchPerlのバージョンは、数日前のcommitで最新版に変更されています。

github.com

またPerl-Buildの中身をplenvはfatpack(Perlモジュールを1枚スクリプトに圧縮)したものを使うようになっています。 Devel::PatchPerlの内容も現在のPerl-Buildのfatpackされたperl-buildに含まれている為、pullして更新すると最新のDevel::PatchPerlを使うことになり、問題が解決されます。

ということで

plenvを使っている皆さんは今すぐ $cd ~/.plenv/plugins/perl-build; git pull しましょう!!!!!