Skip to content

Commit 765410f

Browse files
authored
Add .jar file support for custom commands and GitHub executors (#217)
Includes handling of `.jar` files as input URLs for downloads, dependencies, and binary patterns. Enhanced argument customization and introduced a utility to identify `.jar` files in installation paths. Note that this won't append java as dep if jar is in release files, because it calculates deps beforehand. I don't know how to get around this, besides using the api to query for files before completing the resolve, but I feel that's simply "too much".
1 parent 9aaffa1 commit 765410f

File tree

3 files changed

+91
-10
lines changed

3 files changed

+91
-10
lines changed

src/stage4/src/executor.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,19 @@ pub fn java_deps<'a>() -> Pin<Box<dyn Future<Output = Vec<ExecutorDep>> + 'a>> {
322322
Box::pin(async move { vec![ExecutorDep::new("java".to_string(), None)] })
323323
}
324324

325+
pub fn find_jar_file(app_path: &AppPath) -> Option<String> {
326+
if let Ok(entries) = std::fs::read_dir(&app_path.install_dir) {
327+
for entry in entries.flatten() {
328+
if let Some(name) = entry.file_name().to_str() {
329+
if name.ends_with(".jar") {
330+
return Some(name.to_string());
331+
}
332+
}
333+
}
334+
}
335+
None
336+
}
337+
325338
fn get_executor_app_path(
326339
_executor: &dyn Executor,
327340
input: &AppInput,

src/stage4/src/executors/custom_command.rs

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
1+
use std::collections::HashSet;
12
use std::future::Future;
23
use std::path::PathBuf;
34
use std::pin::Pin;
45

56
use semver::VersionReq;
67

7-
use crate::executor::{AppInput, AppPath, BinPattern, Download, ExecutorCmd};
8+
use crate::executor::{
9+
find_jar_file, AppInput, AppPath, BinPattern, Download, ExecutorCmd, ExecutorDep,
10+
};
11+
use crate::target::{Arch, Os, Variant};
812
use crate::Executor;
913

1014
pub struct CustomCommand {
1115
pub executor_cmd: ExecutorCmd,
1216
}
1317

18+
impl CustomCommand {
19+
fn is_jar_url(url: &str) -> bool {
20+
(url.starts_with("http://") || url.starts_with("https://")) && url.ends_with(".jar")
21+
}
22+
}
23+
1424
impl Executor for CustomCommand {
1525
fn get_executor_cmd(&self) -> &ExecutorCmd {
1626
&self.executor_cmd
@@ -22,26 +32,69 @@ impl Executor for CustomCommand {
2232

2333
fn get_download_urls<'a>(
2434
&'a self,
25-
_input: &'a AppInput,
35+
input: &'a AppInput,
2636
) -> Pin<Box<dyn Future<Output = Vec<Download>> + 'a>> {
27-
Box::pin(async move { vec![] })
37+
Box::pin(async move {
38+
if let Some(first_arg) = input.app_args.first() {
39+
if Self::is_jar_url(first_arg) {
40+
return vec![Download {
41+
download_url: first_arg.clone(),
42+
version: None,
43+
os: Some(Os::Any),
44+
arch: Some(Arch::Any),
45+
variant: Some(Variant::Any),
46+
tags: HashSet::new(),
47+
}];
48+
}
49+
}
50+
vec![]
51+
})
2852
}
2953

3054
fn get_bins(&self, input: &AppInput) -> Vec<BinPattern> {
31-
vec![BinPattern::Exact(
32-
input.app_args[0].as_str().to_string(),
33-
)]
55+
if let Some(first_arg) = input.app_args.first() {
56+
if Self::is_jar_url(first_arg) {
57+
return vec![BinPattern::Exact("java".to_string())];
58+
}
59+
}
60+
vec![BinPattern::Exact(input.app_args[0].as_str().to_string())]
3461
}
3562

3663
fn get_name(&self) -> &str {
3764
"custom_command"
3865
}
3966

40-
fn customize_args(&self, input: &AppInput, _app_path: &AppPath) -> Vec<String> {
67+
fn get_deps<'a>(
68+
&'a self,
69+
input: &'a AppInput,
70+
) -> Pin<Box<dyn Future<Output = Vec<ExecutorDep>> + 'a>> {
71+
Box::pin(async move {
72+
if let Some(first_arg) = input.app_args.first() {
73+
if Self::is_jar_url(first_arg) {
74+
return vec![ExecutorDep::new("java".to_string(), None)];
75+
}
76+
}
77+
vec![]
78+
})
79+
}
80+
81+
fn customize_args(&self, input: &AppInput, app_path: &AppPath) -> Vec<String> {
82+
if let Some(jar_name) = find_jar_file(app_path) {
83+
if let Some(jar_path) = app_path.install_dir.join(&jar_name).to_str() {
84+
let mut args = vec!["-jar".to_string(), jar_path.to_string()];
85+
args.extend(input.app_args.iter().skip(1).cloned());
86+
return args;
87+
}
88+
}
4189
input.app_args.clone().into_iter().skip(1).collect()
4290
}
4391

44-
fn custom_prep(&self, _input: &AppInput) -> Option<AppPath> {
92+
fn custom_prep(&self, input: &AppInput) -> Option<AppPath> {
93+
if let Some(first_arg) = input.app_args.first() {
94+
if Self::is_jar_url(first_arg) {
95+
return None;
96+
}
97+
}
4598
Some(AppPath {
4699
install_dir: PathBuf::new(),
47100
})

src/stage4/src/executors/github.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::future::Future;
33
use std::pin::Pin;
44

55
use crate::executor::{
6-
AppInput, AppPath, BinPattern, Download, Executor, ExecutorCmd, ExecutorDep, GgVersion,
6+
find_jar_file, AppInput, AppPath, BinPattern, Download, Executor, ExecutorCmd, ExecutorDep,
7+
GgVersion,
78
};
89
use crate::github_utils::{create_github_client, detect_arch_from_name, detect_os_from_name};
910
use crate::target::Os::Windows;
@@ -74,7 +75,9 @@ impl GitHub {
7475
return false;
7576
}
7677

77-
let binary_extensions = [".exe", ".zip", ".tar.gz", ".tgz", ".tar.bz2", ".7z", ".gem"];
78+
let binary_extensions = [
79+
".exe", ".zip", ".tar.gz", ".tgz", ".tar.bz2", ".7z", ".gem", ".jar",
80+
];
7881

7982
for ext in &binary_extensions {
8083
if name_lower.contains(ext) {
@@ -202,6 +205,7 @@ impl Executor for GitHub {
202205
}
203206

204207
patterns.push(BinPattern::Regex(r"^[^.]*$".to_string()));
208+
patterns.push(BinPattern::Exact("java".to_string()));
205209

206210
patterns
207211
}
@@ -210,6 +214,17 @@ impl Executor for GitHub {
210214
&self.repo
211215
}
212216

217+
fn customize_args(&self, input: &AppInput, app_path: &AppPath) -> Vec<String> {
218+
if let Some(jar_name) = find_jar_file(app_path) {
219+
if let Some(jar_path) = app_path.install_dir.join(&jar_name).to_str() {
220+
let mut args = vec!["-jar".to_string(), jar_path.to_string()];
221+
args.extend_from_slice(&input.app_args);
222+
return args;
223+
}
224+
}
225+
input.app_args.clone()
226+
}
227+
213228
fn get_deps<'a>(
214229
&'a self,
215230
_input: &'a AppInput,

0 commit comments

Comments
 (0)