2019/09/21

git clean を使って untracked なファイルを削除する

Mercurial には hg purge というコマンドがあって、 hg で control していないファイルを一括削除できます。
具体的には add してないファイルとか、.c から作った .o とか、間違って作った Rails の migration とか。
それを Git でもできないかなー、と調べたメモ。


環境

  • OS: macOS Mojave 10.14.6
  • Git: 2.23.0


git clean

hg purge のようなコマンドは Git にも default でも存在していて、git clean だそうです。

untracked なファイルを消す際は
  • $ git clean -fd
とかすると add してないファイルが消えます。

あとは、すぐに消すのではなく、消す対象が何かを教えてくれる -n (--dry-run) option が便利です。
  • $ git clean -fdn
で削除対象一覧を出してくれます。ちなみに
  • git clean -f -d -n
と書いても良いみたいです。

他には 
  • -X option: .gitignore で指定されたファイルのみを消す
    • .o とかが消えてくれる。
    • あと untracked なファイルは消えない
    • 新規にファイルを作った上で rebuild したい時に便利だよ、とのこと
  • -x option: .gitignore で指定されたファイルも削除対象 + untracked のファイルも削除対象
    • かなり危険なので事前に dry-run を付けた方が良いです
    • git clean -fdx とかすると clone 直後くらい綺麗な状態になります
とかですかね。
さらに詳細を知りたい場合は man git-clean を読んで頂ければ。


参考

2019/09/16

Terminal.app を使って mac を sleep させる

Terminal から mac を sleep させる方法無いかなー、と思ったのでそのメモ。


経緯

私は普段 MacBookPro + Display + Keyboard で作業をしています。
この状態からそのまま MBP を閉じると clamshell mode になってしまいます。
なので MBP を sleep -> MBP を閉める という流れで全体を sleep させています。
MBP を sleep させるには Shift + Control + 電源ボタン の shortcut を使うことが多いです。

しかし、たまに MBP を sleep させずに閉じてしまう時があります。
外付け keyboard には電源ボタンが無い。ので  sleep させられない。
そのせいで一旦閉じた MBP を再度開いて sleep させて閉じる、とかやっていたのですがちょっと面倒。

ということで、外付け Keyboard だけで clamshell mode の MBP を sleep させる方法た無いかな、と思って調べました。


環境

  • OS: macOS mojave 10.14.6 Version (18G95)


コマンド

  • $ pmset sleepnow
sleep させることができます。思ったより楽だった。


2019/09/01

neovim で plugin を利用せずに sudo を使う

root 権限が必要なファイルを neovim や vim で編集する事があると思います。
その際、 sudoers で許可されているユーザならば
  • :write ! sudo tee % > /dev/null
で sudo を使って root として書き込むことができます。

ですが、 neovim では
  • :write ! sudo tee % > /dev/null
    • sudo: no tty present and no askpass program specified
    • shell returned 1
と言われて sudo が使えません。


解決策

以下のようなコマンドを定義することで対応できます。 このコマンドは vim と neovim の両方で利用できます。

vim で利用する場合は ~/.vimrc に追記します。
neovim で利用する場合は ~/.cofig/nvim/init.vim に追記します。


使い方

  • $ nvim /etc/hosts
    • root 権限が必要なファイルを開いて編集します。保存の際は
  • :SudoWriteCurrentBuffer
    • を実行します。
    • パスワードを入力すれば root で書き込む事ができます。


動作確認をした環境

大元の環境(vim と neovim で動作確認済)
  • OS: macOS Mojave 10.14.6 (18G95)
  • Homebrew: 2.1.11
    • Homebrew/homebrew-core: (git revision 883ee; last commit 2019-09-01)
  • neovim: v0.3.8
  • vim: 8.0.1365
  • sudo: version 1.8.17p1
    • Sudoers policy plugin version 1.8.17p1
    • Sudoers file grammar version 45
    • Sudoers I/O plugin version 1.8.17p1
  • docker: 19.03.1, build 74b1e89

    docker を使っていくつかの distribution でも動作を確認
    • Alpine linux: 3.10.2
      • neovim: v0.3.7
      • vim: 8.1.1365
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • CentOS: release 7.6.1810 (Core)
      • vim: 7.4.1099
      • sudo: version 1.8.23
        • Sudoers policy plugin version 1.8.23
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.23
    • Fedora: release 30
      • vim: 8.1.1912
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • Ubuntu: 18.04.3
      • vim: 8.0.1453
      • sudo: version 1.8.21p2
        • Sudoers policy plugin version 1.8.21p2
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.21p2
    • Debian: 10.0 (buster-20190812)
      • vim: 8.1.1401
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27


    何故 neovim では sudo が使えないのか

    ここから先は先程の Vimscript を作るに至った経緯を書きます。
    興味のある方はご覧ください。

    まず sudo の error message
    • sudo: no tty present and no askpass program specified
    を見ると、 tty と askpass が無いと言っています。


    tty と askpass

    実際、vim では
    • : ! tty
      • /dev/ttys004 
    などが得られますが、 neovim では
    • : ! tty
      • not a tty
      • shell returned 1
    と言われてしまいます。

    askpass は使ったことが無いのですが、fedora の container で dnf search すると
    の様に、いくつかの askpass が確認できます。のでちょっと試してみます。
    • x11-ssh-askpass
    • openssh-askpass
    • ksshaskpass
    という感じで全然起動してくれません。
    ですがエラーの内容的に display を開こうとしているのが分かります。
    なので、おそらく GUI で password を聞くような物だと思われます。


    askpass を作る

    askpass について調べていると、どうやら
    • password を stdout に出力するもの
    であることが分かりました

    よって
    • neovim 内で password を取得
    • password を stdout に出力する
    • password の履歴はどこにも残さない
    ようなものを作れば解決できそうです。

    それで完成したのが /tmp/askpass を作るこの Vimscript です。

    本当はファイル名は固定でなく tempfile 的な物で対応するなど、改善点はいくつも存在するかと思います。
    ですが私は Vimscript に明るくないので、"3つの条件を満たして動けばOK" という条件で作成しました。
    他により良い対応方法があればご指摘頂けると幸いです。


    その他の解決策

    調べた結果、 suda.vim というプラグインがあるようです。
    また、他にも sudo.vim など、似たようなプラグインはいくつかあるらしいです。

    これを使わなかった理由としては
    • docker のコンテナ内で作業をする事が多々ある
    • init.vim を配置するスクリプトは既にある
    • plugin を install するスクリプトはまだ無い
    • 全コンテナに plugin を入れるのも面倒だし結構サイズがある
      • $ du -sh ~/.config/nvim/repos
        • 100M    /Users/atton/.config/nvim/repos
    などがあります。

    また、"sudo が使えるならこの際 root になってしまう" という解決策もあるのですが
    • 前述した理由の後半3つ
    • 複数人数のユーザが使う環境だと、 /root 配下に自分専用の設定を置くことになる
    のでこちらも無しで。

    他には、 "sudoers で NOPASSWD を設定する" という解決策もあります。
    が、sudo を no password でガンガン使えば実質 root で作業しているのと変わらず、危険すぎるのでこちらも無し。

    ということでこの Vimscript を書くに至った、という訳なのです。


    おまけ: 環境変数の unlet

    スクリプト内部では askpass の場所を示す SUDO_ASKPASS を設定している部分があります。
    具体的には
    • let $SUDO_ASKPASS  = s:askpass_path
    ですね。

    この環境変数を定義していると、 sudo -A した際に指定したファイルが実行されます。
    一応、 :SudoWriteCurrentBuffer の実行後にはなるべく元の環境に戻すために
    • unlet $SUDO_ASKPASS
    を書いていた時もありました。

    ですが動作確認中、 Vim 8.0.1365 で unlet 時にエラーが出てしまいました。
    また 、-A を指定しなければ sudo の動作は変わらないので 、残っていても無害と判断して unlet しない形になりました。


    おまけ: shebang を指定しないとどうなるのか

    ちなみに askpass の shebang を消すと
    • sudo: unable to run /tmp/askpass: Exec format error
    • sudo: no password was provided
    と言われる為、きちんと書いておく必要があります。


    おまけ: x flag を付けないとどうなるのか

    setfperm(s:askpass_path, "rwxr-xr-x")  をせずに 644 のままだと
    • sudo: unable to run /tmp/askpass: Permission denied
      • sudo: no password was provided
      と言われるので、こちらもきちんと指定しておく必要があります。


      参考

      2019/08/29

      tmux 2.9a の window 分割線を ascii character にする

      2019/05/01 に tmux 2.9a がリリースされていました
      残念ながら 2.9 は見逃がしてしまいました。
      ということで恒例の分割線を EastAsianAmbiguous から ascii の線に変更するバージョンを作成。
      2.8の時とか2.7 の時とかの作業履歴とかもまとめてあります。
      そもそもどういう問題なのかはこの記事で。


      環境

      • OS: macOS mojave 10.14.6 (18G95)
      • tmux: 2.9a-border-ascii ( f976aed943f322a3652f51846b0fe472534ab6d6 )
      • Homebrew: 2.1.11
      • Homebrew/homebrew-core: (git revision 269c; last commit 2019-08-29)
      • Font: Ricty: 3.2.2(no option)


      作業

      今回も割とあっさりできました。cherry-pick して tag 更新して終わり。
      • $ git pull upstream
      • $ git checkout 2.9a
      • $ git cherry-pick border-ascii
      • $ git checkout -b 2.9a-border-ascii
      make できるかの確認は
      • $ sh autogen.sh
      • $ ./configure 
      • $ make
      で。

      ちなみに brew edit tmux して本家のビルド手順を参考にしてます。
      あと、 dependencies から utf8proc が消えて ncurses が追加。

      make すると current directory に tmux command ができるので、動作確認も可能。
      • $ ./tmux -V
        • tmux 2.9a
      • $ ./tmux
        • border-ascii 版の tmux が起動します。
      あとは自分用の tap に反映しておしまい。


      インストール方法

      1からインストールする場合のコマンドは
      • $ brew install --HEAD atton/customs/tmux
      でいけます。
      必要あらば自動で atton/cusoms を tap してくれるようになってました。便利。

      2019/08/20

      hub コマンドの user 設定を変更する

      hub というコマンドがあります。
      GitHub に関連したコマンドが追加された git の wrapper です。
      例えば
      • $ hub clone neovim/neovim
      とすると
      • $ git clone git@github.com:neovim/neovim.git
      相当の事をしてくれます。
      git の wrapper になってるので、 hub だけで全てを済ませる派の人がいるかもしれません。


      環境

      • OS: macOS Mojave 10.14.6
      • Homebrew: 2.1.10
      • Homebrew/homebrew-core:  (git revision ea34; last commit 2019-08-20)
      • hub: version 2.12.3
      • git: version 2.23.0


      設定を変更するきっかけ

      • $ hub browse tmux/tmux
        • とすると tmux/tmux をブラウザで開いてくれます。
      • $ hub browse hoge
      • $ git config --list
        • で git の設定を確認しても 'atton-' は存在しない。
        • むしろ github.user=atton になってるくらい。
        • hub が git の wrapper になってる事のデメリットがちょっとあって
      • $ hub config --list
        • としても git config --list の時と同じ内容が出てくる。
        • つまり hub 経由で config を update しても git の config が変更されそう。
      ということで 'atton-' を設定している部分を探してみる。


      設定箇所探し + 設定

      • $ hub --help
        • hub と git の help が出る
        • hub 部分に config とか setting とかの項目は無い
      • $ man hub
        • config で search するとありました。 
        • どうやら $HOME/.config/hub に書かれているようです。
        • 編集すると 'user: atton-' になっていたので 'user: atton' に修正。
      • $ hub browse dot_files


      おまけ

      ちなみに私が良く使うコマンドは
      • $ hub browse
      です。
      current directory の repository の github ページがブラウザで開きます。
      あとは hub clone くらい……?

      実際 hub をあまり使わないのは
      • hub が無い環境で作業することもある
      • wrapper が隠してくれているオプションとかに「気付かずに助けられている」のは勘弁
      とかの理由があります。

      なので、個人的にはなるべく git を使うようにしています。
      もちろん hub の方が便利な時は hub を使います。