@@ -56,6 +56,53 @@ fn encoding_from_name(encoding_name: &str) -> Option<&(dyn encoding::Encoding +
5656 }
5757}
5858
59+ /// Convert a user-supplied path to an absolute path, and convert it to a verbatim path on Windows.
60+ fn path_from_string ( path : & str ) -> PathBuf {
61+ let mut path = PathBuf :: from ( path) ;
62+ // make path absolute
63+ if path. is_relative ( ) {
64+ path = std:: env:: current_dir ( ) . unwrap ( ) . join ( path)
65+ } ;
66+ let mut components = path. components ( ) ;
67+
68+ // make Windows paths verbatim (with `\\?\` prefixes) which allow for extended-length paths.
69+ let mut result = match components. next ( ) {
70+ None => unimplemented ! ( "empty path" ) ,
71+
72+ Some ( component) => match component {
73+ std:: path:: Component :: Prefix ( prefix) => match prefix. kind ( ) {
74+ std:: path:: Prefix :: Disk ( drive) => {
75+ let root = format ! ( r"\\?\{}:\" , drive as char ) ;
76+ PathBuf :: from ( root)
77+ }
78+ std:: path:: Prefix :: UNC ( server, share) => {
79+ let mut root = std:: ffi:: OsString :: from ( r"\\?\UNC\" ) ;
80+ root. push ( server) ;
81+ root. push ( r"\" ) ;
82+ root. push ( share) ;
83+ PathBuf :: from ( root)
84+ }
85+ std:: path:: Prefix :: Verbatim ( _)
86+ | std:: path:: Prefix :: VerbatimUNC ( _, _)
87+ | std:: path:: Prefix :: VerbatimDisk ( _)
88+ | std:: path:: Prefix :: DeviceNS ( _) => Path :: new ( & component) . to_path_buf ( ) ,
89+ } ,
90+ _ => Path :: new ( & component) . to_path_buf ( ) ,
91+ } ,
92+ } ;
93+ // remove `.` and `..` components
94+ for component in components {
95+ match component {
96+ std:: path:: Component :: CurDir => continue ,
97+ std:: path:: Component :: ParentDir => {
98+ result. pop ( ) ;
99+ }
100+ _ => result. push ( component) ,
101+ }
102+ }
103+ result
104+ }
105+
59106fn main ( ) -> std:: io:: Result < ( ) > {
60107 tracing_subscriber:: fmt ( )
61108 . with_target ( false )
@@ -122,15 +169,15 @@ fn main() -> std::io::Result<()> {
122169 let src_archive_dir = matches
123170 . value_of ( "source-archive-dir" )
124171 . expect ( "missing --source-archive-dir" ) ;
125- let src_archive_dir = PathBuf :: from ( src_archive_dir) ;
172+ let src_archive_dir = path_from_string ( src_archive_dir) ;
126173
127174 let trap_dir = matches
128175 . value_of ( "output-dir" )
129176 . expect ( "missing --output-dir" ) ;
130- let trap_dir = PathBuf :: from ( trap_dir) ;
177+ let trap_dir = path_from_string ( trap_dir) ;
131178
132179 let file_list = matches. value_of ( "file-list" ) . expect ( "missing --file-list" ) ;
133- let file_list = fs:: File :: open ( file_list) ?;
180+ let file_list = fs:: File :: open ( path_from_string ( file_list) ) ?;
134181
135182 let language = tree_sitter_ruby:: language ( ) ;
136183 let erb = tree_sitter_embedded_template:: language ( ) ;
@@ -164,7 +211,7 @@ fn main() -> std::io::Result<()> {
164211 & path,
165212 & source,
166213 & [ ] ,
167- ) ? ;
214+ ) ;
168215
169216 let ( ranges, line_breaks) = scan_erb (
170217 erb,
@@ -251,7 +298,7 @@ fn main() -> std::io::Result<()> {
251298 & path,
252299 & source,
253300 & code_ranges,
254- ) ? ;
301+ ) ;
255302 std:: fs:: create_dir_all ( & src_archive_file. parent ( ) . unwrap ( ) ) ?;
256303 if needs_conversion {
257304 std:: fs:: write ( & src_archive_file, & source) ?;
0 commit comments