You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ripgrep-all/src/adapters/tar.rs

133 lines
3.8 KiB
Rust

use crate::{
adapted_iter::AdaptedFilesIterBox,
adapters::AdapterMeta,
matching::{FastFileMatcher, FileMatcher},
print_bytes,
};
use anyhow::*;
use async_stream::stream;
use async_trait::async_trait;
use lazy_static::lazy_static;
use log::*;
use std::path::PathBuf;
use tokio_stream::StreamExt;
use super::{AdaptInfo, FileAdapter, GetMetadata};
static EXTENSIONS: &[&str] = &["tar"];
lazy_static! {
static ref METADATA: AdapterMeta = AdapterMeta {
name: "tar".to_owned(),
version: 1,
description: "Reads a tar file as a stream and recurses down into its contents".to_owned(),
recurses: true,
fast_matchers: EXTENSIONS
.iter()
.map(|s| FastFileMatcher::FileExtension(s.to_string()))
.collect(),
slow_matchers: None,
keep_fast_matchers_if_accurate: true,
disabled_by_default: false
};
}
#[derive(Default, Clone)]
pub struct TarAdapter;
impl TarAdapter {
pub fn new() -> TarAdapter {
TarAdapter
}
}
impl GetMetadata for TarAdapter {
fn metadata(&self) -> &AdapterMeta {
&METADATA
}
}
#[async_trait]
impl FileAdapter for TarAdapter {
async fn adapt(
&self,
ai: AdaptInfo,
_detection_reason: &FileMatcher,
) -> Result<AdaptedFilesIterBox> {
let AdaptInfo {
filepath_hint,
inp,
line_prefix,
archive_recursion_depth,
config,
postprocess,
..
} = ai;
let mut archive = ::tokio_tar::Archive::new(inp);
let mut entries = archive.entries()?;
let s = stream! {
while let Some(entry) = entries.next().await {
let file = entry?;
if tokio_tar::EntryType::Regular == file.header().entry_type() {
let path = PathBuf::from(file.path()?.to_owned());
debug!(
"{}|{}: {}",
filepath_hint.display(),
path.display(),
print_bytes(file.header().size().unwrap_or(0) as f64),
);
let line_prefix = &format!("{}{}: ", line_prefix, path.display());
let ai2: AdaptInfo = AdaptInfo {
filepath_hint: path,
is_real_file: false,
archive_recursion_depth: archive_recursion_depth + 1,
inp: Box::pin(file),
line_prefix: line_prefix.to_string(),
config: config.clone(),
postprocess,
};
yield Ok(ai2);
}
}
};
Ok(Box::pin(s))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{preproc::loop_adapt, test_utils::*};
use pretty_assertions::assert_eq;
use tokio::fs::File;
#[tokio::test]
async fn test_simple_tar() -> Result<()> {
let filepath = test_data_dir().join("hello.tar");
let (a, d) = simple_adapt_info(&filepath, Box::pin(File::open(&filepath).await?));
let adapter = TarAdapter::new();
let r = loop_adapt(&adapter, d, a).await.context("adapt")?;
let o = adapted_to_vec(r).await.context("adapted_to_vec")?;
assert_eq!(
String::from_utf8(o).context("parsing utf8")?,
"PREFIX:dir/file-b.pdf: Page 1: hello world
PREFIX:dir/file-b.pdf: Page 1: this is just a test.
PREFIX:dir/file-b.pdf: Page 1:
PREFIX:dir/file-b.pdf: Page 1: 1
PREFIX:dir/file-b.pdf: Page 1:
PREFIX:dir/file-b.pdf: Page 1:
PREFIX:dir/file-a.pdf: Page 1: hello world
PREFIX:dir/file-a.pdf: Page 1: this is just a test.
PREFIX:dir/file-a.pdf: Page 1:
PREFIX:dir/file-a.pdf: Page 1: 1
PREFIX:dir/file-a.pdf: Page 1:
PREFIX:dir/file-a.pdf: Page 1:
"
);
Ok(())
}
}