Skip to content

Commit

Permalink
Add a clone repository command
Browse files Browse the repository at this point in the history
Add a command to clone a git repository in the the first search path and
create a session for the cloned repository.
  • Loading branch information
petersimonsson committed Feb 9, 2024
1 parent c545ca0 commit 1a810aa
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 30 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,21 @@ Using this command you can automatically generate missing worktree windows for t
Use `tms --help`

```
Scan for all git folders in specified directories, select one and open it as a new tmux session
Scan for all git folders in specified directorires, select one and open it as a new tmux session
Usage: tms [COMMAND]
Commands:
config Configure the defaults for search paths and excluded directories
start Initialize tmux with the default sessions
switch Display other sessions with a fuzzy finder and a preview window
windows Display the current session's windows with a fuzzy finder and a preview window
kill Kill the current tmux session and jump to another
sessions Show running tmux sessions with asterisk on the current session
rename Rename the active session and the working directory
refresh Creates new worktree windows for the selected session
help Print this message or the help of the given subcommand(s)
config Configure the defaults for search paths and excluded directories
start Initialize tmux with the default sessions
switch Display other sessions with a fuzzy finder and a preview window
windows Display the current session's windows with a fuzzy finder and a preview window
kill Kill the current tmux session and jump to another
sessions Show running tmux sessions with asterisk on the current session
rename Rename the active session and the working directory
refresh Creates new worktree windows for the selected session
clone-repo Clone repository into the first search path and create a new session for it
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
Expand Down
63 changes: 62 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::{
configs::SearchDirectory,
configs::{Config, SessionSortOrderConfig},
dirty_paths::DirtyUtf8Path,
execute_command, execute_tmux_command, get_single_selection, TmsError,
execute_command, execute_tmux_command, get_single_selection, session_exists, set_up_tmux_env,
switch_to_session, TmsError,
};
use clap::{Args, Parser, Subcommand};
use error_stack::{Result, ResultExt};
Expand Down Expand Up @@ -38,6 +39,8 @@ pub enum CliCommand {
Rename(RenameCommand),
/// Creates new worktree windows for the selected session
Refresh(RefreshCommand),
/// Clone repository into the first search path and create a new session for it
CloneRepo(CloneRepoCommand),
}

#[derive(Debug, Args)]
Expand Down Expand Up @@ -99,6 +102,12 @@ pub struct RefreshCommand {
name: Option<String>,
}

#[derive(Debug, Args)]
pub struct CloneRepoCommand {
/// Git repository to clone
repository: String,
}

impl Cli {
pub(crate) fn handle_sub_commands(&self) -> Result<SubCommandGiven, TmsError> {
// Get the configuration from the config file
Expand Down Expand Up @@ -147,6 +156,12 @@ impl Cli {
refresh_command(args)?;
Ok(SubCommandGiven::Yes)
}

Some(CliCommand::CloneRepo(args)) => {
clone_repo_command(args, config)?;
Ok(SubCommandGiven::Yes)
}

None => Ok(SubCommandGiven::No(config.into())),
}
}
Expand Down Expand Up @@ -561,6 +576,52 @@ fn refresh_command(args: &RefreshCommand) -> Result<(), TmsError> {
Ok(())
}

fn clone_repo_command(args: &CloneRepoCommand, config: Config) -> Result<(), TmsError> {
let search_dirs = config
.search_dirs
.ok_or(TmsError::ConfigError)
.attach_printable("No search path configured")?;
let mut path = search_dirs
.first()
.ok_or(TmsError::ConfigError)
.attach_printable("No search path configured")?
.path
.clone();

let (_, repo_name) = args
.repository
.rsplit_once('/')
.expect("Repository path contains '/'");
let repo_name = repo_name.trim_end_matches(".git");
path.push(repo_name);

let repo = Repository::clone(&args.repository, &path).change_context(TmsError::GitError)?;

let mut session_name = repo_name.to_string();

if session_exists(&session_name) {
session_name = format!(
"{}/{}",
path.parent()
.unwrap()
.file_name()
.expect("The file name doesn't end in `..`")
.to_string()?,
session_name
);
}

execute_tmux_command(&format!(
"tmux new-session -ds {} -c {}",
session_name,
path.display()
));
set_up_tmux_env(&repo, &session_name)?;
switch_to_session(&session_name);

Ok(())
}

pub enum SubCommandGiven {
Yes,
No(Box<Config>),
Expand Down
43 changes: 25 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,34 +110,41 @@ fn main() -> Result<(), TmsError> {
repo_name
};

// Get the tmux sessions
let sessions = String::from_utf8(execute_tmux_command("tmux list-sessions -F #S").stdout)
.expect("The tmux command static string should always be valid utf-8");
let mut sessions = sessions.lines();

// If the session already exists switch to it, else create the new session and then switch
let session_previously_existed = sessions.any(|line| {
// tmux will return the output with extra ' and \n characters
line.to_owned().retain(|char| char != '\'' && char != '\n');
line == repo_short_name
});
if !session_previously_existed {
if !session_exists(&repo_short_name) {
execute_tmux_command(&format!(
"tmux new-session -ds {repo_short_name } -c {path}",
));
set_up_tmux_env(found_repo, &repo_short_name)?;
}

switch_to_session(&repo_short_name);

Ok(())
}

pub(crate) fn switch_to_session(repo_short_name: &str) {
if !is_in_tmux_session() {
execute_tmux_command(&format!("tmux attach -t {repo_short_name}"));
return Ok(());
} else {
let result = execute_tmux_command(&format!("tmux switch-client -t {repo_short_name}"));
if !result.status.success() {
execute_tmux_command(&format!("tmux attach -t {repo_short_name}"));
}
}
}

let result = execute_tmux_command(&format!("tmux switch-client -t {repo_short_name}"));
if !result.status.success() {
execute_tmux_command(&format!("tmux attach -t {repo_short_name}"));
}
Ok(())
pub(crate) fn session_exists(repo_short_name: &str) -> bool {
// Get the tmux sessions
let sessions = String::from_utf8(execute_tmux_command("tmux list-sessions -F #S").stdout)
.expect("The tmux command static string should always be valid utf-8");
let mut sessions = sessions.lines();

// If the session already exists switch to it, else create the new session and then switch
sessions.any(|line| {
// tmux will return the output with extra ' and \n characters
line.to_owned().retain(|char| char != '\'' && char != '\n');
line == repo_short_name
})
}

pub(crate) fn set_up_tmux_env(repo: &Repository, repo_name: &str) -> Result<(), TmsError> {
Expand Down

0 comments on commit 1a810aa

Please sign in to comment.