Skip to content

Commit 8f7c103

Browse files
authored
Do not resolve symlinks for config paths (#331)
Resolving symbolic links can cause issues in certain read-only file systems. The approach of simply canonicalising a path was replaced by retrieving the absolute path and a subsequent simplification (the latter to avoid regression from #115)
1 parent 892ec09 commit 8f7c103

File tree

1 file changed

+44
-42
lines changed

1 file changed

+44
-42
lines changed

vhdl_lang/src/data/source.rs

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::io;
1616
pub use std::path::{Path, PathBuf};
1717
use std::sync::Arc;
1818

19+
#[derive(Debug)]
1920
struct FileId {
2021
name: FilePath,
2122
/// Hash value of `self.name`.
@@ -24,11 +25,9 @@ struct FileId {
2425

2526
impl FileId {
2627
fn new(name: &Path) -> FileId {
27-
let hash = hash(name);
28-
Self {
29-
name: FilePath::new(name),
30-
hash,
31-
}
28+
let name = FilePath::new(name);
29+
let hash = hash(&name);
30+
Self { name, hash }
3231
}
3332
}
3433

@@ -58,7 +57,10 @@ struct UniqueSource {
5857
impl fmt::Debug for UniqueSource {
5958
/// Custom implementation to avoid large contents strings.
6059
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61-
write!(f, "Source {{file_name: {:?}}}", self.file_name())
60+
f.debug_struct(stringify!(UniqueSource))
61+
.field(stringify!(file_id), &self.file_id)
62+
.field(stringify!(contents), &"...")
63+
.finish()
6264
}
6365
}
6466

@@ -102,13 +104,11 @@ impl UniqueSource {
102104
/// A thread-safe reference to a source file.
103105
/// Multiple objects of this type can refer to the same source.
104106
#[derive(Debug, Clone)]
105-
pub struct Source {
106-
source: Arc<UniqueSource>,
107-
}
107+
pub struct Source(Arc<UniqueSource>);
108108

109109
impl PartialEq for Source {
110110
fn eq(&self, other: &Self) -> bool {
111-
self.source.file_id == other.source.file_id
111+
self.0.file_id == other.0.file_id
112112
}
113113
}
114114

@@ -120,15 +120,15 @@ impl PartialOrd for Source {
120120

121121
impl Ord for Source {
122122
fn cmp(&self, other: &Source) -> std::cmp::Ordering {
123-
self.source.file_name().cmp(other.file_name())
123+
self.file_name().cmp(other.file_name())
124124
}
125125
}
126126

127127
impl Eq for Source {}
128128

129129
impl Hash for Source {
130130
fn hash<H: Hasher>(&self, hasher: &mut H) {
131-
hasher.write_u64(self.source.file_id.hash)
131+
hasher.write_u64(self.0.file_id.hash)
132132
}
133133
}
134134

@@ -138,34 +138,28 @@ impl Source {
138138
/// Note: For differing values of `contents`, the value of `file_name`
139139
/// *must* differ as well.
140140
pub fn inline(file_name: &Path, contents: &str) -> Source {
141-
Source {
142-
source: Arc::new(UniqueSource::inline(file_name, contents)),
143-
}
141+
Source(Arc::new(UniqueSource::inline(file_name, contents)))
144142
}
145143

146144
pub fn from_latin1_file(file_name: &Path) -> io::Result<Source> {
147-
Ok(Source {
148-
source: Arc::new(UniqueSource::from_latin1_file(file_name)?),
149-
})
145+
Ok(Source(Arc::new(UniqueSource::from_latin1_file(file_name)?)))
150146
}
151147

152148
#[cfg(test)]
153149
pub fn from_contents(file_name: &Path, contents: Contents) -> Source {
154-
Source {
155-
source: Arc::new(UniqueSource::from_contents(file_name, contents)),
156-
}
150+
Source(Arc::new(UniqueSource::from_contents(file_name, contents)))
157151
}
158152

159153
pub fn contents(&self) -> RwLockReadGuard<'_, Contents> {
160-
self.source.contents()
154+
self.0.contents()
161155
}
162156

163157
pub fn file_name(&self) -> &Path {
164-
self.source.file_name()
158+
self.0.file_name()
165159
}
166160

167161
pub(crate) fn file_path(&self) -> &FilePath {
168-
self.source.file_path()
162+
self.0.file_path()
169163
}
170164

171165
pub fn pos(&self, start: Position, end: Position) -> SrcPos {
@@ -176,7 +170,7 @@ impl Source {
176170
}
177171

178172
pub fn change(&self, range: Option<&Range>, content: &str) {
179-
let mut contents = self.source.contents.write();
173+
let mut contents = self.0.contents.write();
180174
if let Some(range) = range {
181175
contents.change(range, content);
182176
} else {
@@ -528,36 +522,44 @@ impl<T: HasSrcPos> HasSource for T {
528522
}
529523
}
530524

531-
/// A wrapper arround a PathBuf that ensures the path is canoninicalized
532-
#[derive(PartialEq, Eq, Hash, Clone)]
533-
pub(crate) struct FilePath {
534-
path: PathBuf,
535-
}
525+
/// A wrapper around a PathBuf that ensures the path is absolute and simplified.
526+
///
527+
/// This struct can be used similar to a [PathBuf], i.e., dereferencing it will return a [Path]
528+
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
529+
pub(crate) struct FilePath(PathBuf);
536530

537531
impl std::ops::Deref for FilePath {
538532
type Target = Path;
539533
fn deref(&self) -> &Self::Target {
540-
&self.path
534+
&self.0
541535
}
542536
}
543537

544538
impl FilePath {
545539
pub fn new(path: &Path) -> Self {
546-
let path = match dunce::canonicalize(path) {
547-
Ok(path) => path,
540+
// In tests, when using inline files, paths are used that do not point to an existing file.
541+
// In this case, we simply want to preserve the name without changing it.
542+
if cfg!(test) && !path.exists() {
543+
return Self(path.to_owned());
544+
}
545+
// It would also be possible to use dunce::canonicalize here instead of path::absolute
546+
// and dunce::simplify, but dunce::canonicalize resolves symlinks
547+
// which we don't want (see issue #327)
548+
let path = match std::path::absolute(path) {
549+
// dunce::simplified converts UNC paths to regular paths.
550+
// UNC paths have caused issues when a file was mounted on a network drive.
551+
// Related issue: #115
552+
Ok(path) => dunce::simplified(&path).to_owned(),
548553
Err(err) => {
549-
if !cfg!(test) {
550-
eprintln!(
551-
"Could not create absolute path {}: {:?}",
552-
path.to_string_lossy(),
553-
err
554-
);
555-
}
554+
eprintln!(
555+
"Could not create absolute path {}: {:?}",
556+
path.to_string_lossy(),
557+
err
558+
);
556559
path.to_owned()
557560
}
558561
};
559-
560-
Self { path }
562+
Self(path)
561563
}
562564
}
563565

0 commit comments

Comments
 (0)