drawbridge_server/store/
tag.rs

1// SPDX-FileCopyrightText: 2022 Profian Inc. <opensource@profian.com>
2// SPDX-License-Identifier: Apache-2.0
3
4use super::{CreateError, Entity, Node};
5
6use std::ops::Deref;
7
8use drawbridge_type::{Meta, TreeDirectory, TreeEntry, TreePath};
9
10use camino::{Utf8Path, Utf8PathBuf};
11use futures::{try_join, AsyncRead};
12use tracing::debug;
13
14#[repr(transparent)]
15#[derive(Copy, Clone, Debug)]
16pub struct Tag<'a, P = Utf8PathBuf>(Entity<'a, P>);
17
18impl<'a, P> Deref for Tag<'a, P> {
19    type Target = Entity<'a, P>;
20
21    fn deref(&self) -> &Self::Target {
22        &self.0
23    }
24}
25
26impl<'a, P> From<Entity<'a, P>> for Tag<'a, P> {
27    fn from(entity: Entity<'a, P>) -> Self {
28        Self(entity)
29    }
30}
31
32impl<'a, P: AsRef<Utf8Path>> Tag<'a, P> {
33    pub fn node(&self, path: &TreePath) -> Node<'a, Utf8PathBuf> {
34        if path.is_empty() {
35            self.0.child("tree").into()
36        } else {
37            self.0
38                .child(format!("tree/entries/{}", path.intersperse("/entries/")))
39                .into()
40        }
41    }
42
43    pub async fn create_file_node(
44        &self,
45        path: &TreePath,
46        meta: Meta,
47        rdr: impl Unpin + AsyncRead,
48    ) -> Result<Node<'a, Utf8PathBuf>, CreateError<anyhow::Error>> {
49        // TODO: Validate node hash against parents' expected values
50        // https://github.com/profianinc/drawbridge/issues/77
51        let node = self.node(path);
52        node.create_dir("").await.map_err(|e| {
53            debug!(target: "app::store::Tag::create_file_node", "failed to create content directory: {:?}", e);
54            e
55        })?;
56        node.create_from_reader(meta, rdr).await?;
57        Ok(node)
58    }
59
60    pub async fn create_directory_node(
61        &self,
62        path: &TreePath,
63        meta: Meta,
64        dir: &TreeDirectory<TreeEntry>,
65    ) -> Result<Node<'a, Utf8PathBuf>, CreateError<anyhow::Error>> {
66        // TODO: Validate node hash against parents' expected values
67        // https://github.com/profianinc/drawbridge/issues/77
68        let node = self.node(path);
69        node.create_dir("").await.map_err(|e| {
70            debug!(target: "app::store::Tag::create_directory_node", "failed to create content directory: {:?}", e);
71            e
72        })?;
73        try_join!(node.create_json(meta, dir), node.create_dir("entries"))?;
74        Ok(node)
75    }
76}