Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/revlog/file_io.rs @ 52297:7be39c5110c9
hg-core: add a complete VFS
This will be used from Python in a later change.
More changes are needed in hg-core and rhg to properly clean up the APIs
of the old VFS implementation but it can be done when the dust settles
and we start adding more functionality to the pure Rust VFS.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Mon, 29 Jul 2024 20:47:43 +0200 |
parents | 426696af24d3 |
children | 8d35941689af |
rev | line source |
---|---|
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
1 //! Helpers for revlog file reading and writing. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
3 use std::{ |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
4 cell::RefCell, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
5 fs::File, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
6 io::{Read, Seek, SeekFrom, Write}, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
7 path::{Path, PathBuf}, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
8 sync::{Arc, Mutex}, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
9 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
10 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
11 use crate::{ |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
12 errors::{HgError, IoResultExt}, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
13 vfs::Vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
14 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
15 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
16 /// Wraps accessing arbitrary chunks of data within a file and reusing handles. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
17 /// This is currently useful for accessing a revlog's data file, only reading |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
18 /// the ranges that are currently relevant, like a sort of basic and manual |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
19 /// file-based mmap. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
20 /// |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
21 /// XXX should this just be replaced with `mmap` + `madvise` ranges? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
22 /// The upcoming `UncompressedChunkCache` will make up for most of the slowness |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
23 /// of re-reading the same chunks, so this might not be as useful. Aside from |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
24 /// the major benefit of having less code to take care of, using `mmap` will |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
25 /// allow multiple processes to share the same pages, especially for the |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
26 /// changelog and manifest, which would make a difference in server contexts. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
27 pub struct RandomAccessFile { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
28 /// The current store VFS to pass it to [`FileHandle`] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
29 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
30 /// Filename of the open file, relative to the vfs root |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
31 pub filename: PathBuf, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
32 /// The current read-only handle on the file, if any |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
33 pub reading_handle: RefCell<Option<FileHandle>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
34 /// The current read-write handle on the file, if any |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
35 pub writing_handle: RefCell<Option<FileHandle>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
36 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
37 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
38 impl RandomAccessFile { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
39 /// Wrap a file for random access |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
40 pub fn new(vfs: Box<dyn Vfs>, filename: PathBuf) -> Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
41 assert!(filename.is_relative()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
42 Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
43 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
44 filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
45 reading_handle: RefCell::new(None), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
46 writing_handle: RefCell::new(None), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
47 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
48 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
49 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
50 /// Read a chunk of bytes from the file. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
51 pub fn read_chunk( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
52 &self, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
53 offset: usize, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
54 length: usize, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
55 ) -> Result<Vec<u8>, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
56 let mut handle = self.get_read_handle()?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
57 handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
58 .seek(SeekFrom::Start(offset as u64)) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
59 .when_reading_file(&self.filename)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
60 handle.read_exact(length).when_reading_file(&self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
61 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
62 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
63 /// `pub` only for hg-cpython |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
64 #[doc(hidden)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
65 pub fn get_read_handle(&self) -> Result<FileHandle, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
66 if let Some(handle) = &*self.writing_handle.borrow() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
67 // Use a file handle being actively used for writes, if available. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
68 // There is some danger to doing this because reads will seek the |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
69 // file. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
70 // However, [`Revlog::write_entry`] performs a `SeekFrom::End(0)` |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
71 // before all writes, so we should be safe. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
72 return Ok(handle.clone()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
73 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
74 if let Some(handle) = &*self.reading_handle.borrow() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
75 return Ok(handle.clone()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
76 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
77 // early returns done to work around borrowck being overzealous |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
78 // See https://github.com/rust-lang/rust/issues/103108 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
79 let new_handle = FileHandle::new( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
80 dyn_clone::clone_box(&*self.vfs), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
81 &self.filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
82 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
83 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
84 )?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
85 *self.reading_handle.borrow_mut() = Some(new_handle.clone()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
86 Ok(new_handle) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
87 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
88 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
89 /// `pub` only for hg-cpython |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
90 #[doc(hidden)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
91 pub fn exit_reading_context(&self) { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
92 self.reading_handle.take(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
93 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
94 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
95 // Returns whether this file currently open |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
96 pub fn is_open(&self) -> bool { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
97 self.reading_handle.borrow().is_some() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
98 || self.writing_handle.borrow().is_some() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
99 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
100 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
101 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
102 /// A buffer that holds new changelog index data that needs to be written |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
103 /// after the manifest and filelogs so that the repo is updated atomically to |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
104 /// external processes. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
105 #[derive(Clone, Debug, Default)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
106 pub struct DelayedBuffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
107 // The actual in-memory bytes storing the delayed writes |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
108 pub(super) buffer: Vec<u8>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
109 /// The current offset into the virtual file composed of file + buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
110 offset: u64, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
111 /// The size of the file at the time of opening |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
112 file_size: u64, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
113 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
114 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
115 impl DelayedBuffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
116 /// Returns the length of the full data (on-disk + buffer length). |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
117 pub fn len(&self) -> u64 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
118 self.buffer.len() as u64 + self.file_size |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
119 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
120 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
121 pub fn is_empty(&self) -> bool { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
122 self.len() == 0 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
123 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
124 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
125 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
126 /// Holds an open [`File`] and the related data. This can be used for reading |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
127 /// and writing. Writes can be delayed to a buffer before touching the disk, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
128 /// if relevant (in the changelog case), but reads are transparent. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
129 pub struct FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
130 /// The actual open file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
131 pub file: File, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
132 /// The VFS with which the file was opened |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
133 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
134 /// Filename of the open file, relative to the repo root |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
135 filename: PathBuf, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
136 /// Buffer of delayed entry writes to the changelog index. This points |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
137 /// back to the buffer inside the revlog this handle refers to. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
138 delayed_buffer: Option<Arc<Mutex<DelayedBuffer>>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
139 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
140 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
141 impl std::fmt::Debug for FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
143 f.debug_struct("FileHandle") |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
144 .field("filename", &self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
145 .field("delayed_buffer", &self.delayed_buffer) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
146 .field("file", &self.file) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
147 .finish() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
148 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
149 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
150 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
151 impl Clone for FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
152 fn clone(&self) -> Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
153 Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
154 vfs: dyn_clone::clone_box(&*self.vfs), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
155 filename: self.filename.clone(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
156 delayed_buffer: self.delayed_buffer.clone(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
157 // This can only fail if the OS doesn't have the file handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
158 // anymore, so we're not going to do anything useful anyway. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
159 file: self.file.try_clone().expect("couldn't clone file handle"), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
160 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
161 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
162 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
163 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
164 impl FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
165 /// Get a (read or write) file handle to `filename`. Only creates the file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
166 /// if `create` is `true`. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
167 pub fn new( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
168 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
169 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
170 create: bool, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
171 write: bool, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
172 ) -> Result<Self, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
173 let file = if create { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
174 vfs.create(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
175 } else if write { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
176 vfs.open(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
177 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
178 vfs.open_read(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
179 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
180 Ok(Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
181 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
182 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
183 delayed_buffer: None, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
184 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
185 }) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
186 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
187 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
188 /// Get a file handle to `filename`, but writes go to a [`DelayedBuffer`]. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
189 pub fn new_delayed( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
190 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
191 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
192 create: bool, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
193 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
194 ) -> Result<Self, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
195 let mut file = if create { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
196 vfs.create(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
197 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
198 vfs.open(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
199 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
200 let size = vfs.file_size(&file)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
201 let offset = file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
202 .stream_position() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
203 .when_reading_file(filename.as_ref())?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
204 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
205 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
206 let mut buf = delayed_buffer.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
207 buf.file_size = size; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
208 buf.offset = offset; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
209 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
210 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
211 Ok(Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
212 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
213 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
214 delayed_buffer: Some(delayed_buffer), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
215 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
216 }) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
217 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
218 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
219 /// Wrap an existing [`File`] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
220 pub fn from_file( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
221 file: File, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
222 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
223 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
224 ) -> Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
225 Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
226 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
227 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
228 delayed_buffer: None, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
229 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
230 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
231 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
232 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
233 /// Wrap an existing [`File`], but writes go to a [`DelayedBuffer`]. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
234 pub fn from_file_delayed( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
235 mut file: File, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
236 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
237 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
238 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
239 ) -> Result<Self, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
240 let size = vfs.file_size(&file)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
241 let offset = file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
242 .stream_position() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
243 .when_reading_file(filename.as_ref())?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
244 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
245 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
246 let mut buf = delayed_buffer.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
247 buf.file_size = size; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
248 buf.offset = offset; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
249 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
250 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
251 Ok(Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
252 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
253 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
254 delayed_buffer: Some(delayed_buffer), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
255 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
256 }) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
257 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
258 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
259 /// Move the position of the handle to `pos`, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
260 /// spanning the [`DelayedBuffer`] if defined. Will return an error if |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
261 /// an invalid seek position is asked, or for any standard io error. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
262 pub fn seek(&mut self, pos: SeekFrom) -> Result<u64, std::io::Error> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
263 if let Some(delay_buf) = &self.delayed_buffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
264 let mut delay_buf = delay_buf.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
265 // Virtual file offset spans real file and data |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
266 match pos { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
267 SeekFrom::Start(offset) => delay_buf.offset = offset, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
268 SeekFrom::End(offset) => { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
269 delay_buf.offset = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
270 delay_buf.len().saturating_add_signed(offset) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
271 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
272 SeekFrom::Current(offset) => { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
273 delay_buf.offset = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
274 delay_buf.offset.saturating_add_signed(offset); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
275 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
276 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
277 if delay_buf.offset < delay_buf.file_size { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
278 self.file.seek(pos) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
279 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
280 Ok(delay_buf.offset) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
281 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
282 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
283 self.file.seek(pos) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
284 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
285 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
286 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
287 /// Read exactly `length` bytes from the current position. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
288 /// Errors are the same as [`std::io::Read::read_exact`]. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
289 pub fn read_exact( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
290 &mut self, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
291 length: usize, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
292 ) -> Result<Vec<u8>, std::io::Error> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
293 if let Some(delay_buf) = self.delayed_buffer.as_mut() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
294 let mut delay_buf = delay_buf.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
295 let mut buf = vec![0; length]; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
296 let offset: isize = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
297 delay_buf.offset.try_into().expect("buffer too large"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
298 let file_size: isize = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
299 delay_buf.file_size.try_into().expect("file too large"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
300 let span: isize = offset - file_size; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
301 let length = length.try_into().expect("too large of a length"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
302 let absolute_span: u64 = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
303 span.unsigned_abs().try_into().expect("length too large"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
304 if span < 0 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
305 if length <= absolute_span { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
306 // We're only in the file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
307 self.file.read_exact(&mut buf)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
308 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
309 // We're spanning file and buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
310 self.file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
311 .read_exact(&mut buf[..absolute_span as usize])?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
312 delay_buf |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
313 .buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
314 .take(length - absolute_span) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
315 .read_exact(&mut buf[absolute_span as usize..])?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
316 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
317 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
318 // We're only in the buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
319 delay_buf.buffer[absolute_span as usize..] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
320 .take(length) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
321 .read_exact(&mut buf)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
322 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
323 delay_buf.offset += length; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
324 Ok(buf.to_owned()) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
325 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
326 let mut buf = vec![0; length]; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
327 self.file.read_exact(&mut buf)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
328 Ok(buf) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
329 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
330 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
331 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
332 /// Flush the in-memory changes to disk. This does *not* write the |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
333 /// delayed buffer, only the pending file changes. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
334 pub fn flush(&mut self) -> Result<(), HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
335 self.file.flush().when_writing_file(&self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
336 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
337 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
338 /// Return the current position in the file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
339 pub fn position(&mut self) -> Result<u64, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
340 self.file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
341 .stream_position() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
342 .when_reading_file(&self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
343 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
344 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
345 /// Append `data` to the file, or to the [`DelayedBuffer`], if any. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
346 pub fn write_all(&mut self, data: &[u8]) -> Result<(), HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
347 if let Some(buf) = &mut self.delayed_buffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
348 let mut delayed_buffer = buf.lock().expect("propagate the panic"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
349 assert_eq!(delayed_buffer.offset, delayed_buffer.len()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
350 delayed_buffer.buffer.extend_from_slice(data); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
351 delayed_buffer.offset += data.len() as u64; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
352 Ok(()) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
353 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
354 self.file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
355 .write_all(data) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
356 .when_writing_file(&self.filename)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
357 Ok(()) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
358 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
359 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
360 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
361 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
362 /// Write handles to a given revlog (index + maybe data) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
363 #[derive(Debug)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
364 pub struct WriteHandles { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
365 /// Handle to the index file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
366 pub index_handle: FileHandle, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
367 /// Handle to the data file, if the revlog is non-inline |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
368 pub data_handle: Option<FileHandle>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
369 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
370 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
371 #[cfg(test)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
372 mod tests { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
373 use std::io::ErrorKind; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
374 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
375 use crate::vfs::VfsImpl; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
376 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
377 use super::*; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
378 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
379 #[test] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
380 fn test_random_access_file() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
381 let base = tempfile::tempdir().unwrap().into_path(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
382 let filename = Path::new("a"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
383 let file_path = base.join(filename); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
384 let raf = RandomAccessFile::new( |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
385 Box::new(VfsImpl::new(base.clone(), true)), |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
386 filename.to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
387 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
388 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
389 assert!(!raf.is_open()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
390 assert_eq!(&raf.filename, &filename); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
391 // Should fail to read a non-existing file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
392 match raf.get_read_handle().unwrap_err() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
393 HgError::IoError { error, .. } => match error.kind() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
394 std::io::ErrorKind::NotFound => {} |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
395 _ => panic!("should be not found"), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
396 }, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
397 e => panic!("{}", e.to_string()), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
398 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
399 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
400 std::fs::write(file_path, b"1234567890").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
401 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
402 // Should be able to open an existing file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
403 let mut handle = raf.get_read_handle().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
404 assert!(raf.is_open()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
405 assert_eq!(handle.read_exact(10).unwrap(), b"1234567890".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
406 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
407 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
408 #[test] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
409 fn test_file_handle() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
410 let base = tempfile::tempdir().unwrap().into_path(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
411 let filename = base.join("a"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
412 // No `create` should fail |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
413 FileHandle::new( |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
414 Box::new(VfsImpl::new(base.clone(), false)), |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
415 &filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
416 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
417 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
418 ) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
419 .unwrap_err(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
420 std::fs::write(&filename, b"1234567890").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
421 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
422 let mut read_handle = FileHandle::new( |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
423 Box::new(VfsImpl::new(base.clone(), true)), |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
424 &filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
425 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
426 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
427 ) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
428 .unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
429 assert_eq!(&read_handle.filename, &filename); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
430 assert_eq!(read_handle.position().unwrap(), 0); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
431 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
432 // Writing to an explicit read handle should fail |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
433 read_handle.write_all(b"some data").unwrap_err(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
434 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
435 // reading exactly n bytes should work |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
436 assert_eq!(read_handle.read_exact(3).unwrap(), b"123".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
437 // and the position should be remembered |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
438 assert_eq!(read_handle.read_exact(2).unwrap(), b"45".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
439 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
440 // Seeking should work |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
441 let position = read_handle.position().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
442 read_handle.seek(SeekFrom::Current(-2)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
443 assert_eq!(position - 2, read_handle.position().unwrap()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
444 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
445 // Seeking too much data should fail |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
446 read_handle.read_exact(1000).unwrap_err(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
447 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
448 // Open a write handle |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
449 let mut handle = FileHandle::new( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
450 Box::new(VfsImpl::new(base.clone(), false)), |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
451 &filename, |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
452 false, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
453 true, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
454 ) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
455 .unwrap(); |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
456 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
457 // Now writing should succeed |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
458 handle.write_all(b"new data").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
459 // Opening or writing does not seek, so we should be at the start |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
460 assert_eq!(handle.position().unwrap(), 8); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
461 // We can still read |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
462 assert_eq!(handle.read_exact(2).unwrap(), b"90".to_vec()); |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
463 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
464 let mut read_handle = FileHandle::new( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
465 Box::new(VfsImpl::new(base.clone(), true)), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
466 &filename, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
467 false, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
468 false, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
469 ) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
470 .unwrap(); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
471 read_handle.seek(SeekFrom::Start(0)).unwrap(); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
472 // On-disk file contents should be changed |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
473 assert_eq!( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
474 &read_handle.read_exact(10).unwrap(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
475 &b"new data90".to_vec(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
476 ); |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
477 // Flushing doesn't do anything unexpected |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
478 handle.flush().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
479 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
480 let delayed_buffer = Arc::new(Mutex::new(DelayedBuffer::default())); |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
481 let mut handle = FileHandle::new_delayed( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
482 Box::new(VfsImpl::new(base.clone(), false)), |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
483 &filename, |
52297
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52285
diff
changeset
|
484 false, |
52285
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
485 delayed_buffer, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
486 ) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
487 .unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
488 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
489 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
490 handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
491 .delayed_buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
492 .as_ref() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
493 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
494 .lock() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
495 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
496 .file_size, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
497 10 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
498 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
499 handle.seek(SeekFrom::End(0)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
500 handle.write_all(b"should go to buffer").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
501 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
502 handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
503 .delayed_buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
504 .as_ref() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
505 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
506 .lock() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
507 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
508 .len(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
509 29 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
510 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
511 read_handle.seek(SeekFrom::Start(0)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
512 // On-disk file contents should be unchanged |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
513 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
514 read_handle.read_exact(10).unwrap(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
515 b"new data90".to_vec(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
516 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
517 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
518 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
519 read_handle.read_exact(1).unwrap_err().kind(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
520 ErrorKind::UnexpectedEof |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
521 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
522 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
523 handle.flush().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
524 // On-disk file contents should still be unchanged after a flush |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
525 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
526 read_handle.read_exact(1).unwrap_err().kind(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
527 ErrorKind::UnexpectedEof |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
528 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
529 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
530 // Read from the buffer only |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
531 handle.seek(SeekFrom::End(-1)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
532 assert_eq!(handle.read_exact(1).unwrap(), b"r".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
533 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
534 // Read from an overlapping section of file and buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
535 handle.seek(SeekFrom::Start(6)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
536 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
537 handle.read_exact(20).unwrap(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
538 b"ta90should go to buf".to_vec() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
539 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
540 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
541 // Read from file only |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
542 handle.seek(SeekFrom::Start(0)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
543 assert_eq!(handle.read_exact(8).unwrap(), b"new data".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
544 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
545 } |