radicle/storage/git/
temp.rs1use std::io;
2use std::path::{Path, PathBuf};
3
4use crate::prelude::RepoId;
5
6use super::{Repository, RepositoryError, UserInfo};
7
8pub struct TempRepository {
19 repo: Repository,
20 path: PathBuf,
21}
22
23impl TempRepository {
24 pub(crate) const EXT: &str = "tmp";
26
27 const RANDOMNESS_LENGTH: usize = 6;
28
29 pub(super) fn new<P>(root: P, rid: RepoId, info: &UserInfo) -> Result<Self, RepositoryError>
30 where
31 P: AsRef<Path>,
32 {
33 let random: String = std::iter::repeat_with(fastrand::alphanumeric)
34 .take(Self::RANDOMNESS_LENGTH)
35 .collect();
36 let path = root
37 .as_ref()
38 .join(format!("{}.{random}", rid.canonical()))
39 .with_extension(Self::EXT);
40 let repo = Repository::create(&path, rid, info)?;
41 Ok(Self { repo, path })
42 }
43
44 pub fn cleanup(self) {
49 let path = self.path.clone();
50 drop(self.repo);
51 Self::remove(&path)
52 }
53
54 pub fn mv<P>(self, to: P) -> io::Result<()>
62 where
63 P: AsRef<Path>,
64 {
65 let to = to.as_ref();
66 let rid = self.repo.id;
67 let path = self.path.clone();
68 drop(self.repo);
69 if to.exists() {
70 log::warn!(target: "radicle", "Refusing to move from temporary directory '{}' because destination {rid} already exists. Removing the temporary directory.", self.path.display());
71 Self::remove(&path);
72 }
73 std::fs::rename(path, to)
74 }
75
76 fn remove(path: &PathBuf) {
77 if let Err(err) = std::fs::remove_dir_all(path) {
78 let path = path.display();
79 log::error!(target: "worker", "Failed to remove temporary directory '{path}': {err}");
80 }
81 }
82}
83
84impl AsRef<Repository> for TempRepository {
85 fn as_ref(&self) -> &Repository {
86 &self.repo
87 }
88}