Skip to content

Commit

Permalink
Merge pull request #2 from Hamster5295/dev
Browse files Browse the repository at this point in the history
V0.1.0
  • Loading branch information
Hamster5295 authored Jan 6, 2024
2 parents 477f48b + 335d95b commit 4e7bb59
Show file tree
Hide file tree
Showing 7 changed files with 505 additions and 103 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# ChangeLog
This is the changelog of **Godo**, a version manager for [Godot Engine](https://github.com/godotengine/godot).

## [1.0.0] - 2024-1-6
### Added
* Basic command support
* `install` - Install Godot Engine with specific version.
* `uninstall` - Uninstall Godot Engine with specific version.
* `available` - Show the list of the available Godot Engine versions.
* `list` - List the installed Godot Engines.
* `run` - Run Godot Engine with specific version.
* Automatic installing, uninstalling and running features.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
[package]
name = "godo"
version = "0.1.0"
authors = ["Hamster5295 <[email protected]>"]
edition = "2021"
description = "A version manager for Godot Engine."
readme= "README.md"
repository = "https://github.com/Hamster5295/godo"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
60 changes: 55 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,58 @@
# Godo
A command-line tool for managing Godot Engines on local machine.
A command-line tool for managing different versions of [Godot Engine](https://github.com/godotengine/godot)s.

Written in Rust.
**Currently Under Development**

## Expected Features
* Installing and uninstalling Godot by specified versions.
* Running Godot instances from Cli.
> [info]
> Currently **Godo** supports Windows only, and will soon catch up with macos and linux :D
## Quick Start
Install the latest stable version of Godot:
```Bash
godo install
```

...with **Mono** support:
```Bash
godo install -m
```

Install 3.x version:
```Bash
godo install 3
```


Run Godot with latest stable version:
```Bash
godo run
```

...with specified version:
```Bash
godo run 3
```


See what's available to install!
```Bash
godo available
```


...with **prereleased** versions
```Bash
godo available -p
```


What's already installed?
```Bash
godo list
```


I don't want the version anymore!
```Bash
godo uninstall 4.2-stable
```
220 changes: 180 additions & 40 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,96 +1,181 @@
mod procedure;
mod remote;
mod utils;
mod version;

use std::fs;
use std::{fs, process::exit};

use clap::{Parser, Subcommand};
use console::Style;
use dialoguer::Confirm;
use remote::get_download_info;
use remote::search_remote_version;
use reqwest::Client;

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Args {
#[command(subcommand)]
command: Command,
command: CliCommand,
}

#[derive(Subcommand, Clone)]
enum Command {
enum CliCommand {
/// Install Godot with optional specific version.
Install {
/// The version to install
/// The version to install.
version: Option<String>,

/// Whether to install the Mono version (with C# support)
/// Whether to install the Mono version (with C# support).
#[arg(short, long)]
mono: bool,
},
/// List all the available released versions

/// Uninstall specific Godot version.
Uninstall {
/// The version to install.
version: Option<String>,

/// Whether to install the Mono version (with C# support).
#[arg(short, long)]
mono: bool,
},

/// List available Godot versions.
Available {
/// Whether to list prereleased versions
#[arg(short, long)]
prerelease: bool,
},
/// List all the installed versions

/// List installed Godot versions.
List,

/// Run Godot with specific version.
Run {
/// The version to run. Automaticly runs the latest stable version when not specified.
version: Option<String>,

/// Whether to run the Mono version.
#[arg(short, long)]
mono: Option<bool>,

/// Whether to run with console. Has no effect with Godot 3.x
#[arg(short, long)]
console: bool,
},
}

#[tokio::main]
async fn main() {
let args = Args::parse();

let cyan = Style::new().cyan().bold().bright();
match &args.command {
CliCommand::Install { version, mono } => handle_install(version, mono).await,
CliCommand::Uninstall { version, mono } => handle_uninstall(version, mono),
CliCommand::Available { prerelease } => handle_available(prerelease).await,
CliCommand::List => handle_list(),
CliCommand::Run {
version,
mono,
console,
} => handle_run(version, mono, console).await,
}
}

async fn handle_available(prerelease: &bool) {
let client = Client::new();
remote::list_avail(&client, *prerelease).await;
}

fn handle_list() {
let dim = Style::new().dim();
let yellow = Style::new().yellow().bold();
let red = Style::new().red().bold();
let green = Style::new().green().bold();

match &args.command {
Command::Install { version, mono } => {
handle_install(version, mono);
println!("{}", yellow.apply_to("Installed"));
println!("{}", dim.apply_to("=".repeat(15)));

let installed_dirs = utils::get_installed_dirs();
if installed_dirs.len() > 0 {
for dir in installed_dirs {
if let Some(ver) = version::parse(dir) {
println!("{}", ver.short_name());
}
}
Command::Available { prerelease } => {
let client = Client::new();
remote::list_avail(&client, *prerelease).await;
} else {
println!("{}", dim.apply_to("Nothing yet..."));
}
}

async fn handle_run(version: &Option<String>, mono: &Option<bool>, console: &bool) {
let red = Style::new().red().bold();

if let Some(ver) = utils::search_installed_version(version, *mono) {
if let Some(exec) = utils::get_executable(ver.dir_name(), *console) {
tokio::process::Command::new(exec).spawn().expect(
format!(
"{} {}",
red.apply_to("Failed to run"),
red.apply_to(ver.version_name())
)
.as_str(),
);
}
Command::List => {
let installed_dirs = utils::get_installed_dirs();
for dir in installed_dirs {
println!("{}", dir);
} else {
println!("{}", red.apply_to("No installed version found."));
if Confirm::new()
.with_prompt("Install a new version?")
.wait_for_newline(true)
.interact()
.unwrap()
{
if let Some(mono_flag) = mono {
handle_install(version, mono_flag).await;
} else {
handle_install(version, &false).await;
}
} else {
println!("{}", red.apply_to("Aborted."));
}
}
}

async fn handle_install(version: &Option<String>, mono: &bool) {
let cyan = Style::new().cyan().bold().bright();
let yellow = Style::new().yellow().bold();
let cmd = Style::new().yellow().underlined().bold();
let red = Style::new().red().bold();
let green = Style::new().green().bold();

let version_str: String;
match version {
Some(ver) => {
version_str = ver.clone();
}
None => version_str = "4".to_string(),
}

let proc = &mut procedure::new(5);
let client = Client::new();

match get_download_info(&client, version_str, *mono).await {
Some((tag, url)) => {
let proc = &mut procedure::new(4);
let version_name = utils::get_version_name(&tag, mono);
let file_name = utils::get_dir_name(&tag, mono);
proc.next("Searching for available versions...".to_string());
match search_remote_version(&client, version, *mono).await {
Some((ver, url)) => {
proc.finish("Found!".to_string());
let installed = utils::get_installed_versions();
if installed.contains(&ver) {
println!(
"{} {}",
cyan.apply_to(ver.version_name()),
"has been installed already."
);
println!(
"Use {} to list the installed versions.",
cmd.apply_to("godo list")
);
println!("{}", red.apply_to("Aborted."));
exit(0);
}

let version_name = ver.version_name();
let file_name = ver.dir_name();

// Confirm before download
proc.next("Please confirm your installation:".to_string());
proc.next("The following version is about to be installed:".to_string());
println!("\t> {} <", cyan.apply_to(&version_name));
if Confirm::new()
.with_prompt("Do you want to proceed?")
.with_prompt("Proceed?")
.default(true)
.show_default(true)
.wait_for_newline(true)
Expand All @@ -104,7 +189,7 @@ async fn handle_install(version: &Option<String>, mono: &bool) {

// Unzip
proc.next(format!("{}", yellow.apply_to("Unzipping...")));
remote::unzip(&path);
remote::unzip(&path, ver.mono());
proc.finish("Unzipped!".to_string());

// Remove the original zipped file
Expand All @@ -120,11 +205,39 @@ async fn handle_install(version: &Option<String>, mono: &bool) {
);
println!(
"Use {} {} to start.",
yellow.apply_to("godo run"),
green.apply_to(&tag)
cmd.apply_to("godo run"),
green.apply_to(ver.tag())
);
println!();

if ver.mono() {
let non_mono_ver = version::new(ver.tag(), false);
if installed.contains(&non_mono_ver) {
println!(
"Non-Mono version {} is detected.",
cyan.apply_to(non_mono_ver.short_name())
);
println!(
"Mono version contains {} within non-mono ones.",
yellow.apply_to("All Features")
);

if Confirm::new()
.with_prompt("Uninstall the non-mono version?")
.default(true)
.show_default(true)
.wait_for_newline(true)
.interact()
.unwrap()
{
handle_uninstall(&Some(non_mono_ver.tag()), &false);
} else {
println!("{}", green.apply_to("Done!"))
}
}
}
} else {
println!("{}", red.apply_to("Installation aborted"))
println!("{}", red.apply_to("Aborted."))
}
}
None => {
Expand All @@ -136,3 +249,30 @@ async fn handle_install(version: &Option<String>, mono: &bool) {
}
};
}

fn handle_uninstall(version: &Option<String>, mono: &bool) {
let red = Style::new().red().bold();

if let Some(ver) = utils::search_installed_version(version, Some(*mono)) {
let mut proc = procedure::new(2);

proc.next("The following version is about to be uninstalled:".to_string());
println!("\t> {} <", red.apply_to(ver.version_name()));
if Confirm::new()
.with_prompt("Do you want to proceed?")
.default(true)
.show_default(true)
.wait_for_newline(true)
.interact()
.unwrap()
{
proc.next("Uninstalling".to_string());
utils::uninstall_version(ver);
proc.finish("Uninstalled!".to_string());
} else {
println!("{}", red.apply_to("Aborted."))
}
} else {
println!("{}", red.apply_to("No installed version found."));
}
}
Loading

0 comments on commit 4e7bb59

Please sign in to comment.