Compare commits

..

2 Commits

Author SHA1 Message Date
cuddle-please
253d64efa4 chore(release): 0.2.1
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-09-22 14:27:30 +00:00
c2faf6d0b6
feat: spawn a subshell for session
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-22 16:25:44 +02:00
7 changed files with 119 additions and 4 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.2.1] - 2024-09-22 ## [0.2.1] - 2024-09-22
### Added ### Added
- spawn a subshell for session
- implement git clone - implement git clone
- include vhs demo - include vhs demo
- add interactive search - add interactive search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 KiB

After

Width:  |  Height:  |  Size: 476 KiB

View File

@ -8,6 +8,7 @@ use crate::{
git_provider::Repository, git_provider::Repository,
interactive::InteractiveApp, interactive::InteractiveApp,
projects_list::ProjectsListApp, projects_list::ProjectsListApp,
shell::ShellApp,
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -25,6 +26,8 @@ impl RootCommand {
search: Option<impl Into<String>>, search: Option<impl Into<String>>,
cache: bool, cache: bool,
clone: bool, clone: bool,
shell: bool,
force_refresh: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
tracing::debug!("executing"); tracing::debug!("executing");
@ -72,7 +75,28 @@ impl RootCommand {
}; };
if clone { if clone {
self.app.git_clone().clone_repo(&repo).await?; self.app
.git_clone()
.clone_repo(&repo, force_refresh)
.await?;
} else {
tracing::info!("skipping clone for repo: {}", &repo.to_rel_path().display());
}
if shell {
self.app.shell().spawn_shell(&repo).await?;
} else {
tracing::info!("skipping shell for repo: {}", &repo.to_rel_path().display());
println!(
"{}",
self.app
.config
.settings
.projects
.directory
.join(repo.to_rel_path())
.display()
);
} }
Ok(()) Ok(())

View File

@ -9,7 +9,11 @@ impl GitClone {
Self { app } Self { app }
} }
pub async fn clone_repo(&self, repository: &Repository) -> anyhow::Result<()> { pub async fn clone_repo(
&self,
repository: &Repository,
force_refresh: bool,
) -> anyhow::Result<()> {
let project_path = self let project_path = self
.app .app
.config .config
@ -18,6 +22,10 @@ impl GitClone {
.directory .directory
.join(repository.to_rel_path()); .join(repository.to_rel_path());
if force_refresh {
tokio::fs::remove_dir_all(&project_path).await?;
}
if project_path.exists() { if project_path.exists() {
tracing::info!( tracing::info!(
"project: {} already exists, skipping clone", "project: {} already exists, skipping clone",

View File

@ -17,6 +17,7 @@ mod git_clone;
mod git_provider; mod git_provider;
mod interactive; mod interactive;
mod projects_list; mod projects_list;
mod shell;
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about, long_about = Some("Navigate git projects at the speed of thought"))] #[command(author, version, about, long_about = Some("Navigate git projects at the speed of thought"))]
@ -32,6 +33,12 @@ struct Command {
#[arg(long = "no-clone", default_value = "false")] #[arg(long = "no-clone", default_value = "false")]
no_clone: bool, no_clone: bool,
#[arg(long = "no-shell", default_value = "false")]
no_shell: bool,
#[arg(long = "force-refresh", default_value = "false")]
force_refresh: bool,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
@ -64,7 +71,13 @@ async fn main() -> anyhow::Result<()> {
Some(_) => todo!(), Some(_) => todo!(),
None => { None => {
RootCommand::new(app) RootCommand::new(app)
.execute(cli.search.as_ref(), !cli.no_cache, !cli.no_clone) .execute(
cli.search.as_ref(),
!cli.no_cache,
!cli.no_clone,
!cli.no_shell,
cli.force_refresh,
)
.await?; .await?;
} }
} }

View File

@ -0,0 +1,65 @@
use anyhow::Context;
use crate::{app::App, git_provider::Repository};
pub struct Shell {
app: &'static App,
}
impl Shell {
pub fn new(app: &'static App) -> Self {
Self { app }
}
pub async fn spawn_shell(&self, repository: &Repository) -> anyhow::Result<()> {
let project_path = self
.app
.config
.settings
.projects
.directory
.join(repository.to_rel_path());
if !project_path.exists() {
anyhow::bail!(
"project path: {} does not exists, it is either a file, or hasn't been cloned",
project_path.display()
);
}
let shell = std::env::var("SHELL")
.context("failed to find SHELL variable, required for spawning embedded shells")?;
let mut shell_cmd = tokio::process::Command::new(shell);
shell_cmd.current_dir(project_path);
let mut process = shell_cmd.spawn().context("failed to spawn child session")?;
let status = process.wait().await?;
if !status.success() {
tracing::warn!(
"child session returned non-zero, or missing return code: {}",
status.code().unwrap_or_default()
);
anyhow::bail!(
"child shell session failed with exit: {}",
status.code().unwrap_or(-1)
);
} else {
tracing::debug!("child session returned 0 exit code");
}
Ok(())
}
}
pub trait ShellApp {
fn shell(&self) -> Shell;
}
impl ShellApp for &'static App {
fn shell(&self) -> Shell {
Shell::new(self)
}
}

View File

@ -3,11 +3,15 @@ Set Theme "Dracula"
Set Width 1200 Set Width 1200
Set Height 1000 Set Height 1000
Hide Hide
Type "./target/debug/gitnow --no-cache" Type "./target/debug/gitnow --no-cache --force-refresh"
Enter Enter
Show Show
Sleep 2s Sleep 2s
Type@500ms "bevy" Type@500ms "bevy"
Sleep 1s Sleep 1s
Enter Enter
Sleep 10s
Type "echo 'I am now in bevy!'"
Enter
Sleep 5s Sleep 5s
Sleep 2s