Skip to content

Commit

Permalink
feat: Allow customising the root
Browse files Browse the repository at this point in the history
  • Loading branch information
siketyan committed Nov 5, 2022
1 parent d978295 commit c7388f1
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 4 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,21 @@ owner = "acme" # Applies company profiles to all repositories in `acme` org
[[rules]]
profile.name = "default"
```

### Finding path of the repository
```shell
ghr path # Root directory
ghr path <owner> # Owner root
ghr path <owner> <repo> # Repository directory
ghr path --host=github.com # Host root
ghr path --host=github.com <owner> # Owner root of the specified host
ghr path --host=github.com <owner> <repo> # Repository directory of the specified host
```

## 🛠 Customising
You can change the root of repositories managed by ghr by setting environment variable `GHR_ROOT` in your shell profile.

```shell
ghr path # ~/.ghr
GHR_ROOT=/path/to/root ghr path # /path/to/root
```
4 changes: 4 additions & 0 deletions src/cmd/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod clone;
mod path;
mod profile;

use anyhow::Result;
Expand All @@ -8,6 +9,8 @@ use clap::{Parser, Subcommand};
pub enum Action {
/// Clones a Git repository to local.
Clone(clone::Cmd),
/// Prints the path to root, owner, or a repository.
Path(path::Cmd),
/// Manages profiles to use in repositories.
Profile(profile::Cmd),
}
Expand All @@ -23,6 +26,7 @@ impl Cli {
use Action::*;
match self.action {
Clone(cmd) => cmd.run().await,
Path(cmd) => cmd.run(),
Profile(cmd) => cmd.run(),
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/cmd/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::path::PartialPath;
use crate::root::Root;
use anyhow::{anyhow, Result};
use clap::Parser;
use std::path::PathBuf;

#[derive(Debug, Parser)]
pub struct Cmd {
/// Remote host of the repository.
/// Defaults to github.com.
#[clap(long)]
host: Option<String>,
/// Owner name of the repository.
owner: Option<String>,
/// Repository name.
repo: Option<String>,
}

impl Cmd {
pub fn run(self) -> Result<()> {
let root = Root::find()?;
let path = PartialPath {
root: &root,
host: self.host,
owner: self.owner,
repo: self.repo,
};

let path = PathBuf::from(path);
if !path.exists() || !path.is_dir() {
return Err(anyhow!(
"The path does not exist or is not a directory. Did you cloned the repository?"
));
}

println!("{}", path.to_string_lossy());

Ok(())
}
}
5 changes: 4 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ mod root;
mod rule;
mod url;

use clap::Parser;
use std::io::stderr;
use std::process::exit;

use clap::Parser;
use tracing::error;
use tracing_subscriber::filter::LevelFilter;
use tracing_subscriber::EnvFilter;
Expand All @@ -25,6 +27,7 @@ async fn main() {
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy(),
)
.with_writer(stderr)
.init();

if let Err(e) = Cli::parse().run().await {
Expand Down
34 changes: 34 additions & 0 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,37 @@ impl<'a> From<Path<'a>> for PathBuf {
(&p).into()
}
}

pub struct PartialPath<'a> {
pub root: &'a Root,
pub host: Option<String>,
pub owner: Option<String>,
pub repo: Option<String>,
}

impl<'a> From<&PartialPath<'a>> for PathBuf {
fn from(p: &PartialPath<'a>) -> Self {
let mut path = p.root.path().to_owned();

match p.host.as_deref() {
Some(h) => path = path.join(h),
_ => return path,
}

match p.owner.as_deref() {
Some(o) => path = path.join(o),
_ => return path,
}

match p.repo.as_deref() {
Some(r) => path.join(r),
_ => path,
}
}
}

impl<'a> From<PartialPath<'a>> for PathBuf {
fn from(p: PartialPath<'a>) -> Self {
(&p).into()
}
}
17 changes: 14 additions & 3 deletions src/root.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
use std::env::var;
use std::path::PathBuf;
use std::str::FromStr;

use anyhow::{anyhow, Result};
use dirs::home_dir;
use tracing::info;

const ENV_VAR_KEY: &str = "GHR_ROOT";
const DEFAULT_ROOT_NAME: &str = ".ghr";

pub struct Root {
path: PathBuf,
}

impl Root {
pub fn find() -> Result<Self> {
let path = home_dir()
.ok_or_else(|| anyhow!("Could not find a home directory"))?
.join(".ghr");
let path = match var(ENV_VAR_KEY).ok().and_then(|s| match s.is_empty() {
true => None,
_ => Some(s),
}) {
Some(p) => PathBuf::from_str(&p)?.canonicalize()?,
_ => home_dir()
.ok_or_else(|| anyhow!("Could not find a home directory"))?
.join(DEFAULT_ROOT_NAME),
};

info!(
"Found a root directory: {}",
Expand Down

0 comments on commit c7388f1

Please sign in to comment.