Skip to content

Commit a8ce1b5

Browse files
committed
rename dir before pack
1 parent e02c056 commit a8ce1b5

File tree

2 files changed

+45
-39
lines changed

2 files changed

+45
-39
lines changed

src/bin/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ struct Cli {
195195
fn main() -> io::Result<()> {
196196
let cli = Cli::parse();
197197

198-
let mut zup_tree = zup::write::Tree::new();
198+
let mut zup_tree = zup::write::Tree::new(PathBuf::from("zup_tree_work"));
199199
let mut zup_flavors = Vec::new();
200200

201201
let num_threads = cli.num_threads.unwrap_or(1);

src/zup/write.rs

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use rand::seq::SliceRandom;
22
use sha2::{Digest, Sha256};
33
use std::borrow::Cow;
4-
use std::cell::RefCell;
54
use std::collections::HashMap;
65
use std::fs::{self};
76
use std::io::{self, Write};
@@ -29,14 +28,25 @@ pub struct DirectoryEntry {
2928
pub node_id: NodeId,
3029
}
3130

31+
enum PathOrData {
32+
Path(
33+
(
34+
PathBuf,
35+
Mutex<Arc<dyn Fn(&Path, &mut Vec<u8>) + Sync + Send>>,
36+
usize,
37+
),
38+
),
39+
Data(Arc<Vec<u8>>),
40+
}
41+
3242
pub struct File {
33-
contents: RefCell<PathOrData>,
43+
contents: PathOrData,
3444
}
3545

3646
impl File {
3747
pub fn from_data(data: Vec<u8>) -> Self {
3848
Self {
39-
contents: RefCell::new(PathOrData::Data(Arc::new(data))),
49+
contents: PathOrData::Data(Arc::new(data)),
4050
}
4151
}
4252

@@ -46,46 +56,31 @@ impl File {
4656
len: usize,
4757
) -> Self {
4858
Self {
49-
contents: RefCell::new(PathOrData::Path((path, Mutex::new(data_filter), len))),
59+
contents: PathOrData::Path((path, Mutex::new(data_filter), len)),
5060
}
5161
}
5262

5363
fn len(&self) -> usize {
54-
match &*self.contents.borrow() {
64+
match &self.contents {
5565
PathOrData::Path((_, _, len)) => *len,
5666
PathOrData::Data(data) => data.len(),
57-
_ => unreachable!(),
5867
}
5968
}
6069

6170
fn data(&self) -> io::Result<FileData> {
62-
{
63-
let mut contents = self.contents.borrow_mut();
64-
65-
if let PathOrData::Path((path, data_filter, _)) = &*contents {
71+
match &self.contents {
72+
PathOrData::Path((path, data_filter, _)) => {
6673
let mut data = fs::read(&path)?;
6774
{
6875
let data_filter = data_filter.lock().unwrap();
6976
(data_filter)(&path, &mut data);
7077
}
7178

72-
*contents = PathOrData::Data(Arc::new(data));
79+
Ok(FileData(Arc::new(data)))
7380
}
74-
}
75-
76-
let contents = self.contents.borrow();
77-
78-
match &*contents {
7981
PathOrData::Data(data) => Ok(FileData(data.clone())),
80-
_ => unreachable!(),
8182
}
8283
}
83-
84-
fn reset(&self) {
85-
let mut contents = self.contents.borrow_mut();
86-
87-
*contents = PathOrData::None;
88-
}
8984
}
9085

9186
pub struct FileData(Arc<Vec<u8>>);
@@ -96,18 +91,6 @@ impl AsRef<[u8]> for FileData {
9691
}
9792
}
9893

99-
enum PathOrData {
100-
Path(
101-
(
102-
PathBuf,
103-
Mutex<Arc<dyn Fn(&Path, &mut Vec<u8>) + Sync + Send>>,
104-
usize,
105-
),
106-
),
107-
Data(Arc<Vec<u8>>),
108-
None,
109-
}
110-
11194
impl Node {
11295
fn hash(&mut self) -> [u8; 32] {
11396
let mut hash = Sha256::new();
@@ -140,14 +123,18 @@ pub struct Tree {
140123
nodes: HashMap<NodeId, Node>,
141124
hash_dedup: HashMap<[u8; 32], NodeId>,
142125
next_id: u64,
126+
work_dir: PathBuf,
127+
next_dir: u64,
143128
}
144129

145130
impl Tree {
146-
pub fn new() -> Self {
131+
pub fn new(work_dir: PathBuf) -> Self {
147132
Self {
148133
nodes: HashMap::new(),
149134
hash_dedup: HashMap::new(),
150135
next_id: 0,
136+
work_dir: work_dir,
137+
next_dir: 0,
151138
}
152139
}
153140

@@ -175,6 +162,24 @@ impl Tree {
175162
path: &Path,
176163
file_filter: &Box<dyn Fn(&Path) -> bool>,
177164
data_filter: &Arc<dyn Fn(&Path, &mut Vec<u8>) + Send + Sync>,
165+
) -> io::Result<Option<NodeId>> {
166+
let to = self
167+
.work_dir
168+
.join(self.next_dir.to_string())
169+
.join(path.file_name().unwrap());
170+
171+
fs::create_dir_all(to.parent().unwrap())?;
172+
fs::rename(path, &to)?;
173+
174+
self.next_dir += 1;
175+
self.pack_inner(&to, file_filter, data_filter)
176+
}
177+
178+
fn pack_inner(
179+
&mut self,
180+
path: &Path,
181+
file_filter: &Box<dyn Fn(&Path) -> bool>,
182+
data_filter: &Arc<dyn Fn(&Path, &mut Vec<u8>) + Send + Sync>,
178183
) -> io::Result<Option<NodeId>> {
179184
let path = path.canonicalize()?;
180185

@@ -195,7 +200,7 @@ impl Tree {
195200
continue;
196201
}
197202

198-
let Some(node_id) = self.pack(&child, &file_filter, &data_filter)? else {
203+
let Some(node_id) = self.pack_inner(&child, &file_filter, &data_filter)? else {
199204
continue;
200205
};
201206
let name = entry.file_name().to_string_lossy().to_string();
@@ -279,6 +284,8 @@ impl Tree {
279284
let root = w.write(root)?;
280285
w.finish(root)?;
281286

287+
fs::remove_dir_all(&self.work_dir)?;
288+
282289
Ok(())
283290
}
284291
}
@@ -319,7 +326,6 @@ impl<'a> Writer<'a> {
319326
}
320327
Node::File(file) => {
321328
let result = self.write_node(file.data().unwrap())?;
322-
file.reset(); // Hack to drop the data without having to restructure the recursion
323329

324330
result
325331
}

0 commit comments

Comments
 (0)