セカンドユーザーの zcompinit

Mac + Homebrew をマルチユーザーで使ってて、 セカンドユーザーでターミナル立ち上げたら zcompinit が insecure だ何だって警告してくるのがすごくイヤでちょっと調べてみた

警告が出る理由

  • brew がインストールしたファイルの owner は root ではなく brew したユーザー
  • つまり、brew でインストールされた補完関数の owner も root ではなく別ユーザー
  • compinit のセキュアチェックは root か自分自身以外が編集できる状態だと警告を出す

解決方法

解決方法は2つ

  1. compinit がロードする補完関数の owner を root に変更する
  2. セキュアチェックを無視(-u)、またはセキュアでないものはいれない(-i)

brew 管理下にあるファイルの owner を変更したら、今度は brew がごちゃごちゃしてくるので後者を選択

zplug で compinit されていたので $ZPLUG_HOME/repos/zplug/zplug/base/core/load.zsh を修正して compinit に -u オプションを追加

...
    # Plugins with defer-level set
    source "$_zplug_cache[defer_1_plugin]"
    compinit -u -d "$ZPLUG_HOME/zcompdump"
    if (( $_zplug_boolean_true[(I)$is_verbose] )); then
        __zplug::io::print::f \
            --zplug "$fg[yellow]Run compinit$reset_color\n"
    fi
    source "$_zplug_cache[defer_2_plugin]"
    source "$_zplug_cache[defer_3_plugin]"
...

ちとめんどう

補足

compinit のオプションに関しては以下を参考

# The -C flag bypasses both the check for rebuilding the dump file and the
# usual call to compaudit; the -i flag causes insecure directories found by
# compaudit to be ignored, and the -u flag causes all directories found by
# compaudit to be used (without security checking). Otherwise the user is
# queried for whether to use or ignore the insecure directories (which
# means compinit should not be called from non-interactive shells).

(引用) https://github.com/zsh-users/zsh/blob/master/Completion/compinit

zshrc ダイエット

zsh の設定とかに時間を食いつぶされたくなくて zshrc をスリムにしてみた

#
# zplug
#

export ZPLUG_HOME=~/.zplug
source $ZPLUG_HOME/init.zsh

# zplug self manage
zplug 'zplug/zplug', hook-build:'zplug --self-manage'

# history
zplug "zsh-users/zsh-history-substring-search"

# autocomplete
zplug "zsh-users/zsh-autosuggestions"
zplug "zsh-users/zsh-completions"

# syntax highlighting
zplug "chrissicool/zsh-256color"
zplug "zsh-users/zsh-syntax-highlighting", defer:2

# theme
zplug "mafredri/zsh-async", from:github
zplug "sindresorhus/pure", use:pure.zsh, from:github, as:theme

# install plugins
if ! zplug check --verbose; then
    printf "Install? [y/N]: "
    if read -q; then
        echo; zplug install
    fi
fi

# load plugins, and add commands to $PATH
zplug load --verbose


#
# zstyle
#

zstyle ':completion:*' menu select


#
# history settings
#

HISTFILE=$HOME/.zsh_history
HISTSIZE=1000
SAVEHIST=10000


#
# aliases
#

alias ls="ls -G"
alias la="ls -a"
alias ll="ls -lh"


#
# rbenv
#

if [ -e "$HOME/.rbenv" ]; then
  eval "$(rbenv init - zsh)"
fi

zplug は brew ではなく curl や git clone で ~/.zplug へインストールする
マルチユーザで Mac 使うと zplug の log ファイルのアクセス権でめんどうなことになったから

ボクノ Git チートシート

Git を使用していて「どうするんだっけ?」と思ったことをどんどん追記していく

リポジトリの状態に戻す (変更をなかったことにする)

% git checkout <filename>

ディレクトリを指定すると、まとめて戻せる

% git checkout .

ローカルで作ったブランチをリモートに push する

% git push --set-upstream origin <branchname>

削除されたリモートブランチをローカルに反映させる

% git fetch --prune

ローカルブランチは削除されないので、不要であればローカルブランチを削除する

ブランチの削除

% git branch --delete <branchname>

stash

% git stash

stash リスト

% git stash list

stash 適用

% git stash apply <stash>

stash 削除

% git stash drop <stash>

stash 適用 & 削除

% git stash pop <stash>

RSpec の基本的な使い方

最近、RSpec を学習していたので調べたことまとめ

まずは

おそらくここが正式なドキュメントサイト
(参考) RSpec: Behaviour Driven Development for Ruby

RSpec の初期設定


% bundle exec rspec --init
  create   spec/spec_helper.rb
  create   .rspec

テストプログラムは作成された spec ディレクトリに配置するのが基本

テストプログラム


テストプログラムのファイル名はテスト対象のファイル名に "_spec" をつけるのが慣例ぽい (例: hello.rb => hello_spec.rb)
テストプログラムは単に spec と表現されるのをよく見る
以下、簡単な spec の例

require 'hello'

describe 'Hello#message' do
  it 'returns hello message' do
    expect(Hello.new.message).to eq 'Hello World!'
  end
end

describe/context/example/it を利用してテストケースをグループ分けしていく
(参考) RSpecの(describe/context/example/it)の使い分け

テスト対象のロードについて

テスト対象の require をどこに記述すればよいのかしばらく悩んでいた

結論

各 spec ファイルに require 'spec_helper' は記述しない
各 spec ファイルの先頭でテスト対象モジュールを require する
モジュールのパスに変更があったときは -I オプションを指定して $LOAD_PATH を変更することで対応する

経緯

spec_helper.rb に記述して一括管理するのがよい?
こうすると、モジュールのディレクトリ変更でパスが変わり、全 spec ファイルを修正することになるリスクを減らせるかもしれない
しかし、この方法だと部分的なテストを行うときに全モジュールをロードするのが負担にならないか?

ちなみに RSpec はデフォルトで lib と spec を $LOAD_PATH に追加する
なので lib 配下のファイルはパスなしでよい (例: lib/hello.rb => require 'hello')
(参考) RSpecコードリーディング(第1部:RSpec)

各 spec に require 'spec_helper' を記述しない方がいいという意見も見かけた
その場合は、.spec ファイルに以下のデフォルトオプションを追加する

--require spec_helper

試してみようとしたら rspec --init で作成されたデフォルトの .spec にすでに記述されていた

http://rspec.info の Let's get started! を見ると、spec で require 'spec_helper' しないし、かわりにテスト対象モジュールを require してるから、それが想定している基本的な使い方なのだろう

いろいろあさっていたら、3.5 で config.when_first_matching_example_defined が追加されたから、一部の spec でしか使用しないセットアップロジックはこれ使うといいよ、という旨の記事をドキュメントサイトのブログで見つけた
(参考) RSpec 3.5 がリリースされました!

まだ勉強段階なので必要ないけど、今後必要になるかもしれない
頭の片隅に置いておこう

Bundler の基本的な使い方

Bundler のインストール

% rbenv exec gem install bundler
% rbenv rehash
% bunder -v

rbenv rehash はコマンドプログラムの更新
rbenv のヘルプには次のようにある

Rehash rbenv shims (run this after installing executables)

Bundler で gem をインストールする

Gemfile を作って編集し bundle install

% bundle init
% vi Gemfile
% rbenv exec bundler install

すると Gemfile.lock ファイルが作成される


注意!ここから先は未確認・未検証!

別環境で gem をインストールする

% rbenv exec bundler install

Gemfile.lock が存在し Gemfile が更新されていなければ Gemfile.lock に従う (Gemfile.lock は更新されない)
Gemfile.lock が存在し Gemfile が更新されている場合、更新された gem に対して依存性の再解決を行う

以下、bundler install のヘルプより引用

Install the gems specified in your Gemfile(5). If this is the first time you run bundle install (and a Gemfile.lock does not exist), Bundler will fetch all remote sources, resolve dependencies and install all needed gems.

If a Gemfile.lock does exist, and you have not updated your Gemfile(5), Bundler will fetch all remote sources, but use the dependencies specified in the Gemfile.lock instead of resolving dependencies.

If a Gemfile.lock does exist, and you have updated your Gemfile(5), Bundler will use the dependencies in the Gemfile.lock for all gems that you did not update, but will re-resolve the dependencies of gems that you did update. You can find more information about this update process below under CONSERVATIVE UPDATING.

インストールされている Gem を更新する (version up)

% rbenv exec bundler update

このとき Gem のバージョンが変わると Gemfile.lock が更新される

Git コマンドラインの認証で macOS のキーチェーンを利用する

credential-osxkeychain サブコマンドが使えるか確認する

% git credential-osxkeychain

usage: git credential-osxkeychain <get|store|erase>

 

credential-osxkeychain を有効にする

% git config --global credential.helper osxkeychain

これだけ、おわり

 

認証情報を削除したい場合は、キーチェーンアクセスから認証情報を検索し削除すればOK

rbenv で Ruby環境構築

昨年(2017-04-25)の記録が残っていたのでまとめておく

 

前提

  • ログインシェルは zsh
  • Xcodeコマンドラインツールがインストールされてること
  • Homebrew がインストールされてること

 

はじめる前に

Rubyバージョンを確認しておく

$ ruby -v

(記録時では 2.0.0)

 

(念のため) Homebrew に rbenv と ruby-build があるか確認しておく

$ brew search rbenv

$ brew search ruby-build 

 

rbenv + ruby-build のインストール

$ brew install rbenv ruby-build 

rbenv をインストールしたら rbenv init してみる

% rbenv init

# Load rbenv automatically by appending

# the following to ~/.zshrc:

 

eval "$(rbenv init -)" 

指示されているとおり ~/.zshrc に eval "$(rbenv init -)" を追記する

 

バージョンを指定して Ruby をインストールする

インストールできる Ruby バージョンは次のように確認できる

% rbenv install -l

...

  2.3.0

  2.3.1

  2.3.2

  2.3.3

  2.3.4

  2.4.0-dev

  2.4.0-preview1

  2.4.0-preview2

  2.4.0-preview3

  2.4.0-rc1

  2.4.0

  2.4.1

  2.5.0-dev

...

この中からインストールするバージョンを選ぶ

(当時は 2.3.3 を選択)

 

選んだバージョンを指定して rbenv で Ruby をインストール

% rbenv install 2.3.3

 

インストールされている Rubyバージョンは次のように確認できる

% rbenv versions

* system (set by /Users/username/.rbenv/version)

  2.3.3

「*」がついているものが現在有効になっているバージョン

 

特定のディレクトリにのみ Rubyバージョン変更を適用する

ワーキングディレクトリ(今回は ~/working)に移動して Rubyバージョンを確認

% cd ~/working

% ruby -v

ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin16]

% rbenv version

system (set by /Users/username/.rbenv/version)

% rbenv which ruby

/usr/bin/ruby

 

Rubyバージョンを変更する

% rbenv local 2.3.3

% ruby -v

ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-darwin16]

% rbenv version

2.3.3 (set by /Users/username/working/.ruby-version)

% rbenv which ruby

/Users/username/.rbenv/versions/2.3.3/bin/ruby

% ls -a

.             ..            .ruby-version 

ruby コマンドが切り替わっているのがわる

rbenv local で Ruby バージョンを切り替えた場合、そのディレクトリ配下では指定したバージョンが有効になる

 

(おまけ) そのとき gem は?

上の手順で ruby は変更されているが gem はどうなっているのか?

 

まずはホームディレクトリで gem を調べてみる

% gem -v

2.0.14.1

% rbenv which gem

/usr/bin/gem

% gem environment

RubyGems Environment:

  - RUBYGEMS VERSION: 2.0.14.1

  - RUBY VERSION: 2.0.0 (2015-12-16 patchlevel 648) [universal.x86_64-darwin16]

  - INSTALLATION DIRECTORY: /Library/Ruby/Gems/2.0.0

  - RUBY EXECUTABLE: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby

  - EXECUTABLE DIRECTORY: /usr/local/bin

  - RUBYGEMS PLATFORMS:

    - ruby

    - universal-darwin-16

  - GEM PATHS:

     - /Library/Ruby/Gems/2.0.0

     - /Users/username/.gem/ruby/2.0.0

     - /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/gems/2.0.0

  - GEM CONFIGURATION:

     - :update_sources => true

     - :verbose => true

     - :backtrace => false

     - :bulk_threshold => 1000

  - REMOTE SOURCES:

     - https://rubygems.org/

 

次に Ruby 2.3.3 を適用したワーキングディレクトリで

% gem -v

2.5.2

% rbenv which gem

/Users/username/.rbenv/versions/2.3.3/bin/gem

% gem environment

RubyGems Environment:

  - RUBYGEMS VERSION: 2.5.2

  - RUBY VERSION: 2.3.3 (2016-11-21 patchlevel 222) [x86_64-darwin16]

  - INSTALLATION DIRECTORY: /Users/username/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0

  - USER INSTALLATION DIRECTORY: /Users/username/.gem/ruby/2.3.0

  - RUBY EXECUTABLE: /Users/username/.rbenv/versions/2.3.3/bin/ruby

  - EXECUTABLE DIRECTORY: /Users/username/.rbenv/versions/2.3.3/bin

  - SPEC CACHE DIRECTORY: /Users/username/.gem/specs

  - SYSTEM CONFIGURATION DIRECTORY: /Users/username/.rbenv/versions/2.3.3/etc

  - RUBYGEMS PLATFORMS:

    - ruby

    - x86_64-darwin-16

  - GEM PATHS:

     - /Users/username/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0

     - /Users/username/.gem/ruby/2.3.0

  - GEM CONFIGURATION:

     - :update_sources => true

     - :verbose => true

     - :backtrace => false

     - :bulk_threshold => 1000

  - REMOTE SOURCES:

     - https://rubygems.org/

  - SHELL PATH:

     - /Users/username/.rbenv/versions/2.3.3/bin

     - /usr/local/Cellar/rbenv/1.1.0/libexec

     - /Users/username/.rbenv/shims

     - /usr/local/bin

     - /usr/bin

     - /bin

     - /usr/sbin

     - /sbin

     - /Users/username/bin

gem もちゃんと切り替わっているのがわかる

gem パッケージのインストール先も ~/.rbenv/versions/... になっている

 

いろいろ調べてみると、rbenv を利用している際の gem インストールは rbenv exec gem install を、bundler は rbenv exec bundle を使用するのがよさそう

上の調査結果を見る限り gem install は rbenv exec を使用していなくてもよさそうだが、システムに同名のコマンドが混在しているとどっちが適用されるか不安があるから rbenv exec を利用するのが安全か?