Skip to content

Commit

Permalink
fix: OpenFile::read_at no longer errors on invalid offset or length (#…
Browse files Browse the repository at this point in the history
…331)

This is needed if weired access to the `OpenFile` is made. This is e.g.
the case for the `mount` command.

Also the docu of the affected methods has been clarified.

---------

Co-authored-by: simonsan <[email protected]>
  • Loading branch information
aawsome and simonsan authored Oct 14, 2024
1 parent b32b773 commit c9c4285
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 5 deletions.
6 changes: 6 additions & 0 deletions crates/core/src/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,12 @@ impl<P, S: IndexedFull> Repository<P, S> {
/// * `offset` - The offset to start reading
/// * `length` - The length to read
///
/// # Returns
///
/// The read bytes from the given offset and length.
/// If offset is behind the end of the file, an empty `Bytes` is returned.
/// If length is too large, the result up to the end of the file is returned.
///
/// # Errors
///
// TODO: Document errors
Expand Down
8 changes: 5 additions & 3 deletions crates/core/src/vfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,15 +476,17 @@ impl OpenFile {
///
/// * `repo` - The repository to read the `OpenFile` from
/// * `offset` - The offset to read the `OpenFile` from
/// * `length` - The length until to read the `OpenFile`
/// * `length` - The length of the content to read from the `OpenFile`
///
/// # Errors
///
// TODO: Document errors
///
/// # Returns
///
/// The read bytes from the given offset and length
/// The read bytes from the given offset and length.
/// If offset is behind the end of the file, an empty `Bytes` is returned.
/// If length is too large, the result up to the end of the file is returned.
pub fn read_at<P, S: IndexedFull>(
&self,
repo: &Repository<P, S>,
Expand All @@ -497,7 +499,7 @@ impl OpenFile {
offset -= self.content[i].starts_at;
let mut result = BytesMut::with_capacity(length);

while length > 0 && i < self.content.len() {
while length > 0 && i < self.content.len() - 1 {
let data = repo.get_blob_cached(&BlobId::from(*self.content[i].id), BlobType::Data)?;
if offset > data.len() {
// we cannot read behind the blob. This only happens if offset is too large to fit in the last blob
Expand Down
19 changes: 17 additions & 2 deletions crates/core/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
//! The fixtures are passed as arguments to the test functions.

use anyhow::Result;
use bytes::Bytes;
use flate2::read::GzDecoder;
use globset::Glob;
use insta::{
Expand Down Expand Up @@ -414,7 +415,7 @@ fn test_backup_stdin_command(
}

#[rstest]
fn test_ls(
fn test_ls_and_read(
tar_gz_testdata: Result<TestSource>,
set_up_repo: Result<RepoOpen>,
insta_node_redaction: Settings,
Expand Down Expand Up @@ -444,8 +445,22 @@ fn test_ls(
.collect::<RusticResult<_>>()?;

insta_node_redaction.bind(|| {
assert_with_win("ls", entries);
assert_with_win("ls", &entries);
});

// test reading a file from the repository
let repo = repo.to_indexed()?;
let path: PathBuf = ["test", "0", "tests", "testfile"].iter().collect();
let node = entries.get(&path).unwrap();
let file = repo.open_file(node)?;

let data = repo.read_file_at(&file, 0, 21)?; // read full content
assert_eq!(Bytes::from("This is a test file.\n"), &data);
let data2 = repo.read_file_at(&file, 0, 4096)?; // read beyond file end
assert_eq!(data2, &data);
assert_eq!(Bytes::new(), repo.read_file_at(&file, 25, 1)?); // offset beyond file end
assert_eq!(Bytes::from("test"), repo.read_file_at(&file, 10, 4)?); // read partial content

Ok(())
}

Expand Down

0 comments on commit c9c4285

Please sign in to comment.