mirror of
https://github.com/github/codeql.git
synced 2025-12-22 11:46:32 +01:00
It is now called `tree-sitter-extractor`, to make it clearer that it builds on tree-sitter grammars.
136 lines
5.1 KiB
Rust
136 lines
5.1 KiB
Rust
use std::path::{Path, PathBuf};
|
|
|
|
/// Normalizes the path according the common CodeQL specification. Assumes that
|
|
/// `path` has already been canonicalized using `std::fs::canonicalize`.
|
|
pub fn normalize_path(path: &Path) -> String {
|
|
if cfg!(windows) {
|
|
// The way Rust canonicalizes paths doesn't match the CodeQL spec, so we
|
|
// have to do a bit of work removing certain prefixes and replacing
|
|
// backslashes.
|
|
let mut components: Vec<String> = Vec::new();
|
|
for component in path.components() {
|
|
match component {
|
|
std::path::Component::Prefix(prefix) => match prefix.kind() {
|
|
std::path::Prefix::Disk(letter) | std::path::Prefix::VerbatimDisk(letter) => {
|
|
components.push(format!("{}:", letter as char));
|
|
}
|
|
std::path::Prefix::Verbatim(x) | std::path::Prefix::DeviceNS(x) => {
|
|
components.push(x.to_string_lossy().to_string());
|
|
}
|
|
std::path::Prefix::UNC(server, share)
|
|
| std::path::Prefix::VerbatimUNC(server, share) => {
|
|
components.push(server.to_string_lossy().to_string());
|
|
components.push(share.to_string_lossy().to_string());
|
|
}
|
|
},
|
|
std::path::Component::Normal(n) => {
|
|
components.push(n.to_string_lossy().to_string());
|
|
}
|
|
std::path::Component::RootDir => {}
|
|
std::path::Component::CurDir => {}
|
|
std::path::Component::ParentDir => {}
|
|
}
|
|
}
|
|
components.join("/")
|
|
} else {
|
|
// For other operating systems, we can use the canonicalized path
|
|
// without modifications.
|
|
format!("{}", path.display())
|
|
}
|
|
}
|
|
|
|
/// Convert a user-supplied path to an absolute path, and convert it to a verbatim path on Windows.
|
|
pub fn path_from_string(path: &str) -> PathBuf {
|
|
let mut path = PathBuf::from(path);
|
|
// make path absolute
|
|
if path.is_relative() {
|
|
path = std::env::current_dir().unwrap().join(path)
|
|
};
|
|
let mut components = path.components();
|
|
|
|
// make Windows paths verbatim (with `\\?\` prefixes) which allow for extended-length paths.
|
|
let mut result = match components.next() {
|
|
None => unreachable!("empty path"),
|
|
|
|
Some(component) => match component {
|
|
std::path::Component::Prefix(prefix) => match prefix.kind() {
|
|
std::path::Prefix::Disk(drive) => {
|
|
let root = format!(r"\\?\{}:\", drive as char);
|
|
PathBuf::from(root)
|
|
}
|
|
std::path::Prefix::UNC(server, share) => {
|
|
let mut root = std::ffi::OsString::from(r"\\?\UNC\");
|
|
root.push(server);
|
|
root.push(r"\");
|
|
root.push(share);
|
|
PathBuf::from(root)
|
|
}
|
|
std::path::Prefix::Verbatim(_)
|
|
| std::path::Prefix::VerbatimUNC(_, _)
|
|
| std::path::Prefix::VerbatimDisk(_)
|
|
| std::path::Prefix::DeviceNS(_) => Path::new(&component).to_path_buf(),
|
|
},
|
|
_ => Path::new(&component).to_path_buf(),
|
|
},
|
|
};
|
|
// remove `.` and `..` components
|
|
for component in components {
|
|
match component {
|
|
std::path::Component::CurDir => continue,
|
|
std::path::Component::ParentDir => {
|
|
result.pop();
|
|
}
|
|
_ => result.push(component),
|
|
}
|
|
}
|
|
result
|
|
}
|
|
|
|
pub fn path_for(dir: &Path, path: &Path, ext: &str) -> PathBuf {
|
|
let mut result = PathBuf::from(dir);
|
|
for component in path.components() {
|
|
match component {
|
|
std::path::Component::Prefix(prefix) => match prefix.kind() {
|
|
std::path::Prefix::Disk(letter) | std::path::Prefix::VerbatimDisk(letter) => {
|
|
result.push(format!("{}_", letter as char))
|
|
}
|
|
std::path::Prefix::Verbatim(x) | std::path::Prefix::DeviceNS(x) => {
|
|
result.push(x);
|
|
}
|
|
std::path::Prefix::UNC(server, share)
|
|
| std::path::Prefix::VerbatimUNC(server, share) => {
|
|
result.push("unc");
|
|
result.push(server);
|
|
result.push(share);
|
|
}
|
|
},
|
|
std::path::Component::RootDir => {
|
|
// skip
|
|
}
|
|
std::path::Component::Normal(_) => {
|
|
result.push(component);
|
|
}
|
|
std::path::Component::CurDir => {
|
|
// skip
|
|
}
|
|
std::path::Component::ParentDir => {
|
|
result.pop();
|
|
}
|
|
}
|
|
}
|
|
if !ext.is_empty() {
|
|
match result.extension() {
|
|
Some(x) => {
|
|
let mut new_ext = x.to_os_string();
|
|
new_ext.push(".");
|
|
new_ext.push(ext);
|
|
result.set_extension(new_ext);
|
|
}
|
|
None => {
|
|
result.set_extension(ext);
|
|
}
|
|
}
|
|
}
|
|
result
|
|
}
|