diff --git a/src/buckify.rs b/src/buckify.rs index 73e7bfbf..33392847 100644 --- a/src/buckify.rs +++ b/src/buckify.rs @@ -269,7 +269,14 @@ fn generate_nonvendored_sources_archive<'scope>( }, Source::Git { repo, commit_hash, .. - } => generate_git_fetch(repo, commit_hash).map(Some), + } => match context.config.vendor { + VendorConfig::Off => generate_git_fetch(repo, commit_hash).map(Some), + VendorConfig::LocalRegistry => { + generate_extract_archive_git(context, pkg, lockfile_package, repo, commit_hash) + .map(Some) + } + VendorConfig::Source(_) => unreachable!(), + }, Source::Unrecognized(_) => { bail!( "`vendor = false` mode is supported only with exclusively crates.io and https git dependencies. \"{}\" {} is coming from some other source", @@ -286,7 +293,6 @@ fn generate_extract_archive<'scope>( _lockfile_package: &LockfilePackage, ) -> anyhow::Result { let vendordir = "vendor"; - Ok(Rule::ExtractArchive(ExtractArchive { name: Name(format!("{}-{}.crate", pkg.name, pkg.version)), src: BuckPath(PathBuf::from(format!( @@ -300,6 +306,32 @@ fn generate_extract_archive<'scope>( })) } +fn generate_extract_archive_git<'scope>( + _context: &'scope RuleContext<'scope>, + pkg: &'scope Manifest, + _lockfile_package: &LockfilePackage, + repo: &str, + _commit_hash: &str, +) -> anyhow::Result { + let vendordir = "vendor"; + let short_name = short_name_for_git_repo(repo)?; + Ok(Rule::ExtractArchive(ExtractArchive { + name: Name(format!("{}.git", short_name)), + // + // Would be nice if cargo local-registry wrote out a git-related name instead + // of `mycrate-0.1.0.crate`. However it does not. + // + src: BuckPath(PathBuf::from(format!( + "{vendordir}/{}-{}.crate", + pkg.name, pkg.version + ))), + strip_prefix: format!("{}-{}", pkg.name, pkg.version), + sub_targets: BTreeSet::new(), // populated later after all fixups are constructed + visibility: Visibility::Private, + sort_key: Name(format!("{}-{}", pkg.name, pkg.version)), + })) +} + fn generate_http_archive<'scope>( context: &'scope RuleContext<'scope>, pkg: &'scope Manifest, @@ -445,7 +477,12 @@ fn generate_target_rules<'scope>( if context.config.vendor.is_source() || matches!(pkg.source, Source::Local) { relative_path(&paths.third_party_dir, manifest_dir) } else if let Source::Git { repo, .. } = &pkg.source { - let git_fetch = short_name_for_git_repo(repo)?; + let mut git_fetch = short_name_for_git_repo(repo)?; + if matches!(context.config.vendor, VendorConfig::LocalRegistry) { + // Subtle difference -- git_fetch rules will strip the `.git` off the name + // when used as a dependency. extract_archive will not. + git_fetch += ".git"; + } let repository_root = find_repository_root(manifest_dir)?; let path_within_repo = relative_path(repository_root, manifest_dir); PathBuf::from(git_fetch).join(path_within_repo) diff --git a/src/vendor.rs b/src/vendor.rs index 001b22f9..1ed19f41 100644 --- a/src/vendor.rs +++ b/src/vendor.rs @@ -49,6 +49,7 @@ pub(crate) fn cargo_vendor( "-s", paths.lockfile_path.to_str().unwrap(), vendordir.to_str().unwrap(), + "--git", ]; if no_delete { cmdline.push("--no-delete");