mirror of
https://seed.radicle.dev/rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt.git
synced 2026-10-18 19:10:31 +08:00
The main dependant of `radicle-git`, and its crates, is [`heartwood`]. It is licensed under MIT or Apache-2.0, which has been incompatible with the GPL-3.0 license. Since the intellectual property of this code base is with the Better Internet Foundation, it was decided to re-license code in this repository to make the upstream repository compatible. - Remove the license headers (and instructions to add them) - Add MIT and Apache-2.0 licenses - Remove the GPL-3.0 license - Change the license declarations in the `Cargo.toml` files [`heartwood`]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
143 lines
3.5 KiB
Rust
143 lines
3.5 KiB
Rust
use std::{borrow::Cow, collections::BTreeMap, iter::FromIterator};
|
|
|
|
/// A simplified representation of a git tree, intended mainly to be created
|
|
/// from literals.
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// use radicle_git_ext::tree::{Tree, blob};
|
|
///
|
|
/// let my_tree = vec![
|
|
/// ("README", blob(b"awe")),
|
|
/// ("src", vec![("main.rs", blob(b"fn main() {}"))].into_iter().collect()),
|
|
/// ]
|
|
/// .into_iter()
|
|
/// .collect::<Tree>();
|
|
///
|
|
/// assert_eq!(
|
|
/// format!("{:?}", my_tree),
|
|
/// "Tree(\
|
|
/// {\
|
|
/// \"README\": Blob(\
|
|
/// [\
|
|
/// 97, \
|
|
/// 119, \
|
|
/// 101\
|
|
/// ]\
|
|
/// ), \
|
|
/// \"src\": Tree(\
|
|
/// Tree(\
|
|
/// {\
|
|
/// \"main.rs\": Blob(\
|
|
/// [\
|
|
/// 102, \
|
|
/// 110, \
|
|
/// 32, \
|
|
/// 109, \
|
|
/// 97, \
|
|
/// 105, \
|
|
/// 110, \
|
|
/// 40, \
|
|
/// 41, \
|
|
/// 32, \
|
|
/// 123, \
|
|
/// 125\
|
|
/// ]\
|
|
/// )\
|
|
/// }\
|
|
/// )\
|
|
/// )\
|
|
/// }\
|
|
/// )"
|
|
/// )
|
|
/// ```
|
|
#[derive(Clone, Debug)]
|
|
pub struct Tree<'a>(BTreeMap<Cow<'a, str>, Node<'a>>);
|
|
|
|
impl Tree<'_> {
|
|
pub fn write(&self, repo: &git2::Repository) -> Result<git2::Oid, git2::Error> {
|
|
use Node::*;
|
|
|
|
let mut builder = repo.treebuilder(None)?;
|
|
for (name, node) in &self.0 {
|
|
match node {
|
|
Blob(data) => {
|
|
let oid = repo.blob(data)?;
|
|
builder.insert(name.as_ref(), oid, git2::FileMode::Blob.into())?;
|
|
}
|
|
Tree(sub) => {
|
|
let oid = sub.write(repo)?;
|
|
builder.insert(name.as_ref(), oid, git2::FileMode::Tree.into())?;
|
|
}
|
|
}
|
|
}
|
|
|
|
builder.write()
|
|
}
|
|
}
|
|
|
|
impl<'a> From<BTreeMap<Cow<'a, str>, Node<'a>>> for Tree<'a> {
|
|
fn from(map: BTreeMap<Cow<'a, str>, Node<'a>>) -> Self {
|
|
Self(map)
|
|
}
|
|
}
|
|
|
|
impl<'a, K, N> FromIterator<(K, N)> for Tree<'a>
|
|
where
|
|
K: Into<Cow<'a, str>>,
|
|
N: Into<Node<'a>>,
|
|
{
|
|
fn from_iter<T>(iter: T) -> Self
|
|
where
|
|
T: IntoIterator<Item = (K, N)>,
|
|
{
|
|
Self(
|
|
iter.into_iter()
|
|
.map(|(k, v)| (k.into(), v.into()))
|
|
.collect(),
|
|
)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum Node<'a> {
|
|
Blob(Cow<'a, [u8]>),
|
|
Tree(Tree<'a>),
|
|
}
|
|
|
|
pub fn blob(slice: &[u8]) -> Node {
|
|
Node::from(slice)
|
|
}
|
|
|
|
impl<'a> From<&'a [u8]> for Node<'a> {
|
|
fn from(slice: &'a [u8]) -> Self {
|
|
Self::from(Cow::Borrowed(slice))
|
|
}
|
|
}
|
|
|
|
impl<'a> From<Cow<'a, [u8]>> for Node<'a> {
|
|
fn from(bytes: Cow<'a, [u8]>) -> Self {
|
|
Self::Blob(bytes)
|
|
}
|
|
}
|
|
|
|
impl<'a> From<Tree<'a>> for Node<'a> {
|
|
fn from(tree: Tree<'a>) -> Self {
|
|
Self::Tree(tree)
|
|
}
|
|
}
|
|
|
|
impl<'a, K, N> FromIterator<(K, N)> for Node<'a>
|
|
where
|
|
K: Into<Cow<'a, str>>,
|
|
N: Into<Node<'a>>,
|
|
{
|
|
fn from_iter<T>(iter: T) -> Self
|
|
where
|
|
T: IntoIterator<Item = (K, N)>,
|
|
{
|
|
Self::Tree(iter.into_iter().collect())
|
|
}
|
|
}
|