diff --git a/coffee_cmd/src/cmd.rs b/coffee_cmd/src/cmd.rs index 6f605021..1ca3d73d 100644 --- a/coffee_cmd/src/cmd.rs +++ b/coffee_cmd/src/cmd.rs @@ -29,6 +29,8 @@ pub enum CoffeeCommand { verbose: bool, #[arg(short, long, action = clap::ArgAction::SetTrue)] dynamic: bool, + #[arg(short, long)] + branch: Option, }, /// upgrade a single repository. #[clap(arg_required_else_help = true)] @@ -92,7 +94,8 @@ impl From<&CoffeeCommand> for coffee_core::CoffeeOperation { plugin, verbose, dynamic, - } => Self::Install(plugin.to_owned(), *verbose, *dynamic), + branch, + } => Self::Install(plugin.to_owned(), *verbose, *dynamic, branch.to_owned()), CoffeeCommand::Upgrade { repo, verbose } => Self::Upgrade(repo.to_owned(), *verbose), CoffeeCommand::List {} => Self::List, CoffeeCommand::Setup { cln_conf } => Self::Setup(cln_conf.to_owned()), diff --git a/coffee_cmd/src/main.rs b/coffee_cmd/src/main.rs index 623a6f24..3bc40cfa 100644 --- a/coffee_cmd/src/main.rs +++ b/coffee_cmd/src/main.rs @@ -20,13 +20,14 @@ async fn run(args: CoffeeArgs, mut coffee: CoffeeManager) -> Result<(), CoffeeEr plugin, verbose, dynamic, + branch, } => { let spinner = if !verbose { Some(term::spinner("Compiling and installing")) } else { None }; - let result = coffee.install(&plugin, verbose, dynamic).await; + let result = coffee.install(&plugin, verbose, dynamic, branch).await; if let Some(spinner) = spinner { if result.is_ok() { spinner.finish(); diff --git a/coffee_core/src/coffee.rs b/coffee_core/src/coffee.rs index 98e32c9d..cc8bfe31 100644 --- a/coffee_core/src/coffee.rs +++ b/coffee_core/src/coffee.rs @@ -246,6 +246,7 @@ impl PluginManager for CoffeeManager { plugin: &str, verbose: bool, try_dynamic: bool, + branch: Option, ) -> Result<(), CoffeeError> { log::debug!("installing plugin: {plugin}"); // keep track if the plugin is successfully installed @@ -358,12 +359,11 @@ impl PluginManager for CoffeeManager { UpgradeStatus::Updated(_, _) => { for plugins in status.plugins_effected.iter() { self.remove(plugins).await?; - self.install(plugins, verbose, false).await?; + self.install(plugins, verbose, false, branch).await?; } } _ => {} } - self.flush().await?; Ok(status) } diff --git a/coffee_core/src/lib.rs b/coffee_core/src/lib.rs index fe695e1e..a3540f11 100644 --- a/coffee_core/src/lib.rs +++ b/coffee_core/src/lib.rs @@ -7,8 +7,8 @@ pub use coffee_lib as lib; #[derive(Clone, Debug)] pub enum CoffeeOperation { - /// Install(plugin name, verbose run, dynamic installation) - Install(String, bool, bool), + /// Install(plugin name, verbose run, dynamic installation, branch) + Install(String, bool, bool, Option), /// List List, // Upgrade(name of the repository, verbose run) diff --git a/coffee_github/src/repository.rs b/coffee_github/src/repository.rs index 589f1356..7ebd0ba3 100644 --- a/coffee_github/src/repository.rs +++ b/coffee_github/src/repository.rs @@ -308,6 +308,28 @@ impl Repository for Github { } } + async fn switch_branch(&mut self, branch_name: &str) -> Result<(), CoffeeError> { + // FIXME: implement the From git2 Error for `CoffeError` + let repo = git2::Repository::open(&self.url.path_string) + .map_err(|err| error!("{}", err.message()))?; + let mut remote = repo + .find_remote("origin") + .map_err(|err| error!("{}", err.message()))?; + remote + .fetch(&[&branch_name], None, None) + .map_err(|err| error!("{}", err.message()))?; + let oid = repo + .refname_to_id(&format!("refs/remotes/origin/{}", branch_name)) + .map_err(|err| error!("{}", err.message()))?; + let obj = repo + .find_object(oid, None) + .map_err(|err| error!("{}", err.message()))?; + repo.reset(&obj, git2::ResetType::Hard, None) + .map_err(|err| error!("{}", err.message()))?; + self.branch = branch_name.to_string(); + Ok(()) + } + /// list of the plugin installed inside the repository. async fn list(&self) -> Result, CoffeeError> { Ok(self.plugins.clone()) diff --git a/coffee_httpd/src/httpd/server.rs b/coffee_httpd/src/httpd/server.rs index 32a6fe33..20c35e88 100644 --- a/coffee_httpd/src/httpd/server.rs +++ b/coffee_httpd/src/httpd/server.rs @@ -91,7 +91,8 @@ async fn coffee_install( let try_dynamic = body.try_dynamic; let mut coffee = data.coffee.lock().await; - let result = coffee.install(plugin, false, try_dynamic).await; + let branch = body.branch; + let result = coffee.install(plugin, false, try_dynamic, branch).await; handle_httpd_response!(result, "Plugin '{plugin}' installed successfully") } diff --git a/coffee_lib/src/plugin_manager.rs b/coffee_lib/src/plugin_manager.rs index 65bca03a..c524bc89 100644 --- a/coffee_lib/src/plugin_manager.rs +++ b/coffee_lib/src/plugin_manager.rs @@ -16,6 +16,7 @@ pub trait PluginManager { plugins: &str, verbose: bool, try_dynamic: bool, + branch: Option, ) -> Result<(), CoffeeError>; // remove a plugin by name, return an error if some error happens. diff --git a/coffee_lib/src/repository.rs b/coffee_lib/src/repository.rs index dbb9bec7..bb303e3a 100644 --- a/coffee_lib/src/repository.rs +++ b/coffee_lib/src/repository.rs @@ -34,6 +34,9 @@ pub trait Repository: Any { /// recover the repository from the commit id. async fn recover(&mut self) -> Result<(), CoffeeError>; + /// switch to the specified branch. + async fn switch_branch(&mut self, branch_name: &str) -> Result<(), CoffeeError>; + /// return the name of the repository. fn name(&self) -> String; diff --git a/coffee_lib/src/types/mod.rs b/coffee_lib/src/types/mod.rs index 794dc53a..e5c0dbec 100644 --- a/coffee_lib/src/types/mod.rs +++ b/coffee_lib/src/types/mod.rs @@ -11,6 +11,7 @@ pub mod request { pub struct Install { pub plugin: String, pub try_dynamic: bool, + pub branch: Option, } #[cfg(feature = "open-api")] diff --git a/coffee_plugin/src/plugin/plugin_mod.rs b/coffee_plugin/src/plugin/plugin_mod.rs index 4f3fa403..cc390b60 100644 --- a/coffee_plugin/src/plugin/plugin_mod.rs +++ b/coffee_plugin/src/plugin/plugin_mod.rs @@ -91,7 +91,7 @@ fn coffee_install(plugin: &mut Plugin, request: Value) -> Result ``` +#### Branch Specification for Plugin Installation + +User can install a plugin from a specific branch using the command: +```bash +coffee install --branch +``` + ### Removing a Plugin > ✅ Implemented diff --git a/tests/src/coffee_httpd_integration_tests.rs b/tests/src/coffee_httpd_integration_tests.rs index 7e6d799f..3bc0acc9 100644 --- a/tests/src/coffee_httpd_integration_tests.rs +++ b/tests/src/coffee_httpd_integration_tests.rs @@ -45,6 +45,7 @@ pub async fn httpd_init_add_remote() { let install_request = Install { plugin: "summary".to_string(), try_dynamic: true, + branch: None, }; // Send the request to install a plugin @@ -107,6 +108,7 @@ pub async fn httpd_add_remove_plugins() { let install_request = Install { plugin: "summary".to_string(), try_dynamic: false, + branch: None, }; let response = client diff --git a/tests/src/coffee_integration_tests.rs b/tests/src/coffee_integration_tests.rs index 126af133..c9f4bd16 100644 --- a/tests/src/coffee_integration_tests.rs +++ b/tests/src/coffee_integration_tests.rs @@ -112,7 +112,7 @@ pub async fn init_coffee_test_add_remote() { .unwrap(); manager .coffee() - .install("summary", true, true) + .install("summary", true, true, None) .await .unwrap(); @@ -167,13 +167,13 @@ pub async fn test_add_remove_plugins() { ); // Install summary plugin - let result = manager.coffee().install("summary", true, false).await; + let result = manager.coffee().install("summary", true, false, None).await; assert!(result.is_ok(), "{:?}", result); // Install helpme plugin manager .coffee() - .install("helpme", true, false) + .install("helpme", true, false, None) .await .unwrap(); @@ -276,7 +276,7 @@ pub async fn test_errors_and_show() { ); // Install summary plugin - let result = manager.coffee().install("summary", true, false).await; + let result = manager.coffee().install("summary", true, false, None).await; assert!(result.is_ok(), "{:?}", result); // Get the README file for a plugin that is not installed @@ -285,7 +285,7 @@ pub async fn test_errors_and_show() { assert!(val.starts_with("# Helpme plugin")); // Install a plugin that is not in the repository - let result = manager.coffee().install("x", true, false).await; + let result = manager.coffee().install("x", true, false, None).await; assert!(result.is_err(), "{:?}", result); // Remove helpme plugin @@ -353,7 +353,7 @@ pub async fn install_plugin_in_two_networks() -> anyhow::Result<()> { // This should install summary plugin for regtest network manager .coffee() - .install("summary", true, true) + .install("summary", true, true, None) .await .unwrap(); // Ensure that summary is installed for regtest network @@ -393,7 +393,7 @@ pub async fn install_plugin_in_two_networks() -> anyhow::Result<()> { // This should install summary plugin for testnet network manager .coffee() - .install("summary", true, true) + .install("summary", true, true, None) .await .unwrap(); // Ensure that summary is installed for testnet network @@ -428,13 +428,13 @@ pub async fn test_double_slash() { .unwrap(); // Install summary plugin - let result = manager.coffee().install("summary", true, false).await; + let result = manager.coffee().install("summary", true, false, None).await; assert!(result.is_ok(), "{:?}", result); // Install helpme plugin manager .coffee() - .install("helpme", true, false) + .install("helpme", true, false, None) .await .unwrap(); @@ -493,7 +493,7 @@ pub async fn test_plugin_installation_path() { // Install summary plugin for regtest network manager .coffee() - .install("summary", true, false) + .install("summary", true, false, None) .await .unwrap();