use unilang::{ ErrorData, ErrorCode };
use claude_storage_core::Storage;
pub( super ) fn create_storage() -> core::result::Result< Storage, ErrorData >
{
match std::env::var( "CLAUDE_STORAGE_ROOT" )
{
Ok( root ) if !root.is_empty() =>
Ok( Storage::with_root( std::path::Path::new( &root ) ) ),
_ =>
Storage::new()
.map_err( | e | ErrorData::new( ErrorCode::InternalError, format!( "Failed to create storage: {e}" ) ) ),
}
}
pub( super ) fn resolve_path_parameter( param : &str ) -> core::result::Result< String, String >
{
use std::path::Path;
match param
{
"." =>
{
std::env::current_dir()
.map( | p | p.to_string_lossy().to_string() )
.map_err( | e | format!( "Failed to get current directory: {e}" ) )
},
".." =>
{
let current = std::env::current_dir()
.map_err( | e | format!( "Failed to get current directory: {e}" ) )?;
let parent = current.parent()
.ok_or_else( || "Current directory has no parent".to_string() )?;
Ok( parent.to_string_lossy().to_string() )
},
s if s.starts_with( '~' ) =>
{
let home = std::env::var( "HOME" )
.map_err( | e | format!( "Failed to get HOME directory: {e}" ) )?;
if s.len() == 1
{
Ok( home )
}
else if let Some( stripped ) = s.strip_prefix( "~/" )
{
let path = Path::new( &home ).join( stripped );
Ok( path.to_string_lossy().to_string() )
}
else
{
Ok( s.to_string() )
}
},
s if s.starts_with( '/' ) =>
{
Ok( s.to_string() )
},
s if s.contains( '/' ) =>
{
let current = std::env::current_dir()
.map_err( | e | format!( "Failed to get current directory: {e}" ) )?;
let resolved = current.join( s );
Ok( resolved.to_string_lossy().to_string() )
},
s =>
{
Ok( s.to_string() )
},
}
}
#[ inline ]
pub fn parse_project_parameter( input : &str )
-> core::result::Result< claude_storage_core::ProjectId, String >
{
use claude_storage_core::{ ProjectId, decode_path };
use std::path::PathBuf;
if let Some( path_str ) = input.strip_prefix( "Path(\"" ).and_then( | s | s.strip_suffix( "\")" ) )
{
return Ok( ProjectId::path( path_str ) );
}
let path = PathBuf::from( input );
if path.is_absolute()
{
return Ok( ProjectId::path( input ) );
}
if input.starts_with( '-' )
{
match decode_path( input )
{
Ok( decoded ) => return Ok( ProjectId::path( decoded ) ),
Err( e ) => return Err( format!( "Failed to decode path: {e}" ) ),
}
}
if input == "~" || input.starts_with( "~/" )
{
let home = std::env::var( "HOME" )
.map_err( | _ | "HOME environment variable not set".to_string() )?;
let expanded = if input == "~"
{
home
}
else
{
format!( "{}{}", home, &input[ 1.. ] )
};
return Ok( ProjectId::path( expanded ) );
}
if input == "." || input == ".." ||
input.starts_with( "./" ) || input.starts_with( "../" )
{
let cwd = std::env::current_dir()
.map_err( | e | format!( "Failed to get current directory: {e}" ) )?;
let path = cwd.join( input );
if input == "." || input == ".."
{
match path.canonicalize()
{
Ok( abs_path ) => return Ok( ProjectId::path( abs_path.to_string_lossy().to_string() ) ),
Err( e ) => return Err( format!( "Failed to resolve path '{input}': {e}" ) ),
}
}
use std::path::Component;
let mut normalized = PathBuf::new();
for component in path.components()
{
match component
{
Component::ParentDir =>
{
normalized.pop();
}
Component::CurDir =>
{
}
_ => normalized.push( component ),
}
}
return Ok( ProjectId::path( normalized.to_string_lossy().to_string() ) );
}
Ok( ProjectId::uuid( input ) )
}
pub( super ) fn load_project_for_param(
storage : &Storage,
proj_id : &str,
) -> core::result::Result< claude_storage_core::Project, ErrorData >
{
let id = parse_project_parameter( proj_id )
.map_err( | e | ErrorData::new( ErrorCode::InternalError, e ) )?;
storage.load_project( &id )
.map_err( | e | ErrorData::new( ErrorCode::InternalError, format!( "Failed to load project: {e}" ) ) )
}
pub( super ) fn find_session_mut< 'a >(
sessions : &'a mut [ claude_storage_core::Session ],
session_id : &str,
) -> core::result::Result< &'a mut claude_storage_core::Session, ErrorData >
{
sessions.iter_mut()
.find( | s | s.id() == session_id || s.id().contains( session_id ) )
.ok_or_else( || ErrorData::new( ErrorCode::InternalError, format!( "Session not found: {session_id}" ) ) )
}