Skip to content

Add reftable test and archive #1825

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

Merged
merged 6 commits into from
Apr 15, 2025
Merged
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
30 changes: 19 additions & 11 deletions gix-discover/src/is.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{borrow::Cow, ffi::OsStr, path::Path};

use crate::{DOT_GIT_DIR, MODULES};
use std::{borrow::Cow, ffi::OsStr, path::Path};

/// Returns true if the given `git_dir` seems to be a bare repository.
///
Expand Down Expand Up @@ -67,21 +66,30 @@ pub(crate) fn git_with_metadata(

{
// Fast-path: avoid doing the complete search if HEAD is already not there.
// TODO(reftable): use a ref-store to lookup HEAD if ref-tables should be supported, or detect ref-tables beforehand.
// Actually ref-tables still keep a specially marked `HEAD` around, so nothing might be needed here
// Even though our head-check later would fail without supporting it.
if !dot_git.join("HEAD").exists() {
return Err(crate::is_git::Error::MissingHead);
}
// We expect to be able to parse any ref-hash, so we shouldn't have to know the repos hash here.
// With ref-table, the has is probably stored as part of the ref-db itself, so we can handle it from there.
// With ref-table, the hash is probably stored as part of the ref-db itself, so we can handle it from there.
// In other words, it's important not to fail on detached heads here because we guessed the hash kind wrongly.
let refs = gix_ref::file::Store::at(dot_git.as_ref().into(), Default::default());
let head = refs.find_loose("HEAD")?;
if head.name.as_bstr() != "HEAD" {
return Err(crate::is_git::Error::MisplacedHead {
name: head.name.into_inner(),
});
match refs.find_loose("HEAD") {
Ok(head) => {
if head.name.as_bstr() != "HEAD" {
return Err(crate::is_git::Error::MisplacedHead {
name: head.name.into_inner(),
});
}
}
Err(gix_ref::file::find::existing::Error::Find(gix_ref::file::find::Error::ReferenceCreation {
source: _,
relative_path,
})) if relative_path == Path::new("HEAD") => {
// It's fine as long as the reference is found is `HEAD`.
}
Err(err) => {
return Err(err.into());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,18 @@ fn split_worktree_using_configuration() -> crate::Result {
}
Ok(())
}

#[test]
fn reftable() -> crate::Result {
let repo_path = match gix_testtools::scripted_fixture_read_only("make_reftable_repo.sh") {
Ok(root) => root.join("reftable-clone/.git"),
Err(_) if *gix_testtools::GIT_VERSION < (2, 44, 0) => {
eprintln!("Fixture script failure ignored as it looks like Git isn't recent enough.");
return Ok(());
}
Err(err) => panic!("{err}"),
};
let kind = gix_discover::is_git(&repo_path)?;
assert_eq!(kind, gix_discover::repository::Kind::WorkTree { linked_git_dir: None });
Ok(())
}
Binary file not shown.
13 changes: 13 additions & 0 deletions gix-discover/tests/fixtures/make_reftable_repo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -eu -o pipefail

git init -q

git checkout -b main
touch this
git add this
git commit -q -m c1
echo hello >> this
git commit -q -am c2

git clone --ref-format=reftable . reftable-clone
4 changes: 2 additions & 2 deletions gix-fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ pub struct Stack {
}

#[cfg(unix)]
/// Returns whether a a file has the executable permission set.
/// Returns whether a file has the executable permission set.
pub fn is_executable(metadata: &std::fs::Metadata) -> bool {
use std::os::unix::fs::MetadataExt;
(metadata.mode() & 0o100) != 0
(metadata.mode() & 0o111) != 0
}

/// Classifiers for IO-errors.
Expand Down
5 changes: 5 additions & 0 deletions gix-validate/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub mod component {
DotGitDir,
#[error("The .gitmodules file must not be a symlink")]
SymlinkedGitModules,
#[error("Relative components '.' and '..' are disallowed")]
Relative,
}

/// Further specify what to check for in [`component()`](super::component())
Expand Down Expand Up @@ -78,6 +80,9 @@ pub fn component(
if input.is_empty() {
return Err(component::Error::Empty);
}
if input == ".." || input == "." {
return Err(component::Error::Relative);
}
if protect_windows {
if input.find_byteset(br"/\").is_some() {
return Err(component::Error::PathSeparator);
Expand Down
4 changes: 4 additions & 0 deletions gix-validate/tests/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ mod component {
mktest!(con_with_extension, b"CON.abc", Error::WindowsReservedName);
mktest!(con_with_middle, b"CON.tar.xz", Error::WindowsReservedName);
mktest!(con_mixed_with_middle, b"coN.tar.xz ", Error::WindowsReservedName);
mktest!(dot_dot, b"..", Error::Relative);
mktest!(dot_dot_no_opts, b"..", Error::Relative, NO_OPTS);
mktest!(single_dot, b".", Error::Relative);
mktest!(single_dot_no_opts, b".", Error::Relative, NO_OPTS);
mktest!(
conout_mixed_with_extension,
b"ConOut$ .xyz",
Expand Down
Binary file not shown.
13 changes: 13 additions & 0 deletions gix/tests/fixtures/make_reftable_repo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -eu -o pipefail

git init -q

git checkout -b main
touch this
git add this
git commit -q -m c1
echo hello >> this
git commit -q -am c2

git clone --ref-format=reftable . reftable-clone
27 changes: 27 additions & 0 deletions gix/tests/gix/repository/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,33 @@ fn on_root_with_decomposed_unicode() -> crate::Result {
Ok(())
}

#[test]
fn non_bare_reftable() -> crate::Result {
let repo = match named_subrepo_opts(
"make_reftable_repo.sh",
"reftable-clone",
gix::open::Options::isolated(),
) {
Ok(r) => r,
Err(_) if *gix_testtools::GIT_VERSION < (2, 44, 0) => {
eprintln!("Fixture script failure ignored as it looks like Git isn't recent enough.");
return Ok(());
}
Err(err) => panic!("{err}"),
};
assert!(
repo.head_id().is_err(),
"Trying to do anything with head will fail as we don't support reftables yet"
);
assert!(!repo.is_bare());
assert_ne!(
repo.workdir(),
None,
"Otherwise it can be used, but it's hard to do without refs"
);
Ok(())
}

#[test]
fn bare_repo_with_index() -> crate::Result {
let repo = named_subrepo_opts(
Expand Down
4 changes: 3 additions & 1 deletion gix/tests/gix/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ pub fn named_subrepo_opts(
name: &str,
opts: open::Options,
) -> std::result::Result<Repository, gix::open::Error> {
let repo_path = gix_testtools::scripted_fixture_read_only(fixture).unwrap().join(name);
let repo_path = gix_testtools::scripted_fixture_read_only(fixture)
.map_err(|err| gix::open::Error::Io(std::io::Error::other(err)))?
.join(name);
Ok(ThreadSafeRepository::open_opts(repo_path, opts)?.to_thread_local())
}

Expand Down
9 changes: 3 additions & 6 deletions tests/tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,13 +583,10 @@ fn scripted_fixture_read_only_with_args_inner(
};
if !output.status.success() {
write_failure_marker(&failure_marker);
eprintln!("stdout: {}", output.stdout.as_bstr());
eprintln!("stderr: {}", output.stderr.as_bstr());
return Err(format!("fixture script of {cmd:?} failed").into());
}
assert!(
output.status.success(),
"fixture script of {cmd:?} failed: stdout: {}\nstderr: {}",
output.stdout.as_bstr(),
output.stderr.as_bstr()
);
create_archive_if_we_should(
&script_result_directory,
&archive_file_path,
Expand Down
Loading