Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

git: refactoring the lookup config file #241

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 111 additions & 74 deletions coffee_github/src/repository.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::any::Any;
use std::path::Path;

use async_trait::async_trait;
use git2;

Check warning on line 5 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

the item `git2` is imported redundantly

Check warning on line 5 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

the item `git2` is imported redundantly
use log::debug;
use tokio::fs::File;
use tokio::io::AsyncReadExt;
Expand Down Expand Up @@ -51,6 +52,12 @@
.unwrap_or(false)
}

struct IndexingInfo {
config: Option<Conf>,
lang: PluginLang,
exec_path: String,
}

impl Github {
/// Create a new instance of the Repository
/// with a name and a url
Expand All @@ -66,6 +73,99 @@
}
}

// check if the plugin has the custom configuration to read.
async fn lookup_config_file(
&self,
root_path: &str,
) -> Result<Option<IndexingInfo>, CoffeeError> {
for file in ["coffee.yaml", "coffee.yml"] {
#[allow(unused_assignments)]
let mut plugin_lang = PluginLang::Unknown;
let conf_path = format!("{}/{}", root_path, file);
if let Ok(mut conf_file) = File::open(conf_path).await {
let mut conf_str = String::new();
conf_file.read_to_string(&mut conf_str).await?;
log::debug!("found plugin configuration: {}", conf_str);

let conf_file = serde_yaml::from_str::<Conf>(&conf_str)
.map_err(|err| error!("Coffee manifest malformed: {err}"))?;
let conf_lang = conf_file.plugin.lang.to_owned();
match conf_lang.as_str() {
"pypip" => plugin_lang = PluginLang::PyPip,
"pypoetry" => plugin_lang = PluginLang::PyPoetry,
"go" => plugin_lang = PluginLang::Go,
"rs" | "rust" => plugin_lang = PluginLang::Rust,
"dart" => plugin_lang = PluginLang::Dart,
"js" => plugin_lang = PluginLang::JavaScript,
"ts" => plugin_lang = PluginLang::TypeScript,
"java" | "kotlin" | "scala" => plugin_lang = PluginLang::JVM,
_ => {
return Err(error!("language {conf_lang} not supported"));
}
};

let exec_path = format!("{root_path}/{}", conf_file.plugin.main);
return Ok(Some(IndexingInfo {
config: Some(conf_file),
lang: plugin_lang,
exec_path,
}));
}
}
Ok(None)
}

/// When a configuration file is not found this function is called
/// and we try to guess the programming language used.
async fn try_guess_language(
&self,
plugin_path: &Path,
) -> Result<Option<IndexingInfo>, CoffeeError> {
log::debug!("conf file not found, so we try to guess the language");
// try to understand the language from the file
let files = WalkDir::new(plugin_path).max_depth(1);
for file in files {
let file_dir = file.unwrap().clone();
let (derived_root_path, derived_name) = get_plugin_info_from_path(file_dir.path())?;
let exec_path = None;
let plugin_name = Some(derived_name.to_string());

Check warning on line 131 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `plugin_name`

Check warning on line 131 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `plugin_name`

Check warning on line 131 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `plugin_name`

Check warning on line 131 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `plugin_name`

Check warning on line 131 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `plugin_name`

Check warning on line 131 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `plugin_name`
debug!("looking for {derived_name} in {derived_root_path}");
let file_name = file_dir.file_name().to_str().unwrap();
let plugin_lang = match file_name {
"requirements.txt" => {
let exec_path = Some(format!("{derived_root_path}/{derived_name}.py"));

Check warning on line 136 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `exec_path`

Check warning on line 136 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `exec_path`

Check warning on line 136 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `exec_path`

Check warning on line 136 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `exec_path`

Check warning on line 136 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `exec_path`

Check warning on line 136 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `exec_path`
PluginLang::PyPip
}
"pyproject.toml" => {
let exec_path = Some(format!("{derived_root_path}/{derived_name}.py"));

Check warning on line 140 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `exec_path`

Check warning on line 140 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `exec_path`

Check warning on line 140 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `exec_path`

Check warning on line 140 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `exec_path`

Check warning on line 140 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `exec_path`

Check warning on line 140 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `exec_path`
PluginLang::PyPoetry
}
// We dot have any information on standard pattern on where to find the
// plugin exec path, so for now we skip the indexing!
//
// N.B: The plugin should use the coffee manifest, period.
"go.mod" => PluginLang::Go,
"cargo.toml" => PluginLang::Rust,
"pubspec.yaml" => PluginLang::Dart,
"package.json" => PluginLang::JavaScript,
"tsconfig.json" => PluginLang::TypeScript,
_ => PluginLang::Unknown,
};
if plugin_lang != PluginLang::Unknown {
// TODO: call recursive to look under sub directory
break;
} else {
return Ok(Some(IndexingInfo {
exec_path: exec_path.unwrap(),
config: None,
lang: plugin_lang,
}));
}
}
// There is nothing in this path
Ok(None)
}

/// Index the repository to store information
/// related to the plugins
pub async fn index_repository(&mut self) -> Result<(), CoffeeError> {
Expand All @@ -85,82 +185,19 @@
.to_os_string()
.to_string_lossy()
.to_string();
let mut conf = None;
let mut exec_path = None;
let mut plugin_name = None;
let mut plugin_lang = PluginLang::Unknown;

// check if the plugin has the custom configuration to read.
let mut conf = None;
for file in ["coffee.yaml", "coffee.yml"] {
let conf_path = format!("{}/{}", root_path, file);
if let Ok(mut conf_file) = File::open(conf_path).await {
let mut conf_str = String::new();
conf_file.read_to_string(&mut conf_str).await?;
debug!("found plugin configuration: {}", conf_str);

let conf_file = serde_yaml::from_str::<Conf>(&conf_str)
.map_err(|err| error!("Coffee manifest malformed: {err}"))?;
plugin_name = Some(conf_file.plugin.name.to_string());
let conf_lang = conf_file.plugin.lang.to_owned();
match conf_lang.as_str() {
"pypip" => plugin_lang = PluginLang::PyPip,
"pypoetry" => plugin_lang = PluginLang::PyPoetry,
"go" => plugin_lang = PluginLang::Go,
"rs" | "rust" => plugin_lang = PluginLang::Rust,
"dart" => plugin_lang = PluginLang::Dart,
"js" => plugin_lang = PluginLang::JavaScript,
"ts" => plugin_lang = PluginLang::TypeScript,
"java" | "kotlin" | "scala" => plugin_lang = PluginLang::JVM,
_ => {
return Err(error!("language {conf_lang} not supported"));
}
};

exec_path = Some(format!("{root_path}/{}", conf_file.plugin.main));
conf = Some(conf_file);
break;
}
}

// check if there was a coffee configuration file
if conf.is_none() {
debug!("conf file not found, so we try to guess the language");
// try to understand the language from the file
let files = WalkDir::new(plugin_path.path()).max_depth(1);
for file in files {
let file_dir = file.unwrap().clone();
let (derived_root_path, derived_name) =
get_plugin_info_from_path(file_dir.path())?;

plugin_name = Some(derived_name.to_string());
debug!("looking for {derived_name} in {derived_root_path}");
let file_name = file_dir.file_name().to_str().unwrap();
plugin_lang = match file_name {
"requirements.txt" => {
exec_path =
Some(format!("{derived_root_path}/{derived_name}.py"));
PluginLang::PyPip
}
"pyproject.toml" => {
exec_path =
Some(format!("{derived_root_path}/{derived_name}.py"));
PluginLang::PyPoetry
}
// We dot have any information on standard pattern on where to find the
// plugin exec path, so for now we skip the indexing!
//
// N.B: The plugin should use the coffee manifest, period.
"go.mod" => PluginLang::Go,
"cargo.toml" => PluginLang::Rust,
"pubspec.yaml" => PluginLang::Dart,
"package.json" => PluginLang::JavaScript,
"tsconfig.json" => PluginLang::TypeScript,
_ => PluginLang::Unknown,
};
if plugin_lang != PluginLang::Unknown {
break;
}
}
let mut plugin_name = None;
if let Some(index_info) = self.lookup_config_file(&root_path).await? {
exec_path = Some(index_info.exec_path);
plugin_lang = index_info.lang;
// SAFETY: it is safe to unwrap because a config gile has always a file
let config = index_info.config.clone().unwrap();
plugin_name = Some(config.plugin.name.to_owned());
conf = index_info.config;
} else {
let index_info = self.try_guess_language(plugin_path.path()).await?;

Check warning on line 200 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `index_info`

Check warning on line 200 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (nightly)

unused variable: `index_info`

Check warning on line 200 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `index_info`

Check warning on line 200 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (beta)

unused variable: `index_info`

Check warning on line 200 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `index_info`

Check warning on line 200 in coffee_github/src/repository.rs

View workflow job for this annotation

GitHub Actions / Build (stable)

unused variable: `index_info`
}
debug!("possible plugin language: {:?}", plugin_lang);
if exec_path.is_none() {
Expand Down
Loading