1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
//! ### Which `Easy*` is for me?
//!
//! * Use `Easy*Exclusive` when the underlying `Repository` eventually needs mutation, for instance to update data structures
//! - This is useful for long-running applications that eventually need to adapt to changes in the repository and pick up
//! new packs after a GC operation or a received pack.
//! * Use the non-exclusive variants if the `Repository` doesn't ever have to change, for example as in one-off commands.
//!
//! ### Implementation Notes
//!
//! - Why no `Easy` with simply an owned `Repository`, instead `Rc<Repository>` is enforced
//! - When this is desired, rather use `EasyShared` and drop the `EasyShared` once mutable access to the `Repository` is needed.
//! `Access` is not usable for functions that require official `&mut` mutability, it's made for interior mutability to support
//! trees of objects.
use std::{
cell::RefCell,
ops::{Deref, DerefMut},
sync::Arc,
time::SystemTime,
};
use git_hash::ObjectId;
use git_object as objs;
use git_odb as odb;
use git_ref as refs;
use crate::Repository;
mod impls;
pub(crate) mod ext;
pub mod borrow;
pub mod object;
mod oid;
pub mod reference;
pub mod state;
/// An [ObjectId] with access to a repository.
#[derive(Eq, Hash, Ord, PartialOrd, Clone, Copy)]
pub struct Oid<'r, A> {
id: ObjectId,
access: &'r A,
}
/// A decoded object with a reference to its owning repository.
///
/// ## Limitations
///
/// Note that it holds a reference to a buffer of it's associated repository handle, so there
/// can only be one at a time, per handle.
pub struct ObjectRef<'repo, A> {
/// The id of the object
pub id: ObjectId,
/// The kind of the object
pub kind: objs::Kind,
/// The fully decoded object data
pub data: std::cell::Ref<'repo, [u8]>,
access: &'repo A,
}
/// A decoded tree object with access to its owning repository.
///
/// Please note that the limitations described in [ObjectRef] apply here as well.
pub struct TreeRef<'repo, A> {
/// The id of the tree
pub id: ObjectId,
/// The fully decoded tree data
pub data: std::cell::Ref<'repo, [u8]>,
access: &'repo A,
}
/// A detached, self-contained object, without access to its source repository.
///
/// Use it if an `ObjectRef` should be sent over thread boundaries or stored in collections.
#[derive(Clone)]
pub struct Object {
/// The id of the object
pub id: ObjectId,
/// The kind of the object
pub kind: objs::Kind,
/// The fully decoded object data
pub data: Vec<u8>,
}
/// A reference that points to an object or reference, with access to its source repository.
pub struct Reference<'r, A> {
pub(crate) backing: Option<reference::Backing>,
pub(crate) access: &'r A,
}
#[cfg(not(feature = "local"))]
type PackCache = odb::pack::cache::Never;
#[cfg(feature = "local")]
type PackCache = odb::pack::cache::lru::StaticLinkedList<64>;
#[derive(Default)]
struct ModifieablePackedRefsBuffer {
packed_refs: Option<refs::packed::Buffer>,
modified: Option<SystemTime>,
}
/// State for use in `Easy*` to provide mutable parts of a repository such as caches and buffers.
#[derive(Default)]
pub struct State {
/// As the packed-buffer may hold onto a memory map, we avoid that to exist once per thread, multiplying system resources.
/// This seems worth the cost of always going through an `Arc<RwLock<…>>>`. Note that `EasyArcExclusive` uses the same construct
/// but the reason we make this distinction at all is that there are other easy's that allows to chose exactly what you need in
/// your application. `State` is one size fits all with supporting single-threaded applications only.
packed_refs: Arc<parking_lot::RwLock<ModifieablePackedRefsBuffer>>,
pack_cache: RefCell<PackCache>,
buf: RefCell<Vec<u8>>,
}
/// A utility trait to represent access to a repository.
///
/// It provides immutable and possibly mutable access. Both types of access are validated at runtime, which may fail
/// or may block, depending on the implementation.
///
/// Furthermore it provides access to additional state for use with the [`Repository`]. It is designed for thread-local
/// mutable access, which is checked at runtime as well. This means that operations can't freely be interleaved and some
/// care as to be taken especially in conjunction with [`ObjectRef`] instances.
pub trait Access {
/// The type of a shared borrow to the Repository
type RepoRef: Deref<Target = Repository>;
// TODO: Once GATs become stable, try to use them to make it work with RefCells too, aka EasyExclusive
/// The type of a mutable borrow to the Repository
type RepoRefMut: DerefMut<Target = Repository>;
/// Return a shared borrow to the repository.
///
/// This may fail if there already is a mutable borrow
fn repo(&self) -> borrow::repo::Result<Self::RepoRef>;
/// Returns a mutable borrow to the repository if possible.
///
/// # NOTE
///
/// This may not be supported by all implementations. Choosing an implementation that does support it is particularly
/// relevant for long-running applications that make changes to the repository.
fn repo_mut(&self) -> borrow::repo::Result<Self::RepoRefMut>;
/// Return a shared borrow of the repository state, with support for interior mutability.
fn state(&self) -> &State;
}