Skip to content

Commit

Permalink
v0.4.0
Browse files Browse the repository at this point in the history
- Improved dependency usage
- Removed configuration options
- Removed most subcommands
  • Loading branch information
edfloreshz committed Dec 30, 2024
1 parent 1e37427 commit 6c61eba
Show file tree
Hide file tree
Showing 56 changed files with 907 additions and 9,481 deletions.
File renamed without changes.
6,868 changes: 637 additions & 6,231 deletions Cargo.lock

Large diffs are not rendered by default.

47 changes: 14 additions & 33 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,43 +1,24 @@
[package]
name = "devmode"
description = "A project management utility for developers"
version = "0.3.0"
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
categories.workspace = true
keywords.workspace = true

[dependencies]
libset = "=0.1.2"
clap = { version = "3.2.14", features = ["derive"] }
requestty = "0.4.1"
colored = "2.0.0"
regex = "1.5.4"
git2 = "0.14.4"
git2_credentials = "0.8.0"
cmd_lib = "1.1.0"
walkdir = "2.3.2"
serde = { version = "1.0.126", features = ["derive"] }
fs_extra = "1.2.0"
derive_setters = "0.1.6"
git-url-parse = "0.4.4"
thiserror = "1.0.64"
log = "0.4.22"

[workspace.package]
version = "0.1.0"
version = "0.4.0"
authors = ["Eduardo Flores <[email protected]>"]
description = "Devmode is a project management utility for developers."
edition = "2021"
license = "MIT"
license = "GPL-3.0-only"
repository = "https://github.com/edfloreshz/devmode/"
homepage = "https://devmode.edfloreshz.dev/"
categories = ["development-tools"]
keywords = ["development", "utility"]
exclude = [".idea", ".github", ".vscode"]
exclude = [".idea", ".github", ".vscode", "assets"]
readme = "README.md"

[workspace]
resolver = "2"
members = ["src/cli", "src/ui"]
members = ["cli"]

[workspace.dependencies]
git2 = "0.19.0"
git2_credentials = "0.14.0"
git-url-parse = "0.4.4"
thiserror = "2.0.9"
log = "0.4.22"
dirs = "5.0.1"
2 changes: 1 addition & 1 deletion src/ui/LICENSE → LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
<https://www.gnu.org/licenses/why-not-lgpl.html>.
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<div align="center">
<img width=200 src="https://github.com/edfloreshz/devmode/blob/main/assets/img/devmode.png?raw=true"/>
<h1>Dev(mode)</h1>
<a href="https://crates.io/crates/devmode">
<img src="https://img.shields.io/crates/v/devmode?label=Devmode" alt="crate"/>
</a>
<a href="https://crates.io/crates/devmode">
<img src="https://img.shields.io/crates/d/devmode" alt="downloads"/>
</a>
<a href="https://aur.archlinux.org/packages/devmode-git/">
<img src="https://img.shields.io/aur/version/devmode-git" alt="devmode-git"/>
</a>
</div>

**Devmode** is a project management utility for developers.

```
Usage: dm <COMMAND>
Commands:
cl Clones a repository in a specific folder structure.
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
```

## Installation

#### Cargo

```
cargo install devmode
```
#### Arch Linux
```
paru -S devmode-git
```
## Cloning

When you clone a repository it will be stored to your filesystem using a specific folder structure.

You can also use ` dm cl`

```
$HOME
└── Developer
└── host
└── owner
└── repo
```

| Syntax | Description | Example |
| ---------------- | ------------------------- | ------------------------------------------------ |
| `dm clone <url>` | Clone by providing a URL. | `dm clone https://github.com/edfloreshz/devmode` |

# Dependencies
- openssl

## Proposals

If you have a proposal for a new feature, open a new [issue](https://github.com/edfloreshz/devmode/issues).
Binary file added assets/img/devmode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/img/logo.png
Binary file not shown.
26 changes: 26 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "devmode"
version.workspace = true
description.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
categories.workspace = true
keywords.workspace = true
exclude.workspace = true

[[bin]]
name = "dm"
path = "src/main.rs"

[dependencies]
thiserror = { workspace = true }
log = { workspace = true }
pretty_env_logger = "0.5.0"
clap = { version = "4.5.23", features = ["derive", "cargo"] }
git2 = { workspace = true }
git2_credentials = { workspace = true }
git-url-parse = { workspace = true }
dirs = { workspace = true }
57 changes: 57 additions & 0 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use crate::Error;
use clap::{Parser, Subcommand};
use devmode::{services, CliError};

#[derive(Parser, Debug)]
#[clap(name = "Devmode")]
#[clap(about = "Devmode is a project management utility for developers.")]
#[clap(author, version, about, arg_required_else_help = true)]
pub struct Cli {
#[command(subcommand)]
pub commands: Commands,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
#[command(
about = "Clones a repository in a specific folder structure.",
name = "cl"
)]
Clone {
#[arg(help = "Provide either a Git <url> or a Git <host> <owner> <repo>.")]
url: String,
},
}

impl Cli {
pub fn run(&self) -> Result<(), Error> {
match &self.commands {
Commands::Clone { url } => match services::clone(&url) {
Ok(_) => {
log::info!("Repository cloned to {}", url);
Ok(())
}
Err(services::Error::Clone(services::CloneError::PathExists(path))) => {
if overwrite() {
std::fs::remove_dir_all(&path)?;
log::info!("Removing existing repository at {}", path.display());
log::info!("Cloning {}...", url.to_string());
services::clone(&url)?;
log::info!("Repository cloned to {}", path.display());
Ok(())
} else {
Err(CliError::RepositoryExists.into())
}
}
Err(e) => Err(e.into()),
},
}
}
}

fn overwrite() -> bool {
println!("Found existing repository, overwrite it? y/n");
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
matches!(input.trim(), "y" | "Y")
}
19 changes: 19 additions & 0 deletions cli/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
#[error("{0}")]
Services(#[from] crate::services::Error),
#[error("{0}")]
Parse(#[from] clap::Error),
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
Cli(#[from] CliError),
}

#[derive(Error, Debug)]
pub enum CliError {
#[error("Repository already exists")]
RepositoryExists,
}
4 changes: 4 additions & 0 deletions cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod error;
pub use error::*;

pub mod services;
20 changes: 20 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use ::devmode::Error;
use clap::Parser;
use cli::Cli;

pub mod cli;

fn main() -> Result<(), Error> {
if cfg!(debug_assertions) {
std::env::set_var("RUST_LOG", "trace");
} else {
std::env::set_var("RUST_LOG", "info");
}

pretty_env_logger::init();
let cli = Cli::parse();
if let Err(e) = cli.run() {
log::error!("{e}")
}
Ok(())
}
40 changes: 40 additions & 0 deletions cli/src/services/clone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use git2_credentials::CredentialHandler;
use git_url_parse::GitUrl;

use super::{CloneError, Error};

pub fn clone(url: &str) -> Result<(), Error> {
let url = GitUrl::parse(url)?;

let path = match (&url.host, &url.owner, &url.name) {
(Some(host), Some(owner), name) if !owner.is_empty() => dirs::home_dir()
.unwrap()
.join("Developer")
.join(host)
.join(owner)
.join(name),
_ => return Err(CloneError::InvalidUrl.into()),
};

if path.exists() {
return Err(CloneError::PathExists(path).into());
}

let mut cb = git2::RemoteCallbacks::new();
let config = git2::Config::open_default()?;
let mut credential_handler = CredentialHandler::new(config);

cb.credentials(move |url, username, allowed| {
credential_handler.try_next_credential(url, username, allowed)
});

let mut fetch_options = git2::FetchOptions::new();
fetch_options.remote_callbacks(cb);

let mut builder = git2::build::RepoBuilder::new();
builder.fetch_options(fetch_options);

builder.clone(url.to_string().as_str(), &path)?;

Ok(())
}
21 changes: 21 additions & 0 deletions cli/src/services/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
#[error("{0}")]
GirUrlParseError(#[from] git_url_parse::GitUrlParseError),
#[error("{0}")]
Git(#[from] git2::Error),
#[error("{0}")]
Clone(#[from] CloneError),
}

#[derive(Error, Debug)]
pub enum CloneError {
#[error("Failed to clone repository")]
FailedToCloneRepository,
#[error("This is not a valid Git repository url")]
InvalidUrl,
#[error("Path already exists.")]
PathExists(std::path::PathBuf),
}
5 changes: 5 additions & 0 deletions cli/src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod clone;
pub use clone::*;

mod error;
pub use error::*;
17 changes: 0 additions & 17 deletions src/cli/.gitignore

This file was deleted.

33 changes: 0 additions & 33 deletions src/cli/Cargo.toml

This file was deleted.

Loading

0 comments on commit 6c61eba

Please sign in to comment.