@@ -38,6 +38,8 @@ impl RelativePath {
3838#[ derive( Debug , thiserror:: Error ) ]
3939#[ allow( missing_docs) ]
4040pub enum Error {
41+ #[ error( "A RelativePath is not allowed to be absolute" ) ]
42+ IsAbsolute ,
4143 #[ error( transparent) ]
4244 ContainsInvalidComponent ( #[ from] gix_validate:: path:: component:: Error ) ,
4345 #[ error( transparent) ]
@@ -51,6 +53,11 @@ impl<'a> TryFrom<&'a str> for &'a RelativePath {
5153 use std:: path:: Path ;
5254
5355 let path: & std:: path:: Path = Path :: new ( value) ;
56+
57+ if path. is_absolute ( ) {
58+ return Err ( Error :: IsAbsolute ) ;
59+ }
60+
5461 let options: Options = Default :: default ( ) ;
5562
5663 for component in path. components ( ) {
@@ -68,6 +75,11 @@ impl<'a> TryFrom<&'a BStr> for &'a RelativePath {
6875
6976 fn try_from ( value : & ' a BStr ) -> Result < Self , Self :: Error > {
7077 let path: & std:: path:: Path = & try_from_bstr ( value) ?;
78+
79+ if path. is_absolute ( ) {
80+ return Err ( Error :: IsAbsolute ) ;
81+ }
82+
7183 let options: Options = Default :: default ( ) ;
7284
7385 for component in path. components ( ) {
@@ -87,6 +99,10 @@ impl<'a, const N: usize> TryFrom<&'a [u8; N]> for &'a RelativePath {
8799 fn try_from ( value : & ' a [ u8 ; N ] ) -> Result < Self , Self :: Error > {
88100 let path: & std:: path:: Path = try_from_byte_slice ( value) ?;
89101
102+ if path. is_absolute ( ) {
103+ return Err ( Error :: IsAbsolute ) ;
104+ }
105+
90106 let options: Options = Default :: default ( ) ;
91107
92108 for component in path. components ( ) {
@@ -105,6 +121,10 @@ impl<'a> TryFrom<&'a BString> for &'a RelativePath {
105121 fn try_from ( value : & ' a BString ) -> Result < Self , Self :: Error > {
106122 let path: & std:: path:: Path = & try_from_bstr ( value. as_bstr ( ) ) ?;
107123
124+ if path. is_absolute ( ) {
125+ return Err ( Error :: IsAbsolute ) ;
126+ }
127+
108128 let options: Options = Default :: default ( ) ;
109129
110130 for component in path. components ( ) {
@@ -131,3 +151,33 @@ impl AsRef<[u8]> for RelativePath {
131151 self . inner . as_bytes ( )
132152 }
133153}
154+
155+ #[ cfg( test) ]
156+ mod tests {
157+ use super :: * ;
158+
159+ #[ test]
160+ fn absolute_paths_return_err ( ) {
161+ let path_str: & str = "/refs/heads" ;
162+ let path_bstr: & BStr = path_str. into ( ) ;
163+ let path_u8: & [ u8 ; 11 ] = b"/refs/heads" ;
164+ let path_bstring: BString = "/refs/heads" . into ( ) ;
165+
166+ assert ! ( matches!(
167+ TryInto :: <& RelativePath >:: try_into( path_str) ,
168+ Err ( Error :: IsAbsolute )
169+ ) ) ;
170+ assert ! ( matches!(
171+ TryInto :: <& RelativePath >:: try_into( path_bstr) ,
172+ Err ( Error :: IsAbsolute )
173+ ) ) ;
174+ assert ! ( matches!(
175+ TryInto :: <& RelativePath >:: try_into( path_u8) ,
176+ Err ( Error :: IsAbsolute )
177+ ) ) ;
178+ assert ! ( matches!(
179+ TryInto :: <& RelativePath >:: try_into( & path_bstring) ,
180+ Err ( Error :: IsAbsolute )
181+ ) ) ;
182+ }
183+ }
0 commit comments