Skip to content

Commit 1dd3d67

Browse files
cesfahaniByron
authored andcommitted
feat: add basic connectivity check
Implement a simple connectivity check in a new `gix-fsck` crate, and add this to `gix` via a new `fsck` subcommand. Currently this is functionally equivalent to: `git rev-list --objects --quiet --missing=print` feat: add basic connectivity check - address review feedback
1 parent e47c46d commit 1dd3d67

File tree

18 files changed

+377
-2
lines changed

18 files changed

+377
-2
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ members = [
281281
"gix-archive",
282282
"gix-worktree-stream",
283283
"gix-revwalk",
284+
"gix-fsck",
284285

285286
"tests/tools",
286287

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ is usable to some extent.
140140
* [gix-tui](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-tui)
141141
* [gix-tix](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-tix)
142142
* [gix-bundle](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-bundle)
143+
* [gix-fsck](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-fsck)
143144

144145
### Stress Testing
145146
* [x] Verify huge packs

crate-status.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,18 @@ See its [README.md](https://github.com/Byron/gitoxide/blob/main/gix-lock/README.
775775
* [x] validate submodule names
776776
* [x] [validate][tagname-validation] tag names
777777

778+
### gix-fsck
779+
* [x] validate connectivity when provided a specific commit as a starting point
780+
* [ ] validate connectivity of all `refs` in the index
781+
* [ ] identify objects that exist but are not reference by any reference nodes (e.g. `refs` or a provided commit)
782+
* [ ] add support for various options
783+
* [ ] write dangling objects to the `.git/log-found` directory structure
784+
* [ ] `strict` mode, to check for tree objects with `g+w` permissions
785+
* [ ] consider reflog entries as reference nodes/heads
786+
* [ ] when reporting reachable objects, include _how_ they are reachable
787+
* [ ] which reference node(s) made them reachable
788+
* [ ] parent commit(s)
789+
778790
### gix-ref
779791
* [ ] Prepare code for arrival of longer hashes like Sha256. It's part of the [V2 proposal][reftable-v2] but should work for loose refs as well.
780792
* **Stores**

gitoxide-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ gix-pack-for-configuration-only = { package = "gix-pack", version = "^0.44.0", p
4949
gix-transport-configuration-only = { package = "gix-transport", version = "^0.38.0", path = "../gix-transport", default-features = false }
5050
gix-archive-for-configuration-only = { package = "gix-archive", version = "^0.6.0", path = "../gix-archive", optional = true, features = ["tar", "tar_gz"] }
5151
gix-status = { version = "^0.2.0", path = "../gix-status" }
52+
gix-fsck = { version = "^0.0.0", path = "../gix-fsck" }
5253
serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }
5354
anyhow = "1.0.42"
5455
thiserror = "1.0.34"

gitoxide-core/src/repository/fsck.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use std::io::{BufWriter, Write};
2+
3+
use anyhow::Context;
4+
use gix::{objs::Kind, ObjectId};
5+
6+
pub fn connectivity(mut repo: gix::Repository, spec: Option<String>, out: impl std::io::Write) -> anyhow::Result<()> {
7+
let mut out = BufWriter::with_capacity(64 * 1024, out);
8+
let spec = spec.unwrap_or("HEAD".into());
9+
10+
repo.object_cache_size_if_unset(4 * 1024 * 1024);
11+
// We expect to be finding a bunch of non-existent objects here - never refresh the ODB
12+
repo.objects.refresh_never();
13+
14+
let id = repo
15+
.rev_parse_single(spec.as_str())
16+
.context("Only single revisions are supported")?;
17+
let commits: gix::revision::Walk<'_> = id
18+
.object()?
19+
.peel_to_kind(gix::object::Kind::Commit)
20+
.context("Need commitish as starting point")?
21+
.id()
22+
.ancestors()
23+
.all()?;
24+
25+
let missing_cb = |oid: &ObjectId, kind: Kind| {
26+
writeln!(out, "{oid}: {kind}").expect("failed to write output");
27+
};
28+
let mut conn = gix_fsck::ConnectivityCheck::new(&repo.objects, missing_cb);
29+
30+
// Walk all commits, checking each one for connectivity
31+
for commit in commits {
32+
let commit = commit?;
33+
conn.check_commit(&commit.id);
34+
for parent in commit.parent_ids {
35+
conn.check_commit(&parent);
36+
}
37+
}
38+
39+
Ok(())
40+
}

gitoxide-core/src/repository/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub use clone::function::clone;
3535
pub use fetch::function::fetch;
3636

3737
pub mod commitgraph;
38+
pub mod fsck;
3839
pub mod index;
3940
pub mod mailmap;
4041
pub mod odb;

gix-fsck/Cargo.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "gix-fsck"
3+
version = "0.0.0"
4+
repository = "https://github.com/Byron/gitoxide"
5+
authors = ["Cameron Esfahani <[email protected]>", "Sebastian Thiel <[email protected]>"]
6+
license = "MIT OR Apache-2.0"
7+
description = "Verifies the connectivity and validity of objects in the database"
8+
edition = "2021"
9+
include = ["src/**/*", "LICENSE-*", "CHANGELOG.md"]
10+
rust-version = "1.65"
11+
12+
[lib]
13+
doctest = false
14+
15+
[dependencies]
16+
gix-hash = { version = "^0.13.1", path = "../gix-hash" }
17+
gix-hashtable = { version = "^0.4.0", path = "../gix-hashtable" }
18+
gix-object = { version = "^0.38.0", path = "../gix-object" }
19+
20+
[dev-dependencies]
21+
gix-odb = { path = "../gix-odb" }
22+
gix-testtools = { path = "../tests/tools"}

gix-fsck/Changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

gix-fsck/LICENSE-APACHE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE-APACHE

0 commit comments

Comments
 (0)