blue_build/
build_scripts.rs1use std::{
2 fs::{self, DirEntry, OpenOptions},
3 io::{Read, Write},
4 ops::Not,
5 os::unix::fs::PermissionsExt,
6 path::PathBuf,
7};
8
9use blue_build_utils::constants::{BLUE_BUILD_SCRIPTS_DIR_IGNORE, GITIGNORE_PATH};
10use cached::proc_macro::once;
11use miette::{Context, IntoDiagnostic, Result, miette};
12use rust_embed::Embed;
13
14const SCRIPT_DIR_PREFIX: &str = ".bluebuild-scripts_";
15
16#[derive(Embed)]
17#[folder = "scripts/"]
18pub struct BuildScripts;
19
20impl BuildScripts {
21 pub fn extract_mount_dir() -> Result<PathBuf> {
31 #[once(result = true)]
32 fn inner() -> Result<PathBuf> {
33 update_gitignore()?;
34 delete_old_dirs()?;
35
36 let dir = PathBuf::from(format!(
37 "{SCRIPT_DIR_PREFIX}{}",
38 crate::shadow::SHORT_COMMIT
39 ));
40 fs::create_dir(&dir)
41 .into_diagnostic()
42 .wrap_err("Failed to create dir for build scripts.")?;
43
44 for file_path in BuildScripts::iter() {
45 let file = BuildScripts::get(file_path.as_ref())
46 .ok_or_else(|| miette!("Failed to get file {file_path}"))?;
47 let file_path = dir.join(&*file_path);
48 fs::write(&file_path, &file.data)
49 .into_diagnostic()
50 .wrap_err_with(|| {
51 format!("Failed to write build script file {}", file_path.display())
52 })?;
53
54 let mut perm = fs::metadata(&file_path)
55 .into_diagnostic()
56 .wrap_err_with(|| {
57 format!(
58 "Failed to get file permissions for file {}",
59 file_path.display()
60 )
61 })?
62 .permissions();
63
64 perm.set_mode(0o755);
65 fs::set_permissions(&file_path, perm).into_diagnostic()?;
66 }
67
68 Ok(dir)
69 }
70
71 inner()
72 }
73}
74
75fn delete_old_dirs() -> Result<()> {
76 let dirs = fs::read_dir(".")
77 .into_diagnostic()
78 .wrap_err("Failed to read current directory")?
79 .collect::<std::result::Result<Vec<DirEntry>, _>>()
80 .into_diagnostic()
81 .wrap_err("Failed to read dir entry")?;
82
83 for dir in dirs {
84 if dir
85 .file_name()
86 .display()
87 .to_string()
88 .starts_with(SCRIPT_DIR_PREFIX)
89 {
90 fs::remove_dir_all(dir.path())
91 .into_diagnostic()
92 .wrap_err_with(|| {
93 format!(
94 "Failed to remove old build script dir at {}",
95 dir.path().display()
96 )
97 })?;
98 }
99 }
100
101 Ok(())
102}
103
104fn update_gitignore() -> Result<()> {
105 let file = &mut OpenOptions::new()
106 .read(true)
107 .append(true)
108 .create(true)
109 .open(GITIGNORE_PATH)
110 .into_diagnostic()
111 .wrap_err_with(|| format!("Failed to open {GITIGNORE_PATH} for editing"))?;
112
113 let ignore_contents = {
114 let mut cont = String::new();
115 file.read_to_string(&mut cont)
116 .into_diagnostic()
117 .wrap_err_with(|| format!("Failed to read {GITIGNORE_PATH}"))?;
118 cont
119 };
120
121 if ignore_contents
122 .contains(BLUE_BUILD_SCRIPTS_DIR_IGNORE)
123 .not()
124 {
125 writeln!(file, "{BLUE_BUILD_SCRIPTS_DIR_IGNORE}")
126 .into_diagnostic()
127 .wrap_err_with(|| {
128 format!("Failed to add {BLUE_BUILD_SCRIPTS_DIR_IGNORE} to {GITIGNORE_PATH}")
129 })?;
130 }
131
132 Ok(())
133}