Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ description = "A simple CLI tool to mannage platforms for git repositories"
homepage = "https://github.com/feraxhp/grp"

[dependencies]
grp-core = { path = "./grp-core", version="0.1.0" }
grp-core = { path = "./grp-core", version="0.1.2" }
tokio = { version = "1.49.0", features = ["rt", "rt-multi-thread", "macros"] }
reqwest = { version = "0.13.1", features = ["json"] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
clap = { version = "4.5.54" , features = ["cargo"] }
clap = { version = "4.5.60" , features = ["cargo"] }
dirs = "6.0.0"
color-print = "0.3.7"
indicatif = "0.18.3"
futures = "0.3.31"
git2 = "0.20.3"
urlencoding = "2.1.3"
regex = "1.12.2"
clap_complete = { version = "4.5.65", features = ["unstable-dynamic"] }
clap_complete = { version = "4.5.66", features = ["unstable-dynamic"] }
cfg-if = "1.0.4"
directories = "6.0.0"

[[bin]]
name = "grp"
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ cargo install girep --version 0.11.0-beta
~~~bash
source <(COMPLETE=bash grp)
~~~
Currently bash has a little problem with the autocompletion...
so, in order to solve the problem for auto completion of the repostructure
you may whant to add the completion to a file, and replace the last 5 lines
for the next:
~~~bash
if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then
COMP_WORDBREAKS=${COMP_WORDBREAKS//:} complete -o nospace -o bashdefault -o nosort -F _clap_complete_grp dgrp
else
COMP_WORDBREAKS=${COMP_WORDBREAKS//:} complete -o nospace -o bashdefault -F _clap_complete_grp dgrp
fi
~~~
> [!note]
> I already open a feature request in [clap-rs](https://github.com/clap-rs/clap/)
> if you find this a _Headache_ please help me by comenting in this [issue](https://github.com/clap-rs/clap/issues/6280)

### zsh
~~~zsh
Expand Down
2 changes: 1 addition & 1 deletion grp-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "grp-core"
version = "0.1.1"
version = "0.1.2"
edition = "2024"
license = "GPL-3.0-only"
authors = ["feraxhp <feraxhp+gh@gmail.com>"]
Expand Down
6 changes: 5 additions & 1 deletion grp-core/src/error/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ impl Error {
}
}

pub fn new_custom<T: Into<String>>(message: T, content: Vec<T>) -> Error {
pub fn new_custom<M, C>(message: M, content: Vec<C>) -> Error
where
M: Into<String>,
C: Into<String>
{
Error {
message: message.into(),
content: content.into_iter().map(|s| s.into()).collect()
Expand Down
3 changes: 3 additions & 0 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod structure;
pub mod users;
pub mod repos;
68 changes: 68 additions & 0 deletions src/cache/repos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use grp_core::Error;
use grp_core::structs::Repo;
use std::collections::{HashMap, HashSet};

use crate::cache::structure::{Cacher, Hasher, Uncacher, Values};

impl Hasher for Vec<Repo> {
fn to_set(&self) -> HashSet<String> {
let mut hash = HashSet::new();
self.iter()
.map(|s| { s.path.clone() })
.for_each(|s| { hash.insert(s); });

hash
}

fn to_values(&self) -> Values {
Values {
repos: self.to_set(),
users: HashSet::new()
}
}
}

impl Cacher for Vec<Repo> {
fn get(pconf: &str) -> Result<HashSet<String>, Error> {
let values = Self::load()?;
match values.get(pconf) {
Some(v) => Ok(v.repos.clone()),
None => Ok(HashSet::new()),
}
}

fn put(&self, pconf: &str, union: bool) -> Result<HashMap<String, Values>, Error> {
let mut values = Self::load()?;

match values.get_mut(pconf) {
Some(p) if union => {
p.repos = p.repos
.union(&self.to_set())
.cloned()
.collect();
}
Some(p) => {
p.repos = self.to_set();
}
None => {
values.insert(pconf.to_string(), self.to_values());
}
};

Ok(values)
}
}

impl Uncacher<Vec<Repo>> for Repo {
fn __rm(pconf: &str, name: &str) -> Result<Option<HashMap<String, Values>>, Error> {
let mut values = Self::load()?;

let removed = match values.get_mut(pconf) {
Some(p) => p.repos.remove(name),
None => false
};

if removed { Ok(Some(values)) }
else { Ok(None) }
}
}
74 changes: 74 additions & 0 deletions src/cache/structure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use std::{collections::{HashMap, HashSet}, path::PathBuf};

use color_print::cformat;
use grp_core::{Error, JSON};
use serde::{Deserialize, Serialize};

use crate::system::{directories::{Cache, Directories}, file::File};

#[derive(Debug, Serialize, Deserialize)]
pub struct Values {
pub users: HashSet<String>,
pub repos: HashSet<String>
}

pub trait Cacher {
fn path() -> Result<PathBuf, Error> { Cache::file() }
fn load() -> Result<HashMap<String, Values>, Error> {
let path = Self::path()?;
let text = File::read(&path)?;

if text.is_empty() { return Ok(HashMap::new()) }

JSON::from_str(&text)
}

fn get(pconf: &str) -> Result<HashSet<String>, Error>;
fn put(&self, pconf: &str, union: bool) -> Result<HashMap<String, Values>, Error>;

fn save(&self, pconf: &str, union: bool) -> Result<(), Error> {
let path = Self::path()?;
let data = self.put(pconf, union)?;

let contents = serde_json::to_string_pretty(&data)
.map_err(|e| Error::new_custom(
"Error creating the configuration file".to_string(),
vec![
cformat!("<r>* Error:</> {:?}", e)
]
))?;

File::write(&path, &contents)
}
}

pub trait Uncacher<T>
where
T: Cacher
{
fn load() -> Result<HashMap<String, Values>, Error> { T::load() }
fn remove(pconf: &str, name: &str) -> Result<bool, Error> {
let path = T::path()?;
let data = match Self::__rm(pconf, name)? {
Some(d) => d,
None => return Ok(false),
};

let contents = serde_json::to_string_pretty(&data)
.map_err(|e| Error::new_custom(
"Error creating the configuration file".to_string(),
vec![
cformat!("<r>* Error:</> {:?}", e)
]
))?;

File::write(&path, &contents)?;
Ok(true)
}
fn __rm(pconf: &str, name: &str) -> Result<Option<HashMap<String, Values>>, Error>;
}

pub trait Hasher {
fn to_set(&self) -> HashSet<String>;
fn to_values(&self) -> Values;
}
73 changes: 73 additions & 0 deletions src/cache/users.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use grp_core::Error;
use grp_core::structs::User;
use std::collections::{HashMap, HashSet};

use crate::cache::structure::{Cacher, Hasher, Uncacher, Values};

impl Hasher for Vec<User> {
fn to_set(&self) -> HashSet<String> {
let mut hash = HashSet::new();
self.iter()
.map(|s| {
match &s.path {
Some(p) => p.clone(),
None => s.name.clone(),
}
})
.for_each(|s| { hash.insert(s); });

hash
}

fn to_values(&self) -> Values {
Values {
users: self.to_set(),
repos: HashSet::new()
}
}
}

impl Cacher for Vec<User> {
fn get(pconf: &str) -> Result<HashSet<String>, Error> {
let values = Self::load()?;
match values.get(pconf) {
Some(v) => Ok(v.users.clone()),
None => Ok(HashSet::new()),
}
}

fn put(&self, pconf: &str, union: bool) -> Result<HashMap<String, Values>, Error> {
let mut values = Self::load()?;

match values.get_mut(pconf) {
Some(p) if union => {
p.users = p.users
.union(&self.to_set())
.cloned()
.collect();
}
Some(p) => {
p.users = self.to_set();
}
None => {
values.insert(pconf.to_string(), self.to_values());
}
};

Ok(values)
}
}

impl Uncacher<Vec<User>> for User {
fn __rm(pconf: &str, name: &str) -> Result<Option<HashMap<String, Values>>, Error> {
let mut values = Self::load()?;

let removed = match values.get_mut(pconf) {
Some(p) => p.users.remove(name),
_ => false
};

if removed { Ok(Some(values)) }
else { Ok(None) }
}
}
Loading