Skip to content

shallow support (Repository) #765

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

Closed
wants to merge 4 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
4 changes: 4 additions & 0 deletions SHORTCOMINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ This file is for tracking features that are less well implemented or less powerf
* **Objects larger than 32 bits cannot be loaded on 32 bit systems**
* in-memory representations objects cannot handle objects greater than the amount of addressable memory.
* This will not affect git LFS though.

### `gix`

* object replacements are read once upon opening the repository from their refs and changes to these won't be picked up.

### `gix-url`

Expand Down
9 changes: 9 additions & 0 deletions gix/src/config/cache/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,15 @@ fn apply_environment_overrides(
},
],
),
(
"gitoxide",
Some(Cow::Borrowed("core".into())),
git_prefix,
&[{
let key = &gitoxide::Core::SHALLOW_FILE;
(env(key), key.name)
}],
),
(
"gitoxide",
Some(Cow::Borrowed("author".into())),
Expand Down
32 changes: 28 additions & 4 deletions gix/src/config/tree/sections/gitoxide.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::config;
use crate::config::tree::{keys, Gitoxide, Key, Section};

impl Gitoxide {
/// The `gitoxide.allow` section.
pub const ALLOW: Allow = Allow;
/// The `gitoxide.author` section.
pub const AUTHOR: Author = Author;
/// The `gitoxide.core` section.
pub const CORE: Core = Core;
/// The `gitoxide.commit` section.
pub const COMMIT: Commit = Commit;
/// The `gitoxide.committer` section.
Expand Down Expand Up @@ -39,6 +42,7 @@ impl Section for Gitoxide {
&[
&Self::ALLOW,
&Self::AUTHOR,
&Self::CORE,
&Self::COMMIT,
&Self::COMMITTER,
&Self::HTTP,
Expand All @@ -56,6 +60,29 @@ mod subsections {
Tree,
};

/// The `Core` sub-section.
#[derive(Copy, Clone, Default)]
pub struct Core;

impl Core {
/// The `gitoxide.core.shallowFile` key.
pub const SHALLOW_FILE: keys::Path = keys::Path::new_path("shallowFile", &Gitoxide::CORE)
.with_environment_override("GIT_SHALLOW_FILE")
.with_deviation(
"relative file paths will always be made relative to the git-common-dir, whereas `git` keeps them as is.",
);
}

impl Section for Core {
fn name(&self) -> &str {
"core"
}

fn keys(&self) -> &[&dyn Key] {
&[&Self::SHALLOW_FILE]
}
}

/// The `Http` sub-section.
#[derive(Copy, Clone, Default)]
pub struct Http;
Expand Down Expand Up @@ -341,6 +368,7 @@ mod subsections {
}
}
}
pub use subsections::{Allow, Author, Commit, Committer, Core, Http, Https, Objects, Ssh, User};

pub mod validate {
use std::error::Error;
Expand All @@ -357,7 +385,3 @@ pub mod validate {
}
}
}

pub use subsections::{Allow, Author, Commit, Committer, Http, Https, Objects, Ssh, User};

use crate::config;
17 changes: 17 additions & 0 deletions gix/src/diff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
pub use gix_diff::*;

///
pub mod rename {
/// Determine how to do rename tracking.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Tracking {
/// Do not track renames at all, the fastest option.
Disabled,
/// Track renames.
Renames,
/// Track renames and copies.
///
/// This is the most expensive option.
RenamesAndCopies,
}
}
79 changes: 10 additions & 69 deletions gix/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,7 @@ pub mod interrupt;

mod ext;
///
pub mod prelude {
pub use gix_features::parallel::reduce::Finalize;
pub use gix_odb::{Find, FindExt, Header, HeaderExt, Write};

pub use crate::ext::*;
}
pub mod prelude;

///
pub mod path;
Expand Down Expand Up @@ -133,31 +128,10 @@ mod repository;
pub mod tag;

///
pub mod progress {
#[cfg(feature = "progress-tree")]
pub use gix_features::progress::prodash::tree;
pub use gix_features::progress::*;
}
pub mod progress;

///
pub mod diff {
pub use gix_diff::*;
///
pub mod rename {
/// Determine how to do rename tracking.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Tracking {
/// Do not track renames at all, the fastest option.
Disabled,
/// Track renames.
Renames,
/// Track renames and copies.
///
/// This is the most expensive option.
RenamesAndCopies,
}
}
}
pub mod diff;

/// See [ThreadSafeRepository::discover()], but returns a [`Repository`] instead.
#[allow(clippy::result_large_err)]
Expand Down Expand Up @@ -238,20 +212,10 @@ pub fn open_opts(directory: impl Into<std::path::PathBuf>, options: open::Option
}

///
pub mod permission {
///
pub mod env_var {
///
pub mod resource {
///
pub type Error = gix_sec::permission::Error<std::path::PathBuf>;
}
}
}
pub mod permission;

///
pub mod permissions {
pub use crate::repository::permissions::{Config, Environment};
}
pub mod permissions;
pub use repository::permissions::Permissions;

///
Expand All @@ -278,33 +242,10 @@ pub mod remote;
pub mod init;

/// Not to be confused with 'status'.
pub mod state {
/// Tell what operation is currently in progress.
#[derive(Debug, PartialEq, Eq)]
pub enum InProgress {
/// A mailbox is being applied.
ApplyMailbox,
/// A rebase is happening while a mailbox is being applied.
// TODO: test
ApplyMailboxRebase,
/// A git bisect operation has not yet been concluded.
Bisect,
/// A cherry pick operation.
CherryPick,
/// A cherry pick with multiple commits pending.
CherryPickSequence,
/// A merge operation.
Merge,
/// A rebase operation.
Rebase,
/// An interactive rebase operation.
RebaseInteractive,
/// A revert operation.
Revert,
/// A revert operation with multiple commits pending.
RevertSequence,
}
}
pub mod state;

///
pub mod shallow;

///
pub mod discover;
Expand Down
1 change: 1 addition & 0 deletions gix/src/open/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ impl ThreadSafeRepository {
// used when spawning new repositories off this one when following worktrees
linked_worktree_options: options,
index: gix_features::fs::MutableSnapshot::new().into(),
shallow_commits: gix_features::fs::MutableSnapshot::new().into(),
})
}
}
Expand Down
8 changes: 8 additions & 0 deletions gix/src/permission.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
///
pub mod env_var {
///
pub mod resource {
///
pub type Error = gix_sec::permission::Error<std::path::PathBuf>;
}
}
1 change: 1 addition & 0 deletions gix/src/permissions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub use crate::repository::permissions::{Config, Environment};
4 changes: 4 additions & 0 deletions gix/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub use gix_features::parallel::reduce::Finalize;
pub use gix_odb::{Find, FindExt, Header, HeaderExt, Write};

pub use crate::ext::*;
3 changes: 3 additions & 0 deletions gix/src/progress.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#[cfg(feature = "progress-tree")]
pub use gix_features::progress::prodash::tree;
pub use gix_features::progress::*;
4 changes: 4 additions & 0 deletions gix/src/repository/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ impl Clone for crate::Repository {
self.config.clone(),
self.options.clone(),
self.index.clone(),
self.shallow_commits.clone(),
)
}
}
Expand Down Expand Up @@ -40,6 +41,7 @@ impl From<&crate::ThreadSafeRepository> for crate::Repository {
repo.config.clone(),
repo.linked_worktree_options.clone(),
repo.index.clone(),
repo.shallow_commits.clone(),
)
}
}
Expand All @@ -54,6 +56,7 @@ impl From<crate::ThreadSafeRepository> for crate::Repository {
repo.config,
repo.linked_worktree_options,
repo.index,
repo.shallow_commits,
)
}
}
Expand All @@ -68,6 +71,7 @@ impl From<crate::Repository> for crate::ThreadSafeRepository {
config: r.config,
linked_worktree_options: r.options,
index: r.index,
shallow_commits: r.shallow_commits,
}
}
}
3 changes: 3 additions & 0 deletions gix/src/repository/init.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::cell::RefCell;

impl crate::Repository {
#[allow(clippy::too_many_arguments)]
pub(crate) fn from_refs_and_objects(
refs: crate::RefStore,
objects: crate::OdbHandle,
Expand All @@ -9,6 +10,7 @@ impl crate::Repository {
config: crate::config::Cache,
linked_worktree_options: crate::open::Options,
index: crate::worktree::IndexStorage,
shallow_commits: crate::shallow::CommitsStorage,
) -> Self {
let objects = setup_objects(objects, &config);
crate::Repository {
Expand All @@ -20,6 +22,7 @@ impl crate::Repository {
config,
options: linked_worktree_options,
index,
shallow_commits,
}
}

Expand Down
1 change: 1 addition & 0 deletions gix/src/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub(crate) mod permissions;
mod reference;
mod remote;
mod revision;
mod shallow;
mod snapshots;
mod state;
mod thread_safe;
Expand Down
59 changes: 59 additions & 0 deletions gix/src/repository/shallow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::bstr::ByteSlice;
use crate::config::tree::{gitoxide, Key};
use crate::Repository;
use std::borrow::Cow;
use std::path::PathBuf;

impl Repository {
/// Return `true` if the repository is a shallow clone, i.e. contains history only up to a certain depth.
pub fn is_shallow(&self) -> bool {
self.shallow_file()
.metadata()
.map_or(false, |m| m.is_file() && m.len() > 0)
}

/// Return a shared list of shallow commits which is updated automatically if the in-memory snapshot has become stale as the underlying file
/// on disk has changed.
///
/// The shared list is shared across all clones of this repository.
pub fn shallow_commits(&self) -> Result<Option<crate::shallow::Commits>, crate::shallow::open::Error> {
self.shallow_commits.recent_snapshot(
|| self.shallow_file().metadata().ok().and_then(|m| m.modified().ok()),
|| {
let buf = match std::fs::read(self.shallow_file()) {
Ok(buf) => buf,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
Err(err) => return Err(err.into()),
};

let mut commits = buf
.lines()
.map(gix_hash::ObjectId::from_hex)
.collect::<Result<Vec<_>, _>>()?;

commits.sort();
if commits.is_empty() {
Ok(None)
} else {
Ok(Some(commits))
}
},
)
}

/// Return the path to the `shallow` file which contains hashes, one per line, that describe commits that don't have their
/// parents within this repository.
///
/// Note that it may not exist if the repository isn't actually shallow.
pub fn shallow_file(&self) -> PathBuf {
let shallow_name = self
.config
.resolved
.string_filter_by_key(
gitoxide::Core::SHALLOW_FILE.logical_name().as_str(),
&mut self.filter_config_section(),
)
.unwrap_or_else(|| Cow::Borrowed("shallow".into()));
self.common_dir().join(gix_path::from_bstr(shallow_name))
}
}
2 changes: 2 additions & 0 deletions gix/src/revision/spec/parse/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ pub enum Error {
},
#[error(transparent)]
Traverse(#[from] gix_traverse::commit::ancestors::Error),
#[error(transparent)]
Walk(#[from] crate::revision::walk::Error),
#[error("Spec does not contain a single object id")]
SingleNotFound,
}
Loading