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
145
146
147
148
149
150
|
//! Work Draft
//!
//! Work Draft is the local workspace of `Rorolala`, used to store files being modified
use std::path::PathBuf;
use crate::{
DirPtrData, DirSearchPattern, RolaError, RolaModule, dir_search_prev,
workdraft::constants::ROLA_DRAFT_DIR,
};
#[rorolala_internal_macros::constants]
pub mod constants {
/// The name of the workdraft directory
pub const ROLA_DRAFT_DIR: &str = ".rola";
/// The name of the directory containing bucket bindings
pub const ROLA_BINDED_BUCKETS_DIR: &str = ".rola/BIND/";
/// The name of the bind file
pub const ROLA_BINDED_BUCKET_FILE: &str = ".rola/BIND/{bucket}";
}
/// Work Draft Pointer
///
/// This struct is used to point to an operable local work draft directory on disk
#[derive(Debug, Default, Clone)]
pub struct WorkDraft;
impl DirPtrData for WorkDraft {
fn fix(raw_path: PathBuf) -> Option<PathBuf> {
let draft_dir = ROLA_DRAFT_DIR();
dir_search_prev(raw_path, DirSearchPattern::Dir(&draft_dir))
}
}
impl WorkDraft {
/// Creates a new work draft directory at the given path
pub fn create(path: PathBuf) -> Result<(), RolaError> {
let dir = path.join(ROLA_DRAFT_DIR());
std::fs::create_dir_all(dir).map_err(|e| RolaError::from((RolaModule::Workdraft, e)))?;
Ok(())
}
}
/// Module for managing workdraft bucket bindings
pub mod bucket_bind_mgr {
use std::path::PathBuf;
use crate::{
DirPtr, RolaError, RolaModule, WorkDraft, constants::ROLA_BINDED_BUCKETS_DIR,
workdraft::constants::ROLA_BINDED_BUCKET_FILE,
};
impl DirPtr<WorkDraft> {
/// Returns the path to the bind file for this work draft
pub fn bind_bucket_path(&self, bucket: impl AsRef<str>) -> PathBuf {
self.path().join(ROLA_BINDED_BUCKET_FILE(bucket))
}
/// Returns the path to the bind file for this work draft
pub fn bind_bucket(&self, bucket: impl AsRef<str>) -> Result<String, RolaError> {
let bucket_path = self.bind_bucket_path(bucket);
let parent = bucket_path.parent().ok_or_else(|| -> RolaError {
RolaError::from((
RolaModule::Workdraft,
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid bucket path: {}", bucket_path.to_string_lossy()),
),
))
})?;
if !parent.exists() {
std::fs::create_dir_all(parent)
.map_err(|e| RolaError::from((RolaModule::Workdraft, e)))?;
}
match std::fs::read_to_string(bucket_path) {
Ok(str) => Ok(str),
Err(err) => Err(RolaError::from((RolaModule::Workdraft, err))),
}
}
/// Binds the work draft to the specified bucket
pub fn bind_bucket_to(&self, bucket: &str) -> Result<(), RolaError> {
let bucket_path = self.bind_bucket_path(bucket);
let parent = bucket_path.parent().ok_or_else(|| -> RolaError {
RolaError::from((
RolaModule::Workdraft,
std::io::Error::new(std::io::ErrorKind::InvalidInput, "invalid bucket path"),
))
})?;
if !parent.exists() {
std::fs::create_dir_all(parent)
.map_err(|e| RolaError::from((RolaModule::Workdraft, e)))?;
}
std::fs::write(&bucket_path, bucket)
.map_err(|e| RolaError::from((RolaModule::Workdraft, e)))?;
Ok(())
}
/// Returns all bound bucket names for this work draft
pub fn binded_buckets(&self) -> Result<Vec<String>, RolaError> {
let bind_dir = self.path().join(ROLA_BINDED_BUCKETS_DIR());
if !bind_dir.exists() {
return Ok(Vec::new());
}
let mut buckets = Vec::new();
let entries = std::fs::read_dir(&bind_dir)
.map_err(|e| RolaError::from((RolaModule::Workdraft, e)))?;
for entry in entries {
let entry = entry.map_err(|e| RolaError::from((RolaModule::Workdraft, e)))?;
let path = entry.path();
if path.is_file() {
// Read the file content which contains the bucket name
if let Ok(content) = std::fs::read_to_string(&path) {
let bucket = content.trim().to_string();
if !bucket.is_empty() {
buckets.push(bucket);
}
}
}
}
Ok(buckets)
}
/// Removes the binding for the specified bucket
pub fn unbind_bucket(&self, bucket: impl AsRef<str>) -> Result<(), RolaError> {
let bucket_path = self.bind_bucket_path(bucket);
if bucket_path.exists() {
std::fs::remove_file(&bucket_path)
.map_err(|e| RolaError::from((RolaModule::Workdraft, e)))?;
}
Ok(())
}
/// Removes bindings for all specified buckets
pub fn unbind_buckets(&self, buckets: &[impl AsRef<str>]) -> Result<(), RolaError> {
for bucket in buckets {
self.unbind_bucket(bucket)?;
}
Ok(())
}
}
}
|