Skip to content

Commit

Permalink
feat: predefined gitlab vars
Browse files Browse the repository at this point in the history
Imported predefined gitlab vars for autocomplete.
  • Loading branch information
alesbrelih committed Apr 6, 2024
1 parent 3dd9fae commit fa4d300
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 100 deletions.
36 changes: 36 additions & 0 deletions src/gitlab_ci_ls_parser/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,42 @@ impl LSPHandlers {
let mut all_stages = self.stages.lock().unwrap();
let mut all_variables = self.variables.lock().unwrap();

info!("importing files from base");
let base_uri = format!("{}base", self.cfg.cache_path);
let base_uri_path = Url::parse(format!("file://{base_uri}/").as_str())?;
for dir in std::fs::read_dir(&base_uri)?.flatten() {
let file_uri = base_uri_path.join(dir.file_name().to_str().unwrap())?;
let file_content = std::fs::read_to_string(dir.path())?;

if let Some(results) = self.parser.parse_contents(&file_uri, &file_content, false) {
for file in results.files {
info!("found file: {:?}", &file);
store.insert(file.path, file.content);
}

for node in results.nodes {
info!("found node: {:?}", &node);
let content = node.content.unwrap_or(String::new());

all_nodes
.entry(node.uri)
.or_default()
.insert(node.key, content);
}

for stage in results.stages {
info!("found stage: {:?}", &stage);
all_stages.insert(stage.key.clone(), stage);
}

for variable in results.variables {
info!("found variable: {:?}", &variable);
all_variables.insert(variable.key.clone(), variable);
}
}
}

info!("importing from root file");
let mut uri = Url::parse(format!("file://{root_dir}/").as_str())?;
info!("uri: {}", &uri);

Expand Down
197 changes: 99 additions & 98 deletions src/gitlab_ci_ls_parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,23 +260,109 @@ impl Parser for ParserImpl {
parse_results.stages = found_stages;
}

let element = self
if let Some(element) = self
.treesitter
.get_root_node(uri.as_str(), content, "include")?;
.get_root_node(uri.as_str(), content, "include")
{
let documents = YamlLoader::load_from_str(element.content?.as_str()).ok()?;
let content = &documents[0];
if let Yaml::Hash(include_root) = content {
for (_, root) in include_root {
if let Yaml::Array(includes) = root {
for include in includes {
if let Yaml::Hash(item) = include {
let mut remote_pkg = String::new();
let mut remote_tag = String::new();
let mut remote_files: Vec<String> = vec![];

for (key, item_value) in item {
if follow && !remote_pkg.is_empty() {
let remote_files = match self.git.fetch_remote_repository(
remote_pkg.as_str(),
remote_tag.as_str(),
&remote_files,
) {
Ok(rf) => rf,
Err(err) => {
error!("error retrieving remote files: {}", err);

vec![]
}
};

let documents = YamlLoader::load_from_str(element.content?.as_str()).ok()?;
let content = &documents[0];
self.parse_remote_files(parse_results, &remote_files);
}

if let Yaml::Hash(include_root) = content {
for (_, root) in include_root {
if let Yaml::Array(includes) = root {
for include in includes {
if let Yaml::Hash(item) = include {
let mut remote_pkg = String::new();
let mut remote_tag = String::new();
let mut remote_files: Vec<String> = vec![];
if let Yaml::String(key_str) = key {
match key_str.trim().to_lowercase().as_str() {
"local" => {
if let Yaml::String(value) = item_value {
let current_uri =
uri.join(value.as_str()).ok()?;
let current_content =
std::fs::read_to_string(current_uri.path())
.ok()?;

if follow {
self.parse_contents_recursive(
parse_results,
&current_uri,
&current_content,
follow,
iteration + 1,
);
}
}
}
"remote" => {
if let Yaml::String(value) = item_value {
let remote_url = match Url::parse(value) {
Ok(f) => f,
Err(err) => {
error!("could not parse remote URL: {}; got err: {:?}", value, err);
continue;
}
};

let file = match self
.git
.fetch_remote(remote_url.clone())
{
Ok(res) => res,
Err(err) => {
error!("error retrieving remote file: {}; got err: {:?}", remote_url, err);
continue;
}
};

self.parse_remote_files(parse_results, &[file]);
}
}
"project" => {
if let Yaml::String(value) = item_value {
remote_pkg = value.clone();
}
}
"ref" => {
if let Yaml::String(value) = item_value {
remote_tag = value.clone();
}
}
"file" => {
debug!("files: {:?}", item_value);
if let Yaml::Array(value) = item_value {
for yml in value {
if let Yaml::String(p) = yml {
remote_files.push(p.to_string());
}
}
}
}
_ => break,
}
}
}

for (key, item_value) in item {
if follow && !remote_pkg.is_empty() {
let remote_files = match self.git.fetch_remote_repository(
remote_pkg.as_str(),
Expand All @@ -293,91 +379,6 @@ impl Parser for ParserImpl {

self.parse_remote_files(parse_results, &remote_files);
}

if let Yaml::String(key_str) = key {
match key_str.trim().to_lowercase().as_str() {
"local" => {
if let Yaml::String(value) = item_value {
let current_uri = uri.join(value.as_str()).ok()?;
let current_content =
std::fs::read_to_string(current_uri.path())
.ok()?;

if follow {
self.parse_contents_recursive(
parse_results,
&current_uri,
&current_content,
follow,
iteration + 1,
);
}
}
}
"remote" => {
if let Yaml::String(value) = item_value {
let remote_url = match Url::parse(value) {
Ok(f) => f,
Err(err) => {
error!("could not parse remote URL: {}; got err: {:?}", value, err);
continue;
}
};

let file = match self
.git
.fetch_remote(remote_url.clone())
{
Ok(res) => res,
Err(err) => {
error!("error retrieving remote file: {}; got err: {:?}", remote_url, err);
continue;
}
};

self.parse_remote_files(parse_results, &[file]);
}
}
"project" => {
if let Yaml::String(value) = item_value {
remote_pkg = value.clone();
}
}
"ref" => {
if let Yaml::String(value) = item_value {
remote_tag = value.clone();
}
}
"file" => {
debug!("files: {:?}", item_value);
if let Yaml::Array(value) = item_value {
for yml in value {
if let Yaml::String(p) = yml {
remote_files.push(p.to_string());
}
}
}
}
_ => break,
}
}
}

if follow && !remote_pkg.is_empty() {
let remote_files = match self.git.fetch_remote_repository(
remote_pkg.as_str(),
remote_tag.as_str(),
&remote_files,
) {
Ok(rf) => rf,
Err(err) => {
error!("error retrieving remote files: {}", err);

vec![]
}
};

self.parse_remote_files(parse_results, &remote_files);
}
}
}
Expand Down
21 changes: 19 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::anyhow;
use git2::Repository;
use log::{error, info, LevelFilter};
use regex::Regex;
Expand All @@ -11,7 +12,8 @@ use lsp_types::{

use std::collections::HashMap;
use std::error::Error;
use std::fs;
use std::fs::{self, File};
use std::io::Write;
use std::path::Path;

use crate::gitlab_ci_ls_parser::messages;
Expand Down Expand Up @@ -142,7 +144,7 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
.filter_map(|remote| get_remote_hosts(remote.as_str()))
.collect();

// get_remote_urls(repo.remotes()?.iter())?;
save_base_files(&init_params)?;

let lsp_events =
gitlab_ci_ls_parser::handlers::LSPHandlers::new(gitlab_ci_ls_parser::LSPConfig {
Expand All @@ -161,6 +163,21 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
Ok(())
}

fn save_base_files(init_params: &InitializationParams) -> anyhow::Result<()> {
let base_path = format!("{}base", init_params.initialization_options.cache_path);
fs::create_dir_all(&base_path)?;

let gitlab_predefined = include_str!("./resources/gitlab_predefined_vars.yaml");
let gitlab_predefined_path = format!("{base_path}/gitlab_predefined_vars.yaml");
info!("predefined path: {}", gitlab_predefined_path);

let mut file = File::create(&gitlab_predefined_path)
.map_err(|e| anyhow!("error creating file: {gitlab_predefined_path}; got err: {e}"))?;
file.write_all(gitlab_predefined.as_bytes())?;

Ok(())
}

fn get_remote_hosts(remote: &str) -> Option<String> {
let re = Regex::new(r"^(ssh://)?([^:/]+@[^:/]+(?::\d+)?[:/])").expect("Invalid REGEX");
let captures = re.captures(remote)?;
Expand Down
Loading

0 comments on commit fa4d300

Please sign in to comment.