Perforceのセットアップ for Mac
はじめに
PerforceはSubversionのようなバージョン管理システムでbinaryの管理に向いているそうです。今回はp4v
というツールとp4
というコマンドラインツールを導入したのでそのセットアップ方法について書きます。
p4v
のセットアップ
設定はこちらのリンク に沿ってやるだけですが、管理者からServerのアドレスとuser名をいただき入力するだけです。
以上で設定は完了です。
p4v
の使い方
ログイン後、始めに差分を取得するためルートディレクトリで右クリックを押しGet Latest Revision
を取得します。
全てのファイルはRead Onlyになっており編集権限がありません。もし編集したい場合はファイルを右クリックでCheck out
する必要があります。チェックアウトをすると編集が可能になり、その情報は他のユーザにシェアがされます。編集後、右クリックを押しsubmitすることで他のユーザに変更がシェアされます。
もし差分を見たい場合は、右クリックでDiff Against Have Revision
を押すとp4vdiff
が起動し差分を見ることが可能です。
p4
のセットアップ
p4v
だとマウス操作が多いため、やはりCLIでどうにかしたいところです。そのためp4
をインストールします。リンクはこちら。
次にパスなどの情報をセットします。
私は.zshrc
をGithub上で管理しているため、secretな情報を隠すために別ファイルを用意しました。
# ~/.secret.sh export P4PATH=<server-url> export P4USER=<user-name> export P4CLIENT=<workspace-name> p4 login
# ~/.zshrc if [ -f $HOME/.secret.sh ]; then source $HOME/.secret.sh fi
上記の.secret.sh
を.zshrc
で読み込み、terminal起動時にp4
にログインをしています。これで準備は完了です。
編集したいときは、p4 edit
を使用することでチェックアウトが可能になります。また他にもいくつかコマンドがあるので試してください。
まとめ
私はgit
ばかり触っているゆとりですが、少しずつ慣れていこうかなと思っています。
次回はp4
+ vim
あたりについて書こうと思います。
リンク
Ruby on Railsのセットアップ
はじめに
Rubyデビューしたので初心に戻ってその勉強記録を記して行きたいと思います。
手順は
- rbenv (バージョン管理システム)
- nokogiriのインストール
- Railsのインストール
- アプリの起動
です。
rbenvのインストール
rbenvは最も有名なバージョン管理ツールらしいので、流行りに乗ってインストールしたいと思います。
…のつもりが、長いことmacを使っていると自ずとrbenvがインストールされていることもあるようで、gem installが通らなかったりしたのでuninstallから始めます。
手順はこちらです。
uninstall? · Issue #148 · rbenv/rbenv · GitHub
$ rm -rf ~/.rbenv $ brew uninstall rbenv
と、.zshrc
からrbenv
なる記述を削除しました。
それでは気を取り直してインストールします。
$ brew install rbenv
後は.zshrc
に追記します。
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc $ echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.zshrc
Rubyのセットアップ
次にrubyをインストールします。
$ rbenv install 2.4.1
最新版をインストールしたい方はrbenv install -l
で最新版をチェックしてください。
rbenv rehash rbenv global 2.4.1
以上で完了です。
nokogiriのインストール
ここで少しハマったのがmacではnokogiriのインストールをmacのインストレーションに沿ってやらないといけないようなので、別途インストールします。
$ gem update --system $ xcode-select --install $ gem install nokogiri
これはmac OS Xというところに記載されています。
Railsのインストール
$ gem install rails
コマンドはこちらだけですね、とても簡単。
アプリの起動
適当なディレクトリに行き、以下のコマンドを叩きます。 チュートリアルに沿って、
$ rails new hello_app
$ cd hello_app
$ rails server
これでhttp://localhost:3000/にアクセスすると以下の画面が表示されます。
まとめ
とても簡単にRailsサーバが立ち上がりました。
Yay! I'm on Rails!
はい。せっかくなので何かサーバ建てたいですね。
リンク
classの継承についての考察
概要
ES6の継承が遅すぎると話題なので検証・最適化をしました。
どれくらい遅いのか
こちらのベンチマークによると、少しずつ改善は見られるものの、2.3-17倍程度遅い様子です。
実際に検証しました。
- Node v6.10.1
- benchmark.js v2.1.4
継承
// classes function ParentES5(value) { this._value = value; } function ES5(value) { ParentES5.call(this, value); } util.inherits(ES5, ParentES5); class ParentES6 { constructor(value) { this._value = value; } } class ES6 extends ParentES6 { constructor(value) { super(value); } } // functions const funcs = { 'es5': function() { return new ES5(1); }, 'es6': function() { return new ES6(1); } };
**** benchmark.js **** [1] "es5" 0.000029ms [1.00] [2] "es6" 0.000045ms [1.56]
単純にclassを使うだけでも1.5倍遅いようです。
super classメソッドの呼び出し
function ParentES5(value) { this._value = value; } ParentES5.prototype.get = function() { return this._value; }; function ES5(value) { ParentES5.call(this, value); } util.inherits(ES5, ParentES5); ES5.prototype.get = function() { return ParentES5.prototype.get.call(this) * 2; }; class ParentES6 { constructor(value) { this._value = value; } get() { return this._value; } } class ES6 extends ParentES6 { constructor(value) { super(value); } get() { return super.get() * 2; } } const es5 = new ES5(1); const es6 = new ES6(1); // functions const funcs = { 'es5': function() { return es5.get(); }, 'es6': function() { return es6.get(); } }
**** benchmark.js **** [1] "es5" 0.000021ms [1.00] [2] "es6" 0.000078ms [3.79]
super classメソッドの呼び出しは非常に遅いので避けたいところです。
考察
super classメソッドの呼び出し
function ParentES5(value) { this._value = value; } ParentES5.prototype.get = function() { return this._value; }; function ES5(value) { ParentES5.call(this, value); } util.inherits(ES5, ParentES5); ES5.prototype.get = function() { return ParentES5.prototype.get.call(this) * 2; }; class ParentES6 { constructor(value) { this._value = value; } get() { return this._value; } } class ES6 extends ParentES6 { constructor(value) { super(value); } get() { return ParentES6.prototype.get.call(this) * 2; } } const es5 = new ES5(1); const es6 = new ES6(1); // functions const funcs = { 'es5': function() { return es5.get(); }, 'es6': function() { return es6.get(); } }
**** benchmark.js **** [1] "es6" 0.000020ms [1.00] [2] "es5" 0.000020ms [1.02]
super.get()
の代わりにsuper classメソッドをcall
することでes5と同等のパフォーマンスが得られました。これは使えそうです。
こちらのパターンも同じような結果が得られます。
function ParentES5(value) { this._value = value; } function getES5() { return this._value; }; function ES5(value) { ParentES5.call(this, value); } util.inherits(ES5, ParentES5); ES5.prototype.get = function() { return getES5.call(this) * 2; }; class ParentES6 { constructor(value) { this._value = value; } } function getES6() { return this._value; }; class ES6 extends ParentES6 { constructor(value) { super(value); } get() { return getES6.call(this) * 2; } } const es5 = new ES5(1); const es6 = new ES6(1); // functions const funcs = { 'es5': function() { return es5.get(); }, 'es6': function() { return es6.get(); } }
**** benchmark.js **** [1] "es5" 0.000023ms [1.00] [2] "es6" 0.000023ms [1.00]
こちらもなかなか使いどころがありそうです。
継承
ParentES6.prototype.constructor
へのアクセスは禁止されているため、classをextendsしsuperを呼び出す必要があります。
class ParentES6 { constructor(value) { this._value = value; } } class ES6 extends ParentES6 { constructor(value) { super(value); } } // エラー class ES6 { constructor(value) { ParentES6.prototype.constructor.call(this, value); } } // TypeError: Class constructor ParentES6 cannot be invoked without 'new'
今のところたどり着いた最速の継承はこちらです。
function ParentES5(value) { this._value = value; } function ES5(value) { ParentES5.call(this, value); } util.inherits(ES5, ParentES5); class ParentES6 { constructor(value) { this._value = value; } get() { return this._value; } } function ES6(value) { this._value = value; } ES6.prototype = ParentES6.prototype; const es5 = new ES5(1); const es6 = new ES6(1); console.log(es6.get()); // 1 console.log(es6 instanceof ParentES6); // true // functions const funcs = { 'es5': function() { return es5.get(); }, 'es6': function() { return es6.get(); } }
[1] "es6" 0.000020ms [1.00] [2] "es5" 0.000026ms [1.33]
es5の継承よりも高速な継承が可能となりました。もう少し検証が必要ですが、instanceofがtrueとみなされるのでこちらは意外と使えるかもしれません。 こちらの案はthamminさんがベースを提供してくれました。
まとめ
superクラスの呼び出しを避ける考察でした。ns,μsレベルのチューニングなので普通にsuperを呼んでいただければと思います。
JavaScriptっておもしろい。
リンク
Powerlineの導入
概要
Powerlineとはshell・vimにちょっとした情報をカッコよく表示してくれるツールです。何よりカッコいい。導入手順はこちらです。
Powerline for Shell
まずはshellからカッコよくしていきます。はじめにpowerline-shell
をクローンします。
$ cd ~
$ git clone https://github.com/milkbikis/powerline-shell
このディレクトリは削除できないのでお好みなところにクローンしてきてください。
次にインストールします。設定を変えたい場合はconfig.py
を変更することでお好みの設定に変更できます。設定変更後は再度install.sh
を実行する必要があります。
$ ./install.sh
これでpowerline-shell.pyが生成されるので、Symlinkを貼ります。
$ ln -s ~/powerline-shell/powerline-shell.py ~/powerline-shell.py
私はzshを使用しているので、zshrc
に設定を以下のように追加します。bash, fishの設定はこちらを参照してください。
# power-shell function powerline_precmd() { PS1="$(~/powerline-shell.py --cwd-max-depth 1 $? --shell zsh 2> /dev/null)" } function install_powerline_precmd() { for s in "${precmd_functions[@]}"; do if [ "$s" = "powerline_precmd" ]; then return fi done precmd_functions+=(powerline_precmd) } if [ "$TERM" != "linux" ]; then install_powerline_precmd fi
次にフォントのインストールをします。こちらはREADMEのスクリプトをそのまま実行するだけです。
# clone git clone https://github.com/powerline/fonts.git # install cd fonts ./install.sh # clean-up a bit cd .. rm -rf fonts
こんな感じになりました、カッコいいだけでなく意外に便利です。
Powerline for Vim
次にvimのpowerlineの設定をしていきます。はじめにお使いのvimの環境を確認してください。こちらから条件を確認できます。
私はvim-plugを使っているので.vimrc
に以下のように追加します。
Plug 'powerline/powerline', {'rtp': 'powerline/bindings/vim/'}
フォントもインストール済みなので、以上で設定は終了です。 別のプラグインを使っている方はこちらから確認してみてください。
こんな感じになります。
まとめ
デメリットはshellが少し重くなりますが、カッコいいだけでなく意外にも便利だったので導入してもいいかなと思いました。
リンク
- GitHub - powerline/powerline: Powerline is a statusline plugin for vim, and provides statuslines and prompts for several other applications, including zsh, bash, tmux, IPython, Awesome and Qtile.
- GitHub - banga/powerline-shell: A beautiful and useful prompt for your shell
- GitHub - powerline/fonts: Patched fonts for Powerline users.
AnyenvでGoのバージョン管理
概要
Anyenvとはこれ一つで色々なパッケージ管理ができるスグレモノのようです。今回はGolangまわりだけ整理していたので、Golangのセットアップ手順について書きます。
インストール
まずはリポジトリをクローン。
$ git clone https://github.com/riywo/anyenv ~/.anyenv
.zshrc
に以下を追記。
# anyenv export PATH="$HOME/.anyenv/bin:$PATH" eval "$(anyenv init -)"
goenv
をインストールします。
$ anyenv install goenv
$ goenv install 1.8
.zshrc
にGOPATHを設定します。(goenv rehashで解決してくれると思ったらそうでもない)
# Go export GO_VERSION=1.8 export GOROOT=$HOME/.anyenv/envs/goenv/versions/$GO_VERSION export GOPATH=$HOME/dev export PATH=$HOME/.anyenv/envs/goenv/shims/bin:$PATH export PATH=$GOROOT/bin:$PATH export PATH=$GOPATH/bin:$PATH echo Now using golang v$GO_VERSION
なんとなくnvm
と同じechoを追加します。
Now using node v6.10.1 (npm v3.10.10) Now using golang v1.8 $ go version go version go1.8 darwin/amd64
良い感じになりました。
まとめ
Version Managerにこだわりが無いようでしたら、新しい言語をインストールするときにあちこちVersion Managerを探しに行くよりサクッとインストールできるのでいいかなぁと思います。
リンク
Dockerのお掃除
概要
MBPの容量が圧迫しておりどうやら犯人はDocker for Macのようなのでお掃除していきます。
不要なコンテナの削除
Docker – Clean Up After Yourself! | Yohan Liyanage
こちらのブログより。
exited containersは自動削除されないとのことで、こちらを実行してくださいとの。
$ docker rm -v $(docker ps -a -q -f status=exited)
rmコマンドは少なくとも1つ以上の引数を必要とするので、
"docker rm" requires at least 1 argument(s). See 'docker rm --help'. Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...] Remove one or more containers
このエラーが出た場合は削除できるexited containersが存在しないとのことなので気にせず進みます。
不要なイメージの削除
macos - How to clean up Docker for Mac containers - Ask Different
続いてこちら。 ポイポイしていきます。
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /etc:/etc spotify/docker-gc
不要なコンテナ・イメージの削除【追記】
Christinaさんよりアドバイスいただき、以下のコマンドで上記2つは解決できるそうです、ありがとうございます。
$ docker system prune
Docker.qcow2の削除
最後のこちらが一番大物で、私の場合は30GBほど占領していました。 キャッシュのようですが容量をこんなに占拠されては困りますのでポイポイしていきます。
$ rm ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.qcow2
ソース
Node.jsで内部変数・関数の取得
概要
テストやちょっとしたツールを作りたいときに内部変数・関数にアクセスしたい時がありますが、
そんなときに便利なのがvm
モジュールです。しかしvm
ではvar
の変数は取得できるものの、let
やconst
の変数は取得できません。
そこで色々試行錯誤して作ったツールについて書きます。
vmを用いた内部関数の取得
vm.runInNewContext
ではコードを実行時にglobalオブジェクトをセットすることができます。vm.runInThisContext
は自動的に現在のglobalオブジェクトが使われます。
この関数は実行時にglobalスコープ上のvar
をglobalオブジェクトに代入することで外からのアクセスを可能にしてくれますが、let
やconst
は変換されません。
sample.js
const test1 = 'test1'; let test2 = 'test2'; var test3 = 'test3'; function test(arg1, arg2, arg3) { const sum = arg1 + arg2 + arg3; let num1 = 1; var num2 = 2; num3 = 3; return sum + num1 + num2 + num3; }
exec.js
const vm = require('vm'); const fs = require('fs'); const path = require('path'); const filepath = path.resolve(__dirname, 'sample.js'); const file = fs.readFileSync(filepath, 'utf8'); const context = {}; vm.runInNewContext(file, context); console.log(context); /* * { test3: 'test3', * test: [Function: test] } // let, constが取得できない */
vm-agent
今回作ったツールはlet
, const
が取得できるのと、関数を自動実行して値を取得できるツールを作りました。
また関数の実行も可能です。
const fs = require('fs'); const path = require('path'); const { Agent } = require('vm-agent'); const filepath = path.resolve(__dirname, ''sample.js'); const file = fs.readFileSync(filepath, 'utf8'); const result1 = new Agent(file) .run() .getInnerVariable(); console.log(result1); /* * { test1: 'test1', * test2: 'test2', * test3: 'test3', * test: [Function: test] } */ const result2 = new Agent(result1.test) .setArguments(4, 5, 6) .run() .getInnerVariable(); console.log(result2); /* * { arg1: 4, * arg2: 5, * arg3: 6, * sum: 15, * num1: 1, * num2: 2, * num3: 3 } */
vm-agent/example at master · suguru03/vm-agent · GitHub
実装内容
実装内容はesprima
を用いてlet
, const
をvar
に変換し、escodegen
を用いてコードを再構築し実行するというものです。const
が上書きできてしまったりパフォーマンスが低下したりしますが、テスト用なのでいったん良しとします。
また関数の実行については、関数の引数を解析し変数に変換することでvm
モジュールでのアクセスを可能にしています。