Revert "Add rime-ice-installer with offline assets and no sudo when its packages are present"

This reverts commit 5e0ff0df95.
This commit is contained in:
ZacharyZhang-NY committed 2026-10-08 23:48:13 -04:00
1 parent 7000c95661
commit 44d4d231be
3 files changed
-385

No files matched your search

@@ -1,8 +0,0 @@
{
"source": "local",
"sync": false,
"origin": {
"aur": "rime-ice-installer",
"commit": "08b3592fd79845148efde23768e5f1cfbda8bcd2"
}
}
-57
View File
@@ -1,57 +0,0 @@
# Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
pkgname=rime-ice-installer
pkgver=0.1.10
pkgrel=1
pkgdesc='TUI installer for Fcitx5, Rime Ice and Wanxiang on Arch Linux'
arch=('x86_64')
url='https://github.com/manateelazycat/rime-ice-installer'
license=('custom:unknown')
depends=('curl' 'dbus' 'dialog' 'git' 'glib2' 'sudo' 'unzip')
makedepends=('go')
source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz"
'omarchy-offline.patch')
sha256sums=('64008e326ece22d156c0fb634cc784c60a41c48858eb0d949349b41dfd0c5477'
'f2b9a8ec97796d4432f3461396fa0332901624e70c873187703b85d61478c384')
_setup_go_env() {
export GOPATH="$srcdir"
export GOMODCACHE="$srcdir/pkg/mod"
export GOFLAGS='-buildmode=pie -trimpath -mod=readonly -modcacherw'
}
prepare() {
cd "$srcdir/$pkgname-$pkgver"
patch -Np1 -i "$srcdir/omarchy-offline.patch"
_setup_go_env
go mod download
}
build() {
cd "$srcdir/$pkgname-$pkgver"
_setup_go_env
export CGO_CPPFLAGS="${CPPFLAGS}"
export CGO_CFLAGS="${CFLAGS}"
export CGO_CXXFLAGS="${CXXFLAGS}"
export CGO_LDFLAGS="${LDFLAGS}"
go build -o "$pkgname" .
}
check() {
cd "$srcdir/$pkgname-$pkgver"
_setup_go_env
go test ./...
}
package() {
cd "$srcdir/$pkgname-$pkgver"
install -Dm755 "$pkgname" "$pkgdir/usr/bin/$pkgname"
install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md"
}
@@ -1,320 +0,0 @@
diff --git a/internal/app/app.go b/internal/app/app.go
index 17e01bf..fd73578 100644
--- a/internal/app/app.go
+++ b/internal/app/app.go
@@ -84,7 +84,8 @@ func Run(ctx context.Context, cfg config.InstallConfig) error {
return err
}
- if os.Geteuid() != 0 {
+ missingPackages := fcitx.MissingPackages()
+ if os.Geteuid() != 0 && len(missingPackages) > 0 {
if dialogUI != nil {
if err := validateSudoWithDialog(ctx, runner, dialogUI, detectedEnv.FingerprintAvailable); err != nil {
if errors.Is(err, ui.ErrCancelled) {
@@ -140,7 +141,7 @@ func Run(ctx context.Context, cfg config.InstallConfig) error {
}
if err := step("安装 Fcitx5 与依赖", func() error {
- return fcitx.InstallPackages(ctx, runner, cfg, detectedEnv)
+ return fcitx.InstallPackages(ctx, runner, missingPackages, detectedEnv)
}); err != nil {
closeGauge(gauge)
return fail(dialogUI, logger, err)
@@ -181,7 +182,7 @@ func Run(ctx context.Context, cfg config.InstallConfig) error {
if err := step("下载并补丁雾凇拼音", func() error {
var err error
- rimeWorkspace, err = rime.PrepareWorkspace(ctx, downloader, cfg.WorkspaceDir)
+ rimeWorkspace, err = rime.PrepareWorkspace(ctx, downloader, cfg.WorkspaceDir, cfg.AssetDir)
return err
}); err != nil {
closeGauge(gauge)
@@ -191,7 +192,7 @@ func Run(ctx context.Context, cfg config.InstallConfig) error {
if cfg.EnableWanxiang {
if err := step("下载并启用万象语法模型", func() error {
var err error
- modelRelease, err = wanxiang.Integrate(ctx, downloader, cfg.WorkspaceDir, rimeWorkspace.SourceDir)
+ modelRelease, err = wanxiang.Integrate(ctx, downloader, cfg.WorkspaceDir, rimeWorkspace.SourceDir, cfg.AssetDir)
return err
}); err != nil {
closeGauge(gauge)
diff --git a/internal/config/config.go b/internal/config/config.go
index e3554e8..2efc8c2 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -18,6 +18,7 @@ type InstallConfig struct {
DryRun bool
Verbose bool
WorkspaceDir string
+ AssetDir string
}
type DetectedEnv struct {
diff --git a/internal/fcitx/fcitx.go b/internal/fcitx/fcitx.go
index fba202a..f252ca1 100644
--- a/internal/fcitx/fcitx.go
+++ b/internal/fcitx/fcitx.go
@@ -34,10 +34,23 @@ const (
defaultGroupName = "Default"
)
-func InstallPackages(ctx context.Context, runner *system.Runner, cfg config.InstallConfig, env config.DetectedEnv) error {
- args := append([]string{"-S", "--needed", "--noconfirm"}, pacmanPackages...)
- if err := runner.RunPrivileged(ctx, "pacman", args...); err != nil {
- return err
+// MissingPackages 返回尚未安装的 pacman 包。
+func MissingPackages() []string {
+ var missing []string
+ for _, pkg := range pacmanPackages {
+ if exec.Command("pacman", "-Q", pkg).Run() != nil {
+ missing = append(missing, pkg)
+ }
+ }
+ return missing
+}
+
+func InstallPackages(ctx context.Context, runner *system.Runner, missing []string, env config.DetectedEnv) error {
+ if len(missing) > 0 {
+ args := append([]string{"-S", "--needed", "--noconfirm"}, missing...)
+ if err := runner.RunPrivileged(ctx, "pacman", args...); err != nil {
+ return err
+ }
}
if !env.HasOctagramPlugin {
diff --git a/internal/rime/asset_dir_test.go b/internal/rime/asset_dir_test.go
new file mode 100644
index 0000000..9e66346
--- /dev/null
+++ b/internal/rime/asset_dir_test.go
@@ -0,0 +1,49 @@
+package rime
+
+import (
+ "archive/zip"
+ "context"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestPrepareWorkspaceReadsFullZipFromAssetDir(t *testing.T) {
+ assetDir := t.TempDir()
+ archive, err := os.Create(filepath.Join(assetDir, rimeIceAsset))
+ if err != nil {
+ t.Fatal(err)
+ }
+ writer := zip.NewWriter(archive)
+ entry, err := writer.Create("rime_ice.schema.yaml")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := entry.Write([]byte("schema:\n schema_id: rime_ice\n")); err != nil {
+ t.Fatal(err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatal(err)
+ }
+ archive.Close()
+
+ workspace := t.TempDir()
+ prepared, err := PrepareWorkspace(context.Background(), nil, workspace, assetDir)
+ if err != nil {
+ t.Fatalf("PrepareWorkspace() error = %v", err)
+ }
+ if prepared.Release.Tag != "local" || prepared.Release.AssetName != rimeIceAsset {
+ t.Fatalf("release = %+v, want local %s", prepared.Release, rimeIceAsset)
+ }
+ for _, name := range []string{"rime_ice.schema.yaml", "default.custom.yaml", "user.yaml"} {
+ if _, err := os.Stat(filepath.Join(prepared.SourceDir, name)); err != nil {
+ t.Fatalf("%s missing from prepared workspace: %v", name, err)
+ }
+ }
+}
+
+func TestPrepareWorkspaceFailsWithoutLocalFullZip(t *testing.T) {
+ if _, err := PrepareWorkspace(context.Background(), nil, t.TempDir(), t.TempDir()); err == nil {
+ t.Fatal("PrepareWorkspace() succeeded without full.zip in the asset dir")
+ }
+}
diff --git a/internal/rime/rime.go b/internal/rime/rime.go
index 1db520b..45900be 100644
--- a/internal/rime/rime.go
+++ b/internal/rime/rime.go
@@ -26,20 +26,28 @@ type PreparedWorkspace struct {
Release config.ReleaseInfo
}
-func PrepareWorkspace(ctx context.Context, client *download.Client, workspace string) (*PreparedWorkspace, error) {
- release, err := client.ReleaseByTag(ctx, rimeIceOwner, rimeIceRepo, rimeIceTag)
- if err != nil {
- return nil, err
- }
+func PrepareWorkspace(ctx context.Context, client *download.Client, workspace, assetDir string) (*PreparedWorkspace, error) {
+ info := config.ReleaseInfo{Owner: rimeIceOwner, Repo: rimeIceRepo, Tag: "local", AssetName: rimeIceAsset}
+ downloadPath := filepath.Join(assetDir, rimeIceAsset)
+ if assetDir == "" {
+ release, err := client.ReleaseByTag(ctx, rimeIceOwner, rimeIceRepo, rimeIceTag)
+ if err != nil {
+ return nil, err
+ }
- asset, err := download.FindAsset(release, rimeIceAsset)
- if err != nil {
- return nil, err
- }
+ asset, err := download.FindAsset(release, rimeIceAsset)
+ if err != nil {
+ return nil, err
+ }
- downloadPath := filepath.Join(workspace, "downloads", asset.Name)
- if err := client.DownloadAsset(ctx, asset, downloadPath); err != nil {
- return nil, err
+ downloadPath = filepath.Join(workspace, "downloads", asset.Name)
+ if err := client.DownloadAsset(ctx, asset, downloadPath); err != nil {
+ return nil, err
+ }
+ info.Tag = release.TagName
+ info.AssetName = asset.Name
+ info.Digest = normalizeDigest(asset.Digest)
+ info.URL = asset.BrowserDownloadURL
}
sourceDir := filepath.Join(workspace, "source", "rime-ice")
@@ -54,17 +62,7 @@ func PrepareWorkspace(ctx context.Context, client *download.Client, workspace st
return nil, err
}
- return &PreparedWorkspace{
- SourceDir: sourceDir,
- Release: config.ReleaseInfo{
- Owner: rimeIceOwner,
- Repo: rimeIceRepo,
- Tag: release.TagName,
- AssetName: asset.Name,
- Digest: normalizeDigest(asset.Digest),
- URL: asset.BrowserDownloadURL,
- },
- }, nil
+ return &PreparedWorkspace{SourceDir: sourceDir, Release: info}, nil
}
func MergeDefaultCustomConfig(path string) error {
diff --git a/internal/wanxiang/asset_dir_test.go b/internal/wanxiang/asset_dir_test.go
new file mode 100644
index 0000000..23554b3
--- /dev/null
+++ b/internal/wanxiang/asset_dir_test.go
@@ -0,0 +1,33 @@
+package wanxiang
+
+import (
+ "context"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func TestIntegrateReadsModelFromAssetDir(t *testing.T) {
+ assetDir := t.TempDir()
+ if err := os.WriteFile(filepath.Join(assetDir, modelAsset), []byte("model"), 0o644); err != nil {
+ t.Fatal(err)
+ }
+
+ sourceDir := t.TempDir()
+ info, err := Integrate(context.Background(), nil, t.TempDir(), sourceDir, assetDir)
+ if err != nil {
+ t.Fatalf("Integrate() error = %v", err)
+ }
+ if info.Tag != "local" || info.AssetName != modelAsset {
+ t.Fatalf("release = %+v, want local %s", info, modelAsset)
+ }
+ model, err := os.ReadFile(filepath.Join(sourceDir, modelAsset))
+ if err != nil || string(model) != "model" {
+ t.Fatalf("model copy = %q, %v", model, err)
+ }
+ custom, err := os.ReadFile(filepath.Join(sourceDir, "rime_ice.custom.yaml"))
+ if err != nil || !strings.Contains(string(custom), "wanxiang-lts-zh-hans") {
+ t.Fatalf("custom yaml = %q, %v", custom, err)
+ }
+}
diff --git a/internal/wanxiang/wanxiang.go b/internal/wanxiang/wanxiang.go
index f629977..a0fd266 100644
--- a/internal/wanxiang/wanxiang.go
+++ b/internal/wanxiang/wanxiang.go
@@ -21,23 +21,31 @@ const (
modelAsset = "wanxiang-lts-zh-hans.gram"
)
-func Integrate(ctx context.Context, client *download.Client, workspace, sourceDir string) (*config.ReleaseInfo, error) {
- release, err := client.ReleaseByTag(ctx, modelOwner, modelRepo, modelTag)
- if err != nil {
- return nil, err
- }
+func Integrate(ctx context.Context, client *download.Client, workspace, sourceDir, assetDir string) (*config.ReleaseInfo, error) {
+ info := &config.ReleaseInfo{Owner: modelOwner, Repo: modelRepo, Tag: "local", AssetName: modelAsset}
+ downloadPath := filepath.Join(assetDir, modelAsset)
+ if assetDir == "" {
+ release, err := client.ReleaseByTag(ctx, modelOwner, modelRepo, modelTag)
+ if err != nil {
+ return nil, err
+ }
- asset, err := download.FindAsset(release, modelAsset)
- if err != nil {
- return nil, err
- }
+ asset, err := download.FindAsset(release, modelAsset)
+ if err != nil {
+ return nil, err
+ }
- downloadPath := filepath.Join(workspace, "downloads", asset.Name)
- if err := client.DownloadAsset(ctx, asset, downloadPath); err != nil {
- return nil, err
+ downloadPath = filepath.Join(workspace, "downloads", asset.Name)
+ if err := client.DownloadAsset(ctx, asset, downloadPath); err != nil {
+ return nil, err
+ }
+ info.Tag = release.TagName
+ info.AssetName = asset.Name
+ info.Digest = strings.TrimPrefix(asset.Digest, "sha256:")
+ info.URL = asset.BrowserDownloadURL
}
- targetModelPath := filepath.Join(sourceDir, asset.Name)
+ targetModelPath := filepath.Join(sourceDir, modelAsset)
modelContent, err := os.ReadFile(downloadPath)
if err != nil {
return nil, fmt.Errorf("读取模型文件失败: %w", err)
@@ -50,14 +58,7 @@ func Integrate(ctx context.Context, client *download.Client, workspace, sourceDi
return nil, err
}
- return &config.ReleaseInfo{
- Owner: modelOwner,
- Repo: modelRepo,
- Tag: release.TagName,
- AssetName: asset.Name,
- Digest: strings.TrimPrefix(asset.Digest, "sha256:"),
- URL: asset.BrowserDownloadURL,
- }, nil
+ return info, nil
}
func MergeCustomConfig(path string) error {
diff --git a/main.go b/main.go
index 50f00f3..15439bd 100644
--- a/main.go
+++ b/main.go
@@ -19,6 +19,7 @@ func main() {
flag.BoolVar(&cfg.EnableWanxiang, "enable-wanxiang", cfg.EnableWanxiang, "下载并启用万象 LTS 语法模型")
flag.IntVar(&cfg.FontSize, "font-size", cfg.FontSize, "Fcitx5 候选框字体大小(8-48)")
flag.StringVar(&cfg.WorkspaceDir, "workspace-dir", cfg.WorkspaceDir, "工作目录,用于下载缓存和日志")
+ flag.StringVar(&cfg.AssetDir, "asset-dir", "", "从此目录读取 full.zip 和万象模型,不访问 GitHub")
flag.Parse()
if err := app.Run(context.Background(), cfg); err != nil {