Skip to content

Commit

Permalink
feat: add git and http extension
Browse files Browse the repository at this point in the history
  • Loading branch information
tsirysndr committed Mar 16, 2024
1 parent 4839946 commit 4fa3381
Show file tree
Hide file tree
Showing 16 changed files with 900 additions and 29 deletions.
310 changes: 298 additions & 12 deletions Cargo.lock

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions crates/core/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,54 @@ impl Graph {
}
}

pub fn execute_vertex(&mut self, id: &str) -> Result<(), String> {
let mut visited = vec![false; self.vertices.len()];
let mut stack = Vec::new();
let mut index = 0;
for (i, vertex) in self.vertices.iter().enumerate() {
if vertex.id == id {
index = i;
break;
}
}
stack.push(index);
while let Some(i) = stack.pop() {
if visited[i] {
continue;
}
visited[i] = true;
for edge in self.edges.iter().filter(|e| e.from == i) {
stack.push(edge.to);
}
let (tx, _rx) = mpsc::channel();

if self.vertices[i].label == "withWorkdir" {
if !Path::new(&self.vertices[i].command).exists() {
return Err(format!("Error: {}", self.vertices[i].id));
}
self.work_dir = self.vertices[i].command.clone();
continue;
}

match self.vertices[i].run(
self.runner.clone(),
tx,
Output::Stdout,
false,
&self.work_dir,
) {
Ok(status) => {
if !status.success() {
return Err(format!("Error: {}", self.vertices[i].id));
}
}
Err(e) => {
return Err(format!("Error: {}", e));
}
};
}
Ok(())
}
pub fn size(&self) -> usize {
self.vertices.len()
}
Expand Down
2 changes: 2 additions & 0 deletions crates/ext/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ version = "0.1.0"
anyhow = "1.0.80"
fluentci-types = {path = "../types"}
owo-colors = "4.0.0"
reqwest = {version = "0.11.26", features = ["rustls-tls", "blocking"], default-features = false}
sha256 = "1.5.0"
users = "0.11.0"
93 changes: 93 additions & 0 deletions crates/ext/src/git.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use std::{
io::{BufRead, BufReader},
process::{Command, ExitStatus, Stdio},
sync::mpsc::{self, Receiver, Sender},
thread,
};

use crate::{pkgx::Pkgx, Extension};
use anyhow::Error;
use fluentci_types::Output;

#[derive(Default)]
pub struct Git {}

impl Extension for Git {
fn exec(
&self,
url: &str,
tx: Sender<String>,
out: Output,
last_cmd: bool,
work_dir: &str,
) -> Result<ExitStatus, Error> {
self.setup()?;

if url.is_empty() {
return Ok(ExitStatus::default());
}

let (stdout_tx, stdout_rx): (Sender<String>, Receiver<String>) = mpsc::channel();
let (stderr_tx, stderr_rx): (Sender<String>, Receiver<String>) = mpsc::channel();

let mut child = Command::new("bash")
.arg("-c")
.arg(format!("git clone {}", url))
.current_dir(work_dir)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;

let stdout_tx_clone = stdout_tx.clone();
let stdout = child.stdout.take().unwrap();
let stderr = child.stderr.take().unwrap();

let out_clone = out.clone();
let tx_clone = tx.clone();

thread::spawn(move || {
let mut stdout = String::new();
while let Ok(line) = stdout_rx.recv() {
println!("{}", line);
stdout.push_str(&line);
stdout.push_str("\n");
}
if out_clone == Output::Stdout && last_cmd {
tx_clone.send(stdout).unwrap();
}
});

thread::spawn(move || {
let mut stderr = String::new();
while let Ok(line) = stderr_rx.recv() {
println!("{}", line);
stderr.push_str(&line);
stderr.push_str("\n");
}
if out == Output::Stderr && last_cmd {
tx.send(stderr).unwrap();
}
});

thread::spawn(move || {
let reader = BufReader::new(stdout);
for line in reader.lines() {
stdout_tx_clone.send(line.unwrap()).unwrap();
}
});

thread::spawn(move || {
let reader = BufReader::new(stderr);
for line in reader.lines() {
stderr_tx.send(line.unwrap()).unwrap();
}
});

child.wait().map_err(Error::from)
}

fn setup(&self) -> Result<(), Error> {
Pkgx::default().install(vec!["git"])?;
Ok(())
}
}
94 changes: 94 additions & 0 deletions crates/ext/src/http.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::{
io::{BufRead, BufReader},
process::{Command, ExitStatus, Stdio},
sync::mpsc::{self, Receiver, Sender},
thread,
};

use crate::{pkgx::Pkgx, Extension};
use anyhow::Error;
use fluentci_types::Output;

#[derive(Default)]
pub struct Http {}

impl Extension for Http {
fn exec(
&self,
url: &str,
tx: Sender<String>,
out: Output,
last_cmd: bool,
work_dir: &str,
) -> Result<ExitStatus, Error> {
self.setup()?;

if url.is_empty() {
return Ok(ExitStatus::default());
}

let (stdout_tx, stdout_rx): (Sender<String>, Receiver<String>) = mpsc::channel();
let (stderr_tx, stderr_rx): (Sender<String>, Receiver<String>) = mpsc::channel();

let filename = sha256::digest(url).to_string();
let mut child = Command::new("bash")
.arg("-c")
.arg(format!("curl -s {} -o {}", url, filename))
.current_dir(work_dir)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;

let stdout_tx_clone = stdout_tx.clone();
let stdout = child.stdout.take().unwrap();
let stderr = child.stderr.take().unwrap();

let out_clone = out.clone();
let tx_clone = tx.clone();

thread::spawn(move || {
let mut stdout = String::new();
while let Ok(line) = stdout_rx.recv() {
println!("{}", line);
stdout.push_str(&line);
stdout.push_str("\n");
}
if out_clone == Output::Stdout && last_cmd {
tx_clone.send(stdout).unwrap();
}
});

thread::spawn(move || {
let mut stderr = String::new();
while let Ok(line) = stderr_rx.recv() {
println!("{}", line);
stderr.push_str(&line);
stderr.push_str("\n");
}
if out == Output::Stderr && last_cmd {
tx.send(stderr).unwrap();
}
});

thread::spawn(move || {
let reader = BufReader::new(stdout);
for line in reader.lines() {
stdout_tx_clone.send(line.unwrap()).unwrap();
}
});

thread::spawn(move || {
let reader = BufReader::new(stderr);
for line in reader.lines() {
stderr_tx.send(line.unwrap()).unwrap();
}
});

child.wait().map_err(Error::from)
}

fn setup(&self) -> Result<(), Error> {
Pkgx::default().install(vec!["curl"])?;
Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/ext/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub mod devbox;
pub mod devenv;
pub mod envhub;
pub mod flox;
pub mod git;
pub mod http;
pub mod nix;
pub mod pkgx;
pub mod runner;
Expand Down
1 change: 1 addition & 0 deletions crates/graphql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ version = "0.1.0"
anyhow = "1.0.80"
async-graphql = "7.0.2"
async-graphql-actix-web = "7.0.2"
dirs = "5.0.1"
fluentci-core = {path = "../core", version = "0.1.0"}
fluentci-ext = {path = "../ext", version = "0.1.0"}
fluentci-types = {path = "../types", version = "0.1.0"}
Expand Down
22 changes: 18 additions & 4 deletions crates/graphql/src/schema/directory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::sync::{Arc, Mutex};
use std::{
fs::canonicalize,
path::Path,
sync::{Arc, Mutex},
};

use super::objects::{cache::Cache, directory::Directory};
use super::objects::directory::Directory;
use async_graphql::{Context, Error, Object, ID};
use fluentci_core::deps::{Graph, GraphCommand};
use uuid::Uuid;
Expand All @@ -10,9 +14,19 @@ pub struct DirectoryQuery;

#[Object]
impl DirectoryQuery {
async fn directory(&self, ctx: &Context<'_>) -> Result<Directory, Error> {
async fn directory(&self, ctx: &Context<'_>, path: String) -> Result<Directory, Error> {
let graph = ctx.data::<Arc<Mutex<Graph>>>().unwrap();
let mut graph = graph.lock().unwrap();

if !Path::new(&path).exists() && !path.starts_with("/") {
let dir = canonicalize(".").unwrap();
let dir = dir.to_str().unwrap();
let dir = format!("{}/{}", dir, path);
return Err(Error::new(format!("Path `{}` does not exist", dir)));
}

graph.work_dir = path.clone();

let id = Uuid::new_v4().to_string();
graph.execute(GraphCommand::AddVertex(
id.clone(),
Expand All @@ -23,7 +37,7 @@ impl DirectoryQuery {

drop(graph);

let directory = Directory { id: ID(id) };
let directory = Directory { id: ID(id), path };
Ok(directory)
}
}
6 changes: 3 additions & 3 deletions crates/graphql/src/schema/file.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::{Arc, Mutex};

use super::objects::{cache::Cache, directory::Directory, file::File};
use super::objects::file::File;
use async_graphql::{Context, Error, Object, ID};
use fluentci_core::deps::{Graph, GraphCommand};
use uuid::Uuid;
Expand All @@ -10,7 +10,7 @@ pub struct FileQuery;

#[Object]
impl FileQuery {
async fn file(&self, ctx: &Context<'_>) -> Result<File, Error> {
async fn file(&self, ctx: &Context<'_>, path: String) -> Result<File, Error> {
let graph = ctx.data::<Arc<Mutex<Graph>>>().unwrap();
let mut graph = graph.lock().unwrap();
let id = Uuid::new_v4().to_string();
Expand All @@ -23,7 +23,7 @@ impl FileQuery {

drop(graph);

let file = File { id: ID(id) };
let file = File { id: ID(id), path };
Ok(file)
}
}
20 changes: 17 additions & 3 deletions crates/graphql/src/schema/git.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
use std::sync::{Arc, Mutex};
use std::{
fs,
sync::{Arc, Mutex},
};

use super::objects::git::Git;
use async_graphql::{Context, Error, Object, ID};
use fluentci_core::deps::{Graph, GraphCommand};
use fluentci_ext::git::Git as GitExt;
use uuid::Uuid;

#[derive(Default, Clone)]
pub struct GitQuery;

#[Object]
impl GitQuery {
async fn git(&self, ctx: &Context<'_>) -> Result<Git, Error> {
async fn git(&self, ctx: &Context<'_>, url: String) -> Result<Git, Error> {
let graph = ctx.data::<Arc<Mutex<Graph>>>().unwrap();
let mut graph = graph.lock().unwrap();
graph.reset();
graph.runner = Arc::new(Box::new(GitExt::default()));
graph.runner.setup()?;
graph.work_dir = format!(
"{}/.fluentci/cache",
dirs::home_dir().unwrap().to_str().unwrap()
);
fs::create_dir_all(&graph.work_dir)?;

let id = Uuid::new_v4().to_string();
graph.execute(GraphCommand::AddVertex(
id.clone(),
"git".into(),
"".into(),
url,
vec![],
));
graph.execute_vertex(&id)?;

drop(graph);

Expand Down
Loading

0 comments on commit 4fa3381

Please sign in to comment.