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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }