Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate gitoxide #2

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ jobs:

# Deny warnings on CI to avoid warnings getting into the codebase.
- run: cargo test --features 'deny-warnings'
- name: gitoxide tests (git-related and enabled tests only)
run: RUSTFLAGS='--cfg test_gitoxide' cargo test git
# The testsuite generates a huge amount of data, and fetch-smoke-test was
# running out of disk space.
- name: Clear test output
Expand Down
34 changes: 33 additions & 1 deletion crates/cargo-test-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {
};
}
let is_not_nightly = !version().1;
#[cfg(test_gitoxide)]
let mut enable_gitoxide_test = false;
for rule in split_rules(attr) {
match rule.as_str() {
"build_std_real" => {
Expand Down Expand Up @@ -59,6 +61,12 @@ pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {
requires_reason = true;
set_ignore!(is_not_nightly, "requires nightly");
}
"gitoxide" => {
#[cfg(test_gitoxide)]
{
enable_gitoxide_test = true;
}
}
s if s.starts_with("requires_") => {
let command = &s[9..];
set_ignore!(!has_command(command), "{command} not installed");
Expand All @@ -81,6 +89,13 @@ pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {
such as #[cargo_test(nightly, reason = \"needs -Z unstable-thing\")]"
);
}
#[cfg(test_gitoxide)]
if !enable_gitoxide_test {
ignore = true;
implicit_reasons.push(
"not yet enabled for using 'gitoxide' and tested in the standard test run".to_string(),
)
}

// Construct the appropriate attributes.
let span = Span::call_site();
Expand Down Expand Up @@ -114,7 +129,8 @@ pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {
}

// Find where the function body starts, and add the boilerplate at the start.
for token in item {
let mut item = item.into_iter();
while let Some(token) = item.next() {
let group = match token {
TokenTree::Group(g) => {
if g.delimiter() == Delimiter::Brace {
Expand All @@ -124,6 +140,22 @@ pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {
continue;
}
}
// Remove duplicate ignore statements to avoid errors - ours take precedence.
// Only needed for handling `gitoxide` tests.
#[cfg(test_gitoxide)]
TokenTree::Punct(p) if p.as_char() == '#' => {
let next = item.next().expect("group");
let TokenTree::Group(g) = next else {
ret.extend([TokenTree::Punct(p), next]);
continue
};
if g.delimiter() == Delimiter::Bracket && g.to_string().contains("ignore") {
continue;
}

ret.extend([TokenTree::Punct(p), TokenTree::Group(g)]);
continue;
}
other => {
ret.extend(Some(other));
continue;
Expand Down
23 changes: 23 additions & 0 deletions crates/cargo-test-support/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,26 @@ pub fn tag(repo: &git2::Repository, name: &str) {
false
));
}

/// A utility trait to make enabling `gitoxide` related features easier in select tests.
///
/// Generally this will only affect arguments to `Execs` if we are in a special test run
/// marked with `RUSTFLAGS=--cfg test_gitoxide`.
pub trait Gitoxide {
fn maybe_fetch_with_gitoxide(&mut self) -> &mut Self;
}

impl Gitoxide for crate::Execs {
/// Fetch both the crates-index as well as git dependencies with `gitoxide`.
fn maybe_fetch_with_gitoxide(&mut self) -> &mut Self {
#[cfg(test_gitoxide)]
enable_feature(self, "fetch");
self
}
}

#[cfg(test_gitoxide)]
fn enable_feature(exec: &mut crate::Execs, name: &str) {
exec.masquerade_as_nightly_cargo(&["gitoxide"])
.arg(format!("-Zgitoxide={}", name));
}
51 changes: 51 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ unstable_cli_options!(
doctest_xcompile: bool = ("Compile and run doctests for non-host target using runner config"),
dual_proc_macros: bool = ("Build proc-macros for both the host and the target"),
features: Option<Vec<String>> = (HIDDEN),
gitoxide: Option<GitoxideFeatures> = ("Use gitoxide for the given git interactions, or all of them if no argument is given"),
jobserver_per_rustc: bool = (HIDDEN),
minimal_versions: bool = ("Resolve minimal dependency versions instead of maximum"),
mtime_on_use: bool = ("Configure Cargo to update the mtime of used files"),
Expand Down Expand Up @@ -778,6 +779,50 @@ where
parse_check_cfg(crates.into_iter()).map_err(D::Error::custom)
}

#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct GitoxideFeatures {
/// All featches are done with gitoxide, which includes git dependencies as well as the crates index.
pub fetch: bool,
/// When cloning the index, perform a shallow clone. Maintain shallowness upon subsequent fetches.
pub shallow_index: bool,
/// Checkout git dependencies using `gitoxide` (submodules are still handled by git2 ATM, and filters
/// like linefeed conversions are unsupported).
pub checkout: bool,
}

impl GitoxideFeatures {
fn all() -> Self {
GitoxideFeatures {
fetch: true,
shallow_index: true,
checkout: true,
}
}
}

fn parse_gitoxide(
it: impl Iterator<Item = impl AsRef<str>>,
) -> CargoResult<Option<GitoxideFeatures>> {
let mut out = GitoxideFeatures::default();
let GitoxideFeatures {
fetch,
shallow_index,
checkout,
} = &mut out;

for e in it {
match e.as_ref() {
"fetch" => *fetch = true,
"shallow_index" => *shallow_index = true,
"checkout" => *checkout = true,
_ => {
bail!("unstable 'gitoxide' only takes `fetch`, 'shallow_index' and 'checkout' as valid inputs")
}
}
}
Ok(Some(out))
}

fn parse_check_cfg(
it: impl Iterator<Item = impl AsRef<str>>,
) -> CargoResult<Option<(bool, bool, bool, bool)>> {
Expand Down Expand Up @@ -928,6 +973,12 @@ impl CliUnstable {
"doctest-in-workspace" => self.doctest_in_workspace = parse_empty(k, v)?,
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
"jobserver-per-rustc" => self.jobserver_per_rustc = parse_empty(k, v)?,
"gitoxide" => {
self.gitoxide = v.map_or_else(
|| Ok(Some(GitoxideFeatures::all())),
|v| parse_gitoxide(v.split(',')),
)?
}
"host-config" => self.host_config = parse_empty(k, v)?,
"target-applies-to-host" => self.target_applies_to_host = parse_empty(k, v)?,
"publish-timeout" => self.publish_timeout = parse_empty(k, v)?,
Expand Down
4 changes: 3 additions & 1 deletion tests/testsuite/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use cargo::core::SourceId;
use cargo_test_support::cargo_process;
use cargo_test_support::git::Gitoxide;
use cargo_test_support::paths::{self, CargoPathExt};
use cargo_test_support::registry::{
self, registry_path, Dependency, Package, RegistryBuilder, TestRegistry,
Expand Down Expand Up @@ -1422,7 +1423,7 @@ fn fetch_downloads_http() {
fetch_downloads(cargo_http);
}

#[cargo_test]
#[cargo_test(gitoxide)]
fn fetch_downloads_git() {
fetch_downloads(cargo_stable);
}
Expand All @@ -1447,6 +1448,7 @@ fn fetch_downloads(cargo: fn(&Project, &str) -> Execs) {
Package::new("a", "0.1.0").publish();

cargo(&p, "fetch")
.maybe_fetch_with_gitoxide()
.with_stderr(
"\
[UPDATING] `[..]` index
Expand Down