codebase-graph 1.5.1

Native codebaseGraph CLI and MCP server for local code knowledge graphs.
use std::io::{self, Write};
use std::path::Path;

pub(super) fn write_csv_field(writer: &mut dyn Write, value: &str) -> io::Result<()> {
    if !value
        .bytes()
        .any(|byte| matches!(byte, b',' | b'"' | b'\n' | b'\r'))
    {
        return writer.write_all(value.as_bytes());
    }
    writer.write_all(b"\"")?;
    let mut start = 0;
    for (index, byte) in value.bytes().enumerate() {
        if byte != b'"' {
            continue;
        }
        writer.write_all(&value.as_bytes()[start..index])?;
        writer.write_all(b"\"\"")?;
        start = index + 1;
    }
    writer.write_all(&value.as_bytes()[start..])?;
    writer.write_all(b"\"")
}

pub(super) fn stage_file_stem(name: &str) -> String {
    let stem = name
        .chars()
        .map(|character| {
            if character.is_ascii_alphanumeric() {
                character.to_ascii_lowercase()
            } else {
                '_'
            }
        })
        .collect::<String>()
        .trim_matches('_')
        .to_string();
    if stem.is_empty() {
        "table".to_string()
    } else {
        stem
    }
}

pub(super) fn copy_path(path: &Path) -> String {
    let mut copy_path = path.to_string_lossy().replace('\\', "/");
    if let Some(stripped) = copy_path.strip_prefix("//?/UNC/") {
        copy_path = format!("//{stripped}");
    } else if let Some(stripped) = copy_path.strip_prefix("//?/") {
        copy_path = stripped.to_string();
    }
    copy_path.replace('"', "\\\"")
}