@@ -25,21 +25,29 @@ fn decode_user_version_to_semver(user_version: u32) -> String {
2525}
2626
2727fn find_schema_dir ( manifest_dir : & Path ) -> Result < PathBuf , Box < dyn std:: error:: Error > > {
28+ // 1. Explicit override.
2829 if let Ok ( path) = env:: var ( "DUC_SCHEMA_DIR" ) {
2930 let candidate = PathBuf :: from ( path) ;
3031 if candidate. join ( "duc.sql" ) . is_file ( ) {
3132 return Ok ( candidate) ;
3233 }
3334 }
3435
36+ // 2. Bundled schema — present after `cargo publish`.
37+ let bundled = manifest_dir. join ( "schema" ) ;
38+ if bundled. join ( "duc.sql" ) . is_file ( ) {
39+ return Ok ( bundled) ;
40+ }
41+
42+ // 3. Local workspace: walk up until we hit the repo root `schema/`.
43+ // When found, mirror it into `manifest_dir/schema/` so the crate is
44+ // self-contained for `cargo publish` and does not rely on the parent
45+ // directory layout once it is on crates.io.
3546 for ancestor in manifest_dir. ancestors ( ) {
36- for candidate in [
37- ancestor. join ( "schema" ) ,
38- ancestor. join ( "packages" ) . join ( "ducpy" ) . join ( "schema" ) ,
39- ] {
40- if candidate. join ( "duc.sql" ) . is_file ( ) {
41- return Ok ( candidate) ;
42- }
47+ let candidate = ancestor. join ( "schema" ) ;
48+ if candidate. join ( "duc.sql" ) . is_file ( ) {
49+ mirror_schema ( & candidate, & bundled) ?;
50+ return Ok ( bundled) ;
4351 }
4452 }
4553
@@ -50,6 +58,52 @@ fn find_schema_dir(manifest_dir: &Path) -> Result<PathBuf, Box<dyn std::error::E
5058 . into ( ) )
5159}
5260
61+ /// Recursively mirror `src` into `dst`, creating/overwriting as needed.
62+ fn mirror_schema ( src : & Path , dst : & Path ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
63+ if dst. exists ( ) {
64+ let _ = fs:: remove_dir_all ( dst) ;
65+ }
66+ fs:: create_dir_all ( dst) ?;
67+
68+ for entry in fs:: read_dir ( src) ? {
69+ let entry = entry?;
70+ let from = entry. path ( ) ;
71+ let name = match from. file_name ( ) {
72+ Some ( n) => n,
73+ None => continue ,
74+ } ;
75+ let to = dst. join ( name) ;
76+
77+ let meta = entry. metadata ( ) ?;
78+ if meta. is_dir ( ) {
79+ mirror_dir ( & from, & to) ?;
80+ } else {
81+ fs:: copy ( & from, & to) ?;
82+ }
83+ }
84+ Ok ( ( ) )
85+ }
86+
87+ fn mirror_dir ( src : & Path , dst : & Path ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
88+ fs:: create_dir_all ( dst) ?;
89+ for entry in fs:: read_dir ( src) ? {
90+ let entry = entry?;
91+ let from = entry. path ( ) ;
92+ let name = match from. file_name ( ) {
93+ Some ( n) => n,
94+ None => continue ,
95+ } ;
96+ let to = dst. join ( name) ;
97+ let meta = entry. metadata ( ) ?;
98+ if meta. is_dir ( ) {
99+ mirror_dir ( & from, & to) ?;
100+ } else {
101+ fs:: copy ( & from, & to) ?;
102+ }
103+ }
104+ Ok ( ( ) )
105+ }
106+
53107fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
54108 let manifest_dir = PathBuf :: from ( env:: var ( "CARGO_MANIFEST_DIR" ) ?) ;
55109 let schema_dir = find_schema_dir ( & manifest_dir) ?;
0 commit comments