rust/hg-core/src/revlog/file_io.rs
author Raphaël Gomès <rgomes@octobus.net>
Thu, 10 Oct 2024 15:54:45 +0200
changeset 52185 8d35941689af
parent 52171 7be39c5110c9
permissions -rw-r--r--
rust-vfs: support checkambig This was missing from the Rust code, which means worse caching. See https://wiki.mercurial-scm.org/ExactCacheValidationPlan. Explanations on what ambiguity means inline.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52159
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
    io::{Read, Seek, SeekFrom, Write},
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
    path::{Path, PathBuf},
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
    sync::{Arc, Mutex},
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
};
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
use crate::{
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    11
    errors::{HgError, IoResultExt},
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
    12
    vfs::{Vfs, VfsFile},
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    13
};
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
/// 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
    16
/// 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
    17
/// 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
    18
/// file-based mmap.
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    19
///
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    20
/// 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
    21
/// 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
    22
/// 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
    23
/// 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
    24
/// 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
    25
/// 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
    26
pub struct RandomAccessFile {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    27
    /// 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
    28
    vfs: Box<dyn Vfs>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    29
    /// 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
    30
    pub filename: PathBuf,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    31
    /// 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
    32
    pub reading_handle: RefCell<Option<FileHandle>>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    33
    /// 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
    34
    pub writing_handle: RefCell<Option<FileHandle>>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    35
}
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
impl RandomAccessFile {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    38
    /// Wrap a file for random access
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    39
    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
    40
        assert!(filename.is_relative());
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    41
        Self {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    42
            vfs,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    43
            filename,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    44
            reading_handle: RefCell::new(None),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    45
            writing_handle: RefCell::new(None),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    46
        }
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
    /// 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
    50
    pub fn read_chunk(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    51
        &self,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    52
        offset: usize,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    53
        length: usize,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    54
    ) -> Result<Vec<u8>, HgError> {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    55
        let mut handle = self.get_read_handle()?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    56
        handle
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    57
            .seek(SeekFrom::Start(offset as u64))
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    58
            .when_reading_file(&self.filename)?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    59
        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
    60
    }
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
    /// `pub` only for hg-cpython
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    63
    #[doc(hidden)]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    64
    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
    65
        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
    66
            // 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
    67
            // 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
    68
            // file.
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    69
            // 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
    70
            // 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
    71
            return Ok(handle.clone());
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    72
        }
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    73
        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
    74
            return Ok(handle.clone());
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    75
        }
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    76
        // 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
    77
        // 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
    78
        let new_handle = FileHandle::new(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    79
            dyn_clone::clone_box(&*self.vfs),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    80
            &self.filename,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    81
            false,
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
        )?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    84
        *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
    85
        Ok(new_handle)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    86
    }
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
    /// `pub` only for hg-cpython
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    89
    #[doc(hidden)]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    90
    pub fn exit_reading_context(&self) {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    91
        self.reading_handle.take();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    92
    }
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
    // Returns whether this file currently open
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    95
    pub fn is_open(&self) -> bool {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    96
        self.reading_handle.borrow().is_some()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    97
            || self.writing_handle.borrow().is_some()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    98
    }
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
/// 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
   102
/// 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
   103
/// external processes.
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   104
#[derive(Clone, Debug, Default)]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   105
pub struct DelayedBuffer {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   106
    // 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
   107
    pub(super) buffer: Vec<u8>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   108
    /// 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
   109
    offset: u64,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   110
    /// 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
   111
    file_size: u64,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   112
}
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
impl DelayedBuffer {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   115
    /// 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
   116
    pub fn len(&self) -> u64 {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   117
        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
   118
    }
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
    pub fn is_empty(&self) -> bool {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   121
        self.len() == 0
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   122
    }
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
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   125
/// Holds an open [`VfsFile`] and the related data. This can be used for
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   126
/// reading and writing. Writes can be delayed to a buffer before touching
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   127
/// the disk, if relevant (in the changelog case), but reads are transparent.
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   128
pub struct FileHandle {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   129
    /// The actual open file
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   130
    pub file: VfsFile,
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   131
    /// 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
   132
    vfs: Box<dyn Vfs>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   133
    /// 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
   134
    filename: PathBuf,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   135
    /// 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
   136
    /// 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
   137
    delayed_buffer: Option<Arc<Mutex<DelayedBuffer>>>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   138
}
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
impl std::fmt::Debug for FileHandle {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   141
    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
   142
        f.debug_struct("FileHandle")
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   143
            .field("filename", &self.filename)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   144
            .field("delayed_buffer", &self.delayed_buffer)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   145
            .field("file", &self.file)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   146
            .finish()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   147
    }
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
impl Clone for FileHandle {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   151
    fn clone(&self) -> Self {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   152
        Self {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   153
            vfs: dyn_clone::clone_box(&*self.vfs),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   154
            filename: self.filename.clone(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   155
            delayed_buffer: self.delayed_buffer.clone(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   156
            // 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
   157
            // 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
   158
            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
   159
        }
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
impl FileHandle {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   164
    /// 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
   165
    /// if `create` is `true`.
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   166
    pub fn new(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   167
        vfs: Box<dyn Vfs>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   168
        filename: impl AsRef<Path>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   169
        create: bool,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   170
        write: bool,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   171
    ) -> Result<Self, HgError> {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   172
        let file = if create {
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   173
            vfs.create(filename.as_ref(), false)?
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   174
        } else if write {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   175
            vfs.open(filename.as_ref())?
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   176
        } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   177
            vfs.open_read(filename.as_ref())?
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   178
        };
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   179
        Ok(Self {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   180
            vfs,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   181
            filename: filename.as_ref().to_owned(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   182
            delayed_buffer: None,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   183
            file,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   184
        })
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
    /// 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
   188
    pub fn new_delayed(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   189
        vfs: Box<dyn Vfs>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   190
        filename: impl AsRef<Path>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   191
        create: bool,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   192
        delayed_buffer: Arc<Mutex<DelayedBuffer>>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   193
    ) -> Result<Self, HgError> {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   194
        let mut file = if create {
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   195
            vfs.create(filename.as_ref(), false)?
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   196
        } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   197
            vfs.open(filename.as_ref())?
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   198
        };
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   199
        let size = vfs.file_size(&file)?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   200
        let offset = file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   201
            .stream_position()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   202
            .when_reading_file(filename.as_ref())?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   203
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
            let mut buf = delayed_buffer.lock().unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   206
            buf.file_size = size;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   207
            buf.offset = offset;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   208
        }
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
        Ok(Self {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   211
            vfs,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   212
            filename: filename.as_ref().to_owned(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   213
            delayed_buffer: Some(delayed_buffer),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   214
            file,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   215
        })
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
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   218
    /// Wrap an existing [`VfsFile`]
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   219
    pub fn from_file(
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   220
        file: VfsFile,
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   221
        vfs: Box<dyn Vfs>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   222
        filename: impl AsRef<Path>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   223
    ) -> Self {
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
            vfs,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   226
            filename: filename.as_ref().to_owned(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   227
            delayed_buffer: None,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   228
            file,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   229
        }
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
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   232
    /// Wrap an existing [`VfsFile`], but writes go to a [`DelayedBuffer`].
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   233
    pub fn from_file_delayed(
52185
8d35941689af rust-vfs: support checkambig
Raphaël Gomès <rgomes@octobus.net>
parents: 52171
diff changeset
   234
        mut file: VfsFile,
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   235
        vfs: Box<dyn Vfs>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   236
        filename: impl AsRef<Path>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   237
        delayed_buffer: Arc<Mutex<DelayedBuffer>>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   238
    ) -> Result<Self, HgError> {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   239
        let size = vfs.file_size(&file)?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   240
        let offset = file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   241
            .stream_position()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   242
            .when_reading_file(filename.as_ref())?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   243
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
            let mut buf = delayed_buffer.lock().unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   246
            buf.file_size = size;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   247
            buf.offset = offset;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   248
        }
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
        Ok(Self {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   251
            vfs,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   252
            filename: filename.as_ref().to_owned(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   253
            delayed_buffer: Some(delayed_buffer),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   254
            file,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   255
        })
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
    /// 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
   259
    /// 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
   260
    /// 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
   261
    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
   262
        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
   263
            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
   264
            // 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
   265
            match pos {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   266
                SeekFrom::Start(offset) => delay_buf.offset = offset,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   267
                SeekFrom::End(offset) => {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   268
                    delay_buf.offset =
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   269
                        delay_buf.len().saturating_add_signed(offset)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   270
                }
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   271
                SeekFrom::Current(offset) => {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   272
                    delay_buf.offset =
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   273
                        delay_buf.offset.saturating_add_signed(offset);
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   274
                }
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
            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
   277
                self.file.seek(pos)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   278
            } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   279
                Ok(delay_buf.offset)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   280
            }
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   281
        } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   282
            self.file.seek(pos)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   283
        }
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
    /// 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
   287
    /// 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
   288
    pub fn read_exact(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   289
        &mut self,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   290
        length: usize,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   291
    ) -> Result<Vec<u8>, std::io::Error> {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   292
        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
   293
            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
   294
            let mut buf = vec![0; length];
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   295
            let offset: isize =
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   296
                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
   297
            let file_size: isize =
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   298
                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
   299
            let span: isize = offset - file_size;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   300
            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
   301
            let absolute_span: u64 =
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   302
                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
   303
            if span < 0 {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   304
                if length <= absolute_span {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   305
                    // We're only in the file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   306
                    self.file.read_exact(&mut buf)?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   307
                } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   308
                    // We're spanning file and buffer
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   309
                    self.file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   310
                        .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
   311
                    delay_buf
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   312
                        .buffer
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   313
                        .take(length - absolute_span)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   314
                        .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
   315
                }
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   316
            } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   317
                // We're only in the buffer
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   318
                delay_buf.buffer[absolute_span as usize..]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   319
                    .take(length)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   320
                    .read_exact(&mut buf)?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   321
            }
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   322
            delay_buf.offset += length;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   323
            Ok(buf.to_owned())
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   324
        } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   325
            let mut buf = vec![0; length];
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   326
            self.file.read_exact(&mut buf)?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   327
            Ok(buf)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   328
        }
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
    /// 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
   332
    /// delayed buffer, only the pending file changes.
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   333
    pub fn flush(&mut self) -> Result<(), HgError> {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   334
        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
   335
    }
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
    /// Return the current position in the file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   338
    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
   339
        self.file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   340
            .stream_position()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   341
            .when_reading_file(&self.filename)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   342
    }
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
    /// 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
   345
    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
   346
        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
   347
            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
   348
            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
   349
            delayed_buffer.buffer.extend_from_slice(data);
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   350
            delayed_buffer.offset += data.len() as u64;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   351
            Ok(())
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   352
        } else {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   353
            self.file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   354
                .write_all(data)
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   355
                .when_writing_file(&self.filename)?;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   356
            Ok(())
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   357
        }
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
/// 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
   362
#[derive(Debug)]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   363
pub struct WriteHandles {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   364
    /// Handle to the index file
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   365
    pub index_handle: FileHandle,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   366
    /// 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
   367
    pub data_handle: Option<FileHandle>,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   368
}
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
#[cfg(test)]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   371
mod tests {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   372
    use std::io::ErrorKind;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   373
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   374
    use crate::vfs::VfsImpl;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   375
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   376
    use super::*;
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   377
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   378
    #[test]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   379
    fn test_random_access_file() {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   380
        let base = tempfile::tempdir().unwrap().into_path();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   381
        let filename = Path::new("a");
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   382
        let file_path = base.join(filename);
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   383
        let raf = RandomAccessFile::new(
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   384
            Box::new(VfsImpl::new(base.clone(), true)),
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   385
            filename.to_owned(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   386
        );
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
        assert!(!raf.is_open());
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   389
        assert_eq!(&raf.filename, &filename);
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   390
        // 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
   391
        match raf.get_read_handle().unwrap_err() {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   392
            HgError::IoError { error, .. } => match error.kind() {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   393
                std::io::ErrorKind::NotFound => {}
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   394
                _ => panic!("should be not found"),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   395
            },
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   396
            e => panic!("{}", e.to_string()),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   397
        }
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
        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
   400
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   401
        // 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
   402
        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
   403
        assert!(raf.is_open());
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   404
        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
   405
    }
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
    #[test]
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   408
    fn test_file_handle() {
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   409
        let base = tempfile::tempdir().unwrap().into_path();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   410
        let filename = base.join("a");
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   411
        // No `create` should fail
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   412
        FileHandle::new(
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   413
            Box::new(VfsImpl::new(base.clone(), false)),
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   414
            &filename,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   415
            false,
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
        )
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   418
        .unwrap_err();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   419
        std::fs::write(&filename, b"1234567890").unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   420
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   421
        let mut read_handle = FileHandle::new(
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   422
            Box::new(VfsImpl::new(base.clone(), true)),
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   423
            &filename,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   424
            false,
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
        )
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   427
        .unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   428
        assert_eq!(&read_handle.filename, &filename);
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   429
        assert_eq!(read_handle.position().unwrap(), 0);
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   430
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   431
        // 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
   432
        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
   433
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   434
        // reading exactly n bytes should work
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   435
        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
   436
        // and the position should be remembered
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   437
        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
   438
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   439
        // Seeking should work
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   440
        let position = read_handle.position().unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   441
        read_handle.seek(SeekFrom::Current(-2)).unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   442
        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
   443
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   444
        // Seeking too much data should fail
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   445
        read_handle.read_exact(1000).unwrap_err();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   446
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   447
        // Open a write handle
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   448
        let mut handle = FileHandle::new(
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   449
            Box::new(VfsImpl::new(base.clone(), false)),
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   450
            &filename,
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   451
            false,
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   452
            true,
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   453
        )
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   454
        .unwrap();
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   455
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   456
        // Now writing should succeed
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   457
        handle.write_all(b"new data").unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   458
        // 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
   459
        assert_eq!(handle.position().unwrap(), 8);
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   460
        // We can still read
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   461
        assert_eq!(handle.read_exact(2).unwrap(), b"90".to_vec());
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   462
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   463
        let mut read_handle = FileHandle::new(
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   464
            Box::new(VfsImpl::new(base.clone(), true)),
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   465
            &filename,
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   466
            false,
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   467
            false,
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   468
        )
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   469
        .unwrap();
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   470
        read_handle.seek(SeekFrom::Start(0)).unwrap();
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   471
        // On-disk file contents should be changed
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   472
        assert_eq!(
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   473
            &read_handle.read_exact(10).unwrap(),
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   474
            &b"new data90".to_vec(),
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   475
        );
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   476
        // Flushing doesn't do anything unexpected
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   477
        handle.flush().unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   478
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   479
        let delayed_buffer = Arc::new(Mutex::new(DelayedBuffer::default()));
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   480
        let mut handle = FileHandle::new_delayed(
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   481
            Box::new(VfsImpl::new(base.clone(), false)),
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   482
            &filename,
52171
7be39c5110c9 hg-core: add a complete VFS
Raphaël Gomès <rgomes@octobus.net>
parents: 52159
diff changeset
   483
            false,
52159
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   484
            delayed_buffer,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   485
        )
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   486
        .unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   487
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   488
        assert_eq!(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   489
            handle
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   490
                .delayed_buffer
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   491
                .as_ref()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   492
                .unwrap()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   493
                .lock()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   494
                .unwrap()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   495
                .file_size,
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   496
            10
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   497
        );
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   498
        handle.seek(SeekFrom::End(0)).unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   499
        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
   500
        assert_eq!(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   501
            handle
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   502
                .delayed_buffer
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   503
                .as_ref()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   504
                .unwrap()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   505
                .lock()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   506
                .unwrap()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   507
                .len(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   508
            29
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   509
        );
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   510
        read_handle.seek(SeekFrom::Start(0)).unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   511
        // On-disk file contents should be unchanged
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   512
        assert_eq!(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   513
            read_handle.read_exact(10).unwrap(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   514
            b"new data90".to_vec(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   515
        );
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
        assert_eq!(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   518
            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
   519
            ErrorKind::UnexpectedEof
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   520
        );
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
        handle.flush().unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   523
        // 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
   524
        assert_eq!(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   525
            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
   526
            ErrorKind::UnexpectedEof
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   527
        );
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
        // Read from the buffer only
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   530
        handle.seek(SeekFrom::End(-1)).unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   531
        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
   532
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   533
        // 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
   534
        handle.seek(SeekFrom::Start(6)).unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   535
        assert_eq!(
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   536
            handle.read_exact(20).unwrap(),
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   537
            b"ta90should go to buf".to_vec()
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   538
        );
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
        // Read from file only
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   541
        handle.seek(SeekFrom::Start(0)).unwrap();
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   542
        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
   543
    }
426696af24d3 rust-revlog: add file IO helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   544
}