現象
includeIfをしようしてgitconfigを切り替えている場合に、cargo new <プロジェクト名>をするとCargo.tomlのauthorsに切り替えたgitconfigの情報が入らずに、globalで設定しているgitconfig情報が入ってしまう。
例えばglobalのgitconfigの設定が
username: global_takoyaki
includeIfで設定したgitconfigの設定が
username: local_takoyaki
とした場合に、切り替わるはずのディレクトリでcargo new <プロジェクト名>をするとglobal_takoyakiが設定されてしまう。
local_takoyakiにしたい!
追跡
GitHub - rust-lang/cargo: The Rust package manager
ここからCargoのRepoがあるので追跡してみる。
src/cargo/ops配下にCargoのコマンドのファイルがあります。
src/cargo/ops/cargo_new.rs
にはcargo newとcargo initのコマンド記述があります。
これらのメソッドは共通して
fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()>
を呼び出しており、ここでgit initやCargo.tomlの一連の処理を行なっているようです。
特にgit initの処理は
fn init_vcs(path: &Path, vcs: VersionControl, config: &Config) -> CargoResult<()>
を呼び出しており、そこからバージョン管理のツールごとに場合分けを行なっています。
Gitの処理はsrc/cargo/util/vcs.rsのGitRepo構造体で管理されており、実態はlibgit2 for Rustが使用されているようです。
gitのincludeIfの仕様
対象のフォルダへ行ってgit config user.nameを実行しただけでは、globalのgitconfigが参照される。
git initをして、gitリポジトリが生成されてからgit config user.nameを実行するとincludeIfのgitconfigが参照される。
gitのincludeIfで指定したgitconfigが反映されない理由
原因はgitが生成されるディレクトリからgitconfigを取得しようとしていないためです。
例えば、takoyakiフォルダでCargo new <プロジェクト名>とした時の現在のディレクトリはtakoyakiなので、gitはtakoyakiフォルダにgitがないのでグローバルの設定を取得しにいこうとします。
かなり雑にCargoのソースコード修正
impl GitRepo { pub fn init(path: &Path, _: &Path) -> CargoResult<GitRepo> { let _ = env::set_current_dir(path).is_ok(); // <=====ここ git2::Repository::init(path)?; Ok(GitRepo) } // 省略 }
let _ = env::set_current_dir(path).is_ok();
git initの処理される前に、現在の作業ディレクトリをgitが生成されるディレクトリに変更すれば、includeIfで設定したgitconfigが反映されます。
※ かなり雑です。何も考慮してません。
代替案
mkdir sample cd sample cargo init .
でcargo initを使用する方法ならgitの生成されるディレクトと作業ディレクトリが一致するので、想定のgitconfigの情報が反映されます。
修正すべきか?
微妙な気がします。
一応cargoのヘルプをみると以下のように記載されていて、
USAGE: cargo new [OPTIONS] <path> OPTIONS: -q, --quiet No output printed to stdout --registry <REGISTRY> Registry to use --vcs <VCS> Initialize a new repository for the given version control system (git, hg, pijul, or fossil) or do not initialize any version control at all (none), overriding a global configuration. [possible values: git, hg, pijul, fossil, none] --bin Use a binary (application) template [default] --lib Use a library template --edition <YEAR> Edition to set for the crate generated [possible values: 2015, 2018] --name <NAME> Set the resulting package name, defaults to the directory name -v, --verbose Use verbose output (-vv very verbose/build.rs output) --color <WHEN> Coloring: auto, always, never --frozen Require Cargo.lock and cache are up to date --locked Require Cargo.lock is up to date --offline Run without accessing the network -Z <FLAG>... Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details -h, --help Prints help information ARGS: <path>
と書いてあるので、大丈夫と言えば、大丈夫なのですが、意識しないと、うっかりとglobalの方のgitconfigがtomlに反映されてしまうので、個人的には自動でincludeIfで設定したgitconfigを参照してほしい気がします。