diff --git a/src/cargo/ops/common_for_install_and_uninstall.rs b/src/cargo/ops/common_for_install_and_uninstall.rs index f33847d5767..8eca4c920c9 100644 --- a/src/cargo/ops/common_for_install_and_uninstall.rs +++ b/src/cargo/ops/common_for_install_and_uninstall.rs @@ -7,6 +7,8 @@ use std::rc::Rc; use std::task::Poll; use anyhow::{bail, format_err, Context as _}; +use gix::bstr::BStr; +use gix::url::{parse, Scheme}; use ops::FilterRule; use serde::{Deserialize, Serialize}; @@ -16,6 +18,7 @@ use crate::core::{Dependency, FeatureValue, Package, PackageId, QueryKind, Sourc use crate::ops::{self, CompileFilter, CompileOptions}; use crate::sources::PathSource; use crate::util::errors::CargoResult; +use crate::util::interning::InternedString; use crate::util::Config; use crate::util::{FileLock, Filesystem}; @@ -521,6 +524,40 @@ pub fn path_source(source_id: SourceId, config: &Config) -> CargoResult InstallSuggestion { + if dep.source_id().is_registry() { + if let Ok(git_url) = parse(BStr::new(dep.package_name().as_bytes())) { + let final_git_url: Option = match git_url.scheme { + Scheme::Http | Scheme::Https => Some(dep.package_name()), + // cargo doesn't support cargo install git@ urls + _ => None, + }; + + if let Some(final_git_url) = final_git_url { + return InstallSuggestion::NormalisedGitUrl(format!( + "To install a package from a git repository, use `--git {final_git_url}`", + )); + } else { + return InstallSuggestion::None; + } + } + } + return InstallSuggestion::None; +} + /// Gets a Package based on command-line requirements. pub fn select_dep_pkg( source: &mut T, @@ -578,12 +615,24 @@ where source.source_id() ) } else { - bail!( - "could not find `{}` in {} with version `{}`", - dep.package_name(), - source.source_id(), - dep.version_req(), - ) + if let InstallSuggestion::NormalisedGitUrl(suggestion) = + was_git_url_miscategorised_as_a_registry_dep(&dep) + { + bail!( + "could not find `{}` in {} with version `{}`. {}", + dep.package_name(), + source.source_id(), + dep.version_req(), + suggestion, + ) + } else { + bail!( + "could not find `{}` in {} with version `{}`", + dep.package_name(), + source.source_id(), + dep.version_req(), + ) + } } } } diff --git a/tests/testsuite/install.rs b/tests/testsuite/install.rs index 0c7fc5037e4..9235a19a9b5 100644 --- a/tests/testsuite/install.rs +++ b/tests/testsuite/install.rs @@ -1642,6 +1642,19 @@ fn test_install_git_cannot_be_a_base_url() { .run(); } +#[cargo_test] +fn test_install_from_https_git_generate_suggestion() { + registry::init(); + cargo_process("install https://github.com/rust-lang/cargo") + .with_status(101) + .with_stderr( + "\ +[UPDATING] `[..]` index +error: could not find `https://github.com/rust-lang/cargo` in registry `crates-io` with version `*`. To install a package from a git repository, use `--git https://github.com/rust-lang/cargo`", + ) + .run(); +} + #[cargo_test] fn uninstall_multiple_and_specifying_bin() { cargo_process("uninstall foo bar --bin baz")