equal
deleted
inserted
replaced
1 //! Helpers for revlog file reading and writing. |
1 //! Helpers for revlog file reading and writing. |
2 |
2 |
3 use std::{ |
3 use std::{ |
4 cell::RefCell, |
4 cell::RefCell, |
5 fs::File, |
|
6 io::{Read, Seek, SeekFrom, Write}, |
5 io::{Read, Seek, SeekFrom, Write}, |
7 path::{Path, PathBuf}, |
6 path::{Path, PathBuf}, |
8 sync::{Arc, Mutex}, |
7 sync::{Arc, Mutex}, |
9 }; |
8 }; |
10 |
9 |
11 use crate::{ |
10 use crate::{ |
12 errors::{HgError, IoResultExt}, |
11 errors::{HgError, IoResultExt}, |
13 vfs::Vfs, |
12 vfs::{Vfs, VfsFile}, |
14 }; |
13 }; |
15 |
14 |
16 /// Wraps accessing arbitrary chunks of data within a file and reusing handles. |
15 /// Wraps accessing arbitrary chunks of data within a file and reusing handles. |
17 /// This is currently useful for accessing a revlog's data file, only reading |
16 /// This is currently useful for accessing a revlog's data file, only reading |
18 /// the ranges that are currently relevant, like a sort of basic and manual |
17 /// the ranges that are currently relevant, like a sort of basic and manual |
121 pub fn is_empty(&self) -> bool { |
120 pub fn is_empty(&self) -> bool { |
122 self.len() == 0 |
121 self.len() == 0 |
123 } |
122 } |
124 } |
123 } |
125 |
124 |
126 /// Holds an open [`File`] and the related data. This can be used for reading |
125 /// Holds an open [`VfsFile`] and the related data. This can be used for |
127 /// and writing. Writes can be delayed to a buffer before touching the disk, |
126 /// reading and writing. Writes can be delayed to a buffer before touching |
128 /// if relevant (in the changelog case), but reads are transparent. |
127 /// the disk, if relevant (in the changelog case), but reads are transparent. |
129 pub struct FileHandle { |
128 pub struct FileHandle { |
130 /// The actual open file |
129 /// The actual open file |
131 pub file: File, |
130 pub file: VfsFile, |
132 /// The VFS with which the file was opened |
131 /// The VFS with which the file was opened |
133 vfs: Box<dyn Vfs>, |
132 vfs: Box<dyn Vfs>, |
134 /// Filename of the open file, relative to the repo root |
133 /// Filename of the open file, relative to the repo root |
135 filename: PathBuf, |
134 filename: PathBuf, |
136 /// Buffer of delayed entry writes to the changelog index. This points |
135 /// Buffer of delayed entry writes to the changelog index. This points |
169 filename: impl AsRef<Path>, |
168 filename: impl AsRef<Path>, |
170 create: bool, |
169 create: bool, |
171 write: bool, |
170 write: bool, |
172 ) -> Result<Self, HgError> { |
171 ) -> Result<Self, HgError> { |
173 let file = if create { |
172 let file = if create { |
174 vfs.create(filename.as_ref())? |
173 vfs.create(filename.as_ref(), false)? |
175 } else if write { |
174 } else if write { |
176 vfs.open(filename.as_ref())? |
175 vfs.open(filename.as_ref())? |
177 } else { |
176 } else { |
178 vfs.open_read(filename.as_ref())? |
177 vfs.open_read(filename.as_ref())? |
179 }; |
178 }; |
191 filename: impl AsRef<Path>, |
190 filename: impl AsRef<Path>, |
192 create: bool, |
191 create: bool, |
193 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
192 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
194 ) -> Result<Self, HgError> { |
193 ) -> Result<Self, HgError> { |
195 let mut file = if create { |
194 let mut file = if create { |
196 vfs.create(filename.as_ref())? |
195 vfs.create(filename.as_ref(), false)? |
197 } else { |
196 } else { |
198 vfs.open(filename.as_ref())? |
197 vfs.open(filename.as_ref())? |
199 }; |
198 }; |
200 let size = vfs.file_size(&file)?; |
199 let size = vfs.file_size(&file)?; |
201 let offset = file |
200 let offset = file |
214 delayed_buffer: Some(delayed_buffer), |
213 delayed_buffer: Some(delayed_buffer), |
215 file, |
214 file, |
216 }) |
215 }) |
217 } |
216 } |
218 |
217 |
219 /// Wrap an existing [`File`] |
218 /// Wrap an existing [`VfsFile`] |
220 pub fn from_file( |
219 pub fn from_file( |
221 file: File, |
220 file: VfsFile, |
222 vfs: Box<dyn Vfs>, |
221 vfs: Box<dyn Vfs>, |
223 filename: impl AsRef<Path>, |
222 filename: impl AsRef<Path>, |
224 ) -> Self { |
223 ) -> Self { |
225 Self { |
224 Self { |
226 vfs, |
225 vfs, |
228 delayed_buffer: None, |
227 delayed_buffer: None, |
229 file, |
228 file, |
230 } |
229 } |
231 } |
230 } |
232 |
231 |
233 /// Wrap an existing [`File`], but writes go to a [`DelayedBuffer`]. |
232 /// Wrap an existing [`VfsFile`], but writes go to a [`DelayedBuffer`]. |
234 pub fn from_file_delayed( |
233 pub fn from_file_delayed( |
235 mut file: File, |
234 mut file: VfsFile, |
236 vfs: Box<dyn Vfs>, |
235 vfs: Box<dyn Vfs>, |
237 filename: impl AsRef<Path>, |
236 filename: impl AsRef<Path>, |
238 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
237 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
239 ) -> Result<Self, HgError> { |
238 ) -> Result<Self, HgError> { |
240 let size = vfs.file_size(&file)?; |
239 let size = vfs.file_size(&file)?; |