From 25e6aca340f4da57ea16d812924e0bffe5de3f7b Mon Sep 17 00:00:00 2001 From: mbecker20 Date: Sat, 1 Mar 2025 12:58:08 -0800 Subject: [PATCH] init sync file new repo --- bin/core/src/api/write/stack.rs | 4 +- bin/core/src/api/write/sync.rs | 277 +++++++++++++++++++++----------- bin/core/src/sync/remote.rs | 10 +- lib/git/src/init.rs | 53 ++++++ lib/git/src/lib.rs | 12 +- lib/git/src/pull.rs | 39 +---- 6 files changed, 253 insertions(+), 142 deletions(-) create mode 100644 lib/git/src/init.rs diff --git a/bin/core/src/api/write/stack.rs b/bin/core/src/api/write/stack.rs index b9c9232ee..da8dc3e72 100644 --- a/bin/core/src/api/write/stack.rs +++ b/bin/core/src/api/write/stack.rs @@ -149,7 +149,7 @@ impl Resolve for WriteStackFileContents { } Err(e) => { update.push_error_log( - "Write file contents", + "Write File Contents", format_serror(&e.into()), ); } @@ -187,7 +187,7 @@ impl Resolve for WriteStackFileContents { } Err(e) => { update.push_error_log( - "Write file contents", + "Write File Contents", format_serror(&e.into()), ); } diff --git a/bin/core/src/api/write/sync.rs b/bin/core/src/api/write/sync.rs index 3c80b0531..b32aa868b 100644 --- a/bin/core/src/api/write/sync.rs +++ b/bin/core/src/api/write/sync.rs @@ -45,6 +45,7 @@ use crate::{ api::read::ReadArgs, config::core_config, helpers::{ + git_token, query::get_id_to_tags, update::{add_update, make_update, update_update}, }, @@ -135,68 +136,116 @@ impl Resolve for RenameResourceSync { } } -impl Resolve for WriteSyncFileContents { - async fn resolve(self, args: &WriteArgs) -> serror::Result { - let WriteSyncFileContents { - sync, - resource_path, - file_path, - contents, - } = self; - let WriteArgs { user } = args; +async fn write_sync_file_contents_on_host( + req: WriteSyncFileContents, + args: &WriteArgs, + sync: ResourceSync, + mut update: Update, +) -> serror::Result { + let WriteSyncFileContents { + sync: _, + resource_path, + file_path, + contents, + } = req; - let sync = resource::get_check_permissions::( - &sync, - user, - PermissionLevel::Write, + let root = core_config() + .sync_directory + .join(to_komodo_name(&sync.name)); + let file_path = + file_path.parse::().context("Invalid file path")?; + let resource_path = resource_path + .parse::() + .context("Invalid resource path")?; + let full_path = root.join(&resource_path).join(&file_path); + + if let Some(parent) = full_path.parent() { + let _ = fs::create_dir_all(parent).await; + } + + if let Err(e) = + fs::write(&full_path, &contents).await.with_context(|| { + format!("Failed to write file contents to {full_path:?}") + }) + { + update.push_error_log("Write File", format_serror(&e.into())); + } else { + update.push_simple_log( + "Write File", + format!("File written to {full_path:?}"), + ); + }; + + if !all_logs_success(&update.logs) { + update.finalize(); + update.id = add_update(update.clone()).await?; + + return Ok(update); + } + + if let Err(e) = (RefreshResourceSyncPending { sync: sync.name }) + .resolve(args) + .await + { + update.push_error_log( + "Refresh failed", + format_serror(&e.error.into()), + ); + } + + update.finalize(); + update.id = add_update(update.clone()).await?; + + Ok(update) +} + +async fn write_sync_file_contents_git( + req: WriteSyncFileContents, + args: &WriteArgs, + sync: ResourceSync, + mut update: Update, +) -> serror::Result { + let WriteSyncFileContents { + sync: _, + resource_path, + file_path, + contents, + } = req; + + let mut clone_args: CloneArgs = (&sync).into(); + let root = clone_args.unique_path(&core_config().repo_directory)?; + + let file_path = + file_path.parse::().context("Invalid file path")?; + let resource_path = resource_path + .parse::() + .context("Invalid resource path")?; + let full_path = root.join(&resource_path).join(&file_path); + + if let Some(parent) = full_path.parent() { + let _ = fs::create_dir_all(parent).await; + } + + // Ensure the folder is initialized as git repo. + // This allows a new file to be committed on a branch that may not exist. + if !root.join(".git").exists() { + let access_token = if let Some(account) = &clone_args.account { + git_token(&clone_args.provider, account, |https| clone_args.https = https) + .await + .with_context( + || format!("Failed to get git token in call to db. Stopping run. | {} | {account}", clone_args.provider), + )? + } else { + None + }; + + git::init_folder_as_repo( + &root, + &clone_args, + access_token.as_deref(), + &mut update.logs, ) - .await?; - - if !sync.config.files_on_host && sync.config.repo.is_empty() { - return Err( - anyhow!( - "This method is only for files on host, or repo based syncs." - ) - .into(), - ); - } - - let mut update = - make_update(&sync, Operation::WriteSyncContents, &user); - - update.push_simple_log("File contents", &contents); - - let root = if sync.config.files_on_host { - core_config() - .sync_directory - .join(to_komodo_name(&sync.name)) - } else { - let clone_args: CloneArgs = (&sync).into(); - clone_args.unique_path(&core_config().repo_directory)? - }; - let file_path = - file_path.parse::().context("Invalid file path")?; - let resource_path = resource_path - .parse::() - .context("Invalid resource path")?; - let full_path = root.join(&resource_path).join(&file_path); - - if let Some(parent) = full_path.parent() { - let _ = fs::create_dir_all(parent).await; - } - - if let Err(e) = - fs::write(&full_path, &contents).await.with_context(|| { - format!("Failed to write file contents to {full_path:?}") - }) - { - update.push_error_log("Write file", format_serror(&e.into())); - } else { - update.push_simple_log( - "Write file", - format!("File written to {full_path:?}"), - ); - }; + .await; if !all_logs_success(&update.logs) { update.finalize(); @@ -204,48 +253,82 @@ impl Resolve for WriteSyncFileContents { return Ok(update); } + } - if sync.config.files_on_host { - if let Err(e) = (RefreshResourceSyncPending { sync: sync.name }) - .resolve(args) - .await - { - update.push_error_log( - "Refresh failed", - format_serror(&e.error.into()), - ); - } - - update.finalize(); - update.id = add_update(update.clone()).await?; - - return Ok(update); - } - - let commit_res = git::commit_file( - &format!("{}: Commit Resource File", user.username), - &root, - &resource_path.join(&file_path), - &sync.config.branch, - ) - .await; - - update.logs.extend(commit_res.logs); - - if let Err(e) = (RefreshResourceSyncPending { sync: sync.name }) - .resolve(args) - .await - { - update.push_error_log( - "Refresh failed", - format_serror(&e.error.into()), - ); - } + if let Err(e) = + fs::write(&full_path, &contents).await.with_context(|| { + format!("Failed to write file contents to {full_path:?}") + }) + { + update.push_error_log("Write File", format_serror(&e.into())); + } else { + update.push_simple_log( + "Write File", + format!("File written to {full_path:?}"), + ); + }; + if !all_logs_success(&update.logs) { update.finalize(); update.id = add_update(update.clone()).await?; - Ok(update) + return Ok(update); + } + + let commit_res = git::commit_file( + &format!("{}: Commit Resource File", args.user.username), + &root, + &resource_path.join(&file_path), + &sync.config.branch, + ) + .await; + + update.logs.extend(commit_res.logs); + + if let Err(e) = (RefreshResourceSyncPending { sync: sync.name }) + .resolve(args) + .await + { + update.push_error_log( + "Refresh failed", + format_serror(&e.error.into()), + ); + } + + update.finalize(); + update.id = add_update(update.clone()).await?; + + Ok(update) +} + +impl Resolve for WriteSyncFileContents { + async fn resolve(self, args: &WriteArgs) -> serror::Result { + let sync = resource::get_check_permissions::( + &self.sync, + &args.user, + PermissionLevel::Write, + ) + .await?; + + if !sync.config.files_on_host && sync.config.repo.is_empty() { + return Err( + anyhow!( + "This method is only for 'files on host' or 'repo' based syncs." + ) + .into(), + ); + } + + let mut update = + make_update(&sync, Operation::WriteSyncContents, &args.user); + + update.push_simple_log("File contents", &self.contents); + + if sync.config.files_on_host { + write_sync_file_contents_on_host(self, args, sync, update).await + } else { + write_sync_file_contents_git(self, args, sync, update).await + } } } diff --git a/bin/core/src/sync/remote.rs b/bin/core/src/sync/remote.rs index 6365e1ce6..743dce8a0 100644 --- a/bin/core/src/sync/remote.rs +++ b/bin/core/src/sync/remote.rs @@ -133,9 +133,9 @@ pub async fn get_remote_resources( format!("Failed to update resource repo at {repo_path:?}") })?; - let hash = hash.context("failed to get commit hash")?; - let message = - message.context("failed to get commit hash message")?; + // let hash = hash.context("failed to get commit hash")?; + // let message = + // message.context("failed to get commit hash message")?; let (mut files, mut file_errors) = (Vec::new(), Vec::new()); let resources = super::file::read_resources( @@ -152,7 +152,7 @@ pub async fn get_remote_resources( files, file_errors, logs, - hash: Some(hash), - message: Some(message), + hash, + message, }) } diff --git a/lib/git/src/init.rs b/lib/git/src/init.rs new file mode 100644 index 000000000..397886a31 --- /dev/null +++ b/lib/git/src/init.rs @@ -0,0 +1,53 @@ +use std::path::Path; + +use command::run_komodo_command; +use formatting::format_serror; +use komodo_client::entities::{ + all_logs_success, update::Log, CloneArgs, +}; + +pub async fn init_folder_as_repo( + folder_path: &Path, + args: &CloneArgs, + access_token: Option<&str>, + logs: &mut Vec, +) { + // let folder_path = args.path(repo_dir); + // Initialize the folder as a git repo + let init_repo = run_komodo_command( + "Git Init", + folder_path.as_ref(), + "git init", + false, + ) + .await; + logs.push(init_repo); + if !all_logs_success(&logs) { + return; + } + let repo_url = match args.remote_url(access_token.as_deref()) { + Ok(url) => url, + Err(e) => { + logs + .push(Log::error("Add git remote", format_serror(&e.into()))); + return; + } + }; + // Set remote url + let mut set_remote = run_komodo_command( + "Add git remote", + folder_path.as_ref(), + format!("git remote add origin {repo_url}"), + false, + ) + .await; + // Sanitize the output + if let Some(token) = &access_token { + set_remote.command = set_remote.command.replace(token, ""); + set_remote.stdout = set_remote.stdout.replace(token, ""); + set_remote.stderr = set_remote.stderr.replace(token, ""); + } + if !set_remote.success { + logs.push(set_remote); + } +} diff --git a/lib/git/src/lib.rs b/lib/git/src/lib.rs index 8191eb18b..5094ec169 100644 --- a/lib/git/src/lib.rs +++ b/lib/git/src/lib.rs @@ -12,13 +12,17 @@ pub mod environment; mod clone; mod commit; +mod init; mod pull; mod pull_or_clone; -pub use clone::clone; -pub use commit::{commit_all, commit_file, write_commit_file}; -pub use pull::pull; -pub use pull_or_clone::pull_or_clone; +pub use crate::{ + clone::clone, + commit::{commit_all, commit_file, write_commit_file}, + init::init_folder_as_repo, + pull::pull, + pull_or_clone::pull_or_clone, +}; #[derive(Debug, Default, Clone)] pub struct GitRes { diff --git a/lib/git/src/pull.rs b/lib/git/src/pull.rs index 0e05e70e0..4446562a7 100644 --- a/lib/git/src/pull.rs +++ b/lib/git/src/pull.rs @@ -73,15 +73,13 @@ where // Check for '.git' path to see if the folder is initialized as a git repo let dot_git_path = folder_path.join(".git"); if !dot_git_path.exists() { - // Initialize the folder as a git repo - let init_repo = run_komodo_command( - "Git init", - folder_path.as_ref(), - "git init", - false, + crate::init::init_folder_as_repo( + &folder_path, + &args, + access_token.as_deref(), + &mut logs, ) .await; - logs.push(init_repo); if !all_logs_success(&logs) { return Ok(GitRes { logs, @@ -90,33 +88,6 @@ where env_file_path: None, }); } - let repo_url = args.remote_url(access_token.as_deref())?; - // Set remote url - let mut set_remote = run_komodo_command( - "Set git remote", - folder_path.as_ref(), - format!("git remote add origin {repo_url}"), - false, - ) - .await; - // Sanitize the output - if let Some(token) = &access_token { - set_remote.command = - set_remote.command.replace(token, ""); - set_remote.stdout = - set_remote.stdout.replace(token, ""); - set_remote.stderr = - set_remote.stderr.replace(token, ""); - } - if !set_remote.success { - logs.push(set_remote); - return Ok(GitRes { - logs, - hash: None, - message: None, - env_file_path: None, - }); - } } let repo_url = args.remote_url(access_token.as_deref())?;