thot-local 0.10.0-intermediate

Local functionality for Thot data management and analysis software.
Documentation
//! Project and project settings.
use crate::common::{project_file_of, project_settings_file_of};
use crate::result::Result;
use crate::system::settings::user_settings::UserSettings;
use cluFlock::FlockLock;
use serde::{Deserialize, Serialize};
use settings_manager::local_settings::{LocalSettings, LockSettingsFile};
use settings_manager::result::{
    Error as SettingsError, LocalSettingsError, Result as SettingsResult,
};
use settings_manager::settings::Settings;
use settings_manager::system_settings::SystemSettings;
use settings_manager::types::Priority as SettingsPriority;
use std::fs::File;
use std::path::{Path, PathBuf};
use thot_core::project::Project as CoreProject;
use thot_core::types::{Creator, UserId, UserPermissions};

// ***************
// *** Project ***
// ***************

/// Represents a Thot project.
#[derive(Serialize, Deserialize, Debug)]
pub struct Project {
    #[serde(skip)]
    _file_lock: Option<FlockLock<File>>,

    #[serde(skip)]
    _base_path: Option<PathBuf>,

    pub properties: CoreProject,
}

impl Project {
    /// Creates a new Project.
    pub fn new(name: &str) -> Result<Self> {
        // get active user
        let settings = UserSettings::load()?;
        let creator = match settings.active_user {
            None => None,
            Some(uid) => Some(UserId::Id(uid)),
        };
        let creator = Creator::User(creator);

        let mut properties = CoreProject::new(name);
        properties.creator = creator;

        Ok(Project {
            _file_lock: None,
            _base_path: None,
            properties,
        })
    }
}

impl Default for Project {
    fn default() -> Self {
        // attempt to create new project
        let new_prj = Project::new("");
        if let Ok(prj) = new_prj {
            return prj;
        }

        // if fail, create manually
        Project {
            _file_lock: None,
            _base_path: None,
            properties: CoreProject::default(),
        }
    }
}

impl Settings for Project {
    fn store_lock(&mut self, lock: FlockLock<File>) {
        self._file_lock = Some(lock);
    }

    fn controls_file(&self) -> bool {
        self._file_lock.is_some()
    }

    fn priority(&self) -> SettingsPriority {
        SettingsPriority::Project
    }
}

impl LocalSettings for Project {
    fn rel_path() -> SettingsResult<PathBuf> {
        Ok(project_file_of(Path::new("")))
    }

    fn base_path(&self) -> SettingsResult<PathBuf> {
        self._base_path
            .clone()
            .ok_or(SettingsError::LocalSettingsError(
                LocalSettingsError::PathNotSet,
            ))
    }

    fn set_base_path(&mut self, path: PathBuf) -> SettingsResult {
        self._base_path = Some(path);
        Ok(())
    }
}

impl LockSettingsFile for Project {}

// ************************
// *** Project Settings ***
// ************************

/// Settings for a Thot project.
///
/// # Fields
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct ProjectSettings {
    #[serde(skip)]
    _file_lock: Option<FlockLock<File>>,

    #[serde(skip)]
    _base_path: Option<PathBuf>,

    permissions: Vec<UserPermissions>,
}

impl ProjectSettings {
    /// Creates a new project settings.
    pub fn new() -> Self {
        ProjectSettings {
            _file_lock: None,
            _base_path: None,

            permissions: Vec::new(),
        }
    }
}

impl Settings for ProjectSettings {
    fn store_lock(&mut self, lock: FlockLock<File>) {
        self._file_lock = Some(lock);
    }

    fn controls_file(&self) -> bool {
        self._file_lock.is_some()
    }

    fn priority(&self) -> SettingsPriority {
        SettingsPriority::Project
    }
}

impl LocalSettings for ProjectSettings {
    fn rel_path() -> SettingsResult<PathBuf> {
        Ok(project_settings_file_of(Path::new("")))
    }

    fn base_path(&self) -> SettingsResult<PathBuf> {
        match self._base_path.clone() {
            Some(path) => Ok(path),
            None => Err(SettingsError::LocalSettingsError(
                LocalSettingsError::PathNotSet,
            )),
        }
    }

    fn set_base_path(&mut self, path: PathBuf) -> SettingsResult {
        self._base_path = Some(path);
        Ok(())
    }
}

impl LockSettingsFile for ProjectSettings {}

#[cfg(test)]
#[path = "./project_test.rs"]
mod project_test;