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

Sweep: fix: git pull on downloaded plugin does not working (βœ“ Sandbox Passed) #81

Merged
merged 31 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
da010ba
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 2, 2024
0c14961
feat: Updated fluere-plugin/src/util.rs
sweep-ai[bot] Jan 2, 2024
c1f577b
style: `rustfmt`
sweep-ai[bot] Jan 2, 2024
91ba052
feat: Updated fluere-plugin/Cargo.toml
sweep-ai[bot] Jan 2, 2024
52fd135
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 2, 2024
7c2248e
feat: Updated fluere-plugin/src/util.rs
sweep-ai[bot] Jan 2, 2024
eced9b5
style: `rustfmt`
sweep-ai[bot] Jan 2, 2024
2d2a104
feat: Updated fluere-plugin/src/lib.rs
sweep-ai[bot] Jan 2, 2024
c47bfc7
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 2, 2024
06651fe
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 2, 2024
8a8e0bc
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 2, 2024
21ec1ea
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 2, 2024
e98e084
feat: Updated fluere-plugin/src/util.rs
sweep-ai[bot] Jan 2, 2024
0568f4e
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 2, 2024
a48601a
feat: Updated fluere-plugin/Cargo.toml
sweep-ai[bot] Jan 2, 2024
d5091ff
Merge main into sweep/fix_git_pull_on_downloaded_plugin_does_n
sweep-ai[bot] Jan 2, 2024
aa09712
style: `rustfmt`
sweep-ai[bot] Jan 2, 2024
e5abcb9
Merge main into sweep/fix_git_pull_on_downloaded_plugin_does_n
sweep-ai[bot] Jan 2, 2024
9ac3535
feat: Updated fluere-plugin/src/lib.rs
sweep-ai[bot] Jan 3, 2024
caa7a35
style: `rustfmt`
sweep-ai[bot] Jan 3, 2024
0ebf26b
fix(plugin): correct git clone directory issue
SkuldNorniern Jan 3, 2024
9740d90
style: `rustfmt`
SkuldNorniern Jan 3, 2024
9b45d29
fix(plugin): remove useless part from download repo function
SkuldNorniern Jan 3, 2024
8ce6fdb
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 3, 2024
97f9876
style: `rustfmt`
sweep-ai[bot] Jan 3, 2024
f3acbfb
feat: Updated fluere-plugin/src/downloader.rs
sweep-ai[bot] Jan 3, 2024
455d874
build(plugin): add `inksac`
SkuldNorniern Jan 5, 2024
6751a52
fix(plugin): fix pull operation
SkuldNorniern Jan 5, 2024
268bcd7
chore(plugin): bump version to 0.1.1
SkuldNorniern Jan 5, 2024
32827e2
feat: Updated src/net/live_fluereflow.rs
sweep-ai[bot] Jan 5, 2024
22ceccc
fix(plugin): fix unintended bot's edit
SkuldNorniern Jan 5, 2024
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
4 changes: 3 additions & 1 deletion fluere-plugin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fluere_plugin"
version = "0.1.0"
version = "0.1.1"
authors = ["Skuld Norniern <skuldnorniern@gmail.com>"]
edition = "2021"
description = "Plugin API for Fluere."
Expand All @@ -14,12 +14,14 @@ repository = "https://github.com/SkuldNorniern/fluere"


[dependencies]
git2 = "0.18.1"
tokio = { version = "1.32", features = ["full","macros", "rt-multi-thread"] }
fluere-config = { version = "0.1.2", path = "../fluere-config" }
#fluere-plugin-trait = { path = "../fluere-plugin-trait" }
fluereflow = { version = "0.3.2", path = "../fluereflow" }
dirs = "5.0.1"
mlua = { version = "0.9.2", features = ["lua54", "vendored","async","send"] }
inksac = "0.4.0"

[lib]
name = "fluere_plugin"
148 changes: 133 additions & 15 deletions fluere-plugin/src/downloader.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,141 @@
use git2::{
build::CheckoutBuilder, FetchOptions, ObjectType, Repository, ResetType, StatusOptions,
};
use inksac::{Color, Style, Stylish};

use std::fmt;
use std::io;
use std::path::Path;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

use crate::util::home_cache_path;
use std::process::Command;

pub fn download_plugin_from_github(repo_name: &str) -> Result<(), std::io::Error> {
let url = format!("https://github.com/{}.git", repo_name);
let path = home_cache_path();
let cd_cmd = format!("cd {}", path.display());
#[derive(Debug)]
pub enum DownloadError {
Io(std::io::Error),
Git(git2::Error),
Other(String),
}

impl fmt::Display for DownloadError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DownloadError::Io(err) => write!(f, "IO error: {}", err),
DownloadError::Git(err) => write!(f, "Git error: {}", err),
DownloadError::Other(err) => write!(f, "{}", err),
}
}
}

impl From<std::io::Error> for DownloadError {
fn from(err: std::io::Error) -> Self {
DownloadError::Io(err)
}
}

impl From<git2::Error> for DownloadError {
fn from(err: git2::Error) -> Self {
DownloadError::Git(err)
}
}

impl From<String> for DownloadError {
fn from(err: String) -> Self {
DownloadError::Other(err)
}
}

pub fn download_plugin_from_github(repo_name: &str) -> Result<(), DownloadError> {
let url = format!("https://github.com/{}", repo_name);
let warn_style = Style::builder().foreground(Color::Yellow).build();
let highlight_style = Style::builder().foreground(Color::Green).bold().build();
let path = home_cache_path()?;
if !path.exists() {
std::fs::create_dir_all(path.clone())?;
std::fs::create_dir_all(&path)?;
}
if path.join(repo_name.split('/').last().unwrap()).exists() {
Command::new("bash")
.arg("-c")
.arg(cd_cmd + ";git fetch ;git pull")
.output()?;

let repo_path = path.join(repo_name.split('/').last().unwrap());
let repository_path = Path::new(&repo_path);

let repo = match Repository::open(repository_path) {
Ok(repo) => repo,
Err(_) => Repository::clone(&url, repository_path)?,
};
let mut remote = repo.find_remote("origin")?;
let mut fetch_options = FetchOptions::new();
remote.fetch(&["main"], Some(&mut fetch_options), None)?;

let fetch_head = repo.find_reference("FETCH_HEAD")?;

let fetch_commit = fetch_head.peel(ObjectType::Commit)?.id();
let local_commit = repo.head()?.target().unwrap();

if fetch_commit != local_commit {
println!(
"An update is available for '{}'. Do you want to update? [y/N] (auto skip in 5 seconds)",
repo_name.styled(highlight_style)
);
if user_confirms()? {
if has_local_changes(&repo)? {
println!("{}: You have uncommitted changes. Updating will overwrite these changes. Continue? [y/N] (auto skip in 5 seconds)","Warning".styled(warn_style));
if !user_confirms()? {
println!("Update skipped for {}", repo_name.styled(highlight_style));
return Ok(());
}
}

// Resetting the HEAD to the fetched commit
let fetch_commit_obj = repo.find_commit(fetch_commit)?;
repo.reset(fetch_commit_obj.as_object(), ResetType::Hard, None)?;

// Checking out the commit to update the working directory and index
let mut checkout_builder = CheckoutBuilder::new();
let _ = checkout_builder.force();
repo.checkout_tree(fetch_commit_obj.as_object(), Some(&mut checkout_builder))?;
repo.set_head_detached(fetch_commit)?;

println!(
"Successfully updated to the latest version for {}",
repo_name.styled(highlight_style)
);
} else {
println!("Update skipped for {}", repo_name.styled(highlight_style));
}
} else {
Command::new("bash")
.arg("-c")
.arg(cd_cmd + "; git clone " + &url)
.output()?;
println!("{} is up to date.", repo_name.styled(highlight_style));
}

Ok(())
}
fn user_confirms() -> Result<bool, DownloadError> {
let (sender, receiver) = mpsc::channel();

// Spawn a new thread for user input
thread::spawn(move || {
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(_) => {
let _ = sender.send(input.trim().eq_ignore_ascii_case("y"));
}
Err(_) => {
let _ = sender.send(false);
}
}
});

// Wait for input or timeout after 5 seconds
match receiver.recv_timeout(Duration::from_secs(5)) {
Ok(result) => Ok(result),
Err(_) => {
print!("Timeout. ");
Ok(false)
}
}
}

fn has_local_changes(repo: &Repository) -> Result<bool, DownloadError> {
let statuses = repo.statuses(Some(StatusOptions::new().include_untracked(true)))?;
Ok(statuses.iter().any(|s| s.status() != git2::Status::CURRENT))
}
18 changes: 9 additions & 9 deletions fluere-plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ pub struct PluginManager {
lua: Arc<Mutex<Lua>>,
sender: mpsc::Sender<FluereRecord>,
receiver: Arc<Mutex<mpsc::Receiver<FluereRecord>>>,
//worker: Arc<Mutex<tokio::task::JoinHandle<()>>>,
plugins: Arc<Mutex<HashSet<String>>>,
}

Expand All @@ -30,7 +29,6 @@ impl PluginManager {
lua,
sender,
receiver: Arc::new(Mutex::new(receiver)),
//worker: Arc::new(Mutex::new(tokio::task::JoinHandle::new())),
plugins,
})
}
Expand All @@ -46,7 +44,7 @@ impl PluginManager {
let mut owned_path_str = path.clone();
let name_of_main_file = "/init.lua";
owned_path_str.push_str(name_of_main_file);
// println!("path: {}", owned_path_str);

match std::fs::read_to_string(owned_path_str) {
Ok(code) => {
let lua_clone = self.lua.clone();
Expand Down Expand Up @@ -103,7 +101,7 @@ impl PluginManager {
None => {
match download_plugin_from_github(name) {
Ok(_) => {
let path = home_cache_path().join(name.split('/').last().unwrap());
let path = home_cache_path()?.join(name.split('/').last().unwrap());
match std::fs::read_to_string(path.join("init.lua")) {
Ok(code) => {
let lua_clone = self.lua.clone();
Expand Down Expand Up @@ -151,14 +149,16 @@ impl PluginManager {
plugins_guard.insert(name.clone());
println!("Loaded plugin {}", name);
}
Err(_) => {
Err(eri) => {
println!("Failed to read plugin: {}", name);
println!("Error: {}", eri);
continue;
}
}
}
Err(_) => {
Err(eri) => {
println!("Unable to download plugin: {}", name);
println!("Error: {}", eri);
}
}
}
Expand Down Expand Up @@ -220,7 +220,7 @@ impl PluginManager {
{
lua_table
.set(*key, record_vec[index].clone())
.expect(format!("Failed to set key: {}", key).as_str());
.unwrap_or_else(|_| panic!("Failed to set key: {}", key));
}

for plugin_name in plugins.iter() {
Expand All @@ -231,7 +231,7 @@ impl PluginManager {

if let Ok(func) = plugin_table.get::<_, mlua::Function>("process_data") {
func.call::<mlua::Table<'_>, ()>(lua_table.clone())
.expect(format!("Error on plugin: {}", plugin_name).as_str());
.unwrap_or_else(|_| panic!("Error on plugin: {}", plugin_name));
} else {
println!(
"'process_data' function not found in plugin: {}",
Expand Down Expand Up @@ -270,7 +270,7 @@ impl PluginManager {

if let Ok(func) = plugin_table.get::<_, mlua::Function>("cleanup") {
func.call::<(), ()>(())
.expect(format!("Error on plugin: {}", plugin_name).as_str());
.unwrap_or_else(|_| panic!("Error on plugin: {}", plugin_name));
} else {
println!("cleanup function not found in plugin: {}", plugin_name);
}
Expand Down
13 changes: 9 additions & 4 deletions fluere-plugin/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::env;
use std::fs;
use std::path::{Path, PathBuf};

pub fn home_cache_path() -> PathBuf {
pub fn home_cache_path() -> Result<PathBuf, std::io::Error> {
// Check for the SUDO_USER environment variable
let sudo_user = env::var("SUDO_USER");

Expand All @@ -16,13 +16,18 @@ pub fn home_cache_path() -> PathBuf {
}
Err(_) => {
// If not running under sudo, just use the config_dir function as before
cache_dir().unwrap()
cache_dir().ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
"Failed to find cache directory",
)
})?
}
};

let path_config = path_base.join("fluere");
if !path_config.exists() {
fs::create_dir_all(path_config.clone()).unwrap();
fs::create_dir_all(path_config.clone())?;
}
path_config
Ok(path_config)
}
2 changes: 1 addition & 1 deletion src/net/live_fluereflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ fn draw_ui(
flow_columns[5],
);
}
async fn listen_for_exit_keys() -> Result<(),std::io::Error> {
async fn listen_for_exit_keys() -> Result<(), std::io::Error> {
loop {
if event::poll(std::time::Duration::from_millis(100))? {
if let event::Event::Key(KeyEvent {
Expand Down
Loading