windowsでsymlinkを含んだリポジトリを扱う方法のまとめ
まず、windows環境でsymlinkが使われているようなリポジトリを、何も設定せずにcloneしてくると、symlinkが死ぬ。これをどうにかする必要があった。いろいろ試行錯誤した結果のまとめのメモ。
要約
端的にまとめるなら以下ができれば良い。
- .gitconfigで
core.symlinks = true
を設定 - windowsを開発者モードに変更する
はい。
windowsでsymlinkを壊さずcloneする方法
そのまま使うと壊れるので壊さない方法を。
core.symlinks = true
自分の環境のところで有効にするには以下を実行すれば良い。
$ git config --global core.symlinks true
- https://git-scm.com/docs/git-config.html#Documentation/git-config.txt-coresymlinks
- Gitへ移行して、シンボリックリンクにはまったお話 (Usersにシンボリックリンク作成権限を付与するまで)
developer mode
あとは、権限が不足しているようなので追加して上げる必要がある。ところで管理者権限が必要と言われるので、このままだと、管理者モードで開いたものでしかsymlinkが扱えない。
どうやら管理者モードを有効にしないといけないらしい。
- ghacks.net | Windows 10 Creators Update: Symlinks without elevation
- Microsoft Windows Blogs | Symlinks in Windows 10!
Do the following to enable Developer Mode on the Windows 10 machine:
はい。
gpedit?
ちなみに、以下の記事などでは、「ローカルセキュリティーポリシー」というものや「gpedit」というものを使って頑張って権限を設定しているがその理由がよくわからなかった。
- Gitへ移行して、シンボリックリンクにはまったお話 (Usersにシンボリックリンク作成権限を付与するまで)
- グループポリシーgpedit.mscが見つからない時の対処 – Windows10 Home
windowsでsymlinkを作る方法
次にwindowsでsymlinkを作る方法。Powerhellでは以下のような形でsymlinkが作れるらしい。
New-Item -Type SymbolicLink <link name> -Value <target file>
ところでこの方法では問題があり、絶対パスとしてのsymlinkしか作れないようだった。
work-aroundとしてコマンドプロンプトの時代に使われていたmklink
を使う方法が紹介されていた。
このような感じで使うらしい。
cmd /C mklink /D <link name> .\mytarget
はい。
まとめ
core.symlinks = true
と 開発者モードが必要。この辺りはwindowsを常用している人にとっては常識なのかもしれない。
eshellを使うようにしたらwindows環境でのEmacsもマシにはなった
諸事情によりwindowsの環境で作業しなければいけないことになった。windowsでの開発自体はWSLなどで便利になったものの直接windows環境で作業したい事がある。困っていたのは特にシェルの環境だった。
困りどころ
M-x shell
で動くシェルはコマンドプロンプトのように見えた。おそらく何らかの設定をすればPowerShellが使えるようになるのかもしれないが、PowerShellも使いにくい。最もunix系のシェルと異なる解釈をされて困ったのは"*"の扱い。これがCLIのアプリにそのまま渡されてくるので、grepなどが死ぬ。
ソフトウェアのインストール自体はscoopを使っていた1。
加えて、シェルとエディタ(Emacs)との行ったり来たりがやりづらかった。
eshellの利用
元々Macの環境やLinuxの環境でで作業するときには、M-x shell
で立ち上がるシェル(bash)をそのまま使っていた。ちょっとした仕掛けとしてC-j S
で現在開いているバッファのディレクトリ上にcdした状態で開く関数を作っていた。
具体的に言うと以下ができて欲しい。
- 開いたバッファからeshellを起動
- eshellからバッファを開く
前者はC-j S
にバインドしていた関数で環境がwindowsならeshellを使うようにした。後者はeshellのページを見てaliasの設定を追加した。
後者は、emacswikiの情報を見て設定を追加した。
以下のような設定。
(defun current-directory () (if load-file-name (file-name-directory load-file-name) default-directory)) (defun my:shell-on-current-dir (&optional arg) (interactive "P") (let ((dir (current-directory))) (cond ((equal system-type 'windows-nt) (my:eshell-on-dir dir arg)) (t (my:shell-on-dir dir arg))))) (defun my:eshell-on-dir (dir &optional arg) (cl-letf (((symbol-function 'pop-to-buffer-same-window) (lambda (buf) (pop-to-buffer buf)))) (eshell arg) (cd dir) (eshell-emit-prompt) (goto-char (point-max)))) (defun my:shell-on-dir (dir &optional arg) (comint-simple-send (get-buffer-process dir) (concat "cd " dir)) (goto-char (point-max)))
aliasは以下のような感じ。
alias emacs 'for i in ${eshell-flatten-list $*} {find-file $i}' alias e 'for i in ${eshell-flatten-list $*} {find-file $i}'
細かい話としては、eshellではelispがそのまま呼べてしまうので、grepが死ぬ。このへんはripgrep (rg)を使うようにすればどうにかなった。
-
後で考えてみるとchocolateyでも良かったかもしれない。https://chocolatey.org/↩