On note_com from August 24 to 31, 2021.
Summary of articles posted in the last week.
直近一週間に投稿した記事のまとめ
Qt5再入門: 状態の読み込み|チブル・システムズ|note
Qt5再入門: QStandardItem|チブル・システムズ|note
Qt5再入門: QStandardItemModel|チブル・システムズ|note
Qt5再入門: シグナル/スロット|チブル・システムズ|note
Qt5再入門: モデルデータ 追加と削除|チブル・システムズ|note
Qt5再入門: ブックマークの保存、復元|チブル・システムズ|note
Qt5再入門・・・計7件
On note.com from August 17 to 23, 2021.
Summary of articles posted in the last week.
直近一週間に投稿した記事のまとめ
Notes C API探訪: NLS_string_bytes/NLS_string_chars(関数)|チブル・システムズ|note
Notes C API探訪: NLS_translate(関数)(その1)|チブル・システムズ|note
Notes C API探訪: NLS_translate(関数)(その2)|チブル・システムズ|note
Notes C API探訪: LMBCS文字列のクラス化|チブル・システムズ|note
Notes C API探訪: LMBCS文字列とQString|チブル・システムズ|note
Notes C API探訪: PathNetをラップする|チブル・システムズ|note
Notes C API探訪: データベースハンドルをラップする|チブル・システムズ|note
Notes C API探訪・・・計7件
突然Git Pushができなくなった時の一つの解
それはある日突然訪れた。
取引先と共有しているBitBucket上のリモートリポジトリに、ローカルでコミットしたソースコードがPushできなくなった。ソースコードはSails.jsサーバ上で組んでいるもので、クライアントはReactを使用してビルドしたものだ。
Sails.js | Realtime MVC Framework for Node.js
React – ユーザインターフェース構築のための JavaScript ライブラリ
これまで問題なく使えていたのだが、ある日突然次のようなログに見舞われPushできなくなった。
Enumerating objects: 47, done. Counting objects: 100% (47/47), done. Delta compression using up to 12 threads Compressing objects: 100% (29/29), done. fatal: the remote end hung up unexpectedly Connection to bitbucket.org closed by remote host. fatal: the remote end hung up unexpectedly
少量の変更なら問題なく使えたので、どう切り分ければいいのか皆目見当が付かない。
主眼を「大量データのPush」に絞り、 git push fatal hung up
のようなキーワードでググり、.git/config上で ssh.postBuffer
をいじってみたり、~/.ssh/config上に ServerAliveInterval
を設定してみたりと手を尽くしたものの、一切変化がなかった。
もしやBitBucket特有のものかと思っていたら、別の取引先でGitHub上に共有していたソースコードも同様のログとともにPushできない事象に見舞われた。OMG
実は問題なく使えていた時と、問題が発生した時の環境で唯一違いがあった。それは「引越し」をしたことだ。プロバイダや回線は全く一緒なのだが、引っ越したことでネットワーク環境に何らかの差異が発生したのではと思った。
そこで自宅のLAN環境を無効にして、モバイルWi-Fiルーターで試してみた。が、問題は解決しなかった。なんやねん!
目の前が真っ暗になりかけたその時、検索画面に次の記事の検索結果が引っかかった。
根本的な解決方法ではなさそうなものの、見出しが気になりリンクをたどると、内容は「ssh接続をhttpsポート(443)でつなぐ」というものだった。なるほど、22番以外でも接続することはできるのかと思い、失敗していたGitHub.comへの接続設定に適用してみた。
「こいつ・・・動くぞ!」
なんとこれまでウンともスンともPushできなかったコミットが、さらっと completed
のメッセージとともにPushを完了した。そこで問題のBitbucketの方もやってみたところ、こちらも問題解決!見事に突破した。
22番ポートの何がダメになってしまったのか、そもそもの話はまるでわからないままだが、443番ポートを介することで、できなかったことができたことに違いはない。
参考にしたサイトに謝意を述べるとともに、リンクを掲載しておく。もし postBuffer
や ServerAliveInterval
などで一切解決できなかった方はお試しあれ。
BitbucketにHTTPSポートでSSH接続する方法 – Memoteki
22 番ポートが通らない環境で GitHub / BitBucket / GitLab を SSH 経由で利用する方法 - Qiita
GitリポジトリサーバのSSH鍵を使い分け
自分用のメモ。
基本的には以下のページが非常に参考になる。
謝意を述べたい。
これに、私なりの理解や補足を加えておく。
結論
同一のリポジトリサーバ(GitHubやBitBucketのような)内を、目的やアカウントで、使用するSSH鍵を使い分けたい場合、SSHのホスト設定とGitのローカル設定を駆使すればできる。
Gitグローバル設定
まず、Gitのグローバル設定は空っぽが望ましい。Gitをインストールすると、大抵 git config --global user.email
の設定を推奨されるが、アカウントの使い分けをする上では「うっかりミス」を誘発してしまう。もしEメールを使い分けるなら user.email
をグローバル設定には置かないようにする。もしあるなら以下のようにする。
$ git config --global --unset user.email
SSH設定
例えば、A社用とB社用でGitHubで使うEメールアドレスやSSH鍵を使い分けなければならない場合、それぞれにSSH鍵を発行、登録していたとして、~/.ssh/configファイルに次のように設定する。
Host github_a_company HostName github.com User git IdentityFile ~/.ssh/id_rsa_github_a => これの公開鍵をA社アカウントでGitHubに登録 IdentitiesOnly yes Host github_b_company HostName github.com User git IdentityFile ~/.ssh/id_rsa_github _b => これの公開鍵をB社アカウントでGitHubに登録 IdentitiesOnly yes
Gitローカル設定
あとはプロジェクトのディレクトリに移動し、Gitのローカル側設定を以下のようにする。
$ cd project_a $ git init $ git config user.name "My Name" $ git config user.email myname@a.com $ git config url.github_a_company.insteadof git@github.com
$ cd project_b $ git init $ git config user.name "My Name" $ git config user.email myname@b.com $ git config url.github_b_company.insteadof git@github.com
こうすると、例えばA社のプロジェクトでソースコードをPushすると、
$ cd project_a $ git remote -v origin git@github.com:myaccount/myproject.git (fetch) origin git@github.com:myaccount/myproject.git (push) $ git push origin master
Push時のホスト名は以下のように変化する。
git@github.com => github_a_company (.git/configを適用) github_a_company => git@github.com (~/.ssh/configを適用)
?元に戻っただけ?
否!
github_a_company
を適用した時点で、A社用の「SSH公開鍵」が使われるようになっている。
Gitクローン時
なお、 .git/config
がまだ存在しない、例えば git clone
操作する場合はどうするか?
その場合、ホスト名を ~/.ssh/config
に設定した Host xxx
の xxx
を代わりに使えばできる。
例えば、B社用のSSH鍵でsomeprojectのソースコードをクローンしたい場合は次のようにする。
$ git clone git@github_b_company:someaccout/someproject.git
あとは必要に応じてプロジェクト内でGitを初期化、ローカル設定すればいい。
DominoでGraphQL
DominoサーバでGraphQLを作れたらいいな・・・と思ったので、超簡単なプロトタイプを作ってみました。
GraphQL、ご存じない方のために簡単に説明すると、「つながり」でできたデータ構造に問い合わせてデータを取得したり、更新したりすることができる「クエリ仕様」と言えばいいだろうか。
Facebook社が開発したんだけど、Facebook内のデータっていろんなところに「つながり」を持っていて、それを捌くのに開発したんじゃねっていう理解。なので、ツリー構造になっているNotesデータベース構造って、GraphQLでも扱いやすいんじゃないかと思ったのがきっかけ。
GraphQLはスキーマを決めて、スキーマに沿って問い合わせればいい、至極簡単。でもそれって使う側の言い分。実際問題、提供する側は結構面倒。JSONっぽいQueryは似て非なり。なので改めてQueryを字句解析しないといけない。C++での実装はそこが骨の折れるところ。でも優秀なライブラリを見つけたので、今回はこれのおかげ。
Microsoftとあるけど、LinuxやMacでもできるらしい。
ちなみに、試しに作ったスキーマはこれ。
schema { query: Query } type Query { dbDirectory(rootPath: String!): [DbNode!]! } interface DbNode { path: String! isDirectory: Boolean! } type DbDirectory implements DbNode { path: String! isDirectory: Boolean! dbDirectory: [DbNode!]! } type Database implements DbNode { path: String! isDirectory: Boolean! replicaId: String! }
最初の schema
はGraphQLの3つの機能、問い合わせ(Query)、変更(Mutation)、サブスクリプション(Subscription)のどれを使うかってことらしい。サブスクは基本的にWebSocketなどがないと動かない。Domino HTTPのアドイン(DSAPI)ではおそらくなんともしがたいと思う。
今回はデータの取得だけなので、Queryのみを定義する。
続く type Query
は、その問い合わせの仕様について。 dbDirectory
というキーワードに rootPath
でどのディレクトリ内にあるデータベースやサブディレクトリを取得するかを特定する引数を定義している。後ろの [DbNode!]!
は、 DbNode
のリストを意味する戻り値の仕様。
interface DbNode
は先の DbNode
の仕様に他ならないが、先頭が type
ではなく interface
なのがミソ。Javaなどのインターフェースと同義で、仕様のみで実装はない。Notes C APIではNotesデータベースとディレクトリって扱いが似ていて、ディレクトリもデータベースと同じくデータベースハンドル(DBHANDLE)で扱う。なので、両社に共通のパス名と、ディレクトリであるか否かを判定できるブール値を仕様にしている。
type DbDirectory
ではその DbNode
を実装してディレクトリを定義している。データベースとの違いは、さらに別のデータベースやディレクトリを配下に持てるので、再帰的に dbDirectory
を持っている。最初の Query
との違いは、すでにパスを保持している点にある。
type Database
は DbNode
を実装しつつ、ディレクトリにはないものを実装する。今回レプリカIDを取得できるようにしてみた。
例えば、これを使って、 mail
ディレクトリ内のデータベースを取得しようと思ったら、次のようなGraphQLを書けばよい。
query { dbDirectory(rootPath: "mail") { path isDirectory ...on Database { replicaId } } }
これでDomino GraphQLに問い合わせると、
{ "data": { "dbDirectory": [ { "path": "mail\\admin.nsf", "isDirectory": false, "replicaId": "49257D76xxxxxxxx" }, { "path": "mail\\hkobayas.nsf", "isDirectory": false, "replicaId": "492581B9xxxxxxxx" }, { "path": "mail\\kshiden.nsf", "isDirectory": false, "replicaId": "492581B9xxxxxxxx" }, { "path": "mail\\rhosei.nsf", "isDirectory": false, "replicaId": "492581B9xxxxxxxx" } ] } }
のようなJSONデータが返ってくる。なお、 replicaId
を付与すると、一つ一つDBをオープンしてレプリカIDを取得するような実装方法を取ったため、取得するDBやディレクトリが多いと途端に遅くなるので、改善の余地がある。
GraphQLがRESTなどに比べてすごいところは、取りたいデータをコントロールするすべを仕様が定義しているところ。例えば、先ほどのクエリを以下のように変えてみる。
query { dbDirectory(rootPath: "mail") { path } }
すると、返ってくるデータは次のようになる。
{ "data": { "dbDirectory": [ { "path": "mail\\admin.nsf", }, { "path": "mail\\hkobayas.nsf", }, { "path": "mail\\kshiden.nsf", }, { "path": "mail\\rhosei.nsf", } ] } }
求めたいフィールドを変更すると、戻り値のフィールドも変更される。GraphQLはそれを仕様として定義している。RESTでももちろんできるが、仕様ではないので、手法は実装者に委ねられている。
今回は本当に序の口。まだまだ紹介できるレベルには達していない。でもなんか元旦早々嬉しくなったので、早出ししてみた。