Compare commits
2 Commits
9d413d4d84
...
253d64efa4
Author | SHA1 | Date | |
---|---|---|---|
|
253d64efa4 | ||
c2faf6d0b6 |
@ -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 |
@ -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(())
|
||||||
|
@ -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",
|
||||||
|
@ -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?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
crates/gitnow/src/shell.rs
Normal file
65
crates/gitnow/src/shell.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user