ごらくらいふ

プログラミングしたりゲームしたり

lsコマンドで更新日時順に表示するには -t オプションをつける

更新日時順に一覧を出したいときにパッとわからなかったので備忘録。

結論

$ ls -t

で更新日時順に表示される。(新しいものほど先)

バリエーション

リスト表示かつ、古いものから先に表示する。

$ ls -ltr

直近更新の数件だけ見たい時に tail コマンドと合わせて使うといい感じ。

iOSシミュレーター内のアプリケーションコンテナはUUIDが振り直される

経緯

  • アプリケーションそのままに、アプリケーションコンテナ(以下、コンテナ)内のリソースを弄って確認したい時があった。
  • macの都合で作業中断する必要があり、 pwdで出したパスを書き残して再起動した。
  • 再起動後、そのパスめがけて cdをかけるも見つからないとエラー。

原因

シミュレーター内の各コンテナを確認したところ、アプリケーションごとのUUIDが変更されていることがわかった。

対策

シミュレーターのパスは変わらないので、コンテナの中にマーカーを残しておくのがいいと思う。

touch marker_000

cd /Users/${username}/Library/Developer/CoreSimulator/Devices/${simulatorID}/data/Containers/Data/Application
find . -name marker_000

なんでだろう

  • アプリケーションコンテナのIDが振り直されなかったら、他のアプリケーションからの介入ができてしまうかもしれないから?

PS4に外付けSSDぶっこんだよ

ロード時間がかなり改善された。もう導入してから1ヶ月は経つかな。

もとは↓の記事で書いたように換装した2TBのHDDをつかってた。

yajamon.hatenablog.com

ベンチマークってほどじゃないけど、FF15を起動してからLoad savedata が完了するまで、HDD時代は 1分30秒くらいだったのだけど、 外付けSSDにしたら 30秒で終わった。

この数字だけだとまー所詮1分じゃん、ってなわけだけど、ペルソナ5とかマップ間のロードがすごいスムーズなのね。 ローディング中、主人公の顔が回る回数激減。すげー早い。快適性が高まりすぎる。

いい買い物したわ感ですよ。

以下に買った商品貼っておく。自分の環境ではいい感じに動いた。

トラブルシューティング

PS4に繋いでUSB3.0対応ストレージとして認識されない事象があった。 ケース側の接触不良だったようで、ケーブルとケースを「しっかり刺した」くらい刺さないといかんかったよ。

アルミケース良いよアルミケース。

SanDisk 内蔵SSD 2.5インチ/1TB/SSD Ultra 3D/SATA3.0/3年保証/SDSSDH3-1T00-J25

SanDisk 内蔵SSD 2.5インチ/1TB/SSD Ultra 3D/SATA3.0/3年保証/SDSSDH3-1T00-J25

ほんと、SSDの速度には抗えない魅力があるよ。うん。

権限のクリーンなURL, タイトルコピー系chrome拡張を作った。

はい。

や、職場で「ガバガバ権限まじでやめて」って言われたので「じゃーもう自作しますわ」ってなってやりました。

久しぶりに作って頭の体操になった感じする。

chrome.google.com

「このサイトを共有したい」そう思ったときにタイトルとリンクが一度にコピーできると便利です。

この拡張は権限がクリーンであることを特徴としています。

"アクセスしたウェブサイト上にある自分の全データの読み取りと変更"を必要としません。 この権限ができることは広く、セキュリティ管理の都合から拡張を手放すよう指導されることもあります。

この権限問題を解消すべく、不安のない拡張を作りたいという思いから、この拡張は作られました。

ポップアップを開いた時点でクリップボードにコピーをしに行くので、拡張機能を起動するショートカットを登録するのがおすすめ。自分はcmd+Shift+Cにしてる。 設定はchrome://extensions/shortcutsにて。

コードはGitHubにあります。

github.com

完全に自分が必要なフォーマット${title}\n${url}だけの状態で公開してるので、Markdown用のやつがほしいとかあると、オプションページを作る動機になる。donate枠とか作れるし。

Pull-Requestお待ちしてます。

あとはぺろっとほしいものリストでも貼っておきますね。 https://www.amazon.co.jp/gp/registry/wishlist/10FZP34Z9U32Q

URLConnectionの通信をURLSessionに書き換えた

NSURLConnectionがiOS 9.0でDeprecatedになってから時間も経ち、もうiOS 12が出る時勢にNSURLSessionへの書き換え事案が発生した。

感想

NSURLConnectionDataDelegateとNSURLSessionDataDelegateの互換性はわりと確保されていて助かった。 なぜかcompletionHandlerにわたす引数の順序が変わってたけど。

NSURLConnectionにおけるdidFinishLoadingとdidFailWithErrorが、 didCompleteWithErrorにまとまったので、errorをちゃんと確認しないといけないのが「あーそうですかぁ」という感じ。

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    if (error) {
        // connection:didFailWithError: 相当の処理
        return;
    }
    // connectionDidFinishLoading: 相当の処理
}

だいたいどんなことをしたか。

サブスレッドでNSURLConnectionを動かすために、NSRunLoopとwhileを組み合わせて待機させていた。 また、そのサブスレッドの中で同期的な動きをするところに依存していた。

これをNSURLSessionに書き換えるとき、RunLoopを使う必要がないので、NSConditionでwaitをかけて再現した。

// before
- (void) download:(NSURLRequest *)request {
    // befor
    self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
    while(!self.completed && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) ;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    self.completed = YES;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    self.completed = YES;
}
// after
- (void) download:(NSURLRequest *)request {
    NSURLSessionConfiguration *configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration;
    self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    self.task = [self.session dataTaskWithRequest:request];
    [self.task resume];
    
    [self.condition lock];
    [self.condition wait];
    [self.condiiton unlock];
    self.condition = nil;
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    [self.condition lock];
    [self.condition signal];
    [self.condition unlock];
}

delegateQueuenilを与えているのはどこでもいいから他のスレッドで処理してもらうため。 後続処理のwaitによってsessionを作るスレッドはスリープしてしまう。

Rust Vec<T>を特定の長さで分割する

背景

gifとかzipとかパースしたいなあ+Rust触りたいなあ! ということで、まずはバイナリダンプから始めようとした。

以下のようなフォーマットで標準出力に吐き出したい。

50 4b 03 04 00 00 00 00 00 00 00 00 00 00 00 00 | PK.............. 

一行出力するにあたり、バイナリのほか、一時的に格納した文字列情報が必要。

最初はfor文に食わせて、愚直にカウンタ制御でVecに文字を詰めたり改行して実装した。 当然ながら、どこまで出力されているかを意識してコードを書かなければならない。

これではしんどいので、octet単位ではなく行単位の出力で考えたい。

目的

Vec<u8> *1 を二次元配列的に扱えるように変換する。

結論

let lines: Vec<&[u8]> = binary.chunks(BYTES_IN_LINE).collect();

各行の長さをあとで変えたり、所有権も持たせたくてVec<Vec<u8>>が良いならば以下のとおり。

const BYTES_IN_LINE: usize = 16;
let lines: Vec<Vec<u8>> = binary.chunks(BYTES_IN_LINE).map(|chunk| chunk.to_vec()).collect();

余談

.chunksを探しに行く前に、愚直に作る処理を書いてみたのだけれど、これが数行で済むのだから便利だなぁ。

const BYTES_IN_LINE: usize = 16;
let lines: &mut Vec<Vec<u8>> = &mut vec![];
let mut line: Vec<u8> = vec![];
for octet in binary {
    line.push(octet.clone());
    if line.len() >= BYTES_IN_LINE {
        lines.push(line);
        line = vec![];
    }
}
if line.len() > 0 {
    lines.push(line);
}

*1:軽量なデータから始めるので、fs.read(path) -> Vecを使う。

DeployGateのコマンドラインツールから Commands::Deploy Error: NoMethodError と怒られる件

環境

  • ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
  • deploygate-cli v0.6.4
  • Xcode 9.4.1

現象

dg deployを実行すると、適切にBundle Identifierを指定しているにも関わらず、Bundle Identifierの入力を求められたのち、 下記のエラーが発生する。

Status
deploygate-cli ver 0.6.4

Error message
undefined method `build_configuration_list' for nil:NilClass

Backtrace
/path/to/gemroot/gems/deploygate-0.6.4/lib/deploygate/xcode/analyze.rb:145:in `target_build_configration'
/path/to/gemroot/gems/deploygate-0.6.4/lib/deploygate/xcode/analyze.rb:91:in `target_xcode_setting_provisioning_profile_uuid'
/path/to/gemroot/gems/deploygate-0.6.4/lib/deploygate/commands/deploy/build.rb:50:in `ios'
/path/to/gemroot/gems/deploygate-0.6.4/lib/deploygate/commands/deploy/build.rb:22:in `run'
/path/to/gemroot/gems/deploygate-0.6.4/lib/deploygate/commands/deploy.rb:16:in `run'
/path/to/gemroot/gems/deploygate-0.6.4/lib/deploygate/command_builder.rb:70:in `block (2 levels) in run'
/path/to/gemroot/gems/commander-4.4.5/lib/commander/command.rb:182:in `call'
/path/to/gemroot/gems/commander-4.4.5/lib/commander/command.rb:153:in `run'
/path/to/gemroot/gems/commander-4.4.5/lib/commander/runner.rb:446:in `run_active_command'
/path/to/gemroot/gems/fastlane-2.57.2/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:64:in `run!'
/path/to/gemroot/gems/commander-4.4.5/lib/commander/delegates.rb:15:in `run!'
/path/to/gemroot/gems/deploygate-0.6.4/lib/deploygate/command_builder.rb:128:in `run'
/path/to/gemroot/gems/deploygate-0.6.4/bin/dg:6:in `<top (required)>'
/path/to/gemroot/bin/dg:23:in `load'
/path/to/gemroot/bin/dg:23:in `<main>'
/path/to/gemroot/bin/ruby_executable_hooks:15:in `eval'
/path/to/gemroot/bin/ruby_executable_hooks:15:in `<main>'

解消方法

Xcodeのメニューバーから、[Product]> [Scheme]> [Manage Schemes ...] を開き、閉じる。

原因

  • lib/deploygate/xcode/analyze.rbが必要とする、*.xcschemeが存在しないため

調査記録

なんだか業務issue感さえ漂うので、何を調べたのか書き残す。余談。

Backtraceいわく、target_build_configrationの処理中に問題が発生したことがわかる。

def target_build_configration
  target_project_setting.build_configuration_list.build_configurations.reject{|conf| conf.name != @build_configuration}.first
end

https://github.com/DeployGate/deploygate-cli/blob/v0.6.4/lib/deploygate/xcode/analyze.rb#L145

undefined method 'build_configuration_list' for nil:NilClassということから、target_project_settingの結果がnilであることが直接の問題であるとわかる。

def target_project_setting
  scheme_file = find_xcschemes
  xs = Xcodeproj::XCScheme.new(scheme_file)
  target_name = xs.profile_action.buildable_product_runnable.buildable_reference.target_name


  target_project.native_targets.reject{|target| target.name != target_name}.first
end

https://github.com/DeployGate/deploygate-cli/blob/v0.6.4/lib/deploygate/xcode/analyze.rb#L153-L155

ではtarget_project_settingの中身で何が起きているのか確認するため、scheme_file, xs, target_nameをprintしてみたところ、すべてnilであることが確認できた。

この時点で、まずfind_xcschemesが怪しいと直感を得た。(悪い癖)

native_targets.reject{|target| target.name != target_name}を見て、「ああ、target_nameがnilになっちゃって正しいtargetも捨てちゃってるんだな」という認識を挟むのが正しい怪しみ方だろう。

def find_xcschemes
  shared_schemes = Dir[File.join(@xcodeproj, 'xcshareddata', 'xcschemes', '*.xcscheme')].reject do |scheme|
    @scheme != File.basename(scheme, '.xcscheme')
  end
  user_schemes = Dir[File.join(@xcodeproj, 'xcuserdata', '*.xcuserdatad', 'xcschemes', '*.xcscheme')].reject do |scheme|
    @scheme != File.basename(scheme, '.xcscheme')
  end


  shared_schemes.concat(user_schemes).first
end

https://github.com/DeployGate/deploygate-cli/blob/v0.6.4/lib/deploygate/xcode/analyze.rb#L165-L170

で、find_xcschemesの中にあるshared_schemes, user_schemesもprintしてみればこっちもnilだと確認した。 というかブロックの中に入っていなかった。

File.joinで組んでいるパターンをターミナルからも確かめた結果、*.xcschemeが生成されていないことがわかった。 おそらくこれが原因だろうと、schemeを作る手段を求めて上記解消方法を試したところ、*.xcschemeが生成されたことを確認できた。

関連リンク

解消手順を報告させてもらったissue