herokuからcloneできないソースコードをサルベージする
太古の昔にデプロイしていたサービスでgit管理もしていなくて、でもherokuにはソースコードがあるはず…。といったコードをサルベージする方法を書き残します。
heroku remoteからgit cloneできればよかったんですが、できなかった(時間が経ちすぎた?)ので、この方法をとりました。
heroku run '/bin/bash -c "tar -czf /opt/app.tgz ./ && base64 /opt/app.tgz"' --app $HEROKU_APP > app.base64 && \ base64 -d ./app.base64 > app.tgz && \ mkdir -p app && tar -xzf app.tgz -C app
要はアーカイブにしたものをbase64でホストコンピュータにリダイレクション、そしてアンアーカイブしてるだけです。
ファイルが大きすぎる…ということであれば、.git
を諦めればVCS管理下のファイルだけを取得することもできます。
heroku run '/bin/bash -c "git archive HEAD -o /opt/app.zip && base64 /opt/app.zip"' --app $HEROKU_APP > app.base64 && \ base64 -d ./app.base64 > app.zip && \ unzip app.zip -d ./app
dynoを起動する必要があるので、無料期間終了の11月27日までにクローズするサービスについてはサルベージしておきたいですね。
そもそもGithubにプッシュしとけっつー話よな
Android物理デバイスをミラーリングする2022
Androidエンジニアの開発のお供であるミラーリングの話。
私がAndroidエンジニアとして駆け出しのころは Android Screen Monitor に大変お世話になりました。
2022年ミラーリングしたいと思ったときになにを使えばいいのか。Genymotion を作っている Geneymobile が便利なツールを作っていたことを知りました。
コマンド叩くだけでMac*1からミラーリングできて、かつマウスやキーボードから操作ができるツールです。 デバイス側に特別なアプリをインストールする必要もなく、adbで接続されてさえいれば使いはじめることができる。コピペ操作もMacからそのまますることができるところが最高。
ただ一点だけ面倒だなと思ったのは、コマンドで実行しないといけないので、ターミナルのタブを一つ提供しないといけないことだ。
バックグラウンドで動いてくれるように &
つけて起動することもできるけど、実行時のログがちらちらしてきて煩わしい。
ウインドウを前面に持ってきたいと思ったときにExposeしてクリックしないといけないことも面倒。
要するにAlfredからコマンド起動できて、かつ、すでに起動済みだったら前面に表示すればいいんだろうってことで、スクリプト書きました。
Alfred + Powerpackを使っていればnpm経由でインストールすることができます。
ちょっとまえから気になっていた alfy という Alfred workflow をインストールするための仕組みも使うことができて満足。
*1:マルチプラットフォームもがんばっていそうな雰囲気がありますが未確認
Charlesを快適に使うためにやっていること
Charles Web Debugging Proxy とても便利ですよね。
今でこそ、Stetho や Flipper などの、Androidアプリ側に仕込むライブラリでも事足りるようにもなってきましたが、通信内容の改ざんや特定のリクエストのみ他のサーバに転送したりなど、多岐にわたる機能がとても便利なため、どうしてもこれらのライブラリでは手が届かないところは、Charlesを使い続けています。
そもそも Charles って何なの?どう使うの?といった内容のブログは山程あるので、そういった方はそちらを見ていただくとして、私が紹介したいのは、Charlesをよりストレスフリーに使うためのテクニックをご紹介したいと思います。mitmproxy など、他のプロキシツールでも使えるテクニックです。
Charlesを使いながら面倒だなあと思うこと
Charlesを日常で使っていて面倒なことといえば、プロキシの設定じゃないでしょうか。AndroidでWiFiのプロキシを設定しようと思った場合、設定アプリのWiFiの画面を表示して、いま接続しているWiFiのオプションを開き、プロキシを設定するモードにして、IPアドレスを設定して、ポート番号を指定して… となかなかステップ数が多く、モバイルの小さい画面でIPアドレスを打つのはなかなかストレスフルです。そもそもIPアドレスを設定するためには、プロキシサーバになる母艦のIPアドレスを知る必要があるので、ターミナルでifconfig
とか打たないといけないですね*1。
逆にプロキシを使いたくない時もまた面倒だなあと思うことがあります。プロキシの設定がされたままではAndroid側は通信をすることができないので、母艦でCharlesを立ち上げ続けておく必要があります。Charlesはそんなに軽いアプリケーションというわけでもなく、必要ないときには起動しておきたくないので、モバイル側のプロキシの設定を消す必要があります。 ここで消したら再び使いたいときに、また奥まった機能の小さな画面でIPアドレス打ったりしないといけません。
PAC
日々プロキシの設定をしたり消したりしているうちに、あるオプションに気づきました。
プロキシの種類を指定するところに「プロキシの自動設定」とあります。なんとも甘味な響きに胸を打たれ、なんなのかと調べました。 調べてみると、これはプロキシに関する設定を定義として配布できる仕組みだと分かりました。
起源はNetscape時代から始まっており、なかなか歴史があるものなのですが、全然知りませんでした。 これを使えば小さい画面でポチポチプロキシの設定することから開放されそうです。
PACをどう書くのか
PACファイルはhttp(s) によってアクセスできる場所に置いておく必要があります。Amazon S3やGoogle Cloud Storageが手軽で適当だと思いました。 そこに次のようなファイルを置くとプロキシが有効になります。
function FindProxyForURL(url, host) { if (isPlainHostName(host) || isInNet(host,"127.0.0.1", "255.255.255.255")) { return "DIRECT"; } else { return "PROXY 192.168.10.2:8888; DIRECT"; } }
PACファイルはJavascriptで記述します。FindProxyForURL
という関数によってプロキシを使うかどうかを判定します。
この記述内容であれば、「通信先がローカルホストでなければ 192.168.10.2:8888
をプロキシとして使う」という内容になっています。
逆にプロキシを使わない場合は、次のようなファイルにしておきます。
function FindProxyForURL(url, host) { return "DIRECT"; }
DIRECT
という文字列を返すと、プロキシを使いません。
詳しい書式は割愛します。プロキシ自動設定ファイル - HTTP | MDN あたりが詳しいです。
あとは、このファイルにアクセスするためのURLをモバイル側のプロキシの設定として設定するだけです。
日常でPACを使うために
Amazon S3やGoogle Cloud Storageなどにファイルを置くようにすればファイルの更新も容易ですが、IPアドレスを調べたり、ファイルを更新したりといった作業も面倒だと思い、ツールを作りました。
コマンド一つでPACファイルを通してプロキシの有効/無効を切り替えることができるツールです。 局所的にそこだけコマンドを紹介すると、次のようなコマンドになります。
$ pac enable # プロキシ有効化 $ pac disable # プロキシ無効化
詳しい pacコマンドの設定や使い方は次節に書きます。
pac コマンドの使い方
設定
pacコマンドを使うためには、まず設定をする必要があります。これは、pacファイルをどこに置いておくか、という設定なので、誰しもがやる必要があります。 例えば Amazon S3にファイルを置く場合は次のようになります。
--- s3: bucket: your-bucket-name path: /
だいたい読み取れるんじゃないかと思いますが、この内容で、 s3://your-bucket-name/yout-name.pac
という場所にPACファイルができます*2。 自分の環境に合わせてバケット名やパスを設定できます。
プロキシの有効化
次のコマンドで有効になります。
$ pac enable
内部で aws
コマンドを使っているため、あらかじめ認証が通るようにしておく必要があります。
プロキシの無効化
$ pac disable
補足
- Google Cloud Storageのことも書きましたが、実はサポートしていません。自分が使う範囲で使えるなーと思ったので、公開しました。気が向いたらGCSを対応するかもしれませんが、PR貰えれば嬉しいです。
- Androidを中心に例を挙げましたが、もちろんiOSでも使うことができます。
最後に
PACファイルという存在を知ってから、プロキシを設定しなくてはならない、解除しなくてはならない、といったシチュエーションでだいぶストレスが減りました。通信内容を確認したいと思ったときに手軽にそれを使うことができるのは、とてもよいものですね。気持ちよく開発をすることができます。
通知センターの通知を全部消す
通知の種類をアラートからバナーに変更するとすぐに消えてしまって見逃しがありそう…ってことで、だいたいの通知はアラートにして、自動的に消えないようにしています。 ですが、ちょっと離席したときに通知が溜まっていると、それを全部ポチポチ消すのは面倒ですね。
そこで全部消すためのスクリプトをAlfred workflowにしています。 動作イメージはこんな感じ。
シュッと消えてくれて便利です。 こちらからダウンロードできますが、macOSの設定を英語にしていないと動きません。
ここのClose
を閉じる
に変更すると日本語でも動くので、その場合はビルドしなおして alfredworkflowファイルを作り直してください。
https://github.com/tomorrowkey/alfred-workflows/blob/master/clear_notification/clear.applescript#L5
cloneしていないリポジトリのmasterのハッシュを調べる
git-ls-remote
を使う
$ git ls-remote https://github.com/tomorrowkey/adb-peco master 788d83985e44f747a785cb948ac75fe4a048862d refs/heads/master
もちろんgithubじゃなくてもいいからandroidのframework/baseのmasterを取得する場合はこんな感じ
$ git ls-remote https://android.googlesource.com/platform/frameworks/base master d68f003c67ca6364202a57f0c695012d4ea4571e refs/heads/master
オプションなど
$ man git-ls-remote GIT-LS-REMOTE(1) Git Manual GIT-LS-REMOTE(1) NAME git-ls-remote - List references in a remote repository SYNOPSIS git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>] [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>] [--symref] [<repository> [<refs>...]] DESCRIPTION Displays references available in a remote repository along with the associated commit IDs. OPTIONS -h, --heads, -t, --tags Limit to only refs/heads and refs/tags, respectively. These options are not mutually exclusive; when given both, references stored in refs/heads and refs/tags are displayed. --refs Do not show peeled tags or pseudorefs like HEAD in the output. -q, --quiet Do not print remote URL to stderr. --upload-pack=<exec> Specify the full path of git-upload-pack on the remote host. This allows listing references from repositories accessed via SSH and where the SSH daemon does not use the PATH configured by the user. --exit-code Exit with status "2" when no matching refs are found in the remote repository. Usually the command exits with status "0" to indicate it successfully talked with the remote repository, whether it found any matching refs. --get-url Expand the URL of the given remote repository taking into account any "url.<base>.insteadOf" config setting (See git-config(1)) and exit without talking to the remote. --symref In addition to the object pointed by it, show the underlying ref pointed by it when showing a symbolic ref. Currently, upload-pack only shows the symref HEAD, so it will be the only one shown by ls-remote. --sort=<key> Sort based on the key given. Prefix - to sort in descending order of the value. Supports "version:refname" or "v:refname" (tag names are treated as versions). The "version:refname" sort order can also be affected by the "versionsort.suffix" configuration variable. See git-for-each-ref(1) for more sort options, but be aware keys like committerdate that require access to the objects themselves will not work for refs whose objects have not yet been fetched from the remote, and will give a missing object error. -o <option>, --server-option=<option> Transmit the given string to the server when communicating using protocol version 2. The given string must not contain a NUL or LF character. When multiple --server-option=<option> are given, they are all sent to the other side in the order listed on the command line. <repository> The "remote" repository to query. This parameter can be either a URL or the name of a remote (see the GIT URLS and REMOTES sections of git-fetch(1)). <refs>... When unspecified, all references, after filtering done with --heads and --tags, are shown. When <refs>... are specified, only references matching the given patterns are displayed. EXAMPLES $ git ls-remote --tags ./. d6602ec5194c87b0fc87103ca4d67251c76f233a refs/tags/v0.99 f25a265a342aed6041ab0cc484224d9ca54b6f41 refs/tags/v0.99.1 7ceca275d047c90c0c7d5afb13ab97efdf51bd6e refs/tags/v0.99.3 c5db5456ae3b0873fc659c19fafdde22313cc441 refs/tags/v0.99.2 0918385dbd9656cab0d1d81ba7453d49bbc16250 refs/tags/junio-gpg-pub $ git ls-remote http://www.kernel.org/pub/scm/git/git.git master pu rc 5fe978a5381f1fbad26a80e682ddd2a401966740 refs/heads/master c781a84b5204fb294c9ccc79f8b3baceeb32c061 refs/heads/pu $ git remote add korg http://www.kernel.org/pub/scm/git/git.git $ git ls-remote --tags korg v\* d6602ec5194c87b0fc87103ca4d67251c76f233a refs/tags/v0.99 f25a265a342aed6041ab0cc484224d9ca54b6f41 refs/tags/v0.99.1 c5db5456ae3b0873fc659c19fafdde22313cc441 refs/tags/v0.99.2 7ceca275d047c90c0c7d5afb13ab97efdf51bd6e refs/tags/v0.99.3 SEE ALSO git-check-ref-format(1). GIT Part of the git(1) suite Git 2.18.0 06/21/2018 GIT-LS-REMOTE(1)
配列の要素を一意にする
RubyでいうところのArray#uniq
みたいなもの
let array = [1, 1, 2, 4, 1, 3, 2] array.enumerated().compactMap({ index, item in array.index(of: item) == index ? item : nil })
それぞれの「index」と「arrayからindex(of:)
で取得したindex」が一致した場合のみ要素が残るようにしている。
つまり最初に出現した要素だけが残るようになっている。
毎回書くののも面倒なので、extensionしておくと便利
Closureの即時実行を使ったスコープの切り分け
Swiftのletはimmutableな変数宣言で、一度値を入れたらその後に変更することができない。
let hoge = "hoge" hoge = "fuga" // コンパイルエラー
これは変数宣言のときに値を入れないといけない、という制限ではなく、その変数が使われるまでに値が入っていれば問題ない。 ただし、その場合は型の宣言を省略できない。
let hoge: String hoge = "hoge" // OK
「その変数が使われるまでに値が入っていれば問題ない。」というのは例えばif文やswitch文を使っても大丈夫
let hoge: String if arc4random() % 2 == 0 { str = "even" } else { str = "odd" } debugPrint(str) // "even" もしくは "odd"が出力される
たまに処理が複雑で使い捨て変数を割り当てないといけないことがある。
let array = Array(1...10) var sum = 0 array.forEach({ sum += $0 }) let average = sum / array.count
このときsum
変数は一時的な変数で、average
を求めたら必要なくなる。このexampleではそんなことないんだけど、使い捨ての変数名を考えるが面倒で、手が止まってしまうことがしばしばあり、違うスコープを切りたい時に有効なのがクロージャだ。
let array = Array(1...10) let average: Int = { var sum = 0 array.forEach({ sum += $0 }) return sum / array.count }()
クロージャ内部は別のスコープなので、使い捨ての変数は本当に使いたい部分でだけ有効になる。 まぁそもそもこのexampleではreduceを使えばいい話なんだけど…
let average = array.reduce(0) { sum, i in sum + i } / array.count
Viewに関するコードを書いていると使い捨ての変数を定義したくなることがあるので、そういうときに使うと便利。