rust/hg-core/src/utils/hg_path.rs
changeset 44265 c18dd48cea4a
parent 44191 732098027b34
child 44266 9ab4830e9e3d
equal deleted inserted replaced
44264:d3f776c4760e 44265:c18dd48cea4a
    13 
    13 
    14 #[derive(Debug, Eq, PartialEq)]
    14 #[derive(Debug, Eq, PartialEq)]
    15 pub enum HgPathError {
    15 pub enum HgPathError {
    16     /// Bytes from the invalid `HgPath`
    16     /// Bytes from the invalid `HgPath`
    17     LeadingSlash(Vec<u8>),
    17     LeadingSlash(Vec<u8>),
    18     /// Bytes and index of the second slash
    18     ConsecutiveSlashes {
    19     ConsecutiveSlashes(Vec<u8>, usize),
    19         bytes: Vec<u8>,
    20     /// Bytes and index of the null byte
    20         second_slash_index: usize,
    21     ContainsNullByte(Vec<u8>, usize),
    21     },
       
    22     ContainsNullByte {
       
    23         bytes: Vec<u8>,
       
    24         null_byte_index: usize,
       
    25     },
    22     /// Bytes
    26     /// Bytes
    23     DecodeError(Vec<u8>),
    27     DecodeError(Vec<u8>),
       
    28     /// The rest come from audit errors
       
    29     EndsWithSlash(HgPathBuf),
       
    30     ContainsIllegalComponent(HgPathBuf),
       
    31     /// Path is inside the `.hg` folder
       
    32     InsideDotHg(HgPathBuf),
       
    33     IsInsideNestedRepo {
       
    34         path: HgPathBuf,
       
    35         nested_repo: HgPathBuf,
       
    36     },
       
    37     TraversesSymbolicLink {
       
    38         path: HgPathBuf,
       
    39         symlink: HgPathBuf,
       
    40     },
       
    41     NotFsCompliant(HgPathBuf),
       
    42     /// `path` is the smallest invalid path
       
    43     NotUnderRoot {
       
    44         path: PathBuf,
       
    45         root: PathBuf,
       
    46     },
    24 }
    47 }
    25 
    48 
    26 impl ToString for HgPathError {
    49 impl ToString for HgPathError {
    27     fn to_string(&self) -> String {
    50     fn to_string(&self) -> String {
    28         match self {
    51         match self {
    29             HgPathError::LeadingSlash(bytes) => {
    52             HgPathError::LeadingSlash(bytes) => {
    30                 format!("Invalid HgPath '{:?}': has a leading slash.", bytes)
    53                 format!("Invalid HgPath '{:?}': has a leading slash.", bytes)
    31             }
    54             }
    32             HgPathError::ConsecutiveSlashes(bytes, pos) => format!(
    55             HgPathError::ConsecutiveSlashes {
    33                 "Invalid HgPath '{:?}': consecutive slahes at pos {}.",
    56                 bytes,
       
    57                 second_slash_index: pos,
       
    58             } => format!(
       
    59                 "Invalid HgPath '{:?}': consecutive slashes at pos {}.",
    34                 bytes, pos
    60                 bytes, pos
    35             ),
    61             ),
    36             HgPathError::ContainsNullByte(bytes, pos) => format!(
    62             HgPathError::ContainsNullByte {
       
    63                 bytes,
       
    64                 null_byte_index: pos,
       
    65             } => format!(
    37                 "Invalid HgPath '{:?}': contains null byte at pos {}.",
    66                 "Invalid HgPath '{:?}': contains null byte at pos {}.",
    38                 bytes, pos
    67                 bytes, pos
    39             ),
    68             ),
    40             HgPathError::DecodeError(bytes) => {
    69             HgPathError::DecodeError(bytes) => {
    41                 format!("Invalid HgPath '{:?}': could not be decoded.", bytes)
    70                 format!("Invalid HgPath '{:?}': could not be decoded.", bytes)
    42             }
    71             }
       
    72             HgPathError::EndsWithSlash(path) => {
       
    73                 format!("Audit failed for '{}': ends with a slash.", path)
       
    74             }
       
    75             HgPathError::ContainsIllegalComponent(path) => format!(
       
    76                 "Audit failed for '{}': contains an illegal component.",
       
    77                 path
       
    78             ),
       
    79             HgPathError::InsideDotHg(path) => format!(
       
    80                 "Audit failed for '{}': is inside the '.hg' folder.",
       
    81                 path
       
    82             ),
       
    83             HgPathError::IsInsideNestedRepo {
       
    84                 path,
       
    85                 nested_repo: nested,
       
    86             } => format!(
       
    87                 "Audit failed for '{}': is inside a nested repository '{}'.",
       
    88                 path, nested
       
    89             ),
       
    90             HgPathError::TraversesSymbolicLink { path, symlink } => format!(
       
    91                 "Audit failed for '{}': traverses symbolic link '{}'.",
       
    92                 path, symlink
       
    93             ),
       
    94             HgPathError::NotFsCompliant(path) => format!(
       
    95                 "Audit failed for '{}': cannot be turned into a \
       
    96                  filesystem path.",
       
    97                 path
       
    98             ),
       
    99             HgPathError::NotUnderRoot { path, root } => format!(
       
   100                 "Audit failed for '{}': not under root {}.",
       
   101                 path.display(),
       
   102                 root.display()
       
   103             ),
    43         }
   104         }
    44     }
   105     }
    45 }
   106 }
    46 
   107 
    47 impl From<HgPathError> for std::io::Error {
   108 impl From<HgPathError> for std::io::Error {
   227             return Err(HgPathError::LeadingSlash(bytes.to_vec()));
   288             return Err(HgPathError::LeadingSlash(bytes.to_vec()));
   228         }
   289         }
   229         for (index, byte) in bytes.iter().enumerate() {
   290         for (index, byte) in bytes.iter().enumerate() {
   230             match byte {
   291             match byte {
   231                 0 => {
   292                 0 => {
   232                     return Err(HgPathError::ContainsNullByte(
   293                     return Err(HgPathError::ContainsNullByte {
   233                         bytes.to_vec(),
   294                         bytes: bytes.to_vec(),
   234                         index,
   295                         null_byte_index: index,
   235                     ))
   296                     })
   236                 }
   297                 }
   237                 b'/' => {
   298                 b'/' => {
   238                     if previous_byte.is_some() && previous_byte == Some(b'/') {
   299                     if previous_byte.is_some() && previous_byte == Some(b'/') {
   239                         return Err(HgPathError::ConsecutiveSlashes(
   300                         return Err(HgPathError::ConsecutiveSlashes {
   240                             bytes.to_vec(),
   301                             bytes: bytes.to_vec(),
   241                             index,
   302                             second_slash_index: index,
   242                         ));
   303                         });
   243                     }
   304                     }
   244                 }
   305                 }
   245                 _ => (),
   306                 _ => (),
   246             };
   307             };
   247             previous_byte = Some(*byte);
   308             previous_byte = Some(*byte);
   429         assert_eq!(
   490         assert_eq!(
   430             Err(HgPathError::LeadingSlash(b"/".to_vec())),
   491             Err(HgPathError::LeadingSlash(b"/".to_vec())),
   431             HgPath::new(b"/").check_state()
   492             HgPath::new(b"/").check_state()
   432         );
   493         );
   433         assert_eq!(
   494         assert_eq!(
   434             Err(HgPathError::ConsecutiveSlashes(b"a/b//c".to_vec(), 4)),
   495             Err(HgPathError::ConsecutiveSlashes {
       
   496                 bytes: b"a/b//c".to_vec(),
       
   497                 second_slash_index: 4
       
   498             }),
   435             HgPath::new(b"a/b//c").check_state()
   499             HgPath::new(b"a/b//c").check_state()
   436         );
   500         );
   437         assert_eq!(
   501         assert_eq!(
   438             Err(HgPathError::ContainsNullByte(b"a/b/\0c".to_vec(), 4)),
   502             Err(HgPathError::ContainsNullByte {
       
   503                 bytes: b"a/b/\0c".to_vec(),
       
   504                 null_byte_index: 4
       
   505             }),
   439             HgPath::new(b"a/b/\0c").check_state()
   506             HgPath::new(b"a/b/\0c").check_state()
   440         );
   507         );
   441         // TODO test HgPathError::DecodeError for the Windows implementation.
   508         // TODO test HgPathError::DecodeError for the Windows implementation.
   442         assert_eq!(true, HgPath::new(b"").is_valid());
   509         assert_eq!(true, HgPath::new(b"").is_valid());
   443         assert_eq!(true, HgPath::new(b"a/b/c").is_valid());
   510         assert_eq!(true, HgPath::new(b"a/b/c").is_valid());