Compare commits
2
Commits
v0.1.8-beta.1
...
v0.1.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9799f88ade | ||
|
|
dc5adddd06 |
No files matched your search
@@ -2,6 +2,21 @@
|
||||
|
||||
每个版本一节,标题写成 `## [版本号]`,可以在后面加日期。发布流程(`.github/workflows/release.yml`)把与 tag 同版本的那一节原样作为更新说明:显示在 GitHub Release 和官网的更新日志里(ShellRS 的更新对话框用「查看更新内容」打开官网的更新日志),用 Markdown 书写,面向使用者。
|
||||
|
||||
## [0.1.8]
|
||||
|
||||
### 新增
|
||||
|
||||
- 设置 › 终端新增「终端交互」:选中即复制,右键可设为粘贴、显示菜单或无动作。
|
||||
|
||||
### 改进
|
||||
|
||||
- macOS 安装包分为 Apple Silicon 和 Intel 两种,下载更小。
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复 ESXi 等主机「测试连接」报需要键盘交互式认证、保存的密码不起作用。
|
||||
- 修复启动后不久检查更新时,「重启并安装」报找不到文件。
|
||||
|
||||
## [0.1.8-beta.1]
|
||||
|
||||
### 新增
|
||||
|
||||
Generated
+1
-1
@@ -7738,7 +7738,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "shellrs"
|
||||
version = "0.1.8-beta.1"
|
||||
version = "0.1.8"
|
||||
dependencies = [
|
||||
"alacritty_terminal",
|
||||
"anyhow",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "shellrs"
|
||||
version = "0.1.8-beta.1"
|
||||
version = "0.1.8"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
description = "SSH client and host manager: terminal, SFTP, port forwarding"
|
||||
|
||||
+12
-3
@@ -207,8 +207,9 @@ pub trait Installer: Send + Sync {
|
||||
|
||||
/// Remove what earlier updates left next to the installed copy. Called a
|
||||
/// while after start, so a version that crashes right away leaves the
|
||||
/// previous one's backup behind.
|
||||
fn clean_up(&self);
|
||||
/// previous one's backup behind. An update newer than `current` stays:
|
||||
/// it may have been staged since start and be waiting for the restart.
|
||||
fn clean_up(&self, current: &Version);
|
||||
}
|
||||
|
||||
/// For copies that cannot replace themselves.
|
||||
@@ -237,7 +238,7 @@ impl Installer for NoInstaller {
|
||||
))
|
||||
}
|
||||
|
||||
fn clean_up(&self) {}
|
||||
fn clean_up(&self, _: &Version) {}
|
||||
}
|
||||
|
||||
/// The installer for this copy of ShellRS. `bundle` is `cx.app_path()`.
|
||||
@@ -296,6 +297,14 @@ pub(crate) fn sibling(path: &Path, name: &str) -> PathBuf {
|
||||
path.with_file_name(name)
|
||||
}
|
||||
|
||||
/// Whether `name` is an update staged as `<prefix><version>` that this copy
|
||||
/// no longer needs: one not newer than `current`, or not named by a version.
|
||||
#[cfg(any(target_os = "macos", target_os = "linux", test))]
|
||||
pub(crate) fn is_stale_update(name: &str, prefix: &str, current: &Version) -> bool {
|
||||
name.strip_prefix(prefix)
|
||||
.is_some_and(|version| Version::parse(version).map_or(true, |version| version <= *current))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -10,7 +10,9 @@ use std::os::unix::fs::PermissionsExt as _;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::error::UpdateError;
|
||||
use super::install::{InstallKind, Installer, Relaunch, Staged, sibling};
|
||||
use semver::Version;
|
||||
|
||||
use super::install::{InstallKind, Installer, Relaunch, Staged, is_stale_update, sibling};
|
||||
use super::manifest::Release;
|
||||
|
||||
pub struct AppImageInstaller {
|
||||
@@ -59,13 +61,13 @@ impl Installer for AppImageInstaller {
|
||||
})
|
||||
}
|
||||
|
||||
fn clean_up(&self) {
|
||||
fn clean_up(&self, current: &Version) {
|
||||
let Some(folder) = self.file.parent() else {
|
||||
return;
|
||||
};
|
||||
let prefix = self.prefix();
|
||||
for entry in fs::read_dir(folder).into_iter().flatten().flatten() {
|
||||
if entry.file_name().to_string_lossy().starts_with(&prefix) {
|
||||
if is_stale_update(&entry.file_name().to_string_lossy(), &prefix, current) {
|
||||
let _ = fs::remove_file(entry.path());
|
||||
}
|
||||
}
|
||||
@@ -115,13 +117,26 @@ mod tests {
|
||||
"stale",
|
||||
)
|
||||
.unwrap();
|
||||
installer.clean_up();
|
||||
let left: Vec<_> = fs::read_dir(folder.path())
|
||||
// Staged since start and waiting for the restart: kept.
|
||||
fs::write(
|
||||
sibling(&file, ".ShellRS-x86_64.AppImage.update-0.3.0"),
|
||||
"next",
|
||||
)
|
||||
.unwrap();
|
||||
installer.clean_up(&Version::new(0, 2, 0));
|
||||
let mut left: Vec<_> = fs::read_dir(folder.path())
|
||||
.unwrap()
|
||||
.flatten()
|
||||
.map(|entry| entry.file_name().to_string_lossy().into_owned())
|
||||
.collect();
|
||||
assert_eq!(left.len(), 2, "{left:?}");
|
||||
assert!(left.contains(&"ShellRS-x86_64.AppImage".to_string()));
|
||||
left.sort();
|
||||
assert_eq!(
|
||||
left,
|
||||
[
|
||||
".ShellRS-x86_64.AppImage.update-0.3.0",
|
||||
"ShellRS-x86_64.AppImage",
|
||||
"downloaded"
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,11 @@ use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use semver::Version;
|
||||
|
||||
use super::build_info::APPLE_TEAM_ID;
|
||||
use super::error::UpdateError;
|
||||
use super::install::{InstallKind, Installer, Relaunch, Staged, sibling};
|
||||
use super::install::{InstallKind, Installer, Relaunch, Staged, is_stale_update, sibling};
|
||||
use super::manifest::Release;
|
||||
use crate::i18n::t;
|
||||
|
||||
@@ -217,7 +219,7 @@ impl Installer for MacInstaller {
|
||||
})
|
||||
}
|
||||
|
||||
fn clean_up(&self) {
|
||||
fn clean_up(&self, current: &Version) {
|
||||
let Some(folder) = self.bundle.parent() else {
|
||||
return;
|
||||
};
|
||||
@@ -227,7 +229,7 @@ impl Installer for MacInstaller {
|
||||
);
|
||||
for entry in fs::read_dir(folder).into_iter().flatten().flatten() {
|
||||
let name = entry.file_name().to_string_lossy().into_owned();
|
||||
if name.starts_with(&old) || name.starts_with(&update) {
|
||||
if name.starts_with(&old) || is_stale_update(&name, &update, current) {
|
||||
let _ = fs::remove_dir_all(entry.path());
|
||||
}
|
||||
}
|
||||
@@ -349,10 +351,40 @@ mod tests {
|
||||
assert_eq!(names.len(), 2, "{names:?}");
|
||||
assert!(names[0].starts_with(".ShellRS.app.old-"), "{names:?}");
|
||||
|
||||
installer.clean_up();
|
||||
// Run by 0.2.0, once it has started.
|
||||
installer.clean_up(&Version::new(0, 2, 0));
|
||||
assert_eq!(names_in(folder.path()), ["ShellRS.app"]);
|
||||
}
|
||||
|
||||
/// The clean-up runs a while after start; an update downloaded and
|
||||
/// staged before then is still there to install on restart.
|
||||
#[test]
|
||||
fn the_clean_up_keeps_an_update_staged_for_the_restart() {
|
||||
let (folder, bundle) = installed();
|
||||
let installer = MacInstaller::new(bundle.clone(), FakeTools::new("0.2.0", None));
|
||||
for stale in [
|
||||
".ShellRS.app.update-0.1.0",
|
||||
".ShellRS.app.update-later",
|
||||
".ShellRS.app.old-1",
|
||||
] {
|
||||
fs::create_dir(folder.path().join(stale)).unwrap();
|
||||
}
|
||||
let staged = installer
|
||||
.stage(Path::new("package.zip"), &release("0.2.0"))
|
||||
.unwrap();
|
||||
|
||||
installer.clean_up(&Version::new(0, 1, 0));
|
||||
assert_eq!(
|
||||
names_in(folder.path()),
|
||||
[".ShellRS.app.update-0.2.0", "ShellRS.app"]
|
||||
);
|
||||
assert_eq!(
|
||||
installer.apply(&staged, true),
|
||||
Ok(Relaunch::Restart(bundle.clone()))
|
||||
);
|
||||
assert_eq!(version_at(&bundle), "0.2.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_failed_swap_puts_the_old_bundle_back() {
|
||||
let (folder, bundle) = installed();
|
||||
@@ -367,8 +399,12 @@ mod tests {
|
||||
Err(UpdateError::Install(_))
|
||||
));
|
||||
assert_eq!(version_at(&bundle), "0.1.0");
|
||||
installer.clean_up();
|
||||
assert_eq!(names_in(folder.path()), ["ShellRS.app"]);
|
||||
installer.clean_up(&Version::new(0, 1, 0));
|
||||
assert!(
|
||||
!names_in(folder.path())
|
||||
.iter()
|
||||
.any(|name| name.starts_with(".ShellRS.app.old-"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -484,7 +520,7 @@ mod tests {
|
||||
.check_signature(&bundle, Some("SHELLRS"))
|
||||
.is_err()
|
||||
);
|
||||
installer.clean_up();
|
||||
installer.clean_up(&Version::new(0, 2, 0));
|
||||
assert_eq!(names_in(&installed), ["ShellRS.app"]);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use semver::Version;
|
||||
|
||||
use super::error::UpdateError;
|
||||
use super::install::{InstallKind, Installer, Launch, Relaunch, Staged};
|
||||
use super::manifest::Release;
|
||||
@@ -99,7 +101,8 @@ impl Installer for SetupInstaller {
|
||||
}
|
||||
|
||||
/// The setup program removes what the previous version left.
|
||||
fn clean_up(&self) {}
|
||||
// The package waits in the downloads folder, which the updater tidies.
|
||||
fn clean_up(&self, _: &Version) {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -507,7 +507,7 @@ impl Updater {
|
||||
return;
|
||||
};
|
||||
cx.background_spawn(async move {
|
||||
services.installer.clean_up();
|
||||
services.installer.clean_up(&services.current);
|
||||
clean_downloads(&services.folder, &services.current);
|
||||
})
|
||||
.detach();
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ impl Installer for FakeInstaller {
|
||||
})
|
||||
}
|
||||
|
||||
fn clean_up(&self) {}
|
||||
fn clean_up(&self, _: &Version) {}
|
||||
}
|
||||
|
||||
/// A copy of ShellRS that can install updates itself.
|
||||
|
||||
Reference in new issue
Block a user