Skip to content

Commit

Permalink
remove indexer command, move relevant subcommands to geode project
Browse files Browse the repository at this point in the history
  • Loading branch information
HJfod committed Feb 26, 2023
1 parent 359f95b commit 15e85dc
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 92 deletions.
152 changes: 81 additions & 71 deletions src/indexer.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,12 @@
use crate::config::{Config, geode_root};
use crate::config::{geode_root};
use crate::input::ask_value;
use std::fs;
use std::path::PathBuf;
use git2::{Repository, ResetType, IndexAddOption, Signature};
use clap::Subcommand;
use crate::package::mod_json_from_archive;
use crate::{info, warn, done, fatal};
use crate::{info, done, fatal, warn};
use colored::Colorize;

#[derive(Subcommand, Debug)]
#[clap(rename_all = "kebab-case")]
pub enum Indexer {
/// Initializes your indexer
Init,

/// Lists all entries in your indexer
List,

/// Removes an entry from your indexer
Remove {
/// Mod ID that you want to remove
id: String
},

/// Exports an entry to your indexer, updating if it always exists
Export {
/// Path to the .geode file
package: PathBuf
}
}

fn reset_and_commit(repo: &Repository, msg: &str) {
let head = repo.head().expect("Broken repository, can't get HEAD");
if !head.is_branch() {
Expand All @@ -53,31 +30,47 @@ fn reset_and_commit(repo: &Repository, msg: &str) {
repo.commit(Some("HEAD"), &sig, &sig, msg, &tree, &[&commit]).expect("Unable to commit");
}

fn initialize() {
let indexer_path = geode_root().join("indexer");
if indexer_path.exists() {
warn!("Indexer is already initialized. Exiting.");
return;
}
pub fn indexer_path() -> PathBuf {
geode_root().join("indexer")
}

info!("Welcome to the Indexer Setup. Here, we will set up your indexer to be compatible with the Geode index.");
info!("Before continuing, make a github fork of https://github.com/geode-sdk/indexer.");
pub fn is_initialized() -> bool {
indexer_path().exists()
}

let fork_url = ask_value("Enter your forked URL", None, true);
Repository::clone(&fork_url, indexer_path).expect("Unable to clone your repository.");
pub fn initialize() {
if is_initialized() {
done!("Indexer is already initialized");
return;
}

done!("Successfully initialized");
info!(
"Before publishing mods on the Geode index, we need to make you a local \
Indexer, which handles everything related to publishing mods."
);
info!(
"The mod binaries will be hosted on your Indexer repository, which will \
automatically request them to be added to the official Mods Index."
);
info!(
"To get started, log in to Github using your account, and go to \
https://github.com/geode-sdk/indexer/fork to make a fork of the Indexer."
);

let fork_url = ask_value("Enter the URL of your fork", None, true);
Repository::clone(&fork_url, indexer_path()).expect("Unable to clone your repository.");

done!("Successfully initialized Indexer");
}

fn list_mods() {
let indexer_path = geode_root().join("indexer");
if !indexer_path.exists() {
fatal!("Indexer has not yet been initialized.");
pub fn list_mods() {
if !is_initialized() {
fatal!("Indexer has not been set up - use `geode indexer init` to set it up");
}

println!("Mod list:");
println!("Published mods:");

for dir in fs::read_dir(indexer_path).unwrap() {
for dir in fs::read_dir(indexer_path()).unwrap() {
let path = dir.unwrap().path();

if path.is_dir() && path.join("mod.geode").exists() {
Expand All @@ -86,11 +79,11 @@ fn list_mods() {
}
}

fn remove_mod(id: String) {
let indexer_path = geode_root().join("indexer");
if !indexer_path.exists() {
fatal!("Indexer has not yet been initialized.");
pub fn remove_mod(id: String) {
if !is_initialized() {
fatal!("Indexer has not been set up - use `geode indexer init` to set it up");
}
let indexer_path = indexer_path();

let mod_path = indexer_path.join(&id);
if !mod_path.exists() {
Expand All @@ -103,18 +96,18 @@ fn remove_mod(id: String) {
reset_and_commit(&repo, &format!("Remove {}", &id));

done!("Succesfully removed {}\n", id);
info!("You will need to force-push this commit yourself. Type: ");
info!("git -C {} push -f", indexer_path.to_str().unwrap());
info!("You will need to force-push to sync your changes.");
info!("Run `git -C {} push -f` to sync your changes", indexer_path.to_str().unwrap());
}

fn export_mod(package: PathBuf) {
let indexer_path = geode_root().join("indexer");
if !indexer_path.exists() {
fatal!("Indexer has not yet been initialized.");
pub fn add_mod(package: PathBuf) {
if !is_initialized() {
fatal!("Indexer has not been set up - use `geode indexer init` to set it up");
}
let indexer_path = indexer_path();

if !package.exists() {
fatal!("Path not found");
fatal!("Package path {} does not exist!", package.display());
}

let mut archive = zip::ZipArchive::new(fs::File::open(&package).unwrap()).expect("Unable to read package");
Expand Down Expand Up @@ -142,28 +135,45 @@ fn export_mod(package: PathBuf) {

let mod_path = indexer_path.join(format!("{}@{}", &mod_id, &major_version));
if !mod_path.exists() {
fs::create_dir(&mod_path).expect("Unable to create folder");
fs::create_dir(&mod_path)
.expect("Unable to create directory in local indexer for mod");
}

fs::copy(package, mod_path.join("mod.geode")).expect("Unable to copy mod");
fs::copy(package, mod_path.join("mod.geode"))
.expect("Unable to copy .geode package to local Indexer");

let repo = Repository::open(&indexer_path).expect("Unable to open repository");
let repo = Repository::open(&indexer_path)
.expect("Unable to open local Indexer repository");
reset_and_commit(&repo, &format!("Add/Update {}", &mod_id));

done!("Successfully exported {}@{} to your indexer\n", mod_id, major_version);

info!("You will need to force-push this commit yourself. Type: ");
info!("git -C {} push -f", indexer_path.to_str().unwrap());
}

pub fn subcommand(_config: &mut Config, cmd: Indexer) {
match cmd {
Indexer::Init => initialize(),

Indexer::List => list_mods(),

Indexer::Remove { id } => remove_mod(id),

Indexer::Export { package } => export_mod(package)
match repo.find_remote("origin").and_then(|mut o| o.push(&["main"], None)) {
Ok(_) => {
done!(
"Succesfully added {}@{} to your indexer!",
mod_id, major_version
);
},
Err(_) => {
done!("Successfully added {}@{}\n", mod_id, major_version);
warn!(
"Unable to automatically sync the changes to Github. \
You will need to push this commit yourself."
);
info!("Run `git -C {} push -f` to push the commit", indexer_path.to_str().unwrap());
},
}
if let Some(url) = repo.find_remote("origin").unwrap().url() {
info!(
"To let us know you're ready to publish your mod, please open \
a Pull Request on your repository: \
{}/compare/geode-sdk:indexer:main...main",
url
);
}
else {
info!(
"To let us know you're ready to publish your mod, please open \
a Pull Request on your Indexer fork repository."
);
};
}
7 changes: 0 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,6 @@ enum GeodeCommands {
Index {
#[clap(subcommand)]
commands: crate::index::Index,
},

/// Subcommand for interacting with your indexer
Indexer {
#[clap(subcommand)]
commands: crate::indexer::Indexer,
}
}

Expand Down Expand Up @@ -106,7 +100,6 @@ fn main() {
GeodeCommands::Package { commands } => package::subcommand(&mut config, commands),
GeodeCommands::Project { commands } => project::subcommand(&mut config, commands),
GeodeCommands::Index { commands } => index::subcommand(&mut config, commands),
GeodeCommands::Indexer { commands } => indexer::subcommand(&mut config, commands),
}

config.save();
Expand Down
84 changes: 70 additions & 14 deletions src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
use std::{fs, path::{PathBuf, Path}, collections::HashMap};
use clap::Subcommand;
use semver::{Version, VersionReq};
use crate::{util::{config::Config, mod_file::{parse_mod_info, ModFileInfo, Dependency, try_parse_mod_info}}, package::get_working_dir, done, warn, info, index::{update_index, index_mods_dir, install_mod}, fail, file::read_dir_recursive, fatal, template};
use crate::{util::{config::Config, mod_file::{parse_mod_info, ModFileInfo, Dependency, try_parse_mod_info}}, package::get_working_dir, done, warn, info, index::{update_index, index_mods_dir, install_mod}, fail, file::read_dir_recursive, fatal, template, indexer};
use edit_distance::edit_distance;

#[derive(Subcommand, Debug)]
#[clap(rename_all = "kebab-case")]
pub enum Project {
/// Initialize a new Geode project
/// Initialize a new Geode project (same as `geode new`)
New {
/// The target directory to create the project in
path: Option<PathBuf>
Expand All @@ -32,28 +32,50 @@ pub enum Project {
#[clap(long, num_args(0..))]
externals: Vec<String>,
},

/// Publish this project on the Geode mods index
Publish {
/// Path to the project's built .geode file. If you are using Geode
/// v1.0.0-beta.8 or newer, CLI should be able to figure this out
/// automatically, unless you are building multiple mods from the
/// same directory
#[clap(short, long)]
package: Option<PathBuf>,
},

/// Unpublish a project from the Geode mods index
Unpublish {
/// ID of the mod to unpublish. If not provided, current opened project
/// is used
id: Option<String>,
},

/// List all published mods
ListPublished,
}

fn find_build_directory(root: &Path, _config: &Config) -> Option<PathBuf> {
fn find_build_directory(root: &Path) -> Option<PathBuf> {
#[cfg(windows)]
{
// this works for 99% of users.
// if you want to parse the CMakeLists.txt file to find the true build
// directory 100% of the time, go ahead, but i'm not doing it
for path in [
root.join("build").join("RelWithDebInfo"),
root.join("build").join("Release"),
root.join("build").join("MinSizeRel"),
] {
if path.exists() {
return Some(path);
}
if root.join("build").exists() {
return Some(root.join("build"));
}
}
None
}

fn clear_cache(dir: &Path, config: &Config) {
/// Get the project's built .geode file. Path argument should point to the
/// directory with the project's mod.json
pub fn get_built_package(root: &Path) -> Option<PathBuf> {
let mod_info = try_parse_mod_info(root).ok()?;
let geode_pkg = find_build_directory(root)?.join(format!("{}.geode", mod_info.id));
geode_pkg.exists().then_some(geode_pkg)
}

fn clear_cache(dir: &Path) {
// Parse mod.json
let mod_info = parse_mod_info(dir);

Expand All @@ -62,7 +84,7 @@ fn clear_cache(dir: &Path, config: &Config) {
fs::remove_dir_all(workdir).expect("Unable to remove cache directory");

// Remove cached .geode package
let dir = find_build_directory(dir, config);
let dir = find_build_directory(dir);
if let Some(dir) = dir {
for file in fs::read_dir(&dir).expect("Unable to read build directory") {
let path = file.unwrap().path();
Expand Down Expand Up @@ -432,17 +454,51 @@ pub fn check_dependencies(config: &Config, input: PathBuf, output: PathBuf, exte
}
}

pub fn publish_project(_config: &Config, dir: &Path, package_path: Option<PathBuf>) {
let Some(pkg) = package_path.or(get_built_package(dir)) else {
fatal!(
"Unable to find the project's .geode package - please try manually \
specifying the path to the project's built .geode package using \
the `--package <path>` option.\nThis issue is likely caused by \
an outdated Geode SDK version (at least 1.0.0-beta.8 needed) or \
by building multiple projects from the same directory."
);
};

// initialize indexer and add mod there
if !indexer::is_initialized() {
indexer::initialize();
}
indexer::add_mod(pkg);
}

pub fn unpublish_project(id: Option<String>) {
if !indexer::is_initialized() {
fatal!("You don't seem to have any mods published!");
}
else {
indexer::remove_mod(
id.unwrap_or_else(|| parse_mod_info(&std::env::current_dir().unwrap()).id)
);
}
}

pub fn subcommand(config: &mut Config, cmd: Project) {
match cmd {
Project::New { path } => template::build_template(config, path),
Project::ClearCache => clear_cache(
&std::env::current_dir().unwrap(), config
&std::env::current_dir().unwrap()
),
Project::Check { install_dir, externals } => check_dependencies(
config,
std::env::current_dir().unwrap(),
install_dir.unwrap_or("build".into()),
externals
),
Project::Publish { package } => publish_project(
config, &std::env::current_dir().unwrap(), package
),
Project::Unpublish { id } => unpublish_project(id),
Project::ListPublished => indexer::list_mods(),
}
}

0 comments on commit 15e85dc

Please sign in to comment.