Update from Gitea release assets
This commit is contained in:
Generated
+1
-1
@@ -667,7 +667,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openstock"
|
name = "openstock"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "openstock"
|
name = "openstock"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -50,15 +50,15 @@ openstock update
|
|||||||
curl -fsSL https://git.hananakick.cc/Autotrade/openstock/raw/branch/main/scripts/update.sh | sh
|
curl -fsSL https://git.hananakick.cc/Autotrade/openstock/raw/branch/main/scripts/update.sh | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
`openstock update`는 현재 실행 중인 바이너리의 디렉터리를 `OPENSTOCK_INSTALL_DIR`로 사용해 설치 스크립트를 다시 실행합니다. 설치 위치를 직접 지정하려면 `OPENSTOCK_INSTALL_DIR=/path openstock update`를 사용합니다. 설치 스크립트 URL은 `OPENSTOCK_INSTALL_SCRIPT_URL`로 바꿀 수 있습니다.
|
`openstock update`는 Gitea 최신 release를 조회하고, 현재 버전보다 최신이면 Linux x86_64 release asset을 내려받아 현재 실행 중인 바이너리의 디렉터리에 설치합니다. 설치 위치를 직접 지정하려면 `OPENSTOCK_INSTALL_DIR=/path openstock update`를 사용합니다. 같은 버전도 재설치하려면 `openstock update --force`를 사용합니다.
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
|
|
||||||
Gitea Actions가 활성화된 저장소에서는 push 시 자동으로 CI가 실행됩니다. `main` branch push는 테스트와 release 빌드 검증만 수행하고, `v*` tag push는 Gitea Release를 만들고 Linux x86_64 바이너리를 asset으로 등록합니다.
|
Gitea Actions가 활성화된 저장소에서는 push 시 자동으로 CI가 실행됩니다. `main` branch push는 테스트와 release 빌드 검증만 수행하고, `v*` tag push는 Gitea Release를 만들고 Linux x86_64 바이너리를 asset으로 등록합니다.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git tag v0.1.0
|
git tag v0.2.0
|
||||||
git push origin main v0.1.0
|
git push origin main v0.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
필요 조건:
|
필요 조건:
|
||||||
@@ -187,11 +187,17 @@ docker compose logs --tail=120 openstock-runner
|
|||||||
|
|
||||||
| Field | Type | Meaning |
|
| Field | Type | Meaning |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `installer_url` | string | 업데이트에 사용한 원격 설치 스크립트 URL입니다. |
|
| `release_api_url` | string | 최신 release 정보를 조회한 Gitea API URL입니다. |
|
||||||
|
| `current_version` | string | 현재 실행 중인 openstock 버전입니다. |
|
||||||
|
| `latest_version` | string | Gitea 최신 release tag에서 해석한 버전입니다. |
|
||||||
|
| `release_tag` | string | Gitea 최신 release tag입니다. |
|
||||||
|
| `release_url` | string | Gitea release 페이지 URL입니다. |
|
||||||
|
| `asset_name` | string | 설치에 사용한 release asset 이름입니다. |
|
||||||
|
| `asset_url` | string | 설치에 사용한 release asset 다운로드 URL입니다. |
|
||||||
| `install_dir` | string | 업데이트 대상 바이너리를 설치한 디렉터리입니다. |
|
| `install_dir` | string | 업데이트 대상 바이너리를 설치한 디렉터리입니다. |
|
||||||
| `status` | string | 업데이트 명령 실행 결과입니다. 성공 시 `updated`입니다. |
|
| `status` | string | 업데이트 명령 실행 결과입니다. `updated` 또는 `up_to_date`입니다. |
|
||||||
| `stdout` | string | 설치 스크립트의 표준 출력입니다. |
|
| `stdout` | string | release asset 설치 스크립트의 표준 출력입니다. |
|
||||||
| `stderr` | string | 설치 스크립트의 표준 오류 출력입니다. |
|
| `stderr` | string | release asset 설치 스크립트의 표준 오류 출력입니다. |
|
||||||
|
|
||||||
#### `api list`
|
#### `api list`
|
||||||
|
|
||||||
@@ -580,16 +586,16 @@ openstock cache prune
|
|||||||
|
|
||||||
### `openstock update`
|
### `openstock update`
|
||||||
|
|
||||||
원격 설치 스크립트를 다시 실행해 현재 openstock 바이너리를 업데이트합니다.
|
Gitea 최신 release asset을 내려받아 현재 openstock 바이너리를 업데이트합니다.
|
||||||
|
|
||||||
| Direction | Data |
|
| Direction | Data |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Input | `OPENSTOCK_INSTALL_DIR`, `OPENSTOCK_INSTALL_SCRIPT_URL` 선택 지정 |
|
| Input | `--force`; `OPENSTOCK_INSTALL_DIR`, `OPENSTOCK_RELEASE_API_URL`, `OPENSTOCK_RELEASE_ASSET_SUFFIX` 선택 지정 |
|
||||||
| External IO | `GET https://git.hananakick.cc/Autotrade/openstock/raw/branch/main/scripts/install.sh`; install script가 source archive를 내려받을 수 있음 |
|
| External IO | `GET https://git.hananakick.cc/api/v1/repos/Autotrade/openstock/releases/latest`; selected release asset download |
|
||||||
| File write | 현재 실행 바이너리 디렉터리 또는 `OPENSTOCK_INSTALL_DIR`의 `openstock` 바이너리 |
|
| File write | 현재 실행 바이너리 디렉터리 또는 `OPENSTOCK_INSTALL_DIR`의 `openstock` 바이너리 |
|
||||||
| Output fields | `installer_url`, `install_dir`, `status`, `stdout`, `stderr` |
|
| Output fields | `release_api_url`, `current_version`, `latest_version`, `release_tag`, `release_url`, `asset_name`, `asset_url`, `install_dir`, `status`, `stdout`, `stderr` |
|
||||||
| Raw | `null` |
|
| Raw | `null` |
|
||||||
| Side effect | release build 후 설치된 바이너리를 교체합니다. `~/.config/openstock` 설정/캐시는 보존합니다. |
|
| Side effect | 최신 release 버전이 현재 버전보다 크거나 `--force`이면 설치된 바이너리를 교체합니다. `~/.config/openstock` 설정/캐시는 보존합니다. |
|
||||||
|
|
||||||
### `openstock api list`
|
### `openstock api list`
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -1,6 +1,11 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
SCRIPT_URL="${OPENSTOCK_INSTALL_SCRIPT_URL:-https://git.hananakick.cc/Autotrade/openstock/raw/branch/main/scripts/install.sh}"
|
BIN_NAME="${OPENSTOCK_BIN_NAME:-openstock}"
|
||||||
|
|
||||||
curl -fsSL "$SCRIPT_URL" | sh
|
if ! command -v "$BIN_NAME" >/dev/null 2>&1; then
|
||||||
|
echo "$BIN_NAME is required for update. Install first with scripts/install.sh." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$BIN_NAME" update "$@"
|
||||||
|
|||||||
+216
-22
@@ -2,11 +2,14 @@ use crate::core::output;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
const DEFAULT_INSTALL_SCRIPT_URL: &str =
|
use crate::UpdateCommand;
|
||||||
"https://git.hananakick.cc/Autotrade/openstock/raw/branch/main/scripts/install.sh";
|
|
||||||
|
|
||||||
pub fn handle_update() {
|
const DEFAULT_RELEASE_API_URL: &str =
|
||||||
match update() {
|
"https://git.hananakick.cc/api/v1/repos/Autotrade/openstock/releases/latest";
|
||||||
|
const DEFAULT_ASSET_SUFFIX: &str = "-linux-x86_64.tar.gz";
|
||||||
|
|
||||||
|
pub fn handle_update(command: &UpdateCommand) {
|
||||||
|
match update(command.force) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
@@ -15,9 +18,39 @@ pub fn handle_update() {
|
|||||||
"openstock 바이너리 업데이트 실행 결과",
|
"openstock 바이너리 업데이트 실행 결과",
|
||||||
vec![
|
vec![
|
||||||
output::field(
|
output::field(
|
||||||
"installer_url",
|
"release_api_url",
|
||||||
"업데이트에 사용한 원격 설치 스크립트 URL",
|
"최신 release 정보를 조회한 Gitea API URL",
|
||||||
serde_json::json!(result.installer_url),
|
serde_json::json!(result.release_api_url),
|
||||||
|
),
|
||||||
|
output::field(
|
||||||
|
"current_version",
|
||||||
|
"현재 실행 중인 openstock 버전",
|
||||||
|
serde_json::json!(result.current_version),
|
||||||
|
),
|
||||||
|
output::field(
|
||||||
|
"latest_version",
|
||||||
|
"Gitea 최신 release tag에서 해석한 버전",
|
||||||
|
serde_json::json!(result.latest_version),
|
||||||
|
),
|
||||||
|
output::field(
|
||||||
|
"release_tag",
|
||||||
|
"Gitea 최신 release tag",
|
||||||
|
serde_json::json!(result.release_tag),
|
||||||
|
),
|
||||||
|
output::field(
|
||||||
|
"release_url",
|
||||||
|
"Gitea release 페이지 URL",
|
||||||
|
serde_json::json!(result.release_url),
|
||||||
|
),
|
||||||
|
output::field(
|
||||||
|
"asset_name",
|
||||||
|
"설치에 사용한 release asset 이름",
|
||||||
|
serde_json::json!(result.asset_name),
|
||||||
|
),
|
||||||
|
output::field(
|
||||||
|
"asset_url",
|
||||||
|
"설치에 사용한 release asset 다운로드 URL",
|
||||||
|
serde_json::json!(result.asset_url),
|
||||||
),
|
),
|
||||||
output::field(
|
output::field(
|
||||||
"install_dir",
|
"install_dir",
|
||||||
@@ -27,16 +60,16 @@ pub fn handle_update() {
|
|||||||
output::field(
|
output::field(
|
||||||
"status",
|
"status",
|
||||||
"업데이트 명령 실행 결과",
|
"업데이트 명령 실행 결과",
|
||||||
serde_json::json!("updated"),
|
serde_json::json!(result.status),
|
||||||
),
|
),
|
||||||
output::field(
|
output::field(
|
||||||
"stdout",
|
"stdout",
|
||||||
"설치 스크립트 표준 출력",
|
"release asset 설치 스크립트 표준 출력",
|
||||||
serde_json::json!(result.stdout),
|
serde_json::json!(result.stdout),
|
||||||
),
|
),
|
||||||
output::field(
|
output::field(
|
||||||
"stderr",
|
"stderr",
|
||||||
"설치 스크립트 표준 오류 출력",
|
"release asset 설치 스크립트 표준 오류 출력",
|
||||||
serde_json::json!(result.stderr),
|
serde_json::json!(result.stderr),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -50,35 +83,154 @@ pub fn handle_update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update() -> Result<UpdateResult, String> {
|
fn update(force: bool) -> Result<UpdateResult, String> {
|
||||||
|
let current_version = env!("CARGO_PKG_VERSION").to_string();
|
||||||
|
let release_api_url = release_api_url();
|
||||||
|
let release = latest_release(&release_api_url)?;
|
||||||
|
let latest_version = normalize_version(&release.tag_name);
|
||||||
|
let asset = release_asset(&release)?;
|
||||||
let install_dir = install_dir()?;
|
let install_dir = install_dir()?;
|
||||||
let installer_url = installer_url();
|
|
||||||
let command = format!("curl -fsSL {} | sh", shell_quote(&installer_url));
|
if !force && compare_versions(&latest_version, ¤t_version) != std::cmp::Ordering::Greater
|
||||||
|
{
|
||||||
|
return Ok(UpdateResult {
|
||||||
|
release_api_url,
|
||||||
|
current_version,
|
||||||
|
latest_version,
|
||||||
|
release_tag: release.tag_name,
|
||||||
|
release_url: release.html_url,
|
||||||
|
asset_name: asset.name,
|
||||||
|
asset_url: asset.browser_download_url,
|
||||||
|
install_dir,
|
||||||
|
status: "up_to_date".to_string(),
|
||||||
|
stdout: String::new(),
|
||||||
|
stderr: String::new(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let script = format!(
|
||||||
|
"set -eu\n\
|
||||||
|
tmp=\"$(mktemp -d \"${{TMPDIR:-/tmp}}/openstock-update.XXXXXX\")\"\n\
|
||||||
|
cleanup() {{ rm -rf \"$tmp\"; }}\n\
|
||||||
|
trap cleanup EXIT\n\
|
||||||
|
curl -fsSL {} -o \"$tmp/openstock.tar.gz\"\n\
|
||||||
|
tar -xzf \"$tmp/openstock.tar.gz\" -C \"$tmp\"\n\
|
||||||
|
test -x \"$tmp/openstock\"\n\
|
||||||
|
mkdir -p {}\n\
|
||||||
|
target={}\n\
|
||||||
|
tmp_target=\"{}/.openstock.tmp.$$\"\n\
|
||||||
|
cp \"$tmp/openstock\" \"$tmp_target\"\n\
|
||||||
|
chmod 755 \"$tmp_target\"\n\
|
||||||
|
mv -f \"$tmp_target\" \"$target\"\n\
|
||||||
|
printf 'installed: %s\\n' \"$target\"\n",
|
||||||
|
shell_quote(&asset.browser_download_url),
|
||||||
|
shell_quote(&install_dir.display().to_string()),
|
||||||
|
shell_quote(&install_dir.join("openstock").display().to_string()),
|
||||||
|
shell_quote(&install_dir.display().to_string()),
|
||||||
|
);
|
||||||
let output = Command::new("sh")
|
let output = Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(command)
|
.arg(script)
|
||||||
.env("OPENSTOCK_INSTALL_DIR", &install_dir)
|
|
||||||
.output()
|
.output()
|
||||||
.map_err(|err| format!("업데이트 스크립트 실행 실패: {}", err))?;
|
.map_err(|err| format!("release asset 설치 스크립트 실행 실패: {}", err))?;
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
|
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
|
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"업데이트 스크립트가 실패했습니다. status={}, stdout={}, stderr={}",
|
"release asset 설치 스크립트가 실패했습니다. status={}, stdout={}, stderr={}",
|
||||||
output.status, stdout, stderr
|
output.status, stdout, stderr
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(UpdateResult {
|
Ok(UpdateResult {
|
||||||
installer_url,
|
release_api_url,
|
||||||
|
current_version,
|
||||||
|
latest_version,
|
||||||
|
release_tag: release.tag_name,
|
||||||
|
release_url: release.html_url,
|
||||||
|
asset_name: asset.name,
|
||||||
|
asset_url: asset.browser_download_url,
|
||||||
install_dir,
|
install_dir,
|
||||||
|
status: "updated".to_string(),
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn latest_release(api_url: &str) -> Result<Release, String> {
|
||||||
|
let response = crate::core::http::agent()
|
||||||
|
.get(api_url)
|
||||||
|
.call()
|
||||||
|
.map_err(|err| format!("최신 release 조회 실패: {}", err))?;
|
||||||
|
let status = response.status();
|
||||||
|
let body = response
|
||||||
|
.into_body()
|
||||||
|
.read_to_string()
|
||||||
|
.map_err(|err| format!("최신 release 응답 읽기 실패: {}", err))?;
|
||||||
|
|
||||||
|
if !status.is_success() {
|
||||||
|
return Err(format!("최신 release 조회 오류 ({}): {}", status, body));
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = serde_json::from_str::<serde_json::Value>(&body)
|
||||||
|
.map_err(|err| format!("최신 release 응답 파싱 실패: {} / 원문: {}", err, body))?;
|
||||||
|
let tag_name = value
|
||||||
|
.get("tag_name")
|
||||||
|
.and_then(|value| value.as_str())
|
||||||
|
.ok_or_else(|| format!("최신 release 응답에 tag_name이 없습니다: {}", body))?
|
||||||
|
.to_string();
|
||||||
|
let html_url = value
|
||||||
|
.get("html_url")
|
||||||
|
.and_then(|value| value.as_str())
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string();
|
||||||
|
let assets = value
|
||||||
|
.get("assets")
|
||||||
|
.and_then(|value| value.as_array())
|
||||||
|
.ok_or_else(|| format!("최신 release 응답에 assets가 없습니다: {}", body))?
|
||||||
|
.iter()
|
||||||
|
.filter_map(|asset| {
|
||||||
|
let name = asset.get("name")?.as_str()?.to_string();
|
||||||
|
let browser_download_url = asset
|
||||||
|
.get("browser_download_url")
|
||||||
|
.or_else(|| asset.get("download_url"))?
|
||||||
|
.as_str()?
|
||||||
|
.to_string();
|
||||||
|
Some(ReleaseAsset {
|
||||||
|
name,
|
||||||
|
browser_download_url,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
Ok(Release {
|
||||||
|
tag_name,
|
||||||
|
html_url,
|
||||||
|
assets,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release_asset(release: &Release) -> Result<ReleaseAsset, String> {
|
||||||
|
let suffix = std::env::var("OPENSTOCK_RELEASE_ASSET_SUFFIX")
|
||||||
|
.ok()
|
||||||
|
.filter(|value| !value.trim().is_empty())
|
||||||
|
.unwrap_or_else(|| DEFAULT_ASSET_SUFFIX.to_string());
|
||||||
|
|
||||||
|
release
|
||||||
|
.assets
|
||||||
|
.iter()
|
||||||
|
.find(|asset| asset.name.ends_with(&suffix) && !asset.name.ends_with(".sha256"))
|
||||||
|
.cloned()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"release {}에서 suffix '{}'에 맞는 바이너리 asset을 찾지 못했습니다",
|
||||||
|
release.tag_name, suffix
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn install_dir() -> Result<PathBuf, String> {
|
fn install_dir() -> Result<PathBuf, String> {
|
||||||
if let Some(value) = std::env::var_os("OPENSTOCK_INSTALL_DIR") {
|
if let Some(value) = std::env::var_os("OPENSTOCK_INSTALL_DIR") {
|
||||||
return Ok(PathBuf::from(value));
|
return Ok(PathBuf::from(value));
|
||||||
@@ -94,20 +246,62 @@ fn install_dir() -> Result<PathBuf, String> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn installer_url() -> String {
|
fn release_api_url() -> String {
|
||||||
std::env::var("OPENSTOCK_INSTALL_SCRIPT_URL")
|
std::env::var("OPENSTOCK_RELEASE_API_URL")
|
||||||
.ok()
|
.ok()
|
||||||
.filter(|value| !value.trim().is_empty())
|
.filter(|value| !value.trim().is_empty())
|
||||||
.unwrap_or_else(|| DEFAULT_INSTALL_SCRIPT_URL.to_string())
|
.unwrap_or_else(|| DEFAULT_RELEASE_API_URL.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shell_quote(value: &str) -> String {
|
fn shell_quote(value: &str) -> String {
|
||||||
format!("'{}'", value.replace('\'', "'\\''"))
|
format!("'{}'", value.replace('\'', "'\\''"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalize_version(tag: &str) -> String {
|
||||||
|
tag.trim().trim_start_matches('v').to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_versions(left: &str, right: &str) -> std::cmp::Ordering {
|
||||||
|
let left_parts = version_parts(left);
|
||||||
|
let right_parts = version_parts(right);
|
||||||
|
left_parts.cmp(&right_parts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version_parts(version: &str) -> Vec<u64> {
|
||||||
|
version
|
||||||
|
.split(|ch| ch == '.' || ch == '-' || ch == '+')
|
||||||
|
.map(|part| {
|
||||||
|
part.chars()
|
||||||
|
.take_while(|ch| ch.is_ascii_digit())
|
||||||
|
.collect::<String>()
|
||||||
|
.parse::<u64>()
|
||||||
|
.unwrap_or(0)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Release {
|
||||||
|
tag_name: String,
|
||||||
|
html_url: String,
|
||||||
|
assets: Vec<ReleaseAsset>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct ReleaseAsset {
|
||||||
|
name: String,
|
||||||
|
browser_download_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
struct UpdateResult {
|
struct UpdateResult {
|
||||||
installer_url: String,
|
release_api_url: String,
|
||||||
|
current_version: String,
|
||||||
|
latest_version: String,
|
||||||
|
release_tag: String,
|
||||||
|
release_url: String,
|
||||||
|
asset_name: String,
|
||||||
|
asset_url: String,
|
||||||
install_dir: PathBuf,
|
install_dir: PathBuf,
|
||||||
|
status: String,
|
||||||
stdout: String,
|
stdout: String,
|
||||||
stderr: String,
|
stderr: String,
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -1,4 +1,4 @@
|
|||||||
use clap::{Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
use commands::account::AccountCommands;
|
use commands::account::AccountCommands;
|
||||||
use commands::api::ApiCommands;
|
use commands::api::ApiCommands;
|
||||||
use commands::cache::CacheCommands;
|
use commands::cache::CacheCommands;
|
||||||
@@ -30,7 +30,7 @@ enum Commands {
|
|||||||
Version,
|
Version,
|
||||||
|
|
||||||
/// 설치된 openstock 바이너리 업데이트
|
/// 설치된 openstock 바이너리 업데이트
|
||||||
Update,
|
Update(UpdateCommand),
|
||||||
|
|
||||||
/// 증권사 API 리스트 조회 및 API 설정
|
/// 증권사 API 리스트 조회 및 API 설정
|
||||||
Api {
|
Api {
|
||||||
@@ -83,7 +83,7 @@ fn main() {
|
|||||||
|
|
||||||
match &cli.command {
|
match &cli.command {
|
||||||
Some(Commands::Version) => commands::handle_version(),
|
Some(Commands::Version) => commands::handle_version(),
|
||||||
Some(Commands::Update) => commands::handle_update(),
|
Some(Commands::Update(command)) => commands::handle_update(command),
|
||||||
Some(Commands::Api { sub }) => commands::handle_api(sub),
|
Some(Commands::Api { sub }) => commands::handle_api(sub),
|
||||||
Some(Commands::Dart { sub }) => commands::handle_dart(sub),
|
Some(Commands::Dart { sub }) => commands::handle_dart(sub),
|
||||||
Some(Commands::Account { sub }) => commands::handle_account(sub),
|
Some(Commands::Account { sub }) => commands::handle_account(sub),
|
||||||
@@ -115,3 +115,10 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
struct UpdateCommand {
|
||||||
|
/// 현재 버전과 같아도 최신 release asset으로 재설치
|
||||||
|
#[arg(long)]
|
||||||
|
force: bool,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user