テストの記事投稿
PostgreSQLでの文字化けは変わらず。
対策も以前と一緒。
対策も以前と一緒。
git を使うようになってだいぶ経つんだけど、ちっとも使い方を覚えなくて、毎回検索してやり方を調べるようなことをしているので、いい加減まとめておくことにする。
主にsubversionとの比較で。
githubなんかと組み合わせて使うときは、github上でリポジトリを作ってからcloneするのが楽。
たぶんほとんどやらないけど、ファイルシステム上にリポジトリを作って他人とコラボレーションしようかな、とか言うときは--bareオプションをつける。
オプションの違いについては図で分かるgit-mergeの--ff, --no-ff, --squashの違い - アジャイルSEを目指すブログに詳しい。
1文字目がstageの状態、2文字目がunstageの状態。
文字の意味は、git status --helpで見られる。svnだとCがconflictだが、gitではCはcopied、Uがconflictになる。
diffの引数は、commitだったり、別のブランチだったり、いろいろできるのでgit diff --help参照。
--graphをつけると、どのようなブランチを辿ってcommitされてきたのかをグラフで見ることができる。
--mergesをつけると、merge commitだけをフィルタして見ることができる。
stash popで待避したものを現在のカレントに適用する。
内部的には、stashもHEADを動かさないcommit?
commitの指定方法とか
remoteの指定方法とか
commitをまとめるとか
主にsubversionとの比較で。
init
% git initそのまま。subversionと一緒。
githubなんかと組み合わせて使うときは、github上でリポジトリを作ってからcloneするのが楽。
たぶんほとんどやらないけど、ファイルシステム上にリポジトリを作って他人とコラボレーションしようかな、とか言うときは--bareオプションをつける。
clone
どこか他にあるリポジトリをローカルに持ってくるのに使う。svn checkoutと一緒。checkout
たぶんsubversionからの移行でいちばんわかりにくいコマンド。% git checkout -b <branch>新しいbranchを作成し、そのブランチに切り替える。svn copy と(ほぼ)同義。
% git checkout <branch>ブランチに切り替える。svn switch相当。ってsvn switch使ったことないけど。
% git checkout <pathes>ローカルの編集を取り消して、元に戻す。svn revert相当。ただし、後述のstageに乗っていないとき(git addしていないとき)
add
リポジトリにないファイルをstageに上げる(svn add相当)、もしくは修正したファイルをstageに上げる。(svn相当なし) あるいは、mergeでconflictしたファイルを修正して解決する(svn resolved相当)commit
stageにあるファイルをcommitする。-aオプションをつけると、stageに上げるのとcommitを同時に行う。fetch
リモートの変更をローカルに持ってくる。(svn相当なし)merge
別のブランチの修正をカレントブランチにマージする。オプションの違いについては図で分かるgit-mergeの--ff, --no-ff, --squashの違い - アジャイルSEを目指すブログに詳しい。
pull
fetch + merge(svn merge + commit相当)push
ローカルリポジトリのcommitをリモートにpushする。(svn commit相当?)status
状態を見る。(svn status相当)% git status On branch feature3 ←現在のブランチ Changes to be committed: ←stageにあるファイル一覧 (use "git reset HEAD-sbオプションをつけると、short formatで表示する。..." to unstage) new file: test.txt Changes not staged for commit: ←変更されたがstageに上がっていないファイル一覧 (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: README.md Untracked files: ←リポジトリに追加されていないファイル一覧 (use "git add ..." to include in what will be committed) test2.txt
% git status -sb ## feature3 M README.md A test.txt ?? test2.txt1行目は現在のブランチで、2行目以降にファイルリストが並ぶ。
1文字目がstageの状態、2文字目がunstageの状態。
文字の意味は、git status --helpで見られる。svnだとCがconflictだが、gitではCはcopied、Uがconflictになる。
diff
svn diff相当。subversionではrevision/changesetと言う考え方で、リビジョン番号で管理するが、gitはcommitで管理する。commitには1e53ba53322a3112eacc5b7813684bf19f28c6fdみたいなSHA-1 hashがつくので、hashで指定する。全部指定するのは面倒なので、頭4文字程度で指定することが可能(指定した文字数でcommitが一意に識別できる必要があるので、同じリポジトリに頭4文字が同じcommitがあると、もっと長い文字数を指定しないといけない)diffの引数は、commitだったり、別のブランチだったり、いろいろできるのでgit diff --help参照。
log
svn log相当。--graphをつけると、どのようなブランチを辿ってcommitされてきたのかをグラフで見ることができる。
--mergesをつけると、merge commitだけをフィルタして見ることができる。
show
git show commitで、特定のcommitのdiff(svnのchangeset)を見ることができる。stash
現在の変更を、一時的に待避する。(svn相当なし)stash popで待避したものを現在のカレントに適用する。
内部的には、stashもHEADを動かさないcommit?
tag
git tag -a tagname で、現在のワーキングツリーにタグを打つことができる。(tagnameの後にcommit を指定することも可能)archive
svn export相当。(実際には、checkout-indexと言うコマンドもあり、そちらの方がsvn exportに近い)取り消し
- 編集したファイルを取り消したい
→git checkout ファイル名 - 編集した上にgit addした(stageに上げた)ファイルを取り消したい
→git reset HEAD ファイル名 - commitを取り消したい
→git reset --soft HEAD~ (ワークファイルは変更が加わったまま)
→git reset --hard HEAD~ (ワークファイルもcommit前に戻る) - commitをやり直したい
→git commit --amend - 複数のcommitをまとめたい
→git rebase -i HEAD~n (ぐぐるとやり方がたくさん見つかる)
commitの指定方法とか
remoteの指定方法とか
commitをまとめるとか
FreeBSDのメンテをしていたら、いつのまにかrubyが1.9から2.0になったり、perlが5.16から5.18になったり、共有ライブラリの*.laファイルを使わない方針になったりといろいろ変わっている。
/usr/ports/UPDATINGを見ながら、それぞれアップデートする。
rubyのバージョンが上がったので、passengerを入れ直したり、bundle installしたりして、なんとなく動いたかな〜、と思っていたら、MovableTypeで文字化けが発生。
状況としては、以下のような感じ。
*.laファイル削除の関係で、文字コード変換系のライブラリが読めてないのかな?と思ってperlとperlのモジュールを全て再インストールしてみたけど変化無し。
もともと、非推奨のPostgreSQLを使っているので、サポート的な物は期待できないし、検索しても似たような例は見当たらない。
そこで、現象の切り分けと推測を始める。
まず、管理コンソールが普通に表示できて、過去に保存した記事が読めることから、DB→cgi→ブラウザでの表示は問題ないことがわかる。
そして、新しく入力した記事が文字化けすること、存在するはずのテンプレート「ヘッダー」が見つからないと言われることから、cgi→DBで文字化けが発生していると考えられる。
後は、ソースからDBとの入出力をしている箇所が特定できれば良いのだが、MovableTypeは自前のOR Mapperを使っているらしく、なかなか該当の箇所が探せない。
諦めかけて、MySQLに移行しようかと思ったりもしたけど、MySQLはあまり好きではない。さらに、SQLレベルでの移行ではなく管理コンソールを使ってのexport/importらしく、試しにexportしてみようとしたが、途中で接続が切れてしまった。
もう少し現象を理解しようと思って、自分でperlのプログラムを書いて検証したところ、DBIモジュールでDBと出し入れするときは、utf8::is_utf8()がtrueを返す文字列(つまり、utf8のperl内部表現の文字列)を使うことになっているが、生のutf-8の文字列を渡すと同じように文字化けすることがわかった。
この辺については、Perl: 文字コードとutf8フラグについて - @bayashi Wikiとか、404 Blog Not Found:perl - utf8::is_utf8("\x{ff}") == 0あたりが詳しい。
とにかく、文字化けしているデータをEncode::decode_utf8(xxx)すると文字化けが治ることがわかったので、後はソースから余計にEncode::encode_utf8(xxx) もしくはEncode::encode('utf8', xxx)している箇所を探せば良い。
のだが、私の力ではMovableTypeのソースが読みこなせなかったので、次はDBに入れるところ(SQLのパラメータをDBIに渡しているところ)が探せれば良いのだが、前述の通りOR Mapper(ObjectDriverと言う名前らしい)を使っているのと、DBIとかPgとか同じ名前のクラスが複数パッケージに存在していて、効きそうな場所が見つけられない。
諦めかけたところで、lib/MT/Object.pm に辿り着く。こいつがOR MapperのObjectのスーパークラスのようで、__core_final_pre_save とか、 __core_final_pre_search とか言うトリガを登録しているところで、Encode::encode()している箇所が怪しそうだと当たりをつける。
そこで、encodeしているところをコメントアウトしてみたところ、無事に文字化けが発生しなくなった。
しかし、この対応が正しいとは思えないので、どなたか正しい原因と対策を教えてください〜。
/usr/ports/UPDATINGを見ながら、それぞれアップデートする。
rubyのバージョンが上がったので、passengerを入れ直したり、bundle installしたりして、なんとなく動いたかな〜、と思っていたら、MovableTypeで文字化けが発生。
状況としては、以下のような感じ。
- 管理コンソールは普通に表示できる。
- 新しい記事を書いて公開しようとすると、テンプレート「ヘッダー」がないよ的なエラーが出た上に保存した記事が文字化けしている。
- DBを覗くと、DBに入っている時点で文字化けしている。
*.laファイル削除の関係で、文字コード変換系のライブラリが読めてないのかな?と思ってperlとperlのモジュールを全て再インストールしてみたけど変化無し。
もともと、非推奨のPostgreSQLを使っているので、サポート的な物は期待できないし、検索しても似たような例は見当たらない。
そこで、現象の切り分けと推測を始める。
まず、管理コンソールが普通に表示できて、過去に保存した記事が読めることから、DB→cgi→ブラウザでの表示は問題ないことがわかる。
そして、新しく入力した記事が文字化けすること、存在するはずのテンプレート「ヘッダー」が見つからないと言われることから、cgi→DBで文字化けが発生していると考えられる。
後は、ソースからDBとの入出力をしている箇所が特定できれば良いのだが、MovableTypeは自前のOR Mapperを使っているらしく、なかなか該当の箇所が探せない。
諦めかけて、MySQLに移行しようかと思ったりもしたけど、MySQLはあまり好きではない。さらに、SQLレベルでの移行ではなく管理コンソールを使ってのexport/importらしく、試しにexportしてみようとしたが、途中で接続が切れてしまった。
もう少し現象を理解しようと思って、自分でperlのプログラムを書いて検証したところ、DBIモジュールでDBと出し入れするときは、utf8::is_utf8()がtrueを返す文字列(つまり、utf8のperl内部表現の文字列)を使うことになっているが、生のutf-8の文字列を渡すと同じように文字化けすることがわかった。
この辺については、Perl: 文字コードとutf8フラグについて - @bayashi Wikiとか、404 Blog Not Found:perl - utf8::is_utf8("\x{ff}") == 0あたりが詳しい。
とにかく、文字化けしているデータをEncode::decode_utf8(xxx)すると文字化けが治ることがわかったので、後はソースから余計にEncode::encode_utf8(xxx) もしくはEncode::encode('utf8', xxx)している箇所を探せば良い。
のだが、私の力ではMovableTypeのソースが読みこなせなかったので、次はDBに入れるところ(SQLのパラメータをDBIに渡しているところ)が探せれば良いのだが、前述の通りOR Mapper(ObjectDriverと言う名前らしい)を使っているのと、DBIとかPgとか同じ名前のクラスが複数パッケージに存在していて、効きそうな場所が見つけられない。
諦めかけたところで、lib/MT/Object.pm に辿り着く。こいつがOR MapperのObjectのスーパークラスのようで、__core_final_pre_save とか、 __core_final_pre_search とか言うトリガを登録しているところで、Encode::encode()している箇所が怪しそうだと当たりをつける。
そこで、encodeしているところをコメントアウトしてみたところ、無事に文字化けが発生しなくなった。
しかし、この対応が正しいとは思えないので、どなたか正しい原因と対策を教えてください〜。
諸君、私はprintfデバッグが好きだ。
でネタを書こうと思ったんけど、元ネタがとても長かったので、改変するのも面倒でやめた。
今どきのARMのマイコンの開発であれば、JTAGを使ってIDE上からデバッグができて、printfなど使わなくても変数の中身は見られるし、ブレークポイントははれるし、ステップ実行もできるのだろう。
しかし、私はJTAGを持っていない。fm3マイコンがもう一枚とか、NXPの安いボードを持っていれば、Open OCDを使ってデバッグができるのだろうが、私は持っていない。
そこで、printfデバッグの出番ですよ!となるのだが、printfの出力をどうやって受けるか?と言う問題がある。
雑誌の付録のfm3マイコンは、USBが2ポートと、多数のマルチファンクションシリアルがあるが、マルチファンクションシリアルはレベル変換をしてあげないと通常のPCのシリアルとは繋げないし、そもそも今どきのPCにはシリアルポートがないので、USB-シリアル変換ケーブルなんぞが必要になる。これも個人では持っていない。
よろしい、ならばUSBだ!(改変を諦めたとか言いながら引きずってる)
基板にあるミニUSBは、FLASH Programmerで書き込みをした後は電源供給にしか役に立っていない。
これを使わない手はないだろうと思って調べてみたところ、さすがUSB、通常のシリアルのように、RxDとTxDだけ押さえれば良いと言うような簡単なものではない。端子の抜き差しから、相手とのネゴシエーション、通信まで全部面倒見てやらないといけないらしい。
とりあえず、USBデバイスにはUSBメモリやHDDみたいなmass storageや、USBオーディオのようなクラスと呼ばれるものがあり、シリアル通信を行うものは CDC と言うらしい。
当然、そこら辺にミドルウェアが転がっているよね?と調べてみたが、open sourceの実装は見つけられず。
Keil MDKの場合は、Proを買うとUSB Deviceのミドルウェアが付いてくるが、試用版では当然使えない。
そして、IAR Embedded Workbenchには、Virtual COM Portと言うCDCのサンプル(相手からのデータをエコーバックするもの)が入っていることを発見。
このサンプルが前回作ったgccでビルドできれば、USB経由で夢のprintfデバッグができるようになるのだ。
試行錯誤ののち、なんとか動くようになったので、いつものようにgithubに上げてある。(fm3/sample3 at master · false-git/fm3>
今回のはまりポイントは、以下。
その過程で調べた、Virtual COM PortのSystemInit()でやっているUSBクロックの初期化について簡単に書いておこう。
基本は、ペリフェラルマニュアルの通信マクロ編である。
書いてて自分で何を言ってるのかさっぱりわからないけど。
でネタを書こうと思ったんけど、元ネタがとても長かったので、改変するのも面倒でやめた。
今どきのARMのマイコンの開発であれば、JTAGを使ってIDE上からデバッグができて、printfなど使わなくても変数の中身は見られるし、ブレークポイントははれるし、ステップ実行もできるのだろう。
しかし、私はJTAGを持っていない。fm3マイコンがもう一枚とか、NXPの安いボードを持っていれば、Open OCDを使ってデバッグができるのだろうが、私は持っていない。
そこで、printfデバッグの出番ですよ!となるのだが、printfの出力をどうやって受けるか?と言う問題がある。
雑誌の付録のfm3マイコンは、USBが2ポートと、多数のマルチファンクションシリアルがあるが、マルチファンクションシリアルはレベル変換をしてあげないと通常のPCのシリアルとは繋げないし、そもそも今どきのPCにはシリアルポートがないので、USB-シリアル変換ケーブルなんぞが必要になる。これも個人では持っていない。
よろしい、ならばUSBだ!(改変を諦めたとか言いながら引きずってる)
基板にあるミニUSBは、FLASH Programmerで書き込みをした後は電源供給にしか役に立っていない。
これを使わない手はないだろうと思って調べてみたところ、さすがUSB、通常のシリアルのように、RxDとTxDだけ押さえれば良いと言うような簡単なものではない。端子の抜き差しから、相手とのネゴシエーション、通信まで全部面倒見てやらないといけないらしい。
とりあえず、USBデバイスにはUSBメモリやHDDみたいなmass storageや、USBオーディオのようなクラスと呼ばれるものがあり、シリアル通信を行うものは CDC と言うらしい。
当然、そこら辺にミドルウェアが転がっているよね?と調べてみたが、open sourceの実装は見つけられず。
Keil MDKの場合は、Proを買うとUSB Deviceのミドルウェアが付いてくるが、試用版では当然使えない。
そして、IAR Embedded Workbenchには、Virtual COM Portと言うCDCのサンプル(相手からのデータをエコーバックするもの)が入っていることを発見。
このサンプルが前回作ったgccでビルドできれば、USB経由で夢のprintfデバッグができるようになるのだ。
試行錯誤ののち、なんとか動くようになったので、いつものようにgithubに上げてある。(fm3/sample3 at master · false-git/fm3>
今回のはまりポイントは、以下。
- intrinsics.h
IAR EW のヘッダファイルには、intrinsics.hと言うものがあるが、MDKにもgccにも該当するファイルはない。このため、空のファイルを作って、アドホックなdefineを入れてみた。 - startup_ARMCM3.S
gccに入っていた startup_ARMCM3.Sだと、isr_vectorが少なくて、今回使うようなUSB関連の割り込みベクタの設定がない。そこで、startup_mb9bf61x.s を参考に、不足している割り込みベクタを補完した。 - Makefile
今回ビルドしたコードには、for(int i = ...)みたいなコードがあり、gccのデフォルトだと怒られるので、--std=c99オプションを追加した。 - arm_comm.h
これは、IAR EWのプロジェクトに含まれるヘッダなのだが、CriticalSecCntrと言う変数の型が、このヘッダとmain.cで違うためエラーになっていたので型を揃えた。
また、中にinlineなメソッドがあるのだが、そのままビルドすると何故かリンク時に Undefined Referenceになるので、staticをつけた。
インラインアセンブラの記述に、asm()を使っていたので、gccで通るように__asm__()にした。(上述のintrinsics.hでdefine)
ArmV7以前とV7の分岐があったので、V7用のコードがコンパイルされるように、__CORE__を7にdefineした(上述のintrinsics.h) - system_mb9bf61x.[ch]
最初、sample2と同じくSysTickのサンプルから持ってきていたのだが、このコードだと SystemInit()の中でUSB/Etherのクロック設定が行われない。
そこで、Virtual COM Portのサンプルから持ってきたら動いた。
SysTickサンプルではなく、Spansionからダウンロードできるtemplateも見てみたが、バージョンは新しいのにUSBクロックの初期化コードや、UCCR等のレジスタのdefineもなかった。
その過程で調べた、Virtual COM PortのSystemInit()でやっているUSBクロックの初期化について簡単に書いておこう。
基本は、ペリフェラルマニュアルの通信マクロ編である。
- UCCRレジスタに0を入れて、UCCRの読出しが0になるまで待つ
UCCRレジスタに0を入れるということは、USB/Etherのクロック出力を停止していると思えば良い。 - UPCR1レジスタに0を入れる
これは、USB-PLLの発振停止 - UPCR2〜UPCR7のレジスタを初期化
細かく書かないけど、今回大事なのはUPCR6のUSBRに2を入れて、PLLCLKの3分周をUSBのクロックとして使用すると言うこと。 - UPCR1レジスタに1を入れ、読出しが1になるまで待つ。
USP-PLLの発振開始。 - UCCRレジスタに0x3Dを入れる
これも細かいことは割愛するけど、USBのクロックとしてCLKPLLを使うと言う設定。 - USBコントローラをonにする前に、5cycleクロック供給
- USBEN0/1レジスタに1を入れる
USBコントローラを有効にする。
書いてて自分で何を言ってるのかさっぱりわからないけど。
最近のコメント
FreeBSDで日本語マニュアル by くぼ: お手数をおかけしまし
FreeBSDで日本語マニュアル by false: くぼさんから以下のコ
FreeBSDで日本語マニュアル by false: コメントありがとうご
FreeBSDで日本語マニュアル by satoumc: いろいろ検討した上で