なっく日報

技術やら生活やらのメモ

グローバルでgitフックスクリプトを仕掛けると`go get`がちゃんと動作しなくなる可能性がある

go getが毎回止まるという現象に悩んでいて、その解決策を見つけたので書いておきます。

原因

yukidarake.hateblo.jp

これで、通常のGitHubGitHub Enterpriseとで、メールアドレスを使いわけるということをやっていたのが原因でした。

解決策

残念ですが、上記の設定を諦める(上手く書けば大丈夫かもしれないが、そこまでするのはもういいや。。。)

git2.8以上を使えば、

git config --global user.useConfigOnly trueを設定し、

リポジトリ毎にuser.nameuser.emailの設定を強制するようにできるようなのでこれでいいかな。。

参考

リポジトリごとに user.name や user.email の設定を強制する - Qiita

Visual Studio CodeのKeyBindingをCTRL+Nを↓、CTRL+Pを↑に変更する

しばらくサボってましたが、今日からは再び頑張りたい。。

諸事情により、Visual Studio Codeを触り始めました。

が、違和感を感じたのが各種ウィンドウでCTRL+N、CTRL+Pのキーバインドが効かないこと。

ググッてみたところ

github.com

↑のEmacs向けのキーバインドを公開してくれている方がいました。

ありがたや。

しかし、自分は生粋のEmacsユーザという訳ではなく、とりあえずCTRL+N、CTRL+Pが効けばよかったので

curl -s https://raw.githubusercontent.com/nana4gonta/emacs-visual-studio-code/master/release/keybindings-osx.json | jq 'map(select(.key=="ctrl+n" or .key=="ctrl+p"))'

で該当する設定だけをいただきました。

あとは、Code -> Preferences -> Keyboard Shortcuts でkeybindings.jsonに貼り付けるだけです。

Mochaで--delayフラグを使って初期化完了までテストを実行しないようにする

--delayフラグ?

http://mochajs.org/#delayed-root-suite

で知りました。

setTimeout(function() {
  // do some setup

  describe('my suite', function() {
    // ...
  });

  run();
}, 5000);

のように書いて、mocha --delay test と実行すると、run()が呼ばれるまでテストの部分までは行かないと。

ちなみにrun()はmochaが勝手にグローバルスコープに追加してくれる関数だそう。

使用例

DBに接続するまでテストを実行しないようにすることができたりとか?

例えば、

↓のようなbootstrap.js というファイルを作り

DB.connect((err, db) => {
  run();
});

mocha --delay -require bootstrap.js test と実行するとか。

これで、connect()の処理が終わるまでテストが動かないようにできるはず。

本当のところ

きちんとコードを書いていれば恐らくこの書き方は必要ないんじゃと思いますw

でも、某古めなプロジェクトで困ったコードがあり、これは使えるんじゃ?と思ったので記事にしました。

本日はこんなところで。

Perlのワンライナーでよく使うテクニック

あまり時間がないので5分で!

ファイルの中身を置換する

↓はカレントディレクトリ配下のJSファイルのfooという文字列をbar

perl -i -pe 's/foo/bar/' **/*.js

findと組み合わせたりもできます。 カレントディレクトリ配下のJSファイルのパスを置換をするために /が入るときはs{}{}の書き方にすると便利です。

find . -name '*.js' | xargs perl -i -pe 's{/tmp}{/var/log}'

マッチした行から必要なテキストだけを表示

echo 'var hoge = "foo";' | perl -lnE '/var (.+?) =/ && say $1'
# => hoge

みたいに書けます。

  • -lは改行の問題で悩まなくて済むようになるので、つけておきましょう。
  • -Esayが使えるのでちょっと楽ちん。

ESLintでWarningで引っかかっているルール名を抜き出す。

eslint . -f unix | perl -lnE 'm#Warning/(.+)\]# && say $1' | sort | uniq

awk的な使い方

  • -aをつけます。
  • これまた-lは改行の問題で悩まなくて済むようになるので、つけておきましょう。
echo 'a b c' | perl -lanE 'say $F[0]'
# => a

awkと違い、インデックスは0からで$F[0], $F[1]みたいに参照できます。

特定の文字列を含むプロセスを殺す! pkillが入ってない場合とかに使ってみてはいかがでしょうか。

ps aux | grep hoge | perl -lanE 'say $F[1]' | xargs kill

本日は

こんなところで。

ESLintでファイルの中身によって設定ファイルを切り替える

yukidarake.hateblo.jp

の続きで、実際やってみたという話です。

雑なメモですがご容赦ください。

ESLint plugin作成

ここではeslint-plugin-fooとしておきましょうか。

package.jsonとindex.jsを作ります。

eslint-plugin-fooという文字列があれば、.eslintrc2.ymlを使うようにします。

ソース

'use strict';
var eslint = require('eslint');
var alternativeCLIEngine = new eslint.CLIEngine({
  configFile: './.eslintrc2.yml',
});

function preprocess(text, filename) {
  if (!/eslint-plugin-foo/.test(text)) {
    return [text];
  }

  var config = alternativeCLIEngine.getConfigForFile(filename);

  var eslintRules = '/*eslint ' + Object.keys(config.rules).map(function(rule) {
    return rule + ':' + JSON.stringify(config.rules[rule]);
  }).join(',') + '*/';

  return [eslintRules + text];
}

function postprocess(messages) {
  return messages[0];
}

module.exports = {
  processors: {
    '.js': {
      preprocess: preprocess,
      postprocess: postprocess,
    },
  },
};

こんな感じ。

https://github.com/yukidarake/eslint-plugin-foo

ソースは↑にあげました。

仕組み

ファイルのどこかにeslint-plugin-fooがあれば、行頭に/*eslint no-var:0*/みたいに付けるという超力技。

動かしてみる

必要なモジュールのインストール

使いたいファイルのあるディレクトリで

npm i eslint
npm i yukidarake/eslint-plugin-foo

してください。

.eslintrcを2つ用意

.eslintrc.yml

---
root: true
plugins:
  - foo
rules:
  no-var: 2

.eslintrc2.yml

---
root: true
rules:
  no-var: 0

実行

これで準備は整いました!

a.js

// eslint-plugin-foo
var a = 1;

というファイルを使って、コメント行の文字列を消したり、戻したりしながら実行してみてください。

./node_modules/.bin/eslint a.js

結果

/private/tmp/a.js
  2:1  error  Unexpected var, use let or const instead  no-var

✖ 1 problem (1 error, 0 warnings)

と出たり出なかったり・・・

ソース中のテキストの有無によって.eslintrc.ymlと.eslintrc2.ymlを切り替えできているようです。

まとめ

この方法をうまいこと使えば同じディレクトリ内でES5とES2015のJSファイルが混在していてもうまいことチェックできたりするのでは?

というアイデアでした。

もっと良い方法や指摘事項等あればぜひ教えてください・・・

SVNの.svnディレクトリを一発で消す

2016年にSVN!?

しかも、Subversion 1.7より前の話!?
(1.7以降はルートにのみ.svnディレクトリがあるので今回みたいなことは起きない)

というのはさておき、困っていたデザイナーさんがいたので救いました
(あと、特に目新しい技術ネタもなかったので。。)

現象

他のディレクトリをまるっとコピーしたことで余計な.svnディレクトリが付いてきて、新しく作ったはずのディレクトリがコミットができない。

A/.svn
A/dir1
A/dir1/.svn
A/dir1/file1
A/dir1/file2

↑みたいなAディレクトリをBディレクトリとしてコピーしたら、.svnまでコピーしちゃったという感じ。

対応

一緒にコピーしてしまった.svnディレクトリだけを消してやると。

ターミナルでサクッと。

find . -type d -name '.svn' | xargs rm -r

本当は

find . -type d -name '.svn' -print0 | xargs -0 rm -r

とやったほうが安全だけど今回は端折りました。

上記のfindとxargsのコマンドの各オプションの意味は↓の記事が解説がしっかりしているのでオススメです。

findとxargsの基本的な使い方 -- ぺけみさお

Ansibleのshellモジュールでヒアドキュメントが使いたいときー

が、あると思います。

shellモジュールでヒアドキュメントを使うと・・・

github.com

コチラのissueにコメントがありましたが、

- shell: |
    cat <<EOT
    a
    b
    EOT

の結果は

 a
 b

(半角スペースがaとbの前に入る)

という。。

大半のケースでは大丈夫でしょうが、困る場合もあります。

対策

Ansibleのコアディベロッパーが推奨しているらしい方法

scriptモジュールを使う。

http://docs.ansible.com/ansible/script_module.html

ローカルにあるファイルをリモートに転送して実行してくれます。

例えば、

roles/common/file/script.sh
roles/common/task/main.yml

な構成をとっていた場合、roles/common/task/main.ymlでは

- script: script.sh

みたいに使えます。

これならAnsible特有の問題で嵌ることもないでしょう。

ワークアラウンド

発想の転換に感心してしまったのですが、sedを使って空白を取り除きますw

- shell: |
    sed 's/^ //' <<EOT | cat
    a
    b
    EOT

これで普通にヒアドキュメントをcatしたのと同じになると。

まとめ

ま、ほんとうは冪等性確保のために、shellモジュールもscriptモジュールも使うなということなのでしょうが・・・

どなたかの参考になれば幸いです。