feat: combine magic plugins into single magic_file plugin

Co-authored-by: aider (openai/andrew/openrouter/anthropic/claude-sonnet-4) <aider@aider.chat>
This commit is contained in:
Andrew Phillips
2025-08-17 17:36:46 -03:00
parent 51453db3c3
commit 133538881f
2 changed files with 85 additions and 46 deletions

View File

@@ -2,54 +2,30 @@ use anyhow::Result;
use magic::{Cookie, CookieFlags};
use std::io;
use std::io::Write;
use rusqlite::Connection;
use crate::meta_plugin::MetaPlugin;
#[derive(Debug, Clone)]
pub struct MagicMetaPlugin {
pub struct MagicFileMetaPlugin {
buffer: Vec<u8>,
meta_name: String,
cookie_flags: CookieFlags,
is_saved: bool,
item_id: Option<i64>,
conn: Option<*mut Connection>,
}
impl MagicMetaPlugin {
pub fn new_file_type() -> MagicMetaPlugin {
MagicMetaPlugin {
impl MagicFileMetaPlugin {
pub fn new() -> MagicFileMetaPlugin {
MagicFileMetaPlugin {
buffer: Vec::new(),
meta_name: "magic_file_type".to_string(),
cookie_flags: CookieFlags::empty(),
is_saved: false,
item_id: None,
conn: None,
}
}
pub fn new_mime_type() -> MagicMetaPlugin {
MagicMetaPlugin {
buffer: Vec::new(),
meta_name: "magic_mime_type".to_string(),
cookie_flags: CookieFlags::MIME_TYPE,
}
}
pub fn new_mime_encoding() -> MagicMetaPlugin {
MagicMetaPlugin {
buffer: Vec::new(),
meta_name: "magic_mime_encoding".to_string(),
cookie_flags: CookieFlags::MIME_ENCODING,
}
}
}
impl MetaPlugin for MagicMetaPlugin {
fn is_internal(&self) -> bool {
true
}
fn create(&self) -> Result<Box<dyn Write>> {
// For meta plugins, we don't actually create a writer since we're buffering data internally
Ok(Box::new(DummyWriter))
}
fn finalize(&mut self) -> io::Result<String> {
let cookie = Cookie::open(self.cookie_flags)
fn get_magic_result(&self, flags: CookieFlags) -> io::Result<String> {
let cookie = Cookie::open(flags)
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Failed to open magic cookie: {}", e)))?;
cookie.load(&[] as &[&str])
@@ -64,7 +40,7 @@ impl MetaPlugin for MagicMetaPlugin {
// For some magic results, we might want just the first part before semicolon or comma
let cleaned = if trimmed.contains(';') {
trimmed.split(';').next().unwrap_or(trimmed).trim()
} else if trimmed.contains(',') && self.meta_name.contains("mime") {
} else if trimmed.contains(',') && flags.contains(CookieFlags::MIME_TYPE | CookieFlags::MIME_ENCODING) {
trimmed.split(',').next().unwrap_or(trimmed).trim()
} else {
trimmed
@@ -73,12 +49,79 @@ impl MetaPlugin for MagicMetaPlugin {
Ok(cleaned.to_string())
}
fn save_all_magic_metadata(&mut self) -> Result<()> {
if let (Some(conn), Some(item_id)) = (self.conn, self.item_id) {
let conn = unsafe { &*conn };
// Save file type
if let Ok(file_type) = self.get_magic_result(CookieFlags::empty()) {
let meta = crate::db::Meta {
id: item_id,
name: "magic_file_type".to_string(),
value: file_type,
};
crate::db::store_meta(conn, meta)?;
}
// Save MIME type
if let Ok(mime_type) = self.get_magic_result(CookieFlags::MIME_TYPE) {
let meta = crate::db::Meta {
id: item_id,
name: "magic_mime_type".to_string(),
value: mime_type,
};
crate::db::store_meta(conn, meta)?;
}
// Save MIME encoding
if let Ok(mime_encoding) = self.get_magic_result(CookieFlags::MIME_ENCODING) {
let meta = crate::db::Meta {
id: item_id,
name: "magic_mime_encoding".to_string(),
value: mime_encoding,
};
crate::db::store_meta(conn, meta)?;
}
self.is_saved = true;
}
Ok(())
}
}
impl MetaPlugin for MagicFileMetaPlugin {
fn is_internal(&self) -> bool {
true
}
fn create(&self) -> Result<Box<dyn Write>> {
// For meta plugins, we don't actually create a writer since we're buffering data internally
Ok(Box::new(DummyWriter))
}
fn initialize(&mut self, conn: &Connection, item_id: i64) -> Result<()> {
self.item_id = Some(item_id);
self.conn = Some(conn as *const Connection as *mut Connection);
Ok(())
}
fn finalize(&mut self) -> io::Result<String> {
// Save all magic metadata if not already saved
if !self.is_saved {
if let Err(e) = self.save_all_magic_metadata() {
return Err(io::Error::new(io::ErrorKind::Other, format!("Failed to save magic metadata: {}", e)));
}
}
// Return empty string since we save during finalize
Ok("".to_string())
}
fn update(&mut self, data: &[u8]) {
self.buffer.extend_from_slice(data);
}
fn meta_name(&mut self) -> String {
self.meta_name.clone()
"magic_file".to_string()
}
}