1
- use std:: path:: { Path , PathBuf } ;
1
+ use std:: ffi:: OsStr ;
2
+ use std:: path:: { Component , Path , PathBuf } ;
2
3
3
4
use crate :: Stack ;
4
5
6
+ ///
7
+ pub mod to_normal_path_components {
8
+ use std:: ffi:: OsString ;
9
+
10
+ /// The error used in [`ToNormalPathComponents::to_normal_path_components()`](crate::ToNormalPathComponents::to_normal_path_components()).
11
+ #[ derive( Debug , thiserror:: Error ) ]
12
+ #[ allow( missing_docs) ]
13
+ pub enum Error {
14
+ #[ error( "Input path \" {path}\" contains relative or absolute components" , path = std:: path:: Path :: new( . 0 . as_os_str( ) ) . display( ) ) ]
15
+ NotANormalComponent ( OsString ) ,
16
+ }
17
+ }
18
+
19
+ /// Obtain an iterator over `OsStr`-components which are normal, none-relative and not absolute.
20
+ pub trait ToNormalPathComponents {
21
+ /// Return an iterator over the normal components of a path, without the separator.
22
+ // TODO(MSRV): turn this into `impl Iterator` once MSRV is 1.75 or higher
23
+ fn to_normal_path_components (
24
+ & self ,
25
+ ) -> Box < dyn Iterator < Item = Result < & OsStr , to_normal_path_components:: Error > > + ' _ > ;
26
+ }
27
+
28
+ impl ToNormalPathComponents for & Path {
29
+ fn to_normal_path_components (
30
+ & self ,
31
+ ) -> Box < dyn Iterator < Item = Result < & OsStr , to_normal_path_components:: Error > > + ' _ > {
32
+ Box :: new ( self . components ( ) . map ( |component| match component {
33
+ Component :: Normal ( os_str) => Ok ( os_str) ,
34
+ _ => Err ( to_normal_path_components:: Error :: NotANormalComponent (
35
+ self . as_os_str ( ) . to_owned ( ) ,
36
+ ) ) ,
37
+ } ) )
38
+ }
39
+ }
40
+
5
41
/// Access
6
42
impl Stack {
7
43
/// Returns the top-level path of the stack.
@@ -64,12 +100,11 @@ impl Stack {
64
100
/// or have leading or trailing slashes (or additionally backslashes on Windows).
65
101
pub fn make_relative_path_current (
66
102
& mut self ,
67
- relative : impl gix_path :: ToPathComponents ,
103
+ relative : impl ToNormalPathComponents ,
68
104
delegate : & mut dyn Delegate ,
69
105
) -> std:: io:: Result < ( ) > {
70
- let components: Vec < _ > = relative. to_components ( ) . collect ( ) ;
71
-
72
- if self . valid_components != 0 && components. is_empty ( ) {
106
+ let mut components = relative. to_normal_path_components ( ) . peekable ( ) ;
107
+ if self . valid_components != 0 && components. peek ( ) . is_none ( ) {
73
108
return Err ( std:: io:: Error :: new (
74
109
std:: io:: ErrorKind :: Other ,
75
110
"empty inputs are not allowed" ,
@@ -79,7 +114,6 @@ impl Stack {
79
114
delegate. push_directory ( self ) ?;
80
115
}
81
116
82
- let mut components = components. into_iter ( ) . peekable ( ) ;
83
117
let mut existing_components = self . current_relative . components ( ) ;
84
118
let mut matching_components = 0 ;
85
119
while let ( Some ( existing_comp) , Some ( new_comp) ) = ( existing_components. next ( ) , components. peek ( ) ) {
@@ -92,8 +126,8 @@ impl Stack {
92
126
break ;
93
127
}
94
128
}
95
- Err ( err) => return Err ( std:: io:: Error :: new ( std :: io :: ErrorKind :: Other , format ! ( "{err}" ) ) ) ,
96
- } ;
129
+ Err ( err) => return Err ( std:: io:: Error :: other ( format ! ( "{err}" ) ) ) ,
130
+ }
97
131
}
98
132
99
133
for _ in 0 ..self . valid_components - matching_components {
@@ -111,12 +145,7 @@ impl Stack {
111
145
}
112
146
113
147
while let Some ( comp) = components. next ( ) {
114
- let comp = match comp {
115
- Ok ( comp) => comp,
116
- Err ( err) => {
117
- return Err ( std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , format ! ( "{err}" ) ) ) ;
118
- }
119
- } ;
148
+ let comp = comp. map_err ( std:: io:: Error :: other) ?;
120
149
let is_last_component = components. peek ( ) . is_none ( ) ;
121
150
self . current_is_directory = !is_last_component;
122
151
self . current . push ( comp) ;
0 commit comments