Skip to content

Commit

Permalink
move stuff around + ws server
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlan404 committed Jul 2, 2024
1 parent e1e7deb commit b47099e
Show file tree
Hide file tree
Showing 109 changed files with 668 additions and 19 deletions.
293 changes: 286 additions & 7 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,5 @@ murmur2 = "0.1"
futures = "0.3"
indextree = "4.6"
schemars = "0.8"
ratatui = "0.27.0"
tokio-tungstenite = "0.23.1"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/api/app/actions/markdown/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;

use anyhow::Result;

use crate::api::{app::App, models::{markdown::{MarkdownOptions, MarkdownOutput}, AddonMetadata, AddonMetadataSource}};
use crate::api::{app::App, models::{markdown::{MarkdownOptions, MarkdownOutput}, metadata::{AddonMetadata, AddonMetadataSource}}};

Check warning on line 5 in src/api/app/actions/markdown/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused imports: `AddonMetadataSource`, `MarkdownOutput`

warning: unused imports: `AddonMetadataSource`, `MarkdownOutput` --> src/api/app/actions/markdown/mod.rs:5:65 | 5 | use crate::api::{app::App, models::{markdown::{MarkdownOptions, MarkdownOutput}, metadata::{AddonMetadata, AddonMetadataSource}}}; | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

impl App {
pub async fn get_markdown_options(&self) -> Option<MarkdownOptions> {

Check warning on line 8 in src/api/app/actions/markdown/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

methods `get_markdown_options`, `get_all_metadata`, `render_markdown_with`, and `render_markdown_and_save` are never used

warning: methods `get_markdown_options`, `get_all_metadata`, `render_markdown_with`, and `render_markdown_and_save` are never used --> src/api/app/actions/markdown/mod.rs:8:18 | 7 | impl App { | -------- methods in this implementation 8 | pub async fn get_markdown_options(&self) -> Option<MarkdownOptions> { | ^^^^^^^^^^^^^^^^^^^^ ... 16 | pub async fn get_all_metadata(self: Arc<Self>) -> Result<Vec<AddonMetadata>> { | ^^^^^^^^^^^^^^^^ ... 31 | pub async fn render_markdown_with(&self, metadata: Vec<AddonMetadata>) -> Result<String> { | ^^^^^^^^^^^^^^^^^^^^ ... 39 | pub async fn render_markdown_and_save(self: Arc<Self>) -> Result<()> { | ^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
1 change: 1 addition & 0 deletions src/api/app/actions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod build;
mod init;
mod markdown;
mod script;
29 changes: 29 additions & 0 deletions src/api/app/actions/script/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use anyhow::Result;

use crate::api::{app::App, models::server::Server, utils::script::Shell};

impl App {
pub fn get_server_execution_arguments(&self) -> Vec<String> {

Check warning on line 6 in src/api/app/actions/script/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

methods `get_server_execution_arguments`, `get_script_lines_for`, and `action_generate_script` are never used

warning: methods `get_server_execution_arguments`, `get_script_lines_for`, and `action_generate_script` are never used --> src/api/app/actions/script/mod.rs:6:12 | 5 | impl App { | -------- methods in this implementation 6 | pub fn get_server_execution_arguments(&self) -> Vec<String> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... 10 | pub fn get_script_lines_for(&self, shell: Shell, server: &Server) -> Vec<String> { | ^^^^^^^^^^^^^^^^^^^^ ... 26 | pub async fn action_generate_script(&self) -> Result<()> { | ^^^^^^^^^^^^^^^^^^^^^^
todo!()
}

pub fn get_script_lines_for(&self, shell: Shell, server: &Server) -> Vec<String> {
let mut lines = vec![];

if shell == Shell::Bat {
lines.push(format!("title {}", server.name));
}

lines.extend(server.launcher.prelaunch.clone());

todo!();

lines.extend(server.launcher.postlaunch.clone());

Check warning on line 21 in src/api/app/actions/script/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unreachable statement

warning: unreachable statement --> src/api/app/actions/script/mod.rs:21:9 | 19 | todo!(); | ------- any code following this expression is unreachable 20 | 21 | lines.extend(server.launcher.postlaunch.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: `#[warn(unreachable_code)]` on by default

lines
}

pub async fn action_generate_script(&self) -> Result<()> {
todo!()
}

Check warning on line 28 in src/api/app/actions/script/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused `async` for function with no await statements

warning: unused `async` for function with no await statements --> src/api/app/actions/script/mod.rs:26:5 | 26 | / pub async fn action_generate_script(&self) -> Result<()> { 27 | | todo!() 28 | | } | |_____^ | = help: consider removing the `async` from this function = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
}
2 changes: 2 additions & 0 deletions src/api/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ mod io;
pub mod options;
mod step;

pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION");

Check warning on line 19 in src/api/app/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

constant `APP_VERSION` is never used

warning: constant `APP_VERSION` is never used --> src/api/app/mod.rs:19:11 | 19 | pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); | ^^^^^^^^^^^ | = note: `#[warn(dead_code)]` on by default

pub const APP_USER_AGENT: &str = concat!(
env!("CARGO_PKG_NAME"),
"/",
Expand Down
1 change: 1 addition & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod sources;
pub mod step;
pub mod tools;
pub mod utils;
pub mod ws;
2 changes: 0 additions & 2 deletions src/api/models/addon/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
mod addon;

Check failure on line 1 in src/api/models/addon/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

module has the same name as its containing module

error: module has the same name as its containing module --> src/api/models/addon/mod.rs:1:1 | 1 | mod addon; | ^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#module_inception = note: `-D clippy::module-inception` implied by `-D clippy::all` = help: to override `-D clippy::all` add `#[allow(clippy::module_inception)]`
mod addon_metadata;
mod addon_target;
mod addon_type;
mod holders;

pub use addon::*;
pub use addon_metadata::*;
pub use addon_target::*;
pub use addon_type::*;
pub use holders::*;
96 changes: 96 additions & 0 deletions src/api/models/launcher/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use serde::{Deserialize, Serialize};
use std::{borrow::ToOwned, collections::HashMap, env};

use crate::api::utils::serde::*;

Check warning on line 4 in src/api/models/launcher/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

usage of wildcard import

warning: usage of wildcard import --> src/api/models/launcher/mod.rs:4:5 | 4 | use crate::api::utils::serde::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::api::utils::serde::is_default` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports

mod preset_flags;
pub use preset_flags::*;

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
#[serde(default)]
pub struct ServerLauncher {
pub eula_args: bool,

#[serde(skip_serializing_if = "is_default")]
pub nogui: bool,
#[serde(skip_serializing_if = "is_default")]
pub preset_flags: PresetFlags,
#[serde(skip_serializing_if = "is_default")]
pub disable: bool,
#[serde(skip_serializing_if = "is_default")]
pub jvm_args: String,
#[serde(skip_serializing_if = "is_default")]
pub game_args: String,
#[serde(skip_serializing_if = "is_default")]
pub memory: String,
#[serde(skip_serializing_if = "is_default")]
pub properties: HashMap<String, String>,

#[serde(skip_serializing_if = "Vec::is_empty")]
pub prelaunch: Vec<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub postlaunch: Vec<String>,

pub java_version: Option<String>,
}

impl ServerLauncher {
pub fn get_args(&self, exec: &str) -> Vec<String> {

Check warning on line 38 in src/api/models/launcher/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

method `get_args` is never used

warning: method `get_args` is never used --> src/api/models/launcher/mod.rs:38:12 | 37 | impl ServerLauncher { | ------------------- method in this implementation 38 | pub fn get_args(&self, exec: &str) -> Vec<String> { | ^^^^^^^^
let mut args = self
.jvm_args
.split_whitespace()
.map(ToOwned::to_owned)
.collect::<Vec<_>>();

if env::var("MC_MEMORY").is_ok() || !self.memory.is_empty() {
let m = env::var("MC_MEMORY").unwrap_or(self.memory.clone());
args.extend([format!("-Xms{m}"), format!("-Xmx{m}")]);
}

args.append(&mut self.preset_flags.get_flags());

if self.eula_args {
args.push(String::from("-Dcom.mojang.eula.agree=true"));
}

for (key, value) in &self.properties {
args.push(format!(
"-D{}={}",
key,
if value.contains(char::is_whitespace) {
format!("\"{value}\"")
} else {
value.clone()
}
));
}

args.extend(exec.split_whitespace().map(ToOwned::to_owned));

if self.nogui && !matches!(self.preset_flags, PresetFlags::Proxy) {
args.push(String::from("--nogui"));
}

args.extend(self.game_args.split_whitespace().map(ToOwned::to_owned));

args
}
}

impl Default for ServerLauncher {
fn default() -> Self {
Self {
preset_flags: PresetFlags::None,
nogui: true,
jvm_args: String::new(),
game_args: String::new(),
disable: false,
eula_args: true,
memory: String::new(),
properties: HashMap::default(),
prelaunch: vec![],
postlaunch: vec![],
java_version: None,
}
}
}
23 changes: 23 additions & 0 deletions src/api/models/launcher/preset_flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Default)]
#[serde(rename_all = "lowercase")]
pub enum PresetFlags {
Aikars,
Proxy,
#[default]
None,
}

impl PresetFlags {
pub fn get_flags(&self) -> Vec<String> {

Check warning on line 13 in src/api/models/launcher/preset_flags.rs

View workflow job for this annotation

GitHub Actions / clippy

method `get_flags` is never used

warning: method `get_flags` is never used --> src/api/models/launcher/preset_flags.rs:13:12 | 12 | impl PresetFlags { | ---------------- method in this implementation 13 | pub fn get_flags(&self) -> Vec<String> { | ^^^^^^^^^
match self {
Self::Aikars => include_str!("../../../../res/aikars_flags"),
Self::Proxy => include_str!("../../../../res/proxy_flags"),
Self::None => "",
}
.split(char::is_whitespace)
.map(ToOwned::to_owned)
.collect()
}
}
2 changes: 1 addition & 1 deletion src/api/models/markdown/render.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::api::{models::AddonMetadata, utils::markdown::{HeaderAlignment, MarkdownHeader, MarkdownTable}};
use crate::api::{models::metadata::AddonMetadata, utils::markdown::{HeaderAlignment, MarkdownHeader, MarkdownTable}};

use super::{MarkdownOptions, MarkdownOutput, MdColumn};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use anyhow::{bail, Result};
use serde::{Deserialize, Serialize};

use crate::api::{app::App, sources::{jenkins::jenkins_job_url, maven::maven_artifact_url}, utils::url::get_filename_from_url};

use super::{Addon, AddonType};
use crate::api::{app::App, models::{Addon, AddonType}, sources::{jenkins::jenkins_job_url, maven::maven_artifact_url}, utils::url::get_filename_from_url};

#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub enum AddonMetadataSource {
Expand Down
7 changes: 7 additions & 0 deletions src/api/models/metadata/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod addon_metadata;

pub use addon_metadata::*;

pub enum MetadataBlock {

Check warning on line 5 in src/api/models/metadata/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

enum `MetadataBlock` is never used

warning: enum `MetadataBlock` is never used --> src/api/models/metadata/mod.rs:5:10 | 5 | pub enum MetadataBlock { | ^^^^^^^^^^^^^
Addons(Vec<AddonMetadata>),
}
2 changes: 2 additions & 0 deletions src/api/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub mod packwiz;
pub mod server;
pub mod unsup;
pub mod markdown;
pub mod metadata;
pub mod launcher;

pub use addon::*;
pub use env::*;
Expand Down
10 changes: 10 additions & 0 deletions src/api/models/modpack_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,13 @@ pub enum ModpackType {
MRPack,
Unsup,
}

impl ToString for ModpackType {
fn to_string(&self) -> String {
match self {
ModpackType::Packwiz => String::from("Packwiz"),
ModpackType::MRPack => String::from("MRPack"),
ModpackType::Unsup => String::from("Unsup"),
}
}
}

Check failure on line 54 in src/api/models/modpack_source.rs

View workflow job for this annotation

GitHub Actions / clippy

direct implementation of `ToString`

error: direct implementation of `ToString` --> src/api/models/modpack_source.rs:46:1 | 46 | / impl ToString for ModpackType { 47 | | fn to_string(&self) -> String { 48 | | match self { 49 | | ModpackType::Packwiz => String::from("Packwiz"), ... | 53 | | } 54 | | } | |_^ | = help: prefer implementing `Display` instead = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl
5 changes: 4 additions & 1 deletion src/api/models/server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};

use super::{markdown::MarkdownOptions, Source};
use super::{launcher::ServerLauncher, markdown::MarkdownOptions, Source};

mod server_flavor;
mod server_type;
Expand All @@ -19,6 +19,8 @@ pub struct Server {
pub jar: Option<ServerJar>,
#[serde(default)]
pub markdown: MarkdownOptions,
#[serde(default)]
pub launcher: ServerLauncher,

#[serde(default = "Vec::new")]
pub sources: Vec<Source>,
Expand All @@ -36,6 +38,7 @@ impl Default for Server {
}),

markdown: MarkdownOptions::default(),
launcher: ServerLauncher::default(),

sources: vec![],
}
Expand Down
31 changes: 27 additions & 4 deletions src/api/models/source.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;

use anyhow::Result;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};

use super::{mrpack::resolve_mrpack_addons, packwiz::resolve_packwiz_addons, Addon, AddonListFile, ModpackType};
Expand All @@ -24,26 +24,49 @@ pub enum Source {
}

impl Source {
pub fn source_name(&self) -> &'static str {

Check warning on line 27 in src/api/models/source.rs

View workflow job for this annotation

GitHub Actions / clippy

methods `source_name`, `source_accessor`, and `modpack_type` are never used

warning: methods `source_name`, `source_accessor`, and `modpack_type` are never used --> src/api/models/source.rs:27:12 | 26 | impl Source { | ----------- methods in this implementation 27 | pub fn source_name(&self) -> &'static str { | ^^^^^^^^^^^ ... 35 | pub fn source_accessor(&self) -> Result<String> { | ^^^^^^^^^^^^^^^ ... 43 | pub fn modpack_type(&self) -> Option<ModpackType> { | ^^^^^^^^^^^^
match self {
Source::File { .. } => "File",
Source::Folder { .. } => "Folder",
Source::Modpack { .. } => "Modpack",
}
}

pub fn source_accessor(&self) -> Result<String> {
match self {
Source::File { path } => Ok(path.clone()),
Source::Folder { path } => Ok(path.clone()),

Check warning on line 38 in src/api/models/source.rs

View workflow job for this annotation

GitHub Actions / clippy

this match arm has an identical body to another arm

warning: this match arm has an identical body to another arm --> src/api/models/source.rs:38:13 | 38 | Source::Folder { path } => Ok(path.clone()), | -----------------------^^^^^^^^^^^^^^^^^^^^ | | | help: try merging the arm patterns: `Source::Folder { path } | Source::File { path }` | = help: or try changing either arm body note: other arm here --> src/api/models/source.rs:37:13 | 37 | Source::File { path } => Ok(path.clone()), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms
Source::Modpack { modpack } => Ok(modpack.accessor()?.to_string()),
}
}

pub fn modpack_type(&self) -> Option<ModpackType> {
match self {
Source::Modpack { modpack } => Some(modpack.modpack_type()),
_ => None,
}
}

pub async fn resolve_addons(&self, app: &App) -> Result<Vec<Addon>> {
match self {
Source::File { path } => {
let file: AddonListFile = read_toml(&PathBuf::from(if path.ends_with(".toml") {

Check warning on line 53 in src/api/models/source.rs

View workflow job for this annotation

GitHub Actions / clippy

case-sensitive file extension comparison

warning: case-sensitive file extension comparison --> src/api/models/source.rs:53:71 | 53 | let file: AddonListFile = read_toml(&PathBuf::from(if path.ends_with(".toml") { | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a case-insensitive comparison instead = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#case_sensitive_file_extension_comparisons = note: `-W clippy::case-sensitive-file-extension-comparisons` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::case_sensitive_file_extension_comparisons)]` help: use std::path::Path | 53 ~ let file: AddonListFile = read_toml(&PathBuf::from(if std::path::Path::new(path) 54 + .extension() 55 ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("toml")) { |
path.clone()
} else {
format!("{path}.toml")
}))?;
})).with_context(|| format!("Source: File => {path}"))?;
Ok(file.flatten())
},

Source::Folder { path } => Ok(vec![]),
Source::Folder { .. } => Ok(vec![]),

Source::Modpack { modpack } => {
let accessor = modpack.accessor()?;
match modpack.modpack_type() {
ModpackType::MRPack => resolve_mrpack_addons(app, accessor).await,
ModpackType::Packwiz => resolve_packwiz_addons(app, accessor).await,
ModpackType::Unsup => todo!(),
}
}.with_context(|| format!("Source: Modpack/{} => {}", modpack.modpack_type().to_string(), modpack.accessor().unwrap().to_string()))
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/api/utils/accessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ pub enum Accessor {
//Zip(ZipArchive<Box<dyn ReadSeek>>),
}

impl ToString for Accessor {
fn to_string(&self) -> String {
match self {
Accessor::Local(path) => path.to_string_lossy().into_owned(),
Accessor::Remote(url) => url.to_string(),
Accessor::ZipLocal(zip) => String::from("a zip archive"),

Check warning on line 27 in src/api/utils/accessor.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `zip`

warning: unused variable: `zip` --> src/api/utils/accessor.rs:27:32 | 27 | Accessor::ZipLocal(zip) => String::from("a zip archive"), | ^^^ help: if this is intentional, prefix it with an underscore: `_zip`
}
}
}

Check failure on line 30 in src/api/utils/accessor.rs

View workflow job for this annotation

GitHub Actions / clippy

direct implementation of `ToString`

error: direct implementation of `ToString` --> src/api/utils/accessor.rs:22:1 | 22 | / impl ToString for Accessor { 23 | | fn to_string(&self) -> String { 24 | | match self { 25 | | Accessor::Local(path) => path.to_string_lossy().into_owned(), ... | 29 | | } 30 | | } | |_^ | = help: prefer implementing `Display` instead = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl

impl Accessor {
pub fn from(str: &str) -> Result<Self> {
if str.starts_with("http://") || str.starts_with("https://") {
Expand Down
1 change: 1 addition & 0 deletions src/api/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod serde;
pub mod url;
pub mod console;
pub mod markdown;
pub mod script;

pub fn try_find_toml_upwards<T: DeserializeOwned>(filename: &str) -> Result<Option<(PathBuf, T)>> {
let mut path = std::env::current_dir()?;
Expand Down
Loading

0 comments on commit b47099e

Please sign in to comment.