mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 92bd145b9b |
@@ -167,7 +167,7 @@ async def write_resource(
|
||||
checksum = await file_service.write_file(full_path, content_str)
|
||||
|
||||
# Get file info
|
||||
file_stats = file_service.file_stats(full_path)
|
||||
file_stats = await file_service.file_stats(full_path)
|
||||
|
||||
# Determine file details
|
||||
file_name = Path(file_path).name
|
||||
|
||||
@@ -5,6 +5,8 @@ from pathlib import Path
|
||||
import re
|
||||
from typing import Any, Dict, Union
|
||||
|
||||
import aiofiles
|
||||
import aiofiles.os
|
||||
import yaml
|
||||
import frontmatter
|
||||
from loguru import logger
|
||||
@@ -87,11 +89,15 @@ async def write_file_atomic(path: FilePath, content: str) -> None:
|
||||
temp_path = path_obj.with_suffix(".tmp")
|
||||
|
||||
try:
|
||||
temp_path.write_text(content, encoding="utf-8")
|
||||
temp_path.replace(path_obj)
|
||||
async with aiofiles.open(temp_path, "w", encoding="utf-8") as f:
|
||||
await f.write(content)
|
||||
await aiofiles.os.replace(temp_path, path_obj)
|
||||
logger.debug("Wrote file atomically", path=str(path_obj), content_length=len(content))
|
||||
except Exception as e: # pragma: no cover
|
||||
temp_path.unlink(missing_ok=True)
|
||||
try:
|
||||
await aiofiles.os.remove(temp_path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
logger.error("Failed to write file", path=str(path_obj), error=str(e))
|
||||
raise FileWriteError(f"Failed to write file {path}: {e}")
|
||||
|
||||
@@ -208,7 +214,8 @@ async def update_frontmatter(path: FilePath, updates: Dict[str, Any]) -> str:
|
||||
path_obj = Path(path) if isinstance(path, str) else path
|
||||
|
||||
# Read current content
|
||||
content = path_obj.read_text(encoding="utf-8")
|
||||
async with aiofiles.open(path_obj, "r", encoding="utf-8") as f:
|
||||
content = await f.read()
|
||||
|
||||
# Parse current frontmatter
|
||||
current_fm = {}
|
||||
|
||||
@@ -5,6 +5,9 @@ from os import stat_result
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Tuple, Union
|
||||
|
||||
import aiofiles
|
||||
import aiofiles.os
|
||||
import aiofiles.ospath
|
||||
from basic_memory import file_utils
|
||||
from basic_memory.file_utils import FileError
|
||||
from basic_memory.markdown.markdown_processor import MarkdownProcessor
|
||||
@@ -97,9 +100,9 @@ class FileService:
|
||||
path_obj = self.base_path / path if isinstance(path, str) else path
|
||||
logger.debug(f"Checking file existence: path={path_obj}")
|
||||
if path_obj.is_absolute():
|
||||
return path_obj.exists()
|
||||
return await aiofiles.ospath.exists(path_obj)
|
||||
else:
|
||||
return (self.base_path / path_obj).exists()
|
||||
return await aiofiles.ospath.exists(self.base_path / path_obj)
|
||||
except Exception as e:
|
||||
logger.error("Failed to check file existence", path=str(path), error=str(e))
|
||||
raise FileOperationError(f"Failed to check file existence: {e}")
|
||||
@@ -169,7 +172,8 @@ class FileService:
|
||||
|
||||
try:
|
||||
logger.debug("Reading file", operation="read_file", path=str(full_path))
|
||||
content = full_path.read_text(encoding="utf-8")
|
||||
async with aiofiles.open(full_path, "r", encoding="utf-8") as f:
|
||||
content = await f.read()
|
||||
checksum = await file_utils.compute_checksum(content)
|
||||
|
||||
logger.debug(
|
||||
@@ -196,7 +200,10 @@ class FileService:
|
||||
# Convert string to Path if needed
|
||||
path_obj = self.base_path / path if isinstance(path, str) else path
|
||||
full_path = path_obj if path_obj.is_absolute() else self.base_path / path_obj
|
||||
full_path.unlink(missing_ok=True)
|
||||
try:
|
||||
await aiofiles.os.remove(full_path)
|
||||
except FileNotFoundError:
|
||||
pass # missing_ok=True behavior
|
||||
|
||||
async def update_frontmatter(self, path: FilePath, updates: Dict[str, Any]) -> str:
|
||||
"""
|
||||
@@ -233,17 +240,19 @@ class FileService:
|
||||
try:
|
||||
if self.is_markdown(path):
|
||||
# read str
|
||||
content = full_path.read_text(encoding="utf-8")
|
||||
async with aiofiles.open(full_path, "r", encoding="utf-8") as f:
|
||||
content = await f.read()
|
||||
else:
|
||||
# read bytes
|
||||
content = full_path.read_bytes()
|
||||
async with aiofiles.open(full_path, "rb") as f:
|
||||
content = await f.read()
|
||||
return await file_utils.compute_checksum(content)
|
||||
|
||||
except Exception as e: # pragma: no cover
|
||||
logger.error("Failed to compute checksum", path=str(full_path), error=str(e))
|
||||
raise FileError(f"Failed to compute checksum for {path}: {e}")
|
||||
|
||||
def file_stats(self, path: FilePath) -> stat_result:
|
||||
async def file_stats(self, path: FilePath) -> stat_result:
|
||||
"""Return file stats for a given path.
|
||||
|
||||
Args:
|
||||
@@ -256,7 +265,7 @@ class FileService:
|
||||
path_obj = self.base_path / path if isinstance(path, str) else path
|
||||
full_path = path_obj if path_obj.is_absolute() else self.base_path / path_obj
|
||||
# get file timestamps
|
||||
return full_path.stat()
|
||||
return await aiofiles.os.stat(full_path)
|
||||
|
||||
def content_type(self, path: FilePath) -> str:
|
||||
"""Return content_type for a given path.
|
||||
|
||||
@@ -548,7 +548,7 @@ class SyncService:
|
||||
file_contains_frontmatter = has_frontmatter(file_content)
|
||||
|
||||
# Get file timestamps for tracking modification times
|
||||
file_stats = self.file_service.file_stats(path)
|
||||
file_stats = await self.file_service.file_stats(path)
|
||||
created = datetime.fromtimestamp(file_stats.st_ctime).astimezone()
|
||||
modified = datetime.fromtimestamp(file_stats.st_mtime).astimezone()
|
||||
|
||||
@@ -621,7 +621,7 @@ class SyncService:
|
||||
await self.entity_service.resolve_permalink(path, skip_conflict_check=True)
|
||||
|
||||
# get file timestamps
|
||||
file_stats = self.file_service.file_stats(path)
|
||||
file_stats = await self.file_service.file_stats(path)
|
||||
created = datetime.fromtimestamp(file_stats.st_ctime).astimezone()
|
||||
modified = datetime.fromtimestamp(file_stats.st_mtime).astimezone()
|
||||
|
||||
@@ -668,7 +668,7 @@ class SyncService:
|
||||
raise
|
||||
else:
|
||||
# Get file timestamps for updating modification time
|
||||
file_stats = self.file_service.file_stats(path)
|
||||
file_stats = await self.file_service.file_stats(path)
|
||||
modified = datetime.fromtimestamp(file_stats.st_mtime).astimezone()
|
||||
|
||||
entity = await self.entity_repository.get_by_file_path(path)
|
||||
|
||||
Reference in New Issue
Block a user