1
0
mirror of https://github.com/Llewellynvdm/starship.git synced 2024-05-31 23:50:52 +00:00

perf(package): only try to read files that exist (#3904)

* perf(package): only try to read files that exist

Have refactored the package module to improve performance. Before this
change the module would try to open every single file that could contain
some package information until it found a valid version. This resulted
in a lot of unneeded disk IO. Have added a new fn, `read_file_from_pwd`
that uses the current context to check if that file already exists and
fast failing if it doesn't. From my local testing this speeds up the
package module from taking ~1ms to ~50µs in an empty directory.

* refactor: move read_file_from_pwd to context

* refactor(haskell): use read_files_from_pwd

* refactor(nodejs): use read_files_from_pwd
This commit is contained in:
Thomas O'Donnell 2022-04-25 16:18:01 +02:00 committed by GitHub
parent 4471e3654c
commit 2a650bfd14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 27 deletions

View File

@ -1,7 +1,7 @@
use crate::config::{ModuleConfig, StarshipConfig};
use crate::configs::StarshipRootConfig;
use crate::module::Module;
use crate::utils::{create_command, exec_timeout, CommandOutput};
use crate::utils::{create_command, exec_timeout, read_file, CommandOutput};
use crate::modules;
use crate::utils::{self, home_dir};
@ -342,6 +342,18 @@ impl<'a> Context<'a> {
.iter()
.find_map(|attempt| self.exec_cmd(attempt[0], &attempt[1..]))
}
/// Returns the string contents of a file from the current working directory
pub fn read_file_from_pwd(&self, file_name: &str) -> Option<String> {
if !self.try_begin_scan()?.set_files(&[file_name]).is_match() {
log::debug!(
"Not attempting to read {file_name} because, it was not found during scan."
);
return None;
}
read_file(self.current_dir.join(file_name)).ok()
}
}
#[derive(Debug)]

View File

@ -2,7 +2,6 @@ use super::{Context, Module, ModuleConfig};
use crate::configs::haskell::HaskellConfig;
use crate::formatter::StringFormatter;
use crate::utils;
/// Creates a module with the current Haskell version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -64,7 +63,7 @@ fn get_snapshot(context: &Context) -> Option<String> {
if !is_stack_project(context) {
return None;
}
let file_contents = utils::read_file(context.current_dir.join("stack.yaml")).ok()?;
let file_contents = context.read_file_from_pwd("stack.yaml")?;
let yaml = yaml_rust::YamlLoader::load_from_str(&file_contents).ok()?;
let version = yaml.first()?["resolver"]
.as_str()

View File

@ -2,7 +2,6 @@ use super::{Context, Module, ModuleConfig};
use crate::configs::nodejs::NodejsConfig;
use crate::formatter::{StringFormatter, VersionFormatter};
use crate::utils;
use once_cell::sync::Lazy;
use regex::Regex;
@ -10,7 +9,6 @@ use semver::Version;
use semver::VersionReq;
use serde_json as json;
use std::ops::Deref;
use std::path::Path;
/// Creates a module with the current Node.js version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -45,7 +43,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
})
.map_style(|variable| match variable {
"style" => {
let engines_version = get_engines_version(&context.current_dir);
let engines_version = get_engines_version(context);
let in_engines_range =
check_engines_version(nodejs_version.deref().as_ref()?, engines_version);
if in_engines_range {
@ -87,8 +85,8 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
Some(module)
}
fn get_engines_version(base_dir: &Path) -> Option<String> {
let json_str = utils::read_file(base_dir.join("package.json")).ok()?;
fn get_engines_version(context: &Context) -> Option<String> {
let json_str = context.read_file_from_pwd("package.json")?;
let package_json: json::Value = json::from_str(&json_str).ok()?;
let raw_version = package_json.get("engines")?.get("node")?.as_str()?;
Some(raw_version.to_string())

View File

@ -1,7 +1,6 @@
use super::{Context, Module, ModuleConfig};
use crate::configs::package::PackageConfig;
use crate::formatter::{StringFormatter, VersionFormatter};
use crate::utils;
use ini::Ini;
use quick_xml::events::Event as QXEvent;
@ -44,7 +43,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
}
fn get_node_package_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(&context.current_dir.join("package.json")).ok()?;
let file_contents = context.read_file_from_pwd("package.json")?;
let package_json: json::Value = json::from_str(&file_contents).ok()?;
if !config.display_private
@ -68,7 +67,7 @@ fn get_node_package_version(context: &Context, config: &PackageConfig) -> Option
}
fn get_poetry_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(&context.current_dir.join("pyproject.toml")).ok()?;
let file_contents = context.read_file_from_pwd("pyproject.toml")?;
let poetry_toml: toml::Value = toml::from_str(&file_contents).ok()?;
let raw_version = poetry_toml
.get("tool")?
@ -80,7 +79,7 @@ fn get_poetry_version(context: &Context, config: &PackageConfig) -> Option<Strin
}
fn get_setup_cfg_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("setup.cfg")).ok()?;
let file_contents = context.read_file_from_pwd("setup.cfg")?;
let ini = Ini::load_from_str(&file_contents).ok()?;
let raw_version = ini.get_from(Some("metadata"), "version")?;
@ -92,7 +91,7 @@ fn get_setup_cfg_version(context: &Context, config: &PackageConfig) -> Option<St
}
fn get_gradle_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("build.gradle")).ok()?;
let file_contents = context.read_file_from_pwd("build.gradle")?;
let re = Regex::new(r#"(?m)^version ['"](?P<version>[^'"]+)['"]$"#).unwrap();
let caps = re.captures(&file_contents)?;
@ -100,7 +99,7 @@ fn get_gradle_version(context: &Context, config: &PackageConfig) -> Option<Strin
}
fn get_composer_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("composer.json")).ok()?;
let file_contents = context.read_file_from_pwd("composer.json")?;
let composer_json: json::Value = json::from_str(&file_contents).ok()?;
let raw_version = composer_json.get("version")?.as_str()?;
@ -108,7 +107,7 @@ fn get_composer_version(context: &Context, config: &PackageConfig) -> Option<Str
}
fn get_julia_project_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("Project.toml")).ok()?;
let file_contents = context.read_file_from_pwd("Project.toml")?;
let project_toml: toml::Value = toml::from_str(&file_contents).ok()?;
let raw_version = project_toml.get("version")?.as_str()?;
@ -116,7 +115,7 @@ fn get_julia_project_version(context: &Context, config: &PackageConfig) -> Optio
}
fn get_helm_package_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("Chart.yaml")).ok()?;
let file_contents = context.read_file_from_pwd("Chart.yaml")?;
let yaml = yaml_rust::YamlLoader::load_from_str(&file_contents).ok()?;
let version = yaml.first()?["version"].as_str()?;
@ -124,7 +123,7 @@ fn get_helm_package_version(context: &Context, config: &PackageConfig) -> Option
}
fn get_mix_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("mix.exs")).ok()?;
let file_contents = context.read_file_from_pwd("mix.exs")?;
let re = Regex::new(r#"(?m)version: "(?P<version>[^"]+)""#).unwrap();
let caps = re.captures(&file_contents)?;
@ -132,8 +131,8 @@ fn get_mix_version(context: &Context, config: &PackageConfig) -> Option<String>
}
fn get_maven_version(context: &Context, config: &PackageConfig) -> Option<String> {
let pom_file = utils::read_file(context.current_dir.join("pom.xml")).ok()?;
let mut reader = QXReader::from_str(&pom_file);
let file_contents = context.read_file_from_pwd("pom.xml")?;
let mut reader = QXReader::from_str(&file_contents);
reader.trim_text(true);
let mut buf = vec![];
@ -171,8 +170,8 @@ fn get_maven_version(context: &Context, config: &PackageConfig) -> Option<String
}
fn get_meson_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("meson.build"))
.ok()?
let file_contents = context
.read_file_from_pwd("meson.build")?
.split_ascii_whitespace()
.collect::<String>();
@ -183,14 +182,14 @@ fn get_meson_version(context: &Context, config: &PackageConfig) -> Option<String
}
fn get_vmod_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("v.mod")).ok()?;
let file_contents = context.read_file_from_pwd("v.mod")?;
let re = Regex::new(r"(?m)^\s*version\s*:\s*'(?P<version>[^']+)'").unwrap();
let caps = re.captures(&file_contents)?;
format_version(&caps["version"], config.version_format)
}
fn get_vpkg_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("vpkg.json")).ok()?;
let file_contents = context.read_file_from_pwd("vpkg.json")?;
let vpkg_json: json::Value = json::from_str(&file_contents).ok()?;
let raw_version = vpkg_json.get("version")?.as_str()?;
@ -198,14 +197,14 @@ fn get_vpkg_version(context: &Context, config: &PackageConfig) -> Option<String>
}
fn get_sbt_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(context.current_dir.join("build.sbt")).ok()?;
let file_contents = context.read_file_from_pwd("build.sbt")?;
let re = Regex::new(r"(?m)^(.*/)*\s*version\s*:=\s*.(?P<version>[\d\.]+)").unwrap();
let caps = re.captures(&file_contents)?;
format_version(&caps["version"], config.version_format)
}
fn get_cargo_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(&context.current_dir.join("Cargo.toml")).ok()?;
let file_contents = context.read_file_from_pwd("Cargo.toml")?;
let cargo_toml: toml::Value = toml::from_str(&file_contents).ok()?;
let raw_version = cargo_toml.get("package")?.get("version")?.as_str()?;
@ -231,7 +230,7 @@ fn get_nimble_version(context: &Context, config: &PackageConfig) -> Option<Strin
}
fn get_shard_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(&context.current_dir.join("shard.yml")).ok()?;
let file_contents = context.read_file_from_pwd("shard.yml")?;
let data = yaml_rust::YamlLoader::load_from_str(&file_contents).ok()?;
let raw_version = data.first()?["version"].as_str()?;
@ -240,7 +239,7 @@ fn get_shard_version(context: &Context, config: &PackageConfig) -> Option<String
}
fn get_dart_pub_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = utils::read_file(&context.current_dir.join("pubspec.yaml")).ok()?;
let file_contents = context.read_file_from_pwd("pubspec.yaml")?;
let data = yaml_rust::YamlLoader::load_from_str(&file_contents).ok()?;
let raw_version = data.first()?["version"].as_str()?;