mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 16:04:23 +00:00
Add logging to storage package
This commit is contained in:
@@ -1,5 +1,3 @@
|
|||||||
// Package storage provides functionalities to interact with the file system,
|
|
||||||
// including listing files, finding files by name, getting file content, saving files, and deleting files.
|
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -32,8 +30,22 @@ type FileNode struct {
|
|||||||
// ListFilesRecursively returns a list of all files in the workspace directory and its subdirectories.
|
// ListFilesRecursively returns a list of all files in the workspace directory and its subdirectories.
|
||||||
// Workspace is identified by the given userID and workspaceID.
|
// Workspace is identified by the given userID and workspaceID.
|
||||||
func (s *Service) ListFilesRecursively(userID, workspaceID int) ([]FileNode, error) {
|
func (s *Service) ListFilesRecursively(userID, workspaceID int) ([]FileNode, error) {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("listing files recursively",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID)
|
||||||
|
|
||||||
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
||||||
return s.walkDirectory(workspacePath, "")
|
nodes, err := s.walkDirectory(workspacePath, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("file listing complete",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"nodeCount", len(nodes))
|
||||||
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// walkDirectory recursively walks the directory and returns a list of files and directories.
|
// walkDirectory recursively walks the directory and returns a list of files and directories.
|
||||||
@@ -104,6 +116,12 @@ func (s *Service) walkDirectory(dir, prefix string) ([]FileNode, error) {
|
|||||||
// Files are searched recursively in the workspace directory and its subdirectories.
|
// Files are searched recursively in the workspace directory and its subdirectories.
|
||||||
// Workspace is identified by the given userID and workspaceID.
|
// Workspace is identified by the given userID and workspaceID.
|
||||||
func (s *Service) FindFileByName(userID, workspaceID int, filename string) ([]string, error) {
|
func (s *Service) FindFileByName(userID, workspaceID int, filename string) ([]string, error) {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("searching for file by name",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"filename", filename)
|
||||||
|
|
||||||
var foundPaths []string
|
var foundPaths []string
|
||||||
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
||||||
|
|
||||||
@@ -131,12 +149,23 @@ func (s *Service) FindFileByName(userID, workspaceID int, filename string) ([]st
|
|||||||
return nil, fmt.Errorf("file not found")
|
return nil, fmt.Errorf("file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("file search complete",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"filename", filename,
|
||||||
|
"matchCount", len(foundPaths))
|
||||||
return foundPaths, nil
|
return foundPaths, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFileContent returns the content of the file at the given filePath.
|
// GetFileContent returns the content of the file at the given filePath.
|
||||||
// Path must be a relative path within the workspace directory given by userID and workspaceID.
|
// Path must be a relative path within the workspace directory given by userID and workspaceID.
|
||||||
func (s *Service) GetFileContent(userID, workspaceID int, filePath string) ([]byte, error) {
|
func (s *Service) GetFileContent(userID, workspaceID int, filePath string) ([]byte, error) {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("reading file content",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"path", filePath)
|
||||||
|
|
||||||
fullPath, err := s.ValidatePath(userID, workspaceID, filePath)
|
fullPath, err := s.ValidatePath(userID, workspaceID, filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -147,6 +176,13 @@ func (s *Service) GetFileContent(userID, workspaceID int, filePath string) ([]by
|
|||||||
// SaveFile writes the content to the file at the given filePath.
|
// SaveFile writes the content to the file at the given filePath.
|
||||||
// Path must be a relative path within the workspace directory given by userID and workspaceID.
|
// Path must be a relative path within the workspace directory given by userID and workspaceID.
|
||||||
func (s *Service) SaveFile(userID, workspaceID int, filePath string, content []byte) error {
|
func (s *Service) SaveFile(userID, workspaceID int, filePath string, content []byte) error {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("saving file",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"path", filePath,
|
||||||
|
"contentSize", len(content))
|
||||||
|
|
||||||
fullPath, err := s.ValidatePath(userID, workspaceID, filePath)
|
fullPath, err := s.ValidatePath(userID, workspaceID, filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -157,17 +193,41 @@ func (s *Service) SaveFile(userID, workspaceID int, filePath string, content []b
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.fs.WriteFile(fullPath, content, 0644)
|
if err := s.fs.WriteFile(fullPath, content, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("file saved",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"path", filePath,
|
||||||
|
"size", len(content))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteFile deletes the file at the given filePath.
|
// DeleteFile deletes the file at the given filePath.
|
||||||
// Path must be a relative path within the workspace directory given by userID and workspaceID.
|
// Path must be a relative path within the workspace directory given by userID and workspaceID.
|
||||||
func (s *Service) DeleteFile(userID, workspaceID int, filePath string) error {
|
func (s *Service) DeleteFile(userID, workspaceID int, filePath string) error {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("deleting file",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"path", filePath)
|
||||||
|
|
||||||
fullPath, err := s.ValidatePath(userID, workspaceID, filePath)
|
fullPath, err := s.ValidatePath(userID, workspaceID, filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return s.fs.Remove(fullPath)
|
|
||||||
|
if err := s.fs.Remove(fullPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("file deleted",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"path", filePath)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileCountStats holds statistics about files in a workspace
|
// FileCountStats holds statistics about files in a workspace
|
||||||
@@ -179,6 +239,11 @@ type FileCountStats struct {
|
|||||||
// GetFileStats returns the total number of files and related statistics in a workspace
|
// GetFileStats returns the total number of files and related statistics in a workspace
|
||||||
// Workspace is identified by the given userID and workspaceID
|
// Workspace is identified by the given userID and workspaceID
|
||||||
func (s *Service) GetFileStats(userID, workspaceID int) (*FileCountStats, error) {
|
func (s *Service) GetFileStats(userID, workspaceID int) (*FileCountStats, error) {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("gathering file statistics",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID)
|
||||||
|
|
||||||
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
||||||
|
|
||||||
// Check if workspace exists
|
// Check if workspace exists
|
||||||
@@ -186,13 +251,33 @@ func (s *Service) GetFileStats(userID, workspaceID int) (*FileCountStats, error)
|
|||||||
return nil, fmt.Errorf("workspace directory does not exist")
|
return nil, fmt.Errorf("workspace directory does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.countFilesInPath(workspacePath)
|
stats, err := s.countFilesInPath(workspacePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("file statistics collected",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"totalFiles", stats.TotalFiles,
|
||||||
|
"totalSize", stats.TotalSize)
|
||||||
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTotalFileStats returns the total file statistics for the storage.
|
// GetTotalFileStats returns the total file statistics for the storage.
|
||||||
func (s *Service) GetTotalFileStats() (*FileCountStats, error) {
|
func (s *Service) GetTotalFileStats() (*FileCountStats, error) {
|
||||||
return s.countFilesInPath(s.RootDir)
|
log := getLogger()
|
||||||
|
log.Debug("gathering total storage statistics")
|
||||||
|
|
||||||
|
stats, err := s.countFilesInPath(s.RootDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("total storage statistics collected",
|
||||||
|
"totalFiles", stats.TotalFiles,
|
||||||
|
"totalSize", stats.TotalSize)
|
||||||
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// countFilesInPath counts the total number of files and the total size of files in the given directory.
|
// countFilesInPath counts the total number of files and the total size of files in the given directory.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"novamd/internal/logging"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,6 +18,15 @@ type fileSystem interface {
|
|||||||
IsNotExist(err error) bool
|
IsNotExist(err error) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var logger logging.Logger
|
||||||
|
|
||||||
|
func getLogger() logging.Logger {
|
||||||
|
if logger == nil {
|
||||||
|
logger = logging.WithGroup("storage")
|
||||||
|
}
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
|
||||||
// osFS implements the FileSystem interface using the real filesystem.
|
// osFS implements the FileSystem interface using the real filesystem.
|
||||||
type osFS struct{}
|
type osFS struct{}
|
||||||
|
|
||||||
|
|||||||
@@ -16,19 +16,37 @@ type RepositoryManager interface {
|
|||||||
// SetupGitRepo sets up a Git repository for the given userID and workspaceID.
|
// SetupGitRepo sets up a Git repository for the given userID and workspaceID.
|
||||||
// The repository is cloned from the given gitURL using the given gitUser and gitToken.
|
// The repository is cloned from the given gitURL using the given gitUser and gitToken.
|
||||||
func (s *Service) SetupGitRepo(userID, workspaceID int, gitURL, gitUser, gitToken, commitName, commitEmail string) error {
|
func (s *Service) SetupGitRepo(userID, workspaceID int, gitURL, gitUser, gitToken, commitName, commitEmail string) error {
|
||||||
|
log := getLogger()
|
||||||
|
log.Info("setting up git repository",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
)
|
||||||
|
|
||||||
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
||||||
|
|
||||||
if _, ok := s.GitRepos[userID]; !ok {
|
if _, ok := s.GitRepos[userID]; !ok {
|
||||||
|
log.Debug("initializing git repo map for user",
|
||||||
|
"userID", userID)
|
||||||
s.GitRepos[userID] = make(map[int]git.Client)
|
s.GitRepos[userID] = make(map[int]git.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.GitRepos[userID][workspaceID] = s.newGitClient(gitURL, gitUser, gitToken, workspacePath, commitName, commitEmail)
|
s.GitRepos[userID][workspaceID] = s.newGitClient(gitURL, gitUser, gitToken, workspacePath, commitName, commitEmail)
|
||||||
|
|
||||||
return s.GitRepos[userID][workspaceID].EnsureRepo()
|
return s.GitRepos[userID][workspaceID].EnsureRepo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableGitRepo disables the Git repository for the given userID and workspaceID.
|
// DisableGitRepo disables the Git repository for the given userID and workspaceID.
|
||||||
func (s *Service) DisableGitRepo(userID, workspaceID int) {
|
func (s *Service) DisableGitRepo(userID, workspaceID int) {
|
||||||
|
log := getLogger()
|
||||||
|
log.Info("disabling git repository",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID)
|
||||||
|
|
||||||
if userRepos, ok := s.GitRepos[userID]; ok {
|
if userRepos, ok := s.GitRepos[userID]; ok {
|
||||||
delete(userRepos, workspaceID)
|
delete(userRepos, workspaceID)
|
||||||
if len(userRepos) == 0 {
|
if len(userRepos) == 0 {
|
||||||
|
log.Debug("removing empty user git repos map",
|
||||||
|
"userID", userID)
|
||||||
delete(s.GitRepos, userID)
|
delete(s.GitRepos, userID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,6 +55,12 @@ func (s *Service) DisableGitRepo(userID, workspaceID int) {
|
|||||||
// StageCommitAndPush stages, commit with the message, and pushes the changes to the Git repository.
|
// StageCommitAndPush stages, commit with the message, and pushes the changes to the Git repository.
|
||||||
// The git repository belongs to the given userID and is associated with the given workspaceID.
|
// The git repository belongs to the given userID and is associated with the given workspaceID.
|
||||||
func (s *Service) StageCommitAndPush(userID, workspaceID int, message string) (git.CommitHash, error) {
|
func (s *Service) StageCommitAndPush(userID, workspaceID int, message string) (git.CommitHash, error) {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("preparing to stage, commit and push changes",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"message", message)
|
||||||
|
|
||||||
repo, ok := s.getGitRepo(userID, workspaceID)
|
repo, ok := s.getGitRepo(userID, workspaceID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return git.CommitHash{}, fmt.Errorf("git settings not configured for this workspace")
|
return git.CommitHash{}, fmt.Errorf("git settings not configured for this workspace")
|
||||||
@@ -47,19 +71,39 @@ func (s *Service) StageCommitAndPush(userID, workspaceID int, message string) (g
|
|||||||
return git.CommitHash{}, err
|
return git.CommitHash{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.Push()
|
if err = repo.Push(); err != nil {
|
||||||
return hash, err
|
return hash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("changes committed and pushed",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"commitHash", hash.String())
|
||||||
|
return hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Pull pulls the changes from the remote Git repository.
|
// Pull pulls the changes from the remote Git repository.
|
||||||
// The git repository belongs to the given userID and is associated with the given workspaceID.
|
// The git repository belongs to the given userID and is associated with the given workspaceID.
|
||||||
func (s *Service) Pull(userID, workspaceID int) error {
|
func (s *Service) Pull(userID, workspaceID int) error {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("preparing to pull changes",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID)
|
||||||
|
|
||||||
repo, ok := s.getGitRepo(userID, workspaceID)
|
repo, ok := s.getGitRepo(userID, workspaceID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("git settings not configured for this workspace")
|
return fmt.Errorf("git settings not configured for this workspace")
|
||||||
}
|
}
|
||||||
|
|
||||||
return repo.Pull()
|
err := repo.Pull()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("changes pulled from remote",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getGitRepo returns the Git repository for the given user and workspace IDs.
|
// getGitRepo returns the Git repository for the given user and workspace IDs.
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ type Options struct {
|
|||||||
|
|
||||||
// NewService creates a new Storage instance with the default options and the given rootDir root directory.
|
// NewService creates a new Storage instance with the default options and the given rootDir root directory.
|
||||||
func NewService(rootDir string) *Service {
|
func NewService(rootDir string) *Service {
|
||||||
|
getLogger().Debug("creating new storage service",
|
||||||
|
"rootDir", rootDir,
|
||||||
|
"options", "default")
|
||||||
return NewServiceWithOptions(rootDir, Options{
|
return NewServiceWithOptions(rootDir, Options{
|
||||||
Fs: &osFS{},
|
Fs: &osFS{},
|
||||||
NewGitClient: git.New,
|
NewGitClient: git.New,
|
||||||
@@ -35,14 +38,23 @@ func NewService(rootDir string) *Service {
|
|||||||
|
|
||||||
// NewServiceWithOptions creates a new Storage instance with the given options and the given rootDir root directory.
|
// NewServiceWithOptions creates a new Storage instance with the given options and the given rootDir root directory.
|
||||||
func NewServiceWithOptions(rootDir string, options Options) *Service {
|
func NewServiceWithOptions(rootDir string, options Options) *Service {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("creating new storage service with custom options",
|
||||||
|
"rootDir", rootDir)
|
||||||
|
|
||||||
if options.Fs == nil {
|
if options.Fs == nil {
|
||||||
|
log.Debug("filesystem not provided, using default osFS")
|
||||||
options.Fs = &osFS{}
|
options.Fs = &osFS{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.NewGitClient == nil {
|
if options.NewGitClient == nil {
|
||||||
|
log.Debug("git client factory not provided, using default git.New")
|
||||||
options.NewGitClient = git.New
|
options.NewGitClient = git.New
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("storage service created",
|
||||||
|
"rootDir", rootDir)
|
||||||
|
|
||||||
return &Service{
|
return &Service{
|
||||||
fs: options.Fs,
|
fs: options.Fs,
|
||||||
newGitClient: options.NewGitClient,
|
newGitClient: options.NewGitClient,
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ type WorkspaceManager interface {
|
|||||||
// ValidatePath validates the if the given path is valid within the workspace directory.
|
// ValidatePath validates the if the given path is valid within the workspace directory.
|
||||||
// Workspace directory is defined as the directory for the given userID and workspaceID.
|
// Workspace directory is defined as the directory for the given userID and workspaceID.
|
||||||
func (s *Service) ValidatePath(userID, workspaceID int, path string) (string, error) {
|
func (s *Service) ValidatePath(userID, workspaceID int, path string) (string, error) {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("validating path",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID,
|
||||||
|
"path", path)
|
||||||
|
|
||||||
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
||||||
|
|
||||||
// First check if the path is absolute
|
// First check if the path is absolute
|
||||||
@@ -43,6 +49,11 @@ func (s *Service) GetWorkspacePath(userID, workspaceID int) string {
|
|||||||
|
|
||||||
// InitializeUserWorkspace creates the workspace directory for the given userID and workspaceID.
|
// InitializeUserWorkspace creates the workspace directory for the given userID and workspaceID.
|
||||||
func (s *Service) InitializeUserWorkspace(userID, workspaceID int) error {
|
func (s *Service) InitializeUserWorkspace(userID, workspaceID int) error {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("initializing workspace directory",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID)
|
||||||
|
|
||||||
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
||||||
err := s.fs.MkdirAll(workspacePath, 0755)
|
err := s.fs.MkdirAll(workspacePath, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -54,6 +65,11 @@ func (s *Service) InitializeUserWorkspace(userID, workspaceID int) error {
|
|||||||
|
|
||||||
// DeleteUserWorkspace deletes the workspace directory for the given userID and workspaceID.
|
// DeleteUserWorkspace deletes the workspace directory for the given userID and workspaceID.
|
||||||
func (s *Service) DeleteUserWorkspace(userID, workspaceID int) error {
|
func (s *Service) DeleteUserWorkspace(userID, workspaceID int) error {
|
||||||
|
log := getLogger()
|
||||||
|
log.Debug("deleting workspace directory",
|
||||||
|
"userID", userID,
|
||||||
|
"workspaceID", workspaceID)
|
||||||
|
|
||||||
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
workspacePath := s.GetWorkspacePath(userID, workspaceID)
|
||||||
err := s.fs.RemoveAll(workspacePath)
|
err := s.fs.RemoveAll(workspacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user