feat: spawn a subshell for session
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Kasper Juul Hermansen 2024-09-22 16:25:44 +02:00
parent a330e4454e
commit c2faf6d0b6
Signed by: kjuulh
SSH Key Fingerprint: SHA256:RjXh0p7U6opxnfd3ga/Y9TCo18FYlHFdSpRIV72S/QM
6 changed files with 118 additions and 4 deletions

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,
interactive::InteractiveApp,
projects_list::ProjectsListApp,
shell::ShellApp,
};
#[derive(Debug, Clone)]
@ -25,6 +26,8 @@ impl RootCommand {
search: Option<impl Into<String>>,
cache: bool,
clone: bool,
shell: bool,
force_refresh: bool,
) -> anyhow::Result<()> {
tracing::debug!("executing");
@ -72,7 +75,28 @@ impl RootCommand {
};
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(())

View File

@ -9,7 +9,11 @@ impl GitClone {
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
.app
.config
@ -18,6 +22,10 @@ impl GitClone {
.directory
.join(repository.to_rel_path());
if force_refresh {
tokio::fs::remove_dir_all(&project_path).await?;
}
if project_path.exists() {
tracing::info!(
"project: {} already exists, skipping clone",

View File

@ -17,6 +17,7 @@ mod git_clone;
mod git_provider;
mod interactive;
mod projects_list;
mod shell;
#[derive(Parser)]
#[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")]
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)]
@ -64,7 +71,13 @@ async fn main() -> anyhow::Result<()> {
Some(_) => todo!(),
None => {
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?;
}
}

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 Height 1000
Hide
Type "./target/debug/gitnow --no-cache"
Type "./target/debug/gitnow --no-cache --force-refresh"
Enter
Show
Sleep 2s
Type@500ms "bevy"
Sleep 1s
Enter
Sleep 10s
Type "echo 'I am now in bevy!'"
Enter
Sleep 5s
Sleep 2s