build.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. use std::fs::{self, File};
  2. use std::io::Write;
  3. use std::path::{Path, PathBuf};
  4. fn main() {
  5. // Step 1: Find `migrations/` folder recursively
  6. let root = Path::new("src");
  7. for migration_path in find_migrations_dirs(root) {
  8. // Step 2: Collect all files inside the migrations dir
  9. let mut files = Vec::new();
  10. visit_dirs(&migration_path, &mut files).expect("Failed to read migrations directory");
  11. files.sort();
  12. // Step 3: Output file path (e.g., `src/db/migrations.rs`)
  13. let parent = migration_path.parent().unwrap();
  14. let skip_path = parent.to_str().unwrap_or_default().len();
  15. let dest_path = parent.join("migrations.rs");
  16. let mut out_file = File::create(&dest_path).expect("Failed to create migrations.rs");
  17. let skip_name = migration_path.to_str().unwrap_or_default().len();
  18. writeln!(out_file, "/// @generated").unwrap();
  19. writeln!(out_file, "/// Auto-generated by build.rs").unwrap();
  20. writeln!(out_file, "pub static MIGRATIONS: &[(&str, &str)] = &[").unwrap();
  21. for path in &files {
  22. let rel_name = &path.to_str().unwrap().replace("\\", "/")[skip_name + 1..]; // for Windows
  23. let rel_path = &path.to_str().unwrap().replace("\\", "/")[skip_path..]; // for Windows
  24. writeln!(
  25. out_file,
  26. " (\"{rel_name}\", include_str!(r#\".{rel_path}\"#)),"
  27. )
  28. .unwrap();
  29. println!("cargo:rerun-if-changed={}", path.display());
  30. }
  31. writeln!(out_file, "];").unwrap();
  32. println!("cargo:rerun-if-changed={}", migration_path.display());
  33. }
  34. }
  35. fn find_migrations_dirs(root: &Path) -> Vec<PathBuf> {
  36. let mut found = Vec::new();
  37. find_migrations_dirs_rec(root, &mut found);
  38. found
  39. }
  40. fn find_migrations_dirs_rec(dir: &Path, found: &mut Vec<PathBuf>) {
  41. if let Ok(entries) = fs::read_dir(dir) {
  42. for entry in entries.flatten() {
  43. let path = entry.path();
  44. if path.is_dir() {
  45. if path.file_name().unwrap_or_default() == "migrations" {
  46. found.push(path.clone());
  47. }
  48. find_migrations_dirs_rec(&path, found);
  49. }
  50. }
  51. }
  52. }
  53. fn visit_dirs(dir: &Path, files: &mut Vec<PathBuf>) -> std::io::Result<()> {
  54. for entry in fs::read_dir(dir)? {
  55. let entry = entry?;
  56. let path = entry.path();
  57. if path.is_dir() {
  58. visit_dirs(&path, files)?;
  59. } else if path.is_file() {
  60. files.push(path);
  61. }
  62. }
  63. Ok(())
  64. }