Skip to content

Commit

Permalink
Merge pull request #2 from Caznix/main
Browse files Browse the repository at this point in the history
rename binaries to proj name
  • Loading branch information
tristanpoland authored Dec 31, 2024
2 parents b29f373 + 3556b6e commit 9ddf205
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 41 deletions.
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[alias]
grip = "run -q --"
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ anyhow = "1.0"
config = "0.13"
bytes = "1.8.0"
thiserror = "1.0"
lazy_static = "1.5.0"

[target.'cfg(windows)'.dependencies]
winreg = "0.50"
winapi = { version = "0.3", features = ["winuser", "minwindef"] }
winapi = { version = "0.3", features = ["winuser", "minwindef"] }
8 changes: 5 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use clap::{Parser, Subcommand};

#[derive(Debug, Parser)]
#[derive(Debug, Parser,Clone)]
#[command(author, version, about = "GitHub Release Package Manager")]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
#[arg(short,long)]
pub debug: bool
}

#[derive(Debug, Subcommand)]
#[derive(Debug, Subcommand,Clone)]
pub enum Commands {
/// Install a package
Install {
Expand All @@ -29,7 +31,7 @@ pub enum Commands {
},
}

#[derive(Debug, Subcommand)]
#[derive(Debug, Subcommand,Clone)]
pub enum RegistryCommands {
/// Add a new registry
Add {
Expand Down
1 change: 0 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use crate::error::Result;

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down
119 changes: 88 additions & 31 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ mod path;
mod registry;
mod utils;

use std::sync::Arc;

use clap::Parser;
use cli::{Cli, Commands, RegistryCommands};
use colored::Colorize;
use config::Config;
use dialoguer::Select;
use error::Result;
use lazy_static::lazy_static;
use registry::RegistryManager;
use clap::Parser;
use dialoguer::Select;

struct Grip {
config: Config,
registry_manager: RegistryManager,
}
lazy_static! {
pub static ref CLI: Arc<Cli> = Arc::new(Cli::parse());
}

impl Grip {
async fn new() -> Result<Self> {
Expand All @@ -36,16 +42,31 @@ impl Grip {
})
}

async fn install(&self, package_name: &str, version: Option<String>, asset: Option<String>) -> Result<()> {
async fn install(
&self,
package_name: &str,
version: Option<String>,
asset: Option<String>,
) -> Result<()> {
println!("{} Looking up package {}", "→".blue(), package_name.cyan());

// Find package in registry
let package = self.registry_manager.find_package(&self.config.registries, package_name).await?;

println!("{} Found package in repository: {}", "→".blue(), package.info.repository.cyan());
let package = self
.registry_manager
.find_package(&self.config.registries, package_name)
.await?;

println!(
"{} Found package in repository: {}",
"→".blue(),
package.info.repository.cyan()
);

// Get releases from GitHub
let releases = self.registry_manager.get_releases(&package.info.repository).await?;
let releases = self
.registry_manager
.get_releases(&package.info.repository)
.await?;

if releases.is_empty() {
anyhow::bail!("No releases found for package '{}'", package_name);
Expand Down Expand Up @@ -85,10 +106,8 @@ impl Grip {
.find(|asset| asset["name"].as_str().unwrap_or("") == a)
.ok_or_else(|| anyhow::anyhow!("Asset {} not found", a))?,
None => {
let asset_names: Vec<&str> = assets
.iter()
.filter_map(|a| a["name"].as_str())
.collect();
let asset_names: Vec<&str> =
assets.iter().filter_map(|a| a["name"].as_str()).collect();

println!("{} Available assets:", "→".blue());
let selection = Select::new()
Expand All @@ -104,29 +123,58 @@ impl Grip {
let download_url = asset_obj["browser_download_url"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("Invalid download URL"))?;

let filename = asset_obj["name"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("Invalid asset name"))?;

// Download and install
let target_dir = self.registry_manager.data_dir
let target_dir = self
.registry_manager
.data_dir
.join("packages")
.join(package_name)
.join(release["tag_name"].as_str().unwrap_or("unknown"));

let downloaded_file = self.registry_manager
let downloaded_file = self
.registry_manager
.download_asset(download_url, filename, &target_dir)
.await?;

let mut binary_name: Option<String> = None;
#[cfg(target_os = "windows")]
if package.info.executable_name.is_some() {

let original_name = asset_obj["name"].to_string();
let path = std::path::Path::new(&original_name);
let extension = path.extension().unwrap_or_default().to_string_lossy();
binary_name = Some(format!("{}.{}", package_name, extension));
}
// Handle archive extraction if needed
if filename.ends_with(".zip") || filename.ends_with(".tar.gz") || filename.ends_with(".tgz") {
if filename.ends_with(".zip") || filename.ends_with(".tar.gz") || filename.ends_with(".tgz")
{
println!("{} Extracting archive...", "→".blue());
utils::extract_archive(&downloaded_file, &target_dir);
utils::extract_archive(&downloaded_file, &target_dir).await?;
println!("{} Extracted to {:?}", "✓".green(), target_dir);

if package.info.executable_name.is_some() {
println!(" tesdafsdfasgsgeg3544ttwrergtdhyrwraesd{}",package.info.executable_name.clone().unwrap());
std::fs::rename(&downloaded_file, target_dir.join(package.info.executable_name.clone().unwrap()))?;
} else {
println!("no exe name")
}
// Clean up archive after extraction
std::fs::remove_file(downloaded_file)?;
} else {
if package.info.executable_name.is_some() {
println!(" tesdafsdfasgsgeg3544ttwrergtdhyrwraesd{}",package.info.executable_name.clone().unwrap());
let path = downloaded_file.parent().unwrap();
let name = binary_name.unwrap();
let name = name.trim_matches('"');
let bin_path = path.join(name);
println!("renaming {} to {}", downloaded_file.display(), bin_path.display());
std::fs::copy(downloaded_file, bin_path)?;
} else {
println!("no zip and no exe name")
}
}

// Add to PATH if needed
Expand All @@ -135,10 +183,13 @@ impl Grip {
println!("{} Installation complete!", "✓".green());
Ok(())
}

async fn handle_registry_command(&mut self, cmd: RegistryCommands) -> Result<()> {
match cmd {
RegistryCommands::Add { name, url, priority } => {
RegistryCommands::Add {
name,
url,
priority,
} => {
if self.config.registries.iter().any(|r| r.name == name) {
anyhow::bail!("Registry '{}' already exists", name);
}
Expand Down Expand Up @@ -167,7 +218,9 @@ impl Grip {
self.config.save()?;

// Remove cached registry
let registry_path = self.registry_manager.data_dir
let registry_path = self
.registry_manager
.data_dir
.join("registries")
.join(&name);
if registry_path.exists() {
Expand All @@ -179,7 +232,8 @@ impl Grip {
RegistryCommands::List => {
println!("{} Configured registries:", "→".blue());
for registry in &self.config.registries {
println!(" {} {} (priority: {}, url: {})",
println!(
" {} {} (priority: {}, url: {})",
"→".blue(),
registry.name.cyan(),
registry.priority,
Expand All @@ -198,10 +252,7 @@ impl Grip {
"dependencies": {}
});

std::fs::write(
"grip.json",
serde_json::to_string_pretty(&config)?,
)?;
std::fs::write("grip.json", serde_json::to_string_pretty(&config)?)?;

println!("{} Created grip.json", "✓".green());
Ok(())
Expand All @@ -210,11 +261,17 @@ impl Grip {

#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
let mut grip = Grip::new().await?;
let cli = Arc::clone(&CLI);

match cli.command {
Commands::Install { package, version, asset } => {
print_debug!("Cli.debug == true");
let mut grip = Grip::new().await?;
let command = cli.command.clone();
match command {
Commands::Install {
package,
version,
asset,
} => {
grip.install(&package, version, asset).await?;
}
Commands::Registry { cmd } => {
Expand All @@ -226,4 +283,4 @@ async fn main() -> Result<()> {
}

Ok(())
}
}
5 changes: 3 additions & 2 deletions src/package.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use serde::{Deserialize, Serialize};
use crate::error::Result;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Debug, Serialize, Deserialize)]
pub struct PackageInfo {
pub name: String,
pub repository: String,
pub description: Option<String>,
pub executable_name: Option<String>,
}

pub struct Package {
Expand All @@ -32,4 +33,4 @@ pub struct Release {
pub struct Asset {
pub name: String,
pub browser_download_url: String,
}
}
12 changes: 12 additions & 0 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ pub async fn add_to_path(path: &Path) -> Result<()> {

#[cfg(unix)]
pub async fn add_to_path(path: &Path) -> Result<()> {

use std::env;
use std::io::Write;

use crate::print_debug;

let home = env::var("HOME")
.map_err(|_| anyhow::anyhow!("Failed to get HOME directory"))?;
Expand All @@ -86,10 +89,19 @@ pub async fn add_to_path(path: &Path) -> Result<()> {
.create(true)
.open(&shell_rc)?
.write_all(export_line.as_bytes())?;
std::process::Command::new("export")
.arg(format!("PATH={}:$PATH",path.to_string_lossy()))
.spawn().unwrap();

println!("{} Added to PATH in {}", "✓".green(), shell_rc);
println!("{} Run 'source {}' or restart your terminal for changes to take effect", "!".yellow(), shell_rc);
} else {
//print_debug!("attempting to export path for good measure");
use crate::Cli;
print!("{}",path.to_string_lossy());
std::process::Command::new("export")
.arg(format!("PATH={}{}:$PATH",path.to_string_lossy(),))
.spawn().unwrap();
println!("{} Directory already in PATH", "✓".green());
}

Expand Down
15 changes: 12 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
use crate::error::Result;
use std::path::Path;

#[macro_export]
macro_rules! print_debug {
($($arg:tt)*) => {

if CLI.debug {
println!($($arg)*);
}
};
}
pub async fn extract_archive(archive_path: &Path, target_dir: &Path) -> Result<()> {
if archive_path.extension().map_or(false, |ext| ext == "zip") {
let file = std::fs::File::open(archive_path)?;
Expand All @@ -10,7 +18,7 @@ pub async fn extract_archive(archive_path: &Path, target_dir: &Path) -> Result<(
use std::process::Command;

Command::new("tar")
.args(&["xzf", &archive_path.to_string_lossy()])
.args(["xzf", &archive_path.to_string_lossy()])
.current_dir(target_dir)
.status()?;
}
Expand Down Expand Up @@ -116,4 +124,5 @@ pub fn create_symlink(src: &Path, dst: &Path) -> Result<()> {
std::os::windows::fs::symlink_dir(src, dst)?;
}
Ok(())
}
}

0 comments on commit 9ddf205

Please sign in to comment.