##// END OF EJS Templates
rhg: Propagate permission errors when finding a repository...
Simon Sapin -
r48584:cf5f8da2 stable
parent child Browse files
Show More
@@ -47,6 +47,8 b' pub enum HgError {'
47 /// Details about where an I/O error happened
47 /// Details about where an I/O error happened
48 #[derive(Debug)]
48 #[derive(Debug)]
49 pub enum IoErrorContext {
49 pub enum IoErrorContext {
50 /// `std::fs::metadata`
51 ReadingMetadata(std::path::PathBuf),
50 ReadingFile(std::path::PathBuf),
52 ReadingFile(std::path::PathBuf),
51 WritingFile(std::path::PathBuf),
53 WritingFile(std::path::PathBuf),
52 RemovingFile(std::path::PathBuf),
54 RemovingFile(std::path::PathBuf),
@@ -108,6 +110,9 b' impl fmt::Display for HgError {'
108 impl fmt::Display for IoErrorContext {
110 impl fmt::Display for IoErrorContext {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 match self {
112 match self {
113 IoErrorContext::ReadingMetadata(path) => {
114 write!(f, "when reading metadata of {}", path.display())
115 }
111 IoErrorContext::ReadingFile(path) => {
116 IoErrorContext::ReadingFile(path) => {
112 write!(f, "when reading {}", path.display())
117 write!(f, "when reading {}", path.display())
113 }
118 }
@@ -6,6 +6,7 b' use crate::utils::files::get_path_from_b'
6 use crate::utils::SliceExt;
6 use crate::utils::SliceExt;
7 use memmap::{Mmap, MmapOptions};
7 use memmap::{Mmap, MmapOptions};
8 use std::collections::HashSet;
8 use std::collections::HashSet;
9 use std::io::ErrorKind;
9 use std::path::{Path, PathBuf};
10 use std::path::{Path, PathBuf};
10
11
11 /// A repository on disk
12 /// A repository on disk
@@ -51,7 +52,7 b' impl Repo {'
51 // ancestors() is inclusive: it first yields `current_directory`
52 // ancestors() is inclusive: it first yields `current_directory`
52 // as-is.
53 // as-is.
53 for ancestor in current_directory.ancestors() {
54 for ancestor in current_directory.ancestors() {
54 if ancestor.join(".hg").is_dir() {
55 if is_dir(ancestor.join(".hg"))? {
55 return Ok(ancestor.to_path_buf());
56 return Ok(ancestor.to_path_buf());
56 }
57 }
57 }
58 }
@@ -73,9 +74,9 b' impl Repo {'
73 explicit_path: Option<PathBuf>,
74 explicit_path: Option<PathBuf>,
74 ) -> Result<Self, RepoError> {
75 ) -> Result<Self, RepoError> {
75 if let Some(root) = explicit_path {
76 if let Some(root) = explicit_path {
76 if root.join(".hg").is_dir() {
77 if is_dir(root.join(".hg"))? {
77 Self::new_at_path(root.to_owned(), config)
78 Self::new_at_path(root.to_owned(), config)
78 } else if root.is_file() {
79 } else if is_file(&root)? {
79 Err(HgError::unsupported("bundle repository").into())
80 Err(HgError::unsupported("bundle repository").into())
80 } else {
81 } else {
81 Err(RepoError::NotFound {
82 Err(RepoError::NotFound {
@@ -130,7 +131,7 b' impl Repo {'
130 if relative {
131 if relative {
131 shared_path = dot_hg.join(shared_path)
132 shared_path = dot_hg.join(shared_path)
132 }
133 }
133 if !shared_path.is_dir() {
134 if !is_dir(&shared_path)? {
134 return Err(HgError::corrupted(format!(
135 return Err(HgError::corrupted(format!(
135 ".hg/sharedpath points to nonexistent directory {}",
136 ".hg/sharedpath points to nonexistent directory {}",
136 shared_path.display()
137 shared_path.display()
@@ -286,3 +287,29 b" impl Vfs<'_> {"
286 .with_context(|| IoErrorContext::RenamingFile { from, to })
287 .with_context(|| IoErrorContext::RenamingFile { from, to })
287 }
288 }
288 }
289 }
290
291 fn fs_metadata(
292 path: impl AsRef<Path>,
293 ) -> Result<Option<std::fs::Metadata>, HgError> {
294 let path = path.as_ref();
295 match std::fs::metadata(path) {
296 Ok(meta) => Ok(Some(meta)),
297 Err(error) => match error.kind() {
298 // TODO: when we require a Rust version where `NotADirectory` is
299 // stable, invert this logic and return None for it and `NotFound`
300 // and propagate any other error.
301 ErrorKind::PermissionDenied => Err(error).with_context(|| {
302 IoErrorContext::ReadingMetadata(path.to_owned())
303 }),
304 _ => Ok(None),
305 },
306 }
307 }
308
309 fn is_dir(path: impl AsRef<Path>) -> Result<bool, HgError> {
310 Ok(fs_metadata(path)?.map_or(false, |meta| meta.is_dir()))
311 }
312
313 fn is_file(path: impl AsRef<Path>) -> Result<bool, HgError> {
314 Ok(fs_metadata(path)?.map_or(false, |meta| meta.is_file()))
315 }
General Comments 0
You need to be logged in to leave comments. Login now