thot_local/project/
script.rs

1use super::container;
2use super::project::{path_is_project_root, project_root_path};
3use super::resources::container::Container;
4use super::resources::script::Scripts;
5use crate::result::{ContainerError, Error, ProjectError, Result};
6use settings_manager::list_setting::ListSetting;
7use settings_manager::local_settings::LocalSettings;
8use std::path::Path;
9use thot_core::project::{Script, ScriptAssociation};
10use thot_core::result::{Error as CoreError, ProjectError as CoreProjectError};
11use thot_core::types::{ResourceId, ResourcePath};
12
13// ***************
14// *** Scripts ***
15// ***************
16
17/// Initialize a file as a Script for a Project.
18///
19/// If `project` is `None`, assumes the file is contained within the project.
20pub fn init(path: &Path, project: Option<&Path>) -> Result<ResourceId> {
21    let project = match project {
22        None => project_root_path(path)?,
23        Some(p) => {
24            // check path is a project root
25            if !path_is_project_root(p) {
26                return Err(Error::ProjectError(ProjectError::PathNotAProjectRoot(
27                    p.to_path_buf(),
28                )));
29            }
30
31            p.to_path_buf()
32        }
33    };
34
35    let s_rp = ResourcePath::new(path.to_path_buf())?;
36    let mut scripts = Scripts::load(&project)?;
37
38    // check if script is already registered
39    for s in &scripts.scripts {
40        if s.path == s_rp {
41            return Ok(s.rid.clone());
42        }
43    }
44
45    let script = Script::new(s_rp)?;
46    let rid = script.rid.clone();
47    scripts.push(script);
48    scripts.save()?;
49
50    Ok(rid)
51}
52
53/// Returns the id of the script associated with the path registered with the given project.
54/// If project path is not given, searches in ancestors for project root.
55/// Errors if the path is not registered.
56pub fn id_by_path(path: &Path, project: Option<&Path>) -> Result<ResourceId> {
57    // get project
58    let project = match project {
59        Some(p) => {
60            if !path_is_project_root(p) {
61                return Err(Error::ProjectError(ProjectError::PathNotAProjectRoot(
62                    p.to_path_buf(),
63                )));
64            }
65            p.to_path_buf()
66        }
67        None => {
68            let p = project_root_path(path)?;
69            p
70        }
71    };
72
73    let scripts = Scripts::load(&project)?;
74    let s_path = ResourcePath::new(path.to_path_buf())?;
75    match scripts.by_path(&s_path) {
76        None => Err(Error::CoreError(CoreError::ProjectError(
77            CoreProjectError::NotRegistered(None, Some(path.to_path_buf())),
78        ))),
79        Some(script) => Ok(script.rid.clone()),
80    }
81}
82
83/// Returns if the path is registered as a script with the given project.
84/// If project path is not given, searches in ancestors for project root.
85pub fn path_is_registered(path: &Path, project: Option<&Path>) -> Result<bool> {
86    // get project
87    let project = match project {
88        Some(p) => {
89            if !path_is_project_root(p) {
90                return Err(Error::ProjectError(ProjectError::PathNotAProjectRoot(
91                    p.to_path_buf(),
92                )));
93            }
94            p.to_path_buf()
95        }
96        None => {
97            let p = project_root_path(path)?;
98            p
99        }
100    };
101
102    // check if script is registered
103    let scripts = Scripts::load(&project)?;
104    let s_path = ResourcePath::new(path.to_path_buf())?;
105    Ok(scripts.contains_path(&s_path))
106}
107
108// **************************
109// *** Script Association ***
110// **************************
111
112/// Add an associaiton with the given script to the given container.
113/// Returns the resource id of the script.
114///
115/// # Arguments
116/// + `container`: Path of the `Container` to associate the script with.
117///     Must be a in a [`Project`].
118///
119/// # Errors
120/// + If `container` is not in a `Project`.
121pub fn add_association(script: &Path, container: &Path) -> Result<ResourceId> {
122    // check script and container are valid
123    if !container::path_is_container(container) {
124        return Err(Error::ContainerError(ContainerError::PathNotAContainer(
125            container.to_path_buf(),
126        )));
127    }
128
129    // get script
130    let prj_path = project_root_path(container)?;
131    let scripts = Scripts::load(&prj_path)?;
132    let s_path = ResourcePath::new(script.to_path_buf())?;
133    let script = match scripts.by_path(&s_path) {
134        Some(s) => s,
135        None => {
136            return Err(Error::CoreError(CoreError::ProjectError(
137                CoreProjectError::NotRegistered(None, Some(script.to_path_buf())),
138            )))
139        }
140    };
141
142    // add association
143    let mut container = Container::load(container)?;
144    let assoc = ScriptAssociation::new(script.rid.clone());
145    container.add_script_association(assoc)?;
146    container.save()?;
147
148    Ok(script.rid.clone())
149}
150
151#[cfg(test)]
152#[path = "./script_test.rs"]
153mod script_test;